diff options
52 files changed, 8263 insertions, 438 deletions
@@ -134,4 +134,7 @@ a license to everyone to use it as detailed in LICENSE.) * Daniele Di Proietto <daniele.di.proietto@gmail.com> * Dan Dascalescu <dNOSPAMdascalescu@gmail.com> * Thomas Borsos <thomasborsos@gmail.com> +* Ori Avtalion <ori@avtalion.name> +* Guillaume Blanc <guillaumeblanc.sc@gmail.com> +* Usagi Ito <usagi@WonderRabbitProject.net> @@ -10,7 +10,83 @@ Not all changes are documented here. In particular, new features, user-oriented Current trunk code ------------------ - To see a list of commits in the active development branch 'incoming', which have not yet been packaged in a release, see - https://github.com/kripken/emscripten/compare/1.13.1...incoming + - Emscripten: https://github.com/kripken/emscripten/compare/1.16.0...incoming + - Emscripten-LLVM: https://github.com/kripken/emscripten-fastcomp/compare/1.16.0...incoming + - Emscripten-Clang: https://github.com/kripken/emscripten-fastcomp-clang/compare/1.16.0...incoming + +v1.16.0: 4/16/2014 +------------------ + - Removed browser warnings message in VFS library about replacing __proto__ performance issue. + - Full list of changes: + - Emscripten: https://github.com/kripken/emscripten/compare/1.15.1...1.16.0 + - Emscripten-LLVM: no changes. + - Emscripten-Clang: https://github.com/kripken/emscripten-fastcomp-clang/compare/1.15.1...1.16.0 + +v1.15.1: 4/15/2014 +------------------ + - Added support for SDL2 touch api. + - Added new user-controllable emdind-related define #define EMSCRIPTEN_HAS_UNBOUND_TYPE_NAMES, which allows optimizing embind for minimal size when std::type_info is not needed. + - Fixed issues with CMake support where CMAKE_AR and CMAKE_RANLIB were not accessible from CMakeLists.txt files. + - Full list of changes: + - Emscripten: https://github.com/kripken/emscripten/compare/1.15.0...1.15.1 + - Emscripten-LLVM: no changes. + - Emscripten-Clang: no changes. + +v1.15.0: 4/11/2014 +------------------ + - Fix outlining feature for functions that return a double (#2278) + - Added support for C++11 atomic constructs (#2273) + - Adjusted stdout and stderr stream behavior in the default shell.html to always print out to both web page text log box, and the browser console. + - Fixed an issue with loop variable optimization. + - Full list of changes: + - Emscripten: https://github.com/kripken/emscripten/compare/1.14.1...1.15.0 + - Emscripten-LLVM: https://github.com/kripken/emscripten-fastcomp/compare/1.14.1...1.15.0 + - Emscripten-Clang: https://github.com/kripken/emscripten-fastcomp-clang/compare/1.14.1...1.15.0 + +v1.14.1: 4/8/2014 +------------------ + - Added new command line utility 'emcmake', which can be used to call emconfigure for cmake. + - Added a new emcc command line parameter '--valid-abspath', which allows selectively suppressing warning messages that occur when using absolute path names in include and link directories. + - Added a new emcc linker command line parameter '--emit-symbol-map', which will save a map file between minified global names and the original function names. + - Fixed an issue with --default-object-ext not always working properly. + - Added optimizations to eliminate redundant loop variables and redundant self-assignments. + - Migrated several libc functions to use compiled code from musl instead of handwritten JS implementations. + - Improved embind support. + - Renamed the EM_ASM_() macro to the form EM_ASM_ARGS(). + - Fixed mouse button ordering issue in glfw. + - Fixed an issue when creating a path name that ends in a slash (#2258, #2263) + - Full list of changes: + - Emscripten: https://github.com/kripken/emscripten/compare/1.14.0...1.14.1 + - Emscripten-LLVM: https://github.com/kripken/emscripten-fastcomp/compare/1.14.0...1.14.1 + - Emscripten-Clang: no changes. + +v1.14.0: 3/25/2014 +------------------ + - Added new emcc linker command line option '-profiling', which defaults JS code generation options suited for benchmarking and profiling purposes. + - Implemented the EGL function eglWaitGL(). + - Fixed an issue with the HTML5 API that caused the HTML5 event listener unregistration to fail. + - Fixed issues with numpad keys in SDL support library. + - Added a new JS optimizer pass 'simplifyIfs', which is run when -s SIMPLIFY_IFS=1 link flag is set and -g is not specified. This pass merges multiple nested if()s together into single comparisons, where possible. + - Removed false positive messages on missing internal "emscripten_xxx" symbols at link stage. + - Updated to latest relooper version. + - Full list of changes: + - Emscripten: https://github.com/kripken/emscripten/compare/1.13.2...1.14.0 + - Emscripten-LLVM: https://github.com/kripken/emscripten-fastcomp/compare/1.13.2...1.14.0 + - Emscripten-Clang: no changes. + +v1.13.2: 3/15/2014 +------------------ + - Fixed issues with SDL audio on Safari. + - Fixed issues with HTML5 API mouse scroll events on Safari. + - Fixed issues with HTML5 fullscreen requests in IE11. + - Enabled support for emscripten_get_callstack on IE10+. + - Fixed issues with Closure symbol minification. + - Further improved em_asm()-related error messages. + - Updated to latest relooper version. + - Full list of changes: + - Emscripten: https://github.com/kripken/emscripten/compare/1.13.1...1.13.2 + - Emscripten-LLVM: https://github.com/kripken/emscripten-fastcomp/compare/1.13.1...1.13.2 + - Emscripten-Clang: no changes. v1.13.1: 3/10/2014 ------------------ @@ -21,7 +97,16 @@ v1.13.1: 3/10/2014 - Fix an issue where extraneous system libraries would get included in the generated output (#2191). - Added a new function emscripten_async_wget2_data() that allows reading from an XMLHTTPRequest directly into memory while supporting advanced features. - Fixed esc key code in GLFW. - - Full list of changes: https://github.com/kripken/emscripten/compare/1.13.0...1.13.1 + - Added new emscripten_debugger() intrinsic function, which calls into JS "debugger;" statement to break into a JS debugger. + - Fixed varargs function call alignment of doubles to 8 bytes. + - Switched to using default function local stack alignment to 16 bytes to be SIMD-friendly. + - Improved error messages when user code has a syntax error in em_asm() statements. + - Switched to using a new custom LLVM datalayout format for Emscripten. See https://github.com/kripken/emscripten-fastcomp/commit/65405351ba0b32a8658c65940e0b65ceb2601ad4 + - Optimized function local stack space to use fewer temporary JS variables. + - Full list of changes: + - Emscripten: https://github.com/kripken/emscripten/compare/1.13.0...1.13.1 + - Emscripten-LLVM: https://github.com/kripken/emscripten-fastcomp/compare/1.13.0...1.13.1 + - Emscripten-Clang: https://github.com/kripken/emscripten-fastcomp-clang/compare/1.13.0...1.13.1 v1.13.0: 3/3/2014 ------------------ diff --git a/cmake/Platform/Emscripten.cmake b/cmake/Platform/Emscripten.cmake index 7d86c467..f9d8c773 100644 --- a/cmake/Platform/Emscripten.cmake +++ b/cmake/Platform/Emscripten.cmake @@ -66,11 +66,11 @@ if ("${CMAKE_CXX_COMPILER}" STREQUAL "") endif() if ("${CMAKE_AR}" STREQUAL "") - set(CMAKE_AR "${EMSCRIPTEN_ROOT_PATH}/emar${EMCC_SUFFIX}") + set(CMAKE_AR "${EMSCRIPTEN_ROOT_PATH}/emar${EMCC_SUFFIX}" CACHE FILEPATH "Emscripten ar") endif() if ("${CMAKE_RANLIB}" STREQUAL "") - set(CMAKE_RANLIB "${EMSCRIPTEN_ROOT_PATH}/emranlib${EMCC_SUFFIX}") + set(CMAKE_RANLIB "${EMSCRIPTEN_ROOT_PATH}/emranlib${EMCC_SUFFIX}" CACHE FILEPATH "Emscripten ranlib") endif() # Don't do compiler autodetection, since we are cross-compiling. @@ -113,8 +113,7 @@ set(CMAKE_CXX_ARCHIVE_APPEND "${CMAKE_AR} r <TARGET> ${CMAKE_START_TEMP_FILE} <L set(CMAKE_C_ARCHIVE_APPEND "${CMAKE_AR} r <TARGET> ${CMAKE_START_TEMP_FILE} <LINK_FLAGS> <OBJECTS>${CMAKE_END_TEMP_FILE}") # Set a global EMSCRIPTEN variable that can be used in client CMakeLists.txt to detect when building using Emscripten. -# There seems to be some kind of bug with CMake, so you might need to define this manually on the command line with "-DEMSCRIPTEN=1". -set(EMSCRIPTEN 1) +set(EMSCRIPTEN 1 CACHE BOOL "If true, we are targeting Emscripten output.") # We are cross-compiling, so unset the common CMake variables that represent the target platform. Leave UNIX define enabled, since Emscripten # mimics a Linux environment. diff --git a/emscripten-version.txt b/emscripten-version.txt index 226e95b7..f488f67e 100644 --- a/emscripten-version.txt +++ b/emscripten-version.txt @@ -1,2 +1,2 @@ -1.15.0 +1.16.0 diff --git a/emscripten.py b/emscripten.py index c8122cb9..c8fab3be 100755 --- a/emscripten.py +++ b/emscripten.py @@ -1003,7 +1003,7 @@ def emscript_fast(infile, settings, outfile, libraries=[], compiler_engine=None, basic_funcs = ['abort', 'assert', 'asmPrintInt', 'asmPrintFloat'] + [m.replace('.', '_') for m in math_envs] if settings['RESERVED_FUNCTION_POINTERS'] > 0: basic_funcs.append('jsCall') - if settings['SAFE_HEAP']: basic_funcs += ['SAFE_HEAP_LOAD', 'SAFE_HEAP_STORE'] + if settings['SAFE_HEAP']: basic_funcs += ['SAFE_HEAP_LOAD', 'SAFE_HEAP_STORE', 'SAFE_FT_MASK'] if settings['CHECK_HEAP_ALIGN']: basic_funcs += ['CHECK_ALIGN_2', 'CHECK_ALIGN_4', 'CHECK_ALIGN_8'] if settings['ASSERTIONS']: if settings['ASSERTIONS'] >= 2: import difflib diff --git a/src/library.js b/src/library.js index 1d5a9140..c2830397 100644 --- a/src/library.js +++ b/src/library.js @@ -3908,12 +3908,18 @@ LibraryManager.library = { {{{ makeCopyValues('(ppdest+'+Runtime.QUANTUM_SIZE+')', '(ppsrc+'+Runtime.QUANTUM_SIZE+')', Runtime.QUANTUM_SIZE, 'null', null, 1) }}}; }, + llvm_bswap_i16__asm: true, + llvm_bswap_i16__sig: 'ii', llvm_bswap_i16: function(x) { - return ((x&0xff)<<8) | ((x>>8)&0xff); + x = x|0; + return (((x&0xff)<<8) | ((x>>8)&0xff))|0; }, + llvm_bswap_i32__asm: true, + llvm_bswap_i32__sig: 'ii', llvm_bswap_i32: function(x) { - return ((x&0xff)<<24) | (((x>>8)&0xff)<<16) | (((x>>16)&0xff)<<8) | (x>>>24); + x = x|0; + return (((x&0xff)<<24) | (((x>>8)&0xff)<<16) | (((x>>16)&0xff)<<8) | (x>>>24))|0; }, llvm_bswap_i64__deps: ['llvm_bswap_i32'], diff --git a/src/library_browser.js b/src/library_browser.js index 0808b9f0..4cd8b392 100644 --- a/src/library_browser.js +++ b/src/library_browser.js @@ -196,41 +196,42 @@ mergeInto(LibraryManager.library, { // Canvas event setup var canvas = Module['canvas']; - - // forced aspect ratio can be enabled by defining 'forcedAspectRatio' on Module - // Module['forcedAspectRatio'] = 4 / 3; - - canvas.requestPointerLock = canvas['requestPointerLock'] || - canvas['mozRequestPointerLock'] || - canvas['webkitRequestPointerLock'] || - canvas['msRequestPointerLock'] || - function(){}; - canvas.exitPointerLock = document['exitPointerLock'] || - document['mozExitPointerLock'] || - document['webkitExitPointerLock'] || - document['msExitPointerLock'] || - function(){}; // no-op if function does not exist - canvas.exitPointerLock = canvas.exitPointerLock.bind(document); - - function pointerLockChange() { - Browser.pointerLock = document['pointerLockElement'] === canvas || - document['mozPointerLockElement'] === canvas || - document['webkitPointerLockElement'] === canvas || - document['msPointerLockElement'] === canvas; - } + if (canvas) { + // forced aspect ratio can be enabled by defining 'forcedAspectRatio' on Module + // Module['forcedAspectRatio'] = 4 / 3; + + canvas.requestPointerLock = canvas['requestPointerLock'] || + canvas['mozRequestPointerLock'] || + canvas['webkitRequestPointerLock'] || + canvas['msRequestPointerLock'] || + function(){}; + canvas.exitPointerLock = document['exitPointerLock'] || + document['mozExitPointerLock'] || + document['webkitExitPointerLock'] || + document['msExitPointerLock'] || + function(){}; // no-op if function does not exist + canvas.exitPointerLock = canvas.exitPointerLock.bind(document); + + function pointerLockChange() { + Browser.pointerLock = document['pointerLockElement'] === canvas || + document['mozPointerLockElement'] === canvas || + document['webkitPointerLockElement'] === canvas || + document['msPointerLockElement'] === canvas; + } - document.addEventListener('pointerlockchange', pointerLockChange, false); - document.addEventListener('mozpointerlockchange', pointerLockChange, false); - document.addEventListener('webkitpointerlockchange', pointerLockChange, false); - document.addEventListener('mspointerlockchange', pointerLockChange, false); + document.addEventListener('pointerlockchange', pointerLockChange, false); + document.addEventListener('mozpointerlockchange', pointerLockChange, false); + document.addEventListener('webkitpointerlockchange', pointerLockChange, false); + document.addEventListener('mspointerlockchange', pointerLockChange, false); - if (Module['elementPointerLock']) { - canvas.addEventListener("click", function(ev) { - if (!Browser.pointerLock && canvas.requestPointerLock) { - canvas.requestPointerLock(); - ev.preventDefault(); - } - }, false); + if (Module['elementPointerLock']) { + canvas.addEventListener("click", function(ev) { + if (!Browser.pointerLock && canvas.requestPointerLock) { + canvas.requestPointerLock(); + ev.preventDefault(); + } + }, false); + } } }, @@ -482,6 +483,8 @@ mergeInto(LibraryManager.library, { mouseY: 0, mouseMovementX: 0, mouseMovementY: 0, + touches: {}, + lastTouches: {}, calculateMouseEvent: function(event) { // event should be mousemove, mousedown or mouseup if (Browser.pointerLock) { @@ -510,8 +513,9 @@ mergeInto(LibraryManager.library, { // Otherwise, calculate the movement based on the changes // in the coordinates. var rect = Module["canvas"].getBoundingClientRect(); - var x, y; - + var cw = Module["canvas"].width; + var ch = Module["canvas"].height; + // Neither .scrollX or .pageXOffset are defined in a spec, but // we prefer .scrollX because it is currently in a spec draft. // (see: http://www.w3.org/TR/2013/WD-cssom-view-20131217/) @@ -522,26 +526,37 @@ mergeInto(LibraryManager.library, { // and we have no viable fallback. assert((typeof scrollX !== 'undefined') && (typeof scrollY !== 'undefined'), 'Unable to retrieve scroll position, mouse positions likely broken.'); #endif - if (event.type == 'touchstart' || - event.type == 'touchend' || - event.type == 'touchmove') { - var t = event.touches.item(0); - if (t) { - x = t.pageX - (scrollX + rect.left); - y = t.pageY - (scrollY + rect.top); - } else { - return; + + if (event.type === 'touchstart' || event.type === 'touchend' || event.type === 'touchmove') { + var touch = event.touch; + if (touch === undefined) { + return; // the "touch" property is only defined in SDL + } - } else { - x = event.pageX - (scrollX + rect.left); - y = event.pageY - (scrollY + rect.top); + var adjustedX = touch.pageX - (scrollX + rect.left); + var adjustedY = touch.pageY - (scrollY + rect.top); + + adjustedX = adjustedX * (cw / rect.width); + adjustedY = adjustedY * (ch / rect.height); + + var coords = { x: adjustedX, y: adjustedY }; + + if (event.type === 'touchstart') { + Browser.lastTouches[touch.identifier] = coords; + Browser.touches[touch.identifier] = coords; + } else if (event.type === 'touchend' || event.type === 'touchmove') { + Browser.lastTouches[touch.identifier] = Browser.touches[touch.identifier]; + Browser.touches[touch.identifier] = { x: adjustedX, y: adjustedY }; + } + return; } + var x = event.pageX - (scrollX + rect.left); + var y = event.pageY - (scrollY + rect.top); + // the canvas might be CSS-scaled compared to its backbuffer; // SDL-using content will want mouse coordinates in terms // of backbuffer units. - var cw = Module["canvas"].width; - var ch = Module["canvas"].height; x = x * (cw / rect.width); y = y * (ch / rect.height); diff --git a/src/library_fs.js b/src/library_fs.js index 3d0036ee..d53210f9 100644 --- a/src/library_fs.js +++ b/src/library_fs.js @@ -394,16 +394,12 @@ mergeInto(LibraryManager.library, { } }); } - if (stream.__proto__) { - // reuse the object - stream.__proto__ = FS.FSStream.prototype; - } else { - var newStream = new FS.FSStream(); - for (var p in stream) { - newStream[p] = stream[p]; - } - stream = newStream; + // clone it, so we can return an instance of FSStream + var newStream = new FS.FSStream(); + for (var p in stream) { + newStream[p] = stream[p]; } + stream = newStream; var fd = FS.nextfd(fd_start, fd_end); stream.fd = fd; FS.streams[fd] = stream; diff --git a/src/library_glfw.js b/src/library_glfw.js index f72aeb24..6d539326 100644 --- a/src/library_glfw.js +++ b/src/library_glfw.js @@ -130,9 +130,11 @@ var LibraryGLFW = { onKeyChanged: function(event, status) { var key = GLFW.DOMToGLFWKeyCode(event.keyCode); - if (key && GLFW.keyFunc) { + if (key) { GLFW.keys[key] = status; - Runtime.dynCall('vii', GLFW.keyFunc, [key, status]); + if (GLFW.keyFunc) { + Runtime.dynCall('vii', GLFW.keyFunc, [key, status]); + } } }, @@ -209,7 +211,7 @@ var LibraryGLFW = { }, onMouseWheel: function(event) { - GLFW.wheelPos += Browser.getMouseWheelDelta(event); + GLFW.wheelPos -= Browser.getMouseWheelDelta(event); if (GLFW.mouseWheelFunc && event.target == Module["canvas"]) { Runtime.dynCall('vi', GLFW.mouseWheelFunc, [GLFW.wheelPos]); diff --git a/src/library_sdl.js b/src/library_sdl.js index d90484ad..6e235e90 100644 --- a/src/library_sdl.js +++ b/src/library_sdl.js @@ -10,7 +10,7 @@ // or otherwise). var LibrarySDL = { - $SDL__deps: ['$FS', '$PATH', '$Browser'], + $SDL__deps: ['$FS', '$PATH', '$Browser', 'SDL_GetTicks'], $SDL: { defaults: { width: 320, @@ -82,6 +82,8 @@ var LibrarySDL = { DOMEventToSDLEvent: {}, + TOUCH_DEFAULT_ID: 0, // Our default deviceID for touch events (we get nothing from the browser) + keyCodes: { // DOM code ==> SDL code. See https://developer.mozilla.org/en/Document_Object_Model_%28DOM%29/KeyboardEvent and SDL_keycode.h // For keys that don't have unicode value, we map DOM codes with the corresponding scan codes + 1024 (using "| 1 << 10") 16: 225 | 1<<10, // shift @@ -417,50 +419,104 @@ var LibrarySDL = { } }, - touchX: 0, touchY: 0, + // the browser sends out touchstart events with the whole group of touches + // even if we received a previous touchstart for a specific touch identifier. + // You can test this by pressing one finger to the screen, then another. You'll + // receive two touchstart events, the first with a touches count of 1 the second + // with a touches count of two. + // SDL sends out a new touchstart event for only each newly started touch so to + // emulate this, we keep track of previously started touches. + downFingers: {}, savedKeydown: null, receiveEvent: function(event) { switch(event.type) { - case 'touchstart': + case 'touchstart': case 'touchmove': { event.preventDefault(); - var touch = event.touches[0]; - touchX = touch.pageX; - touchY = touch.pageY; - var event = { - type: 'mousedown', + + var touches = []; + + // Clear out any touchstart events that we've already processed + if (event.type === 'touchstart') { + for (var i = 0; i < event.touches.length; i++) { + var touch = event.touches[i]; + if (SDL.downFingers[touch.identifier] != true) { + SDL.downFingers[touch.identifier] = true; + touches.push(touch); + } + } + } else { + touches = event.touches; + } + + var firstTouch = touches[0]; + if (event.type == 'touchstart') { + SDL.DOMButtons[0] = 1; + } + var mouseEventType; + switch(event.type) { + case 'touchstart': mouseEventType = 'mousedown'; break; + case 'touchmove': mouseEventType = 'mousemove'; break; + } + var mouseEvent = { + type: mouseEventType, button: 0, - pageX: touchX, - pageY: touchY + pageX: firstTouch.clientX, + pageY: firstTouch.clientY }; - SDL.DOMButtons[0] = 1; - SDL.events.push(event); - break; - case 'touchmove': - event.preventDefault(); - var touch = event.touches[0]; - touchX = touch.pageX; - touchY = touch.pageY; - event = { - type: 'mousemove', - button: 0, - pageX: touchX, - pageY: touchY + SDL.events.push(mouseEvent); + + for (var i = 0; i < touches.length; i++) { + var touch = touches[i]; + SDL.events.push({ + type: event.type, + touch: touch + }); }; - SDL.events.push(event); break; - case 'touchend': + } + case 'touchend': { event.preventDefault(); - event = { + + // Remove the entry in the SDL.downFingers hash + // because the finger is no longer down. + for(var i = 0; i < event.changedTouches.length; i++) { + var touch = event.changedTouches[i]; + if (SDL.downFingers[touch.identifier] === true) { + delete SDL.downFingers[touch.identifier]; + } + } + + var mouseEvent = { type: 'mouseup', button: 0, - pageX: touchX, - pageY: touchY + pageX: event.changedTouches[0].clientX, + pageY: event.changedTouches[0].clientY }; SDL.DOMButtons[0] = 0; - SDL.events.push(event); + SDL.events.push(mouseEvent); + + for (var i = 0; i < event.changedTouches.length; i++) { + var touch = event.changedTouches[i]; + SDL.events.push({ + type: 'touchend', + touch: touch + }); + }; break; + } case 'mousemove': + if (SDL.DOMButtons[0] === 1) { + SDL.events.push({ + type: 'touchmove', + touch: { + identifier: 0, + deviceID: {{{ cDefine('SDL_TOUCH_MOUSEID') }}}, + pageX: event.pageX, + pageY: event.pageY + } + }); + } if (Browser.pointerLock) { // workaround for firefox bug 750111 if ('mozMovementX' in event) { @@ -502,6 +558,15 @@ var LibrarySDL = { }; } else if (event.type == 'mousedown') { SDL.DOMButtons[event.button] = 1; + SDL.events.push({ + type: 'touchstart', + touch: { + identifier: 0, + deviceID: {{{ cDefine('SDL_TOUCH_MOUSEID') }}}, + pageX: event.pageX, + pageY: event.pageY + } + }); } else if (event.type == 'mouseup') { // ignore extra ups, can happen if we leave the canvas while pressing down, then return, // since we add a mouseup in that case @@ -509,6 +574,15 @@ var LibrarySDL = { return; } + SDL.events.push({ + type: 'touchend', + touch: { + identifier: 0, + deviceID: {{{ cDefine('SDL_TOUCH_MOUSEID') }}}, + pageX: event.pageX, + pageY: event.pageY + } + }); SDL.DOMButtons[event.button] = 0; } @@ -600,6 +674,10 @@ var LibrarySDL = { event.handled = true; switch (event.type) { + case 'touchstart': case 'touchend': case 'touchmove': { + Browser.calculateMouseEvent(event); + break; + } case 'keydown': case 'keyup': { var down = event.type === 'keydown'; var code = event.keyCode; @@ -608,8 +686,11 @@ var LibrarySDL = { } else { code = SDL.keyCodes[event.keyCode] || event.keyCode; } + + var scan = code & ~(1 << 10); + scan = SDL.scanCodes[scan] || scan; - {{{ makeSetValue('SDL.keyboardState', 'code', 'down', 'i8') }}}; + {{{ makeSetValue('SDL.keyboardState', 'scan', 'down', 'i8') }}}; // TODO: lmeta, rmeta, numlock, capslock, KMOD_MODE, KMOD_RESERVED SDL.modState = ({{{ makeGetValue('SDL.keyboardState', '1248', 'i8') }}} ? 0x0040 | 0x0080 : 0) | // KMOD_LCTRL & KMOD_RCTRL ({{{ makeGetValue('SDL.keyboardState', '1249', 'i8') }}} ? 0x0001 | 0x0002 : 0) | // KMOD_LSHIFT & KMOD_RSHIFT @@ -690,13 +771,19 @@ var LibrarySDL = { if (event.type != 'mousemove') { var down = event.type === 'mousedown'; {{{ makeSetValue('ptr', C_STRUCTS.SDL_MouseButtonEvent.type, 'SDL.DOMEventToSDLEvent[event.type]', 'i32') }}}; + {{{ makeSetValue('ptr', C_STRUCTS.SDL_MouseButtonEvent.timestamp, '0', 'i32') }}}; + {{{ makeSetValue('ptr', C_STRUCTS.SDL_MouseButtonEvent.windowID, '0', 'i32') }}}; + {{{ makeSetValue('ptr', C_STRUCTS.SDL_MouseButtonEvent.which, '0', 'i32') }}}; {{{ makeSetValue('ptr', C_STRUCTS.SDL_MouseButtonEvent.button, 'event.button+1', 'i8') }}}; // DOM buttons are 0-2, SDL 1-3 {{{ makeSetValue('ptr', C_STRUCTS.SDL_MouseButtonEvent.state, 'down ? 1 : 0', 'i8') }}}; {{{ makeSetValue('ptr', C_STRUCTS.SDL_MouseButtonEvent.x, 'Browser.mouseX', 'i32') }}}; {{{ makeSetValue('ptr', C_STRUCTS.SDL_MouseButtonEvent.y, 'Browser.mouseY', 'i32') }}}; } else { {{{ makeSetValue('ptr', C_STRUCTS.SDL_MouseMotionEvent.type, 'SDL.DOMEventToSDLEvent[event.type]', 'i32') }}}; - {{{ makeSetValue('ptr', C_STRUCTS.SDL_MouseMotionEvent.state, 'SDL.buttonState', 'i8') }}}; + {{{ makeSetValue('ptr', C_STRUCTS.SDL_MouseMotionEvent.timestamp, '0', 'i32') }}}; + {{{ makeSetValue('ptr', C_STRUCTS.SDL_MouseMotionEvent.windowID, '0', 'i32') }}}; + {{{ makeSetValue('ptr', C_STRUCTS.SDL_MouseMotionEvent.which, '0', 'i32') }}}; + {{{ makeSetValue('ptr', C_STRUCTS.SDL_MouseMotionEvent.state, 'SDL.buttonState', 'i32') }}}; {{{ makeSetValue('ptr', C_STRUCTS.SDL_MouseMotionEvent.x, 'Browser.mouseX', 'i32') }}}; {{{ makeSetValue('ptr', C_STRUCTS.SDL_MouseMotionEvent.y, 'Browser.mouseY', 'i32') }}}; {{{ makeSetValue('ptr', C_STRUCTS.SDL_MouseMotionEvent.xrel, 'Browser.mouseMovementX', 'i32') }}}; @@ -704,6 +791,33 @@ var LibrarySDL = { } break; } + case 'touchstart': case 'touchend': case 'touchmove': { + var touch = event.touch; + var w = Module['canvas'].width; + var h = Module['canvas'].height; + var x = Browser.touches[touch.identifier].x / w; + var y = Browser.touches[touch.identifier].y / h; + var lx = Browser.lastTouches[touch.identifier].x / w; + var ly = Browser.lastTouches[touch.identifier].y / h; + var dx = x - lx; + var dy = y - ly; + if (touch['deviceID'] === undefined) touch.deviceID = SDL.TOUCH_DEFAULT_ID; + if (dx === 0 && dy === 0 && event.type === 'touchmove') return; // don't send these if nothing happened + {{{ makeSetValue('ptr', C_STRUCTS.SDL_TouchFingerEvent.type, 'SDL.DOMEventToSDLEvent[event.type]', 'i32') }}}; + {{{ makeSetValue('ptr', C_STRUCTS.SDL_TouchFingerEvent.timestamp, '_SDL_GetTicks()', 'i32') }}}; + {{{ makeSetValue('ptr', C_STRUCTS.SDL_TouchFingerEvent.touchId, 'touch.deviceID', 'i64') }}}; + {{{ makeSetValue('ptr', C_STRUCTS.SDL_TouchFingerEvent.fingerId, 'touch.identifier', 'i64') }}}; + {{{ makeSetValue('ptr', C_STRUCTS.SDL_TouchFingerEvent.x, 'x', 'float') }}}; + {{{ makeSetValue('ptr', C_STRUCTS.SDL_TouchFingerEvent.y, 'y', 'float') }}}; + {{{ makeSetValue('ptr', C_STRUCTS.SDL_TouchFingerEvent.dx, 'dx', 'float') }}}; + {{{ makeSetValue('ptr', C_STRUCTS.SDL_TouchFingerEvent.dy, 'dy', 'float') }}}; + if (touch.force !== undefined) { + {{{ makeSetValue('ptr', C_STRUCTS.SDL_TouchFingerEvent.pressure, 'touch.force', 'float') }}}; + } else { // No pressure data, send a digital 0/1 pressure. + {{{ makeSetValue('ptr', C_STRUCTS.SDL_TouchFingerEvent.pressure, 'event.type == "touchend" ? 0 : 1', 'float') }}}; + } + break; + } case 'unload': { {{{ makeSetValue('ptr', C_STRUCTS.SDL_KeyboardEvent.type, 'SDL.DOMEventToSDLEvent[event.type]', 'i32') }}}; break; @@ -948,14 +1062,17 @@ var LibrarySDL = { SDL.keyboardState = _malloc(0x10000); // Our SDL needs 512, but 64K is safe for older SDLs _memset(SDL.keyboardState, 0, 0x10000); // Initialize this structure carefully for closure - SDL.DOMEventToSDLEvent['keydown'] = 0x300 /* SDL_KEYDOWN */; - SDL.DOMEventToSDLEvent['keyup'] = 0x301 /* SDL_KEYUP */; - SDL.DOMEventToSDLEvent['keypress'] = 0x303 /* SDL_TEXTINPUT */; - SDL.DOMEventToSDLEvent['mousedown'] = 0x401 /* SDL_MOUSEBUTTONDOWN */; - SDL.DOMEventToSDLEvent['mouseup'] = 0x402 /* SDL_MOUSEBUTTONUP */; - SDL.DOMEventToSDLEvent['mousemove'] = 0x400 /* SDL_MOUSEMOTION */; - SDL.DOMEventToSDLEvent['unload'] = 0x100 /* SDL_QUIT */; - SDL.DOMEventToSDLEvent['resize'] = 0x7001 /* SDL_VIDEORESIZE/SDL_EVENT_COMPAT2 */; + SDL.DOMEventToSDLEvent['keydown'] = 0x300 /* SDL_KEYDOWN */; + SDL.DOMEventToSDLEvent['keyup'] = 0x301 /* SDL_KEYUP */; + SDL.DOMEventToSDLEvent['keypress'] = 0x303 /* SDL_TEXTINPUT */; + SDL.DOMEventToSDLEvent['mousedown'] = 0x401 /* SDL_MOUSEBUTTONDOWN */; + SDL.DOMEventToSDLEvent['mouseup'] = 0x402 /* SDL_MOUSEBUTTONUP */; + SDL.DOMEventToSDLEvent['mousemove'] = 0x400 /* SDL_MOUSEMOTION */; + SDL.DOMEventToSDLEvent['touchstart'] = 0x700 /* SDL_FINGERDOWN */; + SDL.DOMEventToSDLEvent['touchend'] = 0x701 /* SDL_FINGERUP */; + SDL.DOMEventToSDLEvent['touchmove'] = 0x702 /* SDL_FINGERMOTION */; + SDL.DOMEventToSDLEvent['unload'] = 0x100 /* SDL_QUIT */; + SDL.DOMEventToSDLEvent['resize'] = 0x7001 /* SDL_VIDEORESIZE/SDL_EVENT_COMPAT2 */; // These are not technically DOM events; the HTML gamepad API is poll-based. // However, we define them here, as the rest of the SDL code assumes that // all SDL events originate as DOM events. @@ -1025,7 +1142,7 @@ var LibrarySDL = { }, SDL_SetVideoMode: function(width, height, depth, flags) { - ['mousedown', 'mouseup', 'mousemove', 'DOMMouseScroll', 'mousewheel', 'mouseout'].forEach(function(event) { + ['touchstart', 'touchend', 'touchmove', 'mousedown', 'mouseup', 'mousemove', 'DOMMouseScroll', 'mousewheel', 'mouseout'].forEach(function(event) { Module['canvas'].addEventListener(event, SDL.receiveEvent, true); }); @@ -1476,20 +1593,28 @@ var LibrarySDL = { return 0; }, - SDL_PeepEvents: function(events, numEvents, action, from, to) { + SDL_PeepEvents: function(events, requestedEventCount, action, from, to) { switch(action) { case 2: { // SDL_GETEVENT - assert(numEvents == 1); - var got = 0; - while (SDL.events.length > 0 && numEvents > 0) { - var type = SDL.DOMEventToSDLEvent[SDL.events[0].type]; - if (type < from || type > to) break; - SDL.makeCEvent(SDL.events.shift(), events); - got++; - numEvents--; - // events += sizeof(..) + // We only handle 1 event right now + assert(requestedEventCount == 1); + + var index = 0; + var retrievedEventCount = 0; + // this should look through the entire queue until it has filled up the events + // array + while (index < SDL.events.length && retrievedEventCount < requestedEventCount) { + var event = SDL.events[index]; + var type = SDL.DOMEventToSDLEvent[event.type]; + if (from <= type && type <= to) { + SDL.makeCEvent(event, events); + SDL.events.splice(index, 1); + retrievedEventCount++; + } else { + index++; + } } - return got; + return retrievedEventCount; } default: throw 'SDL_PeepEvents does not yet support that action: ' + action; } diff --git a/src/modules.js b/src/modules.js index 2d2a75d0..fd5c23cd 100644 --- a/src/modules.js +++ b/src/modules.js @@ -21,6 +21,7 @@ var LLVM = { CONVERSIONS: set('inttoptr', 'ptrtoint', 'uitofp', 'sitofp', 'fptosi', 'fptoui', 'fpext', 'fptrunc'), INTRINSICS_32: set('_llvm_memcpy_p0i8_p0i8_i64', '_llvm_memmove_p0i8_p0i8_i64', '_llvm_memset_p0i8_i64'), // intrinsics that need args converted to i32 in USE_TYPED_ARRAYS == 2 MATHOP_IGNORABLES: set('exact', 'nnan', 'ninf', 'nsz', 'arcp', 'fast'), + PARAM_IGNORABLES: set('nocapture', 'readonly', 'readnone'), }; LLVM.GLOBAL_MODIFIERS = set(keys(LLVM.LINKAGES).concat(['constant', 'global', 'hidden'])); diff --git a/src/parseTools.js b/src/parseTools.js index 4fb76196..4396abd9 100644 --- a/src/parseTools.js +++ b/src/parseTools.js @@ -467,7 +467,7 @@ function parseParamTokens(params) { // handle 'byval' and 'byval align X'. We store the alignment in 'byVal' byVal = QUANTUM_SIZE; segment.splice(1, 1); - if (segment[1] && (segment[1].text === 'nocapture' || segment[1].text === 'readonly')) { + if (segment[1] && (segment[1].text in LLVM.PARAM_IGNORABLES)) { segment.splice(1, 1); } if (segment[1] && segment[1].text === 'align') { @@ -476,7 +476,7 @@ function parseParamTokens(params) { segment.splice(1, 2); } } - if (segment[1] && (segment[1].text === 'nocapture' || segment[1].text === 'readonly')) { + if (segment[1] && (segment[1].text in LLVM.PARAM_IGNORABLES)) { segment.splice(1, 1); } if (segment.length == 1) { diff --git a/src/preamble.js b/src/preamble.js index 89ab5026..5dd8ada1 100644 --- a/src/preamble.js +++ b/src/preamble.js @@ -207,6 +207,14 @@ function SAFE_HEAP_LOAD(dest, bytes, isFloat, unsigned) { return ret; } +function SAFE_FT_MASK(value, mask) { + var ret = value & mask; + if (ret !== value) { + abort('Function table mask error: function pointer is ' + value + ' which is masked by ' + mask + ', the likely cause of this is that the function pointer is being called by the wrong type.'); + } + return ret; +} + #endif #endif diff --git a/src/relooper/Relooper.cpp b/src/relooper/Relooper.cpp index 780a6d59..ce9232d9 100644 --- a/src/relooper/Relooper.cpp +++ b/src/relooper/Relooper.cpp @@ -243,7 +243,7 @@ void Block::Render(bool InLoop) { Details = ProcessedBranchesOut[DefaultTarget]; } bool SetCurrLabel = (SetLabel && Target->IsCheckedMultipleEntry) || ForceSetLabel; - bool HasFusedContent = Fused && contains(Fused->InnerMap, Target); + bool HasFusedContent = Fused && contains(Fused->InnerMap, Target->Id); bool HasContent = SetCurrLabel || Details->Type != Branch::Direct || HasFusedContent || Details->Code; if (iter != ProcessedBranchesOut.end()) { // If there is nothing to show in this branch, omit the condition @@ -286,7 +286,7 @@ void Block::Render(bool InLoop) { if (!First) Indenter::Indent(); Details->Render(Target, SetCurrLabel); if (HasFusedContent) { - Fused->InnerMap.find(Target)->second->Render(InLoop); + Fused->InnerMap.find(Target->Id)->second->Render(InLoop); } else if (Details->Type == Branch::Nested) { // Nest the parent content here, and remove it from showing up afterwards as Next assert(Parent->Next); @@ -312,18 +312,28 @@ void Block::Render(bool InLoop) { // MultipleShape void MultipleShape::RenderLoopPrefix() { - if (NeedLoop) { - if (Labeled) { - PrintIndented("L%d: do {\n", Id); + if (Breaks) { + if (UseSwitch) { + if (Labeled) { + PrintIndented("L%d: ", Id); + } } else { - PrintIndented("do {\n"); + if (Labeled) { + if (UseSwitch) { + PrintIndented("L%d: ", Id); + } else { + PrintIndented("L%d: do {\n", Id); + } + } else { + PrintIndented("do {\n"); + } + Indenter::Indent(); } - Indenter::Indent(); } } void MultipleShape::RenderLoopPostfix() { - if (NeedLoop) { + if (Breaks && !UseSwitch) { Indenter::Unindent(); PrintIndented("} while(0);\n"); } @@ -332,32 +342,41 @@ void MultipleShape::RenderLoopPostfix() { void MultipleShape::Render(bool InLoop) { RenderLoopPrefix(); - // We know that blocks with the same Id were split from the same source, so their contents are identical and they are logically the same, so re-merge them here - typedef std::map<int, Shape*> IdShapeMap; - IdShapeMap IdMap; - for (BlockShapeMap::iterator iter = InnerMap.begin(); iter != InnerMap.end(); iter++) { - int Id = iter->first->Id; - IdShapeMap::iterator Test = IdMap.find(Id); - if (Test != IdMap.end()) { - assert(Shape::IsSimple(iter->second) && Shape::IsSimple(Test->second)); // we can only merge simple blocks, something horrible has gone wrong if we see anything else - continue; + if (!UseSwitch) { + // emit an if-else chain + bool First = true; + for (IdShapeMap::iterator iter = InnerMap.begin(); iter != InnerMap.end(); iter++) { + if (AsmJS) { + PrintIndented("%sif ((label|0) == %d) {\n", First ? "" : "else ", iter->first); + } else { + PrintIndented("%sif (label == %d) {\n", First ? "" : "else ", iter->first); + } + First = false; + Indenter::Indent(); + iter->second->Render(InLoop); + Indenter::Unindent(); + PrintIndented("}\n"); } - IdMap[iter->first->Id] = iter->second; - } - - bool First = true; - for (IdShapeMap::iterator iter = IdMap.begin(); iter != IdMap.end(); iter++) { + } else { + // emit a switch if (AsmJS) { - PrintIndented("%sif ((label|0) == %d) {\n", First ? "" : "else ", iter->first); + PrintIndented("switch (label|0) {\n"); } else { - PrintIndented("%sif (label == %d) {\n", First ? "" : "else ", iter->first); + PrintIndented("switch (label) {\n"); } - First = false; Indenter::Indent(); - iter->second->Render(InLoop); + for (IdShapeMap::iterator iter = InnerMap.begin(); iter != InnerMap.end(); iter++) { + PrintIndented("case %d: {\n", iter->first); + Indenter::Indent(); + iter->second->Render(InLoop); + PrintIndented("break;\n"); + Indenter::Unindent(); + PrintIndented("}\n"); + } Indenter::Unindent(); PrintIndented("}\n"); } + RenderLoopPostfix(); if (Next) Next->Render(InLoop); } @@ -547,7 +566,7 @@ void Relooper::Calculate(Block *Entry) { PriorOut->Ancestor = Ancestor; PriorOut->Type = Type; if (MultipleShape *Multiple = Shape::IsMultiple(Ancestor)) { - Multiple->NeedLoop++; // We are breaking out of this Multiple, so need a loop + Multiple->Breaks++; // We are breaking out of this Multiple, so need a loop } iter++; // carefully increment iter before erasing Target->BranchesIn.erase(Prior); @@ -853,7 +872,7 @@ void Relooper::Calculate(Block *Entry) { iter = Next; // increment carefully because Solipsize can remove us } } - Multiple->InnerMap[CurrEntry] = Process(CurrBlocks, CurrEntries, NULL); + Multiple->InnerMap[CurrEntry->Id] = Process(CurrBlocks, CurrEntries, NULL); // If we are not fused, then our entries will actually be checked if (!Fused) { CurrEntry->IsCheckedMultipleEntry = true; @@ -867,6 +886,11 @@ void Relooper::Calculate(Block *Entry) { NextEntries.insert(Entry); } } + // The multiple has been created, we can decide how to implement it + if (Multiple->InnerMap.size() >= 10) { + Multiple->UseSwitch = true; + Multiple->Breaks++; // switch captures breaks + } return Multiple; } @@ -1021,7 +1045,7 @@ void Relooper::Calculate(Block *Entry) { PostOptimizer(Relooper *ParentInit) : Parent(ParentInit), Closure(NULL) {} #define RECURSE_Multiple(shape, func) \ - for (BlockShapeMap::iterator iter = shape->InnerMap.begin(); iter != shape->InnerMap.end(); iter++) { \ + for (IdShapeMap::iterator iter = shape->InnerMap.begin(); iter != shape->InnerMap.end(); iter++) { \ func(iter->second); \ } #define RECURSE_Loop(shape, func) \ @@ -1042,7 +1066,7 @@ void Relooper::Calculate(Block *Entry) { SHAPE_SWITCH(S, { Out.insert(Simple->Inner); }, { - for (BlockShapeMap::iterator iter = Multiple->InnerMap.begin(); iter != Multiple->InnerMap.end(); iter++) { + for (IdShapeMap::iterator iter = Multiple->InnerMap.begin(); iter != Multiple->InnerMap.end(); iter++) { FollowNaturalFlow(iter->second, Out); } FollowNaturalFlow(Multiple->Next, Out); @@ -1061,7 +1085,7 @@ void Relooper::Calculate(Block *Entry) { SHAPE_SWITCH(Root, { }, { - for (BlockShapeMap::iterator iter = Multiple->InnerMap.begin(); iter != Multiple->InnerMap.end(); iter++) { + for (IdShapeMap::iterator iter = Multiple->InnerMap.begin(); iter != Multiple->InnerMap.end(); iter++) { FindNaturals(iter->second, Root->Natural); } }, { @@ -1111,7 +1135,7 @@ void Relooper::Calculate(Block *Entry) { if (Details->Type == Branch::Break) { Details->Type = Branch::Direct; if (MultipleShape *Multiple = Shape::IsMultiple(Details->Ancestor)) { - Multiple->NeedLoop--; + Multiple->Breaks--; } } else { assert(Details->Type == Branch::Direct); @@ -1130,20 +1154,20 @@ void Relooper::Calculate(Block *Entry) { if (Details->Type != Branch::Direct && contains(NaturalBlocks, Target)) { // note: cannot handle split blocks Details->Type = Branch::Direct; if (MultipleShape *Multiple = Shape::IsMultiple(Details->Ancestor)) { - Multiple->NeedLoop--; + Multiple->Breaks--; } } else if (Details->Type == Branch::Break && LastLoop && LastLoop->Natural == Details->Ancestor->Natural) { // it is important to simplify breaks, as simpler breaks enable other optimizations Details->Labeled = false; if (MultipleShape *Multiple = Shape::IsMultiple(Details->Ancestor)) { - Multiple->NeedLoop--; + Multiple->Breaks--; } } } } }, { - for (BlockShapeMap::iterator iter = Multiple->InnerMap.begin(); iter != Multiple->InnerMap.end(); iter++) { - RemoveUnneededFlows(iter->second, Multiple->Next, Multiple->NeedLoop ? NULL : LastLoop); + for (IdShapeMap::iterator iter = Multiple->InnerMap.begin(); iter != Multiple->InnerMap.end(); iter++) { + RemoveUnneededFlows(iter->second, Multiple->Next, Multiple->Breaks ? NULL : LastLoop); } Next = Multiple->Next; }, { @@ -1169,13 +1193,16 @@ void Relooper::Calculate(Block *Entry) { SHAPE_SWITCH(Root, { MultipleShape *Fused = Shape::IsMultiple(Root->Next); // If we are fusing a Multiple with a loop into this Simple, then visit it now - if (Fused && Fused->NeedLoop) { + if (Fused && Fused->Breaks) { LoopStack.push(Fused); } if (Simple->Inner->BranchVar) { LoopStack.push(NULL); // a switch means breaks are now useless, push a dummy } if (Fused) { + if (Fused->UseSwitch) { + LoopStack.push(NULL); // a switch means breaks are now useless, push a dummy + } RECURSE_Multiple(Fused, FindLabeledLoops); } for (BlockBranchMap::iterator iter = Simple->Inner->ProcessedBranchesOut.begin(); iter != Simple->Inner->ProcessedBranchesOut.end(); iter++) { @@ -1191,10 +1218,13 @@ void Relooper::Calculate(Block *Entry) { } } } + if (Fused && Fused->UseSwitch) { + LoopStack.pop(); + } if (Simple->Inner->BranchVar) { LoopStack.pop(); } - if (Fused && Fused->NeedLoop) { + if (Fused && Fused->Breaks) { LoopStack.pop(); } if (Fused) { @@ -1203,11 +1233,11 @@ void Relooper::Calculate(Block *Entry) { Next = Root->Next; } }, { - if (Multiple->NeedLoop) { + if (Multiple->Breaks) { LoopStack.push(Multiple); } RECURSE(Multiple, FindLabeledLoops); - if (Multiple->NeedLoop) { + if (Multiple->Breaks) { LoopStack.pop(); } Next = Root->Next; @@ -1290,8 +1320,8 @@ void Debugging::Dump(Shape *S, const char *prefix) { printf("<< Simple with block %d\n", Simple->Inner->Id); }, { printf("<< Multiple\n"); - for (BlockShapeMap::iterator iter = Multiple->InnerMap.begin(); iter != Multiple->InnerMap.end(); iter++) { - printf(" with entry %d\n", iter->first->Id); + for (IdShapeMap::iterator iter = Multiple->InnerMap.begin(); iter != Multiple->InnerMap.end(); iter++) { + printf(" with entry %d\n", iter->first); } }, { printf("<< Loop\n"); diff --git a/src/relooper/Relooper.h b/src/relooper/Relooper.h index 152bae0e..c86e63ac 100644 --- a/src/relooper/Relooper.h +++ b/src/relooper/Relooper.h @@ -132,8 +132,6 @@ struct SimpleShape : public Shape { } }; -typedef std::map<Block*, Shape*> BlockShapeMap; - // A shape that may be implemented with a labeled loop. struct LabeledShape : public Shape { bool Labeled; // If we have a loop, whether it needs to be labeled @@ -141,12 +139,16 @@ struct LabeledShape : public Shape { LabeledShape(ShapeType TypeInit) : Shape(TypeInit), Labeled(false) {} }; +// Blocks with the same id were split and are identical, so we just care about ids in Multiple entries +typedef std::map<int, Shape*> IdShapeMap; + struct MultipleShape : public LabeledShape { - BlockShapeMap InnerMap; // entry block -> shape - int NeedLoop; // If we have branches, we need a loop. This is a counter of loop requirements, - // if we optimize it to 0, the loop is unneeded + IdShapeMap InnerMap; // entry block ID -> shape + int Breaks; // If we have branches on us, we need a loop (or a switch). This is a counter of requirements, + // if we optimize it to 0, the loop is unneeded + bool UseSwitch; // Whether to switch on label as opposed to an if-else chain - MultipleShape() : LabeledShape(Multiple), NeedLoop(0) {} + MultipleShape() : LabeledShape(Multiple), Breaks(0), UseSwitch(false) {} void RenderLoopPrefix(); void RenderLoopPostfix(); diff --git a/src/settings.js b/src/settings.js index 8b046e95..a9a72425 100644 --- a/src/settings.js +++ b/src/settings.js @@ -39,7 +39,7 @@ var CHECK_SIGNS = 0; // Runtime errors for signing issues that need correcting. var ASSERTIONS = 1; // Whether we should add runtime assertions, for example to // check that each allocation to the stack does not - // exceed it's size, whether all allocations (stack and static) are + // exceed its size, whether all allocations (stack and static) are // of positive size, etc., whether we should throw if we encounter a bad __label__, i.e., // if code flow runs into a fault // ASSERTIONS == 2 gives even more runtime checks @@ -338,7 +338,7 @@ var EXPORTED_FUNCTIONS = ['_main', '_malloc']; var EXPORT_ALL = 0; // If true, we export all the symbols. Note that this does *not* affect LLVM, so it can // still eliminate functions as dead. This just exports them on the Module object. var EXPORT_BINDINGS = 0; // Export all bindings generator functions (prefixed with emscripten_bind_). This - // is necessary to use the bindings generator with asm.js + // is necessary to use the WebIDL binder or bindings generator with asm.js var RETAIN_COMPILER_SETTINGS = 0; // Remembers the values of these settings, and makes them accessible // through Runtime.getCompilerSetting and emscripten_get_compiler_setting. // To see what is retained, look for compilerSettings in the generated code. diff --git a/src/shell.html b/src/shell.html index 226f12b9..1e213024 100644 --- a/src/shell.html +++ b/src/shell.html @@ -1273,6 +1273,13 @@ } }; Module.setStatus('Downloading...'); + window.onerror = function() { + Module.setStatus('Exception thrown, see JavaScript console'); + spinnerElement.style.display = 'none'; + Module.setStatus = function(text) { + if (text) Module.printErr('[post-exception status] ' + text); + }; + }; </script> {{{ SCRIPT }}} </body> diff --git a/src/shell_minimal.html b/src/shell_minimal.html index 6f483719..7dd67929 100644 --- a/src/shell_minimal.html +++ b/src/shell_minimal.html @@ -129,6 +129,13 @@ } }; Module.setStatus('Downloading...'); + window.onerror = function() { + Module.setStatus('Exception thrown, see JavaScript console'); + spinnerElement.style.display = 'none'; + Module.setStatus = function(text) { + if (text) Module.printErr('[post-exception status] ' + text); + }; + }; </script> {{{ SCRIPT }}} </body> diff --git a/src/struct_info.json b/src/struct_info.json index 2a2b4c64..f762bf2b 100644 --- a/src/struct_info.json +++ b/src/struct_info.json @@ -948,11 +948,10 @@ ], "SDL_MouseMotionEvent": [ "type", + "timestamp", "windowID", + "which", "state", - "padding1", - "padding2", - "padding3", "x", "y", "xrel", @@ -960,7 +959,9 @@ ], "SDL_MouseButtonEvent": [ "type", + "timestamp", "windowID", + "which", "button", "state", "padding1", @@ -983,6 +984,17 @@ "state", "padding1" ], + "SDL_TouchFingerEvent": [ + "type", + "timestamp", + "touchId", + "fingerId", + "x", + "y", + "dx", + "dy", + "pressure" + ], "SDL_ResizeEvent": [ "type", "w", @@ -991,6 +1003,11 @@ } }, { + "file": "SDL/SDL_touch.h", + "defines": ["SDL_TOUCH_MOUSEID"], + "structs": {} + }, + { "file": "SDL/SDL_audio.h", "defines": [ "SDL_AUDIO_MASK_BITSIZE", diff --git a/system/include/SDL/COPYING b/system/include/SDL/COPYING index 15639581..71cc7e42 100644 --- a/system/include/SDL/COPYING +++ b/system/include/SDL/COPYING @@ -17,3 +17,8 @@ freely, subject to the following restrictions: 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. + +--- + + Portions of these headers taken from SDL2 (where noted) + Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org> diff --git a/system/include/SDL/SDL_events.h b/system/include/SDL/SDL_events.h index 8be00ceb..183ea4b2 100644 --- a/system/include/SDL/SDL_events.h +++ b/system/include/SDL/SDL_events.h @@ -2,6 +2,9 @@ Simple DirectMedia Layer Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org> + Portions of these headers taken from SDL2 (where noted) + Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org> + This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. @@ -182,33 +185,43 @@ typedef struct SDL_TextInputEvent /** * \brief Mouse motion event structure (event.motion.*) */ +/*================================= IMPORTANT ================================ + The version of SDL_MouseMotionEvent that comes in these (emscripten) + headers is taken from the finalized version of SDL2 + ============================================================================*/ + typedef struct SDL_MouseMotionEvent { Uint32 type; /**< ::SDL_MOUSEMOTION */ + Uint32 timestamp; Uint32 windowID; /**< The window with mouse focus, if any */ - Uint8 state; /**< The current button state */ - Uint8 padding1; - Uint8 padding2; - Uint8 padding3; - int x; /**< X coordinate, relative to window */ - int y; /**< Y coordinate, relative to window */ - int xrel; /**< The relative motion in the X direction */ - int yrel; /**< The relative motion in the Y direction */ + Uint32 which; /**< The mouse instance id, or SDL_TOUCH_MOUSEID */ + Uint32 state; /**< The current button state */ + Sint32 x; /**< X coordinate, relative to window */ + Sint32 y; /**< Y coordinate, relative to window */ + Sint32 xrel; /**< The relative motion in the X direction */ + Sint32 yrel; /**< The relative motion in the Y direction */ } SDL_MouseMotionEvent; /** * \brief Mouse button event structure (event.button.*) */ +/*================================= IMPORTANT ================================ + The version of SDL_MouseButtonEvent that comes in these (emscripten) + headers is taken from the finalized version of SDL2 + ============================================================================*/ typedef struct SDL_MouseButtonEvent { Uint32 type; /**< ::SDL_MOUSEBUTTONDOWN or ::SDL_MOUSEBUTTONUP */ + Uint32 timestamp; Uint32 windowID; /**< The window with mouse focus, if any */ + Uint32 which; /**< The mouse instance id, or SDL_TOUCH_MOUSEID */ Uint8 button; /**< The mouse button index */ Uint8 state; /**< ::SDL_PRESSED or ::SDL_RELEASED */ Uint8 padding1; Uint8 padding2; - int x; /**< X coordinate, relative to window */ - int y; /**< Y coordinate, relative to window */ + Sint32 x; /**< X coordinate, relative to window */ + Sint32 y; /**< Y coordinate, relative to window */ } SDL_MouseButtonEvent; /** @@ -217,9 +230,11 @@ typedef struct SDL_MouseButtonEvent typedef struct SDL_MouseWheelEvent { Uint32 type; /**< ::SDL_MOUSEWHEEL */ + Uint32 timestamp; Uint32 windowID; /**< The window with mouse focus, if any */ - int x; /**< The amount scrolled horizontally */ - int y; /**< The amount scrolled vertically */ + Uint32 which; /**< The mouse instance id, or SDL_TOUCH_MOUSEID */ + Sint32 x; /**< The amount scrolled horizontally */ + Sint32 y; /**< The amount scrolled vertically */ } SDL_MouseWheelEvent; /** @@ -281,24 +296,25 @@ typedef struct SDL_JoyButtonEvent /** - * \brief Touch finger motion/finger event structure (event.tmotion.*) + * \brief Touch finger motion/finger event structure (event.tfinger.*) */ + +/*================================= IMPORTANT ================================ + The version of SDL_TouchFingerEvent that comes in these (emscripten) + headers is taken from the finalized version of SDL2 + ============================================================================*/ + typedef struct SDL_TouchFingerEvent { - Uint32 type; /**< ::SDL_FINGERMOTION OR - SDL_FINGERDOWN OR SDL_FINGERUP*/ - Uint32 windowID; /**< The window with mouse focus, if any */ - SDL_TouchID touchId; /**< The touch device id */ + Uint32 type; /**< ::SDL_FINGERMOTION or ::SDL_FINGERDOWN or ::SDL_FINGERUP */ + Uint32 timestamp; + SDL_TouchID touchId; /**< The touch device id */ SDL_FingerID fingerId; - Uint8 state; /**< The current button state */ - Uint8 padding1; - Uint8 padding2; - Uint8 padding3; - Uint16 x; - Uint16 y; - Sint16 dx; - Sint16 dy; - Uint16 pressure; + float x; /**< Normalized in the range 0...1 */ + float y; /**< Normalized in the range 0...1 */ + float dx; /**< Normalized in the range 0...1 */ + float dy; /**< Normalized in the range 0...1 */ + float pressure; /**< Normalized in the range 0...1 */ } SDL_TouchFingerEvent; @@ -434,7 +450,7 @@ typedef union SDL_Event SDL_QuitEvent quit; /**< Quit request event data */ SDL_UserEvent user; /**< Custom event data */ SDL_SysWMEvent syswm; /**< System dependent window event data */ - SDL_TouchFingerEvent tfinger; /**< Touch finger event data */ + SDL_TouchFingerEvent tfinger; /**< SDL2 Touch finger event data */ SDL_TouchButtonEvent tbutton; /**< Touch button event data */ SDL_MultiGestureEvent mgesture; /**< Multi Finger Gesture data */ SDL_DollarGestureEvent dgesture; /**< Multi Finger Gesture data */ diff --git a/system/include/SDL/SDL_touch.h b/system/include/SDL/SDL_touch.h index 587efcbf..fe238f10 100644 --- a/system/include/SDL/SDL_touch.h +++ b/system/include/SDL/SDL_touch.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -19,9 +19,15 @@ 3. This notice may not be removed or altered from any source distribution. */ +/* + ================================= IMPORTANT ================================ + This header taken from SDL2 + ============================================================================ +*/ + /** * \file SDL_touch.h - * + * * Include file for SDL touch event handling. */ @@ -35,90 +41,52 @@ #include "begin_code.h" /* Set up for C function definitions, even when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ extern "C" { -/* *INDENT-ON* */ #endif - typedef Sint64 SDL_TouchID; typedef Sint64 SDL_FingerID; +typedef struct SDL_Finger +{ + SDL_FingerID id; + float x; + float y; + float pressure; +} SDL_Finger; -struct SDL_Finger { - SDL_FingerID id; - Uint16 x; - Uint16 y; - Uint16 pressure; - Uint16 xdelta; - Uint16 ydelta; - Uint16 last_x, last_y,last_pressure; /* the last reported coordinates */ - SDL_bool down; -}; - -typedef struct SDL_Touch SDL_Touch; -typedef struct SDL_Finger SDL_Finger; - - -struct SDL_Touch { - - /* Free the touch when it's time */ - void (*FreeTouch) (SDL_Touch * touch); - - /* data common for tablets */ - float pressure_max, pressure_min; - float x_max,x_min; - float y_max,y_min; - Uint16 xres,yres,pressureres; - float native_xres,native_yres,native_pressureres; - float tilt; /* for future use */ - float rotation; /* for future use */ - - /* Data common to all touch */ - SDL_TouchID id; - SDL_Window *focus; - - char *name; - Uint8 buttonstate; - SDL_bool relative_mode; - SDL_bool flush_motion; - - int num_fingers; - int max_fingers; - SDL_Finger** fingers; - - void *driverdata; -}; - +/* Used as the device ID for mouse events simulated with touch input */ +#define SDL_TOUCH_MOUSEID ((Uint32)-1) /* Function prototypes */ /** - * \brief Get the touch object at the given id. - * - * + * \brief Get the number of registered touch devices. */ - extern DECLSPEC SDL_Touch* SDLCALL SDL_GetTouch(SDL_TouchID id); +extern DECLSPEC int SDLCALL SDL_GetNumTouchDevices(void); +/** + * \brief Get the touch ID with the given index, or 0 if the index is invalid. + */ +extern DECLSPEC SDL_TouchID SDLCALL SDL_GetTouchDevice(int index); +/** + * \brief Get the number of active fingers for a given touch device. + */ +extern DECLSPEC int SDLCALL SDL_GetNumTouchFingers(SDL_TouchID touchID); /** - * \brief Get the finger object of the given touch, at the given id. - * - * + * \brief Get the finger object of the given touch, with the given index. */ - extern - DECLSPEC SDL_Finger* SDLCALL SDL_GetFinger(SDL_Touch *touch, SDL_FingerID id); +extern DECLSPEC SDL_Finger * SDLCALL SDL_GetTouchFinger(SDL_TouchID touchID, int index); /* Ends C function definitions when using C++ */ #ifdef __cplusplus -/* *INDENT-OFF* */ } -/* *INDENT-ON* */ #endif #include "close_code.h" -#endif /* _SDL_mouse_h */ +#endif /* _SDL_touch_h */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/system/include/emscripten/bind.h b/system/include/emscripten/bind.h index 29e6a56e..699e834b 100644 --- a/system/include/emscripten/bind.h +++ b/system/include/emscripten/bind.h @@ -932,7 +932,7 @@ namespace emscripten { // NOTE: this returns the class type, not the pointer type template<typename T> inline TYPEID getActualType(T* ptr) { - return reinterpret_cast<TYPEID>(&typeid(*ptr)); + return getLightTypeID(*ptr); }; } @@ -976,15 +976,15 @@ namespace emscripten { template<typename T> struct SmartPtrIfNeeded { template<typename U> - SmartPtrIfNeeded(U& cls) { - cls.template smart_ptr<T>(); + SmartPtrIfNeeded(U& cls, const char* smartPtrName) { + cls.template smart_ptr<T>(smartPtrName); } }; template<typename T> struct SmartPtrIfNeeded<T*> { template<typename U> - SmartPtrIfNeeded(U&) { + SmartPtrIfNeeded(U&, const char*) { } }; }; @@ -1024,7 +1024,7 @@ namespace emscripten { } template<typename PointerType> - const class_& smart_ptr() const { + const class_& smart_ptr(const char* name) const { using namespace internal; typedef smart_ptr_trait<PointerType> PointerTrait; @@ -1040,7 +1040,7 @@ namespace emscripten { _embind_register_smart_ptr( TypeID<PointerType>::get(), TypeID<PointeeType>::get(), - typeid(PointerType).name(), + name, PointerTrait::get_sharing_policy(), getSignature(get), reinterpret_cast<GenericFunction>(get), @@ -1078,10 +1078,10 @@ namespace emscripten { } template<typename SmartPtr, typename... Args, typename... Policies> - const class_& smart_ptr_constructor(SmartPtr (*factory)(Args...), Policies...) const { + const class_& smart_ptr_constructor(const char* smartPtrName, SmartPtr (*factory)(Args...), Policies...) const { using namespace internal; - smart_ptr<SmartPtr>(); + smart_ptr<SmartPtr>(smartPtrName); typename WithPolicies<Policies...>::template ArgTypeList<SmartPtr, Args...> args; auto invoke = &Invoker<SmartPtr, Args...>::invoke; @@ -1096,12 +1096,12 @@ namespace emscripten { } template<typename WrapperType, typename PointerType = WrapperType*> - const class_& allow_subclass() const { + const class_& allow_subclass(const char* wrapperClassName, const char* pointerName = "<UnknownPointerName>") const { using namespace internal; - auto cls = class_<WrapperType, base<ClassType>>(typeid(WrapperType).name()) + auto cls = class_<WrapperType, base<ClassType>>(wrapperClassName) ; - SmartPtrIfNeeded<PointerType> _(cls); + SmartPtrIfNeeded<PointerType> _(cls, pointerName); return class_function( "implement", diff --git a/system/include/emscripten/wire.h b/system/include/emscripten/wire.h index 05b3ac33..c20e2f55 100644 --- a/system/include/emscripten/wire.h +++ b/system/include/emscripten/wire.h @@ -15,22 +15,66 @@ #define EMSCRIPTEN_ALWAYS_INLINE __attribute__((always_inline)) namespace emscripten { + #ifndef EMSCRIPTEN_HAS_UNBOUND_TYPE_NAMES + #define EMSCRIPTEN_HAS_UNBOUND_TYPE_NAMES 1 + #endif + + + #if EMSCRIPTEN_HAS_UNBOUND_TYPE_NAMES + constexpr bool has_unbound_type_names = true; + #else + constexpr bool has_unbound_type_names = false; + #endif + namespace internal { typedef void (*GenericFunction)(); - typedef const struct _TYPEID* TYPEID; + typedef const struct _TYPEID {}* TYPEID; + + + // We don't need the full std::type_info implementation. We + // just need a unique identifier per type and polymorphic type + // identification. + + template<typename T> + struct CanonicalizedID { + static TYPEID get() { + static _TYPEID c; + return &c; + } + }; + + template<typename T> + struct Canonicalized { + typedef typename std::remove_cv<typename std::remove_reference<T>::type>::type type; + }; + + template<typename T> + struct LightTypeID { + static TYPEID get() { + typedef typename Canonicalized<T>::type C; + if (has_unbound_type_names || std::is_polymorphic<C>::value) { + return reinterpret_cast<TYPEID>(&typeid(C)); + } else { + return CanonicalizedID<C>::get(); + } + } + }; + + template<typename T> + const TYPEID getLightTypeID(const T& value) { + typedef typename Canonicalized<T>::type C; + if (has_unbound_type_names || std::is_polymorphic<C>::value) { + return reinterpret_cast<TYPEID>(&typeid(value)); + } else { + return LightTypeID<T>::get(); + } + } - // This implementation is technically not legal, as it's not - // required that two calls to typeid produce the same exact - // std::type_info instance. That said, it's likely to work - // given Emscripten compiles everything into one binary. - // Should it not work in the future: replace TypeID with an - // int, and store all TypeInfo we see in a map, allocating new - // TypeIDs as we add new items to the map. template<typename T> struct TypeID { static TYPEID get() { - return reinterpret_cast<TYPEID>(&typeid(T)); + return LightTypeID<T>::get(); } }; @@ -53,7 +97,7 @@ namespace emscripten { template<typename T> struct TypeID<AllowedRawPointer<T>> { static TYPEID get() { - return reinterpret_cast<TYPEID>(&typeid(T*)); + return LightTypeID<T*>::get(); } }; diff --git a/system/lib/embind/bind.cpp b/system/lib/embind/bind.cpp index f43d1ea1..37918050 100644 --- a/system/lib/embind/bind.cpp +++ b/system/lib/embind/bind.cpp @@ -14,26 +14,32 @@ using namespace emscripten; extern "C" {
const char* __attribute__((used)) __getTypeName(const std::type_info* ti) {
+ if (has_unbound_type_names) {
#ifdef USE_CXA_DEMANGLE
- int stat;
- char* demangled = abi::__cxa_demangle(ti->name(), NULL, NULL, &stat);
- if (stat == 0 && demangled) {
- return demangled;
- }
+ int stat;
+ char* demangled = abi::__cxa_demangle(ti->name(), NULL, NULL, &stat);
+ if (stat == 0 && demangled) {
+ return demangled;
+ }
- switch (stat) {
- case -1:
- return strdup("<allocation failure>");
- case -2:
- return strdup("<invalid C++ symbol>");
- case -3:
- return strdup("<invalid argument>");
- default:
- return strdup("<unknown error>");
- }
+ switch (stat) {
+ case -1:
+ return strdup("<allocation failure>");
+ case -2:
+ return strdup("<invalid C++ symbol>");
+ case -3:
+ return strdup("<invalid argument>");
+ default:
+ return strdup("<unknown error>");
+ }
#else
- return strdup(ti->name());
+ return strdup(ti->name());
#endif
+ } else {
+ char str[80];
+ sprintf(str, "%p", ti);
+ return strdup(str);
+ }
}
}
diff --git a/tests/cmake/target_html/CMakeLists.txt b/tests/cmake/target_html/CMakeLists.txt index b5c69417..ce26c541 100644 --- a/tests/cmake/target_html/CMakeLists.txt +++ b/tests/cmake/target_html/CMakeLists.txt @@ -10,6 +10,38 @@ else() # Either MinSizeRel, RelWithDebInfo or Release, all which run with optimi SET(linkFlags "-O2") endif() +if (NOT CMAKE_AR OR NOT EXISTS "${CMAKE_AR}") + message(FATAL_ERROR "CMAKE_AR='${CMAKE_AR}' does not exist for Emscripten toolchain!") +endif() + +if (NOT CMAKE_RANLIB OR NOT EXISTS "${CMAKE_RANLIB}") + message(FATAL_ERROR "CMAKE_RANLIB='${CMAKE_RANLIB}' does not exist for Emscripten toolchain!") +endif() + +if (NOT CMAKE_C_COMPILER OR NOT EXISTS "${CMAKE_C_COMPILER}") + message(FATAL_ERROR "CMAKE_C_COMPILER='${CMAKE_C_COMPILER}' does not exist for Emscripten toolchain!") +endif() + +if (NOT CMAKE_CXX_COMPILER OR NOT EXISTS "${CMAKE_CXX_COMPILER}") + message(FATAL_ERROR "CMAKE_CXX_COMPILER='${CMAKE_CXX_COMPILER}' does not exist for Emscripten toolchain!") +endif() + +if (WIN32) + message(FATAL_ERROR "WIN32 should not be defined when cross-compiling!") +endif() + +if (APPLE) + message(FATAL_ERROR "APPLE should not be defined when cross-compiling!") +endif() + +if (NOT EMSCRIPTEN) + message(FATAL_ERROR "EMSCRIPTEN should be defined when cross-compiling!") +endif() + +if (NOT CMAKE_C_SIZEOF_DATA_PTR) + message(FATAL_ERROR "CMAKE_C_SIZEOF_DATA_PTR was not defined!") +endif() + SET(CMAKE_EXECUTABLE_SUFFIX ".html") add_executable(hello_world_gles ${sourceFiles}) diff --git a/tests/core/test_atomic_cxx.cpp b/tests/core/test_atomic_cxx.cpp index e347c34a..f78922a1 100644 --- a/tests/core/test_atomic_cxx.cpp +++ b/tests/core/test_atomic_cxx.cpp @@ -8,7 +8,7 @@ #include <atomic> #include <cstdio> -template<typename TYPE> void test(TYPE mask0, TYPE mask1, TYPE mask2) { +template<typename TYPE, typename UNSIGNED_TYPE> void test(TYPE mask0, TYPE mask1, TYPE mask2) { typedef TYPE dog; const TYPE numMemoryOrders = 6; @@ -54,54 +54,54 @@ template<typename TYPE> void test(TYPE mask0, TYPE mask1, TYPE mask2) { atomicDog = 0; for (TYPE i = 0; i < numMemoryOrders; i++) { TYPE old = atomicDog.fetch_add(1, memoryOrder[i]); - printf("fetch_add %lld: old=%lld new=%lld\n", (long long)i, (long long)old, TYPE(atomicDog)); + printf("fetch_add %lld: old=%lld new=%lld\n", (long long)i, (long long)old, (long long)TYPE(atomicDog)); } // fetch_sub for (TYPE i = 0; i < numMemoryOrders; i++) { TYPE old = atomicDog.fetch_sub(1, memoryOrder[i]); - printf("fetch_sub %lld: old=%lld new=%lld\n", (long long)i, (long long)old, TYPE(atomicDog)); + printf("fetch_sub %lld: old=%lld new=%lld\n", (long long)i, (long long)old, (long long)TYPE(atomicDog)); } // fetch_and for (TYPE i = 0; i < numMemoryOrders; i++) { atomicDog.store(mask0, memoryOrder[i]); TYPE old = atomicDog.fetch_and((1<<i), memoryOrder[i]); - printf("fetch_and %lld: old=%llx, new=%llx\n", (long long)i, (long long)old, TYPE(atomicDog)); + printf("fetch_and %lld: old=%llx, new=%llx\n", (long long)i, (unsigned long long)UNSIGNED_TYPE(old), (unsigned long long)UNSIGNED_TYPE(atomicDog)); } // fetch_or atomicDog = 0; for (TYPE i = 0; i < numMemoryOrders; i++) { TYPE old = atomicDog.fetch_or((1<<i), memoryOrder[i]); - printf("fetch_or %lld: old=%llx, new=%llx\n", (long long)i, (long long)old, TYPE(atomicDog)); + printf("fetch_or %lld: old=%llx, new=%llx\n", (long long)i, (unsigned long long)UNSIGNED_TYPE(old), (unsigned long long)UNSIGNED_TYPE(atomicDog)); } // fetch_xor atomicDog = 0; for (int i = 0; i < numMemoryOrders; i++) { int old = atomicDog.fetch_xor((1<<i), memoryOrder[i]); - printf("fetch_xor %lld: old=%llx, new=%llx\n", (long long)i, (long long)old, TYPE(atomicDog)); + printf("fetch_xor %lld: old=%llx, new=%llx\n", (long long)i, (unsigned long long)UNSIGNED_TYPE(old), (unsigned long long)UNSIGNED_TYPE(atomicDog)); } // operator++, -- atomicDog = 0; atomicDog++; - printf("operator++: %lld\n", TYPE(atomicDog)); + printf("operator++: %lld\n", (long long)TYPE(atomicDog)); atomicDog--; - printf("operator--: %lld\n", TYPE(atomicDog)); + printf("operator--: %lld\n", (long long)TYPE(atomicDog)); // operator +=, -=, &=, |=, ^= atomicDog += 10; - printf("operator+=: %lld\n", TYPE(atomicDog)); + printf("operator+=: %lld\n", (long long)TYPE(atomicDog)); atomicDog -= 5; - printf("operator-=: %lld\n", TYPE(atomicDog)); + printf("operator-=: %lld\n", (long long)TYPE(atomicDog)); atomicDog |= mask0; - printf("operator|=: %llx\n", TYPE(atomicDog)); + printf("operator|=: %llx\n", (unsigned long long)UNSIGNED_TYPE(atomicDog)); atomicDog &= mask1; - printf("operator|=: %llx\n", TYPE(atomicDog)); + printf("operator&=: %llx\n", (unsigned long long)UNSIGNED_TYPE(atomicDog)); atomicDog ^= mask2; - printf("operator^=: %llx\n", TYPE(atomicDog)); + printf("operator^=: %llx\n", (unsigned long long)UNSIGNED_TYPE(atomicDog)); } @@ -109,13 +109,13 @@ int main() { // test 8, 16, 32 and 64-bit data types printf("\n8 bits\n\n"); - test<char>(0xFF, 0xF0, 0x0F); + test<char, unsigned char>(0xFF, 0xF0, 0x0F); printf("\n16 bits\n\n"); - test<short>(0xFFFF, 0xF0F0, 0x0F0F); + test<short, unsigned short>(0xFFFF, 0xF0F0, 0x0F0F); printf("\n32 bits\n\n"); - test<int>(0xFFFFFFFF, 0xF0F0F0F0, 0x0F0F0F0F); + test<int, unsigned int>(0xFFFFFFFF, 0xF0F0F0F0, 0x0F0F0F0F); printf("\n64 bits\n\n"); - test<long long>(0xFFFFFFFFFFFFFFFF, 0xF0F0F0F0F0F0F0F0, 0x0F0F0F0F0F0F0F0F); + test<long long, unsigned long long>(0xFFFFFFFFFFFFFFFF, 0xF0F0F0F0F0F0F0F0, 0x0F0F0F0F0F0F0F0F); // test atomic_flag (should also have memory_orders, but probably doesn't matter // to find the missing atomic functions) diff --git a/tests/core/test_atomic_cxx.txt b/tests/core/test_atomic_cxx.txt index e0beb498..da437b57 100644 --- a/tests/core/test_atomic_cxx.txt +++ b/tests/core/test_atomic_cxx.txt @@ -29,12 +29,12 @@ fetch_sub 2: old=4 new=3 fetch_sub 3: old=3 new=2 fetch_sub 4: old=2 new=1 fetch_sub 5: old=1 new=0 -fetch_and 0: old=ffffffffffffffff, new=1 -fetch_and 1: old=ffffffffffffffff, new=2 -fetch_and 2: old=ffffffffffffffff, new=4 -fetch_and 3: old=ffffffffffffffff, new=8 -fetch_and 4: old=ffffffffffffffff, new=10 -fetch_and 5: old=ffffffffffffffff, new=20 +fetch_and 0: old=ff, new=1 +fetch_and 1: old=ff, new=2 +fetch_and 2: old=ff, new=4 +fetch_and 3: old=ff, new=8 +fetch_and 4: old=ff, new=10 +fetch_and 5: old=ff, new=20 fetch_or 0: old=0, new=1 fetch_or 1: old=1, new=3 fetch_or 2: old=3, new=7 @@ -51,9 +51,9 @@ operator++: 1 operator--: 0 operator+=: 10 operator-=: 5 -operator|=: ffffffff -operator|=: fffffff0 -operator^=: ffffffff +operator|=: ff +operator&=: f0 +operator^=: ff 16 bits @@ -85,12 +85,12 @@ fetch_sub 2: old=4 new=3 fetch_sub 3: old=3 new=2 fetch_sub 4: old=2 new=1 fetch_sub 5: old=1 new=0 -fetch_and 0: old=ffffffffffffffff, new=1 -fetch_and 1: old=ffffffffffffffff, new=2 -fetch_and 2: old=ffffffffffffffff, new=4 -fetch_and 3: old=ffffffffffffffff, new=8 -fetch_and 4: old=ffffffffffffffff, new=10 -fetch_and 5: old=ffffffffffffffff, new=20 +fetch_and 0: old=ffff, new=1 +fetch_and 1: old=ffff, new=2 +fetch_and 2: old=ffff, new=4 +fetch_and 3: old=ffff, new=8 +fetch_and 4: old=ffff, new=10 +fetch_and 5: old=ffff, new=20 fetch_or 0: old=0, new=1 fetch_or 1: old=1, new=3 fetch_or 2: old=3, new=7 @@ -107,9 +107,9 @@ operator++: 1 operator--: 0 operator+=: 10 operator-=: 5 -operator|=: ffffffff -operator|=: fffff0f0 -operator^=: ffffffff +operator|=: ffff +operator&=: f0f0 +operator^=: ffff 32 bits @@ -141,12 +141,12 @@ fetch_sub 2: old=4 new=3 fetch_sub 3: old=3 new=2 fetch_sub 4: old=2 new=1 fetch_sub 5: old=1 new=0 -fetch_and 0: old=ffffffffffffffff, new=1 -fetch_and 1: old=ffffffffffffffff, new=2 -fetch_and 2: old=ffffffffffffffff, new=4 -fetch_and 3: old=ffffffffffffffff, new=8 -fetch_and 4: old=ffffffffffffffff, new=10 -fetch_and 5: old=ffffffffffffffff, new=20 +fetch_and 0: old=ffffffff, new=1 +fetch_and 1: old=ffffffff, new=2 +fetch_and 2: old=ffffffff, new=4 +fetch_and 3: old=ffffffff, new=8 +fetch_and 4: old=ffffffff, new=10 +fetch_and 5: old=ffffffff, new=20 fetch_or 0: old=0, new=1 fetch_or 1: old=1, new=3 fetch_or 2: old=3, new=7 @@ -164,7 +164,7 @@ operator--: 0 operator+=: 10 operator-=: 5 operator|=: ffffffff -operator|=: f0f0f0f0 +operator&=: f0f0f0f0 operator^=: ffffffff 64 bits @@ -220,7 +220,7 @@ operator--: 0 operator+=: 10 operator-=: 5 operator|=: ffffffffffffffff -operator|=: f0f0f0f0f0f0f0f0 +operator&=: f0f0f0f0f0f0f0f0 operator^=: ffffffffffffffff atomic_flag: false done. diff --git a/tests/core/test_polymorph.in b/tests/core/test_polymorph.in index 1f24a1aa..af07dc05 100644 --- a/tests/core/test_polymorph.in +++ b/tests/core/test_polymorph.in @@ -16,6 +16,8 @@ struct Child : Parent { struct Other { int one() { return 11; } int two() { return 22; } + virtual int three() { return 33; } + virtual int four() { return 44; } }; int main() { @@ -24,10 +26,16 @@ int main() { printf("*%d,%d,%d,%d*\n", x->getit(), y->getit(), x->implme(), y->implme()); Other *o = new Other; + int (Other::*Ls)() = &Other::one; printf("*%d*\n", (o->*(Ls))()); Ls = &Other::two; printf("*%d*\n", (o->*(Ls))()); + Ls = &Other::three; + printf("*%d*\n", (o->*(Ls))()); + Ls = &Other::four; + printf("*%d*\n", (o->*(Ls))()); + return 0; } diff --git a/tests/core/test_polymorph.out b/tests/core/test_polymorph.out index 0d036bf0..5163ea8e 100644 --- a/tests/core/test_polymorph.out +++ b/tests/core/test_polymorph.out @@ -1,3 +1,5 @@ *11,74,32,1012* *11* -*22*
\ No newline at end of file +*22* +*33* +*44* diff --git a/tests/embind/embind.test.js b/tests/embind/embind.test.js index e2160c33..6bba4de0 100644 --- a/tests/embind/embind.test.js +++ b/tests/embind/embind.test.js @@ -1408,7 +1408,7 @@ module({ var e = assert.throws(cm.BindingError, function() { cm.passThroughCustomSmartPtr(o); }); - assert.equal('Cannot convert argument of type NSt3__110shared_ptrI20HeldByCustomSmartPtrEE to parameter type 14CustomSmartPtrI20HeldByCustomSmartPtrE', e.message); + assert.equal('Cannot convert argument of type shared_ptr<HeldByCustomSmartPtr> to parameter type CustomSmartPtr<HeldByCustomSmartPtr>', e.message); o.delete(); }); @@ -1646,6 +1646,10 @@ module({ if (typeof INVOKED_FROM_EMSCRIPTEN_TEST_RUNNER === "undefined") { // TODO: Enable this to work in Emscripten runner as well! BaseFixture.extend("unbound types", function() { + if (!cm.hasUnboundTypeNames) { + return; + } + function assertMessage(fn, message) { var e = assert.throws(cm.UnboundTypeError, fn); assert.equal(message, e.message); diff --git a/tests/embind/embind_test.cpp b/tests/embind/embind_test.cpp index d299660a..1b835751 100644 --- a/tests/embind/embind_test.cpp +++ b/tests/embind/embind_test.cpp @@ -1150,8 +1150,8 @@ void callDifferentArguments(AbstractClass& ac, int i, double d, unsigned char f, EMSCRIPTEN_BINDINGS(interface_tests) { class_<AbstractClass>("AbstractClass") - .smart_ptr<std::shared_ptr<AbstractClass>>() - .allow_subclass<AbstractClassWrapper>() + .smart_ptr<std::shared_ptr<AbstractClass>>("shared_ptr<AbstractClass>") + .allow_subclass<AbstractClassWrapper>("AbstractClassWrapper") .function("abstractMethod", &AbstractClass::abstractMethod) .function("optionalMethod", &AbstractClass::optionalMethod) ; @@ -1483,7 +1483,7 @@ EMSCRIPTEN_BINDINGS(tests) { function("emval_test_take_and_return_TupleInStruct", &emval_test_take_and_return_TupleInStruct); class_<ValHolder>("ValHolder") - .smart_ptr<std::shared_ptr<ValHolder>>() + .smart_ptr<std::shared_ptr<ValHolder>>("std::shared_ptr<ValHolder>") .constructor<val>() .function("getVal", &ValHolder::getVal) .function("getValNonConst", &ValHolder::getValNonConst) @@ -1522,7 +1522,7 @@ EMSCRIPTEN_BINDINGS(tests) { function("emval_test_take_and_call_functor", &emval_test_take_and_call_functor); class_<StringHolder>("StringHolder") - .smart_ptr<std::shared_ptr<StringHolder>>() + .smart_ptr<std::shared_ptr<StringHolder>>("shared_ptr<StringHolder>") .constructor<std::string>() .function("set", &StringHolder::set) .function("get", &StringHolder::get) @@ -1566,7 +1566,7 @@ EMSCRIPTEN_BINDINGS(tests) { // register Derived before Base as a test that it's possible to // register base classes afterwards class_<Derived, base<Base>>("Derived") - .smart_ptr<std::shared_ptr<Derived>>() + .smart_ptr<std::shared_ptr<Derived>>("shared_ptr<Derived>") .constructor<>() .function("getClassName", &Derived::getClassName) .function("getMember", &Derived::getMember) @@ -1575,7 +1575,7 @@ EMSCRIPTEN_BINDINGS(tests) { ; class_<Base>("Base") - .smart_ptr<std::shared_ptr<Base>>() + .smart_ptr<std::shared_ptr<Base>>("shared_ptr<Base") .constructor<>() .function("getClassName", &Base::getClassName) .function("getClassNameFromBase", &Base::getClassNameFromBase) @@ -1589,7 +1589,7 @@ EMSCRIPTEN_BINDINGS(tests) { ; class_<SecondBase>("SecondBase") - .smart_ptr<std::shared_ptr<SecondBase>>() + .smart_ptr<std::shared_ptr<SecondBase>>("shared_ptr<SecondBase>") .constructor<>() .function("getClassName", &SecondBase::getClassName) .function("getClassNameFromSecondBase", &SecondBase::getClassNameFromSecondBase) @@ -1612,13 +1612,13 @@ EMSCRIPTEN_BINDINGS(tests) { ; class_<SiblingDerived>("SiblingDerived") - .smart_ptr<std::shared_ptr<SiblingDerived>>() + .smart_ptr<std::shared_ptr<SiblingDerived>>("shared_ptr<SiblingDerived>") .constructor<>() .function("getClassName", &SiblingDerived::getClassName) ; class_<MultiplyDerived, base<Base>>("MultiplyDerived") - .smart_ptr<std::shared_ptr<MultiplyDerived>>() + .smart_ptr<std::shared_ptr<MultiplyDerived>>("shared_ptr<MultiplyDerived>") .constructor<>() .function("getClassName", &MultiplyDerived::getClassName) .class_function("getInstanceCount", &MultiplyDerived::getInstanceCount) @@ -1630,26 +1630,26 @@ EMSCRIPTEN_BINDINGS(tests) { ; class_<DerivedThrice, base<Derived> >("DerivedThrice") - .smart_ptr<std::shared_ptr<DerivedThrice>>() + .smart_ptr<std::shared_ptr<DerivedThrice>>("shared_ptr<DerivedThrice>") .constructor<>() .function("getClassName", &DerivedThrice::getClassName) ; class_<PolyBase>("PolyBase") - .smart_ptr<std::shared_ptr<PolyBase>>() + .smart_ptr<std::shared_ptr<PolyBase>>("shared_ptr<PolyBase>") .constructor<>() .function("virtualGetClassName", &PolyBase::virtualGetClassName) .function("getClassName", &PolyBase::getClassName) ; class_<PolySecondBase>("PolySecondBase") - .smart_ptr<std::shared_ptr<PolySecondBase>>() + .smart_ptr<std::shared_ptr<PolySecondBase>>("shared_ptr<PolySecondBase>") .constructor<>() .function("getClassName", &PolySecondBase::getClassName) ; class_<PolyDerived, base<PolyBase>>("PolyDerived") - .smart_ptr<std::shared_ptr<PolyDerived>>() + .smart_ptr<std::shared_ptr<PolyDerived>>("shared_ptr<PolyDerived>") .constructor<>() .function("virtualGetClassName", &PolyDerived::virtualGetClassName) .function("getClassName", &PolyDerived::getClassName) @@ -1671,43 +1671,43 @@ EMSCRIPTEN_BINDINGS(tests) { // } class_<PolySiblingDerived, base<PolyBase>>("PolySiblingDerived") - .smart_ptr<std::shared_ptr<PolySiblingDerived>>() + .smart_ptr<std::shared_ptr<PolySiblingDerived>>("shared_ptr<PolySiblingDerived>") .constructor<>() .function("getClassName", &PolySiblingDerived::getClassName) ; class_<PolyMultiplyDerived, base<PolyBase>>("PolyMultiplyDerived") - .smart_ptr<std::shared_ptr<PolyMultiplyDerived>>() + .smart_ptr<std::shared_ptr<PolyMultiplyDerived>>("shared_ptr<PolyMultiplyDerived>") .constructor<>() .function("getClassName", &PolyMultiplyDerived::getClassName) ; class_<PolyDerivedThrice, base<PolyDerived>>("PolyDerivedThrice") - .smart_ptr<std::shared_ptr<PolyDerivedThrice>>() + .smart_ptr<std::shared_ptr<PolyDerivedThrice>>("shared_ptr<PolyDerivedThrice>") .constructor<>() .function("getClassName", &PolyDerivedThrice::getClassName) ; class_<PolyDiamondBase>("PolyDiamondBase") - .smart_ptr<std::shared_ptr<PolyDiamondBase>>() + .smart_ptr<std::shared_ptr<PolyDiamondBase>>("shared_ptr<PolyDiamondBase>") .constructor<>() .function("getClassName", &PolyDiamondBase::getClassName) ; class_<PolyDiamondDerived>("PolyDiamondDerived") - .smart_ptr<std::shared_ptr<PolyDiamondDerived>>() + .smart_ptr<std::shared_ptr<PolyDiamondDerived>>("shared_ptr<PolyDiamondDerived>") .constructor<>() .function("getClassName", &PolyDiamondDerived::getClassName) ; class_<PolyDiamondSiblingDerived>("PolyDiamondSiblingDerived") - .smart_ptr<std::shared_ptr<PolyDiamondSiblingDerived>>() + .smart_ptr<std::shared_ptr<PolyDiamondSiblingDerived>>("shared_ptr<PolyDiamondSiblingDerived>") .constructor<>() .function("getClassName", &PolyDiamondSiblingDerived::getClassName) ; class_<PolyDiamondMultiplyDerived>("PolyDiamondMultiplyDerived") - .smart_ptr<std::shared_ptr<PolyDiamondMultiplyDerived>>() + .smart_ptr<std::shared_ptr<PolyDiamondMultiplyDerived>>("shared_ptr<PolyDiamondMultiplyDerived>") .constructor<>() .function("getClassName", &PolyDiamondMultiplyDerived::getClassName) ; @@ -1825,8 +1825,8 @@ EMSCRIPTEN_BINDINGS(tests) { auto HeldBySmartPtr_class = class_<HeldBySmartPtr>("HeldBySmartPtr"); HeldBySmartPtr_class - .smart_ptr<CustomSmartPtr<HeldBySmartPtr>>() - .smart_ptr_constructor(&std::make_shared<HeldBySmartPtr, int, std::string>) + .smart_ptr<CustomSmartPtr<HeldBySmartPtr>>("CustomSmartPtr<HeldBySmartPtr>") + .smart_ptr_constructor("shared_ptr<HeldbySmartPtr>", &std::make_shared<HeldBySmartPtr, int, std::string>) .class_function("newCustomPtr", HeldBySmartPtr::newCustomPtr) .function("returnThis", &takesHeldBySmartPtrSharedPtr) .property("i", &HeldBySmartPtr::i) @@ -1836,8 +1836,8 @@ EMSCRIPTEN_BINDINGS(tests) { function("takesHeldBySmartPtrSharedPtr", &takesHeldBySmartPtrSharedPtr); class_<HeldByCustomSmartPtr>("HeldByCustomSmartPtr") - .smart_ptr<std::shared_ptr<HeldByCustomSmartPtr>>() - .smart_ptr_constructor(&HeldByCustomSmartPtr::create) + .smart_ptr<std::shared_ptr<HeldByCustomSmartPtr>>("shared_ptr<HeldByCustomSmartPtr>") + .smart_ptr_constructor("CustomSmartPtr<HeldByCustomSmartPtr>", &HeldByCustomSmartPtr::create) .class_function("createSharedPtr", &HeldByCustomSmartPtr::createSharedPtr) .property("i", &HeldByCustomSmartPtr::i) .property("s", &HeldByCustomSmartPtr::s) @@ -2022,7 +2022,7 @@ EMSCRIPTEN_BINDINGS(overloads) { ; class_<MultipleSmartCtors>("MultipleSmartCtors") - .smart_ptr<std::shared_ptr<MultipleSmartCtors>>() + .smart_ptr<std::shared_ptr<MultipleSmartCtors>>("shared_ptr<MultipleSmartCtors>") .constructor(&std::make_shared<MultipleSmartCtors, int>) .constructor(&std::make_shared<MultipleSmartCtors, int, int>) .function("WhichCtorCalled", &MultipleSmartCtors::WhichCtorCalled) @@ -2147,6 +2147,8 @@ struct BoundClass { }; EMSCRIPTEN_BINDINGS(incomplete) { + constant("hasUnboundTypeNames", emscripten::has_unbound_type_names); + function("getUnboundClass", &passThrough<UnboundClass>); class_<HasUnboundBase, base<UnboundClass>>("HasUnboundBase") @@ -2247,7 +2249,7 @@ std::shared_ptr<Base> return_Base_from_DerivedWithOffset(std::shared_ptr<Derived EMSCRIPTEN_BINDINGS(with_adjustment) { class_<DerivedWithOffset, base<Base>>("DerivedWithOffset") - .smart_ptr_constructor(&std::make_shared<DerivedWithOffset>) + .smart_ptr_constructor("shared_ptr<DerivedWithOffset>", &std::make_shared<DerivedWithOffset>) ; function("return_Base_from_DerivedWithOffset", &return_Base_from_DerivedWithOffset); diff --git a/tests/fuzz/19.c b/tests/fuzz/19.c new file mode 100644 index 00000000..d94318c5 --- /dev/null +++ b/tests/fuzz/19.c @@ -0,0 +1,1408 @@ +/* + * This is a RANDOMLY GENERATED PROGRAM. + * + * Generator: csmith 2.2.0 + * Git version: bf42ffd + * Options: --no-volatiles --no-packed-struct --no-math64 + * Seed: 2524651702 + */ + +#include "csmith.h" + + +static long __undefined; + +/* --- Struct/Union Declarations --- */ +/* --- GLOBAL VARIABLES --- */ +static uint32_t g_2[5][1] = {{0xF1124F01L},{0x1F2C29A3L},{0xF1124F01L},{0x1F2C29A3L},{0xF1124F01L}}; +static int32_t g_3 = 0x3FA75C19L; +static uint32_t g_14[6] = {0xD1A4E665L,0xD1A4E665L,0xD1A4E665L,0xD1A4E665L,0xD1A4E665L,0xD1A4E665L}; +static uint32_t g_15 = 18446744073709551615UL; +static int32_t g_34 = 1L; +static int8_t g_36 = 0x6DL; +static uint8_t g_40[7] = {0xEAL,0xEAL,0xEAL,0xEAL,0xEAL,0xEAL,0xEAL}; +static uint8_t g_44 = 0UL; +static uint8_t *g_43 = &g_44; +static int32_t g_46 = 0x461302D9L; +static int32_t g_51[2][8][3] = {{{0x0D357E8FL,0x604C38DBL,0x0D357E8FL},{0x0D357E8FL,0x349DDA4AL,0x1ADF561FL},{0x0D357E8FL,0x2D584125L,(-4L)},{0x0D357E8FL,0x604C38DBL,0x0D357E8FL},{0x0D357E8FL,0x349DDA4AL,0x1ADF561FL},{0x0D357E8FL,0x2D584125L,(-4L)},{0x0D357E8FL,0x604C38DBL,0x0D357E8FL},{0x0D357E8FL,0x349DDA4AL,0x1ADF561FL}},{{0x0D357E8FL,0x2D584125L,(-4L)},{0x0D357E8FL,0x1ADF561FL,(-10L)},{(-10L),0x0D357E8FL,0xCF8610F1L},{(-10L),(-4L),(-9L)},{(-10L),0x1ADF561FL,(-10L)},{(-10L),0x0D357E8FL,0xCF8610F1L},{(-10L),(-4L),(-9L)},{(-10L),0x1ADF561FL,(-10L)}}}; +static uint32_t g_52 = 0x171C63CCL; +static uint32_t g_56 = 0xFBFBE831L; +static uint32_t *g_55 = &g_56; +static const int8_t * const g_132 = &g_36; +static const int8_t * const *g_131 = &g_132; +static int32_t g_140 = 0L; +static int32_t *g_143 = &g_140; +static uint8_t **g_175 = &g_43; +static uint8_t **g_176 = &g_43; +static uint8_t **g_177 = (void*)0; +static int8_t *g_243[6][2][9] = {{{&g_36,&g_36,&g_36,&g_36,&g_36,&g_36,&g_36,&g_36,&g_36},{&g_36,&g_36,&g_36,&g_36,&g_36,&g_36,&g_36,&g_36,&g_36}},{{&g_36,&g_36,&g_36,&g_36,&g_36,&g_36,&g_36,&g_36,&g_36},{&g_36,&g_36,&g_36,&g_36,&g_36,&g_36,&g_36,&g_36,&g_36}},{{&g_36,&g_36,&g_36,&g_36,&g_36,&g_36,&g_36,&g_36,&g_36},{&g_36,&g_36,&g_36,&g_36,&g_36,&g_36,&g_36,&g_36,&g_36}},{{&g_36,&g_36,&g_36,&g_36,&g_36,&g_36,&g_36,&g_36,&g_36},{&g_36,&g_36,&g_36,&g_36,&g_36,&g_36,&g_36,&g_36,&g_36}},{{&g_36,&g_36,&g_36,&g_36,&g_36,&g_36,&g_36,&g_36,&g_36},{&g_36,&g_36,&g_36,&g_36,&g_36,&g_36,&g_36,&g_36,&g_36}},{{&g_36,&g_36,&g_36,&g_36,&g_36,&g_36,&g_36,&g_36,&g_36},{&g_36,&g_36,&g_36,&g_36,&g_36,&g_36,&g_36,&g_36,&g_36}}}; +static int8_t **g_242 = &g_243[5][1][5]; +static int8_t **g_245 = &g_243[5][1][5]; +static uint16_t g_251 = 0x6187L; +static int8_t g_255 = 0xFEL; +static int16_t g_290 = 0xF4DEL; +static int16_t *g_289 = &g_290; +static uint32_t g_294[5] = {0xFDB146E2L,0xFDB146E2L,0xFDB146E2L,0xFDB146E2L,0xFDB146E2L}; +static int32_t g_297[2] = {1L,1L}; +static int32_t *g_312[2][1][6] = {{{(void*)0,(void*)0,&g_51[0][3][1],(void*)0,(void*)0,&g_51[0][3][1]}},{{(void*)0,(void*)0,&g_51[0][3][1],(void*)0,(void*)0,&g_51[0][3][1]}}}; +static uint8_t g_320 = 0xD4L; +static int16_t g_347 = 0x586CL; +static int16_t g_419 = 0xDAAFL; +static uint32_t g_477 = 0x661A1A9FL; +static uint32_t g_705[6] = {1UL,1UL,1UL,1UL,1UL,1UL}; +static uint32_t ** const g_736 = &g_55; +static uint32_t ** const *g_735 = &g_736; +static uint8_t ****g_897 = (void*)0; +static uint8_t ***g_905 = &g_175; +static uint8_t ****g_904[3][6] = {{&g_905,&g_905,&g_905,&g_905,&g_905,&g_905},{&g_905,&g_905,&g_905,&g_905,&g_905,&g_905},{&g_905,&g_905,&g_905,&g_905,&g_905,&g_905}}; +static int32_t **g_961 = &g_312[1][0][4]; +static int32_t ***g_960 = &g_961; +static uint16_t g_969 = 5UL; +static int8_t ***g_1019[7][1][1] = {{{&g_242}},{{&g_242}},{{&g_242}},{{&g_242}},{{&g_242}},{{&g_242}},{{&g_242}}}; +static int8_t ****g_1018 = &g_1019[3][0][0]; +static int32_t g_1055 = (-8L); +static uint32_t g_1099 = 0xAD3B6902L; +static int32_t g_1132 = (-9L); +static int16_t * const *g_1185 = &g_289; +static int16_t * const * const *g_1184 = &g_1185; +static int16_t g_1189 = 0L; +static uint32_t **g_1238 = &g_55; +static uint32_t ***g_1237[8][4][4] = {{{&g_1238,(void*)0,&g_1238,(void*)0},{&g_1238,(void*)0,&g_1238,&g_1238},{(void*)0,&g_1238,&g_1238,(void*)0},{(void*)0,&g_1238,(void*)0,&g_1238}},{{&g_1238,(void*)0,(void*)0,&g_1238},{&g_1238,&g_1238,&g_1238,(void*)0},{&g_1238,&g_1238,&g_1238,(void*)0},{&g_1238,(void*)0,&g_1238,&g_1238}},{{&g_1238,&g_1238,&g_1238,(void*)0},{&g_1238,&g_1238,&g_1238,&g_1238},{&g_1238,(void*)0,(void*)0,&g_1238},{(void*)0,&g_1238,(void*)0,(void*)0}},{{&g_1238,(void*)0,&g_1238,(void*)0},{&g_1238,&g_1238,(void*)0,(void*)0},{(void*)0,(void*)0,&g_1238,&g_1238},{&g_1238,&g_1238,&g_1238,&g_1238}},{{&g_1238,&g_1238,&g_1238,&g_1238},{&g_1238,&g_1238,&g_1238,&g_1238},{&g_1238,&g_1238,&g_1238,&g_1238},{&g_1238,(void*)0,(void*)0,(void*)0}},{{&g_1238,&g_1238,&g_1238,(void*)0},{&g_1238,(void*)0,&g_1238,(void*)0},{(void*)0,&g_1238,(void*)0,&g_1238},{&g_1238,(void*)0,(void*)0,&g_1238}},{{&g_1238,&g_1238,&g_1238,(void*)0},{&g_1238,&g_1238,&g_1238,&g_1238},{&g_1238,(void*)0,&g_1238,(void*)0},{&g_1238,&g_1238,&g_1238,(void*)0}},{{&g_1238,&g_1238,&g_1238,&g_1238},{(void*)0,(void*)0,&g_1238,&g_1238},{(void*)0,&g_1238,&g_1238,(void*)0},{&g_1238,&g_1238,&g_1238,&g_1238}}}; +static uint32_t ***g_1241 = (void*)0; +static uint32_t g_1254[8][1][8] = {{{0x441F7909L,0x441F7909L,0UL,0x5B976413L,18446744073709551610UL,0UL,18446744073709551610UL,0x5B976413L}},{{0x0ECD52E7L,0x5B976413L,0x0ECD52E7L,0xD72EFABCL,0x5B976413L,0x6701CBD7L,0x6701CBD7L,0x5B976413L}},{{0x5B976413L,0x6701CBD7L,0x6701CBD7L,0x5B976413L,0xD72EFABCL,0x0ECD52E7L,0x5B976413L,0x0ECD52E7L}},{{0x5B976413L,18446744073709551610UL,0UL,18446744073709551610UL,0x5B976413L,0UL,0x441F7909L,0x441F7909L}},{{0x0ECD52E7L,18446744073709551610UL,0xD72EFABCL,0xD72EFABCL,18446744073709551610UL,0x0ECD52E7L,0x6701CBD7L,18446744073709551610UL}},{{0x441F7909L,0x6701CBD7L,0xD72EFABCL,0x441F7909L,0xD72EFABCL,0x6701CBD7L,0x441F7909L,0x0ECD52E7L}},{{18446744073709551610UL,0x5B976413L,0UL,0x441F7909L,0x441F7909L,0UL,0x5B976413L,18446744073709551610UL}},{{0x0ECD52E7L,0x441F7909L,0x6701CBD7L,0xD72EFABCL,0x441F7909L,0xD72EFABCL,0x6701CBD7L,0x441F7909L}}}; +static int16_t g_1285 = 0L; +static uint8_t * const **g_1295 = (void*)0; +static uint8_t g_1298 = 0xB8L; +static int16_t g_1333 = 0x34D4L; +static uint32_t g_1334 = 0x1191E655L; +static int32_t g_1509 = 1L; +static uint8_t ***g_1548 = &g_176; +static uint8_t ***g_1549 = (void*)0; +static uint8_t ***g_1550 = (void*)0; +static uint8_t ***g_1551[3][5] = {{&g_176,&g_176,&g_176,&g_176,&g_176},{&g_176,&g_176,&g_176,&g_176,&g_176},{&g_176,&g_176,&g_176,&g_176,&g_176}}; +static uint8_t ***g_1552[10][9] = {{&g_175,&g_177,&g_175,(void*)0,&g_175,&g_175,(void*)0,&g_175,&g_177},{(void*)0,&g_175,&g_175,(void*)0,&g_175,&g_177,&g_176,&g_175,&g_175},{&g_175,&g_175,&g_177,(void*)0,&g_177,&g_175,&g_175,&g_177,&g_175},{&g_176,&g_175,&g_176,(void*)0,&g_177,&g_176,&g_176,&g_176,&g_177},{&g_176,&g_177,&g_177,&g_176,&g_175,&g_176,(void*)0,&g_177,&g_176},{&g_175,&g_177,&g_175,(void*)0,&g_175,&g_175,(void*)0,&g_175,&g_177},{(void*)0,&g_175,&g_175,(void*)0,&g_175,&g_177,&g_176,&g_175,&g_175},{&g_175,&g_175,&g_177,(void*)0,&g_177,&g_175,&g_175,&g_177,&g_175},{&g_176,&g_175,&g_176,(void*)0,&g_177,&g_176,&g_176,&g_176,&g_177},{&g_176,&g_177,&g_177,&g_176,&g_175,&g_176,(void*)0,&g_177,&g_176}}; +static uint8_t **** const g_1547[1][6][2] = {{{&g_1551[1][3],&g_1552[7][4]},{&g_1551[1][3],&g_1551[1][3]},{&g_1552[7][4],&g_1551[1][3]},{&g_1551[1][3],&g_1552[7][4]},{&g_1551[1][3],&g_1551[1][3]},{&g_1552[7][4],&g_1551[1][3]}}}; +static uint8_t **** const *g_1546[5] = {&g_1547[0][2][0],&g_1547[0][2][0],&g_1547[0][2][0],&g_1547[0][2][0],&g_1547[0][2][0]}; +static int8_t ***g_1656 = &g_245; +static uint16_t g_1766 = 0x2A71L; +static const uint32_t g_1776 = 4294967288UL; +static const uint32_t g_1782[6][8][5] = {{{9UL,1UL,0xC7DDDB76L,0x6C0C4151L,0x8031E06CL},{4294967288UL,0x67522ABBL,4294967289UL,9UL,0x6B1862C6L},{4294967289UL,0x035D4646L,0x4BD87A52L,0xF04D3E88L,0x02BA768FL},{0x67522ABBL,1UL,0xFBE5C2AFL,0x09838561L,0x6E51EAD8L},{0x67522ABBL,0x8031E06CL,0xFC56E314L,0x5133D18EL,0xF04D3E88L},{4294967289UL,0xFBE5C2AFL,4294967286UL,4294967295UL,4294967295UL},{4294967288UL,4294967289UL,4294967288UL,0xFC56E314L,0x4BD87A52L},{9UL,0x09838561L,4294967295UL,1UL,3UL}},{{0xD3C5907BL,0x6C0C4151L,4294967289UL,0x8031E06CL,0x035D4646L},{0x6B1862C6L,0x6E51EAD8L,4294967295UL,3UL,0x02BA768FL},{4294967294UL,0xD3C5907BL,4294967288UL,0x67522ABBL,4294967289UL},{0x6C0C4151L,0x8031E06CL,4294967286UL,4294967295UL,0xB9EFEB98L},{8UL,4294967291UL,0xFC56E314L,4294967295UL,0x2B8C1A21L},{4294967291UL,0x6B1862C6L,0xFBE5C2AFL,1UL,0x2B8C1A21L},{9UL,0x1C34F8ADL,0x4BD87A52L,4294967288UL,0xB9EFEB98L},{1UL,4294967288UL,4294967289UL,0xB9EFEB98L,4294967289UL}},{{0xE9241C7AL,0xE9241C7AL,0x6E51EAD8L,1UL,0x09838561L},{4294967288UL,3UL,0x8031E06CL,4294967291UL,0x37358859L},{1UL,4294967295UL,0xD83C2DFAL,1UL,4294967286UL},{0x4478B581L,3UL,0x2B8C1A21L,8UL,0x5A8F52F4L},{0xB9EFEB98L,0xE9241C7AL,0xF04D3E88L,0xC7DDDB76L,8UL},{1UL,1UL,0UL,7UL,0x5133D18EL},{0xF04D3E88L,4294967291UL,0x084A6D3FL,4294967286UL,0x02BA768FL},{0x02BA768FL,0xB3D218BBL,4294967289UL,4294967286UL,0x09838561L}},{{0x2BAF5CEFL,9UL,0xFDF9E1B7L,7UL,0xB3D218BBL},{4294967291UL,4294967295UL,0xC7DDDB76L,0xC7DDDB76L,4294967295UL},{0x37358859L,0x9D243B0BL,4294967295UL,8UL,4294967289UL},{0xFDF9E1B7L,0x02BA768FL,0x9D243B0BL,1UL,0x6B1862C6L},{1UL,0xFBE5C2AFL,0x6B1862C6L,4294967291UL,4294967286UL},{0xFDF9E1B7L,0x2BAF5CEFL,0x084A6D3FL,1UL,0x731D77D9L},{0x37358859L,0x084A6D3FL,0x035D4646L,0xFC56E314L,0x09838561L},{4294967291UL,0xB9EFEB98L,9UL,1UL,0x4478B581L}},{{0x2BAF5CEFL,4294967295UL,4294967291UL,4294967295UL,1UL},{0x02BA768FL,0x8031E06CL,4294967291UL,8UL,0UL},{0xF04D3E88L,0x37358859L,9UL,0x2B8C1A21L,0x6E51EAD8L},{1UL,0xD3C5907BL,0x035D4646L,0xD3C5907BL,1UL},{0xB9EFEB98L,4294967288UL,0x084A6D3FL,4294967286UL,0xE9241C7AL},{0x4478B581L,0x731D77D9L,0x6B1862C6L,4294967295UL,0x09838561L},{1UL,0xFDF9E1B7L,0x9D243B0BL,4294967288UL,0xE9241C7AL},{4294967288UL,4294967295UL,4294967295UL,0x4BD87A52L,1UL}},{{0xE9241C7AL,0xF04D3E88L,0xC7DDDB76L,8UL,0x6E51EAD8L},{0x8031E06CL,0x4478B581L,0xFDF9E1B7L,4294967291UL,0UL},{1UL,7UL,4294967289UL,0x2BAF5CEFL,1UL},{9UL,7UL,0x084A6D3FL,0x5133D18EL,0x4478B581L},{0x731D77D9L,0x4478B581L,0UL,1UL,0x09838561L},{0xFBE5C2AFL,0xF04D3E88L,0xF04D3E88L,0xFBE5C2AFL,0x731D77D9L},{7UL,4294967295UL,0x2B8C1A21L,0xD83C2DFAL,4294967286UL},{0xB3D218BBL,0xFDF9E1B7L,0xD83C2DFAL,8UL,0x6B1862C6L}}}; +static const uint32_t *g_1781 = &g_1782[2][3][4]; +static int8_t g_1857 = 0L; +static const uint8_t *g_1941 = (void*)0; +static const uint8_t ** const g_1940[7] = {&g_1941,&g_1941,&g_1941,&g_1941,&g_1941,&g_1941,&g_1941}; +static const uint8_t ** const *g_1939 = &g_1940[2]; +static const uint8_t ** const **g_1938 = &g_1939; +static const uint8_t ** const ***g_1937 = &g_1938; +static int16_t g_1961 = (-2L); +static const int8_t g_2067 = (-1L); +static const uint32_t ***g_2068[3] = {(void*)0,(void*)0,(void*)0}; +static int8_t g_2147[10] = {0x23L,0x23L,0x23L,0x23L,0x23L,0x23L,0x23L,0x23L,0x23L,0x23L}; +static uint16_t g_2148 = 0x794EL; +static int16_t g_2207 = 0L; + + +/* --- FORWARD DECLARATIONS --- */ +static uint16_t func_1(void); +static int8_t func_10(uint32_t p_11); +static int32_t func_16(int8_t p_17, uint32_t * p_18, uint32_t * p_19, uint16_t p_20, uint32_t p_21); +static uint32_t * func_22(int16_t p_23, uint32_t p_24, uint32_t * p_25); +static int32_t func_62(int32_t * p_63, uint8_t p_64); +static int32_t * func_65(int8_t p_66, uint16_t p_67, uint8_t p_68, int32_t * p_69, uint32_t * p_70); +static uint8_t * func_71(uint32_t p_72, int8_t p_73); +static int32_t * func_94(uint32_t * p_95, int32_t p_96, const int32_t p_97, int32_t p_98, int8_t p_99); +static int8_t func_100(int32_t * p_101, uint8_t p_102, uint8_t p_103, uint32_t p_104); +static int32_t * func_105(uint32_t p_106); + + +/* --- FUNCTIONS --- */ +/* ------------------------------------------ */ +/* + * reads : g_2 g_14 g_15 g_36 g_40 g_43 g_3 g_52 g_46 g_51 g_55 g_56 g_44 g_251 g_143 g_140 g_176 g_705 g_289 g_290 g_297 g_255 g_34 g_131 g_132 g_243 g_347 g_320 g_736 g_294 g_175 g_897 g_905 g_735 g_960 g_969 g_961 g_312 g_1334 g_1132 g_1184 g_1185 g_1099 g_1656 g_1238 g_1548 g_1018 g_1019 g_1254 g_1766 g_1776 g_1857 g_477 g_1298 g_1937 g_1961 g_242 g_1781 g_1782 g_419 g_2068 g_245 g_1938 g_2147 g_2148 g_1333 g_2207 + * writes: g_3 g_14 g_15 g_34 g_36 g_40 g_52 g_51 g_46 g_255 g_297 g_140 g_312 g_294 g_56 g_44 g_347 g_290 g_897 g_904 g_419 g_251 g_969 g_1334 g_1132 g_1298 g_175 g_1099 g_1055 g_477 g_55 g_1766 g_1781 g_960 g_242 g_961 g_705 g_2068 g_2148 g_2207 + */ +static uint16_t func_1(void) +{ /* block id: 0 */ + int32_t l_38 = 0xCA862934L; + int32_t l_1612 = 0xB952CD69L; + int32_t l_1634 = 0x1D6D5307L; + int16_t l_1658[5][6] = {{0x1999L,0L,0x1999L,0x1999L,0L,0x1999L},{0x1999L,0L,0x1999L,0x1999L,0L,0x0361L},{0x0361L,0x1999L,0x0361L,0x0361L,0x1999L,0x0361L},{0x0361L,0x1999L,0x0361L,0x0361L,0x1999L,0x0361L},{0x0361L,0x1999L,0x0361L,0x0361L,0x1999L,0x0361L}}; + uint8_t * const ***l_1712 = &g_1295; + uint8_t * const ****l_1711[9] = {&l_1712,&l_1712,&l_1712,&l_1712,&l_1712,&l_1712,&l_1712,&l_1712,&l_1712}; + uint8_t **l_1725 = &g_43; + int16_t l_1756[10][2] = {{0xB2C0L,(-1L)},{(-1L),0xB2C0L},{(-1L),(-1L)},{0xB2C0L,(-1L)},{(-1L),0xB2C0L},{(-1L),(-1L)},{0xB2C0L,(-1L)},{(-1L),0xB2C0L},{(-1L),(-1L)},{0xB2C0L,(-1L)}}; + int32_t l_1763 = (-8L); + uint32_t *l_1783 = &g_14[1]; + int32_t ***l_1785 = &g_961; + uint32_t *****l_1788 = (void*)0; + uint8_t l_1831 = 0x9CL; + uint8_t *l_1877 = &g_40[0]; + uint32_t l_2046 = 18446744073709551609UL; + int8_t l_2047 = 1L; + uint32_t l_2048 = 2UL; + int32_t l_2056 = 1L; + int32_t l_2058 = 0L; + int32_t l_2072 = 9L; + uint32_t l_2099 = 4UL; + uint32_t l_2116 = 4UL; + uint32_t l_2184 = 0xE4A882E7L; + int16_t **l_2189[6][6][7] = {{{&g_289,&g_289,&g_289,&g_289,&g_289,&g_289,&g_289},{(void*)0,&g_289,&g_289,(void*)0,(void*)0,&g_289,&g_289},{&g_289,&g_289,&g_289,&g_289,&g_289,&g_289,&g_289},{(void*)0,&g_289,&g_289,&g_289,(void*)0,&g_289,(void*)0},{&g_289,(void*)0,&g_289,&g_289,&g_289,&g_289,&g_289},{&g_289,(void*)0,&g_289,(void*)0,&g_289,&g_289,&g_289}},{{&g_289,&g_289,&g_289,&g_289,&g_289,&g_289,&g_289},{&g_289,&g_289,&g_289,&g_289,&g_289,&g_289,&g_289},{&g_289,&g_289,&g_289,&g_289,&g_289,&g_289,&g_289},{&g_289,&g_289,&g_289,&g_289,&g_289,&g_289,&g_289},{&g_289,&g_289,&g_289,&g_289,&g_289,&g_289,&g_289},{&g_289,&g_289,&g_289,&g_289,&g_289,(void*)0,(void*)0}},{{&g_289,&g_289,&g_289,&g_289,&g_289,&g_289,&g_289},{(void*)0,(void*)0,&g_289,&g_289,&g_289,&g_289,&g_289},{&g_289,&g_289,&g_289,(void*)0,&g_289,&g_289,&g_289},{(void*)0,&g_289,&g_289,&g_289,&g_289,(void*)0,&g_289},{&g_289,&g_289,&g_289,&g_289,&g_289,&g_289,&g_289},{&g_289,&g_289,&g_289,(void*)0,&g_289,&g_289,(void*)0}},{{&g_289,&g_289,&g_289,&g_289,&g_289,&g_289,&g_289},{&g_289,&g_289,&g_289,&g_289,&g_289,&g_289,&g_289},{&g_289,&g_289,&g_289,&g_289,&g_289,(void*)0,&g_289},{&g_289,(void*)0,(void*)0,(void*)0,(void*)0,&g_289,&g_289},{&g_289,&g_289,&g_289,&g_289,&g_289,(void*)0,&g_289},{&g_289,&g_289,(void*)0,&g_289,(void*)0,&g_289,&g_289}},{{&g_289,&g_289,&g_289,(void*)0,&g_289,&g_289,&g_289},{&g_289,&g_289,&g_289,&g_289,&g_289,&g_289,(void*)0},{&g_289,&g_289,&g_289,&g_289,&g_289,&g_289,&g_289},{&g_289,&g_289,&g_289,&g_289,&g_289,(void*)0,&g_289},{&g_289,&g_289,&g_289,&g_289,&g_289,&g_289,&g_289},{&g_289,(void*)0,(void*)0,&g_289,&g_289,&g_289,&g_289}},{{&g_289,(void*)0,&g_289,&g_289,&g_289,&g_289,&g_289},{&g_289,&g_289,(void*)0,&g_289,&g_289,(void*)0,&g_289},{&g_289,&g_289,&g_289,&g_289,&g_289,&g_289,&g_289},{(void*)0,&g_289,&g_289,(void*)0,(void*)0,&g_289,&g_289},{&g_289,&g_289,&g_289,&g_289,&g_289,&g_289,&g_289},{(void*)0,&g_289,&g_289,&g_289,(void*)0,&g_289,(void*)0}}}; + int16_t ***l_2188 = &l_2189[0][5][4]; + int16_t ****l_2187[1]; + int i, j, k; + for (i = 0; i < 1; i++) + l_2187[i] = &l_2188; +lbl_2208: + for (g_3 = 0; (g_3 <= 0); g_3 += 1) + { /* block id: 3 */ + uint32_t *l_12 = (void*)0; + uint32_t *l_13[2][9][7] = {{{&g_14[4],&g_14[2],&g_14[1],&g_14[1],&g_14[1],(void*)0,&g_14[4]},{(void*)0,&g_14[1],&g_14[3],&g_14[1],&g_14[1],&g_14[3],&g_14[1]},{&g_14[4],&g_14[2],&g_14[1],&g_14[1],&g_14[1],(void*)0,&g_14[4]},{(void*)0,&g_14[1],&g_14[3],&g_14[1],&g_14[1],&g_14[3],&g_14[1]},{&g_14[4],&g_14[2],&g_14[1],&g_14[1],&g_14[1],(void*)0,&g_14[4]},{(void*)0,&g_14[1],&g_14[3],&g_14[1],&g_14[1],&g_14[3],&g_14[1]},{&g_14[4],&g_14[2],&g_14[1],&g_14[1],&g_14[1],(void*)0,&g_14[4]},{(void*)0,&g_14[1],&g_14[3],&g_14[1],&g_14[1],&g_14[3],&g_14[1]},{&g_14[4],&g_14[2],&g_14[1],&g_14[1],&g_14[1],(void*)0,&g_14[4]}},{{(void*)0,&g_14[1],&g_14[3],&g_14[1],&g_14[1],&g_14[3],&g_14[1]},{&g_14[4],&g_14[2],&g_14[1],&g_14[1],&g_14[1],(void*)0,&g_14[4]},{(void*)0,&g_14[1],&g_14[3],&g_14[1],(void*)0,&g_14[1],&g_14[0]},{&g_14[1],&g_14[3],&g_14[1],(void*)0,&g_14[4],&g_14[1],&g_14[1]},{&g_14[1],&g_14[0],&g_14[1],(void*)0,(void*)0,&g_14[1],&g_14[0]},{&g_14[1],&g_14[3],&g_14[1],(void*)0,&g_14[4],&g_14[1],&g_14[1]},{&g_14[1],&g_14[0],&g_14[1],(void*)0,(void*)0,&g_14[1],&g_14[0]},{&g_14[1],&g_14[3],&g_14[1],(void*)0,&g_14[4],&g_14[1],&g_14[1]},{&g_14[1],&g_14[0],&g_14[1],(void*)0,(void*)0,&g_14[1],&g_14[0]}}}; + int8_t *l_35 = &g_36; + int32_t l_37 = 0x129EC6EAL; + uint8_t *l_39 = &g_40[1]; + uint32_t l_1611 = 1UL; + const int16_t l_1613 = (-7L); + int32_t l_1616 = 0xF7091F80L; + int32_t l_1618 = 0x81A177EAL; + int32_t l_1623 = (-3L); + int8_t ***l_1657 = &g_245; + int i, j, k; + if ((((((safe_mul_func_int8_t_s_s(((safe_div_func_uint8_t_u_u(((safe_mod_func_int8_t_s_s(func_10((((g_15 &= (g_14[4] ^= g_2[1][0])) == func_16(g_2[2][0], func_22((safe_div_func_int8_t_s_s((safe_mul_func_int16_t_s_s(((safe_div_func_int32_t_s_s((safe_rshift_func_uint8_t_u_s((g_34 = 1UL), ((*l_35) ^= 0x4DL))), l_37)) == (((((*l_39) = l_38) , (--(*l_39))) >= l_37) ^ 0UL)), ((void*)0 == g_43))), g_3)), l_38, l_13[1][1][2]), g_55, l_37, g_56)) >= l_37)), l_38)) == 0x3C9EL), l_38)) , 0xBCL), l_1611)) | l_1612) == 1UL) < l_1613) == 0x39F7L)) + { /* block id: 771 */ + int32_t *l_1614 = &g_1055; + if (l_1613) + break; + (**g_960) = l_1614; + if (l_1611) + continue; + } + else + { /* block id: 775 */ + int32_t *l_1615 = &g_51[1][6][2]; + int32_t *l_1617 = &g_297[1]; + int32_t *l_1619 = &l_1616; + int32_t *l_1620 = (void*)0; + int32_t *l_1621 = &l_1618; + int32_t *l_1622 = &g_297[1]; + int32_t *l_1624 = &g_51[0][3][1]; + int32_t *l_1625 = &l_37; + int32_t *l_1626 = (void*)0; + int32_t *l_1627 = &g_1132; + int32_t *l_1628 = &g_297[1]; + int32_t *l_1629 = &l_1618; + int32_t *l_1630[9] = {&g_297[0],&g_297[0],&g_297[0],&g_297[0],&g_297[0],&g_297[0],&g_297[0],&g_297[0],&g_297[0]}; + uint8_t l_1631 = 6UL; + int i; + --l_1631; + return (*l_1617); + } + l_1634 |= 0xB346B708L; + for (g_1298 = 0; (g_1298 <= 0); g_1298 += 1) + { /* block id: 782 */ + uint32_t l_1635 = 0xEF083A2AL; + int32_t l_1644 = 0x4F483357L; + (*g_143) ^= l_1635; + (*g_143) = (safe_mul_func_uint16_t_u_u(((safe_sub_func_int8_t_s_s(((!(l_38 , l_1611)) != (l_1644 &= (safe_lshift_func_int8_t_s_s((safe_add_func_int8_t_s_s(0x2CL, l_1612)), 4)))), (safe_unary_minus_func_uint32_t_u((safe_div_func_int8_t_s_s(((g_320 <= (((l_38 <= (((safe_add_func_int16_t_s_s((safe_sub_func_uint16_t_u_u((l_1618 & (((safe_div_func_uint16_t_u_u((((((safe_rshift_func_int16_t_s_s(0x3853L, l_1635)) >= l_1612) , g_1656) != l_1657) & l_38), 65531UL)) ^ l_1623) && l_1635)), l_1658[1][1])), 0x80FFL)) == 7UL) == (**g_1238))) > 0x43L) || g_14[5])) , 5L), l_1612)))))) > l_1658[1][1]), 0UL)); + } + for (g_1099 = 0; (g_1099 <= 0); g_1099 += 1) + { /* block id: 789 */ + int16_t l_1661 = 0x12BEL; + uint16_t *l_1666[10][9] = {{(void*)0,&g_969,&g_251,&g_969,&g_251,&g_969,&g_969,&g_251,&g_969},{(void*)0,&g_969,(void*)0,(void*)0,(void*)0,&g_969,(void*)0,(void*)0,(void*)0},{&g_969,(void*)0,&g_251,&g_969,&g_251,&g_251,&g_969,&g_251,(void*)0},{&g_969,&g_969,&g_969,(void*)0,&g_969,(void*)0,&g_969,&g_969,&g_969},{&g_251,&g_251,&g_251,&g_969,&g_969,&g_251,&g_251,&g_251,&g_251},{(void*)0,&g_969,(void*)0,&g_969,(void*)0,&g_969,(void*)0,&g_969,(void*)0},{&g_251,(void*)0,&g_251,&g_251,(void*)0,&g_251,&g_251,&g_969,&g_251},{&g_969,&g_969,&g_969,&g_969,&g_969,&g_969,&g_969,&g_969,&g_969},{&g_969,&g_969,&g_969,&g_969,&g_251,&g_969,&g_251,&g_251,(void*)0},{(void*)0,&g_969,(void*)0,&g_969,(void*)0,&g_969,(void*)0,&g_969,(void*)0}}; + int16_t l_1667 = 0xD2A4L; + int32_t l_1680 = 0x06D2A1F8L; + int32_t l_1681 = 0xB17E7D5CL; + int8_t l_1682 = (-5L); + int32_t *l_1683 = &g_1055; + int i, j; + l_37 ^= ((*l_1683) = ((*g_143) = ((safe_add_func_uint32_t_u_u((--(***g_735)), (safe_mul_func_uint8_t_u_u(((l_1681 = (!((g_969 = (l_1667 &= 1UL)) != ((*g_132) != (((((safe_mul_func_int16_t_s_s(((***g_1548) && (safe_div_func_uint8_t_u_u((((safe_sub_func_int16_t_s_s(((safe_add_func_int32_t_s_s((safe_lshift_func_uint16_t_u_u(g_34, ((*g_1018) != (*g_1018)))), (*g_143))) , (((safe_add_func_uint16_t_u_u((l_1680 = ((((l_1618 = ((***g_1184) | ((((**g_1185) ^ l_1661) && l_1661) , l_1661))) < 1L) || 65533UL) | l_1616)), (-2L))) == l_1658[3][5]) != l_1661)), l_1623)) , 0L) | l_1661), l_1661))), l_1634)) <= (*g_143)) , l_38) || (*g_143)) != (***g_1184)))))) , (*g_43)), (***g_1548))))) <= l_1682))); + } + } + for (l_38 = 2; (l_38 <= (-27)); l_38 = safe_sub_func_int8_t_s_s(l_38, 6)) + { /* block id: 803 */ + int32_t l_1692 = 0L; + int32_t l_1702 = 0xA1267D64L; + uint32_t l_1722 = 8UL; + uint8_t * const * const l_1726 = &g_43; + uint32_t *l_1737 = &g_1099; + int8_t *l_1793 = (void*)0; + int32_t *l_1797 = (void*)0; + uint32_t l_1859 = 0x82CF6B6FL; + int8_t l_1899 = 1L; + uint16_t l_1902 = 65534UL; + int8_t ***l_1936[8] = {(void*)0,&g_242,&g_242,(void*)0,&g_242,&g_242,(void*)0,&g_242}; + uint32_t l_1957 = 5UL; + int32_t **l_2005 = &g_143; + uint32_t l_2007 = 18446744073709551615UL; + int32_t l_2050 = (-1L); + int32_t l_2051 = 5L; + int32_t l_2052[8][1]; + const int8_t *l_2066 = &g_2067; + const int8_t **l_2065[10] = {(void*)0,(void*)0,(void*)0,(void*)0,(void*)0,(void*)0,(void*)0,(void*)0,(void*)0,(void*)0}; + uint32_t l_2071[3][7][7] = {{{0x30CE76AEL,0UL,18446744073709551615UL,1UL,1UL,1UL,0UL},{0xAD0A2372L,0xEA6E9C20L,0UL,0x324BC3A3L,0xF442972AL,0x911E4A42L,0x911E4A42L},{18446744073709551608UL,18446744073709551610UL,0x1262E29EL,18446744073709551610UL,18446744073709551608UL,0x9477AE01L,0xF442972AL},{1UL,5UL,0x30CE76AEL,18446744073709551611UL,0x99881E2AL,0xDA83510BL,18446744073709551615UL},{0xF442972AL,0x911E4A42L,0xFCFF20AAL,0x23F69BAEL,18446744073709551608UL,0x30CE76AEL,0xAD0A2372L},{0x1262E29EL,0UL,18446744073709551615UL,1UL,0x6F0D46CCL,0x1262E29EL,0x7CF12E04L},{18446744073709551615UL,0xF442972AL,0x5F49E352L,5UL,18446744073709551615UL,0UL,0UL}},{{18446744073709551611UL,18446744073709551615UL,0x23F69BAEL,0x30CE76AEL,0UL,18446744073709551615UL,1UL},{0x250C5BC2L,18446744073709551615UL,6UL,0x30CE76AEL,1UL,1UL,0UL},{18446744073709551615UL,0x6F0D46CCL,1UL,5UL,0x911E4A42L,1UL,0x911E4A42L},{1UL,18446744073709551615UL,18446744073709551615UL,1UL,0x9477AE01L,0x23E5CD91L,0x30CE76AEL},{0x2665B0F5L,0UL,1UL,0x23F69BAEL,0xDA83510BL,0x9D1F30D5L,0UL},{18446744073709551611UL,0x5F49E352L,0x84F3CCEFL,0UL,0x9A4CA65DL,18446744073709551610UL,0x30CE76AEL},{6UL,0UL,0x324BC3A3L,0x5F49E352L,1UL,5UL,0x911E4A42L}},{{1UL,18446744073709551608UL,18446744073709551613UL,0xDC003897L,1UL,0UL,0UL},{1UL,18446744073709551615UL,18446744073709551615UL,0x324BC3A3L,18446744073709551608UL,0xCC0F1D77L,1UL},{0x9D1F30D5L,0x7DDAB611L,18446744073709551615UL,0xFCFF20AAL,0UL,0x9D1F30D5L,0UL},{18446744073709551615UL,18446744073709551615UL,18446744073709551613UL,0x7CF12E04L,0UL,0UL,0x7CF12E04L},{0x324BC3A3L,0UL,0x324BC3A3L,0x30CE76AEL,0x7CF12E04L,6UL,0xAD0A2372L},{0x5F49E352L,18446744073709551615UL,0x84F3CCEFL,18446744073709551615UL,18446744073709551614UL,18446744073709551615UL,0UL},{1UL,0UL,1UL,0x27C4E890L,0x911E4A42L,6UL,18446744073709551615UL}}}; + uint16_t l_2191 = 0UL; + uint32_t l_2194 = 0x1CA07694L; + uint8_t *****l_2202 = &g_904[0][3]; + uint8_t ******l_2201 = &l_2202; + uint8_t *l_2205 = &l_1831; + int32_t *l_2206[1][2]; + int i, j, k; + for (i = 0; i < 8; i++) + { + for (j = 0; j < 1; j++) + l_2052[i][j] = 1L; + } + for (i = 0; i < 1; i++) + { + for (j = 0; j < 2; j++) + l_2206[i][j] = &l_2052[2][0]; + } + if (((((0xEC18D826L > 0xC2623D2EL) == (safe_add_func_int32_t_s_s(((void*)0 == (*g_1018)), (*g_143)))) < ((*g_43) |= (((safe_add_func_int8_t_s_s(l_1658[4][2], (**g_131))) == (l_1634 = ((((safe_lshift_func_uint16_t_u_s(g_294[0], 5)) , l_1692) , 0x47L) && 0x07L))) != 0x6DDD7AF3L))) <= l_1692)) + { /* block id: 806 */ + int8_t l_1727 = 0x36L; + uint16_t l_1730 = 0x5E85L; + int32_t l_1758 = 1L; + int32_t l_1760 = 0x8ED80A0BL; + int32_t l_1762 = 0xC5EE06D0L; + int32_t l_1764 = 0x9C30C92FL; + uint8_t l_1773 = 0x04L; + uint32_t l_1795 = 0x25B5191FL; + int32_t *l_1832 = (void*)0; + int32_t l_1850 = 3L; + uint16_t l_1876 = 0xC3DDL; + uint32_t *****l_1891 = (void*)0; + uint16_t l_1901 = 65528UL; + for (g_419 = 0; (g_419 < 27); ++g_419) + { /* block id: 809 */ + int32_t l_1697[6] = {(-8L),(-8L),(-8L),(-8L),(-8L),(-8L)}; + uint16_t *l_1698[10][3] = {{&g_251,&g_251,&g_251},{&g_251,&g_251,&g_251},{&g_251,&g_251,&g_251},{&g_251,&g_969,&g_251},{&g_251,&g_251,&g_251},{&g_251,&g_251,&g_251},{&g_969,&g_251,&g_251},{&g_251,&g_251,&g_251},{&g_251,&g_251,&g_251},{&g_251,&g_969,&g_969}}; + int i, j; + (*g_143) ^= ((**g_736) , l_1612); + l_1634 = (safe_lshift_func_uint16_t_u_s((g_969 = l_1697[1]), 5)); + } + for (g_255 = 0; (g_255 > 7); g_255 = safe_add_func_int16_t_s_s(g_255, 8)) + { /* block id: 816 */ + uint8_t l_1701 = 0xB3L; + uint8_t * const ***l_1709 = (void*)0; + uint8_t * const ****l_1708 = &l_1709; + uint8_t * const *****l_1710[10][10][2] = {{{&l_1708,(void*)0},{&l_1708,&l_1708},{(void*)0,&l_1708},{&l_1708,(void*)0},{&l_1708,&l_1708},{(void*)0,&l_1708},{&l_1708,(void*)0},{&l_1708,&l_1708},{(void*)0,&l_1708},{&l_1708,(void*)0}},{{&l_1708,&l_1708},{(void*)0,&l_1708},{&l_1708,(void*)0},{&l_1708,&l_1708},{(void*)0,&l_1708},{&l_1708,(void*)0},{&l_1708,&l_1708},{(void*)0,&l_1708},{&l_1708,&l_1708},{(void*)0,(void*)0}},{{&l_1708,(void*)0},{(void*)0,&l_1708},{(void*)0,(void*)0},{&l_1708,(void*)0},{(void*)0,&l_1708},{(void*)0,(void*)0},{&l_1708,(void*)0},{(void*)0,&l_1708},{(void*)0,(void*)0},{&l_1708,(void*)0}},{{(void*)0,&l_1708},{(void*)0,(void*)0},{&l_1708,(void*)0},{(void*)0,&l_1708},{(void*)0,(void*)0},{&l_1708,(void*)0},{(void*)0,&l_1708},{(void*)0,(void*)0},{&l_1708,(void*)0},{(void*)0,&l_1708}},{{(void*)0,(void*)0},{&l_1708,(void*)0},{(void*)0,&l_1708},{(void*)0,(void*)0},{&l_1708,(void*)0},{(void*)0,&l_1708},{(void*)0,(void*)0},{&l_1708,(void*)0},{(void*)0,&l_1708},{(void*)0,(void*)0}},{{&l_1708,(void*)0},{(void*)0,&l_1708},{(void*)0,(void*)0},{&l_1708,(void*)0},{(void*)0,&l_1708},{(void*)0,(void*)0},{&l_1708,(void*)0},{(void*)0,&l_1708},{(void*)0,(void*)0},{&l_1708,(void*)0}},{{(void*)0,&l_1708},{(void*)0,(void*)0},{&l_1708,(void*)0},{(void*)0,&l_1708},{(void*)0,(void*)0},{&l_1708,(void*)0},{(void*)0,&l_1708},{(void*)0,(void*)0},{&l_1708,(void*)0},{(void*)0,&l_1708}},{{(void*)0,(void*)0},{&l_1708,(void*)0},{(void*)0,&l_1708},{(void*)0,(void*)0},{&l_1708,(void*)0},{(void*)0,&l_1708},{(void*)0,(void*)0},{&l_1708,(void*)0},{(void*)0,&l_1708},{(void*)0,(void*)0}},{{&l_1708,(void*)0},{(void*)0,&l_1708},{(void*)0,(void*)0},{&l_1708,(void*)0},{(void*)0,&l_1708},{(void*)0,(void*)0},{&l_1708,(void*)0},{(void*)0,&l_1708},{(void*)0,(void*)0},{&l_1708,(void*)0}},{{(void*)0,&l_1708},{(void*)0,(void*)0},{&l_1708,(void*)0},{(void*)0,&l_1708},{(void*)0,(void*)0},{&l_1708,(void*)0},{(void*)0,&l_1708},{(void*)0,(void*)0},{&l_1708,(void*)0},{(void*)0,&l_1708}}}; + int32_t l_1721 = 1L; + uint32_t *l_1728 = &g_477; + int32_t *l_1729[5][7] = {{(void*)0,&l_38,&l_38,&l_38,(void*)0,&l_1692,&l_1692},{&g_34,(void*)0,&l_1612,(void*)0,&g_34,&g_1509,&g_1509},{(void*)0,&l_38,&l_38,&l_38,(void*)0,&l_1692,&l_1692},{&g_34,(void*)0,&l_1612,(void*)0,&g_34,&g_1509,&l_1612},{&l_1692,&l_1692,&g_34,&l_1692,&l_1692,&l_38,&l_38}}; + int8_t *l_1731 = &l_1727; + int32_t l_1739 = 0xD1196770L; + int32_t l_1759 = 0L; + uint16_t *l_1806[2][8] = {{&l_1730,&l_1730,&l_1730,&l_1730,&l_1730,&l_1730,&l_1730,&l_1730},{&l_1730,&l_1730,&l_1730,&l_1730,&l_1730,&l_1730,&l_1730,&l_1730}}; + int32_t *l_1833 = &g_3; + int i, j, k; + l_1702 = l_1701; + if ((safe_lshift_func_uint8_t_u_u((l_38 , 0xE4L), (((safe_mul_func_int8_t_s_s(((*l_1731) = (((safe_unary_minus_func_int8_t_s((&g_1547[0][2][1] != (l_1711[7] = l_1708)))) == (safe_add_func_int8_t_s_s((((**g_736) = (**g_736)) < (((safe_mod_func_uint16_t_u_u(((l_1634 = (((*l_1728) = (safe_mul_func_uint8_t_u_u((((**l_1726) = (((safe_add_func_uint8_t_u_u((l_1721 = l_1701), (l_1722 != (safe_div_func_int32_t_s_s((((l_1725 == l_1726) , 0x32L) > l_1727), (*g_143)))))) , 0UL) <= 0xB756L)) && 0UL), l_1612))) < 0UL)) , g_1132), (**g_1185))) && 0x6EL) | g_1254[7][0][7])), 0xB8L))) >= l_1730)), l_1730)) > 0xF123L) || (*g_43))))) + { /* block id: 825 */ + uint32_t *l_1738 = &g_56; + for (g_477 = (-18); (g_477 >= 4); g_477 = safe_add_func_int32_t_s_s(g_477, 1)) + { /* block id: 828 */ + int8_t l_1736 = 0xE8L; + (*g_143) |= l_1727; + l_1721 = (l_1721 < (l_1739 = ((l_1736 , 0x13L) <= ((l_1738 = l_1737) == ((*g_736) = (*g_736)))))); + if ((*g_143)) + break; + } + } + else + { /* block id: 836 */ + int32_t l_1761 = 0x3F63D84DL; + int32_t l_1784[6] = {0xC54599E7L,0xC54599E7L,0x4344EDEAL,0xC54599E7L,0xC54599E7L,0x4344EDEAL}; + int32_t ***l_1794[9] = {(void*)0,(void*)0,(void*)0,(void*)0,(void*)0,(void*)0,(void*)0,(void*)0,(void*)0}; + int16_t **l_1796[5][2][9] = {{{&g_289,&g_289,(void*)0,&g_289,&g_289,&g_289,(void*)0,(void*)0,&g_289},{(void*)0,&g_289,&g_289,&g_289,&g_289,&g_289,&g_289,&g_289,&g_289}},{{(void*)0,&g_289,&g_289,&g_289,(void*)0,&g_289,(void*)0,&g_289,&g_289},{&g_289,&g_289,(void*)0,&g_289,&g_289,&g_289,&g_289,&g_289,&g_289}},{{&g_289,&g_289,&g_289,&g_289,&g_289,&g_289,(void*)0,&g_289,(void*)0},{&g_289,(void*)0,(void*)0,(void*)0,&g_289,&g_289,&g_289,(void*)0,&g_289}},{{(void*)0,(void*)0,&g_289,&g_289,&g_289,(void*)0,(void*)0,&g_289,&g_289},{&g_289,&g_289,&g_289,&g_289,&g_289,(void*)0,&g_289,&g_289,&g_289}},{{(void*)0,&g_289,&g_289,&g_289,&g_289,&g_289,&g_289,(void*)0,&g_289},{&g_289,(void*)0,(void*)0,&g_289,&g_289,&g_289,&g_289,&g_289,&g_289}}}; + int i, j, k; + for (g_1132 = 0; (g_1132 >= 0); g_1132 -= 1) + { /* block id: 839 */ + int32_t l_1757 = 0x90288987L; + int32_t l_1765 = 0x82B8DD8AL; + const uint32_t *l_1775 = &g_1776; + const uint32_t **l_1774 = &l_1775; + const uint32_t *l_1778 = (void*)0; + const uint32_t **l_1777 = &l_1778; + const uint32_t *l_1780 = &g_1776; + const uint32_t **l_1779 = &l_1780; + int i, j, k; + l_1784[5] = ((safe_sub_func_int32_t_s_s((safe_mul_func_int8_t_s_s((safe_add_func_uint8_t_u_u((++(**l_1725)), ((((l_1761 = ((safe_mod_func_uint32_t_u_u((safe_lshift_func_uint16_t_u_s(0x6591L, g_1254[(g_1132 + 4)][g_1132][(g_1132 + 2)])), (l_1721 & (((safe_add_func_int16_t_s_s(l_1721, (**g_1185))) , &g_1019[3][0][0]) != &g_1019[6][0][0])))) || ((safe_add_func_uint16_t_u_u(((g_1781 = ((*l_1779) = ((*l_1777) = ((*l_1774) = func_22(((((*g_143) = ((++g_1766) < (((((((safe_add_func_int16_t_s_s(((**g_1238) , (safe_rshift_func_uint8_t_u_s(l_1765, 6))), (**g_1185))) , 0xDFL) == l_1721) | (*g_289)) & l_1739) | l_1764) < 0UL))) , l_1761) , l_1773), l_1762, (**g_735)))))) != l_1783), 0x2B14L)) & 0x69A24093L))) > l_1701) >= 1L) == l_1739))), l_1730)), 0xBDA5626EL)) | l_1701); + (*g_143) = l_1761; + l_1797 = func_105((((g_960 = l_1785) != (((safe_mul_func_uint8_t_u_u((l_1788 != (void*)0), (g_14[2] , ((((+(safe_sub_func_uint8_t_u_u((((***g_905) = (safe_mul_func_int8_t_s_s((**g_131), ((*l_1731) = ((*g_131) != l_1793))))) <= (l_1794[4] != (void*)0)), l_1795))) , (void*)0) == l_1796[1][0][3]) && g_1254[(g_1132 + 4)][g_1132][(g_1132 + 2)])))) >= l_1722) , (void*)0)) < 0xA30C448CL)); + return l_1727; + } + (*g_143) ^= ((safe_mul_func_int8_t_s_s(0xA2L, ((safe_div_func_uint8_t_u_u(((**g_1185) < (7L < l_1701)), (*g_43))) && 0x80504E05L))) > 0UL); + } + (**g_960) = (l_1833 = (l_1832 = ((l_1773 | ((safe_mul_func_uint8_t_u_u(((++g_251) , (((--(**l_1726)) ^ ((safe_mod_func_uint32_t_u_u(0xE9892A02L, 0x6E452460L)) | (0xDA1EL && (!(((safe_div_func_int16_t_s_s((safe_rshift_func_uint16_t_u_u((g_251 = ((((safe_add_func_uint16_t_u_u((safe_mul_func_uint16_t_u_u((g_969++), 0UL)), (g_1334 & (!(((l_1758 ^= (safe_div_func_int32_t_s_s(((+((safe_lshift_func_int8_t_s_s((safe_div_func_int32_t_s_s(0x469EB03BL, ((((safe_mod_func_int32_t_s_s(l_1730, l_1773)) | l_1701) , (**g_1238)) , 4294967295UL))), 7)) != (**g_1185))) ^ 65530UL), 0x7B945D20L))) , l_1721) && l_1758))))) < 0x75L) , l_1773) != 0xD86B841BL)), g_1099)), (**g_1185))) == g_1776) != l_1759))))) , (**g_176))), 0x8EL)) || l_1831)) , (void*)0))); + } + if ((safe_div_func_uint8_t_u_u((~(safe_mod_func_uint8_t_u_u((safe_div_func_int32_t_s_s(((***g_1548) < (l_1634 |= (safe_add_func_int16_t_s_s((-3L), ((safe_mul_func_int8_t_s_s((((~(safe_mod_func_int8_t_s_s((**g_131), (safe_mul_func_uint8_t_u_u((safe_div_func_int32_t_s_s((l_1702 , ((l_1850 == (safe_rshift_func_uint16_t_u_s(1UL, (0x3DCC7414L | ((0x04DDBC4DL && (((((safe_mul_func_uint8_t_u_u(255UL, l_1760)) > (***g_1184)) >= (**g_736)) >= g_1857) == 0xD4CEL)) >= l_1763))))) > g_477)), (-1L))), (*g_132)))))) , (void*)0) != &g_961), (*g_43))) >= (**g_1185)))))), 0x7424D03BL)), l_1850))), (***g_905)))) + { /* block id: 868 */ + uint16_t l_1858 = 0x3EA7L; + (*g_143) ^= (l_1858 = 0x9CFAB74FL); + } + else + { /* block id: 871 */ + int16_t **l_1864 = &g_289; + int16_t ***l_1863[5] = {(void*)0,(void*)0,(void*)0,(void*)0,(void*)0}; + const int8_t *l_1873 = &g_36; + const int8_t **l_1872 = &l_1873; + const int8_t ***l_1871 = &l_1872; + int32_t l_1888 = 0x7ACDB461L; + uint32_t ****l_1893 = &g_1241; + uint32_t **** const *l_1892[1][10] = {{&l_1893,&l_1893,&l_1893,&l_1893,&l_1893,&l_1893,&l_1893,&l_1893,&l_1893,&l_1893}}; + uint8_t **l_1898[8] = {&l_1877,&l_1877,&l_1877,&l_1877,&l_1877,&l_1877,&l_1877,&l_1877}; + int32_t l_1900 = 0x122D3568L; + int8_t l_1931 = 0x34L; + int i, j; + (*g_143) |= l_1859; + for (l_1762 = 1; (l_1762 >= 0); l_1762 -= 1) + { /* block id: 875 */ + uint32_t l_1860[3]; + int16_t **l_1862 = &g_289; + int16_t ***l_1861 = &l_1862; + const int8_t ***l_1875 = &l_1872; + const int8_t ****l_1874 = &l_1875; + int i; + for (i = 0; i < 3; i++) + l_1860[i] = 18446744073709551614UL; + (*g_143) |= ((l_1860[0] != (l_1861 == l_1863[2])) & (safe_mul_func_uint8_t_u_u(((safe_mod_func_int32_t_s_s((+((***g_1184) < (safe_div_func_uint8_t_u_u((l_1871 == ((*l_1874) = (void*)0)), l_1876)))), ((*g_55) = ((g_297[l_1762] = (((**g_736) , l_1877) != (*l_1726))) , (**g_736))))) || 0xE5L), l_1860[2]))); + } + (*g_143) = (((safe_lshift_func_uint16_t_u_u(((safe_sub_func_int8_t_s_s((*g_132), (safe_add_func_int16_t_s_s(0x0DE1L, (safe_sub_func_int16_t_s_s((safe_mod_func_uint16_t_u_u(((l_1888 , (*g_55)) && (g_969 < (g_1766 = (((**l_1725) = (((((l_1891 != l_1892[0][2]) , (safe_mul_func_uint8_t_u_u((safe_mul_func_int16_t_s_s(((l_1888 |= ((l_1898[7] != (void*)0) != 0x581BL)) || l_1634), 8UL)), 0x19L))) , (*g_289)) , l_1899) < 0x06L)) <= 0UL)))), l_1900)), (**g_1185))))))) >= 0x94L), l_1901)) != 4294967295UL) , (*g_143)); + if (l_1902) + { /* block id: 885 */ + int32_t l_1905 = 1L; + for (l_1760 = (-2); (l_1760 < (-23)); l_1760 = safe_sub_func_int32_t_s_s(l_1760, 3)) + { /* block id: 888 */ + (*g_143) ^= l_1905; + if (l_1905) + continue; + } + } + else + { /* block id: 892 */ + uint16_t *l_1908[5][4] = {{&g_1766,&g_1766,&g_969,&l_1901},{(void*)0,&g_1766,&g_1766,(void*)0},{&g_1766,(void*)0,&g_1766,&g_969},{&g_1766,&g_1766,&g_1766,&g_969},{(void*)0,&g_969,&g_969,&g_969}}; + int32_t l_1919 = 0x8D5F8744L; + int i, j; + (*g_143) = (l_1702 ^= ((((safe_sub_func_uint16_t_u_u((g_1766 = (++g_251)), ((((safe_div_func_int32_t_s_s(((++g_969) | (safe_mul_func_uint8_t_u_u(l_1919, (l_1919 != l_1658[2][1])))), l_1756[4][1])) <= ((safe_sub_func_int16_t_s_s((safe_lshift_func_uint8_t_u_s(l_1888, l_1730)), (((safe_lshift_func_int16_t_s_s((safe_rshift_func_uint16_t_u_s((((!(l_1919 , 0x59L)) ^ (l_1900 < l_1900)) >= l_1900), 4)), 14)) , (void*)0) != (void*)0))) <= 0xD049L)) > 0x779C7159L) , g_255))) ^ l_1900) | 1L) <= (***g_905))); + for (g_1298 = (-14); (g_1298 >= 3); g_1298++) + { /* block id: 900 */ + int32_t l_1930 = (-1L); + if (l_1930) + break; + if (l_1931) + continue; + l_1919 &= 0xDF650B0EL; + } + for (g_34 = 0; (g_34 <= 3); g_34 += 1) + { /* block id: 907 */ + return g_36; + } + } + } + } + else + { /* block id: 912 */ + int16_t l_1932 = (-4L); + const uint8_t ** const ***l_1943 = &g_1938; + int8_t **l_1974 = &l_1793; + int32_t l_1990 = (-4L); + int32_t *l_2009[3]; + int16_t **l_2027 = &g_289; + int16_t ***l_2026 = &l_2027; + const int16_t *l_2030 = &g_1285; + const int16_t **l_2029 = &l_2030; + const int16_t ***l_2028[3][5][2] = {{{&l_2029,&l_2029},{&l_2029,&l_2029},{&l_2029,&l_2029},{&l_2029,&l_2029},{&l_2029,&l_2029}},{{&l_2029,&l_2029},{&l_2029,&l_2029},{&l_2029,&l_2029},{&l_2029,&l_2029},{&l_2029,&l_2029}},{{&l_2029,&l_2029},{&l_2029,&l_2029},{&l_2029,&l_2029},{&l_2029,&l_2029},{&l_2029,&l_2029}}}; + int32_t l_2031[7][5] = {{0x7B32F464L,0x31A52CFCL,(-1L),0x1CB357FAL,(-1L)},{(-1L),(-1L),0xFE12D187L,0x1CB357FAL,(-10L)},{0x31A52CFCL,0x7B32F464L,0x7B32F464L,0x31A52CFCL,(-1L)},{0x31A52CFCL,0x1CB357FAL,0L,0L,0x1CB357FAL},{(-1L),0x7B32F464L,0L,0xFE12D187L,0xFE12D187L},{0x7B32F464L,(-1L),0x7B32F464L,0L,0xFE12D187L},{0x1CB357FAL,0x31A52CFCL,0xFE12D187L,0x31A52CFCL,0x1CB357FAL}}; + int32_t l_2032 = 4L; + int i, j, k; + for (i = 0; i < 3; i++) + l_2009[i] = &g_3; + if (l_1932) + { /* block id: 913 */ + uint16_t l_1966 = 0xAA16L; + uint8_t l_1967 = 9UL; + int32_t l_1989 = 0x49AFD519L; + int32_t **l_2003 = &g_312[1][0][5]; + for (g_347 = 0; (g_347 <= 18); g_347++) + { /* block id: 916 */ + uint8_t l_1935[1][10][2] = {{{4UL,0x9AL},{4UL,0x9AL},{4UL,0x9AL},{4UL,0x9AL},{4UL,0x9AL},{4UL,0x9AL},{4UL,0x9AL},{4UL,0x9AL},{4UL,0x9AL},{4UL,0x9AL}}}; + int32_t l_1975 = (-9L); + uint8_t l_2006 = 0x8EL; + int i, j, k; + if (l_1935[0][3][1]) + { /* block id: 917 */ + const uint8_t ** const ****l_1942[3][1]; + int i, j; + for (i = 0; i < 3; i++) + { + for (j = 0; j < 1; j++) + l_1942[i][j] = &g_1937; + } + (*g_143) = ((((((void*)0 != l_1936[2]) & (-1L)) , &g_897) != (l_1943 = g_1937)) & (safe_lshift_func_uint16_t_u_s((safe_add_func_int8_t_s_s((*g_132), (0UL <= l_1932))), 4))); + } + else + { /* block id: 920 */ + int32_t *l_1952 = &l_1612; + int32_t l_1960 = 0x13E80650L; + uint16_t *l_1968[9] = {&g_1766,&g_251,&g_1766,&g_1766,&g_251,&g_1766,&g_1766,&g_251,&g_1766}; + int32_t *l_1969 = &g_3; + int32_t ***l_2004[4] = {&l_2003,&l_2003,&l_2003,&l_2003}; + uint32_t *l_2008 = &g_705[2]; + int i; + (*l_1969) ^= ((safe_mul_func_int16_t_s_s((*g_289), (safe_sub_func_uint8_t_u_u(((((*l_1952) = 0x79EFCB11L) , (((0x39L >= ((safe_div_func_int32_t_s_s(((*g_143) = (safe_add_func_int8_t_s_s(l_1957, (g_1857 && (g_251 = (safe_mul_func_uint8_t_u_u((l_1960 | g_1961), ((((safe_mod_func_int32_t_s_s(((safe_lshift_func_uint16_t_u_u(g_1298, l_1960)) == l_1966), l_1967)) && (*g_289)) , (*g_55)) != (*g_55))))))))), l_1960)) && l_1966)) , (***g_1184)) , l_1966)) || (**g_131)), (***g_1548))))) || l_1935[0][6][1]); + l_1990 &= (safe_rshift_func_int16_t_s_u((safe_rshift_func_int8_t_s_s((l_1975 = ((g_320 , ((**g_1018) = (**g_1018))) != l_1974)), 7)), ((l_1935[0][3][1] & (safe_add_func_int16_t_s_s((safe_div_func_int16_t_s_s((((((*l_1969) = ((***g_1184) > ((*l_1969) ^ (l_1989 = (safe_add_func_uint8_t_u_u(((safe_unary_minus_func_uint16_t_u(((((((((safe_lshift_func_int8_t_s_u(((safe_rshift_func_uint8_t_u_u(l_1935[0][6][0], l_1902)) > (((g_1766 = ((l_1967 , (*g_143)) & (*g_143))) , &g_1184) != (void*)0)), l_1935[0][3][1])) , l_1966) , 0x5DL) || 0x87L) <= l_1935[0][3][1]) || (*g_1781)) , &l_1692) == &g_1509))) ^ l_1932), 0xE0L)))))) || 251UL) | 0x46L) > l_1967), 0x3894L)), 0UL))) , g_1782[2][3][4]))); + l_2009[0] = func_105(((*l_2008) |= (safe_mod_func_int8_t_s_s((safe_rshift_func_uint16_t_u_s((g_1766++), ((((**g_1185) || (safe_rshift_func_uint16_t_u_u((((**g_736) = ((((+l_1935[0][3][1]) ^ 0x452888BFL) || ((((+((safe_rshift_func_int16_t_s_u((((l_1763 &= (safe_add_func_uint32_t_u_u((*g_55), ((((((*g_289) = ((*g_143) != ((*l_1969) = (*g_55)))) || 0x3A0FL) , ((((*l_1785) = (*g_960)) != (l_2005 = l_2003)) && l_1989)) , (*l_1969)) < l_1990)))) < 0xC6L) || 0xF854188CL), l_1975)) != l_2006)) <= 6L) , (void*)0) == (void*)0)) , l_2007)) | l_2006), g_251))) || 1L) | 0x7544L))), 4L)))); + } + if (l_1935[0][3][1]) + continue; + } + (*g_143) &= 0xCBD7ED2CL; + } + else + { /* block id: 944 */ + int32_t l_2014 = 0x16460141L; + uint8_t l_2033 = 0x2EL; + uint16_t *l_2039 = &g_251; + int32_t l_2049 = 0L; + int16_t l_2053[3]; + int32_t l_2054 = 0x72FC0805L; + int32_t l_2055 = (-4L); + int32_t l_2057 = 0x441D13AEL; + int32_t l_2059 = 0xB129E460L; + uint32_t l_2060[3][6] = {{1UL,1UL,18446744073709551615UL,1UL,1UL,18446744073709551615UL},{1UL,1UL,18446744073709551615UL,1UL,1UL,18446744073709551615UL},{1UL,1UL,18446744073709551615UL,1UL,1UL,18446744073709551615UL}}; + int i, j; + for (i = 0; i < 3; i++) + l_2053[i] = (-9L); + if (((**l_2005) > ((safe_div_func_uint16_t_u_u(((((**g_736) = (safe_mul_func_int8_t_s_s(0xC9L, l_2014))) & (safe_sub_func_int32_t_s_s((safe_sub_func_uint8_t_u_u((**l_2005), ((safe_mul_func_uint16_t_u_u((((safe_unary_minus_func_int16_t_s(((l_2032 = (l_2014 , (safe_mod_func_int32_t_s_s(0L, (safe_rshift_func_int8_t_s_s(((((((**g_1185) = (l_1658[1][1] == l_2014)) > ((l_2026 = l_2026) == l_2028[1][2][1])) || 1L) < g_1254[4][0][0]) <= g_297[1]), l_2031[3][2])))))) >= 0xFCL))) < (*g_143)) != 65529UL), l_2033)) , l_2014))), 0L))) >= (**l_2005)), (-4L))) || 4L))) + { /* block id: 949 */ + int32_t *l_2036 = (void*)0; + for (g_1298 = 3; (g_1298 < 13); g_1298++) + { /* block id: 952 */ + (*g_961) = l_2036; + (*g_143) = l_2033; + } + } + else + { /* block id: 956 */ + if ((*g_143)) + break; + } + l_2049 ^= ((safe_mod_func_uint16_t_u_u((g_1766 = ((1L ^ (((*l_2039) = ((void*)0 != &g_52)) <= (**g_1185))) , ((((safe_add_func_int16_t_s_s((((((+(safe_mod_func_int32_t_s_s((safe_sub_func_int16_t_s_s(((l_2046 ^ l_2047) >= ((!((l_2048 && (*g_1781)) , (254UL >= 0x4AL))) || 0xC4L)), g_51[0][3][1])), 0xD7857D83L))) , g_419) > g_40[1]) ^ l_2014) | 0x90L), g_1334)) & 0x40A7L) >= 0x889DL) | (**l_2005)))), 0x2C7FL)) != (**g_131)); + l_2060[2][2]--; + l_2059 |= (safe_sub_func_int32_t_s_s(l_2057, (0x662AL ^ (((l_2065[3] = (void*)0) != ((**g_1018) = (**g_1018))) >= ((0x53A4L & ((*l_2039) &= ((&g_736 != (g_2068[0] = g_2068[1])) >= (safe_mul_func_uint8_t_u_u(l_2049, (**g_131)))))) ^ l_2071[1][4][6]))))); + } + } + if (((*g_143) = l_2072)) + { /* block id: 971 */ + uint8_t l_2089 = 0x87L; + int32_t l_2095 = 1L; + const uint16_t l_2097 = 0xBF4DL; + int32_t l_2102[7][4]; + int32_t l_2108 = 0x7BAB6EA1L; + int8_t l_2128 = 0x3DL; + uint32_t *l_2168 = &l_1957; + int32_t l_2182 = 0x479FFEDCL; + int32_t *l_2190[4]; + int i, j; + for (i = 0; i < 7; i++) + { + for (j = 0; j < 4; j++) + l_2102[i][j] = 0x0A83AFD4L; + } + for (i = 0; i < 4; i++) + l_2190[i] = &g_3; + for (l_1692 = 2; (l_1692 >= 0); l_1692 -= 1) + { /* block id: 974 */ + uint32_t l_2085 = 0xB0246361L; + int8_t l_2086 = 0xB9L; + int32_t l_2094 = (-10L); + const uint32_t l_2096[1] = {0xC2A82A10L}; + uint32_t *l_2098 = &l_2071[1][5][2]; + int32_t *l_2100 = &l_1634; + int32_t *l_2101[4]; + uint16_t *l_2179 = &g_2148; + int i, j; + for (i = 0; i < 4; i++) + l_2101[i] = &l_2050; + if ((l_2102[6][0] |= ((*l_2100) &= (safe_mul_func_int8_t_s_s(((safe_div_func_uint8_t_u_u((g_705[2] , (safe_mod_func_int8_t_s_s((((*l_2098) = (safe_lshift_func_uint8_t_u_u((safe_sub_func_int8_t_s_s((((safe_mul_func_int8_t_s_s((l_2085 < l_2086), (g_1782[3][1][1] >= ((((safe_lshift_func_uint8_t_u_s(l_2089, 2)) == (g_705[2] ^ (((safe_mod_func_int16_t_s_s(((***g_1184) = (((((safe_mod_func_int32_t_s_s(((+(l_2095 = (l_2094 = l_2089))) , ((*g_143) = ((*g_143) > l_2085))), (**g_1238))) < (***g_1184)) == l_2089) || l_2096[0]) , 0x2B74L)), l_2089)) == l_2085) , 0x2251L))) != l_2089) || 65535UL)))) <= l_2089) , (-10L)), l_2089)), l_2097))) , l_2099), 0x69L))), l_2089)) <= (*g_55)), (**g_131)))))) + { /* block id: 982 */ + int8_t l_2115 = 1L; + int8_t * const *l_2118 = &g_243[5][0][8]; + int16_t *l_2136 = &l_1658[1][1]; + int16_t **l_2137 = &l_2136; + int32_t l_2146 = 1L; + int32_t ***l_2157 = &g_961; + int32_t ****l_2167 = &g_960; + for (l_1722 = 0; (l_1722 <= 4); l_1722 += 1) + { /* block id: 985 */ + uint16_t *l_2117 = &l_1902; + int16_t *l_2127 = &g_347; + uint32_t l_2135 = 8UL; + int i, j; + l_2095 = (l_2102[6][0] = (((safe_unary_minus_func_uint8_t_u(l_1658[l_1722][(l_1692 + 3)])) != (((((*l_2117) &= (l_1658[l_1692][(l_1722 + 1)] >= (safe_mod_func_uint8_t_u_u((((0L < (((void*)0 != (*g_1656)) , (l_2108 > (safe_add_func_int32_t_s_s(((*l_2100) = ((safe_mod_func_uint32_t_u_u(l_2108, ((safe_mul_func_int8_t_s_s(0xACL, (l_2115 , (**g_175)))) & l_2116))) >= 0x6E903ADFL)), l_2115))))) || (**g_131)) ^ 0UL), l_1658[l_1722][(l_1692 + 3)])))) , (void*)0) != l_2118) & (***g_1184))) || 0xFCE3BADFL)); + (*g_143) = (safe_mod_func_int8_t_s_s(((0xCFL > (safe_rshift_func_uint16_t_u_s((((((*g_1937) == (void*)0) != (*g_143)) && (safe_lshift_func_uint16_t_u_u((((~((*g_289) = (((((safe_lshift_func_uint8_t_u_s(l_2115, 4)) > (-6L)) && ((*l_2127) ^= (*g_289))) , (l_2128 >= (((safe_mod_func_uint16_t_u_u((safe_sub_func_uint8_t_u_u((((*l_2100) = ((safe_add_func_uint8_t_u_u(l_1658[l_1722][(l_1692 + 3)], l_2102[2][1])) ^ l_2135)) < l_2102[0][3]), (**g_175))), l_1658[l_1692][(l_1722 + 1)])) & 3L) , 1L))) >= 1UL))) & l_2108) > 1L), 6))) ^ 0xA1E6L), 14))) <= (*g_132)), (-6L))); + } + (*l_2100) &= (((*l_2137) = l_2136) == (void*)0); + l_2050 &= ((safe_mod_func_int8_t_s_s((l_1634 = (*g_132)), (safe_mod_func_int16_t_s_s((((*g_143) = (*g_143)) > (g_1857 < (l_2058 && (g_2148 |= (((((((void*)0 != &l_2086) == ((***g_735) = (((+(((l_2146 ^= (~(((safe_div_func_int32_t_s_s(0xBFC11C93L, (safe_mod_func_uint32_t_u_u(l_2095, (((*g_289) < 4L) , (*g_1781)))))) ^ 0x95679D65L) >= 0xA1895B12L))) >= (**g_131)) && 4294967293UL)) >= (**g_131)) , g_2147[7]))) , l_2146) <= l_2102[6][0]) , 0xB3BFL) == (-1L)))))), g_705[2])))) == 0x3157L); + if ((*g_143)) + { /* block id: 1003 */ + int32_t ****l_2158 = (void*)0; + int32_t ****l_2159 = &l_2157; + uint16_t *l_2160 = &l_1902; + l_2102[6][0] = (((safe_rshift_func_int16_t_s_u((0L ^ (safe_rshift_func_int8_t_s_s((((*l_2160) = (safe_div_func_int32_t_s_s((safe_mod_func_uint16_t_u_u((((*l_2159) = l_2157) == (void*)0), g_1333)), (*l_2100)))) > ((safe_add_func_int32_t_s_s(0x43A31542L, (safe_rshift_func_uint8_t_u_s((((*l_2136) = ((*g_289) = 0x48A9L)) <= l_2146), (((((((**g_736)--) , &g_960) == l_2167) & l_2089) <= (*g_1781)) < (**g_131)))))) < (*g_143))), 5))), 5)) ^ 0xDFCAL) & 65532UL); + (**g_960) = (***l_2167); + } + else + { /* block id: 1011 */ + int32_t l_2169 = 0xB5AD6469L; + (**g_960) = func_22((*g_289), (*g_1781), l_2168); + (*g_143) = l_2169; + } + } + else + { /* block id: 1015 */ + int32_t **l_2170[5]; + int i; + for (i = 0; i < 5; i++) + l_2170[i] = &l_1797; + l_2100 = ((**l_1785) = (**g_960)); + } + (**g_960) = func_22((safe_div_func_uint16_t_u_u(((((safe_add_func_uint16_t_u_u((l_1692 , g_34), (safe_add_func_uint8_t_u_u(l_2095, 250UL)))) ^ (*g_132)) & ((safe_mod_func_uint32_t_u_u((5UL < (((*l_2179) = ((void*)0 == (**g_1656))) && (safe_mul_func_int16_t_s_s((((l_2182 > 1UL) <= (*g_143)) != (*g_289)), 1UL)))), 0x328F77E6L)) , 1L)) | 1L), g_140)), (***g_735), &l_2048); + for (l_2099 = 0; (l_2099 <= 2); l_2099 += 1) + { /* block id: 1023 */ + int32_t l_2183 = 0x7A6C031CL; + ++l_2184; + l_2102[2][3] = ((*g_143) = (l_2187[0] == &g_1184)); + } + return g_1099; + } + l_2191++; + } + else + { /* block id: 1031 */ + return l_2194; + } + g_2207 |= ((*g_143) = (safe_sub_func_int32_t_s_s(l_2056, (safe_div_func_uint8_t_u_u(((((!(*g_289)) , ((safe_sub_func_int8_t_s_s(((((*l_2201) = &g_904[2][1]) != &g_1547[0][5][0]) & 0x784FL), (safe_sub_func_uint16_t_u_u((l_2205 == (void*)0), g_1132)))) || (0L > (-1L)))) , &g_1019[4][0][0]) != &g_1019[5][0][0]), l_1612))))); + if (l_2050) + goto lbl_2208; + } + return l_1658[1][1]; +} + + +/* ------------------------------------------ */ +/* + * reads : g_290 g_143 g_905 g_1298 + * writes: g_290 g_140 g_175 g_1298 + */ +static int8_t func_10(uint32_t p_11) +{ /* block id: 756 */ + uint32_t l_1605 = 3UL; + uint8_t **l_1608[3][5] = {{&g_43,&g_43,&g_43,&g_43,&g_43},{&g_43,&g_43,&g_43,&g_43,&g_43},{&g_43,&g_43,&g_43,&g_43,&g_43}}; + int i, j; + for (g_290 = 0; (g_290 >= 1); g_290++) + { /* block id: 759 */ + int32_t l_1603 = (-1L); + int32_t *l_1604[10]; + int i; + for (i = 0; i < 10; i++) + l_1604[i] = &g_297[1]; + (*g_143) = (safe_mod_func_int32_t_s_s(l_1603, p_11)); + l_1605++; + if (p_11) + break; + } + (*g_905) = l_1608[2][0]; + for (g_1298 = (-1); (g_1298 == 37); g_1298 = safe_add_func_uint16_t_u_u(g_1298, 9)) + { /* block id: 767 */ + return l_1605; + } + return l_1605; +} + + +/* ------------------------------------------ */ +/* + * reads : g_52 g_43 g_44 g_51 g_251 g_143 g_140 g_176 g_705 g_289 g_290 g_297 g_255 g_55 g_56 g_36 g_34 g_131 g_132 g_243 g_347 g_320 g_736 g_294 g_175 g_897 g_905 g_735 g_960 g_969 g_961 g_312 g_1334 g_1132 g_1184 g_1185 g_1099 g_1298 g_40 + * writes: g_46 g_36 g_255 g_297 g_140 g_312 g_294 g_51 g_34 g_56 g_44 g_347 g_290 g_897 g_904 g_419 g_251 g_969 g_1334 g_1132 g_1298 g_175 + */ +static int32_t func_16(int8_t p_17, uint32_t * p_18, uint32_t * p_19, uint16_t p_20, uint32_t p_21) +{ /* block id: 16 */ + uint32_t l_57 = 0xB31DF952L; + uint32_t *l_58 = &g_56; + int32_t * const l_59[10] = {&g_51[1][4][2],&g_51[1][4][2],&g_51[1][4][2],&g_51[1][4][2],&g_51[1][4][2],&g_51[1][4][2],&g_51[1][4][2],&g_51[1][4][2],&g_51[1][4][2],&g_51[1][4][2]}; + uint32_t l_74[2][9] = {{0x548DC091L,0x548DC091L,0x548DC091L,0x548DC091L,0x548DC091L,0x548DC091L,0x548DC091L,0x548DC091L,0x548DC091L},{0UL,0x253094EEL,0UL,0x253094EEL,0UL,0x253094EEL,0UL,0x253094EEL,0UL}}; + uint8_t *l_1340[8][7] = {{&g_40[1],&g_40[5],&g_1298,&g_1298,&g_40[5],&g_40[1],&g_40[1]},{&g_40[5],&g_40[1],(void*)0,&g_1298,&g_1298,(void*)0,&g_40[1]},{&g_40[5],&g_40[1],&g_40[1],&g_40[5],&g_1298,&g_1298,&g_40[5]},{&g_40[1],&g_40[1],&g_40[1],&g_1298,&g_40[1],&g_40[1],&g_40[1]},{&g_40[1],&g_40[5],(void*)0,&g_40[5],&g_40[1],(void*)0,&g_1298},{&g_1298,&g_40[1],&g_1298,&g_1298,&g_1298,&g_40[1],&g_1298},{&g_40[1],&g_1298,&g_40[1],&g_1298,&g_1298,&g_1298,&g_40[1]},{&g_1298,&g_40[1],&g_1298,&g_40[1],&g_1298,&g_1298,&g_1298}}; + uint8_t *l_1341 = (void*)0; + uint8_t l_1385 = 0UL; + const int8_t *l_1399 = &g_255; + const int8_t ** const l_1398 = &l_1399; + const int8_t ** const *l_1397 = &l_1398; + int16_t **l_1400 = &g_289; + int8_t l_1404 = 0xDEL; + int16_t l_1460 = 0x14BCL; + uint8_t ** const *l_1553 = &g_175; + int32_t *l_1557[2]; + const uint32_t *l_1564[2]; + const uint32_t **l_1563[9][8][3] = {{{&l_1564[1],&l_1564[1],&l_1564[1]},{&l_1564[0],(void*)0,(void*)0},{&l_1564[1],&l_1564[0],&l_1564[1]},{(void*)0,&l_1564[1],&l_1564[1]},{&l_1564[0],&l_1564[1],(void*)0},{(void*)0,&l_1564[1],&l_1564[1]},{&l_1564[1],&l_1564[1],&l_1564[1]},{&l_1564[1],&l_1564[1],&l_1564[1]}},{{(void*)0,&l_1564[0],&l_1564[1]},{&l_1564[1],(void*)0,&l_1564[1]},{&l_1564[0],&l_1564[1],&l_1564[1]},{&l_1564[1],&l_1564[0],&l_1564[1]},{&l_1564[1],&l_1564[1],(void*)0},{&l_1564[0],&l_1564[1],&l_1564[1]},{&l_1564[0],&l_1564[1],&l_1564[0]},{&l_1564[0],&l_1564[1],&l_1564[1]}},{{&l_1564[0],&l_1564[1],&l_1564[0]},{&l_1564[0],&l_1564[1],&l_1564[1]},{&l_1564[1],&l_1564[1],&l_1564[1]},{&l_1564[1],&l_1564[1],&l_1564[1]},{&l_1564[0],&l_1564[0],&l_1564[1]},{&l_1564[1],&l_1564[1],&l_1564[1]},{(void*)0,&l_1564[1],&l_1564[0]},{&l_1564[1],&l_1564[1],&l_1564[0]}},{{&l_1564[1],&l_1564[0],&l_1564[0]},{(void*)0,&l_1564[1],&l_1564[0]},{&l_1564[0],&l_1564[1],&l_1564[0]},{(void*)0,&l_1564[1],&l_1564[1]},{&l_1564[1],(void*)0,&l_1564[1]},{&l_1564[0],(void*)0,&l_1564[1]},{&l_1564[1],&l_1564[1],&l_1564[1]},{&l_1564[1],&l_1564[1],&l_1564[1]}},{{&l_1564[1],&l_1564[1],&l_1564[0]},{&l_1564[1],(void*)0,&l_1564[1]},{&l_1564[1],&l_1564[1],&l_1564[0]},{&l_1564[1],(void*)0,&l_1564[1]},{&l_1564[1],&l_1564[1],(void*)0},{&l_1564[1],&l_1564[1],&l_1564[1]},{&l_1564[1],&l_1564[1],&l_1564[1]},{&l_1564[1],(void*)0,&l_1564[1]}},{{&l_1564[1],(void*)0,&l_1564[1]},{&l_1564[0],&l_1564[1],&l_1564[1]},{(void*)0,&l_1564[1],&l_1564[1]},{&l_1564[1],&l_1564[1],&l_1564[1]},{&l_1564[1],&l_1564[0],(void*)0},{&l_1564[1],&l_1564[1],&l_1564[1]},{(void*)0,&l_1564[1],&l_1564[1]},{&l_1564[0],&l_1564[1],(void*)0}},{{&l_1564[1],&l_1564[0],&l_1564[1]},{&l_1564[1],&l_1564[1],(void*)0},{&l_1564[1],&l_1564[1],&l_1564[0]},{&l_1564[1],&l_1564[1],&l_1564[1]},{&l_1564[1],&l_1564[1],&l_1564[1]},{&l_1564[1],&l_1564[1],&l_1564[1]},{&l_1564[1],&l_1564[1],&l_1564[1]},{&l_1564[1],&l_1564[1],&l_1564[1]}},{{&l_1564[1],&l_1564[1],&l_1564[0]},{&l_1564[1],&l_1564[0],(void*)0},{&l_1564[1],&l_1564[1],&l_1564[1]},{&l_1564[0],(void*)0,(void*)0},{&l_1564[1],&l_1564[0],&l_1564[1]},{(void*)0,&l_1564[1],&l_1564[0]},{&l_1564[1],&l_1564[1],&l_1564[1]},{(void*)0,&l_1564[1],&l_1564[0]}},{{&l_1564[1],&l_1564[1],&l_1564[0]},{&l_1564[1],&l_1564[1],&l_1564[1]},{(void*)0,&l_1564[1],&l_1564[1]},{&l_1564[1],&l_1564[1],&l_1564[0]},{(void*)0,&l_1564[1],&l_1564[1]},{&l_1564[1],&l_1564[1],&l_1564[1]},{(void*)0,&l_1564[0],(void*)0},{(void*)0,(void*)0,&l_1564[1]}}}; + const uint32_t ***l_1562 = &l_1563[2][1][2]; + const uint32_t ****l_1561 = &l_1562; + int32_t l_1574 = (-3L); + int32_t l_1577 = (-2L); + const uint8_t *l_1594 = &g_320; + const uint8_t **l_1593 = &l_1594; + int i, j, k; + for (i = 0; i < 2; i++) + l_1557[i] = &g_1132; + for (i = 0; i < 2; i++) + l_1564[i] = (void*)0; + if (((*g_143) = ((((((*p_18) = l_57) > ((l_58 = &l_57) != ((((l_59[2] != ((safe_rshift_func_int8_t_s_s(g_52, (((void*)0 == p_19) , ((*g_43) , (func_62(func_65((((l_1340[5][0] = func_71(l_74[0][4], p_20)) != l_1341) >= (-1L)), p_17, p_17, p_18, p_19), p_20) & l_1385))))) , (void*)0)) , 5L) == p_21) , (void*)0))) , 1L) | p_21) < p_17))) + { /* block id: 667 */ + int16_t l_1396[4]; + int32_t l_1421 = 7L; + int32_t l_1462 = 0x12662E75L; + int32_t l_1465 = 0x863BF099L; + int32_t l_1467 = 0L; + int32_t l_1470 = 2L; + int32_t l_1477 = 0x4CD2A26BL; + int32_t l_1490[10][2][5] = {{{0L,1L,8L,0x286E9DC0L,0x5DE9A0F1L},{0L,0x8BAB543FL,0x040A2369L,0x8BAB543FL,0L}},{{0x5DE9A0F1L,0x286E9DC0L,8L,1L,0L},{0L,0xF9205F80L,0x3F2E14FAL,0x8BAB543FL,(-1L)}},{{0L,0x286E9DC0L,(-4L),0x286E9DC0L,0L},{(-1L),0x8BAB543FL,0x3F2E14FAL,0xF9205F80L,0L}},{{0L,1L,8L,0x286E9DC0L,0x5DE9A0F1L},{0L,0x8BAB543FL,0x040A2369L,0x8BAB543FL,0L}},{{0x5DE9A0F1L,0x286E9DC0L,8L,1L,0L},{0L,0xF9205F80L,0x3F2E14FAL,0x8BAB543FL,(-1L)}},{{0L,0x286E9DC0L,(-4L),0x286E9DC0L,0L},{(-1L),0x8BAB543FL,0x3F2E14FAL,0xF9205F80L,0L}},{{0L,1L,8L,0x286E9DC0L,0x5DE9A0F1L},{0L,0x8BAB543FL,0x040A2369L,0x8BAB543FL,0L}},{{0x5DE9A0F1L,0x286E9DC0L,8L,1L,0L},{0L,0xF9205F80L,0x3F2E14FAL,0x8BAB543FL,(-1L)}},{{0L,0x286E9DC0L,(-4L),0x286E9DC0L,0L},{(-1L),0x8BAB543FL,0x3F2E14FAL,0xF9205F80L,0L}},{{0L,1L,8L,0x286E9DC0L,0x5DE9A0F1L},{0L,0x8BAB543FL,0x040A2369L,0x8BAB543FL,0L}}}; + uint8_t l_1499 = 0xACL; + const int32_t l_1539[1][3] = {{0L,0L,0L}}; + uint32_t ****l_1575 = &g_1237[6][2][0]; + int32_t **l_1579 = (void*)0; + int i, j, k; + for (i = 0; i < 4; i++) + l_1396[i] = (-1L); + for (g_1298 = 1; (g_1298 <= 5); g_1298 += 1) + { /* block id: 670 */ + int16_t **l_1401 = (void*)0; + uint16_t *l_1402 = &g_969; + int32_t l_1403 = (-1L); + uint32_t ***l_1405 = &g_1238; + uint32_t **l_1406 = &g_55; + uint32_t *l_1422[9]; + uint16_t l_1431 = 3UL; + int32_t l_1432 = 0xD4EEA904L; + int16_t ***l_1449 = &l_1401; + int32_t l_1464 = (-8L); + int32_t l_1468 = (-7L); + int32_t l_1469[8][4] = {{0x419228AFL,0xBFCFCC48L,0x419228AFL,2L},{0x3A8515F3L,0xBFCFCC48L,0x213DF6CAL,0xBFCFCC48L},{0x3A8515F3L,2L,0x419228AFL,0xBFCFCC48L},{0x419228AFL,0xBFCFCC48L,0x419228AFL,2L},{0x3A8515F3L,0xBFCFCC48L,0x213DF6CAL,0xBFCFCC48L},{0x3A8515F3L,2L,0x419228AFL,0xBFCFCC48L},{0x419228AFL,0xBFCFCC48L,0x419228AFL,2L},{0x3A8515F3L,0xBFCFCC48L,0x213DF6CAL,0xBFCFCC48L}}; + int8_t l_1493 = 0L; + int32_t **l_1532 = &g_312[0][0][4]; + int i, j; + for (i = 0; i < 9; i++) + l_1422[i] = &g_1099; + } + } + else + { /* block id: 747 */ + int16_t l_1580 = (-1L); + const uint8_t ***l_1595 = &l_1593; + uint8_t *l_1598[2]; + int i; + for (i = 0; i < 2; i++) + l_1598[i] = &g_1298; + (*g_143) = l_1580; + l_1557[1] = ((safe_lshift_func_int8_t_s_s((!(safe_rshift_func_uint8_t_u_s((l_1580 & (((safe_lshift_func_int16_t_s_u((safe_mod_func_uint8_t_u_u((safe_sub_func_uint16_t_u_u((((g_40[1] != g_34) , ((*l_1595) = l_1593)) == ((*g_905) = &l_1340[5][4])), (safe_sub_func_int32_t_s_s((((void*)0 != l_1598[0]) , ((*g_143) |= p_20)), (((l_1580 ^ l_1580) && p_21) , p_20))))), p_17)), p_20)) && p_17) < p_21)), l_1580))), l_1580)) , (*g_961)); + return l_1580; + } + return p_21; +} + + +/* ------------------------------------------ */ +/* + * reads : g_52 g_46 g_51 + * writes: g_52 g_51 g_36 g_40 + */ +static uint32_t * func_22(int16_t p_23, uint32_t p_24, uint32_t * p_25) +{ /* block id: 10 */ + int32_t *l_45 = &g_46; + int32_t *l_47 = (void*)0; + int32_t *l_48 = &g_46; + int32_t *l_49 = &g_46; + int32_t *l_50[1]; + int i; + for (i = 0; i < 1; i++) + l_50[i] = &g_46; + --g_52; + g_51[0][3][1] &= (*l_48); + for (g_52 = 0; g_52 < 2; g_52 += 1) + { + for (g_36 = 0; g_36 < 8; g_36 += 1) + { + for (p_24 = 0; p_24 < 3; p_24 += 1) + { + g_51[g_52][g_36][p_24] = 0x6F67A21EL; + } + } + } + for (p_24 = 0; p_24 < 7; p_24 += 1) + { + g_40[p_24] = 248UL; + } + return l_50[0]; +} + + +/* ------------------------------------------ */ +/* + * reads : g_143 g_140 + * writes: g_140 + */ +static int32_t func_62(int32_t * p_63, uint8_t p_64) +{ /* block id: 663 */ + uint32_t l_1384 = 4294967295UL; + (*g_143) &= l_1384; + return (*g_143); +} + + +/* ------------------------------------------ */ +/* + * reads : g_143 g_140 g_1132 g_735 g_736 g_55 g_289 g_290 g_56 g_176 g_43 g_1184 g_1185 g_1099 g_44 g_297 g_36 g_51 g_705 g_34 g_131 g_132 g_243 g_347 g_320 g_294 g_175 g_255 g_897 g_905 g_251 g_960 g_969 g_961 g_312 g_1334 + * writes: g_1132 g_44 g_36 g_140 g_312 g_51 g_34 g_56 g_297 g_347 g_290 g_255 g_897 g_904 g_294 g_419 g_251 g_969 g_1334 + */ +static int32_t * func_65(int8_t p_66, uint16_t p_67, uint8_t p_68, int32_t * p_69, uint32_t * p_70) +{ /* block id: 647 */ + int32_t *l_1342 = &g_1132; + int8_t *l_1361 = &g_36; + uint16_t *l_1362[3][5][2] = {{{&g_969,&g_969},{&g_969,&g_969},{&g_969,&g_969},{&g_969,&g_969},{&g_969,&g_969}},{{&g_969,&g_969},{&g_969,&g_969},{&g_969,&g_969},{&g_969,&g_969},{&g_969,&g_969}},{{&g_969,&g_969},{&g_969,&g_969},{&g_969,(void*)0},{&g_969,&g_969},{&g_251,&g_251}}}; + int32_t l_1363[2]; + uint32_t *l_1375[6][5] = {{(void*)0,&g_477,&g_1099,&g_1099,&g_477},{(void*)0,&g_294[0],&g_1099,&g_477,&g_1334},{&g_294[0],&g_1099,&g_1099,(void*)0,&g_1099},{&g_1334,&g_1334,&g_1099,(void*)0,(void*)0},{&g_294[0],(void*)0,(void*)0,(void*)0,(void*)0},{(void*)0,&g_294[2],(void*)0,(void*)0,&g_1334}}; + int32_t l_1376 = 1L; + uint32_t l_1379 = 0xCFCA353CL; + const uint32_t **l_1382 = (void*)0; + const uint32_t ***l_1381 = &l_1382; + const uint32_t ****l_1380[2][1][7] = {{{(void*)0,&l_1381,&l_1381,&l_1381,(void*)0,&l_1381,&l_1381}},{{(void*)0,&l_1381,&l_1381,&l_1381,(void*)0,&l_1381,&l_1381}}}; + const uint32_t ***l_1383 = &l_1382; + int i, j, k; + for (i = 0; i < 2; i++) + l_1363[i] = 0xABF6ADA9L; + (*l_1342) ^= (*g_143); + if (g_140) + goto lbl_1364; + p_69 = func_94((**g_735), (*l_1342), (((((((safe_div_func_int32_t_s_s((safe_mul_func_uint16_t_u_u((safe_rshift_func_int16_t_s_u(p_66, (0xC741L && (((safe_div_func_int8_t_s_s((((safe_mul_func_uint8_t_u_u(0xD3L, (safe_rshift_func_int16_t_s_s((safe_add_func_uint16_t_u_u(((0L > (*g_289)) & (((l_1363[0] = ((p_68 = (safe_mul_func_uint8_t_u_u((((*l_1361) = ((((**g_176) = (safe_mod_func_int16_t_s_s(((((***g_735) , 0x0EL) >= (*l_1342)) || (*g_289)), p_68))) <= 0x01L) < (*l_1342))) , (*l_1342)), p_68))) != 0xDAL)) != p_66) == (*l_1342))), (***g_1184))), 10)))) & 0xF1L) != 249UL), (*l_1342))) != (***g_1184)) > 0x40L)))), (*l_1342))), (*p_70))) , (void*)0) == l_1361) <= g_1099) < (*l_1342)) < (*l_1342)) , (*g_143)), (*l_1342), (*l_1342)); +lbl_1364: + (*g_143) = (+(*l_1342)); + (*g_143) = (1UL == (((safe_rshift_func_int8_t_s_u((safe_lshift_func_int8_t_s_s(((void*)0 != (*g_905)), (3UL != ((safe_rshift_func_int8_t_s_s(((l_1383 = ((((safe_div_func_uint32_t_u_u((p_66 <= (*l_1342)), (l_1376 = (++(*p_70))))) == g_251) && (g_34 <= (p_67 = (((*l_1342) = (safe_sub_func_int16_t_s_s((((((*l_1342) || (-1L)) != (*l_1342)) == l_1379) <= p_67), 0xD1CDL))) & l_1376)))) , (void*)0)) != (void*)0), 0)) != p_68)))), p_66)) ^ 65535UL) || 1UL)); + return p_69; +} + + +/* ------------------------------------------ */ +/* + * reads : g_51 g_44 g_251 g_143 g_140 g_176 g_43 g_705 g_289 g_290 g_297 g_255 g_55 g_56 g_36 g_34 g_131 g_132 g_243 g_347 g_320 g_736 g_294 g_175 g_897 g_905 g_735 g_960 g_969 g_961 g_312 g_1334 + * writes: g_36 g_255 g_297 g_140 g_312 g_294 g_51 g_34 g_56 g_44 g_347 g_290 g_897 g_904 g_419 g_251 g_969 g_1334 + */ +static uint8_t * func_71(uint32_t p_72, int8_t p_73) +{ /* block id: 19 */ + int32_t *l_75 = &g_51[0][3][1]; + int32_t *l_76 = &g_51[0][2][2]; + int32_t *l_77 = &g_51[0][7][1]; + int32_t *l_78 = &g_51[0][3][1]; + int32_t *l_79 = &g_51[0][5][2]; + int32_t *l_80 = &g_51[0][0][0]; + int32_t *l_81 = &g_51[1][3][1]; + int32_t *l_82 = &g_51[1][0][1]; + int32_t *l_83 = &g_51[0][3][1]; + int32_t *l_84 = (void*)0; + int32_t l_85[9][2][7] = {{{(-4L),(-7L),0x7DDA0CFDL,(-8L),0x77CB2DEBL,0x5D6CB7F0L,0L},{0x9A3785E6L,0x69DBBC94L,(-10L),0x74D9FAD1L,(-10L),0x69DBBC94L,0x9A3785E6L}},{{0x5D6CB7F0L,0x6F9888A1L,1L,0x139E91ECL,0xC7048B0AL,0xFEAE78DFL,0x4ABCDCAFL},{(-10L),(-8L),(-1L),3L,0x74D9FAD1L,4L,0x204C5B33L}},{{0x7DDA0CFDL,4L,1L,7L,0x6F9888A1L,7L,1L},{0xB031E64CL,0xB031E64CL,(-10L),1L,0x2DE0ECACL,0x40782372L,0x501D8DD5L}},{{0x6F9888A1L,0x24FAE1B8L,0x7DDA0CFDL,1L,0x4ABCDCAFL,4L,(-7L)},{(-1L),0xEF1A95A0L,0x40782372L,0x53E6AFD1L,0x2DE0ECACL,1L,0x2DE0ECACL}},{{0L,0x4ABCDCAFL,0x4ABCDCAFL,0L,0x6F9888A1L,(-1L),0xE2E886BEL},{0x53E6AFD1L,0x40782372L,0xEF1A95A0L,(-1L),0x74D9FAD1L,0x204C5B33L,1L}},{{1L,0x7DDA0CFDL,0x24FAE1B8L,0x6F9888A1L,0xC7048B0AL,(-4L),0xE2E886BEL},{1L,(-10L),0xB031E64CL,0xB031E64CL,(-10L),1L,0x2DE0ECACL}},{{7L,1L,4L,0x7DDA0CFDL,0x77CB2DEBL,(-1L),(-7L)},{3L,(-1L),(-8L),(-10L),0x53E6AFD1L,0x9A3785E6L,0x501D8DD5L}},{{0x139E91ECL,1L,0x6F9888A1L,0x5D6CB7F0L,0x5D6CB7F0L,0x6F9888A1L,1L},{0x74D9FAD1L,(-10L),0x69DBBC94L,0x9A3785E6L,0x75422B1FL,(-1L),0x204C5B33L}},{{(-8L),0x7DDA0CFDL,(-7L),(-4L),(-1L),0xA96CD894L,0x4ABCDCAFL},{0x69DBBC94L,0x40782372L,0x204C5B33L,0x9A3785E6L,(-8L),(-8L),0x9A3785E6L}}}; + int32_t *l_86 = &l_85[0][1][0]; + int32_t *l_87 = (void*)0; + int32_t *l_88 = &l_85[1][1][4]; + int32_t *l_89 = &g_51[0][3][1]; + int32_t *l_90[3][9] = {{(void*)0,(void*)0,&g_51[0][5][2],(void*)0,(void*)0,&g_51[0][5][2],(void*)0,(void*)0,&g_51[0][5][2]},{&g_3,&g_3,(void*)0,&g_3,&g_3,(void*)0,&g_51[0][3][1],&g_51[0][3][1],&g_3},{(void*)0,(void*)0,(void*)0,(void*)0,(void*)0,(void*)0,(void*)0,(void*)0,(void*)0}}; + uint8_t l_91[9][7][4] = {{{0x14L,253UL,255UL,0x88L},{0x51L,0x35L,0x0BL,254UL},{0xC0L,255UL,1UL,0x5BL},{253UL,0x8DL,0x88L,0x2BL},{0xD1L,0x2CL,0UL,0x01L},{0x9AL,0xD1L,0x35L,0x80L},{0x16L,0x3AL,0x9AL,0x39L}},{{6UL,1UL,0xF3L,0UL},{0x51L,1UL,0x4FL,1UL},{1UL,0x01L,0x50L,0xE4L},{0x30L,0x9AL,1UL,0UL},{0x93L,0x2CL,0x2CL,0x93L},{255UL,1UL,0xA9L,255UL},{4UL,2UL,0x4CL,0x88L}},{{0x5BL,254UL,0xF3L,0x88L},{0UL,2UL,1UL,255UL},{0xDFL,1UL,0x24L,0x93L},{0x23L,0x2CL,0x41L,0UL},{0xD1L,0x9AL,4UL,0xE4L},{0x16L,0x01L,0x23L,1UL},{0x2CL,1UL,248UL,0UL}},{{0x5BL,1UL,255UL,0x39L},{1UL,0x3AL,0x50L,0x80L},{0x80L,0xD1L,0x16L,0x01L},{0x5EL,0x2CL,1UL,0x2BL},{0xE4L,0x8DL,0xF0L,0x5BL},{4UL,255UL,0x51L,254UL},{0x4CL,0x35L,248UL,0x88L}},{{6UL,253UL,0UL,255UL},{253UL,0xF9L,0x24L,0x4DL},{248UL,6UL,0UL,0x01L},{0x23L,0x9AL,0x88L,5UL},{4UL,0UL,0x9AL,1UL},{0x2CL,0x14L,0xEBL,248UL},{0x4CL,1UL,0x4CL,0x39L}},{{0x14L,0xFDL,254UL,251UL},{0x30L,0x23L,0x16L,0xFDL},{0x4DL,6UL,0x16L,0x93L},{0x30L,0x8DL,254UL,0x4FL},{0x14L,0x30L,0x4CL,0xB0L},{0x4CL,0xB0L,0xEBL,254UL},{0x2CL,2UL,0x9AL,255UL}},{{4UL,1UL,0x88L,0x16L},{0x23L,0UL,0UL,0xFDL},{248UL,0xD1L,0x24L,0x8DL},{0xA2L,0xC0L,0x24L,2UL},{0x6AL,0x80L,0xDFL,4UL},{0xFDL,255UL,0x2CL,253UL},{0x80L,0xD2L,255UL,0UL}},{{0x8DL,0x88L,0x2BL,0x16L},{0xA5L,0xF0L,0x5EL,0UL},{0x39L,0x30L,0xEBL,0UL},{0x04L,1UL,0UL,1UL},{0UL,1UL,0xDFL,4UL},{0x4DL,0xF0L,1UL,0x41L},{255UL,1UL,1UL,1UL}},{{4UL,0x16L,0x16L,0x16L},{1UL,1UL,1UL,0x39L},{255UL,0x2CL,0x35L,0x30L},{0xF0L,0x80L,250UL,0x35L},{0UL,0x80L,0xFDL,0x30L},{0x80L,0x2CL,1UL,0x39L},{1UL,1UL,0x4DL,0x16L}}}; + uint32_t *l_115[8] = {&g_56,&g_56,&g_56,&g_56,&g_56,&g_56,&g_56,&g_56}; + int8_t *l_118 = &g_36; + int8_t **l_119 = &l_118; + int8_t *l_121 = &g_36; + int8_t **l_120 = &l_121; + int8_t **l_122 = (void*)0; + int8_t *l_124 = &g_36; + int8_t **l_123 = &l_124; + int8_t *l_126 = &g_36; + int8_t **l_125 = &l_126; + int8_t *l_127[7][8][4] = {{{&g_36,&g_36,&g_36,&g_36},{(void*)0,&g_36,&g_36,&g_36},{(void*)0,(void*)0,&g_36,&g_36},{(void*)0,(void*)0,(void*)0,(void*)0},{&g_36,&g_36,&g_36,(void*)0},{(void*)0,&g_36,&g_36,(void*)0},{&g_36,&g_36,&g_36,&g_36},{&g_36,&g_36,&g_36,(void*)0}},{{(void*)0,&g_36,&g_36,&g_36},{&g_36,&g_36,&g_36,&g_36},{&g_36,(void*)0,&g_36,&g_36},{&g_36,&g_36,&g_36,&g_36},{&g_36,&g_36,&g_36,&g_36},{&g_36,&g_36,&g_36,&g_36},{(void*)0,&g_36,&g_36,&g_36},{&g_36,(void*)0,&g_36,&g_36}},{{&g_36,&g_36,&g_36,&g_36},{&g_36,(void*)0,&g_36,&g_36},{&g_36,&g_36,&g_36,(void*)0},{&g_36,&g_36,&g_36,&g_36},{&g_36,&g_36,&g_36,&g_36},{(void*)0,&g_36,&g_36,(void*)0},{&g_36,&g_36,&g_36,(void*)0},{&g_36,&g_36,&g_36,&g_36}},{{&g_36,(void*)0,&g_36,(void*)0},{&g_36,&g_36,&g_36,&g_36},{&g_36,(void*)0,&g_36,&g_36},{(void*)0,(void*)0,&g_36,&g_36},{&g_36,&g_36,(void*)0,&g_36},{&g_36,(void*)0,&g_36,&g_36},{&g_36,(void*)0,&g_36,&g_36},{&g_36,&g_36,(void*)0,&g_36}},{{(void*)0,&g_36,&g_36,&g_36},{&g_36,(void*)0,&g_36,&g_36},{&g_36,&g_36,&g_36,&g_36},{(void*)0,&g_36,(void*)0,&g_36},{&g_36,&g_36,&g_36,&g_36},{&g_36,(void*)0,(void*)0,&g_36},{&g_36,(void*)0,(void*)0,(void*)0},{&g_36,&g_36,&g_36,&g_36}},{{&g_36,&g_36,&g_36,&g_36},{(void*)0,&g_36,(void*)0,(void*)0},{&g_36,(void*)0,&g_36,&g_36},{(void*)0,(void*)0,(void*)0,&g_36},{&g_36,&g_36,&g_36,&g_36},{(void*)0,&g_36,(void*)0,&g_36},{(void*)0,&g_36,&g_36,&g_36},{&g_36,(void*)0,(void*)0,&g_36}},{{&g_36,&g_36,(void*)0,&g_36},{&g_36,&g_36,&g_36,&g_36},{(void*)0,(void*)0,&g_36,&g_36},{&g_36,(void*)0,&g_36,&g_36},{&g_36,&g_36,&g_36,&g_36},{&g_36,(void*)0,&g_36,&g_36},{&g_36,&g_36,&g_36,(void*)0},{&g_36,&g_36,&g_36,&g_36}}}; + int8_t *l_129 = &g_36; + int8_t **l_128 = &l_129; + int8_t *l_130[4][2] = {{(void*)0,(void*)0},{(void*)0,(void*)0},{(void*)0,(void*)0},{(void*)0,(void*)0}}; + int32_t l_690 = (-1L); + int i, j, k; + ++l_91[2][2][0]; + (*g_961) = func_94(&g_56, ((g_51[1][1][2] >= func_100(func_105(((g_44 ^ ((g_44 , (safe_sub_func_int8_t_s_s((g_36 = (safe_add_func_uint8_t_u_u((safe_sub_func_int8_t_s_s(((*l_86) |= (((~(&g_56 != l_115[6])) , (((((safe_rshift_func_uint16_t_u_u(1UL, 14)) < ((((l_127[6][3][0] = ((*l_125) = ((*l_123) = ((*l_120) = ((*l_119) = l_118))))) == ((*l_128) = &p_73)) ^ 255UL) == p_73)) == 0xCAL) && 8L) ^ 0x2359L)) , p_72)), p_72)), g_51[1][2][0]))), 0xA4L))) == 6UL)) < 0xD5L)), l_690, (*l_79), g_251)) <= 255UL), p_72, (*l_77), p_73); + return (**g_905); +} + + +/* ------------------------------------------ */ +/* + * reads : g_36 g_176 g_43 g_44 g_297 g_143 g_140 g_51 g_705 g_34 g_131 g_132 g_55 g_56 g_243 g_289 g_347 g_320 g_736 g_294 g_175 g_255 g_897 g_905 g_290 g_735 g_251 g_960 g_969 g_961 g_312 g_1334 + * writes: g_36 g_140 g_312 g_51 g_34 g_56 g_297 g_44 g_347 g_290 g_255 g_897 g_904 g_294 g_419 g_251 g_969 g_1334 + */ +static int32_t * func_94(uint32_t * p_95, int32_t p_96, const int32_t p_97, int32_t p_98, int8_t p_99) +{ /* block id: 395 */ + int8_t l_778 = (-5L); + int32_t l_868[8] = {0xC949261DL,0xC949261DL,0xC949261DL,0xC949261DL,0xC949261DL,0xC949261DL,0xC949261DL,0xC949261DL}; + int32_t l_885 = 0L; + int32_t l_891 = 0x3573B375L; + int16_t * const l_916 = &g_419; + uint8_t *** const l_948 = &g_175; + int32_t l_982 = (-1L); + uint32_t *l_983 = &g_294[4]; + int32_t l_984 = 1L; + int8_t l_998 = 0L; + uint8_t ****l_1044[3]; + uint8_t l_1256 = 3UL; + int16_t l_1325[10][7] = {{0x9403L,(-1L),0x5345L,0x2B69L,0x41E0L,0x8199L,0x8199L},{0x640AL,(-1L),0x93F5L,(-1L),0x640AL,0xF19AL,0x93F5L},{(-1L),0x9403L,(-1L),0x5345L,0x2B69L,0x41E0L,0x8199L},{0xD399L,1L,0x6F08L,0xF19AL,0x6F08L,1L,0xD399L},{(-1L),0x5345L,0x8199L,0x2B69L,0x9403L,0x23E0L,(-1L)},{0x640AL,1L,1L,8L,0x640AL,8L,1L},{0x9403L,0x9403L,0x8199L,(-1L),(-1L),0x41E0L,0x5345L},{0x6F08L,(-1L),0x6F08L,8L,0xD399L,(-1L),0xD399L},{0x2B69L,(-1L),(-1L),0x2B69L,(-1L),0x8199L,0x23E0L},{0x640AL,0xF19AL,0x93F5L,0xF19AL,0x640AL,(-1L),0x93F5L}}; + int32_t *l_1339 = &g_51[1][1][1]; + int i, j; + for (i = 0; i < 3; i++) + l_1044[i] = &g_905; + for (g_36 = 0; (g_36 <= (-2)); --g_36) + { /* block id: 398 */ + if (l_778) + break; + } + (*g_143) = ((safe_mod_func_int32_t_s_s((safe_sub_func_uint8_t_u_u(l_778, (**g_176))), (safe_div_func_int16_t_s_s((-1L), (safe_add_func_int16_t_s_s(((void*)0 == &p_95), p_99)))))) , (safe_mul_func_int8_t_s_s(((safe_div_func_uint16_t_u_u((((safe_add_func_int32_t_s_s(p_96, 4294967286UL)) >= 0xB233L) && p_99), g_297[1])) & p_96), 0xFEL))); + for (g_36 = 1; (g_36 >= 0); g_36 -= 1) + { /* block id: 404 */ + int16_t l_806[2]; + int32_t l_814 = (-9L); + uint8_t *l_846[6][2][10] = {{{&g_40[1],&g_44,&g_320,&g_44,(void*)0,(void*)0,(void*)0,(void*)0,&g_320,(void*)0},{&g_40[0],&g_44,(void*)0,&g_40[1],&g_320,&g_40[5],&g_40[5],&g_320,&g_40[1],(void*)0}},{{(void*)0,(void*)0,&g_320,&g_320,&g_40[0],&g_40[3],(void*)0,&g_40[1],&g_44,&g_320},{&g_320,&g_40[1],&g_44,(void*)0,&g_40[1],&g_44,(void*)0,(void*)0,&g_40[6],&g_40[5]}},{{&g_40[5],(void*)0,&g_40[1],&g_40[1],&g_320,&g_320,&g_40[5],&g_40[5],&g_40[5],&g_40[1]},{(void*)0,&g_44,(void*)0,&g_44,&g_40[2],&g_40[5],(void*)0,&g_44,(void*)0,&g_40[1]}},{{(void*)0,&g_44,&g_40[0],(void*)0,&g_40[1],(void*)0,&g_40[0],&g_44,(void*)0,(void*)0},{&g_40[1],&g_40[1],&g_320,&g_44,&g_40[0],(void*)0,&g_44,(void*)0,&g_44,(void*)0}},{{&g_40[0],&g_320,(void*)0,&g_44,&g_40[6],&g_320,(void*)0,&g_40[3],(void*)0,&g_320},{(void*)0,(void*)0,&g_40[5],(void*)0,&g_40[1],&g_40[6],&g_40[1],&g_320,(void*)0,&g_44}},{{&g_40[2],&g_320,&g_320,&g_44,&g_40[3],&g_320,&g_44,&g_40[5],&g_40[5],&g_44},{(void*)0,(void*)0,&g_40[1],&g_40[1],(void*)0,(void*)0,(void*)0,&g_40[0],&g_40[6],(void*)0}}}; + int32_t l_870 = 0x0B9A60E1L; + int32_t l_872 = (-5L); + int32_t l_879 = 0x68AC52C0L; + int32_t l_880 = 1L; + int32_t l_882 = (-3L); + int32_t l_883 = 0x329F4C9FL; + int32_t l_884 = (-2L); + int32_t l_887 = 0x1D6C2448L; + int32_t l_888[9]; + uint8_t ***l_903 = &g_175; + uint8_t ****l_902[5][1] = {{&l_903},{&l_903},{&l_903},{&l_903},{&l_903}}; + int8_t **l_919 = &g_243[1][0][1]; + int i, j, k; + for (i = 0; i < 2; i++) + l_806[i] = 0xDFCAL; + for (i = 0; i < 9; i++) + l_888[i] = 0xAEB8A862L; + for (g_140 = 0; (g_140 <= 1); g_140 += 1) + { /* block id: 407 */ + const uint16_t l_807 = 0UL; + int32_t *l_809 = (void*)0; + int32_t *l_864 = &g_297[1]; + int32_t l_867 = 0xB4D5446DL; + int32_t l_869 = 1L; + int32_t l_871 = 0L; + int32_t l_873 = (-1L); + int8_t l_874 = 1L; + int32_t l_875 = 0x566BCB73L; + int32_t l_876 = 0x640B2514L; + int32_t l_877 = (-10L); + int32_t l_878 = 0L; + int32_t l_881[1][2][1]; + int32_t l_890 = (-10L); + int i, j, k; + for (i = 0; i < 1; i++) + { + for (j = 0; j < 2; j++) + { + for (k = 0; k < 1; k++) + l_881[i][j][k] = (-1L); + } + } + for (p_98 = 0; (p_98 <= 1); p_98 += 1) + { /* block id: 410 */ + uint16_t *l_837[7][2][10] = {{{&g_251,(void*)0,&g_251,(void*)0,&g_251,&g_251,&g_251,(void*)0,&g_251,(void*)0},{(void*)0,&g_251,&g_251,&g_251,(void*)0,&g_251,&g_251,&g_251,&g_251,&g_251}},{{&g_251,&g_251,&g_251,(void*)0,&g_251,&g_251,&g_251,(void*)0,&g_251,&g_251},{(void*)0,&g_251,&g_251,(void*)0,&g_251,&g_251,(void*)0,&g_251,&g_251,&g_251}},{{&g_251,&g_251,(void*)0,&g_251,(void*)0,&g_251,&g_251,&g_251,&g_251,(void*)0},{(void*)0,&g_251,&g_251,(void*)0,&g_251,&g_251,&g_251,(void*)0,&g_251,(void*)0}},{{&g_251,&g_251,&g_251,&g_251,(void*)0,(void*)0,&g_251,&g_251,&g_251,(void*)0},{(void*)0,&g_251,(void*)0,&g_251,&g_251,(void*)0,&g_251,(void*)0,(void*)0,&g_251}},{{&g_251,&g_251,&g_251,(void*)0,&g_251,&g_251,&g_251,&g_251,&g_251,&g_251},{(void*)0,&g_251,&g_251,&g_251,&g_251,&g_251,(void*)0,&g_251,(void*)0,&g_251}},{{&g_251,&g_251,&g_251,&g_251,&g_251,&g_251,&g_251,&g_251,(void*)0,&g_251},{&g_251,&g_251,&g_251,&g_251,&g_251,&g_251,(void*)0,&g_251,&g_251,(void*)0}},{{&g_251,&g_251,&g_251,&g_251,&g_251,(void*)0,&g_251,(void*)0,&g_251,&g_251},{&g_251,&g_251,&g_251,&g_251,&g_251,&g_251,&g_251,&g_251,&g_251,&g_251}}}; + int32_t l_848 = (-7L); + uint8_t *l_856 = &g_40[0]; + int32_t *l_860 = &l_848; + int i, j, k; + g_312[0][0][5] = (void*)0; + g_51[g_36][(p_98 + 1)][g_140] ^= 0x87124F79L; + for (g_34 = 0; (g_34 <= 1); g_34 += 1) + { /* block id: 415 */ + uint32_t l_805[5]; + int32_t *l_808 = &g_297[1]; + int i, j, k; + for (i = 0; i < 5; i++) + l_805[i] = 0UL; + (*l_808) ^= (((safe_mod_func_int32_t_s_s((!(~((g_51[g_36][g_140][g_36] != (g_705[p_98] && ((*g_55) |= ((g_705[(g_34 + 3)] <= ((safe_add_func_int16_t_s_s(g_705[(g_34 + 3)], (safe_sub_func_int32_t_s_s((2UL != ((safe_sub_func_int8_t_s_s(p_98, p_97)) , (safe_mul_func_int16_t_s_s((safe_add_func_int8_t_s_s((((g_51[0][3][1] < l_778) || l_805[0]) > (*g_143)), (**g_131))), l_806[0])))), l_778)))) > 0x76L)) & g_34)))) | l_807))), p_96)) > l_778) ^ p_99); + l_809 = &p_98; + } + for (p_96 = 0; (p_96 <= 1); p_96 += 1) + { /* block id: 422 */ + uint8_t l_847 = 1UL; + int i, j, k; + if (g_51[p_98][(g_36 + 5)][g_140]) + break; + l_814 = ((safe_mul_func_uint16_t_u_u(0x9540L, 65535UL)) <= (++(*g_43))); + for (g_347 = 4; (g_347 >= 0); g_347 -= 1) + { /* block id: 428 */ + int8_t *l_851 = &g_255; + int32_t *l_859 = &g_297[1]; + int i, j, k; + l_848 = (safe_rshift_func_int16_t_s_s((-1L), ((safe_mod_func_uint32_t_u_u(((g_51[g_140][(g_140 + 5)][g_140] = (safe_sub_func_int8_t_s_s((((safe_div_func_uint32_t_u_u(g_51[g_140][(g_36 + 2)][(g_140 + 1)], 2L)) <= (safe_unary_minus_func_uint32_t_u((safe_sub_func_int8_t_s_s((((safe_rshift_func_int8_t_s_s(((safe_add_func_int8_t_s_s((p_98 ^ (safe_add_func_int16_t_s_s((safe_sub_func_int16_t_s_s((safe_mul_func_uint8_t_u_u((((~(safe_unary_minus_func_int8_t_s((((((&g_251 == l_837[2][0][1]) ^ ((-1L) == ((*g_289) = (safe_lshift_func_uint16_t_u_s((l_814 = ((safe_lshift_func_int16_t_s_u(g_51[g_140][(g_36 + 2)][(g_140 + 1)], 13)) >= (safe_sub_func_uint8_t_u_u(((safe_div_func_int8_t_s_s((((g_243[(g_36 + 1)][g_36][(p_96 + 3)] == l_846[0][1][8]) == 0xC75DL) <= g_51[g_140][(g_36 + 2)][(g_140 + 1)]), g_51[p_98][(g_36 + 5)][g_140])) | p_99), 255UL)))), p_98))))) > l_847) , l_778) < 0x4EDBL)))) | g_347) != l_778), (*g_132))), g_51[p_98][(g_36 + 5)][g_140])), 0x4155L))), (*g_43))) <= (-4L)), 4)) < g_320) <= p_97), 0x7DL))))) | 0xE6F3L), p_96))) && (**g_736)), 1UL)) | 0x59L))); + if (p_97) + break; + (*l_859) ^= ((*p_95) && (((safe_div_func_int8_t_s_s(((*l_851) = (g_294[0] >= 0x74B3L)), ((**g_175) = (**g_176)))) , (safe_sub_func_uint8_t_u_u(((!(l_814 = (safe_mod_func_int8_t_s_s(((*l_851) ^= (l_856 == (void*)0)), (p_99 = (safe_lshift_func_int16_t_s_u(g_51[g_140][(g_140 + 5)][g_140], 2))))))) > g_51[g_36][(p_98 + 1)][g_140]), l_778))) , 0UL)); + l_860 = &l_814; + } + for (g_56 = 0; (g_56 <= 1); g_56 += 1) + { /* block id: 444 */ + int32_t **l_861 = &l_809; + (*l_861) = &g_51[0][3][1]; + if (p_99) + break; + } + } + } + (*l_864) = (((l_806[0] , (safe_lshift_func_uint8_t_u_u((p_97 ^ 0UL), 2))) & (~1UL)) == (**g_736)); + for (p_98 = 1; (p_98 >= 0); p_98 -= 1) + { /* block id: 453 */ + int32_t *l_865 = &l_814; + int32_t *l_866[5]; + int16_t l_886[3]; + int32_t l_889 = 0xF193AD92L; + uint32_t l_892 = 4294967295UL; + uint16_t *l_920 = &g_251; + uint32_t l_931 = 4UL; + const uint8_t *l_951[4]; + const uint8_t **l_950 = &l_951[3]; + const uint8_t *** const l_949 = &l_950; + int32_t ***l_962[9] = {&g_961,&g_961,&g_961,&g_961,&g_961,&g_961,&g_961,&g_961,&g_961}; + int i; + for (i = 0; i < 5; i++) + l_866[i] = (void*)0; + for (i = 0; i < 3; i++) + l_886[i] = 0x4E3AL; + for (i = 0; i < 4; i++) + l_951[i] = (void*)0; + l_892--; + for (l_877 = 4; (l_877 >= 0); l_877 -= 1) + { /* block id: 457 */ + uint8_t *****l_898 = (void*)0; + uint8_t *****l_899 = (void*)0; + uint8_t *****l_900 = (void*)0; + uint8_t *****l_901 = (void*)0; + int32_t l_929 = 0x9F81C2E6L; + int32_t l_930[6]; + uint32_t l_954 = 0UL; + int i, j, k; + for (i = 0; i < 6; i++) + l_930[i] = 0xF1E80E14L; + if ((safe_rshift_func_uint16_t_u_s((&g_736 == &g_736), (((g_294[g_140] != g_294[p_98]) && (((1UL != (((g_897 = g_897) != (g_904[0][3] = l_902[0][0])) != ((*g_289) = (((g_294[(g_140 + 1)] = ((safe_mod_func_int16_t_s_s(((**g_131) , (((p_97 || l_882) != 0x37DD31F2L) | 0L)), p_97)) || (*g_143))) ^ (*l_865)) , 1L)))) == (***g_905)) , (*g_289))) ^ (-7L))))) + { /* block id: 462 */ + uint16_t l_921 = 1UL; + int32_t l_922 = 0xB991C690L; + l_922 &= (safe_rshift_func_int8_t_s_u((((safe_div_func_uint8_t_u_u((((l_921 = (((((safe_lshift_func_uint8_t_u_u((1UL != (((safe_rshift_func_uint8_t_u_s((((void*)0 == l_916) == 0xDFCCF46BL), (((((*l_864) | ((p_99 = ((l_920 = (((l_868[1] , l_919) != &g_243[(p_98 + 3)][g_36][(p_98 + 6)]) , (void*)0)) == (void*)0)) <= g_294[(g_140 + 1)])) & 3UL) <= (***g_735)) || (**g_736)))) <= (***g_905)) > g_294[(g_140 + 1)])), p_98)) == (*g_289)) < g_51[0][3][1]) | p_98) , (**g_175))) < 0x64L) < l_814), l_888[1])) , (-4L)) , l_868[6]), 1)); + } + else + { /* block id: 467 */ + uint8_t l_923 = 0xE8L; + int32_t l_926 = (-9L); + int32_t l_927 = 8L; + int32_t l_928 = (-1L); + --l_923; + if (p_96) + continue; + l_931++; + } + (*l_864) = (safe_sub_func_uint8_t_u_u((((*l_865) = (((safe_div_func_uint8_t_u_u(((safe_mod_func_uint16_t_u_u(0xDC88L, (safe_rshift_func_int16_t_s_s(((0UL ^ (-6L)) > p_97), ((safe_add_func_uint16_t_u_u(l_868[6], (safe_add_func_int16_t_s_s((safe_rshift_func_uint8_t_u_s((l_948 == l_949), ((safe_sub_func_int16_t_s_s((l_954 > ((&g_289 != (void*)0) & g_140)), 0x0045L)) > 0UL))), 0xB58DL)))) < (*g_289)))))) < (***g_735)), l_868[6])) != p_98) | p_99)) & (*g_55)), 0x4AL)); + (*l_864) &= 0xD1CAA0FBL; + } + for (l_778 = 1; (l_778 >= 0); l_778 -= 1) + { /* block id: 478 */ + int16_t *l_959 = &l_806[1]; + int32_t l_965 = (-8L); + int8_t *l_966 = &g_255; + uint16_t *l_967 = &g_251; + uint16_t *l_968 = &g_969; + int i, j, k; + (*l_864) = (p_96 |= l_888[6]); + p_96 = (((6UL <= ((safe_mod_func_int8_t_s_s((g_251 , (((*g_289) <= (safe_mod_func_int16_t_s_s(((*l_959) &= ((*l_916) = 0x3137L)), (((g_960 != l_962[4]) , ((*l_968) &= ((*l_967) = ((((safe_add_func_uint16_t_u_u(0xEADCL, ((((((*l_966) &= (l_965 == l_879)) == 0xA5L) , p_96) >= p_96) ^ (*p_95)))) , 5UL) & (*g_143)) , p_99)))) , (*g_289))))) ^ (**g_176))), 3L)) == (*g_55))) && (**g_131)) <= p_97); + } + } + } + if (l_868[6]) + break; + } + if ((p_98 = (safe_mod_func_int16_t_s_s((*g_289), (safe_add_func_uint32_t_u_u(((l_984 = (0x4C7D768FL <= ((*l_983) ^= (safe_mul_func_int8_t_s_s(((**g_736) || (l_982 &= ((p_98 == (safe_sub_func_uint32_t_u_u((((l_948 == l_948) | (safe_lshift_func_int8_t_s_s((0x454BL <= l_868[3]), 0))) ^ ((safe_lshift_func_uint8_t_u_s((!255UL), 0)) <= l_885)), (*p_95)))) || (*g_55)))), 0x15L))))) & l_778), (*p_95))))))) + { /* block id: 496 */ + uint8_t ***l_993 = &g_175; + int16_t l_999 = 0x1B88L; + int8_t *** const *l_1034 = &g_1019[1][0][0]; + int32_t *l_1046 = &l_982; + int32_t l_1048[1][2][7] = {{{0xEA46108CL,0xEA46108CL,0xEA46108CL,0xEA46108CL,0xEA46108CL,0xEA46108CL,0xEA46108CL},{(-1L),(-1L),(-1L),(-1L),(-1L),(-1L),(-1L)}}}; + uint32_t l_1093[3]; + uint16_t l_1131 = 0xE112L; + int16_t **l_1135[6][2][5] = {{{&g_289,&g_289,&g_289,&g_289,(void*)0},{&g_289,&g_289,&g_289,&g_289,&g_289}},{{&g_289,(void*)0,&g_289,(void*)0,&g_289},{&g_289,&g_289,&g_289,(void*)0,(void*)0}},{{&g_289,(void*)0,(void*)0,&g_289,&g_289},{&g_289,(void*)0,(void*)0,&g_289,(void*)0}},{{(void*)0,&g_289,&g_289,&g_289,&g_289},{(void*)0,&g_289,(void*)0,&g_289,&g_289}},{{&g_289,&g_289,&g_289,&g_289,(void*)0},{&g_289,&g_289,&g_289,&g_289,&g_289}},{{&g_289,&g_289,&g_289,(void*)0,(void*)0},{&g_289,(void*)0,(void*)0,(void*)0,(void*)0}}}; + int32_t l_1180 = 0L; + uint8_t l_1276[9]; + int32_t *l_1294 = &g_1132; + int32_t *l_1320 = &g_51[0][3][1]; + int32_t *l_1321 = &g_140; + int32_t *l_1322 = &g_297[1]; + int32_t *l_1323 = &l_1048[0][1][0]; + int32_t *l_1324[1]; + int16_t l_1326 = 0x2195L; + int32_t l_1327 = 0x947976B8L; + uint16_t l_1328 = 0x24D6L; + int i, j, k; + for (i = 0; i < 3; i++) + l_1093[i] = 1UL; + for (i = 0; i < 9; i++) + l_1276[i] = 255UL; + for (i = 0; i < 1; i++) + l_1324[i] = &l_1048[0][0][6]; + for (g_44 = 0; (g_44 <= 6); g_44 += 1) + { /* block id: 499 */ + uint8_t ***l_994 = &g_175; + int8_t l_997 = 0xA6L; + int8_t ***l_1017 = &g_245; + int8_t ****l_1016 = &l_1017; + int32_t l_1050 = 0xF31EAA3DL; + int32_t l_1051 = 0x0917F34DL; + int32_t l_1056 = 0x36E77B1BL; + int32_t l_1057 = 0x4D998F65L; + int8_t l_1113 = 0x9DL; + uint32_t l_1114[6]; + int32_t l_1168 = 0xF8E5B00AL; + int32_t l_1170 = 0x729BDDB8L; + int32_t l_1171 = 1L; + int32_t l_1172 = (-1L); + int32_t l_1173 = 0L; + int32_t l_1176[5][7][6] = {{{0xBDCB05A3L,0L,0xCD8737B6L,0L,0xBDCB05A3L,0xC7DD3347L},{0L,0xBDCB05A3L,0xC7DD3347L,0xC7DD3347L,0xBDCB05A3L,0L},{(-6L),0L,0xF426EDDCL,0xBDCB05A3L,0xF426EDDCL,0L},{0xF426EDDCL,(-6L),0xC7DD3347L,0xCD8737B6L,0xCD8737B6L,0xCD8737B6L},{0xA0CC386BL,0xA0CC386BL,0xF426EDDCL,0xC7DD3347L,0L,0xC7DD3347L},{0xBDCB05A3L,0xA0CC386BL,0xBDCB05A3L,0xCD8737B6L,0xF426EDDCL,0xF426EDDCL},{(-6L),0xBDCB05A3L,0xBDCB05A3L,(-6L),0xA0CC386BL,0xC7DD3347L}},{{0xC7DD3347L,(-6L),0xF426EDDCL,(-6L),0xC7DD3347L,0xCD8737B6L},{(-6L),0xC7DD3347L,0xCD8737B6L,0xCD8737B6L,0xC7DD3347L,(-6L)},{0xBDCB05A3L,(-6L),0xA0CC386BL,0xC7DD3347L,0xA0CC386BL,(-6L)},{0xA0CC386BL,0xBDCB05A3L,0xCD8737B6L,0xF426EDDCL,0xF426EDDCL,0xCD8737B6L},{0xA0CC386BL,0xA0CC386BL,0xF426EDDCL,0xC7DD3347L,0L,0xC7DD3347L},{0xBDCB05A3L,0xA0CC386BL,0xBDCB05A3L,0xCD8737B6L,0xF426EDDCL,0xF426EDDCL},{(-6L),0xBDCB05A3L,0xBDCB05A3L,(-6L),0xA0CC386BL,0xC7DD3347L}},{{0xC7DD3347L,(-6L),0xF426EDDCL,(-6L),0xC7DD3347L,0xCD8737B6L},{(-6L),0xC7DD3347L,0xCD8737B6L,0xCD8737B6L,0xC7DD3347L,(-6L)},{0xBDCB05A3L,(-6L),0xA0CC386BL,0xC7DD3347L,0xA0CC386BL,(-6L)},{0xA0CC386BL,0xBDCB05A3L,0xCD8737B6L,0xF426EDDCL,0xF426EDDCL,0xCD8737B6L},{0xA0CC386BL,0xA0CC386BL,0xF426EDDCL,0xC7DD3347L,0L,0xC7DD3347L},{0xBDCB05A3L,0xA0CC386BL,0xBDCB05A3L,0xCD8737B6L,0xF426EDDCL,0xF426EDDCL},{(-6L),0xBDCB05A3L,0xBDCB05A3L,(-6L),0xA0CC386BL,0xC7DD3347L}},{{0xC7DD3347L,(-6L),0xF426EDDCL,(-6L),0xC7DD3347L,0xCD8737B6L},{(-6L),0xC7DD3347L,0xCD8737B6L,0xCD8737B6L,0xC7DD3347L,(-6L)},{0xBDCB05A3L,(-6L),0xA0CC386BL,0xC7DD3347L,0xA0CC386BL,(-6L)},{0xA0CC386BL,0xBDCB05A3L,0xCD8737B6L,0xF426EDDCL,0xF426EDDCL,0xCD8737B6L},{0xA0CC386BL,0xA0CC386BL,0xF426EDDCL,0xC7DD3347L,0L,0xC7DD3347L},{0xBDCB05A3L,0xA0CC386BL,0xBDCB05A3L,0xCD8737B6L,0xF426EDDCL,0xF426EDDCL},{(-6L),0xBDCB05A3L,0xBDCB05A3L,(-6L),0xA0CC386BL,0xC7DD3347L}},{{0xC7DD3347L,(-6L),0xF426EDDCL,(-6L),0xC7DD3347L,0xCD8737B6L},{(-6L),0xC7DD3347L,0xCD8737B6L,0xCD8737B6L,0xC7DD3347L,(-6L)},{0xBDCB05A3L,(-6L),0xA0CC386BL,0xC7DD3347L,0xA0CC386BL,(-6L)},{0xA0CC386BL,0xBDCB05A3L,0xCD8737B6L,0xF426EDDCL,0xF426EDDCL,0xCD8737B6L},{0xA0CC386BL,0xA0CC386BL,0xF426EDDCL,0xC7DD3347L,0L,0xC7DD3347L},{0xBDCB05A3L,0xA0CC386BL,0xBDCB05A3L,0xCD8737B6L,0xF426EDDCL,0xF426EDDCL},{(-6L),0xBDCB05A3L,0xBDCB05A3L,(-6L),0xA0CC386BL,0xC7DD3347L}}}; + uint32_t l_1319 = 0x3CC17454L; + int i, j, k; + for (i = 0; i < 6; i++) + l_1114[i] = 1UL; + } + --l_1328; + (*g_143) ^= ((*g_960) == (void*)0); + return (**g_960); + } + else + { /* block id: 635 */ + int32_t *l_1331 = &g_51[0][1][1]; + int32_t *l_1332[6] = {&g_1055,&g_1055,&g_1055,&g_1055,&g_1055,&g_1055}; + int i; + ++g_1334; + for (g_347 = 0; (g_347 == 26); g_347 = safe_add_func_uint16_t_u_u(g_347, 7)) + { /* block id: 639 */ + return (*g_961); + } + } + return l_1339; +} + + +/* ------------------------------------------ */ +/* + * reads : g_143 g_140 g_176 g_43 g_44 g_705 g_289 g_290 g_297 g_255 g_55 g_56 + * writes: g_255 g_297 g_140 g_312 g_294 + */ +static int8_t func_100(int32_t * p_101, uint8_t p_102, uint8_t p_103, uint32_t p_104) +{ /* block id: 323 */ + int8_t ***l_692 = (void*)0; + int8_t ****l_691 = &l_692; + int32_t l_697 = 0xB23966F9L; + int32_t l_704 = 0x17C47AB5L; + int32_t l_712 = 0x92F85846L; + uint32_t l_724 = 1UL; + uint32_t l_754 = 0x40901257L; + uint32_t l_755[9][7] = {{0x3F92B650L,0x3F92B650L,0x59DA734BL,0x3F92B650L,0x3F92B650L,0x59DA734BL,0x3F92B650L},{0x1D3867C8L,4294967286UL,4294967295UL,5UL,4294967295UL,4294967286UL,0x1D3867C8L},{0xB66E3024L,0x3F92B650L,0xB66E3024L,0xB66E3024L,0x3F92B650L,0xB66E3024L,0xB66E3024L},{0x1D3867C8L,5UL,0x67201704L,5UL,0x1D3867C8L,4294967295UL,0x1D3867C8L},{0x3F92B650L,0xB66E3024L,0xB66E3024L,0x3F92B650L,0xB66E3024L,0xB66E3024L,0x3F92B650L},{4294967295UL,5UL,4294967295UL,4294967286UL,0x1D3867C8L,4294967286UL,4294967295UL},{0x3F92B650L,0x3F92B650L,0x59DA734BL,0x3F92B650L,0x3F92B650L,0x59DA734BL,0x3F92B650L},{0x1D3867C8L,4294967286UL,4294967295UL,5UL,4294967295UL,4294967286UL,0x1D3867C8L},{0xB66E3024L,0x3F92B650L,0xB66E3024L,0xB66E3024L,0x3F92B650L,0xB66E3024L,0xB66E3024L}}; + int i, j; + if (((l_691 == &l_692) < (safe_mod_func_int16_t_s_s(((safe_mul_func_int16_t_s_s(((l_697 & (0UL != ((l_697 & ((0L ^ 0UL) <= (safe_mod_func_int32_t_s_s((*g_143), (safe_mod_func_uint8_t_u_u((safe_mul_func_uint8_t_u_u(((l_704 = (p_102 > l_697)) & (**g_176)), 0xD2L)), l_697)))))) && (-1L)))) , g_705[2]), (*g_289))) && l_697), (*g_289))))) + { /* block id: 325 */ + int16_t l_715 = (-7L); + int8_t *l_716 = &g_255; + int8_t **l_717 = (void*)0; + (*g_143) ^= (safe_div_func_int8_t_s_s(((((safe_lshift_func_int8_t_s_u(((((0x7466BED0L && ((safe_rshift_func_int8_t_s_s(l_712, ((0x6627434EL > (safe_mod_func_int16_t_s_s(l_715, 0xA37DL))) == ((((~g_297[1]) & p_102) , ((*p_101) = (p_104 < ((*l_716) ^= l_715)))) > (*g_55))))) && p_102)) , l_704) >= 0x8C828013L) , 0x19L), 6)) > l_715) , l_717) == &l_716), 1UL)); + return p_102; + } + else + { /* block id: 330 */ + int32_t **l_718 = &g_312[1][0][5]; + uint32_t *l_766 = &l_755[0][2]; + (*l_718) = p_101; + for (p_103 = 25; (p_103 != 48); ++p_103) + { /* block id: 334 */ + int8_t l_723[9][8][3] = {{{0x6BL,0L,0xCAL},{0xF4L,0xB1L,0x8BL},{0L,0L,0x53L},{0xBFL,0L,0x76L},{0xBFL,0x39L,0x1BL},{0L,1L,0xDFL},{0xF4L,0xBFL,0x1BL},{0x6BL,0x2AL,0x76L}},{{1L,0x2AL,0x53L},{1L,0xBFL,0x8BL},{0xA4L,1L,0xCAL},{1L,0x39L,0x10L},{1L,0L,0x10L},{0x6BL,0L,0xCAL},{0xF4L,0xB1L,0x8BL},{0L,0L,0x53L}},{{0xBFL,0L,0x76L},{0xBFL,0x39L,0x1BL},{0L,1L,0xDFL},{0xF4L,0xBFL,0x1BL},{0x6BL,0x2AL,0x76L},{1L,0x2AL,0x53L},{1L,0xBFL,0x8BL},{0xA4L,1L,0xCAL}},{{1L,0x39L,0x10L},{1L,0L,0x10L},{0x6BL,0L,0xCAL},{0xF4L,0xB1L,0x8BL},{0L,0L,0x53L},{0xBFL,0L,0x76L},{0xBFL,0x39L,0x1BL},{0L,1L,0xDFL}},{{0xF4L,0xBFL,0x1BL},{0x6BL,0x2AL,0x76L},{1L,0x2AL,0x53L},{1L,0xBFL,0x8BL},{0xA4L,1L,0xCAL},{1L,0x39L,0x10L},{1L,0L,0x10L},{0x6BL,0L,0xCAL}},{{0xF4L,0xB1L,0x8BL},{0L,0L,0x53L},{0x6FL,9L,0x6CL},{0x6FL,0xE5L,0L},{(-1L),0L,1L},{(-9L),0x6FL,0L},{0xE9L,1L,0x6CL},{0xC4L,1L,0xBFL}},{{0L,0x6FL,1L},{1L,0L,0xA4L},{0L,0xE5L,0xB1L},{0xC4L,9L,0xB1L},{0xE9L,(-1L),0xA4L},{(-9L),0x19L,1L},{(-1L),(-1L),0xBFL},{0x6FL,9L,0x6CL}},{{0x6FL,0xE5L,0L},{(-1L),0L,1L},{(-9L),0x6FL,0L},{0xE9L,1L,0x6CL},{0xC4L,1L,0xBFL},{0L,0x6FL,1L},{1L,0L,0xA4L},{0L,0xE5L,0xB1L}},{{0xC4L,9L,0xB1L},{0xE9L,(-1L),0xA4L},{(-9L),0x19L,1L},{(-1L),(-1L),0xBFL},{0x6FL,9L,0x6CL},{0x6FL,0xE5L,0L},{(-1L),0L,1L},{(-9L),0x6FL,0L}}}; + int8_t ***l_761[10] = {&g_245,&g_245,&g_245,&g_245,&g_245,&g_245,&g_245,&g_245,&g_245,&g_245}; + int i, j, k; + } + for (l_704 = 0; l_704 < 5; l_704 += 1) + { + g_294[l_704] = 1UL; + } + } + (*g_143) = (safe_div_func_int32_t_s_s((*g_143), l_704)); + return l_697; +} + + +/* ------------------------------------------ */ +/* + * reads : + * writes: + */ +static int32_t * func_105(uint32_t p_106) +{ /* block id: 29 */ + int8_t *l_134 = &g_36; + int8_t ** const l_133 = &l_134; + int32_t l_156 = 0xE85A3F02L; + uint32_t l_166 = 0x5E662131L; + uint8_t **l_172 = &g_43; + uint8_t **l_174[2][7] = {{&g_43,&g_43,&g_43,&g_43,&g_43,&g_43,&g_43},{&g_43,&g_43,&g_43,&g_43,&g_43,&g_43,&g_43}}; + uint8_t ***l_173[2][9] = {{(void*)0,&l_172,(void*)0,&l_172,(void*)0,&l_172,(void*)0,&l_172,(void*)0},{(void*)0,(void*)0,&l_174[1][0],&l_174[1][0],(void*)0,(void*)0,&l_174[1][0],&l_174[1][0],(void*)0}}; + int32_t *l_211[6] = {&g_3,&g_3,&g_3,&g_3,&g_3,&g_3}; + int32_t l_418 = 0xBEDB2E7EL; + int32_t l_582 = 8L; + int16_t l_587[5][7][2] = {{{0x5323L,1L},{0xDA62L,0xA377L},{0xD174L,0xDA62L},{0x959BL,0x0DAEL},{0x959BL,0xDA62L},{0xD174L,0xA377L},{0xDA62L,1L}},{{0x5323L,(-1L)},{0xA377L,0x9B9BL},{0x9B9BL,0x9B9BL},{0xA377L,(-1L)},{0x5323L,1L},{0xDA62L,0xA377L},{0xD174L,0xDA62L}},{{0x959BL,0x0DAEL},{0x959BL,0xDA62L},{0xD174L,0xA377L},{0xDA62L,1L},{0x5323L,(-1L)},{0xA377L,0x9B9BL},{0x9B9BL,0x9B9BL}},{{0xA377L,(-1L)},{0x5323L,1L},{0xDA62L,0xA377L},{0xD174L,0xDA62L},{0x959BL,0x0DAEL},{(-1L),0x0DAEL},{0x5323L,0x9B9BL}},{{0x0DAEL,0xD174L},{0x959BL,0xA377L},{0x9B9BL,(-7L)},{(-7L),(-7L)},{0x9B9BL,0xA377L},{0x959BL,0xD174L},{0x0DAEL,0x9B9BL}}}; + uint32_t l_614 = 4294967286UL; + int i, j, k; + return &g_297[1]; +} + + + + +/* ---------------------------------------- */ +int main (int argc, char* argv[]) +{ + int i, j, k; + int print_hash_value = 0; + if (argc == 2 && strcmp(argv[1], "1") == 0) print_hash_value = 1; + platform_main_begin(); + crc32_gentab(); + func_1(); + for (i = 0; i < 5; i++) + { + for (j = 0; j < 1; j++) + { + transparent_crc(g_2[i][j], "g_2[i][j]", print_hash_value); + if (print_hash_value) printf("index = [%d][%d]\n", i, j); + + } + } + transparent_crc(g_3, "g_3", print_hash_value); + for (i = 0; i < 6; i++) + { + transparent_crc(g_14[i], "g_14[i]", print_hash_value); + if (print_hash_value) printf("index = [%d]\n", i); + + } + transparent_crc(g_15, "g_15", print_hash_value); + transparent_crc(g_34, "g_34", print_hash_value); + transparent_crc(g_36, "g_36", print_hash_value); + for (i = 0; i < 7; i++) + { + transparent_crc(g_40[i], "g_40[i]", print_hash_value); + if (print_hash_value) printf("index = [%d]\n", i); + + } + transparent_crc(g_44, "g_44", print_hash_value); + transparent_crc(g_46, "g_46", print_hash_value); + for (i = 0; i < 2; i++) + { + for (j = 0; j < 8; j++) + { + for (k = 0; k < 3; k++) + { + transparent_crc(g_51[i][j][k], "g_51[i][j][k]", print_hash_value); + if (print_hash_value) printf("index = [%d][%d][%d]\n", i, j, k); + + } + } + } + transparent_crc(g_52, "g_52", print_hash_value); + transparent_crc(g_56, "g_56", print_hash_value); + transparent_crc(g_140, "g_140", print_hash_value); + transparent_crc(g_251, "g_251", print_hash_value); + transparent_crc(g_255, "g_255", print_hash_value); + transparent_crc(g_290, "g_290", print_hash_value); + for (i = 0; i < 5; i++) + { + transparent_crc(g_294[i], "g_294[i]", print_hash_value); + if (print_hash_value) printf("index = [%d]\n", i); + + } + for (i = 0; i < 2; i++) + { + transparent_crc(g_297[i], "g_297[i]", print_hash_value); + if (print_hash_value) printf("index = [%d]\n", i); + + } + transparent_crc(g_320, "g_320", print_hash_value); + transparent_crc(g_347, "g_347", print_hash_value); + transparent_crc(g_419, "g_419", print_hash_value); + transparent_crc(g_477, "g_477", print_hash_value); + for (i = 0; i < 6; i++) + { + transparent_crc(g_705[i], "g_705[i]", print_hash_value); + if (print_hash_value) printf("index = [%d]\n", i); + + } + transparent_crc(g_969, "g_969", print_hash_value); + transparent_crc(g_1055, "g_1055", print_hash_value); + transparent_crc(g_1099, "g_1099", print_hash_value); + transparent_crc(g_1132, "g_1132", print_hash_value); + transparent_crc(g_1189, "g_1189", print_hash_value); + for (i = 0; i < 8; i++) + { + for (j = 0; j < 1; j++) + { + for (k = 0; k < 8; k++) + { + transparent_crc(g_1254[i][j][k], "g_1254[i][j][k]", print_hash_value); + if (print_hash_value) printf("index = [%d][%d][%d]\n", i, j, k); + + } + } + } + transparent_crc(g_1285, "g_1285", print_hash_value); + transparent_crc(g_1298, "g_1298", print_hash_value); + transparent_crc(g_1333, "g_1333", print_hash_value); + transparent_crc(g_1334, "g_1334", print_hash_value); + transparent_crc(g_1509, "g_1509", print_hash_value); + transparent_crc(g_1766, "g_1766", print_hash_value); + transparent_crc(g_1776, "g_1776", print_hash_value); + for (i = 0; i < 6; i++) + { + for (j = 0; j < 8; j++) + { + for (k = 0; k < 5; k++) + { + transparent_crc(g_1782[i][j][k], "g_1782[i][j][k]", print_hash_value); + if (print_hash_value) printf("index = [%d][%d][%d]\n", i, j, k); + + } + } + } + transparent_crc(g_1857, "g_1857", print_hash_value); + transparent_crc(g_1961, "g_1961", print_hash_value); + transparent_crc(g_2067, "g_2067", print_hash_value); + for (i = 0; i < 10; i++) + { + transparent_crc(g_2147[i], "g_2147[i]", print_hash_value); + if (print_hash_value) printf("index = [%d]\n", i); + + } + transparent_crc(g_2148, "g_2148", print_hash_value); + transparent_crc(g_2207, "g_2207", print_hash_value); + platform_main_end(crc32_context ^ 0xFFFFFFFFUL, print_hash_value); + return 0; +} + +/************************ statistics ************************* +XXX max struct depth: 0 +breakdown: + depth: 0, occurrence: 652 +XXX total union variables: 0 + +XXX non-zero bitfields defined in structs: 0 +XXX zero bitfields defined in structs: 0 +XXX const bitfields defined in structs: 0 +XXX volatile bitfields defined in structs: 0 +XXX structs with bitfields in the program: 0 +breakdown: +XXX full-bitfields structs in the program: 0 +breakdown: +XXX times a bitfields struct's address is taken: 0 +XXX times a bitfields struct on LHS: 0 +XXX times a bitfields struct on RHS: 0 +XXX times a single bitfield on LHS: 0 +XXX times a single bitfield on RHS: 0 + +XXX max expression depth: 41 +breakdown: + depth: 1, occurrence: 169 + depth: 2, occurrence: 42 + depth: 3, occurrence: 3 + depth: 4, occurrence: 2 + depth: 6, occurrence: 1 + depth: 7, occurrence: 1 + depth: 8, occurrence: 1 + depth: 10, occurrence: 1 + depth: 13, occurrence: 1 + depth: 14, occurrence: 1 + depth: 15, occurrence: 1 + depth: 16, occurrence: 3 + depth: 19, occurrence: 1 + depth: 20, occurrence: 1 + depth: 21, occurrence: 4 + depth: 22, occurrence: 2 + depth: 23, occurrence: 2 + depth: 24, occurrence: 2 + depth: 25, occurrence: 1 + depth: 26, occurrence: 2 + depth: 27, occurrence: 3 + depth: 28, occurrence: 4 + depth: 30, occurrence: 1 + depth: 31, occurrence: 1 + depth: 33, occurrence: 1 + depth: 35, occurrence: 2 + depth: 36, occurrence: 2 + depth: 39, occurrence: 4 + depth: 41, occurrence: 2 + +XXX total number of pointers: 428 + +XXX times a variable address is taken: 1238 +XXX times a pointer is dereferenced on RHS: 347 +breakdown: + depth: 1, occurrence: 232 + depth: 2, occurrence: 83 + depth: 3, occurrence: 32 +XXX times a pointer is dereferenced on LHS: 261 +breakdown: + depth: 1, occurrence: 220 + depth: 2, occurrence: 32 + depth: 3, occurrence: 9 +XXX times a pointer is compared with null: 37 +XXX times a pointer is compared with address of another variable: 12 +XXX times a pointer is compared with another pointer: 17 +XXX times a pointer is qualified to be dereferenced: 9414 + +XXX max dereference level: 5 +breakdown: + level: 0, occurrence: 0 + level: 1, occurrence: 1507 + level: 2, occurrence: 661 + level: 3, occurrence: 292 + level: 4, occurrence: 45 + level: 5, occurrence: 6 +XXX number of pointers point to pointers: 210 +XXX number of pointers point to scalars: 218 +XXX number of pointers point to structs: 0 +XXX percent of pointers has null in alias set: 29.2 +XXX average alias set size: 1.54 + +XXX times a non-volatile is read: 2082 +XXX times a non-volatile is write: 921 +XXX times a volatile is read: 0 +XXX times read thru a pointer: 0 +XXX times a volatile is write: 0 +XXX times written thru a pointer: 0 +XXX times a volatile is available for access: 0 +XXX percentage of non-volatile access: 100 + +XXX forward jumps: 1 +XXX backward jumps: 7 + +XXX stmts: 175 +XXX max block depth: 5 +breakdown: + depth: 0, occurrence: 34 + depth: 1, occurrence: 30 + depth: 2, occurrence: 19 + depth: 3, occurrence: 27 + depth: 4, occurrence: 30 + depth: 5, occurrence: 35 + +XXX percentage a fresh-made variable is used: 16.5 +XXX percentage an existing variable is used: 83.5 +********************* end of statistics **********************/ + diff --git a/tests/fuzz/19.c.txt b/tests/fuzz/19.c.txt new file mode 100644 index 00000000..5fac330b --- /dev/null +++ b/tests/fuzz/19.c.txt @@ -0,0 +1 @@ +checksum = 150DAD10 diff --git a/tests/sdl_touch.c b/tests/sdl_touch.c new file mode 100644 index 00000000..dc315c58 --- /dev/null +++ b/tests/sdl_touch.c @@ -0,0 +1,81 @@ +#include <stdio.h> +#include <SDL/SDL.h> +#include <SDL/SDL_ttf.h> +#include <assert.h> +#include <emscripten.h> + +int result = 1; + +static char *TouchFingerTypeToString(int type) { + if (type == SDL_FINGERMOTION) return "SDL_FINGERMOTION"; + if (type == SDL_FINGERDOWN) return "SDL_FINGERDOWN"; + if (type == SDL_FINGERUP) return "SDL_FINGERUP"; + return "UNKNOWN"; +} + +int got_down = 0; +int got_move = 0; +int got_up = 0; + +void progress() { + if (!got_down) printf("Hold down a finger to generate a touch down event.\n"); + else if (!got_move) printf("Drag a finger to generate a touch move event.\n"); + else if (!got_up) printf("Release a finger to generate a touch up event.\n"); + else + { + int result = 0; +#ifdef REPORT_RESULT + REPORT_RESULT(); +#endif + } +} + +void loop() { + SDL_Event event; + while (SDL_PollEvent(&event)) { + switch(event.type) { + case SDL_FINGERMOTION: + case SDL_FINGERDOWN: + case SDL_FINGERUP: { + SDL_TouchFingerEvent *t = (SDL_TouchFingerEvent*)&event; + printf("type: %s, timestamp: %u, touchId: %llu, fingerId: %llu, x: %f, y: %f, dx: %f, dy: %f, pressure: %f\n", + TouchFingerTypeToString(event.type), t->timestamp, t->touchId, t->fingerId, t->x, t->y, t->dx, t->dy, t->pressure); + + if (t->timestamp != 0 && t->x >= 0.f && t->x <= 1.f && t->y >= 0.f && t->y <= 1.f && t->pressure >= 0.f && t->pressure <= 1.f) { + if (event.type == SDL_FINGERDOWN) { got_down = 1; progress(); } + if (event.type == SDL_FINGERMOTION) { got_move = 1; progress(); } + if (event.type == SDL_FINGERDOWN) { got_up = 1; progress(); } + } + break; + } + } + } +} + +int main() { + SDL_Init(SDL_INIT_VIDEO); + SDL_Surface *screen = SDL_SetVideoMode(600, 450, 32, SDL_HWSURFACE); + + progress(); + +#ifdef AUTOMATE_SUCCESS + EM_ASM( + function sendEvent(type, data) { + var event = document.createEvent('Event'); + event.initEvent(type, true, true); + for(var d in data) event[d] = data[d]; + Module['canvas'].dispatchEvent(event); + } + // Pass test coordinates in canvas element coordinate frame. + var x = Module['canvas'].getBoundingClientRect().left; + var y = Module['canvas'].getBoundingClientRect().top; + sendEvent('touchstart', { touches: [ { pageX: x+300, pageY: y+225, deviceID: 1, identifier: 1, force: 1 } ] }); + sendEvent('touchmove', { touches: [ { pageX: x+400, pageY: y+225, deviceID: 1, identifier: 1, force: 1 } ] }); + sendEvent('touchend', { changedTouches: [ { pageX: x+400, pageY: y+225, deviceID: 1, identifier: 1, force: 1 } ] }); + ); +#endif + + emscripten_set_main_loop(loop, 0, 0); + + return 0; +} diff --git a/tests/test_browser.py b/tests/test_browser.py index cf893eb5..c06f11ac 100644 --- a/tests/test_browser.py +++ b/tests/test_browser.py @@ -1793,6 +1793,11 @@ Module["preRun"].push(function () { print opts self.btest(path_from_root('tests', 'test_html5.c'), args=opts, expected='0') + def test_sdl_touch(self): + for opts in [[], ['-O2', '-g1', '--closure', '1']]: + print opts + self.btest(path_from_root('tests', 'sdl_touch.c'), args=opts + ['-DAUTOMATE_SUCCESS=1'], expected='0') + def test_html5_mouse(self): for opts in [[], ['-O2', '-g1', '--closure', '1']]: print opts diff --git a/tests/test_core.py b/tests/test_core.py index 2e2f5587..d25a61be 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -2983,7 +2983,7 @@ def process(filename): output_nicerizer=lambda x, err: x.replace('\n', '*'), post_build=self.dlfcn_post_build) - if Settings.ASM_JS and os.path.exists(SPIDERMONKEY_ENGINE[0]): + if Settings.ASM_JS and SPIDERMONKEY_ENGINE and os.path.exists(SPIDERMONKEY_ENGINE[0]): out = run_js('liblib.so', engine=SPIDERMONKEY_ENGINE, full_output=True, stderr=STDOUT) if 'asm' in out: self.validate_asmjs(out) @@ -5272,8 +5272,10 @@ def process(filename): if 'newfail' in name: continue if os.environ.get('EMCC_FAST_COMPILER') == '0' and os.path.basename(name) in [ '18.cpp', '15.c' - ]: - continue # works only in fastcomp + ]: continue # works only in fastcomp + if x == 'lto' and self.run_name == 'default' and os.path.basename(name) in [ + '19.c' + ]: continue # LLVM LTO bug print name self.do_run(open(path_from_root('tests', 'fuzz', name)).read(), @@ -5969,6 +5971,22 @@ def process(filename): ''' self.do_run(src, '|hello|43|world|41|', post_build=post) + def test_webidl(self): + if self.emcc_args is None: return self.skip('requires emcc') + + output = Popen([PYTHON, path_from_root('tools', 'webidl_binder.py'), + path_from_root('tests', 'webidl', 'test.idl'), + 'glue']).communicate()[0] + assert os.path.exists('glue.cpp') + assert os.path.exists('glue.js') + + self.emcc_args += ['--post-js', 'glue.js', + '--post-js', path_from_root('tests', 'webidl', 'post.js')] + shutil.copyfile(path_from_root('tests', 'webidl', 'test.h'), self.in_dir('test.h')) + shutil.copyfile(path_from_root('tests', 'webidl', 'test.cpp'), self.in_dir('test.cpp')) + src = open('test.cpp').read() + self.do_run(src, open(path_from_root('tests', 'webidl', 'output.txt')).read()) + def test_typeinfo(self): if os.environ.get('EMCC_FAST_COMPILER') != '0': return self.skip('fastcomp does not support RUNTIME_TYPE_INFO') diff --git a/tests/test_interactive.py b/tests/test_interactive.py index 4ac52f55..aa1d96af 100644 --- a/tests/test_interactive.py +++ b/tests/test_interactive.py @@ -25,6 +25,9 @@ class interactive(BrowserCore): def test_html5_mouse(self): self.btest(path_from_root('tests', 'test_html5_mouse.c'), expected='0') + def test_sdl_touch(self): + self.btest(path_from_root('tests', 'sdl_touch.c'), args=['-O2', '-g1', '--closure', '1'], expected='0') + def test_sdl_wm_togglefullscreen(self): self.btest('sdl_wm_togglefullscreen.c', expected='1', args=['-s', 'NO_EXIT_RUNTIME=1']) diff --git a/tests/test_other.py b/tests/test_other.py index af522807..4b5ed666 100644 --- a/tests/test_other.py +++ b/tests/test_other.py @@ -2709,3 +2709,35 @@ int main() assert os.path.exists('hello_world.o') assert os.path.exists('hello_world.bc') + def test_bad_function_pointer_cast(self): + open('src.cpp', 'w').write(r''' +#include <stdio.h> + +typedef int (*callback) (int, ...); + +int impl(int foo) { + printf("Hello, world.\n"); + return 0; +} + +int main() { + volatile callback f = (callback) impl; + f(0); /* This fails with or without additional arguments. */ + return 0; +} +''') + + for opts in [0, 1, 2]: + for safe in [0, 1]: + cmd = [PYTHON, EMCC, 'src.cpp', '-O' + str(opts), '-s', 'SAFE_HEAP=' + str(safe)] + print cmd + Popen(cmd).communicate() + output = run_js('a.out.js', stderr=PIPE, full_output=True) + if safe: + assert 'Function table mask error' in output, output + else: + if opts == 0: + assert 'Invalid function pointer called' in output, output + else: + assert 'abort()' in output, output + diff --git a/tests/webidl/output.txt b/tests/webidl/output.txt new file mode 100644 index 00000000..b874d928 --- /dev/null +++ b/tests/webidl/output.txt @@ -0,0 +1,56 @@ +Parent:42 +* +84 +c1 +Parent:7 +Child1:7 +7 +14 +196 +588 +14 +28 +c1 v2 +Parent:16 +Child1:15 +15 +30 +900 +2700 +c2 +Parent:9 +Child2:9 +9 +18 +5832 +0 +0 +1 +*static* +*virtualf* +*virtualf* +*virtualf2* +Parent:9 +Child2:9 +*js virtualf replacement* +*js virtualf replacement* +*js virtualf2 replacement* +*js virtualf3 replacement 123* +caught: a JSImplementation must implement all functions, you forgot Child2JS::virtualFunc4. +*virtualf* +*virtualf* +*virtualf2* +*ok* +|hello|43|world|41| +12.35 +10 +object +10 +11 +object +10 +11 +21.12 +198 + +done. diff --git a/tests/webidl/post.js b/tests/webidl/post.js new file mode 100644 index 00000000..444efcd1 --- /dev/null +++ b/tests/webidl/post.js @@ -0,0 +1,117 @@ + +// Part 1 + +var sme = new Module.Parent(42); +sme.mulVal(2); +Module.print('*') +Module.print(sme.getVal()); + +Module.print('c1'); + +var c1 = new Module.Child1(); +Module.print(c1.getVal()); +c1.mulVal(2); +Module.print(c1.getVal()); +Module.print(c1.getValSqr()); +Module.print(c1.getValSqr(3)); +Module.print(c1.getValTimes()); // default argument should be 1 +Module.print(c1.getValTimes(2)); + +Module.print('c1 v2'); + +c1 = new Module.Child1(8); // now with a parameter, we should handle the overloading automatically and properly and use constructor #2 +Module.print(c1.getVal()); +c1.mulVal(2); +Module.print(c1.getVal()); +Module.print(c1.getValSqr()); +Module.print(c1.getValSqr(3)); + +Module.print('c2') + +var c2 = new Module.Child2(); +Module.print(c2.getVal()); +c2.mulVal(2); +Module.print(c2.getVal()); +Module.print(c2.getValCube()); +var succeeded; +try { + succeeded = 0; + Module.print(c2.doSomethingSecret()); // should fail since private + succeeded = 1; +} catch(e) {} +Module.print(succeeded); +try { + succeeded = 0; + Module.print(c2.getValSqr()); // function from the other class + succeeded = 1; +} catch(e) {} +Module.print(succeeded); +try { + succeeded = 0; + c2.getValCube(); // sanity + succeeded = 1; +} catch(e) {} +Module.print(succeeded); + +Module.Child2.prototype.printStatic(); // static calls go through the prototype + +// virtual function +c2.virtualFunc(); +Module.Child2.prototype.runVirtualFunc(c2); +c2.virtualFunc2(); + +// extend a class from JS +var c3 = new Module.Child2JS; + +c3.virtualFunc = function() { + Module.print('*js virtualf replacement*'); +}; +c3.virtualFunc2 = function() { + Module.print('*js virtualf2 replacement*'); +}; +c3.virtualFunc3 = function(x) { + Module.print('*js virtualf3 replacement ' + x + '*'); +}; + +c3.virtualFunc(); +Module.Child2.prototype.runVirtualFunc(c3); +c3.virtualFunc2(); +c3.virtualFunc3(123); // this one is not replaced! +try { + c3.virtualFunc4(123); +} catch(e) { + Module.print('caught: ' + e); +} + +c2.virtualFunc(); // original should remain the same +Module.Child2.prototype.runVirtualFunc(c2); +c2.virtualFunc2(); +Module.print('*ok*'); + +// Part 2 + +var suser = new Module.StringUser("hello", 43); +suser.Print(41, "world"); +suser.PrintFloat(12.3456); + +var bv = new Module.RefUser(10); +var bv2 = new Module.RefUser(11); +Module.print(bv2.getValue(bv)); + +Module.print(typeof bv2.getMe()); +Module.print(bv2.getMe().getValue(bv)); +Module.print(bv2.getMe().getValue(bv2)); + +Module.print(typeof bv2.getCopy()); +Module.print(bv2.getCopy().getValue(bv)); +Module.print(bv2.getCopy().getValue(bv2)); + +bv2.getAnother().PrintFloat(21.12); + +Module.print(new Module.Inner().get()); +new Module.Inner().mul(2); + +// + +Module.print('\ndone.') + diff --git a/tests/webidl/test.cpp b/tests/webidl/test.cpp new file mode 100644 index 00000000..8a2b5c72 --- /dev/null +++ b/tests/webidl/test.cpp @@ -0,0 +1,8 @@ +#include "test.h" + +Parent::Parent(int val) : value(val) { printf("Parent:%d\n", val); } +Parent::Parent(Parent *p, Parent *q) : value(p->value + q->value) { printf("Parent:%d\n", value); } +void Parent::mulVal(int mul) { value *= mul; } + +#include "glue.cpp" + diff --git a/tests/webidl/test.h b/tests/webidl/test.h new file mode 100644 index 00000000..903f8f78 --- /dev/null +++ b/tests/webidl/test.h @@ -0,0 +1,72 @@ +#include <stdio.h> + +// Part 1 + +class Parent { +protected: + int value; +public: + Parent(int val); + Parent(Parent *p, Parent *q); // overload constructor + int getVal() { return value; }; // inline should work just fine here, unlike Way 1 before + void mulVal(int mul); +}; + +class Child1 : public Parent { +public: + Child1() : Parent(7) { printf("Child1:%d\n", value); }; + Child1(int val) : Parent(val*2) { value -= 1; printf("Child1:%d\n", value); }; + int getValSqr() { return value*value; } + int getValSqr(int more) { return value*value*more; } + int getValTimes(int times=1) { return value*times; } +}; + +// Child2 has vtable, parent does not. Checks we cast child->parent properly - (Parent*)child is not a no-op, must offset +class Child2 : public Parent { +public: + Child2() : Parent(9) { printf("Child2:%d\n", value); }; + int getValCube() { return value*value*value; } + static void printStatic() { printf("*static*\n"); } + + virtual void virtualFunc() { printf("*virtualf*\n"); } + virtual void virtualFunc2() { printf("*virtualf2*\n"); } + static void runVirtualFunc(Child2 *self) { self->virtualFunc(); }; + virtual void virtualFunc3(int x) { printf("*virtualf3: %d*\n", x); } + virtual void virtualFunc4(int x) { printf("*virtualf4: %d*\n", x); } + +private: + void doSomethingSecret() { printf("security breached!\n"); }; // we should not be able to do this +}; + +// Part 2 + +#include <string.h> + +class StringUser { + char *s; + int i; +public: + StringUser(char *string="NO", int integer=99) : s(strdup(string)), i(integer) {} + void Print(int anotherInteger, char *anotherString) { + printf("|%s|%d|%s|%d|\n", s, i, anotherString, anotherInteger); + } + void PrintFloat(float f) { printf("%.2f\n", f); } +}; + +struct RefUser { + int value; + RefUser(int x = 77) : value(x) {} + int getValue(RefUser b) { return b.value; } + RefUser &getMe() { return *this; } + RefUser getCopy() { return RefUser(value*2); } + StringUser getAnother() { return StringUser("another", 5); } +}; + +namespace Space { + struct Inner { + Inner() {} + int get() { return 198; } + Inner& operator*=(float x) { return *this; } + }; +} + diff --git a/tests/webidl/test.idl b/tests/webidl/test.idl new file mode 100644 index 00000000..98ab5070 --- /dev/null +++ b/tests/webidl/test.idl @@ -0,0 +1,64 @@ + +// Part 1 + +interface Parent { + void Parent(long val); + long getVal(); + void mulVal(long mul); +}; + +interface Child1 { + void Child1(optional long val); + long getValSqr(optional long more); + long getValTimes(optional long times=1); +}; + +Child1 implements Parent; + +interface Child2 { + void Child2(); + long getValCube(); + static void printStatic(); + void virtualFunc(); + void virtualFunc2(); + void virtualFunc3(long x); + void virtualFunc4(long x); + static void runVirtualFunc(Child2 self); +}; + +Child2 implements Parent; + +[JSImplementation="Child2"] +interface Child2JS { + void Child2JS(); + void virtualFunc(); + void virtualFunc2(); + void virtualFunc3(long x); + void virtualFunc4(long x); +}; + +// Part 2 + +interface StringUser { + void StringUser(); + void StringUser(DOMString str, long i); + void Print(long anotherInteger, DOMString anotherString); + void PrintFloat(float f); +}; + +interface RefUser { + void RefUser(); + void RefUser(long value); + long getValue([Ref] RefUser b); + [Ref] RefUser getMe(); + [Value] RefUser getCopy(); // must have zero-arg constructor + [Value] StringUser getAnother(); +}; + +[Prefix="Space::"] +interface Inner { + void Inner(); + long get(); + [Operator="*=", Ref] Inner mul(float x); +}; + diff --git a/third_party/WebIDL.py b/third_party/WebIDL.py new file mode 100644 index 00000000..867a7cbc --- /dev/null +++ b/third_party/WebIDL.py @@ -0,0 +1,5030 @@ +# from http://mxr.mozilla.org/mozilla-central/source/dom/bindings/parser/WebIDL.py +# rev 501baeb3a034 + +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +""" A WebIDL parser. """ + +from ply import lex, yacc +import re +import os +import traceback +import math + +# Machinery + +def parseInt(literal): + string = literal + sign = 0 + base = 0 + + if string[0] == '-': + sign = -1 + string = string[1:] + else: + sign = 1 + + if string[0] == '0' and len(string) > 1: + if string[1] == 'x' or string[1] == 'X': + base = 16 + string = string[2:] + else: + base = 8 + string = string[1:] + else: + base = 10 + + value = int(string, base) + return value * sign + +# Magic for creating enums +def M_add_class_attribs(attribs, start): + def foo(name, bases, dict_): + for v, k in enumerate(attribs): + dict_[k] = start + v + assert 'length' not in dict_ + dict_['length'] = start + len(attribs) + return type(name, bases, dict_) + return foo + +def enum(*names, **kw): + if len(kw) == 1: + base = kw['base'].__class__ + start = base.length + else: + assert len(kw) == 0 + base = object + start = 0 + class Foo(base): + __metaclass__ = M_add_class_attribs(names, start) + def __setattr__(self, name, value): # this makes it read-only + raise NotImplementedError + return Foo() + +class WebIDLError(Exception): + def __init__(self, message, locations, warning=False): + self.message = message + self.locations = [str(loc) for loc in locations] + self.warning = warning + + def __str__(self): + return "%s: %s%s%s" % (self.warning and 'warning' or 'error', + self.message, + ", " if len(self.locations) != 0 else "", + "\n".join(self.locations)) + +class Location(object): + def __init__(self, lexer, lineno, lexpos, filename): + self._line = None + self._lineno = lineno + self._lexpos = lexpos + self._lexdata = lexer.lexdata + self._file = filename if filename else "<unknown>" + + def __eq__(self, other): + return self._lexpos == other._lexpos and \ + self._file == other._file + + def filename(self): + return self._file + + def resolve(self): + if self._line: + return + + startofline = self._lexdata.rfind('\n', 0, self._lexpos) + 1 + endofline = self._lexdata.find('\n', self._lexpos, self._lexpos + 80) + if endofline != -1: + self._line = self._lexdata[startofline:endofline] + else: + self._line = self._lexdata[startofline:] + self._colno = self._lexpos - startofline + + # Our line number seems to point to the start of self._lexdata + self._lineno += self._lexdata.count('\n', 0, startofline) + + def get(self): + self.resolve() + return "%s line %s:%s" % (self._file, self._lineno, self._colno) + + def _pointerline(self): + return " " * self._colno + "^" + + def __str__(self): + self.resolve() + return "%s line %s:%s\n%s\n%s" % (self._file, self._lineno, self._colno, + self._line, self._pointerline()) + +class BuiltinLocation(object): + def __init__(self, text): + self.msg = text + "\n" + + def __eq__(self, other): + return isinstance(other, BuiltinLocation) and \ + self.msg == other.msg + + def filename(self): + return '<builtin>' + + def resolve(self): + pass + + def get(self): + return self.msg + + def __str__(self): + return self.get() + + +# Data Model + +class IDLObject(object): + def __init__(self, location): + self.location = location + self.userData = dict() + + def filename(self): + return self.location.filename() + + def isInterface(self): + return False + + def isEnum(self): + return False + + def isCallback(self): + return False + + def isType(self): + return False + + def isDictionary(self): + return False; + + def isUnion(self): + return False + + def getUserData(self, key, default): + return self.userData.get(key, default) + + def setUserData(self, key, value): + self.userData[key] = value + + def addExtendedAttributes(self, attrs): + assert False # Override me! + + def handleExtendedAttribute(self, attr): + assert False # Override me! + + def _getDependentObjects(self): + assert False # Override me! + + def getDeps(self, visited=None): + """ Return a set of files that this object depends on. If any of + these files are changed the parser needs to be rerun to regenerate + a new IDLObject. + + The visited argument is a set of all the objects already visited. + We must test to see if we are in it, and if so, do nothing. This + prevents infinite recursion.""" + + # NB: We can't use visited=set() above because the default value is + # evaluated when the def statement is evaluated, not when the function + # is executed, so there would be one set for all invocations. + if visited == None: + visited = set() + + if self in visited: + return set() + + visited.add(self) + + deps = set() + if self.filename() != "<builtin>": + deps.add(self.filename()) + + for d in self._getDependentObjects(): + deps = deps.union(d.getDeps(visited)) + + return deps + +class IDLScope(IDLObject): + def __init__(self, location, parentScope, identifier): + IDLObject.__init__(self, location) + + self.parentScope = parentScope + if identifier: + assert isinstance(identifier, IDLIdentifier) + self._name = identifier + else: + self._name = None + + self._dict = {} + + def __str__(self): + return self.QName() + + def QName(self): + if self._name: + return self._name.QName() + "::" + return "::" + + def ensureUnique(self, identifier, object): + """ + Ensure that there is at most one 'identifier' in scope ('self'). + Note that object can be None. This occurs if we end up here for an + interface type we haven't seen yet. + """ + assert isinstance(identifier, IDLUnresolvedIdentifier) + assert not object or isinstance(object, IDLObjectWithIdentifier) + assert not object or object.identifier == identifier + + if identifier.name in self._dict: + if not object: + return + + # ensureUnique twice with the same object is not allowed + assert id(object) != id(self._dict[identifier.name]) + + replacement = self.resolveIdentifierConflict(self, identifier, + self._dict[identifier.name], + object) + self._dict[identifier.name] = replacement + return + + assert object + + self._dict[identifier.name] = object + + def resolveIdentifierConflict(self, scope, identifier, originalObject, newObject): + if isinstance(originalObject, IDLExternalInterface) and \ + isinstance(newObject, IDLExternalInterface) and \ + originalObject.identifier.name == newObject.identifier.name: + return originalObject + + if (isinstance(originalObject, IDLExternalInterface) or + isinstance(newObject, IDLExternalInterface)): + raise WebIDLError( + "Name collision between " + "interface declarations for identifier '%s' at '%s' and '%s'" + % (identifier.name, + originalObject.location, newObject.location), []) + + # We do the merging of overloads here as opposed to in IDLInterface + # because we need to merge overloads of NamedConstructors and we need to + # detect conflicts in those across interfaces. See also the comment in + # IDLInterface.addExtendedAttributes for "NamedConstructor". + if originalObject.tag == IDLInterfaceMember.Tags.Method and \ + newObject.tag == IDLInterfaceMember.Tags.Method: + return originalObject.addOverload(newObject) + + # Default to throwing, derived classes can override. + conflictdesc = "\n\t%s at %s\n\t%s at %s" % \ + (originalObject, originalObject.location, newObject, newObject.location) + + raise WebIDLError( + "Multiple unresolvable definitions of identifier '%s' in scope '%s%s" + % (identifier.name, str(self), conflictdesc), []) + + def _lookupIdentifier(self, identifier): + return self._dict[identifier.name] + + def lookupIdentifier(self, identifier): + assert isinstance(identifier, IDLIdentifier) + assert identifier.scope == self + return self._lookupIdentifier(identifier) + +class IDLIdentifier(IDLObject): + def __init__(self, location, scope, name): + IDLObject.__init__(self, location) + + self.name = name + assert isinstance(scope, IDLScope) + self.scope = scope + + def __str__(self): + return self.QName() + + def QName(self): + return self.scope.QName() + self.name + + def __hash__(self): + return self.QName().__hash__() + + def __eq__(self, other): + return self.QName() == other.QName() + + def object(self): + return self.scope.lookupIdentifier(self) + +class IDLUnresolvedIdentifier(IDLObject): + def __init__(self, location, name, allowDoubleUnderscore = False, + allowForbidden = False): + IDLObject.__init__(self, location) + + assert len(name) > 0 + + if name[:2] == "__" and name != "__content" and name != "___noSuchMethod__" and not allowDoubleUnderscore: + raise WebIDLError("Identifiers beginning with __ are reserved", + [location]) + if name[0] == '_' and not allowDoubleUnderscore: + name = name[1:] + # TODO: Bug 872377, Restore "toJSON" to below list. + # We sometimes need custom serialization, so allow toJSON for now. + if (name in ["constructor", "toString"] and + not allowForbidden): + raise WebIDLError("Cannot use reserved identifier '%s'" % (name), + [location]) + + self.name = name + + def __str__(self): + return self.QName() + + def QName(self): + return "<unresolved scope>::" + self.name + + def resolve(self, scope, object): + assert isinstance(scope, IDLScope) + assert not object or isinstance(object, IDLObjectWithIdentifier) + assert not object or object.identifier == self + + scope.ensureUnique(self, object) + + identifier = IDLIdentifier(self.location, scope, self.name) + if object: + object.identifier = identifier + return identifier + + def finish(self): + assert False # Should replace with a resolved identifier first. + +class IDLObjectWithIdentifier(IDLObject): + def __init__(self, location, parentScope, identifier): + IDLObject.__init__(self, location) + + assert isinstance(identifier, IDLUnresolvedIdentifier) + + self.identifier = identifier + + if parentScope: + self.resolve(parentScope) + + self.treatNullAs = "Default" + + def resolve(self, parentScope): + assert isinstance(parentScope, IDLScope) + assert isinstance(self.identifier, IDLUnresolvedIdentifier) + self.identifier.resolve(parentScope, self) + + def checkForStringHandlingExtendedAttributes(self, attrs, + isDictionaryMember=False, + isOptional=False): + """ + A helper function to deal with TreatNullAs. Returns the list + of attrs it didn't handle itself. + """ + assert isinstance(self, IDLArgument) or isinstance(self, IDLAttribute) + unhandledAttrs = list() + for attr in attrs: + if not attr.hasValue(): + unhandledAttrs.append(attr) + continue + + identifier = attr.identifier() + value = attr.value() + if identifier == "TreatNullAs": + if not self.type.isDOMString() or self.type.nullable(): + raise WebIDLError("[TreatNullAs] is only allowed on " + "arguments or attributes whose type is " + "DOMString", + [self.location]) + if isDictionaryMember: + raise WebIDLError("[TreatNullAs] is not allowed for " + "dictionary members", [self.location]) + if value != 'EmptyString': + raise WebIDLError("[TreatNullAs] must take the identifier " + "'EmptyString', not '%s'" % value, + [self.location]) + self.treatNullAs = value + else: + unhandledAttrs.append(attr) + + return unhandledAttrs + +class IDLObjectWithScope(IDLObjectWithIdentifier, IDLScope): + def __init__(self, location, parentScope, identifier): + assert isinstance(identifier, IDLUnresolvedIdentifier) + + IDLObjectWithIdentifier.__init__(self, location, parentScope, identifier) + IDLScope.__init__(self, location, parentScope, self.identifier) + +class IDLIdentifierPlaceholder(IDLObjectWithIdentifier): + def __init__(self, location, identifier): + assert isinstance(identifier, IDLUnresolvedIdentifier) + IDLObjectWithIdentifier.__init__(self, location, None, identifier) + + def finish(self, scope): + try: + scope._lookupIdentifier(self.identifier) + except: + raise WebIDLError("Unresolved type '%s'." % self.identifier, + [self.location]) + + obj = self.identifier.resolve(scope, None) + return scope.lookupIdentifier(obj) + +class IDLExternalInterface(IDLObjectWithIdentifier): + def __init__(self, location, parentScope, identifier): + assert isinstance(identifier, IDLUnresolvedIdentifier) + assert isinstance(parentScope, IDLScope) + self.parent = None + IDLObjectWithIdentifier.__init__(self, location, parentScope, identifier) + IDLObjectWithIdentifier.resolve(self, parentScope) + + def finish(self, scope): + pass + + def validate(self): + pass + + def isExternal(self): + return True + + def isInterface(self): + return True + + def isConsequential(self): + return False + + def addExtendedAttributes(self, attrs): + assert len(attrs) == 0 + + def resolve(self, parentScope): + pass + + def getJSImplementation(self): + return None + + def isJSImplemented(self): + return False + + def getNavigatorProperty(self): + return None + + def _getDependentObjects(self): + return set() + +class IDLInterface(IDLObjectWithScope): + def __init__(self, location, parentScope, name, parent, members, + isPartial): + assert isinstance(parentScope, IDLScope) + assert isinstance(name, IDLUnresolvedIdentifier) + assert not isPartial or not parent + + self.parent = None + self._callback = False + self._finished = False + self.members = [] + # namedConstructors needs deterministic ordering because bindings code + # outputs the constructs in the order that namedConstructors enumerates + # them. + self.namedConstructors = list() + self.implementedInterfaces = set() + self._consequential = False + self._isPartial = True + # self.interfacesBasedOnSelf is the set of interfaces that inherit from + # self or have self as a consequential interface, including self itself. + # Used for distinguishability checking. + self.interfacesBasedOnSelf = set([self]) + # self.interfacesImplementingSelf is the set of interfaces that directly + # have self as a consequential interface + self.interfacesImplementingSelf = set() + self._hasChildInterfaces = False + self._isOnGlobalProtoChain = False + # Tracking of the number of reserved slots we need for our + # members and those of ancestor interfaces. + self.totalMembersInSlots = 0 + # Tracking of the number of own own members we have in slots + self._ownMembersInSlots = 0 + + IDLObjectWithScope.__init__(self, location, parentScope, name) + + if not isPartial: + self.setNonPartial(location, parent, members) + else: + # Just remember our members for now + self.members = members + + def __str__(self): + return "Interface '%s'" % self.identifier.name + + def ctor(self): + identifier = IDLUnresolvedIdentifier(self.location, "constructor", + allowForbidden=True) + try: + return self._lookupIdentifier(identifier) + except: + return None + + def resolveIdentifierConflict(self, scope, identifier, originalObject, newObject): + assert isinstance(scope, IDLScope) + assert isinstance(originalObject, IDLInterfaceMember) + assert isinstance(newObject, IDLInterfaceMember) + + retval = IDLScope.resolveIdentifierConflict(self, scope, identifier, + originalObject, newObject) + + # Might be a ctor, which isn't in self.members + if newObject in self.members: + self.members.remove(newObject) + return retval + + def finish(self, scope): + if self._finished: + return + + self._finished = True + + if self._isPartial: + raise WebIDLError("Interface %s does not have a non-partial " + "declaration" % self.identifier.name, + [self.location]) + + assert not self.parent or isinstance(self.parent, IDLIdentifierPlaceholder) + parent = self.parent.finish(scope) if self.parent else None + if parent and isinstance(parent, IDLExternalInterface): + raise WebIDLError("%s inherits from %s which does not have " + "a definition" % + (self.identifier.name, + self.parent.identifier.name), + [self.location]) + assert not parent or isinstance(parent, IDLInterface) + + self.parent = parent + + assert iter(self.members) + + if self.parent: + self.parent.finish(scope) + + self.parent._hasChildInterfaces = True + + self.totalMembersInSlots = self.parent.totalMembersInSlots + + # Interfaces with [Global] must not have anything inherit from them + if self.parent.getExtendedAttribute("Global"): + # Note: This is not a self.parent.isOnGlobalProtoChain() check + # because ancestors of a [Global] interface can have other + # descendants. + raise WebIDLError("[Global] interface has another interface " + "inheriting from it", + [self.location, self.parent.location]) + + # Callbacks must not inherit from non-callbacks or inherit from + # anything that has consequential interfaces. + # XXXbz Can non-callbacks inherit from callbacks? Spec issue pending. + # XXXbz Can callbacks have consequential interfaces? Spec issue pending + if self.isCallback(): + if not self.parent.isCallback(): + raise WebIDLError("Callback interface %s inheriting from " + "non-callback interface %s" % + (self.identifier.name, + self.parent.identifier.name), + [self.location, self.parent.location]) + elif self.parent.isCallback(): + raise WebIDLError("Non-callback interface %s inheriting from " + "callback interface %s" % + (self.identifier.name, + self.parent.identifier.name), + [self.location, self.parent.location]) + + for iface in self.implementedInterfaces: + iface.finish(scope) + + cycleInGraph = self.findInterfaceLoopPoint(self) + if cycleInGraph: + raise WebIDLError("Interface %s has itself as ancestor or " + "implemented interface" % self.identifier.name, + [self.location, cycleInGraph.location]) + + if self.isCallback(): + # "implements" should have made sure we have no + # consequential interfaces. + assert len(self.getConsequentialInterfaces()) == 0 + # And that we're not consequential. + assert not self.isConsequential() + + # Now resolve() and finish() our members before importing the + # ones from our implemented interfaces. + + # resolve() will modify self.members, so we need to iterate + # over a copy of the member list here. + for member in list(self.members): + member.resolve(self) + + for member in self.members: + member.finish(scope) + + ctor = self.ctor() + if ctor is not None: + ctor.finish(scope) + + for ctor in self.namedConstructors: + ctor.finish(scope) + + # Make a copy of our member list, so things that implement us + # can get those without all the stuff we implement ourselves + # admixed. + self.originalMembers = list(self.members) + + # Import everything from our consequential interfaces into + # self.members. Sort our consequential interfaces by name + # just so we have a consistent order. + for iface in sorted(self.getConsequentialInterfaces(), + cmp=cmp, + key=lambda x: x.identifier.name): + # Flag the interface as being someone's consequential interface + iface.setIsConsequentialInterfaceOf(self) + additionalMembers = iface.originalMembers; + for additionalMember in additionalMembers: + for member in self.members: + if additionalMember.identifier.name == member.identifier.name: + raise WebIDLError( + "Multiple definitions of %s on %s coming from 'implements' statements" % + (member.identifier.name, self), + [additionalMember.location, member.location]) + self.members.extend(additionalMembers) + iface.interfacesImplementingSelf.add(self) + + for ancestor in self.getInheritedInterfaces(): + ancestor.interfacesBasedOnSelf.add(self) + for ancestorConsequential in ancestor.getConsequentialInterfaces(): + ancestorConsequential.interfacesBasedOnSelf.add(self) + + for member in self.members: + if (member.isAttr() and member.isUnforgeable() and + not hasattr(member, "originatingInterface")): + member.originatingInterface = self + + # Compute slot indices for our members before we pull in + # unforgeable members from our parent. + for member in self.members: + if (member.isAttr() and + (member.getExtendedAttribute("StoreInSlot") or + member.getExtendedAttribute("Cached"))): + member.slotIndex = self.totalMembersInSlots + self.totalMembersInSlots += 1 + if member.getExtendedAttribute("StoreInSlot"): + self._ownMembersInSlots += 1 + + if self.parent: + # Make sure we don't shadow any of the [Unforgeable] attributes on + # our ancestor interfaces. We don't have to worry about + # consequential interfaces here, because those have already been + # imported into the relevant .members lists. And we don't have to + # worry about anything other than our parent, because it has already + # imported its ancestors unforgeable attributes into its member + # list. + for unforgeableAttr in (attr for attr in self.parent.members if + attr.isAttr() and not attr.isStatic() and + attr.isUnforgeable()): + shadows = [ m for m in self.members if + (m.isAttr() or m.isMethod()) and + not m.isStatic() and + m.identifier.name == unforgeableAttr.identifier.name ] + if len(shadows) != 0: + locs = [unforgeableAttr.location] + [ s.location for s + in shadows ] + raise WebIDLError("Interface %s shadows [Unforgeable] " + "members of %s" % + (self.identifier.name, + ancestor.identifier.name), + locs) + # And now just stick it in our members, since we won't be + # inheriting this down the proto chain. If we really cared we + # could try to do something where we set up the unforgeable + # attributes of ancestor interfaces, with their corresponding + # getters, on our interface, but that gets pretty complicated + # and seems unnecessary. + self.members.append(unforgeableAttr) + + # Ensure that there's at most one of each {named,indexed} + # {getter,setter,creator,deleter}, at most one stringifier, + # and at most one legacycaller. Note that this last is not + # quite per spec, but in practice no one overloads + # legacycallers. + specialMembersSeen = {} + for member in self.members: + if not member.isMethod(): + continue + + if member.isGetter(): + memberType = "getters" + elif member.isSetter(): + memberType = "setters" + elif member.isCreator(): + memberType = "creators" + elif member.isDeleter(): + memberType = "deleters" + elif member.isStringifier(): + memberType = "stringifiers" + elif member.isJsonifier(): + memberType = "jsonifiers" + elif member.isLegacycaller(): + memberType = "legacycallers" + else: + continue + + if (memberType != "stringifiers" and memberType != "legacycallers" and + memberType != "jsonifiers"): + if member.isNamed(): + memberType = "named " + memberType + else: + assert member.isIndexed() + memberType = "indexed " + memberType + + if memberType in specialMembersSeen: + raise WebIDLError("Multiple " + memberType + " on %s" % (self), + [self.location, + specialMembersSeen[memberType].location, + member.location]) + + specialMembersSeen[memberType] = member + + if self._isOnGlobalProtoChain: + # Make sure we have no named setters, creators, or deleters + for memberType in ["setter", "creator", "deleter"]: + memberId = "named " + memberType + "s" + if memberId in specialMembersSeen: + raise WebIDLError("Interface with [Global] has a named %s" % + memberType, + [self.location, + specialMembersSeen[memberId].location]) + # Make sure we're not [OverrideBuiltins] + if self.getExtendedAttribute("OverrideBuiltins"): + raise WebIDLError("Interface with [Global] also has " + "[OverrideBuiltins]", + [self.location]) + # Mark all of our ancestors as being on the global's proto chain too + parent = self.parent + while parent: + # Must not inherit from an interface with [OverrideBuiltins] + if parent.getExtendedAttribute("OverrideBuiltins"): + raise WebIDLError("Interface with [Global] inherits from " + "interface with [OverrideBuiltins]", + [self.location, parent.location]) + parent._isOnGlobalProtoChain = True + parent = parent.parent + + def validate(self): + for member in self.members: + member.validate() + + # Check that PutForwards refers to another attribute and that no + # cycles exist in forwarded assignments. + if member.isAttr(): + iface = self + attr = member + putForwards = attr.getExtendedAttribute("PutForwards") + if putForwards and self.isCallback(): + raise WebIDLError("[PutForwards] used on an attribute " + "on interface %s which is a callback " + "interface" % self.identifier.name, + [self.location, member.location]) + + while putForwards is not None: + forwardIface = attr.type.unroll().inner + fowardAttr = None + + for forwardedMember in forwardIface.members: + if (not forwardedMember.isAttr() or + forwardedMember.identifier.name != putForwards[0]): + continue + if forwardedMember == member: + raise WebIDLError("Cycle detected in forwarded " + "assignments for attribute %s on " + "%s" % + (member.identifier.name, self), + [member.location]) + fowardAttr = forwardedMember + break + + if fowardAttr is None: + raise WebIDLError("Attribute %s on %s forwards to " + "missing attribute %s" % + (attr.identifier.name, iface, putForwards), + [attr.location]) + + iface = forwardIface + attr = fowardAttr + putForwards = attr.getExtendedAttribute("PutForwards") + + + def isInterface(self): + return True + + def isExternal(self): + return False + + def setIsConsequentialInterfaceOf(self, other): + self._consequential = True + self.interfacesBasedOnSelf.add(other) + + def isConsequential(self): + return self._consequential + + def setCallback(self, value): + self._callback = value + + def isCallback(self): + return self._callback + + def isSingleOperationInterface(self): + assert self.isCallback() or self.isJSImplemented() + return ( + # JS-implemented things should never need the + # this-handling weirdness of single-operation interfaces. + not self.isJSImplemented() and + # Not inheriting from another interface + not self.parent and + # No consequential interfaces + len(self.getConsequentialInterfaces()) == 0 and + # No attributes of any kinds + not any(m.isAttr() for m in self.members) and + # There is at least one regular operation, and all regular + # operations have the same identifier + len(set(m.identifier.name for m in self.members if + m.isMethod() and not m.isStatic())) == 1) + + def inheritanceDepth(self): + depth = 0 + parent = self.parent + while parent: + depth = depth + 1 + parent = parent.parent + return depth + + def hasConstants(self): + return any(m.isConst() for m in self.members) + + def hasInterfaceObject(self): + if self.isCallback(): + return self.hasConstants() + return not hasattr(self, "_noInterfaceObject") + + def hasInterfacePrototypeObject(self): + return not self.isCallback() and self.getUserData('hasConcreteDescendant', False) + + def addExtendedAttributes(self, attrs): + self._extendedAttrDict = {} + for attr in attrs: + identifier = attr.identifier() + + # Special cased attrs + if identifier == "TreatNonCallableAsNull": + raise WebIDLError("TreatNonCallableAsNull cannot be specified on interfaces", + [attr.location, self.location]) + if identifier == "TreatNonObjectAsNull": + raise WebIDLError("TreatNonObjectAsNull cannot be specified on interfaces", + [attr.location, self.location]) + elif identifier == "NoInterfaceObject": + if not attr.noArguments(): + raise WebIDLError("[NoInterfaceObject] must take no arguments", + [attr.location]) + + if self.ctor(): + raise WebIDLError("Constructor and NoInterfaceObject are incompatible", + [self.location]) + + self._noInterfaceObject = True + elif identifier == "Constructor" or identifier == "NamedConstructor" or identifier == "ChromeConstructor": + if identifier == "Constructor" and not self.hasInterfaceObject(): + raise WebIDLError(str(identifier) + " and NoInterfaceObject are incompatible", + [self.location]) + + if identifier == "NamedConstructor" and not attr.hasValue(): + raise WebIDLError("NamedConstructor must either take an identifier or take a named argument list", + [attr.location]) + + if identifier == "ChromeConstructor" and not self.hasInterfaceObject(): + raise WebIDLError(str(identifier) + " and NoInterfaceObject are incompatible", + [self.location]) + + args = attr.args() if attr.hasArgs() else [] + + retType = IDLWrapperType(self.location, self) + + if identifier == "Constructor" or identifier == "ChromeConstructor": + name = "constructor" + allowForbidden = True + else: + name = attr.value() + allowForbidden = False + + methodIdentifier = IDLUnresolvedIdentifier(self.location, name, + allowForbidden=allowForbidden) + + method = IDLMethod(self.location, methodIdentifier, retType, + args, static=True) + # Constructors are always NewObject and are always + # assumed to be able to throw (since there's no way to + # indicate otherwise) and never have any other + # extended attributes. + method.addExtendedAttributes( + [IDLExtendedAttribute(self.location, ("NewObject",)), + IDLExtendedAttribute(self.location, ("Throws",))]) + if identifier == "ChromeConstructor": + method.addExtendedAttributes( + [IDLExtendedAttribute(self.location, ("ChromeOnly",))]) + + if identifier == "Constructor" or identifier == "ChromeConstructor": + method.resolve(self) + else: + # We need to detect conflicts for NamedConstructors across + # interfaces. We first call resolve on the parentScope, + # which will merge all NamedConstructors with the same + # identifier accross interfaces as overloads. + method.resolve(self.parentScope) + + # Then we look up the identifier on the parentScope. If the + # result is the same as the method we're adding then it + # hasn't been added as an overload and it's the first time + # we've encountered a NamedConstructor with that identifier. + # If the result is not the same as the method we're adding + # then it has been added as an overload and we need to check + # whether the result is actually one of our existing + # NamedConstructors. + newMethod = self.parentScope.lookupIdentifier(method.identifier) + if newMethod == method: + self.namedConstructors.append(method) + elif not newMethod in self.namedConstructors: + raise WebIDLError("NamedConstructor conflicts with a NamedConstructor of a different interface", + [method.location, newMethod.location]) + elif (identifier == "ArrayClass"): + if not attr.noArguments(): + raise WebIDLError("[ArrayClass] must take no arguments", + [attr.location]) + if self.parent: + raise WebIDLError("[ArrayClass] must not be specified on " + "an interface with inherited interfaces", + [attr.location, self.location]) + elif identifier == "Global": + if not attr.noArguments(): + raise WebIDLError("[Global] must take no arguments", + [attr.location]) + self._isOnGlobalProtoChain = True + elif (identifier == "NeedNewResolve" or + identifier == "OverrideBuiltins" or + identifier == "NoDelete" or + identifier == "ChromeOnly"): + # Known extended attributes that do not take values + if not attr.noArguments(): + raise WebIDLError("[%s] must take no arguments" % identifier, + [attr.location]) + elif (identifier == "Pref" or + identifier == "JSImplementation" or + identifier == "HeaderFile" or + identifier == "NavigatorProperty" or + identifier == "AvailableIn" or + identifier == "Prefix" or + identifier == "Func"): + # Known extended attributes that take a string value + if not attr.hasValue(): + raise WebIDLError("[%s] must have a value" % identifier, + [attr.location]) + else: + raise WebIDLError("Unknown extended attribute %s on interface" % identifier, + [attr.location]) + + attrlist = attr.listValue() + self._extendedAttrDict[identifier] = attrlist if len(attrlist) else True + + def addImplementedInterface(self, implementedInterface): + assert(isinstance(implementedInterface, IDLInterface)) + self.implementedInterfaces.add(implementedInterface) + + def getInheritedInterfaces(self): + """ + Returns a list of the interfaces this interface inherits from + (not including this interface itself). The list is in order + from most derived to least derived. + """ + assert(self._finished) + if not self.parent: + return [] + parentInterfaces = self.parent.getInheritedInterfaces() + parentInterfaces.insert(0, self.parent) + return parentInterfaces + + def getConsequentialInterfaces(self): + assert(self._finished) + # The interfaces we implement directly + consequentialInterfaces = set(self.implementedInterfaces) + + # And their inherited interfaces + for iface in self.implementedInterfaces: + consequentialInterfaces |= set(iface.getInheritedInterfaces()) + + # And now collect up the consequential interfaces of all of those + temp = set() + for iface in consequentialInterfaces: + temp |= iface.getConsequentialInterfaces() + + return consequentialInterfaces | temp + + def findInterfaceLoopPoint(self, otherInterface): + """ + Finds an interface, amongst our ancestors and consequential interfaces, + that inherits from otherInterface or implements otherInterface + directly. If there is no such interface, returns None. + """ + if self.parent: + if self.parent == otherInterface: + return self + loopPoint = self.parent.findInterfaceLoopPoint(otherInterface) + if loopPoint: + return loopPoint + if otherInterface in self.implementedInterfaces: + return self + for iface in self.implementedInterfaces: + loopPoint = iface.findInterfaceLoopPoint(otherInterface) + if loopPoint: + return loopPoint + return None + + def getExtendedAttribute(self, name): + return self._extendedAttrDict.get(name, None) + + def setNonPartial(self, location, parent, members): + assert not parent or isinstance(parent, IDLIdentifierPlaceholder) + if not self._isPartial: + raise WebIDLError("Two non-partial definitions for the " + "same interface", + [location, self.location]) + self._isPartial = False + # Now make it look like we were parsed at this new location, since + # that's the place where the interface is "really" defined + self.location = location + assert not self.parent + self.parent = parent + # Put the new members at the beginning + self.members = members + self.members + + def getJSImplementation(self): + classId = self.getExtendedAttribute("JSImplementation") + if not classId: + return classId + assert isinstance(classId, list) + assert len(classId) == 1 + return classId[0] + + def isJSImplemented(self): + return bool(self.getJSImplementation()) + + def getNavigatorProperty(self): + naviProp = self.getExtendedAttribute("NavigatorProperty") + if not naviProp: + return None + assert len(naviProp) == 1 + assert isinstance(naviProp, list) + assert len(naviProp[0]) != 0 + return naviProp[0] + + def hasChildInterfaces(self): + return self._hasChildInterfaces + + def isOnGlobalProtoChain(self): + return self._isOnGlobalProtoChain + + def _getDependentObjects(self): + deps = set(self.members) + deps.union(self.implementedInterfaces) + if self.parent: + deps.add(self.parent) + return deps + + def hasMembersInSlots(self): + return self._ownMembersInSlots != 0 + +class IDLDictionary(IDLObjectWithScope): + def __init__(self, location, parentScope, name, parent, members): + assert isinstance(parentScope, IDLScope) + assert isinstance(name, IDLUnresolvedIdentifier) + assert not parent or isinstance(parent, IDLIdentifierPlaceholder) + + self.parent = parent + self._finished = False + self.members = list(members) + + IDLObjectWithScope.__init__(self, location, parentScope, name) + + def __str__(self): + return "Dictionary '%s'" % self.identifier.name + + def isDictionary(self): + return True; + + def finish(self, scope): + if self._finished: + return + + self._finished = True + + if self.parent: + assert isinstance(self.parent, IDLIdentifierPlaceholder) + oldParent = self.parent + self.parent = self.parent.finish(scope) + if not isinstance(self.parent, IDLDictionary): + raise WebIDLError("Dictionary %s has parent that is not a dictionary" % + self.identifier.name, + [oldParent.location, self.parent.location]) + + # Make sure the parent resolves all its members before we start + # looking at them. + self.parent.finish(scope) + + for member in self.members: + member.resolve(self) + if not member.isComplete(): + member.complete(scope) + assert member.type.isComplete() + + # Members of a dictionary are sorted in lexicographic order + self.members.sort(cmp=cmp, key=lambda x: x.identifier.name) + + inheritedMembers = [] + ancestor = self.parent + while ancestor: + if ancestor == self: + raise WebIDLError("Dictionary %s has itself as an ancestor" % + self.identifier.name, + [self.identifier.location]) + inheritedMembers.extend(ancestor.members) + ancestor = ancestor.parent + + # Catch name duplication + for inheritedMember in inheritedMembers: + for member in self.members: + if member.identifier.name == inheritedMember.identifier.name: + raise WebIDLError("Dictionary %s has two members with name %s" % + (self.identifier.name, member.identifier.name), + [member.location, inheritedMember.location]) + + def validate(self): + def typeContainsDictionary(memberType, dictionary): + """ + Returns a tuple whose: + + - First element is a Boolean value indicating whether + memberType contains dictionary. + + - Second element is: + A list of locations that leads from the type that was passed in + the memberType argument, to the dictionary being validated, + if the boolean value in the first element is True. + + None, if the boolean value in the first element is False. + """ + + if memberType.nullable() or \ + memberType.isArray() or \ + memberType.isSequence(): + return typeContainsDictionary(memberType.inner, dictionary) + + if memberType.isDictionary(): + if memberType.inner == dictionary: + return (True, [memberType.location]) + + (contains, locations) = dictionaryContainsDictionary(memberType.inner, \ + dictionary) + if contains: + return (True, [memberType.location] + locations) + + if memberType.isUnion(): + for member in memberType.flatMemberTypes: + (contains, locations) = typeContainsDictionary(member, dictionary) + if contains: + return (True, locations) + + return (False, None) + + def dictionaryContainsDictionary(dictMember, dictionary): + for member in dictMember.members: + (contains, locations) = typeContainsDictionary(member.type, dictionary) + if contains: + return (True, [member.location] + locations) + + if dictMember.parent: + if dictMember.parent == dictionary: + return (True, [dictMember.location]) + else: + (contains, locations) = dictionaryContainsDictionary(dictMember.parent, dictionary) + if contains: + return (True, [dictMember.location] + locations) + + return (False, None) + + for member in self.members: + if member.type.isDictionary() and member.type.nullable(): + raise WebIDLError("Dictionary %s has member with nullable " + "dictionary type" % self.identifier.name, + [member.location]) + (contains, locations) = typeContainsDictionary(member.type, self) + if contains: + raise WebIDLError("Dictionary %s has member with itself as type." % + self.identifier.name, + [member.location] + locations) + + def addExtendedAttributes(self, attrs): + assert len(attrs) == 0 + + def _getDependentObjects(self): + deps = set(self.members) + if (self.parent): + deps.add(self.parent) + return deps + +class IDLEnum(IDLObjectWithIdentifier): + def __init__(self, location, parentScope, name, values): + assert isinstance(parentScope, IDLScope) + assert isinstance(name, IDLUnresolvedIdentifier) + + if len(values) != len(set(values)): + raise WebIDLError("Enum %s has multiple identical strings" % name.name, + [location]) + + IDLObjectWithIdentifier.__init__(self, location, parentScope, name) + self._values = values + + def values(self): + return self._values + + def finish(self, scope): + pass + + def validate(self): + pass + + def isEnum(self): + return True + + def addExtendedAttributes(self, attrs): + assert len(attrs) == 0 + + def _getDependentObjects(self): + return set() + +class IDLType(IDLObject): + Tags = enum( + # The integer types + 'int8', + 'uint8', + 'int16', + 'uint16', + 'int32', + 'uint32', + 'int64', + 'uint64', + # Additional primitive types + 'bool', + 'unrestricted_float', + 'float', + 'unrestricted_double', + # "double" last primitive type to match IDLBuiltinType + 'double', + # Other types + 'any', + 'domstring', + 'bytestring', + 'object', + 'date', + 'void', + # Funny stuff + 'interface', + 'dictionary', + 'enum', + 'callback', + 'union', + 'sequence', + 'array' + ) + + def __init__(self, location, name): + IDLObject.__init__(self, location) + self.name = name + self.builtin = False + + def __eq__(self, other): + return other and self.builtin == other.builtin and self.name == other.name + + def __ne__(self, other): + return not self == other + + def __str__(self): + return str(self.name) + + def isType(self): + return True + + def nullable(self): + return False + + def isPrimitive(self): + return False + + def isBoolean(self): + return False + + def isNumeric(self): + return False + + def isString(self): + return False + + def isByteString(self): + return False + + def isDOMString(self): + return False + + def isVoid(self): + return self.name == "Void" + + def isSequence(self): + return False + + def isArray(self): + return False + + def isArrayBuffer(self): + return False + + def isArrayBufferView(self): + return False + + def isTypedArray(self): + return False + + def isCallbackInterface(self): + return False + + def isNonCallbackInterface(self): + return False + + def isGeckoInterface(self): + """ Returns a boolean indicating whether this type is an 'interface' + type that is implemented in Gecko. At the moment, this returns + true for all interface types that are not types from the TypedArray + spec.""" + return self.isInterface() and not self.isSpiderMonkeyInterface() + + def isSpiderMonkeyInterface(self): + """ Returns a boolean indicating whether this type is an 'interface' + type that is implemented in Spidermonkey. At the moment, this + only returns true for the types from the TypedArray spec. """ + return self.isInterface() and (self.isArrayBuffer() or \ + self.isArrayBufferView() or \ + self.isTypedArray()) + + def isDictionary(self): + return False + + def isInterface(self): + return False + + def isAny(self): + return self.tag() == IDLType.Tags.any + + def isDate(self): + return self.tag() == IDLType.Tags.date + + def isObject(self): + return self.tag() == IDLType.Tags.object + + def isPromise(self): + return False + + def isComplete(self): + return True + + def includesRestrictedFloat(self): + return False + + def isFloat(self): + return False + + def isUnrestricted(self): + # Should only call this on float types + assert self.isFloat() + + def isSerializable(self): + return False + + def tag(self): + assert False # Override me! + + def treatNonCallableAsNull(self): + assert self.tag() == IDLType.Tags.callback + return self.nullable() and self.inner._treatNonCallableAsNull + + def treatNonObjectAsNull(self): + assert self.tag() == IDLType.Tags.callback + return self.nullable() and self.inner._treatNonObjectAsNull + + def addExtendedAttributes(self, attrs): + assert len(attrs) == 0 + + def resolveType(self, parentScope): + pass + + def unroll(self): + return self + + def isDistinguishableFrom(self, other): + raise TypeError("Can't tell whether a generic type is or is not " + "distinguishable from other things") + +class IDLUnresolvedType(IDLType): + """ + Unresolved types are interface types + """ + + def __init__(self, location, name): + IDLType.__init__(self, location, name) + + def isComplete(self): + return False + + def complete(self, scope): + obj = None + try: + obj = scope._lookupIdentifier(self.name) + except: + raise WebIDLError("Unresolved type '%s'." % self.name, + [self.location]) + + assert obj + if obj.isType(): + # obj itself might not be complete; deal with that. + assert obj != self + if not obj.isComplete(): + obj = obj.complete(scope) + return obj + + name = self.name.resolve(scope, None) + return IDLWrapperType(self.location, obj) + + def isDistinguishableFrom(self, other): + raise TypeError("Can't tell whether an unresolved type is or is not " + "distinguishable from other things") + +class IDLNullableType(IDLType): + def __init__(self, location, innerType): + assert not innerType.isVoid() + assert not innerType == BuiltinTypes[IDLBuiltinType.Types.any] + + IDLType.__init__(self, location, innerType.name) + self.inner = innerType + self.builtin = False + + def __eq__(self, other): + return isinstance(other, IDLNullableType) and self.inner == other.inner + + def __str__(self): + return self.inner.__str__() + "OrNull" + + def nullable(self): + return True + + def isCallback(self): + return self.inner.isCallback() + + def isPrimitive(self): + return self.inner.isPrimitive() + + def isBoolean(self): + return self.inner.isBoolean() + + def isNumeric(self): + return self.inner.isNumeric() + + def isString(self): + return self.inner.isString() + + def isByteString(self): + return self.inner.isByteString() + + def isDOMString(self): + return self.inner.isDOMString() + + def isFloat(self): + return self.inner.isFloat() + + def isUnrestricted(self): + return self.inner.isUnrestricted() + + def includesRestrictedFloat(self): + return self.inner.includesRestrictedFloat() + + def isInteger(self): + return self.inner.isInteger() + + def isVoid(self): + return False + + def isSequence(self): + return self.inner.isSequence() + + def isArray(self): + return self.inner.isArray() + + def isArrayBuffer(self): + return self.inner.isArrayBuffer() + + def isArrayBufferView(self): + return self.inner.isArrayBufferView() + + def isTypedArray(self): + return self.inner.isTypedArray() + + def isDictionary(self): + return self.inner.isDictionary() + + def isInterface(self): + return self.inner.isInterface() + + def isCallbackInterface(self): + return self.inner.isCallbackInterface() + + def isNonCallbackInterface(self): + return self.inner.isNonCallbackInterface() + + def isEnum(self): + return self.inner.isEnum() + + def isUnion(self): + return self.inner.isUnion() + + def isSerializable(self): + return self.inner.isSerializable() + + def tag(self): + return self.inner.tag() + + def resolveType(self, parentScope): + assert isinstance(parentScope, IDLScope) + self.inner.resolveType(parentScope) + + def isComplete(self): + return self.inner.isComplete() + + def complete(self, scope): + self.inner = self.inner.complete(scope) + if self.inner.nullable(): + raise WebIDLError("The inner type of a nullable type must not be " + "a nullable type", + [self.location, self.inner.location]) + if self.inner.isUnion(): + if self.inner.hasNullableType: + raise WebIDLError("The inner type of a nullable type must not " + "be a union type that itself has a nullable " + "type as a member type", [self.location]) + + self.name = self.inner.name + return self + + def unroll(self): + return self.inner.unroll() + + def isDistinguishableFrom(self, other): + if (other.nullable() or (other.isUnion() and other.hasNullableType) or + other.isDictionary()): + # Can't tell which type null should become + return False + return self.inner.isDistinguishableFrom(other) + + def _getDependentObjects(self): + return self.inner._getDependentObjects() + +class IDLSequenceType(IDLType): + def __init__(self, location, parameterType): + assert not parameterType.isVoid() + + IDLType.__init__(self, location, parameterType.name) + self.inner = parameterType + self.builtin = False + + def __eq__(self, other): + return isinstance(other, IDLSequenceType) and self.inner == other.inner + + def __str__(self): + return self.inner.__str__() + "Sequence" + + def nullable(self): + return False + + def isPrimitive(self): + return False; + + def isString(self): + return False; + + def isByteString(self): + return False + + def isDOMString(self): + return False + + def isVoid(self): + return False + + def isSequence(self): + return True + + def isArray(self): + return False + + def isDictionary(self): + return False + + def isInterface(self): + return False + + def isEnum(self): + return False + + def isSerializable(self): + return self.inner.isSerializable() + + def includesRestrictedFloat(self): + return self.inner.includesRestrictedFloat() + + def tag(self): + return IDLType.Tags.sequence + + def resolveType(self, parentScope): + assert isinstance(parentScope, IDLScope) + self.inner.resolveType(parentScope) + + def isComplete(self): + return self.inner.isComplete() + + def complete(self, scope): + self.inner = self.inner.complete(scope) + self.name = self.inner.name + return self + + def unroll(self): + return self.inner.unroll() + + def isDistinguishableFrom(self, other): + if other.isUnion(): + # Just forward to the union; it'll deal + return other.isDistinguishableFrom(self) + return (other.isPrimitive() or other.isString() or other.isEnum() or + other.isDate() or other.isNonCallbackInterface()) + + def _getDependentObjects(self): + return self.inner._getDependentObjects() + +class IDLUnionType(IDLType): + def __init__(self, location, memberTypes): + IDLType.__init__(self, location, "") + self.memberTypes = memberTypes + self.hasNullableType = False + self.hasDictionaryType = False + self.flatMemberTypes = None + self.builtin = False + + def __eq__(self, other): + return isinstance(other, IDLUnionType) and self.memberTypes == other.memberTypes + + def isVoid(self): + return False + + def isUnion(self): + return True + + def isSerializable(self): + return all(m.isSerializable() for m in self.memberTypes) + + def includesRestrictedFloat(self): + return any(t.includesRestrictedFloat() for t in self.memberTypes) + + def tag(self): + return IDLType.Tags.union + + def resolveType(self, parentScope): + assert isinstance(parentScope, IDLScope) + for t in self.memberTypes: + t.resolveType(parentScope) + + def isComplete(self): + return self.flatMemberTypes is not None + + def complete(self, scope): + def typeName(type): + if isinstance(type, IDLNullableType): + return typeName(type.inner) + "OrNull" + if isinstance(type, IDLWrapperType): + return typeName(type._identifier.object()) + if isinstance(type, IDLObjectWithIdentifier): + return typeName(type.identifier) + if isinstance(type, IDLType) and (type.isArray() or type.isSequence()): + return str(type) + return type.name + + for (i, type) in enumerate(self.memberTypes): + if not type.isComplete(): + self.memberTypes[i] = type.complete(scope) + + self.name = "Or".join(typeName(type) for type in self.memberTypes) + self.flatMemberTypes = list(self.memberTypes) + i = 0 + while i < len(self.flatMemberTypes): + if self.flatMemberTypes[i].nullable(): + if self.hasNullableType: + raise WebIDLError("Can't have more than one nullable types in a union", + [nullableType.location, self.flatMemberTypes[i].location]) + if self.hasDictionaryType: + raise WebIDLError("Can't have a nullable type and a " + "dictionary type in a union", + [dictionaryType.location, + self.flatMemberTypes[i].location]) + self.hasNullableType = True + nullableType = self.flatMemberTypes[i] + self.flatMemberTypes[i] = self.flatMemberTypes[i].inner + continue + if self.flatMemberTypes[i].isDictionary(): + if self.hasNullableType: + raise WebIDLError("Can't have a nullable type and a " + "dictionary type in a union", + [nullableType.location, + self.flatMemberTypes[i].location]) + self.hasDictionaryType = True + dictionaryType = self.flatMemberTypes[i] + elif self.flatMemberTypes[i].isUnion(): + self.flatMemberTypes[i:i + 1] = self.flatMemberTypes[i].memberTypes + continue + i += 1 + + for (i, t) in enumerate(self.flatMemberTypes[:-1]): + for u in self.flatMemberTypes[i + 1:]: + if not t.isDistinguishableFrom(u): + raise WebIDLError("Flat member types of a union should be " + "distinguishable, " + str(t) + " is not " + "distinguishable from " + str(u), + [self.location, t.location, u.location]) + + return self + + def isDistinguishableFrom(self, other): + if self.hasNullableType and other.nullable(): + # Can't tell which type null should become + return False + if other.isUnion(): + otherTypes = other.unroll().memberTypes + else: + otherTypes = [other] + # For every type in otherTypes, check that it's distinguishable from + # every type in our types + for u in otherTypes: + if any(not t.isDistinguishableFrom(u) for t in self.memberTypes): + return False + return True + + def _getDependentObjects(self): + return set(self.memberTypes) + +class IDLArrayType(IDLType): + def __init__(self, location, parameterType): + assert not parameterType.isVoid() + if parameterType.isSequence(): + raise WebIDLError("Array type cannot parameterize over a sequence type", + [location]) + if parameterType.isDictionary(): + raise WebIDLError("Array type cannot parameterize over a dictionary type", + [location]) + + IDLType.__init__(self, location, parameterType.name) + self.inner = parameterType + self.builtin = False + + def __eq__(self, other): + return isinstance(other, IDLArrayType) and self.inner == other.inner + + def __str__(self): + return self.inner.__str__() + "Array" + + def nullable(self): + return False + + def isPrimitive(self): + return False + + def isString(self): + return False + + def isByteString(self): + return False + + def isDOMString(self): + return False + + def isVoid(self): + return False + + def isSequence(self): + assert not self.inner.isSequence() + return False + + def isArray(self): + return True + + def isDictionary(self): + assert not self.inner.isDictionary() + return False + + def isInterface(self): + return False + + def isEnum(self): + return False + + def tag(self): + return IDLType.Tags.array + + def resolveType(self, parentScope): + assert isinstance(parentScope, IDLScope) + self.inner.resolveType(parentScope) + + def isComplete(self): + return self.inner.isComplete() + + def complete(self, scope): + self.inner = self.inner.complete(scope) + self.name = self.inner.name + + if self.inner.isDictionary(): + raise WebIDLError("Array type must not contain " + "dictionary as element type.", + [self.inner.location]) + + assert not self.inner.isSequence() + + return self + + def unroll(self): + return self.inner.unroll() + + def isDistinguishableFrom(self, other): + if other.isUnion(): + # Just forward to the union; it'll deal + return other.isDistinguishableFrom(self) + return (other.isPrimitive() or other.isString() or other.isEnum() or + other.isDate() or other.isNonCallbackInterface()) + + def _getDependentObjects(self): + return self.inner._getDependentObjects() + +class IDLTypedefType(IDLType, IDLObjectWithIdentifier): + def __init__(self, location, innerType, name): + IDLType.__init__(self, location, innerType.name) + + identifier = IDLUnresolvedIdentifier(location, name) + + IDLObjectWithIdentifier.__init__(self, location, None, identifier) + + self.inner = innerType + self.name = name + self.builtin = False + + def __eq__(self, other): + return isinstance(other, IDLTypedefType) and self.inner == other.inner + + def __str__(self): + return self.identifier.name + + def nullable(self): + return self.inner.nullable() + + def isPrimitive(self): + return self.inner.isPrimitive() + + def isBoolean(self): + return self.inner.isBoolean() + + def isNumeric(self): + return self.inner.isNumeric() + + def isString(self): + return self.inner.isString() + + def isByteString(self): + return self.inner.isByteString() + + def isDOMString(self): + return self.inner.isDOMString() + + def isVoid(self): + return self.inner.isVoid() + + def isSequence(self): + return self.inner.isSequence() + + def isArray(self): + return self.inner.isArray() + + def isDictionary(self): + return self.inner.isDictionary() + + def isArrayBuffer(self): + return self.inner.isArrayBuffer() + + def isArrayBufferView(self): + return self.inner.isArrayBufferView() + + def isTypedArray(self): + return self.inner.isTypedArray() + + def isInterface(self): + return self.inner.isInterface() + + def isCallbackInterface(self): + return self.inner.isCallbackInterface() + + def isNonCallbackInterface(self): + return self.inner.isNonCallbackInterface() + + def isComplete(self): + return False + + def complete(self, parentScope): + if not self.inner.isComplete(): + self.inner = self.inner.complete(parentScope) + assert self.inner.isComplete() + return self.inner + + def finish(self, parentScope): + # Maybe the IDLObjectWithIdentifier for the typedef should be + # a separate thing from the type? If that happens, we can + # remove some hackery around avoiding isInterface() in + # Configuration.py. + self.complete(parentScope) + + def validate(self): + pass + + # Do we need a resolveType impl? I don't think it's particularly useful.... + + def tag(self): + return self.inner.tag() + + def unroll(self): + return self.inner.unroll() + + def isDistinguishableFrom(self, other): + return self.inner.isDistinguishableFrom(other) + + def _getDependentObjects(self): + return self.inner._getDependentObjects() + +class IDLWrapperType(IDLType): + def __init__(self, location, inner): + IDLType.__init__(self, location, inner.identifier.name) + self.inner = inner + self._identifier = inner.identifier + self.builtin = False + + def __eq__(self, other): + return isinstance(other, IDLWrapperType) and \ + self._identifier == other._identifier and \ + self.builtin == other.builtin + + def __str__(self): + return str(self.name) + " (Wrapper)" + + def nullable(self): + return False + + def isPrimitive(self): + return False + + def isString(self): + return False + + def isByteString(self): + return False + + def isDOMString(self): + return False + + def isVoid(self): + return False + + def isSequence(self): + return False + + def isArray(self): + return False + + def isDictionary(self): + return isinstance(self.inner, IDLDictionary) + + def isInterface(self): + return isinstance(self.inner, IDLInterface) or \ + isinstance(self.inner, IDLExternalInterface) + + def isCallbackInterface(self): + return self.isInterface() and self.inner.isCallback() + + def isNonCallbackInterface(self): + return self.isInterface() and not self.inner.isCallback() + + def isEnum(self): + return isinstance(self.inner, IDLEnum) + + def isPromise(self): + return isinstance(self.inner, IDLInterface) and \ + self.inner.identifier.name == "Promise" + + def isSerializable(self): + if self.isInterface(): + if self.inner.isExternal(): + return False + return any(m.isMethod() and m.isJsonifier() for m in self.inner.members) + elif self.isEnum(): + return True + elif self.isDictionary(): + return all(m.type.isSerializable() for m in self.inner.members) + else: + raise WebIDLError("IDLWrapperType wraps type %s that we don't know if " + "is serializable" % type(self.inner), [self.location]) + + def resolveType(self, parentScope): + assert isinstance(parentScope, IDLScope) + self.inner.resolve(parentScope) + + def isComplete(self): + return True + + def tag(self): + if self.isInterface(): + return IDLType.Tags.interface + elif self.isEnum(): + return IDLType.Tags.enum + elif self.isDictionary(): + return IDLType.Tags.dictionary + else: + assert False + + def isDistinguishableFrom(self, other): + if other.isUnion(): + # Just forward to the union; it'll deal + return other.isDistinguishableFrom(self) + assert self.isInterface() or self.isEnum() or self.isDictionary() + if self.isEnum(): + return (other.isPrimitive() or other.isInterface() or other.isObject() or + other.isCallback() or other.isDictionary() or + other.isSequence() or other.isArray() or + other.isDate()) + if self.isDictionary() and other.nullable(): + return False + if other.isPrimitive() or other.isString() or other.isEnum() or other.isDate(): + return True + if self.isDictionary(): + return other.isNonCallbackInterface() + + assert self.isInterface() + if other.isInterface(): + if other.isSpiderMonkeyInterface(): + # Just let |other| handle things + return other.isDistinguishableFrom(self) + assert self.isGeckoInterface() and other.isGeckoInterface() + if self.inner.isExternal() or other.unroll().inner.isExternal(): + return self != other + return (len(self.inner.interfacesBasedOnSelf & + other.unroll().inner.interfacesBasedOnSelf) == 0 and + (self.isNonCallbackInterface() or + other.isNonCallbackInterface())) + if (other.isDictionary() or other.isCallback() or + other.isSequence() or other.isArray()): + return self.isNonCallbackInterface() + + # Not much else |other| can be + assert other.isObject() + return False + + def _getDependentObjects(self): + # NB: The codegen for an interface type depends on + # a) That the identifier is in fact an interface (as opposed to + # a dictionary or something else). + # b) The native type of the interface. + # If we depend on the interface object we will also depend on + # anything the interface depends on which is undesirable. We + # considered implementing a dependency just on the interface type + # file, but then every modification to an interface would cause this + # to be regenerated which is still undesirable. We decided not to + # depend on anything, reasoning that: + # 1) Changing the concrete type of the interface requires modifying + # Bindings.conf, which is still a global dependency. + # 2) Changing an interface to a dictionary (or vice versa) with the + # same identifier should be incredibly rare. + return set() + +class IDLBuiltinType(IDLType): + + Types = enum( + # The integer types + 'byte', + 'octet', + 'short', + 'unsigned_short', + 'long', + 'unsigned_long', + 'long_long', + 'unsigned_long_long', + # Additional primitive types + 'boolean', + 'unrestricted_float', + 'float', + 'unrestricted_double', + # IMPORTANT: "double" must be the last primitive type listed + 'double', + # Other types + 'any', + 'domstring', + 'bytestring', + 'object', + 'date', + 'void', + # Funny stuff + 'ArrayBuffer', + 'ArrayBufferView', + 'Int8Array', + 'Uint8Array', + 'Uint8ClampedArray', + 'Int16Array', + 'Uint16Array', + 'Int32Array', + 'Uint32Array', + 'Float32Array', + 'Float64Array' + ) + + TagLookup = { + Types.byte: IDLType.Tags.int8, + Types.octet: IDLType.Tags.uint8, + Types.short: IDLType.Tags.int16, + Types.unsigned_short: IDLType.Tags.uint16, + Types.long: IDLType.Tags.int32, + Types.unsigned_long: IDLType.Tags.uint32, + Types.long_long: IDLType.Tags.int64, + Types.unsigned_long_long: IDLType.Tags.uint64, + Types.boolean: IDLType.Tags.bool, + Types.unrestricted_float: IDLType.Tags.unrestricted_float, + Types.float: IDLType.Tags.float, + Types.unrestricted_double: IDLType.Tags.unrestricted_double, + Types.double: IDLType.Tags.double, + Types.any: IDLType.Tags.any, + Types.domstring: IDLType.Tags.domstring, + Types.bytestring: IDLType.Tags.bytestring, + Types.object: IDLType.Tags.object, + Types.date: IDLType.Tags.date, + Types.void: IDLType.Tags.void, + Types.ArrayBuffer: IDLType.Tags.interface, + Types.ArrayBufferView: IDLType.Tags.interface, + Types.Int8Array: IDLType.Tags.interface, + Types.Uint8Array: IDLType.Tags.interface, + Types.Uint8ClampedArray: IDLType.Tags.interface, + Types.Int16Array: IDLType.Tags.interface, + Types.Uint16Array: IDLType.Tags.interface, + Types.Int32Array: IDLType.Tags.interface, + Types.Uint32Array: IDLType.Tags.interface, + Types.Float32Array: IDLType.Tags.interface, + Types.Float64Array: IDLType.Tags.interface + } + + def __init__(self, location, name, type): + IDLType.__init__(self, location, name) + self.builtin = True + self._typeTag = type + + def isPrimitive(self): + return self._typeTag <= IDLBuiltinType.Types.double + + def isBoolean(self): + return self._typeTag == IDLBuiltinType.Types.boolean + + def isNumeric(self): + return self.isPrimitive() and not self.isBoolean() + + def isString(self): + return self._typeTag == IDLBuiltinType.Types.domstring or \ + self._typeTag == IDLBuiltinType.Types.bytestring + + def isByteString(self): + return self._typeTag == IDLBuiltinType.Types.bytestring + + def isDOMString(self): + return self._typeTag == IDLBuiltinType.Types.domstring + + def isInteger(self): + return self._typeTag <= IDLBuiltinType.Types.unsigned_long_long + + def isArrayBuffer(self): + return self._typeTag == IDLBuiltinType.Types.ArrayBuffer + + def isArrayBufferView(self): + return self._typeTag == IDLBuiltinType.Types.ArrayBufferView + + def isTypedArray(self): + return self._typeTag >= IDLBuiltinType.Types.Int8Array and \ + self._typeTag <= IDLBuiltinType.Types.Float64Array + + def isInterface(self): + # TypedArray things are interface types per the TypedArray spec, + # but we handle them as builtins because SpiderMonkey implements + # all of it internally. + return self.isArrayBuffer() or \ + self.isArrayBufferView() or \ + self.isTypedArray() + + def isNonCallbackInterface(self): + # All the interfaces we can be are non-callback + return self.isInterface() + + def isFloat(self): + return self._typeTag == IDLBuiltinType.Types.float or \ + self._typeTag == IDLBuiltinType.Types.double or \ + self._typeTag == IDLBuiltinType.Types.unrestricted_float or \ + self._typeTag == IDLBuiltinType.Types.unrestricted_double + + def isUnrestricted(self): + assert self.isFloat() + return self._typeTag == IDLBuiltinType.Types.unrestricted_float or \ + self._typeTag == IDLBuiltinType.Types.unrestricted_double + + def isSerializable(self): + return self.isPrimitive() or self.isDOMString() or self.isDate() + + def includesRestrictedFloat(self): + return self.isFloat() and not self.isUnrestricted() + + def tag(self): + return IDLBuiltinType.TagLookup[self._typeTag] + + def isDistinguishableFrom(self, other): + if other.isUnion(): + # Just forward to the union; it'll deal + return other.isDistinguishableFrom(self) + if self.isBoolean(): + return (other.isNumeric() or other.isString() or other.isEnum() or + other.isInterface() or other.isObject() or + other.isCallback() or other.isDictionary() or + other.isSequence() or other.isArray() or + other.isDate()) + if self.isNumeric(): + return (other.isBoolean() or other.isString() or other.isEnum() or + other.isInterface() or other.isObject() or + other.isCallback() or other.isDictionary() or + other.isSequence() or other.isArray() or + other.isDate()) + if self.isString(): + return (other.isPrimitive() or other.isInterface() or + other.isObject() or + other.isCallback() or other.isDictionary() or + other.isSequence() or other.isArray() or + other.isDate()) + if self.isAny(): + # Can't tell "any" apart from anything + return False + if self.isObject(): + return other.isPrimitive() or other.isString() or other.isEnum() + if self.isDate(): + return (other.isPrimitive() or other.isString() or other.isEnum() or + other.isInterface() or other.isCallback() or + other.isDictionary() or other.isSequence() or + other.isArray()) + if self.isVoid(): + return not other.isVoid() + # Not much else we could be! + assert self.isSpiderMonkeyInterface() + # Like interfaces, but we know we're not a callback + return (other.isPrimitive() or other.isString() or other.isEnum() or + other.isCallback() or other.isDictionary() or + other.isSequence() or other.isArray() or other.isDate() or + (other.isInterface() and ( + # ArrayBuffer is distinguishable from everything + # that's not an ArrayBuffer or a callback interface + (self.isArrayBuffer() and not other.isArrayBuffer()) or + # ArrayBufferView is distinguishable from everything + # that's not an ArrayBufferView or typed array. + (self.isArrayBufferView() and not other.isArrayBufferView() and + not other.isTypedArray()) or + # Typed arrays are distinguishable from everything + # except ArrayBufferView and the same type of typed + # array + (self.isTypedArray() and not other.isArrayBufferView() and not + (other.isTypedArray() and other.name == self.name))))) + + def _getDependentObjects(self): + return set() + +BuiltinTypes = { + IDLBuiltinType.Types.byte: + IDLBuiltinType(BuiltinLocation("<builtin type>"), "Byte", + IDLBuiltinType.Types.byte), + IDLBuiltinType.Types.octet: + IDLBuiltinType(BuiltinLocation("<builtin type>"), "Octet", + IDLBuiltinType.Types.octet), + IDLBuiltinType.Types.short: + IDLBuiltinType(BuiltinLocation("<builtin type>"), "Short", + IDLBuiltinType.Types.short), + IDLBuiltinType.Types.unsigned_short: + IDLBuiltinType(BuiltinLocation("<builtin type>"), "UnsignedShort", + IDLBuiltinType.Types.unsigned_short), + IDLBuiltinType.Types.long: + IDLBuiltinType(BuiltinLocation("<builtin type>"), "Long", + IDLBuiltinType.Types.long), + IDLBuiltinType.Types.unsigned_long: + IDLBuiltinType(BuiltinLocation("<builtin type>"), "UnsignedLong", + IDLBuiltinType.Types.unsigned_long), + IDLBuiltinType.Types.long_long: + IDLBuiltinType(BuiltinLocation("<builtin type>"), "LongLong", + IDLBuiltinType.Types.long_long), + IDLBuiltinType.Types.unsigned_long_long: + IDLBuiltinType(BuiltinLocation("<builtin type>"), "UnsignedLongLong", + IDLBuiltinType.Types.unsigned_long_long), + IDLBuiltinType.Types.boolean: + IDLBuiltinType(BuiltinLocation("<builtin type>"), "Boolean", + IDLBuiltinType.Types.boolean), + IDLBuiltinType.Types.float: + IDLBuiltinType(BuiltinLocation("<builtin type>"), "Float", + IDLBuiltinType.Types.float), + IDLBuiltinType.Types.unrestricted_float: + IDLBuiltinType(BuiltinLocation("<builtin type>"), "UnrestrictedFloat", + IDLBuiltinType.Types.unrestricted_float), + IDLBuiltinType.Types.double: + IDLBuiltinType(BuiltinLocation("<builtin type>"), "Double", + IDLBuiltinType.Types.double), + IDLBuiltinType.Types.unrestricted_double: + IDLBuiltinType(BuiltinLocation("<builtin type>"), "UnrestrictedDouble", + IDLBuiltinType.Types.unrestricted_double), + IDLBuiltinType.Types.any: + IDLBuiltinType(BuiltinLocation("<builtin type>"), "Any", + IDLBuiltinType.Types.any), + IDLBuiltinType.Types.domstring: + IDLBuiltinType(BuiltinLocation("<builtin type>"), "String", + IDLBuiltinType.Types.domstring), + IDLBuiltinType.Types.bytestring: + IDLBuiltinType(BuiltinLocation("<builtin type>"), "ByteString", + IDLBuiltinType.Types.bytestring), + IDLBuiltinType.Types.object: + IDLBuiltinType(BuiltinLocation("<builtin type>"), "Object", + IDLBuiltinType.Types.object), + IDLBuiltinType.Types.date: + IDLBuiltinType(BuiltinLocation("<builtin type>"), "Date", + IDLBuiltinType.Types.date), + IDLBuiltinType.Types.void: + IDLBuiltinType(BuiltinLocation("<builtin type>"), "Void", + IDLBuiltinType.Types.void), + IDLBuiltinType.Types.ArrayBuffer: + IDLBuiltinType(BuiltinLocation("<builtin type>"), "ArrayBuffer", + IDLBuiltinType.Types.ArrayBuffer), + IDLBuiltinType.Types.ArrayBufferView: + IDLBuiltinType(BuiltinLocation("<builtin type>"), "ArrayBufferView", + IDLBuiltinType.Types.ArrayBufferView), + IDLBuiltinType.Types.Int8Array: + IDLBuiltinType(BuiltinLocation("<builtin type>"), "Int8Array", + IDLBuiltinType.Types.Int8Array), + IDLBuiltinType.Types.Uint8Array: + IDLBuiltinType(BuiltinLocation("<builtin type>"), "Uint8Array", + IDLBuiltinType.Types.Uint8Array), + IDLBuiltinType.Types.Uint8ClampedArray: + IDLBuiltinType(BuiltinLocation("<builtin type>"), "Uint8ClampedArray", + IDLBuiltinType.Types.Uint8ClampedArray), + IDLBuiltinType.Types.Int16Array: + IDLBuiltinType(BuiltinLocation("<builtin type>"), "Int16Array", + IDLBuiltinType.Types.Int16Array), + IDLBuiltinType.Types.Uint16Array: + IDLBuiltinType(BuiltinLocation("<builtin type>"), "Uint16Array", + IDLBuiltinType.Types.Uint16Array), + IDLBuiltinType.Types.Int32Array: + IDLBuiltinType(BuiltinLocation("<builtin type>"), "Int32Array", + IDLBuiltinType.Types.Int32Array), + IDLBuiltinType.Types.Uint32Array: + IDLBuiltinType(BuiltinLocation("<builtin type>"), "Uint32Array", + IDLBuiltinType.Types.Uint32Array), + IDLBuiltinType.Types.Float32Array: + IDLBuiltinType(BuiltinLocation("<builtin type>"), "Float32Array", + IDLBuiltinType.Types.Float32Array), + IDLBuiltinType.Types.Float64Array: + IDLBuiltinType(BuiltinLocation("<builtin type>"), "Float64Array", + IDLBuiltinType.Types.Float64Array) + } + + +integerTypeSizes = { + IDLBuiltinType.Types.byte: (-128, 127), + IDLBuiltinType.Types.octet: (0, 255), + IDLBuiltinType.Types.short: (-32768, 32767), + IDLBuiltinType.Types.unsigned_short: (0, 65535), + IDLBuiltinType.Types.long: (-2147483648, 2147483647), + IDLBuiltinType.Types.unsigned_long: (0, 4294967295), + IDLBuiltinType.Types.long_long: (-9223372036854775808, + 9223372036854775807), + IDLBuiltinType.Types.unsigned_long_long: (0, 18446744073709551615) + } + +def matchIntegerValueToType(value): + for type, extremes in integerTypeSizes.items(): + (min, max) = extremes + if value <= max and value >= min: + return BuiltinTypes[type] + + return None + +class IDLValue(IDLObject): + def __init__(self, location, type, value): + IDLObject.__init__(self, location) + self.type = type + assert isinstance(type, IDLType) + + self.value = value + + def coerceToType(self, type, location): + if type == self.type: + return self # Nothing to do + + # We first check for unions to ensure that even if the union is nullable + # we end up with the right flat member type, not the union's type. + if type.isUnion(): + # We use the flat member types here, because if we have a nullable + # member type, or a nested union, we want the type the value + # actually coerces to, not the nullable or nested union type. + for subtype in type.unroll().flatMemberTypes: + try: + coercedValue = self.coerceToType(subtype, location) + # Create a new IDLValue to make sure that we have the + # correct float/double type. This is necessary because we + # use the value's type when it is a default value of a + # union, and the union cares about the exact float type. + return IDLValue(self.location, subtype, coercedValue.value) + except: + pass + # If the type allows null, rerun this matching on the inner type, except + # nullable enums. We handle those specially, because we want our + # default string values to stay strings even when assigned to a nullable + # enum. + elif type.nullable() and not type.isEnum(): + innerValue = self.coerceToType(type.inner, location) + return IDLValue(self.location, type, innerValue.value) + + elif self.type.isInteger() and type.isInteger(): + # We're both integer types. See if we fit. + + (min, max) = integerTypeSizes[type._typeTag] + if self.value <= max and self.value >= min: + # Promote + return IDLValue(self.location, type, self.value) + else: + raise WebIDLError("Value %s is out of range for type %s." % + (self.value, type), [location]) + elif self.type.isInteger() and type.isFloat(): + # Convert an integer literal into float + if -2**24 <= self.value <= 2**24: + floatType = BuiltinTypes[IDLBuiltinType.Types.float] + return IDLValue(self.location, floatType, float(self.value)) + else: + raise WebIDLError("Converting value %s to %s will lose precision." % + (self.value, type), [location]) + elif self.type.isString() and type.isEnum(): + # Just keep our string, but make sure it's a valid value for this enum + enum = type.unroll().inner + if self.value not in enum.values(): + raise WebIDLError("'%s' is not a valid default value for enum %s" + % (self.value, enum.identifier.name), + [location, enum.location]) + return self + elif self.type.isFloat() and type.isFloat(): + if (not type.isUnrestricted() and + (self.value == float("inf") or self.value == float("-inf") or + math.isnan(self.value))): + raise WebIDLError("Trying to convert unrestricted value %s to non-unrestricted" + % self.value, [location]); + return self + raise WebIDLError("Cannot coerce type %s to type %s." % + (self.type, type), [location]) + + def _getDependentObjects(self): + return set() + +class IDLNullValue(IDLObject): + def __init__(self, location): + IDLObject.__init__(self, location) + self.type = None + self.value = None + + def coerceToType(self, type, location): + if (not isinstance(type, IDLNullableType) and + not (type.isUnion() and type.hasNullableType) and + not (type.isUnion() and type.hasDictionaryType) and + not type.isDictionary() and + not type.isAny()): + raise WebIDLError("Cannot coerce null value to type %s." % type, + [location]) + + nullValue = IDLNullValue(self.location) + if type.isUnion() and not type.nullable() and type.hasDictionaryType: + # We're actually a default value for the union's dictionary member. + # Use its type. + for t in type.flatMemberTypes: + if t.isDictionary(): + nullValue.type = t + return nullValue + nullValue.type = type + return nullValue + + def _getDependentObjects(self): + return set() + +class IDLUndefinedValue(IDLObject): + def __init__(self, location): + IDLObject.__init__(self, location) + self.type = None + self.value = None + + def coerceToType(self, type, location): + if not type.isAny(): + raise WebIDLError("Cannot coerce undefined value to type %s." % type, + [location]) + + undefinedValue = IDLUndefinedValue(self.location) + undefinedValue.type = type + return undefinedValue + + def _getDependentObjects(self): + return set() + +class IDLInterfaceMember(IDLObjectWithIdentifier): + + Tags = enum( + 'Const', + 'Attr', + 'Method' + ) + + Special = enum( + 'Static', + 'Stringifier' + ) + + def __init__(self, location, identifier, tag): + IDLObjectWithIdentifier.__init__(self, location, None, identifier) + self.tag = tag + self._extendedAttrDict = {} + + def isMethod(self): + return self.tag == IDLInterfaceMember.Tags.Method + + def isAttr(self): + return self.tag == IDLInterfaceMember.Tags.Attr + + def isConst(self): + return self.tag == IDLInterfaceMember.Tags.Const + + def addExtendedAttributes(self, attrs): + for attr in attrs: + self.handleExtendedAttribute(attr) + attrlist = attr.listValue() + self._extendedAttrDict[attr.identifier()] = attrlist if len(attrlist) else True + + def handleExtendedAttribute(self, attr): + pass + + def getExtendedAttribute(self, name): + return self._extendedAttrDict.get(name, None) + +class IDLConst(IDLInterfaceMember): + def __init__(self, location, identifier, type, value): + IDLInterfaceMember.__init__(self, location, identifier, + IDLInterfaceMember.Tags.Const) + + assert isinstance(type, IDLType) + if type.isDictionary(): + raise WebIDLError("A constant cannot be of a dictionary type", + [self.location]) + self.type = type + self.value = value + + if identifier.name == "prototype": + raise WebIDLError("The identifier of a constant must not be 'prototype'", + [location]) + + def __str__(self): + return "'%s' const '%s'" % (self.type, self.identifier) + + def finish(self, scope): + if not self.type.isComplete(): + type = self.type.complete(scope) + if not type.isPrimitive() and not type.isString(): + locations = [self.type.location, type.location] + try: + locations.append(type.inner.location) + except: + pass + raise WebIDLError("Incorrect type for constant", locations) + self.type = type + + # The value might not match the type + coercedValue = self.value.coerceToType(self.type, self.location) + assert coercedValue + + self.value = coercedValue + + def validate(self): + pass + + def _getDependentObjects(self): + return set([self.type, self.value]) + +class IDLAttribute(IDLInterfaceMember): + def __init__(self, location, identifier, type, readonly, inherit=False, + static=False, stringifier=False): + IDLInterfaceMember.__init__(self, location, identifier, + IDLInterfaceMember.Tags.Attr) + + assert isinstance(type, IDLType) + self.type = type + self.readonly = readonly + self.inherit = inherit + self.static = static + self.lenientThis = False + self._unforgeable = False + self.stringifier = stringifier + self.enforceRange = False + self.clamp = False + self.slotIndex = None + + if static and identifier.name == "prototype": + raise WebIDLError("The identifier of a static attribute must not be 'prototype'", + [location]) + + if readonly and inherit: + raise WebIDLError("An attribute cannot be both 'readonly' and 'inherit'", + [self.location]) + + def isStatic(self): + return self.static + + def __str__(self): + return "'%s' attribute '%s'" % (self.type, self.identifier) + + def finish(self, scope): + if not self.type.isComplete(): + t = self.type.complete(scope) + + assert not isinstance(t, IDLUnresolvedType) + assert not isinstance(t, IDLTypedefType) + assert not isinstance(t.name, IDLUnresolvedIdentifier) + self.type = t + + if self.type.isDictionary() and not self.getExtendedAttribute("Cached"): + raise WebIDLError("An attribute cannot be of a dictionary type", + [self.location]) + if self.type.isSequence() and not self.getExtendedAttribute("Cached"): + raise WebIDLError("A non-cached attribute cannot be of a sequence " + "type", [self.location]) + if self.type.isUnion(): + for f in self.type.unroll().flatMemberTypes: + if f.isDictionary(): + raise WebIDLError("An attribute cannot be of a union " + "type if one of its member types (or " + "one of its member types's member " + "types, and so on) is a dictionary " + "type", [self.location, f.location]) + if f.isSequence(): + raise WebIDLError("An attribute cannot be of a union " + "type if one of its member types (or " + "one of its member types's member " + "types, and so on) is a sequence " + "type", [self.location, f.location]) + if not self.type.isInterface() and self.getExtendedAttribute("PutForwards"): + raise WebIDLError("An attribute with [PutForwards] must have an " + "interface type as its type", [self.location]) + + if not self.type.isInterface() and self.getExtendedAttribute("SameObject"): + raise WebIDLError("An attribute with [SameObject] must have an " + "interface type as its type", [self.location]) + + def validate(self): + if ((self.getExtendedAttribute("Cached") or + self.getExtendedAttribute("StoreInSlot")) and + not self.getExtendedAttribute("Constant") and + not self.getExtendedAttribute("Pure")): + raise WebIDLError("Cached attributes and attributes stored in " + "slots must be constant or pure, since the " + "getter won't always be called.", + [self.location]) + if self.getExtendedAttribute("Frozen"): + if not self.type.isSequence() and not self.type.isDictionary(): + raise WebIDLError("[Frozen] is only allowed on sequence-valued " + "and dictionary-valued attributes", + [self.location]) + + def handleExtendedAttribute(self, attr): + identifier = attr.identifier() + if identifier == "SetterThrows" and self.readonly: + raise WebIDLError("Readonly attributes must not be flagged as " + "[SetterThrows]", + [self.location]) + elif (((identifier == "Throws" or identifier == "GetterThrows") and + self.getExtendedAttribute("StoreInSlot")) or + (identifier == "StoreInSlot" and + (self.getExtendedAttribute("Throws") or + self.getExtendedAttribute("GetterThrows")))): + raise WebIDLError("Throwing things can't be [Pure] or [Constant] " + "or [SameObject] or [StoreInSlot]", + [attr.location]) + elif identifier == "LenientThis": + if not attr.noArguments(): + raise WebIDLError("[LenientThis] must take no arguments", + [attr.location]) + if self.isStatic(): + raise WebIDLError("[LenientThis] is only allowed on non-static " + "attributes", [attr.location, self.location]) + if self.getExtendedAttribute("CrossOriginReadable"): + raise WebIDLError("[LenientThis] is not allowed in combination " + "with [CrossOriginReadable]", + [attr.location, self.location]) + if self.getExtendedAttribute("CrossOriginWritable"): + raise WebIDLError("[LenientThis] is not allowed in combination " + "with [CrossOriginWritable]", + [attr.location, self.location]) + self.lenientThis = True + elif identifier == "Unforgeable": + if not self.readonly: + raise WebIDLError("[Unforgeable] is only allowed on readonly " + "attributes", [attr.location, self.location]) + if self.isStatic(): + raise WebIDLError("[Unforgeable] is only allowed on non-static " + "attributes", [attr.location, self.location]) + self._unforgeable = True + elif identifier == "SameObject" and not self.readonly: + raise WebIDLError("[SameObject] only allowed on readonly attributes", + [attr.location, self.location]) + elif identifier == "Constant" and not self.readonly: + raise WebIDLError("[Constant] only allowed on readonly attributes", + [attr.location, self.location]) + elif identifier == "PutForwards": + if not self.readonly: + raise WebIDLError("[PutForwards] is only allowed on readonly " + "attributes", [attr.location, self.location]) + if self.isStatic(): + raise WebIDLError("[PutForwards] is only allowed on non-static " + "attributes", [attr.location, self.location]) + if self.getExtendedAttribute("Replaceable") is not None: + raise WebIDLError("[PutForwards] and [Replaceable] can't both " + "appear on the same attribute", + [attr.location, self.location]) + if not attr.hasValue(): + raise WebIDLError("[PutForwards] takes an identifier", + [attr.location, self.location]) + elif identifier == "Replaceable": + if self.getExtendedAttribute("PutForwards") is not None: + raise WebIDLError("[PutForwards] and [Replaceable] can't both " + "appear on the same attribute", + [attr.location, self.location]) + elif identifier == "LenientFloat": + if self.readonly: + raise WebIDLError("[LenientFloat] used on a readonly attribute", + [attr.location, self.location]) + if not self.type.includesRestrictedFloat(): + raise WebIDLError("[LenientFloat] used on an attribute with a " + "non-restricted-float type", + [attr.location, self.location]) + elif identifier == "EnforceRange": + if self.readonly: + raise WebIDLError("[EnforceRange] used on a readonly attribute", + [attr.location, self.location]) + self.enforceRange = True + elif identifier == "Clamp": + if self.readonly: + raise WebIDLError("[Clamp] used on a readonly attribute", + [attr.location, self.location]) + self.clamp = True + elif identifier == "StoreInSlot": + if self.getExtendedAttribute("Cached"): + raise WebIDLError("[StoreInSlot] and [Cached] must not be " + "specified on the same attribute", + [attr.location, self.location]) + elif identifier == "Cached": + if self.getExtendedAttribute("StoreInSlot"): + raise WebIDLError("[Cached] and [StoreInSlot] must not be " + "specified on the same attribute", + [attr.location, self.location]) + elif (identifier == "CrossOriginReadable" or + identifier == "CrossOriginWritable"): + if not attr.noArguments(): + raise WebIDLError("[%s] must take no arguments" % identifier, + [attr.location]) + if self.isStatic(): + raise WebIDLError("[%s] is only allowed on non-static " + "attributes" % identifier, + [attr.location, self.location]) + if self.getExtendedAttribute("LenientThis"): + raise WebIDLError("[LenientThis] is not allowed in combination " + "with [%s]" % identifier, + [attr.location, self.location]) + elif (identifier == "Pref" or + identifier == "SetterThrows" or + identifier == "Pure" or + identifier == "Throws" or + identifier == "GetterThrows" or + identifier == "ChromeOnly" or + identifier == "SameObject" or + identifier == "Constant" or + identifier == "Func" or + identifier == "Frozen" or + identifier == "AvailableIn" or + identifier == "Const" or + identifier == "Value" or + identifier == "NewObject"): + # Known attributes that we don't need to do anything with here + pass + else: + raise WebIDLError("Unknown extended attribute %s on attribute" % identifier, + [attr.location]) + IDLInterfaceMember.handleExtendedAttribute(self, attr) + + def resolve(self, parentScope): + assert isinstance(parentScope, IDLScope) + self.type.resolveType(parentScope) + IDLObjectWithIdentifier.resolve(self, parentScope) + + def addExtendedAttributes(self, attrs): + attrs = self.checkForStringHandlingExtendedAttributes(attrs) + IDLInterfaceMember.addExtendedAttributes(self, attrs) + + def hasLenientThis(self): + return self.lenientThis + + def isUnforgeable(self): + return self._unforgeable + + def _getDependentObjects(self): + return set([self.type]) + +class IDLArgument(IDLObjectWithIdentifier): + def __init__(self, location, identifier, type, optional=False, defaultValue=None, variadic=False, dictionaryMember=False): + IDLObjectWithIdentifier.__init__(self, location, None, identifier) + + assert isinstance(type, IDLType) + self.type = type + + self.optional = optional + self.defaultValue = defaultValue + self.variadic = variadic + self.dictionaryMember = dictionaryMember + self._isComplete = False + self.enforceRange = False + self.clamp = False + self._allowTreatNonCallableAsNull = False + + self._extraAttributes = {} + + assert not variadic or optional + + def getExtendedAttribute(self, name): + return self._extraAttributes.get(name) + + def addExtendedAttributes(self, attrs): + attrs = self.checkForStringHandlingExtendedAttributes( + attrs, + isDictionaryMember=self.dictionaryMember, + isOptional=self.optional) + for attribute in attrs: + identifier = attribute.identifier() + if identifier == "Clamp": + if not attribute.noArguments(): + raise WebIDLError("[Clamp] must take no arguments", + [attribute.location]) + if self.enforceRange: + raise WebIDLError("[EnforceRange] and [Clamp] are mutually exclusive", + [self.location]); + self.clamp = True + elif identifier == "EnforceRange": + if not attribute.noArguments(): + raise WebIDLError("[EnforceRange] must take no arguments", + [attribute.location]) + if self.clamp: + raise WebIDLError("[EnforceRange] and [Clamp] are mutually exclusive", + [self.location]); + self.enforceRange = True + elif identifier == "TreatNonCallableAsNull": + self._allowTreatNonCallableAsNull = True + elif identifier in ['Ref', 'Const']: + # ok in emscripten + self._extraAttributes[identifier] = True + else: + raise WebIDLError("Unhandled extended attribute on an argument", + [attribute.location]) + + def isComplete(self): + return self._isComplete + + def complete(self, scope): + if self._isComplete: + return + + self._isComplete = True + + if not self.type.isComplete(): + type = self.type.complete(scope) + assert not isinstance(type, IDLUnresolvedType) + assert not isinstance(type, IDLTypedefType) + assert not isinstance(type.name, IDLUnresolvedIdentifier) + self.type = type + + if ((self.type.isDictionary() or + self.type.isUnion() and self.type.unroll().hasDictionaryType) and + self.optional and not self.defaultValue): + # Default optional dictionaries to null, for simplicity, + # so the codegen doesn't have to special-case this. + self.defaultValue = IDLNullValue(self.location) + elif self.type.isAny(): + assert (self.defaultValue is None or + isinstance(self.defaultValue, IDLNullValue)) + # optional 'any' values always have a default value + if self.optional and not self.defaultValue and not self.variadic: + # Set the default value to undefined, for simplicity, so the + # codegen doesn't have to special-case this. + self.defaultValue = IDLUndefinedValue(self.location) + + # Now do the coercing thing; this needs to happen after the + # above creation of a default value. + if self.defaultValue: + self.defaultValue = self.defaultValue.coerceToType(self.type, + self.location) + assert self.defaultValue + + def allowTreatNonCallableAsNull(self): + return self._allowTreatNonCallableAsNull + + def _getDependentObjects(self): + deps = set([self.type]) + if self.defaultValue: + deps.add(self.defaultValue) + return deps + +class IDLCallbackType(IDLType, IDLObjectWithScope): + def __init__(self, location, parentScope, identifier, returnType, arguments): + assert isinstance(returnType, IDLType) + + IDLType.__init__(self, location, identifier.name) + + self._returnType = returnType + # Clone the list + self._arguments = list(arguments) + + IDLObjectWithScope.__init__(self, location, parentScope, identifier) + + for (returnType, arguments) in self.signatures(): + for argument in arguments: + argument.resolve(self) + + self._treatNonCallableAsNull = False + self._treatNonObjectAsNull = False + + def isCallback(self): + return True + + def signatures(self): + return [(self._returnType, self._arguments)] + + def tag(self): + return IDLType.Tags.callback + + def finish(self, scope): + if not self._returnType.isComplete(): + type = self._returnType.complete(scope) + + assert not isinstance(type, IDLUnresolvedType) + assert not isinstance(type, IDLTypedefType) + assert not isinstance(type.name, IDLUnresolvedIdentifier) + self._returnType = type + + for argument in self._arguments: + if argument.type.isComplete(): + continue + + type = argument.type.complete(scope) + + assert not isinstance(type, IDLUnresolvedType) + assert not isinstance(type, IDLTypedefType) + assert not isinstance(type.name, IDLUnresolvedIdentifier) + argument.type = type + + def validate(self): + pass + + def isDistinguishableFrom(self, other): + if other.isUnion(): + # Just forward to the union; it'll deal + return other.isDistinguishableFrom(self) + return (other.isPrimitive() or other.isString() or other.isEnum() or + other.isNonCallbackInterface() or other.isDate()) + + def addExtendedAttributes(self, attrs): + unhandledAttrs = [] + for attr in attrs: + if attr.identifier() == "TreatNonCallableAsNull": + self._treatNonCallableAsNull = True + elif attr.identifier() == "TreatNonObjectAsNull": + self._treatNonObjectAsNull = True + else: + unhandledAttrs.append(attr) + if self._treatNonCallableAsNull and self._treatNonObjectAsNull: + raise WebIDLError("Cannot specify both [TreatNonCallableAsNull] " + "and [TreatNonObjectAsNull]", [self.location]) + if len(unhandledAttrs) != 0: + IDLType.addExtendedAttributes(self, unhandledAttrs) + + def _getDependentObjects(self): + return set([self._returnType] + self._arguments) + +class IDLMethodOverload: + """ + A class that represents a single overload of a WebIDL method. This is not + quite the same as an element of the "effective overload set" in the spec, + because separate IDLMethodOverloads are not created based on arguments being + optional. Rather, when multiple methods have the same name, there is an + IDLMethodOverload for each one, all hanging off an IDLMethod representing + the full set of overloads. + """ + def __init__(self, returnType, arguments, location): + self.returnType = returnType + # Clone the list of arguments, just in case + self.arguments = list(arguments) + self.location = location + + def _getDependentObjects(self): + deps = set(self.arguments) + deps.add(self.returnType) + return deps + +class IDLMethod(IDLInterfaceMember, IDLScope): + + Special = enum( + 'Getter', + 'Setter', + 'Creator', + 'Deleter', + 'LegacyCaller', + base=IDLInterfaceMember.Special + ) + + TypeSuffixModifier = enum( + 'None', + 'QMark', + 'Brackets' + ) + + NamedOrIndexed = enum( + 'Neither', + 'Named', + 'Indexed' + ) + + def __init__(self, location, identifier, returnType, arguments, + static=False, getter=False, setter=False, creator=False, + deleter=False, specialType=NamedOrIndexed.Neither, + legacycaller=False, stringifier=False, jsonifier=False): + # REVIEW: specialType is NamedOrIndexed -- wow, this is messed up. + IDLInterfaceMember.__init__(self, location, identifier, + IDLInterfaceMember.Tags.Method) + + self._hasOverloads = False + + assert isinstance(returnType, IDLType) + + # self._overloads is a list of IDLMethodOverloads + self._overloads = [IDLMethodOverload(returnType, arguments, location)] + + assert isinstance(static, bool) + self._static = static + assert isinstance(getter, bool) + self._getter = getter + assert isinstance(setter, bool) + self._setter = setter + assert isinstance(creator, bool) + self._creator = creator + assert isinstance(deleter, bool) + self._deleter = deleter + assert isinstance(legacycaller, bool) + self._legacycaller = legacycaller + assert isinstance(stringifier, bool) + self._stringifier = stringifier + assert isinstance(jsonifier, bool) + self._jsonifier = jsonifier + self._specialType = specialType + + if static and identifier.name == "prototype": + raise WebIDLError("The identifier of a static operation must not be 'prototype'", + [location]) + + self.assertSignatureConstraints() + + def __str__(self): + return "Method '%s'" % self.identifier + + def assertSignatureConstraints(self): + if self._getter or self._deleter: + assert len(self._overloads) == 1 + overload = self._overloads[0] + arguments = overload.arguments + assert len(arguments) == 1 + assert arguments[0].type == BuiltinTypes[IDLBuiltinType.Types.domstring] or \ + arguments[0].type == BuiltinTypes[IDLBuiltinType.Types.unsigned_long] + assert not arguments[0].optional and not arguments[0].variadic + assert not self._getter or not overload.returnType.isVoid() + + if self._setter or self._creator: + assert len(self._overloads) == 1 + arguments = self._overloads[0].arguments + assert len(arguments) == 2 + assert arguments[0].type == BuiltinTypes[IDLBuiltinType.Types.domstring] or \ + arguments[0].type == BuiltinTypes[IDLBuiltinType.Types.unsigned_long] + assert not arguments[0].optional and not arguments[0].variadic + assert not arguments[1].optional and not arguments[1].variadic + + if self._stringifier: + assert len(self._overloads) == 1 + overload = self._overloads[0] + assert len(overload.arguments) == 0 + assert overload.returnType == BuiltinTypes[IDLBuiltinType.Types.domstring] + + if self._jsonifier: + assert len(self._overloads) == 1 + overload = self._overloads[0] + assert len(overload.arguments) == 0 + assert overload.returnType == BuiltinTypes[IDLBuiltinType.Types.object] + + def isStatic(self): + return self._static + + def isGetter(self): + return self._getter + + def isSetter(self): + return self._setter + + def isCreator(self): + return self._creator + + def isDeleter(self): + return self._deleter + + def isNamed(self): + assert self._specialType == IDLMethod.NamedOrIndexed.Named or \ + self._specialType == IDLMethod.NamedOrIndexed.Indexed + return self._specialType == IDLMethod.NamedOrIndexed.Named + + def isIndexed(self): + assert self._specialType == IDLMethod.NamedOrIndexed.Named or \ + self._specialType == IDLMethod.NamedOrIndexed.Indexed + return self._specialType == IDLMethod.NamedOrIndexed.Indexed + + def isLegacycaller(self): + return self._legacycaller + + def isStringifier(self): + return self._stringifier + + def isJsonifier(self): + return self._jsonifier + + def hasOverloads(self): + return self._hasOverloads + + def isIdentifierLess(self): + return self.identifier.name[:2] == "__" and self.identifier.name != "__noSuchMethod__" + + def resolve(self, parentScope): + assert isinstance(parentScope, IDLScope) + IDLObjectWithIdentifier.resolve(self, parentScope) + IDLScope.__init__(self, self.location, parentScope, self.identifier) + for (returnType, arguments) in self.signatures(): + for argument in arguments: + argument.resolve(self) + + def addOverload(self, method): + assert len(method._overloads) == 1 + + if self._extendedAttrDict != method ._extendedAttrDict: + raise WebIDLError("Extended attributes differ on different " + "overloads of %s" % method.identifier, + [self.location, method.location]) + + self._overloads.extend(method._overloads) + + self._hasOverloads = True + + if self.isStatic() != method.isStatic(): + raise WebIDLError("Overloaded identifier %s appears with different values of the 'static' attribute" % method.identifier, + [method.location]) + + if self.isLegacycaller() != method.isLegacycaller(): + raise WebIDLError("Overloaded identifier %s appears with different values of the 'legacycaller' attribute" % method.identifier, + [method.location]) + + # Can't overload special things! + assert not self.isGetter() + assert not method.isGetter() + assert not self.isSetter() + assert not method.isSetter() + assert not self.isCreator() + assert not method.isCreator() + assert not self.isDeleter() + assert not method.isDeleter() + assert not self.isStringifier() + assert not method.isStringifier() + assert not self.isJsonifier() + assert not method.isJsonifier() + + return self + + def signatures(self): + return [(overload.returnType, overload.arguments) for overload in + self._overloads] + + def finish(self, scope): + overloadWithPromiseReturnType = None + overloadWithoutPromiseReturnType = None + for overload in self._overloads: + variadicArgument = None + + arguments = overload.arguments + for (idx, argument) in enumerate(arguments): + if not argument.isComplete(): + argument.complete(scope) + assert argument.type.isComplete() + + if (argument.type.isDictionary() or + (argument.type.isUnion() and + argument.type.unroll().hasDictionaryType)): + # Dictionaries and unions containing dictionaries at the + # end of the list or followed by optional arguments must be + # optional. + if (not argument.optional and + all(arg.optional for arg in arguments[idx+1:])): + raise WebIDLError("Dictionary argument or union " + "argument containing a dictionary " + "not followed by a required argument " + "must be optional", + [argument.location]) + + # An argument cannot be a Nullable Dictionary + if argument.type.nullable(): + raise WebIDLError("An argument cannot be a nullable " + "dictionary or nullable union " + "containing a dictionary", + [argument.location]) + + # Only the last argument can be variadic + if variadicArgument: + raise WebIDLError("Variadic argument is not last argument", + [variadicArgument.location]) + if argument.variadic: + variadicArgument = argument + + returnType = overload.returnType + if not returnType.isComplete(): + returnType = returnType.complete(scope) + assert not isinstance(returnType, IDLUnresolvedType) + assert not isinstance(returnType, IDLTypedefType) + assert not isinstance(returnType.name, IDLUnresolvedIdentifier) + overload.returnType = returnType + + if returnType.isPromise(): + overloadWithPromiseReturnType = overload + else: + overloadWithoutPromiseReturnType = overload + + # Make sure either all our overloads return Promises or none do + if overloadWithPromiseReturnType and overloadWithoutPromiseReturnType: + raise WebIDLError("We have overloads with both Promise and " + "non-Promise return types", + [overloadWithPromiseReturnType.location, + overloadWithoutPromiseReturnType.location]) + + if overloadWithPromiseReturnType and self._legacycaller: + raise WebIDLError("May not have a Promise return type for a " + "legacycaller.", + [overloadWithPromiseReturnType.location]) + + # Now compute various information that will be used by the + # WebIDL overload resolution algorithm. + self.maxArgCount = max(len(s[1]) for s in self.signatures()) + self.allowedArgCounts = [ i for i in range(self.maxArgCount+1) + if len(self.signaturesForArgCount(i)) != 0 ] + + def validate(self): + # Make sure our overloads are properly distinguishable and don't have + # different argument types before the distinguishing args. + for argCount in self.allowedArgCounts: + possibleOverloads = self.overloadsForArgCount(argCount) + if len(possibleOverloads) == 1: + continue + distinguishingIndex = self.distinguishingIndexForArgCount(argCount) + for idx in range(distinguishingIndex): + firstSigType = possibleOverloads[0].arguments[idx].type + for overload in possibleOverloads[1:]: + if overload.arguments[idx].type != firstSigType: + raise WebIDLError( + "Signatures for method '%s' with %d arguments have " + "different types of arguments at index %d, which " + "is before distinguishing index %d" % + (self.identifier.name, argCount, idx, + distinguishingIndex), + [self.location, overload.location]) + + def overloadsForArgCount(self, argc): + return [overload for overload in self._overloads if + len(overload.arguments) == argc or + (len(overload.arguments) > argc and + all(arg.optional for arg in overload.arguments[argc:])) or + (len(overload.arguments) < argc and + len(overload.arguments) > 0 and + overload.arguments[-1].variadic)] + + def signaturesForArgCount(self, argc): + return [(overload.returnType, overload.arguments) for overload + in self.overloadsForArgCount(argc)] + + def locationsForArgCount(self, argc): + return [overload.location for overload in self.overloadsForArgCount(argc)] + + def distinguishingIndexForArgCount(self, argc): + def isValidDistinguishingIndex(idx, signatures): + for (firstSigIndex, (firstRetval, firstArgs)) in enumerate(signatures[:-1]): + for (secondRetval, secondArgs) in signatures[firstSigIndex+1:]: + if idx < len(firstArgs): + firstType = firstArgs[idx].type + else: + assert(firstArgs[-1].variadic) + firstType = firstArgs[-1].type + if idx < len(secondArgs): + secondType = secondArgs[idx].type + else: + assert(secondArgs[-1].variadic) + secondType = secondArgs[-1].type + if not firstType.isDistinguishableFrom(secondType): + return False + return True + signatures = self.signaturesForArgCount(argc) + for idx in range(argc): + if isValidDistinguishingIndex(idx, signatures): + return idx + # No valid distinguishing index. Time to throw + locations = self.locationsForArgCount(argc) + raise WebIDLError("Signatures with %d arguments for method '%s' are not " + "distinguishable" % (argc, self.identifier.name), + locations) + + def handleExtendedAttribute(self, attr): + identifier = attr.identifier() + if identifier == "GetterThrows": + raise WebIDLError("Methods must not be flagged as " + "[GetterThrows]", + [attr.location, self.location]) + elif identifier == "SetterThrows": + raise WebIDLError("Methods must not be flagged as " + "[SetterThrows]", + [attr.location, self.location]) + elif identifier == "Unforgeable": + raise WebIDLError("Methods must not be flagged as " + "[Unforgeable]", + [attr.location, self.location]) + elif identifier == "SameObject": + raise WebIDLError("Methods must not be flagged as [SameObject]", + [attr.location, self.location]); + elif identifier == "Constant": + raise WebIDLError("Methods must not be flagged as [Constant]", + [attr.location, self.location]); + elif identifier == "PutForwards": + raise WebIDLError("Only attributes support [PutForwards]", + [attr.location, self.location]) + elif identifier == "LenientFloat": + # This is called before we've done overload resolution + assert len(self.signatures()) == 1 + sig = self.signatures()[0] + if not sig[0].isVoid(): + raise WebIDLError("[LenientFloat] used on a non-void method", + [attr.location, self.location]) + if not any(arg.type.includesRestrictedFloat() for arg in sig[1]): + raise WebIDLError("[LenientFloat] used on an operation with no " + "restricted float type arguments", + [attr.location, self.location]) + elif (identifier == "Throws" or + identifier == "NewObject" or + identifier == "ChromeOnly" or + identifier == "Pref" or + identifier == "Func" or + identifier == "AvailableIn" or + identifier == "Pure" or + identifier == "CrossOriginCallable" or + identifier == "Ref" or + identifier == "Value" or + identifier == "Operator" or + identifier == "WebGLHandlesContextLoss"): + # Known attributes that we don't need to do anything with here + pass + else: + raise WebIDLError("Unknown extended attribute %s on method" % identifier, + [attr.location]) + IDLInterfaceMember.handleExtendedAttribute(self, attr) + + def returnsPromise(self): + return self._overloads[0].returnType.isPromise() + + def _getDependentObjects(self): + deps = set() + for overload in self._overloads: + deps.union(overload._getDependentObjects()) + return deps + +class IDLImplementsStatement(IDLObject): + def __init__(self, location, implementor, implementee): + IDLObject.__init__(self, location) + self.implementor = implementor; + self.implementee = implementee + + def finish(self, scope): + assert(isinstance(self.implementor, IDLIdentifierPlaceholder)) + assert(isinstance(self.implementee, IDLIdentifierPlaceholder)) + implementor = self.implementor.finish(scope) + implementee = self.implementee.finish(scope) + # NOTE: we depend on not setting self.implementor and + # self.implementee here to keep track of the original + # locations. + if not isinstance(implementor, IDLInterface): + raise WebIDLError("Left-hand side of 'implements' is not an " + "interface", + [self.implementor.location]) + if implementor.isCallback(): + raise WebIDLError("Left-hand side of 'implements' is a callback " + "interface", + [self.implementor.location]) + if not isinstance(implementee, IDLInterface): + raise WebIDLError("Right-hand side of 'implements' is not an " + "interface", + [self.implementee.location]) + if implementee.isCallback(): + raise WebIDLError("Right-hand side of 'implements' is a callback " + "interface", + [self.implementee.location]) + implementor.addImplementedInterface(implementee) + + def validate(self): + pass + + def addExtendedAttributes(self, attrs): + assert len(attrs) == 0 + +class IDLExtendedAttribute(IDLObject): + """ + A class to represent IDL extended attributes so we can give them locations + """ + def __init__(self, location, tuple): + IDLObject.__init__(self, location) + self._tuple = tuple + + def identifier(self): + return self._tuple[0] + + def noArguments(self): + return len(self._tuple) == 1 + + def hasValue(self): + return len(self._tuple) >= 2 and isinstance(self._tuple[1], str) + + def value(self): + assert(self.hasValue()) + return self._tuple[1] + + def hasArgs(self): + return (len(self._tuple) == 2 and isinstance(self._tuple[1], list) or + len(self._tuple) == 3) + + def args(self): + assert(self.hasArgs()) + # Our args are our last element + return self._tuple[-1] + + def listValue(self): + """ + Backdoor for storing random data in _extendedAttrDict + """ + return list(self._tuple)[1:] + +# Parser + +class Tokenizer(object): + tokens = [ + "INTEGER", + "FLOATLITERAL", + "IDENTIFIER", + "STRING", + "WHITESPACE", + "OTHER" + ] + + def t_FLOATLITERAL(self, t): + r'(-?(([0-9]+\.[0-9]*|[0-9]*\.[0-9]+)([Ee][+-]?[0-9]+)?|[0-9]+[Ee][+-]?[0-9]+|Infinity))|NaN' + t.value = float(t.value) + return t + + def t_INTEGER(self, t): + r'-?(0([0-7]+|[Xx][0-9A-Fa-f]+)?|[1-9][0-9]*)' + try: + # Can't use int(), because that doesn't handle octal properly. + t.value = parseInt(t.value) + except: + raise WebIDLError("Invalid integer literal", + [Location(lexer=self.lexer, + lineno=self.lexer.lineno, + lexpos=self.lexer.lexpos, + filename=self._filename)]) + return t + + def t_IDENTIFIER(self, t): + r'[A-Z_a-z][0-9A-Z_a-z]*' + t.type = self.keywords.get(t.value, 'IDENTIFIER') + return t + + def t_STRING(self, t): + r'"[^"]*"' + t.value = t.value[1:-1] + return t + + def t_WHITESPACE(self, t): + r'[\t\n\r ]+|[\t\n\r ]*((//[^\n]*|/\*.*?\*/)[\t\n\r ]*)+' + pass + + def t_ELLIPSIS(self, t): + r'\.\.\.' + t.type = self.keywords.get(t.value) + return t + + def t_OTHER(self, t): + r'[^\t\n\r 0-9A-Z_a-z]' + t.type = self.keywords.get(t.value, 'OTHER') + return t + + keywords = { + "module": "MODULE", + "interface": "INTERFACE", + "partial": "PARTIAL", + "dictionary": "DICTIONARY", + "exception": "EXCEPTION", + "enum": "ENUM", + "callback": "CALLBACK", + "typedef": "TYPEDEF", + "implements": "IMPLEMENTS", + "const": "CONST", + "null": "NULL", + "true": "TRUE", + "false": "FALSE", + "serializer": "SERIALIZER", + "stringifier": "STRINGIFIER", + "jsonifier": "JSONIFIER", + "unrestricted": "UNRESTRICTED", + "attribute": "ATTRIBUTE", + "readonly": "READONLY", + "inherit": "INHERIT", + "static": "STATIC", + "getter": "GETTER", + "setter": "SETTER", + "creator": "CREATOR", + "deleter": "DELETER", + "legacycaller": "LEGACYCALLER", + "optional": "OPTIONAL", + "...": "ELLIPSIS", + "::": "SCOPE", + "Date": "DATE", + "DOMString": "DOMSTRING", + "ByteString": "BYTESTRING", + "any": "ANY", + "boolean": "BOOLEAN", + "byte": "BYTE", + "double": "DOUBLE", + "float": "FLOAT", + "long": "LONG", + "object": "OBJECT", + "octet": "OCTET", + "optional": "OPTIONAL", + "sequence": "SEQUENCE", + "short": "SHORT", + "unsigned": "UNSIGNED", + "void": "VOID", + ":": "COLON", + ";": "SEMICOLON", + "{": "LBRACE", + "}": "RBRACE", + "(": "LPAREN", + ")": "RPAREN", + "[": "LBRACKET", + "]": "RBRACKET", + "?": "QUESTIONMARK", + ",": "COMMA", + "=": "EQUALS", + "<": "LT", + ">": "GT", + "ArrayBuffer": "ARRAYBUFFER", + "or": "OR" + } + + tokens.extend(keywords.values()) + + def t_error(self, t): + raise WebIDLError("Unrecognized Input", + [Location(lexer=self.lexer, + lineno=self.lexer.lineno, + lexpos=self.lexer.lexpos, + filename = self.filename)]) + + def __init__(self, outputdir, lexer=None): + if lexer: + self.lexer = lexer + else: + self.lexer = lex.lex(object=self, + outputdir=outputdir, + lextab='webidllex', + reflags=re.DOTALL) + +class Parser(Tokenizer): + def getLocation(self, p, i): + return Location(self.lexer, p.lineno(i), p.lexpos(i), self._filename) + + def globalScope(self): + return self._globalScope + + # The p_Foo functions here must match the WebIDL spec's grammar. + # It's acceptable to split things at '|' boundaries. + def p_Definitions(self, p): + """ + Definitions : ExtendedAttributeList Definition Definitions + """ + if p[2]: + p[0] = [p[2]] + p[2].addExtendedAttributes(p[1]) + else: + assert not p[1] + p[0] = [] + + p[0].extend(p[3]) + + def p_DefinitionsEmpty(self, p): + """ + Definitions : + """ + p[0] = [] + + def p_Definition(self, p): + """ + Definition : CallbackOrInterface + | PartialInterface + | Dictionary + | Exception + | Enum + | Typedef + | ImplementsStatement + """ + p[0] = p[1] + assert p[1] # We might not have implemented something ... + + def p_CallbackOrInterfaceCallback(self, p): + """ + CallbackOrInterface : CALLBACK CallbackRestOrInterface + """ + if p[2].isInterface(): + assert isinstance(p[2], IDLInterface) + p[2].setCallback(True) + + p[0] = p[2] + + def p_CallbackOrInterfaceInterface(self, p): + """ + CallbackOrInterface : Interface + """ + p[0] = p[1] + + def p_CallbackRestOrInterface(self, p): + """ + CallbackRestOrInterface : CallbackRest + | Interface + """ + assert p[1] + p[0] = p[1] + + def p_Interface(self, p): + """ + Interface : INTERFACE IDENTIFIER Inheritance LBRACE InterfaceMembers RBRACE SEMICOLON + """ + location = self.getLocation(p, 1) + identifier = IDLUnresolvedIdentifier(self.getLocation(p, 2), p[2]) + members = p[5] + parent = p[3] + + try: + if self.globalScope()._lookupIdentifier(identifier): + p[0] = self.globalScope()._lookupIdentifier(identifier) + if not isinstance(p[0], IDLInterface): + raise WebIDLError("Partial interface has the same name as " + "non-interface object", + [location, p[0].location]) + p[0].setNonPartial(location, parent, members) + return + except Exception, ex: + if isinstance(ex, WebIDLError): + raise ex + pass + + p[0] = IDLInterface(location, self.globalScope(), identifier, parent, + members, isPartial=False) + + def p_InterfaceForwardDecl(self, p): + """ + Interface : INTERFACE IDENTIFIER SEMICOLON + """ + location = self.getLocation(p, 1) + identifier = IDLUnresolvedIdentifier(self.getLocation(p, 2), p[2]) + + try: + if self.globalScope()._lookupIdentifier(identifier): + p[0] = self.globalScope()._lookupIdentifier(identifier) + if not isinstance(p[0], IDLExternalInterface): + raise WebIDLError("Name collision between external " + "interface declaration for identifier " + "%s and %s" % (identifier.name, p[0]), + [location, p[0].location]) + return + except Exception, ex: + if isinstance(ex, WebIDLError): + raise ex + pass + + p[0] = IDLExternalInterface(location, self.globalScope(), identifier) + + def p_PartialInterface(self, p): + """ + PartialInterface : PARTIAL INTERFACE IDENTIFIER LBRACE InterfaceMembers RBRACE SEMICOLON + """ + location = self.getLocation(p, 2) + identifier = IDLUnresolvedIdentifier(self.getLocation(p, 3), p[3]) + members = p[5] + + try: + if self.globalScope()._lookupIdentifier(identifier): + p[0] = self.globalScope()._lookupIdentifier(identifier) + if not isinstance(p[0], IDLInterface): + raise WebIDLError("Partial interface has the same name as " + "non-interface object", + [location, p[0].location]) + # Just throw our members into the existing IDLInterface. If we + # have extended attributes, those will get added to it + # automatically. + p[0].members.extend(members) + return + except Exception, ex: + if isinstance(ex, WebIDLError): + raise ex + pass + + p[0] = IDLInterface(location, self.globalScope(), identifier, None, + members, isPartial=True) + pass + + def p_Inheritance(self, p): + """ + Inheritance : COLON ScopedName + """ + p[0] = IDLIdentifierPlaceholder(self.getLocation(p, 2), p[2]) + + def p_InheritanceEmpty(self, p): + """ + Inheritance : + """ + pass + + def p_InterfaceMembers(self, p): + """ + InterfaceMembers : ExtendedAttributeList InterfaceMember InterfaceMembers + """ + p[0] = [p[2]] if p[2] else [] + + assert not p[1] or p[2] + p[2].addExtendedAttributes(p[1]) + + p[0].extend(p[3]) + + def p_InterfaceMembersEmpty(self, p): + """ + InterfaceMembers : + """ + p[0] = [] + + def p_InterfaceMember(self, p): + """ + InterfaceMember : Const + | AttributeOrOperation + """ + p[0] = p[1] + + def p_Dictionary(self, p): + """ + Dictionary : DICTIONARY IDENTIFIER Inheritance LBRACE DictionaryMembers RBRACE SEMICOLON + """ + location = self.getLocation(p, 1) + identifier = IDLUnresolvedIdentifier(self.getLocation(p, 2), p[2]) + members = p[5] + p[0] = IDLDictionary(location, self.globalScope(), identifier, p[3], members) + + def p_DictionaryMembers(self, p): + """ + DictionaryMembers : ExtendedAttributeList DictionaryMember DictionaryMembers + | + """ + if len(p) == 1: + # We're at the end of the list + p[0] = [] + return + # Add our extended attributes + p[2].addExtendedAttributes(p[1]) + p[0] = [p[2]] + p[0].extend(p[3]) + + def p_DictionaryMember(self, p): + """ + DictionaryMember : Type IDENTIFIER DefaultValue SEMICOLON + """ + # These quack a lot like optional arguments, so just treat them that way. + t = p[1] + assert isinstance(t, IDLType) + identifier = IDLUnresolvedIdentifier(self.getLocation(p, 2), p[2]) + defaultValue = p[3] + + p[0] = IDLArgument(self.getLocation(p, 2), identifier, t, optional=True, + defaultValue=defaultValue, variadic=False, + dictionaryMember=True) + + def p_DefaultValue(self, p): + """ + DefaultValue : EQUALS ConstValue + | + """ + if len(p) > 1: + p[0] = p[2] + else: + p[0] = None + + def p_Exception(self, p): + """ + Exception : EXCEPTION IDENTIFIER Inheritance LBRACE ExceptionMembers RBRACE SEMICOLON + """ + pass + + def p_Enum(self, p): + """ + Enum : ENUM IDENTIFIER LBRACE EnumValueList RBRACE SEMICOLON + """ + location = self.getLocation(p, 1) + identifier = IDLUnresolvedIdentifier(self.getLocation(p, 2), p[2]) + + values = p[4] + assert values + p[0] = IDLEnum(location, self.globalScope(), identifier, values) + + def p_EnumValueList(self, p): + """ + EnumValueList : STRING EnumValueListComma + """ + p[0] = [p[1]] + p[0].extend(p[2]) + + def p_EnumValueListComma(self, p): + """ + EnumValueListComma : COMMA EnumValueListString + """ + p[0] = p[2] + + def p_EnumValueListCommaEmpty(self, p): + """ + EnumValueListComma : + """ + p[0] = [] + + def p_EnumValueListString(self, p): + """ + EnumValueListString : STRING EnumValueListComma + """ + p[0] = [p[1]] + p[0].extend(p[2]) + + def p_EnumValueListStringEmpty(self, p): + """ + EnumValueListString : + """ + p[0] = [] + + def p_CallbackRest(self, p): + """ + CallbackRest : IDENTIFIER EQUALS ReturnType LPAREN ArgumentList RPAREN SEMICOLON + """ + identifier = IDLUnresolvedIdentifier(self.getLocation(p, 1), p[1]) + p[0] = IDLCallbackType(self.getLocation(p, 1), self.globalScope(), + identifier, p[3], p[5]) + + def p_ExceptionMembers(self, p): + """ + ExceptionMembers : ExtendedAttributeList ExceptionMember ExceptionMembers + | + """ + pass + + def p_Typedef(self, p): + """ + Typedef : TYPEDEF Type IDENTIFIER SEMICOLON + """ + typedef = IDLTypedefType(self.getLocation(p, 1), p[2], p[3]) + typedef.resolve(self.globalScope()) + p[0] = typedef + + def p_ImplementsStatement(self, p): + """ + ImplementsStatement : ScopedName IMPLEMENTS ScopedName SEMICOLON + """ + assert(p[2] == "implements") + implementor = IDLIdentifierPlaceholder(self.getLocation(p, 1), p[1]) + implementee = IDLIdentifierPlaceholder(self.getLocation(p, 3), p[3]) + p[0] = IDLImplementsStatement(self.getLocation(p, 1), implementor, + implementee) + + def p_Const(self, p): + """ + Const : CONST ConstType IDENTIFIER EQUALS ConstValue SEMICOLON + """ + location = self.getLocation(p, 1) + type = p[2] + identifier = IDLUnresolvedIdentifier(self.getLocation(p, 3), p[3]) + value = p[5] + p[0] = IDLConst(location, identifier, type, value) + + def p_ConstValueBoolean(self, p): + """ + ConstValue : BooleanLiteral + """ + location = self.getLocation(p, 1) + booleanType = BuiltinTypes[IDLBuiltinType.Types.boolean] + p[0] = IDLValue(location, booleanType, p[1]) + + def p_ConstValueInteger(self, p): + """ + ConstValue : INTEGER + """ + location = self.getLocation(p, 1) + + # We don't know ahead of time what type the integer literal is. + # Determine the smallest type it could possibly fit in and use that. + integerType = matchIntegerValueToType(p[1]) + if integerType == None: + raise WebIDLError("Integer literal out of range", [location]) + + p[0] = IDLValue(location, integerType, p[1]) + + def p_ConstValueFloat(self, p): + """ + ConstValue : FLOATLITERAL + """ + location = self.getLocation(p, 1) + p[0] = IDLValue(location, BuiltinTypes[IDLBuiltinType.Types.unrestricted_float], p[1]) + + def p_ConstValueString(self, p): + """ + ConstValue : STRING + """ + location = self.getLocation(p, 1) + stringType = BuiltinTypes[IDLBuiltinType.Types.domstring] + p[0] = IDLValue(location, stringType, p[1]) + + def p_ConstValueNull(self, p): + """ + ConstValue : NULL + """ + p[0] = IDLNullValue(self.getLocation(p, 1)) + + def p_BooleanLiteralTrue(self, p): + """ + BooleanLiteral : TRUE + """ + p[0] = True + + def p_BooleanLiteralFalse(self, p): + """ + BooleanLiteral : FALSE + """ + p[0] = False + + def p_AttributeOrOperation(self, p): + """ + AttributeOrOperation : Attribute + | Operation + """ + p[0] = p[1] + + def p_AttributeWithQualifier(self, p): + """ + Attribute : Qualifier AttributeRest + """ + static = IDLInterfaceMember.Special.Static in p[1] + stringifier = IDLInterfaceMember.Special.Stringifier in p[1] + (location, identifier, type, readonly) = p[2] + p[0] = IDLAttribute(location, identifier, type, readonly, static=static, + stringifier=stringifier) + + def p_Attribute(self, p): + """ + Attribute : Inherit AttributeRest + """ + (location, identifier, type, readonly) = p[2] + p[0] = IDLAttribute(location, identifier, type, readonly, inherit=p[1]) + + def p_AttributeRest(self, p): + """ + AttributeRest : ReadOnly ATTRIBUTE Type IDENTIFIER SEMICOLON + """ + location = self.getLocation(p, 2) + readonly = p[1] + t = p[3] + identifier = IDLUnresolvedIdentifier(self.getLocation(p, 4), p[4]) + p[0] = (location, identifier, t, readonly) + + def p_ReadOnly(self, p): + """ + ReadOnly : READONLY + """ + p[0] = True + + def p_ReadOnlyEmpty(self, p): + """ + ReadOnly : + """ + p[0] = False + + def p_Inherit(self, p): + """ + Inherit : INHERIT + """ + p[0] = True + + def p_InheritEmpty(self, p): + """ + Inherit : + """ + p[0] = False + + def p_Operation(self, p): + """ + Operation : Qualifiers OperationRest + """ + qualifiers = p[1] + + # Disallow duplicates in the qualifier set + if not len(set(qualifiers)) == len(qualifiers): + raise WebIDLError("Duplicate qualifiers are not allowed", + [self.getLocation(p, 1)]) + + static = IDLInterfaceMember.Special.Static in p[1] + # If static is there that's all that's allowed. This is disallowed + # by the parser, so we can assert here. + assert not static or len(qualifiers) == 1 + + stringifier = IDLInterfaceMember.Special.Stringifier in p[1] + # If stringifier is there that's all that's allowed. This is disallowed + # by the parser, so we can assert here. + assert not stringifier or len(qualifiers) == 1 + + getter = True if IDLMethod.Special.Getter in p[1] else False + setter = True if IDLMethod.Special.Setter in p[1] else False + creator = True if IDLMethod.Special.Creator in p[1] else False + deleter = True if IDLMethod.Special.Deleter in p[1] else False + legacycaller = True if IDLMethod.Special.LegacyCaller in p[1] else False + + if getter or deleter: + if setter or creator: + raise WebIDLError("getter and deleter are incompatible with setter and creator", + [self.getLocation(p, 1)]) + + (returnType, identifier, arguments) = p[2] + + assert isinstance(returnType, IDLType) + + specialType = IDLMethod.NamedOrIndexed.Neither + + if getter or deleter: + if len(arguments) != 1: + raise WebIDLError("%s has wrong number of arguments" % + ("getter" if getter else "deleter"), + [self.getLocation(p, 2)]) + argType = arguments[0].type + if argType == BuiltinTypes[IDLBuiltinType.Types.domstring]: + specialType = IDLMethod.NamedOrIndexed.Named + elif argType == BuiltinTypes[IDLBuiltinType.Types.unsigned_long]: + specialType = IDLMethod.NamedOrIndexed.Indexed + else: + raise WebIDLError("%s has wrong argument type (must be DOMString or UnsignedLong)" % + ("getter" if getter else "deleter"), + [arguments[0].location]) + if arguments[0].optional or arguments[0].variadic: + raise WebIDLError("%s cannot have %s argument" % + ("getter" if getter else "deleter", + "optional" if arguments[0].optional else "variadic"), + [arguments[0].location]) + if getter: + if returnType.isVoid(): + raise WebIDLError("getter cannot have void return type", + [self.getLocation(p, 2)]) + if setter or creator: + if len(arguments) != 2: + raise WebIDLError("%s has wrong number of arguments" % + ("setter" if setter else "creator"), + [self.getLocation(p, 2)]) + argType = arguments[0].type + if argType == BuiltinTypes[IDLBuiltinType.Types.domstring]: + specialType = IDLMethod.NamedOrIndexed.Named + elif argType == BuiltinTypes[IDLBuiltinType.Types.unsigned_long]: + specialType = IDLMethod.NamedOrIndexed.Indexed + else: + raise WebIDLError("%s has wrong argument type (must be DOMString or UnsignedLong)" % + ("setter" if setter else "creator"), + [arguments[0].location]) + if arguments[0].optional or arguments[0].variadic: + raise WebIDLError("%s cannot have %s argument" % + ("setter" if setter else "creator", + "optional" if arguments[0].optional else "variadic"), + [arguments[0].location]) + if arguments[1].optional or arguments[1].variadic: + raise WebIDLError("%s cannot have %s argument" % + ("setter" if setter else "creator", + "optional" if arguments[1].optional else "variadic"), + [arguments[1].location]) + + if stringifier: + if len(arguments) != 0: + raise WebIDLError("stringifier has wrong number of arguments", + [self.getLocation(p, 2)]) + if not returnType.isDOMString(): + raise WebIDLError("stringifier must have DOMString return type", + [self.getLocation(p, 2)]) + + # identifier might be None. This is only permitted for special methods. + if not identifier: + if not getter and not setter and not creator and \ + not deleter and not legacycaller and not stringifier: + raise WebIDLError("Identifier required for non-special methods", + [self.getLocation(p, 2)]) + + location = BuiltinLocation("<auto-generated-identifier>") + identifier = IDLUnresolvedIdentifier(location, "__%s%s%s%s%s%s%s" % + ("named" if specialType == IDLMethod.NamedOrIndexed.Named else \ + "indexed" if specialType == IDLMethod.NamedOrIndexed.Indexed else "", + "getter" if getter else "", + "setter" if setter else "", + "deleter" if deleter else "", + "creator" if creator else "", + "legacycaller" if legacycaller else "", + "stringifier" if stringifier else ""), allowDoubleUnderscore=True) + + method = IDLMethod(self.getLocation(p, 2), identifier, returnType, arguments, + static=static, getter=getter, setter=setter, creator=creator, + deleter=deleter, specialType=specialType, + legacycaller=legacycaller, stringifier=stringifier) + p[0] = method + + def p_Stringifier(self, p): + """ + Operation : STRINGIFIER SEMICOLON + """ + identifier = IDLUnresolvedIdentifier(BuiltinLocation("<auto-generated-identifier>"), + "__stringifier", + allowDoubleUnderscore=True) + method = IDLMethod(self.getLocation(p, 1), + identifier, + returnType=BuiltinTypes[IDLBuiltinType.Types.domstring], + arguments=[], + stringifier=True) + p[0] = method + + def p_Jsonifier(self, p): + """ + Operation : JSONIFIER SEMICOLON + """ + identifier = IDLUnresolvedIdentifier(BuiltinLocation("<auto-generated-identifier>"), + "__jsonifier", allowDoubleUnderscore=True) + method = IDLMethod(self.getLocation(p, 1), + identifier, + returnType=BuiltinTypes[IDLBuiltinType.Types.object], + arguments=[], + jsonifier=True) + p[0] = method + + def p_QualifierStatic(self, p): + """ + Qualifier : STATIC + """ + p[0] = [IDLInterfaceMember.Special.Static] + + def p_QualifierStringifier(self, p): + """ + Qualifier : STRINGIFIER + """ + p[0] = [IDLInterfaceMember.Special.Stringifier] + + def p_Qualifiers(self, p): + """ + Qualifiers : Qualifier + | Specials + """ + p[0] = p[1] + + def p_Specials(self, p): + """ + Specials : Special Specials + """ + p[0] = [p[1]] + p[0].extend(p[2]) + + def p_SpecialsEmpty(self, p): + """ + Specials : + """ + p[0] = [] + + def p_SpecialGetter(self, p): + """ + Special : GETTER + """ + p[0] = IDLMethod.Special.Getter + + def p_SpecialSetter(self, p): + """ + Special : SETTER + """ + p[0] = IDLMethod.Special.Setter + + def p_SpecialCreator(self, p): + """ + Special : CREATOR + """ + p[0] = IDLMethod.Special.Creator + + def p_SpecialDeleter(self, p): + """ + Special : DELETER + """ + p[0] = IDLMethod.Special.Deleter + + def p_SpecialLegacyCaller(self, p): + """ + Special : LEGACYCALLER + """ + p[0] = IDLMethod.Special.LegacyCaller + + def p_OperationRest(self, p): + """ + OperationRest : ReturnType OptionalIdentifier LPAREN ArgumentList RPAREN SEMICOLON + """ + p[0] = (p[1], p[2], p[4]) + + def p_OptionalIdentifier(self, p): + """ + OptionalIdentifier : IDENTIFIER + """ + p[0] = IDLUnresolvedIdentifier(self.getLocation(p, 1), p[1]) + + def p_OptionalIdentifierEmpty(self, p): + """ + OptionalIdentifier : + """ + pass + + def p_ArgumentList(self, p): + """ + ArgumentList : Argument Arguments + """ + p[0] = [p[1]] if p[1] else [] + p[0].extend(p[2]) + + def p_ArgumentListEmpty(self, p): + """ + ArgumentList : + """ + p[0] = [] + + def p_Arguments(self, p): + """ + Arguments : COMMA Argument Arguments + """ + p[0] = [p[2]] if p[2] else [] + p[0].extend(p[3]) + + def p_ArgumentsEmpty(self, p): + """ + Arguments : + """ + p[0] = [] + + def p_Argument(self, p): + """ + Argument : ExtendedAttributeList Optional Type Ellipsis ArgumentName DefaultValue + """ + t = p[3] + assert isinstance(t, IDLType) + identifier = IDLUnresolvedIdentifier(self.getLocation(p, 5), p[5]) + + optional = p[2] + variadic = p[4] + defaultValue = p[6] + + if not optional and defaultValue: + raise WebIDLError("Mandatory arguments can't have a default value.", + [self.getLocation(p, 6)]) + + # We can't test t.isAny() here and give it a default value as needed, + # since at this point t is not a fully resolved type yet (e.g. it might + # be a typedef). We'll handle the 'any' case in IDLArgument.complete. + + if variadic: + if optional: + raise WebIDLError("Variadic arguments should not be marked optional.", + [self.getLocation(p, 2)]) + optional = variadic + + p[0] = IDLArgument(self.getLocation(p, 5), identifier, t, optional, defaultValue, variadic) + p[0].addExtendedAttributes(p[1]) + + def p_ArgumentName(self, p): + """ + ArgumentName : IDENTIFIER + | ATTRIBUTE + | CALLBACK + | CONST + | CREATOR + | DELETER + | DICTIONARY + | ENUM + | EXCEPTION + | GETTER + | IMPLEMENTS + | INHERIT + | INTERFACE + | LEGACYCALLER + | PARTIAL + | SERIALIZER + | SETTER + | STATIC + | STRINGIFIER + | JSONIFIER + | TYPEDEF + | UNRESTRICTED + """ + p[0] = p[1] + + def p_Optional(self, p): + """ + Optional : OPTIONAL + """ + p[0] = True + + def p_OptionalEmpty(self, p): + """ + Optional : + """ + p[0] = False + + def p_Ellipsis(self, p): + """ + Ellipsis : ELLIPSIS + """ + p[0] = True + + def p_EllipsisEmpty(self, p): + """ + Ellipsis : + """ + p[0] = False + + def p_ExceptionMember(self, p): + """ + ExceptionMember : Const + | ExceptionField + """ + pass + + def p_ExceptionField(self, p): + """ + ExceptionField : Type IDENTIFIER SEMICOLON + """ + pass + + def p_ExtendedAttributeList(self, p): + """ + ExtendedAttributeList : LBRACKET ExtendedAttribute ExtendedAttributes RBRACKET + """ + p[0] = [p[2]] + if p[3]: + p[0].extend(p[3]) + + def p_ExtendedAttributeListEmpty(self, p): + """ + ExtendedAttributeList : + """ + p[0] = [] + + def p_ExtendedAttribute(self, p): + """ + ExtendedAttribute : ExtendedAttributeNoArgs + | ExtendedAttributeArgList + | ExtendedAttributeIdent + | ExtendedAttributeNamedArgList + """ + p[0] = IDLExtendedAttribute(self.getLocation(p, 1), p[1]) + + def p_ExtendedAttributeEmpty(self, p): + """ + ExtendedAttribute : + """ + pass + + def p_ExtendedAttributes(self, p): + """ + ExtendedAttributes : COMMA ExtendedAttribute ExtendedAttributes + """ + p[0] = [p[2]] if p[2] else [] + p[0].extend(p[3]) + + def p_ExtendedAttributesEmpty(self, p): + """ + ExtendedAttributes : + """ + p[0] = [] + + def p_Other(self, p): + """ + Other : INTEGER + | FLOATLITERAL + | IDENTIFIER + | STRING + | OTHER + | ELLIPSIS + | COLON + | SCOPE + | SEMICOLON + | LT + | EQUALS + | GT + | QUESTIONMARK + | DATE + | DOMSTRING + | BYTESTRING + | ANY + | ATTRIBUTE + | BOOLEAN + | BYTE + | LEGACYCALLER + | CONST + | CREATOR + | DELETER + | DOUBLE + | EXCEPTION + | FALSE + | FLOAT + | GETTER + | IMPLEMENTS + | INHERIT + | INTERFACE + | LONG + | MODULE + | NULL + | OBJECT + | OCTET + | OPTIONAL + | SEQUENCE + | SETTER + | SHORT + | STATIC + | STRINGIFIER + | JSONIFIER + | TRUE + | TYPEDEF + | UNSIGNED + | VOID + """ + pass + + def p_OtherOrComma(self, p): + """ + OtherOrComma : Other + | COMMA + """ + pass + + def p_TypeSingleType(self, p): + """ + Type : SingleType + """ + p[0] = p[1] + + def p_TypeUnionType(self, p): + """ + Type : UnionType TypeSuffix + """ + p[0] = self.handleModifiers(p[1], p[2]) + + def p_SingleTypeNonAnyType(self, p): + """ + SingleType : NonAnyType + """ + p[0] = p[1] + + def p_SingleTypeAnyType(self, p): + """ + SingleType : ANY TypeSuffixStartingWithArray + """ + p[0] = self.handleModifiers(BuiltinTypes[IDLBuiltinType.Types.any], p[2]) + + def p_UnionType(self, p): + """ + UnionType : LPAREN UnionMemberType OR UnionMemberType UnionMemberTypes RPAREN + """ + types = [p[2], p[4]] + types.extend(p[5]) + p[0] = IDLUnionType(self.getLocation(p, 1), types) + + def p_UnionMemberTypeNonAnyType(self, p): + """ + UnionMemberType : NonAnyType + """ + p[0] = p[1] + + def p_UnionMemberTypeArrayOfAny(self, p): + """ + UnionMemberTypeArrayOfAny : ANY LBRACKET RBRACKET + """ + p[0] = IDLArrayType(self.getLocation(p, 2), + BuiltinTypes[IDLBuiltinType.Types.any]) + + def p_UnionMemberType(self, p): + """ + UnionMemberType : UnionType TypeSuffix + | UnionMemberTypeArrayOfAny TypeSuffix + """ + p[0] = self.handleModifiers(p[1], p[2]) + + def p_UnionMemberTypes(self, p): + """ + UnionMemberTypes : OR UnionMemberType UnionMemberTypes + """ + p[0] = [p[2]] + p[0].extend(p[3]) + + def p_UnionMemberTypesEmpty(self, p): + """ + UnionMemberTypes : + """ + p[0] = [] + + def p_NonAnyType(self, p): + """ + NonAnyType : PrimitiveOrStringType TypeSuffix + | ARRAYBUFFER TypeSuffix + | OBJECT TypeSuffix + """ + if p[1] == "object": + type = BuiltinTypes[IDLBuiltinType.Types.object] + elif p[1] == "ArrayBuffer": + type = BuiltinTypes[IDLBuiltinType.Types.ArrayBuffer] + else: + type = BuiltinTypes[p[1]] + + p[0] = self.handleModifiers(type, p[2]) + + def p_NonAnyTypeSequenceType(self, p): + """ + NonAnyType : SEQUENCE LT Type GT Null + """ + innerType = p[3] + type = IDLSequenceType(self.getLocation(p, 1), innerType) + if p[5]: + type = IDLNullableType(self.getLocation(p, 5), type) + p[0] = type + + def p_NonAnyTypeScopedName(self, p): + """ + NonAnyType : ScopedName TypeSuffix + """ + assert isinstance(p[1], IDLUnresolvedIdentifier) + + type = None + + try: + if self.globalScope()._lookupIdentifier(p[1]): + obj = self.globalScope()._lookupIdentifier(p[1]) + if obj.isType(): + type = obj + else: + type = IDLWrapperType(self.getLocation(p, 1), p[1]) + p[0] = self.handleModifiers(type, p[2]) + return + except: + pass + + type = IDLUnresolvedType(self.getLocation(p, 1), p[1]) + p[0] = self.handleModifiers(type, p[2]) + + def p_NonAnyTypeDate(self, p): + """ + NonAnyType : DATE TypeSuffix + """ + p[0] = self.handleModifiers(BuiltinTypes[IDLBuiltinType.Types.date], + p[2]) + + def p_ConstType(self, p): + """ + ConstType : PrimitiveOrStringType Null + """ + type = BuiltinTypes[p[1]] + if p[2]: + type = IDLNullableType(self.getLocation(p, 1), type) + p[0] = type + + def p_ConstTypeIdentifier(self, p): + """ + ConstType : IDENTIFIER Null + """ + identifier = IDLUnresolvedIdentifier(self.getLocation(p, 1), p[1]) + + type = IDLUnresolvedType(self.getLocation(p, 1), identifier) + if p[2]: + type = IDLNullableType(self.getLocation(p, 1), type) + p[0] = type + + def p_PrimitiveOrStringTypeUint(self, p): + """ + PrimitiveOrStringType : UnsignedIntegerType + """ + p[0] = p[1] + + def p_PrimitiveOrStringTypeBoolean(self, p): + """ + PrimitiveOrStringType : BOOLEAN + """ + p[0] = IDLBuiltinType.Types.boolean + + def p_PrimitiveOrStringTypeByte(self, p): + """ + PrimitiveOrStringType : BYTE + """ + p[0] = IDLBuiltinType.Types.byte + + def p_PrimitiveOrStringTypeOctet(self, p): + """ + PrimitiveOrStringType : OCTET + """ + p[0] = IDLBuiltinType.Types.octet + + def p_PrimitiveOrStringTypeFloat(self, p): + """ + PrimitiveOrStringType : FLOAT + """ + p[0] = IDLBuiltinType.Types.float + + def p_PrimitiveOrStringTypeUnrestictedFloat(self, p): + """ + PrimitiveOrStringType : UNRESTRICTED FLOAT + """ + p[0] = IDLBuiltinType.Types.unrestricted_float + + def p_PrimitiveOrStringTypeDouble(self, p): + """ + PrimitiveOrStringType : DOUBLE + """ + p[0] = IDLBuiltinType.Types.double + + def p_PrimitiveOrStringTypeUnrestictedDouble(self, p): + """ + PrimitiveOrStringType : UNRESTRICTED DOUBLE + """ + p[0] = IDLBuiltinType.Types.unrestricted_double + + def p_PrimitiveOrStringTypeDOMString(self, p): + """ + PrimitiveOrStringType : DOMSTRING + """ + p[0] = IDLBuiltinType.Types.domstring + + def p_PrimitiveOrStringTypeBytestring(self, p): + """ + PrimitiveOrStringType : BYTESTRING + """ + p[0] = IDLBuiltinType.Types.bytestring + + def p_UnsignedIntegerTypeUnsigned(self, p): + """ + UnsignedIntegerType : UNSIGNED IntegerType + """ + p[0] = p[2] + 1 # Adding one to a given signed integer type + # gets you the unsigned type. + + def p_UnsignedIntegerType(self, p): + """ + UnsignedIntegerType : IntegerType + """ + p[0] = p[1] + + def p_IntegerTypeShort(self, p): + """ + IntegerType : SHORT + """ + p[0] = IDLBuiltinType.Types.short + + def p_IntegerTypeLong(self, p): + """ + IntegerType : LONG OptionalLong + """ + if p[2]: + p[0] = IDLBuiltinType.Types.long_long + else: + p[0] = IDLBuiltinType.Types.long + + def p_OptionalLong(self, p): + """ + OptionalLong : LONG + """ + p[0] = True + + def p_OptionalLongEmpty(self, p): + """ + OptionalLong : + """ + p[0] = False + + def p_TypeSuffixBrackets(self, p): + """ + TypeSuffix : LBRACKET RBRACKET TypeSuffix + """ + p[0] = [(IDLMethod.TypeSuffixModifier.Brackets, self.getLocation(p, 1))] + p[0].extend(p[3]) + + def p_TypeSuffixQMark(self, p): + """ + TypeSuffix : QUESTIONMARK TypeSuffixStartingWithArray + """ + p[0] = [(IDLMethod.TypeSuffixModifier.QMark, self.getLocation(p, 1))] + p[0].extend(p[2]) + + def p_TypeSuffixEmpty(self, p): + """ + TypeSuffix : + """ + p[0] = [] + + def p_TypeSuffixStartingWithArray(self, p): + """ + TypeSuffixStartingWithArray : LBRACKET RBRACKET TypeSuffix + """ + p[0] = [(IDLMethod.TypeSuffixModifier.Brackets, self.getLocation(p, 1))] + p[0].extend(p[3]) + + def p_TypeSuffixStartingWithArrayEmpty(self, p): + """ + TypeSuffixStartingWithArray : + """ + p[0] = [] + + def p_Null(self, p): + """ + Null : QUESTIONMARK + | + """ + if len(p) > 1: + p[0] = True + else: + p[0] = False + + def p_ReturnTypeType(self, p): + """ + ReturnType : Type + """ + p[0] = p[1] + + def p_ReturnTypeVoid(self, p): + """ + ReturnType : VOID + """ + p[0] = BuiltinTypes[IDLBuiltinType.Types.void] + + def p_ScopedName(self, p): + """ + ScopedName : AbsoluteScopedName + | RelativeScopedName + """ + p[0] = p[1] + + def p_AbsoluteScopedName(self, p): + """ + AbsoluteScopedName : SCOPE IDENTIFIER ScopedNameParts + """ + assert False + pass + + def p_RelativeScopedName(self, p): + """ + RelativeScopedName : IDENTIFIER ScopedNameParts + """ + assert not p[2] # Not implemented! + + p[0] = IDLUnresolvedIdentifier(self.getLocation(p, 1), p[1]) + + def p_ScopedNameParts(self, p): + """ + ScopedNameParts : SCOPE IDENTIFIER ScopedNameParts + """ + assert False + pass + + def p_ScopedNamePartsEmpty(self, p): + """ + ScopedNameParts : + """ + p[0] = None + + def p_ExtendedAttributeNoArgs(self, p): + """ + ExtendedAttributeNoArgs : IDENTIFIER + """ + p[0] = (p[1],) + + def p_ExtendedAttributeArgList(self, p): + """ + ExtendedAttributeArgList : IDENTIFIER LPAREN ArgumentList RPAREN + """ + p[0] = (p[1], p[3]) + + def p_ExtendedAttributeIdent(self, p): + """ + ExtendedAttributeIdent : IDENTIFIER EQUALS STRING + | IDENTIFIER EQUALS IDENTIFIER + """ + p[0] = (p[1], p[3]) + + def p_ExtendedAttributeNamedArgList(self, p): + """ + ExtendedAttributeNamedArgList : IDENTIFIER EQUALS IDENTIFIER LPAREN ArgumentList RPAREN + """ + p[0] = (p[1], p[3], p[5]) + + def p_error(self, p): + if not p: + raise WebIDLError("Syntax Error at end of file. Possibly due to missing semicolon(;), braces(}) or both", + [self._filename]) + else: + raise WebIDLError("invalid syntax", [Location(self.lexer, p.lineno, p.lexpos, self._filename)]) + + def __init__(self, outputdir='', lexer=None): + Tokenizer.__init__(self, outputdir, lexer) + self.parser = yacc.yacc(module=self, + outputdir=outputdir, + tabmodule='webidlyacc', + errorlog=yacc.NullLogger(), + picklefile='WebIDLGrammar.pkl') + self._globalScope = IDLScope(BuiltinLocation("<Global Scope>"), None, None) + self._installBuiltins(self._globalScope) + self._productions = [] + + self._filename = "<builtin>" + self.lexer.input(Parser._builtins) + self._filename = None + + self.parser.parse(lexer=self.lexer,tracking=True) + + def _installBuiltins(self, scope): + assert isinstance(scope, IDLScope) + + # xrange omits the last value. + for x in xrange(IDLBuiltinType.Types.ArrayBuffer, IDLBuiltinType.Types.Float64Array + 1): + builtin = BuiltinTypes[x] + name = builtin.name + + typedef = IDLTypedefType(BuiltinLocation("<builtin type>"), builtin, name) + typedef.resolve(scope) + + @ staticmethod + def handleModifiers(type, modifiers): + for (modifier, modifierLocation) in modifiers: + assert modifier == IDLMethod.TypeSuffixModifier.QMark or \ + modifier == IDLMethod.TypeSuffixModifier.Brackets + + if modifier == IDLMethod.TypeSuffixModifier.QMark: + type = IDLNullableType(modifierLocation, type) + elif modifier == IDLMethod.TypeSuffixModifier.Brackets: + type = IDLArrayType(modifierLocation, type) + + return type + + def parse(self, t, filename=None): + self.lexer.input(t) + + #for tok in iter(self.lexer.token, None): + # print tok + + self._filename = filename + self._productions.extend(self.parser.parse(lexer=self.lexer,tracking=True)) + self._filename = None + + def finish(self): + # First, finish all the IDLImplementsStatements. In particular, we + # have to make sure we do those before we do the IDLInterfaces. + # XXX khuey hates this bit and wants to nuke it from orbit. + implementsStatements = [ p for p in self._productions if + isinstance(p, IDLImplementsStatement)] + otherStatements = [ p for p in self._productions if + not isinstance(p, IDLImplementsStatement)] + for production in implementsStatements: + production.finish(self.globalScope()) + for production in otherStatements: + production.finish(self.globalScope()) + + # Do any post-finish validation we need to do + for production in self._productions: + production.validate() + + # De-duplicate self._productions, without modifying its order. + seen = set() + result = [] + for p in self._productions: + if p not in seen: + seen.add(p) + result.append(p) + return result + + def reset(self): + return Parser(lexer=self.lexer) + + # Builtin IDL defined by WebIDL + _builtins = """ + typedef unsigned long long DOMTimeStamp; + """ + +def main(): + # Parse arguments. + from optparse import OptionParser + usageString = "usage: %prog [options] files" + o = OptionParser(usage=usageString) + o.add_option("--cachedir", dest='cachedir', default=None, + help="Directory in which to cache lex/parse tables.") + o.add_option("--verbose-errors", action='store_true', default=False, + help="When an error happens, display the Python traceback.") + (options, args) = o.parse_args() + + if len(args) < 1: + o.error(usageString) + + fileList = args + baseDir = os.getcwd() + + # Parse the WebIDL. + parser = Parser(options.cachedir) + try: + for filename in fileList: + fullPath = os.path.normpath(os.path.join(baseDir, filename)) + f = open(fullPath, 'rb') + lines = f.readlines() + f.close() + print fullPath + parser.parse(''.join(lines), fullPath) + parser.finish() + except WebIDLError, e: + if options.verbose_errors: + traceback.print_exc() + else: + print e + +if __name__ == '__main__': + main() + diff --git a/third_party/__init__.py b/third_party/__init__.py new file mode 100644 index 00000000..8fa2136f --- /dev/null +++ b/third_party/__init__.py @@ -0,0 +1,2 @@ +# + diff --git a/tools/bindings_generator.py b/tools/bindings_generator.py index 5bf0996e..9bc8b929 100755 --- a/tools/bindings_generator.py +++ b/tools/bindings_generator.py @@ -1,6 +1,61 @@ #!/usr/bin/env python2 ''' + + + + + + + + + + + + + + + + + + + + + + + + +XXX THIS IS DEPRECATED, see webidl_binder.py XXX + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Use CppHeaderParser to parse some C++ headers, and generate binding code for them. Usage: diff --git a/tools/eliminator/asm-eliminator-test-output.js b/tools/eliminator/asm-eliminator-test-output.js index 9caf99d0..1a5dca55 100644 --- a/tools/eliminator/asm-eliminator-test-output.js +++ b/tools/eliminator/asm-eliminator-test-output.js @@ -147,27 +147,25 @@ function looop3() { } } function looop4() { - var i = 0, helper = 0; + var i = 0, i$looptemp = 0; while (1) { do_it(); - helper = i + 1 | 0; - f(i, helper); - if (condition()) { - i = helper; - } else { + i$looptemp = i; + i = i + 1 | 0; + f(i$looptemp, i); + if (!condition()) { break; } } } function looop4b() { - var i = 0, helper = 0; + var i = 0, i$looptemp = 0; while (1) { do_it(); - helper = i + 1 | 0; - g(helper); - if (condition(i)) { - i = helper; - } else { + i$looptemp = i; + i = i + 1 | 0; + g(i); + if (!condition(i$looptemp)) { break; } } @@ -251,24 +249,22 @@ function multiloop($n_0, $35) { function multiloop2($n_0, $35) { $n_0 = $n_0 | 0; $35 = $35 | 0; - var $p_0 = 0, $39 = 0, $41 = 0, $46 = 0; + var $p_0 = 0, $41 = 0, $p_0$looptemp = 0; $n_0 = $35; $p_0 = (HEAP32[$15 >> 2] | 0) + ($35 << 1) | 0; while (1) { - $39 = $p_0 - 2 | 0; - $41 = HEAPU16[$39 >> 1] | 0; + $p_0$looptemp = $p_0; + $p_0 = $p_0 - 2 | 0; + $41 = HEAPU16[$p_0 >> 1] | 0; if ($41 >>> 0 < $2 >>> 0) { $_off0 = 0; } else { $_off0 = $41 - $2 & 65535; } - HEAP16[$39 >> 1] = $p_0; - $46 = $n_0 - 1 | 0; - if (($46 | 0) == 0) { + HEAP16[$p_0 >> 1] = $p_0$looptemp; + $n_0 = $n_0 - 1 | 0; + if (($n_0 | 0) == 0) { break; - } else { - $n_0 = $46; - $p_0 = $39; } } } @@ -901,4 +897,18 @@ function elimOneLoopVar4() { } } } +function elimOneLoopVarStillUsed() { + var $call10 = Math_fround(0), $curri$012 = 0, $j$010 = 0, $retval$0 = 0, $j$010$looptemp = 0; + while (1) { + $j$010$looptemp = $j$010; + $j$010 = $j$010 + 1 | 0; + if ((($curri$012 | 0) % ($j$010$looptemp | 0) & -1 | 0) == 0) { + break; + } + if (!(Math_fround($j$010 | 0) < $call10)) { + break; + } + } + return $retval$0 | 0; +} diff --git a/tools/eliminator/asm-eliminator-test.js b/tools/eliminator/asm-eliminator-test.js index a3de3d9d..d5bbd8d5 100644 --- a/tools/eliminator/asm-eliminator-test.js +++ b/tools/eliminator/asm-eliminator-test.js @@ -1131,5 +1131,26 @@ function elimOneLoopVar4() { } } } -// EMSCRIPTEN_GENERATED_FUNCTIONS: ["asm", "__Z11printResultPiS_j", "_segment_holding", "__ZN5identC2EiPKcPci", "_vec2Length", "exc", "label", "confuusion", "tempDouble", "_org_apache_harmony_luni_util_NumberConverter_freeFormat__", "__ZN23b2EdgeAndPolygonContact8EvaluateEP10b2ManifoldRK11b2TransformS4_", "_java_nio_charset_Charset_forNameInternal___java_lang_String", "looop2", "looop3", "looop4", "looop5", "looop6", "looop7", "looop8", "multiloop", "multiloop2", "tempDouble2", "watIf", "select2", "binary", "cute", "selfAssign", "elimOneLoopVar", "elimOneLoopVar2", "elimOneLoopVar3", "elimOneLoopVar4"] +function elimOneLoopVarStillUsed() { + var $0 = 0, $1 = 0, $arg$0 = 0, $arrayidx = 0, $call10 = Math_fround(0), $cmp = 0, $cmp11 = 0, $cmp119 = 0, $cmp12 = 0, $cmp7 = 0, $conv = 0, $conv8 = Math_fround(0), $conv9 = Math_fround(0), $curri$012 = 0, $inc = 0, $inc14$primes$0 = 0, $inc16 = 0, $j$010 = 0, $ok$0 = 0; + var $primes$011 = 0, $rem = 0, $retval$0 = 0, $sub = 0, $vararg_buffer1 = 0, label = 0, sp = 0; + while (1) { + $rem = ($curri$012 | 0) % ($j$010 | 0) & -1; + $cmp12 = ($rem | 0) == 0; + $inc = $j$010 + 1 | 0; + if ($cmp12) { + $ok$0 = 0; + break; + } + $conv8 = Math_fround($inc | 0); + $cmp11 = $conv8 < $call10; + if ($cmp11) { + $j$010 = $inc; + } else { + break; + } + } + return $retval$0 | 0; +} +// EMSCRIPTEN_GENERATED_FUNCTIONS: ["asm", "__Z11printResultPiS_j", "_segment_holding", "__ZN5identC2EiPKcPci", "_vec2Length", "exc", "label", "confuusion", "tempDouble", "_org_apache_harmony_luni_util_NumberConverter_freeFormat__", "__ZN23b2EdgeAndPolygonContact8EvaluateEP10b2ManifoldRK11b2TransformS4_", "_java_nio_charset_Charset_forNameInternal___java_lang_String", "looop2", "looop3", "looop4", "looop5", "looop6", "looop7", "looop8", "multiloop", "multiloop2", "tempDouble2", "watIf", "select2", "binary", "cute", "selfAssign", "elimOneLoopVar", "elimOneLoopVar2", "elimOneLoopVar3", "elimOneLoopVar4", "elimOneLoopVarStillUsed"] diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js index c4585b84..db85965d 100644 --- a/tools/js-optimizer.js +++ b/tools/js-optimizer.js @@ -3519,12 +3519,15 @@ function eliminate(ast, memSafe) { seenUses[name]++; } } else if (type === 'while') { + if (!asm) return; // try to remove loop helper variables specifically var stats = node[2][1]; var last = stats[stats.length-1]; if (last && last[0] === 'if' && last[2][0] === 'block' && last[3] && last[3][0] === 'block') { var ifTrue = last[2]; var ifFalse = last[3]; + clearEmptyNodes(ifTrue[1]); + clearEmptyNodes(ifFalse[1]); var flip = false; if (ifFalse[1][0] && ifFalse[1][0][0] === 'break') { // canonicalize break in the if var temp = ifFalse; @@ -3589,17 +3592,25 @@ function eliminate(ast, memSafe) { } } if (found < 0) return; + // if a loop variable is used after we assigned to the helper, we must save its value and use that. + // (note that this can happen due to elimination, if we eliminate an expression containing the + // loop var far down, past the assignment!) + var temp = looper + '$looptemp'; var looperUsed = false; - for (var i = found+1; i < stats.length && !looperUsed; i++) { + assert(!(temp in asmData.vars)); + for (var i = found+1; i < stats.length; i++) { var curr = i < stats.length-1 ? stats[i] : last[1]; // on the last line, just look in the condition traverse(curr, function(node, type) { if (type === 'name' && node[1] === looper) { + node[1] = temp; looperUsed = true; - return true; } }); } - if (looperUsed) return; + if (looperUsed) { + asmData.vars[temp] = asmData.vars[looper]; + stats.splice(found, 0, ['stat', ['assign', true, ['name', temp], ['name', looper]]]); + } } for (var l = 0; l < helpers.length; l++) { for (var k = 0; k < helpers.length; k++) { @@ -4915,36 +4926,44 @@ function safeHeap(ast) { } } } else if (type === 'sub') { - var heap = node[1][1]; - if (heap[0] !== 'H') return; - var ptr = fixPtr(node[2], heap); - // SAFE_HEAP_LOAD(ptr, bytes, isFloat) - switch (heap) { - case 'HEAP8': { - return makeAsmCoercion(['call', ['name', 'SAFE_HEAP_LOAD'], [ptr, ['num', 1], ['num', '0'], ['num', '0']]], ASM_INT); - } - case 'HEAPU8': { - return makeAsmCoercion(['call', ['name', 'SAFE_HEAP_LOAD'], [ptr, ['num', 1], ['num', '0'], ['num', '1']]], ASM_INT); - } - case 'HEAP16': { - return makeAsmCoercion(['call', ['name', 'SAFE_HEAP_LOAD'], [ptr, ['num', 2], ['num', '0'], ['num', '0']]], ASM_INT); - } - case 'HEAPU16': { - return makeAsmCoercion(['call', ['name', 'SAFE_HEAP_LOAD'], [ptr, ['num', 2], ['num', '0'], ['num', '1']]], ASM_INT); - } - case 'HEAP32': { - return makeAsmCoercion(['call', ['name', 'SAFE_HEAP_LOAD'], [ptr, ['num', 4], ['num', '0'], ['num', '0']]], ASM_INT); - } - case 'HEAPU32': { - return makeAsmCoercion(['call', ['name', 'SAFE_HEAP_LOAD'], [ptr, ['num', 4], ['num', '0'], ['num', '1']]], ASM_INT); - } - case 'HEAPF32': { - return makeAsmCoercion(['call', ['name', 'SAFE_HEAP_LOAD'], [ptr, ['num', 4], ['num', '1'], ['num', '0']]], ASM_DOUBLE); - } - case 'HEAPF64': { - return makeAsmCoercion(['call', ['name', 'SAFE_HEAP_LOAD'], [ptr, ['num', 8], ['num', '1'], ['num', '0']]], ASM_DOUBLE); + var target = node[1][1]; + if (target[0] === 'H') { + // heap access + var heap = target; + var ptr = fixPtr(node[2], heap); + // SAFE_HEAP_LOAD(ptr, bytes, isFloat) + switch (heap) { + case 'HEAP8': { + return makeAsmCoercion(['call', ['name', 'SAFE_HEAP_LOAD'], [ptr, ['num', 1], ['num', '0'], ['num', '0']]], ASM_INT); + } + case 'HEAPU8': { + return makeAsmCoercion(['call', ['name', 'SAFE_HEAP_LOAD'], [ptr, ['num', 1], ['num', '0'], ['num', '1']]], ASM_INT); + } + case 'HEAP16': { + return makeAsmCoercion(['call', ['name', 'SAFE_HEAP_LOAD'], [ptr, ['num', 2], ['num', '0'], ['num', '0']]], ASM_INT); + } + case 'HEAPU16': { + return makeAsmCoercion(['call', ['name', 'SAFE_HEAP_LOAD'], [ptr, ['num', 2], ['num', '0'], ['num', '1']]], ASM_INT); + } + case 'HEAP32': { + return makeAsmCoercion(['call', ['name', 'SAFE_HEAP_LOAD'], [ptr, ['num', 4], ['num', '0'], ['num', '0']]], ASM_INT); + } + case 'HEAPU32': { + return makeAsmCoercion(['call', ['name', 'SAFE_HEAP_LOAD'], [ptr, ['num', 4], ['num', '0'], ['num', '1']]], ASM_INT); + } + case 'HEAPF32': { + return makeAsmCoercion(['call', ['name', 'SAFE_HEAP_LOAD'], [ptr, ['num', 4], ['num', '1'], ['num', '0']]], ASM_DOUBLE); + } + case 'HEAPF64': { + return makeAsmCoercion(['call', ['name', 'SAFE_HEAP_LOAD'], [ptr, ['num', 8], ['num', '1'], ['num', '0']]], ASM_DOUBLE); + } + default: throw 'bad heap ' + heap; } - default: throw 'bad heap ' + heap; + } else { + assert(target[0] == 'F'); + // function table indexing mask + assert(node[2][0] === 'binary' && node[2][1] === '&'); + node[2][2] = makeAsmCoercion(['call', ['name', 'SAFE_FT_MASK'], [makeAsmCoercion(node[2][2], ASM_INT), makeAsmCoercion(node[2][3], ASM_INT)]], ASM_INT); } } }); diff --git a/tools/shared.py b/tools/shared.py index e912a700..82bdd98b 100644 --- a/tools/shared.py +++ b/tools/shared.py @@ -746,13 +746,14 @@ else: # Engine tweaks try: - new_spidermonkey = listify(SPIDERMONKEY_ENGINE) - if 'gcparam' not in str(new_spidermonkey): - new_spidermonkey += ['-e', "gcparam('maxBytes', 1024*1024*1024);"] # Our very large files need lots of gc heap - if '-w' not in str(new_spidermonkey): - new_spidermonkey += ['-w'] - JS_ENGINES = map(lambda x: new_spidermonkey if x == SPIDERMONKEY_ENGINE else x, JS_ENGINES) - SPIDERMONKEY_ENGINE = new_spidermonkey + if SPIDERMONKEY_ENGINE: + new_spidermonkey = listify(SPIDERMONKEY_ENGINE) + if 'gcparam' not in str(new_spidermonkey): + new_spidermonkey += ['-e', "gcparam('maxBytes', 1024*1024*1024);"] # Our very large files need lots of gc heap + if '-w' not in str(new_spidermonkey): + new_spidermonkey += ['-w'] + JS_ENGINES = map(lambda x: new_spidermonkey if x == SPIDERMONKEY_ENGINE else x, JS_ENGINES) + SPIDERMONKEY_ENGINE = new_spidermonkey except NameError: pass diff --git a/tools/webidl_binder.py b/tools/webidl_binder.py new file mode 100644 index 00000000..0507cc78 --- /dev/null +++ b/tools/webidl_binder.py @@ -0,0 +1,432 @@ + +''' +WebIDL binder + +https://github.com/kripken/emscripten/wiki/WebIDL-Binder +''' + +import os, sys + +import shared + +sys.path.append(shared.path_from_root('third_party')) +sys.path.append(shared.path_from_root('third_party', 'ply')) + +import WebIDL + +class Dummy: + def __init__(self, init): + for k, v in init.iteritems(): + self.__dict__[k] = v + + def getExtendedAttribute(self, name): + return None + +input_file = sys.argv[1] +output_base = sys.argv[2] + +shared.try_delete(output_base + '.cpp') +shared.try_delete(output_base + '.js') + +p = WebIDL.Parser() +p.parse(open(input_file).read()) +data = p.finish() + +interfaces = {} +implements = {} + +for thing in data: + if isinstance(thing, WebIDL.IDLInterface): + interfaces[thing.identifier.name] = thing + elif isinstance(thing, WebIDL.IDLImplementsStatement): + implements.setdefault(thing.implementor.identifier.name, []).append(thing.implementee.identifier.name) + +#print interfaces +#print implements + +pre_c = [] +mid_c = [] +mid_js = [] + +pre_c += [r''' +#include <emscripten.h> +'''] + +mid_c += [r''' +extern "C" { +'''] + +def emit_constructor(name): + global mid_js + mid_js += [r'''%s.prototype = %s; +%s.prototype.constructor = %s; +%s.prototype.__class__ = %s; +%s.__cache__ = {}; +Module['%s'] = %s; +''' % (name, 'Object.create(%s.prototype)' % (implements[name][0] if implements.get(name) else 'WrapperObject'), name, name, name, name, name, name, name)] + + +mid_js += [''' +// Bindings utilities + +function WrapperObject() { +} +'''] + +emit_constructor('WrapperObject') + +mid_js += [''' +function getCache(__class__) { + return (__class__ || WrapperObject).__cache__; +} +Module['getCache'] = getCache; + +function wrapPointer(ptr, __class__) { + var cache = getCache(__class__); + var ret = cache[ptr]; + if (ret) return ret; + ret = Object.create((__class__ || WrapperObject).prototype); + ret.ptr = ptr; + return cache[ptr] = ret; +} +Module['wrapPointer'] = wrapPointer; + +function castObject(obj, __class__) { + return wrapPointer(obj.ptr, __class__); +} +Module['castObject'] = castObject; + +Module['NULL'] = wrapPointer(0); + +function destroy(obj) { + if (!obj['__destroy__']) throw 'Error: Cannot destroy object. (Did you create it yourself?)'; + obj['__destroy__'](); + // Remove from cache, so the object can be GC'd and refs added onto it released + delete getCache(obj.__class__)[obj.ptr]; +} +Module['destroy'] = destroy; + +function compare(obj1, obj2) { + return obj1.ptr === obj2.ptr; +} +Module['compare'] = compare; + +function getPointer(obj) { + return obj.ptr; +} +Module['getPointer'] = getPointer; + +function getClass(obj) { + return obj.__class__; +} +Module['getClass'] = getClass; + +// Converts a value into a C-style string. +function ensureString(value) { + if (typeof value == 'string') return allocate(intArrayFromString(value), 'i8', ALLOC_STACK); + return value; +} + +'''] + +C_FLOATS = ['float', 'double'] + +def type_to_c(t, non_pointing=False): + #print 'to c ', t + t = t.replace(' (Wrapper)', '') + if t == 'Long': + return 'int' + elif t == 'Short': + return 'short' + elif t == 'Void': + return 'void' + elif t == 'String': + return 'char*' + elif t == 'Float': + return 'float' + elif t == 'Double': + return 'double' + elif t == 'Boolean': + return 'bool' + elif t in interfaces: + return (interfaces[t].getExtendedAttribute('Prefix') or [''])[0] + t + ('' if non_pointing else '*') + else: + return t + +def take_addr_if_nonpointer(m): + if m.getExtendedAttribute('Ref') or m.getExtendedAttribute('Value'): + return '&' + return '' + +def deref_if_nonpointer(m): + if m.getExtendedAttribute('Ref') or m.getExtendedAttribute('Value'): + return '*' + return '' + +def type_to_cdec(raw): + name = ret = type_to_c(raw.type.name, non_pointing=True) + if raw.getExtendedAttribute('Const'): ret = 'const ' + ret + if name not in interfaces: return ret + if raw.getExtendedAttribute('Ref'): + return ret + '&' + if raw.getExtendedAttribute('Value'): + return ret + return ret + '*' + +def render_function(class_name, func_name, sigs, return_type, non_pointer, copy, operator, constructor, func_scope, call_content=None, const=False): + global mid_c, mid_js, js_impl_methods + + #print 'renderfunc', class_name, func_name, sigs, return_type, constructor + + bindings_name = class_name + '_' + func_name + min_args = min(sigs.keys()) + max_args = max(sigs.keys()) + + c_names = {} + + # JS + + cache = ('getCache(%s)[this.ptr] = this;' % class_name) if constructor else '' + call_prefix = '' if not constructor else 'this.ptr = ' + call_postfix = '' + if return_type != 'Void' and not constructor: call_prefix = 'return ' + if not constructor: + if return_type in interfaces: + call_prefix += 'wrapPointer(' + call_postfix += ', ' + return_type + ')' + + args = ['arg%d' % i for i in range(max_args)] + if not constructor: + body = ' var self = this.ptr;\n' + pre_arg = ['self'] + else: + body = '' + pre_arg = [] + + for i in range(max_args): + # note: null has typeof object, but is ok to leave as is, since we are calling into asm code where null|0 = 0 + body += " if (arg%d && typeof arg%d === 'object') arg%d = arg%d.ptr;\n" % (i, i, i, i) + body += " else arg%d = ensureString(arg%d);\n" % (i, i) + + for i in range(min_args, max_args): + c_names[i] = 'emscripten_bind_%s_%d' % (bindings_name, i) + body += ' if (arg%d === undefined) { %s%s(%s)%s%s }\n' % (i, call_prefix, '_' + c_names[i], ', '.join(pre_arg + args[:i]), call_postfix, '' if 'return ' in call_prefix else '; ' + (cache or ' ') + 'return') + c_names[max_args] = 'emscripten_bind_%s_%d' % (bindings_name, max_args) + body += ' %s%s(%s)%s;\n' % (call_prefix, '_' + c_names[max_args], ', '.join(pre_arg + args), call_postfix) + if cache: + body += ' ' + cache + '\n' + mid_js += [r'''function%s(%s) { +%s +}''' % ((' ' + func_name) if constructor else '', ', '.join(args), body[:-1])] + + # C + + for i in range(min_args, max_args+1): + raw = sigs.get(i) + if raw is None: continue + sig = [arg.type.name for arg in raw] + + c_arg_types = map(type_to_c, sig) + + normal_args = ', '.join(['%s arg%d' % (c_arg_types[j], j) for j in range(i)]) + if constructor: + full_args = normal_args + else: + full_args = type_to_c(class_name, non_pointing=True) + '* self' + ('' if not normal_args else ', ' + normal_args) + call_args = ', '.join(['%sarg%d' % ('*' if raw[j].getExtendedAttribute('Ref') else '', j) for j in range(i)]) + if constructor: + call = 'new ' + type_to_c(class_name, non_pointing=True) + call += '(' + call_args + ')' + elif call_content is not None: + call = call_content + else: + call = 'self->' + func_name + call += '(' + call_args + ')' + + if operator: + assert '=' in operator, 'can only do += *= etc. for now, all with "="' + cast_self = 'self' + if class_name != func_scope: + # this function comes from an ancestor class; for operators, we must cast it + cast_self = 'dynamic_cast<' + type_to_c(func_scope) + '>(' + cast_self + ')' + call = '(*%s %s %sarg0)' % (cast_self, operator, '*' if sig[0] in interfaces else '') + + pre = '' + + basic_return = 'return ' if constructor or return_type is not 'Void' else '' + return_prefix = basic_return + return_postfix = '' + if non_pointer: + return_prefix += '&'; + if copy: + pre += ' static %s temp;\n' % type_to_c(return_type, non_pointing=True) + return_prefix += '(temp = ' + return_postfix += ', &temp)' + + c_return_type = type_to_c(return_type) + mid_c += [r''' +%s%s EMSCRIPTEN_KEEPALIVE %s(%s) { +%s %s%s%s; +} +''' % ('const ' if const else '', type_to_c(class_name) if constructor else c_return_type, c_names[i], full_args, pre, return_prefix, call, return_postfix)] + + if not constructor: + if i == max_args: + dec_args = ', '.join(map(lambda j: type_to_cdec(raw[j]) + ' arg' + str(j), range(i))) + js_call_args = ', '.join(['%sarg%d' % (('(int)' if sig[j] in interfaces else '') + ('&' if raw[j].getExtendedAttribute('Ref') or raw[j].getExtendedAttribute('Value') else ''), j) for j in range(i)]) + + js_impl_methods += [r''' %s %s(%s) { + %sEM_ASM_%s({ + var self = Module['getCache'](Module['%s'])[$0]; + if (!self.hasOwnProperty('%s')) throw 'a JSImplementation must implement all functions, you forgot %s::%s.'; + %sself.%s(%s)%s; + }, (int)this%s); + }''' % (c_return_type, func_name, dec_args, + basic_return, 'INT' if c_return_type not in C_FLOATS else 'DOUBLE', + class_name, + func_name, class_name, func_name, + return_prefix, + func_name, + ','.join(['$%d' % i for i in range(1, max_args)]), + return_postfix, + (', ' if js_call_args else '') + js_call_args)] + + +for name, interface in interfaces.iteritems(): + js_impl = interface.getExtendedAttribute('JSImplementation') + if not js_impl: continue + implements[name] = [js_impl[0]] + +names = interfaces.keys() +names.sort(lambda x, y: 1 if implements.get(x) and implements[x][0] == y else (-1 if implements.get(y) and implements[y][0] == x else 0)) + +for name in names: + interface = interfaces[name] + + mid_js += ['\n// ' + name + '\n'] + mid_c += ['\n// ' + name + '\n'] + + global js_impl_methods + js_impl_methods = [] + + cons = interface.getExtendedAttribute('Constructor') + if type(cons) == list: raise Exception('do not use "Constructor", instead create methods with the name of the interface') + + js_impl = interface.getExtendedAttribute('JSImplementation') + if js_impl: + js_impl = js_impl[0] + + # Methods + + seen_constructor = False # ensure a constructor, even for abstract base classes + for m in interface.members: + if m.identifier.name == name: + seen_constructor = True + break + if not seen_constructor: + mid_js += ['function %s() { throw "cannot construct a %s, no constructor in IDL" }\n' % (name, name)] + emit_constructor(name) + + for m in interface.members: + if not m.isMethod(): continue + constructor = m.identifier.name == name + if not constructor: + parent_constructor = False + temp = m.parentScope + while temp.parentScope: + if temp.identifier.name == m.identifier.name: + parent_constructor = True + temp = temp.parentScope + if parent_constructor: + continue + if not constructor: + mid_js += [r''' +%s.prototype.%s = ''' % (name, m.identifier.name)] + sigs = {} + return_type = None + for ret, args in m.signatures(): + if return_type is None: + return_type = ret.name + else: + assert return_type == ret.name, 'overloads must have the same return type' + for i in range(len(args)+1): + if i == len(args) or args[i].optional: + assert i not in sigs, 'overloading must differentiate by # of arguments (cannot have two signatures that differ by types but not by length)' + sigs[i] = args[:i] + render_function(name, + m.identifier.name, sigs, return_type, + m.getExtendedAttribute('Ref'), + m.getExtendedAttribute('Value'), + (m.getExtendedAttribute('Operator') or [None])[0], + constructor, + func_scope=m.parentScope.identifier.name) + mid_js += [';\n'] + if constructor: + emit_constructor(name) + + for m in interface.members: + if not m.isAttr(): continue + attr = m.identifier.name + + get_name = 'get_' + attr + mid_js += [r''' + %s.prototype.%s= ''' % (name, get_name)] + render_function(name, + get_name, { 0: [] }, m.type.name, + None, + None, + None, + False, + func_scope=interface, + call_content=take_addr_if_nonpointer(m) + 'self->' + attr, + const=m.getExtendedAttribute('Const')) + + set_name = 'set_' + attr + mid_js += [r''' + %s.prototype.%s= ''' % (name, set_name)] + render_function(name, + set_name, { 1: [Dummy({ 'type': m.type })] }, 'Void', + None, + None, + None, + False, + func_scope=interface, + call_content='self->' + attr + ' = ' + deref_if_nonpointer(m) + 'arg0', + const=m.getExtendedAttribute('Const')) + + if not interface.getExtendedAttribute('NoDelete'): + mid_js += [r''' + %s.prototype.__destroy__ = ''' % name] + render_function(name, + '__destroy__', { 0: [] }, 'Void', + None, + None, + None, + False, + func_scope=interface, + call_content='delete self') + + # Emit C++ class implementation that calls into JS implementation + + if js_impl: + pre_c += [r''' +class %s : public %s { +public: +%s +}; +''' % (name, type_to_c(js_impl, non_pointing=True), '\n'.join(js_impl_methods))] + +mid_c += ['\n}\n\n'] +mid_js += ['\n'] + +# Write + +c = open(output_base + '.cpp', 'w') +for x in pre_c: c.write(x) +for x in mid_c: c.write(x) +c.close() + +js = open(output_base + '.js', 'w') +for x in mid_js: js.write(x) +js.close() + |