From 40c0f755c998d2615fe8466aab20c6d81bd463e7 Mon Sep 17 00:00:00 2001 From: Ryan Date: Wed, 22 Apr 2009 19:35:47 +0200 Subject: [PATCH] import full versions of dependency libraries! --- configure | 18 +- deps/libebb/.gitignore | 5 + deps/libebb/LICENSE | 21 + deps/libebb/README | 7 + deps/libebb/config.mk | 38 + deps/libebb/doc/icon.png | Bin 0 -> 9412 bytes deps/libebb/doc/index.html | 240 + deps/libebb/ebb.c | 798 ++ deps/libebb/ebb.h | 120 + deps/libebb/ebb_request_parser.h | 117 + deps/libebb/ebb_request_parser.rl | 413 + deps/libebb/examples/ca-cert.pem | 12 + deps/libebb/examples/ca-key.pem | 15 + deps/libebb/examples/hello_world.c | 101 + deps/libebb/rbtree.c | 412 + deps/libebb/rbtree.h | 54 + deps/libebb/test_examples.rb | 60 + deps/libebb/test_rbtree.c | 108 + deps/libebb/test_request_parser.c | 746 ++ deps/liboi/LICENSE | 23 + deps/liboi/README | 36 + deps/liboi/config.mk | 33 + deps/liboi/oi.h | 8 + deps/liboi/oi.pod | 278 + deps/liboi/oi_async.c | 486 + deps/liboi/oi_async.h | 218 + deps/liboi/oi_buf.c | 41 + deps/liboi/oi_buf.h | 30 + deps/liboi/oi_error.h | 25 + deps/liboi/oi_file.c | 391 + deps/liboi/oi_file.h | 58 + deps/liboi/oi_queue.h | 69 + deps/liboi/oi_socket.c | 941 ++ deps/liboi/oi_socket.h | 98 + deps/liboi/test/common.c | 110 + deps/liboi/test/connection_interruption.c | 159 + deps/liboi/test/echo.c | 102 + deps/liboi/test/fancy_copy.c | 223 + deps/liboi/test/ping_pong.c | 165 + deps/liboi/test/sleeping_tasks.c | 54 + deps/liboi/test/stdout.c | 64 + deps/liboi/test/timeout.rb | 96 + deps/v8/AUTHORS | 15 + deps/v8/ChangeLog | 816 ++ deps/v8/LICENSE | 51 + deps/v8/SConstruct | 775 ++ deps/v8/benchmarks/README.txt | 42 + deps/v8/benchmarks/base.js | 233 + deps/v8/benchmarks/crypto.js | 1698 +++ deps/v8/benchmarks/deltablue.js | 880 ++ deps/v8/benchmarks/earley-boyer.js | 4685 +++++++++ deps/v8/benchmarks/raytrace.js | 3434 ++++++ deps/v8/benchmarks/regexp.js | 1614 +++ deps/v8/benchmarks/revisions.html | 62 + deps/v8/benchmarks/richards.js | 539 + deps/v8/benchmarks/run.html | 102 + deps/v8/benchmarks/run.js | 60 + deps/v8/benchmarks/style.css | 70 + deps/v8/benchmarks/v8-logo.png | Bin 0 -> 24293 bytes deps/v8/include/v8-debug.h | 179 + deps/v8/include/v8.h | 2538 +++++ deps/v8/samples/SConscript | 38 + deps/v8/samples/count-hosts.js | 42 + deps/v8/samples/process.cc | 622 ++ deps/v8/samples/shell.cc | 281 + deps/v8/scons-LICENSE | 25 + deps/v8/scons-README | 204 + deps/v8/scons-time.py | 1513 +++ deps/v8/scons.py | 165 + deps/v8/sconsign.py | 502 + deps/v8/src/SConscript | 183 + deps/v8/src/accessors.cc | 548 + deps/v8/src/accessors.h | 101 + deps/v8/src/allocation.cc | 197 + deps/v8/src/allocation.h | 168 + deps/v8/src/api.cc | 3348 ++++++ deps/v8/src/api.h | 454 + deps/v8/src/apinatives.js | 109 + deps/v8/src/apiutils.h | 69 + deps/v8/src/arguments.h | 70 + deps/v8/src/array.js | 938 ++ deps/v8/src/assembler-arm-inl.h | 249 + deps/v8/src/assembler-arm.cc | 1471 +++ deps/v8/src/assembler-arm.h | 789 ++ deps/v8/src/assembler-ia32-inl.h | 302 + deps/v8/src/assembler-ia32.cc | 2205 ++++ deps/v8/src/assembler-ia32.h | 863 ++ deps/v8/src/assembler.cc | 585 ++ deps/v8/src/assembler.h | 456 + deps/v8/src/ast.cc | 490 + deps/v8/src/ast.h | 1710 +++ deps/v8/src/bootstrapper.cc | 1528 +++ deps/v8/src/bootstrapper.h | 80 + deps/v8/src/builtins-arm.cc | 658 ++ deps/v8/src/builtins-ia32.cc | 756 ++ deps/v8/src/builtins.cc | 744 ++ deps/v8/src/builtins.h | 217 + deps/v8/src/bytecodes-irregexp.h | 103 + deps/v8/src/char-predicates-inl.h | 85 + deps/v8/src/char-predicates.h | 64 + deps/v8/src/checks.cc | 98 + deps/v8/src/checks.h | 263 + deps/v8/src/code-stubs.cc | 142 + deps/v8/src/code-stubs.h | 109 + deps/v8/src/code.h | 67 + deps/v8/src/codegen-arm.cc | 5203 ++++++++++ deps/v8/src/codegen-arm.h | 446 + deps/v8/src/codegen-ia32.cc | 7116 +++++++++++++ deps/v8/src/codegen-ia32.h | 621 ++ deps/v8/src/codegen-inl.h | 75 + deps/v8/src/codegen.cc | 622 ++ deps/v8/src/codegen.h | 311 + deps/v8/src/compilation-cache.cc | 230 + deps/v8/src/compilation-cache.h | 105 + deps/v8/src/compiler.cc | 353 + deps/v8/src/compiler.h | 73 + deps/v8/src/constants-arm.h | 235 + deps/v8/src/contexts.cc | 252 + deps/v8/src/contexts.h | 335 + deps/v8/src/conversions-inl.h | 94 + deps/v8/src/conversions.cc | 707 ++ deps/v8/src/conversions.h | 116 + deps/v8/src/counters.cc | 77 + deps/v8/src/counters.h | 238 + deps/v8/src/cpu-arm.cc | 124 + deps/v8/src/cpu-ia32.cc | 65 + deps/v8/src/cpu.h | 64 + deps/v8/src/d8-debug.cc | 345 + deps/v8/src/d8-debug.h | 155 + deps/v8/src/d8-posix.cc | 668 ++ deps/v8/src/d8-readline.cc | 128 + deps/v8/src/d8-windows.cc | 42 + deps/v8/src/d8.cc | 726 ++ deps/v8/src/d8.h | 220 + deps/v8/src/d8.js | 1434 +++ deps/v8/src/date-delay.js | 1051 ++ deps/v8/src/dateparser-inl.h | 106 + deps/v8/src/dateparser.cc | 185 + deps/v8/src/dateparser.h | 239 + deps/v8/src/debug-agent.cc | 414 + deps/v8/src/debug-agent.h | 117 + deps/v8/src/debug-arm.cc | 195 + deps/v8/src/debug-delay.js | 1853 ++++ deps/v8/src/debug-ia32.cc | 218 + deps/v8/src/debug.cc | 2227 ++++ deps/v8/src/debug.h | 722 ++ deps/v8/src/disasm-arm.cc | 891 ++ deps/v8/src/disasm-ia32.cc | 1202 +++ deps/v8/src/disasm.h | 77 + deps/v8/src/disassembler.cc | 309 + deps/v8/src/disassembler.h | 55 + deps/v8/src/dtoa-config.c | 84 + deps/v8/src/execution.cc | 637 ++ deps/v8/src/execution.h | 276 + deps/v8/src/factory.cc | 902 ++ deps/v8/src/factory.h | 361 + deps/v8/src/flag-definitions.h | 384 + deps/v8/src/flags.cc | 554 + deps/v8/src/flags.h | 80 + deps/v8/src/frames-arm.cc | 117 + deps/v8/src/frames-arm.h | 379 + deps/v8/src/frames-ia32.cc | 115 + deps/v8/src/frames-ia32.h | 291 + deps/v8/src/frames-inl.h | 226 + deps/v8/src/frames.cc | 740 ++ deps/v8/src/frames.h | 689 ++ deps/v8/src/func-name-inferrer.cc | 74 + deps/v8/src/func-name-inferrer.h | 127 + deps/v8/src/global-handles.cc | 383 + deps/v8/src/global-handles.h | 148 + deps/v8/src/globals.h | 519 + deps/v8/src/handles-inl.h | 75 + deps/v8/src/handles.cc | 688 ++ deps/v8/src/handles.h | 338 + deps/v8/src/hashmap.cc | 170 + deps/v8/src/hashmap.h | 116 + deps/v8/src/heap-inl.h | 286 + deps/v8/src/heap.cc | 3393 ++++++ deps/v8/src/heap.h | 1313 +++ deps/v8/src/ic-arm.cc | 799 ++ deps/v8/src/ic-ia32.cc | 892 ++ deps/v8/src/ic-inl.h | 88 + deps/v8/src/ic.cc | 1218 +++ deps/v8/src/ic.h | 369 + deps/v8/src/interpreter-irregexp.cc | 596 ++ deps/v8/src/interpreter-irregexp.h | 47 + deps/v8/src/jsregexp-inl.h | 259 + deps/v8/src/jsregexp.cc | 4463 ++++++++ deps/v8/src/jsregexp.h | 1372 +++ deps/v8/src/jump-target-arm.cc | 335 + deps/v8/src/jump-target-ia32.cc | 335 + deps/v8/src/jump-target.cc | 731 ++ deps/v8/src/jump-target.h | 325 + deps/v8/src/list-inl.h | 132 + deps/v8/src/list.h | 127 + deps/v8/src/log.cc | 1193 +++ deps/v8/src/log.h | 292 + deps/v8/src/macro-assembler-arm.cc | 936 ++ deps/v8/src/macro-assembler-arm.h | 303 + deps/v8/src/macro-assembler-ia32.cc | 1046 ++ deps/v8/src/macro-assembler-ia32.h | 348 + deps/v8/src/macro-assembler.h | 50 + deps/v8/src/macros.py | 120 + deps/v8/src/mark-compact.cc | 1765 ++++ deps/v8/src/mark-compact.h | 407 + deps/v8/src/math.js | 190 + deps/v8/src/memory.h | 61 + deps/v8/src/messages.cc | 178 + deps/v8/src/messages.h | 110 + deps/v8/src/messages.js | 686 ++ deps/v8/src/mirror-delay.js | 2089 ++++ deps/v8/src/mksnapshot.cc | 186 + deps/v8/src/natives.h | 62 + deps/v8/src/objects-debug.cc | 1094 ++ deps/v8/src/objects-inl.h | 2597 +++++ deps/v8/src/objects.cc | 7424 +++++++++++++ deps/v8/src/objects.h | 4337 ++++++++ deps/v8/src/oprofile-agent.cc | 111 + deps/v8/src/oprofile-agent.h | 68 + deps/v8/src/parser.cc | 4579 ++++++++ deps/v8/src/parser.h | 200 + deps/v8/src/platform-freebsd.cc | 639 ++ deps/v8/src/platform-linux.cc | 677 ++ deps/v8/src/platform-macos.cc | 566 + deps/v8/src/platform-nullos.cc | 435 + deps/v8/src/platform-posix.cc | 350 + deps/v8/src/platform-win32.cc | 1864 ++++ deps/v8/src/platform.h | 528 + deps/v8/src/prettyprinter.cc | 1102 ++ deps/v8/src/prettyprinter.h | 118 + deps/v8/src/property.cc | 109 + deps/v8/src/property.h | 396 + deps/v8/src/regexp-delay.js | 412 + deps/v8/src/regexp-macro-assembler-arm.cc | 43 + deps/v8/src/regexp-macro-assembler-arm.h | 41 + deps/v8/src/regexp-macro-assembler-ia32.cc | 1390 +++ deps/v8/src/regexp-macro-assembler-ia32.h | 285 + .../src/regexp-macro-assembler-irregexp-inl.h | 71 + .../v8/src/regexp-macro-assembler-irregexp.cc | 491 + deps/v8/src/regexp-macro-assembler-irregexp.h | 147 + deps/v8/src/regexp-macro-assembler-tracer.cc | 420 + deps/v8/src/regexp-macro-assembler-tracer.h | 118 + deps/v8/src/regexp-macro-assembler.cc | 78 + deps/v8/src/regexp-macro-assembler.h | 230 + deps/v8/src/regexp-stack.cc | 94 + deps/v8/src/regexp-stack.h | 106 + deps/v8/src/register-allocator-arm.cc | 96 + deps/v8/src/register-allocator-ia32.cc | 130 + deps/v8/src/register-allocator-inl.h | 49 + deps/v8/src/register-allocator.cc | 132 + deps/v8/src/register-allocator.h | 333 + deps/v8/src/rewriter.cc | 839 ++ deps/v8/src/rewriter.h | 53 + deps/v8/src/runtime.cc | 6961 +++++++++++++ deps/v8/src/runtime.h | 385 + deps/v8/src/runtime.js | 525 + deps/v8/src/scanner.cc | 850 ++ deps/v8/src/scanner.h | 239 + deps/v8/src/scopeinfo.cc | 570 + deps/v8/src/scopeinfo.h | 155 + deps/v8/src/scopes.cc | 946 ++ deps/v8/src/scopes.h | 366 + deps/v8/src/serialize.cc | 1596 +++ deps/v8/src/serialize.h | 335 + deps/v8/src/shell.h | 49 + deps/v8/src/simulator-arm.cc | 1598 +++ deps/v8/src/simulator-arm.h | 198 + deps/v8/src/simulator-ia32.cc | 30 + deps/v8/src/simulator-ia32.h | 47 + deps/v8/src/smart-pointer.h | 108 + deps/v8/src/snapshot-common.cc | 74 + deps/v8/src/snapshot-empty.cc | 39 + deps/v8/src/snapshot.h | 58 + deps/v8/src/spaces-inl.h | 356 + deps/v8/src/spaces.cc | 2599 +++++ deps/v8/src/spaces.h | 1703 +++ deps/v8/src/string-stream.cc | 577 ++ deps/v8/src/string-stream.h | 174 + deps/v8/src/string.js | 866 ++ deps/v8/src/stub-cache-arm.cc | 1125 ++ deps/v8/src/stub-cache-ia32.cc | 1179 +++ deps/v8/src/stub-cache.cc | 921 ++ deps/v8/src/stub-cache.h | 480 + deps/v8/src/third_party/dtoa/COPYING | 15 + deps/v8/src/third_party/dtoa/dtoa.c | 3324 ++++++ deps/v8/src/token.cc | 162 + deps/v8/src/token.h | 281 + deps/v8/src/top.cc | 921 ++ deps/v8/src/top.h | 377 + deps/v8/src/unicode-inl.h | 238 + deps/v8/src/unicode.cc | 754 ++ deps/v8/src/unicode.h | 279 + deps/v8/src/uri.js | 409 + deps/v8/src/usage-analyzer.cc | 450 + deps/v8/src/usage-analyzer.h | 39 + deps/v8/src/utils.cc | 297 + deps/v8/src/utils.h | 540 + deps/v8/src/v8-counters.cc | 54 + deps/v8/src/v8-counters.h | 162 + deps/v8/src/v8.cc | 120 + deps/v8/src/v8.h | 97 + deps/v8/src/v8natives.js | 540 + deps/v8/src/v8threads.cc | 379 + deps/v8/src/v8threads.h | 131 + deps/v8/src/variables.cc | 162 + deps/v8/src/variables.h | 223 + deps/v8/src/virtual-frame-arm.cc | 437 + deps/v8/src/virtual-frame-arm.h | 480 + deps/v8/src/virtual-frame-ia32.cc | 1040 ++ deps/v8/src/virtual-frame-ia32.h | 493 + deps/v8/src/virtual-frame.cc | 536 + deps/v8/src/virtual-frame.h | 206 + deps/v8/src/zone-inl.h | 72 + deps/v8/src/zone.cc | 189 + deps/v8/src/zone.h | 203 + deps/v8/test/cctest/SConscript | 85 + deps/v8/test/cctest/cctest.cc | 126 + deps/v8/test/cctest/cctest.h | 75 + deps/v8/test/cctest/cctest.status | 50 + deps/v8/test/cctest/test-alloc.cc | 146 + deps/v8/test/cctest/test-api.cc | 6189 +++++++++++ deps/v8/test/cctest/test-assembler-arm.cc | 227 + deps/v8/test/cctest/test-assembler-ia32.cc | 395 + deps/v8/test/cctest/test-ast.cc | 97 + deps/v8/test/cctest/test-compiler.cc | 318 + deps/v8/test/cctest/test-conversions.cc | 130 + deps/v8/test/cctest/test-debug.cc | 4251 ++++++++ deps/v8/test/cctest/test-decls.cc | 594 ++ deps/v8/test/cctest/test-disasm-arm.cc | 281 + deps/v8/test/cctest/test-disasm-ia32.cc | 384 + deps/v8/test/cctest/test-flags.cc | 234 + .../test/cctest/test-func-name-inference.cc | 223 + deps/v8/test/cctest/test-hashmap.cc | 123 + deps/v8/test/cctest/test-heap.cc | 785 ++ deps/v8/test/cctest/test-list.cc | 67 + deps/v8/test/cctest/test-lock.cc | 63 + deps/v8/test/cctest/test-log-ia32.cc | 314 + deps/v8/test/cctest/test-mark-compact.cc | 314 + deps/v8/test/cctest/test-platform-linux.cc | 80 + deps/v8/test/cctest/test-platform-macos.cc | 10 + deps/v8/test/cctest/test-platform-nullos.cc | 80 + deps/v8/test/cctest/test-platform-win32.cc | 26 + deps/v8/test/cctest/test-regexp.cc | 1536 +++ deps/v8/test/cctest/test-serialize.cc | 268 + deps/v8/test/cctest/test-sockets.cc | 161 + deps/v8/test/cctest/test-spaces.cc | 248 + deps/v8/test/cctest/test-strings.cc | 446 + deps/v8/test/cctest/test-threads.cc | 54 + deps/v8/test/cctest/test-utils.cc | 179 + deps/v8/test/cctest/testcfg.py | 108 + deps/v8/test/message/message.status | 31 + deps/v8/test/message/regress/regress-73.js | 33 + deps/v8/test/message/regress/regress-73.out | 30 + deps/v8/test/message/regress/regress-75.js | 32 + deps/v8/test/message/regress/regress-75.out | 30 + deps/v8/test/message/simple-throw.js | 28 + deps/v8/test/message/simple-throw.out | 30 + deps/v8/test/message/testcfg.py | 135 + .../message/try-catch-finally-no-message.js | 51 + .../message/try-catch-finally-no-message.out | 26 + .../try-catch-finally-return-in-finally.js | 39 + .../try-catch-finally-return-in-finally.out | 28 + ...atch-finally-throw-in-catch-and-finally.js | 34 + ...tch-finally-throw-in-catch-and-finally.out | 30 + .../try-catch-finally-throw-in-catch.js | 34 + .../try-catch-finally-throw-in-catch.out | 30 + .../try-catch-finally-throw-in-finally.js | 34 + .../try-catch-finally-throw-in-finally.out | 30 + .../message/try-finally-return-in-finally.js | 37 + .../message/try-finally-return-in-finally.out | 28 + .../message/try-finally-throw-in-finally.js | 32 + .../message/try-finally-throw-in-finally.out | 30 + .../try-finally-throw-in-try-and-finally.js | 32 + .../try-finally-throw-in-try-and-finally.out | 30 + .../test/message/try-finally-throw-in-try.js | 32 + .../test/message/try-finally-throw-in-try.out | 30 + .../api-call-after-bypassed-exception.js | 39 + deps/v8/test/mjsunit/apply.js | 184 + deps/v8/test/mjsunit/arguments-call-apply.js | 41 + deps/v8/test/mjsunit/arguments-enum.js | 52 + deps/v8/test/mjsunit/arguments-indirect.js | 47 + deps/v8/test/mjsunit/arguments-opt.js | 130 + deps/v8/test/mjsunit/arguments.js | 97 + deps/v8/test/mjsunit/array-concat.js | 120 + .../test/mjsunit/array-functions-prototype.js | 159 + deps/v8/test/mjsunit/array-indexing.js | 66 + deps/v8/test/mjsunit/array-iteration.js | 228 + deps/v8/test/mjsunit/array-join.js | 45 + .../mjsunit/array-length-number-conversion.js | 53 + deps/v8/test/mjsunit/array-length.js | 111 + deps/v8/test/mjsunit/array-sort.js | 154 + deps/v8/test/mjsunit/array-splice-webkit.js | 60 + deps/v8/test/mjsunit/array-splice.js | 311 + deps/v8/test/mjsunit/ascii-regexp-subject.js | 49 + deps/v8/test/mjsunit/big-array-literal.js | 111 + deps/v8/test/mjsunit/big-object-literal.js | 114 + .../mjsunit/binary-operation-overwrite.js | 36 + deps/v8/test/mjsunit/body-not-visible.js | 39 + deps/v8/test/mjsunit/bugs/bug-1344252.js | 79 + deps/v8/test/mjsunit/bugs/bug-222.js | 42 + deps/v8/test/mjsunit/bugs/bug-223.js | 39 + deps/v8/test/mjsunit/bugs/bug-900066.js | 38 + deps/v8/test/mjsunit/bugs/bug-941049.js | 100 + .../v8/test/mjsunit/call-non-function-call.js | 38 + deps/v8/test/mjsunit/call-non-function.js | 54 + deps/v8/test/mjsunit/call.js | 87 + deps/v8/test/mjsunit/char-escape.js | 53 + deps/v8/test/mjsunit/class-of-builtins.js | 50 + deps/v8/test/mjsunit/closure.js | 37 + deps/v8/test/mjsunit/compare-nan.js | 44 + deps/v8/test/mjsunit/const-declaration.js | 172 + deps/v8/test/mjsunit/const-eval-init.js | 111 + deps/v8/test/mjsunit/const-redecl.js | 220 + deps/v8/test/mjsunit/const.js | 70 + deps/v8/test/mjsunit/constant-folding.js | 171 + .../mjsunit/context-variable-assignments.js | 37 + .../v8/test/mjsunit/cyclic-array-to-string.js | 65 + deps/v8/test/mjsunit/d8-os.js | 180 + deps/v8/test/mjsunit/date-parse.js | 268 + deps/v8/test/mjsunit/date.js | 149 + deps/v8/test/mjsunit/debug-backtrace-text.js | 122 + deps/v8/test/mjsunit/debug-backtrace.js | 227 + deps/v8/test/mjsunit/debug-breakpoints.js | 120 + .../v8/test/mjsunit/debug-changebreakpoint.js | 108 + deps/v8/test/mjsunit/debug-clearbreakpoint.js | 101 + deps/v8/test/mjsunit/debug-compile-event.js | 95 + .../mjsunit/debug-conditional-breakpoints.js | 171 + deps/v8/test/mjsunit/debug-constructed-by.js | 60 + deps/v8/test/mjsunit/debug-constructor.js | 78 + deps/v8/test/mjsunit/debug-continue.js | 113 + .../debug-enable-disable-breakpoints.js | 90 + .../test/mjsunit/debug-evaluate-arguments.js | 93 + deps/v8/test/mjsunit/debug-evaluate-locals.js | 132 + .../test/mjsunit/debug-evaluate-recursive.js | 167 + deps/v8/test/mjsunit/debug-evaluate-with.js | 77 + deps/v8/test/mjsunit/debug-evaluate.js | 117 + deps/v8/test/mjsunit/debug-event-listener.js | 73 + deps/v8/test/mjsunit/debug-handle.js | 199 + .../test/mjsunit/debug-ignore-breakpoints.js | 89 + deps/v8/test/mjsunit/debug-mirror-cache.js | 85 + .../mjsunit/debug-multiple-breakpoints.js | 105 + deps/v8/test/mjsunit/debug-referenced-by.js | 112 + deps/v8/test/mjsunit/debug-references.js | 118 + .../test/mjsunit/debug-script-breakpoints.js | 112 + deps/v8/test/mjsunit/debug-script.js | 92 + deps/v8/test/mjsunit/debug-scripts-request.js | 95 + deps/v8/test/mjsunit/debug-setbreakpoint.js | 153 + deps/v8/test/mjsunit/debug-sourceinfo.js | 276 + deps/v8/test/mjsunit/debug-sourceslice.js | 74 + .../mjsunit/debug-step-stub-callfunction.js | 73 + deps/v8/test/mjsunit/debug-step.js | 82 + .../test/mjsunit/debug-stepin-constructor.js | 74 + deps/v8/test/mjsunit/declare-locally.js | 43 + deps/v8/test/mjsunit/deep-recursion.js | 64 + deps/v8/test/mjsunit/delay-syntax-error.js | 41 + .../test/mjsunit/delete-global-properties.js | 37 + deps/v8/test/mjsunit/delete-in-eval.js | 32 + deps/v8/test/mjsunit/delete-in-with.js | 34 + deps/v8/test/mjsunit/delete-vars-from-eval.js | 40 + deps/v8/test/mjsunit/delete.js | 163 + deps/v8/test/mjsunit/do-not-strip-fc.js | 31 + deps/v8/test/mjsunit/dont-enum-array-holes.js | 35 + .../v8/test/mjsunit/dont-reinit-global-var.js | 47 + deps/v8/test/mjsunit/double-equals.js | 114 + deps/v8/test/mjsunit/dtoa.js | 32 + deps/v8/test/mjsunit/enumeration-order.js | 59 + deps/v8/test/mjsunit/error-constructors.js | 32 + deps/v8/test/mjsunit/escape.js | 118 + .../test/mjsunit/eval-typeof-non-existing.js | 32 + deps/v8/test/mjsunit/eval.js | 136 + .../mjsunit/execScript-case-insensitive.js | 34 + deps/v8/test/mjsunit/extra-arguments.js | 54 + deps/v8/test/mjsunit/extra-commas.js | 46 + .../test/mjsunit/for-in-null-or-undefined.js | 33 + deps/v8/test/mjsunit/for-in-special-cases.js | 64 + deps/v8/test/mjsunit/for-in.js | 86 + deps/v8/test/mjsunit/fun-as-prototype.js | 36 + deps/v8/test/mjsunit/fun-name.js | 34 + .../test/mjsunit/function-arguments-null.js | 30 + deps/v8/test/mjsunit/function-caller.js | 48 + deps/v8/test/mjsunit/function-names.js | 133 + deps/v8/test/mjsunit/function-property.js | 29 + deps/v8/test/mjsunit/function-prototype.js | 97 + deps/v8/test/mjsunit/function-source.js | 49 + deps/v8/test/mjsunit/function.js | 83 + deps/v8/test/mjsunit/fuzz-accessors.js | 85 + deps/v8/test/mjsunit/fuzz-natives.js | 151 + deps/v8/test/mjsunit/getter-in-prototype.js | 50 + .../test/mjsunit/getter-in-value-prototype.js | 35 + .../mjsunit/global-const-var-conflicts.js | 57 + .../mjsunit/global-load-from-eval-in-with.js | 59 + deps/v8/test/mjsunit/global-load-from-eval.js | 85 + .../mjsunit/global-load-from-nested-eval.js | 66 + deps/v8/test/mjsunit/global-vars-eval.js | 34 + deps/v8/test/mjsunit/global-vars-with.js | 43 + deps/v8/test/mjsunit/greedy.js | 60 + deps/v8/test/mjsunit/has-own-property.js | 38 + deps/v8/test/mjsunit/html-comments.js | 57 + deps/v8/test/mjsunit/html-string-funcs.js | 47 + deps/v8/test/mjsunit/if-in-undefined.js | 36 + deps/v8/test/mjsunit/in.js | 159 + deps/v8/test/mjsunit/indexed-accessors.js | 120 + deps/v8/test/mjsunit/instanceof.js | 93 + deps/v8/test/mjsunit/integer-to-string.js | 35 + deps/v8/test/mjsunit/invalid-lhs.js | 68 + deps/v8/test/mjsunit/keyed-ic.js | 207 + deps/v8/test/mjsunit/keyed-storage-extend.js | 55 + .../test/mjsunit/large-object-allocation.js | 300 + deps/v8/test/mjsunit/large-object-literal.js | 56 + deps/v8/test/mjsunit/lazy-load.js | 34 + deps/v8/test/mjsunit/leakcheck.js | 53 + deps/v8/test/mjsunit/length.js | 78 + deps/v8/test/mjsunit/local-load-from-eval.js | 39 + deps/v8/test/mjsunit/math-min-max.js | 72 + deps/v8/test/mjsunit/megamorphic-callbacks.js | 70 + deps/v8/test/mjsunit/mirror-array.js | 137 + deps/v8/test/mjsunit/mirror-boolean.js | 59 + deps/v8/test/mjsunit/mirror-date.js | 75 + deps/v8/test/mjsunit/mirror-error.js | 93 + deps/v8/test/mjsunit/mirror-function.js | 89 + deps/v8/test/mjsunit/mirror-null.js | 50 + deps/v8/test/mjsunit/mirror-number.js | 77 + deps/v8/test/mjsunit/mirror-object.js | 227 + deps/v8/test/mjsunit/mirror-regexp.js | 109 + deps/v8/test/mjsunit/mirror-script.js | 92 + deps/v8/test/mjsunit/mirror-string.js | 89 + deps/v8/test/mjsunit/mirror-undefined.js | 50 + .../mjsunit/mirror-unresolved-function.js | 78 + deps/v8/test/mjsunit/mjsunit.js | 151 + deps/v8/test/mjsunit/mjsunit.status | 68 + deps/v8/test/mjsunit/mul-exhaustive.js | 4511 ++++++++ deps/v8/test/mjsunit/multiple-return.js | 62 + deps/v8/test/mjsunit/negate-zero.js | 42 + deps/v8/test/mjsunit/negate.js | 59 + deps/v8/test/mjsunit/new.js | 56 + deps/v8/test/mjsunit/newline-in-string.js | 46 + deps/v8/test/mjsunit/no-branch-elimination.js | 36 + .../mjsunit/no-octal-constants-above-256.js | 32 + deps/v8/test/mjsunit/no-semicolon.js | 45 + deps/v8/test/mjsunit/non-ascii-replace.js | 30 + deps/v8/test/mjsunit/nul-characters.js | 38 + deps/v8/test/mjsunit/number-limits.js | 43 + .../test/mjsunit/number-string-index-call.js | 32 + deps/v8/test/mjsunit/number-tostring-small.js | 395 + deps/v8/test/mjsunit/number-tostring.js | 338 + deps/v8/test/mjsunit/obj-construct.js | 46 + deps/v8/test/mjsunit/object-literal-gc.js | 66 + deps/v8/test/mjsunit/object-literal.js | 105 + .../mjsunit/override-read-only-property.js | 64 + deps/v8/test/mjsunit/parse-int-float.js | 82 + .../test/mjsunit/property-load-across-eval.js | 85 + deps/v8/test/mjsunit/property-object-key.js | 36 + deps/v8/test/mjsunit/proto.js | 33 + deps/v8/test/mjsunit/prototype.js | 93 + deps/v8/test/mjsunit/regexp-UC16.js | 47 + deps/v8/test/mjsunit/regexp-capture.js | 57 + deps/v8/test/mjsunit/regexp-indexof.js | 77 + deps/v8/test/mjsunit/regexp-lookahead.js | 166 + deps/v8/test/mjsunit/regexp-loop-capture.js | 29 + .../mjsunit/regexp-multiline-stack-trace.js | 114 + deps/v8/test/mjsunit/regexp-multiline.js | 112 + deps/v8/test/mjsunit/regexp-pcre.js | 6603 ++++++++++++ deps/v8/test/mjsunit/regexp-standalones.js | 78 + deps/v8/test/mjsunit/regexp-static.js | 167 + deps/v8/test/mjsunit/regexp-string-methods.js | 51 + deps/v8/test/mjsunit/regexp.js | 377 + .../test/mjsunit/regress/regress-1030466.js | 45 + .../test/mjsunit/regress/regress-1036894.js | 38 + .../test/mjsunit/regress/regress-1039610.js | 29 + .../test/mjsunit/regress/regress-1050043.js | 51 + .../test/mjsunit/regress/regress-1062422.js | 30 + .../test/mjsunit/regress/regress-1066899.js | 37 + .../test/mjsunit/regress/regress-1081309.js | 110 + .../test/mjsunit/regress/regress-1102760.js | 35 + .../test/mjsunit/regress/regress-1110164.js | 46 + .../test/mjsunit/regress/regress-1112051.js | 33 + .../test/mjsunit/regress/regress-1114040.js | 58 + .../test/mjsunit/regress/regress-1134697.js | 31 + deps/v8/test/mjsunit/regress/regress-114.js | 43 + deps/v8/test/mjsunit/regress/regress-116.js | 40 + .../test/mjsunit/regress/regress-1170187.js | 80 + .../test/mjsunit/regress/regress-1173979.js | 48 + .../test/mjsunit/regress/regress-1175390.js | 30 + .../test/mjsunit/regress/regress-1177518.js | 39 + .../test/mjsunit/regress/regress-1177809.js | 31 + .../test/mjsunit/regress/regress-1178598.js | 90 + .../test/mjsunit/regress/regress-1182832.js | 38 + .../test/mjsunit/regress/regress-1187524.js | 34 + .../test/mjsunit/regress/regress-1199401.js | 61 + .../test/mjsunit/regress/regress-1199637.js | 78 + .../test/mjsunit/regress/regress-1200351.js | 2032 ++++ .../test/mjsunit/regress/regress-1201933.js | 40 + .../test/mjsunit/regress/regress-1203459.js | 29 + .../test/mjsunit/regress/regress-1207276.js | 36 + .../test/mjsunit/regress/regress-1213516.js | 40 + .../test/mjsunit/regress/regress-1213575.js | 41 + .../test/mjsunit/regress/regress-1215653.js | 365 + deps/v8/test/mjsunit/regress/regress-124.js | 57 + .../test/mjsunit/regress/regress-1254366.js | 38 + .../test/mjsunit/regress/regress-1327557.js | 36 + .../test/mjsunit/regress/regress-1341167.js | 33 + .../test/mjsunit/regress/regress-1346700.js | 29 + deps/v8/test/mjsunit/regress/regress-137.js | 46 + .../test/mjsunit/regress/regress-1439135.js | 40 + deps/v8/test/mjsunit/regress/regress-149.js | 28 + .../test/mjsunit/regress/regress-1493017.js | 52 + deps/v8/test/mjsunit/regress/regress-171.js | 41 + deps/v8/test/mjsunit/regress/regress-176.js | 50 + deps/v8/test/mjsunit/regress/regress-186.js | 72 + deps/v8/test/mjsunit/regress/regress-187.js | 30 + deps/v8/test/mjsunit/regress/regress-189.js | 36 + deps/v8/test/mjsunit/regress/regress-191.js | 42 + deps/v8/test/mjsunit/regress/regress-192.js | 38 + deps/v8/test/mjsunit/regress/regress-193.js | 44 + .../test/mjsunit/regress/regress-20070207.js | 42 + deps/v8/test/mjsunit/regress/regress-201.js | 37 + deps/v8/test/mjsunit/regress/regress-219.js | 176 + deps/v8/test/mjsunit/regress/regress-220.js | 31 + deps/v8/test/mjsunit/regress/regress-221.js | 34 + deps/v8/test/mjsunit/regress/regress-225.js | 32 + deps/v8/test/mjsunit/regress/regress-227.js | 33 + deps/v8/test/mjsunit/regress/regress-231.js | 92 + deps/v8/test/mjsunit/regress/regress-233.js | 39 + deps/v8/test/mjsunit/regress/regress-244.js | 67 + deps/v8/test/mjsunit/regress/regress-246.js | 31 + deps/v8/test/mjsunit/regress/regress-253.js | 31 + deps/v8/test/mjsunit/regress/regress-254.js | 58 + deps/v8/test/mjsunit/regress/regress-259.js | 33 + deps/v8/test/mjsunit/regress/regress-260.js | 33 + deps/v8/test/mjsunit/regress/regress-263.js | 38 + deps/v8/test/mjsunit/regress/regress-265.js | 64 + deps/v8/test/mjsunit/regress/regress-267.js | 35 + deps/v8/test/mjsunit/regress/regress-269.js | 49 + deps/v8/test/mjsunit/regress/regress-279.js | 62 + deps/v8/test/mjsunit/regress/regress-284.js | 50 + deps/v8/test/mjsunit/regress/regress-286.js | 36 + deps/v8/test/mjsunit/regress/regress-294.js | 43 + deps/v8/test/mjsunit/regress/regress-312.js | 31 + deps/v8/test/mjsunit/regress/regress-317.js | 31 + deps/v8/test/mjsunit/regress/regress-318.js | 35 + deps/v8/test/mjsunit/regress/regress-35.js | 33 + deps/v8/test/mjsunit/regress/regress-57.js | 32 + .../v8/test/mjsunit/regress/regress-588599.js | 31 + .../v8/test/mjsunit/regress/regress-662254.js | 40 + .../v8/test/mjsunit/regress/regress-666721.js | 53 + .../v8/test/mjsunit/regress/regress-667061.js | 90 + .../v8/test/mjsunit/regress/regress-670147.js | 34 + .../v8/test/mjsunit/regress/regress-674753.js | 87 + .../v8/test/mjsunit/regress/regress-676025.js | 31 + .../v8/test/mjsunit/regress/regress-678525.js | 59 + .../v8/test/mjsunit/regress/regress-682649.js | 30 + deps/v8/test/mjsunit/regress/regress-69.js | 43 + .../v8/test/mjsunit/regress/regress-734862.js | 37 + .../v8/test/mjsunit/regress/regress-737588.js | 34 + deps/v8/test/mjsunit/regress/regress-74.js | 41 + .../v8/test/mjsunit/regress/regress-780423.js | 39 + .../v8/test/mjsunit/regress/regress-799761.js | 92 + .../v8/test/mjsunit/regress/regress-806473.js | 60 + .../v8/test/mjsunit/regress/regress-842017.js | 60 + deps/v8/test/mjsunit/regress/regress-86.js | 46 + deps/v8/test/mjsunit/regress/regress-87.js | 58 + .../v8/test/mjsunit/regress/regress-874178.js | 32 + .../v8/test/mjsunit/regress/regress-875031.js | 37 + .../v8/test/mjsunit/regress/regress-877615.js | 37 + .../v8/test/mjsunit/regress/regress-892742.js | 50 + .../v8/test/mjsunit/regress/regress-900055.js | 42 + .../v8/test/mjsunit/regress/regress-900966.js | 38 + deps/v8/test/mjsunit/regress/regress-91.js | 38 + .../v8/test/mjsunit/regress/regress-925537.js | 42 + .../v8/test/mjsunit/regress/regress-937896.js | 50 + .../v8/test/mjsunit/regress/regress-990205.js | 35 + .../v8/test/mjsunit/regress/regress-992733.js | 35 + .../v8/test/mjsunit/regress/regress-996542.js | 40 + .../v8/test/mjsunit/regress/regress-998565.js | 51 + deps/v8/test/mjsunit/scanner.js | 30 + deps/v8/test/mjsunit/short-circuit-boolean.js | 46 + deps/v8/test/mjsunit/smi-negative-zero.js | 100 + deps/v8/test/mjsunit/smi-ops.js | 102 + deps/v8/test/mjsunit/sparse-array-reverse.js | 131 + deps/v8/test/mjsunit/sparse-array.js | 41 + deps/v8/test/mjsunit/str-to-num.js | 158 + deps/v8/test/mjsunit/stress-array-push.js | 34 + deps/v8/test/mjsunit/strict-equals.js | 90 + deps/v8/test/mjsunit/string-add.js | 175 + deps/v8/test/mjsunit/string-case.js | 28 + deps/v8/test/mjsunit/string-charat.js | 53 + deps/v8/test/mjsunit/string-charcodeat.js | 189 + .../test/mjsunit/string-compare-alignment.js | 47 + deps/v8/test/mjsunit/string-flatten.js | 37 + deps/v8/test/mjsunit/string-index.js | 154 + deps/v8/test/mjsunit/string-indexof.js | 142 + deps/v8/test/mjsunit/string-lastindexof.js | 51 + deps/v8/test/mjsunit/string-localecompare.js | 40 + deps/v8/test/mjsunit/string-match.js | 149 + deps/v8/test/mjsunit/string-replace-gc.js | 57 + deps/v8/test/mjsunit/string-replace.js | 182 + deps/v8/test/mjsunit/string-search.js | 30 + deps/v8/test/mjsunit/string-split.js | 126 + deps/v8/test/mjsunit/substr.js | 65 + deps/v8/test/mjsunit/switch.js | 289 + deps/v8/test/mjsunit/testcfg.py | 106 + deps/v8/test/mjsunit/this-in-callbacks.js | 47 + deps/v8/test/mjsunit/this.js | 46 + .../test/mjsunit/throw-and-catch-function.js | 50 + .../throw-exception-for-null-access.js | 37 + deps/v8/test/mjsunit/to-precision.js | 82 + deps/v8/test/mjsunit/tobool.js | 36 + deps/v8/test/mjsunit/toint32.js | 129 + deps/v8/test/mjsunit/tools/splaytree.js | 166 + deps/v8/test/mjsunit/top-level-assignments.js | 107 + deps/v8/test/mjsunit/touint32.js | 72 + .../mjsunit/try-catch-extension-object.js | 58 + deps/v8/test/mjsunit/try-catch-scopes.js | 42 + deps/v8/test/mjsunit/try-finally-nested.js | 46 + deps/v8/test/mjsunit/try.js | 349 + .../test/mjsunit/unicode-string-to-number.js | 46 + deps/v8/test/mjsunit/unicode-test.js | 9169 +++++++++++++++++ deps/v8/test/mjsunit/unusual-constructor.js | 38 + deps/v8/test/mjsunit/uri.js | 78 + .../mjsunit/value-callic-prototype-change.js | 94 + deps/v8/test/mjsunit/var.js | 37 + .../test/mjsunit/with-function-expression.js | 36 + deps/v8/test/mjsunit/with-leave.js | 61 + deps/v8/test/mjsunit/with-parameter-access.js | 47 + deps/v8/test/mjsunit/with-prototype.js | 44 + deps/v8/test/mjsunit/with-value.js | 38 + .../test/mozilla/mozilla-shell-emulation.js | 37 + deps/v8/test/mozilla/mozilla.status | 821 ++ deps/v8/test/mozilla/testcfg.py | 136 + deps/v8/tools/js2c.py | 365 + deps/v8/tools/jsmin.py | 218 + deps/v8/tools/linux-tick-processor.py | 78 + deps/v8/tools/presubmit.py | 231 + deps/v8/tools/run-valgrind.py | 77 + deps/v8/tools/splaytree.js | 322 + deps/v8/tools/splaytree.py | 226 + deps/v8/tools/stats-viewer.py | 372 + deps/v8/tools/test.py | 1330 +++ deps/v8/tools/tickprocessor.py | 535 + deps/v8/tools/utils.py | 80 + deps/v8/tools/v8.xcodeproj/project.pbxproj | 1598 +++ deps/v8/tools/visual_studio/README.txt | 71 + deps/v8/tools/visual_studio/arm.vsprops | 12 + deps/v8/tools/visual_studio/common.vsprops | 37 + deps/v8/tools/visual_studio/d8.vcproj | 199 + deps/v8/tools/visual_studio/d8js2c.cmd | 6 + deps/v8/tools/visual_studio/debug.vsprops | 17 + deps/v8/tools/visual_studio/js2c.cmd | 6 + deps/v8/tools/visual_studio/release.vsprops | 24 + deps/v8/tools/visual_studio/v8.sln | 101 + deps/v8/tools/visual_studio/v8.vcproj | 219 + deps/v8/tools/visual_studio/v8_arm.sln | 74 + deps/v8/tools/visual_studio/v8_base.vcproj | 923 ++ .../v8/tools/visual_studio/v8_base_arm.vcproj | 919 ++ deps/v8/tools/visual_studio/v8_cctest.vcproj | 239 + .../tools/visual_studio/v8_cctest_arm.vcproj | 225 + .../tools/visual_studio/v8_mksnapshot.vcproj | 151 + .../visual_studio/v8_process_sample.vcproj | 151 + .../visual_studio/v8_shell_sample.vcproj | 151 + .../v8/tools/visual_studio/v8_snapshot.vcproj | 142 + .../tools/visual_studio/v8_snapshot_cc.vcproj | 92 + deps/v8/tools/windows-tick-processor.py | 137 + wscript | 18 +- 763 files changed, 265280 insertions(+), 22 deletions(-) create mode 100644 deps/libebb/.gitignore create mode 100644 deps/libebb/LICENSE create mode 100644 deps/libebb/README create mode 100644 deps/libebb/config.mk create mode 100644 deps/libebb/doc/icon.png create mode 100644 deps/libebb/doc/index.html create mode 100644 deps/libebb/ebb.c create mode 100644 deps/libebb/ebb.h create mode 100644 deps/libebb/ebb_request_parser.h create mode 100644 deps/libebb/ebb_request_parser.rl create mode 100644 deps/libebb/examples/ca-cert.pem create mode 100644 deps/libebb/examples/ca-key.pem create mode 100644 deps/libebb/examples/hello_world.c create mode 100644 deps/libebb/rbtree.c create mode 100644 deps/libebb/rbtree.h create mode 100644 deps/libebb/test_examples.rb create mode 100644 deps/libebb/test_rbtree.c create mode 100644 deps/libebb/test_request_parser.c create mode 100644 deps/liboi/LICENSE create mode 100644 deps/liboi/README create mode 100644 deps/liboi/config.mk create mode 100644 deps/liboi/oi.h create mode 100644 deps/liboi/oi.pod create mode 100644 deps/liboi/oi_async.c create mode 100644 deps/liboi/oi_async.h create mode 100644 deps/liboi/oi_buf.c create mode 100644 deps/liboi/oi_buf.h create mode 100644 deps/liboi/oi_error.h create mode 100644 deps/liboi/oi_file.c create mode 100644 deps/liboi/oi_file.h create mode 100644 deps/liboi/oi_queue.h create mode 100644 deps/liboi/oi_socket.c create mode 100644 deps/liboi/oi_socket.h create mode 100644 deps/liboi/test/common.c create mode 100644 deps/liboi/test/connection_interruption.c create mode 100644 deps/liboi/test/echo.c create mode 100644 deps/liboi/test/fancy_copy.c create mode 100644 deps/liboi/test/ping_pong.c create mode 100644 deps/liboi/test/sleeping_tasks.c create mode 100644 deps/liboi/test/stdout.c create mode 100755 deps/liboi/test/timeout.rb create mode 100644 deps/v8/AUTHORS create mode 100644 deps/v8/ChangeLog create mode 100644 deps/v8/LICENSE create mode 100644 deps/v8/SConstruct create mode 100644 deps/v8/benchmarks/README.txt create mode 100644 deps/v8/benchmarks/base.js create mode 100644 deps/v8/benchmarks/crypto.js create mode 100644 deps/v8/benchmarks/deltablue.js create mode 100644 deps/v8/benchmarks/earley-boyer.js create mode 100644 deps/v8/benchmarks/raytrace.js create mode 100644 deps/v8/benchmarks/regexp.js create mode 100644 deps/v8/benchmarks/revisions.html create mode 100644 deps/v8/benchmarks/richards.js create mode 100644 deps/v8/benchmarks/run.html create mode 100644 deps/v8/benchmarks/run.js create mode 100644 deps/v8/benchmarks/style.css create mode 100644 deps/v8/benchmarks/v8-logo.png create mode 100644 deps/v8/include/v8-debug.h create mode 100644 deps/v8/include/v8.h create mode 100644 deps/v8/samples/SConscript create mode 100644 deps/v8/samples/count-hosts.js create mode 100644 deps/v8/samples/process.cc create mode 100644 deps/v8/samples/shell.cc create mode 100644 deps/v8/scons-LICENSE create mode 100644 deps/v8/scons-README create mode 100755 deps/v8/scons-time.py create mode 100755 deps/v8/scons.py create mode 100755 deps/v8/sconsign.py create mode 100644 deps/v8/src/SConscript create mode 100644 deps/v8/src/accessors.cc create mode 100644 deps/v8/src/accessors.h create mode 100644 deps/v8/src/allocation.cc create mode 100644 deps/v8/src/allocation.h create mode 100644 deps/v8/src/api.cc create mode 100644 deps/v8/src/api.h create mode 100644 deps/v8/src/apinatives.js create mode 100644 deps/v8/src/apiutils.h create mode 100644 deps/v8/src/arguments.h create mode 100644 deps/v8/src/array.js create mode 100644 deps/v8/src/assembler-arm-inl.h create mode 100644 deps/v8/src/assembler-arm.cc create mode 100644 deps/v8/src/assembler-arm.h create mode 100644 deps/v8/src/assembler-ia32-inl.h create mode 100644 deps/v8/src/assembler-ia32.cc create mode 100644 deps/v8/src/assembler-ia32.h create mode 100644 deps/v8/src/assembler.cc create mode 100644 deps/v8/src/assembler.h create mode 100644 deps/v8/src/ast.cc create mode 100644 deps/v8/src/ast.h create mode 100644 deps/v8/src/bootstrapper.cc create mode 100644 deps/v8/src/bootstrapper.h create mode 100644 deps/v8/src/builtins-arm.cc create mode 100644 deps/v8/src/builtins-ia32.cc create mode 100644 deps/v8/src/builtins.cc create mode 100644 deps/v8/src/builtins.h create mode 100644 deps/v8/src/bytecodes-irregexp.h create mode 100644 deps/v8/src/char-predicates-inl.h create mode 100644 deps/v8/src/char-predicates.h create mode 100644 deps/v8/src/checks.cc create mode 100644 deps/v8/src/checks.h create mode 100644 deps/v8/src/code-stubs.cc create mode 100644 deps/v8/src/code-stubs.h create mode 100644 deps/v8/src/code.h create mode 100644 deps/v8/src/codegen-arm.cc create mode 100644 deps/v8/src/codegen-arm.h create mode 100644 deps/v8/src/codegen-ia32.cc create mode 100644 deps/v8/src/codegen-ia32.h create mode 100644 deps/v8/src/codegen-inl.h create mode 100644 deps/v8/src/codegen.cc create mode 100644 deps/v8/src/codegen.h create mode 100644 deps/v8/src/compilation-cache.cc create mode 100644 deps/v8/src/compilation-cache.h create mode 100644 deps/v8/src/compiler.cc create mode 100644 deps/v8/src/compiler.h create mode 100644 deps/v8/src/constants-arm.h create mode 100644 deps/v8/src/contexts.cc create mode 100644 deps/v8/src/contexts.h create mode 100644 deps/v8/src/conversions-inl.h create mode 100644 deps/v8/src/conversions.cc create mode 100644 deps/v8/src/conversions.h create mode 100644 deps/v8/src/counters.cc create mode 100644 deps/v8/src/counters.h create mode 100644 deps/v8/src/cpu-arm.cc create mode 100644 deps/v8/src/cpu-ia32.cc create mode 100644 deps/v8/src/cpu.h create mode 100644 deps/v8/src/d8-debug.cc create mode 100644 deps/v8/src/d8-debug.h create mode 100644 deps/v8/src/d8-posix.cc create mode 100644 deps/v8/src/d8-readline.cc create mode 100644 deps/v8/src/d8-windows.cc create mode 100644 deps/v8/src/d8.cc create mode 100644 deps/v8/src/d8.h create mode 100644 deps/v8/src/d8.js create mode 100644 deps/v8/src/date-delay.js create mode 100644 deps/v8/src/dateparser-inl.h create mode 100644 deps/v8/src/dateparser.cc create mode 100644 deps/v8/src/dateparser.h create mode 100644 deps/v8/src/debug-agent.cc create mode 100644 deps/v8/src/debug-agent.h create mode 100644 deps/v8/src/debug-arm.cc create mode 100644 deps/v8/src/debug-delay.js create mode 100644 deps/v8/src/debug-ia32.cc create mode 100644 deps/v8/src/debug.cc create mode 100644 deps/v8/src/debug.h create mode 100644 deps/v8/src/disasm-arm.cc create mode 100644 deps/v8/src/disasm-ia32.cc create mode 100644 deps/v8/src/disasm.h create mode 100644 deps/v8/src/disassembler.cc create mode 100644 deps/v8/src/disassembler.h create mode 100644 deps/v8/src/dtoa-config.c create mode 100644 deps/v8/src/execution.cc create mode 100644 deps/v8/src/execution.h create mode 100644 deps/v8/src/factory.cc create mode 100644 deps/v8/src/factory.h create mode 100644 deps/v8/src/flag-definitions.h create mode 100644 deps/v8/src/flags.cc create mode 100644 deps/v8/src/flags.h create mode 100644 deps/v8/src/frames-arm.cc create mode 100644 deps/v8/src/frames-arm.h create mode 100644 deps/v8/src/frames-ia32.cc create mode 100644 deps/v8/src/frames-ia32.h create mode 100644 deps/v8/src/frames-inl.h create mode 100644 deps/v8/src/frames.cc create mode 100644 deps/v8/src/frames.h create mode 100644 deps/v8/src/func-name-inferrer.cc create mode 100644 deps/v8/src/func-name-inferrer.h create mode 100644 deps/v8/src/global-handles.cc create mode 100644 deps/v8/src/global-handles.h create mode 100644 deps/v8/src/globals.h create mode 100644 deps/v8/src/handles-inl.h create mode 100644 deps/v8/src/handles.cc create mode 100644 deps/v8/src/handles.h create mode 100644 deps/v8/src/hashmap.cc create mode 100644 deps/v8/src/hashmap.h create mode 100644 deps/v8/src/heap-inl.h create mode 100644 deps/v8/src/heap.cc create mode 100644 deps/v8/src/heap.h create mode 100644 deps/v8/src/ic-arm.cc create mode 100644 deps/v8/src/ic-ia32.cc create mode 100644 deps/v8/src/ic-inl.h create mode 100644 deps/v8/src/ic.cc create mode 100644 deps/v8/src/ic.h create mode 100644 deps/v8/src/interpreter-irregexp.cc create mode 100644 deps/v8/src/interpreter-irregexp.h create mode 100644 deps/v8/src/jsregexp-inl.h create mode 100644 deps/v8/src/jsregexp.cc create mode 100644 deps/v8/src/jsregexp.h create mode 100644 deps/v8/src/jump-target-arm.cc create mode 100644 deps/v8/src/jump-target-ia32.cc create mode 100644 deps/v8/src/jump-target.cc create mode 100644 deps/v8/src/jump-target.h create mode 100644 deps/v8/src/list-inl.h create mode 100644 deps/v8/src/list.h create mode 100644 deps/v8/src/log.cc create mode 100644 deps/v8/src/log.h create mode 100644 deps/v8/src/macro-assembler-arm.cc create mode 100644 deps/v8/src/macro-assembler-arm.h create mode 100644 deps/v8/src/macro-assembler-ia32.cc create mode 100644 deps/v8/src/macro-assembler-ia32.h create mode 100644 deps/v8/src/macro-assembler.h create mode 100644 deps/v8/src/macros.py create mode 100644 deps/v8/src/mark-compact.cc create mode 100644 deps/v8/src/mark-compact.h create mode 100644 deps/v8/src/math.js create mode 100644 deps/v8/src/memory.h create mode 100644 deps/v8/src/messages.cc create mode 100644 deps/v8/src/messages.h create mode 100644 deps/v8/src/messages.js create mode 100644 deps/v8/src/mirror-delay.js create mode 100644 deps/v8/src/mksnapshot.cc create mode 100644 deps/v8/src/natives.h create mode 100644 deps/v8/src/objects-debug.cc create mode 100644 deps/v8/src/objects-inl.h create mode 100644 deps/v8/src/objects.cc create mode 100644 deps/v8/src/objects.h create mode 100644 deps/v8/src/oprofile-agent.cc create mode 100644 deps/v8/src/oprofile-agent.h create mode 100644 deps/v8/src/parser.cc create mode 100644 deps/v8/src/parser.h create mode 100644 deps/v8/src/platform-freebsd.cc create mode 100644 deps/v8/src/platform-linux.cc create mode 100644 deps/v8/src/platform-macos.cc create mode 100644 deps/v8/src/platform-nullos.cc create mode 100644 deps/v8/src/platform-posix.cc create mode 100644 deps/v8/src/platform-win32.cc create mode 100644 deps/v8/src/platform.h create mode 100644 deps/v8/src/prettyprinter.cc create mode 100644 deps/v8/src/prettyprinter.h create mode 100644 deps/v8/src/property.cc create mode 100644 deps/v8/src/property.h create mode 100644 deps/v8/src/regexp-delay.js create mode 100644 deps/v8/src/regexp-macro-assembler-arm.cc create mode 100644 deps/v8/src/regexp-macro-assembler-arm.h create mode 100644 deps/v8/src/regexp-macro-assembler-ia32.cc create mode 100644 deps/v8/src/regexp-macro-assembler-ia32.h create mode 100644 deps/v8/src/regexp-macro-assembler-irregexp-inl.h create mode 100644 deps/v8/src/regexp-macro-assembler-irregexp.cc create mode 100644 deps/v8/src/regexp-macro-assembler-irregexp.h create mode 100644 deps/v8/src/regexp-macro-assembler-tracer.cc create mode 100644 deps/v8/src/regexp-macro-assembler-tracer.h create mode 100644 deps/v8/src/regexp-macro-assembler.cc create mode 100644 deps/v8/src/regexp-macro-assembler.h create mode 100644 deps/v8/src/regexp-stack.cc create mode 100644 deps/v8/src/regexp-stack.h create mode 100644 deps/v8/src/register-allocator-arm.cc create mode 100644 deps/v8/src/register-allocator-ia32.cc create mode 100644 deps/v8/src/register-allocator-inl.h create mode 100644 deps/v8/src/register-allocator.cc create mode 100644 deps/v8/src/register-allocator.h create mode 100644 deps/v8/src/rewriter.cc create mode 100644 deps/v8/src/rewriter.h create mode 100644 deps/v8/src/runtime.cc create mode 100644 deps/v8/src/runtime.h create mode 100644 deps/v8/src/runtime.js create mode 100644 deps/v8/src/scanner.cc create mode 100644 deps/v8/src/scanner.h create mode 100644 deps/v8/src/scopeinfo.cc create mode 100644 deps/v8/src/scopeinfo.h create mode 100644 deps/v8/src/scopes.cc create mode 100644 deps/v8/src/scopes.h create mode 100644 deps/v8/src/serialize.cc create mode 100644 deps/v8/src/serialize.h create mode 100644 deps/v8/src/shell.h create mode 100644 deps/v8/src/simulator-arm.cc create mode 100644 deps/v8/src/simulator-arm.h create mode 100644 deps/v8/src/simulator-ia32.cc create mode 100644 deps/v8/src/simulator-ia32.h create mode 100644 deps/v8/src/smart-pointer.h create mode 100644 deps/v8/src/snapshot-common.cc create mode 100644 deps/v8/src/snapshot-empty.cc create mode 100644 deps/v8/src/snapshot.h create mode 100644 deps/v8/src/spaces-inl.h create mode 100644 deps/v8/src/spaces.cc create mode 100644 deps/v8/src/spaces.h create mode 100644 deps/v8/src/string-stream.cc create mode 100644 deps/v8/src/string-stream.h create mode 100644 deps/v8/src/string.js create mode 100644 deps/v8/src/stub-cache-arm.cc create mode 100644 deps/v8/src/stub-cache-ia32.cc create mode 100644 deps/v8/src/stub-cache.cc create mode 100644 deps/v8/src/stub-cache.h create mode 100644 deps/v8/src/third_party/dtoa/COPYING create mode 100644 deps/v8/src/third_party/dtoa/dtoa.c create mode 100644 deps/v8/src/token.cc create mode 100644 deps/v8/src/token.h create mode 100644 deps/v8/src/top.cc create mode 100644 deps/v8/src/top.h create mode 100644 deps/v8/src/unicode-inl.h create mode 100644 deps/v8/src/unicode.cc create mode 100644 deps/v8/src/unicode.h create mode 100644 deps/v8/src/uri.js create mode 100644 deps/v8/src/usage-analyzer.cc create mode 100644 deps/v8/src/usage-analyzer.h create mode 100644 deps/v8/src/utils.cc create mode 100644 deps/v8/src/utils.h create mode 100644 deps/v8/src/v8-counters.cc create mode 100644 deps/v8/src/v8-counters.h create mode 100644 deps/v8/src/v8.cc create mode 100644 deps/v8/src/v8.h create mode 100644 deps/v8/src/v8natives.js create mode 100644 deps/v8/src/v8threads.cc create mode 100644 deps/v8/src/v8threads.h create mode 100644 deps/v8/src/variables.cc create mode 100644 deps/v8/src/variables.h create mode 100644 deps/v8/src/virtual-frame-arm.cc create mode 100644 deps/v8/src/virtual-frame-arm.h create mode 100644 deps/v8/src/virtual-frame-ia32.cc create mode 100644 deps/v8/src/virtual-frame-ia32.h create mode 100644 deps/v8/src/virtual-frame.cc create mode 100644 deps/v8/src/virtual-frame.h create mode 100644 deps/v8/src/zone-inl.h create mode 100644 deps/v8/src/zone.cc create mode 100644 deps/v8/src/zone.h create mode 100644 deps/v8/test/cctest/SConscript create mode 100644 deps/v8/test/cctest/cctest.cc create mode 100644 deps/v8/test/cctest/cctest.h create mode 100644 deps/v8/test/cctest/cctest.status create mode 100644 deps/v8/test/cctest/test-alloc.cc create mode 100644 deps/v8/test/cctest/test-api.cc create mode 100644 deps/v8/test/cctest/test-assembler-arm.cc create mode 100644 deps/v8/test/cctest/test-assembler-ia32.cc create mode 100644 deps/v8/test/cctest/test-ast.cc create mode 100644 deps/v8/test/cctest/test-compiler.cc create mode 100644 deps/v8/test/cctest/test-conversions.cc create mode 100644 deps/v8/test/cctest/test-debug.cc create mode 100644 deps/v8/test/cctest/test-decls.cc create mode 100644 deps/v8/test/cctest/test-disasm-arm.cc create mode 100644 deps/v8/test/cctest/test-disasm-ia32.cc create mode 100644 deps/v8/test/cctest/test-flags.cc create mode 100644 deps/v8/test/cctest/test-func-name-inference.cc create mode 100644 deps/v8/test/cctest/test-hashmap.cc create mode 100644 deps/v8/test/cctest/test-heap.cc create mode 100644 deps/v8/test/cctest/test-list.cc create mode 100644 deps/v8/test/cctest/test-lock.cc create mode 100644 deps/v8/test/cctest/test-log-ia32.cc create mode 100644 deps/v8/test/cctest/test-mark-compact.cc create mode 100644 deps/v8/test/cctest/test-platform-linux.cc create mode 100644 deps/v8/test/cctest/test-platform-macos.cc create mode 100644 deps/v8/test/cctest/test-platform-nullos.cc create mode 100644 deps/v8/test/cctest/test-platform-win32.cc create mode 100644 deps/v8/test/cctest/test-regexp.cc create mode 100644 deps/v8/test/cctest/test-serialize.cc create mode 100644 deps/v8/test/cctest/test-sockets.cc create mode 100644 deps/v8/test/cctest/test-spaces.cc create mode 100644 deps/v8/test/cctest/test-strings.cc create mode 100644 deps/v8/test/cctest/test-threads.cc create mode 100644 deps/v8/test/cctest/test-utils.cc create mode 100644 deps/v8/test/cctest/testcfg.py create mode 100644 deps/v8/test/message/message.status create mode 100644 deps/v8/test/message/regress/regress-73.js create mode 100644 deps/v8/test/message/regress/regress-73.out create mode 100644 deps/v8/test/message/regress/regress-75.js create mode 100644 deps/v8/test/message/regress/regress-75.out create mode 100644 deps/v8/test/message/simple-throw.js create mode 100644 deps/v8/test/message/simple-throw.out create mode 100644 deps/v8/test/message/testcfg.py create mode 100644 deps/v8/test/message/try-catch-finally-no-message.js create mode 100644 deps/v8/test/message/try-catch-finally-no-message.out create mode 100644 deps/v8/test/message/try-catch-finally-return-in-finally.js create mode 100644 deps/v8/test/message/try-catch-finally-return-in-finally.out create mode 100644 deps/v8/test/message/try-catch-finally-throw-in-catch-and-finally.js create mode 100644 deps/v8/test/message/try-catch-finally-throw-in-catch-and-finally.out create mode 100644 deps/v8/test/message/try-catch-finally-throw-in-catch.js create mode 100644 deps/v8/test/message/try-catch-finally-throw-in-catch.out create mode 100644 deps/v8/test/message/try-catch-finally-throw-in-finally.js create mode 100644 deps/v8/test/message/try-catch-finally-throw-in-finally.out create mode 100644 deps/v8/test/message/try-finally-return-in-finally.js create mode 100644 deps/v8/test/message/try-finally-return-in-finally.out create mode 100644 deps/v8/test/message/try-finally-throw-in-finally.js create mode 100644 deps/v8/test/message/try-finally-throw-in-finally.out create mode 100644 deps/v8/test/message/try-finally-throw-in-try-and-finally.js create mode 100644 deps/v8/test/message/try-finally-throw-in-try-and-finally.out create mode 100644 deps/v8/test/message/try-finally-throw-in-try.js create mode 100644 deps/v8/test/message/try-finally-throw-in-try.out create mode 100644 deps/v8/test/mjsunit/api-call-after-bypassed-exception.js create mode 100644 deps/v8/test/mjsunit/apply.js create mode 100644 deps/v8/test/mjsunit/arguments-call-apply.js create mode 100644 deps/v8/test/mjsunit/arguments-enum.js create mode 100644 deps/v8/test/mjsunit/arguments-indirect.js create mode 100644 deps/v8/test/mjsunit/arguments-opt.js create mode 100644 deps/v8/test/mjsunit/arguments.js create mode 100644 deps/v8/test/mjsunit/array-concat.js create mode 100644 deps/v8/test/mjsunit/array-functions-prototype.js create mode 100644 deps/v8/test/mjsunit/array-indexing.js create mode 100644 deps/v8/test/mjsunit/array-iteration.js create mode 100644 deps/v8/test/mjsunit/array-join.js create mode 100644 deps/v8/test/mjsunit/array-length-number-conversion.js create mode 100644 deps/v8/test/mjsunit/array-length.js create mode 100644 deps/v8/test/mjsunit/array-sort.js create mode 100644 deps/v8/test/mjsunit/array-splice-webkit.js create mode 100644 deps/v8/test/mjsunit/array-splice.js create mode 100644 deps/v8/test/mjsunit/ascii-regexp-subject.js create mode 100644 deps/v8/test/mjsunit/big-array-literal.js create mode 100644 deps/v8/test/mjsunit/big-object-literal.js create mode 100644 deps/v8/test/mjsunit/binary-operation-overwrite.js create mode 100644 deps/v8/test/mjsunit/body-not-visible.js create mode 100644 deps/v8/test/mjsunit/bugs/bug-1344252.js create mode 100644 deps/v8/test/mjsunit/bugs/bug-222.js create mode 100644 deps/v8/test/mjsunit/bugs/bug-223.js create mode 100644 deps/v8/test/mjsunit/bugs/bug-900066.js create mode 100644 deps/v8/test/mjsunit/bugs/bug-941049.js create mode 100644 deps/v8/test/mjsunit/call-non-function-call.js create mode 100644 deps/v8/test/mjsunit/call-non-function.js create mode 100644 deps/v8/test/mjsunit/call.js create mode 100644 deps/v8/test/mjsunit/char-escape.js create mode 100644 deps/v8/test/mjsunit/class-of-builtins.js create mode 100644 deps/v8/test/mjsunit/closure.js create mode 100644 deps/v8/test/mjsunit/compare-nan.js create mode 100644 deps/v8/test/mjsunit/const-declaration.js create mode 100644 deps/v8/test/mjsunit/const-eval-init.js create mode 100644 deps/v8/test/mjsunit/const-redecl.js create mode 100644 deps/v8/test/mjsunit/const.js create mode 100644 deps/v8/test/mjsunit/constant-folding.js create mode 100644 deps/v8/test/mjsunit/context-variable-assignments.js create mode 100644 deps/v8/test/mjsunit/cyclic-array-to-string.js create mode 100644 deps/v8/test/mjsunit/d8-os.js create mode 100644 deps/v8/test/mjsunit/date-parse.js create mode 100644 deps/v8/test/mjsunit/date.js create mode 100644 deps/v8/test/mjsunit/debug-backtrace-text.js create mode 100644 deps/v8/test/mjsunit/debug-backtrace.js create mode 100644 deps/v8/test/mjsunit/debug-breakpoints.js create mode 100644 deps/v8/test/mjsunit/debug-changebreakpoint.js create mode 100644 deps/v8/test/mjsunit/debug-clearbreakpoint.js create mode 100644 deps/v8/test/mjsunit/debug-compile-event.js create mode 100644 deps/v8/test/mjsunit/debug-conditional-breakpoints.js create mode 100644 deps/v8/test/mjsunit/debug-constructed-by.js create mode 100644 deps/v8/test/mjsunit/debug-constructor.js create mode 100644 deps/v8/test/mjsunit/debug-continue.js create mode 100644 deps/v8/test/mjsunit/debug-enable-disable-breakpoints.js create mode 100644 deps/v8/test/mjsunit/debug-evaluate-arguments.js create mode 100644 deps/v8/test/mjsunit/debug-evaluate-locals.js create mode 100644 deps/v8/test/mjsunit/debug-evaluate-recursive.js create mode 100644 deps/v8/test/mjsunit/debug-evaluate-with.js create mode 100644 deps/v8/test/mjsunit/debug-evaluate.js create mode 100644 deps/v8/test/mjsunit/debug-event-listener.js create mode 100644 deps/v8/test/mjsunit/debug-handle.js create mode 100644 deps/v8/test/mjsunit/debug-ignore-breakpoints.js create mode 100644 deps/v8/test/mjsunit/debug-mirror-cache.js create mode 100644 deps/v8/test/mjsunit/debug-multiple-breakpoints.js create mode 100644 deps/v8/test/mjsunit/debug-referenced-by.js create mode 100644 deps/v8/test/mjsunit/debug-references.js create mode 100644 deps/v8/test/mjsunit/debug-script-breakpoints.js create mode 100644 deps/v8/test/mjsunit/debug-script.js create mode 100644 deps/v8/test/mjsunit/debug-scripts-request.js create mode 100644 deps/v8/test/mjsunit/debug-setbreakpoint.js create mode 100644 deps/v8/test/mjsunit/debug-sourceinfo.js create mode 100644 deps/v8/test/mjsunit/debug-sourceslice.js create mode 100644 deps/v8/test/mjsunit/debug-step-stub-callfunction.js create mode 100644 deps/v8/test/mjsunit/debug-step.js create mode 100644 deps/v8/test/mjsunit/debug-stepin-constructor.js create mode 100644 deps/v8/test/mjsunit/declare-locally.js create mode 100644 deps/v8/test/mjsunit/deep-recursion.js create mode 100644 deps/v8/test/mjsunit/delay-syntax-error.js create mode 100644 deps/v8/test/mjsunit/delete-global-properties.js create mode 100644 deps/v8/test/mjsunit/delete-in-eval.js create mode 100644 deps/v8/test/mjsunit/delete-in-with.js create mode 100644 deps/v8/test/mjsunit/delete-vars-from-eval.js create mode 100644 deps/v8/test/mjsunit/delete.js create mode 100644 deps/v8/test/mjsunit/do-not-strip-fc.js create mode 100644 deps/v8/test/mjsunit/dont-enum-array-holes.js create mode 100644 deps/v8/test/mjsunit/dont-reinit-global-var.js create mode 100644 deps/v8/test/mjsunit/double-equals.js create mode 100644 deps/v8/test/mjsunit/dtoa.js create mode 100644 deps/v8/test/mjsunit/enumeration-order.js create mode 100644 deps/v8/test/mjsunit/error-constructors.js create mode 100644 deps/v8/test/mjsunit/escape.js create mode 100644 deps/v8/test/mjsunit/eval-typeof-non-existing.js create mode 100644 deps/v8/test/mjsunit/eval.js create mode 100644 deps/v8/test/mjsunit/execScript-case-insensitive.js create mode 100644 deps/v8/test/mjsunit/extra-arguments.js create mode 100644 deps/v8/test/mjsunit/extra-commas.js create mode 100644 deps/v8/test/mjsunit/for-in-null-or-undefined.js create mode 100644 deps/v8/test/mjsunit/for-in-special-cases.js create mode 100644 deps/v8/test/mjsunit/for-in.js create mode 100644 deps/v8/test/mjsunit/fun-as-prototype.js create mode 100644 deps/v8/test/mjsunit/fun-name.js create mode 100644 deps/v8/test/mjsunit/function-arguments-null.js create mode 100644 deps/v8/test/mjsunit/function-caller.js create mode 100644 deps/v8/test/mjsunit/function-names.js create mode 100644 deps/v8/test/mjsunit/function-property.js create mode 100644 deps/v8/test/mjsunit/function-prototype.js create mode 100644 deps/v8/test/mjsunit/function-source.js create mode 100644 deps/v8/test/mjsunit/function.js create mode 100644 deps/v8/test/mjsunit/fuzz-accessors.js create mode 100644 deps/v8/test/mjsunit/fuzz-natives.js create mode 100644 deps/v8/test/mjsunit/getter-in-prototype.js create mode 100644 deps/v8/test/mjsunit/getter-in-value-prototype.js create mode 100644 deps/v8/test/mjsunit/global-const-var-conflicts.js create mode 100644 deps/v8/test/mjsunit/global-load-from-eval-in-with.js create mode 100644 deps/v8/test/mjsunit/global-load-from-eval.js create mode 100644 deps/v8/test/mjsunit/global-load-from-nested-eval.js create mode 100644 deps/v8/test/mjsunit/global-vars-eval.js create mode 100644 deps/v8/test/mjsunit/global-vars-with.js create mode 100644 deps/v8/test/mjsunit/greedy.js create mode 100644 deps/v8/test/mjsunit/has-own-property.js create mode 100644 deps/v8/test/mjsunit/html-comments.js create mode 100644 deps/v8/test/mjsunit/html-string-funcs.js create mode 100644 deps/v8/test/mjsunit/if-in-undefined.js create mode 100644 deps/v8/test/mjsunit/in.js create mode 100644 deps/v8/test/mjsunit/indexed-accessors.js create mode 100644 deps/v8/test/mjsunit/instanceof.js create mode 100644 deps/v8/test/mjsunit/integer-to-string.js create mode 100644 deps/v8/test/mjsunit/invalid-lhs.js create mode 100644 deps/v8/test/mjsunit/keyed-ic.js create mode 100644 deps/v8/test/mjsunit/keyed-storage-extend.js create mode 100644 deps/v8/test/mjsunit/large-object-allocation.js create mode 100644 deps/v8/test/mjsunit/large-object-literal.js create mode 100644 deps/v8/test/mjsunit/lazy-load.js create mode 100644 deps/v8/test/mjsunit/leakcheck.js create mode 100644 deps/v8/test/mjsunit/length.js create mode 100644 deps/v8/test/mjsunit/local-load-from-eval.js create mode 100644 deps/v8/test/mjsunit/math-min-max.js create mode 100644 deps/v8/test/mjsunit/megamorphic-callbacks.js create mode 100644 deps/v8/test/mjsunit/mirror-array.js create mode 100644 deps/v8/test/mjsunit/mirror-boolean.js create mode 100644 deps/v8/test/mjsunit/mirror-date.js create mode 100644 deps/v8/test/mjsunit/mirror-error.js create mode 100644 deps/v8/test/mjsunit/mirror-function.js create mode 100644 deps/v8/test/mjsunit/mirror-null.js create mode 100644 deps/v8/test/mjsunit/mirror-number.js create mode 100644 deps/v8/test/mjsunit/mirror-object.js create mode 100644 deps/v8/test/mjsunit/mirror-regexp.js create mode 100644 deps/v8/test/mjsunit/mirror-script.js create mode 100644 deps/v8/test/mjsunit/mirror-string.js create mode 100644 deps/v8/test/mjsunit/mirror-undefined.js create mode 100644 deps/v8/test/mjsunit/mirror-unresolved-function.js create mode 100644 deps/v8/test/mjsunit/mjsunit.js create mode 100644 deps/v8/test/mjsunit/mjsunit.status create mode 100644 deps/v8/test/mjsunit/mul-exhaustive.js create mode 100644 deps/v8/test/mjsunit/multiple-return.js create mode 100644 deps/v8/test/mjsunit/negate-zero.js create mode 100644 deps/v8/test/mjsunit/negate.js create mode 100644 deps/v8/test/mjsunit/new.js create mode 100644 deps/v8/test/mjsunit/newline-in-string.js create mode 100644 deps/v8/test/mjsunit/no-branch-elimination.js create mode 100644 deps/v8/test/mjsunit/no-octal-constants-above-256.js create mode 100644 deps/v8/test/mjsunit/no-semicolon.js create mode 100644 deps/v8/test/mjsunit/non-ascii-replace.js create mode 100644 deps/v8/test/mjsunit/nul-characters.js create mode 100644 deps/v8/test/mjsunit/number-limits.js create mode 100644 deps/v8/test/mjsunit/number-string-index-call.js create mode 100644 deps/v8/test/mjsunit/number-tostring-small.js create mode 100644 deps/v8/test/mjsunit/number-tostring.js create mode 100644 deps/v8/test/mjsunit/obj-construct.js create mode 100644 deps/v8/test/mjsunit/object-literal-gc.js create mode 100644 deps/v8/test/mjsunit/object-literal.js create mode 100644 deps/v8/test/mjsunit/override-read-only-property.js create mode 100644 deps/v8/test/mjsunit/parse-int-float.js create mode 100644 deps/v8/test/mjsunit/property-load-across-eval.js create mode 100644 deps/v8/test/mjsunit/property-object-key.js create mode 100644 deps/v8/test/mjsunit/proto.js create mode 100644 deps/v8/test/mjsunit/prototype.js create mode 100644 deps/v8/test/mjsunit/regexp-UC16.js create mode 100755 deps/v8/test/mjsunit/regexp-capture.js create mode 100644 deps/v8/test/mjsunit/regexp-indexof.js create mode 100644 deps/v8/test/mjsunit/regexp-lookahead.js create mode 100644 deps/v8/test/mjsunit/regexp-loop-capture.js create mode 100644 deps/v8/test/mjsunit/regexp-multiline-stack-trace.js create mode 100644 deps/v8/test/mjsunit/regexp-multiline.js create mode 100644 deps/v8/test/mjsunit/regexp-pcre.js create mode 100644 deps/v8/test/mjsunit/regexp-standalones.js create mode 100644 deps/v8/test/mjsunit/regexp-static.js create mode 100644 deps/v8/test/mjsunit/regexp-string-methods.js create mode 100644 deps/v8/test/mjsunit/regexp.js create mode 100644 deps/v8/test/mjsunit/regress/regress-1030466.js create mode 100644 deps/v8/test/mjsunit/regress/regress-1036894.js create mode 100644 deps/v8/test/mjsunit/regress/regress-1039610.js create mode 100644 deps/v8/test/mjsunit/regress/regress-1050043.js create mode 100644 deps/v8/test/mjsunit/regress/regress-1062422.js create mode 100644 deps/v8/test/mjsunit/regress/regress-1066899.js create mode 100644 deps/v8/test/mjsunit/regress/regress-1081309.js create mode 100644 deps/v8/test/mjsunit/regress/regress-1102760.js create mode 100644 deps/v8/test/mjsunit/regress/regress-1110164.js create mode 100644 deps/v8/test/mjsunit/regress/regress-1112051.js create mode 100644 deps/v8/test/mjsunit/regress/regress-1114040.js create mode 100644 deps/v8/test/mjsunit/regress/regress-1134697.js create mode 100644 deps/v8/test/mjsunit/regress/regress-114.js create mode 100644 deps/v8/test/mjsunit/regress/regress-116.js create mode 100644 deps/v8/test/mjsunit/regress/regress-1170187.js create mode 100644 deps/v8/test/mjsunit/regress/regress-1173979.js create mode 100644 deps/v8/test/mjsunit/regress/regress-1175390.js create mode 100644 deps/v8/test/mjsunit/regress/regress-1177518.js create mode 100644 deps/v8/test/mjsunit/regress/regress-1177809.js create mode 100644 deps/v8/test/mjsunit/regress/regress-1178598.js create mode 100644 deps/v8/test/mjsunit/regress/regress-1182832.js create mode 100644 deps/v8/test/mjsunit/regress/regress-1187524.js create mode 100644 deps/v8/test/mjsunit/regress/regress-1199401.js create mode 100644 deps/v8/test/mjsunit/regress/regress-1199637.js create mode 100644 deps/v8/test/mjsunit/regress/regress-1200351.js create mode 100644 deps/v8/test/mjsunit/regress/regress-1201933.js create mode 100644 deps/v8/test/mjsunit/regress/regress-1203459.js create mode 100644 deps/v8/test/mjsunit/regress/regress-1207276.js create mode 100644 deps/v8/test/mjsunit/regress/regress-1213516.js create mode 100644 deps/v8/test/mjsunit/regress/regress-1213575.js create mode 100644 deps/v8/test/mjsunit/regress/regress-1215653.js create mode 100644 deps/v8/test/mjsunit/regress/regress-124.js create mode 100644 deps/v8/test/mjsunit/regress/regress-1254366.js create mode 100644 deps/v8/test/mjsunit/regress/regress-1327557.js create mode 100644 deps/v8/test/mjsunit/regress/regress-1341167.js create mode 100644 deps/v8/test/mjsunit/regress/regress-1346700.js create mode 100644 deps/v8/test/mjsunit/regress/regress-137.js create mode 100644 deps/v8/test/mjsunit/regress/regress-1439135.js create mode 100644 deps/v8/test/mjsunit/regress/regress-149.js create mode 100644 deps/v8/test/mjsunit/regress/regress-1493017.js create mode 100644 deps/v8/test/mjsunit/regress/regress-171.js create mode 100644 deps/v8/test/mjsunit/regress/regress-176.js create mode 100644 deps/v8/test/mjsunit/regress/regress-186.js create mode 100644 deps/v8/test/mjsunit/regress/regress-187.js create mode 100644 deps/v8/test/mjsunit/regress/regress-189.js create mode 100644 deps/v8/test/mjsunit/regress/regress-191.js create mode 100644 deps/v8/test/mjsunit/regress/regress-192.js create mode 100644 deps/v8/test/mjsunit/regress/regress-193.js create mode 100644 deps/v8/test/mjsunit/regress/regress-20070207.js create mode 100644 deps/v8/test/mjsunit/regress/regress-201.js create mode 100644 deps/v8/test/mjsunit/regress/regress-219.js create mode 100644 deps/v8/test/mjsunit/regress/regress-220.js create mode 100644 deps/v8/test/mjsunit/regress/regress-221.js create mode 100644 deps/v8/test/mjsunit/regress/regress-225.js create mode 100644 deps/v8/test/mjsunit/regress/regress-227.js create mode 100644 deps/v8/test/mjsunit/regress/regress-231.js create mode 100644 deps/v8/test/mjsunit/regress/regress-233.js create mode 100644 deps/v8/test/mjsunit/regress/regress-244.js create mode 100755 deps/v8/test/mjsunit/regress/regress-246.js create mode 100644 deps/v8/test/mjsunit/regress/regress-253.js create mode 100755 deps/v8/test/mjsunit/regress/regress-254.js create mode 100644 deps/v8/test/mjsunit/regress/regress-259.js create mode 100644 deps/v8/test/mjsunit/regress/regress-260.js create mode 100644 deps/v8/test/mjsunit/regress/regress-263.js create mode 100644 deps/v8/test/mjsunit/regress/regress-265.js create mode 100644 deps/v8/test/mjsunit/regress/regress-267.js create mode 100644 deps/v8/test/mjsunit/regress/regress-269.js create mode 100644 deps/v8/test/mjsunit/regress/regress-279.js create mode 100644 deps/v8/test/mjsunit/regress/regress-284.js create mode 100644 deps/v8/test/mjsunit/regress/regress-286.js create mode 100644 deps/v8/test/mjsunit/regress/regress-294.js create mode 100644 deps/v8/test/mjsunit/regress/regress-312.js create mode 100644 deps/v8/test/mjsunit/regress/regress-317.js create mode 100644 deps/v8/test/mjsunit/regress/regress-318.js create mode 100644 deps/v8/test/mjsunit/regress/regress-35.js create mode 100644 deps/v8/test/mjsunit/regress/regress-57.js create mode 100644 deps/v8/test/mjsunit/regress/regress-588599.js create mode 100644 deps/v8/test/mjsunit/regress/regress-662254.js create mode 100644 deps/v8/test/mjsunit/regress/regress-666721.js create mode 100644 deps/v8/test/mjsunit/regress/regress-667061.js create mode 100644 deps/v8/test/mjsunit/regress/regress-670147.js create mode 100644 deps/v8/test/mjsunit/regress/regress-674753.js create mode 100644 deps/v8/test/mjsunit/regress/regress-676025.js create mode 100644 deps/v8/test/mjsunit/regress/regress-678525.js create mode 100644 deps/v8/test/mjsunit/regress/regress-682649.js create mode 100644 deps/v8/test/mjsunit/regress/regress-69.js create mode 100644 deps/v8/test/mjsunit/regress/regress-734862.js create mode 100644 deps/v8/test/mjsunit/regress/regress-737588.js create mode 100644 deps/v8/test/mjsunit/regress/regress-74.js create mode 100644 deps/v8/test/mjsunit/regress/regress-780423.js create mode 100644 deps/v8/test/mjsunit/regress/regress-799761.js create mode 100644 deps/v8/test/mjsunit/regress/regress-806473.js create mode 100644 deps/v8/test/mjsunit/regress/regress-842017.js create mode 100644 deps/v8/test/mjsunit/regress/regress-86.js create mode 100644 deps/v8/test/mjsunit/regress/regress-87.js create mode 100644 deps/v8/test/mjsunit/regress/regress-874178.js create mode 100644 deps/v8/test/mjsunit/regress/regress-875031.js create mode 100644 deps/v8/test/mjsunit/regress/regress-877615.js create mode 100644 deps/v8/test/mjsunit/regress/regress-892742.js create mode 100644 deps/v8/test/mjsunit/regress/regress-900055.js create mode 100644 deps/v8/test/mjsunit/regress/regress-900966.js create mode 100644 deps/v8/test/mjsunit/regress/regress-91.js create mode 100644 deps/v8/test/mjsunit/regress/regress-925537.js create mode 100644 deps/v8/test/mjsunit/regress/regress-937896.js create mode 100644 deps/v8/test/mjsunit/regress/regress-990205.js create mode 100644 deps/v8/test/mjsunit/regress/regress-992733.js create mode 100644 deps/v8/test/mjsunit/regress/regress-996542.js create mode 100644 deps/v8/test/mjsunit/regress/regress-998565.js create mode 100644 deps/v8/test/mjsunit/scanner.js create mode 100644 deps/v8/test/mjsunit/short-circuit-boolean.js create mode 100644 deps/v8/test/mjsunit/smi-negative-zero.js create mode 100644 deps/v8/test/mjsunit/smi-ops.js create mode 100644 deps/v8/test/mjsunit/sparse-array-reverse.js create mode 100644 deps/v8/test/mjsunit/sparse-array.js create mode 100644 deps/v8/test/mjsunit/str-to-num.js create mode 100644 deps/v8/test/mjsunit/stress-array-push.js create mode 100644 deps/v8/test/mjsunit/strict-equals.js create mode 100644 deps/v8/test/mjsunit/string-add.js create mode 100644 deps/v8/test/mjsunit/string-case.js create mode 100644 deps/v8/test/mjsunit/string-charat.js create mode 100644 deps/v8/test/mjsunit/string-charcodeat.js create mode 100644 deps/v8/test/mjsunit/string-compare-alignment.js create mode 100644 deps/v8/test/mjsunit/string-flatten.js create mode 100644 deps/v8/test/mjsunit/string-index.js create mode 100644 deps/v8/test/mjsunit/string-indexof.js create mode 100644 deps/v8/test/mjsunit/string-lastindexof.js create mode 100644 deps/v8/test/mjsunit/string-localecompare.js create mode 100644 deps/v8/test/mjsunit/string-match.js create mode 100644 deps/v8/test/mjsunit/string-replace-gc.js create mode 100644 deps/v8/test/mjsunit/string-replace.js create mode 100644 deps/v8/test/mjsunit/string-search.js create mode 100644 deps/v8/test/mjsunit/string-split.js create mode 100644 deps/v8/test/mjsunit/substr.js create mode 100644 deps/v8/test/mjsunit/switch.js create mode 100644 deps/v8/test/mjsunit/testcfg.py create mode 100644 deps/v8/test/mjsunit/this-in-callbacks.js create mode 100644 deps/v8/test/mjsunit/this.js create mode 100644 deps/v8/test/mjsunit/throw-and-catch-function.js create mode 100644 deps/v8/test/mjsunit/throw-exception-for-null-access.js create mode 100644 deps/v8/test/mjsunit/to-precision.js create mode 100644 deps/v8/test/mjsunit/tobool.js create mode 100644 deps/v8/test/mjsunit/toint32.js create mode 100644 deps/v8/test/mjsunit/tools/splaytree.js create mode 100644 deps/v8/test/mjsunit/top-level-assignments.js create mode 100644 deps/v8/test/mjsunit/touint32.js create mode 100644 deps/v8/test/mjsunit/try-catch-extension-object.js create mode 100644 deps/v8/test/mjsunit/try-catch-scopes.js create mode 100644 deps/v8/test/mjsunit/try-finally-nested.js create mode 100644 deps/v8/test/mjsunit/try.js create mode 100644 deps/v8/test/mjsunit/unicode-string-to-number.js create mode 100644 deps/v8/test/mjsunit/unicode-test.js create mode 100644 deps/v8/test/mjsunit/unusual-constructor.js create mode 100644 deps/v8/test/mjsunit/uri.js create mode 100644 deps/v8/test/mjsunit/value-callic-prototype-change.js create mode 100644 deps/v8/test/mjsunit/var.js create mode 100644 deps/v8/test/mjsunit/with-function-expression.js create mode 100644 deps/v8/test/mjsunit/with-leave.js create mode 100644 deps/v8/test/mjsunit/with-parameter-access.js create mode 100644 deps/v8/test/mjsunit/with-prototype.js create mode 100644 deps/v8/test/mjsunit/with-value.js create mode 100644 deps/v8/test/mozilla/mozilla-shell-emulation.js create mode 100644 deps/v8/test/mozilla/mozilla.status create mode 100644 deps/v8/test/mozilla/testcfg.py create mode 100755 deps/v8/tools/js2c.py create mode 100644 deps/v8/tools/jsmin.py create mode 100755 deps/v8/tools/linux-tick-processor.py create mode 100755 deps/v8/tools/presubmit.py create mode 100755 deps/v8/tools/run-valgrind.py create mode 100644 deps/v8/tools/splaytree.js create mode 100644 deps/v8/tools/splaytree.py create mode 100755 deps/v8/tools/stats-viewer.py create mode 100755 deps/v8/tools/test.py create mode 100644 deps/v8/tools/tickprocessor.py create mode 100644 deps/v8/tools/utils.py create mode 100644 deps/v8/tools/v8.xcodeproj/project.pbxproj create mode 100644 deps/v8/tools/visual_studio/README.txt create mode 100644 deps/v8/tools/visual_studio/arm.vsprops create mode 100644 deps/v8/tools/visual_studio/common.vsprops create mode 100644 deps/v8/tools/visual_studio/d8.vcproj create mode 100644 deps/v8/tools/visual_studio/d8js2c.cmd create mode 100644 deps/v8/tools/visual_studio/debug.vsprops create mode 100644 deps/v8/tools/visual_studio/js2c.cmd create mode 100644 deps/v8/tools/visual_studio/release.vsprops create mode 100644 deps/v8/tools/visual_studio/v8.sln create mode 100644 deps/v8/tools/visual_studio/v8.vcproj create mode 100644 deps/v8/tools/visual_studio/v8_arm.sln create mode 100644 deps/v8/tools/visual_studio/v8_base.vcproj create mode 100644 deps/v8/tools/visual_studio/v8_base_arm.vcproj create mode 100644 deps/v8/tools/visual_studio/v8_cctest.vcproj create mode 100644 deps/v8/tools/visual_studio/v8_cctest_arm.vcproj create mode 100644 deps/v8/tools/visual_studio/v8_mksnapshot.vcproj create mode 100644 deps/v8/tools/visual_studio/v8_process_sample.vcproj create mode 100644 deps/v8/tools/visual_studio/v8_shell_sample.vcproj create mode 100644 deps/v8/tools/visual_studio/v8_snapshot.vcproj create mode 100644 deps/v8/tools/visual_studio/v8_snapshot_cc.vcproj create mode 100755 deps/v8/tools/windows-tick-processor.py diff --git a/configure b/configure index db2d3c52b8..fbe2e5ad0d 100755 --- a/configure +++ b/configure @@ -4,19 +4,11 @@ # Fancy colors used to beautify the output a bit. # -if [ "$NOCOLOR" ] ; then - NORMAL="" - BOLD="" - RED="" - YELLOW="" - GREEN="" -else - NORMAL='\\033[0m' - BOLD='\\033[01;1m' - RED='\\033[01;91m' - YELLOW='\\033[00;33m' - GREEN='\\033[01;92m' -fi +NORMAL="" +BOLD="" +RED="" +YELLOW="" +GREEN="" EXIT_SUCCESS=0 EXIT_FAILURE=1 diff --git a/deps/libebb/.gitignore b/deps/libebb/.gitignore new file mode 100644 index 0000000000..f65038b4e3 --- /dev/null +++ b/deps/libebb/.gitignore @@ -0,0 +1,5 @@ +*.o +examples/hello_world +test_request_parser +ebb_request_parser.c +tags diff --git a/deps/libebb/LICENSE b/deps/libebb/LICENSE new file mode 100644 index 0000000000..91b52e6a4c --- /dev/null +++ b/deps/libebb/LICENSE @@ -0,0 +1,21 @@ +Copyright (c) 2008 Ryan Dahl (ry@ndahl.us) + +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/deps/libebb/README b/deps/libebb/README new file mode 100644 index 0000000000..d5b7ce3a4b --- /dev/null +++ b/deps/libebb/README @@ -0,0 +1,7 @@ +see doc/index.html and examples/hello_world.c for explanation + +webpage: http://tinyclouds.org/libebb/ +git repository: http://github.com/ry/libebb/tree/master + +To build libebb please edit config.mk to reflect your system's parameters. + diff --git a/deps/libebb/config.mk b/deps/libebb/config.mk new file mode 100644 index 0000000000..5564bddebf --- /dev/null +++ b/deps/libebb/config.mk @@ -0,0 +1,38 @@ +PREFIX = $(HOME)/local/libebb + +# libev +EVINC = $(HOME)/local/libev/include +EVLIB = $(HOME)/local/libev/lib +EVLIBS = -L${EVLIB} -lev + +# GnuTLS, comment if you don't want it (necessary for HTTPS) +GNUTLSLIB = /usr/lib +GNUTLSINC = /usr/include +GNUTLSLIBS = -L${GNUTLSLIB} -lgnutls +GNUTLSFLAGS = -DHAVE_GNUTLS + +# includes and libs +INCS = -I${EVINC} -I${GNUTLSINC} +LIBS = ${EVLIBS} ${GNUTLSLIBS} -lefence + +# flags +CPPFLAGS = -DVERSION=\"$(VERSION)\" ${GNUTLSFLAGS} +CFLAGS = -O2 -g -Wall ${INCS} ${CPPFLAGS} -fPIC +LDFLAGS = -s ${LIBS} +LDOPT = -shared +SUFFIX = so +SONAME = -Wl,-soname,$(OUTPUT_LIB) + +# Solaris +#CFLAGS = -fast ${INCS} -DVERSION=\"$(VERSION)\" -fPIC +#LDFLAGS = ${LIBS} +#SONAME = + +# Darwin +# LDOPT = -dynamiclib +# SUFFIX = dylib +# SONAME = -current_version $(VERSION) -compatibility_version $(VERSION) + +# compiler and linker +CC = cc +RANLIB = ranlib diff --git a/deps/libebb/doc/icon.png b/deps/libebb/doc/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..702f4b5bba0e6e2c66daa3e24e92487c8651796d GIT binary patch literal 9412 zcmW-nbyyUS*Tshr76DnhV*zOiLFrl=>29REW08)f>x*;?h{Tct0#X73N=rycDc#-m z&hPzWcAlB%*`1l4JNKOPxf83QrhxyH>L~yK_)3bhTHxCHe+vX1{Co^W#{gGoURnxp zpk|b28{EKgS2XkjfM?(Tx1gnSKBESAVtXs8%3;r96O)q&EglVafV(KY&X&5- zV?MBj>u8d+)n_vEj4=08l*Iljlh;n@pS2X=`$A!5$yMJ66^Oy7*7_I&Q6@Fe8$=)a z9bgw6Vq&1r5SMdl89a7+eClzy@RENyTX=I=*y|ZD??*}Syrdw1g_0f

RkOrvOV_ zvB(Q-a36adx+zPB4H_VzO05imY2o5($Fc)Zue_>HSYnjfSus^y)oIE$R@#%PftzN; zrlxrc&(!O91y_ag-tEuNostVBd3k#WZbwqm48TheIXUU9YAov60%5BL0PvU3F`}}i z#e2Ei+^>pW8D8Yx-QJq0s%rdYKeX8~cmu%9`Mw!*KwxV=Y50XD71l^d?KFjtv$=Ny({S zK%YwgNn@`q_gmd>MVJ3(-oS;L-YE#NVZjWw*cy{CJXl@7|5-VGef=Z3s`3a2VY2@8Jc#_0Dg0U79bmkd0!q52eT(Vx$ z4AgTeOp=Uo8f3KPr10IB&KP9u3snmxSqUdSvZyZKLi)383_U}HM?4nluDZXxeyxyn zpA&e4HzxXwP9hHa@`y0O!>d7y0ZO4?qQmjdEJ7F$&_qp*D6cc&rzJNxcbSi!B~+c9 zJVpLD``vmn%12BF0G#LR$gCz7rrQ1HJXK<9lgGTQqnYa?U?Acv;QHt z$`#R=G*G$oxG@SBTlf#5t@%SuhBr27oNho0wfNI2x2U^|{qB8YoBRBeEe zVTFeU@^>o*hhnv4Ao+B^_oZcPmE_H#;_y=LatV^E6>)DF}jH258wy&Cl6!-fgGwX<-Q2;Q^rwee}%n@DeD{hI~=+S-#Xvsv?BzfQ$xUK8c3 zHG5ss0aAVjAr+C=h_*|60jl1WYLkYV726`CYAoPvYsqEu=9M-}(%A6VjFj}!U-mLL zm^hf|`D&XhZx7f1YI>s#xN9S!W@B9*;*atwIH?|4Jd8Ykh}H&f}t4 zK^c`4M=@LMObE%+e>@jsu>N_XJ~6@n6>)m+IkKtEs;(j&kYq~{7HVrCjBWA4u9pRk?>t7a3xd5bZyx|f6~;{ zB(S}m0UZe>#5SZd$!V&pj_&9)mh3IkYWpqG&FldgPb+%Yv@4Da*L+-uCM!{6gjH`l~n>x6qGTB z0onJwv~=ADEjXA&RU2}gcQ~3qSV|uEn5vo^T*tr zQpvBhj7&=T{6`B{TUSfVi4Pj(IvhEl(9lTJ(_um3`+Lp~O-7|!75mQn-&rh?8lHpO zL;4fGfo+CtB$N`>(++NAWR(0@*my?zKy-{iR ze06`YXoO_5#_Z1*O}AM`+yz`DKydj}6<;=d#v48uYsUAN(=MrqHQ-49(pIX4@)60G zW&F#E4f{U&I|>*d9}i`VySbNrIpATXkocdX%DKPzkOx%S3QZ9*zI$FpD2`*GRUzm7 z{oBsY4vNyyG$}CLb3U+S=-4yoV0N@?S%W&<|f~9*%yQHyQ1(hNVL# zWf`D%IayOaa+3U_xi)i~{Yg=foZM`DdXcFt0x3wXiE4<&jSi1GL8(@De(KP2Dcj&= zuPHN0YwK6AC012q1U!Mlm6eACs78L7Clk;TW%3FvO--H2OBY4A8Ea^)FK%%ajM%bkxnQT?w3IaAe3kKRgm)rr#W8G z`Nn@^h^OPO=Ts#BAd_i;C4t(?#6jA^B1k5pBj40lt>CjnR4cqWT98;lsl?C`88uMb6Ej46l~~0#?RBkIFXv z1Y)F;lr>db;=y^kkdG@&3P2m*@!lVz#DXgVV9nt59#v-7i#$VH<9+Rpvr0!v5NTE` zxW!2V*U5eOv16#>-iE*dxQ0%~mhC8h`PkFiQ@-Q1Z;& zVq#~<^<6)Cve?^(p4q^|={#nv?Fpi0sju1iEGQw7qtHJqFY*5+cws zMuwRU=Y&HN-xBfSU8$>8WtGP?FJ-kJe(UBDbo(pH`+Qs_;6ulXICg-jnUXby{I6NRtF2m5-+fm*^M?8_57z%v zl*f}{!9o%)$X^1<`@FpOTHbAIlGtPe7Wrxe9&ei?T3^ z?fs}<-PGcdg5>7pI>Zsh_hqf5;Phe*^xtK8pCqS|U}|c6dA)gqi<)WRy8RWGj{h_= zK6R41w&SL!kzKg;UFKvB)oWvl)i4VTXBTJRz4^rt8lYdo4!CWZ-O80~hGLo(6o_;@ znC$emAr2*G?VrFBk`mnOnpbD!OgoB=Se!0Z?7N@{gdpUtmDOtYX+`@w5;`$5z{U@c>BFAQ^?6j5VqP1Q_ewa~0iAERNTJ3W1-5?pjV zi7o9{@}bU%1$0X5JO5s~41W9(_LrR7^fkq}1E>iviz+I%Wlz|1ctBk$IQ^Xq_RrsX zdNf1XF{=GZRD1yk0jigQk@>0SV+9=;clmiVprKSA;!Nl!0I?O+OAtOBT^zuQZV>v z#dpGe@cVIuWihDRg02tpCDZ=?Ed*QS=)ix9%!k7Tatv2*kE20Z0)>t)h4-v)TU#)= zW4*|fC^wFlX7Bo)bn{$Gp?8>7(kd@Z=-V%|y*w)(GRG0aW{eS=R+S_lxg+ntkm%A~wNfu{kAus{bT(K|B8q6;} zd^~D0ekv;~U#GjeSGBga62e`{$TUgN0fE=Aht@r*si`X>-)T?E=mqKdjz-330-+SE z4yml5l8Ch~ou0&xF=6ttfTh#JkBN|t56$9X6 zTQMNm8;^t||I?bA@R-Pskwrp%s1;a|=`2Ukx~I6fAreQpV>8jL-z9|&NaRKW zosvwrSusKRwk@6b=8J?|^whz?=Z)QNlroLy>uv-fa;k$+c1+B%F~r451xUdcRzfRkU<;w6&Gz#{*=YEiG+r zZ5fHcOenHgR5Ad@t?+9v>?r&#(iO?$RuB3Yro$d4dTL2`2aBEE(!>MF_y@E?m-~i5 z=ts#1ze?vYx&znl4h%Q4#lbF*NeV71AQbx1;by4<8k4|-20*34G}uTW_@<1=GXfmL z&-Q5DvX-_SBoML=N%OK9&h$b3<-Em-iT7FFJ-@nxhkpB?=_H&D-IwK%KRy#=wQxiG$qle4<|dNiPXdWZUn z;B{#<-m1YkQmi03m$5*tvaC5$^h<%jxX=|xu)zy(wrXyS$M$p17vJQDU_jnUYT z4G)evAB}zU$NDW9YriUvUmNq8>vo(8UEYna-2uldZ^MHC)`#94K; zmg4eCHc!`7Nq`_y<4rt=@N=8}%-jMZN$P)g3Mx97Bja+-t{8CM1Fa$ZxVQuezn~x| z8y9m6%1t~A{q9~bxP4)=R~$SLf#m+k&mme7>m%X<^ZR(a4EYk%#xtfwd1A8pkh%AA zrh(dJGa+AhaFf>CJKA5@7~hjqs4(Q+_p5|S)m;qLKBK=U1-|hnM7N1{;o-n6iHWI= zsWAzMK2N`-G=B#3_VKk9R{J$;Z{_lYK}UcMZwZ5(+%8-x0&Zbt^91UwBfvpLjlU%W zq21r7M3aG3RHO92G%_%CCCOSky4c_o_GFWAEAWaja`LCCFM&tTuPhK2{tIxVNQnehXB52N@x4GpIF z-lqU{et&O+#RF)>y#0QDR{!kf8TGwyH0yPGSLw84sTOWhZ(;C5A3eLBNnYM3)$A#e zdmj-mejL@w!fLZq;|V3~fN1hE^(TNkjo@u!wv~KhOP;UK@n`kU#fSXd_|u*zr&k|1 z0s`7dhcZFkI-I*bEhfke>F{YY;L6B~D=gkmN^E)se5mQ{T&;GMSOUG(5;yl;qfM?_ z*%(httKG~6vM8c!`IKqwmJp8mUB$`%V(90{?sBag!rVMeYTP$C|HksZKRj1(lK(Rn z^5XR3gd|p0PfxF&PxJZnQqC@eKMM=P9(lQ_p(Bgq&Ly)MPfrDW^}42}#kR+9GsewK zF%UG6nS7euE?}&?dLc37OT@6dx*rK0>?j!f%muIeT&c{R+1A!-XpqH8k_d#(e-+8D z!h-1->yLSW+`{oKJ3cAU2ORI`<|X+psN4^Ti78B1+CC_ zwqejMCNccI_NYb-I!NC91dp^a$=tHvXT^ywz2r{^fSmbo-|GVKU^z;|esuy=FC46f z0RVDXPoAhZ@W$~0Du#prj7|TcLn0#lv9ZrzyL%_fGZDqw=VWB%I0{hNM8|w9gH*+d zrbFT6t+dG6ES0AxDn= zWT>Z?&++*M*%E!>^~}Wi9kpZA{J_v8*tLMCV+b&K;lRMY9@whE=I!aN<0O#(vL#yP z$+!GU4lrWvuDVFYL5pXaMH1XH(|GZSR}Sr$l~A8>T;x0wd(>v z#gygZCTG{RW6JyZU$%9=a8h{kBobr<-C-S|6A|R+ z2b;?2$ywmxqOe{@28rB#@IQiTJyEN{HP_B1qS)`h`!^yfC#$Nf9e~gRo6L58)<$zk z@3=@lx93|wkRc8Za&GXL4AX}zKw?$<7*l>gg+_Qz^vwb#EDXftH2pgyzAZnNnTqc0 z>@Ejiirc&yT0OUzDJTqV?~u8{dTexxRxbVAm{vIrDxiGH_01ob!!A)o?@s#3yb&ul zww(6lm;AP`AE=iky`fSQ^HlPx$32%D9cSTrZ~v{lt)1Duq!+`44G(|)f>;i# zNM&_hyi2e8)IUG?6y|+k;)rtVs4Fk0m2}eMz!x=0H1ZPTQ(`94(_coEmp8WG=?rGy zX2q)wJScTW*Ze16Vp!+5{UM93i%uL0f59;woBA`5|GgTEzTVGbrXGhJy$T(LWY&`; zoP^`!?;pw12UqZ~U+^iFOncHOK$OHh!js4UksD3KN-F*ljy3M#?RQ5_^(Xild$4%%N+!2K1lXpnJM9=TaA{d~@WR<@bijiKEfik9_^S-N z>wGrK6b_-kPD*fe#y{Svasi|wh!gAt?lAhhM9t8FmM=nl5TKaNuj{^7gLXL~fN-rG zS6M@$|FLiu?QTy0k&9fZt;hG555d8c^G)$BgGK(;W&StY{B;Fk=Xh0*mv1c+&i#YR ze!C`k9DWN0$rD%UL>Hyqb>zTR~q9N(UTJ}1z=Js0IP@G}ysJoZDS!+rZ;aUT3Znt^S@i^KDi z#`zV#ewu;fM~egtYDz9y>}Rxdk3$x5#q;~AI4~^t#B`-+RuBMLrz?2?)p%Sp3T~sq z&uvKZ@$ny8Io$Hcb;z(0bTimIoWX#7{N*TV^d;*pI^m7)?P%d8{YMA?dvcWj^=&=Z zfX5#8n~ZhSF~M)vc21(Z=QHrz^HR1-BfSQn0Yn8k4-5(7w9CDPj8ueakp_|gGTq>8 zIq}o2`B1>s+rVBjOv=DS%g9XgxLgr5)HU~a{2A*TAxDRUl^mGAwlsUo)N&Y_>c+Rv zW0hF(Dc>^yy~I(fg)e{3&ui6A7K-`!-y)Vzm27=o7SS16e0KHh?L)$kv%M;Eo1KG> zgx?N!&y`lS|MQ&JO;KFiU%y^m!T|pYiJ%RWjV33K^c<)bXoH0JE8`ndOG!xTo=%HDdO*(vVZ!rv@4Ld+W*2baM@N?sG-}+9bELPEN9QzBdl@ z*w-_!1-kx|=r$B?Jsf@vU2R!tzmvn=P%pSzXet%P;^sfRkL)Y8!8wk|G+xr&&c_4Mi;D~Tkgq33zR!^3OQWuX-#4v4=QJ+|9lE-_=;d8@ zxwoDAK`6Pmr~t{9u+egHSrk2$EU&Ej#OAoWktnkoz4vgu+1BI(08vFV!L8flDJ5iN z8*K>Z#Q50%f!H?fjD5;>zUY4;4BqA^?{8i3tKXjEJncc|iDwRO#<#d%f7V0cAMHBK z27=<6o|cY-IXqHq41pO_8)G0=g%0A+&1=lsB-V%L6yC>rE%`SD2rlo7BJza`2b(L@ z-Q7|Y(+bif*#<#1nb7jT@5d)j`SE9npZA+NV~X|Wh9}MDTQ_iImW~iNXC}G1@jG=8 z7oc*PpGKjFeW)1}1rWgl1KaU45CNj15DWO-e^)KtfkjeMlL8=S5fBuV zf%M7B$vtyc9qNbJ=X|QJ;<|nieEsUQ%#9HFvXusEX=T;hE8u!oo>dN!2vGUmw0C%U zH$_EyG3(bfR5HyW{-^(M_naP`x)_~=Z+m9f@`tVR)DUKKwKvfK6wZJI3tvr5*ed2j z7@(&=1lA@DGnwYi-K%4S%pDJAojms@Pa^*oMIjL@vZbw6WL6X!iUt%M9JDL_2FTVX zU47~?0&U@tqSO+mM_7@fJ$w3V0k$;d(y4{JzaqGDXb`@EzudcOkRq#r5YeEGg`6?{ z;df4Yz6ZvRO<#@lBKXL7!+VO2_X{$Au5%6HME?JVeAL)W)}}gM!dNQmTwa!>q-Oxo zddE$l+Vp@Laq7Gq95+PkUC>sBt!XXAcuoXMOL>Pc1*N8yn-m!O z?7_!}9>%~aTE;mL0b=64RGR=_*La5^^f{aM@?oc$_v-n+zMg@>^VWcrzx*fV(zw_p z&_TQvPFfdAQ6!!Vi_jo%Cs1qPE)`gOYA()zkgjn>Xy}X(!gdh^0H@G|@ zDA#9;doyHIvThG1yQ4?Hj|azGamC=gVCQ@fcd~4Le!j7>oZDQ9^J~zbxt|_V_8|%N z4GqL_HWrTJ++>8d*XeeHof`>Bo_Ys`FmK>MhAJ43L7q>Yn-eVIUdL%`11W0G%uH-* z>Me0Ihr*X#mxVusbSbS46p93W+4{Y|-{w1(eZJA0E4ZZw6Pz8o zi28Pb4{Gk~s*#blXRw{6kpV4^d|n@UD=Ypn6}!&6+D>WdnwnAHFRueG_e0$4PQ?q- z&E365q7sSwlVal&!=SG?bDuuN4GIeUq?&`o=|-Y5re&j|F(9Ogai`?mm9KKr&8xtD z$jFORcLdlVyY|}-apPTKNP}TrJ>8iZ!6Q;H3XnmAb|jJfU7|_N%yzozD8`@hafZ~N zeukRM<8}9Khh^&d0uFaAV>7No-fISlCK4_u%;s)9DpDRw+hE!^(&0dkyD70c?(Tk4 z&)(bLmIl~(x*9wtGqB{C!Xbc$`Lg@5veDyzomnfUl6P0V$pQ34WUe#!ANDBnN-%oTmy(f%pW1_{kKONLs`t3BI3_c!b1y}+P!+Q!LWsqsP8{T5IXSueO2w&E0D$@YfA0e9Ig6^2 z^p-{4yIvLq-G*pZOkZXaN41v8pQ=+mcw+TutqVy(LjU{Za5jaRCq~1CY2jYDa@Ash zi^~ptY;1IXEb6^uU(xH;w#%VL9yMh?PIu%IbOXe9_XQo1a<7YrAgZ+H!X@T>f0! zBOu>SCqLcXp3gSj4uCce+Vf#43`BLjgxTe(BTUhLBOy+BjM5 z@9l{N?W`s4c5cO;w${{`v80NMibfJZ(v@G}*=Eb z@`;MGExza9>Uf=~Q87n#iB9^_7X;S>p}NNU&Gy?Tn=I;uuQnGm?K)deZ|T7~ViX?T z*@~1T{73yV(TvMNTF7eD@h3F6ANM(Wq=u{?1rJnAd;tWTwd-r_#yVgyaO=AE2SObZq3j~Z+$DkAK)DHy;Y=fRrk7{bHX_saPGB>7td68^U; zyB6ecjAZfG%t-$ZGiD+QU&W7lsFC4esubQTM6H>__Vzve#@^@aS%L}#oD5O-3$bv# zEZqJf&e5 zp)6$kV0Y40IYlAyB9vFM>qC(=;XKdBtqT{(-|Hz{5>;Y26%`4z2OQLO-4{%aN}P|a z7*EY1U(WZb=K4pKjtd674Mw2rq=g_g0!mjsM z&TYzeNJ~zNnx>A4GoG9#5~>1GoqXo&`v}2O7Zz$WP=3*ib%sFrkn)~gd03S&F+syi zZAd}d;ehWn+2B#n=UOw031wAKsMh=QQ6~-w7t|-`R*z{TQx#_VY zA#y#l<%+moUacmbHn(bK($y);=a;9r+r*%=WN)h5q9=L@mZpO?%YmpLMB==XeSKxm zv#sU(;NVLx0RfShJ-_>JrnVc<9?(i{Y(nxxMj}cl?00r|Wo{$C%gXil_1g=~b2{jQ z;M?ub-Sq4)Ch>(uHY8RQ0fnIL6bKHYlWAwRy`eo(H&IH&1>i{OGWDna{KOy;oZGb1 z(#3|7k5`Pv@$K>oLsU_!TEXDpXz)$9V^f+Ii46xC21Gb%(q4c_TU&gn@<1|#iSO0A z6%=eU@~BdWc^xhmTEBn>EeC^y4O=20MZUy=JOv4TNg5A>1JI0h9aF`tOM&r6w2G&_ WCH?`8Vc?rQfRdb=Yz_Qv`2PXR`y^`s literal 0 HcmV?d00001 diff --git a/deps/libebb/doc/index.html b/deps/libebb/doc/index.html new file mode 100644 index 0000000000..612c9e9fbf --- /dev/null +++ b/deps/libebb/doc/index.html @@ -0,0 +1,240 @@ + + + +

+ +

libebb

+ +

+ libebb is a lightweight HTTP server library for C. It lays the + foundation for writing a web server by providing the socket juggling + and request parsing. By implementing the HTTP/1.1 grammar provided in + RFC2612, libebb understands most most valid HTTP/1.1 connections + (persistent, pipelined, and chunked requests included) and rejects + invalid or malicious requests. libebb supports SSL over HTTP. +

+ +

+ The library embraces a minimalistic single-threaded evented design. + No control is removed from the user. For example, all allocations are + done through callbacks so that the user might implement in optimal + ways for their specific application. By design libebb is not + thread-safe and all provided callbacks must not block. libebb uses + the high-performance + libev event loop, but does not control it. The user of the library may + start and stop the loop at will, they may attach thier own watchers. +

+ +

+ libebb depends on POSIX sockets, libev, and optionally GnuTLS. +

+ +

+ libebb is in the early stages of development and probably contains + many bugs. The API is subject to radical changes. If you're + interested checkout + the source code and join the mailing + list. A release will be made when it proves stable. +

+ +

libebb is released under the + X11 license.

+ +

Usage

+ +

+ libebb is a simple API, mostly it is providing callbacks. There are + two types of callbacks that one will work with: +

+ +
    +
  • callbacks to allocate and initialize data for libebb. These are + named new_* like new_connection and + new_request
  • +
  • callbacks which happen on an event and might provide a pointer to + a chunk of data. These are named on_* like + on_body and on_close.
  • +
+ +

+ In libebb there are three important classes: ebb_server, + ebb_connection, and ebb_request. + Each server has many peer connections. Each peer connection may have many + requests. + There are two additional classes ebb_buf and ebb_request_parser + which may or may not be useful. +

+ +

ebb_server

+

+ ebb_server represents a single web server listening on a + single port. The user must allocate the structure themselves, then + call ebb_server_init() and provide a libev event loop. + ebb_server_set_secure() will make the server understand + HTTPS connections. +

+ +

+ After initialized the ebb_server_listen_on_port() can be + called to open the server up to new connections. libebb does not + control the event loop, it is the user's responsibility to start the + event loop (using ev_loop()) after + ebb_server_listen_on_port() is called. +

+ +

+ To accept connections you must provide the new server with a callback + called new_connection. This callback must return an allocated + and initialized ebb_connection structure. + To set this callback do +

+ +
my_server->new_connection = my_new_connection_callback;
+ +

+ Additional documentation can be found in ebb.h +

+ +

ebb_connection

+ +

+ This structure contains information and callbacks for a single client + connection. It is allocated and initialized through the + new_connection callback in ebb_server. + To initialize a newly allocated ebb_connection use + ebb_connection_init(). +

+ +

+ After ebb_connection_init() is called a number of + callbacks can be set: new_request, new_buf, + on_timeout, and on_close. +

+ +

+ When an ebb_connection is returned to an + ebb_server, data is immediately data is read from the + socket. This data must be stored somewhere. Because libebb is + agnostic about allocation decisions, it passes this off to the user in + the form of a callback: connection->new_buf. This + callback returns a newly allocated and initialized + ebb_buf structure. How much libebb attempts to read from + the socket is determined by how large the returned + ebb_buf structure is. Using new_buf is + optional. By default libebb reads data into a static buffer + (allocated at compile time), writing over it on each read. In many + web server using the static buffer will be sufficent because callbacks + made during the parsing will buffer the data elsewhere. Providing a + new_buf callback is necessary only if you want to save + the raw data coming from the socket. +

+ +

+ The new_request callback is called at the beginning of a + request. It must return a newly allocated and initialized + ebb_request structure. Because HTTP/1.1 supports peristant + connections, there may be many requests per connection. +

+ +

+ You may access the file descriptor for the client socket inside the + ebb_connection structure. Writing the response, in valid + HTTP, is the user's responsibility. Remember, requests must be + returned to client in the same order that they were received. +

+ +

+ A convience function, ebb_connection_write, is provided + which will write a single string to the peer. You may use + this function or you may write to the file descriptor directly. +

+ +

+ To close a peer connection use + ebb_connnection_schedule_close(). Because SSL may require + some additional communication to close the connection properly, the + file descriptor cannot be closed immediately. The + on_close callback will be made when the peer socket is + finally closed. + Only once on_close is called may the + user free the ebb_connection structure. +

+ + +

ebb_request

+ +

+ This structure provides information about a request. For example, + request->method == EBB_POST would mean the method of + the request is POST. There are also many callbacks + which can be set to handle data from a request as it is parsed. +

+ +

+ The on_uri callback and all other + ebb_element_cb callbacks provide pointers to request + data. The annoying thing is they do not necessarily provide a + complete string. This is because the reads from the socket may not + contain an entire request and for efficency libebb does not attempt to + buffer the data. Theoretically, one might receive an + on_uri callback 10 times, each providing just a single + character of the request's URI. See ebb_request_parser.h for + a full list of callbacks that you may provide. (If you don't set them, + they are ignored.) +

+ +

+ The on_complete callback is called at the end of + each request. + Only once on_complete is called may the + user free the ebb_request structure. +

+ +

Example

+ +

+ A simple example is provided in examples/hello_world.c. +

+ +
+ diff --git a/deps/libebb/ebb.c b/deps/libebb/ebb.c new file mode 100644 index 0000000000..a4c5e78ac6 --- /dev/null +++ b/deps/libebb/ebb.c @@ -0,0 +1,798 @@ +/* This file is part of libebb. + * + * Copyright (c) 2008 Ryan Dahl (ry@ndahl.us) + * All rights reserved. + * + * 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. + */ +#include +#include +#include +#include +#include +#include /* TCP_NODELAY */ +#include /* inet_ntoa */ +#include /* inet_ntoa */ +#include +#include /* perror */ +#include /* perror */ +#include /* for the default methods */ +#include + +#include "ebb.h" +#include "ebb_request_parser.h" +#ifdef HAVE_GNUTLS +# include +# include "rbtree.h" /* for session_cache */ +#endif + +#ifndef TRUE +# define TRUE 1 +#endif +#ifndef FALSE +# define FALSE 0 +#endif +#ifndef MIN +# define MIN(a,b) (a < b ? a : b) +#endif + +#define error(FORMAT, ...) fprintf(stderr, "error: " FORMAT "\n", ##__VA_ARGS__) + +#define CONNECTION_HAS_SOMETHING_TO_WRITE (connection->to_write != NULL) + +static void +set_nonblock (int fd) +{ + int flags = fcntl(fd, F_GETFL, 0); + int r = fcntl(fd, F_SETFL, flags | O_NONBLOCK); + assert(0 <= r && "Setting socket non-block failed!"); +} + +static ssize_t +nosigpipe_push(void *data, const void *buf, size_t len) +{ + int fd = (int)data; + int flags = 0; +#ifdef MSG_NOSIGNAL + flags = MSG_NOSIGNAL; +#endif + return send(fd, buf, len, flags); +} + +static void +close_connection(ebb_connection *connection) +{ +#ifdef HAVE_GNUTLS + if(connection->server->secure) + ev_io_stop(connection->server->loop, &connection->handshake_watcher); +#endif + ev_io_stop(connection->server->loop, &connection->read_watcher); + ev_io_stop(connection->server->loop, &connection->write_watcher); + ev_timer_stop(connection->server->loop, &connection->timeout_watcher); + + if(0 > close(connection->fd)) + error("problem closing connection fd"); + + connection->open = FALSE; + + if(connection->on_close) + connection->on_close(connection); + /* No access to the connection past this point! + * The user is allowed to free in the callback + */ +} + +#ifdef HAVE_GNUTLS +#define GNUTLS_NEED_WRITE (gnutls_record_get_direction(connection->session) == 1) +#define GNUTLS_NEED_READ (gnutls_record_get_direction(connection->session) == 0) + +#define EBB_MAX_SESSION_KEY 32 +#define EBB_MAX_SESSION_VALUE 512 + +struct session_cache { + struct rbtree_node_t node; + + gnutls_datum_t key; + gnutls_datum_t value; + + char key_storage[EBB_MAX_SESSION_KEY]; + char value_storage[EBB_MAX_SESSION_VALUE]; +}; + +static int +session_cache_compare (void *left, void *right) +{ + gnutls_datum_t *left_key = left; + gnutls_datum_t *right_key = right; + if(left_key->size < right_key->size) + return -1; + else if(left_key->size > right_key->size) + return 1; + else + return memcmp( left_key->data + , right_key->data + , MIN(left_key->size, right_key->size) + ); +} + +static int +session_cache_store(void *data, gnutls_datum_t key, gnutls_datum_t value) +{ + rbtree tree = data; + + if( tree == NULL + || key.size > EBB_MAX_SESSION_KEY + || value.size > EBB_MAX_SESSION_VALUE + ) return -1; + + struct session_cache *cache = gnutls_malloc(sizeof(struct session_cache)); + + memcpy (cache->key_storage, key.data, key.size); + cache->key.size = key.size; + cache->key.data = (void*)cache->key_storage; + + memcpy (cache->value_storage, value.data, value.size); + cache->value.size = value.size; + cache->value.data = (void*)cache->value_storage; + + cache->node.key = &cache->key; + cache->node.value = &cache; + + rbtree_insert(tree, (rbtree_node)cache); + + //printf("session_cache_store\n"); + + return 0; +} + +static gnutls_datum_t +session_cache_retrieve (void *data, gnutls_datum_t key) +{ + rbtree tree = data; + gnutls_datum_t res = { NULL, 0 }; + struct session_cache *cache = rbtree_lookup(tree, &key); + + if(cache == NULL) + return res; + + res.size = cache->value.size; + res.data = gnutls_malloc (res.size); + if(res.data == NULL) + return res; + + memcpy(res.data, cache->value.data, res.size); + + //printf("session_cache_retrieve\n"); + + return res; +} + +static int +session_cache_remove (void *data, gnutls_datum_t key) +{ + rbtree tree = data; + + if(tree == NULL) + return -1; + + struct session_cache *cache = (struct session_cache *)rbtree_delete(tree, &key); + if(cache == NULL) + return -1; + + gnutls_free(cache); + + //printf("session_cache_remove\n"); + + return 0; +} + +static void +on_handshake(struct ev_loop *loop ,ev_io *watcher, int revents) +{ + ebb_connection *connection = watcher->data; + + //printf("on_handshake\n"); + + assert(ev_is_active(&connection->timeout_watcher)); + assert(!ev_is_active(&connection->read_watcher)); + assert(!ev_is_active(&connection->write_watcher)); + + if(EV_ERROR & revents) { + error("on_handshake() got error event, closing connection.n"); + goto error; + } + + int r = gnutls_handshake(connection->session); + if(r < 0) { + if(gnutls_error_is_fatal(r)) goto error; + if(r == GNUTLS_E_INTERRUPTED || r == GNUTLS_E_AGAIN) + ev_io_set( watcher + , connection->fd + , (GNUTLS_NEED_WRITE ? EV_WRITE : EV_READ) + ); + return; + } + + ebb_connection_reset_timeout(connection); + ev_io_stop(loop, watcher); + + ev_io_start(loop, &connection->read_watcher); + if(CONNECTION_HAS_SOMETHING_TO_WRITE) + ev_io_start(loop, &connection->write_watcher); + + return; +error: + close_connection(connection); +} + +#endif /* HAVE_GNUTLS */ + + +/* Internal callback + * called by connection->timeout_watcher + */ +static void +on_timeout(struct ev_loop *loop, ev_timer *watcher, int revents) +{ + ebb_connection *connection = watcher->data; + + assert(watcher == &connection->timeout_watcher); + + //printf("on_timeout\n"); + + /* if on_timeout returns true, we don't time out */ + if(connection->on_timeout) { + int r = connection->on_timeout(connection); + + if(r == EBB_AGAIN) { + ebb_connection_reset_timeout(connection); + return; + } + } + + ebb_connection_schedule_close(connection); +} + +/* Internal callback + * called by connection->read_watcher + */ +static void +on_readable(struct ev_loop *loop, ev_io *watcher, int revents) +{ + ebb_connection *connection = watcher->data; + char recv_buffer[TCP_MAXWIN]; + ssize_t recved; + + //printf("on_readable\n"); + // TODO -- why is this broken? + //assert(ev_is_active(&connection->timeout_watcher)); + assert(watcher == &connection->read_watcher); + + if(EV_ERROR & revents) { + error("on_readable() got error event, closing connection."); + goto error; + } + +#ifdef HAVE_GNUTLS + assert(!ev_is_active(&connection->handshake_watcher)); + + if(connection->server->secure) { + recved = gnutls_record_recv( connection->session + , recv_buffer + , TCP_MAXWIN + ); + if(recved <= 0) { + if(gnutls_error_is_fatal(recved)) goto error; + if( (recved == GNUTLS_E_INTERRUPTED || recved == GNUTLS_E_AGAIN) + && GNUTLS_NEED_WRITE + ) ev_io_start(loop, &connection->write_watcher); + return; + } + } else { +#endif /* HAVE_GNUTLS */ + + recved = recv(connection->fd, recv_buffer, TCP_MAXWIN, 0); + if(recved <= 0) goto error; + +#ifdef HAVE_GNUTLS + } +#endif /* HAVE_GNUTLS */ + + ebb_connection_reset_timeout(connection); + + ebb_request_parser_execute(&connection->parser, recv_buffer, recved); + + /* parse error? just drop the client. screw the 400 response */ + if(ebb_request_parser_has_error(&connection->parser)) goto error; + return; +error: + ebb_connection_schedule_close(connection); +} + +/* Internal callback + * called by connection->write_watcher + */ +static void +on_writable(struct ev_loop *loop, ev_io *watcher, int revents) +{ + ebb_connection *connection = watcher->data; + ssize_t sent; + + //printf("on_writable\n"); + + assert(CONNECTION_HAS_SOMETHING_TO_WRITE); + assert(connection->written <= connection->to_write_len); + // TODO -- why is this broken? + //assert(ev_is_active(&connection->timeout_watcher)); + assert(watcher == &connection->write_watcher); + + if(connection->to_write == 0) + goto stop_writing; + +#ifdef HAVE_GNUTLS + assert(!ev_is_active(&connection->handshake_watcher)); + + if(connection->server->secure) { + sent = gnutls_record_send( connection->session + , connection->to_write + connection->written + , connection->to_write_len - connection->written + ); + if(sent < 0) { + if(gnutls_error_is_fatal(sent)) goto error; + if( (sent == GNUTLS_E_INTERRUPTED || sent == GNUTLS_E_AGAIN) + && GNUTLS_NEED_READ + ) ev_io_stop(loop, watcher); + return; + } + } else { +#endif /* HAVE_GNUTLS */ + + sent = nosigpipe_push( (void*)connection->fd + , connection->to_write + connection->written + , connection->to_write_len - connection->written + ); + if(sent < 0) goto error; + if(sent == 0) return; + +#ifdef HAVE_GNUTLS + } +#endif /* HAVE_GNUTLS */ + + ebb_connection_reset_timeout(connection); + + connection->written += sent; + + if(connection->written == connection->to_write_len) { + goto stop_writing; + } + return; +stop_writing: + ev_io_stop(loop, watcher); + connection->to_write = NULL; + + if(connection->after_write_cb) + connection->after_write_cb(connection); + return; +error: + error("close connection on write."); + ebb_connection_schedule_close(connection); +} + +#ifdef HAVE_GNUTLS + +static void +on_goodbye_tls(struct ev_loop *loop, ev_io *watcher, int revents) +{ + ebb_connection *connection = watcher->data; + assert(watcher == &connection->goodbye_tls_watcher); + + if(EV_ERROR & revents) { + error("on_goodbye() got error event, closing connection."); + goto die; + } + + int r = gnutls_bye(connection->session, GNUTLS_SHUT_RDWR); + if(r < 0) { + if(gnutls_error_is_fatal(r)) goto die; + if(r == GNUTLS_E_INTERRUPTED || r == GNUTLS_E_AGAIN) + ev_io_set( watcher + , connection->fd + , (GNUTLS_NEED_WRITE ? EV_WRITE : EV_READ) + ); + return; + } + +die: + ev_io_stop(loop, watcher); + if(connection->session) + gnutls_deinit(connection->session); + close_connection(connection); +} +#endif /* HAVE_GNUTLS*/ + +static void +on_goodbye(struct ev_loop *loop, ev_timer *watcher, int revents) +{ + ebb_connection *connection = watcher->data; + assert(watcher == &connection->goodbye_watcher); + + close_connection(connection); +} + + +static ebb_request* +new_request_wrapper(void *data) +{ + ebb_connection *connection = data; + if(connection->new_request) + return connection->new_request(connection); + return NULL; +} + +/* Internal callback + * Called by server->connection_watcher. + */ +static void +on_connection(struct ev_loop *loop, ev_io *watcher, int revents) +{ + ebb_server *server = watcher->data; + + //printf("on connection!\n"); + + assert(server->listening); + assert(server->loop == loop); + assert(&server->connection_watcher == watcher); + + if(EV_ERROR & revents) { + error("on_connection() got error event, closing server."); + ebb_server_unlisten(server); + return; + } + + struct sockaddr_in addr; // connector's address information + socklen_t addr_len = sizeof(addr); + int fd = accept( server->fd + , (struct sockaddr*) & addr + , & addr_len + ); + if(fd < 0) { + perror("accept()"); + return; + } + + ebb_connection *connection = NULL; + if(server->new_connection) + connection = server->new_connection(server, &addr); + if(connection == NULL) { + close(fd); + return; + } + + set_nonblock(fd); + connection->fd = fd; + connection->open = TRUE; + connection->server = server; + memcpy(&connection->sockaddr, &addr, addr_len); + if(server->port[0] != '\0') + connection->ip = inet_ntoa(connection->sockaddr.sin_addr); + +#ifdef SO_NOSIGPIPE + int arg = 1; + setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, &arg, sizeof(int)); +#endif + +#ifdef HAVE_GNUTLS + if(server->secure) { + gnutls_init(&connection->session, GNUTLS_SERVER); + gnutls_transport_set_lowat(connection->session, 0); + gnutls_set_default_priority(connection->session); + gnutls_credentials_set(connection->session, GNUTLS_CRD_CERTIFICATE, connection->server->credentials); + + gnutls_transport_set_ptr(connection->session, (gnutls_transport_ptr) fd); + gnutls_transport_set_push_function(connection->session, nosigpipe_push); + + gnutls_db_set_ptr (connection->session, &server->session_cache); + gnutls_db_set_store_function (connection->session, session_cache_store); + gnutls_db_set_retrieve_function (connection->session, session_cache_retrieve); + gnutls_db_set_remove_function (connection->session, session_cache_remove); + } + + ev_io_set(&connection->handshake_watcher, connection->fd, EV_READ | EV_WRITE); +#endif /* HAVE_GNUTLS */ + + /* Note: not starting the write watcher until there is data to be written */ + ev_io_set(&connection->write_watcher, connection->fd, EV_WRITE); + ev_io_set(&connection->read_watcher, connection->fd, EV_READ); + /* XXX: seperate error watcher? */ + + ev_timer_again(loop, &connection->timeout_watcher); + +#ifdef HAVE_GNUTLS + if(server->secure) { + ev_io_start(loop, &connection->handshake_watcher); + return; + } +#endif + + ev_io_start(loop, &connection->read_watcher); +} + +/** + * Begin the server listening on a file descriptor. This DOES NOT start the + * event loop. Start the event loop after making this call. + */ +int +ebb_server_listen_on_fd(ebb_server *server, const int fd) +{ + assert(server->listening == FALSE); + + if (listen(fd, EBB_MAX_CONNECTIONS) < 0) { + perror("listen()"); + return -1; + } + + set_nonblock(fd); /* XXX superfluous? */ + + server->fd = fd; + server->listening = TRUE; + + ev_io_set (&server->connection_watcher, server->fd, EV_READ); + ev_io_start (server->loop, &server->connection_watcher); + + return server->fd; +} + + +/** + * Begin the server listening on a file descriptor This DOES NOT start the + * event loop. Start the event loop after making this call. + */ +int +ebb_server_listen_on_port(ebb_server *server, const int port) +{ + int fd = -1; + struct linger ling = {0, 0}; + struct sockaddr_in addr; + int flags = 1; + + if ((fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { + perror("socket()"); + goto error; + } + + flags = 1; + setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void *)&flags, sizeof(flags)); + setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void *)&flags, sizeof(flags)); + setsockopt(fd, SOL_SOCKET, SO_LINGER, (void *)&ling, sizeof(ling)); + + /* XXX: Sending single byte chunks in a response body? Perhaps there is a + * need to enable the Nagel algorithm dynamically. For now disabling. + */ + setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (void *)&flags, sizeof(flags)); + + /* the memset call clears nonstandard fields in some impementations that + * otherwise mess things up. + */ + memset(&addr, 0, sizeof(addr)); + + addr.sin_family = AF_INET; + addr.sin_port = htons(port); + addr.sin_addr.s_addr = htonl(INADDR_ANY); + + if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) { + perror("bind()"); + goto error; + } + + int ret = ebb_server_listen_on_fd(server, fd); + if (ret >= 0) { + sprintf(server->port, "%d", port); + } + return ret; +error: + if(fd > 0) close(fd); + return -1; +} + +/** + * Stops the server. Will not accept new connections. Does not drop + * existing connections. + */ +void +ebb_server_unlisten(ebb_server *server) +{ + if(server->listening) { + ev_io_stop(server->loop, &server->connection_watcher); + close(server->fd); + server->port[0] = '\0'; + server->listening = FALSE; + } +} + +/** + * Initialize an ebb_server structure. After calling ebb_server_init set + * the callback server->new_connection and, optionally, callback data + * server->data. The new connection MUST be initialized with + * ebb_connection_init before returning it to the server. + * + * @param server the server to initialize + * @param loop a libev loop + */ +void +ebb_server_init(ebb_server *server, struct ev_loop *loop) +{ + server->loop = loop; + server->listening = FALSE; + server->port[0] = '\0'; + server->fd = -1; + server->connection_watcher.data = server; + ev_init (&server->connection_watcher, on_connection); + server->secure = FALSE; + +#ifdef HAVE_GNUTLS + rbtree_init(&server->session_cache, session_cache_compare); + server->credentials = NULL; +#endif + + server->new_connection = NULL; + server->data = NULL; +} + + +#ifdef HAVE_GNUTLS +/* similar to server_init. + * + * the user of secure server might want to set additional callbacks from + * GNUTLS. In particular + * gnutls_global_set_mem_functions() + * gnutls_global_set_log_function() + * Also see the note above ebb_connection_init() about setting gnutls cache + * access functions + * + * cert_file: the filename of a PEM certificate file + * + * key_file: the filename of a private key. Currently only PKCS-1 encoded + * RSA and DSA private keys are accepted. + */ +int +ebb_server_set_secure (ebb_server *server, const char *cert_file, const char *key_file) +{ + server->secure = TRUE; + gnutls_global_init(); + gnutls_certificate_allocate_credentials(&server->credentials); + /* todo gnutls_certificate_free_credentials */ + int r = gnutls_certificate_set_x509_key_file( server->credentials + , cert_file + , key_file + , GNUTLS_X509_FMT_PEM + ); + if(r < 0) { + error("loading certificates"); + return -1; + } + return 1; +} +#endif /* HAVE_GNUTLS */ + +/** + * Initialize an ebb_connection structure. After calling this function you + * must setup callbacks for the different actions the server can take. See + * server.h for which callbacks are availible. + * + * This should be called immediately after allocating space for a new + * ebb_connection structure. Most likely, this will only be called within + * the ebb_server->new_connection callback which you supply. + * + * If using SSL do consider setting + * gnutls_db_set_retrieve_function (connection->session, _); + * gnutls_db_set_remove_function (connection->session, _); + * gnutls_db_set_store_function (connection->session, _); + * gnutls_db_set_ptr (connection->session, _); + * To provide a better means of storing SSL session caches. libebb provides + * only a simple default implementation. + * + * @param connection the connection to initialize + * @param timeout the timeout in seconds + */ +void +ebb_connection_init(ebb_connection *connection) +{ + connection->fd = -1; + connection->server = NULL; + connection->ip = NULL; + connection->open = FALSE; + + ebb_request_parser_init( &connection->parser ); + connection->parser.data = connection; + connection->parser.new_request = new_request_wrapper; + + ev_init (&connection->write_watcher, on_writable); + connection->write_watcher.data = connection; + connection->to_write = NULL; + + ev_init(&connection->read_watcher, on_readable); + connection->read_watcher.data = connection; + +#ifdef HAVE_GNUTLS + connection->handshake_watcher.data = connection; + ev_init(&connection->handshake_watcher, on_handshake); + + ev_init(&connection->goodbye_tls_watcher, on_goodbye_tls); + connection->goodbye_tls_watcher.data = connection; + + connection->session = NULL; +#endif /* HAVE_GNUTLS */ + + ev_timer_init(&connection->goodbye_watcher, on_goodbye, 0., 0.); + connection->goodbye_watcher.data = connection; + + ev_timer_init(&connection->timeout_watcher, on_timeout, 0., EBB_DEFAULT_TIMEOUT); + connection->timeout_watcher.data = connection; + + connection->new_request = NULL; + connection->on_timeout = NULL; + connection->on_close = NULL; + connection->data = NULL; +} + +void +ebb_connection_schedule_close (ebb_connection *connection) +{ +#ifdef HAVE_GNUTLS + if(connection->server->secure) { + ev_io_set(&connection->goodbye_tls_watcher, connection->fd, EV_READ | EV_WRITE); + ev_io_start(connection->server->loop, &connection->goodbye_tls_watcher); + return; + } +#endif + ev_timer_start(connection->server->loop, &connection->goodbye_watcher); +} + +/* + * Resets the timeout to stay alive for another connection->timeout seconds + */ +void +ebb_connection_reset_timeout(ebb_connection *connection) +{ + ev_timer_again(connection->server->loop, &connection->timeout_watcher); +} + +/** + * Writes a string to the socket. This is actually sets a watcher + * which may take multiple iterations to write the entire string. + * + * This can only be called once at a time. If you call it again + * while the connection is writing another buffer the ebb_connection_write + * will return FALSE and ignore the request. + */ +int +ebb_connection_write (ebb_connection *connection, const char *buf, size_t len, ebb_after_write_cb cb) +{ + if(ev_is_active(&connection->write_watcher)) + return FALSE; + assert(!CONNECTION_HAS_SOMETHING_TO_WRITE); + connection->to_write = buf; + connection->to_write_len = len; + connection->written = 0; + connection->after_write_cb = cb; + ev_io_start(connection->server->loop, &connection->write_watcher); + return TRUE; +} + diff --git a/deps/libebb/ebb.h b/deps/libebb/ebb.h new file mode 100644 index 0000000000..e5e90b495e --- /dev/null +++ b/deps/libebb/ebb.h @@ -0,0 +1,120 @@ +/* This file is part of libebb. + * + * Copyright (c) 2008 Ryan Dahl (ry@ndahl.us) + * All rights reserved. + * + * 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. + */ +#ifndef EBB_H +#define EBB_H + +#include +#include +#include +#ifdef HAVE_GNUTLS +# include +# include "rbtree.h" /* for ebb_server.session_cache */ +#endif +#include "ebb_request_parser.h" + +#define EBB_MAX_CONNECTIONS 1024 +#define EBB_DEFAULT_TIMEOUT 30.0 + +#define EBB_AGAIN 0 +#define EBB_STOP 1 + +typedef struct ebb_server ebb_server; +typedef struct ebb_connection ebb_connection; +typedef void (*ebb_after_write_cb) (ebb_connection *connection); +typedef void (*ebb_connection_cb)(ebb_connection *connection, void *data); + +struct ebb_server { + int fd; /* ro */ + struct sockaddr_in sockaddr; /* ro */ + socklen_t socklen; /* ro */ + char port[6]; /* ro */ + struct ev_loop *loop; /* ro */ + unsigned listening:1; /* ro */ + unsigned secure:1; /* ro */ +#ifdef HAVE_GNUTLS + gnutls_certificate_credentials_t credentials; /* private */ + struct rbtree_t session_cache; /* private */ +#endif + ev_io connection_watcher; /* private */ + + /* Public */ + + /* Allocates and initializes an ebb_connection. NULL by default. */ + ebb_connection* (*new_connection) (ebb_server*, struct sockaddr_in*); + + void *data; +}; + +struct ebb_connection { + int fd; /* ro */ + struct sockaddr_in sockaddr; /* ro */ + socklen_t socklen; /* ro */ + ebb_server *server; /* ro */ + char *ip; /* ro */ + unsigned open:1; /* ro */ + + const char *to_write; /* ro */ + size_t to_write_len; /* ro */ + size_t written; /* ro */ + ebb_after_write_cb after_write_cb; /* ro */ + + ebb_request_parser parser; /* private */ + ev_io write_watcher; /* private */ + ev_io read_watcher; /* private */ + ev_timer timeout_watcher; /* private */ + ev_timer goodbye_watcher; /* private */ +#ifdef HAVE_GNUTLS + ev_io handshake_watcher; /* private */ + gnutls_session_t session; /* private */ + ev_io goodbye_tls_watcher; /* private */ +#endif + + /* Public */ + + ebb_request* (*new_request) (ebb_connection*); + + /* Returns EBB_STOP or EBB_AGAIN. NULL by default. */ + int (*on_timeout) (ebb_connection*); + + void (*on_close) (ebb_connection*); + + void *data; +}; + +void ebb_server_init (ebb_server *server, struct ev_loop *loop); +#ifdef HAVE_GNUTLS +int ebb_server_set_secure (ebb_server *server, const char *cert_file, + const char *key_file); +#endif +int ebb_server_listen_on_port (ebb_server *server, const int port); +int ebb_server_listen_on_fd (ebb_server *server, const int sfd); +void ebb_server_unlisten (ebb_server *server); + +void ebb_connection_init (ebb_connection *); +void ebb_connection_schedule_close (ebb_connection *); +void ebb_connection_reset_timeout (ebb_connection *); +int ebb_connection_write (ebb_connection *, const char *buf, size_t len, ebb_after_write_cb); + +#endif diff --git a/deps/libebb/ebb_request_parser.h b/deps/libebb/ebb_request_parser.h new file mode 100644 index 0000000000..93d502f4b5 --- /dev/null +++ b/deps/libebb/ebb_request_parser.h @@ -0,0 +1,117 @@ +/* This file is part of the libebb web server library + * + * Copyright (c) 2008 Ryan Dahl (ry@ndahl.us) + * All rights reserved. + * + * This parser is based on code from Zed Shaw's Mongrel. + * Copyright (c) 2005 Zed A. Shaw + * + * 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. + */ +#ifndef ebb_request_parser_h +#define ebb_request_parser_h +#ifdef __cplusplus +extern "C" { +#endif + + +#include + +typedef struct ebb_request ebb_request; +typedef struct ebb_request_parser ebb_request_parser; +typedef void (*ebb_header_cb)(ebb_request*, const char *at, size_t length, int header_index); +typedef void (*ebb_element_cb)(ebb_request*, const char *at, size_t length); + +#define EBB_MAX_MULTIPART_BOUNDARY_LEN 20 + +/* HTTP Methods */ +#define EBB_COPY 0x00000001 +#define EBB_DELETE 0x00000002 +#define EBB_GET 0x00000004 +#define EBB_HEAD 0x00000008 +#define EBB_LOCK 0x00000010 +#define EBB_MKCOL 0x00000020 +#define EBB_MOVE 0x00000040 +#define EBB_OPTIONS 0x00000080 +#define EBB_POST 0x00000100 +#define EBB_PROPFIND 0x00000200 +#define EBB_PROPPATCH 0x00000400 +#define EBB_PUT 0x00000800 +#define EBB_TRACE 0x00001000 +#define EBB_UNLOCK 0x00002000 + +/* Transfer Encodings */ +#define EBB_IDENTITY 0x00000001 +#define EBB_CHUNKED 0x00000002 + +struct ebb_request { + int method; + int transfer_encoding; /* ro */ + int expect_continue; /* ro */ + unsigned int version_major; /* ro */ + unsigned int version_minor; /* ro */ + int number_of_headers; /* ro */ + int keep_alive; /* private - use ebb_request_should_keep_alive */ + size_t content_length; /* ro - 0 if unknown */ + size_t body_read; /* ro */ + + /* Public - ordered list of callbacks */ + ebb_element_cb on_path; + ebb_element_cb on_query_string; + ebb_element_cb on_uri; + ebb_element_cb on_fragment; + ebb_header_cb on_header_field; + ebb_header_cb on_header_value; + void (*on_headers_complete)(ebb_request *); + ebb_element_cb on_body; + void (*on_complete)(ebb_request *); + void *data; +}; + +struct ebb_request_parser { + int cs; /* private */ + size_t chunk_size; /* private */ + unsigned eating:1; /* private */ + ebb_request *current_request; /* ro */ + const char *header_field_mark; + const char *header_value_mark; + const char *query_string_mark; + const char *path_mark; + const char *uri_mark; + const char *fragment_mark; + + /* Public */ + ebb_request* (*new_request)(void*); + void *data; +}; + +void ebb_request_parser_init(ebb_request_parser *parser); +size_t ebb_request_parser_execute(ebb_request_parser *parser, const char *data, size_t len); +int ebb_request_parser_has_error(ebb_request_parser *parser); +int ebb_request_parser_is_finished(ebb_request_parser *parser); +void ebb_request_init(ebb_request *); +int ebb_request_should_keep_alive(ebb_request *request); +#define ebb_request_has_body(request) \ + (request->transfer_encoding == EBB_CHUNKED || request->content_length > 0 ) + +#ifdef __cplusplus +} +#endif +#endif diff --git a/deps/libebb/ebb_request_parser.rl b/deps/libebb/ebb_request_parser.rl new file mode 100644 index 0000000000..63e36a8a49 --- /dev/null +++ b/deps/libebb/ebb_request_parser.rl @@ -0,0 +1,413 @@ +/* This file is part of the libebb web server library + * + * Copyright (c) 2008 Ryan Dahl (ry@ndahl.us) + * All rights reserved. + * + * This parser is based on code from Zed Shaw's Mongrel. + * Copyright (c) 2005 Zed A. Shaw + * + * 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. + */ +#include "ebb_request_parser.h" + +#include +#include + +static int unhex[] = {-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 + , 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1 + ,-1,10,11,12,13,14,15,-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,10,11,12,13,14,15,-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 + }; +#define TRUE 1 +#define FALSE 0 +#define MIN(a,b) (a < b ? a : b) + +#define REMAINING (pe - p) +#define CURRENT (parser->current_request) +#define CONTENT_LENGTH (parser->current_request->content_length) +#define CALLBACK(FOR) \ + if(parser->FOR##_mark && CURRENT->on_##FOR) { \ + CURRENT->on_##FOR( CURRENT \ + , parser->FOR##_mark \ + , p - parser->FOR##_mark \ + ); \ + } +#define HEADER_CALLBACK(FOR) \ + if(parser->FOR##_mark && CURRENT->on_##FOR) { \ + CURRENT->on_##FOR( CURRENT \ + , parser->FOR##_mark \ + , p - parser->FOR##_mark \ + , CURRENT->number_of_headers \ + ); \ + } +#define END_REQUEST \ + if(CURRENT->on_complete) \ + CURRENT->on_complete(CURRENT); \ + CURRENT = NULL; + + +%%{ + machine ebb_request_parser; + + action mark_header_field { parser->header_field_mark = p; } + action mark_header_value { parser->header_value_mark = p; } + action mark_fragment { parser->fragment_mark = p; } + action mark_query_string { parser->query_string_mark = p; } + action mark_request_path { parser->path_mark = p; } + action mark_request_uri { parser->uri_mark = p; } + + action write_field { + HEADER_CALLBACK(header_field); + parser->header_field_mark = NULL; + } + + action write_value { + HEADER_CALLBACK(header_value); + parser->header_value_mark = NULL; + } + + action request_uri { + CALLBACK(uri); + parser->uri_mark = NULL; + } + + action fragment { + CALLBACK(fragment); + parser->fragment_mark = NULL; + } + + action query_string { + CALLBACK(query_string); + parser->query_string_mark = NULL; + } + + action request_path { + CALLBACK(path); + parser->path_mark = NULL; + } + + action content_length { + CURRENT->content_length *= 10; + CURRENT->content_length += *p - '0'; + } + + action use_identity_encoding { CURRENT->transfer_encoding = EBB_IDENTITY; } + action use_chunked_encoding { CURRENT->transfer_encoding = EBB_CHUNKED; } + + action set_keep_alive { CURRENT->keep_alive = TRUE; } + action set_not_keep_alive { CURRENT->keep_alive = FALSE; } + + action expect_continue { + CURRENT->expect_continue = TRUE; + } + + action trailer { + /* not implemenetd yet. (do requests even have trailing headers?) */ + } + + action version_major { + CURRENT->version_major *= 10; + CURRENT->version_major += *p - '0'; + } + + action version_minor { + CURRENT->version_minor *= 10; + CURRENT->version_minor += *p - '0'; + } + + action end_header_line { + CURRENT->number_of_headers++; + } + + action end_headers { + if(CURRENT->on_headers_complete) + CURRENT->on_headers_complete(CURRENT); + } + + action add_to_chunk_size { + parser->chunk_size *= 16; + parser->chunk_size += unhex[(int)*p]; + } + + action skip_chunk_data { + skip_body(&p, parser, MIN(parser->chunk_size, REMAINING)); + fhold; + if(parser->chunk_size > REMAINING) { + fbreak; + } else { + fgoto chunk_end; + } + } + + action end_chunked_body { + END_REQUEST; + fnext main; + } + + action start_req { + assert(CURRENT == NULL); + CURRENT = parser->new_request(parser->data); + } + + action body_logic { + if(CURRENT->transfer_encoding == EBB_CHUNKED) { + fnext ChunkedBody; + } else { + /* this is pretty stupid. i'd prefer to combine this with skip_chunk_data */ + parser->chunk_size = CURRENT->content_length; + p += 1; + skip_body(&p, parser, MIN(REMAINING, CURRENT->content_length)); + fhold; + if(parser->chunk_size > REMAINING) { + fbreak; + } + } + } + +# +## +### +#### HTTP/1.1 STATE MACHINE +### +## RequestHeaders and character types are from +# Zed Shaw's beautiful Mongrel parser. + + CRLF = "\r\n"; + +# character types + CTL = (cntrl | 127); + safe = ("$" | "-" | "_" | "."); + extra = ("!" | "*" | "'" | "(" | ")" | ","); + reserved = (";" | "/" | "?" | ":" | "@" | "&" | "=" | "+"); + unsafe = (CTL | " " | "\"" | "#" | "%" | "<" | ">"); + national = any -- (alpha | digit | reserved | extra | safe | unsafe); + unreserved = (alpha | digit | safe | extra | national); + escape = ("%" xdigit xdigit); + uchar = (unreserved | escape); + pchar = (uchar | ":" | "@" | "&" | "=" | "+"); + tspecials = ("(" | ")" | "<" | ">" | "@" | "," | ";" | ":" | "\\" | "\"" | "/" | "[" | "]" | "?" | "=" | "{" | "}" | " " | "\t"); + +# elements + token = (ascii -- (CTL | tspecials)); + quote = "\""; +# qdtext = token -- "\""; +# quoted_pair = "\" ascii; +# quoted_string = "\"" (qdtext | quoted_pair )* "\""; + +# headers + + Method = ( "COPY" %{ CURRENT->method = EBB_COPY; } + | "DELETE" %{ CURRENT->method = EBB_DELETE; } + | "GET" %{ CURRENT->method = EBB_GET; } + | "HEAD" %{ CURRENT->method = EBB_HEAD; } + | "LOCK" %{ CURRENT->method = EBB_LOCK; } + | "MKCOL" %{ CURRENT->method = EBB_MKCOL; } + | "MOVE" %{ CURRENT->method = EBB_MOVE; } + | "OPTIONS" %{ CURRENT->method = EBB_OPTIONS; } + | "POST" %{ CURRENT->method = EBB_POST; } + | "PROPFIND" %{ CURRENT->method = EBB_PROPFIND; } + | "PROPPATCH" %{ CURRENT->method = EBB_PROPPATCH; } + | "PUT" %{ CURRENT->method = EBB_PUT; } + | "TRACE" %{ CURRENT->method = EBB_TRACE; } + | "UNLOCK" %{ CURRENT->method = EBB_UNLOCK; } + ); # Not allowing extension methods + + HTTP_Version = "HTTP/" digit+ $version_major "." digit+ $version_minor; + + scheme = ( alpha | digit | "+" | "-" | "." )* ; + absolute_uri = (scheme ":" (uchar | reserved )*); + path = ( pchar+ ( "/" pchar* )* ) ; + query = ( uchar | reserved )* >mark_query_string %query_string ; + param = ( pchar | "/" )* ; + params = ( param ( ";" param )* ) ; + rel_path = ( path? (";" params)? ) ; + absolute_path = ( "/"+ rel_path ) >mark_request_path %request_path ("?" query)?; + Request_URI = ( "*" | absolute_uri | absolute_path ) >mark_request_uri %request_uri; + Fragment = ( uchar | reserved )* >mark_fragment %fragment; + + field_name = ( token -- ":" )+; + Field_Name = field_name >mark_header_field %write_field; + + field_value = ((any - " ") any*)?; + Field_Value = field_value >mark_header_value %write_value; + + hsep = ":" " "*; + header = (field_name hsep field_value) :> CRLF; + Header = ( ("Content-Length"i hsep digit+ $content_length) + | ("Connection"i hsep + ( "Keep-Alive"i %set_keep_alive + | "close"i %set_not_keep_alive + ) + ) + | ("Transfer-Encoding"i %use_chunked_encoding hsep "identity" %use_identity_encoding) + # | ("Expect"i hsep "100-continue"i %expect_continue) + # | ("Trailer"i hsep field_value %trailer) + | (Field_Name hsep Field_Value) + ) :> CRLF; + + Request_Line = ( Method " " Request_URI ("#" Fragment)? " " HTTP_Version CRLF ) ; + RequestHeader = Request_Line (Header %end_header_line)* :> CRLF @end_headers; + +# chunked message + trailing_headers = header*; + #chunk_ext_val = token | quoted_string; + chunk_ext_val = token*; + chunk_ext_name = token*; + chunk_extension = ( ";" " "* chunk_ext_name ("=" chunk_ext_val)? )*; + last_chunk = "0"+ chunk_extension CRLF; + chunk_size = (xdigit* [1-9a-fA-F] xdigit*) $add_to_chunk_size; + chunk_end = CRLF; + chunk_body = any >skip_chunk_data; + chunk_begin = chunk_size chunk_extension CRLF; + chunk = chunk_begin chunk_body chunk_end; + ChunkedBody := chunk* last_chunk trailing_headers CRLF @end_chunked_body; + + Request = RequestHeader >start_req @body_logic; + + main := Request*; # sequence of requests (for keep-alive) +}%% + +%% write data; + +static void +skip_body(const char **p, ebb_request_parser *parser, size_t nskip) { + if(CURRENT->on_body && nskip > 0) { + CURRENT->on_body(CURRENT, *p, nskip); + } + CURRENT->body_read += nskip; + parser->chunk_size -= nskip; + *p += nskip; + if(0 == parser->chunk_size) { + parser->eating = FALSE; + if(CURRENT->transfer_encoding == EBB_IDENTITY) { + END_REQUEST; + } + } else { + parser->eating = TRUE; + } +} + +void ebb_request_parser_init(ebb_request_parser *parser) +{ + int cs = 0; + %% write init; + parser->cs = cs; + + parser->chunk_size = 0; + parser->eating = 0; + + parser->current_request = NULL; + + parser->header_field_mark = parser->header_value_mark = + parser->query_string_mark = parser->path_mark = + parser->uri_mark = parser->fragment_mark = NULL; + + parser->new_request = NULL; +} + + +/** exec **/ +size_t ebb_request_parser_execute(ebb_request_parser *parser, const char *buffer, size_t len) +{ + const char *p, *pe; + int cs = parser->cs; + + assert(parser->new_request && "undefined callback"); + + p = buffer; + pe = buffer+len; + + if(0 < parser->chunk_size && parser->eating) { + /* eat body */ + size_t eat = MIN(len, parser->chunk_size); + skip_body(&p, parser, eat); + } + + if(parser->header_field_mark) parser->header_field_mark = buffer; + if(parser->header_value_mark) parser->header_value_mark = buffer; + if(parser->fragment_mark) parser->fragment_mark = buffer; + if(parser->query_string_mark) parser->query_string_mark = buffer; + if(parser->path_mark) parser->path_mark = buffer; + if(parser->uri_mark) parser->uri_mark = buffer; + + %% write exec; + + parser->cs = cs; + + HEADER_CALLBACK(header_field); + HEADER_CALLBACK(header_value); + CALLBACK(fragment); + CALLBACK(query_string); + CALLBACK(path); + CALLBACK(uri); + + assert(p <= pe && "buffer overflow after parsing execute"); + + return(p - buffer); +} + +int ebb_request_parser_has_error(ebb_request_parser *parser) +{ + return parser->cs == ebb_request_parser_error; +} + +int ebb_request_parser_is_finished(ebb_request_parser *parser) +{ + return parser->cs == ebb_request_parser_first_final; +} + +void ebb_request_init(ebb_request *request) +{ + request->expect_continue = FALSE; + request->body_read = 0; + request->content_length = 0; + request->version_major = 0; + request->version_minor = 0; + request->number_of_headers = 0; + request->transfer_encoding = EBB_IDENTITY; + request->keep_alive = -1; + + request->on_complete = NULL; + request->on_headers_complete = NULL; + request->on_body = NULL; + request->on_header_field = NULL; + request->on_header_value = NULL; + request->on_uri = NULL; + request->on_fragment = NULL; + request->on_path = NULL; + request->on_query_string = NULL; +} + +int ebb_request_should_keep_alive(ebb_request *request) +{ + if(request->keep_alive == -1) + if(request->version_major == 1) + return (request->version_minor != 0); + else if(request->version_major == 0) + return FALSE; + else + return TRUE; + else + return request->keep_alive; +} diff --git a/deps/libebb/examples/ca-cert.pem b/deps/libebb/examples/ca-cert.pem new file mode 100644 index 0000000000..606283b1ec --- /dev/null +++ b/deps/libebb/examples/ca-cert.pem @@ -0,0 +1,12 @@ +-----BEGIN CERTIFICATE----- +MIIBzDCCATegAwIBAgIESIuNVTALBgkqhkiG9w0BAQUwADAeFw0wODA3MjYyMDQ3 +MTlaFw0xMTA0MjIyMDQ3MjVaMAAwgZwwCwYJKoZIhvcNAQEBA4GMADCBiAKBgOm9 +l/FoXbTIcEusk/QlS5YrlR04+oWIbSdZIf3GJBEWEUPljDxAX96qHsTcaVnGK+EP +keU4cIZvdY+hzbqa5cc1j2/9IeJNejL8gpQ/ocyMM69yq5Ib2F8K4mGWm1xr30hU +bYpY5D0MrZ1b0HtYFVc8KVAr0ADGG+pye0P9c3B/AgMBAAGjWjBYMAwGA1UdEwEB +/wQCMAAwFAYDVR0RBA0wC4IJbG9jYWxob3N0MBMGA1UdJQQMMAoGCCsGAQUFBwMB +MB0GA1UdDgQWBBTYgVB7kJnnm+jgX9DgrapzGfUmxjALBgkqhkiG9w0BAQUDgYEA +GkadA2H8CAzU3w4oCGZu9Ry9Tj/9Agw1XMFKvoJuG7VLPk7+B25JvNFVsmpROLxO +0TJ6mIU2hz5/rLvEfTBGQ+DYtbsjIxCz1fD7R5c1kKBtA0d0u8mY8pTlPNlxFPSW +3ymx5DB2zyDa/HuX6m6/VmzMYmA0vp7Dp1cl+pA9Nhs= +-----END CERTIFICATE----- diff --git a/deps/libebb/examples/ca-key.pem b/deps/libebb/examples/ca-key.pem new file mode 100644 index 0000000000..afb953d69b --- /dev/null +++ b/deps/libebb/examples/ca-key.pem @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXQIBAAKBgQDpvZfxaF20yHBLrJP0JUuWK5UdOPqFiG0nWSH9xiQRFhFD5Yw8 +QF/eqh7E3GlZxivhD5HlOHCGb3WPoc26muXHNY9v/SHiTXoy/IKUP6HMjDOvcquS +G9hfCuJhlptca99IVG2KWOQ9DK2dW9B7WBVXPClQK9AAxhvqcntD/XNwfwIDAQAB +AoGAJqo3LTbfcV1KvinhG5zjwQaalwfq4RXtQHoNFmalZrIozvt01C6t7S5lApmX +T8NpVMR3lNxeOM7NOqJAXuLqqVVqk81YEYuMx6E4gB/Ifl7jVZk1jstmLILhh59D +pXrlpzvvm5X2hVsI7lp/YGAvtdLS1iVy37bGgmQWfCeeZiECQQDtZLfcJb4oE1yR +ZfLOcPDlBCw02wGMNFpAjwbspf/du3Yn3ONWHVfhSCCcCe262h9PLblL97LoB+gF +OHOlM9JvAkEA/A+U3/p9pwL4L742pxZP62/rmk6p5mZFIykk2jIUTpdilXBWBlcT +OjgjnpquZpwnaClmvgFpkzdhIPF7Nq4K8QJBAITVKagOmnOUOeTF1fI78h9DkXTV +4uzP0nxzS52ZWS16Gqg9ihuCecz97flB+Prn2EMWw6tFY58/5U0ehF85OxMCQQDF +08TYdVSg+6emcPeb89sNwW18UjjuZ13j1qrhxWRCunXZK62YlEa27tCl7mjqh6w2 +CChm/9zIejJ1FJHLvJVBAkBj63ZbwggMYkxuj60jIBbNrEtDx9y7zM0sXkiJqcKp +5uGtJNafG+yZrLAHE6/b4aqUOtGsCGsiZpT9ms7CoaVr +-----END RSA PRIVATE KEY----- diff --git a/deps/libebb/examples/hello_world.c b/deps/libebb/examples/hello_world.c new file mode 100644 index 0000000000..bec0070937 --- /dev/null +++ b/deps/libebb/examples/hello_world.c @@ -0,0 +1,101 @@ +#include +#include +#include +#include +#include + +#include +#include "ebb.h" + +#define MSG ("HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\nContent-Length: 12\r\n\r\nhello world\n") +static int c = 0; + +struct hello_connection { + unsigned int responses_to_write; +}; + +void on_close(ebb_connection *connection) +{ + free(connection->data); + free(connection); +} + +static void continue_responding(ebb_connection *connection) +{ + int r; + struct hello_connection *connection_data = connection->data; + //printf("response complete \n"); + if(--connection_data->responses_to_write > 0) { + /* write another response */ + r = ebb_connection_write(connection, MSG, sizeof MSG, continue_responding); + assert(r); + } else { + ebb_connection_schedule_close(connection); + } +} + +static void request_complete(ebb_request *request) +{ + //printf("request complete \n"); + ebb_connection *connection = request->data; + struct hello_connection *connection_data = connection->data; + + if(ebb_request_should_keep_alive(request)) + connection_data->responses_to_write++; + else + connection_data->responses_to_write = 1; + + ebb_connection_write(connection, MSG, sizeof MSG, continue_responding); + free(request); +} + +static ebb_request* new_request(ebb_connection *connection) +{ + //printf("request %d\n", ++c); + ebb_request *request = malloc(sizeof(ebb_request)); + ebb_request_init(request); + request->data = connection; + request->on_complete = request_complete; + return request; +} + +ebb_connection* new_connection(ebb_server *server, struct sockaddr_in *addr) +{ + struct hello_connection *connection_data = malloc(sizeof(struct hello_connection)); + if(connection_data == NULL) + return NULL; + connection_data->responses_to_write = 0; + + ebb_connection *connection = malloc(sizeof(ebb_connection)); + if(connection == NULL) { + free(connection_data); + return NULL; + } + + ebb_connection_init(connection); + connection->data = connection_data; + connection->new_request = new_request; + connection->on_close = on_close; + + printf("connection: %d\n", c++); + return connection; +} + +int main(int argc, char **_) +{ + struct ev_loop *loop = ev_default_loop(0); + ebb_server server; + + ebb_server_init(&server, loop); + if(argc > 1) { + printf("using SSL\n"); + ebb_server_set_secure(&server, "ca-cert.pem", "ca-key.pem"); + } + server.new_connection = new_connection; + + printf("hello_world listening on port 5000\n"); + ebb_server_listen_on_port(&server, 5000); + ev_loop(loop, 0); + + return 0; +} diff --git a/deps/libebb/rbtree.c b/deps/libebb/rbtree.c new file mode 100644 index 0000000000..4a66972a26 --- /dev/null +++ b/deps/libebb/rbtree.c @@ -0,0 +1,412 @@ +/* Copyright (c) 2008 Derrick Coetzee + * http://en.literateprograms.org/Red-black_tree_(C)?oldid=7982 + * + * 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. +*/ + +#include "rbtree.h" +#include + +#ifndef NULL +# define NULL ((void*)0) +#endif + + +typedef rbtree_node node; +typedef enum rbtree_node_color color; + + +static node grandparent(node n); +static node sibling(node n); +static node uncle(node n); +static void verify_properties(rbtree t); +static void verify_property_1(node root); +/* static void verify_property_2(node root); */ +static color node_color(node n); +static void verify_property_4(node root); +/* static void verify_property_5(node root); */ +static void verify_property_5_helper(node n, int black_count, int* black_count_path); + +static node lookup_node(rbtree t, void* key); +static void rotate_left(rbtree t, node n); +static void rotate_right(rbtree t, node n); + +static void replace_node(rbtree t, node oldn, node newn); +static void insert_case1(rbtree t, node n); +static void insert_case2(rbtree t, node n); +static void insert_case3(rbtree t, node n); +static void insert_case4(rbtree t, node n); +static void insert_case5(rbtree t, node n); +static node maximum_node(node root); +static void delete_case1(rbtree t, node n); +static void delete_case2(rbtree t, node n); +static void delete_case3(rbtree t, node n); +static void delete_case4(rbtree t, node n); +static void delete_case5(rbtree t, node n); +static void delete_case6(rbtree t, node n); + +node grandparent(node n) { + assert (n != NULL); + assert (n->parent != NULL); /* Not the root node */ + assert (n->parent->parent != NULL); /* Not child of root */ + return n->parent->parent; +} + +node sibling(node n) { + assert (n != NULL); + assert (n->parent != NULL); /* Root node has no sibling */ + if (n == n->parent->left) + return n->parent->right; + else + return n->parent->left; +} + +node uncle(node n) { + assert (n != NULL); + assert (n->parent != NULL); /* Root node has no uncle */ + assert (n->parent->parent != NULL); /* Children of root have no uncle */ + return sibling(n->parent); +} + +void verify_properties(rbtree t) { +#ifdef VERIFY_RBTREE + verify_property_1(t->root); + verify_property_2(t->root); + /* Property 3 is implicit */ + verify_property_4(t->root); + verify_property_5(t->root); +#endif +} + +void verify_property_1(node n) { + assert(node_color(n) == RED || node_color(n) == BLACK); + if (n == NULL) return; + verify_property_1(n->left); + verify_property_1(n->right); +} + +/* +void verify_property_2(node root) { + assert(node_color(root) == BLACK); +} +*/ + +color node_color(node n) { + return n == NULL ? BLACK : n->color; +} + +void verify_property_4(node n) { + if (node_color(n) == RED) { + assert (node_color(n->left) == BLACK); + assert (node_color(n->right) == BLACK); + assert (node_color(n->parent) == BLACK); + } + if (n == NULL) return; + verify_property_4(n->left); + verify_property_4(n->right); +} + +/* +void verify_property_5(node root) { + int black_count_path = -1; + verify_property_5_helper(root, 0, &black_count_path); +} +*/ + +void verify_property_5_helper(node n, int black_count, int* path_black_count) { + if (node_color(n) == BLACK) { + black_count++; + } + if (n == NULL) { + if (*path_black_count == -1) { + *path_black_count = black_count; + } else { + assert (black_count == *path_black_count); + } + return; + } + verify_property_5_helper(n->left, black_count, path_black_count); + verify_property_5_helper(n->right, black_count, path_black_count); +} + +void rbtree_init(rbtree t, rbtree_compare_func compare) { + t->root = NULL; + t->compare = compare; + verify_properties(t); +} + +node lookup_node(rbtree t, void* key) { + node n = t->root; + while (n != NULL) { + int comp_result = t->compare(key, n->key); + if (comp_result == 0) { + return n; + } else if (comp_result < 0) { + n = n->left; + } else { + assert(comp_result > 0); + n = n->right; + } + } + return n; +} + +void* rbtree_lookup(rbtree t, void* key) { + node n = lookup_node(t, key); + return n == NULL ? NULL : n->value; +} + +void rotate_left(rbtree t, node n) { + node r = n->right; + replace_node(t, n, r); + n->right = r->left; + if (r->left != NULL) { + r->left->parent = n; + } + r->left = n; + n->parent = r; +} + +void rotate_right(rbtree t, node n) { + node L = n->left; + replace_node(t, n, L); + n->left = L->right; + if (L->right != NULL) { + L->right->parent = n; + } + L->right = n; + n->parent = L; +} + +void replace_node(rbtree t, node oldn, node newn) { + if (oldn->parent == NULL) { + t->root = newn; + } else { + if (oldn == oldn->parent->left) + oldn->parent->left = newn; + else + oldn->parent->right = newn; + } + if (newn != NULL) { + newn->parent = oldn->parent; + } +} + +void rbtree_insert(rbtree t, rbtree_node inserted_node) { + inserted_node->color = RED; + inserted_node->left = NULL; + inserted_node->right = NULL; + inserted_node->parent = NULL; + + if (t->root == NULL) { + t->root = inserted_node; + } else { + node n = t->root; + while (1) { + int comp_result = t->compare(inserted_node->key, n->key); + if (comp_result == 0) { + n->value = inserted_node->value; + return; + } else if (comp_result < 0) { + if (n->left == NULL) { + n->left = inserted_node; + break; + } else { + n = n->left; + } + } else { + assert (comp_result > 0); + if (n->right == NULL) { + n->right = inserted_node; + break; + } else { + n = n->right; + } + } + } + inserted_node->parent = n; + } + insert_case1(t, inserted_node); + verify_properties(t); +} + +void insert_case1(rbtree t, node n) { + if (n->parent == NULL) + n->color = BLACK; + else + insert_case2(t, n); +} + +void insert_case2(rbtree t, node n) { + if (node_color(n->parent) == BLACK) + return; /* Tree is still valid */ + else + insert_case3(t, n); +} + +void insert_case3(rbtree t, node n) { + if (node_color(uncle(n)) == RED) { + n->parent->color = BLACK; + uncle(n)->color = BLACK; + grandparent(n)->color = RED; + insert_case1(t, grandparent(n)); + } else { + insert_case4(t, n); + } +} + +void insert_case4(rbtree t, node n) { + if (n == n->parent->right && n->parent == grandparent(n)->left) { + rotate_left(t, n->parent); + n = n->left; + } else if (n == n->parent->left && n->parent == grandparent(n)->right) { + rotate_right(t, n->parent); + n = n->right; + } + insert_case5(t, n); +} + +void insert_case5(rbtree t, node n) { + n->parent->color = BLACK; + grandparent(n)->color = RED; + if (n == n->parent->left && n->parent == grandparent(n)->left) { + rotate_right(t, grandparent(n)); + } else { + assert (n == n->parent->right && n->parent == grandparent(n)->right); + rotate_left(t, grandparent(n)); + } +} + +rbtree_node rbtree_delete(rbtree t, void* key) { + node child; + node n = lookup_node(t, key); + if (n == NULL) return NULL; /* Key not found, do nothing */ + if (n->left != NULL && n->right != NULL) { + /* Copy key/value from predecessor and then delete it instead */ + node pred = maximum_node(n->left); + n->key = pred->key; + n->value = pred->value; + n = pred; + } + + assert(n->left == NULL || n->right == NULL); + child = n->right == NULL ? n->left : n->right; + if (node_color(n) == BLACK) { + n->color = node_color(child); + delete_case1(t, n); + } + replace_node(t, n, child); + + verify_properties(t); + return n; +} + +static node maximum_node(node n) { + assert (n != NULL); + while (n->right != NULL) { + n = n->right; + } + return n; +} + +void delete_case1(rbtree t, node n) { + if (n->parent == NULL) + return; + else + delete_case2(t, n); +} + +void delete_case2(rbtree t, node n) { + if (node_color(sibling(n)) == RED) { + n->parent->color = RED; + sibling(n)->color = BLACK; + if (n == n->parent->left) + rotate_left(t, n->parent); + else + rotate_right(t, n->parent); + } + delete_case3(t, n); +} + +void delete_case3(rbtree t, node n) { + if (node_color(n->parent) == BLACK && + node_color(sibling(n)) == BLACK && + node_color(sibling(n)->left) == BLACK && + node_color(sibling(n)->right) == BLACK) + { + sibling(n)->color = RED; + delete_case1(t, n->parent); + } + else + delete_case4(t, n); +} + +void delete_case4(rbtree t, node n) { + if (node_color(n->parent) == RED && + node_color(sibling(n)) == BLACK && + node_color(sibling(n)->left) == BLACK && + node_color(sibling(n)->right) == BLACK) + { + sibling(n)->color = RED; + n->parent->color = BLACK; + } + else + delete_case5(t, n); +} + +void delete_case5(rbtree t, node n) { + if (n == n->parent->left && + node_color(sibling(n)) == BLACK && + node_color(sibling(n)->left) == RED && + node_color(sibling(n)->right) == BLACK) + { + sibling(n)->color = RED; + sibling(n)->left->color = BLACK; + rotate_right(t, sibling(n)); + } + else if (n == n->parent->right && + node_color(sibling(n)) == BLACK && + node_color(sibling(n)->right) == RED && + node_color(sibling(n)->left) == BLACK) + { + sibling(n)->color = RED; + sibling(n)->right->color = BLACK; + rotate_left(t, sibling(n)); + } + delete_case6(t, n); +} + +void delete_case6(rbtree t, node n) { + sibling(n)->color = node_color(n->parent); + n->parent->color = BLACK; + if (n == n->parent->left) { + assert (node_color(sibling(n)->right) == RED); + sibling(n)->right->color = BLACK; + rotate_left(t, n->parent); + } + else + { + assert (node_color(sibling(n)->left) == RED); + sibling(n)->left->color = BLACK; + rotate_right(t, n->parent); + } +} + + diff --git a/deps/libebb/rbtree.h b/deps/libebb/rbtree.h new file mode 100644 index 0000000000..5962a3c118 --- /dev/null +++ b/deps/libebb/rbtree.h @@ -0,0 +1,54 @@ +/* Copyright (c) 2008 Derrick Coetzee + * http://en.literateprograms.org/Red-black_tree_(C)?oldid=7982 + * Small changes by Ryah Dahl + * + * 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. + */ + +#ifndef _RBTREE_H_ +#define _RBTREE_H_ + +enum rbtree_node_color { RED, BLACK }; + +typedef int (*rbtree_compare_func)(void* left_key, void* right_key); + +typedef struct rbtree_node_t { + struct rbtree_node_t* left; /* private */ + struct rbtree_node_t* right; /* private */ + struct rbtree_node_t* parent; /* private */ + enum rbtree_node_color color; /* private */ + void* key; /* public */ + void* value; /* public */ +} *rbtree_node; + +typedef struct rbtree_t { + rbtree_node root; /* private */ + rbtree_compare_func compare; /* private */ +} *rbtree; + + +void rbtree_init(rbtree t, rbtree_compare_func); +void* rbtree_lookup(rbtree t, void* key); +void rbtree_insert(rbtree t, rbtree_node); +/* you must free the returned node */ +rbtree_node rbtree_delete(rbtree t, void* key); + +#endif + diff --git a/deps/libebb/test_examples.rb b/deps/libebb/test_examples.rb new file mode 100644 index 0000000000..2af658cab8 --- /dev/null +++ b/deps/libebb/test_examples.rb @@ -0,0 +1,60 @@ +require 'test/unit' +require 'socket' + +REQ = "GET /hello/%d HTTP/1.1\r\n\r\n" +HOST = '0.0.0.0' +PORT = 5000 + +class TCPSocket + def full_send(string) + written = 0 + while(written < string.length) + sent = write(string) + string = string.slice(sent, 10000) + end + written + end + + def full_read + response = "" + while chunk = read(10000) + response += chunk + end + response + end + +end + +class EbbTest < Test::Unit::TestCase + + def setup + @socket = TCPSocket.new(HOST, PORT) + end + + def test_bad_req + @socket.full_send("hello") + assert_equal "", @socket.full_read + #assert @socket.closed? + end + + def test_single + written = 0 + req = REQ % 1 + @socket.full_send(req) + response = @socket.full_read() + count = 0 + response.scan("hello world") { count += 1 } + + assert_equal 1, count + end + + def test_pipeline + written = 0 + req = (REQ % 1) + (REQ % 2) + (REQ % 3) + (REQ % 4) + @socket.full_send(req) + response = @socket.full_read() + count = 0 + response.scan("hello world") { count += 1 } + assert_equal 4, count + end +end diff --git a/deps/libebb/test_rbtree.c b/deps/libebb/test_rbtree.c new file mode 100644 index 0000000000..f5ee1d6cd1 --- /dev/null +++ b/deps/libebb/test_rbtree.c @@ -0,0 +1,108 @@ +/* Copyright (c) 2008 Derrick Coetzee + * http://en.literateprograms.org/Red-black_tree_(C)?oldid=7982 + * + * 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. +*/ + +#include "rbtree.h" +#include +#include +#include /* rand(), malloc(), free() */ + +static int compare_int(void* left, void* right); +static void print_tree(rbtree t); +static void print_tree_helper(rbtree_node n, int indent); + +int compare_int(void* leftp, void* rightp) { + int left = (int)leftp; + int right = (int)rightp; + if (left < right) + return -1; + else if (left > right) + return 1; + else { + assert (left == right); + return 0; + } +} + +#define INDENT_STEP 4 + +void print_tree_helper(rbtree_node n, int indent); + +void print_tree(rbtree t) { + print_tree_helper(t->root, 0); + puts(""); +} + +void print_tree_helper(rbtree_node n, int indent) { + int i; + if (n == NULL) { + fputs("", stdout); + return; + } + if (n->right != NULL) { + print_tree_helper(n->right, indent + INDENT_STEP); + } + for(i=0; icolor == BLACK) + printf("%d\n", (int)n->key); + else + printf("<%d>\n", (int)n->key); + if (n->left != NULL) { + print_tree_helper(n->left, indent + INDENT_STEP); + } +} + +int main() { + int i; + struct rbtree_t t; + rbtree_init(&t, compare_int); + print_tree(&t); + + for(i=0; i<5000; i++) { + int x = rand() % 10000; + int y = rand() % 10000; +#ifdef TRACE + print_tree(&t); + printf("Inserting %d -> %d\n\n", x, y); +#endif + rbtree_node node = (rbtree_node) malloc(sizeof(struct rbtree_node_t)); + node->key = (void*)x; + node->value = (void*)y; + rbtree_insert(&t, node); + assert(rbtree_lookup(&t, (void*)x) == (void*)y); + } + for(i=0; i<60000; i++) { + int x = rand() % 10000; +#ifdef TRACE + print_tree(&t); + printf("Deleting key %d\n\n", x); +#endif + rbtree_node n = rbtree_delete(&t, (void*)x); + if(n != NULL) { + free(n); + } + } + printf("Okay\n"); + return 0; +} + diff --git a/deps/libebb/test_request_parser.c b/deps/libebb/test_request_parser.c new file mode 100644 index 0000000000..5a5dca38f1 --- /dev/null +++ b/deps/libebb/test_request_parser.c @@ -0,0 +1,746 @@ +/* unit tests for request parser + * Copyright 2008 ryah dahl, ry@ndahl.us + * + * This software may be distributed under the "MIT" license included in the + * README + */ +#include "ebb_request_parser.h" +#include +#include +#include +#include + +#define TRUE 1 +#define FALSE 0 + +#define MAX_HEADERS 500 +#define MAX_ELEMENT_SIZE 500 + +static ebb_request_parser parser; +struct request_data { + const char *raw; + int request_method; + char request_path[MAX_ELEMENT_SIZE]; + char request_uri[MAX_ELEMENT_SIZE]; + char fragment[MAX_ELEMENT_SIZE]; + char query_string[MAX_ELEMENT_SIZE]; + char body[MAX_ELEMENT_SIZE]; + int num_headers; + char header_fields[MAX_HEADERS][MAX_ELEMENT_SIZE]; + char header_values[MAX_HEADERS][MAX_ELEMENT_SIZE]; + int should_keep_alive; + ebb_request request; +}; +static struct request_data requests[5]; +static int num_requests; + +const struct request_data curl_get = + { raw: "GET /test HTTP/1.1\r\n" + "User-Agent: curl/7.18.0 (i486-pc-linux-gnu) libcurl/7.18.0 OpenSSL/0.9.8g zlib/1.2.3.3 libidn/1.1\r\n" + "Host: 0.0.0.0:5000\r\n" + "Accept: */*\r\n" + "\r\n" + , should_keep_alive: TRUE + , request_method: EBB_GET + , query_string: "" + , fragment: "" + , request_path: "/test" + , request_uri: "/test" + , num_headers: 3 + , header_fields: { "User-Agent", "Host", "Accept" } + , header_values: { "curl/7.18.0 (i486-pc-linux-gnu) libcurl/7.18.0 OpenSSL/0.9.8g zlib/1.2.3.3 libidn/1.1", "0.0.0.0:5000", "*/*" } + , body: "" + }; + +const struct request_data firefox_get = + { raw: "GET /favicon.ico HTTP/1.1\r\n" + "Host: 0.0.0.0:5000\r\n" + "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9) Gecko/2008061015 Firefox/3.0\r\n" + "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n" + "Accept-Language: en-us,en;q=0.5\r\n" + "Accept-Encoding: gzip,deflate\r\n" + "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\n" + "Keep-Alive: 300\r\n" + "Connection: keep-alive\r\n" + "\r\n" + , should_keep_alive: TRUE + , request_method: EBB_GET + , query_string: "" + , fragment: "" + , request_path: "/favicon.ico" + , request_uri: "/favicon.ico" + , num_headers: 8 + , header_fields: + { "Host" + , "User-Agent" + , "Accept" + , "Accept-Language" + , "Accept-Encoding" + , "Accept-Charset" + , "Keep-Alive" + , "Connection" + } + , header_values: + { "0.0.0.0:5000" + , "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9) Gecko/2008061015 Firefox/3.0" + , "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8" + , "en-us,en;q=0.5" + , "gzip,deflate" + , "ISO-8859-1,utf-8;q=0.7,*;q=0.7" + , "300" + , "keep-alive" + } + , body: "" + }; + +const struct request_data dumbfuck = + { raw: "GET /dumbfuck HTTP/1.1\r\n" + "aaaaaaaaaaaaa:++++++++++\r\n" + "\r\n" + , should_keep_alive: TRUE + , request_method: EBB_GET + , query_string: "" + , fragment: "" + , request_path: "/dumbfuck" + , request_uri: "/dumbfuck" + , num_headers: 1 + , header_fields: { "aaaaaaaaaaaaa" } + , header_values: { "++++++++++" } + , body: "" + }; + +const struct request_data fragment_in_uri = + { raw: "GET /forums/1/topics/2375?page=1#posts-17408 HTTP/1.1\r\n" + "\r\n" + , should_keep_alive: TRUE + , request_method: EBB_GET + , query_string: "page=1" + , fragment: "posts-17408" + , request_path: "/forums/1/topics/2375" + /* XXX request uri does not include fragment? */ + , request_uri: "/forums/1/topics/2375?page=1" + , num_headers: 0 + , body: "" + }; + + +// get - no headers - no body +const struct request_data get_no_headers_no_body = + { raw: "GET /get_no_headers_no_body/world HTTP/1.1\r\n" + "\r\n" + , should_keep_alive: TRUE + , request_method: EBB_GET + , query_string: "" + , fragment: "" + , request_path: "/get_no_headers_no_body/world" + , request_uri: "/get_no_headers_no_body/world" + , num_headers: 0 + , body: "" + }; + +// get - one header - no body +const struct request_data get_one_header_no_body = + { raw: "GET /get_one_header_no_body HTTP/1.1\r\n" + "Accept: */*\r\n" + "\r\n" + , should_keep_alive: TRUE + , request_method: EBB_GET + , query_string: "" + , fragment: "" + , request_path: "/get_one_header_no_body" + , request_uri: "/get_one_header_no_body" + , num_headers: 1 + , header_fields: { "Accept" } + , header_values: { "*/*" } + , body: "" + }; + +// get - no headers - body "HELLO" +const struct request_data get_funky_content_length_body_hello = + { raw: "GET /get_funky_content_length_body_hello HTTP/1.0\r\n" + "conTENT-Length: 5\r\n" + "\r\n" + "HELLO" + , should_keep_alive: FALSE + , request_method: EBB_GET + , query_string: "" + , fragment: "" + , request_path: "/get_funky_content_length_body_hello" + , request_uri: "/get_funky_content_length_body_hello" + , num_headers: 1 + , header_fields: { "conTENT-Length" } + , header_values: { "5" } + , body: "HELLO" + }; + +// post - one header - body "World" +const struct request_data post_identity_body_world = + { raw: "POST /post_identity_body_world?q=search#hey HTTP/1.1\r\n" + "Accept: */*\r\n" + "Transfer-Encoding: identity\r\n" + "Content-Length: 5\r\n" + "\r\n" + "World" + , should_keep_alive: TRUE + , request_method: EBB_POST + , query_string: "q=search" + , fragment: "hey" + , request_path: "/post_identity_body_world" + , request_uri: "/post_identity_body_world?q=search" + , num_headers: 3 + , header_fields: { "Accept", "Transfer-Encoding", "Content-Length" } + , header_values: { "*/*", "identity", "5" } + , body: "World" + }; + +// post - no headers - chunked body "all your base are belong to us" +const struct request_data post_chunked_all_your_base = + { raw: "POST /post_chunked_all_your_base HTTP/1.1\r\n" + "Transfer-Encoding: chunked\r\n" + "\r\n" + "1e\r\nall your base are belong to us\r\n" + "0\r\n" + "\r\n" + , should_keep_alive: TRUE + , request_method: EBB_POST + , query_string: "" + , fragment: "" + , request_path: "/post_chunked_all_your_base" + , request_uri: "/post_chunked_all_your_base" + , num_headers: 1 + , header_fields: { "Transfer-Encoding" } + , header_values: { "chunked" } + , body: "all your base are belong to us" + }; + +// two chunks ; triple zero ending +const struct request_data two_chunks_mult_zero_end = + { raw: "POST /two_chunks_mult_zero_end HTTP/1.1\r\n" + "Transfer-Encoding: chunked\r\n" + "\r\n" + "5\r\nhello\r\n" + "6\r\n world\r\n" + "000\r\n" + "\r\n" + , should_keep_alive: TRUE + , request_method: EBB_POST + , query_string: "" + , fragment: "" + , request_path: "/two_chunks_mult_zero_end" + , request_uri: "/two_chunks_mult_zero_end" + , num_headers: 1 + , header_fields: { "Transfer-Encoding" } + , header_values: { "chunked" } + , body: "hello world" + }; + + +// chunked with trailing headers. blech. +const struct request_data chunked_w_trailing_headers = + { raw: "POST /chunked_w_trailing_headers HTTP/1.1\r\n" + "Transfer-Encoding: chunked\r\n" + "\r\n" + "5\r\nhello\r\n" + "6\r\n world\r\n" + "0\r\n" + "Vary: *\r\n" + "Content-Type: text/plain\r\n" + "\r\n" + , should_keep_alive: TRUE + , request_method: EBB_POST + , query_string: "" + , fragment: "" + , request_path: "/chunked_w_trailing_headers" + , request_uri: "/chunked_w_trailing_headers" + , num_headers: 1 + , header_fields: { "Transfer-Encoding" } + , header_values: { "chunked" } + , body: "hello world" + }; + +// with bullshit after the length +const struct request_data chunked_w_bullshit_after_length = + { raw: "POST /chunked_w_bullshit_after_length HTTP/1.1\r\n" + "Transfer-Encoding: chunked\r\n" + "\r\n" + "5; ihatew3;whatthefuck=aretheseparametersfor\r\nhello\r\n" + "6; blahblah; blah\r\n world\r\n" + "0\r\n" + "\r\n" + , should_keep_alive: TRUE + , request_method: EBB_POST + , query_string: "" + , fragment: "" + , request_path: "/chunked_w_bullshit_after_length" + , request_uri: "/chunked_w_bullshit_after_length" + , num_headers: 1 + , header_fields: { "Transfer-Encoding" } + , header_values: { "chunked" } + , body: "hello world" + }; + +const struct request_data *fixtures[] = + { &curl_get + , &firefox_get + , &dumbfuck + , &fragment_in_uri + , &get_no_headers_no_body + , &get_one_header_no_body + , &get_funky_content_length_body_hello + , &post_identity_body_world + , &post_chunked_all_your_base + , &two_chunks_mult_zero_end + , &chunked_w_trailing_headers + , &chunked_w_bullshit_after_length + , NULL + }; + + +int request_data_eq + ( struct request_data *r1 + , const struct request_data *r2 + ) +{ + if(ebb_request_should_keep_alive(&r1->request) != r2->should_keep_alive) { + printf("requests disagree on keep-alive"); + return FALSE; + } + + if(0 != strcmp(r1->body, r2->body)) { + printf("body '%s' != '%s'\n", r1->body, r2->body); + return FALSE; + } + if(0 != strcmp(r1->fragment, r2->fragment)) { + printf("fragment '%s' != '%s'\n", r1->fragment, r2->fragment); + return FALSE; + } + if(0 != strcmp(r1->query_string, r2->query_string)) { + printf("query_string '%s' != '%s'\n", r1->query_string, r2->query_string); + return FALSE; + } + if(r1->request.method != r2->request_method) { + printf("request_method '%d' != '%d'\n", r1->request.method, r2->request_method); + return FALSE; + } + if(0 != strcmp(r1->request_path, r2->request_path)) { + printf("request_path '%s' != '%s'\n", r1->request_path, r2->request_path); + return FALSE; + } + if(0 != strcmp(r1->request_uri, r2->request_uri)) { + printf("request_uri '%s' != '%s'\n", r1->request_uri, r2->request_uri); + return FALSE; + } + if(r1->num_headers != r2->num_headers) { + printf("num_headers '%d' != '%d'\n", r1->num_headers, r2->num_headers); + return FALSE; + } + int i; + for(i = 0; i < r1->num_headers; i++) { + if(0 != strcmp(r1->header_fields[i], r2->header_fields[i])) { + printf("header field '%s' != '%s'\n", r1->header_fields[i], r2->header_fields[i]); + return FALSE; + } + if(0 != strcmp(r1->header_values[i], r2->header_values[i])) { + printf("header field '%s' != '%s'\n", r1->header_values[i], r2->header_values[i]); + return FALSE; + } + } + return TRUE; +} + +int request_eq + ( int index + , const struct request_data *expected + ) +{ + return request_data_eq(&requests[index], expected); +} + +void request_complete(ebb_request *info) +{ + num_requests++; +} + +void request_path_cb(ebb_request *request, const char *p, size_t len) +{ + strncat(requests[num_requests].request_path, p, len); +} + +void request_uri_cb(ebb_request *request, const char *p, size_t len) +{ + strncat(requests[num_requests].request_uri, p, len); +} + +void query_string_cb(ebb_request *request, const char *p, size_t len) +{ + strncat(requests[num_requests].query_string, p, len); +} + +void fragment_cb(ebb_request *request, const char *p, size_t len) +{ + strncat(requests[num_requests].fragment, p, len); +} + +void header_field_cb(ebb_request *request, const char *p, size_t len, int header_index) +{ + strncat(requests[num_requests].header_fields[header_index], p, len); +} + +void header_value_cb(ebb_request *request, const char *p, size_t len, int header_index) +{ + strncat(requests[num_requests].header_values[header_index], p, len); + requests[num_requests].num_headers = header_index + 1; +} + +void body_handler(ebb_request *request, const char *p, size_t len) +{ + strncat(requests[num_requests].body, p, len); + // printf("body_handler: '%s'\n", requests[num_requests].body); +} + +ebb_request* new_request () +{ + requests[num_requests].num_headers = 0; + requests[num_requests].request_method = -1; + requests[num_requests].request_path[0] = 0; + requests[num_requests].request_uri[0] = 0; + requests[num_requests].fragment[0] = 0; + requests[num_requests].query_string[0] = 0; + requests[num_requests].body[0] = 0; + int i; + for(i = 0; i < MAX_HEADERS; i++) { + requests[num_requests].header_fields[i][0] = 0; + requests[num_requests].header_values[i][0] = 0; + } + + ebb_request *r = &requests[num_requests].request; + ebb_request_init(r); + + r->on_complete = request_complete; + r->on_header_field = header_field_cb; + r->on_header_value = header_value_cb; + r->on_path = request_path_cb; + r->on_uri = request_uri_cb; + r->on_fragment = fragment_cb; + r->on_query_string = query_string_cb; + r->on_body = body_handler; + r->on_headers_complete = NULL; + + r->data = &requests[num_requests]; + // printf("new request %d\n", num_requests); + return r; +} + +void parser_init() +{ + num_requests = 0; + + ebb_request_parser_init(&parser); + + parser.new_request = new_request; +} + +int test_request + ( const struct request_data *request_data + ) +{ + size_t traversed = 0; + parser_init(); + + traversed = ebb_request_parser_execute( &parser + , request_data->raw + , strlen(request_data->raw) + ); + if( ebb_request_parser_has_error(&parser) ) + return FALSE; + if(! ebb_request_parser_is_finished(&parser) ) + return FALSE; + if(num_requests != 1) + return FALSE; + + return request_eq(0, request_data); +} + +int test_error + ( const char *buf + ) +{ + size_t traversed = 0; + parser_init(); + + traversed = ebb_request_parser_execute(&parser, buf, strlen(buf)); + + return ebb_request_parser_has_error(&parser); +} + + +int test_multiple3 + ( const struct request_data *r1 + , const struct request_data *r2 + , const struct request_data *r3 + ) +{ + char total[80*1024] = "\0"; + + strcat(total, r1->raw); + strcat(total, r2->raw); + strcat(total, r3->raw); + + size_t traversed = 0; + parser_init(); + + traversed = ebb_request_parser_execute(&parser, total, strlen(total)); + + + if( ebb_request_parser_has_error(&parser) ) + return FALSE; + if(! ebb_request_parser_is_finished(&parser) ) + return FALSE; + if(num_requests != 3) + return FALSE; + + if(!request_eq(0, r1)){ + printf("request 1 error.\n"); + return FALSE; + } + if(!request_eq(1, r2)){ + printf("request 2 error.\n"); + return FALSE; + } + if(!request_eq(2, r3)){ + printf("request 3 error.\n"); + return FALSE; + } + + return TRUE; +} + +/** + * SCAN through every possible breaking to make sure the + * parser can handle getting the content in any chunks that + * might come from the socket + */ +int test_scan2 + ( const struct request_data *r1 + , const struct request_data *r2 + , const struct request_data *r3 + ) +{ + char total[80*1024] = "\0"; + char buf1[80*1024] = "\0"; + char buf2[80*1024] = "\0"; + + strcat(total, r1->raw); + strcat(total, r2->raw); + strcat(total, r3->raw); + + int total_len = strlen(total); + + //printf("total_len = %d\n", total_len); + int i; + for(i = 1; i < total_len - 1; i ++ ) { + + parser_init(); + + int buf1_len = i; + strncpy(buf1, total, buf1_len); + buf1[buf1_len] = 0; + + int buf2_len = total_len - i; + strncpy(buf2, total+i, buf2_len); + buf2[buf2_len] = 0; + + ebb_request_parser_execute(&parser, buf1, buf1_len); + + if( ebb_request_parser_has_error(&parser) ) { + return FALSE; + } + /* + if(ebb_request_parser_is_finished(&parser)) + return FALSE; + */ + + ebb_request_parser_execute(&parser, buf2, buf2_len); + + if( ebb_request_parser_has_error(&parser)) + return FALSE; + if(!ebb_request_parser_is_finished(&parser)) + return FALSE; + + if(3 != num_requests) { + printf("scan error: got %d requests in iteration %d\n", num_requests, i); + return FALSE; + } + + if(!request_eq(0, r1)) { + printf("not maching r1\n"); + return FALSE; + } + if(!request_eq(1, r2)) { + printf("not maching r2\n"); + return FALSE; + } + if(!request_eq(2, r3)) { + printf("not maching r3\n"); + return FALSE; + } + } + return TRUE; +} + +int test_scan3 + ( const struct request_data *r1 + , const struct request_data *r2 + , const struct request_data *r3 + ) +{ + char total[80*1024] = "\0"; + char buf1[80*1024] = "\0"; + char buf2[80*1024] = "\0"; + char buf3[80*1024] = "\0"; + + strcat(total, r1->raw); + strcat(total, r2->raw); + strcat(total, r3->raw); + + int total_len = strlen(total); + + //printf("total_len = %d\n", total_len); + int i,j; + for(j = 2; j < total_len - 1; j ++ ) { + for(i = 1; i < j; i ++ ) { + + parser_init(); + + + + + int buf1_len = i; + strncpy(buf1, total, buf1_len); + buf1[buf1_len] = 0; + + int buf2_len = j - i; + strncpy(buf2, total+i, buf2_len); + buf2[buf2_len] = 0; + + int buf3_len = total_len - j; + strncpy(buf3, total+j, buf3_len); + buf3[buf3_len] = 0; + + /* + printf("buf1: %s - %d\n", buf1, buf1_len); + printf("buf2: %s - %d \n", buf2, buf2_len ); + printf("buf3: %s - %d\n\n", buf3, buf3_len); + */ + + ebb_request_parser_execute(&parser, buf1, buf1_len); + + if( ebb_request_parser_has_error(&parser) ) { + return FALSE; + } + + ebb_request_parser_execute(&parser, buf2, buf2_len); + + if( ebb_request_parser_has_error(&parser) ) { + return FALSE; + } + + ebb_request_parser_execute(&parser, buf3, buf3_len); + + if( ebb_request_parser_has_error(&parser)) + return FALSE; + if(!ebb_request_parser_is_finished(&parser)) + return FALSE; + + if(3 != num_requests) { + printf("scan error: only got %d requests in iteration %d\n", num_requests, i); + return FALSE; + } + + if(!request_eq(0, r1)) { + printf("not maching r1\n"); + return FALSE; + } + if(!request_eq(1, r2)) { + printf("not maching r2\n"); + return FALSE; + } + if(!request_eq(2, r3)) { + printf("not maching r3\n"); + return FALSE; + } + } + } + return TRUE; +} + +int main() +{ + + assert(test_error("hello world")); + assert(test_error("GET / HTP/1.1\r\n\r\n")); + + assert(test_request(&curl_get)); + assert(test_request(&firefox_get)); + + // Zed's header tests + + assert(test_request(&dumbfuck)); + + const char *dumbfuck2 = "GET / HTTP/1.1\r\nX-SSL-Bullshit: -----BEGIN CERTIFICATE-----\r\n\tMIIFbTCCBFWgAwIBAgICH4cwDQYJKoZIhvcNAQEFBQAwcDELMAkGA1UEBhMCVUsx\r\n\tETAPBgNVBAoTCGVTY2llbmNlMRIwEAYDVQQLEwlBdXRob3JpdHkxCzAJBgNVBAMT\r\n\tAkNBMS0wKwYJKoZIhvcNAQkBFh5jYS1vcGVyYXRvckBncmlkLXN1cHBvcnQuYWMu\r\n\tdWswHhcNMDYwNzI3MTQxMzI4WhcNMDcwNzI3MTQxMzI4WjBbMQswCQYDVQQGEwJV\r\n\tSzERMA8GA1UEChMIZVNjaWVuY2UxEzARBgNVBAsTCk1hbmNoZXN0ZXIxCzAJBgNV\r\n\tBAcTmrsogriqMWLAk1DMRcwFQYDVQQDEw5taWNoYWVsIHBhcmQYJKoZIhvcNAQEB\r\n\tBQADggEPADCCAQoCggEBANPEQBgl1IaKdSS1TbhF3hEXSl72G9J+WC/1R64fAcEF\r\n\tW51rEyFYiIeZGx/BVzwXbeBoNUK41OK65sxGuflMo5gLflbwJtHBRIEKAfVVp3YR\r\n\tgW7cMA/s/XKgL1GEC7rQw8lIZT8RApukCGqOVHSi/F1SiFlPDxuDfmdiNzL31+sL\r\n\t0iwHDdNkGjy5pyBSB8Y79dsSJtCW/iaLB0/n8Sj7HgvvZJ7x0fr+RQjYOUUfrePP\r\n\tu2MSpFyf+9BbC/aXgaZuiCvSR+8Snv3xApQY+fULK/xY8h8Ua51iXoQ5jrgu2SqR\r\n\twgA7BUi3G8LFzMBl8FRCDYGUDy7M6QaHXx1ZWIPWNKsCAwEAAaOCAiQwggIgMAwG\r\n\tA1UdEwEB/wQCMAAwEQYJYIZIAYb4QgEBBAQDAgWgMA4GA1UdDwEB/wQEAwID6DAs\r\n\tBglghkgBhvhCAQ0EHxYdVUsgZS1TY2llbmNlIFVzZXIgQ2VydGlmaWNhdGUwHQYD\r\n\tVR0OBBYEFDTt/sf9PeMaZDHkUIldrDYMNTBZMIGaBgNVHSMEgZIwgY+AFAI4qxGj\r\n\tloCLDdMVKwiljjDastqooXSkcjBwMQswCQYDVQQGEwJVSzERMA8GA1UEChMIZVNj\r\n\taWVuY2UxEjAQBgNVBAsTCUF1dGhvcml0eTELMAkGA1UEAxMCQ0ExLTArBgkqhkiG\r\n\t9w0BCQEWHmNhLW9wZXJhdG9yQGdyaWQtc3VwcG9ydC5hYy51a4IBADApBgNVHRIE\r\n\tIjAggR5jYS1vcGVyYXRvckBncmlkLXN1cHBvcnQuYWMudWswGQYDVR0gBBIwEDAO\r\n\tBgwrBgEEAdkvAQEBAQYwPQYJYIZIAYb4QgEEBDAWLmh0dHA6Ly9jYS5ncmlkLXN1\r\n\tcHBvcnQuYWMudmT4sopwqlBWsvcHViL2NybC9jYWNybC5jcmwwPQYJYIZIAYb4QgEDBDAWLmh0\r\n\tdHA6Ly9jYS5ncmlkLXN1cHBvcnQuYWMudWsvcHViL2NybC9jYWNybC5jcmwwPwYD\r\n\tVR0fBDgwNjA0oDKgMIYuaHR0cDovL2NhLmdyaWQt5hYy51ay9wdWIv\r\n\tY3JsL2NhY3JsLmNybDANBgkqhkiG9w0BAQUFAAOCAQEAS/U4iiooBENGW/Hwmmd3\r\n\tXCy6Zrt08YjKCzGNjorT98g8uGsqYjSxv/hmi0qlnlHs+k/3Iobc3LjS5AMYr5L8\r\n\tUO7OSkgFFlLHQyC9JzPfmLCAugvzEbyv4Olnsr8hbxF1MbKZoQxUZtMVu29wjfXk\r\n\thTeApBv7eaKCWpSp7MCbvgzm74izKhu3vlDk9w6qVrxePfGgpKPqfHiOoGhFnbTK\r\n\twTC6o2xq5y0qZ03JonF7OJspEd3I5zKY3E+ov7/ZhW6DqT8UFvsAdjvQbXyhV8Eu\r\n\tYhixw1aKEPzNjNowuIseVogKOLXxWI5vAi5HgXdS0/ES5gDGsABo4fqovUKlgop3\r\n\tRA==\r\n\t-----END CERTIFICATE-----\r\n\r\n"; + assert(test_error(dumbfuck2)); + + assert(test_request(&fragment_in_uri)); + + /* TODO sending junk and large headers gets rejected */ + + + /* check to make sure our predefined requests are okay */ + + assert(test_request(&get_no_headers_no_body)); + assert(test_request(&get_one_header_no_body)); + assert(test_request(&get_no_headers_no_body)); + + // no content-length + const char *bad_get_no_headers_no_body = "GET /bad_get_no_headers_no_body/world HTTP/1.1\r\nAccept: */*\r\nHELLO\r\n"; + assert(test_error(bad_get_no_headers_no_body)); // error if there is a body without content length + + assert(test_request(&get_funky_content_length_body_hello)); + assert(test_request(&post_identity_body_world)); + assert(test_request(&post_chunked_all_your_base)); + assert(test_request(&two_chunks_mult_zero_end)); + assert(test_request(&chunked_w_trailing_headers)); + + assert(test_request(&chunked_w_bullshit_after_length)); + assert(1 == requests[0].request.version_major); + assert(1 == requests[0].request.version_minor); + + // three requests - no bodies + assert( test_multiple3( &get_no_headers_no_body + , &get_one_header_no_body + , &get_no_headers_no_body + )); + + // three requests - one body + assert( test_multiple3(&get_no_headers_no_body, &get_funky_content_length_body_hello, &get_no_headers_no_body)); + + // three requests with bodies -- last is chunked + assert( test_multiple3(&get_funky_content_length_body_hello, &post_identity_body_world, &post_chunked_all_your_base)); + + // three chunked requests + assert( test_multiple3(&two_chunks_mult_zero_end, &post_chunked_all_your_base, &chunked_w_trailing_headers)); + + + assert(test_scan2(&get_no_headers_no_body, &get_one_header_no_body, &get_no_headers_no_body)); + assert(test_scan2(&get_funky_content_length_body_hello, &post_identity_body_world, &post_chunked_all_your_base)); + assert(test_scan2(&two_chunks_mult_zero_end, &chunked_w_trailing_headers, &chunked_w_bullshit_after_length)); + + assert(test_scan3(&get_no_headers_no_body, &get_one_header_no_body, &get_no_headers_no_body)); + assert(test_scan3(&get_funky_content_length_body_hello, &post_identity_body_world, &post_chunked_all_your_base)); + assert(test_scan3(&two_chunks_mult_zero_end, &chunked_w_trailing_headers, &chunked_w_bullshit_after_length)); + + + printf("okay\n"); + return 0; +} + diff --git a/deps/liboi/LICENSE b/deps/liboi/LICENSE new file mode 100644 index 0000000000..a5a6e0191f --- /dev/null +++ b/deps/liboi/LICENSE @@ -0,0 +1,23 @@ +liboi is Copyright (C) 2009 Ryan Dahl. + +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 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/deps/liboi/README b/deps/liboi/README new file mode 100644 index 0000000000..0609ab4961 --- /dev/null +++ b/deps/liboi/README @@ -0,0 +1,36 @@ +liboi is a C library for doing evented I/O. It is intended for building +efficent internet programs. + +liboi is released under the X11 license. + += Feature Summary + + * The library has a minimalist design + - Does not make internal allocations + - Does not wrap functionality of GnuTLS or libev. The user must use those + libraries in conjuction with liboi. + * Supports both server and client sockets. + * Supports evented file I/O emulation through a thread pool. + * SSL support + * Sendfile (file to socket) with emulation on platforms that do not support + it. + += Building + + 1 Edit config.mk. You almost certainly will need to set the EVDIR and + GNUTLSDIR variables. + 2 Run "make" + += Documentation + + 1 make doc + 2 man ./oi.3 + += Website + +http://github.com/ry/liboi + += Author + +Ryan Dahl (ry@tinyclouds.org) + diff --git a/deps/liboi/config.mk b/deps/liboi/config.mk new file mode 100644 index 0000000000..311f8cb535 --- /dev/null +++ b/deps/liboi/config.mk @@ -0,0 +1,33 @@ +# Define EVDIR=/foo/bar if your libev header and library files are in +# /foo/bar/include and /foo/bar/lib directories. +EVDIR=$(HOME)/local/libev + +# Define GNUTLSDIR=/foo/bar if your gnutls header and library files are in +# /foo/bar/include and /foo/bar/lib directories. +#GNUTLSDIR=/usr +# +# +# Define NO_PREAD if you have a problem with pread() system call (e.g. +# cygwin.dll before v1.5.22). +# +# +# Define NO_SENDFILE if you have a problem with the sendfile() system call +# +# + +uname_S := $(shell sh -c 'uname -s 2>/dev/null || echo not') +uname_M := $(shell sh -c 'uname -m 2>/dev/null || echo not') +uname_O := $(shell sh -c 'uname -o 2>/dev/null || echo not') +uname_R := $(shell sh -c 'uname -r 2>/dev/null || echo not') +uname_P := $(shell sh -c 'uname -p 2>/dev/null || echo not') + +# CFLAGS and LDFLAGS are for the users to override from the command line. +CFLAGS = -g +LDFLAGS = + +PREFIX = $(HOME)/local/liboi + +CC = gcc +AR = ar +RM = rm -f +RANLIB = ranlib diff --git a/deps/liboi/oi.h b/deps/liboi/oi.h new file mode 100644 index 0000000000..c7145ea351 --- /dev/null +++ b/deps/liboi/oi.h @@ -0,0 +1,8 @@ +#ifndef oi_h +#define oi_h + +#include +#include +#include + +#endif diff --git a/deps/liboi/oi.pod b/deps/liboi/oi.pod new file mode 100644 index 0000000000..8b07115ee6 --- /dev/null +++ b/deps/liboi/oi.pod @@ -0,0 +1,278 @@ +=head1 NAME + +liboi - a C library for doing evented I/O. + +=head1 SYNOPSIS + + #include + +=head1 DESCRIPTION + +liboi is an object oriented library for doing evented socket and file I/O. +The API is mostly about registering callbacks to be executed on certain +events. + +Because most systems do not support asynchornous file I/O, the behavior is +emulated with an internal thread pool. The thread pool is accessed with the +C and C objects. Typically one will not need to use these +directly as C wraps that functionality. + +=head2 CONVENTIONS + +liboi's goal is to be very simple layer above the POSIX API. To that end it +avoids internal allocations as much as possible. Unless otherwise noted you +should assume all pointers passed into liboi will remain your responsibility +to maintain. That means you should not free the data passed into liboi +until the object in question has completed. + +C and C objects must be attached to an event loop. This +is completed with the C<*_attach> and C<*_detach> methods. When an object +is detached, other methods can be called - just the loop will not churn out +callbacks. + +Both C and C contain a number of callback pointers. +These are to be set manually after calling their initalization functions. +All classes include a C member which is left for you to use. + +=head1 ERROR HANDLING + + +=head1 Sockets + +The C structure represents a socket. +The callbacks inside C are + void (*on_connect) (oi_socket *); + void (*on_read) (oi_socket *, const void *buf, size_t count); + void (*on_drain) (oi_socket *); + void (*on_error) (oi_socket *, struct oi_error e); + void (*on_close) (oi_socket *); + void (*on_timeout) (oi_socket *); + +A the memory for a socket is released when the C callback is +made. That is, the user may free the memory for the socket with-in the +C callback. + +=over 4 + +=item void oi_socket_init (oi_socket *, float timeout); + +Initialize a socket. C is the number of seconds of inactivity that +is allowed before the socket closes. The timeout only starts once the +socket is attached to a loop and open. + +A C argument of 0.0 signals that no timeout should be used. + +After calling this function, register your callbacks manually. Thus your +code will probably look like this + oi_socket socket; + oi_socket_init(&socket, 60.0); + socket.on_connect = my_on_connect; + socket.on_read = my_on_read; + /* etc */ + + +=item int oi_socket_connect (oi_socket *, struct addrinfo *addrinfo); + +Open a client connect to the specified address. When the connection is made +C will be called. + +Here is an example of filling in C for a local TCP connection on +port 5555: + struct addrinfo *servinfo; + struct addrinfo hints; + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_PASSIVE; + r = getaddrinfo(NULL, "5555", &hints, &servinfo); + assert(r == 0); + oi_socket_connect(socket, servinfo); + +=item void oi_socket_attach (oi_socket *, struct ev_loop *loop); + +A socket must be attached to a loop in order before any callbacks will be +made. + +=item void oi_socket_detach (oi_socket *); + +Detaching a socket will not close the connection. + +=item void oi_socket_read_start (oi_socket *); + +This will make the socket start receiving data. When data is received the +C callback is made. The maximum amount of data that can be +receive at a time is controlled by C. + +The buffer returned by C is statically allocated exists only +for the length of the callback. That means if you need to save any of the +data coming down the line, you must copy it to a new buffer. + +Ideally you will have a parser attached to the C callback which can +be interrupted at any time. + +C can be changed at any time. + +=item void oi_socket_read_stop (oi_socket *); + +Stops receiving data. You may receive spurious C attempts even +though the socket reading is stopped - be prepared to handle them. + +=item void oi_socket_reset_timeout (oi_socket *); + +Reset the timeout to allow the socket to exist for another few seconds +(however long you specified in the initialization function). + +=item void oi_socket_write (oi_socket *socket, oi_buf *buf); + +Write the I to the socket. Each socket has a queue of C objects +to be written - this appends the specified buffer to the end of that queue. +You will be notified when the queue is empty with the C +callback. When the socket has written the buffer C will be +called. The release callback does not imply that the buffer was successfully +written. + +=item void oi_socket_write_simple (oi_socket *, const char *str, size_t len); + +Sometimes you are just hacking around and need to quickly write a string to +the socket. This convenience function allocates an C object, and +Cs the given string. The allocated buffer will be freed by liboi +internally. + +Most production most applications will use their own memory pool and will +not need this function. + +=item void oi_socket_write_eof (oi_socket *); + +This closes the write end of the socket. Further writes are not allowed +after this. + +=item void oi_socket_close (oi_socket *); + +Attempts to close the socket. + +If the socket is secure, an SSL bye message will be sent. +SSL recommends that you wait for a bye response from the peer however this +tends to be overkill for most people. By default liboi will not wait for +peer to send a matching bye message. If you require this then set +C to 1. + +When the close is complete C is made. The C +callback is not made until the program returns to the event loop. This is +because C may free the socket memory and if C was +called from C, then the socket object might unexpectedly +be gone. To summarize: C does not call C and +the socket memory is still accessable immediately after making calling +C. + +=item void oi_socket_set_secure_session (oi_socket *, gnutls_session_t); + +This make a socket use SSL. You must create the GnuTLS session yourself and +assign its credentials. + +=back + +=head1 Servers + +A server simply listens on an address for new connections. The connections +come in the form of C objects. The key is to give a +C callback which returns an initialized C. +The callback looks like this + + oi_socket* (*on_connection) (oi_server *, struct sockaddr *remote_addr, socklen_t remove_addr_len); + +Returning NULL from C will reject the connection. + +=over 4 + +=item void oi_server_init (oi_server *, int backlog); + +Initializes a server object. C is the argument given +internally to C. Set the C callback +after calling this. + +=item int oi_server_listen (oi_server *, struct addrinfo *addrinfo); + +Listens on the specified address. The server will not accept connections +until it is attached to a loop, however. + +=item void oi_server_attach (oi_server *, struct ev_loop *loop); + +Attaches a server to a loop. + +=item void oi_server_detach (oi_server *); + +Detaches a server to a loop. Does not close the server. + +=item void oi_server_close (oi_server *); + +Stops the server from listening. + +=back + +=head1 Files + +Files internally use a thread pool to operate without blocking. +The thread pool is started once a file is attached and it continues until +program termination. + +The following callbacks are used inside of the file object + void (*on_open) (oi_file *); + void (*on_read) (oi_file *, size_t count); + void (*on_drain) (oi_file *); + void (*on_error) (oi_file *, struct oi_error); + void (*on_close) (oi_file *); + +=over 4 + +=item int oi_file_init (oi_file *); + +Initializes a file object. + +=item void oi_file_attach (oi_file *, struct ev_loop *); + +Attaches a file object to a loop. If the thread pool has not been started, +then it is started at this call. + +=item void oi_file_detach (oi_file *); + +Detaches a file object from the loop. + +=item int oi_file_open_path (oi_file *, const char *path, int flags, mode_t mode); + +Opens a file specified by the path. The C and C arguments are +the same as used by L. The C callback is triggered +when the file is opened. Returns 0 on success. Returns -1 if the given file +is already open. + +WARNING: path argument must be valid until C object is closed and +the C callback is made. I.E., liboi does not strdup the path +pointer. + +=item int oi_file_open_stdin (oi_file *); + +=item int oi_file_open_stdout (oi_file *); + +=item int oi_file_open_stderr (oi_file *); + +=item void oi_file_read_start (oi_file *, void *buffer, size_t bufsize); + + + +=item void oi_file_read_stop (oi_file *); + +=item int oi_file_write (oi_file *, oi_buf *to_write); + +=item int oi_file_write_simple (oi_file *, const char *, size_t); + +=item int oi_file_send (oi_file *source, oi_socket *destination, off_t offset, size_t length); + +=item void oi_file_close (oi_file *); + +=over 4 + +=back + +=head1 AUTHOR + +Ryan Dahl + diff --git a/deps/liboi/oi_async.c b/deps/liboi/oi_async.c new file mode 100644 index 0000000000..1d5459d625 --- /dev/null +++ b/deps/liboi/oi_async.c @@ -0,0 +1,486 @@ +#include /* malloc() */ +#include /* perror() */ +#include +#include +#include /* read(), write() */ +#include +#include +#include +#include + +#if HAVE_SENDFILE +# if __linux +# include +# elif __freebsd +# include +# include +# elif __hpux +# include +# elif __solaris /* not yet */ +# include +# else +# error sendfile support requested but not available +# endif +#endif + +#include +#include + +#define NWORKERS 4 +/* TODO make adjustable + * once it is fix sleeping_tasks + */ + +static int active_watchers = 0; +static int active_workers = 0; +static int readiness_pipe[2] = {-1, -1}; +static oi_queue waiting_tasks; +static pthread_mutex_t queue_lock = PTHREAD_MUTEX_INITIALIZER; +static pthread_mutex_t finished_lock = PTHREAD_MUTEX_INITIALIZER; + +struct worker { + oi_task *task; + pthread_t thread; + pthread_attr_t thread_attr; +}; + +/* Sendfile and pread emulation come from Marc Lehmann's libeio and are + * Copyright (C)2007,2008 Marc Alexander Lehmann. + * Many ideas of oi_async.* are taken from libeio and in fact, I plan to + * use libeio once it becomes usable for me. (The problem is issuing tasks + * from multiple threads.) + */ + +#if !HAVE_PREADWRITE +/* + * make our pread/pwrite emulation safe against themselves, but not against + * normal read/write by using a mutex. slows down execution a lot, + * but that's your problem, not mine. + */ +static pthread_mutex_t preadwritelock = PTHREAD_MUTEX_INITIALIZER; +#endif + +#if !HAVE_PREADWRITE +# undef pread +# undef pwrite +# define pread eio__pread +# define pwrite eio__pwrite + +static ssize_t +eio__pread (int fd, void *buf, size_t count, off_t offset) +{ + ssize_t res; + off_t ooffset; + + pthread_mutex_lock(&preadwritelock); + ooffset = lseek (fd, 0, SEEK_CUR); + lseek (fd, offset, SEEK_SET); + res = read (fd, buf, count); + lseek (fd, ooffset, SEEK_SET); + pthread_mutex_unlock(&preadwritelock); + + return res; +} + +static ssize_t +eio__pwrite (int fd, void *buf, size_t count, off_t offset) +{ + ssize_t res; + off_t ooffset; + + pthread_mutex_lock(&preadwritelock); + ooffset = lseek (fd, 0, SEEK_CUR); + lseek (fd, offset, SEEK_SET); + res = write (fd, buf, count); + lseek (fd, offset, SEEK_SET); + pthread_mutex_unlock(&preadwritelock); + + return res; +} +#endif + + +/* sendfile always needs emulation */ +static ssize_t +eio__sendfile (int ofd, int ifd, off_t offset, size_t count) +{ + ssize_t res; + + if (!count) + return 0; + +#if HAVE_SENDFILE +# if __linux + res = sendfile (ofd, ifd, &offset, count); + +# elif __freebsd + /* + * Of course, the freebsd sendfile is a dire hack with no thoughts + * wasted on making it similar to other I/O functions. + */ + { + off_t sbytes; + res = sendfile (ifd, ofd, offset, count, 0, &sbytes, 0); + + if (res < 0 && sbytes) + /* maybe only on EAGAIN: as usual, the manpage leaves you guessing */ + res = sbytes; + } + +# elif __hpux + res = sendfile (ofd, ifd, offset, count, 0, 0); + +# elif __solaris + { + struct sendfilevec vec; + size_t sbytes; + + vec.sfv_fd = ifd; + vec.sfv_flag = 0; + vec.sfv_off = offset; + vec.sfv_len = count; + + res = sendfilev (ofd, &vec, 1, &sbytes); + + if (res < 0 && sbytes) + res = sbytes; + } + +# endif +#else + res = -1; + errno = ENOSYS; +#endif + + if (res < 0 + && (errno == ENOSYS || errno == EINVAL || errno == ENOTSOCK +#if __solaris + || errno == EAFNOSUPPORT || errno == EPROTOTYPE +#endif + ) + ) + { + /* emulate sendfile. this is a major pain in the ass */ +/* buffer size for various temporary buffers */ +#define EIO_BUFSIZE 65536 + char *eio_buf = malloc (EIO_BUFSIZE); + errno = ENOMEM; + if (!eio_buf) + return -1; + + res = 0; + + while (count) { + ssize_t cnt; + + cnt = pread (ifd, eio_buf, count > EIO_BUFSIZE ? EIO_BUFSIZE : count, offset); + + if (cnt <= 0) { + if (cnt && !res) res = -1; + break; + } + + cnt = write (ofd, eio_buf, cnt); + + if (cnt <= 0) { + if (cnt && !res) res = -1; + break; + } + + offset += cnt; + res += cnt; + count -= cnt; + } + + free(eio_buf); + } + + return res; +} + +static oi_task* +queue_shift(pthread_mutex_t *lock, oi_queue *queue) +{ + oi_queue *last = NULL; + pthread_mutex_lock(lock); + if(!oi_queue_empty(queue)) { + last = oi_queue_last(queue); + oi_queue_remove(last); + } + pthread_mutex_unlock(lock); + + if(last == NULL) + return NULL; + + return oi_queue_data(last, oi_task, queue); +} + +#define P1(name,a) { \ + t->params.name.result = name( t->params.name.a ); \ + break; \ +} + +#define P2(name,a,b) { \ + t->params.name.result = name( t->params.name.a \ + , t->params.name.b \ + ); \ + break; \ +} + +#define P3(name,a,b,c) { \ + t->params.name.result = name( t->params.name.a \ + , t->params.name.b \ + , t->params.name.c \ + ); \ + break; \ +} + +#define P4(name,a,b,c,d) { \ + t->params.name.result = name( t->params.name.a \ + , t->params.name.b \ + , t->params.name.c \ + , t->params.name.d \ + ); \ + break; \ +} + +static void +execute_task(oi_task *t) +{ + errno = 0; + switch(t->type) { + case OI_TASK_OPEN: P3(open, pathname, flags, mode); + case OI_TASK_READ: P3(read, fd, buf, count); + case OI_TASK_WRITE: P3(write, fd, buf, count); + case OI_TASK_CLOSE: P1(close, fd); + case OI_TASK_SLEEP: P1(sleep, seconds); + case OI_TASK_SENDFILE: P4(eio__sendfile, out_fd, in_fd, offset, count); + case OI_TASK_GETADDRINFO: P4(getaddrinfo, nodename, servname, hints, res); + case OI_TASK_LSTAT: P2(lstat, path, buf); + default: + assert(0 && "unknown task type"); + break; + } + t->errorno = errno; +} + +static void +attempt_to_get_a_task(struct worker *worker) +{ + char dummy; + assert(readiness_pipe[0] > 0); + int r = read(readiness_pipe[0], &dummy, 1); + if(r == -1 && (errno != EAGAIN || errno != EINTR)) { + perror("read(readiness_pipe[0])"); + return; + } + + // 1 pop task from queue + assert(worker->task == NULL); + oi_task *task = queue_shift(&queue_lock, &waiting_tasks); + if(task == NULL) return; + worker->task = task; + + // 2 run task + execute_task(task); + + // 3 notify complition + oi_async *async = task->async; + assert(async != NULL); + pthread_mutex_lock(&finished_lock); + oi_queue_insert_head(&async->finished_tasks, &task->queue); + pthread_mutex_unlock(&finished_lock); + ev_async_send(async->loop, &async->watcher); + worker->task = NULL; + + /* attempt to pull another task */ + return attempt_to_get_a_task(worker); +} + +void * +worker_loop(void *data) +{ + int r; + struct worker *worker = data; + fd_set readfds; + FD_ZERO(&readfds); + FD_SET(readiness_pipe[0], &readfds); + + active_workers++; + assert(active_workers <= NWORKERS); + + while(1) { + r = select(1+readiness_pipe[0], &readfds, 0, 0, 0); + if(r == -1) break; + attempt_to_get_a_task(worker); + } + active_workers--; + + return NULL; +} + +static struct worker* +worker_new() +{ + int r; + struct worker *worker = calloc(sizeof(struct worker), 1); + if(worker == NULL ) { return NULL; } + + worker->task = NULL; + pthread_attr_setdetachstate(&worker->thread_attr, PTHREAD_CREATE_DETACHED); + + r = pthread_create( &worker->thread + , NULL // &worker->thread_attr + , worker_loop + , worker + ); + if(r != 0) { + /* TODO: error checking */ + perror("pthread_create"); + goto error; + } + + return worker; +error: + free(worker); + return NULL; +} + +static void +start_workers() +{ + assert(readiness_pipe[0] == -1); + assert(readiness_pipe[1] == -1); + assert(active_workers == 0); + + int r = pipe(readiness_pipe); + if(r < 0) { + perror("pipe()"); + assert(0 && "TODO HANDLE ME"); + } + + /* set the write end non-blocking */ + int flags = fcntl(readiness_pipe[1], F_GETFL, 0); + r = fcntl(readiness_pipe[1], F_SETFL, flags | O_NONBLOCK); + if(r < 0) { + assert(0 && "error setting pipe to non-blocking?"); + /* TODO error report */ + } + + oi_queue_init(&waiting_tasks); + + int i; + for(i = 0; i < NWORKERS; i++) + worker_new(); +} + +/* +static void +stop_workers() +{ + assert(0 && "TODO implement me"); +} +*/ + +static void +on_completion(struct ev_loop *loop, ev_async *watcher, int revents) +{ + oi_async *async = watcher->data; + oi_task *task; + + while((task = queue_shift(&finished_lock, &async->finished_tasks))) { + assert(task->active); + task->active = 0; + errno = task->errorno; +# define done_cb(kind) { \ + assert(task->params.kind.cb); \ + task->params.kind.cb(task, task->params.kind.result); \ + break; \ + } + switch(task->type) { + case OI_TASK_OPEN: done_cb(open); + case OI_TASK_READ: done_cb(read); + case OI_TASK_WRITE: done_cb(write); + case OI_TASK_CLOSE: done_cb(close); + case OI_TASK_SLEEP: done_cb(sleep); + case OI_TASK_SENDFILE: done_cb(eio__sendfile); + case OI_TASK_GETADDRINFO: done_cb(getaddrinfo); + case OI_TASK_LSTAT: done_cb(lstat); + } + /* the task is possibly freed by callback. do not access it again. */ + } +} + +void +oi_async_init (oi_async *async) +{ + ev_async_init(&async->watcher, on_completion); + + oi_queue_init(&async->finished_tasks); + oi_queue_init(&async->new_tasks); + + async->watcher.data = async; +} + +static void +dispatch_tasks(oi_async *async) +{ + while(!oi_queue_empty(&async->new_tasks)) { + oi_queue *last = oi_queue_last(&async->new_tasks); + oi_queue_remove(last); + oi_task *task = oi_queue_data(last, oi_task, queue); + + // 1. add task to task queue. + pthread_mutex_lock(&queue_lock); + oi_queue_insert_head(&waiting_tasks, &task->queue); + pthread_mutex_unlock(&queue_lock); + + // 2. write byte to pipe + char dummy; + int written = write(readiness_pipe[1], &dummy, 1); + + // 3. TODO make sure byte is written + assert(written == 1); + } +} + +void +oi_async_attach (struct ev_loop *loop, oi_async *async) +{ + if(active_watchers == 0 && active_workers == 0) + start_workers(); + active_watchers++; + + ev_async_start(loop, &async->watcher); + async->loop = loop; + + dispatch_tasks(async); +} + +void +oi_async_detach (oi_async *async) +{ + if(async->loop == NULL) + return; + ev_async_stop(async->loop, &async->watcher); + async->loop = NULL; + active_watchers--; + if(active_watchers == 0) { + //stop_workers(); + } +} + +void +oi_async_submit (oi_async *async, oi_task *task) +{ + assert(!task->active); + assert(task->async == NULL); + task->async = async; + task->active = 1; + + oi_queue_insert_head(&async->new_tasks, &task->queue); + if(ev_is_active(&async->watcher)) { + dispatch_tasks(async); + } +} + diff --git a/deps/liboi/oi_async.h b/deps/liboi/oi_async.h new file mode 100644 index 0000000000..f3ba937caf --- /dev/null +++ b/deps/liboi/oi_async.h @@ -0,0 +1,218 @@ +#include +#include +#include +#include + +#ifndef oi_async_h +#define oi_async_h +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct oi_async oi_async; +typedef struct oi_task oi_task; + +struct oi_async { + /* private */ + ev_async watcher; + struct ev_loop *loop; + + oi_queue finished_tasks; + oi_queue new_tasks; + + /* public */ + void *data; +}; + +typedef void (*oi_task_int_cb)(oi_task *, int result); +typedef void (*oi_task_uint_cb)(oi_task *, unsigned int result); +typedef void (*oi_task_ssize_cb)(oi_task *, ssize_t result); + +struct oi_task { + /* private */ + oi_async *async; + oi_queue queue; + int type; + union { + + struct { + const char *pathname; + int flags; + mode_t mode; + oi_task_int_cb cb; + int result; + } open; + + struct { + int fd; + void *buf; + size_t count; + oi_task_ssize_cb cb; + ssize_t result; + } read; + + struct { + int fd; + const void *buf; + size_t count; + oi_task_ssize_cb cb; + ssize_t result; + } write; + + struct { + int fd; + oi_task_int_cb cb; + int result; + } close; + + struct { + unsigned int seconds; + oi_task_uint_cb cb; + unsigned int result; + } sleep; + + struct { + int out_fd; + int in_fd; + off_t offset; + size_t count; + oi_task_ssize_cb cb; + ssize_t result; + } eio__sendfile; + + struct { + const char *nodename; /* restrict ? */ + const char *servname; /* restrict ? */ + struct addrinfo *hints; + struct addrinfo **res; /* restrict ? */ + oi_task_int_cb cb; + int result; + } getaddrinfo; + + struct { + const char *path; + struct stat *buf; + oi_task_int_cb cb; + int result; + } lstat; + + } params; + + /* read-only */ + volatile unsigned active:1; + int errorno; + + /* public */ + void *data; +}; + +void oi_async_init (oi_async *); +void oi_async_attach (struct ev_loop *loop, oi_async *); +void oi_async_detach (oi_async *); +void oi_async_submit (oi_async *, oi_task *); + +/* To submit a task for async processing + * (0) allocate memory for your task + * (1) initialize the task with one of the functions below + * (2) optionally set the task->data pointer + * (3) oi_async_submit() the task + */ + +enum { OI_TASK_OPEN + , OI_TASK_READ + , OI_TASK_WRITE + , OI_TASK_CLOSE + , OI_TASK_SLEEP + , OI_TASK_SENDFILE + , OI_TASK_GETADDRINFO + , OI_TASK_LSTAT + }; + +#define oi_task_init_common(task, _type) do {\ + (task)->active = 0;\ + (task)->async = NULL;\ + (task)->type = _type;\ +} while(0) + +static inline void +oi_task_init_open(oi_task *t, oi_task_int_cb cb, const char *pathname, int flags, mode_t mode) +{ + oi_task_init_common(t, OI_TASK_OPEN); + t->params.open.cb = cb; + t->params.open.pathname = pathname; + t->params.open.flags = flags; + t->params.open.mode = mode; +} + +static inline void +oi_task_init_read(oi_task *t, oi_task_ssize_cb cb, int fd, void *buf, size_t count) +{ + oi_task_init_common(t, OI_TASK_READ); + t->params.read.cb = cb; + t->params.read.fd = fd; + t->params.read.buf = buf; + t->params.read.count = count; +} + +static inline void +oi_task_init_write(oi_task *t, oi_task_ssize_cb cb, int fd, const void *buf, size_t count) +{ + oi_task_init_common(t, OI_TASK_WRITE); + t->params.write.cb = cb; + t->params.write.fd = fd; + t->params.write.buf = buf; + t->params.write.count = count; +} + +static inline void +oi_task_init_close(oi_task *t, oi_task_int_cb cb, int fd) +{ + oi_task_init_common(t, OI_TASK_CLOSE); + t->params.close.cb = cb; + t->params.close.fd = fd; +} + +static inline void +oi_task_init_sleep(oi_task *t, oi_task_uint_cb cb, unsigned int seconds) +{ + oi_task_init_common(t, OI_TASK_SLEEP); + t->params.sleep.cb = cb; + t->params.sleep.seconds = seconds; +} + +static inline void +oi_task_init_sendfile(oi_task *t, oi_task_ssize_cb cb, int out_fd, int in_fd, off_t offset, size_t count) +{ + oi_task_init_common(t, OI_TASK_SENDFILE); + t->params.eio__sendfile.cb = cb; + t->params.eio__sendfile.out_fd = out_fd; + t->params.eio__sendfile.in_fd = in_fd; + t->params.eio__sendfile.offset = offset; + t->params.eio__sendfile.count = count; +} + +static inline void +oi_task_init_getaddrinfo(oi_task *t, oi_task_int_cb cb, const char *node, + const char *service, struct addrinfo *hints, struct addrinfo **res) +{ + oi_task_init_common(t, OI_TASK_GETADDRINFO); + t->params.getaddrinfo.cb = cb; + t->params.getaddrinfo.nodename = node; + t->params.getaddrinfo.servname = service; + t->params.getaddrinfo.hints = hints; + t->params.getaddrinfo.res = res; +} + +static inline void +oi_task_init_lstat(oi_task *t, oi_task_int_cb cb, const char *path, struct stat *buf) +{ + oi_task_init_common(t, OI_TASK_LSTAT); + t->params.lstat.cb = cb; + t->params.lstat.path = path; + t->params.lstat.buf = buf; +} + +#ifdef __cplusplus +} +#endif +#endif /* oi_async_h */ diff --git a/deps/liboi/oi_buf.c b/deps/liboi/oi_buf.c new file mode 100644 index 0000000000..a192f7dc58 --- /dev/null +++ b/deps/liboi/oi_buf.c @@ -0,0 +1,41 @@ +#include +#include +#include + +void oi_buf_destroy + ( oi_buf *buf + ) +{ + free(buf->base); + free(buf); +} + +oi_buf * oi_buf_new2 + ( size_t len + ) +{ + oi_buf *buf = malloc(sizeof(oi_buf)); + if(!buf) + return NULL; + buf->base = malloc(len); + if(!buf->base) { + free(buf); + return NULL; + } + buf->len = len; + buf->release = oi_buf_destroy; + return buf; +} + +oi_buf * oi_buf_new + ( const char *base + , size_t len + ) +{ + oi_buf *buf = oi_buf_new2(len); + if(!buf) + return NULL; + memcpy(buf->base, base, len); + return buf; +} + diff --git a/deps/liboi/oi_buf.h b/deps/liboi/oi_buf.h new file mode 100644 index 0000000000..b810c050e5 --- /dev/null +++ b/deps/liboi/oi_buf.h @@ -0,0 +1,30 @@ +#include + +#ifndef oi_buf_h +#define oi_buf_h +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct oi_buf oi_buf; + +struct oi_buf { + /* public */ + char *base; + size_t len; + void (*release) (oi_buf *); /* called when oi is done with the object */ + void *data; + + /* private */ + size_t written; + oi_queue queue; +}; + +oi_buf * oi_buf_new (const char* base, size_t len); +oi_buf * oi_buf_new2 (size_t len); +void oi_buf_destroy (oi_buf *); + +#ifdef __cplusplus +} +#endif +#endif // oi_buf_h diff --git a/deps/liboi/oi_error.h b/deps/liboi/oi_error.h new file mode 100644 index 0000000000..0f8730f5b5 --- /dev/null +++ b/deps/liboi/oi_error.h @@ -0,0 +1,25 @@ +#ifndef oi_error_h +#define oi_error_h +#ifdef __cplusplus +extern "C" { +#endif + +struct oi_error { + enum { OI_ERROR_GNUTLS + , OI_ERROR_EV + , OI_ERROR_CLOSE + , OI_ERROR_SHUTDOWN + , OI_ERROR_OPEN + , OI_ERROR_SEND + , OI_ERROR_RECV + , OI_ERROR_WRITE + , OI_ERROR_READ + , OI_ERROR_SENDFILE + } domain; + int code; /* errno */ +}; + +#ifdef __cplusplus +} +#endif +#endif // oi_error_h diff --git a/deps/liboi/oi_file.c b/deps/liboi/oi_file.c new file mode 100644 index 0000000000..1073b0852a --- /dev/null +++ b/deps/liboi/oi_file.c @@ -0,0 +1,391 @@ +#include +#include +#include +#include +#include +#include + +#include +#include + +#define RELEASE_BUF(buf) if(buf->release) { buf->release(buf); } +#define DRAIN_CB(file) if(file->on_drain) { file->on_drain(file); } +#define RAISE_ERROR(s, _domain, _code) do { \ + if(s->on_error) { \ + struct oi_error __oi_error; \ + __oi_error.domain = _domain; \ + __oi_error.code = _code; \ + s->on_error(s, __oi_error); \ + } \ +} while(0) \ + +/* forwards */ +static void dispatch_write_buf (oi_file *file); +static void maybe_do_read (oi_file *file); + +static void +after_read(oi_task *task, ssize_t recved) +{ + oi_file *file = task->data; + + if(recved == -1) { + RAISE_ERROR(file, OI_ERROR_READ, errno); + return; + } + + if(recved == 0) + oi_file_read_stop(file); + + if(file->on_read) + file->on_read(file, recved); + + maybe_do_read(file); +} + +static void +maybe_do_read(oi_file *file) +{ + if ( file->read_buffer == NULL + || file->write_buf != NULL + || file->write_socket != NULL + || !oi_queue_empty(&file->write_queue) + || file->io_task.active + ) return; + + assert(file->fd > 0); + + oi_task_init_read ( &file->io_task + , after_read + , file->fd + , file->read_buffer + , file->read_buffer_size + ); + file->io_task.data = file; + oi_async_submit(&file->async, &file->io_task); +} + +static void +submit_read (oi_file *file) +{ +} + +int +oi_file_init (oi_file *file) +{ + oi_async_init(&file->async); + file->async.data = file; + + oi_queue_init(&file->write_queue); + + file->fd = -1; + file->loop = NULL; + file->write_buf = NULL; + file->read_buffer = NULL; + + file->on_open = NULL; + file->on_read = NULL; + file->on_drain = NULL; + file->on_error = NULL; + file->on_close = NULL; + return 0; +} + +void +oi_file_read_start (oi_file *file, void *buffer, size_t bufsize) +{ + file->read_buffer = buffer; + file->read_buffer_size = bufsize; + maybe_do_read(file); +} + +void +oi_file_read_stop (oi_file *file) +{ + file->read_buffer = NULL; +} + +void +oi_api_free_buf_with_heap_base(oi_buf *buf) +{ + free(buf->base); + free(buf); +} + +static void +after_open(oi_task *task, int result) +{ + oi_file *file = task->data; + + if(result == -1) { + RAISE_ERROR(file, OI_ERROR_OPEN, errno); + return; + } + + file->fd = result; + + if(file->on_open) { + file->on_open(file); + } + + maybe_do_read(file); +} + +int +oi_file_open_path (oi_file *file, const char *path, int flags, mode_t mode) +{ + if(file->fd >= 0) + return -1; + oi_task_init_open( &file->io_task + , after_open + , path + , flags + , mode + ); + file->io_task.data = file; + oi_async_submit(&file->async, &file->io_task); + return 0; +} + +int +oi_file_open_stdin (oi_file *file) +{ + if(file->fd >= 0) + return -1; + file->fd = STDIN_FILENO; + if(file->on_open) + file->on_open(file); + return 0; +} + +int +oi_file_open_stdout (oi_file *file) +{ + if(file->fd >= 0) + return -1; + file->fd = STDOUT_FILENO; + if(file->on_open) + file->on_open(file); + return 0; +} + +int +oi_file_open_stderr (oi_file *file) +{ + if(file->fd >= 0) + return -1; + file->fd = STDERR_FILENO; + if(file->on_open) + file->on_open(file); + return 0; +} + +void +oi_file_attach (oi_file *file, struct ev_loop *loop) +{ + oi_async_attach (loop, &file->async); + file->loop = loop; +} + +void +oi_file_detach (oi_file *file) +{ + oi_async_detach (&file->async); + file->loop = NULL; +} + +static void +after_write(oi_task *task, ssize_t result) +{ + oi_file *file = task->data; + + if(result == -1) { + RAISE_ERROR(file, OI_ERROR_WRITE, errno); + return; + } + + assert(file->write_buf != NULL); + oi_buf *buf = file->write_buf; + + buf->written += result; + if(buf->written < buf->len) { + oi_task_init_write ( &file->io_task + , after_write + , file->fd + , buf->base + buf->written + , buf->len - buf->written + ); + file->io_task.data = file; + oi_async_submit(&file->async, &file->io_task); + return; + } + + assert(buf->written == buf->len); + + RELEASE_BUF(file->write_buf); + file->write_buf = NULL; + + if(oi_queue_empty(&file->write_queue)) { + DRAIN_CB(file); + maybe_do_read(file); + } else { + dispatch_write_buf(file); + } + + return; +} + +static void +dispatch_write_buf(oi_file *file) +{ + if(file->write_buf != NULL) + return; + if(oi_queue_empty(&file->write_queue)) + return; + + oi_queue *q = oi_queue_last(&file->write_queue); + oi_queue_remove(q); + oi_buf *buf = file->write_buf = oi_queue_data(q, oi_buf, queue); + + assert(!file->io_task.active); + oi_task_init_write ( &file->io_task + , after_write + , file->fd + , buf->base + buf->written + , buf->len - buf->written + ); + file->io_task.data = file; + oi_async_submit(&file->async, &file->io_task); +} + +int +oi_file_write (oi_file *file, oi_buf *buf) +{ + if(file->fd < 0) + return -1; + if(file->read_buffer) + return -2; + /* TODO better business check*/ + + buf->written = 0; + oi_queue_insert_head(&file->write_queue, &buf->queue); + dispatch_write_buf(file); + + return 0; +} + +// Writes a string to the file. +// NOTE: Allocates memory. Avoid for performance applications. +int +oi_file_write_simple (oi_file *file, const char *str, size_t len) +{ + if(file->fd < 0) + return -1; + if(file->read_buffer) + return -2; + /* TODO better business check*/ + + oi_buf *buf = malloc(sizeof(oi_buf)); + buf->base = malloc(len); + memcpy(buf->base, str, len); + buf->len = len; + buf->release = oi_api_free_buf_with_heap_base; + + oi_file_write(file, buf); + return 0; +} + +static void +clear_write_queue(oi_file *file) +{ + while(!oi_queue_empty(&file->write_queue)) { + oi_queue *q = oi_queue_last(&file->write_queue); + oi_queue_remove(q); + oi_buf *buf = oi_queue_data(q, oi_buf, queue); + RELEASE_BUF(buf); + } +} + +static void +after_close(oi_task *task, int result) +{ + oi_file *file = task->data; + + assert(oi_queue_empty(&file->write_queue)); + + if(result == -1) { + RAISE_ERROR(file, OI_ERROR_CLOSE, errno); + return; + // TODO try to close again? + } + + file->fd = -1; + // TODO deinit task_queue, detach thread_pool_result_watcher + + if(file->on_close) { + file->on_close(file); + } + + return; +} + +void +oi_file_close (oi_file *file) +{ + assert(file->fd >= 0 && "file not open!"); + clear_write_queue(file); + oi_task_init_close ( &file->io_task + , after_close + , file->fd + ); + file->io_task.data = file; + oi_async_submit(&file->async, &file->io_task); +} + +static void +after_sendfile(oi_task *task, ssize_t sent) +{ + oi_file *file = task->data; + oi_socket *socket = file->write_socket; + assert(socket != NULL); + file->write_socket = NULL; + + if(sent == -1) { + RAISE_ERROR(file, OI_ERROR_SENDFILE, errno); + return; + } + + if(socket->on_drain) { + socket->on_drain(socket); + } + + maybe_do_read(file); +} + +int +oi_file_send (oi_file *file, oi_socket *destination, off_t offset, size_t count) +{ + if(file->fd < 0) + return -1; + if(file->read_buffer) + return -2; + /* TODO better business check*/ + + assert(file->write_socket == NULL); + // (1) make sure the write queue on the socket is cleared. + // + // (2) + // + file->write_socket = destination; + oi_task_init_sendfile ( &file->io_task + , after_sendfile + , destination->fd + , file->fd + , offset + , count + ); + file->io_task.data = file; + oi_async_submit(&file->async, &file->io_task); + + return 0; +} + diff --git a/deps/liboi/oi_file.h b/deps/liboi/oi_file.h new file mode 100644 index 0000000000..6cd917ea4c --- /dev/null +++ b/deps/liboi/oi_file.h @@ -0,0 +1,58 @@ +#include +#include +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef oi_file_h +#define oi_file_h + +typedef struct oi_file oi_file; + +int oi_file_init (oi_file *); + +void oi_file_attach (oi_file *, struct ev_loop *); +void oi_file_detach (oi_file *); + +/* WARNING oi_file_open_path: path argument must be valid until oi_file + * object is closed and the on_close() callback is made. oi does not strdup + * the path pointer. */ +int oi_file_open_path (oi_file *, const char *path, int flags, mode_t mode); +int oi_file_open_stdin (oi_file *); +int oi_file_open_stdout (oi_file *); +int oi_file_open_stderr (oi_file *); + +void oi_file_read_start (oi_file *, void *buffer, size_t bufsize); +void oi_file_read_stop (oi_file *); +int oi_file_write (oi_file *, oi_buf *to_write); +int oi_file_write_simple (oi_file *, const char *, size_t); +int oi_file_send (oi_file *source, oi_socket *destination, off_t offset, size_t length); +void oi_file_close (oi_file *); + +struct oi_file { + /* private */ + oi_async async; + oi_task io_task; + struct ev_loop *loop; + oi_queue write_queue; + oi_buf *write_buf; /* TODO this pointer is unnecessary - remove and just look at first element of the queue */ + oi_socket *write_socket; + void *read_buffer; + size_t read_buffer_size; + + /* read-only */ + int fd; + + /* public */ + void (*on_open) (oi_file *); + void (*on_read) (oi_file *, size_t count); + void (*on_drain) (oi_file *); + void (*on_error) (oi_file *, struct oi_error); + void (*on_close) (oi_file *); + void *data; +}; + +#ifdef __cplusplus +} +#endif +#endif /* oi_file_h */ diff --git a/deps/liboi/oi_queue.h b/deps/liboi/oi_queue.h new file mode 100644 index 0000000000..0405e336f5 --- /dev/null +++ b/deps/liboi/oi_queue.h @@ -0,0 +1,69 @@ +/* Copyright (C) 2002-2009 Igor Sysoev + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY AUTHOR 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 AUTHOR 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. + */ +#ifndef oi_queue_h +#define oi_queue_h +#ifdef __cplusplus +extern "C" { +#endif + +#include /* offsetof() */ + +typedef struct oi_queue oi_queue; +struct oi_queue { + oi_queue *prev; + oi_queue *next; +}; + +#define oi_queue_init(q) \ + (q)->prev = q; \ + (q)->next = q + +#define oi_queue_empty(h) \ + (h == (h)->prev) + +#define oi_queue_insert_head(h, x) \ + (x)->next = (h)->next; \ + (x)->next->prev = x; \ + (x)->prev = h; \ + (h)->next = x + +#define oi_queue_head(h) \ + (h)->next + +#define oi_queue_last(h) \ + (h)->prev + +#define oi_queue_remove(x) \ + (x)->next->prev = (x)->prev; \ + (x)->prev->next = (x)->next; \ + (x)->prev = NULL; \ + (x)->next = NULL + +#define oi_queue_data(q, type, link) \ + (type *) ((unsigned char *) q - offsetof(type, link)) + +#ifdef __cplusplus +} +#endif +#endif // oi_queue_h diff --git a/deps/liboi/oi_socket.c b/deps/liboi/oi_socket.c new file mode 100644 index 0000000000..f922d23890 --- /dev/null +++ b/deps/liboi/oi_socket.c @@ -0,0 +1,941 @@ +#include +#include +#include +#include /* close() */ +#include /* fcntl() */ +#include /* for the default methods */ +#include /* memset */ + +#include /* TCP_NODELAY */ + +#include +#include + +#if HAVE_GNUTLS +# include +# define GNUTLS_NEED_WRITE (gnutls_record_get_direction(socket->session) == 1) +# define GNUTLS_NEED_READ (gnutls_record_get_direction(socket->session) == 0) +#endif + +#undef TRUE +#define TRUE 1 +#undef FALSE +#define FALSE 0 +#undef MIN +#define MIN(a,b) ((a) < (b) ? (a) : (b)) + +#define OKAY 0 +#define AGAIN 1 +#define ERROR 2 + +#define RAISE_ERROR(s, _domain, _code) do { \ + if(s->on_error) { \ + struct oi_error __oi_error; \ + __oi_error.domain = _domain; \ + __oi_error.code = _code; \ + s->on_error(s, __oi_error); \ + } \ +} while(0) \ + +static int +full_close(oi_socket *socket) +{ + if(-1 == close(socket->fd) && errno == EINTR) { + /* TODO fd still open. next loop call close again? */ + assert(0 && "implement me"); + return ERROR; + } + + socket->read_action = NULL; + socket->write_action = NULL; + + if(socket->loop) { + ev_feed_event(socket->loop, &socket->read_watcher, EV_READ); + } + return OKAY; +} + +static int +half_close(oi_socket *socket) +{ + int r = shutdown(socket->fd, SHUT_WR); + + if(r == -1) { + RAISE_ERROR(socket, OI_ERROR_SHUTDOWN, errno); + return ERROR; + } + + socket->write_action = NULL; + + /* TODO set timer to zero so we get a callback soon */ + return OKAY; +} + +static void +update_write_buffer_after_send(oi_socket *socket, ssize_t sent) +{ + oi_queue *q = oi_queue_last(&socket->out_stream); + oi_buf *to_write = oi_queue_data(q, oi_buf, queue); + to_write->written += sent; + socket->written += sent; + + if(to_write->written == to_write->len) { + + oi_queue_remove(q); + + if(to_write->release) { + to_write->release(to_write); + } + + if(oi_queue_empty(&socket->out_stream)) { + ev_io_stop(socket->loop, &socket->write_watcher); + if(socket->on_drain) + socket->on_drain(socket); + } + } +} + + +#if HAVE_GNUTLS +static int secure_socket_send(oi_socket *socket); +static int secure_socket_recv(oi_socket *socket); + +/* TODO can this be done without ignoring SIGPIPE? */ +static ssize_t +nosigpipe_push(gnutls_transport_ptr_t data, const void *buf, size_t len) +{ + oi_socket *socket = (oi_socket*)data; + assert(socket->secure); + int flags = 0; +#ifdef MSG_NOSIGNAL + flags |= MSG_NOSIGNAL; +#endif +#ifdef MSG_DONTWAIT + flags |= MSG_DONTWAIT; +#endif + int r = send(socket->fd, buf, len, flags); + + if(r == -1) { + gnutls_transport_set_errno(socket->session, errno); /* necessary ? */ + } + + return r; +} + +static int +secure_handshake(oi_socket *socket) +{ + assert(socket->secure); + + int r = gnutls_handshake(socket->session); + + if(gnutls_error_is_fatal(r)) { + RAISE_ERROR(socket, OI_ERROR_GNUTLS, r); + return ERROR; + } + + if(r == GNUTLS_E_INTERRUPTED || r == GNUTLS_E_AGAIN) + return AGAIN; + + oi_socket_reset_timeout(socket); + + if(!socket->connected) { + socket->connected = TRUE; + if(socket->on_connect) + socket->on_connect(socket); + } + + if(socket->read_action) + socket->read_action = secure_socket_recv; + + if(socket->write_action) + socket->write_action = secure_socket_send; + + return OKAY; +} + +static int +secure_socket_send(oi_socket *socket) +{ + ssize_t sent; + + if(oi_queue_empty(&socket->out_stream)) { + ev_io_stop(socket->loop, &socket->write_watcher); + return AGAIN; + } + + oi_queue *q = oi_queue_last(&socket->out_stream); + oi_buf *to_write = oi_queue_data(q, oi_buf, queue); + + assert(socket->secure); + + sent = gnutls_record_send( socket->session + , to_write->base + to_write->written + , to_write->len - to_write->written + ); + + if(gnutls_error_is_fatal(sent)) { + RAISE_ERROR(socket, OI_ERROR_GNUTLS, sent); + return ERROR; + } + + if(sent == 0) + return AGAIN; + + oi_socket_reset_timeout(socket); + + if(sent == GNUTLS_E_INTERRUPTED || sent == GNUTLS_E_AGAIN) { + if(GNUTLS_NEED_READ) { + if(socket->read_action) { + socket->read_action = secure_socket_send; + } else { + /* TODO GnuTLS needs read but already got EOF */ + assert(0 && "needs read but already got EOF"); + return ERROR; + } + } + return AGAIN; + } + + if(sent > 0) { + /* make sure the callbacks are correct */ + if(socket->read_action) + socket->read_action = secure_socket_recv; + update_write_buffer_after_send(socket, sent); + return OKAY; + } + + assert(0 && "Unhandled return code from gnutls_record_send()!"); + return ERROR; +} + +static int +secure_socket_recv(oi_socket *socket) +{ + char recv_buffer[TCP_MAXWIN]; + size_t recv_buffer_size = MIN(TCP_MAXWIN, socket->chunksize); + ssize_t recved; + + assert(socket->secure); + + recved = gnutls_record_recv(socket->session, recv_buffer, recv_buffer_size); + + //printf("secure socket recv %d %p\n", recved, socket->on_connect); + + if(gnutls_error_is_fatal(recved)) { + RAISE_ERROR(socket, OI_ERROR_GNUTLS, recved); + return ERROR; + } + + if(recved == GNUTLS_E_INTERRUPTED || recved == GNUTLS_E_AGAIN) { + if(GNUTLS_NEED_WRITE) { + if(socket->write_action) { + printf("need write\n"); + socket->write_action = secure_socket_recv; + } else { + /* TODO GnuTLS needs send but already closed write end */ + assert(0 && "needs read but cannot"); + return ERROR; + } + } + return AGAIN; + } + + oi_socket_reset_timeout(socket); + + /* A server may also receive GNUTLS_E_REHANDSHAKE when a client has + * initiated a handshake. In that case the server can only initiate a + * handshake or terminate the connection. */ + if(recved == GNUTLS_E_REHANDSHAKE) { + if(socket->write_action) { + socket->read_action = secure_handshake; + socket->write_action = secure_handshake; + return OKAY; + } else { + /* TODO */ + assert(0 && "needs read but cannot"); + return ERROR; + } + } + + if(recved >= 0) { + /* Got EOF */ + if(recved == 0) + socket->read_action = NULL; + + if(socket->write_action) + socket->write_action = secure_socket_send; + + if(socket->on_read) { socket->on_read(socket, recv_buffer, recved); } + + return OKAY; + } + + assert(0 && "Unhandled return code from gnutls_record_send()!"); + return ERROR; +} + +static int +secure_goodbye(oi_socket *socket, gnutls_close_request_t how) +{ + assert(socket->secure); + + int r = gnutls_bye(socket->session, how); + + if(gnutls_error_is_fatal(r)) { + RAISE_ERROR(socket, OI_ERROR_GNUTLS, r); + return ERROR; + } + + if(r == GNUTLS_E_INTERRUPTED || r == GNUTLS_E_AGAIN) + return AGAIN; + + return OKAY; +} + +static int +secure_full_goodbye(oi_socket *socket) +{ + int r = secure_goodbye(socket, GNUTLS_SHUT_RDWR); + if(OKAY == r) { + return full_close(socket); + } + return r; +} + +static int +secure_half_goodbye(oi_socket *socket) +{ + int r = secure_goodbye(socket, GNUTLS_SHUT_WR); + if(OKAY == r) { + return half_close(socket); + } + return r; +} + +/* Tells the socket to use transport layer security (SSL). liboi does not + * want to make any decisions about security requirements, so the + * majoirty of GnuTLS configuration is left to the user. Only the transport + * layer of GnuTLS is controlled by liboi. + * + * That is, do not use gnutls_transport_* functions. + * Do use the rest of GnuTLS's API. + */ +void +oi_socket_set_secure_session (oi_socket *socket, gnutls_session_t session) +{ + socket->session = session; + socket->secure = TRUE; +} +#endif /* HAVE GNUTLS */ + +static int +socket_send(oi_socket *socket) +{ + ssize_t sent; + + assert(socket->secure == FALSE); + + if(oi_queue_empty(&socket->out_stream)) { + ev_io_stop(socket->loop, &socket->write_watcher); + return AGAIN; + } + + oi_queue *q = oi_queue_last(&socket->out_stream); + oi_buf *to_write = oi_queue_data(q, oi_buf, queue); + + int flags = 0; +#ifdef MSG_NOSIGNAL + flags |= MSG_NOSIGNAL; +#endif +#ifdef MSG_DONTWAIT + flags |= MSG_DONTWAIT; +#endif + + /* TODO use writev() here */ + + sent = send( socket->fd + , to_write->base + to_write->written + , to_write->len - to_write->written + , flags + ); + + if(sent < 0) { + switch(errno) { + case EAGAIN: + return AGAIN; + + case ECONNREFUSED: + case ECONNRESET: + socket->write_action = NULL; + /* TODO maybe just clear write buffer instead of error? + * They should be able to read still from the socket. + */ + RAISE_ERROR(socket, OI_ERROR_SEND, errno); + return ERROR; + + default: + perror("send()"); + assert(0 && "oi shouldn't let this happen."); + return ERROR; + } + } + + oi_socket_reset_timeout(socket); + + if(!socket->connected) { + socket->connected = TRUE; + if(socket->on_connect) { socket->on_connect(socket); } + } + + update_write_buffer_after_send(socket, sent); + + return OKAY; +} + +static int +socket_recv(oi_socket *socket) +{ + char buf[TCP_MAXWIN]; + size_t buf_size = TCP_MAXWIN; + ssize_t recved; + + assert(socket->secure == FALSE); + + if(!socket->connected) { + socket->connected = TRUE; + if(socket->on_connect) { socket->on_connect(socket); } + return OKAY; + } + + recved = recv(socket->fd, buf, buf_size, 0); + + if(recved < 0) { + switch(errno) { + case EAGAIN: + case EINTR: + return AGAIN; + + /* A remote host refused to allow the network connection (typically + * because it is not running the requested service). */ + case ECONNREFUSED: + RAISE_ERROR(socket, OI_ERROR_RECV, errno); + return ERROR; + + case ECONNRESET: + RAISE_ERROR(socket, OI_ERROR_RECV, errno); + return ERROR; + + default: + perror("recv()"); + printf("unmatched errno %d\n", errno); + assert(0 && "recv returned error that oi should have caught before."); + return ERROR; + } + } + + oi_socket_reset_timeout(socket); + + if(recved == 0) { + oi_socket_read_stop(socket); + socket->read_action = NULL; + } + + /* NOTE: EOF is signaled with recved == 0 on callback */ + if(socket->on_read) { socket->on_read(socket, buf, recved); } + + return OKAY; +} + +static void +assign_file_descriptor(oi_socket *socket, int fd) +{ + socket->fd = fd; + + ev_io_set (&socket->read_watcher, fd, EV_READ); + ev_io_set (&socket->write_watcher, fd, EV_WRITE); + + socket->read_action = socket_recv; + socket->write_action = socket_send; + +#if HAVE_GNUTLS + if(socket->secure) { + gnutls_transport_set_lowat(socket->session, 0); + gnutls_transport_set_push_function(socket->session, nosigpipe_push); + gnutls_transport_set_ptr2 ( socket->session + /* recv */ , (gnutls_transport_ptr_t)fd + /* send */ , socket + ); + socket->read_action = secure_handshake; + socket->write_action = secure_handshake; + } +#endif +} + + +/* Internal callback + * Called by server->connection_watcher. + */ +static void +on_connection(struct ev_loop *loop, ev_io *watcher, int revents) +{ + oi_server *server = watcher->data; + + // printf("on connection!\n"); + + assert(server->listening); + assert(server->loop == loop); + assert(&server->connection_watcher == watcher); + + if(EV_ERROR & revents) { + oi_server_close(server); + return; + } + + struct sockaddr address; /* connector's address information */ + socklen_t addr_len = sizeof(address); + + /* TODO accept all possible connections? currently: just one */ + int fd = accept(server->fd, (struct sockaddr*)&address, &addr_len); + if(fd < 0) { + perror("accept()"); + return; + } + + oi_socket *socket = NULL; + if(server->on_connection) + socket = server->on_connection(server, (struct sockaddr*)&address, addr_len); + + if(socket == NULL) { + close(fd); + return; + } + + int flags = fcntl(fd, F_GETFL, 0); + int r = fcntl(fd, F_SETFL, flags | O_NONBLOCK); + if(r < 0) { + /* TODO error report */ + } + +#ifdef SO_NOSIGPIPE + flags = 1; + setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, &flags, sizeof(flags)); +#endif + + socket->server = server; + assign_file_descriptor(socket, fd); + oi_socket_attach(socket, loop); +} + +int +oi_server_listen(oi_server *server, struct addrinfo *addrinfo) +{ + int fd = -1; + struct linger ling = {0, 0}; + assert(server->listening == FALSE); + + fd = socket( addrinfo->ai_family + , addrinfo->ai_socktype + , addrinfo->ai_protocol + ); + if(fd < 0) { + perror("socket()"); + return -1; + } + + int flags = fcntl(fd, F_GETFL, 0); + int r = fcntl(fd, F_SETFL, flags | O_NONBLOCK); + if(r < 0) { + perror("fcntl()"); + return -1; + } + + flags = 1; + setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void *)&flags, sizeof(flags)); + setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void *)&flags, sizeof(flags)); + setsockopt(fd, SOL_SOCKET, SO_LINGER, (void *)&ling, sizeof(ling)); + + /* XXX: Sending single byte chunks in a response body? Perhaps there is a + * need to enable the Nagel algorithm dynamically. For now disabling. + */ + //setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (void *)&flags, sizeof(flags)); + + if (bind(fd, addrinfo->ai_addr, addrinfo->ai_addrlen) < 0) { + perror("bind()"); + close(fd); + return -1; + } + + if (listen(fd, server->backlog) < 0) { + perror("listen()"); + close(fd); + return -1; + } + + server->fd = fd; + server->listening = TRUE; + ev_io_set (&server->connection_watcher, server->fd, EV_READ); + + return 0; +} + +/** + * Stops the server. Will not accept new connections. Does not drop + * existing connections. + */ +void +oi_server_close(oi_server *server) +{ + if(server->listening) { + oi_server_detach(server); + close(server->fd); + /* TODO do this on the loop? check return value? */ + server->listening = FALSE; + } +} + +void +oi_server_attach (oi_server *server, struct ev_loop *loop) +{ + ev_io_start (loop, &server->connection_watcher); + server->loop = loop; +} + +void +oi_server_detach (oi_server *server) +{ + ev_io_stop (server->loop, &server->connection_watcher); + server->loop = NULL; +} + +void +oi_server_init(oi_server *server, int backlog) +{ + server->backlog = backlog; + server->listening = FALSE; + server->fd = -1; + server->connection_watcher.data = server; + ev_init (&server->connection_watcher, on_connection); + + server->on_connection = NULL; + server->on_error = NULL; + server->data = NULL; +} + +/* Internal callback. called by socket->timeout_watcher */ +static void +on_timeout(struct ev_loop *loop, ev_timer *watcher, int revents) +{ + oi_socket *socket = watcher->data; + + assert(watcher == &socket->timeout_watcher); + + // printf("on_timeout\n"); + + if(socket->on_timeout) { socket->on_timeout(socket); } + + + /* TODD set timer to zero */ + full_close(socket); +} + +static void +release_write_buffer(oi_socket *socket) +{ + while(!oi_queue_empty(&socket->out_stream)) { + oi_queue *q = oi_queue_last(&socket->out_stream); + oi_buf *buf = oi_queue_data(q, oi_buf, queue); + oi_queue_remove(q); + if(buf->release) { buf->release(buf); } + } +} + +/* Internal callback. called by socket->read_watcher */ +static void +on_io_event(struct ev_loop *loop, ev_io *watcher, int revents) +{ + oi_socket *socket = watcher->data; + + if(revents & EV_ERROR) { + RAISE_ERROR(socket, OI_ERROR_EV, 0); + goto close; + } + + int r; + int have_read_event = TRUE; + int have_write_event = TRUE; + + while(have_read_event || have_write_event) { + + if(socket->read_action) { + r = socket->read_action(socket); + if(r == ERROR) goto close; + if(r == AGAIN) have_read_event = FALSE; + } else { + have_read_event = FALSE; + } + + if(socket->write_action) { + r = socket->write_action(socket); + if(r == ERROR) goto close; + if(r == AGAIN) have_write_event = FALSE; + } else { + have_write_event = FALSE; + } + + + if(socket->read_watcher.active == FALSE) + have_read_event = FALSE; + if(socket->write_watcher.active == FALSE) + have_write_event = FALSE; + } + + if(socket->write_action == NULL && socket->read_action == NULL) + goto close; + + return; + +close: + release_write_buffer(socket); + + ev_clear_pending (socket->loop, &socket->write_watcher); + ev_clear_pending (socket->loop, &socket->read_watcher); + ev_clear_pending (socket->loop, &socket->timeout_watcher); + + oi_socket_detach(socket); + + if(socket->on_close) { socket->on_close(socket); } + /* WARNING: user can free socket in on_close so no more + * access beyond this point. */ +} + +/** + * If using SSL do consider setting + * gnutls_db_set_retrieve_function (socket->session, _); + * gnutls_db_set_remove_function (socket->session, _); + * gnutls_db_set_store_function (socket->session, _); + * gnutls_db_set_ptr (socket->session, _); + */ +void +oi_socket_init(oi_socket *socket, float timeout) +{ + socket->fd = -1; + socket->server = NULL; + socket->loop = NULL; + socket->connected = FALSE; + + oi_queue_init(&socket->out_stream); + + ev_init (&socket->write_watcher, on_io_event); + socket->write_watcher.data = socket; + + ev_init(&socket->read_watcher, on_io_event); + socket->read_watcher.data = socket; + + socket->secure = FALSE; + socket->wait_for_secure_hangup = FALSE; +#if HAVE_GNUTLS + socket->session = NULL; +#endif + + /* TODO higher resolution timer */ + ev_timer_init(&socket->timeout_watcher, on_timeout, 0., timeout); + socket->timeout_watcher.data = socket; + + socket->read_action = NULL; + socket->write_action = NULL; + + socket->chunksize = TCP_MAXWIN; + socket->on_connect = NULL; + socket->on_read = NULL; + socket->on_drain = NULL; + socket->on_error = NULL; + socket->on_timeout = NULL; +} + +void +oi_socket_write_eof (oi_socket *socket) +{ +#if HAVE_GNUTLS + /* try to hang up properly for secure connections */ + if(socket->secure) + { + if( socket->connected /* completed handshake */ + && socket->write_action /* write end is open */ + ) + { + socket->write_action = secure_half_goodbye; + if(socket->loop) + ev_io_start(socket->loop, &socket->write_watcher); + return; + } + /* secure servers cannot handle half-closed connections? */ + full_close(socket); + return; + } +#endif // HAVE_GNUTLS + + if(socket->write_action) + half_close(socket); + else + full_close(socket); +} + +void +oi_socket_close (oi_socket *socket) +{ +#if HAVE_GNUTLS + /* try to hang up properly for secure connections */ + if( socket->secure + && socket->connected /* completed handshake */ + && socket->write_action /* write end is open */ + ) + { + if(socket->wait_for_secure_hangup && socket->read_action) { + socket->write_action = secure_full_goodbye; + socket->read_action = secure_full_goodbye; + } else { + socket->write_action = secure_half_goodbye; + socket->read_action = NULL; + } + + if(socket->loop) + ev_io_start(socket->loop, &socket->write_watcher); + + return; + } +#endif // HAVE_GNUTLS + + full_close(socket); +} + +/* + * Resets the timeout to stay alive for another socket->timeout seconds + */ +void +oi_socket_reset_timeout(oi_socket *socket) +{ + ev_timer_again(socket->loop, &socket->timeout_watcher); +} + +/** + * Writes a string to the socket. This is actually sets a watcher which may + * take multiple iterations to write the entire string. + */ +void +oi_socket_write(oi_socket *socket, oi_buf *buf) +{ + if(socket->write_action == NULL) + return; + + oi_queue_insert_head(&socket->out_stream, &buf->queue); + + buf->written = 0; + ev_io_start(socket->loop, &socket->write_watcher); +} + +static void +free_simple_buf ( oi_buf *buf ) +{ + free(buf->base); + free(buf); +} + +/* Writes a string to the socket. + * NOTE: Allocates memory. Avoid for performance applications. + */ +void +oi_socket_write_simple(oi_socket *socket, const char *str, size_t len) +{ + oi_buf *buf = malloc(sizeof(oi_buf)); + buf->release = free_simple_buf; + buf->base = strdup(str); + buf->len = len; + + oi_socket_write(socket, buf); +} + +void +oi_socket_attach(oi_socket *socket, struct ev_loop *loop) +{ + socket->loop = loop; + + ev_timer_again(loop, &socket->timeout_watcher); + + if(socket->read_action) + ev_io_start(loop, &socket->read_watcher); + + if(socket->write_action) + ev_io_start(loop, &socket->write_watcher); + + /* make sure the io_event happens soon in the case we're being reattached */ + ev_feed_event(loop, &socket->read_watcher, EV_READ); +} + +void +oi_socket_detach(oi_socket *socket) +{ + if(socket->loop) { + ev_io_stop(socket->loop, &socket->write_watcher); + ev_io_stop(socket->loop, &socket->read_watcher); + ev_timer_stop(socket->loop, &socket->timeout_watcher); + socket->loop = NULL; + } +} + +void +oi_socket_read_stop (oi_socket *socket) +{ + ev_io_stop(socket->loop, &socket->read_watcher); + ev_clear_pending (socket->loop, &socket->read_watcher); +} + +void +oi_socket_read_start (oi_socket *socket) +{ + if(socket->read_action) { + ev_io_start(socket->loop, &socket->read_watcher); + /* XXX feed event? */ + } +} + +int +oi_socket_connect(oi_socket *s, struct addrinfo *addrinfo) +{ + int fd = socket( addrinfo->ai_family + , addrinfo->ai_socktype + , addrinfo->ai_protocol + ); + if(fd < 0) { + perror("socket()"); + return -1; + } + + int flags = fcntl(fd, F_GETFL, 0); + int r = fcntl(fd, F_SETFL, flags | O_NONBLOCK); + if(r < 0) { + perror("fcntl()"); + return -1; + } + +#ifdef SO_NOSIGPIPE + flags = 1; + setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, &flags, sizeof(flags)); +#endif + + r = connect( fd + , addrinfo->ai_addr + , addrinfo->ai_addrlen + ); + + if(r < 0 && errno != EINPROGRESS) { + perror("connect"); + close(fd); + return -1; + } + + assign_file_descriptor(s, fd); + + return 0; +} + diff --git a/deps/liboi/oi_socket.h b/deps/liboi/oi_socket.h new file mode 100644 index 0000000000..1b51f0f21c --- /dev/null +++ b/deps/liboi/oi_socket.h @@ -0,0 +1,98 @@ +#include +#include +#include +#include +#include + +#ifndef oi_socket_h +#define oi_socket_h +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef HAVE_GNUTLS +# define HAVE_GNUTLS 0 +#endif +#if HAVE_GNUTLS +# include +#endif + +typedef struct oi_server oi_server; +typedef struct oi_socket oi_socket; + +void oi_server_init (oi_server *, int backlog); + int oi_server_listen (oi_server *, struct addrinfo *addrinfo); +void oi_server_attach (oi_server *, struct ev_loop *loop); +void oi_server_detach (oi_server *); +void oi_server_close (oi_server *); + +void oi_socket_init (oi_socket *, float timeout); + int oi_socket_pair (oi_socket *a, oi_socket *b); /* TODO */ + int oi_socket_connect (oi_socket *, struct addrinfo *addrinfo); +void oi_socket_attach (oi_socket *, struct ev_loop *loop); +void oi_socket_detach (oi_socket *); +void oi_socket_read_start (oi_socket *); +void oi_socket_read_stop (oi_socket *); +void oi_socket_reset_timeout (oi_socket *); +void oi_socket_write (oi_socket *, oi_buf *); +void oi_socket_write_simple (oi_socket *, const char *str, size_t len); +void oi_socket_write_eof (oi_socket *); +void oi_socket_close (oi_socket *); +#if HAVE_GNUTLS +void oi_socket_set_secure_session (oi_socket *, gnutls_session_t); +#endif + +struct oi_server { + /* read only */ + int fd; + int backlog; + struct ev_loop *loop; + unsigned listening:1; + + /* private */ + ev_io connection_watcher; + + /* public */ + oi_socket* (*on_connection) (oi_server *, struct sockaddr *remote_addr, socklen_t remove_addr_len); + void (*on_error) (oi_server *, struct oi_error e); + void *data; +}; + +struct oi_socket { + /* read only */ + int fd; + struct ev_loop *loop; + oi_server *server; + oi_queue out_stream; + size_t written; + unsigned connected:1; + unsigned secure:1; + unsigned wait_for_secure_hangup:1; + + /* if these are NULL then it means that end of the socket is closed. */ + int (*read_action) (oi_socket *); + int (*write_action) (oi_socket *); + + /* private */ + ev_io write_watcher; + ev_io read_watcher; + ev_timer timeout_watcher; +#if HAVE_GNUTLS + gnutls_session_t session; +#endif + + /* public */ + size_t chunksize; /* the maximum chunk that on_read() will return */ + void (*on_connect) (oi_socket *); + void (*on_read) (oi_socket *, const void *buf, size_t count); + void (*on_drain) (oi_socket *); + void (*on_error) (oi_socket *, struct oi_error e); + void (*on_close) (oi_socket *); + void (*on_timeout) (oi_socket *); + void *data; +}; + +#ifdef __cplusplus +} +#endif +#endif /* oi_socket_h */ diff --git a/deps/liboi/test/common.c b/deps/liboi/test/common.c new file mode 100644 index 0000000000..4703b402fd --- /dev/null +++ b/deps/liboi/test/common.c @@ -0,0 +1,110 @@ +#include +#include +#include +#include +#include + +#include +#include +#include +#include + + +#include +#include +#include + +#define HOST "127.0.0.1" +#define SOCKFILE "/tmp/oi.sock" +#define PORT "5000" + +int nconnections; + +static void +on_peer_close(oi_socket *socket) +{ + //printf("server connection closed\n"); +#if HAVE_GNUTLS +#if SECURE + gnutls_deinit(socket->session); +#endif +#endif + free(socket); +} + +static void +on_client_timeout(oi_socket *socket) +{ + printf("client connection timeout\n"); + assert(0); +} + +static void +on_peer_timeout(oi_socket *socket) +{ + fprintf(stderr, "peer connection timeout\n"); + assert(0); +} + +static void +on_client_error(oi_socket *socket, struct oi_error e) +{ + assert(0); +} + + +#if HAVE_GNUTLS +#if SECURE +#define DH_BITS 768 +gnutls_anon_server_credentials_t server_credentials; +const int kx_prio[] = { GNUTLS_KX_ANON_DH, 0 }; +static gnutls_dh_params_t dh_params; + +void anon_tls_init() +{ + gnutls_global_init(); + + gnutls_dh_params_init (&dh_params); + + fprintf(stderr, ".."); + fsync((int)stderr); + gnutls_dh_params_generate2 (dh_params, DH_BITS); + fprintf(stderr, "."); + + gnutls_anon_allocate_server_credentials (&server_credentials); + gnutls_anon_set_server_dh_params (server_credentials, dh_params); +} + +void anon_tls_server(oi_socket *socket) +{ + gnutls_session_t session; + socket->data = session; + + int r = gnutls_init(&session, GNUTLS_SERVER); + assert(r == 0); + gnutls_set_default_priority(session); + gnutls_kx_set_priority (session, kx_prio); + gnutls_credentials_set(session, GNUTLS_CRD_ANON, server_credentials); + gnutls_dh_set_prime_bits(session, DH_BITS); + + oi_socket_set_secure_session(socket, session); +} + +void anon_tls_client(oi_socket *socket) +{ + gnutls_session_t client_session; + gnutls_anon_client_credentials_t client_credentials; + + gnutls_anon_allocate_client_credentials (&client_credentials); + gnutls_init (&client_session, GNUTLS_CLIENT); + gnutls_set_default_priority(client_session); + gnutls_kx_set_priority(client_session, kx_prio); + /* Need to enable anonymous KX specifically. */ + gnutls_credentials_set (client_session, GNUTLS_CRD_ANON, client_credentials); + + oi_socket_set_secure_session(socket, client_session); + assert(socket->secure); +} + +#endif // SECURE +#endif // HAVE_GNUTLS diff --git a/deps/liboi/test/connection_interruption.c b/deps/liboi/test/connection_interruption.c new file mode 100644 index 0000000000..0b9169a9d1 --- /dev/null +++ b/deps/liboi/test/connection_interruption.c @@ -0,0 +1,159 @@ +#include "test/common.c" +#define NCONN 100 +#define TIMEOUT 1000.0 + +static oi_server server; + +static void +on_peer_read(oi_socket *socket, const void *base, size_t len) +{ + assert(len == 0); + oi_socket_write_simple(socket, "BYE", 3); + //printf("server wrote bye\n"); +} + +static void +on_peer_drain(oi_socket *socket) +{ + oi_socket_close(socket); +} + +static void +on_peer_error2(oi_socket *socket, struct oi_error e) +{ + if(e.domain == OI_ERROR_GNUTLS) return; + assert(0); +} + +static oi_socket* +on_server_connection(oi_server *server, struct sockaddr *addr, socklen_t len) +{ + oi_socket *socket = malloc(sizeof(oi_socket)); + oi_socket_init(socket, TIMEOUT); + socket->on_read = on_peer_read; + socket->on_drain = on_peer_drain; + socket->on_error = on_peer_error2; + socket->on_close = on_peer_close; + socket->on_timeout = on_peer_timeout; + +#if HAVE_GNUTLS +# if SECURE + anon_tls_server(socket); +# endif +#endif + + //printf("on server connection\n"); + + return socket; +} + +static void +on_client_connect(oi_socket *socket) +{ + //printf("on client connection\n"); + oi_socket_write_eof(socket); +} + +static void +on_client_close(oi_socket *socket) +{ + oi_socket_close(socket); // already closed, but it shouldn't crash if we try to do it again + + //printf("client connection closed\n"); + if(++nconnections == NCONN) { + oi_server_detach(&server); + //printf("detaching server\n"); + } +} + +static void +on_client_read(oi_socket *socket, const void *base, size_t len) +{ + char buf[200000]; + strncpy(buf, base, len); + buf[len] = 0; + + //printf("client got message: %s\n", buf); + + if(strcmp(buf, "BYE") == 0) { + oi_socket_close(socket); + } else { + assert(0); + } +} + +int +main(int argc, const char *argv[]) +{ + int r; + struct ev_loop *loop = ev_default_loop(0); + + oi_server_init(&server, 1000); + server.on_connection = on_server_connection; +#if HAVE_GNUTLS +# if SECURE + anon_tls_init(); +# endif +#endif + + struct addrinfo *servinfo; + struct addrinfo hints; + memset(&hints, 0, sizeof hints); +#if TCP + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_PASSIVE; + r = getaddrinfo(NULL, PORT, &hints, &servinfo); + assert(r == 0); +#else + struct stat tstat; + if (lstat(SOCKFILE, &tstat) == 0) { + if (S_ISSOCK(tstat.st_mode)) + unlink(SOCKFILE); + } + + servinfo = malloc(sizeof(struct addrinfo)); + servinfo->ai_family = AF_UNIX; + servinfo->ai_socktype = SOCK_STREAM; + servinfo->ai_protocol = 0; + + struct sockaddr_un *sockaddr = calloc(sizeof(struct sockaddr_un), 1); + sockaddr->sun_family = AF_UNIX; + strcpy(sockaddr->sun_path, SOCKFILE); + + servinfo->ai_addr = (struct sockaddr*)sockaddr; + servinfo->ai_addrlen = sizeof(struct sockaddr_un); +#endif + + oi_server_listen(&server, servinfo); + oi_server_attach(&server, loop); + + int i; + for(i = 0; i < NCONN; i++) { + oi_socket *client = malloc(sizeof(oi_socket)); + oi_socket_init(client, TIMEOUT); + client->on_read = on_client_read; + client->on_error = on_client_error; + client->on_connect = on_client_connect; + client->on_close = on_client_close; + client->on_timeout = on_client_timeout; +#if HAVE_GNUTLS +#if SECURE + anon_tls_client(client); +#endif +#endif + r = oi_socket_connect(client, servinfo); + assert(r == 0 && "problem connecting"); + oi_socket_attach(client, loop); + } + + ev_loop(loop, 0); + + assert(nconnections == NCONN); + +#if TCP + freeaddrinfo(servinfo); +#endif + + return 0; +} diff --git a/deps/liboi/test/echo.c b/deps/liboi/test/echo.c new file mode 100644 index 0000000000..c68b94cf34 --- /dev/null +++ b/deps/liboi/test/echo.c @@ -0,0 +1,102 @@ +#include "test/common.c" + +int successful_ping_count; + +static void +on_peer_read(oi_socket *socket, const void *base, size_t len) +{ + if(len == 0) + return; + + oi_socket_write_simple(socket, base, len); +} + +static void +on_peer_error(oi_socket *socket, struct oi_error e) +{ + assert(0); +} + +static oi_socket* +on_server_connection(oi_server *server, struct sockaddr *addr, socklen_t len) +{ + oi_socket *socket = malloc(sizeof(oi_socket)); + oi_socket_init(socket, 5.0); + socket->on_read = on_peer_read; + socket->on_error = on_peer_error; + socket->on_close = on_peer_close; + socket->on_timeout = on_peer_timeout; + + nconnections++; + +#if HAVE_GNUTLS +# if SECURE + anon_tls_server(socket); +# endif +#endif + + //printf("on server connection\n"); + + return socket; +} + +int +main(int argc, const char *argv[]) +{ + int r; + struct ev_loop *loop = ev_default_loop(0); + oi_server server; + oi_socket client; + + //printf("sizeof(oi_server): %d\n", sizeof(oi_server)); + //printf("sizeof(oi_socket): %d\n", sizeof(oi_socket)); + + oi_server_init(&server, 10); + server.on_connection = on_server_connection; + +#if HAVE_GNUTLS +# if SECURE + anon_tls_init(); +# endif +#endif + + struct addrinfo *servinfo; + struct addrinfo hints; + memset(&hints, 0, sizeof hints); +#if TCP + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_PASSIVE; + r = getaddrinfo(NULL, PORT, &hints, &servinfo); + assert(r == 0); +#else + struct stat tstat; + if (lstat(SOCKFILE, &tstat) == 0) { + if (S_ISSOCK(tstat.st_mode)) + unlink(SOCKFILE); + } + + servinfo = malloc(sizeof(struct addrinfo)); + servinfo->ai_family = AF_UNIX; + servinfo->ai_socktype = SOCK_STREAM; + servinfo->ai_protocol = 0; + + struct sockaddr_un *sockaddr = calloc(sizeof(struct sockaddr_un), 1); + sockaddr->sun_family = AF_UNIX; + strcpy(sockaddr->sun_path, SOCKFILE); + + servinfo->ai_addr = (struct sockaddr*)sockaddr; + servinfo->ai_addrlen = sizeof(struct sockaddr_un); +#endif + r = oi_server_listen(&server, servinfo); + assert(r == 0); + oi_server_attach(&server, loop); + + ev_loop(loop, 0); + +#if TCP + freeaddrinfo(servinfo); +#endif + + return 0; +} diff --git a/deps/liboi/test/fancy_copy.c b/deps/liboi/test/fancy_copy.c new file mode 100644 index 0000000000..f5d2ba7194 --- /dev/null +++ b/deps/liboi/test/fancy_copy.c @@ -0,0 +1,223 @@ +/* This test uses most of oi's facilities. It starts by opening a new file + * and writing N characters to it. Once the first chunk is written, it opens + * that file with another handle + * + * /tmp/oi_test_src == /tmp/oi_test_dst + * | ^ + * | | + * stream | | write + * | | + * V | + * client ----------> server/connection + */ +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#ifndef TRUE +# define TRUE 1 +#endif +#ifndef FALSE +# define FALSE 0 +#endif + +#include +#include + +#define PORT "5555" + +static struct ev_loop *loop; +static oi_file file_src; +static oi_file file_dst; +static oi_socket client; +static oi_server server; +static oi_socket connection; +static int got_connection = 0; + +static char *src_filename; +static char *dst_filename; + +static void +file_error(oi_file *_) +{ + assert(0); +} + +static void +on_file_dst_open (oi_file *_) +{ + assert(connection.fd > 0); + oi_socket_read_start(&connection); + //printf("file_dst is open\n"); +} + +static void +on_file_dst_close (oi_file *_) +{ + //printf("file dst closed\n"); + oi_file_detach(&file_dst); +} + +static void +on_connection_read (oi_socket *_, const void *buf, size_t count) +{ + assert(file_dst.fd > 0); + if(count == 0) { + file_dst.on_drain = oi_file_close; + oi_socket_close(&connection); + } else { + oi_file_write_simple(&file_dst, buf, count); + } +} + +static void +on_connection_connect (oi_socket *_) +{ + oi_file_init(&file_dst); + file_dst.on_open = on_file_dst_open; + file_dst.on_close = on_file_dst_close; + oi_file_open_path(&file_dst, dst_filename, O_WRONLY | O_CREAT, 0644); + oi_file_attach(&file_dst, loop); + + oi_socket_read_stop(&connection); +} + +static void +on_connection_timeout (oi_socket *_) +{ + assert(0); +} + +static void +on_connection_error (oi_socket *_, struct oi_error e) +{ + assert(0); +} + +static void +on_connection_close (oi_socket *_) +{ + oi_server_close(&server); + oi_server_detach(&server); +} + +static oi_socket* +on_server_connection(oi_server *_, struct sockaddr *addr, socklen_t len) +{ + assert(got_connection == FALSE); + oi_socket_init(&connection, 5.0); + connection.on_connect = on_connection_connect; + connection.on_read = on_connection_read; + connection.on_error = on_connection_error; + connection.on_close = on_connection_close; + connection.on_timeout = on_connection_timeout; + connection.on_drain = oi_socket_close; + got_connection = TRUE; + //printf("on server connection\n"); + return &connection; +} + +static void +on_client_read (oi_socket *_, const void *buf, size_t count) +{ + assert(0); +} + +static void +on_client_error (oi_socket *_, struct oi_error e) +{ + assert(0); +} + +static void +on_client_connect (oi_socket *_) +{ + if(file_src.fd > 0) { + oi_file_send(&file_src, &client, 0, 50*1024); + } +} + +static void +on_client_drain (oi_socket *_) +{ + oi_socket_close(&client); + oi_file_close(&file_src); +} + +static void +on_file_src_open (oi_file *_) +{ + if(client.fd > 0) { + oi_file_send(&file_src, &client, 0, 50*1024); + } +} + +static void +on_client_timeout (oi_socket *_) +{ + assert(0); +} + +int +main(int argc, char *argv[]) +{ + int r; + loop = ev_default_loop(0); + + assert(argc == 3); + src_filename = argv[1]; + dst_filename = argv[2]; + + assert(strlen(src_filename) > 0); + assert(strlen(dst_filename) > 0); + + oi_server_init(&server, 10); + server.on_connection = on_server_connection; + + struct addrinfo *servinfo; + struct addrinfo hints; + memset(&hints, 0, sizeof hints); + + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_PASSIVE; + r = getaddrinfo(NULL, PORT, &hints, &servinfo); + assert(r == 0); + + r = oi_server_listen(&server, servinfo); + assert(r >= 0 && "problem listening"); + oi_server_attach(&server, loop); + + oi_socket_init(&client, 5.0); + client.on_read = on_client_read; + client.on_error = on_client_error; + client.on_connect = on_client_connect; + client.on_timeout = on_client_timeout; + //client.on_close = oi_socket_detach; + client.on_drain = on_client_drain; + r = oi_socket_connect(&client, servinfo); + assert(r == 0 && "problem connecting"); + oi_socket_attach(&client, loop); + + oi_file_init(&file_src); + file_src.on_open = on_file_src_open; + file_src.on_drain = file_error; + file_src.on_close = oi_file_detach; + oi_file_open_path(&file_src, src_filename, O_RDONLY, 0700); + oi_file_attach(&file_src, loop); + + ev_loop(loop, 0); + + printf("\noi_file: %d bytes\n", sizeof(oi_file)); + printf("oi_socket: %d bytes\n", sizeof(oi_socket)); + + return 0; +} + diff --git a/deps/liboi/test/ping_pong.c b/deps/liboi/test/ping_pong.c new file mode 100644 index 0000000000..93199eaa42 --- /dev/null +++ b/deps/liboi/test/ping_pong.c @@ -0,0 +1,165 @@ +#include "test/common.c" + +#define PING "PING" +#define PONG "PONG" +#define EXCHANGES 100 + +int successful_ping_count; + +static void +on_peer_read(oi_socket *socket, const void *base, size_t len) +{ + if(len == 0) + return; + + char buf[2000]; + strncpy(buf, base, len); + buf[len] = 0; + //printf("server got message: %s\n", buf); + + oi_socket_write_simple(socket, PONG, sizeof PONG); +} + +static void +on_peer_error(oi_socket *socket, struct oi_error e) +{ + assert(0); +} + +static void +on_client_close(oi_socket *socket) +{ + //printf("client connection closed\n"); + ev_unloop(socket->loop, EVUNLOOP_ALL); +} + +static oi_socket* +on_server_connection(oi_server *server, struct sockaddr *addr, socklen_t len) +{ + oi_socket *socket = malloc(sizeof(oi_socket)); + oi_socket_init(socket, 5.0); + socket->on_read = on_peer_read; + socket->on_error = on_peer_error; + socket->on_close = on_peer_close; + socket->on_timeout = on_peer_timeout; + + nconnections++; + +#if HAVE_GNUTLS +# if SECURE + anon_tls_server(socket); +# endif +#endif + + //printf("on server connection\n"); + + return socket; +} + +static void +on_client_connect(oi_socket *socket) +{ + //printf("client connected. sending ping\n"); + oi_socket_write_simple(socket, PING, sizeof PING); +} + +static void +on_client_read(oi_socket *socket, const void *base, size_t len) +{ + char buf[200000]; + strncpy(buf, base, len); + buf[len] = 0; + //printf("client got message: %s\n", buf); + + if(strcmp(buf, PONG) == 0) { + + if(++successful_ping_count > EXCHANGES) { + oi_socket_close(socket); + return; + } + oi_socket_write_simple(socket, PING, sizeof PING); + } else { + assert(0); + } +} + +int +main(int argc, const char *argv[]) +{ + int r; + struct ev_loop *loop = ev_default_loop(0); + oi_server server; + oi_socket client; + + //printf("sizeof(oi_server): %d\n", sizeof(oi_server)); + //printf("sizeof(oi_socket): %d\n", sizeof(oi_socket)); + + oi_server_init(&server, 10); + server.on_connection = on_server_connection; + +#if HAVE_GNUTLS +# if SECURE + anon_tls_init(); +# endif +#endif + + struct addrinfo *servinfo; + struct addrinfo hints; + memset(&hints, 0, sizeof hints); +#if TCP + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_PASSIVE; + r = getaddrinfo(NULL, PORT, &hints, &servinfo); + assert(r == 0); +#else + struct stat tstat; + if (lstat(SOCKFILE, &tstat) == 0) { + if (S_ISSOCK(tstat.st_mode)) + unlink(SOCKFILE); + } + + servinfo = malloc(sizeof(struct addrinfo)); + servinfo->ai_family = AF_UNIX; + servinfo->ai_socktype = SOCK_STREAM; + servinfo->ai_protocol = 0; + + struct sockaddr_un *sockaddr = calloc(sizeof(struct sockaddr_un), 1); + sockaddr->sun_family = AF_UNIX; + strcpy(sockaddr->sun_path, SOCKFILE); + + servinfo->ai_addr = (struct sockaddr*)sockaddr; + servinfo->ai_addrlen = sizeof(struct sockaddr_un); +#endif + r = oi_server_listen(&server, servinfo); + assert(r == 0); + oi_server_attach(&server, loop); + + oi_socket_init(&client, 5.0); + client.on_read = on_client_read; + client.on_error = on_client_error; + client.on_connect = on_client_connect; + client.on_close = on_client_close; + client.on_timeout = on_client_timeout; + +#if HAVE_GNUTLS +# if SECURE + anon_tls_client(&client); +# endif +#endif + + r = oi_socket_connect(&client, servinfo); + assert(r == 0 && "problem connecting"); + oi_socket_attach(&client, loop); + + ev_loop(loop, 0); + + assert(successful_ping_count == EXCHANGES + 1); + assert(nconnections == 1); + +#if TCP + freeaddrinfo(servinfo); +#endif + + return 0; +} diff --git a/deps/liboi/test/sleeping_tasks.c b/deps/liboi/test/sleeping_tasks.c new file mode 100644 index 0000000000..d9aeadb799 --- /dev/null +++ b/deps/liboi/test/sleeping_tasks.c @@ -0,0 +1,54 @@ +#include /* sleep() */ +#include /* malloc(), free() */ +#include +#include +#include + +#define SLEEPS 4 +static int runs = 0; + +static void +done (oi_task *task, unsigned int result) +{ + assert(result == 0); + if(++runs == SLEEPS) { + ev_timer *timer = task->data; + ev_timer_stop(task->async->loop, timer); + oi_async_detach(task->async); + } + free(task); +} + +static void +on_timeout(struct ev_loop *loop, ev_timer *w, int events) +{ + assert(0 && "timeout before all sleeping tasks were complete!"); +} + +int +main() +{ + struct ev_loop *loop = ev_default_loop(0); + oi_async async; + ev_timer timer; + int i; + + oi_async_init(&async); + for(i = 0; i < SLEEPS; i++) { + oi_task *task = malloc(sizeof(oi_task)); + oi_task_init_sleep(task, done, 1); + task->data = &timer; + oi_async_submit(&async, task); + } + oi_async_attach(loop, &async); + + + ev_timer_init (&timer, on_timeout, 1.2, 0.); + ev_timer_start (loop, &timer); + + ev_loop(loop, 0); + + assert(runs == SLEEPS); + + return 0; +} diff --git a/deps/liboi/test/stdout.c b/deps/liboi/test/stdout.c new file mode 100644 index 0000000000..1bb2469406 --- /dev/null +++ b/deps/liboi/test/stdout.c @@ -0,0 +1,64 @@ +#include /* sleep() */ +#include /* malloc(), free() */ +#include +#include +#include + +#include +#include +#include + +#include +#include + +static oi_file file; +static oi_file out; + +#define READ_BUFSIZE (5) +static char read_buf[READ_BUFSIZE]; +# define SEP "~~~~~~~~~~~~~~~~~~~~~~\n" + +static void +on_open(oi_file *f) +{ + oi_file_write_simple(&out, "\n", 1); + oi_file_write_simple(&out, SEP, sizeof(SEP)); + oi_file_read_start(f, read_buf, READ_BUFSIZE); +} + +static void +on_close(oi_file *f) +{ + oi_file_write_simple(&out, SEP, sizeof(SEP)); + oi_file_detach(f); + out.on_drain = oi_file_detach; +} + +static void +on_read(oi_file *f, size_t recved) +{ + if(recved == 0) /* EOF */ + oi_file_close(f); + else + oi_file_write_simple(&out, read_buf, recved); +} + +int +main() +{ + struct ev_loop *loop = ev_default_loop(0); + + oi_file_init(&file); + file.on_open = on_open; + file.on_read = on_read; + file.on_close = on_close; + oi_file_open_path(&file, "LICENSE", O_RDONLY, 0); + oi_file_attach(&file, loop); + + oi_file_init(&out); + oi_file_open_stdout(&out); + oi_file_attach(&out, loop); + + ev_loop(loop, 0); + return 0; +} diff --git a/deps/liboi/test/timeout.rb b/deps/liboi/test/timeout.rb new file mode 100755 index 0000000000..dd1dd729ed --- /dev/null +++ b/deps/liboi/test/timeout.rb @@ -0,0 +1,96 @@ +#!/usr/bin/env ruby + +def test(description) + pid = fork do + exec(File.dirname(__FILE__) + "/echo") + end + + begin + sleep 0.5 # give time for the server to start + yield(pid) + rescue + puts "\033[1;31mFAIL\033[m: #{description}" + raise $! + ensure + `kill -9 #{pid}` + end + puts "\033[1;32mPASS\033[m: #{description}" +end + +test("make sure echo server works") do + socket = TCPSocket.open("localhost", 5000) + w = socket.write("hello"); + raise "error" unless w == 5 + + got = socket.recv(5); + raise "error" unless got == "hello" + + socket.close +end + +test("doing nothing should not timeout the server") do |pid| + 10.times do + print "." + STDOUT.flush + if Process.waitpid(pid, Process::WNOHANG) + raise "server died when it shouldn't have" + end + sleep 1 + end + puts "" +end + +test("connecting and doing nothing to should timeout in 5 seconds") do |pid| + socket = TCPSocket.open("localhost", 5000) + i = 0 + 10.times do + print "." + STDOUT.flush + break if Process.waitpid(pid, Process::WNOHANG) + sleep 1 + i+=1 + end + puts "" + raise "died too soon (after #{i} seconds)" if i < 5 + raise "died too late (after #{i} seconds)" if i > 6 +end + + +test("connecting and writing once to should timeout in 5 seconds") do |pid| + socket = TCPSocket.open("localhost", 5000) + w = socket.write("hello"); + raise "error" unless w == 5 + + i = 0 + 10.times do + print "." + STDOUT.flush + break if Process.waitpid(pid, Process::WNOHANG) + sleep 1 + i+=1 + end + puts "" + raise "died too soon (after #{i} seconds)" if i < 5 + raise "died too late (after #{i} seconds)" if i > 6 +end + +test("connecting waiting 3, writing once to should timeout in 8 seconds") do |pid| + socket = TCPSocket.open("localhost", 5000) + + sleep 3 + + w = socket.write("hello"); + raise "error" unless w == 5 + + i = 0 + 10.times do + print "." + STDOUT.flush + break if Process.waitpid(pid, Process::WNOHANG) + sleep 1 + i+=1 + end + puts "" + raise "died too soon (after #{i} seconds)" if i < 5 + raise "died too late (after #{i} seconds)" if i > 6 +end diff --git a/deps/v8/AUTHORS b/deps/v8/AUTHORS new file mode 100644 index 0000000000..060393f645 --- /dev/null +++ b/deps/v8/AUTHORS @@ -0,0 +1,15 @@ +# Below is a list of people and organizations that have contributed +# to the V8 project. Names should be added to the list like so: +# +# Name/Organization + +Google Inc. + +Rene Rebe +Rafal Krypa +Jay Freeman +Daniel James +Paolo Giarrusso +Daniel Andersson +Alexander Botero-Lowry +Matt Hanselman diff --git a/deps/v8/ChangeLog b/deps/v8/ChangeLog new file mode 100644 index 0000000000..d5c30c7f5e --- /dev/null +++ b/deps/v8/ChangeLog @@ -0,0 +1,816 @@ +2009-04-15: Version 1.1.10 + + Fixed crash bug that occurred when loading a const variable in the + presence of eval. + + Allowed using with and eval in registered extensions in debug mode + by fixing bogus assert. + + Fixed the source position for function returns to enable the + debugger to break there. + + +2009-04-14: Version 1.1.9 + + Made the stack traversal code in the profiler robust by avoiding + to look into the heap. + + Added name inferencing for anonymous functions to facilitate + debugging and profiling. + + Re-enabled stats timers in the developer shell (d8). + + Fixed issue 303 by avoiding to shortcut cons-symbols. + + +2009-04-11: Version 1.1.8 + + Changed test-debug/ThreadedDebugging to be non-flaky (issue 96). + + Fixed step-in handling for Function.prototype.apply and call in + the debugger (issue 269). + + Fixed v8::Object::DeleteHiddenValue to not bail out when there + are no hidden properties. + + Added workaround for crash bug, where external symbol table + entries with deleted resources would lead to NPEs when looking + up in the symbol table. + + +2009-04-07: Version 1.1.7 + + Added support for easily importing additional environment + variables into the SCons build. + + Optimized strict equality checks. + + Fixed crash in indexed setters on objects without a corresponding + getter (issue 298). + + Re-enabled script compilation cache. + + +2009-04-01: Version 1.1.6 + + Reverted an unsafe code generator change. + + +2009-04-01: Version 1.1.5 + + Fixed bug that caused function literals to not be optimized as + much as other functions. + + Improved profiler support. + + Fixed a crash bug in connection with debugger unloading. + + Fixed a crash bug in the code generator caused by losing the + information that a frame element was copied. + + Fixed an exception propagation bug that could cause non-null + return values when exceptions were thrown. + + +2009-03-30: Version 1.1.4 + + Optimized String.prototype.match. + + Improved the stack information in profiles. + + Fixed bug in ARM port making it possible to compile the runtime + system for thumb mode again. + + Implemented a number of optimizations in the code generator. + + Fixed a number of memory leaks in tests. + + Fixed crash bug in connection with script source code and external + strings. + + +2009-03-24: Version 1.1.3 + + Fixed assertion failures in compilation of loop conditions. + + Removed STL dependency from developer shell (d8). + + Added infrastructure for protecting the V8 heap from corruption + caused by memory modifications from the outside. + + +2009-03-24: Version 1.1.2 + + Improved frame merge code generated by the code generator. + + Optimized String.prototype.replace. + + Implemented __defineGetter__ and __defineSetter__ for properties + with integer keys on non-array objects. + + Improved debugger and profiler support. + + Fixed a number of portability issues to allow compilation for + smaller ARM devices. + + Exposed object cloning through the API. + + Implemented hidden properties. This is used to expose an identity + hash for objects through the API. + + Implemented restarting of regular expressions if their input + string changes representation during preemption. + + Fixed a code generator bug that could cause assignments in loops + to be ignored if using continue to break out of the loop (issue + 284). + + +2009-03-12: Version 1.1.1 + + Fixed an assertion in the new compiler to take stack overflow + exceptions into account. + + Removed exception propagation code that could cause crashes. + + Fixed minor bug in debugger line number computations. + + 8-byte align the C stack on Linux and Windows to speed up floating + point computations. + + +2009-03-12: Version 1.1.0 + + Improved code generation infrastructure by doing simple register + allocation and constant folding and propagation. + + Optimized regular expression matching by avoiding to create + intermediate string arrays and by flattening nested array + representations of RegExp data. + + Traverse a few stack frames when recording profiler samples to + include partial call graphs in the profiling output. + + Added support for using OProfile to profile generated code. + + Added remote debugging support to the D8 developer shell. + + Optimized creation of nested literals like JSON objects. + + Fixed a bug in garbage collecting unused maps and turned it on by + default (--collect-maps). + + Added support for running tests under Valgrind. + + +2009-02-27: Version 1.0.3 + + Optimized double-to-integer conversions in bit operations by using + SSE3 instructions if available. + + Optimized initialization sequences that store to multiple + properties of the same object. + + Changed the D8 debugger frontend to use JSON messages. + + Force garbage collections when disposing contexts. + + Align code objects at 32-byte boundaries. + + +2009-02-25: Version 1.0.2 + + Improved profiling support by performing simple call stack + sampling for ticks and by fixing a bug in the logging of code + addresses. + + Fixed a number of debugger issues. + + Optimized code that uses eval. + + Fixed a couple of bugs in the regular expression engine. + + Reduced the size of generated code for certain regular expressions. + + Removed JSCRE completely. + + Fixed issue where test could not be run if there was a dot in the + checkout path. + + +2009-02-13: Version 1.0.1 + + Fixed two crash-bugs in irregexp (issue 231 and 233). + + Fixed a number of minor bugs (issue 87, 227 and 228). + + Added support for morphing strings to external strings on demand + to avoid having to create copies in the embedding code. + + Removed experimental support for external symbol callbacks. + + +2009-02-09: Version 1.0.0 + + Fixed crash-bug in the code generation for case independent 16 bit + backreferences. + + Made shells more robust in the presence of string conversion + failures (issue 224). + + Fixed a potential infinite loop when attempting to resolve + eval (issue 221). + + Miscellaneous fixes to the new regular expression engine. + + Reduced binary by stripping unneeded text from JavaScript library and + minifying some JavaScript files. + + +2009-01-27: Version 0.4.9 + + Enabled new regular expression engine. + + Made a number of changes to the debugger protocol. + + Fixed a number of bugs in the preemption support. + + Added -p option to the developer shell to run files in parallel + using preemption. + + Fixed a number of minor bugs (including issues 176, 187, 189, 192, + 193, 198 and 201). + + Fixed a number of bugs in the serialization/deserialization + support for the ARM platform. + + +2009-01-19: Version 0.4.8.1 + + Minor patch to debugger support. + + +2009-01-16: Version 0.4.8 + + Fixed string length bug on ARM (issue 171). + + Made most methods in the API const. + + Optimized object literals by improving data locality. + + Fixed bug that caused incomplete functions to be cached in case of + stack overflow exceptions. + + Fixed bugs that caused catch variables and variables introduced by + eval to behave incorrectly when using accessors (issues 186, 190 + and 191). + + +2009-01-06: Version 0.4.7 + + Minor bugfixes and optimizations. + + Added command line debugger to D8 shell. + + Fixed subtle bug that caused the wrong 'this' to be used when + calling a caught function in a catch clause. + + Inline array loads within loops directly in the code instead of + always calling a stub. + + +2008-12-11: Version 0.4.6 + + Fixed exception reporting bug where certain exceptions were + incorrectly reported as uncaught. + + Improved the memory allocation strategy used during compilation to + make running out of memory when compiling huge scripts less + likely. + + Optimized String.replace by avoiding the construction of certain + sub strings. + + Fixed bug in code generation for large switch statements on ARM. + + Fixed bug that caused V8 to change the global object template + passed in by the user. + + Changed the API for creating object groups used during garbage + collection. Entire object groups are now passed to V8 instead of + individual members of the groups. + + +2008-12-03: Version 0.4.5 + + Added experimental API support for allocating V8 symbols as + external strings. + + Fixed bugs in debugging support on ARM. + + Changed eval implementation to correctly detect whether or not a + call to eval is aliased. + + Fixed bug caused by a combination of the compilation cache and + dictionary probing in native code. The bug caused us to sometimes + call functions that had not yet been compiled. + + Added platform support for FreeBSD. + + Added support for building V8 on Windows with either the shared or + static version of MSVCRT + + Added the v8::jscre namespace around the jscre functions to avoid + link errors (duplicate symbols) when building Google Chrome. + + Added support for calling a JavaScript function with the current + debugger execution context as its argument to the debugger + interface. + + Changed the type of names of counters from wchar_t to char. + + Changed the Windows system call used to compute daylight savings + time. The system call that we used to use became four times + slower on WinXP SP3. + + Added support in the d8 developer shell for memory-mapped counters + and added a stats-viewer tool. + + Fixed bug in upper/lower case mappings (issue 149). + + +2008-11-17: Version 0.4.4 + + Reduced code size by using shorter instruction encoding when + possible. + + Added a --help option to the shell sample and to the d8 shell. + + Added visual studio project files for building the ARM simulator. + + Fixed a number of ARM simulator issues. + + Fixed bug in out-of-memory handling on ARM. + + Implemented shell support for passing arguments to a script from + the command line. + + Fixed bug in date code that made certain date functions return -0 + instead of 0 for dates before the epoch. + + Restricted applications of eval so it can only be used in the + context of the associated global object. + + Treat byte-order marks as whitespace characters. + + +2008-11-04: Version 0.4.3 + + Added support for API accessors that prohibit overwriting by + accessors defined in JavaScript code by using __defineGetter__ and + __defineSetter__. + + Improved handling of conditionals in test status files. + + Introduced access control in propertyIsEnumerable. + + Improved performance of some string operations by caching + information about the type of the string between operations. + + Fixed bug in fast-case code for switch statements that only have + integer labels. + + +2008-10-30: Version 0.4.2 + + Improved performance of Array.prototype.concat by moving the + implementation to C++ (issue 123). + + Fixed heap growth policy to avoid growing old space to its maximum + capacity before doing a garbage collection and fixed issue that + would lead to artificial out of memory situations (issue 129). + + Fixed Date.prototype.toLocaleDateString to return the date in the + same format as WebKit. + + Added missing initialization checks to debugger API. + + Added removing of unused maps during GC. + + +2008-10-28: Version 0.4.1 + + Added caching of RegExp data in compilation cache. + + Added Visual Studio project file for d8 shell. + + Fixed function call performance regression introduced in version + 0.4.0 when splitting the global object in two parts (issue 120). + + Fixed issue 131 by checking for empty handles before throwing and + reporting exceptions. + + +2008-10-23: Version 0.4.0 + + Split the global object into two parts: The state holding global + object and the global object proxy. + + Fixed bug that affected the value of an assignment to an element + in certain cases (issue 116). + + Added GetPropertyNames functionality (issue 33) and extra Date + functions (issue 77) to the API. + + Changed WeakReferenceCallback to take a Persistent instead + of a Persistent (issue 101). + + Fixed issues with message reporting for exceptions in try-finally + blocks (issues 73 and 75). + + Optimized flattening of strings and string equality checking. + + Improved Boyer-Moore implementation for faster indexOf operations. + + Added development shell (d8) which includes counters and + completion support. + + Fixed problem with the receiver passed to functions called from + eval (issue 124). + + +2008-10-16: Version 0.3.5 + + Improved string hash-code distribution by excluding bit-field bits + from the hash-code. + + Changed string search algorithm used in indexOf from KMP to + Boyer-Moore. + + Improved the generated code for the instanceof operator. + + Improved performance of slow-case string equality checks by + specializing the code based on the string representation. + + Improve the handling of out-of-memory situations (issue 70). + + Improved performance of strict equality checks. + + Improved profiler output to make it easier to see anonymous + functions. + + Improved performance of slow-case keyed loads. + + Improved property access performance by allocating a number of + properties in the front object. + + Changed the toString behavior on the built-in object constructors + to print [native code] instead of the actual source. Some web + applications do not like constructors with complex toString + results. + + +2008-10-06: Version 0.3.4 + + Changed Array.prototype.sort to use quick sort. + + Fixed code generation issue where leaving a finally block with + break or continue would accumulate elements on the expression + stack (issue 86). + + Made sure that the name accessor on functions returns the expected + names for builtin JavaScript functions and C++ callback functions. + + Added fast case code for extending the property storage array of + JavaScript objects. + + Ported switch statement optimizations introduced in version 0.3.3 + to the ARM code generator. + + Allowed GCC to use strict-aliasing rules when compiling. + + Improved performance of arguments object allocation by taking care + of arguments adaptor frames in the generated code. + + Updated the V8 benchmark suite to version 2. + + +2008-09-25: Version 0.3.3 + + Improved handling of relocation information to enable more + peep-hole optimizations. + + Optimized switch statements where all labels are constant small + integers. + + Optimized String.prototype.indexOf for common cases. + + Fixed more build issues (issue 80). + + Fixed a couple of profiler issues. + + Fixed bug where the body of a function created using the Function + constructor was not allowed to end with a single-line comment + (issue 85). + + Improved handling of object literals by canonicalizing object + literal maps. This will allow JSON objects with the same set of + properties to share the same map making inline caching work better + for JSON objects. + + +2008-09-17: Version 0.3.2 + + Generalized the EvalCache into a CompilationCache and enabled it + for scripts too. The current strategy is to retire all entries + whenever a mark-sweep collection is started. + + Fixed bug where switch statements containing only a default case + would lead to an unbalanced stack (issue 69). + + Fixed bug that made access to the function in a named function + expression impossible in certain situations (issue 24). + + Fixed even more build issues. + + Optimized calling conventions on ARM. The conventions on ARM and + IA-32 now match. + + Removed static initializers for flags and counters. + + Improved inline caching behavior for uncommon cases where lazily + loading Date and RegExp code could force certain code paths go + megamorphic. + + Removed arguments adaption for builtins written in C++. This + makes Array.prototype.push and Array.prototype.pop slightly + faster. + + +2008-09-11: Version 0.3.1 + + Fixed a number of build issues. + + Fixed problem with missing I-cache flusing on ARM. + + Changed space layout in memory management by splitting up + code space into old data space and code space. + + Added utf-8 conversion support to the API (issue 57). + + Optimized repeated calls to eval with the same strings. These + repeated calls are common in web applications. + + Added Xcode project file. + + Optimized a couple of Array operation. + + Fixed parser bug by checking for end-of-string when parsing break + and continue (issue 35). + + Fixed problem where asian characters were not categorized as + letters. + + Fixed bug that disallowed calling functions fetched from an array + using a string as an array index (issue 32). + + Fixed bug where the internal field count on object templates were + sometimes ignored (issue 54). + + Added -f option to the shell sample for compatibility with other + engines (issue 18). + + Added source info to TryCatches in the API. + + Fixed problem where the seed for the random number generator was + clipped in a double to unsigned int conversion. + + Fixed bug where cons string symbols were sometimes converted to + non-symbol flat strings during GC. + + Fixed bug in error reporting when attempting to convert null to an + object. + + +2008-09-04: Version 0.3.0 + + Added support for running tests on the ARM simulator. + + Fixed bug in the 'in' operator where negative indices were not + treated correctly. + + Fixed build issues on gcc-4.3.1. + + Changed Date.prototype.toLocaleTimeString to not print the + timezone part of the time. + + Renamed debug.h to v8-debug.h to reduce the risk of name conflicts + with user code. + + +2008-09-02: Version 0.2.5 + + Renamed the top level directory 'public' to 'include'. + + Added 'env' option to the SCons build scripts to support + overriding the ENV part of the build environment. This is mostly + to support Windows builds in cases where SCons cannot find the + correct paths to the Windows SDK, as these paths cannot be passed + through shell environment variables. + + Enabled "Buffer Security Check" on for the Windows SCons build and + added the linker option /OPT:ICF as an optimization. + + Added the V8 benchmark suite to the repository. + + +2008-09-01: Version 0.2.4 + + Included mjsunit JavaScript test suite and C++ unit tests. + + Changed the shell sample to not print the result of executing a + script provided on the command line. + + Fixed issue when building samples on Windows using a shared V8 + library. Added visibility option on Linux build which makes the + generated library 18% smaller. + + Changed build system to accept multiple build modes in one build + and generate separate objects, libraries and executables for each + mode. + + Removed deferred negation optimization (a * -b => -(a * b)) since + this visibly changes operand conversion order. + + Improved parsing performance by introducing stack guard in + preparsing. Without a stack guard preparsing always bails out + with stack overflow. + + Changed shell sample to take flags directly from the command-line. + Added API call that implements this. + + Added load, quit and version functions to the shell sample so it's + easier to run benchmarks and tests. + + Fixed issue with building samples and cctests on 64-bit machines. + + Fixed bug in the runtime system where the prototype chain was not + always searched for a setter when setting a property that does not + exist locally. + + +2008-08-14: Version 0.2.3 + + Improved performance of garbage collection by moving the + function that updates pointers during compacting collection + into the updating visitor. This gives the compiler a better + chance to inline and avoid a function call per (potential) + pointer. + + Extended the shell sample with a --runtime-flags option. + + Added Visual Studio project files for the shell.cc and + process.cc samples. + + +2008-08-13: Version 0.2.2 + + Improved performance of garbage collection by changing the way + we use the marking stack in the event of stack overflow during + full garbage collection and by changing the way we mark roots. + + Cleaned up ARM version by removing top of stack caching and by + introducing push/pop elimination. + + Cleaned up the way runtime functions are called to allow + runtime calls with no arguments. + + Changed Windows build options to make sure that exceptions are + disabled and that optimization flags are enabled. + + Added first version of Visual Studio project files. + + +2008-08-06: Version 0.2.1 + + Improved performance of unary addition by avoiding runtime calls. + + Fixed the handling of '>' and '<=' to use right-to-left conversion + and left-to-right evaluation as specified by ECMA-262. + + Fixed a branch elimination bug on the ARM platform where incorrect + code was generated because of overly aggressive branch + elimination. + + Improved performance of code that repeatedly assigns the same + function to the same property of different objects with the same + map. + + Untangled DEBUG and ENABLE_DISASSEMBLER defines. The disassembler + no longer expects DEBUG to be defined. + + Added platform-nullos.cc to serve as the basis for new platform + implementations. + + +2008-07-30: Version 0.2.0 + + Changed all text files to have native svn:eol-style. + + Added a few samples and support for building them. The samples + include a simple shell that can be used to benchmark and test V8. + + Changed V8::GetVersion to return the version as a string. + + Added source for lazily loaded scripts to snapshots and made + serialization non-destructive. + + Improved ARM support by fixing the write barrier code to use + aligned loads and stores and by removing premature locals + optimization that relied on broken support for callee-saved + registers (removed). + + Refactored the code for marking live objects during garbage + collection and the code for allocating objects in paged + spaces. Introduced an abstraction for the map word of a heap- + allocated object and changed the memory allocator to allocate + executable memory only for spaces that may contain code objects. + + Moved StringBuilder to utils.h and ScopedLock to platform.h, where + they can be used by debugging and logging modules. Added + thread-safe message queues for dealing with debugger events. + + Fixed the source code reported by toString for certain builtin + empty functions and made sure that the prototype property of a + function is enumerable. + + Improved performance of converting values to condition flags in + generated code. + + Merged disassembler-{arch} files. + + +2008-07-28: Version 0.1.4 + + Added support for storing JavaScript stack traces in a stack + allocated buffer to make it visible in shallow core dumps. + Controlled by the --preallocate-message-memory flag which is + disabled by default. + + +2008-07-25: Version 0.1.3 + + Fixed bug in JSObject::GetPropertyAttributePostInterceptor where + map transitions would count as properties. + + Allowed aliased eval invocations by treating them as evals in the + global context. This may change in the future. + + Added support for accessing the last entered context through the + API and renamed Context::Current to Context::GetCurrent and + Context::GetSecurityContext to Context::GetCurrentSecurityContext. + + Fixed bug in the debugger that would cause the debugger scripts to + be recursively loaded and changed all disabling of interrupts to + be block-structured. + + Made snapshot data read-only to allow it to be more easily shared + across multiple users of V8 when linked as a shared library. + + +2008-07-16: Version 0.1.2 + + Fixed building on Mac OS X by recognizing i386 and friends as + IA-32 platforms. + + Added propagation of stack overflow exceptions that occur while + compiling nested functions. + + Improved debugger with support for recursive break points and + handling of exceptions that occur in the debugger JavaScript code. + + Renamed GetInternal to GetInternalField and SetInternal to + SetInternalField in the API and moved InternalFieldCount and + SetInternalFieldCount from FunctionTemplate to ObjectTemplate. + + +2008-07-09: Version 0.1.1 + + Fixed bug in stack overflow check code for IA-32 targets where a + non-tagged value in register eax was pushed to the stack. + + Fixed potential quadratic behavior when converting strings to + numbers. + + Fixed bug where the return value from Object::SetProperty could + end up being the property holder instead of the written value. + + Improved debugger support by allowing nested break points and by + dealing with stack-overflows when compiling functions before + setting break points in them. + + +2008-07-03: Version 0.1.0 + + Initial export. + diff --git a/deps/v8/LICENSE b/deps/v8/LICENSE new file mode 100644 index 0000000000..7301556f77 --- /dev/null +++ b/deps/v8/LICENSE @@ -0,0 +1,51 @@ +This license applies to all parts of V8 that are not externally +maintained libraries. The externally maintained libraries used by V8 +are: + + - PCRE test suite, located in test/mjsunit/regexp-pcre.js. This is + based on the test suite from PCRE-7.3, which is copyrighted by the + University of Cambridge and Google, Inc. The copyright notice and + license are embedded in regexp-pcre.js. + + - Dtoa, located under third_party/dtoa. This code is copyrighted by + David M. Gay and released under an MIT license. + + - Strongtalk assembler, the basis of the files assembler-arm-inl.h, + assembler-arm.cc, assembler-arm.h, assembler-ia32-inl.h, + assembler-ia32.cc, assembler-ia32.h, assembler.cc and assembler.h. + This code is copyrighted by Sun Microsystems Inc. and released + under a 3-clause BSD license. + + - JSMin JavaScript minifier, located at tools/jsmin.py. This code is + copyrighted by Douglas Crockford and Baruch Even and released under + an MIT license. + +These libraries have their own licenses; we recommend you read them, +as their terms may differ from the terms below. + +Copyright 2006-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/deps/v8/SConstruct b/deps/v8/SConstruct new file mode 100644 index 0000000000..01083cc5d6 --- /dev/null +++ b/deps/v8/SConstruct @@ -0,0 +1,775 @@ +# Copyright 2008 the V8 project 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. + +import platform +import re +import sys +import os +from os.path import join, dirname, abspath +from types import DictType, StringTypes +root_dir = dirname(File('SConstruct').rfile().abspath) +sys.path.append(join(root_dir, 'tools')) +import js2c, utils + +# ANDROID_TOP is the top of the Android checkout, fetched from the environment +# variable 'TOP'. You will also need to set the CXX, CC, AR and RANLIB +# environment variables to the cross-compiling tools. +ANDROID_TOP = os.environ.get('TOP') +if ANDROID_TOP is None: + ANDROID_TOP="" + +ANDROID_FLAGS = ['-march=armv5te', + '-mtune=xscale', + '-msoft-float', + '-fpic', + '-mthumb-interwork', + '-funwind-tables', + '-fstack-protector', + '-fno-short-enums', + '-fmessage-length=0', + '-finline-functions', + '-fno-inline-functions-called-once', + '-fgcse-after-reload', + '-frerun-cse-after-loop', + '-frename-registers', + '-fomit-frame-pointer', + '-fno-strict-aliasing', + '-finline-limit=64', + '-MD'] + +ANDROID_INCLUDES = [ANDROID_TOP + '/bionic/libc/arch-arm/include', + ANDROID_TOP + '/bionic/libc/include', + ANDROID_TOP + '/bionic/libstdc++/include', + ANDROID_TOP + '/bionic/libc/kernel/common', + ANDROID_TOP + '/bionic/libc/kernel/arch-arm', + ANDROID_TOP + '/bionic/libm/include', + ANDROID_TOP + '/bionic/libm/include/arch/arm', + ANDROID_TOP + '/bionic/libthread_db/include'] + +ANDROID_LINKFLAGS = ['-nostdlib', + '-Bdynamic', + '-Wl,-T,' + ANDROID_TOP + '/build/core/armelf.x', + '-Wl,-dynamic-linker,/system/bin/linker', + '-Wl,--gc-sections', + '-Wl,-z,nocopyreloc', + '-Wl,-rpath-link=' + ANDROID_TOP + '/out/target/product/generic/obj/lib', + ANDROID_TOP + '/out/target/product/generic/obj/lib/crtbegin_dynamic.o', + ANDROID_TOP + '/prebuilt/linux-x86/toolchain/arm-eabi-4.2.1/lib/gcc/arm-eabi/4.2.1/interwork/libgcc.a', + ANDROID_TOP + '/out/target/product/generic/obj/lib/crtend_android.o']; + +LIBRARY_FLAGS = { + 'all': { + 'CPPDEFINES': ['ENABLE_LOGGING_AND_PROFILING'] + }, + 'gcc': { + 'all': { + 'CCFLAGS': ['$DIALECTFLAGS', '$WARNINGFLAGS'], + 'CXXFLAGS': ['$CCFLAGS', '-fno-rtti', '-fno-exceptions'], + }, + 'mode:debug': { + 'CCFLAGS': ['-g', '-O0'], + 'CPPDEFINES': ['ENABLE_DISASSEMBLER', 'DEBUG'], + 'os:android': { + 'CCFLAGS': ['-mthumb'] + } + }, + 'mode:release': { + 'CCFLAGS': ['-O3', '-fomit-frame-pointer', '-fdata-sections', + '-ffunction-sections'], + 'os:android': { + 'CCFLAGS': ['-mthumb', '-Os'], + 'CPPDEFINES': ['SK_RELEASE', 'NDEBUG'] + } + }, + 'os:linux': { + 'CCFLAGS': ['-ansi'], + 'library:shared': { + 'LIBS': ['pthread', 'rt'] + } + }, + 'os:macos': { + 'CCFLAGS': ['-ansi'], + }, + 'os:freebsd': { + 'CCFLAGS': ['-ansi'], + }, + 'os:win32': { + 'CCFLAGS': ['-DWIN32'], + 'CXXFLAGS': ['-DWIN32'], + }, + 'os:android': { + 'CPPDEFINES': ['ANDROID', '__ARM_ARCH_5__', '__ARM_ARCH_5T__', + '__ARM_ARCH_5E__', '__ARM_ARCH_5TE__'], + 'CCFLAGS': ANDROID_FLAGS, + 'WARNINGFLAGS': ['-Wall', '-Wno-unused', '-Werror=return-type', + '-Wstrict-aliasing=2'], + 'CPPPATH': ANDROID_INCLUDES, + }, + 'wordsize:64': { + 'CCFLAGS': ['-m32'], + 'LINKFLAGS': ['-m32'] + }, + 'prof:oprofile': { + 'CPPDEFINES': ['ENABLE_OPROFILE_AGENT'] + } + }, + 'msvc': { + 'all': { + 'DIALECTFLAGS': ['/nologo'], + 'CCFLAGS': ['$DIALECTFLAGS', '$WARNINGFLAGS'], + 'CXXFLAGS': ['$CCFLAGS', '/GR-', '/Gy'], + 'CPPDEFINES': ['WIN32', '_USE_32BIT_TIME_T'], + 'LINKFLAGS': ['/NOLOGO', '/MACHINE:X86', '/INCREMENTAL:NO', + '/NXCOMPAT', '/IGNORE:4221'], + 'ARFLAGS': ['/NOLOGO'], + 'CCPDBFLAGS': ['/Zi'] + }, + 'mode:debug': { + 'CCFLAGS': ['/Od', '/Gm'], + 'CPPDEFINES': ['_DEBUG', 'ENABLE_DISASSEMBLER', 'DEBUG'], + 'LINKFLAGS': ['/DEBUG'], + 'msvcrt:static': { + 'CCFLAGS': ['/MTd'] + }, + 'msvcrt:shared': { + 'CCFLAGS': ['/MDd'] + } + }, + 'mode:release': { + 'CCFLAGS': ['/O2', '/GL'], + 'LINKFLAGS': ['/OPT:REF', '/OPT:ICF', '/LTCG'], + 'ARFLAGS': ['/LTCG'], + 'msvcrt:static': { + 'CCFLAGS': ['/MT'] + }, + 'msvcrt:shared': { + 'CCFLAGS': ['/MD'] + } + }, + } +} + + +V8_EXTRA_FLAGS = { + 'gcc': { + 'all': { + 'CXXFLAGS': [], #['-fvisibility=hidden'], + 'WARNINGFLAGS': ['-Wall', '-Werror', '-W', + '-Wno-unused-parameter'] + }, + 'arch:arm': { + 'CPPDEFINES': ['ARM'] + }, + 'arch:android': { + 'CPPDEFINES': ['ARM'] + }, + 'os:win32': { + 'WARNINGFLAGS': ['-pedantic', '-Wno-long-long'] + }, + 'os:linux': { + 'WARNINGFLAGS': ['-pedantic'] + }, + 'os:macos': { + 'WARNINGFLAGS': ['-pedantic'] + }, + 'disassembler:on': { + 'CPPDEFINES': ['ENABLE_DISASSEMBLER'] + } + }, + 'msvc': { + 'all': { + 'WARNINGFLAGS': ['/W3', '/WX', '/wd4355', '/wd4800'] + }, + 'library:shared': { + 'CPPDEFINES': ['BUILDING_V8_SHARED'], + 'LIBS': ['winmm', 'ws2_32'] + }, + 'arch:arm': { + 'CPPDEFINES': ['ARM'], + # /wd4996 is to silence the warning about sscanf + # used by the arm simulator. + 'WARNINGFLAGS': ['/wd4996'] + }, + 'disassembler:on': { + 'CPPDEFINES': ['ENABLE_DISASSEMBLER'] + } + } +} + + +MKSNAPSHOT_EXTRA_FLAGS = { + 'gcc': { + 'os:linux': { + 'LIBS': ['pthread', 'rt'], + }, + 'os:macos': { + 'LIBS': ['pthread'], + }, + 'os:freebsd': { + 'LIBS': ['pthread'], + }, + 'os:win32': { + 'LIBS': ['winmm', 'ws2_32'], + }, + }, + 'msvc': { + 'all': { + 'LIBS': ['winmm', 'ws2_32'] + } + } +} + + +DTOA_EXTRA_FLAGS = { + 'gcc': { + 'all': { + 'WARNINGFLAGS': ['-Werror', '-Wno-uninitialized'] + } + }, + 'msvc': { + 'all': { + 'WARNINGFLAGS': ['/WX', '/wd4018', '/wd4244'] + } + } +} + + +CCTEST_EXTRA_FLAGS = { + 'all': { + 'CPPPATH': [join(root_dir, 'src')], + 'LIBS': ['$LIBRARY'] + }, + 'gcc': { + 'all': { + 'LIBPATH': [abspath('.')] + }, + 'os:linux': { + 'LIBS': ['pthread', 'rt'], + }, + 'os:macos': { + 'LIBS': ['pthread'], + }, + 'os:freebsd': { + 'LIBS': ['execinfo', 'pthread'] + }, + 'os:win32': { + 'LIBS': ['winmm', 'ws2_32'] + }, + 'wordsize:64': { + 'CCFLAGS': ['-m32'], + 'LINKFLAGS': ['-m32'] + }, + }, + 'msvc': { + 'all': { + 'CPPDEFINES': ['_HAS_EXCEPTIONS=0'], + 'LIBS': ['winmm', 'ws2_32'] + }, + 'library:shared': { + 'CPPDEFINES': ['USING_V8_SHARED'] + } + } +} + + +SAMPLE_FLAGS = { + 'all': { + 'CPPPATH': [join(abspath('.'), 'include')], + 'LIBS': ['$LIBRARY'], + }, + 'gcc': { + 'all': { + 'LIBPATH': ['.'], + 'CCFLAGS': ['-fno-rtti', '-fno-exceptions'] + }, + 'os:linux': { + 'LIBS': ['pthread', 'rt'], + }, + 'os:macos': { + 'LIBS': ['pthread'], + }, + 'os:freebsd': { + 'LIBS': ['execinfo', 'pthread'] + }, + 'os:win32': { + 'LIBS': ['winmm', 'ws2_32'] + }, + 'os:android': { + 'CPPDEFINES': ['ANDROID', '__ARM_ARCH_5__', '__ARM_ARCH_5T__', + '__ARM_ARCH_5E__', '__ARM_ARCH_5TE__'], + 'CCFLAGS': ANDROID_FLAGS, + 'CPPPATH': ANDROID_INCLUDES, + 'LIBPATH': [ANDROID_TOP + '/out/target/product/generic/obj/lib'], + 'LINKFLAGS': ANDROID_LINKFLAGS, + 'LIBS': ['c', 'stdc++', 'm'], + 'mode:release': { + 'CPPDEFINES': ['SK_RELEASE', 'NDEBUG'] + } + }, + 'wordsize:64': { + 'CCFLAGS': ['-m32'], + 'LINKFLAGS': ['-m32'] + }, + 'mode:release': { + 'CCFLAGS': ['-O2'] + }, + 'mode:debug': { + 'CCFLAGS': ['-g', '-O0'] + }, + 'prof:oprofile': { + 'LIBPATH': ['/usr/lib32', '/usr/lib32/oprofile'], + 'LIBS': ['opagent'] + } + }, + 'msvc': { + 'all': { + 'CCFLAGS': ['/nologo'], + 'LINKFLAGS': ['/nologo'], + 'LIBS': ['winmm', 'ws2_32'] + }, + 'library:shared': { + 'CPPDEFINES': ['USING_V8_SHARED'] + }, + 'prof:on': { + 'LINKFLAGS': ['/MAP'] + }, + 'mode:release': { + 'CCFLAGS': ['/O2'], + 'LINKFLAGS': ['/OPT:REF', '/OPT:ICF', '/LTCG'], + 'msvcrt:static': { + 'CCFLAGS': ['/MT'] + }, + 'msvcrt:shared': { + 'CCFLAGS': ['/MD'] + } + }, + 'mode:debug': { + 'CCFLAGS': ['/Od'], + 'LINKFLAGS': ['/DEBUG'], + 'msvcrt:static': { + 'CCFLAGS': ['/MTd'] + }, + 'msvcrt:shared': { + 'CCFLAGS': ['/MDd'] + } + } + } +} + + +D8_FLAGS = { + 'gcc': { + 'console:readline': { + 'LIBS': ['readline'] + }, + 'os:linux': { + 'LIBS': ['pthread', 'rt'], + }, + 'os:macos': { + 'LIBS': ['pthread'], + }, + 'os:freebsd': { + 'LIBS': ['pthread'], + }, + 'os:android': { + 'LIBPATH': [ANDROID_TOP + '/out/target/product/generic/obj/lib'], + 'LINKFLAGS': ANDROID_LINKFLAGS, + 'LIBS': ['c', 'stdc++', 'm'], + }, + 'os:win32': { + 'LIBS': ['winmm', 'ws2_32'], + }, + }, + 'msvc': { + 'all': { + 'LIBS': ['winmm', 'ws2_32'] + } + } +} + + +SUFFIXES = { + 'release': '', + 'debug': '_g' +} + + +def Abort(message): + print message + sys.exit(1) + + +def GuessToolchain(os): + tools = Environment()['TOOLS'] + if 'gcc' in tools: + return 'gcc' + elif 'msvc' in tools: + return 'msvc' + else: + return None + + +OS_GUESS = utils.GuessOS() +TOOLCHAIN_GUESS = GuessToolchain(OS_GUESS) +ARCH_GUESS = utils.GuessArchitecture() +WORDSIZE_GUESS = utils.GuessWordsize() + + +SIMPLE_OPTIONS = { + 'toolchain': { + 'values': ['gcc', 'msvc'], + 'default': TOOLCHAIN_GUESS, + 'help': 'the toolchain to use' + }, + 'os': { + 'values': ['freebsd', 'linux', 'macos', 'win32', 'android'], + 'default': OS_GUESS, + 'help': 'the os to build for' + }, + 'arch': { + 'values':['arm', 'ia32'], + 'default': ARCH_GUESS, + 'help': 'the architecture to build for' + }, + 'snapshot': { + 'values': ['on', 'off', 'nobuild'], + 'default': 'off', + 'help': 'build using snapshots for faster start-up' + }, + 'prof': { + 'values': ['on', 'off', 'oprofile'], + 'default': 'off', + 'help': 'enable profiling of build target' + }, + 'library': { + 'values': ['static', 'shared'], + 'default': 'static', + 'help': 'the type of library to produce' + }, + 'msvcrt': { + 'values': ['static', 'shared'], + 'default': 'static', + 'help': 'the type of MSVCRT library to use' + }, + 'wordsize': { + 'values': ['64', '32'], + 'default': WORDSIZE_GUESS, + 'help': 'the word size' + }, + 'simulator': { + 'values': ['arm', 'none'], + 'default': 'none', + 'help': 'build with simulator' + }, + 'disassembler': { + 'values': ['on', 'off'], + 'default': 'off', + 'help': 'enable the disassembler to inspect generated code' + }, + 'sourcesignatures': { + 'values': ['MD5', 'timestamp'], + 'default': 'MD5', + 'help': 'set how the build system detects file changes' + }, + 'console': { + 'values': ['dumb', 'readline'], + 'default': 'dumb', + 'help': 'the console to use for the d8 shell' + } +} + + +def GetOptions(): + result = Options() + result.Add('mode', 'compilation mode (debug, release)', 'release') + result.Add('sample', 'build sample (shell, process)', '') + result.Add('env', 'override environment settings (NAME0:value0,NAME1:value1,...)', '') + result.Add('importenv', 'import environment settings (NAME0,NAME1,...)', '') + for (name, option) in SIMPLE_OPTIONS.iteritems(): + help = '%s (%s)' % (name, ", ".join(option['values'])) + result.Add(name, help, option.get('default')) + return result + + +def SplitList(str): + return [ s for s in str.split(",") if len(s) > 0 ] + + +def IsLegal(env, option, values): + str = env[option] + for s in SplitList(str): + if not s in values: + Abort("Illegal value for option %s '%s'." % (option, s)) + return False + return True + + +def VerifyOptions(env): + if not IsLegal(env, 'mode', ['debug', 'release']): + return False + if not IsLegal(env, 'sample', ["shell", "process"]): + return False + if env['os'] == 'win32' and env['library'] == 'shared' and env['prof'] == 'on': + Abort("Profiling on windows only supported for static library.") + if env['prof'] == 'oprofile' and env['os'] != 'linux': + Abort("OProfile is only supported on Linux.") + for (name, option) in SIMPLE_OPTIONS.iteritems(): + if (not option.get('default')) and (name not in ARGUMENTS): + message = ("A value for option %s must be specified (%s)." % + (name, ", ".join(option['values']))) + Abort(message) + if not env[name] in option['values']: + message = ("Unknown %s value '%s'. Possible values are (%s)." % + (name, env[name], ", ".join(option['values']))) + Abort(message) + + +class BuildContext(object): + + def __init__(self, options, env_overrides, samples): + self.library_targets = [] + self.mksnapshot_targets = [] + self.cctest_targets = [] + self.sample_targets = [] + self.d8_targets = [] + self.options = options + self.env_overrides = env_overrides + self.samples = samples + self.use_snapshot = (options['snapshot'] != 'off') + self.build_snapshot = (options['snapshot'] == 'on') + self.flags = None + + def AddRelevantFlags(self, initial, flags): + result = initial.copy() + self.AppendFlags(result, flags.get('all')) + toolchain = self.options['toolchain'] + if toolchain in flags: + self.AppendFlags(result, flags[toolchain].get('all')) + for option in sorted(self.options.keys()): + value = self.options[option] + self.AppendFlags(result, flags[toolchain].get(option + ':' + value)) + return result + + def AddRelevantSubFlags(self, options, flags): + self.AppendFlags(options, flags.get('all')) + for option in sorted(self.options.keys()): + value = self.options[option] + self.AppendFlags(options, flags.get(option + ':' + value)) + + def GetRelevantSources(self, source): + result = [] + result += source.get('all', []) + for (name, value) in self.options.iteritems(): + result += source.get(name + ':' + value, []) + return sorted(result) + + def AppendFlags(self, options, added): + if not added: + return + for (key, value) in added.iteritems(): + if key.find(':') != -1: + self.AddRelevantSubFlags(options, { key: value }) + else: + if not key in options: + options[key] = value + else: + prefix = options[key] + if isinstance(prefix, StringTypes): prefix = prefix.split() + options[key] = prefix + value + + def ConfigureObject(self, env, input, **kw): + if (kw.has_key('CPPPATH') and env.has_key('CPPPATH')): + kw['CPPPATH'] += env['CPPPATH'] + if self.options['library'] == 'static': + return env.StaticObject(input, **kw) + else: + return env.SharedObject(input, **kw) + + def ApplyEnvOverrides(self, env): + if not self.env_overrides: + return + if type(env['ENV']) == DictType: + env['ENV'].update(**self.env_overrides) + else: + env['ENV'] = self.env_overrides + + +def PostprocessOptions(options): + # Adjust architecture if the simulator option has been set + if (options['simulator'] != 'none') and (options['arch'] != options['simulator']): + if 'arch' in ARGUMENTS: + # Print a warning if arch has explicitly been set + print "Warning: forcing architecture to match simulator (%s)" % options['simulator'] + options['arch'] = options['simulator'] + + +def ParseEnvOverrides(arg, imports): + # The environment overrides are in the format NAME0:value0,NAME1:value1,... + # The environment imports are in the format NAME0,NAME1,... + overrides = {} + for var in imports.split(','): + if var in os.environ: + overrides[var] = os.environ[var] + for override in arg.split(','): + pos = override.find(':') + if pos == -1: + continue + overrides[override[:pos].strip()] = override[pos+1:].strip() + return overrides + + +def BuildSpecific(env, mode, env_overrides): + options = {'mode': mode} + for option in SIMPLE_OPTIONS: + options[option] = env[option] + PostprocessOptions(options) + + context = BuildContext(options, env_overrides, samples=SplitList(env['sample'])) + + library_flags = context.AddRelevantFlags(os.environ, LIBRARY_FLAGS) + v8_flags = context.AddRelevantFlags(library_flags, V8_EXTRA_FLAGS) + mksnapshot_flags = context.AddRelevantFlags(library_flags, MKSNAPSHOT_EXTRA_FLAGS) + dtoa_flags = context.AddRelevantFlags(library_flags, DTOA_EXTRA_FLAGS) + cctest_flags = context.AddRelevantFlags(v8_flags, CCTEST_EXTRA_FLAGS) + sample_flags = context.AddRelevantFlags(os.environ, SAMPLE_FLAGS) + d8_flags = context.AddRelevantFlags(library_flags, D8_FLAGS) + + context.flags = { + 'v8': v8_flags, + 'mksnapshot': mksnapshot_flags, + 'dtoa': dtoa_flags, + 'cctest': cctest_flags, + 'sample': sample_flags, + 'd8': d8_flags + } + + target_id = mode + suffix = SUFFIXES[target_id] + library_name = 'v8' + suffix + env['LIBRARY'] = library_name + + # Build the object files by invoking SCons recursively. + (object_files, shell_files, mksnapshot) = env.SConscript( + join('src', 'SConscript'), + build_dir=join('obj', target_id), + exports='context', + duplicate=False + ) + + context.mksnapshot_targets.append(mksnapshot) + + # Link the object files into a library. + env.Replace(**context.flags['v8']) + context.ApplyEnvOverrides(env) + if context.options['library'] == 'static': + library = env.StaticLibrary(library_name, object_files) + else: + # There seems to be a glitch in the way scons decides where to put + # PDB files when compiling using MSVC so we specify it manually. + # This should not affect any other platforms. + pdb_name = library_name + '.dll.pdb' + library = env.SharedLibrary(library_name, object_files, PDB=pdb_name) + context.library_targets.append(library) + + d8_env = Environment() + d8_env.Replace(**context.flags['d8']) + shell = d8_env.Program('d8' + suffix, object_files + shell_files) + context.d8_targets.append(shell) + + for sample in context.samples: + sample_env = Environment(LIBRARY=library_name) + sample_env.Replace(**context.flags['sample']) + context.ApplyEnvOverrides(sample_env) + sample_object = sample_env.SConscript( + join('samples', 'SConscript'), + build_dir=join('obj', 'sample', sample, target_id), + exports='sample context', + duplicate=False + ) + sample_name = sample + suffix + sample_program = sample_env.Program(sample_name, sample_object) + sample_env.Depends(sample_program, library) + context.sample_targets.append(sample_program) + + cctest_program = env.SConscript( + join('test', 'cctest', 'SConscript'), + build_dir=join('obj', 'test', target_id), + exports='context object_files', + duplicate=False + ) + context.cctest_targets.append(cctest_program) + + return context + + +def Build(): + opts = GetOptions() + env = Environment(options=opts) + Help(opts.GenerateHelpText(env)) + VerifyOptions(env) + env_overrides = ParseEnvOverrides(env['env'], env['importenv']) + + SourceSignatures(env['sourcesignatures']) + + libraries = [] + mksnapshots = [] + cctests = [] + samples = [] + d8s = [] + modes = SplitList(env['mode']) + for mode in modes: + context = BuildSpecific(env.Copy(), mode, env_overrides) + libraries += context.library_targets + mksnapshots += context.mksnapshot_targets + cctests += context.cctest_targets + samples += context.sample_targets + d8s += context.d8_targets + + env.Alias('library', libraries) + env.Alias('mksnapshot', mksnapshots) + env.Alias('cctests', cctests) + env.Alias('sample', samples) + env.Alias('d8', d8s) + + if env['sample']: + env.Default('sample') + else: + env.Default('library') + + +# We disable deprecation warnings because we need to be able to use +# env.Copy without getting warnings for compatibility with older +# version of scons. Also, there's a bug in some revisions that +# doesn't allow this flag to be set, so we swallow any exceptions. +# Lovely. +try: + SetOption('warn', 'no-deprecated') +except: + pass + + +Build() diff --git a/deps/v8/benchmarks/README.txt b/deps/v8/benchmarks/README.txt new file mode 100644 index 0000000000..46aa57328c --- /dev/null +++ b/deps/v8/benchmarks/README.txt @@ -0,0 +1,42 @@ +V8 Benchmark Suite +================== + +This is the V8 benchmark suite: A collection of pure JavaScript +benchmarks that we have used to tune V8. The licenses for the +individual benchmarks are included in the JavaScript files. + +In addition to the benchmarks, the suite consists of the benchmark +framework (base.js), which must be loaded before any of the individual +benchmark files, and two benchmark runners: An HTML version (run.html) +and a standalone JavaScript version (run.js). + + +Changes From Version 1 To Version 2 +=================================== + +For version 2 the crypto benchmark was fixed. Previously, the +decryption stage was given plaintext as input, which resulted in an +error. Now, the decryption stage is given the output of the +encryption stage as input. The result is checked against the original +plaintext. For this to give the correct results the crypto objects +are reset for each iteration of the benchmark. In addition, the size +of the plain text has been increased a little and the use of +Math.random() and new Date() to build an RNG pool has been removed. + +Other benchmarks were fixed to do elementary verification of the +results of their calculations. This is to avoid accidentally +obtaining scores that are the result of an incorrect JavaScript engine +optimization. + + +Changes From Version 2 To Version 3 +=================================== + +Version 3 adds a new benchmark, RegExp. The RegExp benchmark is +generated by loading 50 of the most popular pages on the web and +logging all regexp operations performed. Each operation is given a +weight that is calculated from an estimate of the popularity of the +pages where it occurs and the number of times it is executed while +loading each page. Finally the literal letters in the data are +encoded using ROT13 in a way that does not affect how the regexps +match their input. diff --git a/deps/v8/benchmarks/base.js b/deps/v8/benchmarks/base.js new file mode 100644 index 0000000000..261733208c --- /dev/null +++ b/deps/v8/benchmarks/base.js @@ -0,0 +1,233 @@ +// Copyright 2008 the V8 project 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. + + +// Simple framework for running the benchmark suites and +// computing a score based on the timing measurements. + + +// A benchmark has a name (string) and a function that will be run to +// do the performance measurement. +function Benchmark(name, run) { + this.name = name; + this.run = run; +} + + +// Benchmark results hold the benchmark and the measured time used to +// run the benchmark. The benchmark score is computed later once a +// full benchmark suite has run to completion. +function BenchmarkResult(benchmark, time) { + this.benchmark = benchmark; + this.time = time; +} + + +// Automatically convert results to numbers. Used by the geometric +// mean computation. +BenchmarkResult.prototype.valueOf = function() { + return this.time; +} + + +// Suites of benchmarks consist of a name and the set of benchmarks in +// addition to the reference timing that the final score will be based +// on. This way, all scores are relative to a reference run and higher +// scores implies better performance. +function BenchmarkSuite(name, reference, benchmarks) { + this.name = name; + this.reference = reference; + this.benchmarks = benchmarks; + BenchmarkSuite.suites.push(this); +} + + +// Keep track of all declared benchmark suites. +BenchmarkSuite.suites = []; + + +// Scores are not comparable across versions. Bump the version if +// you're making changes that will affect that scores, e.g. if you add +// a new benchmark or change an existing one. +BenchmarkSuite.version = '3'; + + +// To make the benchmark results predictable, we replace Math.random +// with a 100% deterministic alternative. +Math.random = (function() { + var seed = 49734321; + return function() { + // Robert Jenkins' 32 bit integer hash function. + seed = ((seed + 0x7ed55d16) + (seed << 12)) & 0xffffffff; + seed = ((seed ^ 0xc761c23c) ^ (seed >>> 19)) & 0xffffffff; + seed = ((seed + 0x165667b1) + (seed << 5)) & 0xffffffff; + seed = ((seed + 0xd3a2646c) ^ (seed << 9)) & 0xffffffff; + seed = ((seed + 0xd3a2646c) ^ (seed << 9)) & 0xffffffff; + seed = ((seed + 0xfd7046c5) + (seed << 3)) & 0xffffffff; + seed = ((seed ^ 0xb55a4f09) ^ (seed >>> 16)) & 0xffffffff; + return (seed & 0xfffffff) / 0x10000000; + }; +})(); + + +// Runs all registered benchmark suites and optionally yields between +// each individual benchmark to avoid running for too long in the +// context of browsers. Once done, the final score is reported to the +// runner. +BenchmarkSuite.RunSuites = function(runner) { + var continuation = null; + var suites = BenchmarkSuite.suites; + var length = suites.length; + BenchmarkSuite.scores = []; + var index = 0; + function RunStep() { + while (continuation || index < length) { + if (continuation) { + continuation = continuation(); + } else { + var suite = suites[index++]; + if (runner.NotifyStart) runner.NotifyStart(suite.name); + continuation = suite.RunStep(runner); + } + if (continuation && typeof window != 'undefined' && window.setTimeout) { + window.setTimeout(RunStep, 100); + return; + } + } + if (runner.NotifyScore) { + var score = BenchmarkSuite.GeometricMean(BenchmarkSuite.scores); + var formatted = BenchmarkSuite.FormatScore(100 * score); + runner.NotifyScore(formatted); + } + } + RunStep(); +} + + +// Counts the total number of registered benchmarks. Useful for +// showing progress as a percentage. +BenchmarkSuite.CountBenchmarks = function() { + var result = 0; + var suites = BenchmarkSuite.suites; + for (var i = 0; i < suites.length; i++) { + result += suites[i].benchmarks.length; + } + return result; +} + + +// Computes the geometric mean of a set of numbers. +BenchmarkSuite.GeometricMean = function(numbers) { + var log = 0; + for (var i = 0; i < numbers.length; i++) { + log += Math.log(numbers[i]); + } + return Math.pow(Math.E, log / numbers.length); +} + + +// Converts a score value to a string with at least three significant +// digits. +BenchmarkSuite.FormatScore = function(value) { + if (value > 100) { + return value.toFixed(0); + } else { + return value.toPrecision(3); + } +} + +// Notifies the runner that we're done running a single benchmark in +// the benchmark suite. This can be useful to report progress. +BenchmarkSuite.prototype.NotifyStep = function(result) { + this.results.push(result); + if (this.runner.NotifyStep) this.runner.NotifyStep(result.benchmark.name); +} + + +// Notifies the runner that we're done with running a suite and that +// we have a result which can be reported to the user if needed. +BenchmarkSuite.prototype.NotifyResult = function() { + var mean = BenchmarkSuite.GeometricMean(this.results); + var score = this.reference / mean; + BenchmarkSuite.scores.push(score); + if (this.runner.NotifyResult) { + var formatted = BenchmarkSuite.FormatScore(100 * score); + this.runner.NotifyResult(this.name, formatted); + } +} + + +// Notifies the runner that running a benchmark resulted in an error. +BenchmarkSuite.prototype.NotifyError = function(error) { + if (this.runner.NotifyError) { + this.runner.NotifyError(this.name, error); + } + if (this.runner.NotifyStep) { + this.runner.NotifyStep(this.name); + } +} + + +// Runs a single benchmark for at least a second and computes the +// average time it takes to run a single iteration. +BenchmarkSuite.prototype.RunSingle = function(benchmark) { + var elapsed = 0; + var start = new Date(); + for (var n = 0; elapsed < 1000; n++) { + benchmark.run(); + elapsed = new Date() - start; + } + var usec = (elapsed * 1000) / n; + this.NotifyStep(new BenchmarkResult(benchmark, usec)); +} + + +// This function starts running a suite, but stops between each +// individual benchmark in the suite and returns a continuation +// function which can be invoked to run the next benchmark. Once the +// last benchmark has been executed, null is returned. +BenchmarkSuite.prototype.RunStep = function(runner) { + this.results = []; + this.runner = runner; + var length = this.benchmarks.length; + var index = 0; + var suite = this; + function RunNext() { + if (index < length) { + try { + suite.RunSingle(suite.benchmarks[index++]); + } catch (e) { + suite.NotifyError(e); + return null; + } + return RunNext; + } + suite.NotifyResult(); + return null; + } + return RunNext(); +} diff --git a/deps/v8/benchmarks/crypto.js b/deps/v8/benchmarks/crypto.js new file mode 100644 index 0000000000..12b88ef294 --- /dev/null +++ b/deps/v8/benchmarks/crypto.js @@ -0,0 +1,1698 @@ +/* + * Copyright (c) 2003-2005 Tom Wu + * All Rights Reserved. + * + * 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" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL TOM WU BE LIABLE FOR ANY SPECIAL, INCIDENTAL, + * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF + * THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * In addition, the following condition applies: + * + * All redistributions must retain an intact copy of this copyright notice + * and disclaimer. + */ + + +// The code has been adapted for use as a benchmark by Google. +var Crypto = new BenchmarkSuite('Crypto', 203037, [ + new Benchmark("Encrypt", encrypt), + new Benchmark("Decrypt", decrypt) +]); + + +// Basic JavaScript BN library - subset useful for RSA encryption. + +// Bits per digit +var dbits; +var BI_DB; +var BI_DM; +var BI_DV; + +var BI_FP; +var BI_FV; +var BI_F1; +var BI_F2; + +// JavaScript engine analysis +var canary = 0xdeadbeefcafe; +var j_lm = ((canary&0xffffff)==0xefcafe); + +// (public) Constructor +function BigInteger(a,b,c) { + this.array = new Array(); + if(a != null) + if("number" == typeof a) this.fromNumber(a,b,c); + else if(b == null && "string" != typeof a) this.fromString(a,256); + else this.fromString(a,b); +} + +// return new, unset BigInteger +function nbi() { return new BigInteger(null); } + +// am: Compute w_j += (x*this_i), propagate carries, +// c is initial carry, returns final carry. +// c < 3*dvalue, x < 2*dvalue, this_i < dvalue +// We need to select the fastest one that works in this environment. + +// am1: use a single mult and divide to get the high bits, +// max digit bits should be 26 because +// max internal value = 2*dvalue^2-2*dvalue (< 2^53) +function am1(i,x,w,j,c,n) { + var this_array = this.array; + var w_array = w.array; + while(--n >= 0) { + var v = x*this_array[i++]+w_array[j]+c; + c = Math.floor(v/0x4000000); + w_array[j++] = v&0x3ffffff; + } + return c; +} + +// am2 avoids a big mult-and-extract completely. +// Max digit bits should be <= 30 because we do bitwise ops +// on values up to 2*hdvalue^2-hdvalue-1 (< 2^31) +function am2(i,x,w,j,c,n) { + var this_array = this.array; + var w_array = w.array; + var xl = x&0x7fff, xh = x>>15; + while(--n >= 0) { + var l = this_array[i]&0x7fff; + var h = this_array[i++]>>15; + var m = xh*l+h*xl; + l = xl*l+((m&0x7fff)<<15)+w_array[j]+(c&0x3fffffff); + c = (l>>>30)+(m>>>15)+xh*h+(c>>>30); + w_array[j++] = l&0x3fffffff; + } + return c; +} + +// Alternately, set max digit bits to 28 since some +// browsers slow down when dealing with 32-bit numbers. +function am3(i,x,w,j,c,n) { + var this_array = this.array; + var w_array = w.array; + + var xl = x&0x3fff, xh = x>>14; + while(--n >= 0) { + var l = this_array[i]&0x3fff; + var h = this_array[i++]>>14; + var m = xh*l+h*xl; + l = xl*l+((m&0x3fff)<<14)+w_array[j]+c; + c = (l>>28)+(m>>14)+xh*h; + w_array[j++] = l&0xfffffff; + } + return c; +} + +// This is tailored to VMs with 2-bit tagging. It makes sure +// that all the computations stay within the 29 bits available. +function am4(i,x,w,j,c,n) { + var this_array = this.array; + var w_array = w.array; + + var xl = x&0x1fff, xh = x>>13; + while(--n >= 0) { + var l = this_array[i]&0x1fff; + var h = this_array[i++]>>13; + var m = xh*l+h*xl; + l = xl*l+((m&0x1fff)<<13)+w_array[j]+c; + c = (l>>26)+(m>>13)+xh*h; + w_array[j++] = l&0x3ffffff; + } + return c; +} + +// am3/28 is best for SM, Rhino, but am4/26 is best for v8. +// Kestrel (Opera 9.5) gets its best result with am4/26. +// IE7 does 9% better with am3/28 than with am4/26. +// Firefox (SM) gets 10% faster with am3/28 than with am4/26. + +setupEngine = function(fn, bits) { + BigInteger.prototype.am = fn; + dbits = bits; + + BI_DB = dbits; + BI_DM = ((1<= 0; --i) r_array[i] = this_array[i]; + r.t = this.t; + r.s = this.s; +} + +// (protected) set from integer value x, -DV <= x < DV +function bnpFromInt(x) { + var this_array = this.array; + this.t = 1; + this.s = (x<0)?-1:0; + if(x > 0) this_array[0] = x; + else if(x < -1) this_array[0] = x+DV; + else this.t = 0; +} + +// return bigint initialized to value +function nbv(i) { var r = nbi(); r.fromInt(i); return r; } + +// (protected) set from string and radix +function bnpFromString(s,b) { + var this_array = this.array; + var k; + if(b == 16) k = 4; + else if(b == 8) k = 3; + else if(b == 256) k = 8; // byte array + else if(b == 2) k = 1; + else if(b == 32) k = 5; + else if(b == 4) k = 2; + else { this.fromRadix(s,b); return; } + this.t = 0; + this.s = 0; + var i = s.length, mi = false, sh = 0; + while(--i >= 0) { + var x = (k==8)?s[i]&0xff:intAt(s,i); + if(x < 0) { + if(s.charAt(i) == "-") mi = true; + continue; + } + mi = false; + if(sh == 0) + this_array[this.t++] = x; + else if(sh+k > BI_DB) { + this_array[this.t-1] |= (x&((1<<(BI_DB-sh))-1))<>(BI_DB-sh)); + } + else + this_array[this.t-1] |= x<= BI_DB) sh -= BI_DB; + } + if(k == 8 && (s[0]&0x80) != 0) { + this.s = -1; + if(sh > 0) this_array[this.t-1] |= ((1<<(BI_DB-sh))-1)< 0 && this_array[this.t-1] == c) --this.t; +} + +// (public) return string representation in given radix +function bnToString(b) { + var this_array = this.array; + if(this.s < 0) return "-"+this.negate().toString(b); + var k; + if(b == 16) k = 4; + else if(b == 8) k = 3; + else if(b == 2) k = 1; + else if(b == 32) k = 5; + else if(b == 4) k = 2; + else return this.toRadix(b); + var km = (1< 0) { + if(p < BI_DB && (d = this_array[i]>>p) > 0) { m = true; r = int2char(d); } + while(i >= 0) { + if(p < k) { + d = (this_array[i]&((1<>(p+=BI_DB-k); + } + else { + d = (this_array[i]>>(p-=k))&km; + if(p <= 0) { p += BI_DB; --i; } + } + if(d > 0) m = true; + if(m) r += int2char(d); + } + } + return m?r:"0"; +} + +// (public) -this +function bnNegate() { var r = nbi(); BigInteger.ZERO.subTo(this,r); return r; } + +// (public) |this| +function bnAbs() { return (this.s<0)?this.negate():this; } + +// (public) return + if this > a, - if this < a, 0 if equal +function bnCompareTo(a) { + var this_array = this.array; + var a_array = a.array; + + var r = this.s-a.s; + if(r != 0) return r; + var i = this.t; + r = i-a.t; + if(r != 0) return r; + while(--i >= 0) if((r=this_array[i]-a_array[i]) != 0) return r; + return 0; +} + +// returns bit length of the integer x +function nbits(x) { + var r = 1, t; + if((t=x>>>16) != 0) { x = t; r += 16; } + if((t=x>>8) != 0) { x = t; r += 8; } + if((t=x>>4) != 0) { x = t; r += 4; } + if((t=x>>2) != 0) { x = t; r += 2; } + if((t=x>>1) != 0) { x = t; r += 1; } + return r; +} + +// (public) return the number of bits in "this" +function bnBitLength() { + var this_array = this.array; + if(this.t <= 0) return 0; + return BI_DB*(this.t-1)+nbits(this_array[this.t-1]^(this.s&BI_DM)); +} + +// (protected) r = this << n*DB +function bnpDLShiftTo(n,r) { + var this_array = this.array; + var r_array = r.array; + var i; + for(i = this.t-1; i >= 0; --i) r_array[i+n] = this_array[i]; + for(i = n-1; i >= 0; --i) r_array[i] = 0; + r.t = this.t+n; + r.s = this.s; +} + +// (protected) r = this >> n*DB +function bnpDRShiftTo(n,r) { + var this_array = this.array; + var r_array = r.array; + for(var i = n; i < this.t; ++i) r_array[i-n] = this_array[i]; + r.t = Math.max(this.t-n,0); + r.s = this.s; +} + +// (protected) r = this << n +function bnpLShiftTo(n,r) { + var this_array = this.array; + var r_array = r.array; + var bs = n%BI_DB; + var cbs = BI_DB-bs; + var bm = (1<= 0; --i) { + r_array[i+ds+1] = (this_array[i]>>cbs)|c; + c = (this_array[i]&bm)<= 0; --i) r_array[i] = 0; + r_array[ds] = c; + r.t = this.t+ds+1; + r.s = this.s; + r.clamp(); +} + +// (protected) r = this >> n +function bnpRShiftTo(n,r) { + var this_array = this.array; + var r_array = r.array; + r.s = this.s; + var ds = Math.floor(n/BI_DB); + if(ds >= this.t) { r.t = 0; return; } + var bs = n%BI_DB; + var cbs = BI_DB-bs; + var bm = (1<>bs; + for(var i = ds+1; i < this.t; ++i) { + r_array[i-ds-1] |= (this_array[i]&bm)<>bs; + } + if(bs > 0) r_array[this.t-ds-1] |= (this.s&bm)<>= BI_DB; + } + if(a.t < this.t) { + c -= a.s; + while(i < this.t) { + c += this_array[i]; + r_array[i++] = c&BI_DM; + c >>= BI_DB; + } + c += this.s; + } + else { + c += this.s; + while(i < a.t) { + c -= a_array[i]; + r_array[i++] = c&BI_DM; + c >>= BI_DB; + } + c -= a.s; + } + r.s = (c<0)?-1:0; + if(c < -1) r_array[i++] = BI_DV+c; + else if(c > 0) r_array[i++] = c; + r.t = i; + r.clamp(); +} + +// (protected) r = this * a, r != this,a (HAC 14.12) +// "this" should be the larger one if appropriate. +function bnpMultiplyTo(a,r) { + var this_array = this.array; + var r_array = r.array; + var x = this.abs(), y = a.abs(); + var y_array = y.array; + + var i = x.t; + r.t = i+y.t; + while(--i >= 0) r_array[i] = 0; + for(i = 0; i < y.t; ++i) r_array[i+x.t] = x.am(0,y_array[i],r,i,0,x.t); + r.s = 0; + r.clamp(); + if(this.s != a.s) BigInteger.ZERO.subTo(r,r); +} + +// (protected) r = this^2, r != this (HAC 14.16) +function bnpSquareTo(r) { + var x = this.abs(); + var x_array = x.array; + var r_array = r.array; + + var i = r.t = 2*x.t; + while(--i >= 0) r_array[i] = 0; + for(i = 0; i < x.t-1; ++i) { + var c = x.am(i,x_array[i],r,2*i,0,1); + if((r_array[i+x.t]+=x.am(i+1,2*x_array[i],r,2*i+1,c,x.t-i-1)) >= BI_DV) { + r_array[i+x.t] -= BI_DV; + r_array[i+x.t+1] = 1; + } + } + if(r.t > 0) r_array[r.t-1] += x.am(i,x_array[i],r,2*i,0,1); + r.s = 0; + r.clamp(); +} + +// (protected) divide this by m, quotient and remainder to q, r (HAC 14.20) +// r != q, this != m. q or r may be null. +function bnpDivRemTo(m,q,r) { + var pm = m.abs(); + if(pm.t <= 0) return; + var pt = this.abs(); + if(pt.t < pm.t) { + if(q != null) q.fromInt(0); + if(r != null) this.copyTo(r); + return; + } + if(r == null) r = nbi(); + var y = nbi(), ts = this.s, ms = m.s; + var pm_array = pm.array; + var nsh = BI_DB-nbits(pm_array[pm.t-1]); // normalize modulus + if(nsh > 0) { pm.lShiftTo(nsh,y); pt.lShiftTo(nsh,r); } + else { pm.copyTo(y); pt.copyTo(r); } + var ys = y.t; + + var y_array = y.array; + var y0 = y_array[ys-1]; + if(y0 == 0) return; + var yt = y0*(1<1)?y_array[ys-2]>>BI_F2:0); + var d1 = BI_FV/yt, d2 = (1<= 0) { + r_array[r.t++] = 1; + r.subTo(t,r); + } + BigInteger.ONE.dlShiftTo(ys,t); + t.subTo(y,y); // "negative" y so we can replace sub with am later + while(y.t < ys) y_array[y.t++] = 0; + while(--j >= 0) { + // Estimate quotient digit + var qd = (r_array[--i]==y0)?BI_DM:Math.floor(r_array[i]*d1+(r_array[i-1]+e)*d2); + if((r_array[i]+=y.am(0,qd,r,j,0,ys)) < qd) { // Try it out + y.dlShiftTo(j,t); + r.subTo(t,r); + while(r_array[i] < --qd) r.subTo(t,r); + } + } + if(q != null) { + r.drShiftTo(ys,q); + if(ts != ms) BigInteger.ZERO.subTo(q,q); + } + r.t = ys; + r.clamp(); + if(nsh > 0) r.rShiftTo(nsh,r); // Denormalize remainder + if(ts < 0) BigInteger.ZERO.subTo(r,r); +} + +// (public) this mod a +function bnMod(a) { + var r = nbi(); + this.abs().divRemTo(a,null,r); + if(this.s < 0 && r.compareTo(BigInteger.ZERO) > 0) a.subTo(r,r); + return r; +} + +// Modular reduction using "classic" algorithm +function Classic(m) { this.m = m; } +function cConvert(x) { + if(x.s < 0 || x.compareTo(this.m) >= 0) return x.mod(this.m); + else return x; +} +function cRevert(x) { return x; } +function cReduce(x) { x.divRemTo(this.m,null,x); } +function cMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); } +function cSqrTo(x,r) { x.squareTo(r); this.reduce(r); } + +Classic.prototype.convert = cConvert; +Classic.prototype.revert = cRevert; +Classic.prototype.reduce = cReduce; +Classic.prototype.mulTo = cMulTo; +Classic.prototype.sqrTo = cSqrTo; + +// (protected) return "-1/this % 2^DB"; useful for Mont. reduction +// justification: +// xy == 1 (mod m) +// xy = 1+km +// xy(2-xy) = (1+km)(1-km) +// x[y(2-xy)] = 1-k^2m^2 +// x[y(2-xy)] == 1 (mod m^2) +// if y is 1/x mod m, then y(2-xy) is 1/x mod m^2 +// should reduce x and y(2-xy) by m^2 at each step to keep size bounded. +// JS multiply "overflows" differently from C/C++, so care is needed here. +function bnpInvDigit() { + var this_array = this.array; + if(this.t < 1) return 0; + var x = this_array[0]; + if((x&1) == 0) return 0; + var y = x&3; // y == 1/x mod 2^2 + y = (y*(2-(x&0xf)*y))&0xf; // y == 1/x mod 2^4 + y = (y*(2-(x&0xff)*y))&0xff; // y == 1/x mod 2^8 + y = (y*(2-(((x&0xffff)*y)&0xffff)))&0xffff; // y == 1/x mod 2^16 + // last step - calculate inverse mod DV directly; + // assumes 16 < DB <= 32 and assumes ability to handle 48-bit ints + y = (y*(2-x*y%BI_DV))%BI_DV; // y == 1/x mod 2^dbits + // we really want the negative inverse, and -DV < y < DV + return (y>0)?BI_DV-y:-y; +} + +// Montgomery reduction +function Montgomery(m) { + this.m = m; + this.mp = m.invDigit(); + this.mpl = this.mp&0x7fff; + this.mph = this.mp>>15; + this.um = (1<<(BI_DB-15))-1; + this.mt2 = 2*m.t; +} + +// xR mod m +function montConvert(x) { + var r = nbi(); + x.abs().dlShiftTo(this.m.t,r); + r.divRemTo(this.m,null,r); + if(x.s < 0 && r.compareTo(BigInteger.ZERO) > 0) this.m.subTo(r,r); + return r; +} + +// x/R mod m +function montRevert(x) { + var r = nbi(); + x.copyTo(r); + this.reduce(r); + return r; +} + +// x = x/R mod m (HAC 14.32) +function montReduce(x) { + var x_array = x.array; + while(x.t <= this.mt2) // pad x so am has enough room later + x_array[x.t++] = 0; + for(var i = 0; i < this.m.t; ++i) { + // faster way of calculating u0 = x[i]*mp mod DV + var j = x_array[i]&0x7fff; + var u0 = (j*this.mpl+(((j*this.mph+(x_array[i]>>15)*this.mpl)&this.um)<<15))&BI_DM; + // use am to combine the multiply-shift-add into one call + j = i+this.m.t; + x_array[j] += this.m.am(0,u0,x,i,0,this.m.t); + // propagate carry + while(x_array[j] >= BI_DV) { x_array[j] -= BI_DV; x_array[++j]++; } + } + x.clamp(); + x.drShiftTo(this.m.t,x); + if(x.compareTo(this.m) >= 0) x.subTo(this.m,x); +} + +// r = "x^2/R mod m"; x != r +function montSqrTo(x,r) { x.squareTo(r); this.reduce(r); } + +// r = "xy/R mod m"; x,y != r +function montMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); } + +Montgomery.prototype.convert = montConvert; +Montgomery.prototype.revert = montRevert; +Montgomery.prototype.reduce = montReduce; +Montgomery.prototype.mulTo = montMulTo; +Montgomery.prototype.sqrTo = montSqrTo; + +// (protected) true iff this is even +function bnpIsEven() { + var this_array = this.array; + return ((this.t>0)?(this_array[0]&1):this.s) == 0; +} + +// (protected) this^e, e < 2^32, doing sqr and mul with "r" (HAC 14.79) +function bnpExp(e,z) { + if(e > 0xffffffff || e < 1) return BigInteger.ONE; + var r = nbi(), r2 = nbi(), g = z.convert(this), i = nbits(e)-1; + g.copyTo(r); + while(--i >= 0) { + z.sqrTo(r,r2); + if((e&(1< 0) z.mulTo(r2,g,r); + else { var t = r; r = r2; r2 = t; } + } + return z.revert(r); +} + +// (public) this^e % m, 0 <= e < 2^32 +function bnModPowInt(e,m) { + var z; + if(e < 256 || m.isEven()) z = new Classic(m); else z = new Montgomery(m); + return this.exp(e,z); +} + +// protected +BigInteger.prototype.copyTo = bnpCopyTo; +BigInteger.prototype.fromInt = bnpFromInt; +BigInteger.prototype.fromString = bnpFromString; +BigInteger.prototype.clamp = bnpClamp; +BigInteger.prototype.dlShiftTo = bnpDLShiftTo; +BigInteger.prototype.drShiftTo = bnpDRShiftTo; +BigInteger.prototype.lShiftTo = bnpLShiftTo; +BigInteger.prototype.rShiftTo = bnpRShiftTo; +BigInteger.prototype.subTo = bnpSubTo; +BigInteger.prototype.multiplyTo = bnpMultiplyTo; +BigInteger.prototype.squareTo = bnpSquareTo; +BigInteger.prototype.divRemTo = bnpDivRemTo; +BigInteger.prototype.invDigit = bnpInvDigit; +BigInteger.prototype.isEven = bnpIsEven; +BigInteger.prototype.exp = bnpExp; + +// public +BigInteger.prototype.toString = bnToString; +BigInteger.prototype.negate = bnNegate; +BigInteger.prototype.abs = bnAbs; +BigInteger.prototype.compareTo = bnCompareTo; +BigInteger.prototype.bitLength = bnBitLength; +BigInteger.prototype.mod = bnMod; +BigInteger.prototype.modPowInt = bnModPowInt; + +// "constants" +BigInteger.ZERO = nbv(0); +BigInteger.ONE = nbv(1); +// Copyright (c) 2005 Tom Wu +// All Rights Reserved. +// See "LICENSE" for details. + +// Extended JavaScript BN functions, required for RSA private ops. + +// (public) +function bnClone() { var r = nbi(); this.copyTo(r); return r; } + +// (public) return value as integer +function bnIntValue() { + var this_array = this.array; + if(this.s < 0) { + if(this.t == 1) return this_array[0]-BI_DV; + else if(this.t == 0) return -1; + } + else if(this.t == 1) return this_array[0]; + else if(this.t == 0) return 0; + // assumes 16 < DB < 32 + return ((this_array[1]&((1<<(32-BI_DB))-1))<>24; +} + +// (public) return value as short (assumes DB>=16) +function bnShortValue() { + var this_array = this.array; + return (this.t==0)?this.s:(this_array[0]<<16)>>16; +} + +// (protected) return x s.t. r^x < DV +function bnpChunkSize(r) { return Math.floor(Math.LN2*BI_DB/Math.log(r)); } + +// (public) 0 if this == 0, 1 if this > 0 +function bnSigNum() { + var this_array = this.array; + if(this.s < 0) return -1; + else if(this.t <= 0 || (this.t == 1 && this_array[0] <= 0)) return 0; + else return 1; +} + +// (protected) convert to radix string +function bnpToRadix(b) { + if(b == null) b = 10; + if(this.signum() == 0 || b < 2 || b > 36) return "0"; + var cs = this.chunkSize(b); + var a = Math.pow(b,cs); + var d = nbv(a), y = nbi(), z = nbi(), r = ""; + this.divRemTo(d,y,z); + while(y.signum() > 0) { + r = (a+z.intValue()).toString(b).substr(1) + r; + y.divRemTo(d,y,z); + } + return z.intValue().toString(b) + r; +} + +// (protected) convert from radix string +function bnpFromRadix(s,b) { + this.fromInt(0); + if(b == null) b = 10; + var cs = this.chunkSize(b); + var d = Math.pow(b,cs), mi = false, j = 0, w = 0; + for(var i = 0; i < s.length; ++i) { + var x = intAt(s,i); + if(x < 0) { + if(s.charAt(i) == "-" && this.signum() == 0) mi = true; + continue; + } + w = b*w+x; + if(++j >= cs) { + this.dMultiply(d); + this.dAddOffset(w,0); + j = 0; + w = 0; + } + } + if(j > 0) { + this.dMultiply(Math.pow(b,j)); + this.dAddOffset(w,0); + } + if(mi) BigInteger.ZERO.subTo(this,this); +} + +// (protected) alternate constructor +function bnpFromNumber(a,b,c) { + if("number" == typeof b) { + // new BigInteger(int,int,RNG) + if(a < 2) this.fromInt(1); + else { + this.fromNumber(a,c); + if(!this.testBit(a-1)) // force MSB set + this.bitwiseTo(BigInteger.ONE.shiftLeft(a-1),op_or,this); + if(this.isEven()) this.dAddOffset(1,0); // force odd + while(!this.isProbablePrime(b)) { + this.dAddOffset(2,0); + if(this.bitLength() > a) this.subTo(BigInteger.ONE.shiftLeft(a-1),this); + } + } + } + else { + // new BigInteger(int,RNG) + var x = new Array(), t = a&7; + x.length = (a>>3)+1; + b.nextBytes(x); + if(t > 0) x[0] &= ((1< 0) { + if(p < BI_DB && (d = this_array[i]>>p) != (this.s&BI_DM)>>p) + r[k++] = d|(this.s<<(BI_DB-p)); + while(i >= 0) { + if(p < 8) { + d = (this_array[i]&((1<>(p+=BI_DB-8); + } + else { + d = (this_array[i]>>(p-=8))&0xff; + if(p <= 0) { p += BI_DB; --i; } + } + if((d&0x80) != 0) d |= -256; + if(k == 0 && (this.s&0x80) != (d&0x80)) ++k; + if(k > 0 || d != this.s) r[k++] = d; + } + } + return r; +} + +function bnEquals(a) { return(this.compareTo(a)==0); } +function bnMin(a) { return(this.compareTo(a)<0)?this:a; } +function bnMax(a) { return(this.compareTo(a)>0)?this:a; } + +// (protected) r = this op a (bitwise) +function bnpBitwiseTo(a,op,r) { + var this_array = this.array; + var a_array = a.array; + var r_array = r.array; + var i, f, m = Math.min(a.t,this.t); + for(i = 0; i < m; ++i) r_array[i] = op(this_array[i],a_array[i]); + if(a.t < this.t) { + f = a.s&BI_DM; + for(i = m; i < this.t; ++i) r_array[i] = op(this_array[i],f); + r.t = this.t; + } + else { + f = this.s&BI_DM; + for(i = m; i < a.t; ++i) r_array[i] = op(f,a_array[i]); + r.t = a.t; + } + r.s = op(this.s,a.s); + r.clamp(); +} + +// (public) this & a +function op_and(x,y) { return x&y; } +function bnAnd(a) { var r = nbi(); this.bitwiseTo(a,op_and,r); return r; } + +// (public) this | a +function op_or(x,y) { return x|y; } +function bnOr(a) { var r = nbi(); this.bitwiseTo(a,op_or,r); return r; } + +// (public) this ^ a +function op_xor(x,y) { return x^y; } +function bnXor(a) { var r = nbi(); this.bitwiseTo(a,op_xor,r); return r; } + +// (public) this & ~a +function op_andnot(x,y) { return x&~y; } +function bnAndNot(a) { var r = nbi(); this.bitwiseTo(a,op_andnot,r); return r; } + +// (public) ~this +function bnNot() { + var this_array = this.array; + var r = nbi(); + var r_array = r.array; + + for(var i = 0; i < this.t; ++i) r_array[i] = BI_DM&~this_array[i]; + r.t = this.t; + r.s = ~this.s; + return r; +} + +// (public) this << n +function bnShiftLeft(n) { + var r = nbi(); + if(n < 0) this.rShiftTo(-n,r); else this.lShiftTo(n,r); + return r; +} + +// (public) this >> n +function bnShiftRight(n) { + var r = nbi(); + if(n < 0) this.lShiftTo(-n,r); else this.rShiftTo(n,r); + return r; +} + +// return index of lowest 1-bit in x, x < 2^31 +function lbit(x) { + if(x == 0) return -1; + var r = 0; + if((x&0xffff) == 0) { x >>= 16; r += 16; } + if((x&0xff) == 0) { x >>= 8; r += 8; } + if((x&0xf) == 0) { x >>= 4; r += 4; } + if((x&3) == 0) { x >>= 2; r += 2; } + if((x&1) == 0) ++r; + return r; +} + +// (public) returns index of lowest 1-bit (or -1 if none) +function bnGetLowestSetBit() { + var this_array = this.array; + for(var i = 0; i < this.t; ++i) + if(this_array[i] != 0) return i*BI_DB+lbit(this_array[i]); + if(this.s < 0) return this.t*BI_DB; + return -1; +} + +// return number of 1 bits in x +function cbit(x) { + var r = 0; + while(x != 0) { x &= x-1; ++r; } + return r; +} + +// (public) return number of set bits +function bnBitCount() { + var r = 0, x = this.s&BI_DM; + for(var i = 0; i < this.t; ++i) r += cbit(this_array[i]^x); + return r; +} + +// (public) true iff nth bit is set +function bnTestBit(n) { + var this_array = this.array; + var j = Math.floor(n/BI_DB); + if(j >= this.t) return(this.s!=0); + return((this_array[j]&(1<<(n%BI_DB)))!=0); +} + +// (protected) this op (1<>= BI_DB; + } + if(a.t < this.t) { + c += a.s; + while(i < this.t) { + c += this_array[i]; + r_array[i++] = c&BI_DM; + c >>= BI_DB; + } + c += this.s; + } + else { + c += this.s; + while(i < a.t) { + c += a_array[i]; + r_array[i++] = c&BI_DM; + c >>= BI_DB; + } + c += a.s; + } + r.s = (c<0)?-1:0; + if(c > 0) r_array[i++] = c; + else if(c < -1) r_array[i++] = BI_DV+c; + r.t = i; + r.clamp(); +} + +// (public) this + a +function bnAdd(a) { var r = nbi(); this.addTo(a,r); return r; } + +// (public) this - a +function bnSubtract(a) { var r = nbi(); this.subTo(a,r); return r; } + +// (public) this * a +function bnMultiply(a) { var r = nbi(); this.multiplyTo(a,r); return r; } + +// (public) this / a +function bnDivide(a) { var r = nbi(); this.divRemTo(a,r,null); return r; } + +// (public) this % a +function bnRemainder(a) { var r = nbi(); this.divRemTo(a,null,r); return r; } + +// (public) [this/a,this%a] +function bnDivideAndRemainder(a) { + var q = nbi(), r = nbi(); + this.divRemTo(a,q,r); + return new Array(q,r); +} + +// (protected) this *= n, this >= 0, 1 < n < DV +function bnpDMultiply(n) { + var this_array = this.array; + this_array[this.t] = this.am(0,n-1,this,0,0,this.t); + ++this.t; + this.clamp(); +} + +// (protected) this += n << w words, this >= 0 +function bnpDAddOffset(n,w) { + var this_array = this.array; + while(this.t <= w) this_array[this.t++] = 0; + this_array[w] += n; + while(this_array[w] >= BI_DV) { + this_array[w] -= BI_DV; + if(++w >= this.t) this_array[this.t++] = 0; + ++this_array[w]; + } +} + +// A "null" reducer +function NullExp() {} +function nNop(x) { return x; } +function nMulTo(x,y,r) { x.multiplyTo(y,r); } +function nSqrTo(x,r) { x.squareTo(r); } + +NullExp.prototype.convert = nNop; +NullExp.prototype.revert = nNop; +NullExp.prototype.mulTo = nMulTo; +NullExp.prototype.sqrTo = nSqrTo; + +// (public) this^e +function bnPow(e) { return this.exp(e,new NullExp()); } + +// (protected) r = lower n words of "this * a", a.t <= n +// "this" should be the larger one if appropriate. +function bnpMultiplyLowerTo(a,n,r) { + var r_array = r.array; + var a_array = a.array; + var i = Math.min(this.t+a.t,n); + r.s = 0; // assumes a,this >= 0 + r.t = i; + while(i > 0) r_array[--i] = 0; + var j; + for(j = r.t-this.t; i < j; ++i) r_array[i+this.t] = this.am(0,a_array[i],r,i,0,this.t); + for(j = Math.min(a.t,n); i < j; ++i) this.am(0,a_array[i],r,i,0,n-i); + r.clamp(); +} + +// (protected) r = "this * a" without lower n words, n > 0 +// "this" should be the larger one if appropriate. +function bnpMultiplyUpperTo(a,n,r) { + var r_array = r.array; + var a_array = a.array; + --n; + var i = r.t = this.t+a.t-n; + r.s = 0; // assumes a,this >= 0 + while(--i >= 0) r_array[i] = 0; + for(i = Math.max(n-this.t,0); i < a.t; ++i) + r_array[this.t+i-n] = this.am(n-i,a_array[i],r,0,0,this.t+i-n); + r.clamp(); + r.drShiftTo(1,r); +} + +// Barrett modular reduction +function Barrett(m) { + // setup Barrett + this.r2 = nbi(); + this.q3 = nbi(); + BigInteger.ONE.dlShiftTo(2*m.t,this.r2); + this.mu = this.r2.divide(m); + this.m = m; +} + +function barrettConvert(x) { + if(x.s < 0 || x.t > 2*this.m.t) return x.mod(this.m); + else if(x.compareTo(this.m) < 0) return x; + else { var r = nbi(); x.copyTo(r); this.reduce(r); return r; } +} + +function barrettRevert(x) { return x; } + +// x = x mod m (HAC 14.42) +function barrettReduce(x) { + x.drShiftTo(this.m.t-1,this.r2); + if(x.t > this.m.t+1) { x.t = this.m.t+1; x.clamp(); } + this.mu.multiplyUpperTo(this.r2,this.m.t+1,this.q3); + this.m.multiplyLowerTo(this.q3,this.m.t+1,this.r2); + while(x.compareTo(this.r2) < 0) x.dAddOffset(1,this.m.t+1); + x.subTo(this.r2,x); + while(x.compareTo(this.m) >= 0) x.subTo(this.m,x); +} + +// r = x^2 mod m; x != r +function barrettSqrTo(x,r) { x.squareTo(r); this.reduce(r); } + +// r = x*y mod m; x,y != r +function barrettMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); } + +Barrett.prototype.convert = barrettConvert; +Barrett.prototype.revert = barrettRevert; +Barrett.prototype.reduce = barrettReduce; +Barrett.prototype.mulTo = barrettMulTo; +Barrett.prototype.sqrTo = barrettSqrTo; + +// (public) this^e % m (HAC 14.85) +function bnModPow(e,m) { + var e_array = e.array; + var i = e.bitLength(), k, r = nbv(1), z; + if(i <= 0) return r; + else if(i < 18) k = 1; + else if(i < 48) k = 3; + else if(i < 144) k = 4; + else if(i < 768) k = 5; + else k = 6; + if(i < 8) + z = new Classic(m); + else if(m.isEven()) + z = new Barrett(m); + else + z = new Montgomery(m); + + // precomputation + var g = new Array(), n = 3, k1 = k-1, km = (1< 1) { + var g2 = nbi(); + z.sqrTo(g[1],g2); + while(n <= km) { + g[n] = nbi(); + z.mulTo(g2,g[n-2],g[n]); + n += 2; + } + } + + var j = e.t-1, w, is1 = true, r2 = nbi(), t; + i = nbits(e_array[j])-1; + while(j >= 0) { + if(i >= k1) w = (e_array[j]>>(i-k1))&km; + else { + w = (e_array[j]&((1<<(i+1))-1))<<(k1-i); + if(j > 0) w |= e_array[j-1]>>(BI_DB+i-k1); + } + + n = k; + while((w&1) == 0) { w >>= 1; --n; } + if((i -= n) < 0) { i += BI_DB; --j; } + if(is1) { // ret == 1, don't bother squaring or multiplying it + g[w].copyTo(r); + is1 = false; + } + else { + while(n > 1) { z.sqrTo(r,r2); z.sqrTo(r2,r); n -= 2; } + if(n > 0) z.sqrTo(r,r2); else { t = r; r = r2; r2 = t; } + z.mulTo(r2,g[w],r); + } + + while(j >= 0 && (e_array[j]&(1< 0) { + x.rShiftTo(g,x); + y.rShiftTo(g,y); + } + while(x.signum() > 0) { + if((i = x.getLowestSetBit()) > 0) x.rShiftTo(i,x); + if((i = y.getLowestSetBit()) > 0) y.rShiftTo(i,y); + if(x.compareTo(y) >= 0) { + x.subTo(y,x); + x.rShiftTo(1,x); + } + else { + y.subTo(x,y); + y.rShiftTo(1,y); + } + } + if(g > 0) y.lShiftTo(g,y); + return y; +} + +// (protected) this % n, n < 2^26 +function bnpModInt(n) { + var this_array = this.array; + if(n <= 0) return 0; + var d = BI_DV%n, r = (this.s<0)?n-1:0; + if(this.t > 0) + if(d == 0) r = this_array[0]%n; + else for(var i = this.t-1; i >= 0; --i) r = (d*r+this_array[i])%n; + return r; +} + +// (public) 1/this % m (HAC 14.61) +function bnModInverse(m) { + var ac = m.isEven(); + if((this.isEven() && ac) || m.signum() == 0) return BigInteger.ZERO; + var u = m.clone(), v = this.clone(); + var a = nbv(1), b = nbv(0), c = nbv(0), d = nbv(1); + while(u.signum() != 0) { + while(u.isEven()) { + u.rShiftTo(1,u); + if(ac) { + if(!a.isEven() || !b.isEven()) { a.addTo(this,a); b.subTo(m,b); } + a.rShiftTo(1,a); + } + else if(!b.isEven()) b.subTo(m,b); + b.rShiftTo(1,b); + } + while(v.isEven()) { + v.rShiftTo(1,v); + if(ac) { + if(!c.isEven() || !d.isEven()) { c.addTo(this,c); d.subTo(m,d); } + c.rShiftTo(1,c); + } + else if(!d.isEven()) d.subTo(m,d); + d.rShiftTo(1,d); + } + if(u.compareTo(v) >= 0) { + u.subTo(v,u); + if(ac) a.subTo(c,a); + b.subTo(d,b); + } + else { + v.subTo(u,v); + if(ac) c.subTo(a,c); + d.subTo(b,d); + } + } + if(v.compareTo(BigInteger.ONE) != 0) return BigInteger.ZERO; + if(d.compareTo(m) >= 0) return d.subtract(m); + if(d.signum() < 0) d.addTo(m,d); else return d; + if(d.signum() < 0) return d.add(m); else return d; +} + +var lowprimes = [2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,509]; +var lplim = (1<<26)/lowprimes[lowprimes.length-1]; + +// (public) test primality with certainty >= 1-.5^t +function bnIsProbablePrime(t) { + var i, x = this.abs(); + var x_array = x.array; + if(x.t == 1 && x_array[0] <= lowprimes[lowprimes.length-1]) { + for(i = 0; i < lowprimes.length; ++i) + if(x_array[0] == lowprimes[i]) return true; + return false; + } + if(x.isEven()) return false; + i = 1; + while(i < lowprimes.length) { + var m = lowprimes[i], j = i+1; + while(j < lowprimes.length && m < lplim) m *= lowprimes[j++]; + m = x.modInt(m); + while(i < j) if(m%lowprimes[i++] == 0) return false; + } + return x.millerRabin(t); +} + +// (protected) true if probably prime (HAC 4.24, Miller-Rabin) +function bnpMillerRabin(t) { + var n1 = this.subtract(BigInteger.ONE); + var k = n1.getLowestSetBit(); + if(k <= 0) return false; + var r = n1.shiftRight(k); + t = (t+1)>>1; + if(t > lowprimes.length) t = lowprimes.length; + var a = nbi(); + for(var i = 0; i < t; ++i) { + a.fromInt(lowprimes[i]); + var y = a.modPow(r,this); + if(y.compareTo(BigInteger.ONE) != 0 && y.compareTo(n1) != 0) { + var j = 1; + while(j++ < k && y.compareTo(n1) != 0) { + y = y.modPowInt(2,this); + if(y.compareTo(BigInteger.ONE) == 0) return false; + } + if(y.compareTo(n1) != 0) return false; + } + } + return true; +} + +// protected +BigInteger.prototype.chunkSize = bnpChunkSize; +BigInteger.prototype.toRadix = bnpToRadix; +BigInteger.prototype.fromRadix = bnpFromRadix; +BigInteger.prototype.fromNumber = bnpFromNumber; +BigInteger.prototype.bitwiseTo = bnpBitwiseTo; +BigInteger.prototype.changeBit = bnpChangeBit; +BigInteger.prototype.addTo = bnpAddTo; +BigInteger.prototype.dMultiply = bnpDMultiply; +BigInteger.prototype.dAddOffset = bnpDAddOffset; +BigInteger.prototype.multiplyLowerTo = bnpMultiplyLowerTo; +BigInteger.prototype.multiplyUpperTo = bnpMultiplyUpperTo; +BigInteger.prototype.modInt = bnpModInt; +BigInteger.prototype.millerRabin = bnpMillerRabin; + +// public +BigInteger.prototype.clone = bnClone; +BigInteger.prototype.intValue = bnIntValue; +BigInteger.prototype.byteValue = bnByteValue; +BigInteger.prototype.shortValue = bnShortValue; +BigInteger.prototype.signum = bnSigNum; +BigInteger.prototype.toByteArray = bnToByteArray; +BigInteger.prototype.equals = bnEquals; +BigInteger.prototype.min = bnMin; +BigInteger.prototype.max = bnMax; +BigInteger.prototype.and = bnAnd; +BigInteger.prototype.or = bnOr; +BigInteger.prototype.xor = bnXor; +BigInteger.prototype.andNot = bnAndNot; +BigInteger.prototype.not = bnNot; +BigInteger.prototype.shiftLeft = bnShiftLeft; +BigInteger.prototype.shiftRight = bnShiftRight; +BigInteger.prototype.getLowestSetBit = bnGetLowestSetBit; +BigInteger.prototype.bitCount = bnBitCount; +BigInteger.prototype.testBit = bnTestBit; +BigInteger.prototype.setBit = bnSetBit; +BigInteger.prototype.clearBit = bnClearBit; +BigInteger.prototype.flipBit = bnFlipBit; +BigInteger.prototype.add = bnAdd; +BigInteger.prototype.subtract = bnSubtract; +BigInteger.prototype.multiply = bnMultiply; +BigInteger.prototype.divide = bnDivide; +BigInteger.prototype.remainder = bnRemainder; +BigInteger.prototype.divideAndRemainder = bnDivideAndRemainder; +BigInteger.prototype.modPow = bnModPow; +BigInteger.prototype.modInverse = bnModInverse; +BigInteger.prototype.pow = bnPow; +BigInteger.prototype.gcd = bnGCD; +BigInteger.prototype.isProbablePrime = bnIsProbablePrime; + +// BigInteger interfaces not implemented in jsbn: + +// BigInteger(int signum, byte[] magnitude) +// double doubleValue() +// float floatValue() +// int hashCode() +// long longValue() +// static BigInteger valueOf(long val) +// prng4.js - uses Arcfour as a PRNG + +function Arcfour() { + this.i = 0; + this.j = 0; + this.S = new Array(); +} + +// Initialize arcfour context from key, an array of ints, each from [0..255] +function ARC4init(key) { + var i, j, t; + for(i = 0; i < 256; ++i) + this.S[i] = i; + j = 0; + for(i = 0; i < 256; ++i) { + j = (j + this.S[i] + key[i % key.length]) & 255; + t = this.S[i]; + this.S[i] = this.S[j]; + this.S[j] = t; + } + this.i = 0; + this.j = 0; +} + +function ARC4next() { + var t; + this.i = (this.i + 1) & 255; + this.j = (this.j + this.S[this.i]) & 255; + t = this.S[this.i]; + this.S[this.i] = this.S[this.j]; + this.S[this.j] = t; + return this.S[(t + this.S[this.i]) & 255]; +} + +Arcfour.prototype.init = ARC4init; +Arcfour.prototype.next = ARC4next; + +// Plug in your RNG constructor here +function prng_newstate() { + return new Arcfour(); +} + +// Pool size must be a multiple of 4 and greater than 32. +// An array of bytes the size of the pool will be passed to init() +var rng_psize = 256; +// Random number generator - requires a PRNG backend, e.g. prng4.js + +// For best results, put code like +// +// in your main HTML document. + +var rng_state; +var rng_pool; +var rng_pptr; + +// Mix in a 32-bit integer into the pool +function rng_seed_int(x) { + rng_pool[rng_pptr++] ^= x & 255; + rng_pool[rng_pptr++] ^= (x >> 8) & 255; + rng_pool[rng_pptr++] ^= (x >> 16) & 255; + rng_pool[rng_pptr++] ^= (x >> 24) & 255; + if(rng_pptr >= rng_psize) rng_pptr -= rng_psize; +} + +// Mix in the current time (w/milliseconds) into the pool +function rng_seed_time() { + // Use pre-computed date to avoid making the benchmark + // results dependent on the current date. + rng_seed_int(1122926989487); +} + +// Initialize the pool with junk if needed. +if(rng_pool == null) { + rng_pool = new Array(); + rng_pptr = 0; + var t; + while(rng_pptr < rng_psize) { // extract some randomness from Math.random() + t = Math.floor(65536 * Math.random()); + rng_pool[rng_pptr++] = t >>> 8; + rng_pool[rng_pptr++] = t & 255; + } + rng_pptr = 0; + rng_seed_time(); + //rng_seed_int(window.screenX); + //rng_seed_int(window.screenY); +} + +function rng_get_byte() { + if(rng_state == null) { + rng_seed_time(); + rng_state = prng_newstate(); + rng_state.init(rng_pool); + for(rng_pptr = 0; rng_pptr < rng_pool.length; ++rng_pptr) + rng_pool[rng_pptr] = 0; + rng_pptr = 0; + //rng_pool = null; + } + // TODO: allow reseeding after first request + return rng_state.next(); +} + +function rng_get_bytes(ba) { + var i; + for(i = 0; i < ba.length; ++i) ba[i] = rng_get_byte(); +} + +function SecureRandom() {} + +SecureRandom.prototype.nextBytes = rng_get_bytes; +// Depends on jsbn.js and rng.js + +// convert a (hex) string to a bignum object +function parseBigInt(str,r) { + return new BigInteger(str,r); +} + +function linebrk(s,n) { + var ret = ""; + var i = 0; + while(i + n < s.length) { + ret += s.substring(i,i+n) + "\n"; + i += n; + } + return ret + s.substring(i,s.length); +} + +function byte2Hex(b) { + if(b < 0x10) + return "0" + b.toString(16); + else + return b.toString(16); +} + +// PKCS#1 (type 2, random) pad input string s to n bytes, and return a bigint +function pkcs1pad2(s,n) { + if(n < s.length + 11) { + alert("Message too long for RSA"); + return null; + } + var ba = new Array(); + var i = s.length - 1; + while(i >= 0 && n > 0) ba[--n] = s.charCodeAt(i--); + ba[--n] = 0; + var rng = new SecureRandom(); + var x = new Array(); + while(n > 2) { // random non-zero pad + x[0] = 0; + while(x[0] == 0) rng.nextBytes(x); + ba[--n] = x[0]; + } + ba[--n] = 2; + ba[--n] = 0; + return new BigInteger(ba); +} + +// "empty" RSA key constructor +function RSAKey() { + this.n = null; + this.e = 0; + this.d = null; + this.p = null; + this.q = null; + this.dmp1 = null; + this.dmq1 = null; + this.coeff = null; +} + +// Set the public key fields N and e from hex strings +function RSASetPublic(N,E) { + if(N != null && E != null && N.length > 0 && E.length > 0) { + this.n = parseBigInt(N,16); + this.e = parseInt(E,16); + } + else + alert("Invalid RSA public key"); +} + +// Perform raw public operation on "x": return x^e (mod n) +function RSADoPublic(x) { + return x.modPowInt(this.e, this.n); +} + +// Return the PKCS#1 RSA encryption of "text" as an even-length hex string +function RSAEncrypt(text) { + var m = pkcs1pad2(text,(this.n.bitLength()+7)>>3); + if(m == null) return null; + var c = this.doPublic(m); + if(c == null) return null; + var h = c.toString(16); + if((h.length & 1) == 0) return h; else return "0" + h; +} + +// Return the PKCS#1 RSA encryption of "text" as a Base64-encoded string +//function RSAEncryptB64(text) { +// var h = this.encrypt(text); +// if(h) return hex2b64(h); else return null; +//} + +// protected +RSAKey.prototype.doPublic = RSADoPublic; + +// public +RSAKey.prototype.setPublic = RSASetPublic; +RSAKey.prototype.encrypt = RSAEncrypt; +//RSAKey.prototype.encrypt_b64 = RSAEncryptB64; +// Depends on rsa.js and jsbn2.js + +// Undo PKCS#1 (type 2, random) padding and, if valid, return the plaintext +function pkcs1unpad2(d,n) { + var b = d.toByteArray(); + var i = 0; + while(i < b.length && b[i] == 0) ++i; + if(b.length-i != n-1 || b[i] != 2) + return null; + ++i; + while(b[i] != 0) + if(++i >= b.length) return null; + var ret = ""; + while(++i < b.length) + ret += String.fromCharCode(b[i]); + return ret; +} + +// Set the private key fields N, e, and d from hex strings +function RSASetPrivate(N,E,D) { + if(N != null && E != null && N.length > 0 && E.length > 0) { + this.n = parseBigInt(N,16); + this.e = parseInt(E,16); + this.d = parseBigInt(D,16); + } + else + alert("Invalid RSA private key"); +} + +// Set the private key fields N, e, d and CRT params from hex strings +function RSASetPrivateEx(N,E,D,P,Q,DP,DQ,C) { + if(N != null && E != null && N.length > 0 && E.length > 0) { + this.n = parseBigInt(N,16); + this.e = parseInt(E,16); + this.d = parseBigInt(D,16); + this.p = parseBigInt(P,16); + this.q = parseBigInt(Q,16); + this.dmp1 = parseBigInt(DP,16); + this.dmq1 = parseBigInt(DQ,16); + this.coeff = parseBigInt(C,16); + } + else + alert("Invalid RSA private key"); +} + +// Generate a new random private key B bits long, using public expt E +function RSAGenerate(B,E) { + var rng = new SecureRandom(); + var qs = B>>1; + this.e = parseInt(E,16); + var ee = new BigInteger(E,16); + for(;;) { + for(;;) { + this.p = new BigInteger(B-qs,1,rng); + if(this.p.subtract(BigInteger.ONE).gcd(ee).compareTo(BigInteger.ONE) == 0 && this.p.isProbablePrime(10)) break; + } + for(;;) { + this.q = new BigInteger(qs,1,rng); + if(this.q.subtract(BigInteger.ONE).gcd(ee).compareTo(BigInteger.ONE) == 0 && this.q.isProbablePrime(10)) break; + } + if(this.p.compareTo(this.q) <= 0) { + var t = this.p; + this.p = this.q; + this.q = t; + } + var p1 = this.p.subtract(BigInteger.ONE); + var q1 = this.q.subtract(BigInteger.ONE); + var phi = p1.multiply(q1); + if(phi.gcd(ee).compareTo(BigInteger.ONE) == 0) { + this.n = this.p.multiply(this.q); + this.d = ee.modInverse(phi); + this.dmp1 = this.d.mod(p1); + this.dmq1 = this.d.mod(q1); + this.coeff = this.q.modInverse(this.p); + break; + } + } +} + +// Perform raw private operation on "x": return x^d (mod n) +function RSADoPrivate(x) { + if(this.p == null || this.q == null) + return x.modPow(this.d, this.n); + + // TODO: re-calculate any missing CRT params + var xp = x.mod(this.p).modPow(this.dmp1, this.p); + var xq = x.mod(this.q).modPow(this.dmq1, this.q); + + while(xp.compareTo(xq) < 0) + xp = xp.add(this.p); + return xp.subtract(xq).multiply(this.coeff).mod(this.p).multiply(this.q).add(xq); +} + +// Return the PKCS#1 RSA decryption of "ctext". +// "ctext" is an even-length hex string and the output is a plain string. +function RSADecrypt(ctext) { + var c = parseBigInt(ctext, 16); + var m = this.doPrivate(c); + if(m == null) return null; + return pkcs1unpad2(m, (this.n.bitLength()+7)>>3); +} + +// Return the PKCS#1 RSA decryption of "ctext". +// "ctext" is a Base64-encoded string and the output is a plain string. +//function RSAB64Decrypt(ctext) { +// var h = b64tohex(ctext); +// if(h) return this.decrypt(h); else return null; +//} + +// protected +RSAKey.prototype.doPrivate = RSADoPrivate; + +// public +RSAKey.prototype.setPrivate = RSASetPrivate; +RSAKey.prototype.setPrivateEx = RSASetPrivateEx; +RSAKey.prototype.generate = RSAGenerate; +RSAKey.prototype.decrypt = RSADecrypt; +//RSAKey.prototype.b64_decrypt = RSAB64Decrypt; + + +nValue="a5261939975948bb7a58dffe5ff54e65f0498f9175f5a09288810b8975871e99af3b5dd94057b0fc07535f5f97444504fa35169d461d0d30cf0192e307727c065168c788771c561a9400fb49175e9e6aa4e23fe11af69e9412dd23b0cb6684c4c2429bce139e848ab26d0829073351f4acd36074eafd036a5eb83359d2a698d3"; +eValue="10001"; +dValue="8e9912f6d3645894e8d38cb58c0db81ff516cf4c7e5a14c7f1eddb1459d2cded4d8d293fc97aee6aefb861859c8b6a3d1dfe710463e1f9ddc72048c09751971c4a580aa51eb523357a3cc48d31cfad1d4a165066ed92d4748fb6571211da5cb14bc11b6e2df7c1a559e6d5ac1cd5c94703a22891464fba23d0d965086277a161"; +pValue="d090ce58a92c75233a6486cb0a9209bf3583b64f540c76f5294bb97d285eed33aec220bde14b2417951178ac152ceab6da7090905b478195498b352048f15e7d"; +qValue="cab575dc652bb66df15a0359609d51d1db184750c00c6698b90ef3465c99655103edbf0d54c56aec0ce3c4d22592338092a126a0cc49f65a4a30d222b411e58f"; +dmp1Value="1a24bca8e273df2f0e47c199bbf678604e7df7215480c77c8db39f49b000ce2cf7500038acfff5433b7d582a01f1826e6f4d42e1c57f5e1fef7b12aabc59fd25"; +dmq1Value="3d06982efbbe47339e1f6d36b1216b8a741d410b0c662f54f7118b27b9a4ec9d914337eb39841d8666f3034408cf94f5b62f11c402fc994fe15a05493150d9fd"; +coeffValue="3a3e731acd8960b7ff9eb81a7ff93bd1cfa74cbd56987db58b4594fb09c09084db1734c8143f98b602b981aaa9243ca28deb69b5b280ee8dcee0fd2625e53250"; + +setupEngine(am3, 28); + +var TEXT = "The quick brown fox jumped over the extremely lazy frog! " + + "Now is the time for all good men to come to the party."; +var encrypted; + +function encrypt() { + var RSA = new RSAKey(); + RSA.setPublic(nValue, eValue); + RSA.setPrivateEx(nValue, eValue, dValue, pValue, qValue, dmp1Value, dmq1Value, coeffValue); + encrypted = RSA.encrypt(TEXT); +} + +function decrypt() { + var RSA = new RSAKey(); + RSA.setPublic(nValue, eValue); + RSA.setPrivateEx(nValue, eValue, dValue, pValue, qValue, dmp1Value, dmq1Value, coeffValue); + var decrypted = RSA.decrypt(encrypted); + if (decrypted != TEXT) { + throw new Error("Crypto operation failed"); + } +} diff --git a/deps/v8/benchmarks/deltablue.js b/deps/v8/benchmarks/deltablue.js new file mode 100644 index 0000000000..b51afd1d2d --- /dev/null +++ b/deps/v8/benchmarks/deltablue.js @@ -0,0 +1,880 @@ +// Copyright 2008 the V8 project authors. All rights reserved. +// Copyright 1996 John Maloney and Mario Wolczko. + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program 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 General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +// This implementation of the DeltaBlue benchmark is derived +// from the Smalltalk implementation by John Maloney and Mario +// Wolczko. Some parts have been translated directly, whereas +// others have been modified more aggresively to make it feel +// more like a JavaScript program. + + +var DeltaBlue = new BenchmarkSuite('DeltaBlue', 71104, [ + new Benchmark('DeltaBlue', deltaBlue) +]); + + +/** + * A JavaScript implementation of the DeltaBlue constrain-solving + * algorithm, as described in: + * + * "The DeltaBlue Algorithm: An Incremental Constraint Hierarchy Solver" + * Bjorn N. Freeman-Benson and John Maloney + * January 1990 Communications of the ACM, + * also available as University of Washington TR 89-08-06. + * + * Beware: this benchmark is written in a grotesque style where + * the constraint model is built by side-effects from constructors. + * I've kept it this way to avoid deviating too much from the original + * implementation. + */ + + +/* --- O b j e c t M o d e l --- */ + +Object.prototype.inherits = function (shuper) { + function Inheriter() { } + Inheriter.prototype = shuper.prototype; + this.prototype = new Inheriter(); + this.superConstructor = shuper; +} + +function OrderedCollection() { + this.elms = new Array(); +} + +OrderedCollection.prototype.add = function (elm) { + this.elms.push(elm); +} + +OrderedCollection.prototype.at = function (index) { + return this.elms[index]; +} + +OrderedCollection.prototype.size = function () { + return this.elms.length; +} + +OrderedCollection.prototype.removeFirst = function () { + return this.elms.pop(); +} + +OrderedCollection.prototype.remove = function (elm) { + var index = 0, skipped = 0; + for (var i = 0; i < this.elms.length; i++) { + var value = this.elms[i]; + if (value != elm) { + this.elms[index] = value; + index++; + } else { + skipped++; + } + } + for (var i = 0; i < skipped; i++) + this.elms.pop(); +} + +/* --- * + * S t r e n g t h + * --- */ + +/** + * Strengths are used to measure the relative importance of constraints. + * New strengths may be inserted in the strength hierarchy without + * disrupting current constraints. Strengths cannot be created outside + * this class, so pointer comparison can be used for value comparison. + */ +function Strength(strengthValue, name) { + this.strengthValue = strengthValue; + this.name = name; +} + +Strength.stronger = function (s1, s2) { + return s1.strengthValue < s2.strengthValue; +} + +Strength.weaker = function (s1, s2) { + return s1.strengthValue > s2.strengthValue; +} + +Strength.weakestOf = function (s1, s2) { + return this.weaker(s1, s2) ? s1 : s2; +} + +Strength.strongest = function (s1, s2) { + return this.stronger(s1, s2) ? s1 : s2; +} + +Strength.prototype.nextWeaker = function () { + switch (this.strengthValue) { + case 0: return Strength.WEAKEST; + case 1: return Strength.WEAK_DEFAULT; + case 2: return Strength.NORMAL; + case 3: return Strength.STRONG_DEFAULT; + case 4: return Strength.PREFERRED; + case 5: return Strength.REQUIRED; + } +} + +// Strength constants. +Strength.REQUIRED = new Strength(0, "required"); +Strength.STONG_PREFERRED = new Strength(1, "strongPreferred"); +Strength.PREFERRED = new Strength(2, "preferred"); +Strength.STRONG_DEFAULT = new Strength(3, "strongDefault"); +Strength.NORMAL = new Strength(4, "normal"); +Strength.WEAK_DEFAULT = new Strength(5, "weakDefault"); +Strength.WEAKEST = new Strength(6, "weakest"); + +/* --- * + * C o n s t r a i n t + * --- */ + +/** + * An abstract class representing a system-maintainable relationship + * (or "constraint") between a set of variables. A constraint supplies + * a strength instance variable; concrete subclasses provide a means + * of storing the constrained variables and other information required + * to represent a constraint. + */ +function Constraint(strength) { + this.strength = strength; +} + +/** + * Activate this constraint and attempt to satisfy it. + */ +Constraint.prototype.addConstraint = function () { + this.addToGraph(); + planner.incrementalAdd(this); +} + +/** + * Attempt to find a way to enforce this constraint. If successful, + * record the solution, perhaps modifying the current dataflow + * graph. Answer the constraint that this constraint overrides, if + * there is one, or nil, if there isn't. + * Assume: I am not already satisfied. + */ +Constraint.prototype.satisfy = function (mark) { + this.chooseMethod(mark); + if (!this.isSatisfied()) { + if (this.strength == Strength.REQUIRED) + alert("Could not satisfy a required constraint!"); + return null; + } + this.markInputs(mark); + var out = this.output(); + var overridden = out.determinedBy; + if (overridden != null) overridden.markUnsatisfied(); + out.determinedBy = this; + if (!planner.addPropagate(this, mark)) + alert("Cycle encountered"); + out.mark = mark; + return overridden; +} + +Constraint.prototype.destroyConstraint = function () { + if (this.isSatisfied()) planner.incrementalRemove(this); + else this.removeFromGraph(); +} + +/** + * Normal constraints are not input constraints. An input constraint + * is one that depends on external state, such as the mouse, the + * keybord, a clock, or some arbitraty piece of imperative code. + */ +Constraint.prototype.isInput = function () { + return false; +} + +/* --- * + * U n a r y C o n s t r a i n t + * --- */ + +/** + * Abstract superclass for constraints having a single possible output + * variable. + */ +function UnaryConstraint(v, strength) { + UnaryConstraint.superConstructor.call(this, strength); + this.myOutput = v; + this.satisfied = false; + this.addConstraint(); +} + +UnaryConstraint.inherits(Constraint); + +/** + * Adds this constraint to the constraint graph + */ +UnaryConstraint.prototype.addToGraph = function () { + this.myOutput.addConstraint(this); + this.satisfied = false; +} + +/** + * Decides if this constraint can be satisfied and records that + * decision. + */ +UnaryConstraint.prototype.chooseMethod = function (mark) { + this.satisfied = (this.myOutput.mark != mark) + && Strength.stronger(this.strength, this.myOutput.walkStrength); +} + +/** + * Returns true if this constraint is satisfied in the current solution. + */ +UnaryConstraint.prototype.isSatisfied = function () { + return this.satisfied; +} + +UnaryConstraint.prototype.markInputs = function (mark) { + // has no inputs +} + +/** + * Returns the current output variable. + */ +UnaryConstraint.prototype.output = function () { + return this.myOutput; +} + +/** + * Calculate the walkabout strength, the stay flag, and, if it is + * 'stay', the value for the current output of this constraint. Assume + * this constraint is satisfied. + */ +UnaryConstraint.prototype.recalculate = function () { + this.myOutput.walkStrength = this.strength; + this.myOutput.stay = !this.isInput(); + if (this.myOutput.stay) this.execute(); // Stay optimization +} + +/** + * Records that this constraint is unsatisfied + */ +UnaryConstraint.prototype.markUnsatisfied = function () { + this.satisfied = false; +} + +UnaryConstraint.prototype.inputsKnown = function () { + return true; +} + +UnaryConstraint.prototype.removeFromGraph = function () { + if (this.myOutput != null) this.myOutput.removeConstraint(this); + this.satisfied = false; +} + +/* --- * + * S t a y C o n s t r a i n t + * --- */ + +/** + * Variables that should, with some level of preference, stay the same. + * Planners may exploit the fact that instances, if satisfied, will not + * change their output during plan execution. This is called "stay + * optimization". + */ +function StayConstraint(v, str) { + StayConstraint.superConstructor.call(this, v, str); +} + +StayConstraint.inherits(UnaryConstraint); + +StayConstraint.prototype.execute = function () { + // Stay constraints do nothing +} + +/* --- * + * E d i t C o n s t r a i n t + * --- */ + +/** + * A unary input constraint used to mark a variable that the client + * wishes to change. + */ +function EditConstraint(v, str) { + EditConstraint.superConstructor.call(this, v, str); +} + +EditConstraint.inherits(UnaryConstraint); + +/** + * Edits indicate that a variable is to be changed by imperative code. + */ +EditConstraint.prototype.isInput = function () { + return true; +} + +EditConstraint.prototype.execute = function () { + // Edit constraints do nothing +} + +/* --- * + * B i n a r y C o n s t r a i n t + * --- */ + +var Direction = new Object(); +Direction.NONE = 0; +Direction.FORWARD = 1; +Direction.BACKWARD = -1; + +/** + * Abstract superclass for constraints having two possible output + * variables. + */ +function BinaryConstraint(var1, var2, strength) { + BinaryConstraint.superConstructor.call(this, strength); + this.v1 = var1; + this.v2 = var2; + this.direction = Direction.NONE; + this.addConstraint(); +} + +BinaryConstraint.inherits(Constraint); + +/** + * Decides if this constratint can be satisfied and which way it + * should flow based on the relative strength of the variables related, + * and record that decision. + */ +BinaryConstraint.prototype.chooseMethod = function (mark) { + if (this.v1.mark == mark) { + this.direction = (this.v1.mark != mark && Strength.stronger(this.strength, this.v2.walkStrength)) + ? Direction.FORWARD + : Direction.NONE; + } + if (this.v2.mark == mark) { + this.direction = (this.v1.mark != mark && Strength.stronger(this.strength, this.v1.walkStrength)) + ? Direction.BACKWARD + : Direction.NONE; + } + if (Strength.weaker(this.v1.walkStrength, this.v2.walkStrength)) { + this.direction = Strength.stronger(this.strength, this.v1.walkStrength) + ? Direction.BACKWARD + : Direction.NONE; + } else { + this.direction = Strength.stronger(this.strength, this.v2.walkStrength) + ? Direction.FORWARD + : Direction.BACKWARD + } +} + +/** + * Add this constraint to the constraint graph + */ +BinaryConstraint.prototype.addToGraph = function () { + this.v1.addConstraint(this); + this.v2.addConstraint(this); + this.direction = Direction.NONE; +} + +/** + * Answer true if this constraint is satisfied in the current solution. + */ +BinaryConstraint.prototype.isSatisfied = function () { + return this.direction != Direction.NONE; +} + +/** + * Mark the input variable with the given mark. + */ +BinaryConstraint.prototype.markInputs = function (mark) { + this.input().mark = mark; +} + +/** + * Returns the current input variable + */ +BinaryConstraint.prototype.input = function () { + return (this.direction == Direction.FORWARD) ? this.v1 : this.v2; +} + +/** + * Returns the current output variable + */ +BinaryConstraint.prototype.output = function () { + return (this.direction == Direction.FORWARD) ? this.v2 : this.v1; +} + +/** + * Calculate the walkabout strength, the stay flag, and, if it is + * 'stay', the value for the current output of this + * constraint. Assume this constraint is satisfied. + */ +BinaryConstraint.prototype.recalculate = function () { + var ihn = this.input(), out = this.output(); + out.walkStrength = Strength.weakestOf(this.strength, ihn.walkStrength); + out.stay = ihn.stay; + if (out.stay) this.execute(); +} + +/** + * Record the fact that this constraint is unsatisfied. + */ +BinaryConstraint.prototype.markUnsatisfied = function () { + this.direction = Direction.NONE; +} + +BinaryConstraint.prototype.inputsKnown = function (mark) { + var i = this.input(); + return i.mark == mark || i.stay || i.determinedBy == null; +} + +BinaryConstraint.prototype.removeFromGraph = function () { + if (this.v1 != null) this.v1.removeConstraint(this); + if (this.v2 != null) this.v2.removeConstraint(this); + this.direction = Direction.NONE; +} + +/* --- * + * S c a l e C o n s t r a i n t + * --- */ + +/** + * Relates two variables by the linear scaling relationship: "v2 = + * (v1 * scale) + offset". Either v1 or v2 may be changed to maintain + * this relationship but the scale factor and offset are considered + * read-only. + */ +function ScaleConstraint(src, scale, offset, dest, strength) { + this.direction = Direction.NONE; + this.scale = scale; + this.offset = offset; + ScaleConstraint.superConstructor.call(this, src, dest, strength); +} + +ScaleConstraint.inherits(BinaryConstraint); + +/** + * Adds this constraint to the constraint graph. + */ +ScaleConstraint.prototype.addToGraph = function () { + ScaleConstraint.superConstructor.prototype.addToGraph.call(this); + this.scale.addConstraint(this); + this.offset.addConstraint(this); +} + +ScaleConstraint.prototype.removeFromGraph = function () { + ScaleConstraint.superConstructor.prototype.removeFromGraph.call(this); + if (this.scale != null) this.scale.removeConstraint(this); + if (this.offset != null) this.offset.removeConstraint(this); +} + +ScaleConstraint.prototype.markInputs = function (mark) { + ScaleConstraint.superConstructor.prototype.markInputs.call(this, mark); + this.scale.mark = this.offset.mark = mark; +} + +/** + * Enforce this constraint. Assume that it is satisfied. + */ +ScaleConstraint.prototype.execute = function () { + if (this.direction == Direction.FORWARD) { + this.v2.value = this.v1.value * this.scale.value + this.offset.value; + } else { + this.v1.value = (this.v2.value - this.offset.value) / this.scale.value; + } +} + +/** + * Calculate the walkabout strength, the stay flag, and, if it is + * 'stay', the value for the current output of this constraint. Assume + * this constraint is satisfied. + */ +ScaleConstraint.prototype.recalculate = function () { + var ihn = this.input(), out = this.output(); + out.walkStrength = Strength.weakestOf(this.strength, ihn.walkStrength); + out.stay = ihn.stay && this.scale.stay && this.offset.stay; + if (out.stay) this.execute(); +} + +/* --- * + * E q u a l i t y C o n s t r a i n t + * --- */ + +/** + * Constrains two variables to have the same value. + */ +function EqualityConstraint(var1, var2, strength) { + EqualityConstraint.superConstructor.call(this, var1, var2, strength); +} + +EqualityConstraint.inherits(BinaryConstraint); + +/** + * Enforce this constraint. Assume that it is satisfied. + */ +EqualityConstraint.prototype.execute = function () { + this.output().value = this.input().value; +} + +/* --- * + * V a r i a b l e + * --- */ + +/** + * A constrained variable. In addition to its value, it maintain the + * structure of the constraint graph, the current dataflow graph, and + * various parameters of interest to the DeltaBlue incremental + * constraint solver. + **/ +function Variable(name, initialValue) { + this.value = initialValue || 0; + this.constraints = new OrderedCollection(); + this.determinedBy = null; + this.mark = 0; + this.walkStrength = Strength.WEAKEST; + this.stay = true; + this.name = name; +} + +/** + * Add the given constraint to the set of all constraints that refer + * this variable. + */ +Variable.prototype.addConstraint = function (c) { + this.constraints.add(c); +} + +/** + * Removes all traces of c from this variable. + */ +Variable.prototype.removeConstraint = function (c) { + this.constraints.remove(c); + if (this.determinedBy == c) this.determinedBy = null; +} + +/* --- * + * P l a n n e r + * --- */ + +/** + * The DeltaBlue planner + */ +function Planner() { + this.currentMark = 0; +} + +/** + * Attempt to satisfy the given constraint and, if successful, + * incrementally update the dataflow graph. Details: If satifying + * the constraint is successful, it may override a weaker constraint + * on its output. The algorithm attempts to resatisfy that + * constraint using some other method. This process is repeated + * until either a) it reaches a variable that was not previously + * determined by any constraint or b) it reaches a constraint that + * is too weak to be satisfied using any of its methods. The + * variables of constraints that have been processed are marked with + * a unique mark value so that we know where we've been. This allows + * the algorithm to avoid getting into an infinite loop even if the + * constraint graph has an inadvertent cycle. + */ +Planner.prototype.incrementalAdd = function (c) { + var mark = this.newMark(); + var overridden = c.satisfy(mark); + while (overridden != null) + overridden = overridden.satisfy(mark); +} + +/** + * Entry point for retracting a constraint. Remove the given + * constraint and incrementally update the dataflow graph. + * Details: Retracting the given constraint may allow some currently + * unsatisfiable downstream constraint to be satisfied. We therefore collect + * a list of unsatisfied downstream constraints and attempt to + * satisfy each one in turn. This list is traversed by constraint + * strength, strongest first, as a heuristic for avoiding + * unnecessarily adding and then overriding weak constraints. + * Assume: c is satisfied. + */ +Planner.prototype.incrementalRemove = function (c) { + var out = c.output(); + c.markUnsatisfied(); + c.removeFromGraph(); + var unsatisfied = this.removePropagateFrom(out); + var strength = Strength.REQUIRED; + do { + for (var i = 0; i < unsatisfied.size(); i++) { + var u = unsatisfied.at(i); + if (u.strength == strength) + this.incrementalAdd(u); + } + strength = strength.nextWeaker(); + } while (strength != Strength.WEAKEST); +} + +/** + * Select a previously unused mark value. + */ +Planner.prototype.newMark = function () { + return ++this.currentMark; +} + +/** + * Extract a plan for resatisfaction starting from the given source + * constraints, usually a set of input constraints. This method + * assumes that stay optimization is desired; the plan will contain + * only constraints whose output variables are not stay. Constraints + * that do no computation, such as stay and edit constraints, are + * not included in the plan. + * Details: The outputs of a constraint are marked when it is added + * to the plan under construction. A constraint may be appended to + * the plan when all its input variables are known. A variable is + * known if either a) the variable is marked (indicating that has + * been computed by a constraint appearing earlier in the plan), b) + * the variable is 'stay' (i.e. it is a constant at plan execution + * time), or c) the variable is not determined by any + * constraint. The last provision is for past states of history + * variables, which are not stay but which are also not computed by + * any constraint. + * Assume: sources are all satisfied. + */ +Planner.prototype.makePlan = function (sources) { + var mark = this.newMark(); + var plan = new Plan(); + var todo = sources; + while (todo.size() > 0) { + var c = todo.removeFirst(); + if (c.output().mark != mark && c.inputsKnown(mark)) { + plan.addConstraint(c); + c.output().mark = mark; + this.addConstraintsConsumingTo(c.output(), todo); + } + } + return plan; +} + +/** + * Extract a plan for resatisfying starting from the output of the + * given constraints, usually a set of input constraints. + */ +Planner.prototype.extractPlanFromConstraints = function (constraints) { + var sources = new OrderedCollection(); + for (var i = 0; i < constraints.size(); i++) { + var c = constraints.at(i); + if (c.isInput() && c.isSatisfied()) + // not in plan already and eligible for inclusion + sources.add(c); + } + return this.makePlan(sources); +} + +/** + * Recompute the walkabout strengths and stay flags of all variables + * downstream of the given constraint and recompute the actual + * values of all variables whose stay flag is true. If a cycle is + * detected, remove the given constraint and answer + * false. Otherwise, answer true. + * Details: Cycles are detected when a marked variable is + * encountered downstream of the given constraint. The sender is + * assumed to have marked the inputs of the given constraint with + * the given mark. Thus, encountering a marked node downstream of + * the output constraint means that there is a path from the + * constraint's output to one of its inputs. + */ +Planner.prototype.addPropagate = function (c, mark) { + var todo = new OrderedCollection(); + todo.add(c); + while (todo.size() > 0) { + var d = todo.removeFirst(); + if (d.output().mark == mark) { + this.incrementalRemove(c); + return false; + } + d.recalculate(); + this.addConstraintsConsumingTo(d.output(), todo); + } + return true; +} + + +/** + * Update the walkabout strengths and stay flags of all variables + * downstream of the given constraint. Answer a collection of + * unsatisfied constraints sorted in order of decreasing strength. + */ +Planner.prototype.removePropagateFrom = function (out) { + out.determinedBy = null; + out.walkStrength = Strength.WEAKEST; + out.stay = true; + var unsatisfied = new OrderedCollection(); + var todo = new OrderedCollection(); + todo.add(out); + while (todo.size() > 0) { + var v = todo.removeFirst(); + for (var i = 0; i < v.constraints.size(); i++) { + var c = v.constraints.at(i); + if (!c.isSatisfied()) + unsatisfied.add(c); + } + var determining = v.determinedBy; + for (var i = 0; i < v.constraints.size(); i++) { + var next = v.constraints.at(i); + if (next != determining && next.isSatisfied()) { + next.recalculate(); + todo.add(next.output()); + } + } + } + return unsatisfied; +} + +Planner.prototype.addConstraintsConsumingTo = function (v, coll) { + var determining = v.determinedBy; + var cc = v.constraints; + for (var i = 0; i < cc.size(); i++) { + var c = cc.at(i); + if (c != determining && c.isSatisfied()) + coll.add(c); + } +} + +/* --- * + * P l a n + * --- */ + +/** + * A Plan is an ordered list of constraints to be executed in sequence + * to resatisfy all currently satisfiable constraints in the face of + * one or more changing inputs. + */ +function Plan() { + this.v = new OrderedCollection(); +} + +Plan.prototype.addConstraint = function (c) { + this.v.add(c); +} + +Plan.prototype.size = function () { + return this.v.size(); +} + +Plan.prototype.constraintAt = function (index) { + return this.v.at(index); +} + +Plan.prototype.execute = function () { + for (var i = 0; i < this.size(); i++) { + var c = this.constraintAt(i); + c.execute(); + } +} + +/* --- * + * M a i n + * --- */ + +/** + * This is the standard DeltaBlue benchmark. A long chain of equality + * constraints is constructed with a stay constraint on one end. An + * edit constraint is then added to the opposite end and the time is + * measured for adding and removing this constraint, and extracting + * and executing a constraint satisfaction plan. There are two cases. + * In case 1, the added constraint is stronger than the stay + * constraint and values must propagate down the entire length of the + * chain. In case 2, the added constraint is weaker than the stay + * constraint so it cannot be accomodated. The cost in this case is, + * of course, very low. Typical situations lie somewhere between these + * two extremes. + */ +function chainTest(n) { + planner = new Planner(); + var prev = null, first = null, last = null; + + // Build chain of n equality constraints + for (var i = 0; i <= n; i++) { + var name = "v" + i; + var v = new Variable(name); + if (prev != null) + new EqualityConstraint(prev, v, Strength.REQUIRED); + if (i == 0) first = v; + if (i == n) last = v; + prev = v; + } + + new StayConstraint(last, Strength.STRONG_DEFAULT); + var edit = new EditConstraint(first, Strength.PREFERRED); + var edits = new OrderedCollection(); + edits.add(edit); + var plan = planner.extractPlanFromConstraints(edits); + for (var i = 0; i < 100; i++) { + first.value = i; + plan.execute(); + if (last.value != i) + alert("Chain test failed."); + } +} + +/** + * This test constructs a two sets of variables related to each + * other by a simple linear transformation (scale and offset). The + * time is measured to change a variable on either side of the + * mapping and to change the scale and offset factors. + */ +function projectionTest(n) { + planner = new Planner(); + var scale = new Variable("scale", 10); + var offset = new Variable("offset", 1000); + var src = null, dst = null; + + var dests = new OrderedCollection(); + for (var i = 0; i < n; i++) { + src = new Variable("src" + i, i); + dst = new Variable("dst" + i, i); + dests.add(dst); + new StayConstraint(src, Strength.NORMAL); + new ScaleConstraint(src, scale, offset, dst, Strength.REQUIRED); + } + + change(src, 17); + if (dst.value != 1170) alert("Projection 1 failed"); + change(dst, 1050); + if (src.value != 5) alert("Projection 2 failed"); + change(scale, 5); + for (var i = 0; i < n - 1; i++) { + if (dests.at(i).value != i * 5 + 1000) + alert("Projection 3 failed"); + } + change(offset, 2000); + for (var i = 0; i < n - 1; i++) { + if (dests.at(i).value != i * 5 + 2000) + alert("Projection 4 failed"); + } +} + +function change(v, newValue) { + var edit = new EditConstraint(v, Strength.PREFERRED); + var edits = new OrderedCollection(); + edits.add(edit); + var plan = planner.extractPlanFromConstraints(edits); + for (var i = 0; i < 10; i++) { + v.value = newValue; + plan.execute(); + } + edit.destroyConstraint(); +} + +// Global variable holding the current planner. +var planner = null; + +function deltaBlue() { + chainTest(100); + projectionTest(100); +} diff --git a/deps/v8/benchmarks/earley-boyer.js b/deps/v8/benchmarks/earley-boyer.js new file mode 100644 index 0000000000..9016a137a1 --- /dev/null +++ b/deps/v8/benchmarks/earley-boyer.js @@ -0,0 +1,4685 @@ +// This file is automatically generated by scheme2js, except for the +// benchmark harness code at the beginning and end of the file. + +var EarleyBoyer = new BenchmarkSuite('EarleyBoyer', 765819, [ + new Benchmark("Earley", function () { BgL_earleyzd2benchmarkzd2(); }), + new Benchmark("Boyer", function () { BgL_nboyerzd2benchmarkzd2(); }) +]); + + +/************* GENERATED FILE - DO NOT EDIT *************/ +/************* GENERATED FILE - DO NOT EDIT *************/ +/************* GENERATED FILE - DO NOT EDIT *************/ +/************* GENERATED FILE - DO NOT EDIT *************/ +/************* GENERATED FILE - DO NOT EDIT *************/ +/************* GENERATED FILE - DO NOT EDIT *************/ +/************* GENERATED FILE - DO NOT EDIT *************/ +/************* GENERATED FILE - DO NOT EDIT *************/ +/* + * To use write/prints/... the default-output port has to be set first. + * Simply setting SC_DEFAULT_OUT and SC_ERROR_OUT to the desired values + * should do the trick. + * In the following example the std-out and error-port are redirected to + * a DIV. +function initRuntime() { + function escapeHTML(s) { + var tmp = s; + tmp = tmp.replace(/&/g, "&"); + tmp = tmp.replace(//g, ">"); + tmp = tmp.replace(/ /g, " "); + tmp = tmp.replace(/\n/g, "
"); + tmp = tmp.replace(/\t/g, "    "); + return tmp; + + } + + document.write("
"); + SC_DEFAULT_OUT = new sc_GenericOutputPort( + function(s) { + var stdout = document.getElementById('stdout'); + stdout.innerHTML = stdout.innerHTML + escapeHTML(s); + }); + SC_ERROR_OUT = SC_DEFAULT_OUT; +} +*/ + + +function sc_print_debug() { + sc_print.apply(null, arguments); +} +/*** META ((export *js*)) */ +var sc_JS_GLOBALS = this; + +var __sc_LINE=-1; +var __sc_FILE=""; + +/*** META ((export #t)) */ +function sc_alert() { + var len = arguments.length; + var s = ""; + var i; + + for( i = 0; i < len; i++ ) { + s += sc_toDisplayString(arguments[ i ]); + } + + return alert( s ); +} + +/*** META ((export #t)) */ +function sc_typeof( x ) { + return typeof x; +} + +/*** META ((export #t)) */ +function sc_error() { + var a = [sc_jsstring2symbol("*error*")]; + for (var i = 0; i < arguments.length; i++) { + a[i+1] = arguments[i]; + } + throw a; +} + +/*** META ((export #t) + (peephole (prefix "throw "))) +*/ +function sc_raise(obj) { + throw obj; +} + +/*** META ((export with-handler-lambda)) */ +function sc_withHandlerLambda(handler, body) { + try { + return body(); + } catch(e) { + if (!e._internalException) + return handler(e); + else + throw e; + } +} + +var sc_properties = new Object(); + +/*** META ((export #t)) */ +function sc_putpropBang(sym, key, val) { + var ht = sc_properties[sym]; + if (!ht) { + ht = new Object(); + sc_properties[sym] = ht; + } + ht[key] = val; +} + +/*** META ((export #t)) */ +function sc_getprop(sym, key) { + var ht = sc_properties[sym]; + if (ht) { + if (key in ht) + return ht[key]; + else + return false; + } else + return false; +} + +/*** META ((export #t)) */ +function sc_rempropBang(sym, key) { + var ht = sc_properties[sym]; + if (ht) + delete ht[key]; +} + +/*** META ((export #t)) */ +function sc_any2String(o) { + return jsstring2string(sc_toDisplayString(o)); +} + +/*** META ((export #t) + (peephole (infix 2 2 "===")) + (type bool)) +*/ +function sc_isEqv(o1, o2) { + return (o1 === o2); +} + +/*** META ((export #t) + (peephole (infix 2 2 "===")) + (type bool)) +*/ +function sc_isEq(o1, o2) { + return (o1 === o2); +} + +/*** META ((export #t) + (type bool)) +*/ +function sc_isNumber(n) { + return (typeof n === "number"); +} + +/*** META ((export #t) + (type bool)) +*/ +function sc_isComplex(n) { + return sc_isNumber(n); +} + +/*** META ((export #t) + (type bool)) +*/ +function sc_isReal(n) { + return sc_isNumber(n); +} + +/*** META ((export #t) + (type bool)) +*/ +function sc_isRational(n) { + return sc_isReal(n); +} + +/*** META ((export #t) + (type bool)) +*/ +function sc_isInteger(n) { + return (parseInt(n) === n); +} + +/*** META ((export #t) + (type bool) + (peephole (postfix ", false"))) +*/ +// we don't have exact numbers... +function sc_isExact(n) { + return false; +} + +/*** META ((export #t) + (peephole (postfix ", true")) + (type bool)) +*/ +function sc_isInexact(n) { + return true; +} + +/*** META ((export = =fx =fl) + (type bool) + (peephole (infix 2 2 "==="))) +*/ +function sc_equal(x) { + for (var i = 1; i < arguments.length; i++) + if (x !== arguments[i]) + return false; + return true; +} + +/*** META ((export < = arguments[i]) + return false; + x = arguments[i]; + } + return true; +} + +/*** META ((export > >fx >fl) + (type bool) + (peephole (infix 2 2 ">"))) +*/ +function sc_greater(x, y) { + for (var i = 1; i < arguments.length; i++) { + if (x <= arguments[i]) + return false; + x = arguments[i]; + } + return true; +} + +/*** META ((export <= <=fx <=fl) + (type bool) + (peephole (infix 2 2 "<="))) +*/ +function sc_lessEqual(x, y) { + for (var i = 1; i < arguments.length; i++) { + if (x > arguments[i]) + return false; + x = arguments[i]; + } + return true; +} + +/*** META ((export >= >=fl >=fx) + (type bool) + (peephole (infix 2 2 ">="))) +*/ +function sc_greaterEqual(x, y) { + for (var i = 1; i < arguments.length; i++) { + if (x < arguments[i]) + return false; + x = arguments[i]; + } + return true; +} + +/*** META ((export #t) + (type bool) + (peephole (postfix "=== 0"))) +*/ +function sc_isZero(x) { + return (x === 0); +} + +/*** META ((export #t) + (type bool) + (peephole (postfix "> 0"))) +*/ +function sc_isPositive(x) { + return (x > 0); +} + +/*** META ((export #t) + (type bool) + (peephole (postfix "< 0"))) +*/ +function sc_isNegative(x) { + return (x < 0); +} + +/*** META ((export #t) + (type bool) + (peephole (postfix "%2===1"))) +*/ +function sc_isOdd(x) { + return (x % 2 === 1); +} + +/*** META ((export #t) + (type bool) + (peephole (postfix "%2===0"))) +*/ +function sc_isEven(x) { + return (x % 2 === 0); +} + +/*** META ((export #t)) */ +var sc_max = Math.max; +/*** META ((export #t)) */ +var sc_min = Math.min; + +/*** META ((export + +fx +fl) + (peephole (infix 0 #f "+" "0"))) +*/ +function sc_plus() { + var sum = 0; + for (var i = 0; i < arguments.length; i++) + sum += arguments[i]; + return sum; +} + +/*** META ((export * *fx *fl) + (peephole (infix 0 #f "*" "1"))) +*/ +function sc_multi() { + var product = 1; + for (var i = 0; i < arguments.length; i++) + product *= arguments[i]; + return product; +} + +/*** META ((export - -fx -fl) + (peephole (minus))) +*/ +function sc_minus(x) { + if (arguments.length === 1) + return -x; + else { + var res = x; + for (var i = 1; i < arguments.length; i++) + res -= arguments[i]; + return res; + } +} + +/*** META ((export / /fl) + (peephole (div))) +*/ +function sc_div(x) { + if (arguments.length === 1) + return 1/x; + else { + var res = x; + for (var i = 1; i < arguments.length; i++) + res /= arguments[i]; + return res; + } +} + +/*** META ((export #t)) */ +var sc_abs = Math.abs; + +/*** META ((export quotient /fx) + (peephole (hole 2 "parseInt(" x "/" y ")"))) +*/ +function sc_quotient(x, y) { + return parseInt(x / y); +} + +/*** META ((export #t) + (peephole (infix 2 2 "%"))) +*/ +function sc_remainder(x, y) { + return x % y; +} + +/*** META ((export #t) + (peephole (modulo))) +*/ +function sc_modulo(x, y) { + var remainder = x % y; + // if they don't have the same sign + if ((remainder * y) < 0) + return remainder + y; + else + return remainder; +} + +function sc_euclid_gcd(a, b) { + var temp; + if (a === 0) return b; + if (b === 0) return a; + if (a < 0) {a = -a;}; + if (b < 0) {b = -b;}; + if (b > a) {temp = a; a = b; b = temp;}; + while (true) { + a %= b; + if(a === 0) {return b;}; + b %= a; + if(b === 0) {return a;}; + }; + return b; +} + +/*** META ((export #t)) */ +function sc_gcd() { + var gcd = 0; + for (var i = 0; i < arguments.length; i++) + gcd = sc_euclid_gcd(gcd, arguments[i]); + return gcd; +} + +/*** META ((export #t)) */ +function sc_lcm() { + var lcm = 1; + for (var i = 0; i < arguments.length; i++) { + var f = Math.round(arguments[i] / sc_euclid_gcd(arguments[i], lcm)); + lcm *= Math.abs(f); + } + return lcm; +} + +// LIMITATION: numerator and denominator don't make sense in floating point world. +//var SC_MAX_DECIMALS = 1000000 +// +// function sc_numerator(x) { +// var rounded = Math.round(x * SC_MAX_DECIMALS); +// return Math.round(rounded / sc_euclid_gcd(rounded, SC_MAX_DECIMALS)); +// } + +// function sc_denominator(x) { +// var rounded = Math.round(x * SC_MAX_DECIMALS); +// return Math.round(SC_MAX_DECIMALS / sc_euclid_gcd(rounded, SC_MAX_DECIMALS)); +// } + +/*** META ((export #t)) */ +var sc_floor = Math.floor; +/*** META ((export #t)) */ +var sc_ceiling = Math.ceil; +/*** META ((export #t)) */ +var sc_truncate = parseInt; +/*** META ((export #t)) */ +var sc_round = Math.round; + +// LIMITATION: sc_rationalize doesn't make sense in a floating point world. + +/*** META ((export #t)) */ +var sc_exp = Math.exp; +/*** META ((export #t)) */ +var sc_log = Math.log; +/*** META ((export #t)) */ +var sc_sin = Math.sin; +/*** META ((export #t)) */ +var sc_cos = Math.cos; +/*** META ((export #t)) */ +var sc_tan = Math.tan; +/*** META ((export #t)) */ +var sc_asin = Math.asin; +/*** META ((export #t)) */ +var sc_acos = Math.acos; +/*** META ((export #t)) */ +var sc_atan = Math.atan; + +/*** META ((export #t)) */ +var sc_sqrt = Math.sqrt; +/*** META ((export #t)) */ +var sc_expt = Math.pow; + +// LIMITATION: we don't have complex numbers. +// LIMITATION: the following functions are hence not implemented. +// LIMITATION: make-rectangular, make-polar, real-part, imag-part, magnitude, angle +// LIMITATION: 2 argument atan + +/*** META ((export #t) + (peephole (id))) +*/ +function sc_exact2inexact(x) { + return x; +} + +/*** META ((export #t) + (peephole (id))) +*/ +function sc_inexact2exact(x) { + return x; +} + +function sc_number2jsstring(x, radix) { + if (radix) + return x.toString(radix); + else + return x.toString(); +} + +function sc_jsstring2number(s, radix) { + if (s === "") return false; + + if (radix) { + var t = parseInt(s, radix); + if (!t && t !== 0) return false; + // verify that each char is in range. (parseInt ignores leading + // white and trailing chars) + var allowedChars = "01234567890abcdefghijklmnopqrstuvwxyz".substring(0, radix+1); + if ((new RegExp("^["+allowedChars+"]*$", "i")).test(s)) + return t; + else return false; + } else { + var t = +s; // does not ignore trailing chars. + if (!t && t !== 0) return false; + // simply verify that first char is not whitespace. + var c = s.charAt(0); + // if +c is 0, but the char is not "0", then we have a whitespace. + if (+c === 0 && c !== "0") return false; + return t; + } +} + +/*** META ((export #t) + (type bool) + (peephole (not))) +*/ +function sc_not(b) { + return b === false; +} + +/*** META ((export #t) + (type bool)) +*/ +function sc_isBoolean(b) { + return (b === true) || (b === false); +} + +function sc_Pair(car, cdr) { + this.car = car; + this.cdr = cdr; +} + +sc_Pair.prototype.toString = function() { + return sc_toDisplayString(this); +}; +sc_Pair.prototype.sc_toWriteOrDisplayString = function(writeOrDisplay) { + var current = this; + + var res = "("; + + while(true) { + res += writeOrDisplay(current.car); + if (sc_isPair(current.cdr)) { + res += " "; + current = current.cdr; + } else if (current.cdr !== null) { + res += " . " + writeOrDisplay(current.cdr); + break; + } else // current.cdr == null + break; + } + + res += ")"; + + return res; +}; +sc_Pair.prototype.sc_toDisplayString = function() { + return this.sc_toWriteOrDisplayString(sc_toDisplayString); +}; +sc_Pair.prototype.sc_toWriteString = function() { + return this.sc_toWriteOrDisplayString(sc_toWriteString); +}; +// sc_Pair.prototype.sc_toWriteCircleString in IO.js + +/*** META ((export #t) + (type bool) + (peephole (postfix " instanceof sc_Pair"))) +*/ +function sc_isPair(p) { + return (p instanceof sc_Pair); +} + +function sc_isPairEqual(p1, p2, comp) { + return (comp(p1.car, p2.car) && comp(p1.cdr, p2.cdr)); +} + +/*** META ((export #t) + (peephole (hole 2 "new sc_Pair(" car ", " cdr ")"))) +*/ +function sc_cons(car, cdr) { + return new sc_Pair(car, cdr); +} + +/*** META ((export cons*)) */ +function sc_consStar() { + var res = arguments[arguments.length - 1]; + for (var i = arguments.length-2; i >= 0; i--) + res = new sc_Pair(arguments[i], res); + return res; +} + +/*** META ((export #t) + (peephole (postfix ".car"))) +*/ +function sc_car(p) { + return p.car; +} + +/*** META ((export #t) + (peephole (postfix ".cdr"))) +*/ +function sc_cdr(p) { + return p.cdr; +} + +/*** META ((export #t) + (peephole (hole 2 p ".car = " val))) +*/ +function sc_setCarBang(p, val) { + p.car = val; +} + +/*** META ((export #t) + (peephole (hole 2 p ".cdr = " val))) +*/ +function sc_setCdrBang(p, val) { + p.cdr = val; +} + +/*** META ((export #t) + (peephole (postfix ".car.car"))) +*/ +function sc_caar(p) { return p.car.car; } +/*** META ((export #t) + (peephole (postfix ".cdr.car"))) +*/ +function sc_cadr(p) { return p.cdr.car; } +/*** META ((export #t) + (peephole (postfix ".car.cdr"))) +*/ +function sc_cdar(p) { return p.car.cdr; } +/*** META ((export #t) + (peephole (postfix ".cdr.cdr"))) +*/ +function sc_cddr(p) { return p.cdr.cdr; } +/*** META ((export #t) + (peephole (postfix ".car.car.car"))) +*/ +function sc_caaar(p) { return p.car.car.car; } +/*** META ((export #t) + (peephole (postfix ".car.cdr.car"))) +*/ +function sc_cadar(p) { return p.car.cdr.car; } +/*** META ((export #t) + (peephole (postfix ".cdr.car.car"))) +*/ +function sc_caadr(p) { return p.cdr.car.car; } +/*** META ((export #t) + (peephole (postfix ".cdr.cdr.car"))) +*/ +function sc_caddr(p) { return p.cdr.cdr.car; } +/*** META ((export #t) + (peephole (postfix ".car.car.cdr"))) +*/ +function sc_cdaar(p) { return p.car.car.cdr; } +/*** META ((export #t) + (peephole (postfix ".cdr.car.cdr"))) +*/ +function sc_cdadr(p) { return p.cdr.car.cdr; } +/*** META ((export #t) + (peephole (postfix ".car.cdr.cdr"))) +*/ +function sc_cddar(p) { return p.car.cdr.cdr; } +/*** META ((export #t) + (peephole (postfix ".cdr.cdr.cdr"))) +*/ +function sc_cdddr(p) { return p.cdr.cdr.cdr; } +/*** META ((export #t) + (peephole (postfix ".car.car.car.car"))) +*/ +function sc_caaaar(p) { return p.car.car.car.car; } +/*** META ((export #t) + (peephole (postfix ".car.cdr.car.car"))) +*/ +function sc_caadar(p) { return p.car.cdr.car.car; } +/*** META ((export #t) + (peephole (postfix ".cdr.car.car.car"))) +*/ +function sc_caaadr(p) { return p.cdr.car.car.car; } +/*** META ((export #t) + (peephole (postfix ".cdr.cdr.car.car"))) +*/ +function sc_caaddr(p) { return p.cdr.cdr.car.car; } +/*** META ((export #t) + (peephole (postfix ".car.car.car.cdr"))) +*/ +function sc_cdaaar(p) { return p.car.car.car.cdr; } +/*** META ((export #t) + (peephole (postfix ".car.cdr.car.cdr"))) +*/ +function sc_cdadar(p) { return p.car.cdr.car.cdr; } +/*** META ((export #t) + (peephole (postfix ".cdr.car.car.cdr"))) +*/ +function sc_cdaadr(p) { return p.cdr.car.car.cdr; } +/*** META ((export #t) + (peephole (postfix ".cdr.cdr.car.cdr"))) +*/ +function sc_cdaddr(p) { return p.cdr.cdr.car.cdr; } +/*** META ((export #t) + (peephole (postfix ".car.car.cdr.car"))) +*/ +function sc_cadaar(p) { return p.car.car.cdr.car; } +/*** META ((export #t) + (peephole (postfix ".car.cdr.cdr.car"))) +*/ +function sc_caddar(p) { return p.car.cdr.cdr.car; } +/*** META ((export #t) + (peephole (postfix ".cdr.car.cdr.car"))) +*/ +function sc_cadadr(p) { return p.cdr.car.cdr.car; } +/*** META ((export #t) + (peephole (postfix ".cdr.cdr.cdr.car"))) +*/ +function sc_cadddr(p) { return p.cdr.cdr.cdr.car; } +/*** META ((export #t) + (peephole (postfix ".car.car.cdr.cdr"))) +*/ +function sc_cddaar(p) { return p.car.car.cdr.cdr; } +/*** META ((export #t) + (peephole (postfix ".car.cdr.cdr.cdr"))) +*/ +function sc_cdddar(p) { return p.car.cdr.cdr.cdr; } +/*** META ((export #t) + (peephole (postfix ".cdr.car.cdr.cdr"))) +*/ +function sc_cddadr(p) { return p.cdr.car.cdr.cdr; } +/*** META ((export #t) + (peephole (postfix ".cdr.cdr.cdr.cdr"))) +*/ +function sc_cddddr(p) { return p.cdr.cdr.cdr.cdr; } + +/*** META ((export #t)) */ +function sc_lastPair(l) { + if (!sc_isPair(l)) sc_error("sc_lastPair: pair expected"); + var res = l; + var cdr = l.cdr; + while (sc_isPair(cdr)) { + res = cdr; + cdr = res.cdr; + } + return res; +} + +/*** META ((export #t) + (type bool) + (peephole (postfix " === null"))) +*/ +function sc_isNull(o) { + return (o === null); +} + +/*** META ((export #t) + (type bool)) +*/ +function sc_isList(o) { + var rabbit; + var turtle; + + var rabbit = o; + var turtle = o; + while (true) { + if (rabbit === null || + (rabbit instanceof sc_Pair && rabbit.cdr === null)) + return true; // end of list + else if ((rabbit instanceof sc_Pair) && + (rabbit.cdr instanceof sc_Pair)) { + rabbit = rabbit.cdr.cdr; + turtle = turtle.cdr; + if (rabbit === turtle) return false; // cycle + } else + return false; // not pair + } +} + +/*** META ((export #t)) */ +function sc_list() { + var res = null; + var a = arguments; + for (var i = a.length-1; i >= 0; i--) + res = new sc_Pair(a[i], res); + return res; +} + +/*** META ((export #t)) */ +function sc_iota(num, init) { + var res = null; + if (!init) init = 0; + for (var i = num - 1; i >= 0; i--) + res = new sc_Pair(i + init, res); + return res; +} + +/*** META ((export #t)) */ +function sc_makeList(nbEls, fill) { + var res = null; + for (var i = 0; i < nbEls; i++) + res = new sc_Pair(fill, res); + return res; +} + +/*** META ((export #t)) */ +function sc_length(l) { + var res = 0; + while (l !== null) { + res++; + l = l.cdr; + } + return res; +} + +/*** META ((export #t)) */ +function sc_remq(o, l) { + var dummy = { cdr : null }; + var tail = dummy; + while (l !== null) { + if (l.car !== o) { + tail.cdr = sc_cons(l.car, null); + tail = tail.cdr; + } + l = l.cdr; + } + return dummy.cdr; +} + +/*** META ((export #t)) */ +function sc_remqBang(o, l) { + var dummy = { cdr : null }; + var tail = dummy; + var needsAssig = true; + while (l !== null) { + if (l.car === o) { + needsAssig = true; + } else { + if (needsAssig) { + tail.cdr = l; + needsAssig = false; + } + tail = l; + } + l = l.cdr; + } + tail.cdr = null; + return dummy.cdr; +} + +/*** META ((export #t)) */ +function sc_delete(o, l) { + var dummy = { cdr : null }; + var tail = dummy; + while (l !== null) { + if (!sc_isEqual(l.car, o)) { + tail.cdr = sc_cons(l.car, null); + tail = tail.cdr; + } + l = l.cdr; + } + return dummy.cdr; +} + +/*** META ((export #t)) */ +function sc_deleteBang(o, l) { + var dummy = { cdr : null }; + var tail = dummy; + var needsAssig = true; + while (l !== null) { + if (sc_isEqual(l.car, o)) { + needsAssig = true; + } else { + if (needsAssig) { + tail.cdr = l; + needsAssig = false; + } + tail = l; + } + l = l.cdr; + } + tail.cdr = null; + return dummy.cdr; +} + +function sc_reverseAppendBang(l1, l2) { + var res = l2; + while (l1 !== null) { + var tmp = res; + res = l1; + l1 = l1.cdr; + res.cdr = tmp; + } + return res; +} + +function sc_dualAppend(l1, l2) { + if (l1 === null) return l2; + if (l2 === null) return l1; + var rev = sc_reverse(l1); + return sc_reverseAppendBang(rev, l2); +} + +/*** META ((export #t)) */ +function sc_append() { + if (arguments.length === 0) + return null; + var res = arguments[arguments.length - 1]; + for (var i = arguments.length - 2; i >= 0; i--) + res = sc_dualAppend(arguments[i], res); + return res; +} + +function sc_dualAppendBang(l1, l2) { + if (l1 === null) return l2; + if (l2 === null) return l1; + var tmp = l1; + while (tmp.cdr !== null) tmp=tmp.cdr; + tmp.cdr = l2; + return l1; +} + +/*** META ((export #t)) */ +function sc_appendBang() { + var res = null; + for (var i = 0; i < arguments.length; i++) + res = sc_dualAppendBang(res, arguments[i]); + return res; +} + +/*** META ((export #t)) */ +function sc_reverse(l1) { + var res = null; + while (l1 !== null) { + res = sc_cons(l1.car, res); + l1 = l1.cdr; + } + return res; +} + +/*** META ((export #t)) */ +function sc_reverseBang(l) { + return sc_reverseAppendBang(l, null); +} + +/*** META ((export #t)) */ +function sc_listTail(l, k) { + var res = l; + for (var i = 0; i < k; i++) { + res = res.cdr; + } + return res; +} + +/*** META ((export #t)) */ +function sc_listRef(l, k) { + return sc_listTail(l, k).car; +} + +/* // unoptimized generic versions +function sc_memX(o, l, comp) { + while (l != null) { + if (comp(l.car, o)) + return l; + l = l.cdr; + } + return false; +} +function sc_memq(o, l) { return sc_memX(o, l, sc_isEq); } +function sc_memv(o, l) { return sc_memX(o, l, sc_isEqv); } +function sc_member(o, l) { return sc_memX(o, l, sc_isEqual); } +*/ + +/* optimized versions */ +/*** META ((export #t)) */ +function sc_memq(o, l) { + while (l !== null) { + if (l.car === o) + return l; + l = l.cdr; + } + return false; +} +/*** META ((export #t)) */ +function sc_memv(o, l) { + while (l !== null) { + if (l.car === o) + return l; + l = l.cdr; + } + return false; +} +/*** META ((export #t)) */ +function sc_member(o, l) { + while (l !== null) { + if (sc_isEqual(l.car,o)) + return l; + l = l.cdr; + } + return false; +} + +/* // generic unoptimized versions +function sc_assX(o, al, comp) { + while (al != null) { + if (comp(al.car.car, o)) + return al.car; + al = al.cdr; + } + return false; +} +function sc_assq(o, al) { return sc_assX(o, al, sc_isEq); } +function sc_assv(o, al) { return sc_assX(o, al, sc_isEqv); } +function sc_assoc(o, al) { return sc_assX(o, al, sc_isEqual); } +*/ +// optimized versions +/*** META ((export #t)) */ +function sc_assq(o, al) { + while (al !== null) { + if (al.car.car === o) + return al.car; + al = al.cdr; + } + return false; +} +/*** META ((export #t)) */ +function sc_assv(o, al) { + while (al !== null) { + if (al.car.car === o) + return al.car; + al = al.cdr; + } + return false; +} +/*** META ((export #t)) */ +function sc_assoc(o, al) { + while (al !== null) { + if (sc_isEqual(al.car.car, o)) + return al.car; + al = al.cdr; + } + return false; +} + +/* can be used for mutable strings and characters */ +function sc_isCharStringEqual(cs1, cs2) { return cs1.val === cs2.val; } +function sc_isCharStringLess(cs1, cs2) { return cs1.val < cs2.val; } +function sc_isCharStringGreater(cs1, cs2) { return cs1.val > cs2.val; } +function sc_isCharStringLessEqual(cs1, cs2) { return cs1.val <= cs2.val; } +function sc_isCharStringGreaterEqual(cs1, cs2) { return cs1.val >= cs2.val; } +function sc_isCharStringCIEqual(cs1, cs2) + { return cs1.val.toLowerCase() === cs2.val.toLowerCase(); } +function sc_isCharStringCILess(cs1, cs2) + { return cs1.val.toLowerCase() < cs2.val.toLowerCase(); } +function sc_isCharStringCIGreater(cs1, cs2) + { return cs1.val.toLowerCase() > cs2.val.toLowerCase(); } +function sc_isCharStringCILessEqual(cs1, cs2) + { return cs1.val.toLowerCase() <= cs2.val.toLowerCase(); } +function sc_isCharStringCIGreaterEqual(cs1, cs2) + { return cs1.val.toLowerCase() >= cs2.val.toLowerCase(); } + + + + +function sc_Char(c) { + var cached = sc_Char.lazy[c]; + if (cached) + return cached; + this.val = c; + sc_Char.lazy[c] = this; + // add return, so FF does not complain. + return undefined; +} +sc_Char.lazy = new Object(); +// thanks to Eric +sc_Char.char2readable = { + "\000": "#\\null", + "\007": "#\\bell", + "\010": "#\\backspace", + "\011": "#\\tab", + "\012": "#\\newline", + "\014": "#\\page", + "\015": "#\\return", + "\033": "#\\escape", + "\040": "#\\space", + "\177": "#\\delete", + + /* poeticless names */ + "\001": "#\\soh", + "\002": "#\\stx", + "\003": "#\\etx", + "\004": "#\\eot", + "\005": "#\\enq", + "\006": "#\\ack", + + "\013": "#\\vt", + "\016": "#\\so", + "\017": "#\\si", + + "\020": "#\\dle", + "\021": "#\\dc1", + "\022": "#\\dc2", + "\023": "#\\dc3", + "\024": "#\\dc4", + "\025": "#\\nak", + "\026": "#\\syn", + "\027": "#\\etb", + + "\030": "#\\can", + "\031": "#\\em", + "\032": "#\\sub", + "\033": "#\\esc", + "\034": "#\\fs", + "\035": "#\\gs", + "\036": "#\\rs", + "\037": "#\\us"}; + +sc_Char.readable2char = { + "null": "\000", + "bell": "\007", + "backspace": "\010", + "tab": "\011", + "newline": "\012", + "page": "\014", + "return": "\015", + "escape": "\033", + "space": "\040", + "delete": "\000", + "soh": "\001", + "stx": "\002", + "etx": "\003", + "eot": "\004", + "enq": "\005", + "ack": "\006", + "bel": "\007", + "bs": "\010", + "ht": "\011", + "nl": "\012", + "vt": "\013", + "np": "\014", + "cr": "\015", + "so": "\016", + "si": "\017", + "dle": "\020", + "dc1": "\021", + "dc2": "\022", + "dc3": "\023", + "dc4": "\024", + "nak": "\025", + "syn": "\026", + "etb": "\027", + "can": "\030", + "em": "\031", + "sub": "\032", + "esc": "\033", + "fs": "\034", + "gs": "\035", + "rs": "\036", + "us": "\037", + "sp": "\040", + "del": "\177"}; + +sc_Char.prototype.toString = function() { + return this.val; +}; +// sc_toDisplayString == toString +sc_Char.prototype.sc_toWriteString = function() { + var entry = sc_Char.char2readable[this.val]; + if (entry) + return entry; + else + return "#\\" + this.val; +}; + +/*** META ((export #t) + (type bool) + (peephole (postfix "instanceof sc_Char"))) +*/ +function sc_isChar(c) { + return (c instanceof sc_Char); +} + +/*** META ((export char=?) + (type bool) + (peephole (hole 2 c1 ".val === " c2 ".val"))) +*/ +var sc_isCharEqual = sc_isCharStringEqual; +/*** META ((export char?) + (type bool) + (peephole (hole 2 c1 ".val > " c2 ".val"))) +*/ +var sc_isCharGreater = sc_isCharStringGreater; +/*** META ((export char<=?) + (type bool) + (peephole (hole 2 c1 ".val <= " c2 ".val"))) +*/ +var sc_isCharLessEqual = sc_isCharStringLessEqual; +/*** META ((export char>=?) + (type bool) + (peephole (hole 2 c1 ".val >= " c2 ".val"))) +*/ +var sc_isCharGreaterEqual = sc_isCharStringGreaterEqual; +/*** META ((export char-ci=?) + (type bool) + (peephole (hole 2 c1 ".val.toLowerCase() === " c2 ".val.toLowerCase()"))) +*/ +var sc_isCharCIEqual = sc_isCharStringCIEqual; +/*** META ((export char-ci?) + (type bool) + (peephole (hole 2 c1 ".val.toLowerCase() > " c2 ".val.toLowerCase()"))) +*/ +var sc_isCharCIGreater = sc_isCharStringCIGreater; +/*** META ((export char-ci<=?) + (type bool) + (peephole (hole 2 c1 ".val.toLowerCase() <= " c2 ".val.toLowerCase()"))) +*/ +var sc_isCharCILessEqual = sc_isCharStringCILessEqual; +/*** META ((export char-ci>=?) + (type bool) + (peephole (hole 2 c1 ".val.toLowerCase() >= " c2 ".val.toLowerCase()"))) +*/ +var sc_isCharCIGreaterEqual = sc_isCharStringCIGreaterEqual; + +var SC_NUMBER_CLASS = "0123456789"; +var SC_WHITESPACE_CLASS = ' \r\n\t\f'; +var SC_LOWER_CLASS = 'abcdefghijklmnopqrstuvwxyz'; +var SC_UPPER_CLASS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; + +function sc_isCharOfClass(c, cl) { return (cl.indexOf(c) != -1); } +/*** META ((export #t) + (type bool)) +*/ +function sc_isCharAlphabetic(c) + { return sc_isCharOfClass(c.val, SC_LOWER_CLASS) || + sc_isCharOfClass(c.val, SC_UPPER_CLASS); } +/*** META ((export #t) + (type bool) + (peephole (hole 1 "SC_NUMBER_CLASS.indexOf(" c ".val) != -1"))) +*/ +function sc_isCharNumeric(c) + { return sc_isCharOfClass(c.val, SC_NUMBER_CLASS); } +/*** META ((export #t) + (type bool)) +*/ +function sc_isCharWhitespace(c) { + var tmp = c.val; + return tmp === " " || tmp === "\r" || tmp === "\n" || tmp === "\t" || tmp === "\f"; +} +/*** META ((export #t) + (type bool) + (peephole (hole 1 "SC_UPPER_CLASS.indexOf(" c ".val) != -1"))) +*/ +function sc_isCharUpperCase(c) + { return sc_isCharOfClass(c.val, SC_UPPER_CLASS); } +/*** META ((export #t) + (type bool) + (peephole (hole 1 "SC_LOWER_CLASS.indexOf(" c ".val) != -1"))) +*/ +function sc_isCharLowerCase(c) + { return sc_isCharOfClass(c.val, SC_LOWER_CLASS); } + +/*** META ((export #t) + (peephole (postfix ".val.charCodeAt(0)"))) +*/ +function sc_char2integer(c) + { return c.val.charCodeAt(0); } +/*** META ((export #t) + (peephole (hole 1 "new sc_Char(String.fromCharCode(" n "))"))) +*/ +function sc_integer2char(n) + { return new sc_Char(String.fromCharCode(n)); } + +/*** META ((export #t) + (peephole (hole 1 "new sc_Char(" c ".val.toUpperCase())"))) +*/ +function sc_charUpcase(c) + { return new sc_Char(c.val.toUpperCase()); } +/*** META ((export #t) + (peephole (hole 1 "new sc_Char(" c ".val.toLowerCase())"))) +*/ +function sc_charDowncase(c) + { return new sc_Char(c.val.toLowerCase()); } + +function sc_makeJSStringOfLength(k, c) { + var fill; + if (c === undefined) + fill = " "; + else + fill = c; + var res = ""; + var len = 1; + // every round doubles the size of fill. + while (k >= len) { + if (k & len) + res = res.concat(fill); + fill = fill.concat(fill); + len *= 2; + } + return res; +} + +function sc_makejsString(k, c) { + var fill; + if (c) + fill = c.val; + else + fill = " "; + return sc_makeJSStringOfLength(k, fill); +} + +function sc_jsstring2list(s) { + var res = null; + for (var i = s.length - 1; i >= 0; i--) + res = sc_cons(new sc_Char(s.charAt(i)), res); + return res; +} + +function sc_list2jsstring(l) { + var a = new Array(); + while(l !== null) { + a.push(l.car.val); + l = l.cdr; + } + return "".concat.apply("", a); +} + +var sc_Vector = Array; + +sc_Vector.prototype.sc_toWriteOrDisplayString = function(writeOrDisplay) { + if (this.length === 0) return "#()"; + + var res = "#(" + writeOrDisplay(this[0]); + for (var i = 1; i < this.length; i++) + res += " " + writeOrDisplay(this[i]); + res += ")"; + return res; +}; +sc_Vector.prototype.sc_toDisplayString = function() { + return this.sc_toWriteOrDisplayString(sc_toDisplayString); +}; +sc_Vector.prototype.sc_toWriteString = function() { + return this.sc_toWriteOrDisplayString(sc_toWriteString); +}; + +/*** META ((export vector? array?) + (type bool) + (peephole (postfix " instanceof sc_Vector"))) +*/ +function sc_isVector(v) { + return (v instanceof sc_Vector); +} + +// only applies to vectors +function sc_isVectorEqual(v1, v2, comp) { + if (v1.length !== v2.length) return false; + for (var i = 0; i < v1.length; i++) + if (!comp(v1[i], v2[i])) return false; + return true; +} + +/*** META ((export make-vector make-array)) */ +function sc_makeVector(size, fill) { + var a = new sc_Vector(size); + if (fill !== undefined) + sc_vectorFillBang(a, fill); + return a; +} + +/*** META ((export vector array) + (peephole (vector))) +*/ +function sc_vector() { + var a = new sc_Vector(); + for (var i = 0; i < arguments.length; i++) + a.push(arguments[i]); + return a; +} + +/*** META ((export vector-length array-length) + (peephole (postfix ".length"))) +*/ +function sc_vectorLength(v) { + return v.length; +} + +/*** META ((export vector-ref array-ref) + (peephole (hole 2 v "[" pos "]"))) +*/ +function sc_vectorRef(v, pos) { + return v[pos]; +} + +/*** META ((export vector-set! array-set!) + (peephole (hole 3 v "[" pos "] = " val))) +*/ +function sc_vectorSetBang(v, pos, val) { + v[pos] = val; +} + +/*** META ((export vector->list array->list)) */ +function sc_vector2list(a) { + var res = null; + for (var i = a.length-1; i >= 0; i--) + res = sc_cons(a[i], res); + return res; +} + +/*** META ((export list->vector list->array)) */ +function sc_list2vector(l) { + var a = new sc_Vector(); + while(l !== null) { + a.push(l.car); + l = l.cdr; + } + return a; +} + +/*** META ((export vector-fill! array-fill!)) */ +function sc_vectorFillBang(a, fill) { + for (var i = 0; i < a.length; i++) + a[i] = fill; +} + + +/*** META ((export #t)) */ +function sc_copyVector(a, len) { + if (len <= a.length) + return a.slice(0, len); + else { + var tmp = a.concat(); + tmp.length = len; + return tmp; + } +} + +/*** META ((export #t) + (peephole (hole 3 a ".slice(" start "," end ")"))) +*/ +function sc_vectorCopy(a, start, end) { + return a.slice(start, end); +} + +/*** META ((export #t)) */ +function sc_vectorCopyBang(target, tstart, source, sstart, send) { + if (!sstart) sstart = 0; + if (!send) send = source.length; + + // if target == source we don't want to overwrite not yet copied elements. + if (tstart <= sstart) { + for (var i = tstart, j = sstart; j < send; i++, j++) { + target[i] = source[j]; + } + } else { + var diff = send - sstart; + for (var i = tstart + diff - 1, j = send - 1; + j >= sstart; + i--, j--) { + target[i] = source[j]; + } + } + return target; +} + +/*** META ((export #t) + (type bool) + (peephole (hole 1 "typeof " o " === 'function'"))) +*/ +function sc_isProcedure(o) { + return (typeof o === "function"); +} + +/*** META ((export #t)) */ +function sc_apply(proc) { + var args = new Array(); + // first part of arguments are not in list-form. + for (var i = 1; i < arguments.length - 1; i++) + args.push(arguments[i]); + var l = arguments[arguments.length - 1]; + while (l !== null) { + args.push(l.car); + l = l.cdr; + } + return proc.apply(null, args); +} + +/*** META ((export #t)) */ +function sc_map(proc, l1) { + if (l1 === undefined) + return null; + // else + var nbApplyArgs = arguments.length - 1; + var applyArgs = new Array(nbApplyArgs); + var revres = null; + while (l1 !== null) { + for (var i = 0; i < nbApplyArgs; i++) { + applyArgs[i] = arguments[i + 1].car; + arguments[i + 1] = arguments[i + 1].cdr; + } + revres = sc_cons(proc.apply(null, applyArgs), revres); + } + return sc_reverseAppendBang(revres, null); +} + +/*** META ((export #t)) */ +function sc_mapBang(proc, l1) { + if (l1 === undefined) + return null; + // else + var l1_orig = l1; + var nbApplyArgs = arguments.length - 1; + var applyArgs = new Array(nbApplyArgs); + while (l1 !== null) { + var tmp = l1; + for (var i = 0; i < nbApplyArgs; i++) { + applyArgs[i] = arguments[i + 1].car; + arguments[i + 1] = arguments[i + 1].cdr; + } + tmp.car = proc.apply(null, applyArgs); + } + return l1_orig; +} + +/*** META ((export #t)) */ +function sc_forEach(proc, l1) { + if (l1 === undefined) + return undefined; + // else + var nbApplyArgs = arguments.length - 1; + var applyArgs = new Array(nbApplyArgs); + while (l1 !== null) { + for (var i = 0; i < nbApplyArgs; i++) { + applyArgs[i] = arguments[i + 1].car; + arguments[i + 1] = arguments[i + 1].cdr; + } + proc.apply(null, applyArgs); + } + // add return so FF does not complain. + return undefined; +} + +/*** META ((export #t)) */ +function sc_filter(proc, l1) { + var dummy = { cdr : null }; + var tail = dummy; + while (l1 !== null) { + if (proc(l1.car) !== false) { + tail.cdr = sc_cons(l1.car, null); + tail = tail.cdr; + } + l1 = l1.cdr; + } + return dummy.cdr; +} + +/*** META ((export #t)) */ +function sc_filterBang(proc, l1) { + var head = sc_cons("dummy", l1); + var it = head; + var next = l1; + while (next !== null) { + if (proc(next.car) !== false) { + it.cdr = next + it = next; + } + next = next.cdr; + } + it.cdr = null; + return head.cdr; +} + +function sc_filterMap1(proc, l1) { + var revres = null; + while (l1 !== null) { + var tmp = proc(l1.car) + if (tmp !== false) revres = sc_cons(tmp, revres); + l1 = l1.cdr; + } + return sc_reverseAppendBang(revres, null); +} +function sc_filterMap2(proc, l1, l2) { + var revres = null; + while (l1 !== null) { + var tmp = proc(l1.car, l2.car); + if(tmp !== false) revres = sc_cons(tmp, revres); + l1 = l1.cdr; + l2 = l2.cdr + } + return sc_reverseAppendBang(revres, null); +} + +/*** META ((export #t)) */ +function sc_filterMap(proc, l1, l2, l3) { + if (l2 === undefined) + return sc_filterMap1(proc, l1); + else if (l3 === undefined) + return sc_filterMap2(proc, l1, l2); + // else + var nbApplyArgs = arguments.length - 1; + var applyArgs = new Array(nbApplyArgs); + var revres = null; + while (l1 !== null) { + for (var i = 0; i < nbApplyArgs; i++) { + applyArgs[i] = arguments[i + 1].car; + arguments[i + 1] = arguments[i + 1].cdr; + } + var tmp = proc.apply(null, applyArgs); + if(tmp !== false) revres = sc_cons(tmp, revres); + } + return sc_reverseAppendBang(revres, null); +} + +/*** META ((export #t)) */ +function sc_any(proc, l) { + var revres = null; + while (l !== null) { + var tmp = proc(l.car); + if(tmp !== false) return tmp; + l = l.cdr; + } + return false; +} + +/*** META ((export any?) + (peephole (hole 2 "sc_any(" proc "," l ") !== false"))) +*/ +function sc_anyPred(proc, l) { + return sc_any(proc, l)!== false; +} + +/*** META ((export #t)) */ +function sc_every(proc, l) { + var revres = null; + var tmp = true; + while (l !== null) { + tmp = proc(l.car); + if (tmp === false) return false; + l = l.cdr; + } + return tmp; +} + +/*** META ((export every?) + (peephole (hole 2 "sc_every(" proc "," l ") !== false"))) +*/ +function sc_everyPred(proc, l) { + var tmp = sc_every(proc, l); + if (tmp !== false) return true; + return false; +} + +/*** META ((export #t) + (peephole (postfix "()"))) +*/ +function sc_force(o) { + return o(); +} + +/*** META ((export #t)) */ +function sc_makePromise(proc) { + var isResultReady = false; + var result = undefined; + return function() { + if (!isResultReady) { + var tmp = proc(); + if (!isResultReady) { + isResultReady = true; + result = tmp; + } + } + return result; + }; +} + +function sc_Values(values) { + this.values = values; +} + +/*** META ((export #t) + (peephole (values))) +*/ +function sc_values() { + if (arguments.length === 1) + return arguments[0]; + else + return new sc_Values(arguments); +} + +/*** META ((export #t)) */ +function sc_callWithValues(producer, consumer) { + var produced = producer(); + if (produced instanceof sc_Values) + return consumer.apply(null, produced.values); + else + return consumer(produced); +} + +/*** META ((export #t)) */ +function sc_dynamicWind(before, thunk, after) { + before(); + try { + var res = thunk(); + return res; + } finally { + after(); + } +} + + +// TODO: eval/scheme-report-environment/null-environment/interaction-environment + +// LIMITATION: 'load' doesn't exist without files. +// LIMITATION: transcript-on/transcript-off doesn't exist without files. + + +function sc_Struct(name) { + this.name = name; +} +sc_Struct.prototype.sc_toDisplayString = function() { + return "#"; +}; +sc_Struct.prototype.sc_toWriteString = sc_Struct.prototype.sc_toDisplayString; + +/*** META ((export #t) + (peephole (hole 1 "new sc_Struct(" name ")"))) +*/ +function sc_makeStruct(name) { + return new sc_Struct(name); +} + +/*** META ((export #t) + (type bool) + (peephole (postfix " instanceof sc_Struct"))) +*/ +function sc_isStruct(o) { + return (o instanceof sc_Struct); +} + +/*** META ((export #t) + (type bool) + (peephole (hole 2 "(" 1 " instanceof sc_Struct) && ( " 1 ".name === " 0 ")"))) +*/ +function sc_isStructNamed(name, s) { + return ((s instanceof sc_Struct) && (s.name === name)); +} + +/*** META ((export struct-field) + (peephole (hole 3 0 "[" 2 "]"))) +*/ +function sc_getStructField(s, name, field) { + return s[field]; +} + +/*** META ((export struct-field-set!) + (peephole (hole 4 0 "[" 2 "] = " 3))) +*/ +function sc_setStructFieldBang(s, name, field, val) { + s[field] = val; +} + +/*** META ((export #t) + (peephole (prefix "~"))) +*/ +function sc_bitNot(x) { + return ~x; +} + +/*** META ((export #t) + (peephole (infix 2 2 "&"))) +*/ +function sc_bitAnd(x, y) { + return x & y; +} + +/*** META ((export #t) + (peephole (infix 2 2 "|"))) +*/ +function sc_bitOr(x, y) { + return x | y; +} + +/*** META ((export #t) + (peephole (infix 2 2 "^"))) +*/ +function sc_bitXor(x, y) { + return x ^ y; +} + +/*** META ((export #t) + (peephole (infix 2 2 "<<"))) +*/ +function sc_bitLsh(x, y) { + return x << y; +} + +/*** META ((export #t) + (peephole (infix 2 2 ">>"))) +*/ +function sc_bitRsh(x, y) { + return x >> y; +} + +/*** META ((export #t) + (peephole (infix 2 2 ">>>"))) +*/ +function sc_bitUrsh(x, y) { + return x >>> y; +} + +/*** META ((export js-field js-property) + (peephole (hole 2 o "[" field "]"))) +*/ +function sc_jsField(o, field) { + return o[field]; +} + +/*** META ((export js-field-set! js-property-set!) + (peephole (hole 3 o "[" field "] = " val))) +*/ +function sc_setJsFieldBang(o, field, val) { + return o[field] = val; +} + +/*** META ((export js-field-delete! js-property-delete!) + (peephole (hole 2 "delete" o "[" field "]"))) +*/ +function sc_deleteJsFieldBang(o, field) { + delete o[field]; +} + +/*** META ((export #t) + (peephole (jsCall))) +*/ +function sc_jsCall(o, fun) { + var args = new Array(); + for (var i = 2; i < arguments.length; i++) + args[i-2] = arguments[i]; + return fun.apply(o, args); +} + +/*** META ((export #t) + (peephole (jsMethodCall))) +*/ +function sc_jsMethodCall(o, field) { + var args = new Array(); + for (var i = 2; i < arguments.length; i++) + args[i-2] = arguments[i]; + return o[field].apply(o, args); +} + +/*** META ((export new js-new) + (peephole (jsNew))) +*/ +function sc_jsNew(c) { + var evalStr = "new c("; + evalStr +=arguments.length > 1? "arguments[1]": ""; + for (var i = 2; i < arguments.length; i++) + evalStr += ", arguments[" + i + "]"; + evalStr +=")"; + return eval(evalStr); +} + +// ======================== RegExp ==================== +/*** META ((export #t)) */ +function sc_pregexp(re) { + return new RegExp(sc_string2jsstring(re)); +} + +/*** META ((export #t)) */ +function sc_pregexpMatch(re, s) { + var reg = (re instanceof RegExp) ? re : sc_pregexp(re); + var tmp = reg.exec(sc_string2jsstring(s)); + + if (tmp == null) return false; + + var res = null; + for (var i = tmp.length-1; i >= 0; i--) { + if (tmp[i] !== null) { + res = sc_cons(sc_jsstring2string(tmp[i]), res); + } else { + res = sc_cons(false, res); + } + } + return res; +} + +/*** META ((export #t)) */ +function sc_pregexpReplace(re, s1, s2) { + var reg; + var jss1 = sc_string2jsstring(s1); + var jss2 = sc_string2jsstring(s2); + + if (re instanceof RegExp) { + if (re.global) + reg = re; + else + reg = new RegExp(re.source); + } else { + reg = new RegExp(sc_string2jsstring(re)); + } + + return jss1.replace(reg, jss2); +} + +/*** META ((export pregexp-replace*)) */ +function sc_pregexpReplaceAll(re, s1, s2) { + var reg; + var jss1 = sc_string2jsstring(s1); + var jss2 = sc_string2jsstring(s2); + + if (re instanceof RegExp) { + if (re.global) + reg = re; + else + reg = new RegExp(re.source, "g"); + } else { + reg = new RegExp(sc_string2jsstring(re), "g"); + } + + return jss1.replace(reg, jss2); +} + +/*** META ((export #t)) */ +function sc_pregexpSplit(re, s) { + var reg = ((re instanceof RegExp) ? + re : + new RegExp(sc_string2jsstring(re))); + var jss = sc_string2jsstring(s); + var tmp = jss.split(reg); + + if (tmp == null) return false; + + return sc_vector2list(tmp); +} + + +/* =========================================================================== */ +/* Other library stuff */ +/* =========================================================================== */ + +/*** META ((export #t) + (peephole (hole 1 "Math.floor(Math.random()*" 'n ")"))) +*/ +function sc_random(n) { + return Math.floor(Math.random()*n); +} + +/*** META ((export current-date) + (peephole (hole 0 "new Date()"))) +*/ +function sc_currentDate() { + return new Date(); +} + +function sc_Hashtable() { +} +sc_Hashtable.prototype.toString = function() { + return "#{%hashtable}"; +}; +// sc_toWriteString == sc_toDisplayString == toString + +function sc_HashtableElement(key, val) { + this.key = key; + this.val = val; +} + +/*** META ((export #t) + (peephole (hole 0 "new sc_Hashtable()"))) +*/ +function sc_makeHashtable() { + return new sc_Hashtable(); +} + +/*** META ((export #t)) */ +function sc_hashtablePutBang(ht, key, val) { + var hash = sc_hash(key); + ht[hash] = new sc_HashtableElement(key, val); +} + +/*** META ((export #t)) */ +function sc_hashtableGet(ht, key) { + var hash = sc_hash(key); + if (hash in ht) + return ht[hash].val; + else + return false; +} + +/*** META ((export #t)) */ +function sc_hashtableForEach(ht, f) { + for (var v in ht) { + if (ht[v] instanceof sc_HashtableElement) + f(ht[v].key, ht[v].val); + } +} + +/*** META ((export hashtable-contains?) + (peephole (hole 2 "sc_hash(" 1 ") in " 0))) +*/ +function sc_hashtableContains(ht, key) { + var hash = sc_hash(key); + if (hash in ht) + return true; + else + return false; +} + +var SC_HASH_COUNTER = 0; + +function sc_hash(o) { + if (o === null) + return "null"; + else if (o === undefined) + return "undefined"; + else if (o === true) + return "true"; + else if (o === false) + return "false"; + else if (typeof o === "number") + return "num-" + o; + else if (typeof o === "string") + return "jsstr-" + o; + else if (o.sc_getHash) + return o.sc_getHash(); + else + return sc_counterHash.call(o); +} +function sc_counterHash() { + if (!this.sc_hash) { + this.sc_hash = "hash-" + SC_HASH_COUNTER; + SC_HASH_COUNTER++; + } + return this.sc_hash; +} + +function sc_Trampoline(args, maxTailCalls) { + this['__trampoline return__'] = true; + this.args = args; + this.MAX_TAIL_CALLs = maxTailCalls; +} +// TODO: call/cc stuff +sc_Trampoline.prototype.restart = function() { + var o = this; + while (true) { + // set both globals. + SC_TAIL_OBJECT.calls = o.MAX_TAIL_CALLs-1; + var fun = o.args.callee; + var res = fun.apply(SC_TAIL_OBJECT, o.args); + if (res instanceof sc_Trampoline) + o = res; + else + return res; + } +} + +/*** META ((export bind-exit-lambda)) */ +function sc_bindExitLambda(proc) { + var escape_obj = new sc_BindExitException(); + var escape = function(res) { + escape_obj.res = res; + throw escape_obj; + }; + try { + return proc(escape); + } catch(e) { + if (e === escape_obj) { + return e.res; + } + throw e; + } +} +function sc_BindExitException() { + this._internalException = true; +} + +var SC_SCM2JS_GLOBALS = new Object(); + +// default tail-call depth. +// normally the program should set it again. but just in case... +var SC_TAIL_OBJECT = new Object(); +SC_SCM2JS_GLOBALS.TAIL_OBJECT = SC_TAIL_OBJECT; +// ======================== I/O ======================= + +/*------------------------------------------------------------------*/ + +function sc_EOF() { +} +var SC_EOF_OBJECT = new sc_EOF(); + +function sc_Port() { +} + +/* --------------- Input ports -------------------------------------*/ + +function sc_InputPort() { +} +sc_InputPort.prototype = new sc_Port(); + +sc_InputPort.prototype.peekChar = function() { + if (!("peeked" in this)) + this.peeked = this.getNextChar(); + return this.peeked; +} +sc_InputPort.prototype.readChar = function() { + var tmp = this.peekChar(); + delete this.peeked; + return tmp; +} +sc_InputPort.prototype.isCharReady = function() { + return true; +} +sc_InputPort.prototype.close = function() { + // do nothing +} + +/* .............. String port ..........................*/ +function sc_ErrorInputPort() { +}; +sc_ErrorInputPort.prototype = new sc_InputPort(); +sc_ErrorInputPort.prototype.getNextChar = function() { + throw "can't read from error-port."; +}; +sc_ErrorInputPort.prototype.isCharReady = function() { + return false; +}; + + +/* .............. String port ..........................*/ + +function sc_StringInputPort(jsStr) { + // we are going to do some charAts on the str. + // instead of recreating all the time a String-object, we + // create one in the beginning. (not sure, if this is really an optim) + this.str = new String(jsStr); + this.pos = 0; +} +sc_StringInputPort.prototype = new sc_InputPort(); +sc_StringInputPort.prototype.getNextChar = function() { + if (this.pos >= this.str.length) + return SC_EOF_OBJECT; + return this.str.charAt(this.pos++); +}; + +/* ------------- Read and other lib-funs -------------------------------*/ +function sc_Token(type, val, pos) { + this.type = type; + this.val = val; + this.pos = pos; +} +sc_Token.EOF = 0/*EOF*/; +sc_Token.OPEN_PAR = 1/*OPEN_PAR*/; +sc_Token.CLOSE_PAR = 2/*CLOSE_PAR*/; +sc_Token.OPEN_BRACE = 3/*OPEN_BRACE*/; +sc_Token.CLOSE_BRACE = 4/*CLOSE_BRACE*/; +sc_Token.OPEN_BRACKET = 5/*OPEN_BRACKET*/; +sc_Token.CLOSE_BRACKET = 6/*CLOSE_BRACKET*/; +sc_Token.WHITESPACE = 7/*WHITESPACE*/; +sc_Token.QUOTE = 8/*QUOTE*/; +sc_Token.ID = 9/*ID*/; +sc_Token.DOT = 10/*DOT*/; +sc_Token.STRING = 11/*STRING*/; +sc_Token.NUMBER = 12/*NUMBER*/; +sc_Token.ERROR = 13/*ERROR*/; +sc_Token.VECTOR_BEGIN = 14/*VECTOR_BEGIN*/; +sc_Token.TRUE = 15/*TRUE*/; +sc_Token.FALSE = 16/*FALSE*/; +sc_Token.UNSPECIFIED = 17/*UNSPECIFIED*/; +sc_Token.REFERENCE = 18/*REFERENCE*/; +sc_Token.STORE = 19/*STORE*/; +sc_Token.CHAR = 20/*CHAR*/; + +var SC_ID_CLASS = SC_LOWER_CLASS + SC_UPPER_CLASS + "!$%*+-./:<=>?@^_~"; +function sc_Tokenizer(port) { + this.port = port; +} +sc_Tokenizer.prototype.peekToken = function() { + if (this.peeked) + return this.peeked; + var newToken = this.nextToken(); + this.peeked = newToken; + return newToken; +}; +sc_Tokenizer.prototype.readToken = function() { + var tmp = this.peekToken(); + delete this.peeked; + return tmp; +}; +sc_Tokenizer.prototype.nextToken = function() { + var port = this.port; + + function isNumberChar(c) { + return (c >= "0" && c <= "9"); + }; + function isIdOrNumberChar(c) { + return SC_ID_CLASS.indexOf(c) != -1 || // ID-char + (c >= "0" && c <= "9"); + } + function isWhitespace(c) { + return c === " " || c === "\r" || c === "\n" || c === "\t" || c === "\f"; + }; + function isWhitespaceOrEOF(c) { + return isWhitespace(c) || c === SC_EOF_OBJECT; + }; + + function readString() { + res = ""; + while (true) { + var c = port.readChar(); + switch (c) { + case '"': + return new sc_Token(11/*STRING*/, res); + case "\\": + var tmp = port.readChar(); + switch (tmp) { + case '0': res += "\0"; break; + case 'a': res += "\a"; break; + case 'b': res += "\b"; break; + case 'f': res += "\f"; break; + case 'n': res += "\n"; break; + case 'r': res += "\r"; break; + case 't': res += "\t"; break; + case 'v': res += "\v"; break; + case '"': res += '"'; break; + case '\\': res += '\\'; break; + case 'x': + /* hexa-number */ + var nb = 0; + while (true) { + var hexC = port.peekChar(); + if (hexC >= '0' && hexC <= '9') { + port.readChar(); + nb = nb * 16 + hexC.charCodeAt(0) - '0'.charCodeAt(0); + } else if (hexC >= 'a' && hexC <= 'f') { + port.readChar(); + nb = nb * 16 + hexC.charCodeAt(0) - 'a'.charCodeAt(0); + } else if (hexC >= 'A' && hexC <= 'F') { + port.readChar(); + nb = nb * 16 + hexC.charCodeAt(0) - 'A'.charCodeAt(0); + } else { + // next char isn't part of hex. + res += String.fromCharCode(nb); + break; + } + } + break; + default: + if (tmp === SC_EOF_OBJECT) { + return new sc_Token(13/*ERROR*/, "unclosed string-literal" + res); + } + res += tmp; + } + break; + default: + if (c === SC_EOF_OBJECT) { + return new sc_Token(13/*ERROR*/, "unclosed string-literal" + res); + } + res += c; + } + } + }; + function readIdOrNumber(firstChar) { + var res = firstChar; + while (isIdOrNumberChar(port.peekChar())) + res += port.readChar(); + if (isNaN(res)) + return new sc_Token(9/*ID*/, res); + else + return new sc_Token(12/*NUMBER*/, res - 0); + }; + + function skipWhitespaceAndComments() { + var done = false; + while (!done) { + done = true; + while (isWhitespace(port.peekChar())) + port.readChar(); + if (port.peekChar() === ';') { + port.readChar(); + done = false; + while (true) { + curChar = port.readChar(); + if (curChar === SC_EOF_OBJECT || + curChar === '\n') + break; + } + } + } + }; + + function readDot() { + if (isWhitespace(port.peekChar())) + return new sc_Token(10/*DOT*/); + else + return readIdOrNumber("."); + }; + + function readSharp() { + var c = port.readChar(); + if (isWhitespace(c)) + return new sc_Token(13/*ERROR*/, "bad #-pattern0."); + + // reference + if (isNumberChar(c)) { + var nb = c - 0; + while (isNumberChar(port.peekChar())) + nb = nb*10 + (port.readChar() - 0); + switch (port.readChar()) { + case '#': + return new sc_Token(18/*REFERENCE*/, nb); + case '=': + return new sc_Token(19/*STORE*/, nb); + default: + return new sc_Token(13/*ERROR*/, "bad #-pattern1." + nb); + } + } + + if (c === "(") + return new sc_Token(14/*VECTOR_BEGIN*/); + + if (c === "\\") { // character + var tmp = "" + while (!isWhitespaceOrEOF(port.peekChar())) + tmp += port.readChar(); + switch (tmp.length) { + case 0: // it's escaping a whitespace char: + if (sc_isEOFObject(port.peekChar)) + return new sc_Token(13/*ERROR*/, "bad #-pattern2."); + else + return new sc_Token(20/*CHAR*/, port.readChar()); + case 1: + return new sc_Token(20/*CHAR*/, tmp); + default: + var entry = sc_Char.readable2char[tmp.toLowerCase()]; + if (entry) + return new sc_Token(20/*CHAR*/, entry); + else + return new sc_Token(13/*ERROR*/, "unknown character description: #\\" + tmp); + } + } + + // some constants (#t, #f, #unspecified) + var res; + var needing; + switch (c) { + case 't': res = new sc_Token(15/*TRUE*/, true); needing = ""; break; + case 'f': res = new sc_Token(16/*FALSE*/, false); needing = ""; break; + case 'u': res = new sc_Token(17/*UNSPECIFIED*/, undefined); needing = "nspecified"; break; + default: + return new sc_Token(13/*ERROR*/, "bad #-pattern3: " + c); + } + while(true) { + c = port.peekChar(); + if ((isWhitespaceOrEOF(c) || c === ')') && + needing == "") + return res; + else if (isWhitespace(c) || needing == "") + return new sc_Token(13/*ERROR*/, "bad #-pattern4 " + c + " " + needing); + else if (needing.charAt(0) == c) { + port.readChar(); // consume + needing = needing.slice(1); + } else + return new sc_Token(13/*ERROR*/, "bad #-pattern5"); + } + + }; + + skipWhitespaceAndComments(); + var curChar = port.readChar(); + if (curChar === SC_EOF_OBJECT) + return new sc_Token(0/*EOF*/, curChar); + switch (curChar) + { + case " ": + case "\n": + case "\t": + return readWhitespace(); + case "(": + return new sc_Token(1/*OPEN_PAR*/); + case ")": + return new sc_Token(2/*CLOSE_PAR*/); + case "{": + return new sc_Token(3/*OPEN_BRACE*/); + case "}": + return new sc_Token(4/*CLOSE_BRACE*/); + case "[": + return new sc_Token(5/*OPEN_BRACKET*/); + case "]": + return new sc_Token(6/*CLOSE_BRACKET*/); + case "'": + return new sc_Token(8/*QUOTE*/); + case "#": + return readSharp(); + case ".": + return readDot(); + case '"': + return readString(); + default: + if (isIdOrNumberChar(curChar)) + return readIdOrNumber(curChar); + throw "unexpected character: " + curChar; + } +}; + +function sc_Reader(tokenizer) { + this.tokenizer = tokenizer; + this.backref = new Array(); +} +sc_Reader.prototype.read = function() { + function readList(listBeginType) { + function matchesPeer(open, close) { + return open === 1/*OPEN_PAR*/ && close === 2/*CLOSE_PAR*/ + || open === 3/*OPEN_BRACE*/ && close === 4/*CLOSE_BRACE*/ + || open === 5/*OPEN_BRACKET*/ && close === 6/*CLOSE_BRACKET*/; + }; + var res = null; + + while (true) { + var token = tokenizer.peekToken(); + + switch (token.type) { + case 2/*CLOSE_PAR*/: + case 4/*CLOSE_BRACE*/: + case 6/*CLOSE_BRACKET*/: + if (matchesPeer(listBeginType, token.type)) { + tokenizer.readToken(); // consume token + return sc_reverseBang(res); + } else + throw "closing par doesn't match: " + listBeginType + + " " + listEndType; + + case 0/*EOF*/: + throw "unexpected end of file"; + + case 10/*DOT*/: + tokenizer.readToken(); // consume token + var cdr = this.read(); + var par = tokenizer.readToken(); + if (!matchesPeer(listBeginType, par.type)) + throw "closing par doesn't match: " + listBeginType + + " " + par.type; + else + return sc_reverseAppendBang(res, cdr); + + + default: + res = sc_cons(this.read(), res); + } + } + }; + function readQuote() { + return sc_cons("quote", sc_cons(this.read(), null)); + }; + function readVector() { + // opening-parenthesis is already consumed + var a = new Array(); + while (true) { + var token = tokenizer.peekToken(); + switch (token.type) { + case 2/*CLOSE_PAR*/: + tokenizer.readToken(); + return a; + + default: + a.push(this.read()); + } + } + }; + + function storeRefence(nb) { + var tmp = this.read(); + this.backref[nb] = tmp; + return tmp; + }; + + function readReference(nb) { + if (nb in this.backref) + return this.backref[nb]; + else + throw "bad reference: " + nb; + }; + + var tokenizer = this.tokenizer; + + var token = tokenizer.readToken(); + + // handle error + if (token.type === 13/*ERROR*/) + throw token.val; + + switch (token.type) { + case 1/*OPEN_PAR*/: + case 3/*OPEN_BRACE*/: + case 5/*OPEN_BRACKET*/: + return readList.call(this, token.type); + case 8/*QUOTE*/: + return readQuote.call(this); + case 11/*STRING*/: + return sc_jsstring2string(token.val); + case 20/*CHAR*/: + return new sc_Char(token.val); + case 14/*VECTOR_BEGIN*/: + return readVector.call(this); + case 18/*REFERENCE*/: + return readReference.call(this, token.val); + case 19/*STORE*/: + return storeRefence.call(this, token.val); + case 9/*ID*/: + return sc_jsstring2symbol(token.val); + case 0/*EOF*/: + case 12/*NUMBER*/: + case 15/*TRUE*/: + case 16/*FALSE*/: + case 17/*UNSPECIFIED*/: + return token.val; + default: + throw "unexpected token " + token.type + " " + token.val; + } +}; + +/*** META ((export #t)) */ +function sc_read(port) { + if (port === undefined) // we assume the port hasn't been given. + port = SC_DEFAULT_IN; // THREAD: shared var... + var reader = new sc_Reader(new sc_Tokenizer(port)); + return reader.read(); +} +/*** META ((export #t)) */ +function sc_readChar(port) { + if (port === undefined) // we assume the port hasn't been given. + port = SC_DEFAULT_IN; // THREAD: shared var... + var t = port.readChar(); + return t === SC_EOF_OBJECT? t: new sc_Char(t); +} +/*** META ((export #t)) */ +function sc_peekChar(port) { + if (port === undefined) // we assume the port hasn't been given. + port = SC_DEFAULT_IN; // THREAD: shared var... + var t = port.peekChar(); + return t === SC_EOF_OBJECT? t: new sc_Char(t); +} +/*** META ((export #t) + (type bool)) +*/ +function sc_isCharReady(port) { + if (port === undefined) // we assume the port hasn't been given. + port = SC_DEFAULT_IN; // THREAD: shared var... + return port.isCharReady(); +} +/*** META ((export #t) + (peephole (postfix ".close()"))) +*/ +function sc_closeInputPort(p) { + return p.close(); +} + +/*** META ((export #t) + (type bool) + (peephole (postfix " instanceof sc_InputPort"))) +*/ +function sc_isInputPort(o) { + return (o instanceof sc_InputPort); +} + +/*** META ((export eof-object?) + (type bool) + (peephole (postfix " === SC_EOF_OBJECT"))) +*/ +function sc_isEOFObject(o) { + return o === SC_EOF_OBJECT; +} + +/*** META ((export #t) + (peephole (hole 0 "SC_DEFAULT_IN"))) +*/ +function sc_currentInputPort() { + return SC_DEFAULT_IN; +} + +/* ------------ file operations are not supported -----------*/ +/*** META ((export #t)) */ +function sc_callWithInputFile(s, proc) { + throw "can't open " + s; +} + +/*** META ((export #t)) */ +function sc_callWithOutputFile(s, proc) { + throw "can't open " + s; +} + +/*** META ((export #t)) */ +function sc_withInputFromFile(s, thunk) { + throw "can't open " + s; +} + +/*** META ((export #t)) */ +function sc_withOutputToFile(s, thunk) { + throw "can't open " + s; +} + +/*** META ((export #t)) */ +function sc_openInputFile(s) { + throw "can't open " + s; +} + +/*** META ((export #t)) */ +function sc_openOutputFile(s) { + throw "can't open " + s; +} + +/* ----------------------------------------------------------------------------*/ +/*** META ((export #t)) */ +function sc_basename(p) { + var i = p.lastIndexOf('/'); + + if(i >= 0) + return p.substring(i + 1, p.length); + else + return ''; +} + +/*** META ((export #t)) */ +function sc_dirname(p) { + var i = p.lastIndexOf('/'); + + if(i >= 0) + return p.substring(0, i); + else + return ''; +} + +/* ----------------------------------------------------------------------------*/ + +/*** META ((export #t)) */ +function sc_withInputFromPort(p, thunk) { + try { + var tmp = SC_DEFAULT_IN; // THREAD: shared var. + SC_DEFAULT_IN = p; + return thunk(); + } finally { + SC_DEFAULT_IN = tmp; + } +} + +/*** META ((export #t)) */ +function sc_withInputFromString(s, thunk) { + return sc_withInputFromPort(new sc_StringInputPort(sc_string2jsstring(s)), thunk); +} + +/*** META ((export #t)) */ +function sc_withOutputToPort(p, thunk) { + try { + var tmp = SC_DEFAULT_OUT; // THREAD: shared var. + SC_DEFAULT_OUT = p; + return thunk(); + } finally { + SC_DEFAULT_OUT = tmp; + } +} + +/*** META ((export #t)) */ +function sc_withOutputToString(thunk) { + var p = new sc_StringOutputPort(); + sc_withOutputToPort(p, thunk); + return p.close(); +} + +/*** META ((export #t)) */ +function sc_withOutputToProcedure(proc, thunk) { + var t = function(s) { proc(sc_jsstring2string(s)); }; + return sc_withOutputToPort(new sc_GenericOutputPort(t), thunk); +} + +/*** META ((export #t) + (peephole (hole 0 "new sc_StringOutputPort()"))) +*/ +function sc_openOutputString() { + return new sc_StringOutputPort(); +} + +/*** META ((export #t)) */ +function sc_openInputString(str) { + return new sc_StringInputPort(sc_string2jsstring(str)); +} + +/* ----------------------------------------------------------------------------*/ + +function sc_OutputPort() { +} +sc_OutputPort.prototype = new sc_Port(); +sc_OutputPort.prototype.appendJSString = function(obj) { + /* do nothing */ +} +sc_OutputPort.prototype.close = function() { + /* do nothing */ +} + +function sc_StringOutputPort() { + this.res = ""; +} +sc_StringOutputPort.prototype = new sc_OutputPort(); +sc_StringOutputPort.prototype.appendJSString = function(s) { + this.res += s; +} +sc_StringOutputPort.prototype.close = function() { + return sc_jsstring2string(this.res); +} + +/*** META ((export #t)) */ +function sc_getOutputString(sp) { + return sc_jsstring2string(sp.res); +} + + +function sc_ErrorOutputPort() { +} +sc_ErrorOutputPort.prototype = new sc_OutputPort(); +sc_ErrorOutputPort.prototype.appendJSString = function(s) { + throw "don't write on ErrorPort!"; +} +sc_ErrorOutputPort.prototype.close = function() { + /* do nothing */ +} + +function sc_GenericOutputPort(appendJSString, close) { + this.appendJSString = appendJSString; + if (close) + this.close = close; +} +sc_GenericOutputPort.prototype = new sc_OutputPort(); + +/*** META ((export #t) + (type bool) + (peephole (postfix " instanceof sc_OutputPort"))) +*/ +function sc_isOutputPort(o) { + return (o instanceof sc_OutputPort); +} + +/*** META ((export #t) + (peephole (postfix ".close()"))) +*/ +function sc_closeOutputPort(p) { + return p.close(); +} + +/* ------------------ write ---------------------------------------------------*/ + +/*** META ((export #t)) */ +function sc_write(o, p) { + if (p === undefined) // we assume not given + p = SC_DEFAULT_OUT; + p.appendJSString(sc_toWriteString(o)); +} + +function sc_toWriteString(o) { + if (o === null) + return "()"; + else if (o === true) + return "#t"; + else if (o === false) + return "#f"; + else if (o === undefined) + return "#unspecified"; + else if (typeof o === 'function') + return "#"; + else if (o.sc_toWriteString) + return o.sc_toWriteString(); + else + return o.toString(); +} + +function sc_escapeWriteString(s) { + var res = ""; + var j = 0; + for (i = 0; i < s.length; i++) { + switch (s.charAt(i)) { + case "\0": res += s.substring(j, i) + "\\0"; j = i + 1; break; + case "\b": res += s.substring(j, i) + "\\b"; j = i + 1; break; + case "\f": res += s.substring(j, i) + "\\f"; j = i + 1; break; + case "\n": res += s.substring(j, i) + "\\n"; j = i + 1; break; + case "\r": res += s.substring(j, i) + "\\r"; j = i + 1; break; + case "\t": res += s.substring(j, i) + "\\t"; j = i + 1; break; + case "\v": res += s.substring(j, i) + "\\v"; j = i + 1; break; + case '"': res += s.substring(j, i) + '\\"'; j = i + 1; break; + case "\\": res += s.substring(j, i) + "\\\\"; j = i + 1; break; + default: + var c = s.charAt(i); + if ("\a" !== "a" && c == "\a") { + res += s.substring(j, i) + "\\a"; j = i + 1; continue; + } + if ("\v" !== "v" && c == "\v") { + res += s.substring(j, i) + "\\v"; j = i + 1; continue; + } + //if (s.charAt(i) < ' ' || s.charCodeAt(i) > 127) { + // CARE: Manuel is this OK with HOP? + if (s.charAt(i) < ' ') { + /* non printable character and special chars */ + res += s.substring(j, i) + "\\x" + s.charCodeAt(i).toString(16); + j = i + 1; + } + // else just let i increase... + } + } + res += s.substring(j, i); + return res; +} + +/* ------------------ display ---------------------------------------------------*/ + +/*** META ((export #t)) */ +function sc_display(o, p) { + if (p === undefined) // we assume not given + p = SC_DEFAULT_OUT; + p.appendJSString(sc_toDisplayString(o)); +} + +function sc_toDisplayString(o) { + if (o === null) + return "()"; + else if (o === true) + return "#t"; + else if (o === false) + return "#f"; + else if (o === undefined) + return "#unspecified"; + else if (typeof o === 'function') + return "#"; + else if (o.sc_toDisplayString) + return o.sc_toDisplayString(); + else + return o.toString(); +} + +/* ------------------ newline ---------------------------------------------------*/ + +/*** META ((export #t)) */ +function sc_newline(p) { + if (p === undefined) // we assume not given + p = SC_DEFAULT_OUT; + p.appendJSString("\n"); +} + +/* ------------------ write-char ---------------------------------------------------*/ + +/*** META ((export #t)) */ +function sc_writeChar(c, p) { + if (p === undefined) // we assume not given + p = SC_DEFAULT_OUT; + p.appendJSString(c.val); +} + +/* ------------------ write-circle ---------------------------------------------------*/ + +/*** META ((export #t)) */ +function sc_writeCircle(o, p) { + if (p === undefined) // we assume not given + p = SC_DEFAULT_OUT; + p.appendJSString(sc_toWriteCircleString(o)); +} + +function sc_toWriteCircleString(o) { + var symb = sc_gensym("writeCircle"); + var nbPointer = new Object(); + nbPointer.nb = 0; + sc_prepWriteCircle(o, symb, nbPointer); + return sc_genToWriteCircleString(o, symb); +} + +function sc_prepWriteCircle(o, symb, nbPointer) { + // TODO sc_Struct + if (o instanceof sc_Pair || + o instanceof sc_Vector) { + if (o[symb] !== undefined) { + // not the first visit. + o[symb]++; + // unless there is already a number, assign one. + if (!o[symb + "nb"]) o[symb + "nb"] = nbPointer.nb++; + return; + } + o[symb] = 0; + if (o instanceof sc_Pair) { + sc_prepWriteCircle(o.car, symb, nbPointer); + sc_prepWriteCircle(o.cdr, symb, nbPointer); + } else { + for (var i = 0; i < o.length; i++) + sc_prepWriteCircle(o[i], symb, nbPointer); + } + } +} + +function sc_genToWriteCircleString(o, symb) { + if (!(o instanceof sc_Pair || + o instanceof sc_Vector)) + return sc_toWriteString(o); + return o.sc_toWriteCircleString(symb); +} +sc_Pair.prototype.sc_toWriteCircleString = function(symb, inList) { + if (this[symb + "use"]) { // use-flag is set. Just use it. + var nb = this[symb + "nb"]; + if (this[symb]-- === 0) { // if we are the last use. remove all fields. + delete this[symb]; + delete this[symb + "nb"]; + delete this[symb + "use"]; + } + if (inList) + return '. #' + nb + '#'; + else + return '#' + nb + '#'; + } + if (this[symb]-- === 0) { // if we are the last use. remove all fields. + delete this[symb]; + delete this[symb + "nb"]; + delete this[symb + "use"]; + } + + var res = ""; + + if (this[symb] !== undefined) { // implies > 0 + this[symb + "use"] = true; + if (inList) + res += '. #' + this[symb + "nb"] + '='; + else + res += '#' + this[symb + "nb"] + '='; + inList = false; + } + + if (!inList) + res += "("; + + // print car + res += sc_genToWriteCircleString(this.car, symb); + + if (sc_isPair(this.cdr)) { + res += " " + this.cdr.sc_toWriteCircleString(symb, true); + } else if (this.cdr !== null) { + res += " . " + sc_genToWriteCircleString(this.cdr, symb); + } + if (!inList) + res += ")"; + return res; +}; +sc_Vector.prototype.sc_toWriteCircleString = function(symb) { + if (this[symb + "use"]) { // use-flag is set. Just use it. + var nb = this[symb + "nb"]; + if (this[symb]-- === 0) { // if we are the last use. remove all fields. + delete this[symb]; + delete this[symb + "nb"]; + delete this[symb + "use"]; + } + return '#' + nb + '#'; + } + if (this[symb]-- === 0) { // if we are the last use. remove all fields. + delete this[symb]; + delete this[symb + "nb"]; + delete this[symb + "use"]; + } + + var res = ""; + if (this[symb] !== undefined) { // implies > 0 + this[symb + "use"] = true; + res += '#' + this[symb + "nb"] + '='; + } + res += "#("; + for (var i = 0; i < this.length; i++) { + res += sc_genToWriteCircleString(this[i], symb); + if (i < this.length - 1) res += " "; + } + res += ")"; + return res; +}; + + +/* ------------------ print ---------------------------------------------------*/ + +/*** META ((export #t)) */ +function sc_print(s) { + if (arguments.length === 1) { + sc_display(s); + sc_newline(); + } + else { + for (var i = 0; i < arguments.length; i++) + sc_display(arguments[i]); + sc_newline(); + } +} + +/* ------------------ format ---------------------------------------------------*/ +/*** META ((export #t)) */ +function sc_format(s, args) { + var len = s.length; + var p = new sc_StringOutputPort(); + var i = 0, j = 1; + + while( i < len ) { + var i2 = s.indexOf("~", i); + + if (i2 == -1) { + p.appendJSString( s.substring( i, len ) ); + return p.close(); + } else { + if (i2 > i) { + if (i2 == (len - 1)) { + p.appendJSString(s.substring(i, len)); + return p.close(); + } else { + p.appendJSString(s.substring(i, i2)); + i = i2; + } + } + + switch(s.charCodeAt(i2 + 1)) { + case 65: + case 97: + // a + sc_display(arguments[j], p); + i += 2; j++; + break; + + case 83: + case 115: + // s + sc_write(arguments[j], p); + i += 2; j++; + break; + + case 86: + case 118: + // v + sc_display(arguments[j], p); + p.appendJSString("\n"); + i += 2; j++; + break; + + case 67: + case 99: + // c + p.appendJSString(String.fromCharCode(arguments[j])); + i += 2; j++; + break; + + case 88: + case 120: + // x + p.appendJSString(arguments[j].toString(6)); + i += 2; j++; + break; + + case 79: + case 111: + // o + p.appendJSString(arguments[j].toString(8)); + i += 2; j++; + break; + + case 66: + case 98: + // b + p.appendJSString(arguments[j].toString(2)); + i += 2; j++; + break; + + case 37: + case 110: + // %, n + p.appendJSString("\n"); + i += 2; break; + + case 114: + // r + p.appendJSString("\r"); + i += 2; break; + + case 126: + // ~ + p.appendJSString("~"); + i += 2; break; + + default: + sc_error( "format: illegal ~" + + String.fromCharCode(s.charCodeAt(i2 + 1)) + + " sequence" ); + return ""; + } + } + } + + return p.close(); +} + +/* ------------------ global ports ---------------------------------------------------*/ + +var SC_DEFAULT_IN = new sc_ErrorInputPort(); +var SC_DEFAULT_OUT = new sc_ErrorOutputPort(); +var SC_ERROR_OUT = new sc_ErrorOutputPort(); + +var sc_SYMBOL_PREFIX = "\u1E9C"; +var sc_KEYWORD_PREFIX = "\u1E9D"; + +/*** META ((export #t) + (peephole (id))) */ +function sc_jsstring2string(s) { + return s; +} + +/*** META ((export #t) + (peephole (prefix "'\\u1E9C' +"))) +*/ +function sc_jsstring2symbol(s) { + return sc_SYMBOL_PREFIX + s; +} + +/*** META ((export #t) + (peephole (id))) +*/ +function sc_string2jsstring(s) { + return s; +} + +/*** META ((export #t) + (peephole (symbol2jsstring_immutable))) +*/ +function sc_symbol2jsstring(s) { + return s.slice(1); +} + +/*** META ((export #t) + (peephole (postfix ".slice(1)"))) +*/ +function sc_keyword2jsstring(k) { + return k.slice(1); +} + +/*** META ((export #t) + (peephole (prefix "'\\u1E9D' +"))) +*/ +function sc_jsstring2keyword(s) { + return sc_KEYWORD_PREFIX + s; +} + +/*** META ((export #t) + (type bool)) +*/ +function sc_isKeyword(s) { + return (typeof s === "string") && + (s.charAt(0) === sc_KEYWORD_PREFIX); +} + + +/*** META ((export #t)) */ +var sc_gensym = function() { + var counter = 1000; + return function(sym) { + counter++; + if (!sym) sym = sc_SYMBOL_PREFIX; + return sym + "s" + counter + "~" + "^sC-GeNsYm "; + }; +}(); + + +/*** META ((export #t) + (type bool)) +*/ +function sc_isEqual(o1, o2) { + return ((o1 === o2) || + (sc_isPair(o1) && sc_isPair(o2) + && sc_isPairEqual(o1, o2, sc_isEqual)) || + (sc_isVector(o1) && sc_isVector(o2) + && sc_isVectorEqual(o1, o2, sc_isEqual))); +} + +/*** META ((export number->symbol integer->symbol)) */ +function sc_number2symbol(x, radix) { + return sc_SYMBOL_PREFIX + sc_number2jsstring(x, radix); +} + +/*** META ((export number->string integer->string)) */ +var sc_number2string = sc_number2jsstring; + +/*** META ((export #t)) */ +function sc_symbol2number(s, radix) { + return sc_jsstring2number(s.slice(1), radix); +} + +/*** META ((export #t)) */ +var sc_string2number = sc_jsstring2number; + +/*** META ((export #t) + (peephole (prefix "+" s))) + ;; peephole will only apply if no radix is given. +*/ +function sc_string2integer(s, radix) { + if (!radix) return +s; + return parseInt(s, radix); +} + +/*** META ((export #t) + (peephole (prefix "+"))) +*/ +function sc_string2real(s) { + return +s; +} + + +/*** META ((export #t) + (type bool)) +*/ +function sc_isSymbol(s) { + return (typeof s === "string") && + (s.charAt(0) === sc_SYMBOL_PREFIX); +} + +/*** META ((export #t) + (peephole (symbol2string_immutable))) +*/ +function sc_symbol2string(s) { + return s.slice(1); +} + +/*** META ((export #t) + (peephole (prefix "'\\u1E9C' +"))) +*/ +function sc_string2symbol(s) { + return sc_SYMBOL_PREFIX + s; +} + +/*** META ((export symbol-append) + (peephole (symbolAppend_immutable))) +*/ +function sc_symbolAppend() { + var res = sc_SYMBOL_PREFIX; + for (var i = 0; i < arguments.length; i++) + res += arguments[i].slice(1); + return res; +} + +/*** META ((export #t) + (peephole (postfix ".val"))) +*/ +function sc_char2string(c) { return c.val; } + +/*** META ((export #t) + (peephole (hole 1 "'\\u1E9C' + " c ".val"))) +*/ +function sc_char2symbol(c) { return sc_SYMBOL_PREFIX + c.val; } + +/*** META ((export #t) + (type bool)) +*/ +function sc_isString(s) { + return (typeof s === "string") && + (s.charAt(0) !== sc_SYMBOL_PREFIX); +} + +/*** META ((export #t)) */ +var sc_makeString = sc_makejsString; + + +/*** META ((export #t)) */ +function sc_string() { + for (var i = 0; i < arguments.length; i++) + arguments[i] = arguments[i].val; + return "".concat.apply("", arguments); +} + +/*** META ((export #t) + (peephole (postfix ".length"))) +*/ +function sc_stringLength(s) { return s.length; } + +/*** META ((export #t)) */ +function sc_stringRef(s, k) { + return new sc_Char(s.charAt(k)); +} + +/* there's no stringSet in the immutable version +function sc_stringSet(s, k, c) +*/ + + +/*** META ((export string=?) + (type bool) + (peephole (hole 2 str1 " === " str2))) +*/ +function sc_isStringEqual(s1, s2) { + return s1 === s2; +} +/*** META ((export string?) + (type bool) + (peephole (hole 2 str1 " > " str2))) +*/ +function sc_isStringGreater(s1, s2) { + return s1 > s2; +} +/*** META ((export string<=?) + (type bool) + (peephole (hole 2 str1 " <= " str2))) +*/ +function sc_isStringLessEqual(s1, s2) { + return s1 <= s2; +} +/*** META ((export string>=?) + (type bool) + (peephole (hole 2 str1 " >= " str2))) +*/ +function sc_isStringGreaterEqual(s1, s2) { + return s1 >= s2; +} +/*** META ((export string-ci=?) + (type bool) + (peephole (hole 2 str1 ".toLowerCase() === " str2 ".toLowerCase()"))) +*/ +function sc_isStringCIEqual(s1, s2) { + return s1.toLowerCase() === s2.toLowerCase(); +} +/*** META ((export string-ci?) + (type bool) + (peephole (hole 2 str1 ".toLowerCase() > " str2 ".toLowerCase()"))) +*/ +function sc_isStringCIGreater(s1, s2) { + return s1.toLowerCase() > s2.toLowerCase(); +} +/*** META ((export string-ci<=?) + (type bool) + (peephole (hole 2 str1 ".toLowerCase() <= " str2 ".toLowerCase()"))) +*/ +function sc_isStringCILessEqual(s1, s2) { + return s1.toLowerCase() <= s2.toLowerCase(); +} +/*** META ((export string-ci>=?) + (type bool) + (peephole (hole 2 str1 ".toLowerCase() >= " str2 ".toLowerCase()"))) +*/ +function sc_isStringCIGreaterEqual(s1, s2) { + return s1.toLowerCase() >= s2.toLowerCase(); +} + +/*** META ((export #t) + (peephole (hole 3 s ".substring(" start ", " end ")"))) +*/ +function sc_substring(s, start, end) { + return s.substring(start, end); +} + +/*** META ((export #t)) +*/ +function sc_isSubstring_at(s1, s2, i) { + return s2 == s1.substring(i, i+ s2.length); +} + +/*** META ((export #t) + (peephole (infix 0 #f "+" "''"))) +*/ +function sc_stringAppend() { + return "".concat.apply("", arguments); +} + +/*** META ((export #t)) */ +var sc_string2list = sc_jsstring2list; + +/*** META ((export #t)) */ +var sc_list2string = sc_list2jsstring; + +/*** META ((export #t) + (peephole (id))) +*/ +function sc_stringCopy(s) { + return s; +} + +/* there's no string-fill in the immutable version +function sc_stringFill(s, c) +*/ + +/*** META ((export #t) + (peephole (postfix ".slice(1)"))) +*/ +function sc_keyword2string(o) { + return o.slice(1); +} + +/*** META ((export #t) + (peephole (prefix "'\\u1E9D' +"))) +*/ +function sc_string2keyword(o) { + return sc_KEYWORD_PREFIX + o; +} + +String.prototype.sc_toDisplayString = function() { + if (this.charAt(0) === sc_SYMBOL_PREFIX) + // TODO: care for symbols with spaces (escape-chars symbols). + return this.slice(1); + else if (this.charAt(0) === sc_KEYWORD_PREFIX) + return ":" + this.slice(1); + else + return this.toString(); +}; + +String.prototype.sc_toWriteString = function() { + if (this.charAt(0) === sc_SYMBOL_PREFIX) + // TODO: care for symbols with spaces (escape-chars symbols). + return this.slice(1); + else if (this.charAt(0) === sc_KEYWORD_PREFIX) + return ":" + this.slice(1); + else + return '"' + sc_escapeWriteString(this) + '"'; +}; +/* Exported Variables */ +var BgL_testzd2boyerzd2; +var BgL_nboyerzd2benchmarkzd2; +var BgL_setupzd2boyerzd2; +/* End Exports */ + +var translate_term_nboyer; +var translate_args_nboyer; +var untranslate_term_nboyer; +var BgL_sc_symbolzd2ze3symbolzd2record_1ze3_nboyer; +var BgL_sc_za2symbolzd2recordszd2alistza2_2z00_nboyer; +var translate_alist_nboyer; +var apply_subst_nboyer; +var apply_subst_lst_nboyer; +var tautologyp_nboyer; +var if_constructor_nboyer; +var rewrite_count_nboyer; +var rewrite_nboyer; +var rewrite_args_nboyer; +var unify_subst_nboyer; +var one_way_unify1_nboyer; +var false_term_nboyer; +var true_term_nboyer; +var trans_of_implies1_nboyer; +var is_term_equal_nboyer; +var is_term_member_nboyer; +var const_nboyer; +var sc_const_3_nboyer; +var sc_const_4_nboyer; +{ + (sc_const_4_nboyer = (new sc_Pair("\u1E9Cimplies",(new sc_Pair((new sc_Pair("\u1E9Cand",(new sc_Pair((new sc_Pair("\u1E9Cimplies",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cand",(new sc_Pair((new sc_Pair("\u1E9Cimplies",(new sc_Pair("\u1E9Cy",(new sc_Pair("\u1E9Cz",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cand",(new sc_Pair((new sc_Pair("\u1E9Cimplies",(new sc_Pair("\u1E9Cz",(new sc_Pair("\u1E9Cu",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cimplies",(new sc_Pair("\u1E9Cu",(new sc_Pair("\u1E9Cw",null)))))),null)))))),null)))))),null)))))),(new sc_Pair((new sc_Pair("\u1E9Cimplies",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cw",null)))))),null))))))); + (sc_const_3_nboyer = sc_list((new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Ccompile",(new sc_Pair("\u1E9Cform",null)))),(new sc_Pair((new sc_Pair("\u1E9Creverse",(new sc_Pair((new sc_Pair("\u1E9Ccodegen",(new sc_Pair((new sc_Pair("\u1E9Coptimize",(new sc_Pair("\u1E9Cform",null)))),(new sc_Pair((new sc_Pair("\u1E9Cnil",null)),null)))))),null)))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Ceqp",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cfix",(new sc_Pair("\u1E9Cx",null)))),(new sc_Pair((new sc_Pair("\u1E9Cfix",(new sc_Pair("\u1E9Cy",null)))),null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cgreaterp",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),(new sc_Pair((new sc_Pair("\u1E9Clessp",(new sc_Pair("\u1E9Cy",(new sc_Pair("\u1E9Cx",null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Clesseqp",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cnot",(new sc_Pair((new sc_Pair("\u1E9Clessp",(new sc_Pair("\u1E9Cy",(new sc_Pair("\u1E9Cx",null)))))),null)))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cgreatereqp",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cnot",(new sc_Pair((new sc_Pair("\u1E9Clessp",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),null)))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cboolean",(new sc_Pair("\u1E9Cx",null)))),(new sc_Pair((new sc_Pair("\u1E9Cor",(new sc_Pair((new sc_Pair("\u1E9Cequal",(new sc_Pair("\u1E9Cx",(new sc_Pair((new sc_Pair("\u1E9Ct",null)),null)))))),(new sc_Pair((new sc_Pair("\u1E9Cequal",(new sc_Pair("\u1E9Cx",(new sc_Pair((new sc_Pair("\u1E9Cf",null)),null)))))),null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Ciff",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cand",(new sc_Pair((new sc_Pair("\u1E9Cimplies",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cimplies",(new sc_Pair("\u1E9Cy",(new sc_Pair("\u1E9Cx",null)))))),null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Ceven1",(new sc_Pair("\u1E9Cx",null)))),(new sc_Pair((new sc_Pair("\u1E9Cif",(new sc_Pair((new sc_Pair("\u1E9Czerop",(new sc_Pair("\u1E9Cx",null)))),(new sc_Pair((new sc_Pair("\u1E9Ct",null)),(new sc_Pair((new sc_Pair("\u1E9Codd",(new sc_Pair((new sc_Pair("\u1E9Csub1",(new sc_Pair("\u1E9Cx",null)))),null)))),null)))))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Ccountps-",(new sc_Pair("\u1E9Cl",(new sc_Pair("\u1E9Cpred",null)))))),(new sc_Pair((new sc_Pair("\u1E9Ccountps-loop",(new sc_Pair("\u1E9Cl",(new sc_Pair("\u1E9Cpred",(new sc_Pair((new sc_Pair("\u1E9Czero",null)),null)))))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cfact-",(new sc_Pair("\u1E9Ci",null)))),(new sc_Pair((new sc_Pair("\u1E9Cfact-loop",(new sc_Pair("\u1E9Ci",(new sc_Pair((1),null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Creverse-",(new sc_Pair("\u1E9Cx",null)))),(new sc_Pair((new sc_Pair("\u1E9Creverse-loop",(new sc_Pair("\u1E9Cx",(new sc_Pair((new sc_Pair("\u1E9Cnil",null)),null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cdivides",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),(new sc_Pair((new sc_Pair("\u1E9Czerop",(new sc_Pair((new sc_Pair("\u1E9Cremainder",(new sc_Pair("\u1E9Cy",(new sc_Pair("\u1E9Cx",null)))))),null)))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cassume-true",(new sc_Pair("\u1E9Cvar",(new sc_Pair("\u1E9Calist",null)))))),(new sc_Pair((new sc_Pair("\u1E9Ccons",(new sc_Pair((new sc_Pair("\u1E9Ccons",(new sc_Pair("\u1E9Cvar",(new sc_Pair((new sc_Pair("\u1E9Ct",null)),null)))))),(new sc_Pair("\u1E9Calist",null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cassume-false",(new sc_Pair("\u1E9Cvar",(new sc_Pair("\u1E9Calist",null)))))),(new sc_Pair((new sc_Pair("\u1E9Ccons",(new sc_Pair((new sc_Pair("\u1E9Ccons",(new sc_Pair("\u1E9Cvar",(new sc_Pair((new sc_Pair("\u1E9Cf",null)),null)))))),(new sc_Pair("\u1E9Calist",null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Ctautology-checker",(new sc_Pair("\u1E9Cx",null)))),(new sc_Pair((new sc_Pair("\u1E9Ctautologyp",(new sc_Pair((new sc_Pair("\u1E9Cnormalize",(new sc_Pair("\u1E9Cx",null)))),(new sc_Pair((new sc_Pair("\u1E9Cnil",null)),null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cfalsify",(new sc_Pair("\u1E9Cx",null)))),(new sc_Pair((new sc_Pair("\u1E9Cfalsify1",(new sc_Pair((new sc_Pair("\u1E9Cnormalize",(new sc_Pair("\u1E9Cx",null)))),(new sc_Pair((new sc_Pair("\u1E9Cnil",null)),null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cprime",(new sc_Pair("\u1E9Cx",null)))),(new sc_Pair((new sc_Pair("\u1E9Cand",(new sc_Pair((new sc_Pair("\u1E9Cnot",(new sc_Pair((new sc_Pair("\u1E9Czerop",(new sc_Pair("\u1E9Cx",null)))),null)))),(new sc_Pair((new sc_Pair("\u1E9Cnot",(new sc_Pair((new sc_Pair("\u1E9Cequal",(new sc_Pair("\u1E9Cx",(new sc_Pair((new sc_Pair("\u1E9Cadd1",(new sc_Pair((new sc_Pair("\u1E9Czero",null)),null)))),null)))))),null)))),(new sc_Pair((new sc_Pair("\u1E9Cprime1",(new sc_Pair("\u1E9Cx",(new sc_Pair((new sc_Pair("\u1E9Csub1",(new sc_Pair("\u1E9Cx",null)))),null)))))),null)))))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cand",(new sc_Pair("\u1E9Cp",(new sc_Pair("\u1E9Cq",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cif",(new sc_Pair("\u1E9Cp",(new sc_Pair((new sc_Pair("\u1E9Cif",(new sc_Pair("\u1E9Cq",(new sc_Pair((new sc_Pair("\u1E9Ct",null)),(new sc_Pair((new sc_Pair("\u1E9Cf",null)),null)))))))),(new sc_Pair((new sc_Pair("\u1E9Cf",null)),null)))))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cor",(new sc_Pair("\u1E9Cp",(new sc_Pair("\u1E9Cq",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cif",(new sc_Pair("\u1E9Cp",(new sc_Pair((new sc_Pair("\u1E9Ct",null)),(new sc_Pair((new sc_Pair("\u1E9Cif",(new sc_Pair("\u1E9Cq",(new sc_Pair((new sc_Pair("\u1E9Ct",null)),(new sc_Pair((new sc_Pair("\u1E9Cf",null)),null)))))))),null)))))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cnot",(new sc_Pair("\u1E9Cp",null)))),(new sc_Pair((new sc_Pair("\u1E9Cif",(new sc_Pair("\u1E9Cp",(new sc_Pair((new sc_Pair("\u1E9Cf",null)),(new sc_Pair((new sc_Pair("\u1E9Ct",null)),null)))))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cimplies",(new sc_Pair("\u1E9Cp",(new sc_Pair("\u1E9Cq",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cif",(new sc_Pair("\u1E9Cp",(new sc_Pair((new sc_Pair("\u1E9Cif",(new sc_Pair("\u1E9Cq",(new sc_Pair((new sc_Pair("\u1E9Ct",null)),(new sc_Pair((new sc_Pair("\u1E9Cf",null)),null)))))))),(new sc_Pair((new sc_Pair("\u1E9Ct",null)),null)))))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cfix",(new sc_Pair("\u1E9Cx",null)))),(new sc_Pair((new sc_Pair("\u1E9Cif",(new sc_Pair((new sc_Pair("\u1E9Cnumberp",(new sc_Pair("\u1E9Cx",null)))),(new sc_Pair("\u1E9Cx",(new sc_Pair((new sc_Pair("\u1E9Czero",null)),null)))))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cif",(new sc_Pair((new sc_Pair("\u1E9Cif",(new sc_Pair("\u1E9Ca",(new sc_Pair("\u1E9Cb",(new sc_Pair("\u1E9Cc",null)))))))),(new sc_Pair("\u1E9Cd",(new sc_Pair("\u1E9Ce",null)))))))),(new sc_Pair((new sc_Pair("\u1E9Cif",(new sc_Pair("\u1E9Ca",(new sc_Pair((new sc_Pair("\u1E9Cif",(new sc_Pair("\u1E9Cb",(new sc_Pair("\u1E9Cd",(new sc_Pair("\u1E9Ce",null)))))))),(new sc_Pair((new sc_Pair("\u1E9Cif",(new sc_Pair("\u1E9Cc",(new sc_Pair("\u1E9Cd",(new sc_Pair("\u1E9Ce",null)))))))),null)))))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Czerop",(new sc_Pair("\u1E9Cx",null)))),(new sc_Pair((new sc_Pair("\u1E9Cor",(new sc_Pair((new sc_Pair("\u1E9Cequal",(new sc_Pair("\u1E9Cx",(new sc_Pair((new sc_Pair("\u1E9Czero",null)),null)))))),(new sc_Pair((new sc_Pair("\u1E9Cnot",(new sc_Pair((new sc_Pair("\u1E9Cnumberp",(new sc_Pair("\u1E9Cx",null)))),null)))),null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cplus",(new sc_Pair((new sc_Pair("\u1E9Cplus",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),(new sc_Pair("\u1E9Cz",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cplus",(new sc_Pair("\u1E9Cx",(new sc_Pair((new sc_Pair("\u1E9Cplus",(new sc_Pair("\u1E9Cy",(new sc_Pair("\u1E9Cz",null)))))),null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cplus",(new sc_Pair("\u1E9Ca",(new sc_Pair("\u1E9Cb",null)))))),(new sc_Pair((new sc_Pair("\u1E9Czero",null)),null)))))),(new sc_Pair((new sc_Pair("\u1E9Cand",(new sc_Pair((new sc_Pair("\u1E9Czerop",(new sc_Pair("\u1E9Ca",null)))),(new sc_Pair((new sc_Pair("\u1E9Czerop",(new sc_Pair("\u1E9Cb",null)))),null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cdifference",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cx",null)))))),(new sc_Pair((new sc_Pair("\u1E9Czero",null)),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cplus",(new sc_Pair("\u1E9Ca",(new sc_Pair("\u1E9Cb",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cplus",(new sc_Pair("\u1E9Ca",(new sc_Pair("\u1E9Cc",null)))))),null)))))),(new sc_Pair((new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cfix",(new sc_Pair("\u1E9Cb",null)))),(new sc_Pair((new sc_Pair("\u1E9Cfix",(new sc_Pair("\u1E9Cc",null)))),null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Czero",null)),(new sc_Pair((new sc_Pair("\u1E9Cdifference",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),null)))))),(new sc_Pair((new sc_Pair("\u1E9Cnot",(new sc_Pair((new sc_Pair("\u1E9Clessp",(new sc_Pair("\u1E9Cy",(new sc_Pair("\u1E9Cx",null)))))),null)))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cequal",(new sc_Pair("\u1E9Cx",(new sc_Pair((new sc_Pair("\u1E9Cdifference",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),null)))))),(new sc_Pair((new sc_Pair("\u1E9Cand",(new sc_Pair((new sc_Pair("\u1E9Cnumberp",(new sc_Pair("\u1E9Cx",null)))),(new sc_Pair((new sc_Pair("\u1E9Cor",(new sc_Pair((new sc_Pair("\u1E9Cequal",(new sc_Pair("\u1E9Cx",(new sc_Pair((new sc_Pair("\u1E9Czero",null)),null)))))),(new sc_Pair((new sc_Pair("\u1E9Czerop",(new sc_Pair("\u1E9Cy",null)))),null)))))),null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cmeaning",(new sc_Pair((new sc_Pair("\u1E9Cplus-tree",(new sc_Pair((new sc_Pair("\u1E9Cappend",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),null)))),(new sc_Pair("\u1E9Ca",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cplus",(new sc_Pair((new sc_Pair("\u1E9Cmeaning",(new sc_Pair((new sc_Pair("\u1E9Cplus-tree",(new sc_Pair("\u1E9Cx",null)))),(new sc_Pair("\u1E9Ca",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cmeaning",(new sc_Pair((new sc_Pair("\u1E9Cplus-tree",(new sc_Pair("\u1E9Cy",null)))),(new sc_Pair("\u1E9Ca",null)))))),null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cmeaning",(new sc_Pair((new sc_Pair("\u1E9Cplus-tree",(new sc_Pair((new sc_Pair("\u1E9Cplus-fringe",(new sc_Pair("\u1E9Cx",null)))),null)))),(new sc_Pair("\u1E9Ca",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cfix",(new sc_Pair((new sc_Pair("\u1E9Cmeaning",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Ca",null)))))),null)))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cappend",(new sc_Pair((new sc_Pair("\u1E9Cappend",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),(new sc_Pair("\u1E9Cz",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cappend",(new sc_Pair("\u1E9Cx",(new sc_Pair((new sc_Pair("\u1E9Cappend",(new sc_Pair("\u1E9Cy",(new sc_Pair("\u1E9Cz",null)))))),null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Creverse",(new sc_Pair((new sc_Pair("\u1E9Cappend",(new sc_Pair("\u1E9Ca",(new sc_Pair("\u1E9Cb",null)))))),null)))),(new sc_Pair((new sc_Pair("\u1E9Cappend",(new sc_Pair((new sc_Pair("\u1E9Creverse",(new sc_Pair("\u1E9Cb",null)))),(new sc_Pair((new sc_Pair("\u1E9Creverse",(new sc_Pair("\u1E9Ca",null)))),null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Ctimes",(new sc_Pair("\u1E9Cx",(new sc_Pair((new sc_Pair("\u1E9Cplus",(new sc_Pair("\u1E9Cy",(new sc_Pair("\u1E9Cz",null)))))),null)))))),(new sc_Pair((new sc_Pair("\u1E9Cplus",(new sc_Pair((new sc_Pair("\u1E9Ctimes",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),(new sc_Pair((new sc_Pair("\u1E9Ctimes",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cz",null)))))),null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Ctimes",(new sc_Pair((new sc_Pair("\u1E9Ctimes",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),(new sc_Pair("\u1E9Cz",null)))))),(new sc_Pair((new sc_Pair("\u1E9Ctimes",(new sc_Pair("\u1E9Cx",(new sc_Pair((new sc_Pair("\u1E9Ctimes",(new sc_Pair("\u1E9Cy",(new sc_Pair("\u1E9Cz",null)))))),null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Ctimes",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),(new sc_Pair((new sc_Pair("\u1E9Czero",null)),null)))))),(new sc_Pair((new sc_Pair("\u1E9Cor",(new sc_Pair((new sc_Pair("\u1E9Czerop",(new sc_Pair("\u1E9Cx",null)))),(new sc_Pair((new sc_Pair("\u1E9Czerop",(new sc_Pair("\u1E9Cy",null)))),null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cexec",(new sc_Pair((new sc_Pair("\u1E9Cappend",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),(new sc_Pair("\u1E9Cpds",(new sc_Pair("\u1E9Cenvrn",null)))))))),(new sc_Pair((new sc_Pair("\u1E9Cexec",(new sc_Pair("\u1E9Cy",(new sc_Pair((new sc_Pair("\u1E9Cexec",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cpds",(new sc_Pair("\u1E9Cenvrn",null)))))))),(new sc_Pair("\u1E9Cenvrn",null)))))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cmc-flatten",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cappend",(new sc_Pair((new sc_Pair("\u1E9Cflatten",(new sc_Pair("\u1E9Cx",null)))),(new sc_Pair("\u1E9Cy",null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cmember",(new sc_Pair("\u1E9Cx",(new sc_Pair((new sc_Pair("\u1E9Cappend",(new sc_Pair("\u1E9Ca",(new sc_Pair("\u1E9Cb",null)))))),null)))))),(new sc_Pair((new sc_Pair("\u1E9Cor",(new sc_Pair((new sc_Pair("\u1E9Cmember",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Ca",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cmember",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cb",null)))))),null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cmember",(new sc_Pair("\u1E9Cx",(new sc_Pair((new sc_Pair("\u1E9Creverse",(new sc_Pair("\u1E9Cy",null)))),null)))))),(new sc_Pair((new sc_Pair("\u1E9Cmember",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Clength",(new sc_Pair((new sc_Pair("\u1E9Creverse",(new sc_Pair("\u1E9Cx",null)))),null)))),(new sc_Pair((new sc_Pair("\u1E9Clength",(new sc_Pair("\u1E9Cx",null)))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cmember",(new sc_Pair("\u1E9Ca",(new sc_Pair((new sc_Pair("\u1E9Cintersect",(new sc_Pair("\u1E9Cb",(new sc_Pair("\u1E9Cc",null)))))),null)))))),(new sc_Pair((new sc_Pair("\u1E9Cand",(new sc_Pair((new sc_Pair("\u1E9Cmember",(new sc_Pair("\u1E9Ca",(new sc_Pair("\u1E9Cb",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cmember",(new sc_Pair("\u1E9Ca",(new sc_Pair("\u1E9Cc",null)))))),null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cnth",(new sc_Pair((new sc_Pair("\u1E9Czero",null)),(new sc_Pair("\u1E9Ci",null)))))),(new sc_Pair((new sc_Pair("\u1E9Czero",null)),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cexp",(new sc_Pair("\u1E9Ci",(new sc_Pair((new sc_Pair("\u1E9Cplus",(new sc_Pair("\u1E9Cj",(new sc_Pair("\u1E9Ck",null)))))),null)))))),(new sc_Pair((new sc_Pair("\u1E9Ctimes",(new sc_Pair((new sc_Pair("\u1E9Cexp",(new sc_Pair("\u1E9Ci",(new sc_Pair("\u1E9Cj",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cexp",(new sc_Pair("\u1E9Ci",(new sc_Pair("\u1E9Ck",null)))))),null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cexp",(new sc_Pair("\u1E9Ci",(new sc_Pair((new sc_Pair("\u1E9Ctimes",(new sc_Pair("\u1E9Cj",(new sc_Pair("\u1E9Ck",null)))))),null)))))),(new sc_Pair((new sc_Pair("\u1E9Cexp",(new sc_Pair((new sc_Pair("\u1E9Cexp",(new sc_Pair("\u1E9Ci",(new sc_Pair("\u1E9Cj",null)))))),(new sc_Pair("\u1E9Ck",null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Creverse-loop",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cappend",(new sc_Pair((new sc_Pair("\u1E9Creverse",(new sc_Pair("\u1E9Cx",null)))),(new sc_Pair("\u1E9Cy",null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Creverse-loop",(new sc_Pair("\u1E9Cx",(new sc_Pair((new sc_Pair("\u1E9Cnil",null)),null)))))),(new sc_Pair((new sc_Pair("\u1E9Creverse",(new sc_Pair("\u1E9Cx",null)))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Ccount-list",(new sc_Pair("\u1E9Cz",(new sc_Pair((new sc_Pair("\u1E9Csort-lp",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),null)))))),(new sc_Pair((new sc_Pair("\u1E9Cplus",(new sc_Pair((new sc_Pair("\u1E9Ccount-list",(new sc_Pair("\u1E9Cz",(new sc_Pair("\u1E9Cx",null)))))),(new sc_Pair((new sc_Pair("\u1E9Ccount-list",(new sc_Pair("\u1E9Cz",(new sc_Pair("\u1E9Cy",null)))))),null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cappend",(new sc_Pair("\u1E9Ca",(new sc_Pair("\u1E9Cb",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cappend",(new sc_Pair("\u1E9Ca",(new sc_Pair("\u1E9Cc",null)))))),null)))))),(new sc_Pair((new sc_Pair("\u1E9Cequal",(new sc_Pair("\u1E9Cb",(new sc_Pair("\u1E9Cc",null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cplus",(new sc_Pair((new sc_Pair("\u1E9Cremainder",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),(new sc_Pair((new sc_Pair("\u1E9Ctimes",(new sc_Pair("\u1E9Cy",(new sc_Pair((new sc_Pair("\u1E9Cquotient",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),null)))))),null)))))),(new sc_Pair((new sc_Pair("\u1E9Cfix",(new sc_Pair("\u1E9Cx",null)))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cpower-eval",(new sc_Pair((new sc_Pair("\u1E9Cbig-plus1",(new sc_Pair("\u1E9Cl",(new sc_Pair("\u1E9Ci",(new sc_Pair("\u1E9Cbase",null)))))))),(new sc_Pair("\u1E9Cbase",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cplus",(new sc_Pair((new sc_Pair("\u1E9Cpower-eval",(new sc_Pair("\u1E9Cl",(new sc_Pair("\u1E9Cbase",null)))))),(new sc_Pair("\u1E9Ci",null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cpower-eval",(new sc_Pair((new sc_Pair("\u1E9Cbig-plus",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",(new sc_Pair("\u1E9Ci",(new sc_Pair("\u1E9Cbase",null)))))))))),(new sc_Pair("\u1E9Cbase",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cplus",(new sc_Pair("\u1E9Ci",(new sc_Pair((new sc_Pair("\u1E9Cplus",(new sc_Pair((new sc_Pair("\u1E9Cpower-eval",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cbase",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cpower-eval",(new sc_Pair("\u1E9Cy",(new sc_Pair("\u1E9Cbase",null)))))),null)))))),null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cremainder",(new sc_Pair("\u1E9Cy",(new sc_Pair((1),null)))))),(new sc_Pair((new sc_Pair("\u1E9Czero",null)),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Clessp",(new sc_Pair((new sc_Pair("\u1E9Cremainder",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),(new sc_Pair("\u1E9Cy",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cnot",(new sc_Pair((new sc_Pair("\u1E9Czerop",(new sc_Pair("\u1E9Cy",null)))),null)))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cremainder",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cx",null)))))),(new sc_Pair((new sc_Pair("\u1E9Czero",null)),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Clessp",(new sc_Pair((new sc_Pair("\u1E9Cquotient",(new sc_Pair("\u1E9Ci",(new sc_Pair("\u1E9Cj",null)))))),(new sc_Pair("\u1E9Ci",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cand",(new sc_Pair((new sc_Pair("\u1E9Cnot",(new sc_Pair((new sc_Pair("\u1E9Czerop",(new sc_Pair("\u1E9Ci",null)))),null)))),(new sc_Pair((new sc_Pair("\u1E9Cor",(new sc_Pair((new sc_Pair("\u1E9Czerop",(new sc_Pair("\u1E9Cj",null)))),(new sc_Pair((new sc_Pair("\u1E9Cnot",(new sc_Pair((new sc_Pair("\u1E9Cequal",(new sc_Pair("\u1E9Cj",(new sc_Pair((1),null)))))),null)))),null)))))),null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Clessp",(new sc_Pair((new sc_Pair("\u1E9Cremainder",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),(new sc_Pair("\u1E9Cx",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cand",(new sc_Pair((new sc_Pair("\u1E9Cnot",(new sc_Pair((new sc_Pair("\u1E9Czerop",(new sc_Pair("\u1E9Cy",null)))),null)))),(new sc_Pair((new sc_Pair("\u1E9Cnot",(new sc_Pair((new sc_Pair("\u1E9Czerop",(new sc_Pair("\u1E9Cx",null)))),null)))),(new sc_Pair((new sc_Pair("\u1E9Cnot",(new sc_Pair((new sc_Pair("\u1E9Clessp",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),null)))),null)))))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cpower-eval",(new sc_Pair((new sc_Pair("\u1E9Cpower-rep",(new sc_Pair("\u1E9Ci",(new sc_Pair("\u1E9Cbase",null)))))),(new sc_Pair("\u1E9Cbase",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cfix",(new sc_Pair("\u1E9Ci",null)))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cpower-eval",(new sc_Pair((new sc_Pair("\u1E9Cbig-plus",(new sc_Pair((new sc_Pair("\u1E9Cpower-rep",(new sc_Pair("\u1E9Ci",(new sc_Pair("\u1E9Cbase",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cpower-rep",(new sc_Pair("\u1E9Cj",(new sc_Pair("\u1E9Cbase",null)))))),(new sc_Pair((new sc_Pair("\u1E9Czero",null)),(new sc_Pair("\u1E9Cbase",null)))))))))),(new sc_Pair("\u1E9Cbase",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cplus",(new sc_Pair("\u1E9Ci",(new sc_Pair("\u1E9Cj",null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cgcd",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cgcd",(new sc_Pair("\u1E9Cy",(new sc_Pair("\u1E9Cx",null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cnth",(new sc_Pair((new sc_Pair("\u1E9Cappend",(new sc_Pair("\u1E9Ca",(new sc_Pair("\u1E9Cb",null)))))),(new sc_Pair("\u1E9Ci",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cappend",(new sc_Pair((new sc_Pair("\u1E9Cnth",(new sc_Pair("\u1E9Ca",(new sc_Pair("\u1E9Ci",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cnth",(new sc_Pair("\u1E9Cb",(new sc_Pair((new sc_Pair("\u1E9Cdifference",(new sc_Pair("\u1E9Ci",(new sc_Pair((new sc_Pair("\u1E9Clength",(new sc_Pair("\u1E9Ca",null)))),null)))))),null)))))),null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cdifference",(new sc_Pair((new sc_Pair("\u1E9Cplus",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),(new sc_Pair("\u1E9Cx",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cfix",(new sc_Pair("\u1E9Cy",null)))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cdifference",(new sc_Pair((new sc_Pair("\u1E9Cplus",(new sc_Pair("\u1E9Cy",(new sc_Pair("\u1E9Cx",null)))))),(new sc_Pair("\u1E9Cx",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cfix",(new sc_Pair("\u1E9Cy",null)))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cdifference",(new sc_Pair((new sc_Pair("\u1E9Cplus",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cplus",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cz",null)))))),null)))))),(new sc_Pair((new sc_Pair("\u1E9Cdifference",(new sc_Pair("\u1E9Cy",(new sc_Pair("\u1E9Cz",null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Ctimes",(new sc_Pair("\u1E9Cx",(new sc_Pair((new sc_Pair("\u1E9Cdifference",(new sc_Pair("\u1E9Cc",(new sc_Pair("\u1E9Cw",null)))))),null)))))),(new sc_Pair((new sc_Pair("\u1E9Cdifference",(new sc_Pair((new sc_Pair("\u1E9Ctimes",(new sc_Pair("\u1E9Cc",(new sc_Pair("\u1E9Cx",null)))))),(new sc_Pair((new sc_Pair("\u1E9Ctimes",(new sc_Pair("\u1E9Cw",(new sc_Pair("\u1E9Cx",null)))))),null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cremainder",(new sc_Pair((new sc_Pair("\u1E9Ctimes",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cz",null)))))),(new sc_Pair("\u1E9Cz",null)))))),(new sc_Pair((new sc_Pair("\u1E9Czero",null)),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cdifference",(new sc_Pair((new sc_Pair("\u1E9Cplus",(new sc_Pair("\u1E9Cb",(new sc_Pair((new sc_Pair("\u1E9Cplus",(new sc_Pair("\u1E9Ca",(new sc_Pair("\u1E9Cc",null)))))),null)))))),(new sc_Pair("\u1E9Ca",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cplus",(new sc_Pair("\u1E9Cb",(new sc_Pair("\u1E9Cc",null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cdifference",(new sc_Pair((new sc_Pair("\u1E9Cadd1",(new sc_Pair((new sc_Pair("\u1E9Cplus",(new sc_Pair("\u1E9Cy",(new sc_Pair("\u1E9Cz",null)))))),null)))),(new sc_Pair("\u1E9Cz",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cadd1",(new sc_Pair("\u1E9Cy",null)))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Clessp",(new sc_Pair((new sc_Pair("\u1E9Cplus",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cplus",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cz",null)))))),null)))))),(new sc_Pair((new sc_Pair("\u1E9Clessp",(new sc_Pair("\u1E9Cy",(new sc_Pair("\u1E9Cz",null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Clessp",(new sc_Pair((new sc_Pair("\u1E9Ctimes",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cz",null)))))),(new sc_Pair((new sc_Pair("\u1E9Ctimes",(new sc_Pair("\u1E9Cy",(new sc_Pair("\u1E9Cz",null)))))),null)))))),(new sc_Pair((new sc_Pair("\u1E9Cand",(new sc_Pair((new sc_Pair("\u1E9Cnot",(new sc_Pair((new sc_Pair("\u1E9Czerop",(new sc_Pair("\u1E9Cz",null)))),null)))),(new sc_Pair((new sc_Pair("\u1E9Clessp",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Clessp",(new sc_Pair("\u1E9Cy",(new sc_Pair((new sc_Pair("\u1E9Cplus",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),null)))))),(new sc_Pair((new sc_Pair("\u1E9Cnot",(new sc_Pair((new sc_Pair("\u1E9Czerop",(new sc_Pair("\u1E9Cx",null)))),null)))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cgcd",(new sc_Pair((new sc_Pair("\u1E9Ctimes",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cz",null)))))),(new sc_Pair((new sc_Pair("\u1E9Ctimes",(new sc_Pair("\u1E9Cy",(new sc_Pair("\u1E9Cz",null)))))),null)))))),(new sc_Pair((new sc_Pair("\u1E9Ctimes",(new sc_Pair("\u1E9Cz",(new sc_Pair((new sc_Pair("\u1E9Cgcd",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cvalue",(new sc_Pair((new sc_Pair("\u1E9Cnormalize",(new sc_Pair("\u1E9Cx",null)))),(new sc_Pair("\u1E9Ca",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cvalue",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Ca",null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cflatten",(new sc_Pair("\u1E9Cx",null)))),(new sc_Pair((new sc_Pair("\u1E9Ccons",(new sc_Pair("\u1E9Cy",(new sc_Pair((new sc_Pair("\u1E9Cnil",null)),null)))))),null)))))),(new sc_Pair((new sc_Pair("\u1E9Cand",(new sc_Pair((new sc_Pair("\u1E9Cnlistp",(new sc_Pair("\u1E9Cx",null)))),(new sc_Pair((new sc_Pair("\u1E9Cequal",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Clistp",(new sc_Pair((new sc_Pair("\u1E9Cgopher",(new sc_Pair("\u1E9Cx",null)))),null)))),(new sc_Pair((new sc_Pair("\u1E9Clistp",(new sc_Pair("\u1E9Cx",null)))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Csamefringe",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cflatten",(new sc_Pair("\u1E9Cx",null)))),(new sc_Pair((new sc_Pair("\u1E9Cflatten",(new sc_Pair("\u1E9Cy",null)))),null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cgreatest-factor",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),(new sc_Pair((new sc_Pair("\u1E9Czero",null)),null)))))),(new sc_Pair((new sc_Pair("\u1E9Cand",(new sc_Pair((new sc_Pair("\u1E9Cor",(new sc_Pair((new sc_Pair("\u1E9Czerop",(new sc_Pair("\u1E9Cy",null)))),(new sc_Pair((new sc_Pair("\u1E9Cequal",(new sc_Pair("\u1E9Cy",(new sc_Pair((1),null)))))),null)))))),(new sc_Pair((new sc_Pair("\u1E9Cequal",(new sc_Pair("\u1E9Cx",(new sc_Pair((new sc_Pair("\u1E9Czero",null)),null)))))),null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cgreatest-factor",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),(new sc_Pair((1),null)))))),(new sc_Pair((new sc_Pair("\u1E9Cequal",(new sc_Pair("\u1E9Cx",(new sc_Pair((1),null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cnumberp",(new sc_Pair((new sc_Pair("\u1E9Cgreatest-factor",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),null)))),(new sc_Pair((new sc_Pair("\u1E9Cnot",(new sc_Pair((new sc_Pair("\u1E9Cand",(new sc_Pair((new sc_Pair("\u1E9Cor",(new sc_Pair((new sc_Pair("\u1E9Czerop",(new sc_Pair("\u1E9Cy",null)))),(new sc_Pair((new sc_Pair("\u1E9Cequal",(new sc_Pair("\u1E9Cy",(new sc_Pair((1),null)))))),null)))))),(new sc_Pair((new sc_Pair("\u1E9Cnot",(new sc_Pair((new sc_Pair("\u1E9Cnumberp",(new sc_Pair("\u1E9Cx",null)))),null)))),null)))))),null)))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Ctimes-list",(new sc_Pair((new sc_Pair("\u1E9Cappend",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),null)))),(new sc_Pair((new sc_Pair("\u1E9Ctimes",(new sc_Pair((new sc_Pair("\u1E9Ctimes-list",(new sc_Pair("\u1E9Cx",null)))),(new sc_Pair((new sc_Pair("\u1E9Ctimes-list",(new sc_Pair("\u1E9Cy",null)))),null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cprime-list",(new sc_Pair((new sc_Pair("\u1E9Cappend",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),null)))),(new sc_Pair((new sc_Pair("\u1E9Cand",(new sc_Pair((new sc_Pair("\u1E9Cprime-list",(new sc_Pair("\u1E9Cx",null)))),(new sc_Pair((new sc_Pair("\u1E9Cprime-list",(new sc_Pair("\u1E9Cy",null)))),null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cequal",(new sc_Pair("\u1E9Cz",(new sc_Pair((new sc_Pair("\u1E9Ctimes",(new sc_Pair("\u1E9Cw",(new sc_Pair("\u1E9Cz",null)))))),null)))))),(new sc_Pair((new sc_Pair("\u1E9Cand",(new sc_Pair((new sc_Pair("\u1E9Cnumberp",(new sc_Pair("\u1E9Cz",null)))),(new sc_Pair((new sc_Pair("\u1E9Cor",(new sc_Pair((new sc_Pair("\u1E9Cequal",(new sc_Pair("\u1E9Cz",(new sc_Pair((new sc_Pair("\u1E9Czero",null)),null)))))),(new sc_Pair((new sc_Pair("\u1E9Cequal",(new sc_Pair("\u1E9Cw",(new sc_Pair((1),null)))))),null)))))),null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cgreatereqp",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cnot",(new sc_Pair((new sc_Pair("\u1E9Clessp",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),null)))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cequal",(new sc_Pair("\u1E9Cx",(new sc_Pair((new sc_Pair("\u1E9Ctimes",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),null)))))),(new sc_Pair((new sc_Pair("\u1E9Cor",(new sc_Pair((new sc_Pair("\u1E9Cequal",(new sc_Pair("\u1E9Cx",(new sc_Pair((new sc_Pair("\u1E9Czero",null)),null)))))),(new sc_Pair((new sc_Pair("\u1E9Cand",(new sc_Pair((new sc_Pair("\u1E9Cnumberp",(new sc_Pair("\u1E9Cx",null)))),(new sc_Pair((new sc_Pair("\u1E9Cequal",(new sc_Pair("\u1E9Cy",(new sc_Pair((1),null)))))),null)))))),null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cremainder",(new sc_Pair((new sc_Pair("\u1E9Ctimes",(new sc_Pair("\u1E9Cy",(new sc_Pair("\u1E9Cx",null)))))),(new sc_Pair("\u1E9Cy",null)))))),(new sc_Pair((new sc_Pair("\u1E9Czero",null)),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Ctimes",(new sc_Pair("\u1E9Ca",(new sc_Pair("\u1E9Cb",null)))))),(new sc_Pair((1),null)))))),(new sc_Pair(sc_list("\u1E9Cand", (new sc_Pair("\u1E9Cnot",(new sc_Pair((new sc_Pair("\u1E9Cequal",(new sc_Pair("\u1E9Ca",(new sc_Pair((new sc_Pair("\u1E9Czero",null)),null)))))),null)))), (new sc_Pair("\u1E9Cnot",(new sc_Pair((new sc_Pair("\u1E9Cequal",(new sc_Pair("\u1E9Cb",(new sc_Pair((new sc_Pair("\u1E9Czero",null)),null)))))),null)))), (new sc_Pair("\u1E9Cnumberp",(new sc_Pair("\u1E9Ca",null)))), (new sc_Pair("\u1E9Cnumberp",(new sc_Pair("\u1E9Cb",null)))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Csub1",(new sc_Pair("\u1E9Ca",null)))),(new sc_Pair((new sc_Pair("\u1E9Czero",null)),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Csub1",(new sc_Pair("\u1E9Cb",null)))),(new sc_Pair((new sc_Pair("\u1E9Czero",null)),null))))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Clessp",(new sc_Pair((new sc_Pair("\u1E9Clength",(new sc_Pair((new sc_Pair("\u1E9Cdelete",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cl",null)))))),null)))),(new sc_Pair((new sc_Pair("\u1E9Clength",(new sc_Pair("\u1E9Cl",null)))),null)))))),(new sc_Pair((new sc_Pair("\u1E9Cmember",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cl",null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Csort2",(new sc_Pair((new sc_Pair("\u1E9Cdelete",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cl",null)))))),null)))),(new sc_Pair((new sc_Pair("\u1E9Cdelete",(new sc_Pair("\u1E9Cx",(new sc_Pair((new sc_Pair("\u1E9Csort2",(new sc_Pair("\u1E9Cl",null)))),null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cdsort",(new sc_Pair("\u1E9Cx",null)))),(new sc_Pair((new sc_Pair("\u1E9Csort2",(new sc_Pair("\u1E9Cx",null)))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Clength",(new sc_Pair((new sc_Pair("\u1E9Ccons",(new sc_Pair("\u1E9Cx1",(new sc_Pair((new sc_Pair("\u1E9Ccons",(new sc_Pair("\u1E9Cx2",(new sc_Pair((new sc_Pair("\u1E9Ccons",(new sc_Pair("\u1E9Cx3",(new sc_Pair((new sc_Pair("\u1E9Ccons",(new sc_Pair("\u1E9Cx4",(new sc_Pair((new sc_Pair("\u1E9Ccons",(new sc_Pair("\u1E9Cx5",(new sc_Pair((new sc_Pair("\u1E9Ccons",(new sc_Pair("\u1E9Cx6",(new sc_Pair("\u1E9Cx7",null)))))),null)))))),null)))))),null)))))),null)))))),null)))))),null)))),(new sc_Pair((new sc_Pair("\u1E9Cplus",(new sc_Pair((6),(new sc_Pair((new sc_Pair("\u1E9Clength",(new sc_Pair("\u1E9Cx7",null)))),null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cdifference",(new sc_Pair((new sc_Pair("\u1E9Cadd1",(new sc_Pair((new sc_Pair("\u1E9Cadd1",(new sc_Pair("\u1E9Cx",null)))),null)))),(new sc_Pair((2),null)))))),(new sc_Pair((new sc_Pair("\u1E9Cfix",(new sc_Pair("\u1E9Cx",null)))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cquotient",(new sc_Pair((new sc_Pair("\u1E9Cplus",(new sc_Pair("\u1E9Cx",(new sc_Pair((new sc_Pair("\u1E9Cplus",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),null)))))),(new sc_Pair((2),null)))))),(new sc_Pair((new sc_Pair("\u1E9Cplus",(new sc_Pair("\u1E9Cx",(new sc_Pair((new sc_Pair("\u1E9Cquotient",(new sc_Pair("\u1E9Cy",(new sc_Pair((2),null)))))),null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Csigma",(new sc_Pair((new sc_Pair("\u1E9Czero",null)),(new sc_Pair("\u1E9Ci",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cquotient",(new sc_Pair((new sc_Pair("\u1E9Ctimes",(new sc_Pair("\u1E9Ci",(new sc_Pair((new sc_Pair("\u1E9Cadd1",(new sc_Pair("\u1E9Ci",null)))),null)))))),(new sc_Pair((2),null)))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cplus",(new sc_Pair("\u1E9Cx",(new sc_Pair((new sc_Pair("\u1E9Cadd1",(new sc_Pair("\u1E9Cy",null)))),null)))))),(new sc_Pair((new sc_Pair("\u1E9Cif",(new sc_Pair((new sc_Pair("\u1E9Cnumberp",(new sc_Pair("\u1E9Cy",null)))),(new sc_Pair((new sc_Pair("\u1E9Cadd1",(new sc_Pair((new sc_Pair("\u1E9Cplus",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),null)))),(new sc_Pair((new sc_Pair("\u1E9Cadd1",(new sc_Pair("\u1E9Cx",null)))),null)))))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cdifference",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cdifference",(new sc_Pair("\u1E9Cz",(new sc_Pair("\u1E9Cy",null)))))),null)))))),(new sc_Pair((new sc_Pair("\u1E9Cif",(new sc_Pair((new sc_Pair("\u1E9Clessp",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cnot",(new sc_Pair((new sc_Pair("\u1E9Clessp",(new sc_Pair("\u1E9Cy",(new sc_Pair("\u1E9Cz",null)))))),null)))),(new sc_Pair((new sc_Pair("\u1E9Cif",(new sc_Pair((new sc_Pair("\u1E9Clessp",(new sc_Pair("\u1E9Cz",(new sc_Pair("\u1E9Cy",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cnot",(new sc_Pair((new sc_Pair("\u1E9Clessp",(new sc_Pair("\u1E9Cy",(new sc_Pair("\u1E9Cx",null)))))),null)))),(new sc_Pair((new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cfix",(new sc_Pair("\u1E9Cx",null)))),(new sc_Pair((new sc_Pair("\u1E9Cfix",(new sc_Pair("\u1E9Cz",null)))),null)))))),null)))))))),null)))))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cmeaning",(new sc_Pair((new sc_Pair("\u1E9Cplus-tree",(new sc_Pair((new sc_Pair("\u1E9Cdelete",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),null)))),(new sc_Pair("\u1E9Ca",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cif",(new sc_Pair((new sc_Pair("\u1E9Cmember",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cdifference",(new sc_Pair((new sc_Pair("\u1E9Cmeaning",(new sc_Pair((new sc_Pair("\u1E9Cplus-tree",(new sc_Pair("\u1E9Cy",null)))),(new sc_Pair("\u1E9Ca",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cmeaning",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Ca",null)))))),null)))))),(new sc_Pair((new sc_Pair("\u1E9Cmeaning",(new sc_Pair((new sc_Pair("\u1E9Cplus-tree",(new sc_Pair("\u1E9Cy",null)))),(new sc_Pair("\u1E9Ca",null)))))),null)))))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Ctimes",(new sc_Pair("\u1E9Cx",(new sc_Pair((new sc_Pair("\u1E9Cadd1",(new sc_Pair("\u1E9Cy",null)))),null)))))),(new sc_Pair((new sc_Pair("\u1E9Cif",(new sc_Pair((new sc_Pair("\u1E9Cnumberp",(new sc_Pair("\u1E9Cy",null)))),(new sc_Pair((new sc_Pair("\u1E9Cplus",(new sc_Pair("\u1E9Cx",(new sc_Pair((new sc_Pair("\u1E9Ctimes",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),null)))))),(new sc_Pair((new sc_Pair("\u1E9Cfix",(new sc_Pair("\u1E9Cx",null)))),null)))))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cnth",(new sc_Pair((new sc_Pair("\u1E9Cnil",null)),(new sc_Pair("\u1E9Ci",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cif",(new sc_Pair((new sc_Pair("\u1E9Czerop",(new sc_Pair("\u1E9Ci",null)))),(new sc_Pair((new sc_Pair("\u1E9Cnil",null)),(new sc_Pair((new sc_Pair("\u1E9Czero",null)),null)))))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Clast",(new sc_Pair((new sc_Pair("\u1E9Cappend",(new sc_Pair("\u1E9Ca",(new sc_Pair("\u1E9Cb",null)))))),null)))),(new sc_Pair((new sc_Pair("\u1E9Cif",(new sc_Pair((new sc_Pair("\u1E9Clistp",(new sc_Pair("\u1E9Cb",null)))),(new sc_Pair((new sc_Pair("\u1E9Clast",(new sc_Pair("\u1E9Cb",null)))),(new sc_Pair((new sc_Pair("\u1E9Cif",(new sc_Pair((new sc_Pair("\u1E9Clistp",(new sc_Pair("\u1E9Ca",null)))),(new sc_Pair((new sc_Pair("\u1E9Ccons",(new sc_Pair((new sc_Pair("\u1E9Ccar",(new sc_Pair((new sc_Pair("\u1E9Clast",(new sc_Pair("\u1E9Ca",null)))),null)))),(new sc_Pair("\u1E9Cb",null)))))),(new sc_Pair("\u1E9Cb",null)))))))),null)))))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Clessp",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),(new sc_Pair("\u1E9Cz",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cif",(new sc_Pair((new sc_Pair("\u1E9Clessp",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Ct",null)),(new sc_Pair("\u1E9Cz",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cf",null)),(new sc_Pair("\u1E9Cz",null)))))),null)))))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cassignment",(new sc_Pair("\u1E9Cx",(new sc_Pair((new sc_Pair("\u1E9Cappend",(new sc_Pair("\u1E9Ca",(new sc_Pair("\u1E9Cb",null)))))),null)))))),(new sc_Pair((new sc_Pair("\u1E9Cif",(new sc_Pair((new sc_Pair("\u1E9Cassignedp",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Ca",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cassignment",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Ca",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cassignment",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cb",null)))))),null)))))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Ccar",(new sc_Pair((new sc_Pair("\u1E9Cgopher",(new sc_Pair("\u1E9Cx",null)))),null)))),(new sc_Pair((new sc_Pair("\u1E9Cif",(new sc_Pair((new sc_Pair("\u1E9Clistp",(new sc_Pair("\u1E9Cx",null)))),(new sc_Pair((new sc_Pair("\u1E9Ccar",(new sc_Pair((new sc_Pair("\u1E9Cflatten",(new sc_Pair("\u1E9Cx",null)))),null)))),(new sc_Pair((new sc_Pair("\u1E9Czero",null)),null)))))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cflatten",(new sc_Pair((new sc_Pair("\u1E9Ccdr",(new sc_Pair((new sc_Pair("\u1E9Cgopher",(new sc_Pair("\u1E9Cx",null)))),null)))),null)))),(new sc_Pair((new sc_Pair("\u1E9Cif",(new sc_Pair((new sc_Pair("\u1E9Clistp",(new sc_Pair("\u1E9Cx",null)))),(new sc_Pair((new sc_Pair("\u1E9Ccdr",(new sc_Pair((new sc_Pair("\u1E9Cflatten",(new sc_Pair("\u1E9Cx",null)))),null)))),(new sc_Pair((new sc_Pair("\u1E9Ccons",(new sc_Pair((new sc_Pair("\u1E9Czero",null)),(new sc_Pair((new sc_Pair("\u1E9Cnil",null)),null)))))),null)))))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cquotient",(new sc_Pair((new sc_Pair("\u1E9Ctimes",(new sc_Pair("\u1E9Cy",(new sc_Pair("\u1E9Cx",null)))))),(new sc_Pair("\u1E9Cy",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cif",(new sc_Pair((new sc_Pair("\u1E9Czerop",(new sc_Pair("\u1E9Cy",null)))),(new sc_Pair((new sc_Pair("\u1E9Czero",null)),(new sc_Pair((new sc_Pair("\u1E9Cfix",(new sc_Pair("\u1E9Cx",null)))),null)))))))),null)))))), (new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cget",(new sc_Pair("\u1E9Cj",(new sc_Pair((new sc_Pair("\u1E9Cset",(new sc_Pair("\u1E9Ci",(new sc_Pair("\u1E9Cval",(new sc_Pair("\u1E9Cmem",null)))))))),null)))))),(new sc_Pair((new sc_Pair("\u1E9Cif",(new sc_Pair((new sc_Pair("\u1E9Ceqp",(new sc_Pair("\u1E9Cj",(new sc_Pair("\u1E9Ci",null)))))),(new sc_Pair("\u1E9Cval",(new sc_Pair((new sc_Pair("\u1E9Cget",(new sc_Pair("\u1E9Cj",(new sc_Pair("\u1E9Cmem",null)))))),null)))))))),null)))))))); + (const_nboyer = (new sc_Pair((new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cf",(new sc_Pair((new sc_Pair("\u1E9Cplus",(new sc_Pair((new sc_Pair("\u1E9Cplus",(new sc_Pair("\u1E9Ca",(new sc_Pair("\u1E9Cb",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cplus",(new sc_Pair("\u1E9Cc",(new sc_Pair((new sc_Pair("\u1E9Czero",null)),null)))))),null)))))),null)))))),(new sc_Pair((new sc_Pair("\u1E9Cy",(new sc_Pair("\u1E9Cf",(new sc_Pair((new sc_Pair("\u1E9Ctimes",(new sc_Pair((new sc_Pair("\u1E9Ctimes",(new sc_Pair("\u1E9Ca",(new sc_Pair("\u1E9Cb",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cplus",(new sc_Pair("\u1E9Cc",(new sc_Pair("\u1E9Cd",null)))))),null)))))),null)))))),(new sc_Pair((new sc_Pair("\u1E9Cz",(new sc_Pair("\u1E9Cf",(new sc_Pair((new sc_Pair("\u1E9Creverse",(new sc_Pair((new sc_Pair("\u1E9Cappend",(new sc_Pair((new sc_Pair("\u1E9Cappend",(new sc_Pair("\u1E9Ca",(new sc_Pair("\u1E9Cb",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cnil",null)),null)))))),null)))),null)))))),(new sc_Pair((new sc_Pair("\u1E9Cu",(new sc_Pair("\u1E9Cequal",(new sc_Pair((new sc_Pair("\u1E9Cplus",(new sc_Pair("\u1E9Ca",(new sc_Pair("\u1E9Cb",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cdifference",(new sc_Pair("\u1E9Cx",(new sc_Pair("\u1E9Cy",null)))))),null)))))))),(new sc_Pair((new sc_Pair("\u1E9Cw",(new sc_Pair("\u1E9Clessp",(new sc_Pair((new sc_Pair("\u1E9Cremainder",(new sc_Pair("\u1E9Ca",(new sc_Pair("\u1E9Cb",null)))))),(new sc_Pair((new sc_Pair("\u1E9Cmember",(new sc_Pair("\u1E9Ca",(new sc_Pair((new sc_Pair("\u1E9Clength",(new sc_Pair("\u1E9Cb",null)))),null)))))),null)))))))),null))))))))))); + BgL_nboyerzd2benchmarkzd2 = function() { + var args = null; + for (var sc_tmp = arguments.length - 1; sc_tmp >= 0; sc_tmp--) { + args = sc_cons(arguments[sc_tmp], args); + } + var n; + return ((n = ((args === null)?(0):(args.car))), (BgL_setupzd2boyerzd2()), (BgL_runzd2benchmarkzd2(("nboyer"+(sc_number2string(n))), (1), function() { + return (BgL_testzd2boyerzd2(n)); + }, function(rewrites) { + if ((sc_isNumber(rewrites))) + switch (n) { + case (0): + return (rewrites===(95024)); + break; + case (1): + return (rewrites===(591777)); + break; + case (2): + return (rewrites===(1813975)); + break; + case (3): + return (rewrites===(5375678)); + break; + case (4): + return (rewrites===(16445406)); + break; + case (5): + return (rewrites===(51507739)); + break; + default: + return true; + break; + } + else + return false; + }))); + }; + BgL_setupzd2boyerzd2 = function() { + return true; + }; + BgL_testzd2boyerzd2 = function() { + return true; + }; + translate_term_nboyer = function(term) { + var lst; + return (!(term instanceof sc_Pair)?term:(new sc_Pair((BgL_sc_symbolzd2ze3symbolzd2record_1ze3_nboyer((term.car))), ((lst = (term.cdr)), ((lst === null)?null:(new sc_Pair((translate_term_nboyer((lst.car))), (translate_args_nboyer((lst.cdr)))))))))); + }; + translate_args_nboyer = function(lst) { + var sc_lst_5; + var term; + return ((lst === null)?null:(new sc_Pair(((term = (lst.car)), (!(term instanceof sc_Pair)?term:(new sc_Pair((BgL_sc_symbolzd2ze3symbolzd2record_1ze3_nboyer((term.car))), (translate_args_nboyer((term.cdr))))))), ((sc_lst_5 = (lst.cdr)), ((sc_lst_5 === null)?null:(new sc_Pair((translate_term_nboyer((sc_lst_5.car))), (translate_args_nboyer((sc_lst_5.cdr)))))))))); + }; + untranslate_term_nboyer = function(term) { + var optrOpnd; + var tail1131; + var L1127; + var falseHead1130; + var symbol_record; + if (!(term instanceof sc_Pair)) + return term; + else + { + (falseHead1130 = (new sc_Pair(null, null))); + (L1127 = (term.cdr)); + (tail1131 = falseHead1130); + while (!(L1127 === null)) { + { + (tail1131.cdr = (new sc_Pair((untranslate_term_nboyer((L1127.car))), null))); + (tail1131 = (tail1131.cdr)); + (L1127 = (L1127.cdr)); + } + } + (optrOpnd = (falseHead1130.cdr)); + return (new sc_Pair(((symbol_record = (term.car)), (symbol_record[(0)])), optrOpnd)); + } + }; + BgL_sc_symbolzd2ze3symbolzd2record_1ze3_nboyer = function(sym) { + var r; + var x; + return ((x = (sc_assq(sym, BgL_sc_za2symbolzd2recordszd2alistza2_2z00_nboyer))), ((x!== false)?(x.cdr):((r = [sym, null]), (BgL_sc_za2symbolzd2recordszd2alistza2_2z00_nboyer = (new sc_Pair((new sc_Pair(sym, r)), BgL_sc_za2symbolzd2recordszd2alistza2_2z00_nboyer))), r))); + }; + (BgL_sc_za2symbolzd2recordszd2alistza2_2z00_nboyer = null); + translate_alist_nboyer = function(alist) { + var sc_alist_6; + var term; + return ((alist === null)?null:(new sc_Pair((new sc_Pair((alist.car.car), ((term = (alist.car.cdr)), (!(term instanceof sc_Pair)?term:(new sc_Pair((BgL_sc_symbolzd2ze3symbolzd2record_1ze3_nboyer((term.car))), (translate_args_nboyer((term.cdr))))))))), ((sc_alist_6 = (alist.cdr)), ((sc_alist_6 === null)?null:(new sc_Pair((new sc_Pair((sc_alist_6.car.car), (translate_term_nboyer((sc_alist_6.car.cdr))))), (translate_alist_nboyer((sc_alist_6.cdr)))))))))); + }; + apply_subst_nboyer = function(alist, term) { + var lst; + var temp_temp; + return (!(term instanceof sc_Pair)?((temp_temp = (sc_assq(term, alist))), ((temp_temp!== false)?(temp_temp.cdr):term)):(new sc_Pair((term.car), ((lst = (term.cdr)), ((lst === null)?null:(new sc_Pair((apply_subst_nboyer(alist, (lst.car))), (apply_subst_lst_nboyer(alist, (lst.cdr)))))))))); + }; + apply_subst_lst_nboyer = function(alist, lst) { + var sc_lst_7; + return ((lst === null)?null:(new sc_Pair((apply_subst_nboyer(alist, (lst.car))), ((sc_lst_7 = (lst.cdr)), ((sc_lst_7 === null)?null:(new sc_Pair((apply_subst_nboyer(alist, (sc_lst_7.car))), (apply_subst_lst_nboyer(alist, (sc_lst_7.cdr)))))))))); + }; + tautologyp_nboyer = function(sc_x_11, true_lst, false_lst) { + var tmp1125; + var x; + var tmp1126; + var sc_x_8; + var sc_tmp1125_9; + var sc_tmp1126_10; + var sc_x_11; + var true_lst; + var false_lst; + while (true) { + if ((((sc_tmp1126_10 = (is_term_equal_nboyer(sc_x_11, true_term_nboyer))), ((sc_tmp1126_10!== false)?sc_tmp1126_10:(is_term_member_nboyer(sc_x_11, true_lst))))!== false)) + return true; + else + if ((((sc_tmp1125_9 = (is_term_equal_nboyer(sc_x_11, false_term_nboyer))), ((sc_tmp1125_9!== false)?sc_tmp1125_9:(is_term_member_nboyer(sc_x_11, false_lst))))!== false)) + return false; + else + if (!(sc_x_11 instanceof sc_Pair)) + return false; + else + if (((sc_x_11.car)===if_constructor_nboyer)) + if ((((sc_x_8 = (sc_x_11.cdr.car)), (tmp1126 = (is_term_equal_nboyer(sc_x_8, true_term_nboyer))), ((tmp1126!== false)?tmp1126:(is_term_member_nboyer(sc_x_8, true_lst))))!== false)) + (sc_x_11 = (sc_x_11.cdr.cdr.car)); + else + if ((((x = (sc_x_11.cdr.car)), (tmp1125 = (is_term_equal_nboyer(x, false_term_nboyer))), ((tmp1125!== false)?tmp1125:(is_term_member_nboyer(x, false_lst))))!== false)) + (sc_x_11 = (sc_x_11.cdr.cdr.cdr.car)); + else + if (((tautologyp_nboyer((sc_x_11.cdr.cdr.car), (new sc_Pair((sc_x_11.cdr.car), true_lst)), false_lst))!== false)) + { + (false_lst = (new sc_Pair((sc_x_11.cdr.car), false_lst))); + (sc_x_11 = (sc_x_11.cdr.cdr.cdr.car)); + } + else + return false; + else + return false; + } + }; + (if_constructor_nboyer = "\u1E9C*"); + (rewrite_count_nboyer = (0)); + rewrite_nboyer = function(term) { + var term2; + var sc_term_12; + var lst; + var symbol_record; + var sc_lst_13; + { + (++rewrite_count_nboyer); + if (!(term instanceof sc_Pair)) + return term; + else + { + (sc_term_12 = (new sc_Pair((term.car), ((sc_lst_13 = (term.cdr)), ((sc_lst_13 === null)?null:(new sc_Pair((rewrite_nboyer((sc_lst_13.car))), (rewrite_args_nboyer((sc_lst_13.cdr)))))))))); + (lst = ((symbol_record = (term.car)), (symbol_record[(1)]))); + while (true) { + if ((lst === null)) + return sc_term_12; + else + if ((((term2 = ((lst.car).cdr.car)), (unify_subst_nboyer = null), (one_way_unify1_nboyer(sc_term_12, term2)))!== false)) + return (rewrite_nboyer((apply_subst_nboyer(unify_subst_nboyer, ((lst.car).cdr.cdr.car))))); + else + (lst = (lst.cdr)); + } + } + } + }; + rewrite_args_nboyer = function(lst) { + var sc_lst_14; + return ((lst === null)?null:(new sc_Pair((rewrite_nboyer((lst.car))), ((sc_lst_14 = (lst.cdr)), ((sc_lst_14 === null)?null:(new sc_Pair((rewrite_nboyer((sc_lst_14.car))), (rewrite_args_nboyer((sc_lst_14.cdr)))))))))); + }; + (unify_subst_nboyer = "\u1E9C*"); + one_way_unify1_nboyer = function(term1, term2) { + var lst1; + var lst2; + var temp_temp; + if (!(term2 instanceof sc_Pair)) + { + (temp_temp = (sc_assq(term2, unify_subst_nboyer))); + if ((temp_temp!== false)) + return (is_term_equal_nboyer(term1, (temp_temp.cdr))); + else + if ((sc_isNumber(term2))) + return (sc_isEqual(term1, term2)); + else + { + (unify_subst_nboyer = (new sc_Pair((new sc_Pair(term2, term1)), unify_subst_nboyer))); + return true; + } + } + else + if (!(term1 instanceof sc_Pair)) + return false; + else + if (((term1.car)===(term2.car))) + { + (lst1 = (term1.cdr)); + (lst2 = (term2.cdr)); + while (true) { + if ((lst1 === null)) + return (lst2 === null); + else + if ((lst2 === null)) + return false; + else + if (((one_way_unify1_nboyer((lst1.car), (lst2.car)))!== false)) + { + (lst1 = (lst1.cdr)); + (lst2 = (lst2.cdr)); + } + else + return false; + } + } + else + return false; + }; + (false_term_nboyer = "\u1E9C*"); + (true_term_nboyer = "\u1E9C*"); + trans_of_implies1_nboyer = function(n) { + var sc_n_15; + return ((sc_isEqual(n, (1)))?(sc_list("\u1E9Cimplies", (0), (1))):(sc_list("\u1E9Cand", (sc_list("\u1E9Cimplies", (n-(1)), n)), ((sc_n_15 = (n-(1))), ((sc_isEqual(sc_n_15, (1)))?(sc_list("\u1E9Cimplies", (0), (1))):(sc_list("\u1E9Cand", (sc_list("\u1E9Cimplies", (sc_n_15-(1)), sc_n_15)), (trans_of_implies1_nboyer((sc_n_15-(1))))))))))); + }; + is_term_equal_nboyer = function(x, y) { + var lst1; + var lst2; + var r2; + var r1; + if ((x instanceof sc_Pair)) + if ((y instanceof sc_Pair)) + if ((((r1 = (x.car)), (r2 = (y.car)), (r1===r2))!== false)) + { + (lst1 = (x.cdr)); + (lst2 = (y.cdr)); + while (true) { + if ((lst1 === null)) + return (lst2 === null); + else + if ((lst2 === null)) + return false; + else + if (((is_term_equal_nboyer((lst1.car), (lst2.car)))!== false)) + { + (lst1 = (lst1.cdr)); + (lst2 = (lst2.cdr)); + } + else + return false; + } + } + else + return false; + else + return false; + else + return (sc_isEqual(x, y)); + }; + is_term_member_nboyer = function(x, lst) { + var x; + var lst; + while (true) { + if ((lst === null)) + return false; + else + if (((is_term_equal_nboyer(x, (lst.car)))!== false)) + return true; + else + (lst = (lst.cdr)); + } + }; + BgL_setupzd2boyerzd2 = function() { + var symbol_record; + var value; + var BgL_sc_symbolzd2record_16zd2; + var sym; + var sc_sym_17; + var term; + var lst; + var sc_term_18; + var sc_term_19; + { + (BgL_sc_za2symbolzd2recordszd2alistza2_2z00_nboyer = null); + (if_constructor_nboyer = (BgL_sc_symbolzd2ze3symbolzd2record_1ze3_nboyer("\u1E9Cif"))); + (false_term_nboyer = ((sc_term_19 = (new sc_Pair("\u1E9Cf",null))), (!(sc_term_19 instanceof sc_Pair)?sc_term_19:(new sc_Pair((BgL_sc_symbolzd2ze3symbolzd2record_1ze3_nboyer((sc_term_19.car))), (translate_args_nboyer((sc_term_19.cdr)))))))); + (true_term_nboyer = ((sc_term_18 = (new sc_Pair("\u1E9Ct",null))), (!(sc_term_18 instanceof sc_Pair)?sc_term_18:(new sc_Pair((BgL_sc_symbolzd2ze3symbolzd2record_1ze3_nboyer((sc_term_18.car))), (translate_args_nboyer((sc_term_18.cdr)))))))); + (lst = sc_const_3_nboyer); + while (!(lst === null)) { + { + (term = (lst.car)); + if (((term instanceof sc_Pair)&&(((term.car)==="\u1E9Cequal")&&((term.cdr.car) instanceof sc_Pair)))) + { + (sc_sym_17 = ((term.cdr.car).car)); + (value = (new sc_Pair((!(term instanceof sc_Pair)?term:(new sc_Pair((BgL_sc_symbolzd2ze3symbolzd2record_1ze3_nboyer((term.car))), (translate_args_nboyer((term.cdr)))))), ((sym = ((term.cdr.car).car)), (BgL_sc_symbolzd2record_16zd2 = (BgL_sc_symbolzd2ze3symbolzd2record_1ze3_nboyer(sym))), (BgL_sc_symbolzd2record_16zd2[(1)]))))); + (symbol_record = (BgL_sc_symbolzd2ze3symbolzd2record_1ze3_nboyer(sc_sym_17))); + (symbol_record[(1)] = value); + } + else + (sc_error("ADD-LEMMA did not like term: ", term)); + (lst = (lst.cdr)); + } + } + return true; + } + }; + BgL_testzd2boyerzd2 = function(n) { + var optrOpnd; + var term; + var sc_n_20; + var answer; + var sc_term_21; + var sc_term_22; + { + (rewrite_count_nboyer = (0)); + (term = sc_const_4_nboyer); + (sc_n_20 = n); + while (!(sc_n_20=== 0)) { + { + (term = (sc_list("\u1E9Cor", term, (new sc_Pair("\u1E9Cf",null))))); + (--sc_n_20); + } + } + (sc_term_22 = term); + if (!(sc_term_22 instanceof sc_Pair)) + (optrOpnd = sc_term_22); + else + (optrOpnd = (new sc_Pair((BgL_sc_symbolzd2ze3symbolzd2record_1ze3_nboyer((sc_term_22.car))), (translate_args_nboyer((sc_term_22.cdr)))))); + (sc_term_21 = (apply_subst_nboyer(((const_nboyer === null)?null:(new sc_Pair((new sc_Pair((const_nboyer.car.car), (translate_term_nboyer((const_nboyer.car.cdr))))), (translate_alist_nboyer((const_nboyer.cdr)))))), optrOpnd))); + (answer = (tautologyp_nboyer((rewrite_nboyer(sc_term_21)), null, null))); + (sc_write(rewrite_count_nboyer)); + (sc_display(" rewrites")); + (sc_newline()); + if ((answer!== false)) + return rewrite_count_nboyer; + else + return false; + } + }; +} +/* Exported Variables */ +var BgL_parsezd2ze3nbzd2treesze3; +var BgL_earleyzd2benchmarkzd2; +var BgL_parsezd2ze3parsedzf3zc2; +var test; +var BgL_parsezd2ze3treesz31; +var BgL_makezd2parserzd2; +/* End Exports */ + +var const_earley; +{ + (const_earley = (new sc_Pair((new sc_Pair("\u1E9Cs",(new sc_Pair((new sc_Pair("\u1E9Ca",null)),(new sc_Pair((new sc_Pair("\u1E9Cs",(new sc_Pair("\u1E9Cs",null)))),null)))))),null))); + BgL_makezd2parserzd2 = function(grammar, lexer) { + var i; + var parser_descr; + var def_loop; + var nb_nts; + var names; + var steps; + var predictors; + var enders; + var starters; + var nts; + var sc_names_1; + var sc_steps_2; + var sc_predictors_3; + var sc_enders_4; + var sc_starters_5; + var nb_confs; + var BgL_sc_defzd2loop_6zd2; + var BgL_sc_nbzd2nts_7zd2; + var sc_nts_8; + var BgL_sc_defzd2loop_9zd2; + var ind; + { + ind = function(nt, sc_nts_10) { + var i; + { + (i = ((sc_nts_10.length)-(1))); + while (true) { + if ((i>=(0))) + if ((sc_isEqual((sc_nts_10[i]), nt))) + return i; + else + (--i); + else + return false; + } + } + }; + (sc_nts_8 = ((BgL_sc_defzd2loop_9zd2 = function(defs, sc_nts_11) { + var rule_loop; + var head; + var def; + return ((defs instanceof sc_Pair)?((def = (defs.car)), (head = (def.car)), (rule_loop = function(rules, sc_nts_12) { + var nt; + var l; + var sc_nts_13; + var rule; + if ((rules instanceof sc_Pair)) + { + (rule = (rules.car)); + (l = rule); + (sc_nts_13 = sc_nts_12); + while ((l instanceof sc_Pair)) { + { + (nt = (l.car)); + (l = (l.cdr)); + (sc_nts_13 = (((sc_member(nt, sc_nts_13))!== false)?sc_nts_13:(new sc_Pair(nt, sc_nts_13)))); + } + } + return (rule_loop((rules.cdr), sc_nts_13)); + } + else + return (BgL_sc_defzd2loop_9zd2((defs.cdr), sc_nts_12)); + }), (rule_loop((def.cdr), (((sc_member(head, sc_nts_11))!== false)?sc_nts_11:(new sc_Pair(head, sc_nts_11)))))):(sc_list2vector((sc_reverse(sc_nts_11))))); + }), (BgL_sc_defzd2loop_9zd2(grammar, null)))); + (BgL_sc_nbzd2nts_7zd2 = (sc_nts_8.length)); + (nb_confs = (((BgL_sc_defzd2loop_6zd2 = function(defs, BgL_sc_nbzd2confs_14zd2) { + var rule_loop; + var def; + return ((defs instanceof sc_Pair)?((def = (defs.car)), (rule_loop = function(rules, BgL_sc_nbzd2confs_15zd2) { + var l; + var BgL_sc_nbzd2confs_16zd2; + var rule; + if ((rules instanceof sc_Pair)) + { + (rule = (rules.car)); + (l = rule); + (BgL_sc_nbzd2confs_16zd2 = BgL_sc_nbzd2confs_15zd2); + while ((l instanceof sc_Pair)) { + { + (l = (l.cdr)); + (++BgL_sc_nbzd2confs_16zd2); + } + } + return (rule_loop((rules.cdr), (BgL_sc_nbzd2confs_16zd2+(1)))); + } + else + return (BgL_sc_defzd2loop_6zd2((defs.cdr), BgL_sc_nbzd2confs_15zd2)); + }), (rule_loop((def.cdr), BgL_sc_nbzd2confs_14zd2))):BgL_sc_nbzd2confs_14zd2); + }), (BgL_sc_defzd2loop_6zd2(grammar, (0))))+BgL_sc_nbzd2nts_7zd2)); + (sc_starters_5 = (sc_makeVector(BgL_sc_nbzd2nts_7zd2, null))); + (sc_enders_4 = (sc_makeVector(BgL_sc_nbzd2nts_7zd2, null))); + (sc_predictors_3 = (sc_makeVector(BgL_sc_nbzd2nts_7zd2, null))); + (sc_steps_2 = (sc_makeVector(nb_confs, false))); + (sc_names_1 = (sc_makeVector(nb_confs, false))); + (nts = sc_nts_8); + (starters = sc_starters_5); + (enders = sc_enders_4); + (predictors = sc_predictors_3); + (steps = sc_steps_2); + (names = sc_names_1); + (nb_nts = (sc_nts_8.length)); + (i = (nb_nts-(1))); + while ((i>=(0))) { + { + (sc_steps_2[i] = (i-nb_nts)); + (sc_names_1[i] = (sc_list((sc_nts_8[i]), (0)))); + (sc_enders_4[i] = (sc_list(i))); + (--i); + } + } + def_loop = function(defs, conf) { + var rule_loop; + var head; + var def; + return ((defs instanceof sc_Pair)?((def = (defs.car)), (head = (def.car)), (rule_loop = function(rules, conf, rule_num) { + var i; + var sc_i_17; + var nt; + var l; + var sc_conf_18; + var sc_i_19; + var rule; + if ((rules instanceof sc_Pair)) + { + (rule = (rules.car)); + (names[conf] = (sc_list(head, rule_num))); + (sc_i_19 = (ind(head, nts))); + (starters[sc_i_19] = (new sc_Pair(conf, (starters[sc_i_19])))); + (l = rule); + (sc_conf_18 = conf); + while ((l instanceof sc_Pair)) { + { + (nt = (l.car)); + (steps[sc_conf_18] = (ind(nt, nts))); + (sc_i_17 = (ind(nt, nts))); + (predictors[sc_i_17] = (new sc_Pair(sc_conf_18, (predictors[sc_i_17])))); + (l = (l.cdr)); + (++sc_conf_18); + } + } + (steps[sc_conf_18] = ((ind(head, nts))-nb_nts)); + (i = (ind(head, nts))); + (enders[i] = (new sc_Pair(sc_conf_18, (enders[i])))); + return (rule_loop((rules.cdr), (sc_conf_18+(1)), (rule_num+(1)))); + } + else + return (def_loop((defs.cdr), conf)); + }), (rule_loop((def.cdr), conf, (1)))):undefined); + }; + (def_loop(grammar, (sc_nts_8.length))); + (parser_descr = [lexer, sc_nts_8, sc_starters_5, sc_enders_4, sc_predictors_3, sc_steps_2, sc_names_1]); + return function(input) { + var optrOpnd; + var sc_optrOpnd_20; + var sc_optrOpnd_21; + var sc_optrOpnd_22; + var loop1; + var BgL_sc_stateza2_23za2; + var toks; + var BgL_sc_nbzd2nts_24zd2; + var sc_steps_25; + var sc_enders_26; + var state_num; + var BgL_sc_statesza2_27za2; + var states; + var i; + var conf; + var l; + var tok_nts; + var sc_i_28; + var sc_i_29; + var l1; + var l2; + var tok; + var tail1129; + var L1125; + var goal_enders; + var BgL_sc_statesza2_30za2; + var BgL_sc_nbzd2nts_31zd2; + var BgL_sc_nbzd2confs_32zd2; + var nb_toks; + var goal_starters; + var sc_states_33; + var BgL_sc_nbzd2confs_34zd2; + var BgL_sc_nbzd2toks_35zd2; + var sc_toks_36; + var falseHead1128; + var sc_names_37; + var sc_steps_38; + var sc_predictors_39; + var sc_enders_40; + var sc_starters_41; + var sc_nts_42; + var lexer; + var sc_ind_43; + var make_states; + var BgL_sc_confzd2setzd2getza2_44za2; + var conf_set_merge_new_bang; + var conf_set_adjoin; + var BgL_sc_confzd2setzd2adjoinza2_45za2; + var BgL_sc_confzd2setzd2adjoinza2za2_46z00; + var conf_set_union; + var forw; + var is_parsed; + var deriv_trees; + var BgL_sc_derivzd2treesza2_47z70; + var nb_deriv_trees; + var BgL_sc_nbzd2derivzd2treesza2_48za2; + { + sc_ind_43 = function(nt, sc_nts_49) { + var i; + { + (i = ((sc_nts_49.length)-(1))); + while (true) { + if ((i>=(0))) + if ((sc_isEqual((sc_nts_49[i]), nt))) + return i; + else + (--i); + else + return false; + } + } + }; + make_states = function(BgL_sc_nbzd2toks_50zd2, BgL_sc_nbzd2confs_51zd2) { + var v; + var i; + var sc_states_52; + { + (sc_states_52 = (sc_makeVector((BgL_sc_nbzd2toks_50zd2+(1)), false))); + (i = BgL_sc_nbzd2toks_50zd2); + while ((i>=(0))) { + { + (v = (sc_makeVector((BgL_sc_nbzd2confs_51zd2+(1)), false))); + (v[(0)] = (-1)); + (sc_states_52[i] = v); + (--i); + } + } + return sc_states_52; + } + }; + BgL_sc_confzd2setzd2getza2_44za2 = function(state, BgL_sc_statezd2num_53zd2, sc_conf_54) { + var conf_set; + var BgL_sc_confzd2set_55zd2; + return ((BgL_sc_confzd2set_55zd2 = (state[(sc_conf_54+(1))])), ((BgL_sc_confzd2set_55zd2!== false)?BgL_sc_confzd2set_55zd2:((conf_set = (sc_makeVector((BgL_sc_statezd2num_53zd2+(6)), false))), (conf_set[(1)] = (-3)), (conf_set[(2)] = (-1)), (conf_set[(3)] = (-1)), (conf_set[(4)] = (-1)), (state[(sc_conf_54+(1))] = conf_set), conf_set))); + }; + conf_set_merge_new_bang = function(conf_set) { + return ((conf_set[((conf_set[(1)])+(5))] = (conf_set[(4)])), (conf_set[(1)] = (conf_set[(3)])), (conf_set[(3)] = (-1)), (conf_set[(4)] = (-1))); + }; + conf_set_adjoin = function(state, conf_set, sc_conf_56, i) { + var tail; + return ((tail = (conf_set[(3)])), (conf_set[(i+(5))] = (-1)), (conf_set[(tail+(5))] = i), (conf_set[(3)] = i), ((tail<(0))?((conf_set[(0)] = (state[(0)])), (state[(0)] = sc_conf_56)):undefined)); + }; + BgL_sc_confzd2setzd2adjoinza2_45za2 = function(sc_states_57, BgL_sc_statezd2num_58zd2, l, i) { + var conf_set; + var sc_conf_59; + var l1; + var state; + { + (state = (sc_states_57[BgL_sc_statezd2num_58zd2])); + (l1 = l); + while ((l1 instanceof sc_Pair)) { + { + (sc_conf_59 = (l1.car)); + (conf_set = (BgL_sc_confzd2setzd2getza2_44za2(state, BgL_sc_statezd2num_58zd2, sc_conf_59))); + if (((conf_set[(i+(5))])=== false)) + { + (conf_set_adjoin(state, conf_set, sc_conf_59, i)); + (l1 = (l1.cdr)); + } + else + (l1 = (l1.cdr)); + } + } + return undefined; + } + }; + BgL_sc_confzd2setzd2adjoinza2za2_46z00 = function(sc_states_60, BgL_sc_statesza2_61za2, BgL_sc_statezd2num_62zd2, sc_conf_63, i) { + var BgL_sc_confzd2setza2_64z70; + var BgL_sc_stateza2_65za2; + var conf_set; + var state; + return ((state = (sc_states_60[BgL_sc_statezd2num_62zd2])), ((((conf_set = (state[(sc_conf_63+(1))])), ((conf_set!== false)?(conf_set[(i+(5))]):false))!== false)?((BgL_sc_stateza2_65za2 = (BgL_sc_statesza2_61za2[BgL_sc_statezd2num_62zd2])), (BgL_sc_confzd2setza2_64z70 = (BgL_sc_confzd2setzd2getza2_44za2(BgL_sc_stateza2_65za2, BgL_sc_statezd2num_62zd2, sc_conf_63))), (((BgL_sc_confzd2setza2_64z70[(i+(5))])=== false)?(conf_set_adjoin(BgL_sc_stateza2_65za2, BgL_sc_confzd2setza2_64z70, sc_conf_63, i)):undefined), true):false)); + }; + conf_set_union = function(state, conf_set, sc_conf_66, other_set) { + var i; + { + (i = (other_set[(2)])); + while ((i>=(0))) { + if (((conf_set[(i+(5))])=== false)) + { + (conf_set_adjoin(state, conf_set, sc_conf_66, i)); + (i = (other_set[(i+(5))])); + } + else + (i = (other_set[(i+(5))])); + } + return undefined; + } + }; + forw = function(sc_states_67, BgL_sc_statezd2num_68zd2, sc_starters_69, sc_enders_70, sc_predictors_71, sc_steps_72, sc_nts_73) { + var next_set; + var next; + var conf_set; + var ender; + var l; + var starter_set; + var starter; + var sc_l_74; + var sc_loop1_75; + var head; + var BgL_sc_confzd2set_76zd2; + var BgL_sc_statezd2num_77zd2; + var state; + var sc_states_78; + var preds; + var BgL_sc_confzd2set_79zd2; + var step; + var sc_conf_80; + var BgL_sc_nbzd2nts_81zd2; + var sc_state_82; + { + (sc_state_82 = (sc_states_67[BgL_sc_statezd2num_68zd2])); + (BgL_sc_nbzd2nts_81zd2 = (sc_nts_73.length)); + while (true) { + { + (sc_conf_80 = (sc_state_82[(0)])); + if ((sc_conf_80>=(0))) + { + (step = (sc_steps_72[sc_conf_80])); + (BgL_sc_confzd2set_79zd2 = (sc_state_82[(sc_conf_80+(1))])); + (head = (BgL_sc_confzd2set_79zd2[(4)])); + (sc_state_82[(0)] = (BgL_sc_confzd2set_79zd2[(0)])); + (conf_set_merge_new_bang(BgL_sc_confzd2set_79zd2)); + if ((step>=(0))) + { + (sc_l_74 = (sc_starters_69[step])); + while ((sc_l_74 instanceof sc_Pair)) { + { + (starter = (sc_l_74.car)); + (starter_set = (BgL_sc_confzd2setzd2getza2_44za2(sc_state_82, BgL_sc_statezd2num_68zd2, starter))); + if (((starter_set[(BgL_sc_statezd2num_68zd2+(5))])=== false)) + { + (conf_set_adjoin(sc_state_82, starter_set, starter, BgL_sc_statezd2num_68zd2)); + (sc_l_74 = (sc_l_74.cdr)); + } + else + (sc_l_74 = (sc_l_74.cdr)); + } + } + (l = (sc_enders_70[step])); + while ((l instanceof sc_Pair)) { + { + (ender = (l.car)); + if ((((conf_set = (sc_state_82[(ender+(1))])), ((conf_set!== false)?(conf_set[(BgL_sc_statezd2num_68zd2+(5))]):false))!== false)) + { + (next = (sc_conf_80+(1))); + (next_set = (BgL_sc_confzd2setzd2getza2_44za2(sc_state_82, BgL_sc_statezd2num_68zd2, next))); + (conf_set_union(sc_state_82, next_set, next, BgL_sc_confzd2set_79zd2)); + (l = (l.cdr)); + } + else + (l = (l.cdr)); + } + } + } + else + { + (preds = (sc_predictors_71[(step+BgL_sc_nbzd2nts_81zd2)])); + (sc_states_78 = sc_states_67); + (state = sc_state_82); + (BgL_sc_statezd2num_77zd2 = BgL_sc_statezd2num_68zd2); + (BgL_sc_confzd2set_76zd2 = BgL_sc_confzd2set_79zd2); + sc_loop1_75 = function(l) { + var sc_state_83; + var BgL_sc_nextzd2set_84zd2; + var sc_next_85; + var pred_set; + var i; + var pred; + if ((l instanceof sc_Pair)) + { + (pred = (l.car)); + (i = head); + while ((i>=(0))) { + { + (pred_set = ((sc_state_83 = (sc_states_78[i])), (sc_state_83[(pred+(1))]))); + if ((pred_set!== false)) + { + (sc_next_85 = (pred+(1))); + (BgL_sc_nextzd2set_84zd2 = (BgL_sc_confzd2setzd2getza2_44za2(state, BgL_sc_statezd2num_77zd2, sc_next_85))); + (conf_set_union(state, BgL_sc_nextzd2set_84zd2, sc_next_85, pred_set)); + } + (i = (BgL_sc_confzd2set_76zd2[(i+(5))])); + } + } + return (sc_loop1_75((l.cdr))); + } + else + return undefined; + }; + (sc_loop1_75(preds)); + } + } + else + return undefined; + } + } + } + }; + is_parsed = function(nt, i, j, sc_nts_86, sc_enders_87, sc_states_88) { + var conf_set; + var state; + var sc_conf_89; + var l; + var BgL_sc_ntza2_90za2; + { + (BgL_sc_ntza2_90za2 = (sc_ind_43(nt, sc_nts_86))); + if ((BgL_sc_ntza2_90za2!== false)) + { + (sc_nts_86.length); + (l = (sc_enders_87[BgL_sc_ntza2_90za2])); + while (true) { + if ((l instanceof sc_Pair)) + { + (sc_conf_89 = (l.car)); + if ((((state = (sc_states_88[j])), (conf_set = (state[(sc_conf_89+(1))])), ((conf_set!== false)?(conf_set[(i+(5))]):false))!== false)) + return true; + else + (l = (l.cdr)); + } + else + return false; + } + } + else + return false; + } + }; + deriv_trees = function(sc_conf_91, i, j, sc_enders_92, sc_steps_93, sc_names_94, sc_toks_95, sc_states_96, BgL_sc_nbzd2nts_97zd2) { + var sc_loop1_98; + var prev; + var name; + return ((name = (sc_names_94[sc_conf_91])), ((name!== false)?((sc_conf_91=(0))) + if (((k>=i)&&(((sc_state_99 = (sc_states_96[k])), (conf_set = (sc_state_99[(prev+(1))])), ((conf_set!== false)?(conf_set[(i+(5))]):false))!== false))) + { + (prev_trees = (deriv_trees(prev, i, k, sc_enders_92, sc_steps_93, sc_names_94, sc_toks_95, sc_states_96, BgL_sc_nbzd2nts_97zd2))); + (ender_trees = (deriv_trees(ender, k, j, sc_enders_92, sc_steps_93, sc_names_94, sc_toks_95, sc_states_96, BgL_sc_nbzd2nts_97zd2))); + loop3 = function(l3, l2) { + var l4; + var sc_l2_100; + var ender_tree; + if ((l3 instanceof sc_Pair)) + { + (ender_tree = (sc_list((l3.car)))); + (l4 = prev_trees); + (sc_l2_100 = l2); + while ((l4 instanceof sc_Pair)) { + { + (sc_l2_100 = (new sc_Pair((sc_append((l4.car), ender_tree)), sc_l2_100))); + (l4 = (l4.cdr)); + } + } + return (loop3((l3.cdr), sc_l2_100)); + } + else + return (loop2((ender_set[(k+(5))]), l2)); + }; + return (loop3(ender_trees, l2)); + } + else + (k = (ender_set[(k+(5))])); + else + return (sc_loop1_98((l1.cdr), l2)); + } + }; + return (loop2((ender_set[(2)]), l2)); + } + else + (l1 = (l1.cdr)); + } + else + return l2; + } + }), (sc_loop1_98((sc_enders_92[(sc_steps_93[prev])]), null))))); + }; + BgL_sc_derivzd2treesza2_47z70 = function(nt, i, j, sc_nts_101, sc_enders_102, sc_steps_103, sc_names_104, sc_toks_105, sc_states_106) { + var conf_set; + var state; + var sc_conf_107; + var l; + var trees; + var BgL_sc_nbzd2nts_108zd2; + var BgL_sc_ntza2_109za2; + { + (BgL_sc_ntza2_109za2 = (sc_ind_43(nt, sc_nts_101))); + if ((BgL_sc_ntza2_109za2!== false)) + { + (BgL_sc_nbzd2nts_108zd2 = (sc_nts_101.length)); + (l = (sc_enders_102[BgL_sc_ntza2_109za2])); + (trees = null); + while ((l instanceof sc_Pair)) { + { + (sc_conf_107 = (l.car)); + if ((((state = (sc_states_106[j])), (conf_set = (state[(sc_conf_107+(1))])), ((conf_set!== false)?(conf_set[(i+(5))]):false))!== false)) + { + (l = (l.cdr)); + (trees = (sc_append((deriv_trees(sc_conf_107, i, j, sc_enders_102, sc_steps_103, sc_names_104, sc_toks_105, sc_states_106, BgL_sc_nbzd2nts_108zd2)), trees))); + } + else + (l = (l.cdr)); + } + } + return trees; + } + else + return false; + } + }; + nb_deriv_trees = function(sc_conf_110, i, j, sc_enders_111, sc_steps_112, sc_toks_113, sc_states_114, BgL_sc_nbzd2nts_115zd2) { + var sc_loop1_116; + var tmp1124; + var prev; + return ((prev = (sc_conf_110-(1))), ((((tmp1124 = (sc_conf_110=(0))) { + if (((k>=i)&&(((state = (sc_states_114[k])), (conf_set = (state[(prev+(1))])), ((conf_set!== false)?(conf_set[(i+(5))]):false))!== false))) + { + (nb_prev_trees = (nb_deriv_trees(prev, i, k, sc_enders_111, sc_steps_112, sc_toks_113, sc_states_114, BgL_sc_nbzd2nts_115zd2))); + (nb_ender_trees = (nb_deriv_trees(ender, k, j, sc_enders_111, sc_steps_112, sc_toks_113, sc_states_114, BgL_sc_nbzd2nts_115zd2))); + (k = (ender_set[(k+(5))])); + (n +=(nb_prev_trees*nb_ender_trees)); + } + else + (k = (ender_set[(k+(5))])); + } + return (sc_loop1_116((l.cdr), n)); + } + else + (l = (l.cdr)); + } + else + return sc_n_118; + } + }), (sc_loop1_116((sc_enders_111[(sc_steps_112[prev])]), (0)))))); + }; + BgL_sc_nbzd2derivzd2treesza2_48za2 = function(nt, i, j, sc_nts_119, sc_enders_120, sc_steps_121, sc_toks_122, sc_states_123) { + var conf_set; + var state; + var sc_conf_124; + var l; + var nb_trees; + var BgL_sc_nbzd2nts_125zd2; + var BgL_sc_ntza2_126za2; + { + (BgL_sc_ntza2_126za2 = (sc_ind_43(nt, sc_nts_119))); + if ((BgL_sc_ntza2_126za2!== false)) + { + (BgL_sc_nbzd2nts_125zd2 = (sc_nts_119.length)); + (l = (sc_enders_120[BgL_sc_ntza2_126za2])); + (nb_trees = (0)); + while ((l instanceof sc_Pair)) { + { + (sc_conf_124 = (l.car)); + if ((((state = (sc_states_123[j])), (conf_set = (state[(sc_conf_124+(1))])), ((conf_set!== false)?(conf_set[(i+(5))]):false))!== false)) + { + (l = (l.cdr)); + (nb_trees = ((nb_deriv_trees(sc_conf_124, i, j, sc_enders_120, sc_steps_121, sc_toks_122, sc_states_123, BgL_sc_nbzd2nts_125zd2))+nb_trees)); + } + else + (l = (l.cdr)); + } + } + return nb_trees; + } + else + return false; + } + }; + (lexer = (parser_descr[(0)])); + (sc_nts_42 = (parser_descr[(1)])); + (sc_starters_41 = (parser_descr[(2)])); + (sc_enders_40 = (parser_descr[(3)])); + (sc_predictors_39 = (parser_descr[(4)])); + (sc_steps_38 = (parser_descr[(5)])); + (sc_names_37 = (parser_descr[(6)])); + (falseHead1128 = (new sc_Pair(null, null))); + (L1125 = (lexer(input))); + (tail1129 = falseHead1128); + while (!(L1125 === null)) { + { + (tok = (L1125.car)); + (l1 = (tok.cdr)); + (l2 = null); + while ((l1 instanceof sc_Pair)) { + { + (sc_i_29 = (sc_ind_43((l1.car), sc_nts_42))); + if ((sc_i_29!== false)) + { + (l1 = (l1.cdr)); + (l2 = (new sc_Pair(sc_i_29, l2))); + } + else + (l1 = (l1.cdr)); + } + } + (sc_optrOpnd_22 = (new sc_Pair((tok.car), (sc_reverse(l2))))); + (sc_optrOpnd_21 = (new sc_Pair(sc_optrOpnd_22, null))); + (tail1129.cdr = sc_optrOpnd_21); + (tail1129 = (tail1129.cdr)); + (L1125 = (L1125.cdr)); + } + } + (sc_optrOpnd_20 = (falseHead1128.cdr)); + (sc_toks_36 = (sc_list2vector(sc_optrOpnd_20))); + (BgL_sc_nbzd2toks_35zd2 = (sc_toks_36.length)); + (BgL_sc_nbzd2confs_34zd2 = (sc_steps_38.length)); + (sc_states_33 = (make_states(BgL_sc_nbzd2toks_35zd2, BgL_sc_nbzd2confs_34zd2))); + (goal_starters = (sc_starters_41[(0)])); + (BgL_sc_confzd2setzd2adjoinza2_45za2(sc_states_33, (0), goal_starters, (0))); + (forw(sc_states_33, (0), sc_starters_41, sc_enders_40, sc_predictors_39, sc_steps_38, sc_nts_42)); + (sc_i_28 = (0)); + while ((sc_i_28=(0))) { + { + (states = sc_states_33); + (BgL_sc_statesza2_27za2 = BgL_sc_statesza2_30za2); + (state_num = i); + (sc_enders_26 = sc_enders_40); + (sc_steps_25 = sc_steps_38); + (BgL_sc_nbzd2nts_24zd2 = BgL_sc_nbzd2nts_31zd2); + (toks = sc_toks_36); + (BgL_sc_stateza2_23za2 = (BgL_sc_statesza2_30za2[i])); + loop1 = function() { + var sc_loop1_127; + var prev; + var BgL_sc_statesza2_128za2; + var sc_states_129; + var j; + var i; + var sc_i_130; + var head; + var conf_set; + var sc_conf_131; + { + (sc_conf_131 = (BgL_sc_stateza2_23za2[(0)])); + if ((sc_conf_131>=(0))) + { + (conf_set = (BgL_sc_stateza2_23za2[(sc_conf_131+(1))])); + (head = (conf_set[(4)])); + (BgL_sc_stateza2_23za2[(0)] = (conf_set[(0)])); + (conf_set_merge_new_bang(conf_set)); + (sc_i_130 = head); + while ((sc_i_130>=(0))) { + { + (i = sc_i_130); + (j = state_num); + (sc_states_129 = states); + (BgL_sc_statesza2_128za2 = BgL_sc_statesza2_27za2); + (prev = (sc_conf_131-(1))); + if (((sc_conf_131>=BgL_sc_nbzd2nts_24zd2)&&((sc_steps_25[prev])>=(0)))) + { + sc_loop1_127 = function(l) { + var k; + var ender_set; + var state; + var ender; + var l; + while (true) { + if ((l instanceof sc_Pair)) + { + (ender = (l.car)); + (ender_set = ((state = (sc_states_129[j])), (state[(ender+(1))]))); + if ((ender_set!== false)) + { + (k = (ender_set[(2)])); + while ((k>=(0))) { + { + if ((k>=i)) + if (((BgL_sc_confzd2setzd2adjoinza2za2_46z00(sc_states_129, BgL_sc_statesza2_128za2, k, prev, i))!== false)) + (BgL_sc_confzd2setzd2adjoinza2za2_46z00(sc_states_129, BgL_sc_statesza2_128za2, j, ender, k)); + (k = (ender_set[(k+(5))])); + } + } + return (sc_loop1_127((l.cdr))); + } + else + (l = (l.cdr)); + } + else + return undefined; + } + }; + (sc_loop1_127((sc_enders_26[(sc_steps_25[prev])]))); + } + (sc_i_130 = (conf_set[(sc_i_130+(5))])); + } + } + return (loop1()); + } + else + return undefined; + } + }; + (loop1()); + (--i); + } + } + (optrOpnd = BgL_sc_statesza2_30za2); + return [sc_nts_42, sc_starters_41, sc_enders_40, sc_predictors_39, sc_steps_38, sc_names_37, sc_toks_36, optrOpnd, is_parsed, BgL_sc_derivzd2treesza2_47z70, BgL_sc_nbzd2derivzd2treesza2_48za2]; + } + }; + } + }; + BgL_parsezd2ze3parsedzf3zc2 = function(parse, nt, i, j) { + var is_parsed; + var states; + var enders; + var nts; + return ((nts = (parse[(0)])), (enders = (parse[(2)])), (states = (parse[(7)])), (is_parsed = (parse[(8)])), (is_parsed(nt, i, j, nts, enders, states))); + }; + BgL_parsezd2ze3treesz31 = function(parse, nt, i, j) { + var BgL_sc_derivzd2treesza2_132z70; + var states; + var toks; + var names; + var steps; + var enders; + var nts; + return ((nts = (parse[(0)])), (enders = (parse[(2)])), (steps = (parse[(4)])), (names = (parse[(5)])), (toks = (parse[(6)])), (states = (parse[(7)])), (BgL_sc_derivzd2treesza2_132z70 = (parse[(9)])), (BgL_sc_derivzd2treesza2_132z70(nt, i, j, nts, enders, steps, names, toks, states))); + }; + BgL_parsezd2ze3nbzd2treesze3 = function(parse, nt, i, j) { + var BgL_sc_nbzd2derivzd2treesza2_133za2; + var states; + var toks; + var steps; + var enders; + var nts; + return ((nts = (parse[(0)])), (enders = (parse[(2)])), (steps = (parse[(4)])), (toks = (parse[(6)])), (states = (parse[(7)])), (BgL_sc_nbzd2derivzd2treesza2_133za2 = (parse[(10)])), (BgL_sc_nbzd2derivzd2treesza2_133za2(nt, i, j, nts, enders, steps, toks, states))); + }; + test = function(k) { + var x; + var p; + return ((p = (BgL_makezd2parserzd2(const_earley, function(l) { + var sc_x_134; + var tail1134; + var L1130; + var falseHead1133; + { + (falseHead1133 = (new sc_Pair(null, null))); + (tail1134 = falseHead1133); + (L1130 = l); + while (!(L1130 === null)) { + { + (tail1134.cdr = (new sc_Pair(((sc_x_134 = (L1130.car)), (sc_list(sc_x_134, sc_x_134))), null))); + (tail1134 = (tail1134.cdr)); + (L1130 = (L1130.cdr)); + } + } + return (falseHead1133.cdr); + } + }))), (x = (p((sc_vector2list((sc_makeVector(k, "\u1E9Ca"))))))), (sc_length((BgL_parsezd2ze3treesz31(x, "\u1E9Cs", (0), k))))); + }; + BgL_earleyzd2benchmarkzd2 = function() { + var args = null; + for (var sc_tmp = arguments.length - 1; sc_tmp >= 0; sc_tmp--) { + args = sc_cons(arguments[sc_tmp], args); + } + var k; + return ((k = ((args === null)?(7):(args.car))), (BgL_runzd2benchmarkzd2("earley", (1), function() { + return (test(k)); + }, function(result) { + return ((sc_display(result)), (sc_newline()), result == 132); + }))); + }; +} + + +/************* END OF GENERATED CODE *************/ +// Invoke this function to run a benchmark. +// The first argument is a string identifying the benchmark. +// The second argument is the number of times to run the benchmark. +// The third argument is a function that runs the benchmark. +// The fourth argument is a unary function that warns if the result +// returned by the benchmark is incorrect. +// +// Example: +// RunBenchmark("new Array()", +// 1, +// function () { new Array(1000000); } +// function (v) { +// return (v instanceof Array) && (v.length == 1000000); +// }); + +SC_DEFAULT_OUT = new sc_GenericOutputPort(function(s) {}); +SC_ERROR_OUT = SC_DEFAULT_OUT; + +function RunBenchmark(name, count, run, warn) { + for (var n = 0; n < count; ++n) { + result = run(); + if (!warn(result)) { + throw new Error("Earley or Boyer did incorrect number of rewrites"); + } + } +} + +var BgL_runzd2benchmarkzd2 = RunBenchmark; + diff --git a/deps/v8/benchmarks/raytrace.js b/deps/v8/benchmarks/raytrace.js new file mode 100644 index 0000000000..925d0ed35c --- /dev/null +++ b/deps/v8/benchmarks/raytrace.js @@ -0,0 +1,3434 @@ +// The ray tracer code in this file is written by Adam Burmister. It +// is available in its original form from: +// +// http://labs.flog.nz.co/raytracer/ +// +// It has been modified slightly by Google to work as a standalone +// benchmark, but the all the computational code remains +// untouched. This file also contains a copy of the Prototype +// JavaScript framework which is used by the ray tracer. + +var RayTrace = new BenchmarkSuite('RayTrace', 932666, [ + new Benchmark('RayTrace', renderScene) +]); + + +var checkNumber; + +// Create dummy objects if we're not running in a browser. +if (typeof document == 'undefined') { + document = { }; + window = { opera: null }; + navigator = { userAgent: null, appVersion: "" }; +} + + +// ------------------------------------------------------------------------ +// ------------------------------------------------------------------------ + + +/* Prototype JavaScript framework, version 1.5.0 + * (c) 2005-2007 Sam Stephenson + * + * Prototype is freely distributable under the terms of an MIT-style license. + * For details, see the Prototype web site: http://prototype.conio.net/ + * +/*--------------------------------------------------------------------------*/ + +//-------------------- +var Prototype = { + Version: '1.5.0', + BrowserFeatures: { + XPath: !!document.evaluate + }, + + ScriptFragment: '(?:)((\n|\r|.)*?)(?:<\/script>)', + emptyFunction: function() {}, + K: function(x) { return x } +} + +var Class = { + create: function() { + return function() { + this.initialize.apply(this, arguments); + } + } +} + +var Abstract = new Object(); + +Object.extend = function(destination, source) { + for (var property in source) { + destination[property] = source[property]; + } + return destination; +} + +Object.extend(Object, { + inspect: function(object) { + try { + if (object === undefined) return 'undefined'; + if (object === null) return 'null'; + return object.inspect ? object.inspect() : object.toString(); + } catch (e) { + if (e instanceof RangeError) return '...'; + throw e; + } + }, + + keys: function(object) { + var keys = []; + for (var property in object) + keys.push(property); + return keys; + }, + + values: function(object) { + var values = []; + for (var property in object) + values.push(object[property]); + return values; + }, + + clone: function(object) { + return Object.extend({}, object); + } +}); + +Function.prototype.bind = function() { + var __method = this, args = $A(arguments), object = args.shift(); + return function() { + return __method.apply(object, args.concat($A(arguments))); + } +} + +Function.prototype.bindAsEventListener = function(object) { + var __method = this, args = $A(arguments), object = args.shift(); + return function(event) { + return __method.apply(object, [( event || window.event)].concat(args).concat($A(arguments))); + } +} + +Object.extend(Number.prototype, { + toColorPart: function() { + var digits = this.toString(16); + if (this < 16) return '0' + digits; + return digits; + }, + + succ: function() { + return this + 1; + }, + + times: function(iterator) { + $R(0, this, true).each(iterator); + return this; + } +}); + +var Try = { + these: function() { + var returnValue; + + for (var i = 0, length = arguments.length; i < length; i++) { + var lambda = arguments[i]; + try { + returnValue = lambda(); + break; + } catch (e) {} + } + + return returnValue; + } +} + +/*--------------------------------------------------------------------------*/ + +var PeriodicalExecuter = Class.create(); +PeriodicalExecuter.prototype = { + initialize: function(callback, frequency) { + this.callback = callback; + this.frequency = frequency; + this.currentlyExecuting = false; + + this.registerCallback(); + }, + + registerCallback: function() { + this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); + }, + + stop: function() { + if (!this.timer) return; + clearInterval(this.timer); + this.timer = null; + }, + + onTimerEvent: function() { + if (!this.currentlyExecuting) { + try { + this.currentlyExecuting = true; + this.callback(this); + } finally { + this.currentlyExecuting = false; + } + } + } +} +String.interpret = function(value){ + return value == null ? '' : String(value); +} + +Object.extend(String.prototype, { + gsub: function(pattern, replacement) { + var result = '', source = this, match; + replacement = arguments.callee.prepareReplacement(replacement); + + while (source.length > 0) { + if (match = source.match(pattern)) { + result += source.slice(0, match.index); + result += String.interpret(replacement(match)); + source = source.slice(match.index + match[0].length); + } else { + result += source, source = ''; + } + } + return result; + }, + + sub: function(pattern, replacement, count) { + replacement = this.gsub.prepareReplacement(replacement); + count = count === undefined ? 1 : count; + + return this.gsub(pattern, function(match) { + if (--count < 0) return match[0]; + return replacement(match); + }); + }, + + scan: function(pattern, iterator) { + this.gsub(pattern, iterator); + return this; + }, + + truncate: function(length, truncation) { + length = length || 30; + truncation = truncation === undefined ? '...' : truncation; + return this.length > length ? + this.slice(0, length - truncation.length) + truncation : this; + }, + + strip: function() { + return this.replace(/^\s+/, '').replace(/\s+$/, ''); + }, + + stripTags: function() { + return this.replace(/<\/?[^>]+>/gi, ''); + }, + + stripScripts: function() { + return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), ''); + }, + + extractScripts: function() { + var matchAll = new RegExp(Prototype.ScriptFragment, 'img'); + var matchOne = new RegExp(Prototype.ScriptFragment, 'im'); + return (this.match(matchAll) || []).map(function(scriptTag) { + return (scriptTag.match(matchOne) || ['', ''])[1]; + }); + }, + + evalScripts: function() { + return this.extractScripts().map(function(script) { return eval(script) }); + }, + + escapeHTML: function() { + var div = document.createElement('div'); + var text = document.createTextNode(this); + div.appendChild(text); + return div.innerHTML; + }, + + unescapeHTML: function() { + var div = document.createElement('div'); + div.innerHTML = this.stripTags(); + return div.childNodes[0] ? (div.childNodes.length > 1 ? + $A(div.childNodes).inject('',function(memo,node){ return memo+node.nodeValue }) : + div.childNodes[0].nodeValue) : ''; + }, + + toQueryParams: function(separator) { + var match = this.strip().match(/([^?#]*)(#.*)?$/); + if (!match) return {}; + + return match[1].split(separator || '&').inject({}, function(hash, pair) { + if ((pair = pair.split('='))[0]) { + var name = decodeURIComponent(pair[0]); + var value = pair[1] ? decodeURIComponent(pair[1]) : undefined; + + if (hash[name] !== undefined) { + if (hash[name].constructor != Array) + hash[name] = [hash[name]]; + if (value) hash[name].push(value); + } + else hash[name] = value; + } + return hash; + }); + }, + + toArray: function() { + return this.split(''); + }, + + succ: function() { + return this.slice(0, this.length - 1) + + String.fromCharCode(this.charCodeAt(this.length - 1) + 1); + }, + + camelize: function() { + var parts = this.split('-'), len = parts.length; + if (len == 1) return parts[0]; + + var camelized = this.charAt(0) == '-' + ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1) + : parts[0]; + + for (var i = 1; i < len; i++) + camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1); + + return camelized; + }, + + capitalize: function(){ + return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase(); + }, + + underscore: function() { + return this.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'#{1}_#{2}').gsub(/([a-z\d])([A-Z])/,'#{1}_#{2}').gsub(/-/,'_').toLowerCase(); + }, + + dasherize: function() { + return this.gsub(/_/,'-'); + }, + + inspect: function(useDoubleQuotes) { + var escapedString = this.replace(/\\/g, '\\\\'); + if (useDoubleQuotes) + return '"' + escapedString.replace(/"/g, '\\"') + '"'; + else + return "'" + escapedString.replace(/'/g, '\\\'') + "'"; + } +}); + +String.prototype.gsub.prepareReplacement = function(replacement) { + if (typeof replacement == 'function') return replacement; + var template = new Template(replacement); + return function(match) { return template.evaluate(match) }; +} + +String.prototype.parseQuery = String.prototype.toQueryParams; + +var Template = Class.create(); +Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/; +Template.prototype = { + initialize: function(template, pattern) { + this.template = template.toString(); + this.pattern = pattern || Template.Pattern; + }, + + evaluate: function(object) { + return this.template.gsub(this.pattern, function(match) { + var before = match[1]; + if (before == '\\') return match[2]; + return before + String.interpret(object[match[3]]); + }); + } +} + +var $break = new Object(); +var $continue = new Object(); + +var Enumerable = { + each: function(iterator) { + var index = 0; + try { + this._each(function(value) { + try { + iterator(value, index++); + } catch (e) { + if (e != $continue) throw e; + } + }); + } catch (e) { + if (e != $break) throw e; + } + return this; + }, + + eachSlice: function(number, iterator) { + var index = -number, slices = [], array = this.toArray(); + while ((index += number) < array.length) + slices.push(array.slice(index, index+number)); + return slices.map(iterator); + }, + + all: function(iterator) { + var result = true; + this.each(function(value, index) { + result = result && !!(iterator || Prototype.K)(value, index); + if (!result) throw $break; + }); + return result; + }, + + any: function(iterator) { + var result = false; + this.each(function(value, index) { + if (result = !!(iterator || Prototype.K)(value, index)) + throw $break; + }); + return result; + }, + + collect: function(iterator) { + var results = []; + this.each(function(value, index) { + results.push((iterator || Prototype.K)(value, index)); + }); + return results; + }, + + detect: function(iterator) { + var result; + this.each(function(value, index) { + if (iterator(value, index)) { + result = value; + throw $break; + } + }); + return result; + }, + + findAll: function(iterator) { + var results = []; + this.each(function(value, index) { + if (iterator(value, index)) + results.push(value); + }); + return results; + }, + + grep: function(pattern, iterator) { + var results = []; + this.each(function(value, index) { + var stringValue = value.toString(); + if (stringValue.match(pattern)) + results.push((iterator || Prototype.K)(value, index)); + }) + return results; + }, + + include: function(object) { + var found = false; + this.each(function(value) { + if (value == object) { + found = true; + throw $break; + } + }); + return found; + }, + + inGroupsOf: function(number, fillWith) { + fillWith = fillWith === undefined ? null : fillWith; + return this.eachSlice(number, function(slice) { + while(slice.length < number) slice.push(fillWith); + return slice; + }); + }, + + inject: function(memo, iterator) { + this.each(function(value, index) { + memo = iterator(memo, value, index); + }); + return memo; + }, + + invoke: function(method) { + var args = $A(arguments).slice(1); + return this.map(function(value) { + return value[method].apply(value, args); + }); + }, + + max: function(iterator) { + var result; + this.each(function(value, index) { + value = (iterator || Prototype.K)(value, index); + if (result == undefined || value >= result) + result = value; + }); + return result; + }, + + min: function(iterator) { + var result; + this.each(function(value, index) { + value = (iterator || Prototype.K)(value, index); + if (result == undefined || value < result) + result = value; + }); + return result; + }, + + partition: function(iterator) { + var trues = [], falses = []; + this.each(function(value, index) { + ((iterator || Prototype.K)(value, index) ? + trues : falses).push(value); + }); + return [trues, falses]; + }, + + pluck: function(property) { + var results = []; + this.each(function(value, index) { + results.push(value[property]); + }); + return results; + }, + + reject: function(iterator) { + var results = []; + this.each(function(value, index) { + if (!iterator(value, index)) + results.push(value); + }); + return results; + }, + + sortBy: function(iterator) { + return this.map(function(value, index) { + return {value: value, criteria: iterator(value, index)}; + }).sort(function(left, right) { + var a = left.criteria, b = right.criteria; + return a < b ? -1 : a > b ? 1 : 0; + }).pluck('value'); + }, + + toArray: function() { + return this.map(); + }, + + zip: function() { + var iterator = Prototype.K, args = $A(arguments); + if (typeof args.last() == 'function') + iterator = args.pop(); + + var collections = [this].concat(args).map($A); + return this.map(function(value, index) { + return iterator(collections.pluck(index)); + }); + }, + + size: function() { + return this.toArray().length; + }, + + inspect: function() { + return '#'; + } +} + +Object.extend(Enumerable, { + map: Enumerable.collect, + find: Enumerable.detect, + select: Enumerable.findAll, + member: Enumerable.include, + entries: Enumerable.toArray +}); +var $A = Array.from = function(iterable) { + if (!iterable) return []; + if (iterable.toArray) { + return iterable.toArray(); + } else { + var results = []; + for (var i = 0, length = iterable.length; i < length; i++) + results.push(iterable[i]); + return results; + } +} + +Object.extend(Array.prototype, Enumerable); + +if (!Array.prototype._reverse) + Array.prototype._reverse = Array.prototype.reverse; + +Object.extend(Array.prototype, { + _each: function(iterator) { + for (var i = 0, length = this.length; i < length; i++) + iterator(this[i]); + }, + + clear: function() { + this.length = 0; + return this; + }, + + first: function() { + return this[0]; + }, + + last: function() { + return this[this.length - 1]; + }, + + compact: function() { + return this.select(function(value) { + return value != null; + }); + }, + + flatten: function() { + return this.inject([], function(array, value) { + return array.concat(value && value.constructor == Array ? + value.flatten() : [value]); + }); + }, + + without: function() { + var values = $A(arguments); + return this.select(function(value) { + return !values.include(value); + }); + }, + + indexOf: function(object) { + for (var i = 0, length = this.length; i < length; i++) + if (this[i] == object) return i; + return -1; + }, + + reverse: function(inline) { + return (inline !== false ? this : this.toArray())._reverse(); + }, + + reduce: function() { + return this.length > 1 ? this : this[0]; + }, + + uniq: function() { + return this.inject([], function(array, value) { + return array.include(value) ? array : array.concat([value]); + }); + }, + + clone: function() { + return [].concat(this); + }, + + size: function() { + return this.length; + }, + + inspect: function() { + return '[' + this.map(Object.inspect).join(', ') + ']'; + } +}); + +Array.prototype.toArray = Array.prototype.clone; + +function $w(string){ + string = string.strip(); + return string ? string.split(/\s+/) : []; +} + +if(window.opera){ + Array.prototype.concat = function(){ + var array = []; + for(var i = 0, length = this.length; i < length; i++) array.push(this[i]); + for(var i = 0, length = arguments.length; i < length; i++) { + if(arguments[i].constructor == Array) { + for(var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++) + array.push(arguments[i][j]); + } else { + array.push(arguments[i]); + } + } + return array; + } +} +var Hash = function(obj) { + Object.extend(this, obj || {}); +}; + +Object.extend(Hash, { + toQueryString: function(obj) { + var parts = []; + + this.prototype._each.call(obj, function(pair) { + if (!pair.key) return; + + if (pair.value && pair.value.constructor == Array) { + var values = pair.value.compact(); + if (values.length < 2) pair.value = values.reduce(); + else { + key = encodeURIComponent(pair.key); + values.each(function(value) { + value = value != undefined ? encodeURIComponent(value) : ''; + parts.push(key + '=' + encodeURIComponent(value)); + }); + return; + } + } + if (pair.value == undefined) pair[1] = ''; + parts.push(pair.map(encodeURIComponent).join('=')); + }); + + return parts.join('&'); + } +}); + +Object.extend(Hash.prototype, Enumerable); +Object.extend(Hash.prototype, { + _each: function(iterator) { + for (var key in this) { + var value = this[key]; + if (value && value == Hash.prototype[key]) continue; + + var pair = [key, value]; + pair.key = key; + pair.value = value; + iterator(pair); + } + }, + + keys: function() { + return this.pluck('key'); + }, + + values: function() { + return this.pluck('value'); + }, + + merge: function(hash) { + return $H(hash).inject(this, function(mergedHash, pair) { + mergedHash[pair.key] = pair.value; + return mergedHash; + }); + }, + + remove: function() { + var result; + for(var i = 0, length = arguments.length; i < length; i++) { + var value = this[arguments[i]]; + if (value !== undefined){ + if (result === undefined) result = value; + else { + if (result.constructor != Array) result = [result]; + result.push(value) + } + } + delete this[arguments[i]]; + } + return result; + }, + + toQueryString: function() { + return Hash.toQueryString(this); + }, + + inspect: function() { + return '#'; + } +}); + +function $H(object) { + if (object && object.constructor == Hash) return object; + return new Hash(object); +}; +ObjectRange = Class.create(); +Object.extend(ObjectRange.prototype, Enumerable); +Object.extend(ObjectRange.prototype, { + initialize: function(start, end, exclusive) { + this.start = start; + this.end = end; + this.exclusive = exclusive; + }, + + _each: function(iterator) { + var value = this.start; + while (this.include(value)) { + iterator(value); + value = value.succ(); + } + }, + + include: function(value) { + if (value < this.start) + return false; + if (this.exclusive) + return value < this.end; + return value <= this.end; + } +}); + +var $R = function(start, end, exclusive) { + return new ObjectRange(start, end, exclusive); +} + +var Ajax = { + getTransport: function() { + return Try.these( + function() {return new XMLHttpRequest()}, + function() {return new ActiveXObject('Msxml2.XMLHTTP')}, + function() {return new ActiveXObject('Microsoft.XMLHTTP')} + ) || false; + }, + + activeRequestCount: 0 +} + +Ajax.Responders = { + responders: [], + + _each: function(iterator) { + this.responders._each(iterator); + }, + + register: function(responder) { + if (!this.include(responder)) + this.responders.push(responder); + }, + + unregister: function(responder) { + this.responders = this.responders.without(responder); + }, + + dispatch: function(callback, request, transport, json) { + this.each(function(responder) { + if (typeof responder[callback] == 'function') { + try { + responder[callback].apply(responder, [request, transport, json]); + } catch (e) {} + } + }); + } +}; + +Object.extend(Ajax.Responders, Enumerable); + +Ajax.Responders.register({ + onCreate: function() { + Ajax.activeRequestCount++; + }, + onComplete: function() { + Ajax.activeRequestCount--; + } +}); + +Ajax.Base = function() {}; +Ajax.Base.prototype = { + setOptions: function(options) { + this.options = { + method: 'post', + asynchronous: true, + contentType: 'application/x-www-form-urlencoded', + encoding: 'UTF-8', + parameters: '' + } + Object.extend(this.options, options || {}); + + this.options.method = this.options.method.toLowerCase(); + if (typeof this.options.parameters == 'string') + this.options.parameters = this.options.parameters.toQueryParams(); + } +} + +Ajax.Request = Class.create(); +Ajax.Request.Events = + ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete']; + +Ajax.Request.prototype = Object.extend(new Ajax.Base(), { + _complete: false, + + initialize: function(url, options) { + this.transport = Ajax.getTransport(); + this.setOptions(options); + this.request(url); + }, + + request: function(url) { + this.url = url; + this.method = this.options.method; + var params = this.options.parameters; + + if (!['get', 'post'].include(this.method)) { + // simulate other verbs over post + params['_method'] = this.method; + this.method = 'post'; + } + + params = Hash.toQueryString(params); + if (params && /Konqueror|Safari|KHTML/.test(navigator.userAgent)) params += '&_=' + + // when GET, append parameters to URL + if (this.method == 'get' && params) + this.url += (this.url.indexOf('?') > -1 ? '&' : '?') + params; + + try { + Ajax.Responders.dispatch('onCreate', this, this.transport); + + this.transport.open(this.method.toUpperCase(), this.url, + this.options.asynchronous); + + if (this.options.asynchronous) + setTimeout(function() { this.respondToReadyState(1) }.bind(this), 10); + + this.transport.onreadystatechange = this.onStateChange.bind(this); + this.setRequestHeaders(); + + var body = this.method == 'post' ? (this.options.postBody || params) : null; + + this.transport.send(body); + + /* Force Firefox to handle ready state 4 for synchronous requests */ + if (!this.options.asynchronous && this.transport.overrideMimeType) + this.onStateChange(); + + } + catch (e) { + this.dispatchException(e); + } + }, + + onStateChange: function() { + var readyState = this.transport.readyState; + if (readyState > 1 && !((readyState == 4) && this._complete)) + this.respondToReadyState(this.transport.readyState); + }, + + setRequestHeaders: function() { + var headers = { + 'X-Requested-With': 'XMLHttpRequest', + 'X-Prototype-Version': Prototype.Version, + 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*' + }; + + if (this.method == 'post') { + headers['Content-type'] = this.options.contentType + + (this.options.encoding ? '; charset=' + this.options.encoding : ''); + + /* Force "Connection: close" for older Mozilla browsers to work + * around a bug where XMLHttpRequest sends an incorrect + * Content-length header. See Mozilla Bugzilla #246651. + */ + if (this.transport.overrideMimeType && + (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005) + headers['Connection'] = 'close'; + } + + // user-defined headers + if (typeof this.options.requestHeaders == 'object') { + var extras = this.options.requestHeaders; + + if (typeof extras.push == 'function') + for (var i = 0, length = extras.length; i < length; i += 2) + headers[extras[i]] = extras[i+1]; + else + $H(extras).each(function(pair) { headers[pair.key] = pair.value }); + } + + for (var name in headers) + this.transport.setRequestHeader(name, headers[name]); + }, + + success: function() { + return !this.transport.status + || (this.transport.status >= 200 && this.transport.status < 300); + }, + + respondToReadyState: function(readyState) { + var state = Ajax.Request.Events[readyState]; + var transport = this.transport, json = this.evalJSON(); + + if (state == 'Complete') { + try { + this._complete = true; + (this.options['on' + this.transport.status] + || this.options['on' + (this.success() ? 'Success' : 'Failure')] + || Prototype.emptyFunction)(transport, json); + } catch (e) { + this.dispatchException(e); + } + + if ((this.getHeader('Content-type') || 'text/javascript').strip(). + match(/^(text|application)\/(x-)?(java|ecma)script(;.*)?$/i)) + this.evalResponse(); + } + + try { + (this.options['on' + state] || Prototype.emptyFunction)(transport, json); + Ajax.Responders.dispatch('on' + state, this, transport, json); + } catch (e) { + this.dispatchException(e); + } + + if (state == 'Complete') { + // avoid memory leak in MSIE: clean up + this.transport.onreadystatechange = Prototype.emptyFunction; + } + }, + + getHeader: function(name) { + try { + return this.transport.getResponseHeader(name); + } catch (e) { return null } + }, + + evalJSON: function() { + try { + var json = this.getHeader('X-JSON'); + return json ? eval('(' + json + ')') : null; + } catch (e) { return null } + }, + + evalResponse: function() { + try { + return eval(this.transport.responseText); + } catch (e) { + this.dispatchException(e); + } + }, + + dispatchException: function(exception) { + (this.options.onException || Prototype.emptyFunction)(this, exception); + Ajax.Responders.dispatch('onException', this, exception); + } +}); + +Ajax.Updater = Class.create(); + +Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), { + initialize: function(container, url, options) { + this.container = { + success: (container.success || container), + failure: (container.failure || (container.success ? null : container)) + } + + this.transport = Ajax.getTransport(); + this.setOptions(options); + + var onComplete = this.options.onComplete || Prototype.emptyFunction; + this.options.onComplete = (function(transport, param) { + this.updateContent(); + onComplete(transport, param); + }).bind(this); + + this.request(url); + }, + + updateContent: function() { + var receiver = this.container[this.success() ? 'success' : 'failure']; + var response = this.transport.responseText; + + if (!this.options.evalScripts) response = response.stripScripts(); + + if (receiver = $(receiver)) { + if (this.options.insertion) + new this.options.insertion(receiver, response); + else + receiver.update(response); + } + + if (this.success()) { + if (this.onComplete) + setTimeout(this.onComplete.bind(this), 10); + } + } +}); + +Ajax.PeriodicalUpdater = Class.create(); +Ajax.PeriodicalUpdater.prototype = Object.extend(new Ajax.Base(), { + initialize: function(container, url, options) { + this.setOptions(options); + this.onComplete = this.options.onComplete; + + this.frequency = (this.options.frequency || 2); + this.decay = (this.options.decay || 1); + + this.updater = {}; + this.container = container; + this.url = url; + + this.start(); + }, + + start: function() { + this.options.onComplete = this.updateComplete.bind(this); + this.onTimerEvent(); + }, + + stop: function() { + this.updater.options.onComplete = undefined; + clearTimeout(this.timer); + (this.onComplete || Prototype.emptyFunction).apply(this, arguments); + }, + + updateComplete: function(request) { + if (this.options.decay) { + this.decay = (request.responseText == this.lastText ? + this.decay * this.options.decay : 1); + + this.lastText = request.responseText; + } + this.timer = setTimeout(this.onTimerEvent.bind(this), + this.decay * this.frequency * 1000); + }, + + onTimerEvent: function() { + this.updater = new Ajax.Updater(this.container, this.url, this.options); + } +}); +function $(element) { + if (arguments.length > 1) { + for (var i = 0, elements = [], length = arguments.length; i < length; i++) + elements.push($(arguments[i])); + return elements; + } + if (typeof element == 'string') + element = document.getElementById(element); + return Element.extend(element); +} + +if (Prototype.BrowserFeatures.XPath) { + document._getElementsByXPath = function(expression, parentElement) { + var results = []; + var query = document.evaluate(expression, $(parentElement) || document, + null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); + for (var i = 0, length = query.snapshotLength; i < length; i++) + results.push(query.snapshotItem(i)); + return results; + }; +} + +document.getElementsByClassName = function(className, parentElement) { + if (Prototype.BrowserFeatures.XPath) { + var q = ".//*[contains(concat(' ', @class, ' '), ' " + className + " ')]"; + return document._getElementsByXPath(q, parentElement); + } else { + var children = ($(parentElement) || document.body).getElementsByTagName('*'); + var elements = [], child; + for (var i = 0, length = children.length; i < length; i++) { + child = children[i]; + if (Element.hasClassName(child, className)) + elements.push(Element.extend(child)); + } + return elements; + } +}; + +/*--------------------------------------------------------------------------*/ + +if (!window.Element) + var Element = new Object(); + +Element.extend = function(element) { + if (!element || _nativeExtensions || element.nodeType == 3) return element; + + if (!element._extended && element.tagName && element != window) { + var methods = Object.clone(Element.Methods), cache = Element.extend.cache; + + if (element.tagName == 'FORM') + Object.extend(methods, Form.Methods); + if (['INPUT', 'TEXTAREA', 'SELECT'].include(element.tagName)) + Object.extend(methods, Form.Element.Methods); + + Object.extend(methods, Element.Methods.Simulated); + + for (var property in methods) { + var value = methods[property]; + if (typeof value == 'function' && !(property in element)) + element[property] = cache.findOrStore(value); + } + } + + element._extended = true; + return element; +}; + +Element.extend.cache = { + findOrStore: function(value) { + return this[value] = this[value] || function() { + return value.apply(null, [this].concat($A(arguments))); + } + } +}; + +Element.Methods = { + visible: function(element) { + return $(element).style.display != 'none'; + }, + + toggle: function(element) { + element = $(element); + Element[Element.visible(element) ? 'hide' : 'show'](element); + return element; + }, + + hide: function(element) { + $(element).style.display = 'none'; + return element; + }, + + show: function(element) { + $(element).style.display = ''; + return element; + }, + + remove: function(element) { + element = $(element); + element.parentNode.removeChild(element); + return element; + }, + + update: function(element, html) { + html = typeof html == 'undefined' ? '' : html.toString(); + $(element).innerHTML = html.stripScripts(); + setTimeout(function() {html.evalScripts()}, 10); + return element; + }, + + replace: function(element, html) { + element = $(element); + html = typeof html == 'undefined' ? '' : html.toString(); + if (element.outerHTML) { + element.outerHTML = html.stripScripts(); + } else { + var range = element.ownerDocument.createRange(); + range.selectNodeContents(element); + element.parentNode.replaceChild( + range.createContextualFragment(html.stripScripts()), element); + } + setTimeout(function() {html.evalScripts()}, 10); + return element; + }, + + inspect: function(element) { + element = $(element); + var result = '<' + element.tagName.toLowerCase(); + $H({'id': 'id', 'className': 'class'}).each(function(pair) { + var property = pair.first(), attribute = pair.last(); + var value = (element[property] || '').toString(); + if (value) result += ' ' + attribute + '=' + value.inspect(true); + }); + return result + '>'; + }, + + recursivelyCollect: function(element, property) { + element = $(element); + var elements = []; + while (element = element[property]) + if (element.nodeType == 1) + elements.push(Element.extend(element)); + return elements; + }, + + ancestors: function(element) { + return $(element).recursivelyCollect('parentNode'); + }, + + descendants: function(element) { + return $A($(element).getElementsByTagName('*')); + }, + + immediateDescendants: function(element) { + if (!(element = $(element).firstChild)) return []; + while (element && element.nodeType != 1) element = element.nextSibling; + if (element) return [element].concat($(element).nextSiblings()); + return []; + }, + + previousSiblings: function(element) { + return $(element).recursivelyCollect('previousSibling'); + }, + + nextSiblings: function(element) { + return $(element).recursivelyCollect('nextSibling'); + }, + + siblings: function(element) { + element = $(element); + return element.previousSiblings().reverse().concat(element.nextSiblings()); + }, + + match: function(element, selector) { + if (typeof selector == 'string') + selector = new Selector(selector); + return selector.match($(element)); + }, + + up: function(element, expression, index) { + return Selector.findElement($(element).ancestors(), expression, index); + }, + + down: function(element, expression, index) { + return Selector.findElement($(element).descendants(), expression, index); + }, + + previous: function(element, expression, index) { + return Selector.findElement($(element).previousSiblings(), expression, index); + }, + + next: function(element, expression, index) { + return Selector.findElement($(element).nextSiblings(), expression, index); + }, + + getElementsBySelector: function() { + var args = $A(arguments), element = $(args.shift()); + return Selector.findChildElements(element, args); + }, + + getElementsByClassName: function(element, className) { + return document.getElementsByClassName(className, element); + }, + + readAttribute: function(element, name) { + element = $(element); + if (document.all && !window.opera) { + var t = Element._attributeTranslations; + if (t.values[name]) return t.values[name](element, name); + if (t.names[name]) name = t.names[name]; + var attribute = element.attributes[name]; + if(attribute) return attribute.nodeValue; + } + return element.getAttribute(name); + }, + + getHeight: function(element) { + return $(element).getDimensions().height; + }, + + getWidth: function(element) { + return $(element).getDimensions().width; + }, + + classNames: function(element) { + return new Element.ClassNames(element); + }, + + hasClassName: function(element, className) { + if (!(element = $(element))) return; + var elementClassName = element.className; + if (elementClassName.length == 0) return false; + if (elementClassName == className || + elementClassName.match(new RegExp("(^|\\s)" + className + "(\\s|$)"))) + return true; + return false; + }, + + addClassName: function(element, className) { + if (!(element = $(element))) return; + Element.classNames(element).add(className); + return element; + }, + + removeClassName: function(element, className) { + if (!(element = $(element))) return; + Element.classNames(element).remove(className); + return element; + }, + + toggleClassName: function(element, className) { + if (!(element = $(element))) return; + Element.classNames(element)[element.hasClassName(className) ? 'remove' : 'add'](className); + return element; + }, + + observe: function() { + Event.observe.apply(Event, arguments); + return $A(arguments).first(); + }, + + stopObserving: function() { + Event.stopObserving.apply(Event, arguments); + return $A(arguments).first(); + }, + + // removes whitespace-only text node children + cleanWhitespace: function(element) { + element = $(element); + var node = element.firstChild; + while (node) { + var nextNode = node.nextSibling; + if (node.nodeType == 3 && !/\S/.test(node.nodeValue)) + element.removeChild(node); + node = nextNode; + } + return element; + }, + + empty: function(element) { + return $(element).innerHTML.match(/^\s*$/); + }, + + descendantOf: function(element, ancestor) { + element = $(element), ancestor = $(ancestor); + while (element = element.parentNode) + if (element == ancestor) return true; + return false; + }, + + scrollTo: function(element) { + element = $(element); + var pos = Position.cumulativeOffset(element); + window.scrollTo(pos[0], pos[1]); + return element; + }, + + getStyle: function(element, style) { + element = $(element); + if (['float','cssFloat'].include(style)) + style = (typeof element.style.styleFloat != 'undefined' ? 'styleFloat' : 'cssFloat'); + style = style.camelize(); + var value = element.style[style]; + if (!value) { + if (document.defaultView && document.defaultView.getComputedStyle) { + var css = document.defaultView.getComputedStyle(element, null); + value = css ? css[style] : null; + } else if (element.currentStyle) { + value = element.currentStyle[style]; + } + } + + if((value == 'auto') && ['width','height'].include(style) && (element.getStyle('display') != 'none')) + value = element['offset'+style.capitalize()] + 'px'; + + if (window.opera && ['left', 'top', 'right', 'bottom'].include(style)) + if (Element.getStyle(element, 'position') == 'static') value = 'auto'; + if(style == 'opacity') { + if(value) return parseFloat(value); + if(value = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/)) + if(value[1]) return parseFloat(value[1]) / 100; + return 1.0; + } + return value == 'auto' ? null : value; + }, + + setStyle: function(element, style) { + element = $(element); + for (var name in style) { + var value = style[name]; + if(name == 'opacity') { + if (value == 1) { + value = (/Gecko/.test(navigator.userAgent) && + !/Konqueror|Safari|KHTML/.test(navigator.userAgent)) ? 0.999999 : 1.0; + if(/MSIE/.test(navigator.userAgent) && !window.opera) + element.style.filter = element.getStyle('filter').replace(/alpha\([^\)]*\)/gi,''); + } else if(value == '') { + if(/MSIE/.test(navigator.userAgent) && !window.opera) + element.style.filter = element.getStyle('filter').replace(/alpha\([^\)]*\)/gi,''); + } else { + if(value < 0.00001) value = 0; + if(/MSIE/.test(navigator.userAgent) && !window.opera) + element.style.filter = element.getStyle('filter').replace(/alpha\([^\)]*\)/gi,'') + + 'alpha(opacity='+value*100+')'; + } + } else if(['float','cssFloat'].include(name)) name = (typeof element.style.styleFloat != 'undefined') ? 'styleFloat' : 'cssFloat'; + element.style[name.camelize()] = value; + } + return element; + }, + + getDimensions: function(element) { + element = $(element); + var display = $(element).getStyle('display'); + if (display != 'none' && display != null) // Safari bug + return {width: element.offsetWidth, height: element.offsetHeight}; + + // All *Width and *Height properties give 0 on elements with display none, + // so enable the element temporarily + var els = element.style; + var originalVisibility = els.visibility; + var originalPosition = els.position; + var originalDisplay = els.display; + els.visibility = 'hidden'; + els.position = 'absolute'; + els.display = 'block'; + var originalWidth = element.clientWidth; + var originalHeight = element.clientHeight; + els.display = originalDisplay; + els.position = originalPosition; + els.visibility = originalVisibility; + return {width: originalWidth, height: originalHeight}; + }, + + makePositioned: function(element) { + element = $(element); + var pos = Element.getStyle(element, 'position'); + if (pos == 'static' || !pos) { + element._madePositioned = true; + element.style.position = 'relative'; + // Opera returns the offset relative to the positioning context, when an + // element is position relative but top and left have not been defined + if (window.opera) { + element.style.top = 0; + element.style.left = 0; + } + } + return element; + }, + + undoPositioned: function(element) { + element = $(element); + if (element._madePositioned) { + element._madePositioned = undefined; + element.style.position = + element.style.top = + element.style.left = + element.style.bottom = + element.style.right = ''; + } + return element; + }, + + makeClipping: function(element) { + element = $(element); + if (element._overflow) return element; + element._overflow = element.style.overflow || 'auto'; + if ((Element.getStyle(element, 'overflow') || 'visible') != 'hidden') + element.style.overflow = 'hidden'; + return element; + }, + + undoClipping: function(element) { + element = $(element); + if (!element._overflow) return element; + element.style.overflow = element._overflow == 'auto' ? '' : element._overflow; + element._overflow = null; + return element; + } +}; + +Object.extend(Element.Methods, {childOf: Element.Methods.descendantOf}); + +Element._attributeTranslations = {}; + +Element._attributeTranslations.names = { + colspan: "colSpan", + rowspan: "rowSpan", + valign: "vAlign", + datetime: "dateTime", + accesskey: "accessKey", + tabindex: "tabIndex", + enctype: "encType", + maxlength: "maxLength", + readonly: "readOnly", + longdesc: "longDesc" +}; + +Element._attributeTranslations.values = { + _getAttr: function(element, attribute) { + return element.getAttribute(attribute, 2); + }, + + _flag: function(element, attribute) { + return $(element).hasAttribute(attribute) ? attribute : null; + }, + + style: function(element) { + return element.style.cssText.toLowerCase(); + }, + + title: function(element) { + var node = element.getAttributeNode('title'); + return node.specified ? node.nodeValue : null; + } +}; + +Object.extend(Element._attributeTranslations.values, { + href: Element._attributeTranslations.values._getAttr, + src: Element._attributeTranslations.values._getAttr, + disabled: Element._attributeTranslations.values._flag, + checked: Element._attributeTranslations.values._flag, + readonly: Element._attributeTranslations.values._flag, + multiple: Element._attributeTranslations.values._flag +}); + +Element.Methods.Simulated = { + hasAttribute: function(element, attribute) { + var t = Element._attributeTranslations; + attribute = t.names[attribute] || attribute; + return $(element).getAttributeNode(attribute).specified; + } +}; + +// IE is missing .innerHTML support for TABLE-related elements +if (document.all && !window.opera){ + Element.Methods.update = function(element, html) { + element = $(element); + html = typeof html == 'undefined' ? '' : html.toString(); + var tagName = element.tagName.toUpperCase(); + if (['THEAD','TBODY','TR','TD'].include(tagName)) { + var div = document.createElement('div'); + switch (tagName) { + case 'THEAD': + case 'TBODY': + div.innerHTML = '' + html.stripScripts() + '
'; + depth = 2; + break; + case 'TR': + div.innerHTML = '' + html.stripScripts() + '
'; + depth = 3; + break; + case 'TD': + div.innerHTML = '
' + html.stripScripts() + '
'; + depth = 4; + } + $A(element.childNodes).each(function(node){ + element.removeChild(node) + }); + depth.times(function(){ div = div.firstChild }); + + $A(div.childNodes).each( + function(node){ element.appendChild(node) }); + } else { + element.innerHTML = html.stripScripts(); + } + setTimeout(function() {html.evalScripts()}, 10); + return element; + } +}; + +Object.extend(Element, Element.Methods); + +var _nativeExtensions = false; + +if(/Konqueror|Safari|KHTML/.test(navigator.userAgent)) + ['', 'Form', 'Input', 'TextArea', 'Select'].each(function(tag) { + var className = 'HTML' + tag + 'Element'; + if(window[className]) return; + var klass = window[className] = {}; + klass.prototype = document.createElement(tag ? tag.toLowerCase() : 'div').__proto__; + }); + +Element.addMethods = function(methods) { + Object.extend(Element.Methods, methods || {}); + + function copy(methods, destination, onlyIfAbsent) { + onlyIfAbsent = onlyIfAbsent || false; + var cache = Element.extend.cache; + for (var property in methods) { + var value = methods[property]; + if (!onlyIfAbsent || !(property in destination)) + destination[property] = cache.findOrStore(value); + } + } + + if (typeof HTMLElement != 'undefined') { + copy(Element.Methods, HTMLElement.prototype); + copy(Element.Methods.Simulated, HTMLElement.prototype, true); + copy(Form.Methods, HTMLFormElement.prototype); + [HTMLInputElement, HTMLTextAreaElement, HTMLSelectElement].each(function(klass) { + copy(Form.Element.Methods, klass.prototype); + }); + _nativeExtensions = true; + } +} + +var Toggle = new Object(); +Toggle.display = Element.toggle; + +/*--------------------------------------------------------------------------*/ + +Abstract.Insertion = function(adjacency) { + this.adjacency = adjacency; +} + +Abstract.Insertion.prototype = { + initialize: function(element, content) { + this.element = $(element); + this.content = content.stripScripts(); + + if (this.adjacency && this.element.insertAdjacentHTML) { + try { + this.element.insertAdjacentHTML(this.adjacency, this.content); + } catch (e) { + var tagName = this.element.tagName.toUpperCase(); + if (['TBODY', 'TR'].include(tagName)) { + this.insertContent(this.contentFromAnonymousTable()); + } else { + throw e; + } + } + } else { + this.range = this.element.ownerDocument.createRange(); + if (this.initializeRange) this.initializeRange(); + this.insertContent([this.range.createContextualFragment(this.content)]); + } + + setTimeout(function() {content.evalScripts()}, 10); + }, + + contentFromAnonymousTable: function() { + var div = document.createElement('div'); + div.innerHTML = '' + this.content + '
'; + return $A(div.childNodes[0].childNodes[0].childNodes); + } +} + +var Insertion = new Object(); + +Insertion.Before = Class.create(); +Insertion.Before.prototype = Object.extend(new Abstract.Insertion('beforeBegin'), { + initializeRange: function() { + this.range.setStartBefore(this.element); + }, + + insertContent: function(fragments) { + fragments.each((function(fragment) { + this.element.parentNode.insertBefore(fragment, this.element); + }).bind(this)); + } +}); + +Insertion.Top = Class.create(); +Insertion.Top.prototype = Object.extend(new Abstract.Insertion('afterBegin'), { + initializeRange: function() { + this.range.selectNodeContents(this.element); + this.range.collapse(true); + }, + + insertContent: function(fragments) { + fragments.reverse(false).each((function(fragment) { + this.element.insertBefore(fragment, this.element.firstChild); + }).bind(this)); + } +}); + +Insertion.Bottom = Class.create(); +Insertion.Bottom.prototype = Object.extend(new Abstract.Insertion('beforeEnd'), { + initializeRange: function() { + this.range.selectNodeContents(this.element); + this.range.collapse(this.element); + }, + + insertContent: function(fragments) { + fragments.each((function(fragment) { + this.element.appendChild(fragment); + }).bind(this)); + } +}); + +Insertion.After = Class.create(); +Insertion.After.prototype = Object.extend(new Abstract.Insertion('afterEnd'), { + initializeRange: function() { + this.range.setStartAfter(this.element); + }, + + insertContent: function(fragments) { + fragments.each((function(fragment) { + this.element.parentNode.insertBefore(fragment, + this.element.nextSibling); + }).bind(this)); + } +}); + +/*--------------------------------------------------------------------------*/ + +Element.ClassNames = Class.create(); +Element.ClassNames.prototype = { + initialize: function(element) { + this.element = $(element); + }, + + _each: function(iterator) { + this.element.className.split(/\s+/).select(function(name) { + return name.length > 0; + })._each(iterator); + }, + + set: function(className) { + this.element.className = className; + }, + + add: function(classNameToAdd) { + if (this.include(classNameToAdd)) return; + this.set($A(this).concat(classNameToAdd).join(' ')); + }, + + remove: function(classNameToRemove) { + if (!this.include(classNameToRemove)) return; + this.set($A(this).without(classNameToRemove).join(' ')); + }, + + toString: function() { + return $A(this).join(' '); + } +}; + +Object.extend(Element.ClassNames.prototype, Enumerable); +var Selector = Class.create(); +Selector.prototype = { + initialize: function(expression) { + this.params = {classNames: []}; + this.expression = expression.toString().strip(); + this.parseExpression(); + this.compileMatcher(); + }, + + parseExpression: function() { + function abort(message) { throw 'Parse error in selector: ' + message; } + + if (this.expression == '') abort('empty expression'); + + var params = this.params, expr = this.expression, match, modifier, clause, rest; + while (match = expr.match(/^(.*)\[([a-z0-9_:-]+?)(?:([~\|!]?=)(?:"([^"]*)"|([^\]\s]*)))?\]$/i)) { + params.attributes = params.attributes || []; + params.attributes.push({name: match[2], operator: match[3], value: match[4] || match[5] || ''}); + expr = match[1]; + } + + if (expr == '*') return this.params.wildcard = true; + + while (match = expr.match(/^([^a-z0-9_-])?([a-z0-9_-]+)(.*)/i)) { + modifier = match[1], clause = match[2], rest = match[3]; + switch (modifier) { + case '#': params.id = clause; break; + case '.': params.classNames.push(clause); break; + case '': + case undefined: params.tagName = clause.toUpperCase(); break; + default: abort(expr.inspect()); + } + expr = rest; + } + + if (expr.length > 0) abort(expr.inspect()); + }, + + buildMatchExpression: function() { + var params = this.params, conditions = [], clause; + + if (params.wildcard) + conditions.push('true'); + if (clause = params.id) + conditions.push('element.readAttribute("id") == ' + clause.inspect()); + if (clause = params.tagName) + conditions.push('element.tagName.toUpperCase() == ' + clause.inspect()); + if ((clause = params.classNames).length > 0) + for (var i = 0, length = clause.length; i < length; i++) + conditions.push('element.hasClassName(' + clause[i].inspect() + ')'); + if (clause = params.attributes) { + clause.each(function(attribute) { + var value = 'element.readAttribute(' + attribute.name.inspect() + ')'; + var splitValueBy = function(delimiter) { + return value + ' && ' + value + '.split(' + delimiter.inspect() + ')'; + } + + switch (attribute.operator) { + case '=': conditions.push(value + ' == ' + attribute.value.inspect()); break; + case '~=': conditions.push(splitValueBy(' ') + '.include(' + attribute.value.inspect() + ')'); break; + case '|=': conditions.push( + splitValueBy('-') + '.first().toUpperCase() == ' + attribute.value.toUpperCase().inspect() + ); break; + case '!=': conditions.push(value + ' != ' + attribute.value.inspect()); break; + case '': + case undefined: conditions.push('element.hasAttribute(' + attribute.name.inspect() + ')'); break; + default: throw 'Unknown operator ' + attribute.operator + ' in selector'; + } + }); + } + + return conditions.join(' && '); + }, + + compileMatcher: function() { + this.match = new Function('element', 'if (!element.tagName) return false; \ + element = $(element); \ + return ' + this.buildMatchExpression()); + }, + + findElements: function(scope) { + var element; + + if (element = $(this.params.id)) + if (this.match(element)) + if (!scope || Element.childOf(element, scope)) + return [element]; + + scope = (scope || document).getElementsByTagName(this.params.tagName || '*'); + + var results = []; + for (var i = 0, length = scope.length; i < length; i++) + if (this.match(element = scope[i])) + results.push(Element.extend(element)); + + return results; + }, + + toString: function() { + return this.expression; + } +} + +Object.extend(Selector, { + matchElements: function(elements, expression) { + var selector = new Selector(expression); + return elements.select(selector.match.bind(selector)).map(Element.extend); + }, + + findElement: function(elements, expression, index) { + if (typeof expression == 'number') index = expression, expression = false; + return Selector.matchElements(elements, expression || '*')[index || 0]; + }, + + findChildElements: function(element, expressions) { + return expressions.map(function(expression) { + return expression.match(/[^\s"]+(?:"[^"]*"[^\s"]+)*/g).inject([null], function(results, expr) { + var selector = new Selector(expr); + return results.inject([], function(elements, result) { + return elements.concat(selector.findElements(result || element)); + }); + }); + }).flatten(); + } +}); + +function $$() { + return Selector.findChildElements(document, $A(arguments)); +} +var Form = { + reset: function(form) { + $(form).reset(); + return form; + }, + + serializeElements: function(elements, getHash) { + var data = elements.inject({}, function(result, element) { + if (!element.disabled && element.name) { + var key = element.name, value = $(element).getValue(); + if (value != undefined) { + if (result[key]) { + if (result[key].constructor != Array) result[key] = [result[key]]; + result[key].push(value); + } + else result[key] = value; + } + } + return result; + }); + + return getHash ? data : Hash.toQueryString(data); + } +}; + +Form.Methods = { + serialize: function(form, getHash) { + return Form.serializeElements(Form.getElements(form), getHash); + }, + + getElements: function(form) { + return $A($(form).getElementsByTagName('*')).inject([], + function(elements, child) { + if (Form.Element.Serializers[child.tagName.toLowerCase()]) + elements.push(Element.extend(child)); + return elements; + } + ); + }, + + getInputs: function(form, typeName, name) { + form = $(form); + var inputs = form.getElementsByTagName('input'); + + if (!typeName && !name) return $A(inputs).map(Element.extend); + + for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) { + var input = inputs[i]; + if ((typeName && input.type != typeName) || (name && input.name != name)) + continue; + matchingInputs.push(Element.extend(input)); + } + + return matchingInputs; + }, + + disable: function(form) { + form = $(form); + form.getElements().each(function(element) { + element.blur(); + element.disabled = 'true'; + }); + return form; + }, + + enable: function(form) { + form = $(form); + form.getElements().each(function(element) { + element.disabled = ''; + }); + return form; + }, + + findFirstElement: function(form) { + return $(form).getElements().find(function(element) { + return element.type != 'hidden' && !element.disabled && + ['input', 'select', 'textarea'].include(element.tagName.toLowerCase()); + }); + }, + + focusFirstElement: function(form) { + form = $(form); + form.findFirstElement().activate(); + return form; + } +} + +Object.extend(Form, Form.Methods); + +/*--------------------------------------------------------------------------*/ + +Form.Element = { + focus: function(element) { + $(element).focus(); + return element; + }, + + select: function(element) { + $(element).select(); + return element; + } +} + +Form.Element.Methods = { + serialize: function(element) { + element = $(element); + if (!element.disabled && element.name) { + var value = element.getValue(); + if (value != undefined) { + var pair = {}; + pair[element.name] = value; + return Hash.toQueryString(pair); + } + } + return ''; + }, + + getValue: function(element) { + element = $(element); + var method = element.tagName.toLowerCase(); + return Form.Element.Serializers[method](element); + }, + + clear: function(element) { + $(element).value = ''; + return element; + }, + + present: function(element) { + return $(element).value != ''; + }, + + activate: function(element) { + element = $(element); + element.focus(); + if (element.select && ( element.tagName.toLowerCase() != 'input' || + !['button', 'reset', 'submit'].include(element.type) ) ) + element.select(); + return element; + }, + + disable: function(element) { + element = $(element); + element.disabled = true; + return element; + }, + + enable: function(element) { + element = $(element); + element.blur(); + element.disabled = false; + return element; + } +} + +Object.extend(Form.Element, Form.Element.Methods); +var Field = Form.Element; +var $F = Form.Element.getValue; + +/*--------------------------------------------------------------------------*/ + +Form.Element.Serializers = { + input: function(element) { + switch (element.type.toLowerCase()) { + case 'checkbox': + case 'radio': + return Form.Element.Serializers.inputSelector(element); + default: + return Form.Element.Serializers.textarea(element); + } + }, + + inputSelector: function(element) { + return element.checked ? element.value : null; + }, + + textarea: function(element) { + return element.value; + }, + + select: function(element) { + return this[element.type == 'select-one' ? + 'selectOne' : 'selectMany'](element); + }, + + selectOne: function(element) { + var index = element.selectedIndex; + return index >= 0 ? this.optionValue(element.options[index]) : null; + }, + + selectMany: function(element) { + var values, length = element.length; + if (!length) return null; + + for (var i = 0, values = []; i < length; i++) { + var opt = element.options[i]; + if (opt.selected) values.push(this.optionValue(opt)); + } + return values; + }, + + optionValue: function(opt) { + // extend element because hasAttribute may not be native + return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text; + } +} + +/*--------------------------------------------------------------------------*/ + +Abstract.TimedObserver = function() {} +Abstract.TimedObserver.prototype = { + initialize: function(element, frequency, callback) { + this.frequency = frequency; + this.element = $(element); + this.callback = callback; + + this.lastValue = this.getValue(); + this.registerCallback(); + }, + + registerCallback: function() { + setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); + }, + + onTimerEvent: function() { + var value = this.getValue(); + var changed = ('string' == typeof this.lastValue && 'string' == typeof value + ? this.lastValue != value : String(this.lastValue) != String(value)); + if (changed) { + this.callback(this.element, value); + this.lastValue = value; + } + } +} + +Form.Element.Observer = Class.create(); +Form.Element.Observer.prototype = Object.extend(new Abstract.TimedObserver(), { + getValue: function() { + return Form.Element.getValue(this.element); + } +}); + +Form.Observer = Class.create(); +Form.Observer.prototype = Object.extend(new Abstract.TimedObserver(), { + getValue: function() { + return Form.serialize(this.element); + } +}); + +/*--------------------------------------------------------------------------*/ + +Abstract.EventObserver = function() {} +Abstract.EventObserver.prototype = { + initialize: function(element, callback) { + this.element = $(element); + this.callback = callback; + + this.lastValue = this.getValue(); + if (this.element.tagName.toLowerCase() == 'form') + this.registerFormCallbacks(); + else + this.registerCallback(this.element); + }, + + onElementEvent: function() { + var value = this.getValue(); + if (this.lastValue != value) { + this.callback(this.element, value); + this.lastValue = value; + } + }, + + registerFormCallbacks: function() { + Form.getElements(this.element).each(this.registerCallback.bind(this)); + }, + + registerCallback: function(element) { + if (element.type) { + switch (element.type.toLowerCase()) { + case 'checkbox': + case 'radio': + Event.observe(element, 'click', this.onElementEvent.bind(this)); + break; + default: + Event.observe(element, 'change', this.onElementEvent.bind(this)); + break; + } + } + } +} + +Form.Element.EventObserver = Class.create(); +Form.Element.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), { + getValue: function() { + return Form.Element.getValue(this.element); + } +}); + +Form.EventObserver = Class.create(); +Form.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), { + getValue: function() { + return Form.serialize(this.element); + } +}); +if (!window.Event) { + var Event = new Object(); +} + +Object.extend(Event, { + KEY_BACKSPACE: 8, + KEY_TAB: 9, + KEY_RETURN: 13, + KEY_ESC: 27, + KEY_LEFT: 37, + KEY_UP: 38, + KEY_RIGHT: 39, + KEY_DOWN: 40, + KEY_DELETE: 46, + KEY_HOME: 36, + KEY_END: 35, + KEY_PAGEUP: 33, + KEY_PAGEDOWN: 34, + + element: function(event) { + return event.target || event.srcElement; + }, + + isLeftClick: function(event) { + return (((event.which) && (event.which == 1)) || + ((event.button) && (event.button == 1))); + }, + + pointerX: function(event) { + return event.pageX || (event.clientX + + (document.documentElement.scrollLeft || document.body.scrollLeft)); + }, + + pointerY: function(event) { + return event.pageY || (event.clientY + + (document.documentElement.scrollTop || document.body.scrollTop)); + }, + + stop: function(event) { + if (event.preventDefault) { + event.preventDefault(); + event.stopPropagation(); + } else { + event.returnValue = false; + event.cancelBubble = true; + } + }, + + // find the first node with the given tagName, starting from the + // node the event was triggered on; traverses the DOM upwards + findElement: function(event, tagName) { + var element = Event.element(event); + while (element.parentNode && (!element.tagName || + (element.tagName.toUpperCase() != tagName.toUpperCase()))) + element = element.parentNode; + return element; + }, + + observers: false, + + _observeAndCache: function(element, name, observer, useCapture) { + if (!this.observers) this.observers = []; + if (element.addEventListener) { + this.observers.push([element, name, observer, useCapture]); + element.addEventListener(name, observer, useCapture); + } else if (element.attachEvent) { + this.observers.push([element, name, observer, useCapture]); + element.attachEvent('on' + name, observer); + } + }, + + unloadCache: function() { + if (!Event.observers) return; + for (var i = 0, length = Event.observers.length; i < length; i++) { + Event.stopObserving.apply(this, Event.observers[i]); + Event.observers[i][0] = null; + } + Event.observers = false; + }, + + observe: function(element, name, observer, useCapture) { + element = $(element); + useCapture = useCapture || false; + + if (name == 'keypress' && + (navigator.appVersion.match(/Konqueror|Safari|KHTML/) + || element.attachEvent)) + name = 'keydown'; + + Event._observeAndCache(element, name, observer, useCapture); + }, + + stopObserving: function(element, name, observer, useCapture) { + element = $(element); + useCapture = useCapture || false; + + if (name == 'keypress' && + (navigator.appVersion.match(/Konqueror|Safari|KHTML/) + || element.detachEvent)) + name = 'keydown'; + + if (element.removeEventListener) { + element.removeEventListener(name, observer, useCapture); + } else if (element.detachEvent) { + try { + element.detachEvent('on' + name, observer); + } catch (e) {} + } + } +}); + +/* prevent memory leaks in IE */ +if (navigator.appVersion.match(/\bMSIE\b/)) + Event.observe(window, 'unload', Event.unloadCache, false); +var Position = { + // set to true if needed, warning: firefox performance problems + // NOT neeeded for page scrolling, only if draggable contained in + // scrollable elements + includeScrollOffsets: false, + + // must be called before calling withinIncludingScrolloffset, every time the + // page is scrolled + prepare: function() { + this.deltaX = window.pageXOffset + || document.documentElement.scrollLeft + || document.body.scrollLeft + || 0; + this.deltaY = window.pageYOffset + || document.documentElement.scrollTop + || document.body.scrollTop + || 0; + }, + + realOffset: function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.scrollTop || 0; + valueL += element.scrollLeft || 0; + element = element.parentNode; + } while (element); + return [valueL, valueT]; + }, + + cumulativeOffset: function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + element = element.offsetParent; + } while (element); + return [valueL, valueT]; + }, + + positionedOffset: function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + element = element.offsetParent; + if (element) { + if(element.tagName=='BODY') break; + var p = Element.getStyle(element, 'position'); + if (p == 'relative' || p == 'absolute') break; + } + } while (element); + return [valueL, valueT]; + }, + + offsetParent: function(element) { + if (element.offsetParent) return element.offsetParent; + if (element == document.body) return element; + + while ((element = element.parentNode) && element != document.body) + if (Element.getStyle(element, 'position') != 'static') + return element; + + return document.body; + }, + + // caches x/y coordinate pair to use with overlap + within: function(element, x, y) { + if (this.includeScrollOffsets) + return this.withinIncludingScrolloffsets(element, x, y); + this.xcomp = x; + this.ycomp = y; + this.offset = this.cumulativeOffset(element); + + return (y >= this.offset[1] && + y < this.offset[1] + element.offsetHeight && + x >= this.offset[0] && + x < this.offset[0] + element.offsetWidth); + }, + + withinIncludingScrolloffsets: function(element, x, y) { + var offsetcache = this.realOffset(element); + + this.xcomp = x + offsetcache[0] - this.deltaX; + this.ycomp = y + offsetcache[1] - this.deltaY; + this.offset = this.cumulativeOffset(element); + + return (this.ycomp >= this.offset[1] && + this.ycomp < this.offset[1] + element.offsetHeight && + this.xcomp >= this.offset[0] && + this.xcomp < this.offset[0] + element.offsetWidth); + }, + + // within must be called directly before + overlap: function(mode, element) { + if (!mode) return 0; + if (mode == 'vertical') + return ((this.offset[1] + element.offsetHeight) - this.ycomp) / + element.offsetHeight; + if (mode == 'horizontal') + return ((this.offset[0] + element.offsetWidth) - this.xcomp) / + element.offsetWidth; + }, + + page: function(forElement) { + var valueT = 0, valueL = 0; + + var element = forElement; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + + // Safari fix + if (element.offsetParent==document.body) + if (Element.getStyle(element,'position')=='absolute') break; + + } while (element = element.offsetParent); + + element = forElement; + do { + if (!window.opera || element.tagName=='BODY') { + valueT -= element.scrollTop || 0; + valueL -= element.scrollLeft || 0; + } + } while (element = element.parentNode); + + return [valueL, valueT]; + }, + + clone: function(source, target) { + var options = Object.extend({ + setLeft: true, + setTop: true, + setWidth: true, + setHeight: true, + offsetTop: 0, + offsetLeft: 0 + }, arguments[2] || {}) + + // find page position of source + source = $(source); + var p = Position.page(source); + + // find coordinate system to use + target = $(target); + var delta = [0, 0]; + var parent = null; + // delta [0,0] will do fine with position: fixed elements, + // position:absolute needs offsetParent deltas + if (Element.getStyle(target,'position') == 'absolute') { + parent = Position.offsetParent(target); + delta = Position.page(parent); + } + + // correct by body offsets (fixes Safari) + if (parent == document.body) { + delta[0] -= document.body.offsetLeft; + delta[1] -= document.body.offsetTop; + } + + // set position + if(options.setLeft) target.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px'; + if(options.setTop) target.style.top = (p[1] - delta[1] + options.offsetTop) + 'px'; + if(options.setWidth) target.style.width = source.offsetWidth + 'px'; + if(options.setHeight) target.style.height = source.offsetHeight + 'px'; + }, + + absolutize: function(element) { + element = $(element); + if (element.style.position == 'absolute') return; + Position.prepare(); + + var offsets = Position.positionedOffset(element); + var top = offsets[1]; + var left = offsets[0]; + var width = element.clientWidth; + var height = element.clientHeight; + + element._originalLeft = left - parseFloat(element.style.left || 0); + element._originalTop = top - parseFloat(element.style.top || 0); + element._originalWidth = element.style.width; + element._originalHeight = element.style.height; + + element.style.position = 'absolute'; + element.style.top = top + 'px'; + element.style.left = left + 'px'; + element.style.width = width + 'px'; + element.style.height = height + 'px'; + }, + + relativize: function(element) { + element = $(element); + if (element.style.position == 'relative') return; + Position.prepare(); + + element.style.position = 'relative'; + var top = parseFloat(element.style.top || 0) - (element._originalTop || 0); + var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0); + + element.style.top = top + 'px'; + element.style.left = left + 'px'; + element.style.height = element._originalHeight; + element.style.width = element._originalWidth; + } +} + +// Safari returns margins on body which is incorrect if the child is absolutely +// positioned. For performance reasons, redefine Position.cumulativeOffset for +// KHTML/WebKit only. +if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) { + Position.cumulativeOffset = function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + if (element.offsetParent == document.body) + if (Element.getStyle(element, 'position') == 'absolute') break; + + element = element.offsetParent; + } while (element); + + return [valueL, valueT]; + } +} + +Element.addMethods(); + + +// ------------------------------------------------------------------------ +// ------------------------------------------------------------------------ + +// The rest of this file is the actual ray tracer written by Adam +// Burmister. It's a concatenation of the following files: +// +// flog/color.js +// flog/light.js +// flog/vector.js +// flog/ray.js +// flog/scene.js +// flog/material/basematerial.js +// flog/material/solid.js +// flog/material/chessboard.js +// flog/shape/baseshape.js +// flog/shape/sphere.js +// flog/shape/plane.js +// flog/intersectioninfo.js +// flog/camera.js +// flog/background.js +// flog/engine.js + + +/* Fake a Flog.* namespace */ +if(typeof(Flog) == 'undefined') var Flog = {}; +if(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {}; + +Flog.RayTracer.Color = Class.create(); + +Flog.RayTracer.Color.prototype = { + red : 0.0, + green : 0.0, + blue : 0.0, + + initialize : function(r, g, b) { + if(!r) r = 0.0; + if(!g) g = 0.0; + if(!b) b = 0.0; + + this.red = r; + this.green = g; + this.blue = b; + }, + + add : function(c1, c2){ + var result = new Flog.RayTracer.Color(0,0,0); + + result.red = c1.red + c2.red; + result.green = c1.green + c2.green; + result.blue = c1.blue + c2.blue; + + return result; + }, + + addScalar: function(c1, s){ + var result = new Flog.RayTracer.Color(0,0,0); + + result.red = c1.red + s; + result.green = c1.green + s; + result.blue = c1.blue + s; + + result.limit(); + + return result; + }, + + subtract: function(c1, c2){ + var result = new Flog.RayTracer.Color(0,0,0); + + result.red = c1.red - c2.red; + result.green = c1.green - c2.green; + result.blue = c1.blue - c2.blue; + + return result; + }, + + multiply : function(c1, c2) { + var result = new Flog.RayTracer.Color(0,0,0); + + result.red = c1.red * c2.red; + result.green = c1.green * c2.green; + result.blue = c1.blue * c2.blue; + + return result; + }, + + multiplyScalar : function(c1, f) { + var result = new Flog.RayTracer.Color(0,0,0); + + result.red = c1.red * f; + result.green = c1.green * f; + result.blue = c1.blue * f; + + return result; + }, + + divideFactor : function(c1, f) { + var result = new Flog.RayTracer.Color(0,0,0); + + result.red = c1.red / f; + result.green = c1.green / f; + result.blue = c1.blue / f; + + return result; + }, + + limit: function(){ + this.red = (this.red > 0.0) ? ( (this.red > 1.0) ? 1.0 : this.red ) : 0.0; + this.green = (this.green > 0.0) ? ( (this.green > 1.0) ? 1.0 : this.green ) : 0.0; + this.blue = (this.blue > 0.0) ? ( (this.blue > 1.0) ? 1.0 : this.blue ) : 0.0; + }, + + distance : function(color) { + var d = Math.abs(this.red - color.red) + Math.abs(this.green - color.green) + Math.abs(this.blue - color.blue); + return d; + }, + + blend: function(c1, c2, w){ + var result = new Flog.RayTracer.Color(0,0,0); + result = Flog.RayTracer.Color.prototype.add( + Flog.RayTracer.Color.prototype.multiplyScalar(c1, 1 - w), + Flog.RayTracer.Color.prototype.multiplyScalar(c2, w) + ); + return result; + }, + + brightness : function() { + var r = Math.floor(this.red*255); + var g = Math.floor(this.green*255); + var b = Math.floor(this.blue*255); + return (r * 77 + g * 150 + b * 29) >> 8; + }, + + toString : function () { + var r = Math.floor(this.red*255); + var g = Math.floor(this.green*255); + var b = Math.floor(this.blue*255); + + return "rgb("+ r +","+ g +","+ b +")"; + } +} +/* Fake a Flog.* namespace */ +if(typeof(Flog) == 'undefined') var Flog = {}; +if(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {}; + +Flog.RayTracer.Light = Class.create(); + +Flog.RayTracer.Light.prototype = { + position: null, + color: null, + intensity: 10.0, + + initialize : function(pos, color, intensity) { + this.position = pos; + this.color = color; + this.intensity = (intensity ? intensity : 10.0); + }, + + getIntensity: function(distance){ + if(distance >= intensity) return 0; + + return Math.pow((intensity - distance) / strength, 0.2); + }, + + toString : function () { + return 'Light [' + this.position.x + ',' + this.position.y + ',' + this.position.z + ']'; + } +} +/* Fake a Flog.* namespace */ +if(typeof(Flog) == 'undefined') var Flog = {}; +if(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {}; + +Flog.RayTracer.Vector = Class.create(); + +Flog.RayTracer.Vector.prototype = { + x : 0.0, + y : 0.0, + z : 0.0, + + initialize : function(x, y, z) { + this.x = (x ? x : 0); + this.y = (y ? y : 0); + this.z = (z ? z : 0); + }, + + copy: function(vector){ + this.x = vector.x; + this.y = vector.y; + this.z = vector.z; + }, + + normalize : function() { + var m = this.magnitude(); + return new Flog.RayTracer.Vector(this.x / m, this.y / m, this.z / m); + }, + + magnitude : function() { + return Math.sqrt((this.x * this.x) + (this.y * this.y) + (this.z * this.z)); + }, + + cross : function(w) { + return new Flog.RayTracer.Vector( + -this.z * w.y + this.y * w.z, + this.z * w.x - this.x * w.z, + -this.y * w.x + this.x * w.y); + }, + + dot : function(w) { + return this.x * w.x + this.y * w.y + this.z * w.z; + }, + + add : function(v, w) { + return new Flog.RayTracer.Vector(w.x + v.x, w.y + v.y, w.z + v.z); + }, + + subtract : function(v, w) { + if(!w || !v) throw 'Vectors must be defined [' + v + ',' + w + ']'; + return new Flog.RayTracer.Vector(v.x - w.x, v.y - w.y, v.z - w.z); + }, + + multiplyVector : function(v, w) { + return new Flog.RayTracer.Vector(v.x * w.x, v.y * w.y, v.z * w.z); + }, + + multiplyScalar : function(v, w) { + return new Flog.RayTracer.Vector(v.x * w, v.y * w, v.z * w); + }, + + toString : function () { + return 'Vector [' + this.x + ',' + this.y + ',' + this.z + ']'; + } +} +/* Fake a Flog.* namespace */ +if(typeof(Flog) == 'undefined') var Flog = {}; +if(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {}; + +Flog.RayTracer.Ray = Class.create(); + +Flog.RayTracer.Ray.prototype = { + position : null, + direction : null, + initialize : function(pos, dir) { + this.position = pos; + this.direction = dir; + }, + + toString : function () { + return 'Ray [' + this.position + ',' + this.direction + ']'; + } +} +/* Fake a Flog.* namespace */ +if(typeof(Flog) == 'undefined') var Flog = {}; +if(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {}; + +Flog.RayTracer.Scene = Class.create(); + +Flog.RayTracer.Scene.prototype = { + camera : null, + shapes : [], + lights : [], + background : null, + + initialize : function() { + this.camera = new Flog.RayTracer.Camera( + new Flog.RayTracer.Vector(0,0,-5), + new Flog.RayTracer.Vector(0,0,1), + new Flog.RayTracer.Vector(0,1,0) + ); + this.shapes = new Array(); + this.lights = new Array(); + this.background = new Flog.RayTracer.Background(new Flog.RayTracer.Color(0,0,0.5), 0.2); + } +} +/* Fake a Flog.* namespace */ +if(typeof(Flog) == 'undefined') var Flog = {}; +if(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {}; +if(typeof(Flog.RayTracer.Material) == 'undefined') Flog.RayTracer.Material = {}; + +Flog.RayTracer.Material.BaseMaterial = Class.create(); + +Flog.RayTracer.Material.BaseMaterial.prototype = { + + gloss: 2.0, // [0...infinity] 0 = matt + transparency: 0.0, // 0=opaque + reflection: 0.0, // [0...infinity] 0 = no reflection + refraction: 0.50, + hasTexture: false, + + initialize : function() { + + }, + + getColor: function(u, v){ + + }, + + wrapUp: function(t){ + t = t % 2.0; + if(t < -1) t += 2.0; + if(t >= 1) t -= 2.0; + return t; + }, + + toString : function () { + return 'Material [gloss=' + this.gloss + ', transparency=' + this.transparency + ', hasTexture=' + this.hasTexture +']'; + } +} +/* Fake a Flog.* namespace */ +if(typeof(Flog) == 'undefined') var Flog = {}; +if(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {}; + +Flog.RayTracer.Material.Solid = Class.create(); + +Flog.RayTracer.Material.Solid.prototype = Object.extend( + new Flog.RayTracer.Material.BaseMaterial(), { + initialize : function(color, reflection, refraction, transparency, gloss) { + this.color = color; + this.reflection = reflection; + this.transparency = transparency; + this.gloss = gloss; + this.hasTexture = false; + }, + + getColor: function(u, v){ + return this.color; + }, + + toString : function () { + return 'SolidMaterial [gloss=' + this.gloss + ', transparency=' + this.transparency + ', hasTexture=' + this.hasTexture +']'; + } + } +); +/* Fake a Flog.* namespace */ +if(typeof(Flog) == 'undefined') var Flog = {}; +if(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {}; + +Flog.RayTracer.Material.Chessboard = Class.create(); + +Flog.RayTracer.Material.Chessboard.prototype = Object.extend( + new Flog.RayTracer.Material.BaseMaterial(), { + colorEven: null, + colorOdd: null, + density: 0.5, + + initialize : function(colorEven, colorOdd, reflection, transparency, gloss, density) { + this.colorEven = colorEven; + this.colorOdd = colorOdd; + this.reflection = reflection; + this.transparency = transparency; + this.gloss = gloss; + this.density = density; + this.hasTexture = true; + }, + + getColor: function(u, v){ + var t = this.wrapUp(u * this.density) * this.wrapUp(v * this.density); + + if(t < 0.0) + return this.colorEven; + else + return this.colorOdd; + }, + + toString : function () { + return 'ChessMaterial [gloss=' + this.gloss + ', transparency=' + this.transparency + ', hasTexture=' + this.hasTexture +']'; + } + } +); +/* Fake a Flog.* namespace */ +if(typeof(Flog) == 'undefined') var Flog = {}; +if(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {}; +if(typeof(Flog.RayTracer.Shape) == 'undefined') Flog.RayTracer.Shape = {}; + +Flog.RayTracer.Shape.BaseShape = Class.create(); + +Flog.RayTracer.Shape.BaseShape.prototype = { + position: null, + material: null, + + initialize : function() { + this.position = new Vector(0,0,0); + this.material = new Flog.RayTracer.Material.SolidMaterial( + new Flog.RayTracer.Color(1,0,1), + 0, + 0, + 0 + ); + }, + + toString : function () { + return 'Material [gloss=' + this.gloss + ', transparency=' + this.transparency + ', hasTexture=' + this.hasTexture +']'; + } +} +/* Fake a Flog.* namespace */ +if(typeof(Flog) == 'undefined') var Flog = {}; +if(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {}; +if(typeof(Flog.RayTracer.Shape) == 'undefined') Flog.RayTracer.Shape = {}; + +Flog.RayTracer.Shape.Sphere = Class.create(); + +Flog.RayTracer.Shape.Sphere.prototype = { + initialize : function(pos, radius, material) { + this.radius = radius; + this.position = pos; + this.material = material; + }, + + intersect: function(ray){ + var info = new Flog.RayTracer.IntersectionInfo(); + info.shape = this; + + var dst = Flog.RayTracer.Vector.prototype.subtract(ray.position, this.position); + + var B = dst.dot(ray.direction); + var C = dst.dot(dst) - (this.radius * this.radius); + var D = (B * B) - C; + + if(D > 0){ // intersection! + info.isHit = true; + info.distance = (-B) - Math.sqrt(D); + info.position = Flog.RayTracer.Vector.prototype.add( + ray.position, + Flog.RayTracer.Vector.prototype.multiplyScalar( + ray.direction, + info.distance + ) + ); + info.normal = Flog.RayTracer.Vector.prototype.subtract( + info.position, + this.position + ).normalize(); + + info.color = this.material.getColor(0,0); + } else { + info.isHit = false; + } + return info; + }, + + toString : function () { + return 'Sphere [position=' + this.position + ', radius=' + this.radius + ']'; + } +} +/* Fake a Flog.* namespace */ +if(typeof(Flog) == 'undefined') var Flog = {}; +if(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {}; +if(typeof(Flog.RayTracer.Shape) == 'undefined') Flog.RayTracer.Shape = {}; + +Flog.RayTracer.Shape.Plane = Class.create(); + +Flog.RayTracer.Shape.Plane.prototype = { + d: 0.0, + + initialize : function(pos, d, material) { + this.position = pos; + this.d = d; + this.material = material; + }, + + intersect: function(ray){ + var info = new Flog.RayTracer.IntersectionInfo(); + + var Vd = this.position.dot(ray.direction); + if(Vd == 0) return info; // no intersection + + var t = -(this.position.dot(ray.position) + this.d) / Vd; + if(t <= 0) return info; + + info.shape = this; + info.isHit = true; + info.position = Flog.RayTracer.Vector.prototype.add( + ray.position, + Flog.RayTracer.Vector.prototype.multiplyScalar( + ray.direction, + t + ) + ); + info.normal = this.position; + info.distance = t; + + if(this.material.hasTexture){ + var vU = new Flog.RayTracer.Vector(this.position.y, this.position.z, -this.position.x); + var vV = vU.cross(this.position); + var u = info.position.dot(vU); + var v = info.position.dot(vV); + info.color = this.material.getColor(u,v); + } else { + info.color = this.material.getColor(0,0); + } + + return info; + }, + + toString : function () { + return 'Plane [' + this.position + ', d=' + this.d + ']'; + } +} +/* Fake a Flog.* namespace */ +if(typeof(Flog) == 'undefined') var Flog = {}; +if(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {}; + +Flog.RayTracer.IntersectionInfo = Class.create(); + +Flog.RayTracer.IntersectionInfo.prototype = { + isHit: false, + hitCount: 0, + shape: null, + position: null, + normal: null, + color: null, + distance: null, + + initialize : function() { + this.color = new Flog.RayTracer.Color(0,0,0); + }, + + toString : function () { + return 'Intersection [' + this.position + ']'; + } +} +/* Fake a Flog.* namespace */ +if(typeof(Flog) == 'undefined') var Flog = {}; +if(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {}; + +Flog.RayTracer.Camera = Class.create(); + +Flog.RayTracer.Camera.prototype = { + position: null, + lookAt: null, + equator: null, + up: null, + screen: null, + + initialize : function(pos, lookAt, up) { + this.position = pos; + this.lookAt = lookAt; + this.up = up; + this.equator = lookAt.normalize().cross(this.up); + this.screen = Flog.RayTracer.Vector.prototype.add(this.position, this.lookAt); + }, + + getRay: function(vx, vy){ + var pos = Flog.RayTracer.Vector.prototype.subtract( + this.screen, + Flog.RayTracer.Vector.prototype.subtract( + Flog.RayTracer.Vector.prototype.multiplyScalar(this.equator, vx), + Flog.RayTracer.Vector.prototype.multiplyScalar(this.up, vy) + ) + ); + pos.y = pos.y * -1; + var dir = Flog.RayTracer.Vector.prototype.subtract( + pos, + this.position + ); + + var ray = new Flog.RayTracer.Ray(pos, dir.normalize()); + + return ray; + }, + + toString : function () { + return 'Ray []'; + } +} +/* Fake a Flog.* namespace */ +if(typeof(Flog) == 'undefined') var Flog = {}; +if(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {}; + +Flog.RayTracer.Background = Class.create(); + +Flog.RayTracer.Background.prototype = { + color : null, + ambience : 0.0, + + initialize : function(color, ambience) { + this.color = color; + this.ambience = ambience; + } +} +/* Fake a Flog.* namespace */ +if(typeof(Flog) == 'undefined') var Flog = {}; +if(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {}; + +Flog.RayTracer.Engine = Class.create(); + +Flog.RayTracer.Engine.prototype = { + canvas: null, /* 2d context we can render to */ + + initialize: function(options){ + this.options = Object.extend({ + canvasHeight: 100, + canvasWidth: 100, + pixelWidth: 2, + pixelHeight: 2, + renderDiffuse: false, + renderShadows: false, + renderHighlights: false, + renderReflections: false, + rayDepth: 2 + }, options || {}); + + this.options.canvasHeight /= this.options.pixelHeight; + this.options.canvasWidth /= this.options.pixelWidth; + + /* TODO: dynamically include other scripts */ + }, + + setPixel: function(x, y, color){ + var pxW, pxH; + pxW = this.options.pixelWidth; + pxH = this.options.pixelHeight; + + if (this.canvas) { + this.canvas.fillStyle = color.toString(); + this.canvas.fillRect (x * pxW, y * pxH, pxW, pxH); + } else { + if (x === y) { + checkNumber += color.brightness(); + } + // print(x * pxW, y * pxH, pxW, pxH); + } + }, + + renderScene: function(scene, canvas){ + checkNumber = 0; + /* Get canvas */ + if (canvas) { + this.canvas = canvas.getContext("2d"); + } else { + this.canvas = null; + } + + var canvasHeight = this.options.canvasHeight; + var canvasWidth = this.options.canvasWidth; + + for(var y=0; y < canvasHeight; y++){ + for(var x=0; x < canvasWidth; x++){ + var yp = y * 1.0 / canvasHeight * 2 - 1; + var xp = x * 1.0 / canvasWidth * 2 - 1; + + var ray = scene.camera.getRay(xp, yp); + + var color = this.getPixelColor(ray, scene); + + this.setPixel(x, y, color); + } + } + if (checkNumber !== 2321) { + throw new Error("Scene rendered incorrectly"); + } + }, + + getPixelColor: function(ray, scene){ + var info = this.testIntersection(ray, scene, null); + if(info.isHit){ + var color = this.rayTrace(info, ray, scene, 0); + return color; + } + return scene.background.color; + }, + + testIntersection: function(ray, scene, exclude){ + var hits = 0; + var best = new Flog.RayTracer.IntersectionInfo(); + best.distance = 2000; + + for(var i=0; i= 0 && info.distance < best.distance){ + best = info; + hits++; + } + } + } + best.hitCount = hits; + return best; + }, + + getReflectionRay: function(P,N,V){ + var c1 = -N.dot(V); + var R1 = Flog.RayTracer.Vector.prototype.add( + Flog.RayTracer.Vector.prototype.multiplyScalar(N, 2*c1), + V + ); + return new Flog.RayTracer.Ray(P, R1); + }, + + rayTrace: function(info, ray, scene, depth){ + // Calc ambient + var color = Flog.RayTracer.Color.prototype.multiplyScalar(info.color, scene.background.ambience); + var oldColor = color; + var shininess = Math.pow(10, info.shape.material.gloss + 1); + + for(var i=0; i 0.0){ + color = Flog.RayTracer.Color.prototype.add( + color, + Flog.RayTracer.Color.prototype.multiply( + info.color, + Flog.RayTracer.Color.prototype.multiplyScalar( + light.color, + L + ) + ) + ); + } + } + + // The greater the depth the more accurate the colours, but + // this is exponentially (!) expensive + if(depth <= this.options.rayDepth){ + // calculate reflection ray + if(this.options.renderReflections && info.shape.material.reflection > 0) + { + var reflectionRay = this.getReflectionRay(info.position, info.normal, ray.direction); + var refl = this.testIntersection(reflectionRay, scene, info.shape); + + if (refl.isHit && refl.distance > 0){ + refl.color = this.rayTrace(refl, reflectionRay, scene, depth + 1); + } else { + refl.color = scene.background.color; + } + + color = Flog.RayTracer.Color.prototype.blend( + color, + refl.color, + info.shape.material.reflection + ); + } + + // Refraction + /* TODO */ + } + + /* Render shadows and highlights */ + + var shadowInfo = new Flog.RayTracer.IntersectionInfo(); + + if(this.options.renderShadows){ + var shadowRay = new Flog.RayTracer.Ray(info.position, v); + + shadowInfo = this.testIntersection(shadowRay, scene, info.shape); + if(shadowInfo.isHit && shadowInfo.shape != info.shape /*&& shadowInfo.shape.type != 'PLANE'*/){ + var vA = Flog.RayTracer.Color.prototype.multiplyScalar(color, 0.5); + var dB = (0.5 * Math.pow(shadowInfo.shape.material.transparency, 0.5)); + color = Flog.RayTracer.Color.prototype.addScalar(vA,dB); + } + } + + // Phong specular highlights + if(this.options.renderHighlights && !shadowInfo.isHit && info.shape.material.gloss > 0){ + var Lv = Flog.RayTracer.Vector.prototype.subtract( + info.shape.position, + light.position + ).normalize(); + + var E = Flog.RayTracer.Vector.prototype.subtract( + scene.camera.position, + info.shape.position + ).normalize(); + + var H = Flog.RayTracer.Vector.prototype.subtract( + E, + Lv + ).normalize(); + + var glossWeight = Math.pow(Math.max(info.normal.dot(H), 0), shininess); + color = Flog.RayTracer.Color.prototype.add( + Flog.RayTracer.Color.prototype.multiplyScalar(light.color, glossWeight), + color + ); + } + } + color.limit(); + return color; + } +}; + + +function renderScene(){ + var scene = new Flog.RayTracer.Scene(); + + scene.camera = new Flog.RayTracer.Camera( + new Flog.RayTracer.Vector(0, 0, -15), + new Flog.RayTracer.Vector(-0.2, 0, 5), + new Flog.RayTracer.Vector(0, 1, 0) + ); + + scene.background = new Flog.RayTracer.Background( + new Flog.RayTracer.Color(0.5, 0.5, 0.5), + 0.4 + ); + + var sphere = new Flog.RayTracer.Shape.Sphere( + new Flog.RayTracer.Vector(-1.5, 1.5, 2), + 1.5, + new Flog.RayTracer.Material.Solid( + new Flog.RayTracer.Color(0,0.5,0.5), + 0.3, + 0.0, + 0.0, + 2.0 + ) + ); + + var sphere1 = new Flog.RayTracer.Shape.Sphere( + new Flog.RayTracer.Vector(1, 0.25, 1), + 0.5, + new Flog.RayTracer.Material.Solid( + new Flog.RayTracer.Color(0.9,0.9,0.9), + 0.1, + 0.0, + 0.0, + 1.5 + ) + ); + + var plane = new Flog.RayTracer.Shape.Plane( + new Flog.RayTracer.Vector(0.1, 0.9, -0.5).normalize(), + 1.2, + new Flog.RayTracer.Material.Chessboard( + new Flog.RayTracer.Color(1,1,1), + new Flog.RayTracer.Color(0,0,0), + 0.2, + 0.0, + 1.0, + 0.7 + ) + ); + + scene.shapes.push(plane); + scene.shapes.push(sphere); + scene.shapes.push(sphere1); + + var light = new Flog.RayTracer.Light( + new Flog.RayTracer.Vector(5, 10, -1), + new Flog.RayTracer.Color(0.8, 0.8, 0.8) + ); + + var light1 = new Flog.RayTracer.Light( + new Flog.RayTracer.Vector(-3, 5, -15), + new Flog.RayTracer.Color(0.8, 0.8, 0.8), + 100 + ); + + scene.lights.push(light); + scene.lights.push(light1); + + var imageWidth = 100; // $F('imageWidth'); + var imageHeight = 100; // $F('imageHeight'); + var pixelSize = "5,5".split(','); // $F('pixelSize').split(','); + var renderDiffuse = true; // $F('renderDiffuse'); + var renderShadows = true; // $F('renderShadows'); + var renderHighlights = true; // $F('renderHighlights'); + var renderReflections = true; // $F('renderReflections'); + var rayDepth = 2;//$F('rayDepth'); + + var raytracer = new Flog.RayTracer.Engine( + { + canvasWidth: imageWidth, + canvasHeight: imageHeight, + pixelWidth: pixelSize[0], + pixelHeight: pixelSize[1], + "renderDiffuse": renderDiffuse, + "renderHighlights": renderHighlights, + "renderShadows": renderShadows, + "renderReflections": renderReflections, + "rayDepth": rayDepth + } + ); + + raytracer.renderScene(scene, null, 0); +} + diff --git a/deps/v8/benchmarks/regexp.js b/deps/v8/benchmarks/regexp.js new file mode 100644 index 0000000000..dce15b8e37 --- /dev/null +++ b/deps/v8/benchmarks/regexp.js @@ -0,0 +1,1614 @@ +// Copyright 2009 the V8 project 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. + +// Automatically generated on 2009-01-30. + +// This benchmark is generated by loading 50 of the most popular pages +// on the web and logging all regexp operations performed. Each +// operation is given a weight that is calculated from an estimate of +// the popularity of the pages where it occurs and the number of times +// it is executed while loading each page. Finally the literal +// letters in the data are encoded using ROT13 in a way that does not +// affect how the regexps match their input. + +var RegRxp = new BenchmarkSuite('RegExp', 995230, [ + new Benchmark("RegExp", runRegExpBenchmark) +]); + +function runRegExpBenchmark() { + var re0 = /^ba/; + var re1 = /(((\w+):\/\/)([^\/:]*)(:(\d+))?)?([^#?]*)(\?([^#]*))?(#(.*))?/; + var re2 = /^\s*|\s*$/g; + var re3 = /\bQBZPbageby_cynprubyqre\b/; + var re4 = /,/; + var re5 = /\bQBZPbageby_cynprubyqre\b/g; + var re6 = /^[\s\xa0]+|[\s\xa0]+$/g; + var re7 = /(\d*)(\D*)/g; + var re8 = /=/; + var re9 = /(^|\s)lhv\-h(\s|$)/; + var str0 = 'Zbmvyyn/5.0 (Jvaqbjf; H; Jvaqbjf AG 5.1; ra-HF) NccyrJroXvg/528.9 (XUGZY, yvxr Trpxb) Puebzr/2.0.157.0 Fnsnev/528.9'; + var re10 = /\#/g; + var re11 = /\./g; + var re12 = /'/g; + var re13 = /\?[\w\W]*(sevraqvq|punaaryvq|tebhcvq)=([^\&\?#]*)/i; + var str1 = 'Fubpxjnir Synfu 9.0 e115'; + var re14 = /\s+/g; + var re15 = /^\s*(\S*(\s+\S+)*)\s*$/; + var re16 = /(-[a-z])/i; + function runBlock0() { + for (var i = 0; i < 6511; i++) { + re0.exec('pyvpx'); + } + for (var i = 0; i < 1844; i++) { + re1.exec('uggc://jjj.snprobbx.pbz/ybtva.cuc'); + } + for (var i = 0; i < 739; i++) { + 'QBZPbageby_cynprubyqre'.replace(re2, ''); + } + for (var i = 0; i < 598; i++) { + re1.exec('uggc://jjj.snprobbx.pbz/'); + } + for (var i = 0; i < 454; i++) { + re1.exec('uggc://jjj.snprobbx.pbz/fepu.cuc'); + } + for (var i = 0; i < 352; i++) { + /qqqq|qqq|qq|q|ZZZZ|ZZZ|ZZ|Z|llll|ll|l|uu|u|UU|U|zz|z|ff|f|gg|g|sss|ss|s|mmm|mm|m/g.exec('qqqq, ZZZ q, llll'); + } + for (var i = 0; i < 312; i++) { + re3.exec('vachggrkg QBZPbageby_cynprubyqre'); + } + for (var i = 0; i < 282; i++) { + re4.exec('/ZlFcnprUbzrcntr/Vaqrk-FvgrUbzr,10000000'); + } + for (var i = 0; i < 177; i++) { + 'vachggrkg'.replace(re5, ''); + } + for (var i = 0; i < 170; i++) { + '528.9'.replace(re6, ''); + re7.exec('528'); + } + for (var i = 0; i < 156; i++) { + re8.exec('VCPhygher=ra-HF'); + re8.exec('CersreerqPhygher=ra-HF'); + } + for (var i = 0; i < 144; i++) { + re0.exec('xrlcerff'); + } + for (var i = 0; i < 139; i++) { + '521'.replace(re6, ''); + re7.exec('521'); + re9.exec(''); + /JroXvg\/(\S+)/.exec(str0); + } + for (var i = 0; i < 137; i++) { + 'qvi .so_zrah'.replace(re10, ''); + 'qvi .so_zrah'.replace(/\[/g, ''); + 'qvi.so_zrah'.replace(re11, ''); + } + for (var i = 0; i < 117; i++) { + 'uvqqra_ryrz'.replace(re2, ''); + } + for (var i = 0; i < 95; i++) { + /(?:^|;)\s*sevraqfgre_ynat=([^;]*)/.exec('sevraqfgre_naba=nvq%3Qn6ss9p85n868ro9s059pn854735956o3%26ers%3Q%26df%3Q%26vpgl%3QHF'); + } + for (var i = 0; i < 93; i++) { + 'uggc://ubzr.zlfcnpr.pbz/vaqrk.psz'.replace(re12, ''); + re13.exec('uggc://ubzr.zlfcnpr.pbz/vaqrk.psz'); + } + for (var i = 0; i < 92; i++) { + str1.replace(/([a-zA-Z]|\s)+/, ''); + } + for (var i = 0; i < 85; i++) { + 'svefg'.replace(re14, ''); + 'svefg'.replace(re15, ''); + 'uggc://cebsvyr.zlfcnpr.pbz/vaqrk.psz'.replace(re12, ''); + 'ynfg'.replace(re14, ''); + 'ynfg'.replace(re15, ''); + re16.exec('qvfcynl'); + re13.exec('uggc://cebsvyr.zlfcnpr.pbz/vaqrk.psz'); + } + } + var re17 = /(^|[^\\])\"\\\/Qngr\((-?[0-9]+)\)\\\/\"/g; + var str2 = '{"anzr":"","ahzoreSbezng":{"PheeraplQrpvznyQvtvgf":2,"PheeraplQrpvznyFrcnengbe":".","VfErnqBayl":gehr,"PheeraplTebhcFvmrf":[3],"AhzoreTebhcFvmrf":[3],"CrepragTebhcFvmrf":[3],"PheeraplTebhcFrcnengbe":",","PheeraplFlzoby":"\xa4","AnAFlzoby":"AnA","PheeraplArtngvirCnggrea":0,"AhzoreArtngvirCnggrea":1,"CrepragCbfvgvirCnggrea":0,"CrepragArtngvirCnggrea":0,"ArtngvirVasvavglFlzoby":"-Vasvavgl","ArtngvirFvta":"-","AhzoreQrpvznyQvtvgf":2,"AhzoreQrpvznyFrcnengbe":".","AhzoreTebhcFrcnengbe":",","PheeraplCbfvgvirCnggrea":0,"CbfvgvirVasvavglFlzoby":"Vasvavgl","CbfvgvirFvta":"+","CrepragQrpvznyQvtvgf":2,"CrepragQrpvznyFrcnengbe":".","CrepragTebhcFrcnengbe":",","CrepragFlzoby":"%","CreZvyyrFlzoby":"\u2030","AngvirQvtvgf":["0","1","2","3","4","5","6","7","8","9"],"QvtvgFhofgvghgvba":1},"qngrGvzrSbezng":{"NZQrfvtangbe":"NZ","Pnyraqne":{"ZvaFhccbegrqQngrGvzr":"@-62135568000000@","ZnkFhccbegrqQngrGvzr":"@253402300799999@","NytbevguzGlcr":1,"PnyraqneGlcr":1,"Renf":[1],"GjbQvtvgLrneZnk":2029,"VfErnqBayl":gehr},"QngrFrcnengbe":"/","SvefgQnlBsJrrx":0,"PnyraqneJrrxEhyr":0,"ShyyQngrGvzrCnggrea":"qqqq, qq ZZZZ llll UU:zz:ff","YbatQngrCnggrea":"qqqq, qq ZZZZ llll","YbatGvzrCnggrea":"UU:zz:ff","ZbaguQnlCnggrea":"ZZZZ qq","CZQrfvtangbe":"CZ","ESP1123Cnggrea":"qqq, qq ZZZ llll UU\':\'zz\':\'ff \'TZG\'","FubegQngrCnggrea":"ZZ/qq/llll","FubegGvzrCnggrea":"UU:zz","FbegnoyrQngrGvzrCnggrea":"llll\'-\'ZZ\'-\'qq\'G\'UU\':\'zz\':\'ff","GvzrFrcnengbe":":","HavirefnyFbegnoyrQngrGvzrCnggrea":"llll\'-\'ZZ\'-\'qq UU\':\'zz\':\'ff\'M\'","LrneZbaguCnggrea":"llll ZZZZ","NooerivngrqQnlAnzrf":["Fha","Zba","Ghr","Jrq","Guh","Sev","Fng"],"FubegrfgQnlAnzrf":["Fh","Zb","Gh","Jr","Gu","Se","Fn"],"QnlAnzrf":["Fhaqnl","Zbaqnl","Ghrfqnl","Jrqarfqnl","Guhefqnl","Sevqnl","Fngheqnl"],"NooerivngrqZbaguAnzrf":["Wna","Sro","Zne","Nce","Znl","Wha","Why","Nht","Frc","Bpg","Abi","Qrp",""],"ZbaguAnzrf":["Wnahnel","Sroehnel","Znepu","Ncevy","Znl","Whar","Whyl","Nhthfg","Frcgrzore","Bpgbore","Abirzore","Qrprzore",""],"VfErnqBayl":gehr,"AngvirPnyraqneAnzr":"Tertbevna Pnyraqne","NooerivngrqZbaguTravgvirAnzrf":["Wna","Sro","Zne","Nce","Znl","Wha","Why","Nht","Frc","Bpg","Abi","Qrp",""],"ZbaguTravgvirAnzrf":["Wnahnel","Sroehnel","Znepu","Ncevy","Znl","Whar","Whyl","Nhthfg","Frcgrzore","Bpgbore","Abirzore","Qrprzore",""]}}'; + var str3 = '{"anzr":"ra-HF","ahzoreSbezng":{"PheeraplQrpvznyQvtvgf":2,"PheeraplQrpvznyFrcnengbe":".","VfErnqBayl":snyfr,"PheeraplTebhcFvmrf":[3],"AhzoreTebhcFvmrf":[3],"CrepragTebhcFvmrf":[3],"PheeraplTebhcFrcnengbe":",","PheeraplFlzoby":"$","AnAFlzoby":"AnA","PheeraplArtngvirCnggrea":0,"AhzoreArtngvirCnggrea":1,"CrepragCbfvgvirCnggrea":0,"CrepragArtngvirCnggrea":0,"ArtngvirVasvavglFlzoby":"-Vasvavgl","ArtngvirFvta":"-","AhzoreQrpvznyQvtvgf":2,"AhzoreQrpvznyFrcnengbe":".","AhzoreTebhcFrcnengbe":",","PheeraplCbfvgvirCnggrea":0,"CbfvgvirVasvavglFlzoby":"Vasvavgl","CbfvgvirFvta":"+","CrepragQrpvznyQvtvgf":2,"CrepragQrpvznyFrcnengbe":".","CrepragTebhcFrcnengbe":",","CrepragFlzoby":"%","CreZvyyrFlzoby":"\u2030","AngvirQvtvgf":["0","1","2","3","4","5","6","7","8","9"],"QvtvgFhofgvghgvba":1},"qngrGvzrSbezng":{"NZQrfvtangbe":"NZ","Pnyraqne":{"ZvaFhccbegrqQngrGvzr":"@-62135568000000@","ZnkFhccbegrqQngrGvzr":"@253402300799999@","NytbevguzGlcr":1,"PnyraqneGlcr":1,"Renf":[1],"GjbQvtvgLrneZnk":2029,"VfErnqBayl":snyfr},"QngrFrcnengbe":"/","SvefgQnlBsJrrx":0,"PnyraqneJrrxEhyr":0,"ShyyQngrGvzrCnggrea":"qqqq, ZZZZ qq, llll u:zz:ff gg","YbatQngrCnggrea":"qqqq, ZZZZ qq, llll","YbatGvzrCnggrea":"u:zz:ff gg","ZbaguQnlCnggrea":"ZZZZ qq","CZQrfvtangbe":"CZ","ESP1123Cnggrea":"qqq, qq ZZZ llll UU\':\'zz\':\'ff \'TZG\'","FubegQngrCnggrea":"Z/q/llll","FubegGvzrCnggrea":"u:zz gg","FbegnoyrQngrGvzrCnggrea":"llll\'-\'ZZ\'-\'qq\'G\'UU\':\'zz\':\'ff","GvzrFrcnengbe":":","HavirefnyFbegnoyrQngrGvzrCnggrea":"llll\'-\'ZZ\'-\'qq UU\':\'zz\':\'ff\'M\'","LrneZbaguCnggrea":"ZZZZ, llll","NooerivngrqQnlAnzrf":["Fha","Zba","Ghr","Jrq","Guh","Sev","Fng"],"FubegrfgQnlAnzrf":["Fh","Zb","Gh","Jr","Gu","Se","Fn"],"QnlAnzrf":["Fhaqnl","Zbaqnl","Ghrfqnl","Jrqarfqnl","Guhefqnl","Sevqnl","Fngheqnl"],"NooerivngrqZbaguAnzrf":["Wna","Sro","Zne","Nce","Znl","Wha","Why","Nht","Frc","Bpg","Abi","Qrp",""],"ZbaguAnzrf":["Wnahnel","Sroehnel","Znepu","Ncevy","Znl","Whar","Whyl","Nhthfg","Frcgrzore","Bpgbore","Abirzore","Qrprzore",""],"VfErnqBayl":snyfr,"AngvirPnyraqneAnzr":"Tertbevna Pnyraqne","NooerivngrqZbaguTravgvirAnzrf":["Wna","Sro","Zne","Nce","Znl","Wha","Why","Nht","Frc","Bpg","Abi","Qrp",""],"ZbaguTravgvirAnzrf":["Wnahnel","Sroehnel","Znepu","Ncevy","Znl","Whar","Whyl","Nhthfg","Frcgrzore","Bpgbore","Abirzore","Qrprzore",""]}}'; + var str4 = 'HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R%3Q'; + var str5 = 'HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R='; + var re18 = /^\s+|\s+$/g; + var str6 = 'uggc://jjj.snprobbx.pbz/vaqrk.cuc'; + var re19 = /(?:^|\s+)ba(?:\s+|$)/; + var re20 = /[+, ]/; + var re21 = /ybnqrq|pbzcyrgr/; + var str7 = ';;jvaqbj.IjPurpxZbhfrCbfvgvbaNQ_VQ=shapgvba(r){vs(!r)ine r=jvaqbj.rirag;ine c=-1;vs(d1)c=d1.EbyybssCnary;ine bo=IjTrgBow("IjCnayNQ_VQ_"+c);vs(bo&&bo.fglyr.ivfvovyvgl=="ivfvoyr"){ine fns=IjFns?8:0;ine pheK=r.pyvragK+IjBOFpe("U")+fns,pheL=r.pyvragL+IjBOFpe("I")+fns;ine y=IjBOEC(NQ_VQ,bo,"Y"),g=IjBOEC(NQ_VQ,bo,"G");ine e=y+d1.Cnaryf[c].Jvqgu,o=g+d1.Cnaryf[c].Urvtug;vs((pheKe)||(pheLo)){vs(jvaqbj.IjBaEbyybssNQ_VQ)IjBaEbyybssNQ_VQ(c);ryfr IjPybfrNq(NQ_VQ,c,gehr,"");}ryfr erghea;}IjPnapryZbhfrYvfgrareNQ_VQ();};;jvaqbj.IjFrgEbyybssCnaryNQ_VQ=shapgvba(c){ine z="zbhfrzbir",q=qbphzrag,s=IjPurpxZbhfrCbfvgvbaNQ_VQ;c=IjTc(NQ_VQ,c);vs(d1&&d1.EbyybssCnary>-1)IjPnapryZbhfrYvfgrareNQ_VQ();vs(d1)d1.EbyybssCnary=c;gel{vs(q.nqqRiragYvfgrare)q.nqqRiragYvfgrare(z,s,snyfr);ryfr vs(q.nggnpuRirag)q.nggnpuRirag("ba"+z,s);}pngpu(r){}};;jvaqbj.IjPnapryZbhfrYvfgrareNQ_VQ=shapgvba(){ine z="zbhfrzbir",q=qbphzrag,s=IjPurpxZbhfrCbfvgvbaNQ_VQ;vs(d1)d1.EbyybssCnary=-1;gel{vs(q.erzbirRiragYvfgrare)q.erzbirRiragYvfgrare(z,s,snyfr);ryfr vs(q.qrgnpuRirag)q.qrgnpuRirag("ba"+z,s);}pngpu(r){}};;d1.IjTc=d2(n,c){ine nq=d1;vs(vfAnA(c)){sbe(ine v=0;v0){vs(nq.FzV.yratgu>0)nq.FzV+="/";nq.FzV+=vh[v];nq.FtZ[nq.FtZ.yratgu]=snyfr;}}};;d1.IjYvzvg0=d2(n,f){ine nq=d1,vh=f.fcyvg("/");sbe(ine v=0;v0){vs(nq.OvC.yratgu>0)nq.OvC+="/";nq.OvC+=vh[v];}}};;d1.IjRVST=d2(n,c){jvaqbj["IjCnayNQ_VQ_"+c+"_Bow"]=IjTrgBow("IjCnayNQ_VQ_"+c+"_Bow");vs(jvaqbj["IjCnayNQ_VQ_"+c+"_Bow"]==ahyy)frgGvzrbhg("IjRVST(NQ_VQ,"+c+")",d1.rvsg);};;d1.IjNavzSHC=d2(n,c){ine nq=d1;vs(c>nq.Cnaryf.yratgu)erghea;ine cna=nq.Cnaryf[c],nn=gehr,on=gehr,yn=gehr,en=gehr,cn=nq.Cnaryf[0],sf=nq.ShF,j=cn.Jvqgu,u=cn.Urvtug;vs(j=="100%"){j=sf;en=snyfr;yn=snyfr;}vs(u=="100%"){u=sf;nn=snyfr;on=snyfr;}vs(cn.YnY=="Y")yn=snyfr;vs(cn.YnY=="E")en=snyfr;vs(cn.GnY=="G")nn=snyfr;vs(cn.GnY=="O")on=snyfr;ine k=0,l=0;fjvgpu(nq.NshP%8){pnfr 0:oernx;pnfr 1:vs(nn)l=-sf;oernx;pnfr 2:k=j-sf;oernx;pnfr 3:vs(en)k=j;oernx;pnfr 4:k=j-sf;l=u-sf;oernx;pnfr 5:k=j-sf;vs(on)l=u;oernx;pnfr 6:l=u-sf;oernx;pnfr 7:vs(yn)k=-sf;l=u-sf;oernx;}vs(nq.NshP++ 0)||(nethzragf.yratgu==3&&bG>0))){pyrneGvzrbhg(cay.UgU);cay.UgU=frgGvzrbhg(cay.UvqrNpgvba,(nethzragf.yratgu==3?bG:cay.UvqrGvzrbhgInyhr));}};;d1.IjErfrgGvzrbhg=d2(n,c,bG){c=IjTc(n,c);IjPnapryGvzrbhg(n,c);riny("IjFgnegGvzrbhg(NQ_VQ,c"+(nethzragf.yratgu==3?",bG":"")+")");};;d1.IjErfrgNyyGvzrbhgf=d2(n){sbe(ine c=0;c]/g; + var str15 = 'FrffvbaQQS2=s6r4579npn4rn2135s904r0s75pp1o5334p6s6pospo12696; ZFPhygher=VC=74.125.75.1&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&CersreerqPhygherCraqvat=&Pbhagel=IIZ=&SbeprqRkcvengvba=633669316860113296&gvzrMbar=0&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R=; AFP_zp_dfctwzs-aowb_80=44132r503660'; + var str16 = 'FrffvbaQQS2=s6r4579npn4rn2135s904r0s75pp1o5334p6s6pospo12696; AFP_zp_dfctwzs-aowb_80=44132r503660; __hgzm=144631658.1231363638.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar); __hgzn=144631658.965867047679498800.1231363638.1231363638.1231363638.1; __hgzo=144631658.0.10.1231363638; __hgzp=144631658; ZFPhygher=VC=74.125.75.1&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&Pbhagel=IIZ%3Q&SbeprqRkcvengvba=633669316860113296&gvzrMbar=-8&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R%3Q'; + var str17 = 'uggc://tbbtyrnqf.t.qbhoyrpyvpx.arg/cntrnq/nqf?pyvrag=pn-svz_zlfcnpr_zlfcnpr-ubzrcntr_wf&qg=1231363621014&uy=ra&nqfnsr=uvtu&br=hgs8&ahz_nqf=4&bhgchg=wf&nqgrfg=bss&pbeeryngbe=1231363621014&punaary=svz_zlfcnpr_ubzrcntr_abgybttrqva%2Psvz_zlfcnpr_aba_HTP%2Psvz_zlfcnpr_havgrq-fgngrf&hey=uggc%3N%2S%2Scebsvyr.zlfcnpr.pbz%2Svaqrk.psz&nq_glcr=grkg&rvq=6083027&rn=0&sez=0&tn_ivq=348699119.1231363624&tn_fvq=1231363624&tn_uvq=895511034&synfu=9.0.115&h_u=768&h_j=1024&h_nu=738&h_nj=1024&h_pq=24&h_gm=-480&h_uvf=2&h_wnin=gehr&h_acyht=7&h_azvzr=22'; + var str18 = 'uggc://jjj.yrobapbva.se/yv'; + var str19 = 'ZFPhygher=VC=74.125.75.1&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&Pbhagel=IIZ%3Q&SbeprqRkcvengvba=633669316860113296&gvzrMbar=-8&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R%3Q'; + var str20 = 'ZFPhygher=VC=74.125.75.1&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&CersreerqPhygherCraqvat=&Pbhagel=IIZ=&SbeprqRkcvengvba=633669316860113296&gvzrMbar=0&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R='; + function runBlock3() { + for (var i = 0; i < 27; i++) { + 'e115'.replace(/[A-Za-z]/g, ''); + } + for (var i = 0; i < 23; i++) { + 'qvfcynl'.replace(re27, ''); + 'cbfvgvba'.replace(re27, ''); + } + for (var i = 0; i < 22; i++) { + 'unaqyr'.replace(re14, ''); + 'unaqyr'.replace(re15, ''); + 'yvar'.replace(re14, ''); + 'yvar'.replace(re15, ''); + 'cnerag puebzr6 fvatyr1 gno'.replace(re14, ''); + 'cnerag puebzr6 fvatyr1 gno'.replace(re15, ''); + 'fyvqre'.replace(re14, ''); + 'fyvqre'.replace(re15, ''); + re28.exec(''); + } + for (var i = 0; i < 21; i++) { + 'uggc://jjj.zlfcnpr.pbz/'.replace(re12, ''); + re13.exec('uggc://jjj.zlfcnpr.pbz/'); + } + for (var i = 0; i < 20; i++) { + 'cntrivrj'.replace(re29, ''); + 'cntrivrj'.replace(re30, ''); + re19.exec('ynfg'); + re19.exec('ba svefg'); + re8.exec('VC=74.125.75.3'); + } + for (var i = 0; i < 19; i++) { + re31.exec('ra'); + } + for (var i = 0; i < 18; i++) { + str10.split(re32); + str11.split(re32); + str12.replace(re33, ''); + re8.exec('144631658.0.10.1231363570'); + re8.exec('144631658.1231363570.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar)'); + re8.exec('144631658.3426875219718084000.1231363570.1231363570.1231363570.1'); + re8.exec(str13); + re8.exec(str14); + re8.exec('__hgzn=144631658.3426875219718084000.1231363570.1231363570.1231363570.1'); + re8.exec('__hgzo=144631658.0.10.1231363570'); + re8.exec('__hgzm=144631658.1231363570.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar)'); + re34.exec(str10); + re34.exec(str11); + } + for (var i = 0; i < 17; i++) { + str0.match(/zfvr/gi); + str0.match(/bcren/gi); + str15.split(re32); + str16.split(re32); + 'ohggba'.replace(re14, ''); + 'ohggba'.replace(re15, ''); + 'puvyq p1 svefg sylbhg pybfrq'.replace(re14, ''); + 'puvyq p1 svefg sylbhg pybfrq'.replace(re15, ''); + 'pvgvrf'.replace(re14, ''); + 'pvgvrf'.replace(re15, ''); + 'pybfrq'.replace(re14, ''); + 'pybfrq'.replace(re15, ''); + 'qry'.replace(re14, ''); + 'qry'.replace(re15, ''); + 'uqy_zba'.replace(re14, ''); + 'uqy_zba'.replace(re15, ''); + str17.replace(re33, ''); + str18.replace(/%3P/g, ''); + str18.replace(/%3R/g, ''); + str18.replace(/%3q/g, ''); + str18.replace(re35, ''); + 'yvaxyvfg16'.replace(re14, ''); + 'yvaxyvfg16'.replace(re15, ''); + 'zvahf'.replace(re14, ''); + 'zvahf'.replace(re15, ''); + 'bcra'.replace(re14, ''); + 'bcra'.replace(re15, ''); + 'cnerag puebzr5 fvatyr1 ps NU'.replace(re14, ''); + 'cnerag puebzr5 fvatyr1 ps NU'.replace(re15, ''); + 'cynlre'.replace(re14, ''); + 'cynlre'.replace(re15, ''); + 'cyhf'.replace(re14, ''); + 'cyhf'.replace(re15, ''); + 'cb_uqy'.replace(re14, ''); + 'cb_uqy'.replace(re15, ''); + 'hyJVzt'.replace(re14, ''); + 'hyJVzt'.replace(re15, ''); + re8.exec('144631658.0.10.1231363638'); + re8.exec('144631658.1231363638.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar)'); + re8.exec('144631658.965867047679498800.1231363638.1231363638.1231363638.1'); + re8.exec('4413268q3660'); + re8.exec('4ss747o77904333q374or84qrr1s9r0nprp8r5q81534o94n'); + re8.exec('SbeprqRkcvengvba=633669321699093060'); + re8.exec('VC=74.125.75.20'); + re8.exec(str19); + re8.exec(str20); + re8.exec('AFP_zp_tfwsbrg-aowb_80=4413268q3660'); + re8.exec('FrffvbaQQS2=4ss747o77904333q374or84qrr1s9r0nprp8r5q81534o94n'); + re8.exec('__hgzn=144631658.965867047679498800.1231363638.1231363638.1231363638.1'); + re8.exec('__hgzo=144631658.0.10.1231363638'); + re8.exec('__hgzm=144631658.1231363638.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar)'); + re34.exec(str15); + re34.exec(str16); + } + } + var re36 = /uers|fep|fryrpgrq/; + var re37 = /\s*([+>~\s])\s*([a-zA-Z#.*:\[])/g; + var re38 = /^(\w+|\*)$/; + var str21 = 'FrffvbaQQS2=s15q53p9n372sn76npr13o271n4s3p5r29p235746p908p58; ZFPhygher=VC=66.249.85.130&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&CersreerqPhygherCraqvat=&Pbhagel=IIZ=&SbeprqRkcvengvba=633669358527244818&gvzrMbar=0&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R='; + var str22 = 'FrffvbaQQS2=s15q53p9n372sn76npr13o271n4s3p5r29p235746p908p58; __hgzm=144631658.1231367822.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar); __hgzn=144631658.4127520630321984500.1231367822.1231367822.1231367822.1; __hgzo=144631658.0.10.1231367822; __hgzp=144631658; ZFPhygher=VC=66.249.85.130&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&Pbhagel=IIZ%3Q&SbeprqRkcvengvba=633669358527244818&gvzrMbar=-8&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R%3Q'; + var str23 = 'uggc://tbbtyrnqf.t.qbhoyrpyvpx.arg/cntrnq/nqf?pyvrag=pn-svz_zlfcnpr_zlfcnpr-ubzrcntr_wf&qg=1231367803797&uy=ra&nqfnsr=uvtu&br=hgs8&ahz_nqf=4&bhgchg=wf&nqgrfg=bss&pbeeryngbe=1231367803797&punaary=svz_zlfcnpr_ubzrcntr_abgybttrqva%2Psvz_zlfcnpr_aba_HTP%2Psvz_zlfcnpr_havgrq-fgngrf&hey=uggc%3N%2S%2Szrffntvat.zlfcnpr.pbz%2Svaqrk.psz&nq_glcr=grkg&rvq=6083027&rn=0&sez=0&tn_ivq=1192552091.1231367807&tn_fvq=1231367807&tn_uvq=1155446857&synfu=9.0.115&h_u=768&h_j=1024&h_nu=738&h_nj=1024&h_pq=24&h_gm=-480&h_uvf=2&h_wnin=gehr&h_acyht=7&h_azvzr=22'; + var str24 = 'ZFPhygher=VC=66.249.85.130&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&Pbhagel=IIZ%3Q&SbeprqRkcvengvba=633669358527244818&gvzrMbar=-8&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R%3Q'; + var str25 = 'ZFPhygher=VC=66.249.85.130&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&CersreerqPhygherCraqvat=&Pbhagel=IIZ=&SbeprqRkcvengvba=633669358527244818&gvzrMbar=0&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R='; + var str26 = 'hy.ynat-fryrpgbe'; + var re39 = /\\/g; + var re40 = / /g; + var re41 = /\/\xc4\/t/; + var re42 = /\/\xd6\/t/; + var re43 = /\/\xdc\/t/; + var re44 = /\/\xdf\/t/; + var re45 = /\/\xe4\/t/; + var re46 = /\/\xf6\/t/; + var re47 = /\/\xfc\/t/; + var re48 = /\W/g; + var re49 = /uers|fep|fglyr/; + function runBlock4() { + for (var i = 0; i < 16; i++) { + ''.replace(/\*/g, ''); + /\bnpgvir\b/.exec('npgvir'); + /sversbk/i.exec(str0); + re36.exec('glcr'); + /zfvr/i.exec(str0); + /bcren/i.exec(str0); + } + for (var i = 0; i < 15; i++) { + str21.split(re32); + str22.split(re32); + 'uggc://ohyyrgvaf.zlfcnpr.pbz/vaqrk.psz'.replace(re12, ''); + str23.replace(re33, ''); + 'yv'.replace(re37, ''); + 'yv'.replace(re18, ''); + re8.exec('144631658.0.10.1231367822'); + re8.exec('144631658.1231367822.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar)'); + re8.exec('144631658.4127520630321984500.1231367822.1231367822.1231367822.1'); + re8.exec(str24); + re8.exec(str25); + re8.exec('__hgzn=144631658.4127520630321984500.1231367822.1231367822.1231367822.1'); + re8.exec('__hgzo=144631658.0.10.1231367822'); + re8.exec('__hgzm=144631658.1231367822.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar)'); + re34.exec(str21); + re34.exec(str22); + /\.([\w-]+)|\[(\w+)(?:([!*^$~|]?=)["']?(.*?)["']?)?\]|:([\w-]+)(?:\(["']?(.*?)?["']?\)|$)/g.exec(str26); + re13.exec('uggc://ohyyrgvaf.zlfcnpr.pbz/vaqrk.psz'); + re38.exec('yv'); + } + for (var i = 0; i < 14; i++) { + ''.replace(re18, ''); + '9.0 e115'.replace(/(\s+e|\s+o[0-9]+)/, ''); + 'Funer guvf tnqtrg'.replace(//g, ''); + 'Funer guvf tnqtrg'.replace(re39, ''); + 'uggc://cebsvyrrqvg.zlfcnpr.pbz/vaqrk.psz'.replace(re12, ''); + 'grnfre'.replace(re40, ''); + 'grnfre'.replace(re41, ''); + 'grnfre'.replace(re42, ''); + 'grnfre'.replace(re43, ''); + 'grnfre'.replace(re44, ''); + 'grnfre'.replace(re45, ''); + 'grnfre'.replace(re46, ''); + 'grnfre'.replace(re47, ''); + 'grnfre'.replace(re48, ''); + re16.exec('znetva-gbc'); + re16.exec('cbfvgvba'); + re19.exec('gno1'); + re9.exec('qz'); + re9.exec('qg'); + re9.exec('zbqobk'); + re9.exec('zbqobkva'); + re9.exec('zbqgvgyr'); + re13.exec('uggc://cebsvyrrqvg.zlfcnpr.pbz/vaqrk.psz'); + re26.exec('/vt/znvytnqtrg'); + re49.exec('glcr'); + } + } + var re50 = /(?:^|\s+)fryrpgrq(?:\s+|$)/; + var re51 = /\&/g; + var re52 = /\+/g; + var re53 = /\?/g; + var re54 = /\t/g; + var re55 = /(\$\{nqiHey\})|(\$nqiHey\b)/g; + var re56 = /(\$\{cngu\})|(\$cngu\b)/g; + function runBlock5() { + for (var i = 0; i < 13; i++) { + 'purpx'.replace(re14, ''); + 'purpx'.replace(re15, ''); + 'pvgl'.replace(re14, ''); + 'pvgl'.replace(re15, ''); + 'qrpe fyvqrgrkg'.replace(re14, ''); + 'qrpe fyvqrgrkg'.replace(re15, ''); + 'svefg fryrpgrq'.replace(re14, ''); + 'svefg fryrpgrq'.replace(re15, ''); + 'uqy_rag'.replace(re14, ''); + 'uqy_rag'.replace(re15, ''); + 'vape fyvqrgrkg'.replace(re14, ''); + 'vape fyvqrgrkg'.replace(re15, ''); + 'vachggrkg QBZPbageby_cynprubyqre'.replace(re5, ''); + 'cnerag puebzr6 fvatyr1 gno fryrpgrq'.replace(re14, ''); + 'cnerag puebzr6 fvatyr1 gno fryrpgrq'.replace(re15, ''); + 'cb_guz'.replace(re14, ''); + 'cb_guz'.replace(re15, ''); + 'fhozvg'.replace(re14, ''); + 'fhozvg'.replace(re15, ''); + re50.exec(''); + /NccyrJroXvg\/([^\s]*)/.exec(str0); + /XUGZY/.exec(str0); + } + for (var i = 0; i < 12; i++) { + '${cebg}://${ubfg}${cngu}/${dz}'.replace(/(\$\{cebg\})|(\$cebg\b)/g, ''); + '1'.replace(re40, ''); + '1'.replace(re10, ''); + '1'.replace(re51, ''); + '1'.replace(re52, ''); + '1'.replace(re53, ''); + '1'.replace(re39, ''); + '1'.replace(re54, ''); + '9.0 e115'.replace(/^(.*)\..*$/, ''); + '9.0 e115'.replace(/^.*e(.*)$/, ''); + ''.replace(re55, ''); + ''.replace(re55, ''); + str1.replace(/^.*\s+(\S+\s+\S+$)/, ''); + 'tzk%2Subzrcntr%2Sfgneg%2Sqr%2S'.replace(re30, ''); + 'tzk'.replace(re30, ''); + 'uggc://${ubfg}${cngu}/${dz}'.replace(/(\$\{ubfg\})|(\$ubfg\b)/g, ''); + 'uggc://nqpyvrag.hvzfrei.arg${cngu}/${dz}'.replace(re56, ''); + 'uggc://nqpyvrag.hvzfrei.arg/wf.at/${dz}'.replace(/(\$\{dz\})|(\$dz\b)/g, ''); + 'frpgvba'.replace(re29, ''); + 'frpgvba'.replace(re30, ''); + 'fvgr'.replace(re29, ''); + 'fvgr'.replace(re30, ''); + 'fcrpvny'.replace(re29, ''); + 'fcrpvny'.replace(re30, ''); + re36.exec('anzr'); + /e/.exec('9.0 e115'); + } + } + var re57 = /##yv4##/gi; + var re58 = /##yv16##/gi; + var re59 = /##yv19##/gi; + var str27 = '##yv4##Cbjreshy Zvpebfbsg grpuabybtl urycf svtug fcnz naq vzcebir frphevgl.##yv19##Trg zber qbar gunaxf gb terngre rnfr naq fcrrq.##yv16##Ybgf bs fgbentr (5 TO) - zber pbby fghss ba gur jnl.##OE## ##OE## ##N##Yrnea zber##/N##'; + var str28 = 'Cbjreshy Zvpebfbsg grpuabybtl urycf svtug fcnz naq vzcebir frphevgl.##yv19##Trg zber qbar gunaxf gb terngre rnfr naq fcrrq.##yv16##Ybgf bs fgbentr (5 TO) - zber pbby fghss ba gur jnl.##OE## ##OE## ##N##Yrnea zber##/N##'; + var str29 = 'Cbjreshy Zvpebfbsg grpuabybtl urycf svtug fcnz naq vzcebir frphevgl.##yv19##Trg zber qbar gunaxf gb terngre rnfr naq fcrrq.Ybgf bs fgbentr (5 TO) - zber pbby fghss ba gur jnl.##OE## ##OE## ##N##Yrnea zber##/N##'; + var str30 = 'Cbjreshy Zvpebfbsg grpuabybtl urycf svtug fcnz naq vzcebir frphevgl.Trg zber qbar gunaxf gb terngre rnfr naq fcrrq.Ybgf bs fgbentr (5 TO) - zber pbby fghss ba gur jnl.##OE## ##OE## ##N##Yrnea zber##/N##'; + var str31 = 'Cbjreshy Zvpebfbsg grpuabybtl urycf svtug fcnz naq vzcebir frphevgl.Trg zber qbar gunaxf gb terngre rnfr naq fcrrq.Ybgf bs fgbentr (5 TO) - zber pbby fghss ba gur jnl. ##N##Yrnea zber##/N##'; + var str32 = 'Cbjreshy Zvpebfbsg grpuabybtl urycf svtug fcnz naq vzcebir frphevgl.Trg zber qbar gunaxf gb terngre rnfr naq fcrrq.Ybgf bs fgbentr (5 TO) - zber pbby fghss ba gur jnl. Yrnea zber##/N##'; + var str33 = 'Bar Jvaqbjf Yvir VQ trgf lbh vagb Ubgznvy, Zrffratre, Kobk YVIR \u2014 naq bgure cynprf lbh frr #~#argjbexybtb#~#'; + var re60 = /(?:^|\s+)bss(?:\s+|$)/; + var re61 = /^(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?$/; + var re62 = /^[^<]*(<(.|\s)+>)[^>]*$|^#(\w+)$/; + var str34 = '${1}://${2}${3}${4}${5}'; + var str35 = ' O=6gnyg0g4znrrn&o=3&f=gc; Q=_lyu=K3bQZGSxnT4lZzD3OS9GNmV3ZGLkAQxRpTyxNmRlZmRmAmNkAQLRqTImqNZjOUEgpTjQnJ5xMKtgoN--; SCF=qy'; + function runBlock6() { + for (var i = 0; i < 11; i++) { + str27.replace(/##yv0##/gi, ''); + str27.replace(re57, ''); + str28.replace(re58, ''); + str29.replace(re59, ''); + str30.replace(/##\/o##/gi, ''); + str30.replace(/##\/v##/gi, ''); + str30.replace(/##\/h##/gi, ''); + str30.replace(/##o##/gi, ''); + str30.replace(/##oe##/gi, ''); + str30.replace(/##v##/gi, ''); + str30.replace(/##h##/gi, ''); + str31.replace(/##n##/gi, ''); + str32.replace(/##\/n##/gi, ''); + str33.replace(/#~#argjbexybtb#~#/g, ''); + / Zbovyr\//.exec(str0); + /##yv1##/gi.exec(str27); + /##yv10##/gi.exec(str28); + /##yv11##/gi.exec(str28); + /##yv12##/gi.exec(str28); + /##yv13##/gi.exec(str28); + /##yv14##/gi.exec(str28); + /##yv15##/gi.exec(str28); + re58.exec(str28); + /##yv17##/gi.exec(str29); + /##yv18##/gi.exec(str29); + re59.exec(str29); + /##yv2##/gi.exec(str27); + /##yv20##/gi.exec(str30); + /##yv21##/gi.exec(str30); + /##yv22##/gi.exec(str30); + /##yv23##/gi.exec(str30); + /##yv3##/gi.exec(str27); + re57.exec(str27); + /##yv5##/gi.exec(str28); + /##yv6##/gi.exec(str28); + /##yv7##/gi.exec(str28); + /##yv8##/gi.exec(str28); + /##yv9##/gi.exec(str28); + re8.exec('473qq1rs0n2r70q9qo1pq48n021s9468ron90nps048p4p29'); + re8.exec('SbeprqRkcvengvba=633669325184628362'); + re8.exec('FrffvbaQQS2=473qq1rs0n2r70q9qo1pq48n021s9468ron90nps048p4p29'); + /AbxvnA[^\/]*/.exec(str0); + } + for (var i = 0; i < 10; i++) { + ' bss'.replace(/(?:^|\s+)bss(?:\s+|$)/g, ''); + str34.replace(/(\$\{0\})|(\$0\b)/g, ''); + str34.replace(/(\$\{1\})|(\$1\b)/g, ''); + str34.replace(/(\$\{pbzcyrgr\})|(\$pbzcyrgr\b)/g, ''); + str34.replace(/(\$\{sentzrag\})|(\$sentzrag\b)/g, ''); + str34.replace(/(\$\{ubfgcbeg\})|(\$ubfgcbeg\b)/g, ''); + str34.replace(re56, ''); + str34.replace(/(\$\{cebgbpby\})|(\$cebgbpby\b)/g, ''); + str34.replace(/(\$\{dhrel\})|(\$dhrel\b)/g, ''); + 'nqfvmr'.replace(re29, ''); + 'nqfvmr'.replace(re30, ''); + 'uggc://${2}${3}${4}${5}'.replace(/(\$\{2\})|(\$2\b)/g, ''); + 'uggc://wf.hv-cbegny.qr${3}${4}${5}'.replace(/(\$\{3\})|(\$3\b)/g, ''); + 'arjf'.replace(re40, ''); + 'arjf'.replace(re41, ''); + 'arjf'.replace(re42, ''); + 'arjf'.replace(re43, ''); + 'arjf'.replace(re44, ''); + 'arjf'.replace(re45, ''); + 'arjf'.replace(re46, ''); + 'arjf'.replace(re47, ''); + 'arjf'.replace(re48, ''); + / PC=i=(\d+)&oe=(.)/.exec(str35); + re60.exec(' '); + re60.exec(' bss'); + re60.exec(''); + re19.exec(' '); + re19.exec('svefg ba'); + re19.exec('ynfg vtaber'); + re19.exec('ba'); + re9.exec('scnq so '); + re9.exec('zrqvgobk'); + re9.exec('hsgy'); + re9.exec('lhv-h'); + /Fnsnev|Xbadhrebe|XUGZY/gi.exec(str0); + re61.exec('uggc://wf.hv-cbegny.qr/tzk/ubzr/wf/20080602/onfr.wf'); + re62.exec('#Ybtva_rznvy'); + } + } + var re63 = /\{0\}/g; + var str36 = 'FrffvbaQQS2=4ss747o77904333q374or84qrr1s9r0nprp8r5q81534o94n; ZFPhygher=VC=74.125.75.20&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&CersreerqPhygherCraqvat=&Pbhagel=IIZ=&SbeprqRkcvengvba=633669321699093060&gvzrMbar=0&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R=; AFP_zp_tfwsbrg-aowb_80=4413268q3660'; + var str37 = 'FrffvbaQQS2=4ss747o77904333q374or84qrr1s9r0nprp8r5q81534o94n; AFP_zp_tfwsbrg-aowb_80=4413268q3660; __hgzm=144631658.1231364074.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar); __hgzn=144631658.2294274870215848400.1231364074.1231364074.1231364074.1; __hgzo=144631658.0.10.1231364074; __hgzp=144631658; ZFPhygher=VC=74.125.75.20&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&Pbhagel=IIZ%3Q&SbeprqRkcvengvba=633669321699093060&gvzrMbar=-8&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R%3Q'; + var str38 = 'uggc://tbbtyrnqf.t.qbhoyrpyvpx.arg/cntrnq/nqf?pyvrag=pn-svz_zlfcnpr_zlfcnpr-ubzrcntr_wf&qg=1231364057761&uy=ra&nqfnsr=uvtu&br=hgs8&ahz_nqf=4&bhgchg=wf&nqgrfg=bss&pbeeryngbe=1231364057761&punaary=svz_zlfcnpr_ubzrcntr_abgybttrqva%2Psvz_zlfcnpr_aba_HTP%2Psvz_zlfcnpr_havgrq-fgngrf&hey=uggc%3N%2S%2Ssevraqf.zlfcnpr.pbz%2Svaqrk.psz&nq_glcr=grkg&rvq=6083027&rn=0&sez=0&tn_ivq=1667363813.1231364061&tn_fvq=1231364061&tn_uvq=1917563877&synfu=9.0.115&h_u=768&h_j=1024&h_nu=738&h_nj=1024&h_pq=24&h_gm=-480&h_uvf=2&h_wnin=gehr&h_acyht=7&h_azvzr=22'; + var str39 = 'ZFPhygher=VC=74.125.75.20&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&Pbhagel=IIZ%3Q&SbeprqRkcvengvba=633669321699093060&gvzrMbar=-8&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R%3Q'; + var str40 = 'ZFPhygher=VC=74.125.75.20&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&CersreerqPhygherCraqvat=&Pbhagel=IIZ=&SbeprqRkcvengvba=633669321699093060&gvzrMbar=0&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R='; + function runBlock7() { + for (var i = 0; i < 9; i++) { + '0'.replace(re40, ''); + '0'.replace(re10, ''); + '0'.replace(re51, ''); + '0'.replace(re52, ''); + '0'.replace(re53, ''); + '0'.replace(re39, ''); + '0'.replace(re54, ''); + 'Lrf'.replace(re40, ''); + 'Lrf'.replace(re10, ''); + 'Lrf'.replace(re51, ''); + 'Lrf'.replace(re52, ''); + 'Lrf'.replace(re53, ''); + 'Lrf'.replace(re39, ''); + 'Lrf'.replace(re54, ''); + } + for (var i = 0; i < 8; i++) { + 'Pybfr {0}'.replace(re63, ''); + 'Bcra {0}'.replace(re63, ''); + str36.split(re32); + str37.split(re32); + 'puvyq p1 svefg gnournqref'.replace(re14, ''); + 'puvyq p1 svefg gnournqref'.replace(re15, ''); + 'uqy_fcb'.replace(re14, ''); + 'uqy_fcb'.replace(re15, ''); + 'uvag'.replace(re14, ''); + 'uvag'.replace(re15, ''); + str38.replace(re33, ''); + 'yvfg'.replace(re14, ''); + 'yvfg'.replace(re15, ''); + 'at_bhgre'.replace(re30, ''); + 'cnerag puebzr5 qbhoyr2 NU'.replace(re14, ''); + 'cnerag puebzr5 qbhoyr2 NU'.replace(re15, ''); + 'cnerag puebzr5 dhnq5 ps NU osyvax zbarl'.replace(re14, ''); + 'cnerag puebzr5 dhnq5 ps NU osyvax zbarl'.replace(re15, ''); + 'cnerag puebzr6 fvatyr1'.replace(re14, ''); + 'cnerag puebzr6 fvatyr1'.replace(re15, ''); + 'cb_qrs'.replace(re14, ''); + 'cb_qrs'.replace(re15, ''); + 'gnopbagrag'.replace(re14, ''); + 'gnopbagrag'.replace(re15, ''); + 'iv_svefg_gvzr'.replace(re30, ''); + /(^|.)(ronl|qri-ehf3.wbg)(|fgberf|zbgbef|yvirnhpgvbaf|jvxv|rkcerff|punggre).(pbz(|.nh|.pa|.ux|.zl|.ft|.oe|.zk)|pb(.hx|.xe|.am)|pn|qr|se|vg|ay|or|ng|pu|vr|va|rf|cy|cu|fr)$/i.exec('cntrf.ronl.pbz'); + re8.exec('144631658.0.10.1231364074'); + re8.exec('144631658.1231364074.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar)'); + re8.exec('144631658.2294274870215848400.1231364074.1231364074.1231364074.1'); + re8.exec('4413241q3660'); + re8.exec('SbeprqRkcvengvba=633669357391353591'); + re8.exec(str39); + re8.exec(str40); + re8.exec('AFP_zp_kkk-gdzogv_80=4413241q3660'); + re8.exec('FrffvbaQQS2=p98s8o9q42nr21or1r61pqorn1n002nsss569635984s6qp7'); + re8.exec('__hgzn=144631658.2294274870215848400.1231364074.1231364074.1231364074.1'); + re8.exec('__hgzo=144631658.0.10.1231364074'); + re8.exec('__hgzm=144631658.1231364074.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar)'); + re8.exec('p98s8o9q42nr21or1r61pqorn1n002nsss569635984s6qp7'); + re34.exec(str36); + re34.exec(str37); + } + } + var re64 = /\b[a-z]/g; + var re65 = /^uggc:\/\//; + var re66 = /(?:^|\s+)qvfnoyrq(?:\s+|$)/; + var str41 = 'uggc://cebsvyr.zlfcnpr.pbz/Zbqhyrf/Nccyvpngvbaf/Cntrf/Pnainf.nfck'; + function runBlock8() { + for (var i = 0; i < 7; i++) { + str1.match(/\d+/g); + 'nsgre'.replace(re64, ''); + 'orsber'.replace(re64, ''); + 'obggbz'.replace(re64, ''); + 'ohvygva_jrngure.kzy'.replace(re65, ''); + 'ohggba'.replace(re37, ''); + 'ohggba'.replace(re18, ''); + 'qngrgvzr.kzy'.replace(re65, ''); + 'uggc://eff.paa.pbz/eff/paa_gbcfgbevrf.eff'.replace(re65, ''); + 'vachg'.replace(re37, ''); + 'vachg'.replace(re18, ''); + 'vafvqr'.replace(re64, ''); + 'cbvagre'.replace(re27, ''); + 'cbfvgvba'.replace(/[A-Z]/g, ''); + 'gbc'.replace(re27, ''); + 'gbc'.replace(re64, ''); + 'hy'.replace(re37, ''); + 'hy'.replace(re18, ''); + str26.replace(re37, ''); + str26.replace(re18, ''); + 'lbhghor_vtbbtyr/i2/lbhghor.kzy'.replace(re65, ''); + 'm-vaqrk'.replace(re27, ''); + /#([\w-]+)/.exec(str26); + re16.exec('urvtug'); + re16.exec('znetvaGbc'); + re16.exec('jvqgu'); + re19.exec('gno0 svefg ba'); + re19.exec('gno0 ba'); + re19.exec('gno4 ynfg'); + re19.exec('gno4'); + re19.exec('gno5'); + re19.exec('gno6'); + re19.exec('gno7'); + re19.exec('gno8'); + /NqborNVE\/([^\s]*)/.exec(str0); + /NccyrJroXvg\/([^ ]*)/.exec(str0); + /XUGZY/gi.exec(str0); + /^(?:obql|ugzy)$/i.exec('YV'); + re38.exec('ohggba'); + re38.exec('vachg'); + re38.exec('hy'); + re38.exec(str26); + /^(\w+|\*)/.exec(str26); + /znp|jva|yvahk/i.exec('Jva32'); + /eton?\([\d\s,]+\)/.exec('fgngvp'); + } + for (var i = 0; i < 6; i++) { + ''.replace(/\r/g, ''); + '/'.replace(re40, ''); + '/'.replace(re10, ''); + '/'.replace(re51, ''); + '/'.replace(re52, ''); + '/'.replace(re53, ''); + '/'.replace(re39, ''); + '/'.replace(re54, ''); + 'uggc://zfacbegny.112.2b7.arg/o/ff/zfacbegnyubzr/1/U.7-cqi-2/{0}?[NDO]&{1}&{2}&[NDR]'.replace(re63, ''); + str41.replace(re12, ''); + 'uggc://jjj.snprobbx.pbz/fepu.cuc'.replace(re23, ''); + 'freivpr'.replace(re40, ''); + 'freivpr'.replace(re41, ''); + 'freivpr'.replace(re42, ''); + 'freivpr'.replace(re43, ''); + 'freivpr'.replace(re44, ''); + 'freivpr'.replace(re45, ''); + 'freivpr'.replace(re46, ''); + 'freivpr'.replace(re47, ''); + 'freivpr'.replace(re48, ''); + /((ZFVR\s+([6-9]|\d\d)\.))/.exec(str0); + re66.exec(''); + re50.exec('fryrpgrq'); + re8.exec('8sqq78r9n442851q565599o401385sp3s04r92rnn7o19ssn'); + re8.exec('SbeprqRkcvengvba=633669340386893867'); + re8.exec('VC=74.125.75.17'); + re8.exec('FrffvbaQQS2=8sqq78r9n442851q565599o401385sp3s04r92rnn7o19ssn'); + /Xbadhrebe|Fnsnev|XUGZY/.exec(str0); + re13.exec(str41); + re49.exec('unfsbphf'); + } + } + var re67 = /zrah_byq/g; + var str42 = 'FrffvbaQQS2=473qq1rs0n2r70q9qo1pq48n021s9468ron90nps048p4p29; ZFPhygher=VC=74.125.75.3&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&CersreerqPhygherCraqvat=&Pbhagel=IIZ=&SbeprqRkcvengvba=633669325184628362&gvzrMbar=0&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R='; + var str43 = 'FrffvbaQQS2=473qq1rs0n2r70q9qo1pq48n021s9468ron90nps048p4p29; __hgzm=144631658.1231364380.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar); __hgzn=144631658.3931862196947939300.1231364380.1231364380.1231364380.1; __hgzo=144631658.0.10.1231364380; __hgzp=144631658; ZFPhygher=VC=74.125.75.3&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&Pbhagel=IIZ%3Q&SbeprqRkcvengvba=633669325184628362&gvzrMbar=-8&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R%3Q'; + var str44 = 'uggc://tbbtyrnqf.t.qbhoyrpyvpx.arg/cntrnq/nqf?pyvrag=pn-svz_zlfcnpr_vzntrf_wf&qg=1231364373088&uy=ra&nqfnsr=uvtu&br=hgs8&ahz_nqf=4&bhgchg=wf&nqgrfg=bss&pbeeryngbe=1231364373088&punaary=svz_zlfcnpr_hfre-ivrj-pbzzragf%2Psvz_zlfcnpr_havgrq-fgngrf&hey=uggc%3N%2S%2Spbzzrag.zlfcnpr.pbz%2Svaqrk.psz&nq_glcr=grkg&rvq=6083027&rn=0&sez=0&tn_ivq=1158737789.1231364375&tn_fvq=1231364375&tn_uvq=415520832&synfu=9.0.115&h_u=768&h_j=1024&h_nu=738&h_nj=1024&h_pq=24&h_gm=-480&h_uvf=2&h_wnin=gehr&h_acyht=7&h_azvzr=22'; + var str45 = 'ZFPhygher=VC=74.125.75.3&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&Pbhagel=IIZ%3Q&SbeprqRkcvengvba=633669325184628362&gvzrMbar=-8&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R%3Q'; + var str46 = 'ZFPhygher=VC=74.125.75.3&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&CersreerqPhygherCraqvat=&Pbhagel=IIZ=&SbeprqRkcvengvba=633669325184628362&gvzrMbar=0&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R='; + var re68 = /^([#.]?)((?:[\w\u0128-\uffff*_-]|\\.)*)/; + var re69 = /\{1\}/g; + var re70 = /\s+/; + var re71 = /(\$\{4\})|(\$4\b)/g; + var re72 = /(\$\{5\})|(\$5\b)/g; + var re73 = /\{2\}/g; + var re74 = /[^+>] [^+>]/; + var re75 = /\bucpyv\s*=\s*([^;]*)/i; + var re76 = /\bucuvqr\s*=\s*([^;]*)/i; + var re77 = /\bucfie\s*=\s*([^;]*)/i; + var re78 = /\bhfucjrn\s*=\s*([^;]*)/i; + var re79 = /\bmvc\s*=\s*([^;]*)/i; + var re80 = /^((?:[\w\u0128-\uffff*_-]|\\.)+)(#)((?:[\w\u0128-\uffff*_-]|\\.)+)/; + var re81 = /^([>+~])\s*(\w*)/i; + var re82 = /^>\s*((?:[\w\u0128-\uffff*_-]|\\.)+)/; + var re83 = /^[\s[]?shapgvba/; + var re84 = /v\/g.tvs#(.*)/i; + var str47 = '#Zbq-Vasb-Vasb-WninFpevcgUvag'; + var str48 = ',n.svryqOgaPnapry'; + var str49 = 'FrffvbaQQS2=p98s8o9q42nr21or1r61pqorn1n002nsss569635984s6qp7; ZFPhygher=VC=74.125.75.3&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&CersreerqPhygherCraqvat=&Pbhagel=IIZ=&SbeprqRkcvengvba=633669357391353591&gvzrMbar=0&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R=; AFP_zp_kkk-gdzogv_80=4413241q3660'; + var str50 = 'FrffvbaQQS2=p98s8o9q42nr21or1r61pqorn1n002nsss569635984s6qp7; AFP_zp_kkk-gdzogv_80=4413241q3660; AFP_zp_kkk-aowb_80=4413235p3660; __hgzm=144631658.1231367708.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar); __hgzn=144631658.2770915348920628700.1231367708.1231367708.1231367708.1; __hgzo=144631658.0.10.1231367708; __hgzp=144631658; ZFPhygher=VC=74.125.75.3&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&Pbhagel=IIZ%3Q&SbeprqRkcvengvba=633669357391353591&gvzrMbar=-8&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R%3Q'; + var str51 = 'uggc://tbbtyrnqf.t.qbhoyrpyvpx.arg/cntrnq/nqf?pyvrag=pn-svz_zlfcnpr_zlfcnpr-ubzrcntr_wf&qg=1231367691141&uy=ra&nqfnsr=uvtu&br=hgs8&ahz_nqf=4&bhgchg=wf&nqgrfg=bss&pbeeryngbe=1231367691141&punaary=svz_zlfcnpr_ubzrcntr_abgybttrqva%2Psvz_zlfcnpr_aba_HTP%2Psvz_zlfcnpr_havgrq-fgngrf&hey=uggc%3N%2S%2Sjjj.zlfcnpr.pbz%2S&nq_glcr=grkg&rvq=6083027&rn=0&sez=0&tn_ivq=320757904.1231367694&tn_fvq=1231367694&tn_uvq=1758792003&synfu=9.0.115&h_u=768&h_j=1024&h_nu=738&h_nj=1024&h_pq=24&h_gm=-480&h_uvf=2&h_wnin=gehr&h_acyht=7&h_azvzr=22'; + var str52 = 'uggc://zfacbegny.112.2b7.arg/o/ff/zfacbegnyubzr/1/U.7-cqi-2/f55332979829981?[NDO]&aqu=1&g=7%2S0%2S2009%2014%3N38%3N42%203%20480&af=zfacbegny&cntrAnzr=HF%20UCZFSGJ&t=uggc%3N%2S%2Sjjj.zfa.pbz%2S&f=1024k768&p=24&x=L&oj=994&ou=634&uc=A&{2}&[NDR]'; + var str53 = 'cnerag puebzr6 fvatyr1 gno fryrpgrq ovaq qbhoyr2 ps'; + var str54 = 'ZFPhygher=VC=74.125.75.3&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&Pbhagel=IIZ%3Q&SbeprqRkcvengvba=633669357391353591&gvzrMbar=-8&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R%3Q'; + var str55 = 'ZFPhygher=VC=74.125.75.3&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&CersreerqPhygherCraqvat=&Pbhagel=IIZ=&SbeprqRkcvengvba=633669357391353591&gvzrMbar=0&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R='; + var str56 = 'ne;ng;nh;or;oe;pn;pu;py;pa;qr;qx;rf;sv;se;to;ux;vq;vr;va;vg;wc;xe;zk;zl;ay;ab;am;cu;cy;cg;eh;fr;ft;gu;ge;gj;mn;'; + var str57 = 'ZP1=I=3&THVQ=6nnpr9q661804s33nnop45nosqp17q85; zu=ZFSG; PHYGHER=RA-HF; SyvtugTebhcVq=97; SyvtugVq=OnfrCntr; ucfie=Z:5|S:5|G:5|R:5|Q:oyh|J:S; ucpyv=J.U|Y.|F.|E.|H.Y|P.|U.; hfucjrn=jp:HFPN0746; ZHVQ=Q783SN9O14054831N4869R51P0SO8886&GHVQ=1'; + var str58 = 'ZP1=I=3&THVQ=6nnpr9q661804s33nnop45nosqp17q85; zu=ZFSG; PHYGHER=RA-HF; SyvtugTebhcVq=97; SyvtugVq=OnfrCntr; ucfie=Z:5|S:5|G:5|R:5|Q:oyh|J:S; ucpyv=J.U|Y.|F.|E.|H.Y|P.|U.; hfucjrn=jp:HFPN0746; ZHVQ=Q783SN9O14054831N4869R51P0SO8886'; + var str59 = 'ZP1=I=3&THVQ=6nnpr9q661804s33nnop45nosqp17q85; zu=ZFSG; PHYGHER=RA-HF; SyvtugTebhcVq=97; SyvtugVq=OnfrCntr; ucfie=Z:5|S:5|G:5|R:5|Q:oyh|J:S; ucpyv=J.U|Y.|F.|E.|H.Y|P.|U.; hfucjrn=jp:HFPN0746; ZHVQ=Q783SN9O14054831N4869R51P0SO8886; mvc=m:94043|yn:37.4154|yb:-122.0585|p:HF|ue:1'; + var str60 = 'ZP1=I=3&THVQ=6nnpr9q661804s33nnop45nosqp17q85; zu=ZFSG; PHYGHER=RA-HF; SyvtugTebhcVq=97; SyvtugVq=OnfrCntr; ucfie=Z:5|S:5|G:5|R:5|Q:oyh|J:S; ucpyv=J.U|Y.|F.|E.|H.Y|P.|U.; hfucjrn=jp:HFPN0746; ZHVQ=Q783SN9O14054831N4869R51P0SO8886; mvc=m:94043|yn:37.4154|yb:-122.0585|p:HF'; + var str61 = 'uggc://gx2.fgp.f-zfa.pbz/oe/uc/11/ra-hf/pff/v/g.tvs#uggc://gx2.fgo.f-zfa.pbz/v/29/4RQP4969777N048NPS4RRR3PO2S7S.wct'; + var str62 = 'uggc://gx2.fgp.f-zfa.pbz/oe/uc/11/ra-hf/pff/v/g.tvs#uggc://gx2.fgo.f-zfa.pbz/v/OQ/63NP9O94NS5OQP1249Q9S1ROP7NS3.wct'; + var str63 = 'zbmvyyn/5.0 (jvaqbjf; h; jvaqbjf ag 5.1; ra-hf) nccyrjroxvg/528.9 (xugzy, yvxr trpxb) puebzr/2.0.157.0 fnsnev/528.9'; + function runBlock9() { + for (var i = 0; i < 5; i++) { + str42.split(re32); + str43.split(re32); + 'svz_zlfcnpr_hfre-ivrj-pbzzragf,svz_zlfcnpr_havgrq-fgngrf'.split(re20); + str44.replace(re33, ''); + 'zrah_arj zrah_arj_gbttyr zrah_gbttyr'.replace(re67, ''); + 'zrah_byq zrah_byq_gbttyr zrah_gbttyr'.replace(re67, ''); + re8.exec('102n9o0o9pq60132qn0337rr867p75953502q2s27s2s5r98'); + re8.exec('144631658.0.10.1231364380'); + re8.exec('144631658.1231364380.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar)'); + re8.exec('144631658.3931862196947939300.1231364380.1231364380.1231364380.1'); + re8.exec('441326q33660'); + re8.exec('SbeprqRkcvengvba=633669341278771470'); + re8.exec(str45); + re8.exec(str46); + re8.exec('AFP_zp_dfctwzssrwh-aowb_80=441326q33660'); + re8.exec('FrffvbaQQS2=102n9o0o9pq60132qn0337rr867p75953502q2s27s2s5r98'); + re8.exec('__hgzn=144631658.3931862196947939300.1231364380.1231364380.1231364380.1'); + re8.exec('__hgzo=144631658.0.10.1231364380'); + re8.exec('__hgzm=144631658.1231364380.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar)'); + } + for (var i = 0; i < 4; i++) { + ' yvfg1'.replace(re14, ''); + ' yvfg1'.replace(re15, ''); + ' yvfg2'.replace(re14, ''); + ' yvfg2'.replace(re15, ''); + ' frneputebhc1'.replace(re14, ''); + ' frneputebhc1'.replace(re15, ''); + str47.replace(re68, ''); + str47.replace(re18, ''); + ''.replace(/&/g, ''); + ''.replace(re35, ''); + '(..-{0})(\|(\d+)|)'.replace(re63, ''); + str48.replace(re18, ''); + '//vzt.jro.qr/vij/FC/${cngu}/${anzr}/${inyhr}?gf=${abj}'.replace(re56, ''); + '//vzt.jro.qr/vij/FC/tzk_uc/${anzr}/${inyhr}?gf=${abj}'.replace(/(\$\{anzr\})|(\$anzr\b)/g, ''); + 'Jvaqbjf Yvir Ubgznvy{1}'.replace(re69, ''); + '{0}{1}'.replace(re63, ''); + '{1}'.replace(re69, ''); + '{1}'.replace(re63, ''); + 'Vzntrf'.replace(re15, ''); + 'ZFA'.replace(re15, ''); + 'Zncf'.replace(re15, ''); + 'Zbq-Vasb-Vasb-WninFpevcgUvag'.replace(re39, ''); + 'Arjf'.replace(re15, ''); + str49.split(re32); + str50.split(re32); + 'Ivqrb'.replace(re15, ''); + 'Jro'.replace(re15, ''); + 'n'.replace(re39, ''); + 'nwnkFgneg'.split(re70); + 'nwnkFgbc'.split(re70); + 'ovaq'.replace(re14, ''); + 'ovaq'.replace(re15, ''); + 'oevatf lbh zber. Zber fcnpr (5TO), zber frphevgl, fgvyy serr.'.replace(re63, ''); + 'puvyq p1 svefg qrpx'.replace(re14, ''); + 'puvyq p1 svefg qrpx'.replace(re15, ''); + 'puvyq p1 svefg qbhoyr2'.replace(re14, ''); + 'puvyq p1 svefg qbhoyr2'.replace(re15, ''); + 'puvyq p2 ynfg'.replace(re14, ''); + 'puvyq p2 ynfg'.replace(re15, ''); + 'puvyq p2'.replace(re14, ''); + 'puvyq p2'.replace(re15, ''); + 'puvyq p3'.replace(re14, ''); + 'puvyq p3'.replace(re15, ''); + 'puvyq p4 ynfg'.replace(re14, ''); + 'puvyq p4 ynfg'.replace(re15, ''); + 'pbclevtug'.replace(re14, ''); + 'pbclevtug'.replace(re15, ''); + 'qZFAZR_1'.replace(re14, ''); + 'qZFAZR_1'.replace(re15, ''); + 'qbhoyr2 ps'.replace(re14, ''); + 'qbhoyr2 ps'.replace(re15, ''); + 'qbhoyr2'.replace(re14, ''); + 'qbhoyr2'.replace(re15, ''); + 'uqy_arj'.replace(re14, ''); + 'uqy_arj'.replace(re15, ''); + 'uc_fubccvatobk'.replace(re30, ''); + 'ugzy%2Rvq'.replace(re29, ''); + 'ugzy%2Rvq'.replace(re30, ''); + str51.replace(re33, ''); + 'uggc://wf.hv-cbegny.qr/tzk/ubzr/wf/20080602/cebgbglcr.wf${4}${5}'.replace(re71, ''); + 'uggc://wf.hv-cbegny.qr/tzk/ubzr/wf/20080602/cebgbglcr.wf${5}'.replace(re72, ''); + str52.replace(re73, ''); + 'uggc://zfacbegny.112.2b7.arg/o/ff/zfacbegnyubzr/1/U.7-cqi-2/f55332979829981?[NDO]&{1}&{2}&[NDR]'.replace(re69, ''); + 'vztZFSG'.replace(re14, ''); + 'vztZFSG'.replace(re15, ''); + 'zfasbbg1 ps'.replace(re14, ''); + 'zfasbbg1 ps'.replace(re15, ''); + str53.replace(re14, ''); + str53.replace(re15, ''); + 'cnerag puebzr6 fvatyr1 gno fryrpgrq ovaq'.replace(re14, ''); + 'cnerag puebzr6 fvatyr1 gno fryrpgrq ovaq'.replace(re15, ''); + 'cevznel'.replace(re14, ''); + 'cevznel'.replace(re15, ''); + 'erpgnatyr'.replace(re30, ''); + 'frpbaqnel'.replace(re14, ''); + 'frpbaqnel'.replace(re15, ''); + 'haybnq'.split(re70); + '{0}{1}1'.replace(re63, ''); + '|{1}1'.replace(re69, ''); + /(..-HF)(\|(\d+)|)/i.exec('xb-xe,ra-va,gu-gu'); + re4.exec('/ZlFcnprNccf/NccPnainf,45000012'); + re8.exec('144631658.0.10.1231367708'); + re8.exec('144631658.1231367708.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar)'); + re8.exec('144631658.2770915348920628700.1231367708.1231367708.1231367708.1'); + re8.exec('4413235p3660'); + re8.exec('441327q73660'); + re8.exec('9995p6rp12rrnr893334ro7nq70o7p64p69rqn844prs1473'); + re8.exec('SbeprqRkcvengvba=633669350559478880'); + re8.exec(str54); + re8.exec(str55); + re8.exec('AFP_zp_dfctwzs-aowb_80=441327q73660'); + re8.exec('AFP_zp_kkk-aowb_80=4413235p3660'); + re8.exec('FrffvbaQQS2=9995p6rp12rrnr893334ro7nq70o7p64p69rqn844prs1473'); + re8.exec('__hgzn=144631658.2770915348920628700.1231367708.1231367708.1231367708.1'); + re8.exec('__hgzo=144631658.0.10.1231367708'); + re8.exec('__hgzm=144631658.1231367708.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar)'); + re34.exec(str49); + re34.exec(str50); + /ZFVR\s+5[.]01/.exec(str0); + /HF(?=;)/i.exec(str56); + re74.exec(str47); + re28.exec('svefg npgvir svefgNpgvir'); + re28.exec('ynfg'); + /\bp:(..)/i.exec('m:94043|yn:37.4154|yb:-122.0585|p:HF'); + re75.exec(str57); + re75.exec(str58); + re76.exec(str57); + re76.exec(str58); + re77.exec(str57); + re77.exec(str58); + /\bhfucce\s*=\s*([^;]*)/i.exec(str59); + re78.exec(str57); + re78.exec(str58); + /\bjci\s*=\s*([^;]*)/i.exec(str59); + re79.exec(str58); + re79.exec(str60); + re79.exec(str59); + /\|p:([a-z]{2})/i.exec('m:94043|yn:37.4154|yb:-122.0585|p:HF|ue:1'); + re80.exec(str47); + re61.exec('cebgbglcr.wf'); + re68.exec(str47); + re81.exec(str47); + re82.exec(str47); + /^Fubpxjnir Synfu (\d)/.exec(str1); + /^Fubpxjnir Synfu (\d+)/.exec(str1); + re83.exec('[bowrpg tybony]'); + re62.exec(str47); + re84.exec(str61); + re84.exec(str62); + /jroxvg/.exec(str63); + } + } + var re85 = /eaq_zbqobkva/; + var str64 = '1231365729213'; + var str65 = '74.125.75.3-1057165600.29978900'; + var str66 = '74.125.75.3-1057165600.29978900.1231365730214'; + var str67 = 'Frnepu%20Zvpebfbsg.pbz'; + var str68 = 'FrffvbaQQS2=8sqq78r9n442851q565599o401385sp3s04r92rnn7o19ssn; ZFPhygher=VC=74.125.75.17&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&CersreerqPhygherCraqvat=&Pbhagel=IIZ=&SbeprqRkcvengvba=633669340386893867&gvzrMbar=0&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R='; + var str69 = 'FrffvbaQQS2=8sqq78r9n442851q565599o401385sp3s04r92rnn7o19ssn; __hgzm=144631658.1231365779.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar); __hgzn=144631658.1877536177953918500.1231365779.1231365779.1231365779.1; __hgzo=144631658.0.10.1231365779; __hgzp=144631658; ZFPhygher=VC=74.125.75.17&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&Pbhagel=IIZ%3Q&SbeprqRkcvengvba=633669340386893867&gvzrMbar=-8&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R%3Q'; + var str70 = 'I=3%26THVQ=757q3ss871q44o7o805n8113n5p72q52'; + var str71 = 'I=3&THVQ=757q3ss871q44o7o805n8113n5p72q52'; + var str72 = 'uggc://tbbtyrnqf.t.qbhoyrpyvpx.arg/cntrnq/nqf?pyvrag=pn-svz_zlfcnpr_zlfcnpr-ubzrcntr_wf&qg=1231365765292&uy=ra&nqfnsr=uvtu&br=hgs8&ahz_nqf=4&bhgchg=wf&nqgrfg=bss&pbeeryngbe=1231365765292&punaary=svz_zlfcnpr_ubzrcntr_abgybttrqva%2Psvz_zlfcnpr_aba_HTP%2Psvz_zlfcnpr_havgrq-fgngrf&hey=uggc%3N%2S%2Sohyyrgvaf.zlfcnpr.pbz%2Svaqrk.psz&nq_glcr=grkg&rvq=6083027&rn=0&sez=0&tn_ivq=1579793869.1231365768&tn_fvq=1231365768&tn_uvq=2056210897&synfu=9.0.115&h_u=768&h_j=1024&h_nu=738&h_nj=1024&h_pq=24&h_gm=-480&h_uvf=2&h_wnin=gehr&h_acyht=7&h_azvzr=22'; + var str73 = 'frnepu.zvpebfbsg.pbz'; + var str74 = 'frnepu.zvpebfbsg.pbz/'; + var str75 = 'ZFPhygher=VC=74.125.75.17&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&Pbhagel=IIZ%3Q&SbeprqRkcvengvba=633669340386893867&gvzrMbar=-8&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R%3Q'; + var str76 = 'ZFPhygher=VC=74.125.75.17&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&CersreerqPhygherCraqvat=&Pbhagel=IIZ=&SbeprqRkcvengvba=633669340386893867&gvzrMbar=0&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R='; + function runBlock10() { + for (var i = 0; i < 3; i++) { + '%3Szxg=ra-HF'.replace(re39, ''); + '-8'.replace(re40, ''); + '-8'.replace(re10, ''); + '-8'.replace(re51, ''); + '-8'.replace(re52, ''); + '-8'.replace(re53, ''); + '-8'.replace(re39, ''); + '-8'.replace(re54, ''); + '1.5'.replace(re40, ''); + '1.5'.replace(re10, ''); + '1.5'.replace(re51, ''); + '1.5'.replace(re52, ''); + '1.5'.replace(re53, ''); + '1.5'.replace(re39, ''); + '1.5'.replace(re54, ''); + '1024k768'.replace(re40, ''); + '1024k768'.replace(re10, ''); + '1024k768'.replace(re51, ''); + '1024k768'.replace(re52, ''); + '1024k768'.replace(re53, ''); + '1024k768'.replace(re39, ''); + '1024k768'.replace(re54, ''); + str64.replace(re40, ''); + str64.replace(re10, ''); + str64.replace(re51, ''); + str64.replace(re52, ''); + str64.replace(re53, ''); + str64.replace(re39, ''); + str64.replace(re54, ''); + '14'.replace(re40, ''); + '14'.replace(re10, ''); + '14'.replace(re51, ''); + '14'.replace(re52, ''); + '14'.replace(re53, ''); + '14'.replace(re39, ''); + '14'.replace(re54, ''); + '24'.replace(re40, ''); + '24'.replace(re10, ''); + '24'.replace(re51, ''); + '24'.replace(re52, ''); + '24'.replace(re53, ''); + '24'.replace(re39, ''); + '24'.replace(re54, ''); + str65.replace(re40, ''); + str65.replace(re10, ''); + str65.replace(re51, ''); + str65.replace(re52, ''); + str65.replace(re53, ''); + str65.replace(re39, ''); + str65.replace(re54, ''); + str66.replace(re40, ''); + str66.replace(re10, ''); + str66.replace(re51, ''); + str66.replace(re52, ''); + str66.replace(re53, ''); + str66.replace(re39, ''); + str66.replace(re54, ''); + '9.0'.replace(re40, ''); + '9.0'.replace(re10, ''); + '9.0'.replace(re51, ''); + '9.0'.replace(re52, ''); + '9.0'.replace(re53, ''); + '9.0'.replace(re39, ''); + '9.0'.replace(re54, ''); + '994k634'.replace(re40, ''); + '994k634'.replace(re10, ''); + '994k634'.replace(re51, ''); + '994k634'.replace(re52, ''); + '994k634'.replace(re53, ''); + '994k634'.replace(re39, ''); + '994k634'.replace(re54, ''); + '?zxg=ra-HF'.replace(re40, ''); + '?zxg=ra-HF'.replace(re10, ''); + '?zxg=ra-HF'.replace(re51, ''); + '?zxg=ra-HF'.replace(re52, ''); + '?zxg=ra-HF'.replace(re53, ''); + '?zxg=ra-HF'.replace(re54, ''); + 'PAA.pbz'.replace(re25, ''); + 'PAA.pbz'.replace(re12, ''); + 'PAA.pbz'.replace(re39, ''); + 'Qngr & Gvzr'.replace(re25, ''); + 'Qngr & Gvzr'.replace(re12, ''); + 'Qngr & Gvzr'.replace(re39, ''); + 'Frnepu Zvpebfbsg.pbz'.replace(re40, ''); + 'Frnepu Zvpebfbsg.pbz'.replace(re54, ''); + str67.replace(re10, ''); + str67.replace(re51, ''); + str67.replace(re52, ''); + str67.replace(re53, ''); + str67.replace(re39, ''); + str68.split(re32); + str69.split(re32); + str70.replace(re52, ''); + str70.replace(re53, ''); + str70.replace(re39, ''); + str71.replace(re40, ''); + str71.replace(re10, ''); + str71.replace(re51, ''); + str71.replace(re54, ''); + 'Jrngure'.replace(re25, ''); + 'Jrngure'.replace(re12, ''); + 'Jrngure'.replace(re39, ''); + 'LbhGhor'.replace(re25, ''); + 'LbhGhor'.replace(re12, ''); + 'LbhGhor'.replace(re39, ''); + str72.replace(re33, ''); + 'erzbgr_vsenzr_1'.replace(/^erzbgr_vsenzr_/, ''); + str73.replace(re40, ''); + str73.replace(re10, ''); + str73.replace(re51, ''); + str73.replace(re52, ''); + str73.replace(re53, ''); + str73.replace(re39, ''); + str73.replace(re54, ''); + str74.replace(re40, ''); + str74.replace(re10, ''); + str74.replace(re51, ''); + str74.replace(re52, ''); + str74.replace(re53, ''); + str74.replace(re39, ''); + str74.replace(re54, ''); + 'lhv-h'.replace(/\-/g, ''); + re9.exec('p'); + re9.exec('qz p'); + re9.exec('zbqynory'); + re9.exec('lhv-h svefg'); + re8.exec('144631658.0.10.1231365779'); + re8.exec('144631658.1231365779.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar)'); + re8.exec('144631658.1877536177953918500.1231365779.1231365779.1231365779.1'); + re8.exec(str75); + re8.exec(str76); + re8.exec('__hgzn=144631658.1877536177953918500.1231365779.1231365779.1231365779.1'); + re8.exec('__hgzo=144631658.0.10.1231365779'); + re8.exec('__hgzm=144631658.1231365779.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar)'); + re34.exec(str68); + re34.exec(str69); + /^$/.exec(''); + re31.exec('qr'); + /^znk\d+$/.exec(''); + /^zva\d+$/.exec(''); + /^erfgber$/.exec(''); + re85.exec('zbqobkva zbqobk_abcnqqvat '); + re85.exec('zbqgvgyr'); + re85.exec('eaq_zbqobkva '); + re85.exec('eaq_zbqgvgyr '); + /frpgvba\d+_pbagragf/.exec('obggbz_ani'); + } + } + var re86 = /;\s*/; + var re87 = /(\$\{inyhr\})|(\$inyhr\b)/g; + var re88 = /(\$\{abj\})|(\$abj\b)/g; + var re89 = /\s+$/; + var re90 = /^\s+/; + var re91 = /(\\\"|\x00-|\x1f|\x7f-|\x9f|\u00ad|\u0600-|\u0604|\u070f|\u17b4|\u17b5|\u200c-|\u200f|\u2028-|\u202f|\u2060-|\u206f|\ufeff|\ufff0-|\uffff)/g; + var re92 = /^(:)([\w-]+)\("?'?(.*?(\(.*?\))?[^(]*?)"?'?\)/; + var re93 = /^([:.#]*)((?:[\w\u0128-\uffff*_-]|\\.)+)/; + var re94 = /^(\[) *@?([\w-]+) *([!*$^~=]*) *('?"?)(.*?)\4 *\]/; + var str77 = '#fubhgobk .pybfr'; + var str78 = 'FrffvbaQQS2=102n9o0o9pq60132qn0337rr867p75953502q2s27s2s5r98; ZFPhygher=VC=74.125.75.1&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&CersreerqPhygherCraqvat=&Pbhagel=IIZ=&SbeprqRkcvengvba=633669341278771470&gvzrMbar=0&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R=; AFP_zp_dfctwzssrwh-aowb_80=441326q33660'; + var str79 = 'FrffvbaQQS2=102n9o0o9pq60132qn0337rr867p75953502q2s27s2s5r98; AFP_zp_dfctwzssrwh-aowb_80=441326q33660; __hgzm=144631658.1231365869.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar); __hgzn=144631658.1670816052019209000.1231365869.1231365869.1231365869.1; __hgzo=144631658.0.10.1231365869; __hgzp=144631658; ZFPhygher=VC=74.125.75.1&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&Pbhagel=IIZ%3Q&SbeprqRkcvengvba=633669341278771470&gvzrMbar=-8&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R%3Q'; + var str80 = 'FrffvbaQQS2=9995p6rp12rrnr893334ro7nq70o7p64p69rqn844prs1473; ZFPhygher=VC=74.125.75.1&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&CersreerqPhygherCraqvat=&Pbhagel=IIZ=&SbeprqRkcvengvba=633669350559478880&gvzrMbar=0&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R=; AFP_zp_dfctwzs-aowb_80=441327q73660'; + var str81 = 'FrffvbaQQS2=9995p6rp12rrnr893334ro7nq70o7p64p69rqn844prs1473; AFP_zp_dfctwzs-aowb_80=441327q73660; __hgzm=144631658.1231367054.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar); __hgzn=144631658.1796080716621419500.1231367054.1231367054.1231367054.1; __hgzo=144631658.0.10.1231367054; __hgzp=144631658; ZFPhygher=VC=74.125.75.1&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&Pbhagel=IIZ%3Q&SbeprqRkcvengvba=633669350559478880&gvzrMbar=-8&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R%3Q'; + var str82 = '[glcr=fhozvg]'; + var str83 = 'n.svryqOga,n.svryqOgaPnapry'; + var str84 = 'n.svryqOgaPnapry'; + var str85 = 'oyvpxchaxg'; + var str86 = 'qvi.bow-nppbeqvba qg'; + var str87 = 'uggc://tbbtyrnqf.t.qbhoyrpyvpx.arg/cntrnq/nqf?pyvrag=pn-svz_zlfcnpr_nccf_wf&qg=1231367052227&uy=ra&nqfnsr=uvtu&br=hgs8&ahz_nqf=4&bhgchg=wf&nqgrfg=bss&pbeeryngbe=1231367052227&punaary=svz_zlfcnpr_nccf-pnainf%2Psvz_zlfcnpr_havgrq-fgngrf&hey=uggc%3N%2S%2Scebsvyr.zlfcnpr.pbz%2SZbqhyrf%2SNccyvpngvbaf%2SCntrf%2SPnainf.nfck&nq_glcr=grkg&rvq=6083027&rn=0&sez=1&tn_ivq=716357910.1231367056&tn_fvq=1231367056&tn_uvq=1387206491&synfu=9.0.115&h_u=768&h_j=1024&h_nu=738&h_nj=1024&h_pq=24&h_gm=-480&h_uvf=2&h_wnin=gehr&h_acyht=7&h_azvzr=22'; + var str88 = 'uggc://tbbtyrnqf.t.qbhoyrpyvpx.arg/cntrnq/nqf?pyvrag=pn-svz_zlfcnpr_zlfcnpr-ubzrcntr_wf&qg=1231365851658&uy=ra&nqfnsr=uvtu&br=hgs8&ahz_nqf=4&bhgchg=wf&nqgrfg=bss&pbeeryngbe=1231365851658&punaary=svz_zlfcnpr_ubzrcntr_abgybttrqva%2Psvz_zlfcnpr_aba_HTP%2Psvz_zlfcnpr_havgrq-fgngrf&hey=uggc%3N%2S%2Scebsvyrrqvg.zlfcnpr.pbz%2Svaqrk.psz&nq_glcr=grkg&rvq=6083027&rn=0&sez=0&tn_ivq=1979828129.1231365855&tn_fvq=1231365855&tn_uvq=2085229649&synfu=9.0.115&h_u=768&h_j=1024&h_nu=738&h_nj=1024&h_pq=24&h_gm=-480&h_uvf=2&h_wnin=gehr&h_acyht=7&h_azvzr=22'; + var str89 = 'uggc://zfacbegny.112.2b7.arg/o/ff/zfacbegnyubzr/1/U.7-cqi-2/f55023338617756?[NDO]&aqu=1&g=7%2S0%2S2009%2014%3N12%3N47%203%20480&af=zfacbegny&cntrAnzr=HF%20UCZFSGJ&t=uggc%3N%2S%2Sjjj.zfa.pbz%2S&f=0k0&p=43835816&x=A&oj=994&ou=634&uc=A&{2}&[NDR]'; + var str90 = 'zrgn[anzr=nwnkHey]'; + var str91 = 'anpuevpugra'; + var str92 = 'b oS={\'oT\':1.1};x $8n(B){z(B!=o9)};x $S(B){O(!$8n(B))z A;O(B.4L)z\'T\';b S=7t B;O(S==\'2P\'&&B.p4){23(B.7f){12 1:z\'T\';12 3:z/\S/.2g(B.8M)?\'ox\':\'oh\'}}O(S==\'2P\'||S==\'x\'){23(B.nE){12 2V:z\'1O\';12 7I:z\'5a\';12 18:z\'4B\'}O(7t B.I==\'4F\'){O(B.3u)z\'pG\';O(B.8e)z\'1p\'}}z S};x $2p(){b 4E={};Z(b v=0;v<1p.I;v++){Z(b X 1o 1p[v]){b nc=1p[v][X];b 6E=4E[X];O(6E&&$S(nc)==\'2P\'&&$S(6E)==\'2P\')4E[X]=$2p(6E,nc);17 4E[X]=nc}}z 4E};b $E=7p.E=x(){b 1d=1p;O(!1d[1])1d=[p,1d[0]];Z(b X 1o 1d[1])1d[0][X]=1d[1][X];z 1d[0]};b $4D=7p.pJ=x(){Z(b v=0,y=1p.I;v-1:p.3F(2R)>-1},nX:x(){z p.3y(/([.*+?^${}()|[\]\/\\])/t,\'\\$1\')}});2V.E({5V:x(1O){O(p.I<3)z A;O(p.I==4&&p[3]==0&&!1O)z\'p5\';b 3P=[];Z(b v=0;v<3;v++){b 52=(p[v]-0).4h(16);3P.1x((52.I==1)?\'0\'+52:52)}z 1O?3P:\'#\'+3P.2u(\'\')},5U:x(1O){O(p.I!=3)z A;b 1i=[];Z(b v=0;v<3;v++){1i.1x(5K((p[v].I==1)?p[v]+p[v]:p[v],16))}z 1O?1i:\'1i(\'+1i.2u(\',\')+\')\'}});7F.E({3n:x(P){b J=p;P=$2p({\'L\':J,\'V\':A,\'1p\':1S,\'2x\':A,\'4s\':A,\'6W\':A},P);O($2O(P.1p)&&$S(P.1p)!=\'1O\')P.1p=[P.1p];z x(V){b 1d;O(P.V){V=V||H.V;1d=[(P.V===1r)?V:Y P.V(V)];O(P.1p)1d.E(P.1p)}17 1d=P.1p||1p;b 3C=x(){z J.3H($5S(P'; + var str93 = 'hagreunyghat'; + var str94 = 'ZFPhygher=VC=74.125.75.1&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&Pbhagel=IIZ%3Q&SbeprqRkcvengvba=633669341278771470&gvzrMbar=-8&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R%3Q'; + var str95 = 'ZFPhygher=VC=74.125.75.1&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&Pbhagel=IIZ%3Q&SbeprqRkcvengvba=633669350559478880&gvzrMbar=-8&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R%3Q'; + var str96 = 'ZFPhygher=VC=74.125.75.1&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&CersreerqPhygherCraqvat=&Pbhagel=IIZ=&SbeprqRkcvengvba=633669341278771470&gvzrMbar=0&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R='; + var str97 = 'ZFPhygher=VC=74.125.75.1&VCPhygher=ra-HF&CersreerqPhygher=ra-HF&CersreerqPhygherCraqvat=&Pbhagel=IIZ=&SbeprqRkcvengvba=633669350559478880&gvzrMbar=0&HFEYBP=DKWyLHAiMTH9AwHjWxAcqUx9GJ91oaEunJ4tIzyyqlMQo3IhqUW5D29xMG1IHlMQo3IhqUW5GzSgMG1Iozy0MJDtH3EuqTImWxEgLHAiMTH9BQN3WxkuqTy0qJEyCGZ3YwDkBGVzGT9hM2y0qJEyCF0kZwVhZQH3APMDo3A0LJkQo2EyCGx0ZQDmWyWyM2yiox5uoJH9D0R='; + var str98 = 'shapgvba (){Cuk.Nccyvpngvba.Frghc.Pber();Cuk.Nccyvpngvba.Frghc.Nwnk();Cuk.Nccyvpngvba.Frghc.Synfu();Cuk.Nccyvpngvba.Frghc.Zbqhyrf()}'; + function runBlock11() { + for (var i = 0; i < 2; i++) { + ' .pybfr'.replace(re18, ''); + ' n.svryqOgaPnapry'.replace(re18, ''); + ' qg'.replace(re18, ''); + str77.replace(re68, ''); + str77.replace(re18, ''); + ''.replace(re39, ''); + ''.replace(/^/, ''); + ''.split(re86); + '*'.replace(re39, ''); + '*'.replace(re68, ''); + '*'.replace(re18, ''); + '.pybfr'.replace(re68, ''); + '.pybfr'.replace(re18, ''); + '//vzt.jro.qr/vij/FC/tzk_uc/fperra/${inyhr}?gf=${abj}'.replace(re87, ''); + '//vzt.jro.qr/vij/FC/tzk_uc/fperra/1024?gf=${abj}'.replace(re88, ''); + '//vzt.jro.qr/vij/FC/tzk_uc/jvafvmr/${inyhr}?gf=${abj}'.replace(re87, ''); + '//vzt.jro.qr/vij/FC/tzk_uc/jvafvmr/992/608?gf=${abj}'.replace(re88, ''); + '300k120'.replace(re30, ''); + '300k250'.replace(re30, ''); + '310k120'.replace(re30, ''); + '310k170'.replace(re30, ''); + '310k250'.replace(re30, ''); + '9.0 e115'.replace(/^.*\.(.*)\s.*$/, ''); + 'Nppbeqvba'.replace(re2, ''); + 'Nxghryy\x0a'.replace(re89, ''); + 'Nxghryy\x0a'.replace(re90, ''); + 'Nccyvpngvba'.replace(re2, ''); + 'Oyvpxchaxg\x0a'.replace(re89, ''); + 'Oyvpxchaxg\x0a'.replace(re90, ''); + 'Svanamra\x0a'.replace(re89, ''); + 'Svanamra\x0a'.replace(re90, ''); + 'Tnzrf\x0a'.replace(re89, ''); + 'Tnzrf\x0a'.replace(re90, ''); + 'Ubebfxbc\x0a'.replace(re89, ''); + 'Ubebfxbc\x0a'.replace(re90, ''); + 'Xvab\x0a'.replace(re89, ''); + 'Xvab\x0a'.replace(re90, ''); + 'Zbqhyrf'.replace(re2, ''); + 'Zhfvx\x0a'.replace(re89, ''); + 'Zhfvx\x0a'.replace(re90, ''); + 'Anpuevpugra\x0a'.replace(re89, ''); + 'Anpuevpugra\x0a'.replace(re90, ''); + 'Cuk'.replace(re2, ''); + 'ErdhrfgSvavfu'.split(re70); + 'ErdhrfgSvavfu.NWNK.Cuk'.split(re70); + 'Ebhgr\x0a'.replace(re89, ''); + 'Ebhgr\x0a'.replace(re90, ''); + str78.split(re32); + str79.split(re32); + str80.split(re32); + str81.split(re32); + 'Fcbeg\x0a'.replace(re89, ''); + 'Fcbeg\x0a'.replace(re90, ''); + 'GI-Fcbg\x0a'.replace(re89, ''); + 'GI-Fcbg\x0a'.replace(re90, ''); + 'Gbhe\x0a'.replace(re89, ''); + 'Gbhe\x0a'.replace(re90, ''); + 'Hagreunyghat\x0a'.replace(re89, ''); + 'Hagreunyghat\x0a'.replace(re90, ''); + 'Ivqrb\x0a'.replace(re89, ''); + 'Ivqrb\x0a'.replace(re90, ''); + 'Jrggre\x0a'.replace(re89, ''); + 'Jrggre\x0a'.replace(re90, ''); + str82.replace(re68, ''); + str82.replace(re18, ''); + str83.replace(re68, ''); + str83.replace(re18, ''); + str84.replace(re68, ''); + str84.replace(re18, ''); + 'nqiFreivprObk'.replace(re30, ''); + 'nqiFubccvatObk'.replace(re30, ''); + 'nwnk'.replace(re39, ''); + 'nxghryy'.replace(re40, ''); + 'nxghryy'.replace(re41, ''); + 'nxghryy'.replace(re42, ''); + 'nxghryy'.replace(re43, ''); + 'nxghryy'.replace(re44, ''); + 'nxghryy'.replace(re45, ''); + 'nxghryy'.replace(re46, ''); + 'nxghryy'.replace(re47, ''); + 'nxghryy'.replace(re48, ''); + str85.replace(re40, ''); + str85.replace(re41, ''); + str85.replace(re42, ''); + str85.replace(re43, ''); + str85.replace(re44, ''); + str85.replace(re45, ''); + str85.replace(re46, ''); + str85.replace(re47, ''); + str85.replace(re48, ''); + 'pngrtbel'.replace(re29, ''); + 'pngrtbel'.replace(re30, ''); + 'pybfr'.replace(re39, ''); + 'qvi'.replace(re39, ''); + str86.replace(re68, ''); + str86.replace(re18, ''); + 'qg'.replace(re39, ''); + 'qg'.replace(re68, ''); + 'qg'.replace(re18, ''); + 'rzorq'.replace(re39, ''); + 'rzorq'.replace(re68, ''); + 'rzorq'.replace(re18, ''); + 'svryqOga'.replace(re39, ''); + 'svryqOgaPnapry'.replace(re39, ''); + 'svz_zlfcnpr_nccf-pnainf,svz_zlfcnpr_havgrq-fgngrf'.split(re20); + 'svanamra'.replace(re40, ''); + 'svanamra'.replace(re41, ''); + 'svanamra'.replace(re42, ''); + 'svanamra'.replace(re43, ''); + 'svanamra'.replace(re44, ''); + 'svanamra'.replace(re45, ''); + 'svanamra'.replace(re46, ''); + 'svanamra'.replace(re47, ''); + 'svanamra'.replace(re48, ''); + 'sbphf'.split(re70); + 'sbphf.gno sbphfva.gno'.split(re70); + 'sbphfva'.split(re70); + 'sbez'.replace(re39, ''); + 'sbez.nwnk'.replace(re68, ''); + 'sbez.nwnk'.replace(re18, ''); + 'tnzrf'.replace(re40, ''); + 'tnzrf'.replace(re41, ''); + 'tnzrf'.replace(re42, ''); + 'tnzrf'.replace(re43, ''); + 'tnzrf'.replace(re44, ''); + 'tnzrf'.replace(re45, ''); + 'tnzrf'.replace(re46, ''); + 'tnzrf'.replace(re47, ''); + 'tnzrf'.replace(re48, ''); + 'ubzrcntr'.replace(re30, ''); + 'ubebfxbc'.replace(re40, ''); + 'ubebfxbc'.replace(re41, ''); + 'ubebfxbc'.replace(re42, ''); + 'ubebfxbc'.replace(re43, ''); + 'ubebfxbc'.replace(re44, ''); + 'ubebfxbc'.replace(re45, ''); + 'ubebfxbc'.replace(re46, ''); + 'ubebfxbc'.replace(re47, ''); + 'ubebfxbc'.replace(re48, ''); + 'uc_cebzbobk_ugzy%2Puc_cebzbobk_vzt'.replace(re30, ''); + 'uc_erpgnatyr'.replace(re30, ''); + str87.replace(re33, ''); + str88.replace(re33, ''); + 'uggc://wf.hv-cbegny.qr/tzk/ubzr/wf/20080602/onfr.wf${4}${5}'.replace(re71, ''); + 'uggc://wf.hv-cbegny.qr/tzk/ubzr/wf/20080602/onfr.wf${5}'.replace(re72, ''); + 'uggc://wf.hv-cbegny.qr/tzk/ubzr/wf/20080602/qlaYvo.wf${4}${5}'.replace(re71, ''); + 'uggc://wf.hv-cbegny.qr/tzk/ubzr/wf/20080602/qlaYvo.wf${5}'.replace(re72, ''); + 'uggc://wf.hv-cbegny.qr/tzk/ubzr/wf/20080602/rssrpgYvo.wf${4}${5}'.replace(re71, ''); + 'uggc://wf.hv-cbegny.qr/tzk/ubzr/wf/20080602/rssrpgYvo.wf${5}'.replace(re72, ''); + str89.replace(re73, ''); + 'uggc://zfacbegny.112.2b7.arg/o/ff/zfacbegnyubzr/1/U.7-cqi-2/f55023338617756?[NDO]&{1}&{2}&[NDR]'.replace(re69, ''); + str6.replace(re23, ''); + 'xvab'.replace(re40, ''); + 'xvab'.replace(re41, ''); + 'xvab'.replace(re42, ''); + 'xvab'.replace(re43, ''); + 'xvab'.replace(re44, ''); + 'xvab'.replace(re45, ''); + 'xvab'.replace(re46, ''); + 'xvab'.replace(re47, ''); + 'xvab'.replace(re48, ''); + 'ybnq'.split(re70); + 'zrqvnzbqgno lhv-anifrg lhv-anifrg-gbc'.replace(re18, ''); + 'zrgn'.replace(re39, ''); + str90.replace(re68, ''); + str90.replace(re18, ''); + 'zbhfrzbir'.split(re70); + 'zbhfrzbir.gno'.split(re70); + str63.replace(/^.*jroxvg\/(\d+(\.\d+)?).*$/, ''); + 'zhfvx'.replace(re40, ''); + 'zhfvx'.replace(re41, ''); + 'zhfvx'.replace(re42, ''); + 'zhfvx'.replace(re43, ''); + 'zhfvx'.replace(re44, ''); + 'zhfvx'.replace(re45, ''); + 'zhfvx'.replace(re46, ''); + 'zhfvx'.replace(re47, ''); + 'zhfvx'.replace(re48, ''); + 'zlfcnpr_nccf_pnainf'.replace(re52, ''); + str91.replace(re40, ''); + str91.replace(re41, ''); + str91.replace(re42, ''); + str91.replace(re43, ''); + str91.replace(re44, ''); + str91.replace(re45, ''); + str91.replace(re46, ''); + str91.replace(re47, ''); + str91.replace(re48, ''); + 'anzr'.replace(re39, ''); + str92.replace(/\b\w+\b/g, ''); + 'bow-nppbeqvba'.replace(re39, ''); + 'bowrpg'.replace(re39, ''); + 'bowrpg'.replace(re68, ''); + 'bowrpg'.replace(re18, ''); + 'cnenzf%2Rfglyrf'.replace(re29, ''); + 'cnenzf%2Rfglyrf'.replace(re30, ''); + 'cbchc'.replace(re30, ''); + 'ebhgr'.replace(re40, ''); + 'ebhgr'.replace(re41, ''); + 'ebhgr'.replace(re42, ''); + 'ebhgr'.replace(re43, ''); + 'ebhgr'.replace(re44, ''); + 'ebhgr'.replace(re45, ''); + 'ebhgr'.replace(re46, ''); + 'ebhgr'.replace(re47, ''); + 'ebhgr'.replace(re48, ''); + 'freivprobk_uc'.replace(re30, ''); + 'fubccvatobk_uc'.replace(re30, ''); + 'fubhgobk'.replace(re39, ''); + 'fcbeg'.replace(re40, ''); + 'fcbeg'.replace(re41, ''); + 'fcbeg'.replace(re42, ''); + 'fcbeg'.replace(re43, ''); + 'fcbeg'.replace(re44, ''); + 'fcbeg'.replace(re45, ''); + 'fcbeg'.replace(re46, ''); + 'fcbeg'.replace(re47, ''); + 'fcbeg'.replace(re48, ''); + 'gbhe'.replace(re40, ''); + 'gbhe'.replace(re41, ''); + 'gbhe'.replace(re42, ''); + 'gbhe'.replace(re43, ''); + 'gbhe'.replace(re44, ''); + 'gbhe'.replace(re45, ''); + 'gbhe'.replace(re46, ''); + 'gbhe'.replace(re47, ''); + 'gbhe'.replace(re48, ''); + 'gi-fcbg'.replace(re40, ''); + 'gi-fcbg'.replace(re41, ''); + 'gi-fcbg'.replace(re42, ''); + 'gi-fcbg'.replace(re43, ''); + 'gi-fcbg'.replace(re44, ''); + 'gi-fcbg'.replace(re45, ''); + 'gi-fcbg'.replace(re46, ''); + 'gi-fcbg'.replace(re47, ''); + 'gi-fcbg'.replace(re48, ''); + 'glcr'.replace(re39, ''); + 'haqrsvarq'.replace(/\//g, ''); + str93.replace(re40, ''); + str93.replace(re41, ''); + str93.replace(re42, ''); + str93.replace(re43, ''); + str93.replace(re44, ''); + str93.replace(re45, ''); + str93.replace(re46, ''); + str93.replace(re47, ''); + str93.replace(re48, ''); + 'ivqrb'.replace(re40, ''); + 'ivqrb'.replace(re41, ''); + 'ivqrb'.replace(re42, ''); + 'ivqrb'.replace(re43, ''); + 'ivqrb'.replace(re44, ''); + 'ivqrb'.replace(re45, ''); + 'ivqrb'.replace(re46, ''); + 'ivqrb'.replace(re47, ''); + 'ivqrb'.replace(re48, ''); + 'ivfvgf=1'.split(re86); + 'jrggre'.replace(re40, ''); + 'jrggre'.replace(re41, ''); + 'jrggre'.replace(re42, ''); + 'jrggre'.replace(re43, ''); + 'jrggre'.replace(re44, ''); + 'jrggre'.replace(re45, ''); + 'jrggre'.replace(re46, ''); + 'jrggre'.replace(re47, ''); + 'jrggre'.replace(re48, ''); + /#[a-z0-9]+$/i.exec('uggc://jjj.fpuhryreim.arg/Qrsnhyg'); + re66.exec('fryrpgrq'); + /(?:^|\s+)lhv-ani(?:\s+|$)/.exec('sff lhv-ani'); + /(?:^|\s+)lhv-anifrg(?:\s+|$)/.exec('zrqvnzbqgno lhv-anifrg'); + /(?:^|\s+)lhv-anifrg-gbc(?:\s+|$)/.exec('zrqvnzbqgno lhv-anifrg'); + re91.exec('GnoThvq'); + re91.exec('thvq'); + /(pbzcngvoyr|jroxvg)/.exec(str63); + /.+(?:ei|vg|en|vr)[\/: ]([\d.]+)/.exec(str63); + re8.exec('144631658.0.10.1231365869'); + re8.exec('144631658.0.10.1231367054'); + re8.exec('144631658.1231365869.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar)'); + re8.exec('144631658.1231367054.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar)'); + re8.exec('144631658.1670816052019209000.1231365869.1231365869.1231365869.1'); + re8.exec('144631658.1796080716621419500.1231367054.1231367054.1231367054.1'); + re8.exec(str94); + re8.exec(str95); + re8.exec(str96); + re8.exec(str97); + re8.exec('__hgzn=144631658.1670816052019209000.1231365869.1231365869.1231365869.1'); + re8.exec('__hgzn=144631658.1796080716621419500.1231367054.1231367054.1231367054.1'); + re8.exec('__hgzo=144631658.0.10.1231365869'); + re8.exec('__hgzo=144631658.0.10.1231367054'); + re8.exec('__hgzm=144631658.1231365869.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar)'); + re8.exec('__hgzm=144631658.1231367054.1.1.hgzpfe=(qverpg)|hgzppa=(qverpg)|hgzpzq=(abar)'); + re34.exec(str78); + re34.exec(str79); + re34.exec(str81); + re74.exec(str77); + re74.exec('*'); + re74.exec(str82); + re74.exec(str83); + re74.exec(str86); + re74.exec('rzorq'); + re74.exec('sbez.nwnk'); + re74.exec(str90); + re74.exec('bowrpg'); + /\/onfr.wf(\?.+)?$/.exec('/uggc://wf.hv-cbegny.qr/tzk/ubzr/wf/20080602/onfr.wf'); + re28.exec('uvag ynfgUvag ynfg'); + re75.exec(''); + re76.exec(''); + re77.exec(''); + re78.exec(''); + re80.exec(str77); + re80.exec('*'); + re80.exec('.pybfr'); + re80.exec(str82); + re80.exec(str83); + re80.exec(str84); + re80.exec(str86); + re80.exec('qg'); + re80.exec('rzorq'); + re80.exec('sbez.nwnk'); + re80.exec(str90); + re80.exec('bowrpg'); + re61.exec('qlaYvo.wf'); + re61.exec('rssrpgYvo.wf'); + re61.exec('uggc://jjj.tzk.arg/qr/?fgnghf=uvajrvf'); + re92.exec(' .pybfr'); + re92.exec(' n.svryqOgaPnapry'); + re92.exec(' qg'); + re92.exec(str48); + re92.exec('.nwnk'); + re92.exec('.svryqOga,n.svryqOgaPnapry'); + re92.exec('.svryqOgaPnapry'); + re92.exec('.bow-nppbeqvba qg'); + re68.exec(str77); + re68.exec('*'); + re68.exec('.pybfr'); + re68.exec(str82); + re68.exec(str83); + re68.exec(str84); + re68.exec(str86); + re68.exec('qg'); + re68.exec('rzorq'); + re68.exec('sbez.nwnk'); + re68.exec(str90); + re68.exec('bowrpg'); + re93.exec(' .pybfr'); + re93.exec(' n.svryqOgaPnapry'); + re93.exec(' qg'); + re93.exec(str48); + re93.exec('.nwnk'); + re93.exec('.svryqOga,n.svryqOgaPnapry'); + re93.exec('.svryqOgaPnapry'); + re93.exec('.bow-nppbeqvba qg'); + re81.exec(str77); + re81.exec('*'); + re81.exec(str48); + re81.exec('.pybfr'); + re81.exec(str82); + re81.exec(str83); + re81.exec(str84); + re81.exec(str86); + re81.exec('qg'); + re81.exec('rzorq'); + re81.exec('sbez.nwnk'); + re81.exec(str90); + re81.exec('bowrpg'); + re94.exec(' .pybfr'); + re94.exec(' n.svryqOgaPnapry'); + re94.exec(' qg'); + re94.exec(str48); + re94.exec('.nwnk'); + re94.exec('.svryqOga,n.svryqOgaPnapry'); + re94.exec('.svryqOgaPnapry'); + re94.exec('.bow-nppbeqvba qg'); + re94.exec('[anzr=nwnkHey]'); + re94.exec(str82); + re31.exec('rf'); + re31.exec('wn'); + re82.exec(str77); + re82.exec('*'); + re82.exec(str48); + re82.exec('.pybfr'); + re82.exec(str82); + re82.exec(str83); + re82.exec(str84); + re82.exec(str86); + re82.exec('qg'); + re82.exec('rzorq'); + re82.exec('sbez.nwnk'); + re82.exec(str90); + re82.exec('bowrpg'); + re83.exec(str98); + re83.exec('shapgvba sbphf() { [angvir pbqr] }'); + re62.exec('#Ybtva'); + re62.exec('#Ybtva_cnffjbeq'); + re62.exec(str77); + re62.exec('#fubhgobkWf'); + re62.exec('#fubhgobkWfReebe'); + re62.exec('#fubhgobkWfFhpprff'); + re62.exec('*'); + re62.exec(str82); + re62.exec(str83); + re62.exec(str86); + re62.exec('rzorq'); + re62.exec('sbez.nwnk'); + re62.exec(str90); + re62.exec('bowrpg'); + re49.exec('pbagrag'); + re24.exec(str6); + /xbadhrebe/.exec(str63); + /znp/.exec('jva32'); + /zbmvyyn/.exec(str63); + /zfvr/.exec(str63); + /ag\s5\.1/.exec(str63); + /bcren/.exec(str63); + /fnsnev/.exec(str63); + /jva/.exec('jva32'); + /jvaqbjf/.exec(str63); + } + } + for (var i = 0; i < 5; i++) { + runBlock0(); + runBlock1(); + runBlock2(); + runBlock3(); + runBlock4(); + runBlock5(); + runBlock6(); + runBlock7(); + runBlock8(); + runBlock9(); + runBlock10(); + runBlock11(); + } +} diff --git a/deps/v8/benchmarks/revisions.html b/deps/v8/benchmarks/revisions.html new file mode 100644 index 0000000000..bba53dc60b --- /dev/null +++ b/deps/v8/benchmarks/revisions.html @@ -0,0 +1,62 @@ + + +V8 Benchmark Suite Revisions + + + +
+

V8 Benchmark Suite Revisions

+ + +
+ +

+ +The V8 benchmark suite is changed from time to time as we fix bugs or +expand the scope of the benchmarks. Here is a list of revisions, with +a description of the changes made. Note that benchmark results are +not comparable unless both results are run with the same revision of +the benchmark suite. + +

+ +

Version 3 (link)

+ +

Version 3 adds a new benchmark, RegExp. The RegExp +benchmark is generated by loading 50 of the most popular pages on the +web and logging all regexp operations performed. Each operation is +given a weight that is calculated from an estimate of the popularity +of the pages where it occurs and the number of times it is executed +while loading each page. Finally the literal letters in the data are +encoded using ROT13 in a way that does not affect how the regexps +match their input. +

+ +

Version 2 (link)

+ +

For version 2 the crypto benchmark was fixed. Previously, the +decryption stage was given plaintext as input, which resulted in an +error. Now, the decryption stage is given the output of the +encryption stage as input. The result is checked against the original +plaintext. For this to give the correct results the crypto objects +are reset for each iteration of the benchmark. In addition, the size +of the plain text has been increased a little and the use of +Math.random() and new Date() to build an RNG pool has been +removed.

+ +

Other benchmarks were fixed to do elementary verification of the +results of their calculations. This is to avoid accidentally +obtaining scores that are the result of an incorrect JavaScript engine +optimization.

+ +

Version 1 (link)

+ +

Initial release.

+ +
+
+ +
+ + + diff --git a/deps/v8/benchmarks/richards.js b/deps/v8/benchmarks/richards.js new file mode 100644 index 0000000000..bb88623cdf --- /dev/null +++ b/deps/v8/benchmarks/richards.js @@ -0,0 +1,539 @@ +// Copyright 2006-2008 the V8 project 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. + + +// This is a JavaScript implementation of the Richards +// benchmark from: +// +// http://www.cl.cam.ac.uk/~mr10/Bench.html +// +// The benchmark was originally implemented in BCPL by +// Martin Richards. + + +var Richards = new BenchmarkSuite('Richards', 34886, [ + new Benchmark("Richards", runRichards) +]); + + +/** + * The Richards benchmark simulates the task dispatcher of an + * operating system. + **/ +function runRichards() { + var scheduler = new Scheduler(); + scheduler.addIdleTask(ID_IDLE, 0, null, COUNT); + + var queue = new Packet(null, ID_WORKER, KIND_WORK); + queue = new Packet(queue, ID_WORKER, KIND_WORK); + scheduler.addWorkerTask(ID_WORKER, 1000, queue); + + queue = new Packet(null, ID_DEVICE_A, KIND_DEVICE); + queue = new Packet(queue, ID_DEVICE_A, KIND_DEVICE); + queue = new Packet(queue, ID_DEVICE_A, KIND_DEVICE); + scheduler.addHandlerTask(ID_HANDLER_A, 2000, queue); + + queue = new Packet(null, ID_DEVICE_B, KIND_DEVICE); + queue = new Packet(queue, ID_DEVICE_B, KIND_DEVICE); + queue = new Packet(queue, ID_DEVICE_B, KIND_DEVICE); + scheduler.addHandlerTask(ID_HANDLER_B, 3000, queue); + + scheduler.addDeviceTask(ID_DEVICE_A, 4000, null); + + scheduler.addDeviceTask(ID_DEVICE_B, 5000, null); + + scheduler.schedule(); + + if (scheduler.queueCount != EXPECTED_QUEUE_COUNT || + scheduler.holdCount != EXPECTED_HOLD_COUNT) { + var msg = + "Error during execution: queueCount = " + scheduler.queueCount + + ", holdCount = " + scheduler.holdCount + "."; + throw new Error(msg); + } +} + +var COUNT = 1000; + +/** + * These two constants specify how many times a packet is queued and + * how many times a task is put on hold in a correct run of richards. + * They don't have any meaning a such but are characteristic of a + * correct run so if the actual queue or hold count is different from + * the expected there must be a bug in the implementation. + **/ +var EXPECTED_QUEUE_COUNT = 2322; +var EXPECTED_HOLD_COUNT = 928; + + +/** + * A scheduler can be used to schedule a set of tasks based on their relative + * priorities. Scheduling is done by maintaining a list of task control blocks + * which holds tasks and the data queue they are processing. + * @constructor + */ +function Scheduler() { + this.queueCount = 0; + this.holdCount = 0; + this.blocks = new Array(NUMBER_OF_IDS); + this.list = null; + this.currentTcb = null; + this.currentId = null; +} + +var ID_IDLE = 0; +var ID_WORKER = 1; +var ID_HANDLER_A = 2; +var ID_HANDLER_B = 3; +var ID_DEVICE_A = 4; +var ID_DEVICE_B = 5; +var NUMBER_OF_IDS = 6; + +var KIND_DEVICE = 0; +var KIND_WORK = 1; + +/** + * Add an idle task to this scheduler. + * @param {int} id the identity of the task + * @param {int} priority the task's priority + * @param {Packet} queue the queue of work to be processed by the task + * @param {int} count the number of times to schedule the task + */ +Scheduler.prototype.addIdleTask = function (id, priority, queue, count) { + this.addRunningTask(id, priority, queue, new IdleTask(this, 1, count)); +}; + +/** + * Add a work task to this scheduler. + * @param {int} id the identity of the task + * @param {int} priority the task's priority + * @param {Packet} queue the queue of work to be processed by the task + */ +Scheduler.prototype.addWorkerTask = function (id, priority, queue) { + this.addTask(id, priority, queue, new WorkerTask(this, ID_HANDLER_A, 0)); +}; + +/** + * Add a handler task to this scheduler. + * @param {int} id the identity of the task + * @param {int} priority the task's priority + * @param {Packet} queue the queue of work to be processed by the task + */ +Scheduler.prototype.addHandlerTask = function (id, priority, queue) { + this.addTask(id, priority, queue, new HandlerTask(this)); +}; + +/** + * Add a handler task to this scheduler. + * @param {int} id the identity of the task + * @param {int} priority the task's priority + * @param {Packet} queue the queue of work to be processed by the task + */ +Scheduler.prototype.addDeviceTask = function (id, priority, queue) { + this.addTask(id, priority, queue, new DeviceTask(this)) +}; + +/** + * Add the specified task and mark it as running. + * @param {int} id the identity of the task + * @param {int} priority the task's priority + * @param {Packet} queue the queue of work to be processed by the task + * @param {Task} task the task to add + */ +Scheduler.prototype.addRunningTask = function (id, priority, queue, task) { + this.addTask(id, priority, queue, task); + this.currentTcb.setRunning(); +}; + +/** + * Add the specified task to this scheduler. + * @param {int} id the identity of the task + * @param {int} priority the task's priority + * @param {Packet} queue the queue of work to be processed by the task + * @param {Task} task the task to add + */ +Scheduler.prototype.addTask = function (id, priority, queue, task) { + this.currentTcb = new TaskControlBlock(this.list, id, priority, queue, task); + this.list = this.currentTcb; + this.blocks[id] = this.currentTcb; +}; + +/** + * Execute the tasks managed by this scheduler. + */ +Scheduler.prototype.schedule = function () { + this.currentTcb = this.list; + while (this.currentTcb != null) { + if (this.currentTcb.isHeldOrSuspended()) { + this.currentTcb = this.currentTcb.link; + } else { + this.currentId = this.currentTcb.id; + this.currentTcb = this.currentTcb.run(); + } + } +}; + +/** + * Release a task that is currently blocked and return the next block to run. + * @param {int} id the id of the task to suspend + */ +Scheduler.prototype.release = function (id) { + var tcb = this.blocks[id]; + if (tcb == null) return tcb; + tcb.markAsNotHeld(); + if (tcb.priority > this.currentTcb.priority) { + return tcb; + } else { + return this.currentTcb; + } +}; + +/** + * Block the currently executing task and return the next task control block + * to run. The blocked task will not be made runnable until it is explicitly + * released, even if new work is added to it. + */ +Scheduler.prototype.holdCurrent = function () { + this.holdCount++; + this.currentTcb.markAsHeld(); + return this.currentTcb.link; +}; + +/** + * Suspend the currently executing task and return the next task control block + * to run. If new work is added to the suspended task it will be made runnable. + */ +Scheduler.prototype.suspendCurrent = function () { + this.currentTcb.markAsSuspended(); + return this.currentTcb; +}; + +/** + * Add the specified packet to the end of the worklist used by the task + * associated with the packet and make the task runnable if it is currently + * suspended. + * @param {Packet} packet the packet to add + */ +Scheduler.prototype.queue = function (packet) { + var t = this.blocks[packet.id]; + if (t == null) return t; + this.queueCount++; + packet.link = null; + packet.id = this.currentId; + return t.checkPriorityAdd(this.currentTcb, packet); +}; + +/** + * A task control block manages a task and the queue of work packages associated + * with it. + * @param {TaskControlBlock} link the preceding block in the linked block list + * @param {int} id the id of this block + * @param {int} priority the priority of this block + * @param {Packet} queue the queue of packages to be processed by the task + * @param {Task} task the task + * @constructor + */ +function TaskControlBlock(link, id, priority, queue, task) { + this.link = link; + this.id = id; + this.priority = priority; + this.queue = queue; + this.task = task; + if (queue == null) { + this.state = STATE_SUSPENDED; + } else { + this.state = STATE_SUSPENDED_RUNNABLE; + } +} + +/** + * The task is running and is currently scheduled. + */ +var STATE_RUNNING = 0; + +/** + * The task has packets left to process. + */ +var STATE_RUNNABLE = 1; + +/** + * The task is not currently running. The task is not blocked as such and may +* be started by the scheduler. + */ +var STATE_SUSPENDED = 2; + +/** + * The task is blocked and cannot be run until it is explicitly released. + */ +var STATE_HELD = 4; + +var STATE_SUSPENDED_RUNNABLE = STATE_SUSPENDED | STATE_RUNNABLE; +var STATE_NOT_HELD = ~STATE_HELD; + +TaskControlBlock.prototype.setRunning = function () { + this.state = STATE_RUNNING; +}; + +TaskControlBlock.prototype.markAsNotHeld = function () { + this.state = this.state & STATE_NOT_HELD; +}; + +TaskControlBlock.prototype.markAsHeld = function () { + this.state = this.state | STATE_HELD; +}; + +TaskControlBlock.prototype.isHeldOrSuspended = function () { + return (this.state & STATE_HELD) != 0 || (this.state == STATE_SUSPENDED); +}; + +TaskControlBlock.prototype.markAsSuspended = function () { + this.state = this.state | STATE_SUSPENDED; +}; + +TaskControlBlock.prototype.markAsRunnable = function () { + this.state = this.state | STATE_RUNNABLE; +}; + +/** + * Runs this task, if it is ready to be run, and returns the next task to run. + */ +TaskControlBlock.prototype.run = function () { + var packet; + if (this.state == STATE_SUSPENDED_RUNNABLE) { + packet = this.queue; + this.queue = packet.link; + if (this.queue == null) { + this.state = STATE_RUNNING; + } else { + this.state = STATE_RUNNABLE; + } + } else { + packet = null; + } + return this.task.run(packet); +}; + +/** + * Adds a packet to the worklist of this block's task, marks this as runnable if + * necessary, and returns the next runnable object to run (the one + * with the highest priority). + */ +TaskControlBlock.prototype.checkPriorityAdd = function (task, packet) { + if (this.queue == null) { + this.queue = packet; + this.markAsRunnable(); + if (this.priority > task.priority) return this; + } else { + this.queue = packet.addTo(this.queue); + } + return task; +}; + +TaskControlBlock.prototype.toString = function () { + return "tcb { " + this.task + "@" + this.state + " }"; +}; + +/** + * An idle task doesn't do any work itself but cycles control between the two + * device tasks. + * @param {Scheduler} scheduler the scheduler that manages this task + * @param {int} v1 a seed value that controls how the device tasks are scheduled + * @param {int} count the number of times this task should be scheduled + * @constructor + */ +function IdleTask(scheduler, v1, count) { + this.scheduler = scheduler; + this.v1 = v1; + this.count = count; +} + +IdleTask.prototype.run = function (packet) { + this.count--; + if (this.count == 0) return this.scheduler.holdCurrent(); + if ((this.v1 & 1) == 0) { + this.v1 = this.v1 >> 1; + return this.scheduler.release(ID_DEVICE_A); + } else { + this.v1 = (this.v1 >> 1) ^ 0xD008; + return this.scheduler.release(ID_DEVICE_B); + } +}; + +IdleTask.prototype.toString = function () { + return "IdleTask" +}; + +/** + * A task that suspends itself after each time it has been run to simulate + * waiting for data from an external device. + * @param {Scheduler} scheduler the scheduler that manages this task + * @constructor + */ +function DeviceTask(scheduler) { + this.scheduler = scheduler; + this.v1 = null; +} + +DeviceTask.prototype.run = function (packet) { + if (packet == null) { + if (this.v1 == null) return this.scheduler.suspendCurrent(); + var v = this.v1; + this.v1 = null; + return this.scheduler.queue(v); + } else { + this.v1 = packet; + return this.scheduler.holdCurrent(); + } +}; + +DeviceTask.prototype.toString = function () { + return "DeviceTask"; +}; + +/** + * A task that manipulates work packets. + * @param {Scheduler} scheduler the scheduler that manages this task + * @param {int} v1 a seed used to specify how work packets are manipulated + * @param {int} v2 another seed used to specify how work packets are manipulated + * @constructor + */ +function WorkerTask(scheduler, v1, v2) { + this.scheduler = scheduler; + this.v1 = v1; + this.v2 = v2; +} + +WorkerTask.prototype.run = function (packet) { + if (packet == null) { + return this.scheduler.suspendCurrent(); + } else { + if (this.v1 == ID_HANDLER_A) { + this.v1 = ID_HANDLER_B; + } else { + this.v1 = ID_HANDLER_A; + } + packet.id = this.v1; + packet.a1 = 0; + for (var i = 0; i < DATA_SIZE; i++) { + this.v2++; + if (this.v2 > 26) this.v2 = 1; + packet.a2[i] = this.v2; + } + return this.scheduler.queue(packet); + } +}; + +WorkerTask.prototype.toString = function () { + return "WorkerTask"; +}; + +/** + * A task that manipulates work packets and then suspends itself. + * @param {Scheduler} scheduler the scheduler that manages this task + * @constructor + */ +function HandlerTask(scheduler) { + this.scheduler = scheduler; + this.v1 = null; + this.v2 = null; +} + +HandlerTask.prototype.run = function (packet) { + if (packet != null) { + if (packet.kind == KIND_WORK) { + this.v1 = packet.addTo(this.v1); + } else { + this.v2 = packet.addTo(this.v2); + } + } + if (this.v1 != null) { + var count = this.v1.a1; + var v; + if (count < DATA_SIZE) { + if (this.v2 != null) { + v = this.v2; + this.v2 = this.v2.link; + v.a1 = this.v1.a2[count]; + this.v1.a1 = count + 1; + return this.scheduler.queue(v); + } + } else { + v = this.v1; + this.v1 = this.v1.link; + return this.scheduler.queue(v); + } + } + return this.scheduler.suspendCurrent(); +}; + +HandlerTask.prototype.toString = function () { + return "HandlerTask"; +}; + +/* --- * + * P a c k e t + * --- */ + +var DATA_SIZE = 4; + +/** + * A simple package of data that is manipulated by the tasks. The exact layout + * of the payload data carried by a packet is not importaint, and neither is the + * nature of the work performed on packets by the tasks. + * + * Besides carrying data, packets form linked lists and are hence used both as + * data and worklists. + * @param {Packet} link the tail of the linked list of packets + * @param {int} id an ID for this packet + * @param {int} kind the type of this packet + * @constructor + */ +function Packet(link, id, kind) { + this.link = link; + this.id = id; + this.kind = kind; + this.a1 = 0; + this.a2 = new Array(DATA_SIZE); +} + +/** + * Add this packet to the end of a worklist, and return the worklist. + * @param {Packet} queue the worklist to add this packet to + */ +Packet.prototype.addTo = function (queue) { + this.link = null; + if (queue == null) return this; + var peek, next = queue; + while ((peek = next.link) != null) + next = peek; + next.link = this; + return queue; +}; + +Packet.prototype.toString = function () { + return "Packet"; +}; diff --git a/deps/v8/benchmarks/run.html b/deps/v8/benchmarks/run.html new file mode 100644 index 0000000000..8663cf10ea --- /dev/null +++ b/deps/v8/benchmarks/run.html @@ -0,0 +1,102 @@ + + +V8 Benchmark Suite + + + + + + + + + + + +
+

V8 Benchmark Suite - version ?

+ + +
+This page contains a suite of pure JavaScript benchmarks that we have +used to tune V8. The final score is computed as the geometric mean of +the individual results to make it independent of the running times of +the individual benchmarks and of a reference system (score +100). Scores are not comparable across benchmark suite versions and +higher scores means better performance: Bigger is better! + +
    +
  • Richards
    OS kernel simulation benchmark, originally written in BCPL by Martin Richards (539 lines).
  • +
  • DeltaBlue
    One-way constraint solver, originally written in Smalltalk by John Maloney and Mario Wolczko (880 lines).
  • +
  • Crypto
    Encryption and decryption benchmark based on code by Tom Wu (1689 lines).
  • +
  • RayTrace
    Ray tracer benchmark based on code by Adam Burmister (3418 lines).
  • +
  • EarleyBoyer
    Classic Scheme benchmarks, translated to JavaScript by Florian Loitsch's Scheme2Js compiler (4682 lines).
  • +
  • RegExp
    Regular expression benchmark generated by extracting regular expression operations from 50 of the most popular web pages +(4758 lines). +
  • +
+ +

+Note that benchmark results are not comparable unless both results are +run with the same revision of the benchmark suite. We will be making +revisions from time to time in order to fix bugs or expand the scope +of the benchmark suite. For previous revisions and the change log see +the revisions page. +

+ +
+
+
Starting...
+
+
+
+
+ +
+ + + diff --git a/deps/v8/benchmarks/run.js b/deps/v8/benchmarks/run.js new file mode 100644 index 0000000000..bdf1fb1ff5 --- /dev/null +++ b/deps/v8/benchmarks/run.js @@ -0,0 +1,60 @@ +// Copyright 2008 the V8 project 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. + + +load('base.js'); +load('richards.js'); +load('deltablue.js'); +load('crypto.js'); +load('raytrace.js'); +load('earley-boyer.js'); +load('regexp.js'); + +var success = true; + +function PrintResult(name, result) { + print(name + ': ' + result); +} + + +function PrintError(name, error) { + PrintResult(name, error); + success = false; +} + + +function PrintScore(score) { + if (success) { + print('----'); + print('Score (version ' + BenchmarkSuite.version + '): ' + score); + } +} + + +BenchmarkSuite.RunSuites({ NotifyResult: PrintResult, + NotifyError: PrintError, + NotifyScore: PrintScore }); diff --git a/deps/v8/benchmarks/style.css b/deps/v8/benchmarks/style.css new file mode 100644 index 0000000000..d976cdd3e7 --- /dev/null +++ b/deps/v8/benchmarks/style.css @@ -0,0 +1,70 @@ +body { + font-family: sans-serif; +} + +hr{ + border: 1px solid; + border-color: #36C; + margin: 1em 0 +} + +h1, h2, h3, h4 { + margin: 0; + margin-bottom: 0; +} + +h1 { + font-size: 190%; + height: 1.2em; +} + + +h2{ + font-size: 140%; + height: 1.2em; +} + +h3{ + font-size: 100%; +} + +li{ + margin: .3em 0 1em 0; +} + +body{ + font-family: Helvetica,Arial,sans-serif; + font-size: small; + color: #000; + background-color: #fff; +} + +div.title { + background-color: rgb(229, 236, 249); + border-top: 1px solid rgb(51, 102, 204); + text-align: center; + padding-top: 0.2em; + padding-bottom: 0.2em; + margin-bottom: 20px; +} + +div.subtitle { + border-bottom: 1px solid rgb(51, 102, 204); + margin-top: 2em; +} + +td.contents { + text-align: start; +} + +div.run { + margin: 20px; + width: 300px; + height: 300px; + float: right; + background-color: rgb(229, 236, 249); + background-image: url(v8-logo.png); + background-position: center center; + background-repeat: no-repeat; + border: 1px solid rgb(51, 102, 204); +} diff --git a/deps/v8/benchmarks/v8-logo.png b/deps/v8/benchmarks/v8-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..91867657f7aa419c355ce4b25667f788905947a4 GIT binary patch literal 24293 zcmV+2Kq9}1P)D)3~444>0B!qZn_~G%G`X z8uin-pVtpD zCR#tQr*S{82fT95lv1LmX(+}>OU^`1L$oXuQzT~{wOvQnT1qL&&o9eD)>?`&5)o0` zw&dLNQ9q6Qc|AnkjA)(szY(2{F+@#6y&K5SGf@b%EDHtiS5Z7S4bAgZQuowTGmd1f zecs@waX+tnN9de05fOzDXibssoEXMD> zr>^Uy4%eys7NY*Vp2q#WzHp_K$a_!Dxe~EMpb!H&TOLbZGUZrmY||8@?Anf8+fs~? zT-%bhmb~|5j9D3I*L4E2`QXV1PxCyHwU$g{sO$TZ%5&O}*TnBR=bi@t!>{H^V!5v| z0}x9oQHqfoV<-e)qAoQ8mMyf9b1g0W^OlXx7;|=djnsagCOS+9{3SK)2=MPq&Sb2m z#16w4L#=B|eb3p0bMA@0KO^_^(&;u*>%@qGet+6?^LvlG z9T{tBVgoOAc%sG_BB1aokuip12t-6QPZL=-=w(@`Ydh-t{vzk{yq?DWPhKGeN^CGW zXG$?j>TJl+LW>xA>soSb$T}rPbk)ZC*{kn+LC|9eN2e2myid-Vh->|(X-e(Szdz3t zlvb*FivuI)-%z8sCGbuAfdCGABjt<&mj7`8lY=g3-1 zEvMc@L?gcsz5^n6&Y67hQj<$Ik`m>rzJFd%&UX9>Dm}QZT-JXKifx+plO;nX|=T2sPx1IsrRl#Y{m+L_tY3eDVIO@oTfjor*Z#N z={6Aw5Y;pd8RsZW2O*9)=g3({DJMz0VSKGh!8LtUQ%5f~>T?YH+&Ue`KaL}{ZA*Th zX_}`}TFCnZ>bmZEAfCqkvr}%O5`jYq6uhTl94W>~frm6EKZ|j7+<$h86$Zmalt&7T z*VW+HXASyR5fmtS+jVp}>?x`~eBcz`Jk#{2asPx%8)A%c6{VY|A!9A=_pkEvK6o)| z*S4#A7RIb;q(>L5?6X51i1c-&zK3CJd|}C%TGvwKd*qxWYwVM^{xt5# zyu9~htrer>le}VW#T3Qpt+iy0rC}V!&`>w)G<8{)RTTe>)6qr^V}_%+M+QSw`rYDC ztfj8+$AGJIsx8Yx(=-XScb;dN&@;w}lm9Ab;c47w9@@w~XANfMoT+Ww)nPsy z_7b6-b+p^Ph~eVF!k}T)EdysT$V(3jKA$$|d$Pm4_r=kn-)#(aT_=tW(cBs<6KVgF zp+f8e=b~*}IX61<0rwx8Ta21exVvN+bEyWPXI!7tSazCu4%o&wuAk{i2>_0rWX*$S#?Anep(~UbO z6KThBtLvZSmgC{Ua6cFANKBjdEBoH(NLvMgkc zEs+^)L+0Qww8%Y4F|HhA@V+qntXl<_oU<7E%{m?bno&pgusU__x=tQe!)Y}hsx?O< zi55Qq!mazyFuc#Ut#l0y$MD(S_E(}a9G{*8$AJfyprcC8ndWJtn4%1|bY1t5ky~d( z`Z>YLgL+%ObNTMpShCK&aaP`Y3f@!7%--Yg@6^u$a}a(&->(hKIl(Bbv6Pogt?P(V zB0tY$jG=M2dm8sg9yu#sG!Y2})X(!O>c$kQp)y93P8$QoNFqWI<`lHs5j^>62*%9=h}AG|v9-{YF+ z`S=+*V*oB7#2jO(9|ozZk@*NZuE3y0l`~D#ke_EtIZ@a3!qn4rT3x!-9C>}O>U*Lc zqcKLnPo%QinL|!WpM^zf%;lVE_A@!_sP6|h%x=XK*vd{~jDj&BZH71ooWUg}S<^Js z4?_t+DN)La=4mQvIj8WyHgaq98R=Duky1|7P(ur`XKhRw*5D|GRzwWp_%l?zwtg^3 zF)xWenxKL|Bh|$L(CPQR9G*sY6Swh*sAMYq`K&Ft0zQ|XGp}21+Hf%Jg2-=;r5H;D zN6HGra@MU7_83CRkQ9KaQ&&yUk#STQtC~O0s#I!>p=mluookI1QqgYrQeG!FGAyGV zO?{R^EbK$vlbADgT`$h>tIrVcKgDBP_4V~HbzLt`?AqDf!vksnKmdfns8J_@3TdsC zVGN|!nmW3$NP&)^x`sZ-u^@_QqpqV|4U*mK9-+sI`+>tBV-V#P9IC$WCGyqZp)M_) zbM*T6uK-J3*RNV)+HpG9u2O%?hZX5;Jsh*BS#tRt6^Pd~jm*Kz_-szX+pqDJzUu|i z25lDEh*5Y8epmlKScY|kzUDPelSpM{CI#U=uWj7!5u-E?o98qdA_6!ReLs{wEVm(A zWmt$p%d*IU)+zQm9$0ID2R>N(^|e0uy#X=(8Ju&)`FURsEoU|;Y)ot@ zlESO{mWasDvwTOxkpzyQYdbPkdWw625=7%1=ZZO?6hM?ln^4n$LyBY?BZg^>rE%Q7 z+mh66Oo&d#bOc>n*S={*X}siC*_UOOUx+1WkRfW8h5|Dsulb(enwIO{F|@uKV^*m) z`i?CRCTykB8YR^S?i^>Lff=2O!dcvl?s=-Mx2mC8(2$756V*W_q7|sssQMOdE*KsR z+wnMOUNSXwG%}=#xR;t-vxQWD)uA^{Lo>I9#Gsi>VvUvWVU(8JsYnOsfV$oLc||xf zjUmfQGVj&W$P#Y#Z1=CPV&F~FP~R1B?V2sdZ;RYu1_3>U;-@i&EY~_fv9(GGoPlmJ zi5?k0tooto+7hY0etjIOT0ZDI2pTY0L|XtzLUH8CRY(&@(Fcue2i7uQP+r*5U&Uer zr0*%ELPk;DfvxYpRSVWA_$63_UY@Wjc@zK$GEoeH96Rb$*?=C@ndfPxjDxHL0+Uvy z_%Qk!)z{*Y=Nj52KZ}mevMfZlOcu_5rfylNulnRa%D9(hp?RLgs0F=budMs57$el_ zw)Xb;->JG+(?#nsNkr)Ho@mmOWJrxQIxJ{6|G8~D;eGeRP~?#2S<-N{`;4`;G!1!Q zB6HXE6hjd42)xHvSY}&Ob9Kb4+gt$s0J<4gc0tb_ZOV?xL|cbl|L$}+2xU03Q)`T& zzUu`WfpgG6o}3GI3bj*5ws0y#fI~qm&d)QoU3d0*0lMq%q5 z)jkVa2t(H16Ng4WOn?yY9mslXhmJn?Y)ze0^I$ zzO<)!iVX%MGvrFI?N*BjYB37U0|1cJx_0v!)_iuInaPec)^^jf%%r&P!!U|`bItkJ ztw}xV8@v}fZQTacJal|s8Lp|&e(T%{L_Fu3=b5JIAXv&c?r8V&a+R9@E@5k$CgIuQ z26t_@>FIPd(EU~YbEm#^eXw+U>Jg@w^k)j-l_t~q$SDUO=BCz6i$LJ9q{iu>%uxE^wCp{!jePE4$Prp zgkHBVPdTx={6H|!gFEP!q!?xB1D~N$4#=o1=+dj_*F+XE&l4@nLc=(IIjg*>aigVi zIPA-yf7emlc4Dks2A4Nh>6~jgI!Zi>h`x3>!FxH-pf*}#rRNH5@EWlPPJmHNv{72u zQcO_{dKku4nyv5MJ?@33fPzSbZ7H_3(#3e=;5f?S?}Y=7dFY(v^TU`^O7!yQzoV|Y zQi9Qd>pAB~kLl{HPqXu4isXZr8FsA!PzRsS7brrSSTSqE$>=yFQ`+tN7B-UMANZP9N&~3OD+$xbuG1HC!QZEw@%G-N;LcVh%q!qh7tPR@U6}a z1|T4raF8>U4h`cSjUn{rxq%DNWPR zFpd;rD8nSnLVljbi9DQf#~4LW5A|Nl4>yFciGW{H59{B16oEcnqk(i|7%Y+2lp?`^ z?`$-H#!f-X6K?6m6gd@dS4Q$(eRqv`BUR3deWp?TI;z#B(>zTyF>6aAw2I^<@*g$V zZ}nY-W6wQtI1_-6ecwyp|JshUkbcGjdd5hHye~EQ7beDTV%*;Q6-dx_9Sy@MsVT-P zw?^|WG3-ZJG!IWN0H8|mr2WECHFN6;hZukl4$Pu@_4u9zt0*(n<8Jq@*nyU9)_r); zOyP)%m}2+F0MM@T^GpjZ)KDWWIw8*}B2L?PH=A+SfEqd!I?W!(-KrJ`CbP>K31Xh+GTyJZt=2-&Nx$0GYrd)W~x`467)uaS$vt2;ms{eDFdcHpZ+# zz+33WX>bidWM(V~_dKOU-7u_h3-ANroa2?!=B;zx_dQM1feaB%(?I~yZ#Qn;>O$KJ zHIjfE+>g8$$aC#O0Uk9`=}BwQrT}^C!Go)8dFri3dv86QqLE^m#DazxgGgvK8Dog5XNu2xI2>duOcRu} zNJW_oCmHOi_0F$t)EF2sYLYE@|0c`$2u-)v(mYKoHB*3qTPvErV%)oz7jZxZl%8bx z=dQ*rlScC_9=dBgnfKjd7-6YAP0go1^gW`MJ_t?I(1H8N)>>L37<9cD9*h;vKsJmp zSR)+(?(b^j(4rHdCEjY}aO=BDipr%$ZRo&AYS|*(C-1$8Wh`_=&4+$iml~B*xFtJK zD7XsykN`7|7aJqwkc6wRgfH;CuZrIHeIe`QOdi4;?6qJoC2M1EA8lbARwkl-usi3Jv~=_E2^Y` zfPNNL7cK46P(#$L)8n>nrFKS78V6X*{UBPwsnrCDI%U13lS4W=O@|dXALN;)X~?p} z+WH*$zFCoPFjZE*UwNir9YUr^mlT&6wrHU#2Yc%I5fv6BMR)SbU2g;%Tl?Bc$zB>ZETP^YPFGDWg~i8 z3XyXhcPk3z76C|$1P1SA!-%n#3>}|ut7ZaF$DRVGF8Rz^l`~roUaPpmp$_A?0`)$c zKd2FX{4S=&^jv~oTmk3h=UGard75Nw^;%<_7kNVkeo zN)-05WvWT(eL+h3)Zof33_HdsQC8%5trLkP=N!>HY_Ym4kaD777+1t2+)ps$u0ia8 zVZ|7W2A(Q=@ZP#~!oAHY$@4kYDn&U_3o_`Itmb9tXSF3h0gdwz0*&KH%{WSF_L=hI zq=7m|eb>`8m(0Y^^VwL;r;J;xQvz_pO?GFF5JK`*sFr+laiGvcg+T+o{m78@mtHA) zFq2B7`8k*LvgmO4s~S`v5F8vt3k*aobWGn`*ODbp1KEJ?HGx*IAtEA`HukIN{85Re z)kB4l!tEZ7DQHoMuR1C1P-HNK9ld^Clm^g7!!tQGwyG(xnB?LcwsN{~OpxVzGp)8^ zsL0%apzAEmdoLra*FevQaio}{WKbcTw;SDkCMxKMj2hKiE2Nc6hSv3m%xZc`8ze|yqaCV7H!!%M~U$l z!wN!{w~nBkyv7A-<-lEubEEe~^W0ioPsZ_>Mz~N}XM0Un5l9p|BDXxdtW`AeKp_}d z4t!W0AQ|Q3v>AF_ko<)~pez6ZLsEKnVl86|RtehQ8||+rm{33KgZ~k*gWfx4>#<|| z*59Qb%azW8N@X>PC+9383^kyn2TU|ZfUbm5#F$%i1+b4!7B)aMLWy*K)e*kF{uP|) zzyJ9^AA)NaM{c1bLav8v)mwl=TN^V`li?8Kzf(%Gp%Y_}N05&toEk;*q(*3tx>YlS zY{F`yh!$WD^-NT`Ck0j$Y4qfnOv9vX9KK z08VJ0X~0XEa7siI#F%ASs8Pb1_gs05=Y-%lO_PwDzH%WjMM#9j_-1v{my8=AjSSZF z?js^v0WR0NM5me~wLCyIcoMuPuXL&Pgpa6tn00!D;SCss@ZnRGaZ0p%hCidc@4a^{ zYXC6BAR-PL#XXmUji@$HlYBSq$GXQbiYDsltfStBQg2JutvPfi^l}5eM)*62iNILX z_zv{br)i@83VY1ku9L0@+Q{!YWq0WVf*0L$ZyP$|*A#ZsAd%kWp{06}HU}2nH^xYc z*|oVHl4_tMs~|jjosCHPlGj?kcZ0$4@et)+i&F;jgF z1Fth&$Vp|T$og3)i9kw3tKp?#95-Lro%_Plvf|}xKvUZzdqqFP~jfZx*=6>~KS+-P0-w-S4(sE04TzsO4bJPR$jb*;2} zw8PY`ziXr5S&d2V_pdA51EQGqG?{h)+JNgU>Jc>Y-m8xzv)F>V&xiefb5-!Uou!4P zk9Fsu1|vUZ++d?=eJ2>%wQ5V;7yv7J;h*lULqn|VO8>P^oi*qLVLMr4OT;^pTN=jk zp(22QNI6S60jjGkY^XH5G^ZKT#wjOhjTvi;jMF=}Q&1 z64~P5{c%-}PI-9+(0eI8$`7b+e)iCzoWS#g69wb17B)c1K&mV-Qu#w)=QUU31Rso-DRc_Co>V zG>2JxC6Frsh9MFV5!v7brPRGliP+syr4pl*kD`kDZu-U1Z&0l|Ow(ZmQ)Hrzp@r2! zA!+R1835UOzgFp9Gt9!qC zE6F2*FsDGM8Ud~i4#Ox(c=z3h`>#GqBNM0f=d{+KY7%24&kOD$l87-^d=}mQ!YC|2 z!k-+S&#k`^*yO&lQKnC{A?x#;mP8Fdi~6~rot9%|DpK1eXKKzoNO+*=)#?o+(5QwG zJB$;wQJv0VZoEvLmDU@E26TE~@6*2ZIOQ#o*Z2M%0{mamqgzFAu5&+n9e{O+*rqWe z1B`)+R_%Mkpa;LvMQe9{`UQMM%TD3%{XCO7u`=mH1E<2W)OrH->wI{JQM>9$l9x=* zxU*!E=6ROZm9=&?XN$I$RiK#Oi7f&GoX#K>ZCxugzna9LYgDa}@>8xlyZESma?Qy1 zp02o7AJNMdP&Vm9i)Xt6^^}^+Z@Z8giPA0R&N*WxqKgb1b_86?G-h+&-JNsTWZH<; zRj{n>Bk5J3w_tva<4)2EOzG&F3=n@(61sYKG_pJ5PrLk@sXc zE4lS|0Xe2#=OoBCgLPWt4J<`*Kx&gr;?%pI9{bIgjHEK>9CI3)LVGsoieai4DbRW! z{n^HiUS%WcRC^X92*@c`!3@LOLHd>Ps`?Q(LNA2FXVD1odo}(~JxsMu83-Qt_&zXV zI9XjY;xIv^png^`WX(}{UT?3qZD~3jXjb;6@7pEOJLfC|Ou_p%z~#rrjp-|v90Isz zKB!}-X_Cn-5GXXLP&){)miP}V5N(%^uxDsy}u)R<9jBe)nwYW4I9!xx^0Q93Wl!v z`+3Q$g@ey@`*YD79DCF5abuETh(S;zk}IU3@9v$U8Yy7 zq8^76h%r#hLmzrGCQ|!zxw-o1YF1C}_1^P}kC5VHaly<4lWV2BdU?Fm&zyq$d8YsU z-~aEeuz@ku|ANfvUfCJ$qi%mfMjjNOja+mW3J>4fHk& zd?7dsaJ})`nf0Q;jdr&1*pb?UgRBJxw%Bi4$`{#&kU^^HBOG)+c(2t=HCX^PPrbFY z7MHjNxVGQF76q7;Xx#0tX5hM(M-)#n$`~)6kG1y8GX&3zPGUrLx96N4VX`~|&#c$B)W!{jm8eiD$K6gmSB&vkXY=pFyJ2DoM2<$$ zVzqO?pLL&H3o~d{8PqO%kO2mkQXZ*0G>uf_m{KB2@ zD8@3f*~aTk;pz28dLLF<0o4jG+&cG=izEKUT3ip#e3Y8&Kyu32e;B!`X-ZAd6hzd| zGj$sS2;d5%pKXm5FbD@5fDJUu7Fx(GMi@=P$7LoOes>&qD|)FWZD{H#j23lG{TVg# zs|^n~N;@48|Lf66jU;1S5wqe^X=kB-2{aRfANql4wo%RW)2*q}(=V?FRP-yOgUCvx zL%}VTRa?G#iW3 z^>6{ch(uRqKtfSmV5Hp}&;B!QpTw_UnT2?btjEj3V~sJ8$BAOJ~3K~&DkCf(Xb+$ry_ z2_`8ekuIvE=&S_(;q5^&)w`W*)E&m9Sxmx+qP1-8M?7S0NLsE(lR(f;D!aapsW4b~ zva6XRSsnGaMDF!_eg$mWGWvhX0F?mIUF;Lh*I&M0oaBv|SAPz`z-1YWNtxK%|GhIV(IiIhlZPr*yP2$vgPk;XW_ipC` zT>uR%o|}&WC@&W zX`$oLhBlV1Ivd<{q<+FR=Q-h7Snzvl$NT+2&7whFs`drdNDE!R+N#WQ_I?b{f$&RXlB;GCnxHW_2297B=c zI^(&zQ|SP}7QLwh%BP6#_%}=j)oH4p-xcA%oK||_0-`A`YU}J><#n{tZ>7j}O|B=- zwEUBnJJL!oQZF%JrjdI6nl&C!4|AYYan_N~p39<15Pi+TmzwMf23bF=r;%Upl95=f za>DaxUWFFV0NLwYti^p)140NvYkyYYXyq04O>qUrJPpkjhNq_nXH2J5mL90 z#8cKcQ%Cu&^|bZp*1%ZZbFU4#?nu;9xk$-?b6|I~*7mM3lWSb)_g{Mt^>2;V*!n6F z8T-W9z+Hu>e1w^tZQQ6!z4xNH5>q6bo$$bO&MVedqv}$<@)YfrX*v`HojJ4^OgJ14 z6j<;ODlGU6|5Ai_Z@FBJP@jV|o3K?(*)d(ENEOQskD<>g5Ge9i=)SGN^; z=dldmELrf4tq6W?1AkuU17;xvnx;v#5s?|Ov zZ+PFe1|6Q)$A-Of!YXCPaE{E)^9bv+UcUWvAtH&?ktZU%zNcXvR|FuvBOXBWsi^(g zmga}C9%GqWL(9^7+)Nv7X_d4>gn?Jmi};X&WKz4nzhOo0PrSD7587ktaLkxAU3AHr zqH0k-%bx3|-J1D`C6k6Rs%~S&a9%Pk`8e2gYMbm=o$<%Ut@aUZ8LB=gAivPE&^%A& z4eVMM%6l(ECar5_tPm0Cd42LhG6oW(A{VLdg{hV{Jjp; zXI_J3r=oVf{q(BFEt@vedgueju2Vqty_=>XAH0Y(H0==`4QHAaNd!7fV_H)VR^%^;}+z~DKM@bydBYb+_PH>Vy;CMO8) zXUZTDXO?A=;f3E2t-be00S<*V!H~PIqvo9%du;eb_Xt_-d(Qyn)n_x>vuf_uKIbJ1 z4^|?98qEZ0ecLSKsDyl1$+=n z%sjdD8*1u#n#$@P9(Zb+hC1iYc8;2EN<^|N&7PnL!};oZ{p!XIFb%>95G%CSl2O|= z!Hb5jnDkohaWph3k$Y>bq$Q2D&szHi^>^^Th&%XMmIM-&HVl9s;3S_JtBs7n|BD8$ z_4Occg%RY>tT@)SdSa)DR`PqJwqL!sA6ix0w&eXx3oSC*2|M3$x4En>lS7b>4#6LtsVUi1thyYRM2NO+%ed)0UwuI3yDnrh*msUL z6}HiSm0RC54NdbTJMd1GG0my zN?*I{x=%B2p4WNN8?spQJgqe4vQlbA)^#c6x9vJQ9QNeB|FoXlqZl;=JF$Er<+4f| zM*WrcAvWg3c-&_Dkwd)JN~W_cOZVW~YMJ`sa46GZt`#ZVei-QW^{;FT0h|vIO*SQb zf-n2LE=!x0L@xUDH;KI^Z`3(ADiRo zuMhB}UYesFV-$zfG!6B`?e@}~!V38f$#18EN2sY?z*-Uv5sVYDbculdA7d3@xoZ*;jpJAEP~8J&ntLOncHVb<=<;_A?o9R-t*aFiABmu*pt>+ za;}wGh3_=%X_}5B&&>JXa)8i-zr}3DS=@5HdiT9?LA|=BX&UOc=rhy6w6$7{Mtv+C}fRxpb*@kJMc6fD63D!dXWl22uNYl;E*c%Q(hyck(`B zfa==d-r08oNb0FnO(WvYISR`{nS~LBSDVw*xE~-rAI6bljC45c%h)3G`_U?r_86zT zXq|2C5u2t1+2*$M0noMw&l~3nEV7=4hib=p?`fJ2N4>!l+ba)j zg%xTW$D>`yDvr6;HcCWta8~o-yqQyzE$%@!_^FqSCn^Iy z$G{;Yec)c~VZRs92lqcP0Yf{1u2QkZT){`++c{Ahd$W*!o5sje$XlSvx41-lscEQT zzWOi>n@(WKnd}X_4DM2|)HIC@ec*s-y)J+WBInw+G))INP$@@sfHwDRF-2*IQ$$ABN*b*&q0vV~jL0c}CLmjSLE_h3LkC z%AI?lBCqUi@-dCp2L`nm^v#>)=*b(kfimYzhKQ_dC7pw)A_(?+3=sl~3oYbw`)iFG zN;ja6V$0{q5f=9hpctl~kS3x8+UloTYiSrp8Gl4{)|*L@bzvn=&te0avj#mM{+>~T z%Z}HE2naH>AN_n-N(>13FpQfR0RrGHrqC`nZVlF8_+txf;~y?#bZUn%R;S3%aIbva z?T+>LT&9d>UJcy3R#qmUSDsR$VHh`Sn14O}MwSE73*a9!Bi-8RNk2GeB5TVg5+|+X@ay@e!HvvqL}r_*nz!mCt@&m8Va00vfQF;seeUDwHwI^>v$cs(xT)a5?xfJEiIWM zsRd?Lr#R^KVV&n$K+sd;zz}D|Xed6ny+B;>r$lXHQ3fsf{L%Tm_4z%!&y6*)c#xJw z_zcS}Azc&C#I-a80i1J`c>6_B;Or!w)Q1NG4glfcIP|i5FsuGW<3=i7jC(H*5oxtC z1wlsi)-&|;JX2;o1H0LR_wsw-j^qBeZMPEqLkbB@MPn&Q=}}s(&ccR+NowOLQQ@Im zWBy4A>zp&qe9wTAckO8)5bCGRBh=hdQyW7IM{i>cEwrptJKpzYxt*m^^_;WNQDX=c zt&e737?0p@qhA zx9I@>r3(l-0AHZ|TVtgfEWXFR`1IgN41pXk4A&1`8?)y_MMTuK#baY1vG+5zN+hvP z?Qr0*;je)d_({k$^H4JR&{a&?* z1O9*JsH=Y;KQHTryq7HvTb>MP;_K^Q5t`GhPC<5Pe<;#AO%orGNm@OfK@A^#u z5j7nI7%=9DL#IJ2ok?|VM?QE#!9(zG#P3@++MJSLCvd3vj6kRC{J|j z)~eRz7AS4h9 z6Lnor3oWurNWaE={p(>Eq<0I2jd~RI-t)wlURV(mL!i850lMmv$F(hWZTBIfEGf5j zg47yoMQeNO=Z!IRIP420vLB>%Gf$IDhSk|YSOSk$XPuslx@`q&-dnQh5iidhU9@qZ za_sj4(N@m+Y%ky(wXXE1wIR2Tm;9*+4kUdg@W6)&`@JFaGyC}>8lGlNIqsJut(>`r zeKfFazke<0HxF8@aD}d;-OC^P^XET$`Sa)O1E5)BD1pHHf6qY=<9O7NS2)Sm{gV_^ z8MWxH{c^(w2Bd*TW3A}Z)y9o`_RwiLYV1bolWQ<&QREh=O=E!|+ zy@qWK;PC1wg>9jaqQn_ODEqW{SGjgf(mOUrmh@fvneqEr_6{9!Ep_$Y@9MUqsp!G@ zZvb&y-HhLUL62NEuCUrl{T#JT+?!c>Sz6Bj)2TR6-K3(2=l(0a7050yMro0WxZS+! zx1N(h_~6AOrj&%1nTWnEJx`1-=al5Z*Y^)(l)mdl>h{wQ&pA3A_S815+U)Yauwm0Q zBB_*OdV_F7=R4(sk$~j#G;DeU7;A=R+qNfp+;BrKj%z_L7%{c2OTxhzfQSq z1Z|YTxwb8O&Pr7kaz7s#CE98&Evu&tMG9#_q zJbl+wUQ`cU_4$YjnWbr(GV;fc;k_HMLL0F?qgkl$2WqHHl@)Y168Zb=A;b5b=jq7I z!bV8`&d6+DUj9hta!o_&`<^mqE|!k#fZppsh{yu(2tzB=no={$E_HU)r?}(4(cqy- zv*cWM*K?PmZM&18XQ5l)e>mn#xhte_> z%uANOt~eiJWWM4x-{Jv#@5#?|(fekkTKE853%j-e{y&!TX~@ zhTySCk2kp%_d@0?q|xDeQ)OlrRP5|0QXzy^(SXV!FX+m@`c6e%7hd{}(`qkdp! zrvi`Zmhv@XibW5MJ?lBU%{C(%*H&0p1F9@iZ}gUFS*RZdiPYcKU$>QG1hM55>rX(T zN^zx8W23kiTM_9uqvtZEXbd$h=6H%*@ZEe1^O-M)bPwsVP!rkH>urYG0i;-f8USqr z&u!!9blQH7gTX-?hOsE8s$qtY*jiiP3!5$Gc@{MjsBAPF%C6QqdU^RH-1qOgP~&Sy z3gGNbbY`uut$G~KRgc?lIfmcd7F(4)&dCa6eNXh-qwl;|=Cg+hkwU9=xVDx0x0ZCB z=jqrAQ$1;j5FqUdF?@)0qqfC*qNM6;sDQW&(jh^=y{8a7&GRHExUR2(4~)B)LKl7c z^QqMT7J!uI5J=58&ouE|woVrz+XQ3Q(b%djBQ;QTss_JyWPJ3vbris@3zl<@|b^Qv=!i@;rJJk;_A#GPZVJ#r=UW9F^7i zqh2>&3#=?3{2T7Kq~T3NyWNW@pS-AC0T>`?mvfnEdz_)vjh zA}yAbC^K!(T1yEBhY$a$3sSu}kfM*CN{P^MyG{3=Pu5N;v0T%!*9+8L8+q6F)OG#Y zKp9>;crSHq%85+FLiI~|?dfokZ64mwlu|FmlC2TUkFps!Mu<3I-WZa*K-I~Tw9SNP z4%A$Mg*DoKi%pbuy8oytKb-V59b^Wcs3;88!!`?ptl#}zKIL8-S{t}*U2Izhq1G)T zoi>Y#i!wZ83}xuEogtkhlV)UAGE8`F*;4tQgJ6S#@B_RsA|QVOLBh{9Y{(5G^(9qd zfOun#E%Lxirp$Y#4V7gNA$W55M)DT6~AVXl~Qrr|$(oCALg2>iT0pUE?E2z7-A_w*` z=~h~O_<+>wo1YXFd_01q`gB^ZQxFZFVQLG*AdNCU$Rc5DW6qhHWudO`X}^D! z`UQ3H)&Z+gNJuAZiRHR}2MSMASXr8~N_5;p+IC&}Y}US8uLG=Vsu|tGeouMHk~!8Yq=;OoxpjnHO>Zqlx4CEU zhmlZCf!qRDu&QWT7ILOcoIx_#skvhq0=8cwbqCc_x6&+}(UPfcyR-IQiH4ifpPuJg zK3iIjJ!GWT5EGmZ2a%qtg$<#qVxy&*Utj+Y@kG}tW6<}o>pEIEg4CNoAzZ1QWUka< zPHoG$b{+dugdb2U^}`_i2LuJ;sQqZT!Ixc3ZNNBSkmWsfAX1Dp^RhbqfN|i_i(S<- zoc3S|yW=)mUP|^5)vjr&%dHg|CZxOgU(xs;$f&ydqy0^b6069H$tCG;bL{Vr<4)$G zq3hjt9WRb=S4b>+8_6bUS;;*ao(i+fL)hw% zU+drkocbyJbXm8{_fZyQVB;xc8kYBmH$S=NuDvY|Cg!oVVQPYl96%~HZsMM_L{V#{ z2VU3R-uq*;Tk>ke60$-2{p(7vZQ%uiu|nTLw1Ix~C8GHP5;CHV)jO-`naT##vc7nd zY$1d|#O)~ON~Qs)gEYEPV}xDTi@Ix8ZM1owH=U4H!+G!XizKn;M>{9Nm0S1X)L!<_ z7|Ns7rXK>NaLoMut#d@duN*vR){k_3Dss1NE94WsB(RR;0H-8k%@iyj zq{(P+Axh<(X_^izLq@Ht*S(s?NUENAEHC(D@4D?e8u~%NB^=^Q+ZI^J7gLm|x{w;e zprhKU?2odRB0H?UAJ&q=tazI8ar6~>XKmL>gfH~mN%p0kay%a`Yp9htwGwQ;@F z;wPl!rcwyf?972hNt|&H2Mn6edbBz{*TfTuF>HzOHHvsbN_;_2A!+F)KhLsRM5p;P z_o(q17S!pLQfJ$BW$kZ22qWw(Xr|ttf{5I(+G|WDRUgM44Z~3CYbAiFH-nrh%(; zeC1S5MCLbT)-~?m4;UHsoN8~0SgyF_DN)mQ5BYsQecHReFA6IPG2T2B8)TCuXG-X0 zbA4w`(IHRF@Ih)TDG-w@oO4ollTQ1MA**DDTGvWT4&}nNE)kqSpPDn1uI;2Y0~-7h z`u=8(5Yts9iYv)t9rYk?VS`;63kDYAiMlqcKD(w-;(h`L&<*tV?@Mc$~UvN3dhFVWYkDX)Zf8rPXo?UV*dC8qd> zrmC0G6OlZaYkJgLW(OQ`{ryFUj9Xgg9%8*CJ2UYFe>aSyOr}K>S8`O-JRQ?^^*P^j zX0>W81RSwKxKRf+rSz`4=V!2*db8-GfoQ-pPGx$9rFI-BdQ?YcuIlYn-?Szu)RCNs zs2>KonNZ&(h1y~jEDl&hjR0?wR&repB8zp7y1u^|8XH+$P+xkUHAGpmU1b}y7-q}~k_ zj9+aI#fl=Um~prA>iRpI#t`uSzBB*;9$HC6K~$My@O^)DMBv+hr4;Cd`8J8jg&6E| zti2ol962SLQ=)OV6D|3zdFAQej+#}Z7XX9>H0SF%V;dtHFN*@|g5bxofqj9$*V+;*L>HoU6 zmGt}8hK&d7xW|t%PSmRUUNm|LW3=5UMO7%-kZLQUJg9f1Zy6WFG*%fFmk&!7 zrR((lT9Nw{z4%cgcVx$S>I`J{`N2s1r_yrgoKPguibBLiJ*9ix`tT#tfG&zi1!4=* zPHewiICah zwpB~FXrw@}w@~bK#rjxp-*`mh2F9}mq-o<9jXpjL|76Xr$q0+m8MD?(UD_xXltyV$ zf6u&EEU7vg?IayJ4u`z}F{pL!jk>zFm5A(|6WZvKv(#bN{yc5l(zx5vIPQd^+Pe1G z1yGI@2M$PmZ9rSRbAC8PJZw@QcC_-Yhc|L!|3uAQ zr`&H0zd24m>BtSbrRI+Z2o_koqVZ`(PZ-gnjO&)QwH|=MXX*Q%LI^ZX2Z_!CMCqwC z-lKM{3x?eH!-|B09{3h55=N=({-`#wXwVZ`NbQ*Fw%9ch^DRu^yQB7d*-l{XIpG~J zkek%@+J6dABPyg3v}O*6y?8xsl=`7IR74EH=E4@xWGyXzSuZl+v=9y=#BkM!EmFWK zt;RS3iY+|j4b~P?Ugz4fiieJK-NF0S!nbQbY@vx#A-7=H8k9eloGHghb2G~x^;+am z%P8eaEobYnOBdjZ90AKatmkQ>%o1CVaN+seDjS`qsf={Su+E0K-)$d2EA1wc`wcKs ztr)_9yI%DhQ(RF~fqG-=$Ta0=FhZ%h<%n9>Fr1_iVt8fE?m}6Sr!2&j;5~JH;idmo zGCOF675GLR@5V~BYAE$2)PXFWM3A_n|S)z%WKZk4h(O|u$|!2OYDa%D$_ za$=q)X?H$Ejf$1i9IRmQSUNCq=K{25*R~Ja2KzEvu7?b?n16kc>Xc0Oi80g6+0rX? z)(INzlvme1W$$OH(?1K!033^{=we|KOUNmFu(d>!Rt(jP4kgNAB@%C1xkb9E=ZdYh zBGptI2PW3^cUqQ3xa#`vPmwV29dBWHC~*uAxqLUcrU#S2qC;SUU}cD5wU2JMdwFQX z{yLzh$1T+W`$uUoXrovV*!4YGV`ZqsaDCZuJ?K>QC=+GV3Kjkga8jacD>PCpQV@a+ ztCwQAAxJ7QgtE5Sx>dTX_eb3<&2nzV1F+5szg!QrKnxM02)J+H|JMq(tCU?uS6bfA z!e28Dw%iH%ZbA$6>Y?jrt(8R+)8Rm`uYaZd!7$KIkcRq_ahJ)ab_LMr1EpN`k&~M< z^<7`m@nxZfj=Ef!Q||lzO$!Yz2hmt#(SrAsNltocZegG;Cz*)iqiX_=SBj(%qo`9` zy+(J-Sgv*TeJ`bi{vHyA)i`Xum32iqRsXGrT}}Z_w{TS2Vc$D?3qL;u3c-_eE%n1d z12Ud-hW;JG8E7qP;b-7i9!o78Ed-v5lFltCX_x&I# z_B_vJn=3d4s^t}_NIyS%I)0VNt@XsDjlezAMI9zQxQ^$UG0Tia^(iH(zcttf6u4g1 z0waXf?Ca}a5q~&0dIK17ZA&97p2Qf00Y^NcRlhHc7(90UceR4dXSxp;83>m!E2(Ey z|4+Qa30W4}Ud;!TNf0&e(T|RIZi&tFQL7%a2^|Yl?q6T&_3!^uh-K(!+`Z6l_aZdu zmzO_3#<0H}xdG<9QPX73GsZL<{x=}wAXyY3tvl}aipALAG%O>)#u&=wX$WIVyi;SS zF$Kv!XD7BU9~N39dONlGL!8yzS$TuY~a&0 z9XG$^^;Sv^#MLdKd(^=l6G8A?Z_#=akwa!S>b-2!G|}O(U&&lU*yE>fGyO6$AO}H3 zlVw@RwvJp*$7wIjeX}89Nj=hU9N3f+8AhhNu9JOQ^E|B_K+`nj$Vpw;GV+a7FU3g1 zIKGL7nyR_bvKq|5um+~swpIWmWlbqj>sr~Ul9x=jIm$162ArIkyN*oaqt}5UOou~p zSdF2$#AA7ccIC3rvT+YialC~{bSFd@JJmrZx|Z+(hLb?%(UXI~EPN=yq;-zQarcm- z3*Tzo&N=c}uOt25^=1zcL%OzmBVB{2B51QBY@k02$zuEr5OhtXF`P?TJSfcQHO!*~%uw6&J#+%(-;H_~iKBCpt0 z6=Duj&K5#`FH{(#ve$~(vWStDOHo(j+#C)E8Kos6(XanW_4LgFHA$DL*-SGbmxNUO z)S?1JOFUpbNYbdoskd`98>>^Z+L48bbre}#M`4-bqUMdVC2G{J?PT;6@2A^0z#6my zth1#TeolW_M;7hmPGt>SSK#+@>T_zq4bMVz_H`LG4C5Q4!n3<)TB_A|zCum{5)M82 zuJ36aN7+F0`uA_y?8?!4_wtAS`|p1qYMH>p7`G;}AT8H5a*YHp8xuxok4a6-=;b`m z)DHvoEFX*LuUjW*rNCgP!$AlxJu8r6ln*QJNwaZ39dC?R7NeETfN{S z15;ZOt@ry^p&5%R?hgmeZfe|!5F-7fYB`DE%W@>HoY){KGua#+d*<`%2-x?-Y77*0 zI9hD7|C$ddmIGq>0XA?#uT8hbwz3JK8@B6V7-Sbn`2~qKrhqeyHotdBH7#_-0pObN zT=GZ@0S5*caWA&En`*;3#Z1G`e+N+ma|D;ndwcK6`!dH4N2LL=5CR?cdz$A--lLRZ z-9K&ES26BW1O#W@YC)ig(Vy|)q7r?8>PSgpgG_3PC;}8qINA#*S{+X33TIu5KGcV* z{`{IdU%s*V;3IoksO(k>ZPSRBW`ST6t6VvGG~H zYiU5+7Nk0a@F7=VQPfyXh#7`KIvt1oo(_loYT%=xMk4mVeqE*JhR4^bo~}oYEz9QN zSx-eJh#Knl6p&x6FA@Vnf0)Gw9cZmJ{XvKrUEvpqOIQhLdNu7?Tver z)PPUVAT1*Ke*aq1a0bl0+HyM1IjPHEUjD4K-C)Rq;v+NJ*aWh5->kK= z4-8!a&33yOJ+5}A0|U{E80#*@n-pF-*YCJc-n^%fns}%OA{j915CTOO(}+A4YdLEJ zyX-q1*N?2ZYi5|N3*rN>xy;oXHpJ&OyPUH_fz_hv-BHX791)8Rl}*U>oc z-srH`#u#Iy>2Ub4b_A6bpR4P-PZ<}|{G}2=)T%bi#%{2!dHe64uU>KGA#)UhtV4!6 z4ki$T_cZ&N4!l+>i}rX&<8JpW4f|@wtr1ELCrH~xt*kN4c{_~Jv(=GM&xwn?FJJSt z9+1#0c^2A^o;tdreyha;^e$=B7y+w>aa;|J&U z#6}HnKZG>KaYz6C_dh~P`R&(LpQ2v>qroxMrW*17FwJLvwQh@H1+SlHS;7~1OjEbM zthMs9M8t<7tPT(|3>by8PS*2)(N_tLx}~04y>G_!C3Ra+f076ao1~TqiR>_TJYRR z25$`m*K2;kSQDC|s;e*+hPpfP01MvNvml}t$j_DB4^|u@CEr3>(H_&BZL0dn#AKUu z>7>_4Yik8oy#jf)0Y;S)I-=kEI_l$j=@d-UVI?H7(zsiA0S4nCWgq(ZV-!+;q;Z4R zX&3-YF;WO#BJ0eOHRpO(7^y~`O=F}_iPRE(;yV4-NV`73ZQBYT9`(5oUJepAh@_m} z1!ase^ykli!ef_}xZ21$${Y^+n`?yuV5*5Knpcizp+yp6jDjxT+o&}cT-0sZnGWM9 zD~z$e$p_W5Opy&49p>fP!J17#2u)@^F4lvSg$&8W( z530^K#!%uKT-W590}nNwdy_jt2uJc0XE}{AWcaxs_IueYM?@=O$gb^vEeifE#!XaK z?m#iL%y}MBEaq-XA>dTN^l1a18V4GR-k?|N0G%ppBm| z-e`gza|j(Z3TJ>moSxG@Ob43%Oyjt_8lsD=K!avzJ8Hdca0vA5yj~7?Ym^)gNH7#N zbb~AMiYb75)*WZ@+qQeA-``bp%ZoN^kOtd0t#dT7=J=(x{3;FZdm)@yQzAK9XGzUR z}3?EWt49C~@<-dKiYO!4! zv580|m34-MZUTNz6Ku3r+Z%P%8%1m2En5Aha0t9OznJ2&v|y#YcJEcV9I7+`$N3Qy{t#gvX7u63nd89IoyivDb;@sM;0Zl%kl@+_L3g(l2<|vdfprck}BcHTSP={)OjgcmQ#Zs zkmG_xHNKa1j{2@I+ydUm^^DdJVBBb3B|nQqtoL3fazO4k-dhB%Q<_cL=d$C$Y3x)HTrekU>(c9R9i0hRQ`hx^*gp;X!HgRcNuGJYNPEHgmWY(n zr_x^?!D=>^PS*oROGIU~ry5R~Q9kIjR93ihihqq74~FA;tEo(~g+Pm2MDQ^$S%@_u zhQgp@urQ@WjVd=#qn0fxvHY2iBp*a?A`*=`425X=Cg!29abYF0tRZqvUK_2iX*$Sv z^ud!4{&=sQqd$NCyUUi7r*U5aT~v~1gs zrs*Juyz4p<{KF=Znj)&_%=>;2liSDl$?*(qQGA{YHd;eAcn)zfsXk`YFEqB9Uo?7^_d-OI|kKCcHi?zU~q zQZ*jzkknXBiG5`OTrHFUBl3P;ZQ(S=P@_ZyBdsUX8nuB`=$Ii$q`a1+)8E_kpYu}G zPZO>8VK+Rsm{KZwVEmaN`GhDBd1h-Y8EcN@50-1T#)`3n%_pe2;+=mbQbRC9*7FR* zQ8S!qrQ#Y>q$Mu0``TDbeb=v8h0p5;7&i_M(nRb%hKG(Z%I>hwrvF{vul7t?Yw6FQ z|7gE|mHBc+>xC6YP!iN4hCr~#air9?lKNgdl4xbuuIr^vMpRBQl2f?AqSQc}rlH0b z38{q^8L<`B*ldWJ<6gE#IV()bi6%NIofl>(n8wl@MN=;FS+aaWYoych^MGjve57@4 z(SCbgKh(I5kq9H{vnx?)_Vbrga~Ue&77`*PYPUL#N6P4fCsU1QqLw}IYM%CnQbTxM zEO;+->p^N$O+*nkUSouA+jT_@FoZxIJGFV5j!O!8dj_zH+R=f^d1-x%om=3klhTgI z>j*l}WrRpbr=!G^wU(T9qIvhcexPy37>gi4&g6p^?+ycdPYLzx^q)Z`@4ZCCk5or> zUt9lwOi{L*xH}C|K!47ABm1;HbMURH*7MS`2`-}ccGl5CYaR5I(#m-X155#l=NPrt zDT8nZvJJdXR%pHVbLj?PpoWJ+u*Ky!2^Id6#trpS?ZNT)TiZxJ8v)Pl)1pUAl~E(T z)H|y{=e)-lBq*|(7yH2&fojjwv|6PUyr+PAnUUt4Gf~de_k;ZY7DEj^Zv8%67t(8F z5?GE1!_QGSghi3*bBi1ua6GNEmreBuWvMN9X+(B8P?vQ-#bs!myG+|njL!Q#O*R=^)hh; zU32iDTh~%lK;U;=+FxyfmdM_2%iZn36Xsv>y4I2R24B(H! zv2ondxZ6Fg>QNm3J>I16d+BGcsFAEg4Tjb=W}DB6+NPRPBei=BpikSj!jA`a((^vA z?-uR<(mkl^@YV7HzBgJBLGLufx}M;@bUVY); z9bC`r7aO-GWcYa&(uv*;b~x;%CclMqacx_~>^Cw585&XOGmvVepD^-!sh36o>qRHJ0{44}1H6~$X&-K%=f4y-Fd4=bjoo{9B>NxIX6x93q>W2nB+d>vu zR>rIeEzJfZj?d?PSwIImC&0p=M8tq_0yd4vh7>J(tXAO$)_2c2(_)Hq9*1$Y@Zov= z@|qjQ)Azls;fZRBsH`Izj{CJY7V=%=U=tnpm8}*D5Rr4O&_U~~<>dxi$|%KH7SsKJ zD4tTH!+tL;F%g`!NAW>yc!ANz5TsK8 z{RAHR;jovei>Qsh?|U`0F{V&w=Y}R0gK*YSO7Y>fv$1Uy3leiml(}Ap1eVZmW0aX} zh+1IPlGZ(YUQgpb4Xm}DFu}0o4F-gMlLb}%RCJEGe zSb;n4cAq|6i6wLK-m4we#!$lp8s``&wtGTRq+!7UeD+5&02%hkW%e7>VH(T8DxtFb z`f!xUV!5MR^A4WZKW5wjsfKZ+{r;7FD4_K4g*W+a?TGE;bM$30&0vAg_jzn#LuB;jdo>!0(*E~PvbuCjd`Ck5Zn+0 zEw8UM?skeqF_j)`4AjPW(SZ}z6&p4ptds_>U6D~P>91RBMVk!SN9&yQ(Z8!Mg{)CZ zNfcPxwtF*}16gEbM%WVuQ1Mw;KaKm#SIg1F8&lTY#z2;rwB2Ckwe0F1rhT&U#zbPf5`5I?elvxm2rbE%N zTQDNZ?XPDF{xt5J716CGSJtCWUh6NI(5L&&Pg#+ zUNW`zbK{5|tF`R+uOh@)RA+Wlhu<5|aL!SRjtp}JYALD1VNZUZ$yiGRQ%0YW`f1!Z zJ(O6r>w}lS_pENZOeNy%_pc)96Jnqk%eF_fa3IQ$d1G3ZB00nWo+xluhxsdVKW*F6 z%gZ0BU5SoTL%F-}npwTFM{B1;bYYqf6uhT#+(~Qec|DE$F45ZBAX!r8xsW$pcuIB&#zxkm?oS;IANQ^WZNH_S;&^lWbHyU6WQDIX- zqg!*>Zw+W2_WJ_haReQPQMmHANPm}Qp^1@u%wl7nx>hNDs-ZlM`ynpOR-=|RI=ZsR zy=jcF-4N}&wxq#Mtr)uJfdu-}({IB&Jo+Ggh%?5VNRT2*D5CWt zEidH%O^1Vw&~|MnT5DL*i^Yq#${L>6Gjd<$^4_na7osu@{tZX zOQWe)Bn{q+9=vG`?OtA1d(&3qoKM4k8uw4Qe$rZ3En##x>{p8kF_2*y)vkAC)rN^J z9x+DQ{%IN`qqIQ2wS>~ssGn*1&+;A!vg=P zt!qPm8us&g8uvYKw2IzE5V9A&G6*v+F{~oGfP=^ccmQO{S=eV!Lw;WWOwIi-UbVQt z$T)Q!O@~9-=;>P7WV#Y~d|uD%Y2452dHt^INmqJa&+BR2&+B= 4) +#define EXPORT __attribute__ ((visibility("default"))) +#else // defined(__GNUC__) && (__GNUC__ >= 4) +#define EXPORT +#endif // defined(__GNUC__) && (__GNUC__ >= 4) + +#endif // _WIN32 + + +/** + * Debugger support for the V8 JavaScript engine. + */ +namespace v8 { + +// Debug events which can occur in the V8 JavaScript engine. +enum DebugEvent { + Break = 1, + Exception = 2, + NewFunction = 3, + BeforeCompile = 4, + AfterCompile = 5 +}; + + +/** + * Debug event callback function. + * + * \param event the type of the debug event that triggered the callback + * (enum DebugEvent) + * \param exec_state execution state (JavaScript object) + * \param event_data event specific data (JavaScript object) + * \param data value passed by the user to SetDebugEventListener + */ +typedef void (*DebugEventCallback)(DebugEvent event, + Handle exec_state, + Handle event_data, + Handle data); + + +/** + * Debug message callback function. + * + * \param message the debug message + * \param length length of the message + * \param data the data value passed when registering the message handler + * A DebugMessageHandler does not take posession of the message string, + * and must not rely on the data persisting after the handler returns. + */ +typedef void (*DebugMessageHandler)(const uint16_t* message, int length, + void* data); + +/** + * Debug host dispatch callback function. + * + * \param dispatch the dispatch value + * \param data the data value passed when registering the dispatch handler + */ +typedef void (*DebugHostDispatchHandler)(void* dispatch, + void* data); + + + +class EXPORT Debug { + public: + // Set a C debug event listener. + static bool SetDebugEventListener(DebugEventCallback that, + Handle data = Handle()); + + // Set a JavaScript debug event listener. + static bool SetDebugEventListener(v8::Handle that, + Handle data = Handle()); + + // Break execution of JavaScript. + static void DebugBreak(); + + // Message based interface. The message protocol is JSON. + static void SetMessageHandler(DebugMessageHandler handler, void* data = NULL, + bool message_handler_thread = true); + static void SendCommand(const uint16_t* command, int length); + + // Dispatch interface. + static void SetHostDispatchHandler(DebugHostDispatchHandler handler, + void* data = NULL); + static void SendHostDispatch(void* dispatch); + + /** + * Run a JavaScript function in the debugger. + * \param fun the function to call + * \param data passed as second argument to the function + * With this call the debugger is entered and the function specified is called + * with the execution state as the first argument. This makes it possible to + * get access to information otherwise not available during normal JavaScript + * execution e.g. details on stack frames. The following example show a + * JavaScript function which when passed to v8::Debug::Call will return the + * current line of JavaScript execution. + * + * \code + * function frame_source_line(exec_state) { + * return exec_state.frame(0).sourceLine(); + * } + * \endcode + */ + static Handle Call(v8::Handle fun, + Handle data = Handle()); + + /** + * Enable the V8 builtin debug agent. The debugger agent will listen on the + * supplied TCP/IP port for remote debugger connection. + * \param name the name of the embedding application + * \param port the TCP/IP port to listen on + */ + static bool EnableAgent(const char* name, int port); +}; + + +} // namespace v8 + + +#undef EXPORT + + +#endif // V8_DEBUG_H_ diff --git a/deps/v8/include/v8.h b/deps/v8/include/v8.h new file mode 100644 index 0000000000..1ddaee02c9 --- /dev/null +++ b/deps/v8/include/v8.h @@ -0,0 +1,2538 @@ +// Copyright 2007-2008 the V8 project 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. + +/** \mainpage V8 API Reference Guide + * + * V8 is Google's open source JavaScript engine. + * + * This set of documents provides reference material generated from the + * V8 header file, include/v8.h. + * + * For other documentation see http://code.google.com/apis/v8/ + */ + +#ifndef V8_H_ +#define V8_H_ + +#include + +#ifdef _WIN32 +typedef int int32_t; +typedef unsigned int uint32_t; +typedef unsigned short uint16_t; // NOLINT +typedef long long int64_t; // NOLINT + +// Setup for Windows DLL export/import. When building the V8 DLL the +// BUILDING_V8_SHARED needs to be defined. When building a program which uses +// the V8 DLL USING_V8_SHARED needs to be defined. When either building the V8 +// static library or building a program which uses the V8 static library neither +// BUILDING_V8_SHARED nor USING_V8_SHARED should be defined. +// The reason for having both V8EXPORT and V8EXPORT_INLINE is that classes which +// have their code inside this header file need to have __declspec(dllexport) +// when building the DLL but cannot have __declspec(dllimport) when building +// a program which uses the DLL. +#if defined(BUILDING_V8_SHARED) && defined(USING_V8_SHARED) +#error both BUILDING_V8_SHARED and USING_V8_SHARED are set - please check the\ + build configuration to ensure that at most one of these is set +#endif + +#ifdef BUILDING_V8_SHARED +#define V8EXPORT __declspec(dllexport) +#define V8EXPORT_INLINE __declspec(dllexport) +#elif USING_V8_SHARED +#define V8EXPORT __declspec(dllimport) +#define V8EXPORT_INLINE +#else +#define V8EXPORT +#define V8EXPORT_INLINE +#endif // BUILDING_V8_SHARED + +#else // _WIN32 + +#include + +// Setup for Linux shared library export. There is no need to destinguish +// neither between building or using the V8 shared library nor between using +// the shared or static V8 library as there is on Windows. Therefore there is +// no checking of BUILDING_V8_SHARED and USING_V8_SHARED. +#if defined(__GNUC__) && (__GNUC__ >= 4) +#define V8EXPORT __attribute__ ((visibility("default"))) +#define V8EXPORT_INLINE __attribute__ ((visibility("default"))) +#else // defined(__GNUC__) && (__GNUC__ >= 4) +#define V8EXPORT +#define V8EXPORT_INLINE +#endif // defined(__GNUC__) && (__GNUC__ >= 4) + +#endif // _WIN32 + +/** + * The v8 JavaScript engine. + */ +namespace v8 { + +class Context; +class String; +class Value; +class Utils; +class Number; +class Object; +class Array; +class Int32; +class Uint32; +class External; +class Primitive; +class Boolean; +class Integer; +class Function; +class Date; +class ImplementationUtilities; +class Signature; +template class Handle; +template class Local; +template class Persistent; +class FunctionTemplate; +class ObjectTemplate; +class Data; + + +// --- W e a k H a n d l e s + + +/** + * A weak reference callback function. + * + * \param object the weak global object to be reclaimed by the garbage collector + * \param parameter the value passed in when making the weak global object + */ +typedef void (*WeakReferenceCallback)(Persistent object, + void* parameter); + + +// --- H a n d l e s --- + +#define TYPE_CHECK(T, S) \ + while (false) { \ + *(static_cast(0)) = static_cast(0); \ + } + +/** + * An object reference managed by the v8 garbage collector. + * + * All objects returned from v8 have to be tracked by the garbage + * collector so that it knows that the objects are still alive. Also, + * because the garbage collector may move objects, it is unsafe to + * point directly to an object. Instead, all objects are stored in + * handles which are known by the garbage collector and updated + * whenever an object moves. Handles should always be passed by value + * (except in cases like out-parameters) and they should never be + * allocated on the heap. + * + * There are two types of handles: local and persistent handles. + * Local handles are light-weight and transient and typically used in + * local operations. They are managed by HandleScopes. Persistent + * handles can be used when storing objects across several independent + * operations and have to be explicitly deallocated when they're no + * longer used. + * + * It is safe to extract the object stored in the handle by + * dereferencing the handle (for instance, to extract the Object* from + * an Handle); the value will still be governed by a handle + * behind the scenes and the same rules apply to these values as to + * their handles. + */ +template class V8EXPORT_INLINE Handle { + public: + + /** + * Creates an empty handle. + */ + Handle(); + + /** + * Creates a new handle for the specified value. + */ + explicit Handle(T* val) : val_(val) { } + + /** + * Creates a handle for the contents of the specified handle. This + * constructor allows you to pass handles as arguments by value and + * to assign between handles. However, if you try to assign between + * incompatible handles, for instance from a Handle to a + * Handle it will cause a compiletime error. Assigning + * between compatible handles, for instance assigning a + * Handle to a variable declared as Handle, is legal + * because String is a subclass of Value. + */ + template inline Handle(Handle that) + : val_(reinterpret_cast(*that)) { + /** + * This check fails when trying to convert between incompatible + * handles. For example, converting from a Handle to a + * Handle. + */ + TYPE_CHECK(T, S); + } + + /** + * Returns true if the handle is empty. + */ + bool IsEmpty() const { return val_ == 0; } + + T* operator->() const; + + T* operator*() const; + + /** + * Sets the handle to be empty. IsEmpty() will then return true. + */ + void Clear() { this->val_ = 0; } + + /** + * Checks whether two handles are the same. + * Returns true if both are empty, or if the objects + * to which they refer are identical. + * The handles' references are not checked. + */ + template bool operator==(Handle that) const { + void** a = reinterpret_cast(**this); + void** b = reinterpret_cast(*that); + if (a == 0) return b == 0; + if (b == 0) return false; + return *a == *b; + } + + /** + * Checks whether two handles are different. + * Returns true if only one of the handles is empty, or if + * the objects to which they refer are different. + * The handles' references are not checked. + */ + template bool operator!=(Handle that) const { + return !operator==(that); + } + + template static inline Handle Cast(Handle that) { + if (that.IsEmpty()) return Handle(); + return Handle(T::Cast(*that)); + } + + private: + T* val_; +}; + + +/** + * A light-weight stack-allocated object handle. All operations + * that return objects from within v8 return them in local handles. They + * are created within HandleScopes, and all local handles allocated within a + * handle scope are destroyed when the handle scope is destroyed. Hence it + * is not necessary to explicitly deallocate local handles. + */ +template class V8EXPORT_INLINE Local : public Handle { + public: + Local(); + template inline Local(Local that) + : Handle(reinterpret_cast(*that)) { + /** + * This check fails when trying to convert between incompatible + * handles. For example, converting from a Handle to a + * Handle. + */ + TYPE_CHECK(T, S); + } + template inline Local(S* that) : Handle(that) { } + template static inline Local Cast(Local that) { + if (that.IsEmpty()) return Local(); + return Local(T::Cast(*that)); + } + + /** Create a local handle for the content of another handle. + * The referee is kept alive by the local handle even when + * the original handle is destroyed/disposed. + */ + static Local New(Handle that); +}; + + +/** + * An object reference that is independent of any handle scope. Where + * a Local handle only lives as long as the HandleScope in which it was + * allocated, a Persistent handle remains valid until it is explicitly + * disposed. + * + * A persistent handle contains a reference to a storage cell within + * the v8 engine which holds an object value and which is updated by + * the garbage collector whenever the object is moved. A new storage + * cell can be created using Persistent::New and existing handles can + * be disposed using Persistent::Dispose. Since persistent handles + * are passed by value you may have many persistent handle objects + * that point to the same storage cell. For instance, if you pass a + * persistent handle as an argument to a function you will not get two + * different storage cells but rather two references to the same + * storage cell. + */ +template class V8EXPORT_INLINE Persistent : public Handle { + public: + + /** + * Creates an empty persistent handle that doesn't point to any + * storage cell. + */ + Persistent(); + + /** + * Creates a persistent handle for the same storage cell as the + * specified handle. This constructor allows you to pass persistent + * handles as arguments by value and to assign between persistent + * handles. However, attempting to assign between incompatible + * persistent handles, for instance from a Persistent to a + * Persistent will cause a compiletime error. Assigning + * between compatible persistent handles, for instance assigning a + * Persistent to a variable declared as Persistent, + * is allowed as String is a subclass of Value. + */ + template inline Persistent(Persistent that) + : Handle(reinterpret_cast(*that)) { + /** + * This check fails when trying to convert between incompatible + * handles. For example, converting from a Handle to a + * Handle. + */ + TYPE_CHECK(T, S); + } + + template inline Persistent(S* that) : Handle(that) { } + + /** + * "Casts" a plain handle which is known to be a persistent handle + * to a persistent handle. + */ + template explicit inline Persistent(Handle that) + : Handle(*that) { } + + template static inline Persistent Cast(Persistent that) { + if (that.IsEmpty()) return Persistent(); + return Persistent(T::Cast(*that)); + } + + /** + * Creates a new persistent handle for an existing local or + * persistent handle. + */ + static Persistent New(Handle that); + + /** + * Releases the storage cell referenced by this persistent handle. + * Does not remove the reference to the cell from any handles. + * This handle's reference, and any any other references to the storage + * cell remain and IsEmpty will still return false. + */ + void Dispose(); + + /** + * Make the reference to this object weak. When only weak handles + * refer to the object, the garbage collector will perform a + * callback to the given V8::WeakReferenceCallback function, passing + * it the object reference and the given parameters. + */ + void MakeWeak(void* parameters, WeakReferenceCallback callback); + + /** Clears the weak reference to this object.*/ + void ClearWeak(); + + /** + *Checks if the handle holds the only reference to an object. + */ + bool IsNearDeath() const; + + /** + * Returns true if the handle's reference is weak. + */ + bool IsWeak() const; + + private: + friend class ImplementationUtilities; + friend class ObjectTemplate; +}; + + + /** + * A stack-allocated class that governs a number of local handles. + * After a handle scope has been created, all local handles will be + * allocated within that handle scope until either the handle scope is + * deleted or another handle scope is created. If there is already a + * handle scope and a new one is created, all allocations will take + * place in the new handle scope until it is deleted. After that, + * new handles will again be allocated in the original handle scope. + * + * After the handle scope of a local handle has been deleted the + * garbage collector will no longer track the object stored in the + * handle and may deallocate it. The behavior of accessing a handle + * for which the handle scope has been deleted is undefined. + */ +class V8EXPORT HandleScope { + public: + HandleScope(); + + ~HandleScope(); + + /** + * Closes the handle scope and returns the value as a handle in the + * previous scope, which is the new current scope after the call. + */ + template Local Close(Handle value); + + /** + * Counts the number of allocated handles. + */ + static int NumberOfHandles(); + + /** + * Creates a new handle with the given value. + */ + static void** CreateHandle(void* value); + + private: + // Make it impossible to create heap-allocated or illegal handle + // scopes by disallowing certain operations. + HandleScope(const HandleScope&); + void operator=(const HandleScope&); + void* operator new(size_t size); + void operator delete(void*, size_t); + + // This Data class is accessible internally through a typedef in the + // ImplementationUtilities class. + class V8EXPORT Data { + public: + int extensions; + void** next; + void** limit; + inline void Initialize() { + extensions = -1; + next = limit = NULL; + } + }; + + Data previous_; + + // Allow for the active closing of HandleScopes which allows to pass a handle + // from the HandleScope being closed to the next top most HandleScope. + bool is_closed_; + void** RawClose(void** value); + + friend class ImplementationUtilities; +}; + + +// --- S p e c i a l o b j e c t s --- + + +/** + * The superclass of values and API object templates. + */ +class V8EXPORT Data { + private: + Data(); +}; + + +/** + * Pre-compilation data that can be associated with a script. This + * data can be calculated for a script in advance of actually + * compiling it, and can be stored between compilations. When script + * data is given to the compile method compilation will be faster. + */ +class V8EXPORT ScriptData { // NOLINT + public: + virtual ~ScriptData() { } + static ScriptData* PreCompile(const char* input, int length); + static ScriptData* New(unsigned* data, int length); + + virtual int Length() = 0; + virtual unsigned* Data() = 0; +}; + + +/** + * The origin, within a file, of a script. + */ +class V8EXPORT ScriptOrigin { + public: + ScriptOrigin(Handle resource_name, + Handle resource_line_offset = Handle(), + Handle resource_column_offset = Handle()) + : resource_name_(resource_name), + resource_line_offset_(resource_line_offset), + resource_column_offset_(resource_column_offset) { } + inline Handle ResourceName() const; + inline Handle ResourceLineOffset() const; + inline Handle ResourceColumnOffset() const; + private: + Handle resource_name_; + Handle resource_line_offset_; + Handle resource_column_offset_; +}; + + +/** + * A compiled JavaScript script. + */ +class V8EXPORT Script { + public: + + /** + * Compiles the specified script. The ScriptOrigin* and ScriptData* + * parameters are owned by the caller of Script::Compile. No + * references to these objects are kept after compilation finishes. + */ + static Local