[
  {
    "path": ".clang-format",
    "content": "BasedOnStyle: LLVM\nAccessModifierOffset: -4\nAlignAfterOpenBracket: Align\nAlignConsecutiveAssignments: false\nAlignConsecutiveMacros: AcrossComments\nAlignOperands: true\nAllowAllArgumentsOnNextLine: false\nAllowAllConstructorInitializersOnNextLine: false\nAllowAllParametersOfDeclarationOnNextLine: false\nAllowShortBlocksOnASingleLine: Always\nAllowShortCaseLabelsOnASingleLine: false\nAllowShortFunctionsOnASingleLine: All\nAllowShortIfStatementsOnASingleLine: Always\nAllowShortLambdasOnASingleLine: All\nAllowShortLoopsOnASingleLine: true\nAlwaysBreakAfterReturnType: None\nAlwaysBreakTemplateDeclarations: Yes\nBreakBeforeBraces: Attach\nBreakBeforeBinaryOperators: None\nBreakBeforeTernaryOperators: true\nBreakConstructorInitializers: BeforeColon\nBreakInheritanceList: BeforeColon\nColumnLimit: 0\nCompactNamespaces: false\nContinuationIndentWidth: 8\nIndentCaseLabels: true\nIndentPPDirectives: AfterHash\nIndentWidth: 4\nKeepEmptyLinesAtTheStartOfBlocks: true\nMaxEmptyLinesToKeep: 2\nNamespaceIndentation: All\nObjCSpaceAfterProperty: false\nObjCSpaceBeforeProtocolList: true\nPointerAlignment: Right\nReflowComments: false\nSpaceAfterCStyleCast: true\nSpaceAfterLogicalNot: false\nSpaceAfterTemplateKeyword: false\nSpaceBeforeAssignmentOperators: true\nSpaceBeforeCpp11BracedList: false\nSpaceBeforeCtorInitializerColon: true\nSpaceBeforeInheritanceColon: true\nSpaceBeforeParens: ControlStatements\nSpaceBeforeRangeBasedForLoopColon: true\nSpaceInEmptyParentheses: false\nSpacesBeforeTrailingComments: 0\nSpacesInAngles: true\nSpacesInCStyleCastParentheses: true\nSpacesInContainerLiterals: false\nSpacesInParentheses: true\nSpacesInSquareBrackets: true\nTabWidth: 4\nUseTab: ForIndentation\nSortIncludes: false\n"
  },
  {
    "path": ".github/FUNDING.yml",
    "content": "# These are supported funding model platforms\n\n#github: hogsy\n"
  },
  {
    "path": ".gitignore",
    "content": "# Object files\n*.o\n*.ko\n#*.obj\n*.elf\n\n# Precompiled Headers\n*.gch\n*.pch\n\n# Libraries\n*.lib\n*.a\n*.la\n*.lo\n\n# Shared objects (inc. Windows DLLs)\n*.dll\n*.so\n*.so.*\n*.dylib\n\n# Executables\n*.exe\n*.out\n*.app\n*.i*86\n*.x86_64\n*.hex\n\n# Debug files\n*.dSYM/\n*.su\n\n# IDE specific\n.vscode/\n.vs/\nbuild/\n\n# OpenHoW\nsrc/3rdparty/SDL2/\nbin/imgui.ini\nbin/debug/\nbin/release/\n\n# Ignore extracted assets \nbin/mods/how/audio/\nbin/mods/how/chars/\nbin/mods/how/frontend/\nbin/mods/how/music/\nbin/mods/how/skys/\nbin/mods/how/speech/\nbin/mods/how/streams/\nbin/mods/how/textures/\nbin/mods/base/debug/\n/.idea/\n/cmake-build-debug/\n/bin/extractor\n/bin/OpenHoW\n/bin/ptgtool\n"
  },
  {
    "path": ".gitmodules",
    "content": "[submodule \"platform\"]\n\tpath = src/3rdparty/platform\n\turl = https://github.com/TalonBraveInfo/platform\n[submodule \"imgui\"]\n\tpath = src/3rdparty/imgui\n\turl = https://github.com/ocornut/imgui.git\n[submodule \"src/3rdparty/openal-soft\"]\n\tpath = src/3rdparty/openal-soft\n\turl = https://github.com/kcat/openal-soft.git\n"
  },
  {
    "path": "CMakeLists.txt",
    "content": "#[[\nThis is free and unencumbered software released into the public domain.\n\nAnyone is free to copy, modify, publish, use, compile, sell, or\ndistribute this software, either in source code form or as a compiled\nbinary, for any purpose, commercial or non-commercial, and by any\nmeans.\n\nIn jurisdictions that recognize copyright laws, the author or authors\nof this software dedicate any and all copyright interest in the\nsoftware to the public domain. We make this dedication for the benefit\nof the public at large and to the detriment of our heirs and\nsuccessors. We intend this dedication to be an overt act of\nrelinquishment in perpetuity of all present and future rights to this\nsoftware under copyright law.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR\nOTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,\nARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\nOTHER DEALINGS IN THE SOFTWARE.\n\nFor more information, please refer to <http://unlicense.org>\n]]\n\ncmake_minimum_required(VERSION 3.5.1)\n\nproject(OpenHoW)\n\n#set(CMAKE_VERBOSE_MAKEFILE ON)\noption(OHW_BUILD_TOOLS \"Build tools and utilities\" ON)\n\n# Set all of our output directories.\nset(CMAKE_LIBRARY_OUTPUT_DIRECTORY \"${CMAKE_SOURCE_DIR}/lib/\")\nset(CMAKE_RUNTIME_OUTPUT_DIRECTORY \"${CMAKE_SOURCE_DIR}/bin/\")\n\nset(CMAKE_CXX_STANDARD 11)\nset(CMAKE_C_STANDARD 11)\n\nset(CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS} -Wall\")\nset(CMAKE_C_FLAGS \"${CMAKE_C_FLAGS} -Wall\")\nif (\"${CMAKE_CXX_COMPILER_ID}\" STREQUAL \"GNU\") #GCC\n    set(CMAKE_C_FLAGS \"${CMAKE_C_FLAGS} -Wsign-compare -Wno-unused-function -Wno-unused-variable -Wno-format-truncation -Wold-style-declaration\")\nendif ()\n\nadd_definitions(\"-D_DEBUG\")\n\nfunction(build_openal)\n    set(LIBTYPE \"STATIC\")\n    add_definitions(\"-DAL_LIBTYPE_STATIC\")\n    set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY \"${CMAKE_SOURCE_DIR}/src/3rdparty/openal-soft/lib/\")\n    set(ALSOFT_UTILS OFF CACHE BOOL \"Build and install utility programs\")\n    set(ALSOFT_EXAMPLES OFF CACHE BOOL \"Build and install example programs\")\n    set(ALSOFT_TESTS OFF CACHE BOOL \"Build and install test programs\")\n    add_subdirectory(src/3rdparty/openal-soft)\nendfunction()\n\nif (WIN32 OR APPLE)\n    build_openal()\nendif ()\n\n# Get the current working branch\nexecute_process(\n        COMMAND git rev-parse --abbrev-ref HEAD\n        WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}\n        OUTPUT_VARIABLE GIT_BRANCH\n        OUTPUT_STRIP_TRAILING_WHITESPACE\n)\n\n# Get the latest abbreviated commit hash of the working branch\nexecute_process(\n        COMMAND git log -1 --format=%h\n        WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}\n        OUTPUT_VARIABLE GIT_COMMIT_HASH\n        OUTPUT_STRIP_TRAILING_WHITESPACE\n)\n\n# Get the number of commits on the working branch\nexecute_process(\n        COMMAND git rev-list HEAD --count\n        WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}\n        OUTPUT_VARIABLE GIT_COMMIT_COUNT\n        OUTPUT_STRIP_TRAILING_WHITESPACE\n)\n\nadd_definitions(-DGIT_COMMIT_HASH=\"${GIT_COMMIT_HASH}\")\nadd_definitions(-DGIT_COMMIT_COUNT=\"${GIT_COMMIT_COUNT}\")\nadd_definitions(-DGIT_BRANCH=\"${GIT_BRANCH}\")\n\n# 3rd-party libraries\nadd_subdirectory(src/3rdparty/platform/plcore/)\nadd_subdirectory(src/3rdparty/platform/plgraphics/)\nadd_subdirectory(src/3rdparty/platform/plmodel/)\nadd_subdirectory(src/3rdparty/platform/plugins/driver_opengl/)\n\n# core openhow components\nadd_subdirectory(src/extractor)\nadd_subdirectory(src/engine)\n"
  },
  {
    "path": "CONTRIBUTORS",
    "content": "https://github.com/hogsy\nhttps://github.com/DummkopfOfHachtenduden\nhttps://github.com/solemnwarning\nhttps://github.com/Bonerlord\nhttps://github.com/sabas\nhttps://github.com/metalvoidzz\n"
  },
  {
    "path": "LICENSE",
    "content": "                    GNU GENERAL PUBLIC LICENSE\n                       Version 3, 29 June 2007\n\n Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n                            Preamble\n\n  The GNU General Public License is a free, copyleft license for\nsoftware and other kinds of works.\n\n  The licenses for most software and other practical works are designed\nto take away your freedom to share and change the works.  By contrast,\nthe GNU General Public License is intended to guarantee your freedom to\nshare and change all versions of a program--to make sure it remains free\nsoftware for all its users.  We, the Free Software Foundation, use the\nGNU General Public License for most of our software; it applies also to\nany other work released this way by its authors.  You can apply it to\nyour programs, too.\n\n  When we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthem if you wish), that you receive source code or can get it if you\nwant it, that you can change the software or use pieces of it in new\nfree programs, and that you know you can do these things.\n\n  To protect your rights, we need to prevent others from denying you\nthese rights or asking you to surrender the rights.  Therefore, you have\ncertain responsibilities if you distribute copies of the software, or if\nyou modify it: responsibilities to respect the freedom of others.\n\n  For example, if you distribute copies of such a program, whether\ngratis or for a fee, you must pass on to the recipients the same\nfreedoms that you received.  You must make sure that they, too, receive\nor can get the source code.  And you must show them these terms so they\nknow their rights.\n\n  Developers that use the GNU GPL protect your rights with two steps:\n(1) assert copyright on the software, and (2) offer you this License\ngiving you legal permission to copy, distribute and/or modify it.\n\n  For the developers' and authors' protection, the GPL clearly explains\nthat there is no warranty for this free software.  For both users' and\nauthors' sake, the GPL requires that modified versions be marked as\nchanged, so that their problems will not be attributed erroneously to\nauthors of previous versions.\n\n  Some devices are designed to deny users access to install or run\nmodified versions of the software inside them, although the manufacturer\ncan do so.  This is fundamentally incompatible with the aim of\nprotecting users' freedom to change the software.  The systematic\npattern of such abuse occurs in the area of products for individuals to\nuse, which is precisely where it is most unacceptable.  Therefore, we\nhave designed this version of the GPL to prohibit the practice for those\nproducts.  If such problems arise substantially in other domains, we\nstand ready to extend this provision to those domains in future versions\nof the GPL, as needed to protect the freedom of users.\n\n  Finally, every program is threatened constantly by software patents.\nStates should not allow patents to restrict development and use of\nsoftware on general-purpose computers, but in those that do, we wish to\navoid the special danger that patents applied to a free program could\nmake it effectively proprietary.  To prevent this, the GPL assures that\npatents cannot be used to render the program non-free.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.\n\n                       TERMS AND CONDITIONS\n\n  0. Definitions.\n\n  \"This License\" refers to version 3 of the GNU General Public License.\n\n  \"Copyright\" also means copyright-like laws that apply to other kinds of\nworks, such as semiconductor masks.\n\n  \"The Program\" refers to any copyrightable work licensed under this\nLicense.  Each licensee is addressed as \"you\".  \"Licensees\" and\n\"recipients\" may be individuals or organizations.\n\n  To \"modify\" a work means to copy from or adapt all or part of the work\nin a fashion requiring copyright permission, other than the making of an\nexact copy.  The resulting work is called a \"modified version\" of the\nearlier work or a work \"based on\" the earlier work.\n\n  A \"covered work\" means either the unmodified Program or a work based\non the Program.\n\n  To \"propagate\" a work means to do anything with it that, without\npermission, would make you directly or secondarily liable for\ninfringement under applicable copyright law, except executing it on a\ncomputer or modifying a private copy.  Propagation includes copying,\ndistribution (with or without modification), making available to the\npublic, and in some countries other activities as well.\n\n  To \"convey\" a work means any kind of propagation that enables other\nparties to make or receive copies.  Mere interaction with a user through\na computer network, with no transfer of a copy, is not conveying.\n\n  An interactive user interface displays \"Appropriate Legal Notices\"\nto the extent that it includes a convenient and prominently visible\nfeature that (1) displays an appropriate copyright notice, and (2)\ntells the user that there is no warranty for the work (except to the\nextent that warranties are provided), that licensees may convey the\nwork under this License, and how to view a copy of this License.  If\nthe interface presents a list of user commands or options, such as a\nmenu, a prominent item in the list meets this criterion.\n\n  1. Source Code.\n\n  The \"source code\" for a work means the preferred form of the work\nfor making modifications to it.  \"Object code\" means any non-source\nform of a work.\n\n  A \"Standard Interface\" means an interface that either is an official\nstandard defined by a recognized standards body, or, in the case of\ninterfaces specified for a particular programming language, one that\nis widely used among developers working in that language.\n\n  The \"System Libraries\" of an executable work include anything, other\nthan the work as a whole, that (a) is included in the normal form of\npackaging a Major Component, but which is not part of that Major\nComponent, and (b) serves only to enable use of the work with that\nMajor Component, or to implement a Standard Interface for which an\nimplementation is available to the public in source code form.  A\n\"Major Component\", in this context, means a major essential component\n(kernel, window system, and so on) of the specific operating system\n(if any) on which the executable work runs, or a compiler used to\nproduce the work, or an object code interpreter used to run it.\n\n  The \"Corresponding Source\" for a work in object code form means all\nthe source code needed to generate, install, and (for an executable\nwork) run the object code and to modify the work, including scripts to\ncontrol those activities.  However, it does not include the work's\nSystem Libraries, or general-purpose tools or generally available free\nprograms which are used unmodified in performing those activities but\nwhich are not part of the work.  For example, Corresponding Source\nincludes interface definition files associated with source files for\nthe work, and the source code for shared libraries and dynamically\nlinked subprograms that the work is specifically designed to require,\nsuch as by intimate data communication or control flow between those\nsubprograms and other parts of the work.\n\n  The Corresponding Source need not include anything that users\ncan regenerate automatically from other parts of the Corresponding\nSource.\n\n  The Corresponding Source for a work in source code form is that\nsame work.\n\n  2. Basic Permissions.\n\n  All rights granted under this License are granted for the term of\ncopyright on the Program, and are irrevocable provided the stated\nconditions are met.  This License explicitly affirms your unlimited\npermission to run the unmodified Program.  The output from running a\ncovered work is covered by this License only if the output, given its\ncontent, constitutes a covered work.  This License acknowledges your\nrights of fair use or other equivalent, as provided by copyright law.\n\n  You may make, run and propagate covered works that you do not\nconvey, without conditions so long as your license otherwise remains\nin force.  You may convey covered works to others for the sole purpose\nof having them make modifications exclusively for you, or provide you\nwith facilities for running those works, provided that you comply with\nthe terms of this License in conveying all material for which you do\nnot control copyright.  Those thus making or running the covered works\nfor you must do so exclusively on your behalf, under your direction\nand control, on terms that prohibit them from making any copies of\nyour copyrighted material outside their relationship with you.\n\n  Conveying under any other circumstances is permitted solely under\nthe conditions stated below.  Sublicensing is not allowed; section 10\nmakes it unnecessary.\n\n  3. Protecting Users' Legal Rights From Anti-Circumvention Law.\n\n  No covered work shall be deemed part of an effective technological\nmeasure under any applicable law fulfilling obligations under article\n11 of the WIPO copyright treaty adopted on 20 December 1996, or\nsimilar laws prohibiting or restricting circumvention of such\nmeasures.\n\n  When you convey a covered work, you waive any legal power to forbid\ncircumvention of technological measures to the extent such circumvention\nis effected by exercising rights under this License with respect to\nthe covered work, and you disclaim any intention to limit operation or\nmodification of the work as a means of enforcing, against the work's\nusers, your or third parties' legal rights to forbid circumvention of\ntechnological measures.\n\n  4. Conveying Verbatim Copies.\n\n  You may convey verbatim copies of the Program's source code as you\nreceive it, in any medium, provided that you conspicuously and\nappropriately publish on each copy an appropriate copyright notice;\nkeep intact all notices stating that this License and any\nnon-permissive terms added in accord with section 7 apply to the code;\nkeep intact all notices of the absence of any warranty; and give all\nrecipients a copy of this License along with the Program.\n\n  You may charge any price or no price for each copy that you convey,\nand you may offer support or warranty protection for a fee.\n\n  5. Conveying Modified Source Versions.\n\n  You may convey a work based on the Program, or the modifications to\nproduce it from the Program, in the form of source code under the\nterms of section 4, provided that you also meet all of these conditions:\n\n    a) The work must carry prominent notices stating that you modified\n    it, and giving a relevant date.\n\n    b) The work must carry prominent notices stating that it is\n    released under this License and any conditions added under section\n    7.  This requirement modifies the requirement in section 4 to\n    \"keep intact all notices\".\n\n    c) You must license the entire work, as a whole, under this\n    License to anyone who comes into possession of a copy.  This\n    License will therefore apply, along with any applicable section 7\n    additional terms, to the whole of the work, and all its parts,\n    regardless of how they are packaged.  This License gives no\n    permission to license the work in any other way, but it does not\n    invalidate such permission if you have separately received it.\n\n    d) If the work has interactive user interfaces, each must display\n    Appropriate Legal Notices; however, if the Program has interactive\n    interfaces that do not display Appropriate Legal Notices, your\n    work need not make them do so.\n\n  A compilation of a covered work with other separate and independent\nworks, which are not by their nature extensions of the covered work,\nand which are not combined with it such as to form a larger program,\nin or on a volume of a storage or distribution medium, is called an\n\"aggregate\" if the compilation and its resulting copyright are not\nused to limit the access or legal rights of the compilation's users\nbeyond what the individual works permit.  Inclusion of a covered work\nin an aggregate does not cause this License to apply to the other\nparts of the aggregate.\n\n  6. Conveying Non-Source Forms.\n\n  You may convey a covered work in object code form under the terms\nof sections 4 and 5, provided that you also convey the\nmachine-readable Corresponding Source under the terms of this License,\nin one of these ways:\n\n    a) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by the\n    Corresponding Source fixed on a durable physical medium\n    customarily used for software interchange.\n\n    b) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by a\n    written offer, valid for at least three years and valid for as\n    long as you offer spare parts or customer support for that product\n    model, to give anyone who possesses the object code either (1) a\n    copy of the Corresponding Source for all the software in the\n    product that is covered by this License, on a durable physical\n    medium customarily used for software interchange, for a price no\n    more than your reasonable cost of physically performing this\n    conveying of source, or (2) access to copy the\n    Corresponding Source from a network server at no charge.\n\n    c) Convey individual copies of the object code with a copy of the\n    written offer to provide the Corresponding Source.  This\n    alternative is allowed only occasionally and noncommercially, and\n    only if you received the object code with such an offer, in accord\n    with subsection 6b.\n\n    d) Convey the object code by offering access from a designated\n    place (gratis or for a charge), and offer equivalent access to the\n    Corresponding Source in the same way through the same place at no\n    further charge.  You need not require recipients to copy the\n    Corresponding Source along with the object code.  If the place to\n    copy the object code is a network server, the Corresponding Source\n    may be on a different server (operated by you or a third party)\n    that supports equivalent copying facilities, provided you maintain\n    clear directions next to the object code saying where to find the\n    Corresponding Source.  Regardless of what server hosts the\n    Corresponding Source, you remain obligated to ensure that it is\n    available for as long as needed to satisfy these requirements.\n\n    e) Convey the object code using peer-to-peer transmission, provided\n    you inform other peers where the object code and Corresponding\n    Source of the work are being offered to the general public at no\n    charge under subsection 6d.\n\n  A separable portion of the object code, whose source code is excluded\nfrom the Corresponding Source as a System Library, need not be\nincluded in conveying the object code work.\n\n  A \"User Product\" is either (1) a \"consumer product\", which means any\ntangible personal property which is normally used for personal, family,\nor household purposes, or (2) anything designed or sold for incorporation\ninto a dwelling.  In determining whether a product is a consumer product,\ndoubtful cases shall be resolved in favor of coverage.  For a particular\nproduct received by a particular user, \"normally used\" refers to a\ntypical or common use of that class of product, regardless of the status\nof the particular user or of the way in which the particular user\nactually uses, or expects or is expected to use, the product.  A product\nis a consumer product regardless of whether the product has substantial\ncommercial, industrial or non-consumer uses, unless such uses represent\nthe only significant mode of use of the product.\n\n  \"Installation Information\" for a User Product means any methods,\nprocedures, authorization keys, or other information required to install\nand execute modified versions of a covered work in that User Product from\na modified version of its Corresponding Source.  The information must\nsuffice to ensure that the continued functioning of the modified object\ncode is in no case prevented or interfered with solely because\nmodification has been made.\n\n  If you convey an object code work under this section in, or with, or\nspecifically for use in, a User Product, and the conveying occurs as\npart of a transaction in which the right of possession and use of the\nUser Product is transferred to the recipient in perpetuity or for a\nfixed term (regardless of how the transaction is characterized), the\nCorresponding Source conveyed under this section must be accompanied\nby the Installation Information.  But this requirement does not apply\nif neither you nor any third party retains the ability to install\nmodified object code on the User Product (for example, the work has\nbeen installed in ROM).\n\n  The requirement to provide Installation Information does not include a\nrequirement to continue to provide support service, warranty, or updates\nfor a work that has been modified or installed by the recipient, or for\nthe User Product in which it has been modified or installed.  Access to a\nnetwork may be denied when the modification itself materially and\nadversely affects the operation of the network or violates the rules and\nprotocols for communication across the network.\n\n  Corresponding Source conveyed, and Installation Information provided,\nin accord with this section must be in a format that is publicly\ndocumented (and with an implementation available to the public in\nsource code form), and must require no special password or key for\nunpacking, reading or copying.\n\n  7. Additional Terms.\n\n  \"Additional permissions\" are terms that supplement the terms of this\nLicense by making exceptions from one or more of its conditions.\nAdditional permissions that are applicable to the entire Program shall\nbe treated as though they were included in this License, to the extent\nthat they are valid under applicable law.  If additional permissions\napply only to part of the Program, that part may be used separately\nunder those permissions, but the entire Program remains governed by\nthis License without regard to the additional permissions.\n\n  When you convey a copy of a covered work, you may at your option\nremove any additional permissions from that copy, or from any part of\nit.  (Additional permissions may be written to require their own\nremoval in certain cases when you modify the work.)  You may place\nadditional permissions on material, added by you to a covered work,\nfor which you have or can give appropriate copyright permission.\n\n  Notwithstanding any other provision of this License, for material you\nadd to a covered work, you may (if authorized by the copyright holders of\nthat material) supplement the terms of this License with terms:\n\n    a) Disclaiming warranty or limiting liability differently from the\n    terms of sections 15 and 16 of this License; or\n\n    b) Requiring preservation of specified reasonable legal notices or\n    author attributions in that material or in the Appropriate Legal\n    Notices displayed by works containing it; or\n\n    c) Prohibiting misrepresentation of the origin of that material, or\n    requiring that modified versions of such material be marked in\n    reasonable ways as different from the original version; or\n\n    d) Limiting the use for publicity purposes of names of licensors or\n    authors of the material; or\n\n    e) Declining to grant rights under trademark law for use of some\n    trade names, trademarks, or service marks; or\n\n    f) Requiring indemnification of licensors and authors of that\n    material by anyone who conveys the material (or modified versions of\n    it) with contractual assumptions of liability to the recipient, for\n    any liability that these contractual assumptions directly impose on\n    those licensors and authors.\n\n  All other non-permissive additional terms are considered \"further\nrestrictions\" within the meaning of section 10.  If the Program as you\nreceived it, or any part of it, contains a notice stating that it is\ngoverned by this License along with a term that is a further\nrestriction, you may remove that term.  If a license document contains\na further restriction but permits relicensing or conveying under this\nLicense, you may add to a covered work material governed by the terms\nof that license document, provided that the further restriction does\nnot survive such relicensing or conveying.\n\n  If you add terms to a covered work in accord with this section, you\nmust place, in the relevant source files, a statement of the\nadditional terms that apply to those files, or a notice indicating\nwhere to find the applicable terms.\n\n  Additional terms, permissive or non-permissive, may be stated in the\nform of a separately written license, or stated as exceptions;\nthe above requirements apply either way.\n\n  8. Termination.\n\n  You may not propagate or modify a covered work except as expressly\nprovided under this License.  Any attempt otherwise to propagate or\nmodify it is void, and will automatically terminate your rights under\nthis License (including any patent licenses granted under the third\nparagraph of section 11).\n\n  However, if you cease all violation of this License, then your\nlicense from a particular copyright holder is reinstated (a)\nprovisionally, unless and until the copyright holder explicitly and\nfinally terminates your license, and (b) permanently, if the copyright\nholder fails to notify you of the violation by some reasonable means\nprior to 60 days after the cessation.\n\n  Moreover, your license from a particular copyright holder is\nreinstated permanently if the copyright holder notifies you of the\nviolation by some reasonable means, this is the first time you have\nreceived notice of violation of this License (for any work) from that\ncopyright holder, and you cure the violation prior to 30 days after\nyour receipt of the notice.\n\n  Termination of your rights under this section does not terminate the\nlicenses of parties who have received copies or rights from you under\nthis License.  If your rights have been terminated and not permanently\nreinstated, you do not qualify to receive new licenses for the same\nmaterial under section 10.\n\n  9. Acceptance Not Required for Having Copies.\n\n  You are not required to accept this License in order to receive or\nrun a copy of the Program.  Ancillary propagation of a covered work\noccurring solely as a consequence of using peer-to-peer transmission\nto receive a copy likewise does not require acceptance.  However,\nnothing other than this License grants you permission to propagate or\nmodify any covered work.  These actions infringe copyright if you do\nnot accept this License.  Therefore, by modifying or propagating a\ncovered work, you indicate your acceptance of this License to do so.\n\n  10. Automatic Licensing of Downstream Recipients.\n\n  Each time you convey a covered work, the recipient automatically\nreceives a license from the original licensors, to run, modify and\npropagate that work, subject to this License.  You are not responsible\nfor enforcing compliance by third parties with this License.\n\n  An \"entity transaction\" is a transaction transferring control of an\norganization, or substantially all assets of one, or subdividing an\norganization, or merging organizations.  If propagation of a covered\nwork results from an entity transaction, each party to that\ntransaction who receives a copy of the work also receives whatever\nlicenses to the work the party's predecessor in interest had or could\ngive under the previous paragraph, plus a right to possession of the\nCorresponding Source of the work from the predecessor in interest, if\nthe predecessor has it or can get it with reasonable efforts.\n\n  You may not impose any further restrictions on the exercise of the\nrights granted or affirmed under this License.  For example, you may\nnot impose a license fee, royalty, or other charge for exercise of\nrights granted under this License, and you may not initiate litigation\n(including a cross-claim or counterclaim in a lawsuit) alleging that\nany patent claim is infringed by making, using, selling, offering for\nsale, or importing the Program or any portion of it.\n\n  11. Patents.\n\n  A \"contributor\" is a copyright holder who authorizes use under this\nLicense of the Program or a work on which the Program is based.  The\nwork thus licensed is called the contributor's \"contributor version\".\n\n  A contributor's \"essential patent claims\" are all patent claims\nowned or controlled by the contributor, whether already acquired or\nhereafter acquired, that would be infringed by some manner, permitted\nby this License, of making, using, or selling its contributor version,\nbut do not include claims that would be infringed only as a\nconsequence of further modification of the contributor version.  For\npurposes of this definition, \"control\" includes the right to grant\npatent sublicenses in a manner consistent with the requirements of\nthis License.\n\n  Each contributor grants you a non-exclusive, worldwide, royalty-free\npatent license under the contributor's essential patent claims, to\nmake, use, sell, offer for sale, import and otherwise run, modify and\npropagate the contents of its contributor version.\n\n  In the following three paragraphs, a \"patent license\" is any express\nagreement or commitment, however denominated, not to enforce a patent\n(such as an express permission to practice a patent or covenant not to\nsue for patent infringement).  To \"grant\" such a patent license to a\nparty means to make such an agreement or commitment not to enforce a\npatent against the party.\n\n  If you convey a covered work, knowingly relying on a patent license,\nand the Corresponding Source of the work is not available for anyone\nto copy, free of charge and under the terms of this License, through a\npublicly available network server or other readily accessible means,\nthen you must either (1) cause the Corresponding Source to be so\navailable, or (2) arrange to deprive yourself of the benefit of the\npatent license for this particular work, or (3) arrange, in a manner\nconsistent with the requirements of this License, to extend the patent\nlicense to downstream recipients.  \"Knowingly relying\" means you have\nactual knowledge that, but for the patent license, your conveying the\ncovered work in a country, or your recipient's use of the covered work\nin a country, would infringe one or more identifiable patents in that\ncountry that you have reason to believe are valid.\n\n  If, pursuant to or in connection with a single transaction or\narrangement, you convey, or propagate by procuring conveyance of, a\ncovered work, and grant a patent license to some of the parties\nreceiving the covered work authorizing them to use, propagate, modify\nor convey a specific copy of the covered work, then the patent license\nyou grant is automatically extended to all recipients of the covered\nwork and works based on it.\n\n  A patent license is \"discriminatory\" if it does not include within\nthe scope of its coverage, prohibits the exercise of, or is\nconditioned on the non-exercise of one or more of the rights that are\nspecifically granted under this License.  You may not convey a covered\nwork if you are a party to an arrangement with a third party that is\nin the business of distributing software, under which you make payment\nto the third party based on the extent of your activity of conveying\nthe work, and under which the third party grants, to any of the\nparties who would receive the covered work from you, a discriminatory\npatent license (a) in connection with copies of the covered work\nconveyed by you (or copies made from those copies), or (b) primarily\nfor and in connection with specific products or compilations that\ncontain the covered work, unless you entered into that arrangement,\nor that patent license was granted, prior to 28 March 2007.\n\n  Nothing in this License shall be construed as excluding or limiting\nany implied license or other defenses to infringement that may\notherwise be available to you under applicable patent law.\n\n  12. No Surrender of Others' Freedom.\n\n  If conditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot convey a\ncovered work so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you may\nnot convey it at all.  For example, if you agree to terms that obligate you\nto collect a royalty for further conveying from those to whom you convey\nthe Program, the only way you could satisfy both those terms and this\nLicense would be to refrain entirely from conveying the Program.\n\n  13. Use with the GNU Affero General Public License.\n\n  Notwithstanding any other provision of this License, you have\npermission to link or combine any covered work with a work licensed\nunder version 3 of the GNU Affero General Public License into a single\ncombined work, and to convey the resulting work.  The terms of this\nLicense will continue to apply to the part which is the covered work,\nbut the special requirements of the GNU Affero General Public License,\nsection 13, concerning interaction through a network will apply to the\ncombination as such.\n\n  14. Revised Versions of this License.\n\n  The Free Software Foundation may publish revised and/or new versions of\nthe GNU General Public License from time to time.  Such new versions will\nbe similar in spirit to the present version, but may differ in detail to\naddress new problems or concerns.\n\n  Each version is given a distinguishing version number.  If the\nProgram specifies that a certain numbered version of the GNU General\nPublic License \"or any later version\" applies to it, you have the\noption of following the terms and conditions either of that numbered\nversion or of any later version published by the Free Software\nFoundation.  If the Program does not specify a version number of the\nGNU General Public License, you may choose any version ever published\nby the Free Software Foundation.\n\n  If the Program specifies that a proxy can decide which future\nversions of the GNU General Public License can be used, that proxy's\npublic statement of acceptance of a version permanently authorizes you\nto choose that version for the Program.\n\n  Later license versions may give you additional or different\npermissions.  However, no additional obligations are imposed on any\nauthor or copyright holder as a result of your choosing to follow a\nlater version.\n\n  15. Disclaimer of Warranty.\n\n  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY\nAPPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT\nHOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY\nOF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,\nTHE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM\nIS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF\nALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n\n  16. Limitation of Liability.\n\n  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS\nTHE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY\nGENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE\nUSE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF\nDATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD\nPARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),\nEVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF\nSUCH DAMAGES.\n\n  17. Interpretation of Sections 15 and 16.\n\n  If the disclaimer of warranty and limitation of liability provided\nabove cannot be given local legal effect according to their terms,\nreviewing courts shall apply local law that most closely approximates\nan absolute waiver of all civil liability in connection with the\nProgram, unless a warranty or assumption of liability accompanies a\ncopy of the Program in return for a fee.\n\n                     END OF TERMS AND CONDITIONS\n\n            How to Apply These Terms to Your New Programs\n\n  If you develop a new program, and you want it to be of the greatest\npossible use to the public, the best way to achieve this is to make it\nfree software which everyone can redistribute and change under these terms.\n\n  To do so, attach the following notices to the program.  It is safest\nto attach them to the start of each source file to most effectively\nstate the exclusion of warranty; and each file should have at least\nthe \"copyright\" line and a pointer to where the full notice is found.\n\n    <one line to give the program's name and a brief idea of what it does.>\n    Copyright (C) <year>  <name of author>\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\nAlso add information on how to contact you by electronic and paper mail.\n\n  If the program does terminal interaction, make it output a short\nnotice like this when it starts in an interactive mode:\n\n    <program>  Copyright (C) <year>  <name of author>\n    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\n    This is free software, and you are welcome to redistribute it\n    under certain conditions; type `show c' for details.\n\nThe hypothetical commands `show w' and `show c' should show the appropriate\nparts of the General Public License.  Of course, your program's commands\nmight be different; for a GUI interface, you would use an \"about box\".\n\n  You should also get your employer (if you work as a programmer) or school,\nif any, to sign a \"copyright disclaimer\" for the program, if necessary.\nFor more information on this, and how to apply and follow the GNU GPL, see\n<http://www.gnu.org/licenses/>.\n\n  The GNU General Public License does not permit incorporating your program\ninto proprietary programs.  If your program is a subroutine library, you\nmay consider it more useful to permit linking proprietary applications with\nthe library.  If this is what you want to do, use the GNU Lesser General\nPublic License instead of this License.  But first, please read\n<http://www.gnu.org/philosophy/why-not-lgpl.html>."
  },
  {
    "path": "README.md",
    "content": "Hello! :wave: \n\nThis project has been archived, for now. For those not aware, there is an [official Hogs of War remaster](https://www.hogsofwar.org/reheated) currently in the works which seems likely to fulfil many of the goals this project set out to accomplish. Rather than compete with that, I've decided to move on to do my own thing.\n\nThis repository will remain, just on the chance that there's a reason to return to it or someone finds something here useful. Thanks to all that contributed and helped out too! :heart:\n\nRegardless of whether or not I ever return to this, this was a really enlightening project to work on. I met a lot of great folks and learnt a lot about engine design and reverse engineering. That said, I've also learnt a lot _since_ and if I _do_ return to this particular project, much of what's here will probably be thrown out a window.\n\nIf you're interested to see what I'm working on next, feel free to check out my blog [here](https://www.hogsy.me/), otherwise thanks for checking the project out! :smile:\n\n----\n\n# OpenHoW\n\n[![Project Stats](https://www.openhub.net/p/openhow/widgets/project_thin_badge.gif)](https://www.openhub.net/p/openhow) \n\n[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2FTalonBraveInfo%2FOpenHoW.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.com%2FTalonBraveInfo%2FOpenHoW?ref=badge_shield)\n[![CodeFactor](https://www.codefactor.io/repository/github/talonbraveinfo/openhow/badge)](https://www.codefactor.io/repository/github/talonbraveinfo/openhow)\n[![Build Status](https://badge.buildkite.com/91e09e49d899659cf45b4898c8aaeb9d5927f2a7b23eaafb28.svg)](https://buildkite.com/solemnwarning/openhow)\n[![version](https://img.shields.io/github/release-pre/TalonBraveInfo/OpenHoW)](https://github.com/TalonBraveInfo/OpenHoW/releases/latest)\n\n## What's this? :pig:\nOpenHoW aims to be an open-source reimplementation of [Hogs of War](https://en.wikipedia.org/wiki/Hogs_of_War),\na turn-based strategy game produced by [Gremlin Interactive](https://en.wikipedia.org/wiki/Gremlin_Interactive).\n\nThe entire project is being built from the ground up, supporting \ncontent from the PC release of the game, and \nthe end goal will be to produce a completely open and free \nversion of the game, featuring completely new assets to \nreplace those of the original (think \n[FreeDOOM](https://freedoom.github.io/)).\n\n## Features :page_with_curl:\nConsider this more of a wish-list at this  point in time ;)\n* Support for Windows and Linux, with possibly more to follow!\n* An editor to allow for easy modification of game data\n* Enhanced graphics over the original game\n\n## Status :mag:\n![Screenshot](./preview/preview00.png?raw=true)\n\nAs of October 1st, 2019, the project is still in a very early phase of development.\nAs we shift onto our next milestone (0.5.0) a lot of work will begin on actually getting\nthe game into a basic playable form.\n\nThe current goal is to get the game into a rough playable state.\n\n## Contributing :hammer:\nInterested in contributing to the project? Know C/C++ and looking to get deep down\ninto some code? Then what are you waiting for!?\n\nThe best place right now to get in touch is through our [Discord](https://discord.gg/EdmwgVk),\nand makes things a hell of a lot easier to coordinate and collaborate as well. If you're\ninterested then jump on in!\n\nOtherwise if you're just simply interested in the progression of the project, you too\nare more than welcome to join us. :smirk:\n\n### Getting Started\n\nHere's a rough guide to getting up and running.\n\nThere are several requirements in order to compile the project successfully, each of which\nhave been listed below.\n\n* [CMake](https://cmake.org/) (needed for project generation)\n* [SDL2](https://www.libsdl.org/) (needed for input, window creation and audio)\n* [OpenAL Soft](https://github.com/kcat/openal-soft) (needed for audio)\n\nAt this time with these dependencies the project should compile for Linux (_Ubuntu 19.10_: ```apt install cmake libglew-dev libopenal-dev libsdl2-dev```)\nbut Windows needs some further care before it will be up and running correctly (see Windows section below).\n\nOnce compiled, you need to use the [extraction](https://github.com/TalonBraveInfo/OpenHoW/tree/master/src/tools/extractor) utility: point it to your Hogs of War installation directory. The tool will then copy across and update any of the original Hogs of War's assets as necessary. If you want the files to be copied over somewhere else, add `-<output-dir>` after specifying your Hogs of War directory, but the default ```bin``` directory is required to get OpenHoW up and running.\n\n\n#### Linux\n\n```\ngit clone https://github.com/TalonBraveInfo/OpenHoW.git\ncd OpenHoW\ngit submodule update --init\nmkdir build\ncd build\ncmake ../\n```\n\n#### Windows\n\nOn Windows, the project has been successfully compiled against [MinGW 64-bit](https://mingw-w64.org/doku.php/download/mingw-builds). One additional step\nyou may need to perform is to download a copy of the [SDL2 development libraries](https://www.libsdl.org/release/SDL2-devel-2.0.9-mingw.tar.gz)\nfor MinGW 64-bit.\n\nAfter you've downloaded these files, place the 'include' and 'lib' directories under 'SDL2-2.0.9/x86_64-w64-mingw32'\nin a new 'SDL2' directory under 'src/3rdparty'.\n\nThis will be changing at a later point to make things a little easier.\n\n#### C/C++ Style Guide\n\nA style guide is available [here](https://github.com/TalonBraveInfo/OpenHoW/tree/master/doc/coding_style.md).\n\nAt the moment the project is a mess of different styles, which is very much an unfortunate side effect of\nexperimenting with different styles during earlier stages of development.\n\n"
  },
  {
    "path": "bin/CREDITS",
    "content": "OpenHoW Icon\n\tCreated by NAMELESS\n\thttps://www.fiverr.com/s2/088679c4e8\n"
  },
  {
    "path": "bin/gamecontrollerdb.txt",
    "content": "# Game Controller DB for SDL in 2.0.6 format\n# Source: https://github.com/gabomdq/SDL_GameControllerDB\n\n# Windows\n03000000fa2d00000100000000000000,3DRUDDER,leftx:a0,lefty:a1,rightx:a5,righty:a2,platform:Windows,\n03000000022000000090000000000000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,\n03000000203800000900000000000000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,\n03000000102800000900000000000000,8Bitdo SFC30 GamePad,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows,\n03000000a00500003232000000000000,8Bitdo Zero GamePad,a:b0,b:b1,back:b10,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Windows,\n030000008f0e00001200000000000000,Acme,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Windows,\n03000000341a00003608000000000000,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n03000000c01100001352000000000000,Battalife Joystick,a:b6,b:b7,back:b2,leftshoulder:b0,leftx:a0,lefty:a1,rightshoulder:b1,start:b3,x:b4,y:b5,platform:Windows,\n030000006b1400000055000000000000,bigben ps3padstreetnew,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,\n0300000066f700000500000000000000,BrutalLegendTest,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b3,platform:Windows,\n03000000d81d00000b00000000000000,BUFFALO BSGP1601 Series ,a:b5,b:b3,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b9,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b13,x:b4,y:b2,platform:Windows,\n03000000e82000006058000000000000,Cideko AK08b,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,\n030000005e0400008e02000000000000,Controller (XBOX 360 For Windows),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,\n03000000260900008888000000000000,Cyber Gadget GameCube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a4,rightx:a2,righty:a3~,start:b7,x:b2,y:b3,platform:Windows,\n03000000a306000022f6000000000000,Cyborg V.3 Rumble Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:-a3,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Windows,\n030000004f04000023b3000000000000,Dual Trigger 3-in-1,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,\n03000000341a00000108000000000000,EXEQ RF USB Gamepad 8206,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,\n030000000d0f00008500000000000000,Fighting Commander 2016 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n030000000d0f00008400000000000000,Fighting Commander 5,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,\n030000000d0f00008800000000000000,Fighting Stick mini 4,a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b8,x:b0,y:b3,platform:Windows,\n030000000d0f00008700000000000000,Fighting Stick mini 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,\n030000000d0f00002700000000000000,FIGHTING STICK V3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,\n78696e70757403000000000000000000,Fightstick TES,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,start:b7,x:b2,y:b3,platform:Windows,\n03000000790000000600000000000000,G-Shark GS-GP702,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b3,y:b0,platform:Windows,\n03000000260900002625000000000000,Gamecube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,lefttrigger:a4,leftx:a0,lefty:a1,righttrigger:a5,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Windows,\n030000008f0e00000d31000000000000,GAMEPAD 3 TURBO,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n03000000280400000140000000000000,GamePad Pro USB,a:b1,b:b2,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,\n03000000ffff00000000000000000000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,\n03000000451300000010000000000000,Generic USB Joystick,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,\n03000000341a00000302000000000000,Hama Scorpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n030000000d0f00004900000000000000,Hatsune Miku Sho Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n03000000d81400000862000000000000,HitBox Edition Cthulhu+,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,lefttrigger:b4,rightshoulder:b7,righttrigger:b6,start:b9,x:b0,y:b3,platform:Windows,\n030000000d0f00005f00000000000000,Hori Fighting Commander 4 (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n030000000d0f00005e00000000000000,Hori Fighting Commander 4 (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,\n030000000d0f00004000000000000000,Hori Fighting Stick Mini 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,lefttrigger:b4,rightshoulder:b7,righttrigger:b6,start:b9,x:b0,y:b3,platform:Windows,\n030000000d0f00006e00000000000000,HORIPAD 4 (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n030000000d0f00006600000000000000,HORIPAD 4 (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,\n030000000d0f0000ee00000000000000,HORIPAD mini4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b13,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,\n030000000d0f00004d00000000000000,HORIPAD3 A,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n03000000250900000017000000000000,HRAP2 on PS/SS/N64 Joypad to USB BOX,a:b2,b:b1,back:b9,leftshoulder:b5,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b6,start:b8,x:b3,y:b0,platform:Windows,\n030000008f0e00001330000000000000,HuiJia SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b9,x:b3,y:b0,platform:Windows,\n03000000d81d00000f00000000000000,iBUFFALO BSGP1204 Series,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,\n03000000d81d00001000000000000000,iBUFFALO BSGP1204P Series,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,\n03000000830500006020000000000000,iBuffalo SNES Controller,a:b1,b:b0,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Windows,\n03000000b50700001403000000000000,IMPACT BLACK,a:b2,b:b3,back:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows,\n030000006f0e00002401000000000000,INJUSTICE FightStick for PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,\n03000000491900000204000000000000,Ipega PG-9023,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,\n030000006d04000011c2000000000000,Logitech Cordless Wingman,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b5,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b2,righttrigger:b7,rightx:a3,righty:a4,x:b4,platform:Windows,\n030000006d04000016c2000000000000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n030000006d04000018c2000000000000,Logitech F510 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n030000006d04000019c2000000000000,Logitech F710 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n03000000380700005032000000000000,Mad Catz FightPad PRO (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n03000000380700005082000000000000,Mad Catz FightPad PRO (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,\n03000000380700008433000000000000,Mad Catz FightStick TE S+ PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,\n03000000380700008483000000000000,Mad Catz FightStick TE S+ PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b6,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,\n03000000380700008134000000000000,Mad Catz FightStick TE2+ PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b7,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b4,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n03000000380700008184000000000000,Mad Catz FightStick TE2+ PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,leftstick:b10,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,\n03000000380700008034000000000000,Mad Catz TE2 PS3 Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n03000000380700008084000000000000,Mad Catz TE2 PS4 Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,\n03000000380700008532000000000000,Madcatz Arcade Fightstick TE S PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n03000000380700003888000000000000,Madcatz Arcade Fightstick TE S+ PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n03000000380700001888000000000000,MadCatz SFIV FightStick PS3,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b4,righttrigger:b6,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,\n03000000380700008081000000000000,MADCATZ SFV Arcade FightStick Alpha PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,\n030000008305000031b0000000000000,MaxfireBlaze3,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,\n03000000250900000128000000000000,Mayflash Arcade Stick,a:b1,b:b2,back:b8,leftshoulder:b0,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b3,righttrigger:b7,start:b9,x:b5,y:b6,platform:Windows,\n03000000790000004418000000000000,Mayflash GameCube Controller,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Windows,\n03000000790000004318000000000000,Mayflash GameCube Controller Adapter,a:b1,b:b2,back:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b0,leftshoulder:b4,leftstick:b0,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b0,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Windows,\n030000008f0e00001030000000000000,Mayflash USB Adapter for original Sega Saturn controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b5,rightshoulder:b2,righttrigger:b7,start:b9,x:b3,y:b4,platform:Windows,\n0300000025090000e803000000000000,Mayflash Wii Classic Controller,a:b1,b:b0,back:b8,dpdown:b13,dpleft:b12,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Windows,\n03000000790000000018000000000000,Mayflash WiiU Pro Game Controller Adapter (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n030000001008000001e5000000000000,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b6,start:b9,x:b3,y:b0,platform:Windows,\n03000000bd12000015d0000000000000,Nintendo Retrolink USB Super SNES Classic Controller,a:b2,b:b1,back:b8,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Windows,\n030000007e0500000920000000000000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,\n030000004b120000014d000000000000,NYKO AIRFLO,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:a3,leftstick:a0,lefttrigger:b6,leftx:h0.6,lefty:h0.12,rightshoulder:b5,rightstick:a2,righttrigger:b7,rightx:h0.9,righty:h0.4,start:b9,x:b2,y:b3,platform:Windows,\n03000000362800000100000000000000,OUYA Game Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:b13,rightx:a3,righty:a4,x:b1,y:b2,platform:Windows,\n03000000120c0000f60e000000000000,P4 Wired Gamepad,a:b1,b:b2,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b5,lefttrigger:b7,rightshoulder:b4,righttrigger:b6,start:b9,x:b0,y:b3,platform:Windows,\n030000008f0e00000300000000000000,Piranha xtreme,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows,\n03000000d62000006dca000000000000,PowerA Pro Ex,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n030000008f0e00007530000000000000,PS (R) Gamepad,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b1,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n03000000e30500009605000000000000,PS to USB convert cable,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows,\n03000000100800000100000000000000,PS1 USB,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows,\n03000000100800000300000000000000,PS2 USB,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a4,righty:a2,start:b9,x:b3,y:b0,platform:Windows,\n03000000888800000803000000000000,PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.8,dpleft:h0.4,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b9,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b0,y:b3,platform:Windows,\n030000004c0500006802000000000000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Windows,\n03000000250900000500000000000000,PS3 DualShock,a:b2,b:b1,back:b9,dpdown:h0.8,dpleft:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b0,y:b3,platform:Windows,\n03000000100000008200000000000000,PS360+ v1.66,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:h0.4,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,\n030000004c050000a00b000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,\n030000004c050000c405000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,\n030000004c050000cc09000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,\n03000000300f00000011000000000000,QanBa Arcade JoyStick 1008,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b10,x:b0,y:b3,platform:Windows,\n03000000300f00001611000000000000,QanBa Arcade JoyStick 4018,a:b1,b:b2,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b8,x:b0,y:b3,platform:Windows,\n03000000222c00000020000000000000,QANBA DRONE ARCADE JOYSTICK,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,rightshoulder:b5,righttrigger:a4,start:b9,x:b0,y:b3,platform:Windows,\n03000000300f00001210000000000000,QanBa Joystick Plus,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Windows,\n03000000341a00000104000000000000,QanBa Joystick Q4RAF,a:b5,b:b6,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b0,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b3,righttrigger:b7,start:b9,x:b1,y:b2,platform:Windows,\n03000000222c00000223000000000000,Qanba Obsidian Arcade Joystick PS3 Mode,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n03000000222c00000023000000000000,Qanba Obsidian Arcade Joystick PS4 Mode,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,\n03000000321500000003000000000000,Razer Hydra,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,\n030000000d0f00001100000000000000,REAL ARCADE PRO.3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,\n030000000d0f00008b00000000000000,Real Arcade Pro.4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n030000000d0f00008a00000000000000,Real Arcade Pro.4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,\n030000000d0f00006b00000000000000,Real Arcade Pro.4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n030000000d0f00006a00000000000000,Real Arcade Pro.4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,\n030000000d0f00007000000000000000,REAL ARCADE PRO.4 VLX,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,\n030000000d0f00002200000000000000,REAL ARCADE Pro.V3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n030000000d0f00005c00000000000000,Real Arcade Pro.V4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n030000000d0f00005b00000000000000,Real Arcade Pro.V4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,\n03000000790000001100000000000000,Retrolink SNES Controller,a:b2,b:b1,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Windows,\n0300000000f000000300000000000000,RetroUSB.com RetroPad,a:b1,b:b5,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Windows,\n0300000000f00000f100000000000000,RetroUSB.com Super RetroPort,a:b1,b:b5,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Windows,\n030000006b140000010d000000000000,Revolution Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,\n030000006f0e00001e01000000000000,Rock Candy Gamepad for PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n030000004f04000003d0000000000000,run'n'drive,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b7,leftshoulder:a3,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:a4,rightstick:b11,righttrigger:b5,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,\n03000000a30600001af5000000000000,Saitek Cyborg,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows,\n03000000a306000023f6000000000000,Saitek Cyborg V.1 Game pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Windows,\n03000000300f00001201000000000000,Saitek Dual Analog Pad,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows,\n03000000a30600000cff000000000000,Saitek P2500 Force Rumble Pad,a:b2,b:b3,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,x:b0,y:b1,platform:Windows,\n03000000a30600000c04000000000000,Saitek P2900,a:b1,b:b2,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b3,platform:Windows,\n03000000300f00001001000000000000,Saitek P480 Rumble Pad,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows,\n03000000a30600000b04000000000000,Saitek P990,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b3,platform:Windows,\n03000000a30600000b04000000010000,Saitek P990 Dual Analog Pad,a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b8,x:b0,y:b3,platform:Windows,\n03000000300f00001101000000000000,saitek rumble pad,a:b2,b:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows,\n0300000000050000289b000000000000,Saturn_Adapter_2.0,a:b1,b:b2,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b0,y:b3,platform:Windows,\n030000009b2800000500000000000000,Saturn_Adapter_2.0,a:b1,b:b2,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b0,y:b3,platform:Windows,\n03000000341a00000208000000000000,SL-6555-SBK,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:-a4,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a4,rightx:a3,righty:a2,start:b7,x:b2,y:b3,platform:Windows,\n030000008f0e00000800000000000000,SpeedLink Strike FX Wireless,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,\n03000000ff1100003133000000000000,SVEN X-PAD,a:b2,b:b3,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a4,start:b5,x:b0,y:b1,platform:Windows,\n03000000fa1900000706000000000000,Team 5,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,\n03000000b50700001203000000000000,Techmobility X6-38V,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows,\n030000004f04000015b3000000000000,Thrustmaster Dual Analog 2,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows,\n030000004f04000000b3000000000000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b11,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b1,y:b3,platform:Windows,\n030000004f04000004b3000000000000,Thrustmaster Firestorm Dual Power 3,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows,\n03000000666600000488000000000000,TigerGame PS/PS2 Game Controller Adapter,a:b2,b:b1,back:b9,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows,\n03000000d90400000200000000000000,TwinShock PS2,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows,\n03000000380700006652000000000000,UnKnown,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows,\n03000000632500002305000000000000,USB Vibration Joystick (BM),a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,\n03000000790000001b18000000000000,Venom Arcade Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,\n03000000450c00002043000000000000,XEOX Gamepad SL-6556-BK,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,\n03000000172700004431000000000000,XiaoMi Game Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b20,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a7,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows,\nxinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,\n03000000786901006e70000000000000,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,\n\n# Mac OS X\n03000000203800000900000000010000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,\n03000000022000000090000001000000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,\n03000000102800000900000000000000,8Bitdo SFC30 GamePad Joystick,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X,\n03000000a00500003232000008010000,8Bitdo Zero GamePad,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Mac OS X,\n030000008305000031b0000000000000,Cideko AK08b,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,\n03000000260900008888000088020000,Cyber Gadget GameCube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a5,rightx:a2,righty:a3~,start:b7,x:b2,y:b3,platform:Mac OS X,\n03000000a306000022f6000001030000,Cyborg V.3 Rumble Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:-a3,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Mac OS X,\n03000000790000000600000000000000,G-Shark GP-702,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b3,y:b0,platform:Mac OS X,\n03000000ad1b000001f9000000000000,Gamestop BB-070 X360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,\n0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X,\n030000000d0f00005f00000000010000,Hori Fighting Commander 4 (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,\n030000000d0f00005e00000000010000,Hori Fighting Commander 4 (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,\n030000000d0f00005f00000000000000,HORI Fighting Commander 4 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,\n030000000d0f00005e00000000000000,HORI Fighting Commander 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,\n030000000d0f00004d00000000000000,HORI Gem Pad 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,\n030000000d0f00006e00000000010000,HORIPAD 4 (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,\n030000000d0f00006600000000010000,HORIPAD 4 (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,\n030000000d0f00006600000000000000,HORIPAD FPS PLUS 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,\n030000008f0e00001330000011010000,HuiJia SNES Controller,a:b4,b:b2,back:b16,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,leftshoulder:b12,rightshoulder:b14,start:b18,x:b6,y:b0,platform:Mac OS X,\n03000000830500006020000000010000,iBuffalo SNES Controller,a:b1,b:b0,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Mac OS X,\n03000000830500006020000000000000,iBuffalo USB 2-axis 8-button Gamepad,a:b1,b:b0,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Mac OS X,\n030000006d04000016c2000000020000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,\n030000006d04000016c2000000030000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,\n030000006d04000016c2000014040000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,\n030000006d04000016c2000000000000,Logitech F310 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,\n030000006d04000018c2000000000000,Logitech F510 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,\n030000006d0400001fc2000000000000,Logitech F710 Gamepad (XInput),a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,\n030000006d04000019c2000000000000,Logitech Wireless Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,\n03000000380700005032000000010000,Mad Catz FightPad PRO (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,\n03000000380700005082000000010000,Mad Catz FightPad PRO (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,\n03000000790000004418000000010000,Mayflash GameCube Controller,a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Mac OS X,\n0300000025090000e803000000000000,Mayflash Wii Classic Controller,a:b1,b:b0,back:b8,dpdown:b13,dpleft:b12,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Mac OS X,\n03000000790000000018000000000000,Mayflash WiiU Pro Game Controller Adapter (DInput),a:b4,b:b8,back:b32,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b16,leftstick:b40,lefttrigger:b24,leftx:a0,lefty:a4,rightshoulder:b20,rightstick:b44,righttrigger:b28,rightx:a8,righty:a12,start:b36,x:b0,y:b12,platform:Mac OS X,\n03000000d8140000cecf000000000000,MC Cthulhu,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X,\n030000001008000001e5000006010000,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b6,start:b9,x:b3,y:b0,platform:Mac OS X,\n030000007e0500000920000000000000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X,\n030000008f0e00000300000000000000,Piranha xtreme,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Mac OS X,\n030000004c0500006802000000010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Mac OS X,\n030000004c0500006802000000000000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Mac OS X,\n030000004c050000a00b000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,\n030000004c050000cc09000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,\n030000004c050000c405000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,\n030000004c050000c405000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,\n030000008916000000fd000000000000,Razer Onza TE,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,\n03000000321500000010000000010000,Razer RAIJU,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,\n0300000032150000030a000000000000,Razer Wildcat,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,\n03000000790000001100000000000000,Retrolink Classic Controller,a:b2,b:b1,back:b8,leftshoulder:b4,leftx:a3,lefty:a4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Mac OS X,\n03000000790000001100000006010000,Retrolink SNES Controller,a:b2,b:b1,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Mac OS X,\n030000006b140000010d000000010000,Revolution Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,\n03000000811700007e05000000000000,Sega Saturn,a:b2,b:b4,dpdown:b16,dpleft:b15,dpright:b14,dpup:b17,leftshoulder:b8,lefttrigger:a5,leftx:a0,lefty:a2,rightshoulder:b9,righttrigger:a4,start:b13,x:b0,y:b6,platform:Mac OS X,\n03000000b40400000a01000000000000,Sega Saturn USB Gamepad,a:b0,b:b1,back:b5,guide:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b8,x:b3,y:b4,platform:Mac OS X,\n030000003512000021ab000000000000,SFC30 Joystick,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X,\n030000004c050000cc09000000000000,Sony DualShock 4 V2,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,\n030000004c050000a00b000000000000,Sony DualShock 4 Wireless Adaptor,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,\n030000005e0400008e02000001000000,Steam Virtual GamePad,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,\n03000000110100002014000000000000,SteelSeries Nimbus,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b12,x:b2,y:b3,platform:Mac OS X,\n03000000110100002014000001000000,SteelSeries Nimbus,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,x:b2,y:b3,platform:Mac OS X,\n03000000381000002014000001000000,SteelSeries Nimbus,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,x:b2,y:b3,platform:Mac OS X,\n03000000110100001714000000000000,SteelSeries Stratus XL,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,start:b12,x:b2,y:b3,platform:Mac OS X,\n03000000110100001714000020010000,SteelSeries Stratus XL,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,start:b12,x:b2,y:b3,platform:Mac OS X,\n030000004f04000015b3000000000000,Thrustmaster Dual Analog 3.2,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Mac OS X,\n030000004f04000000b3000000000000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b11,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b1,y:b3,platform:Mac OS X,\n03000000bd12000015d0000000010000,Tomee SNES USB Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Mac OS X,\n03000000bd12000015d0000000000000,Tomee SNES USB Controller,a:b2,b:b1,back:b8,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Mac OS X,\n03000000100800000100000000000000,Twin USB Joystick,a:b4,b:b2,back:b16,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b12,leftstick:b20,lefttrigger:b8,leftx:a0,lefty:a2,rightshoulder:b14,rightstick:b22,righttrigger:b10,rightx:a6,righty:a4,start:b18,x:b6,y:b0,platform:Mac OS X,\n050000005769696d6f74652028303000,Wii Remote,a:b4,b:b5,back:b7,dpdown:b3,dpleft:b0,dpright:b1,dpup:b2,guide:b8,leftshoulder:b11,lefttrigger:b12,leftx:a0,lefty:a1,start:b6,x:b10,y:b9,platform:Mac OS X,\n050000005769696d6f74652028313800,Wii U Pro Controller,a:b16,b:b15,back:b7,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b8,leftshoulder:b19,leftstick:b23,lefttrigger:b21,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b24,righttrigger:b22,rightx:a2,righty:a3,start:b6,x:b18,y:b17,platform:Mac OS X,\n030000005e0400008e02000000000000,X360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,\n03000000c6240000045d000000000000,Xbox 360 Wired Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,\n030000005e040000e302000000000000,Xbox One Wired Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,\n030000005e040000d102000000000000,Xbox One Wired Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,\n030000005e040000dd02000000000000,Xbox One Wired Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,\n030000005e040000e002000000000000,Xbox Wireless Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Mac OS X,\n030000005e040000fd02000003090000,Xbox Wireless Controller,a:b0,b:b1,back:b16,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,\n030000005e040000ea02000000000000,Xbox Wireless Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,\n030000005e040000e002000003090000,Xbox Wireless Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Mac OS X,\n03000000172700004431000029010000,XiaoMi Game Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a6,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Mac OS X,\n03000000120c0000100e000000010000,ZEROPLUS P4 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,\n\n# Linux\n05000000203800000900000000010000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,\n03000000022000000090000011010000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,\n05000000c82d00002038000000010000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,\n03000000c82d00000190000011010000,8Bitdo NES30 Pro 8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,\n05000000c82d00003028000000010000,8Bitdo SFC30 GamePad,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux,\n05000000102800000900000000010000,8Bitdo SFC30 GamePad,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux,\n05000000a00500003232000008010000,8Bitdo Zero GamePad,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Linux,\n05000000a00500003232000001000000,8Bitdo Zero GamePad,a:b0,b:b1,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Linux,\n030000006f0e00003901000020060000,Afterglow Wired Controller for Xbox One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n03000000100000008200000011010000,Akishop Customs PS360+ v1.66,a:b1,b:b2,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,\n05000000050b00000045000031000000,ASUS Gamepad,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b10,x:b2,y:b3,platform:Linux,\n03000000666600006706000000010000,boom PSX to PC Converter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a2,righty:a3,start:b11,x:b3,y:b0,platform:Linux,\n03000000e82000006058000001010000,Cideko AK08b,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,\n03000000260900008888000000010000,Cyber Gadget GameCube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a5,rightx:a2,righty:a3~,start:b7,x:b2,y:b3,platform:Linux,\n03000000a306000022f6000011010000,Cyborg V.3 Rumble Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:-a3,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Linux,\n03000000b40400000a01000000010000,CYPRESS USB Gamepad,a:b0,b:b1,back:b5,guide:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b8,x:b3,y:b4,platform:Linux,\n03000000790000000600000010010000,DragonRise Inc. Generic USB Joystick,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b3,y:b0,platform:Linux,\n030000006f0e00003001000001010000,EA Sports PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,\n03000000341a000005f7000010010000,GameCube {HuiJia USB box},a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Linux,\n0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,\n030000006f0e00000104000000010000,Gamestop Logic3 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n030000006f0e00001304000000010000,Generic X-Box pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:a0,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:a3,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n030000006f0e00001f01000000010000,Generic X-Box pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n03000000f0250000c183000010010000,Goodbetterbest Ltd USB Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,\n03000000280400000140000000010000,Gravis GamePad Pro USB ,a:b1,b:b2,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,\n030000008f0e00000610000000010000,GreenAsia Electronics 4Axes 12Keys GamePad ,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a3,righty:a2,start:b11,x:b3,y:b0,platform:Linux,\n030000008f0e00001200000010010000,GreenAsia Inc. USB Joystick,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Linux,\n030000008f0e00000300000010010000,GreenAsia Inc. USB Joystick,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux,\n0500000047532067616d657061640000,GS gamepad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,\n06000000adde0000efbe000002010000,Hidromancer Game Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n03000000d81400000862000011010000,HitBox (PS3/PC) Analog Mode,a:b1,b:b2,back:b8,guide:b9,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b12,x:b0,y:b3,platform:Linux,\n03000000c9110000f055000011010000,HJC Game GAMEPAD,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,\n030000000d0f00000d00000000010000,hori,a:b0,b:b6,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b3,leftx:b4,lefty:b5,rightshoulder:b7,start:b9,x:b1,y:b2,platform:Linux,\n030000000d0f00001000000011010000,HORI CO. LTD. FIGHTING STICK 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,\n030000000d0f00006a00000011010000,HORI CO. LTD. Real Arcade Pro.4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,\n030000000d0f00006b00000011010000,HORI CO. LTD. Real Arcade Pro.4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,\n030000000d0f00002200000011010000,HORI CO. LTD. REAL ARCADE Pro.V3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,\n030000000d0f00005f00000011010000,Hori Fighting Commander 4 (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,\n030000000d0f00005e00000011010000,Hori Fighting Commander 4 (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,\n03000000ad1b000001f5000033050000,Hori Pad EX Turbo 2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n030000000d0f00006e00000011010000,HORIPAD 4 (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,\n030000000d0f00006600000011010000,HORIPAD 4 (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,\n030000000d0f00006700000001010000,HORIPAD ONE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n030000008f0e00001330000010010000,HuiJia SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b9,x:b3,y:b0,platform:Linux,\n03000000830500006020000010010000,iBuffalo SNES Controller,a:b1,b:b0,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Linux,\n050000006964726f69643a636f6e0000,idroid:con,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,\n03000000b50700001503000010010000,impact,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Linux,\n03000000fd0500000030000000010000,InterAct GoPad I-73000 (Fighting Game Layout),a:b3,b:b4,back:b6,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,start:b7,x:b0,y:b1,platform:Linux,\n030000006e0500000320000010010000,JC-U3613M - DirectInput Mode,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Linux,\n03000000300f00001001000010010000,Jess Tech Dual Analog Rumble Pad,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Linux,\n03000000ba2200002010000001010000,Jess Technology USB Game Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux,\n030000006f0e00000103000000020000,Logic3 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n030000006d04000019c2000010010000,Logitech Cordless RumblePad 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,\n030000006d04000016c2000011010000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,\n030000006d04000016c2000010010000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,\n030000006d0400001dc2000014400000,Logitech F310 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n030000006d0400001ec2000020200000,Logitech F510 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n030000006d04000019c2000011010000,Logitech F710 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,\n030000006d0400001fc2000005030000,Logitech F710 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n030000006d04000015c2000010010000,Logitech Logitech Extreme 3D,a:b0,b:b4,back:b6,guide:b8,leftshoulder:b9,leftstick:h0.8,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:h0.2,start:b7,x:b2,y:b5,platform:Linux,\n030000006d04000018c2000010010000,Logitech RumblePad 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,\n030000006d04000011c2000010010000,Logitech WingMan Cordless RumblePad,a:b0,b:b1,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b6,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b10,rightx:a3,righty:a4,start:b8,x:b3,y:b4,platform:Linux,\n05000000380700006652000025010000,Mad Catz C.T.R.L.R ,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,\n03000000380700005032000011010000,Mad Catz FightPad PRO (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,\n03000000380700005082000011010000,Mad Catz FightPad PRO (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,\n03000000ad1b00002ef0000090040000,Mad Catz Fightpad SFxT,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,start:b7,x:b2,y:b3,platform:Linux,\n03000000380700008034000011010000,Mad Catz fightstick (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,\n03000000380700008084000011010000,Mad Catz fightstick (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,\n03000000380700008433000011010000,Mad Catz FightStick TE S+ PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,\n03000000380700008483000011010000,Mad Catz FightStick TE S+ PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,\n03000000380700001647000010040000,Mad Catz Wired Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n03000000380700003847000090040000,Mad Catz Wired Xbox 360 Controller (SFIV),a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,\n03000000ad1b000016f0000090040000,Mad Catz Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n03000000380700001888000010010000,MadCatz PC USB Wired Stick 8818,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,\n03000000380700003888000010010000,MadCatz PC USB Wired Stick 8838,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:a0,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,\n03000000790000004418000010010000,Mayflash GameCube Controller,a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Linux,\n03000000780000000600000010010000,Microntek USB Joystick,a:b2,b:b1,back:b8,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux,\n030000005e0400008e02000004010000,Microsoft X-Box 360 pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n030000005e0400008e02000062230000,Microsoft X-Box 360 pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n030000005e040000d102000001010000,Microsoft X-Box One pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n030000005e040000d102000003020000,Microsoft X-Box One pad v2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n030000005e0400008502000000010000,Microsoft X-Box pad (Japan),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux,\n030000005e0400008902000021010000,Microsoft X-Box pad v2 (US),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux,\n05000000d6200000ad0d000001000000,Moga Pro,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Linux,\n030000001008000001e5000010010000,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b6,start:b9,x:b3,y:b0,platform:Linux,\n050000007e0500000920000001000000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,\n050000007e0500003003000001000000,Nintendo Wii Remote Pro Controller,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Linux,\n05000000010000000100000003000000,Nintendo Wiimote,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,\n030000000d0500000308000010010000,Nostromo n45 Dual Analog Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b12,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b10,x:b2,y:b3,platform:Linux,\n03000000550900001072000011010000,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b13,leftshoulder:b4,leftstick:b8,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux,\n03000000451300000830000010010000,NYKO CORE,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,\n030000005e0400000202000000010000,Old Xbox pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux,\n05000000362800000100000002010000,OUYA Game Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2,platform:Linux,\n05000000362800000100000003010000,OUYA Game Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2,platform:Linux,\n03000000ff1100003133000010010000,PC Game Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,\n030000006f0e00006401000001010000,PDP Battlefield One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n03000000ff1100004133000010010000,PS2 Controller,a:b2,b:b1,back:b8,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux,\n030000004c0500006802000010010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux,\n050000004c0500006802000000810000,PS3 Controller,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,\n03000000341a00003608000011010000,PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,\n030000004c0500006802000011810000,PS3 Controller,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,\n050000004c0500006802000000010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:a12,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:a13,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux,\n030000004c0500006802000010810000,PS3 Controller,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,\n030000004c0500006802000011010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux,\n060000004c0500006802000000010000,PS3 Controller (Bluetooth),a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux,\n05000000504c415953544154494f4e00,PS3 Controller (Bluetooth),a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux,\n050000004c050000c405000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,\n030000004c050000a00b000011010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,\n050000004c050000cc09000000810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,\n050000004c050000c405000000810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,\n030000004c050000c405000011810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,\n050000004c050000cc09000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,\n030000004c050000cc09000011010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,\n030000004c050000a00b000011810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,\n030000004c050000cc09000011810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,\n030000004c050000c405000011010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,\n03000000300f00001211000011010000,QanBa Arcade JoyStick,a:b2,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b5,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b6,start:b9,x:b1,y:b3,platform:Linux,\n030000009b2800000300000001010000,raphnet.net 4nes4snes v1.5,a:b0,b:b4,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Linux,\n030000008916000001fd000024010000,Razer Onza Classic Edition,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n030000008916000000fd000024010000,Razer Onza Tournament,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n03000000321500000010000011010000,Razer RAIJU,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,\n03000000c6240000045d000025010000,Razer Sabertooth,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n03000000321500000009000011010000,Razer Serval,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux,\n050000003215000000090000163a0000,Razer Serval,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux,\n0300000032150000030a000001010000,Razer Wildcat,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n03000000790000001100000010010000,Retrolink SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Linux,\n0300000000f000000300000000010000,RetroUSB.com RetroPad,a:b1,b:b5,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Linux,\n0300000000f00000f100000000010000,RetroUSB.com Super RetroPort,a:b1,b:b5,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Linux,\n030000006b140000010d000011010000,Revolution Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,\n030000006f0e00001e01000011010000,Rock Candy Gamepad for PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,\n030000006f0e00004601000001010000,Rock Candy Wired Controller for Xbox One,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n03000000a306000023f6000011010000,Saitek Cyborg V.1 Game Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Linux,\n03000000a30600000cff000010010000,Saitek P2500 Force Rumble Pad,a:b2,b:b3,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,x:b0,y:b1,platform:Linux,\n03000000a30600000c04000011010000,Saitek P2900 Wireless Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b12,x:b0,y:b3,platform:Linux,\n03000000a30600000901000000010000,Saitek P880,a:b2,b:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,x:b0,y:b1,platform:Linux,\n03000000a30600000b04000000010000,Saitek P990 Dual Analog Pad,a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b8,x:b0,y:b3,platform:Linux,\n03000000a306000018f5000010010000,Saitek PLC Saitek P3200 Rumble Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Linux,\n03000000c01600008704000011010000,Serial/Keyboard/Mouse/Joystick,a:b12,b:b10,back:b4,dpdown:b2,dpleft:b3,dpright:b1,dpup:b0,leftshoulder:b9,leftstick:b14,lefttrigger:b6,leftx:a1,lefty:a0,rightshoulder:b8,rightstick:b15,righttrigger:b7,rightx:a2,righty:a3,start:b5,x:b13,y:b11,platform:Linux,\n03000000f025000021c1000010010000,ShanWan Gioteck PS3 Wired Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,\n03000000250900000500000000010000,Sony PS2 pad with SmartJoy adapter,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Linux,\n030000005e0400008e02000073050000,Speedlink TORID Wireless Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n030000005e0400008e02000020200000,SpeedLink XEOX Pro Analog Gamepad pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n03000000de2800000211000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux,\n05000000de2800000511000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux,\n03000000de2800000112000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux,\n05000000de2800000212000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux,\n03000000de280000fc11000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n03000000de2800004211000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux,\n03000000de280000ff11000001000000,Steam Virtual Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n03000000666600000488000000010000,Super Joy Box 5 Pro,a:b2,b:b1,back:b9,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Linux,\n030000004f04000020b3000010010000,Thrustmaster 2 in 1 DT,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Linux,\n030000004f04000015b3000010010000,Thrustmaster Dual Analog 4,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Linux,\n030000004f04000023b3000000010000,Thrustmaster Dual Trigger 3-in-1,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,\n030000004f04000000b3000010010000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b11,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b1,y:b3,platform:Linux,\n030000004f04000008d0000000010000,Thrustmaster Run N Drive Wireless,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,\n030000004f04000009d0000000010000,Thrustmaster Run N Drive Wireless PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,\n03000000bd12000015d0000010010000,Tomee SNES USB Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Linux,\n03000000d814000007cd000011010000,Toodles 2008 Chimp PC/PS3,a:b0,b:b1,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b3,y:b2,platform:Linux,\n03000000100800000100000010010000,Twin USB PS2 Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux,\n03000000100800000300000010010000,USB Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux,\n03000000790000001100000000010000,USB Gamepad1,a:b2,b:b1,back:b8,dpdown:a0,dpleft:a1,dpright:a2,dpup:a4,start:b9,platform:Linux,\n05000000ac0500003232000001000000,VR-BOX,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Linux,\n030000005e0400008e02000014010000,X360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n030000005e0400008e02000010010000,X360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n030000005e0400001907000000010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n030000005e0400009102000007010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n030000005e040000a102000007010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n030000005e040000a102000000010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n0000000058626f782033363020576900,Xbox 360 Wireless Controller,a:b0,b:b1,back:b14,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,guide:b7,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Linux,\n0000000058626f782047616d65706100,Xbox Gamepad (userspace driver),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux,\n050000005e040000e002000003090000,Xbox One Wireless Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n050000005e040000fd02000003090000,Xbox One Wireless Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b16,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,\n03000000450c00002043000010010000,XEOX Gamepad SL-6556-BK,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,\n05000000172700004431000029010000,XiaoMi Game Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b20,leftshoulder:b6,leftstick:b13,lefttrigger:a7,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a6,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Linux,\n03000000c0160000e105000001010000,Xin-Mo Xin-Mo Dual Arcade,a:b4,b:b3,back:b6,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b9,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b1,y:b0,platform:Linux,\nxinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n03000000120c0000100e000011010000,ZEROPLUS P4 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,\n\n# Android\n64633436313965656664373634323364,Microsoft X-Box 360 pad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,x:b2,y:b3,platform:Android,\n61363931656135336130663561616264,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,\n4e564944494120436f72706f72617469,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,\n37336435666338653565313731303834,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,\n35643031303033326130316330353564,PS4 Controller,a:b1,b:b17,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b3,leftstick:b4,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:+a4,rightx:a2,righty:a5,start:b16,x:b0,y:b2,platform:Android,\n05000000de2800000511000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Android,\n5477696e20555342204a6f7973746963,Twin USB Joystick,a:b22,b:b21,back:b28,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b26,leftstick:b30,lefttrigger:b24,leftx:a0,lefty:a1,rightshoulder:b27,rightstick:b31,righttrigger:b25,rightx:a3,righty:a2,start:b29,x:b23,y:b20,platform:Android,\n34356136633366613530316338376136,Xbox Wireless Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b3,leftstick:b15,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b16,righttrigger:a5,rightx:a3,righty:a4,x:b17,y:b2,platform:Android,\n\n# iOS\n4d466947616d65706164010000000000,MFi Extended Gamepad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:iOS,\n4d466947616d65706164020000000000,MFi Gamepad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,rightshoulder:b5,start:b6,x:b2,y:b3,platform:iOS,\n05000000de2800000511000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:iOS,\n"
  },
  {
    "path": "bin/icon.ai",
    "content": "%PDF-1.5\r%\r\n1 0 obj\r<</Metadata 2 0 R/OCProperties<</D<</ON[6 0 R 41 0 R]/Order 42 0 R/RBGroups[]>>/OCGs[6 0 R 41 0 R]>>/Pages 3 0 R/Type/Catalog>>\rendobj\r2 0 obj\r<</Length 22748/Subtype/XML/Type/Metadata>>stream\r\n<?xpacket begin=\"﻿\" id=\"W5M0MpCehiHzreSzNTczkc9d\"?>\n<x:xmpmeta xmlns:x=\"adobe:ns:meta/\" x:xmptk=\"Adobe XMP Core 5.6-c145 79.163499, 2018/08/13-16:40:22        \">\n   <rdf:RDF xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\">\n      <rdf:Description rdf:about=\"\"\n            xmlns:xmp=\"http://ns.adobe.com/xap/1.0/\"\n            xmlns:xmpGImg=\"http://ns.adobe.com/xap/1.0/g/img/\"\n            xmlns:xmpTPg=\"http://ns.adobe.com/xap/1.0/t/pg/\"\n            xmlns:stDim=\"http://ns.adobe.com/xap/1.0/sType/Dimensions#\"\n            xmlns:stFnt=\"http://ns.adobe.com/xap/1.0/sType/Font#\"\n            xmlns:xmpG=\"http://ns.adobe.com/xap/1.0/g/\"\n            xmlns:dc=\"http://purl.org/dc/elements/1.1/\"\n            xmlns:illustrator=\"http://ns.adobe.com/illustrator/1.0/\"\n            xmlns:xmpMM=\"http://ns.adobe.com/xap/1.0/mm/\"\n            xmlns:stEvt=\"http://ns.adobe.com/xap/1.0/sType/ResourceEvent#\"\n            xmlns:pdf=\"http://ns.adobe.com/pdf/1.3/\">\n         <xmp:CreatorTool>Adobe Illustrator CC 23.0 (Windows)</xmp:CreatorTool>\n         <xmp:CreateDate>2019-12-19T21:31:25+02:00</xmp:CreateDate>\n         <xmp:MetadataDate>2019-12-22T21:29:11+01:00</xmp:MetadataDate>\n         <xmp:ModifyDate>2019-12-22T21:29:11+01:00</xmp:ModifyDate>\n         <xmp:Thumbnails>\n            <rdf:Alt>\n               <rdf:li rdf:parseType=\"Resource\">\n                  <xmpGImg:width>244</xmpGImg:width>\n                  <xmpGImg:height>256</xmpGImg:height>\n                  <xmpGImg:format>JPEG</xmpGImg:format>\n                  <xmpGImg:image>/9j/4AAQSkZJRgABAgEASABIAAD/7QAsUGhvdG9zaG9wIDMuMAA4QklNA+0AAAAAABAASAAAAAEA&#xA;AQBIAAAAAQAB/+4ADkFkb2JlAGTAAAAAAf/bAIQABgQEBAUEBgUFBgkGBQYJCwgGBggLDAoKCwoK&#xA;DBAMDAwMDAwQDA4PEA8ODBMTFBQTExwbGxscHx8fHx8fHx8fHwEHBwcNDA0YEBAYGhURFRofHx8f&#xA;Hx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8f/8AAEQgBAAD0AwER&#xA;AAIRAQMRAf/EAaIAAAAHAQEBAQEAAAAAAAAAAAQFAwIGAQAHCAkKCwEAAgIDAQEBAQEAAAAAAAAA&#xA;AQACAwQFBgcICQoLEAACAQMDAgQCBgcDBAIGAnMBAgMRBAAFIRIxQVEGE2EicYEUMpGhBxWxQiPB&#xA;UtHhMxZi8CRygvElQzRTkqKyY3PCNUQnk6OzNhdUZHTD0uIIJoMJChgZhJRFRqS0VtNVKBry4/PE&#xA;1OT0ZXWFlaW1xdXl9WZ2hpamtsbW5vY3R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo+Ck5SVlpeYmZ&#xA;qbnJ2en5KjpKWmp6ipqqusra6voRAAICAQIDBQUEBQYECAMDbQEAAhEDBCESMUEFURNhIgZxgZEy&#xA;obHwFMHR4SNCFVJicvEzJDRDghaSUyWiY7LCB3PSNeJEgxdUkwgJChgZJjZFGidkdFU38qOzwygp&#xA;0+PzhJSktMTU5PRldYWVpbXF1eX1RlZmdoaWprbG1ub2R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo&#xA;+DlJWWl5iZmpucnZ6fkqOkpaanqKmqq6ytrq+v/aAAwDAQACEQMRAD8A9U4q8R/O/wD5Su0/5gI/&#xA;+T02c12z/ej+r+kt2Pk88zUtjsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirs&#xA;VdirsVdirsVdirsVdir6xzu3FeI/nf8A8pXaf8wEf/J6bOa7Z/vR/V/SW7HyeeZqWx2KuxV2KuxV&#xA;2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV9Y53bivEfzv/AOUr&#xA;tP8AmAj/AOT02c12z/ej+r+kt2Pk88zUtjsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsV&#xA;dirsVdirsVdirsVdirsVdirsVdir6xzu3FeI/nf/AMpXaf8AMBH/AMnps5rtn+9H9X9JbsfJ55mp&#xA;bHYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FX1jnd&#xA;uK8R/O//AJSu0/5gI/8Ak9NnNds/3o/q/pLdj5PPM1LY7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7F&#xA;XYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq+sc7txXiP53/8AKV2n/MBH/wAnps5rtn+9H9X9&#xA;JbsfJ55mpbHYq7FXYq7FXYq7FXYq7FXYqoX2oWNhbtc3s6W8C9ZJGCj5b9T7ZOGOUzURZQSwLW/z&#xA;j0u3LRaTbNeuNhPJWKL5gU5t+GbbB2PM7zPCwORhmpfmh5wvSQl0tpGf9126Bf8Ahm5P/wANmyx9&#xA;mYY9L97AzKRy61r969Jb66uGNfhaWR9j12qcyhhxx5AD4MbKlJ+lI15yeui/zNzA+85IcB5Uqpba&#xA;/rtqQbfUbmKn8kzgfcDglp8cucR8lssi0z81fN1mQJpkvYx+xOgrT/WTg331zDy9l4Zchw+5kJlm&#xA;mi/nBoV2Vj1KF9PlO3qf3sX3qAw/4H6c1mbsjJHeJ4vsLMZAzizvbO9gW4tJ0uIG+zLEwdT9IzVT&#xA;hKJqQos7Vsil2KuxV2KuxV2KuxV2KuxV2KvrHO7cV4j+d/8Ayldp/wAwEf8Ayemzmu2f70f1f0lu&#xA;x8nnmalsdirsVdirsVdirsVdirsVYZ50/Miw0IvZWQW71QbMlf3cR/4sI6n/ACR9NM2ei7Oll9Ut&#xA;ofewlOnmkdp5r843/rXE3Ov2Z7lxFAg8EH8EGbszw6aNAfLn+Pe10ZM60b8nNHiVZdTu3vW6mOL9&#xA;3F8q7ufmCM1WbtiZ2iOFmMbLbDyh5YsAv1XTLdWX7MjIJHH+zfk345r8mryz5yLIRCbKiovFQFUd&#xA;ABQZjksm8CqFzp9hdKVubaKdTsVkRXBr/rA5OOSUeRIQxzWvIflSaIy/ohKgHl9WLQsB4qqUU/Ij&#xA;MzDr8wNcXz3RwAsMvPyw0m6BbRtUMUn7NtegCp/4yIP+NTmzh2nOP1x+I/UxOJj02m+dPJt39ZCy&#xA;2gBp9YjPOB/AMRVDXwbfMwZMGpFbH72uiHpPkj8yLXXWWwvlW21Snw02jlp/JXo3+Tmk1vZxxeqO&#xA;8fubIztmuaxsdirsVdirsVdirsVdirsVfWOd24rxH87/APlK7T/mAj/5PTZzXbP96P6v6S3Y+Tzz&#xA;NS2OxV2KuxV2KuxV2KuxVhP5k+dW0W0XTrBv9yl2teY6xRnbl/rN0X782nZui8U8UvpH2tc5UwrQ&#xA;PKUaKt5qa+rcP8YhfcLXf46/abNnqNWT6YcmUMfUsnAAAAFANgBmA2oi0F40gW19T1D2jJB/DIT4&#xA;a3Vklha+YAAZ7lVX+RwJG+mlP+JZhzlj6BiaTdeQUciC3cgUH3VOY5Q3gVDX1/DZIskwb02PHkoq&#xA;AffJwxmXJaWQ6xpk32LhQfBvhP8Aw1MJwyHRaSrXNEDhryzFa7yRr3/ylzIw5ukkgpRbapdwIYuQ&#xA;lgYUaCUc0IPah7ZkSxA79UkJDrPkrStSb61oX+4zVFPNbXlSGRhv+6b/AHW1enb5dcy8OtnDbJ6o&#xA;9/X497VLH3Mt8h+Z7nVbOWx1JTFrOnER3aOKMw6B6eO1G9/nmv1+mGOQlH6JcljK2U5gM3Yq7FXY&#xA;q7FXYq7FXYq+sc7txXiP53/8pXaf8wEf/J6bOa7Z/vR/V/SW7HyeeZqWx2KuxV2KuxV2KuxV2KvE&#xA;lY63591G9n+OK3lcxg9KRt6cQ+gCudOf3WnjEdR+0tUBcmVEgCp6ZgOQivLlj+mudxGxTT43KeuB&#xA;vKy/aEdf2R3b7vHK9RPwtj9X3e9hxXyZna2dtax+nBGEXvTqfmTuc1spmRsqrZFXYq7FVK7to7m2&#xA;kgk+y4pXwPY/QclCXCbVgk8MkEzxSCjoSGHyzaxNi2bori6h3t53hbsyHv7g1U/SMTEHmLUhLbjz&#xA;A66lHaalCsU05pDdxbRSmu1UP2H8aGhPhl0dP6bidh06hgJUaKPypmuW4EPmvQdRXa4vTPYXxH+7&#xA;VVFaJm8SCRv7YOG8M49I1IeXe1SFSeg5qGTsVdirsVdirsVdirsVfWOd24rxH87/APlK7T/mAj/5&#xA;PTZzXbP96P6v6S3Y+TzzNS2OxV2KuxV2KuxV2KuxV4xpcJ03zjrOnTfC7SO0VerKGLKfpR650uWX&#xA;HhhIMMexITvU4JJ9OuoYv7ySJ1T5lSBmLikBIE97bIbJFo35p3+j6Lb6Xb6fCWtVKCV2ahqxJJQU&#xA;3qfHMvN2XHJMzMju4wnQULj82vOEpJjkgt/aOIH/AJOF8nHsnCO8/FfEKCl/MjztKKNqbD/VjiT/&#xA;AIigy0dnYB/D96OMoCbzb5om/vNWuyD1AmdR9ykDLRpMQ/hj8kcRQUmqanIeUl3M58Wkcn8TlgxR&#xA;HIBbbj1XVIjWK8nQ+KyOD+BxOKB5gLZVh5h13nzbULh323kkZ+n+sTkfy+P+aEiZRtv501yKnN0n&#xA;H+WgH/EOOVS0WM+TIZSt1PzDe6ysFqLdVlEgaMpUsWpQAV+eHFp44rNrKZls9DXlxHI1am5980xc&#xA;lL9Juf0v560yztvit9JM1xPIP5yoU/QCqL9+XZY+Hp5SPOdD8fa0yNyeqZoWbsVdirsVdirsVdir&#xA;sVfWOd24rxH87/8AlK7T/mAj/wCT02c12z/ej+r+kt2Pk88zUtjsVdirsVdirsVdirsVedfmdpFl&#xA;Nd2l9YXIj8xKVSGzjDPNcCvwhY0DNyBO21CNjm67LySowIvGevc1z7+qRW/mdra4fT9etpdN1GA8&#xA;Jopo3QhqdGRhzQ+xGZeTRnnDcMo5e9inmf6m2sSyWjo8UoVyyEFeRHxdPffM7S8XAAWrJV7JTmQw&#xA;dirsVdirsVdirsVTvyjJZRat613IsSxRs0bOQBz2HfvQnMXViRhUWzHV7p1fa7qOs3H6L8vwyTPJ&#xA;s0qCjEe1fsL4scxseCOMceQs5ZL2D0fyJ5Nj8uae3qlZdRuaG5lHQAdI1J7D8c0uu1hzS2+kcljG&#xA;mT5gs3Yq7FXYq7FXYq7FXYq+sc7txXiP53/8pXaf8wEf/J6bOa7Z/vR/V/SW7HyeeZqWx2KuxV2K&#xA;uxV2KuxVZ5a0HzB591i50vQJhYaPp7cNa8xMvJY36m3tlOzzcftHog670zZ4NLGMRPJ15D9J8mBN&#xA;7B6voWmeRvIkL23lPT0l1CQcbvWbg+tcTN3Mk7fG9TvQUTwGRz60nYfscnFpepYz538t6L53APmO&#xA;1S6nVSsNyoEc0Y8EkTi1B4Go8cpx6zLA2C5J08CKp82+TPLHl5/NmseXdbhFzPaSSRWzl3jq1tIy&#xA;SACN1qWG/fpm712oyRxRyQNA8/i6sRAkQWef8qx8j/8AVt/5L3H/AFUzUfynn/nfYP1MuAKsf5de&#xA;S0XiulxkD+Z5GP3sxORPaOc/xfcngC4+RPJcKtI2lwhVBLFuRAA3PUnB+eznbiK8ISWWx8khiItC&#xA;hcDoWAWv/EsyRkz9Zll4YQ02neVH+zoVupHTdv8AjXjkxkzD+Mr4YS248seXp5Of1BIu3GNpFX7u&#xA;eXx1WQD6vuXw4qUnlry7DE0j2qrHGpZmLPsFFSftYRqcpNWvBFM/yD/L7yl5s1nU7rzTBcPotmqr&#xA;DFA5jBmlYkcmWjFURT9k9xmVrtX4IA6lhiwmd09gv/yK1Py9ZSX35c3ia7pNS82h3fpx3Y7n0bpF&#xA;RWbf7EyjbuTmuyHHqN5Gpd/T5fqUxMdmNaXq1rqKS+mskNxbuYruznUxzwSrsY5YzurDNZnwSxmp&#xA;f2sgbRuUpdirsVdirsVdirsVdir6xzu3FeI/nf8A8pXaf8wEf/J6bOa7Z/vR/V/SW7HyeeZqWx2K&#xA;uxV2KuxV2KpR5mn1D6nb6dpZA1fWbqHTdOJ2AmuX4Bie3EVNczNFhE8m/wBMdz8GMi9rbTdN8o+X&#xA;bDyVodUstPiUXU3R5pm+J3kI6l2PJvc06DJavOZScvTYgBaWZhOY7FXx/wCcNVlj/MDWdSsJDFIm&#xA;o3DwSof5ZWAb/ZU6Z2GDGDhjGX80Okyn1k+bOtE/OPS5YETWLeS3uQKPLCOcTe9K8l+W/wA80+fs&#xA;eYPoNj7WQyBHzfm95RjDcPrMtOgSICvy5suVDsjMe75p8QJPqv5uaVdxG3gtrmOJvtllj5H22fbM&#xA;jF2TOJskfj4KMgStPO2isafvR80/oTl50U/Jl4oVF846AaVnZa+KPt9wOD8nk7k+LFqTzloKAlZX&#xA;kp2VG3/4ILiNHk7keKGOa/5sl1GM21spgtT9st9t/nToPbM3T6QQNnctc8lvqLyF5TsPK/lm10y0&#xA;cTEj1rm6H+7pZACzj2pQL7AZzWqznLMyLtcOMQjQZVY6heWM4ntZDG4606EeDDuMojIxNhnKAkKK&#xA;R/mv5VTXtIm8/wDluAQebdFj56xaR7Lf2UYq6OB9p0Raxt9rbjv8NNrgyRyx4JcvuPe63NiMCwnT&#xA;7+31CxgvbZuUFwiyRnvRhXf3zVZIGEjE8wxBRGQS7FXYq7FXYq7FXYq+sc7txXiP53/8pXaf8wEf&#xA;/J6bOa7Z/vR/V/SW7HyeeZqWx2KuxV2KuxV2Ku0EwL+aPkdrkqLdb64ZmfZA4s5ShJO1eQ2zY6Dl&#xA;P3D72EuYT/zP+bv5d2msXn1nXYJHM8grbiS5H2j3gWQZH8jmmSRH9H3ufHPCIAtLbT85Py3upBEu&#xA;spFIe00U8IHzaRFX8cEuzs4/h+5kNTjPVONe806fY+VNQ16zuIrqG1t3lhkidZI2cL+7HJSRuxAy&#xA;nFgMsggRVlnPIBEkPm/RPyf8+eYfKq+atNto7mynupLZEaZI53aMAvIBIUUpUla8q1B2zqcurx4j&#xA;UjTqIYpT5N2n5J/mVcSBDpPoLWhkmmgVR9AcsfoGVS7SwD+L7C2DS5D0Zha/kBbaXpzah5k1CS4k&#xA;UqkWm6ao5SzSMEihSWUfE0kjKoHAbnrmIe1TOXDjHxLd+UERci9D8q/kx5S8uRg3tjBqGs15XMsl&#xA;ZoIX/wB826yVBEfT1GHJjUjiDxGFq+0JyPDE0PvbsGnA3IZhNp2nz231Wa1hltqU9B41aOh7cSKZ&#xA;rhMg2Du5RiHmnm/8rfKemTN5hg0mOfS4vi1jShyUCH9qe2MZVkaJfiKV4svQA0zZ6fXZJDgMvV0P&#xA;6D73FyYIj1Vt1Rk/5E/lrfQLLaQT20cqh45be4dgVYAgqZfVGQHameJ3IPwSdJjPJ4R+YnlKHyp5&#xA;puNHguTdQxqkkUjABwsi8grgbVH45v8AR6g5cYkRTr82PglT3/8AJHzNJrfka3inNbrSm+pOe5RF&#xA;Bib/AIAhfoznu08PBlNcpbux0s+KHuZ/mvclOvKF00OuQp1juA0Ui9iGFR+IGXYJVJp1Ebi8P0Sw&#xA;TSr7zFocI42mja1f2VmvXjAsvOMf8DJmT2iPWD/OiC62Ka5r2bsVdirsVdirsVdir6xzu3FeI/nf&#xA;/wApXaf8wEf/ACemzmu2f70f1f0lux8nnmalsdirsVdirsVdiqA1nQtL1q3jttSh9eCKQTKnJl+J&#xA;QVFSpB6Mcuw554jcTRQRarY6VplggjsrSK2UdokVPvoN8jPLKf1ElQFW5tLW6jMdzDHPGeqSKHX7&#xA;mByMZmJsGlYJ588laHZ+W9R1DTLZrW5VULpA7rGy+qvLlGDxoFJPTNtoNbklljGRsefuYSjs9y/K&#xA;yO1vPyI8qXGnCsVktxFdovVZTO/qMwHi4r8jke1InjJcnRyA2R+ap2CXXoVvMflSNwCjaqW4noZI&#xA;rC6mh+kTxoR7gZl6T+I/0f0hx9RyHveP+Y/Pf5nw/mwmj2CSG3+tRxWemLEGS4gYirliOR5DcsG+&#xA;H2pm002jwSwcR59T3OLmzzE6D2nXZLq00/UZdNQXV3BFM1lGa0lkRSY12/mYDNHCIMgCdrdgSeG+&#xA;ryL8lvNvn3zH5k1Sz14yXelx20j3bSwrGkE3JVSPZUoXqV4fTTY5u9fpcOPHxR2PRwMGacp0d1by&#xA;R+dPkzTvL8Wk6pPNBNpaG3hf02lWeOIlYuBjDUPAAfFQe+U6ns3LKfFEfV9jZi1URGj0eJebvME3&#xA;mLzJqGsygr9clLRodysY+GND/qooGbzT4RjgI9zgZJ8UiWa/lK/naPTtRGg3sGnWlzLGk91LH60o&#xA;eNSf3SN+76SfFy9s1vaeTCJDjBke7l82zDOUQaZsfLeuzHneebtaaY9Tb3P1dPojUEDNX+eA5Y4f&#xA;EWz4pfziidOg89aHeQ32iea7uSW3YOkGqBbyN6fsszUYA+I3yUdZjJ9WMf5uy8Uqq1XRINXB1G+1&#xA;gxHVNWv7nULwW/L0g9w9aR86txAA4g9BtlOszRyTBjyAAYxFJlmIydirsVdirsVdirsVfWOd24rx&#xA;H87/APlK7T/mAj/5PTZzXbP96P6v6S3Y+TzzNS2OxV2KuxV2KuxV2KuxV2Kqdzbw3NvLbTqHhmRo&#xA;5UPQqwoR92SjIxII5hCO/wCcV7jXNF84eZvIrUutBiiGorIx/u5HKRqAKfaljYch/kff0GbIMuKO&#xA;TqdmuOxpnHn3X/Luh3l1c3EkdlZxyejHGtS0kg2KxxirMzN0VRmm8E5J8MA7SE+GAMik9r5J/M/z&#xA;fFDqsMcXlS1sJFv9Fgv0Ml9cXVuecH1iNSotoWYUcfE/GopQ5sMOGGLmeKXly/a4ebOZ7Dkmlnqk&#xA;WpfWjDC9je2rcNW0aUj6xZSnqkij7UZ6xSj4XXcGtQMHUac4z/RPVy8OYSHmvzFb0j1q71bWJ28o&#xA;+WGWfzFeRkOxJ9KwgcUe6uGUHhxB+BerNSgOZulwWeOX0D7fJxs+URFD6nzB58/LTzl5F1H6l5is&#xA;Gtw5It7tPjtpgNyYpR8J/wBXZh3AzqMeWMxYdURTFstQ+hfI1lp1p5W09LBvUhljErykULyPu5I8&#xA;QdqdqUzj9dOUssuLm5ERsn2YjJ2KuxV2KuxV2KuxV2KuxV2KvrHO7cV4j+d//KV2n/MBH/yemzmu&#xA;2f70f1f0lux8nnmalsdirsVdirsVdirsVdirsVSSPWNfk8wy6NBozXkvD1rV4Z4UaWKoHwpO0VWU&#xA;mjBWP45sMOhGSHFGXvHd8mBnRZb+U/lv85NA8weZ9StPKiQzeYPqy2d7q93FDDbJCH3lhgM00hPJ&#xA;fhWnTrmyrGMcYk/T3Md7ej6D5D8ueVL/APxL5r1Ea95vlqUvZ1VVg9Q1KWVtUrCvYv8AaPdt6ZCI&#xA;MhwwFR/HMpnPqS35y/ODTNOi9G0nWAyVWO4kFZJD4QQgF3b/AGNfbL8WkrebUchO0XlWqaPrnmu6&#xA;S7S1bSHUkpr100kepAN1MCQvHKlf+LZB7ochn7QxRHCBxfc5GHSTO5NN6r5C8yCOI6f5m1C7VP8A&#xA;eizvbl4vWHtc2ypJGT48WzXYdZjEvXCPw/a5mTBKvTIpt5G832nkmQWK2P6D+suDPaXdPSuJOnJL&#xA;sF0lc9qvz8VzcXizj0n8e51k4ZMZ3esXmu+RfNejvpeuwRTWd38E9neKCgNNjy7UP2XFCD4ZjHBk&#xA;gbCRkBfO/wCZf/OIetWs0mo+QZhqenv8a6XcSKlxHXtHKxWOVf8AWKt/rHMrFrhynsph3JT5P8v+&#xA;fvKvl+Wy1zytqq/V5XeOVIAYVjcA0MrOsY+LkeuYOt0vjZOKBjuGUZUN028u6zPrGni/e0azglJ+&#xA;rK7BneMdJCAKAN267b981WpwjHLhuz1Zg2mmY7J2KuxV2KuxV2KuxV2KuxV9Y53bivEfzv8A+Urt&#xA;P+YCP/k9NnNds/3o/q/pLdj5PPM1LY7FXYq7FXYq7FXYq7FXYqh72wtrxUEwIeJucEyMUkjfpyR1&#xA;oyn5ZbhzSxm4mkEAoCz86ebdM876N5cudais9L1ZvRg1y6t2leKRqqqOsM1mhHPiC21A1T0zotLq&#xA;fFxmRHqj0ceWOi9N8wfl/r9jcoup6888Uy19Sxt1tA56MrGV7uQePwuD75h6jtKcdogBysGlhLcl&#xA;Q0vy7oulu8tnaqtzIKS3Tlpbhx/lzSF5G+ls1eXUTyfUbdjDFGPIJllLN2KrJ4ILiF4Z41mhkFHj&#xA;kUMrDwIOxwgkGwpFvBNW8weYR561LTfy/K2+k6TA5vImPKzBgBaZwsnJYhy+ACOlafPOn02QwxA5&#xA;TZly7/J1GbEJTIiOSHsv+clfOVtbNALaEBhRljkmjjPzTkwzNOGJ5hxaZbp+seY/OGjWt75iuWFr&#xA;OC6aXFyWJo6kJ6rOzu4Zd+PIKR1BzR63XGEjCG3m3QxjmU3VVVQqgKqigA2AAzStzeKuxV2KuxV2&#xA;KuxV2KuxV2KvrHO7cV4j+d//ACldp/zAR/8AJ6bOa7Z/vR/V/SW7HyeeZqWx2KuxV2KuxV2KuxV2&#xA;KuxV2KpJ5v8ALFt5i0h7KQhJ0PqWs5/YkA7/AOSehzK0mpOGfF06sZRtlf5W/nlZzWa+QvzRlNhq&#xA;tqBFp+uTmkcqrsnqyHZXA6SH4XH2jy+1t8+mjljx494lGPIYF6Hqmg3thSWgns3AaK7i+KNlO6mo&#xA;rSozSZMRjzdnjzRkluVNrTuiKWdgqjqxNAMVeSfm1+cNjp1jLovl26W41ScFLi8gYMluh2bi67GQ&#xA;9Nvs/PNvoOzjI8UxUe7vcLUakAVHm8W0zzjf6X5Z1LQ7FFiOrOPr95WsjQqtBCPAEluR71p893PT&#xA;iUxM/wAPIfpcGOQiJA6oryJ5MuPMOoq8qFdKt2BuZegam/pqfFu/gPoyjXawYY7fWeX62MY295RE&#xA;jRURQqIAqqBQADYADOUJtvbwJdirsVdirsVdirsVdirsVdir6xzu3FeI/nf/AMpXaf8AMBH/AMnp&#xA;s5rtn+9H9X9JbsfJ55mpbHYq7FXYq7FXYq7FXYq7FXYq7FUs13y3o+uW/oajbiXj/dyj4ZEJ/lcb&#xA;j9WX4NTPEbiWJAKRaXon5meVqxeTvNs1vYmoFjdMWgAPX90yzQt8/TGbSPamOX95DfyYcB6Jfqfk&#xA;vzzrrmTWNWsIZGPJmsLK3tyT4k28NrX3yf8AKmKP0xJ9/wCCnhPelkn5JTVqmsK5P2i1uR/zMbEd&#xA;tD+Z9v7EeGgZvyX18MPRvrV17lzIh+4I+WjtnH1EvsR4ZTjRPyZtIpFl1e8NyBv9WgBRD/rOfiI+&#xA;QGY+btgkVAV5lIx970S0tLWzt47a1iWG3iHGOJBRQPkM005mRsmy2KuRS7FXYq7FXYq7FXYq7FXY&#xA;q7FXYq+sc7txXiP53/8AKV2n/MBH/wAnps5rtn+9H9X9JbsfJ55mpbHYq7FXYq7FXYq7FUBd+YNB&#xA;s5/q91qNtBOOsUk0aMNq7gkU28cuhp8khYiSPciwjY5I5Y1kicPG4DI6kFSDuCCOoyogg0VXYEux&#xA;V2KuxV2KoC48w6BbTtb3OpWsM6GjxSTxo4J33UsCMujp8khYjIj3FFhfe6zo9jIsd9fW9rIw5Kk8&#xA;qRsVrSoDEbYIYZzFxiT7gpIRFvc29zCk9tKk8DiqSxsHRh02Zag5CUTE0RRVUyKUvHmHQDci1Gp2&#xA;huS/pCATx+oXJ48OPKvKu1Mu/L5KvhlXuKLCIudR0+1khiurmKCW4PGBJXVGkaoFEDEFjUjpkI45&#xA;SBIBNLa2+1bSrAoL69gtDJXgJ5Uj5U605EVwwxTn9IJ9wUlVtrq1u4FuLWZJ4HrwliYOjUNDRlJB&#xA;3GRlExNEUVVcil2KuxV2KuxV2KuxV9Y53bivEfzv/wCUrtP+YCP/AJPTZzXbP96P6v6S3Y+TzzNS&#xA;2OxV2KuxV2KuxVJfOerT6T5Yv763NLiNAsJ8HkYIGFf5eVcytHiGTLGJ5MZGgkvknynpcnlaCXUL&#xA;dbi6vw088z7v+8Jpxf7Snj1INcydbq5jKRE0I7IjHZKfIOp3Wk6jr+gBJb2LT2eW1hSnM8JODhAa&#xA;D4uQNP65ka/GMkYZNo8XNjE1YTGH81tPuLaWS20y7nmiLM8Ea8ikSUrJIy1Cjf8ADKT2VIEAyiB+&#xA;nuTxp/o/m/RtT0STWI5DDa2/L6yJBRoygqQQK12O1OvzzEzaScMnAdyeTISBFpR/yszT0EVzcade&#xA;QaVO4jh1J0Hpkn2BrTr08MyP5NlyEomY6I40V5g8+2WhajBaXlnP6E/EpejiYim3NloSx4V3FMr0&#xA;+glliTEix06qZUt0f8wdP1HWk0mSzubGeZedqblOHqLxLDbqKgbdsObs+UIcYIkBzpRPdj/m63sR&#xA;+Z+hmdI1ieJZJywUKzK0lC9dj9kDfMzSSl+VnXf+pjL6l35uzabcaPbSQvDNcLKF5oVZwh6io3pX&#xA;B2SJCZBsClycmYa3rujeWtNjkuB6cIIitraFRyY/yoooAAPozXYcE88qHPqSzJASzT/P9rNqNvp+&#xA;o2Fzpc92AbQ3CgK/L7Ir1BJ26Zdk0BETKMhIDnSBJj+r2NnpX5qaXdtCPq9/TbiOImkDRqQP5vUo&#xA;1ffMzDOWTSSF7x+7+xiRUks/NC5urvX5Db8/T0eKIsw+ysrn1A3/AANR9GX9mREce/8AGSifNP8A&#xA;z/Lb61YaDZW6gTaxLG0MtAWSJwpIPtR+X+x9sxNADilOR5QH2/j72Ut6Z1bW1va28dtbxrFBEoSO&#xA;NRQKo6AZqpSMjZ5s1TIpdirsVdirsVdirsVfWOd24rxH87/+UrtP+YCP/k9NnNds/wB6P6v6S3Y+&#xA;TzzNS2OxV2KuxV2KuxVjf5i2ct35O1BIlLSRqsoUeEbhm+5QTmb2dMRzRthPku/L/UYr3yhp8isv&#xA;KGP0ZgCPhaM038KijfTjr8ZjmkO/dMDsxz8vYTeecPMWtwnlZvJJFDJQgP6kvMEfIJ+OZnaB4cOP&#xA;Gfq/YwhzJV/yeFuNF1EgL631xvUbvw4LwB+nlke174493CnHyYdZxTf4M81y2wP1F7q2CEfZKrKS&#xA;1K/6yZsZkePjB+qj939rDoWSHRG1LyVay6j5oCaMIYmMf1eCiMi/3YdaOzKdqdTmF43BnIjj9dnq&#xA;WVWOav5ttIYdR8iWfMXEUUqxCQgUkVfQXlTf7WR0kyY5pcjX/FJl0X+bwo/Mjy042YgAn2DtT9eD&#xA;Sf4tkWX1BQ852dpe/mXoVrdxrLby24EkbdCOUtK/TktHMx0syOd/qRL6kP8Amf5a0HS9Fgm0+yjt&#xA;pWmCs6A1IpWm+T7M1OTJMiRvZZgAI/8AMZxF5o8qy3DBbNbgly1OI/eR8q17ccq7OF4sgHOv1pnz&#xA;Cz83FMkugwwb3z3DehT7W/Abf7KmHsk0Jk/TS5OiJ/Nm1lXTLHVYKi4sJw0bLtStH5H/AFfT/HK+&#xA;ypDiMDykFmgtHsRrHlHzHq80bq2qzSXCKTUmG2PJVX/Zc1y3NPw82OA/gFfE/gIAsFC/ls11q2sW&#xA;01yrBdAszbKa7eo7OiVHtGXH3ZZ2lWOBA/ykr/HxpYbl6lmhbXYq7FXYq7FXYq7FXYq+sc7txXiP&#xA;53/8pXaf8wEf/J6bOa7Z/vR/V/SW7HyeeZqWx2KuxV2KuxV2KuZVZSrAFSKEHcEHFWLT/lx5fkml&#xA;eF7i0inIM1rbycIXoa/EnE1FexzPj2jkAF0SOp5sOAJ5Z2WlaLpxigVLSxgBdyTRQAKlmZv1nMWc&#xA;55ZWd5FlVPL/AMu/L2ia5YX0U17cQXfqt6sFvMI/UtyF481oea8q5ve0NRPFIEAEV1HVqgAXptl5&#xA;f0iz0o6VBbKti4YSRGp5c/tFj1qc0c9ROU+Mn1NtJDa/lb5Ut7360I5ZBWogkcGMeAAChvx+eZc+&#xA;1MxjWzHgCL1ryJpGr38V9cT3UU0CqsCwy8Fj4dCg4niflleHXTxx4QBR7wkxtbq3kLSdU1VdUuLq&#xA;8W7jCCFo5uPp+mBTh8JK7/Ft33xxa+cIcAEa9yDG29U8haTqWsDVri5u1vFKmIxzcRHw6BPhqorv&#xA;seuOLXzhDgAjXuUxsq/mTybpnmGSJr+a4CQiiRRSBY6k15FSG+L3yOm1k8N8IG6TG1W68q6Td6LD&#xA;pN2HubeAARSytylBHQ8z3yMdVOMzMbE/JeHZDaR5F0TTbuO7DT3dxAoS3e6k9X0lXoE2FAO3h2ye&#xA;XXTmK2APd1URATTWdJtNX02bT7vl6E4AcoaMKEHYkHwyjDlOOQkOYSRbel6TZabpkOm2yn6rChRQ&#xA;xqSCSTU+5Jxy5ZTmZHmVApDeX/LWmaDBPFYhz9YkMs0khDOWpSlQBsMnqNTLKQZdEAUmuY7J2Kux&#xA;V2KuxV2KuxV2KvrHO7cV4j+d/wDyldp/zAR/8nps5rtn+9H9X9JbsfJ55mpbHYq7FXYq7FXYq7FX&#xA;Yq06JIhR1DowoysKgj3Bwg0hSgsrOBi0EEcTEUJRFUkfQMMpyPMqrZFLsVdirsVdirsVdirsVdir&#xA;sVdirsVdirsVdirsVdirsVdir6xzu3FeI/nf/wApXaf8wEf/ACemzmu2f70f1f0lux8nnmalsdir&#xA;sVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVfWOd24rxH&#xA;87/+UrtP+YCP/k9NnNds/wB6P6v6S3Y+TzzNS2OxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV&#xA;2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KvrHO7cV4j+d//KV2n/MBH/yemzmu2f70f1f0lux8nnma&#xA;lsdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVfWOd&#xA;24rxH87/APlK7T/mAj/5PTZzXbP96P6v6S3Y+TzzNS2OxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV&#xA;2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KvrHO7cVLtR8uaDqc6z6hYQXUyqEWSVAzBQSQtT2&#xA;qxynJp8czcgCUglC/wCB/J//AFZ7T/kUv9Mh+Tw/zR8l4i7/AAP5P/6s9p/yKX+mP5PD/NHyXiLv&#xA;8D+T/wDqz2n/ACKX+mP5PD/NHyXiLv8AA/k//qz2n/Ipf6Y/k8P80fJeIu/wP5P/AOrPaf8AIpf6&#xA;Y/k8P80fJeIu/wAD+T/+rPaf8il/pj+Tw/zR8l4i7/A/k/8A6s9p/wAil/pj+Tw/zR8l4i7/AAP5&#xA;P/6s9p/yKX+mP5PD/NHyXiLv8D+T/wDqz2n/ACKX+mP5PD/NHyXiLv8AA/k//qz2n/Ipf6Y/k8P8&#xA;0fJeIu/wP5P/AOrPaf8AIpf6Y/k8P80fJeIu/wAD+T/+rPaf8il/pj+Tw/zR8l4i7/A/k/8A6s9p&#xA;/wAil/pj+Tw/zR8l4i7/AAP5P/6s9p/yKX+mP5PD/NHyXiLv8D+T/wDqz2n/ACKX+mP5PD/NHyXi&#xA;Lv8AA/k//qz2n/Ipf6Y/k8P80fJeIu/wP5P/AOrPaf8AIpf6Y/k8P80fJeIu/wAD+T/+rPaf8il/&#xA;pj+Tw/zR8l4i7/A/k/8A6s9p/wAil/pj+Tw/zR8l4i7/AAP5P/6s9p/yKX+mP5PD/NHyXiLv8D+T&#xA;/wDqz2n/ACKX+mP5PD/NHyXiLv8AA/k//qz2n/Ipf6Y/k8P80fJeIu/wP5P/AOrPaf8AIpf6Y/k8&#xA;P80fJeIu/wAD+T/+rPaf8il/pj+Tw/zR8l4i7/A/k/8A6s9p/wAil/pj+Tw/zR8l4i7/AAP5P/6s&#xA;9p/yKX+mP5PD/NHyXiLv8D+T/wDqz2n/ACKX+mP5PD/NHyXiLv8AA/k//qz2n/Ipf6Y/k8P80fJe&#xA;Iu/wP5P/AOrPaf8AIpf6Y/k8P80fJeIp3mSh2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV&#xA;2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2&#xA;KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2Kv//Z</xmpGImg:image>\n               </rdf:li>\n            </rdf:Alt>\n         </xmp:Thumbnails>\n         <xmpTPg:NPages>1</xmpTPg:NPages>\n         <xmpTPg:HasVisibleTransparency>False</xmpTPg:HasVisibleTransparency>\n         <xmpTPg:HasVisibleOverprint>False</xmpTPg:HasVisibleOverprint>\n         <xmpTPg:MaxPageSize rdf:parseType=\"Resource\">\n            <stDim:w>1333.333252</stDim:w>\n            <stDim:h>1333.333252</stDim:h>\n            <stDim:unit>Pixels</stDim:unit>\n         </xmpTPg:MaxPageSize>\n         <xmpTPg:Fonts>\n            <rdf:Bag>\n               <rdf:li rdf:parseType=\"Resource\">\n                  <stFnt:fontName>Cambria</stFnt:fontName>\n                  <stFnt:fontFamily>Cambria</stFnt:fontFamily>\n                  <stFnt:fontFace>Regular</stFnt:fontFace>\n                  <stFnt:fontType>TrueType</stFnt:fontType>\n                  <stFnt:versionString>Version 6.99</stFnt:versionString>\n                  <stFnt:composite>False</stFnt:composite>\n                  <stFnt:fontFileName>cambria.ttc</stFnt:fontFileName>\n               </rdf:li>\n            </rdf:Bag>\n         </xmpTPg:Fonts>\n         <xmpTPg:PlateNames>\n            <rdf:Seq>\n               <rdf:li>Cyan</rdf:li>\n               <rdf:li>Magenta</rdf:li>\n               <rdf:li>Yellow</rdf:li>\n               <rdf:li>Black</rdf:li>\n            </rdf:Seq>\n         </xmpTPg:PlateNames>\n         <xmpTPg:SwatchGroups>\n            <rdf:Seq>\n               <rdf:li rdf:parseType=\"Resource\">\n                  <xmpG:groupName>Default Swatch Group</xmpG:groupName>\n                  <xmpG:groupType>0</xmpG:groupType>\n               </rdf:li>\n            </rdf:Seq>\n         </xmpTPg:SwatchGroups>\n         <dc:format>application/pdf</dc:format>\n         <dc:title>\n            <rdf:Alt>\n               <rdf:li xml:lang=\"x-default\">OpenHoW2</rdf:li>\n            </rdf:Alt>\n         </dc:title>\n         <illustrator:Type>Document</illustrator:Type>\n         <xmpMM:DocumentID>xmp.did:fc9d5223-940d-fc4a-8888-c932b67313cb</xmpMM:DocumentID>\n         <xmpMM:InstanceID>uuid:52997245-095d-4a65-8b89-f3bd6e55f8fd</xmpMM:InstanceID>\n         <xmpMM:OriginalDocumentID>xmp.did:fc9d5223-940d-fc4a-8888-c932b67313cb</xmpMM:OriginalDocumentID>\n         <xmpMM:RenditionClass>proof:pdf</xmpMM:RenditionClass>\n         <xmpMM:DerivedFrom rdf:parseType=\"Resource\"/>\n         <xmpMM:History>\n            <rdf:Seq>\n               <rdf:li rdf:parseType=\"Resource\">\n                  <stEvt:action>saved</stEvt:action>\n                  <stEvt:instanceID>xmp.iid:fc9d5223-940d-fc4a-8888-c932b67313cb</stEvt:instanceID>\n                  <stEvt:when>2019-12-19T21:31:24+01:00</stEvt:when>\n                  <stEvt:softwareAgent>Adobe Illustrator CC 23.0 (Windows)</stEvt:softwareAgent>\n                  <stEvt:changed>/</stEvt:changed>\n               </rdf:li>\n            </rdf:Seq>\n         </xmpMM:History>\n         <pdf:Producer>Adobe PDF library 15.00</pdf:Producer>\n      </rdf:Description>\n   </rdf:RDF>\n</x:xmpmeta>\n                                                                                                    \n                                                                                                    \n                                                                                                    \n                                                                                                    \n                                                                                                    \n                                                                                                    \n                                                                                                    \n                                                                                                    \n                                                                                                    \n                                                                                                    \n                                                                                                    \n                                                                                                    \n                                                                                                    \n                                                                                                    \n                                                                                                    \n                                                                                                    \n                                                                                                    \n                                                                                                    \n                                                                                                    \n                                                                                                    \n                           \n<?xpacket end=\"w\"?>\r\nendstream\rendobj\r3 0 obj\r<</Count 1/Kids[8 0 R]/Type/Pages>>\rendobj\r8 0 obj\r<</ArtBox[0.0 0.0 1333.33 1333.33]/BleedBox[0.0 0.0 1333.33 1333.33]/Contents 43 0 R/CropBox[0.0 0.0 1333.33 1333.33]/LastModified(D:20191222212910+02'00')/MediaBox[0.0 0.0 1333.33 1333.33]/Parent 3 0 R/PieceInfo<</Illustrator 44 0 R>>/Resources<</ExtGState<</GS0 45 0 R>>/Properties<</MC0 41 0 R>>/XObject<</Fm0 46 0 R>>>>/Thumb 47 0 R/TrimBox[0.0 0.0 1333.33 1333.33]/Type/Page>>\rendobj\r43 0 obj\r<</Filter/FlateDecode/Length 10661>>stream\r\nHlͲ,G\r\u0014\u0002Ӯ-v\r\u0004\u0001&\u0007pY\\C,x}L9^{FUR*R}u~#ݽ.W~\u001fHWrǏoz~^_^\u0003~c5]ѯ^l;_V?z1{sw]9ݳ]FW{ {kۍRTǕ\u000b\u0001^ݥ#SjW\u0019wyѯR}ұpM\\e^]uޥxVupw\u0002@J\tZX\u0019kxm,]q^g?ss~\u0019lʰ+!q]_׳M\u0015ͻf{\u0000\u0004e^O0\u0006&_w\u0019s%'*%VyFU&*z\u001fo\u0013ƝF}?٣cd\u0002K\u0007\u0013f\u0015d$fL{@\u001b'<k\u00076Av~P\r\u000e+TW?\u0015{\u000e\u0010I\u001d>\u001c3I~uoK\"ųMӢ\u0012ƥ|o5r2q`޳勏9\n853\t\u0017[\u00058˫(A\u0016\u0011*M6lmL:Ki\f<6AA\u0007>Y~fsai\u001d֕*\u0007t\u0007 YI\fJe\u0016M0\u000b\foz\u0002Ji\u0003Re\u0003\u0017J/f\u0000\u0017'\u0000gE%+}GJ8ۥ(d|\u000fs.\u0005jzS\u0001j4\u0007\u001c\u0006ĤI)F\ra|Wt\u001e@}ٵJbwh҇\n.R}U,I\u0010\u0017W\u0014\u000fbٔ a\u0012\u000bf\u0001xֱV\u0006U!Z\u000fó\u0015@fiVK2\u0005\u0011 \u0011-SL\u001a6\n\u0004\u0001[RXR*\u000b)7\u0014$mv7DA\u0011\rظgTZ%D\u000f\u000e3ħ*5\u0003@V_o)+\u0015z\u0000A$U\fA\u0013\u0012@\b8(\\dcmdoV\u001fJh2\u000bF]yR6x2$ۜa\u0019\u0016\"h[x[ =ħv\u001d\u000f\u0012Q[\u001aE}$X8MO\u0014uLS\u000bA'YW*I\u001cD\"TWyTWcp;eqs\u0015(l25rS3MN<\u000e=T\"D(mXE3\u0011Z,7U\u0001n9([~c-nSd~\u0010@p .T\u0013i@\u001e\u0011fc\u0018k9Y<RD0h\r_>l\u0014Npʟ\u001eĤ\u0003\u001c!OB(*\u000e\"/t\u0000:\u0011lsJV>6&isbk\u0015BB@?7B\u0015IcT~\u0015jTLGN\u0006Wr-:c\u000eW\u0003|z[-,L9˧'\u000fR&X e\u001eTzzpFK\u0002\u00141<=IQmB=z\f{hY\u0011>\u0016\u001aT3=ssJXăcTǎ}>Pyo\u0018{s Ψj@ۖ\u0015\u0016Q,G\u0012bB.\u0002:bѥ?{ZfԭQ\u001aBN^VҐM\neHdk|j֫Cų<>76k/vx\u001e\u0013}xߣ QI,:.%\u0019j<z\u0014\u001f\u001c\u000b\\\u001f\u000454\u001bnY],'0J<(%7v\u0001[4w뜀,\u0012/\"<Z\u001e2}\u0012\u0006J4\u0010g];S2,\r\u0003*j\n\u0002#ݚ>X=Z!\u0013D\u0013\bU!a)\u001cDK\u0003\u0014\u0002/\"Lazq\u001a<\n\u001e\u0013uY137\r>I;VTp:<ta&\u0014MGw)\u0014;n-\u001d=U\u0002զ?\u00124T#!\u0010a\u001f̚ʼu&恛ZDF\nf\f^e\u0005\u0011®\r]\u001e˭B5s숣>S`ZM\bE\b'eծ\u0001ƪ\t7Tu\u001d\u0001\u0018{G\u001d\\gx?\u0010-RqP\u00000kBTSԍ;Bl\u0004\r}\u001c52x?8SOȸZ<IJÜz\u0017_!B\u000b=a\u0011R\u00027\u0007Y\u001fhzSr̸|./ek\u001aukn5|0kS)iB\u000fhv\u0018\t`Z\u0014$!efwŘO`-\u000b%ψv9bl\u001c.lfTzD*w\"\b6}\u0015S\\+u%\u000fP\b>zCM/\u0012V:bq\fjyV@=\u001dNWSzVA+\u0007ATsǜ\u0001uͤt\u0015x9\u0013>ϐc$ \u0017z/M#cu\\vi\u0016%6R\u0012iDCD!Y\u000e}:T -cl\u0014\u0017 d1\u001c\r`9J\u001b\u00110癋\u0015\u001amAw}<\r\u0007G`('p=E\u001dS\u0014%#6y\u001d!/=\u001eTŮk z\u001er\u001dR\u0004t\u0000![:c'\u001eK&\fnP&׎\u0012\u0015i_f2yr)T\u0005z}Ai-P|=\u00113y\u001a}(8\u0001uhĽdh\b9\bI\u0017$҅=ĘMM{`\u0004&\u0017g]Cy~a'\fI[-\u0018|ĩ(\u001a\u0001X\u0014\u0004K^148f\u001ax6Z2vσ\fC>?@XFl/\u0017tM=\u001f\u0012kHvYĐ\u0003Yf-JK\\̈́\u001e<5U%x/\u001as\u0006m#4!]s l*͗Œ~@N7^A3J\u001aE֔ g!gBQn)xÄt\t\u000f\u00197\u001b-WtIC9:]ŖQc\bmxj\u001fx\u0004EL+'\u001du)nlPΌ5shZ\u0007Ym\u0014絙[D2NKeyyw\u001cJҔKJR>QI%T\u0012Щ}+tq*\t%Hd̕t~*'}~\u0003On\"b\u0001\u001e՜HV{[w\r\u001a\u001a[\tGi$]6\u001e\u0015hDnP]ӿR\u001eB6v./$u*(r\u0002%*\"\u0006-\u001a0}ڲo+\u0002hAVtmYɒL{ecxBEd)u\u0004C}u2*»9RWk=u\u001bJ\u0005**V\u001a9qzVε\u0014e1%mx\u001c_ox׾\u0004^DaԴyZ\u001d^R\u0006}U,Zڭ[\u0011n^.A-&UR)M\u000b=(:2)g\u0003:\u001eYK1F\u001b8\u0014+,|2\u00108S,]\u0003:2H)u\u0014I\u0010s\u0010\rB#ڗҶ\u0011QE=ɿWǣUlவ\u001c,\rϖeUӗǑߧSׄ3\bzMLNI]ujwF_SbH;wh\u001efe~\rlh+} ({K̨{G-\u0017\u0019i3\u001b@<D${KF.^\u001bH^\u001b\u0010q\u0006M\u001bˑǐm\u001b/vܕ'\u001cf\u0007sl决\u001bj|rƻH4sncM'#Tsgݹ!\u001a4\u001a6xK\u0001;O6~ѻ\u0003Оec\u0005Wq:C]ʺ\"u\u001ak\u000bpU\u0017dmdWDٙ=\u001c\u00139\u0017D>_\\}75\u0004\u0005\u0010h蹡N\u001fg\u001b)Uh\u001eEcb@j[_Th;tәFhk/+|\u0001#|Kګʜ*Ⱥ\u000bhR\u000eav{,x\tRyTkDX\u0002o\n2$9XqX#\\~uKWf[z\u0010SL$צ\u0011'Łjꆢ-}l\r\u0012\u0010EsTI\u001dZ\u0019[1{ۦgݶ\u0011M/\u0002쑑mľn<{I{ٺ7$#L\u000fOG/I@s):\u0017}P$_\u000e\u0010tA M\u001d%u\b\u0005n\u000bTCϒ;]]\u0006u\u0017h=0\u0019k[83 $\u0017$Yamk+8,DR~3\u0004\\3k\u000f|0Wk\nWE·m\u0012@\u00106Zog\u0016[q\u001bb\u0018\u001dlŵI$H\u0010BJ\u001cbD-_xv\u000b\u0012\u001f\u001fUoJKPǩg#%?/0_T\fE\u001a\u001be;KɡmW؅5DW$\u00075Zj&^t\u001f\u0004L\u0013hDۢ oJ\u001698\u00143'mx\u0016x\u0006ᘶ[\u001cYBs\u001f\u0010\re\u000b\u001c<l@{W\u0011yدA\u001b#m~GeXPȅh*@Һ\u0012l{Ey\u0016ŕƳo\u000ett(9M\u0005\u0000bhaX\u0004btM\u0016Vi\u0012sە?e$\u0018DmF6&WMs\u0015i \u001a,\u001f{|քWϜvr\\K\u000bM\u0014T\u0007\u0013\u001a:c&!k\bgX>yGV_w\u001bO%_dv\u001e$E'w\u0016>r~n'Q\n\r\u0011gky\u0004wsƛ\u001e7U\u0002\u000e?HZ̢rhÒ\u000fW]\u0003GE>l\u0007\u0007~Ue\u001563@q\u0002U\u0006d\u0014|V9\u0006WC5R\f/\u000eh\u0007qJFʪFږ\u0006LT_G\u000ev\u0005\"E|tg\u0001\u001ef\u0018>Q*շ`\\\u00126\u0002)8@\u0011a=b3[{ʱPv>W}<\u0014\u0012lDv=\u001b|*B\u0006>NSd2T\bWuJ'\n\u0001)o~h1#\u0004\u0016F\u0007I\u0000I\\\u0005:G!}\u000e\t\u0000ǥ\u000e\u001eѽ 4FT܌rP\"ofZxZ,\u0017I\u0011 m\u0012`\u0004i\u0003(6\u000e8tn\tל:\fNmq$\nL9]\u000b!:<@\u001cuJo$yysk[+3\u0017a5DI\u00128#\u0006OO\u0013<.&E}z#^`\u0019Lfo4\u001e86\u001bO\r+^ !u>\u0012[T0U\u0001T~'T6WX3^AV,g;'~VU\u001eh\u0019T\u001ed\u0000w\u001aoko٭%ラ\t>qvyW\u0005Le:%\u0004\u001cs|\u00040\u0002/F@\"..ŔI4\u0014d\u001cW-\u0013\u0019qZs5\\e˵D!u\u0015aᶳr\u0001W\"q\u001a\u0011fqM6lL6<\r+Sf[cK\ng\u0018A/v{h\\wjZs$EskfP8GZrPHܳ\u000f\u0015$뺾\u0010\\5OH,ːaOʖЄuWqq\f\u001ai\u0019X.\u001a9{A9E\nP\u0001\b}>B\u0018\u0003iTS7Z5-sm]\u0018WКWFq9\u0005fn=\u0005\\B0W;Y=#m/>A2n\u001a\u000fُ˪\u0006O\u001c\u0016\u0015\u001830\u000bQ5<wy\u0011{J7\u0019?ro\u0015.[QC\u0002q*yp-%ja[ԓU6\b߷k\u001c|u8\f\u0019jP*;2a t\"zmQx\\N^\u001aW\u0010\u00060ׅ~kp1Bh\\w˵<]yȬ\u0004\u000b1ҹѴZ\u0016\u0007\u001c;>\u000blqaA.j)[w\u001dZ\t_9\u0017\u0007V\tkv.\u0013\u0015y!/˹0;\u0018#\u0013XqD=\u00166+^SI\u0019cW9l4\u0002\u0005L\u00121жq^d!fp]%/\u0001ִ3XJ\u0003#11{\u0013afG<F\u0005eWj rp\u0012\u0014$>iYxoޠEu4Eqc\u0012'm-CؠsԽgJ4w_\u0002Z\u001b\u0000UGk8\n)˞\u001aГnP>؏>\u0003;8/\u0019VCć\u0007W\fezXt0\u0012G`:hd5>a'cG}\u000f/\fs\u0013\u0001z\u0000>\u0010*\u0017Oo\"^-v;>N޻ޞ\u001e'xG0\u000e\\k^YQ\u0002\u0011\u0016HGJD<4HQE\u0006䨒bD(SmzF+p\u001aԍ\u001a$\\'݇hIP\u0014\u0001Ǫd\\]׍,ڿ\u0004t\u0004\u0001\u0002\u001cN5ܯ{v^\u0011n鐇\u0004̝\u00131Tjm\u00163*\u0005T\u001b<j]m\\u<\u0016K!JГy4\u0016+hZ|?\u00108D\u0017v{\u0006\u0004۬7NףY6t\u00137l.An\u0000yuw9r0[f\u0004\u0019!\u001eɗ}\\,\u001f\u0003֜ȏx\u0019:[;vV\u0017xWUf;\u00174Q'a0v\u0011\u0018Y_wmfT\u0006T[{\u0013m=j\u0004I\u0013g!TO-\u000fAnjg\r/(\u001e}ͫ~WV}/6L$.di~ҏ#\u0001mIp[\u0016a\u0016K\u0018\u0010BSup\r?\u001aNcVϡ<f#F$1,e?ƨܳGRU4iR\b\u0015\u0007B\u0017/ueIZVEWl~/ˌnإ{.3W\u00151xY0[\u001cqy왆\u000fZ\u0017Y\u001cxf֧Q\u001c3_AQؘR\u0016}2\u000e\u001d*ylE\u0007\u0013#'ezLtfj\u0018kƓ+:\u001brb̾jDmzvͩ9(w\f`Uݙ>{\u000b>J3\u001cVزqއpl_oE\"\u0001i2dEMF\"-r[>{+hdto@\u0010\f\u0005^\u001b<&\u000f\u000f\u0015˶\u0004L^Ϻ5robs˷b1\u0014S'\u001dB\u001b\u0012c\u0001v֘Bpe왉്W\u001d4v\u0000IF\u0004\u001d6eN\u0000x.9\u001e\f\u001d/1g\\L\u0003lj^\u0004c\u000ein~\u001bfEG,[\u0006s\tV6\u0005eOr6\u00195oS!M\u0015St@Ӥ)+R-zSƺ\u0001*6`\u0005~\u001a\b+st)R^FU5USV(/mW<\rf\f0 {aɚ4l9ЌoB=L\u000069[JKm\u0007\u0019|kj\u0018`\u0002\u0012\u000fn(\u0013\u0012DSG4\u0013EUfM\u000bV\u001f\u0006\u001dºQ\u0001\u000ekQ\u0000?*\u001a1\\mY4WB\u0019tś9;8\u0006CY8ހOU\u000e\u0014lb=QWsęO_RE\u0012R\u000486ShM4vݞ{=M]6oVY{k\u0016\u0001tE[\t$M&(Ӥ\u001fFe\f;F\u000e\u0015B\u000f8\u0000\t\u0000ho<ac|cע;'iAU\u0017EލV|&εOK\u0003Qd/\u0013f\u0006GFwi\u001al7\u0002\u001b6B\u0011\u0003J(\u0018\u0006H2Zˍ\u0015%S?X\u001fo@#\rfwHm2d)]wǰH\u0007\u000emn@\u001fcPK8\u0001m?\u0003\r=³k\u000fyA\u0013̱B2Tf;})\u0007?,Hk\u0019AxJ\u0006^/d\tˡ*.VA\u0019HW \f2eOQ\u0010#2^Wh%\u0002l-ޚ`P[\tJ\r(\b1CH\u0019\rfq8ظNexI\rlYj\u0015\u0015\u001a/;(\u0013-\u0004l\u0001&MsE1gO\u0005b\u000b\u0019Y!\u0006en-Bb3&D_\f`8m\fid\b\u0015FEnzt]_\f5s)ov3>f<t:J\u00129\u001b\u0000PK[\u0018gwm\u001de%ZSؑ7\u000eJ\u0010;/r\u0006ao8Ry\u0010-\\d\u00128\fHGIy\u001d\rvBRC?\u0002\u0015q)\u0013'u\\:xQD\f!H&\"̣5uiQ.sC#3O\u0013J}\f\u0013Ғ\tИ*JK=WaN-~\u00003$MMVk]B+Hm]\u0004\u0006}q\u000fmٖf,WL\u0012O[\u001cju:\u00014N\u0014!z=~\u000fQ%NGSZ#IqlHgV\u00020j\f}7ܪБk*PolAdk\u00116}*|q&*\f\u00137\u0014V`KV6\rLؠ\u001e\u0013Ӗ\u001fhi\u001f\u00008\b`|v#\u0003cjؖ\n=\b桭+<\u000031`\r\u0016f\u0012%zyγ\bY\u000bH\u0019Y9o\u000b~eO:(\"4*!}\u0014spKC\u0006d\\7iZ\u0018y8^s,\u0017\bJC\u001dj⻅\u000e5U,\u0003\u0004d?d\u0002L\\T\u0003[4\u000b13\u0018\u000f\u0013\u0002(#/\bTޑlVxRFBk^[qw.9\u0001;̟\u001dT\bk~OeۭSy|Tz7oRrz4\u0013`\u0006\r2sGffGw\u0016}Qxpc\u0005CB\u0003xLw2Q맍?u/1j&1\u001c\u000eF\u0006\u001eΏ^\u001auJ'ǣtg~Lb\u00183<\fͲ,\u0010\u0001\n\u0018P\u0018\u0012\u000746j<)s&tpaynݔ3\u0015mWn$\u001a\u0014=m~{]nh\t9\u000f;4\u0001ͻD@g\u0007f;\u0015<\u000bk\u0012(Ӡ\"`z\u00001>\nп&؄_UV\bN5י\u000e\u0000pOIč>6d\u0013^Fz@sh/'T@\u001a<J\u001c(_m[\u0018MzyK\u0001epؗ\"LE\u0003O\u001d\u0007bѵAP:'d6S\u001a?Jiz84߄G\u0011:Z7\u001dYѺh<x\u0014\u0017\u001d7\u0017&wx#LLMDgl<n\u001eFC4\u001fXh>MBף(h}RP=\u0018蛀2~\u001e7\u0007\u0005/\u0012z\u0017\u000b=CCH@ȷc\u001d31\t\u0017g\u001b\u000fD\u001d%üۧjXdI\u0006NXlhEK3\u0017J!\u00190cWKH0e(RsdzFN[Nlޏ|iI$&\\dB\ts]d2RotaU+;\u001c\b\u0012򈀜- G#4Qԣ\u0001N \u001e!Ettr[9ĩ1>\u000fn\u001co(\u001aC5hǗf\t8r~4U~+\u001b\fS3b\"\u001a\u0016\rT\rƇl\u0018+\r%\u0012>,OĄ1H\u0006&k\u0018<&3b@\u001c:V˗\u0003V-_￮\u0005uszׯkǶ6𺳽_9\u0003sszCBko_\u0019=~\u000fp0A7\u0011qbү]BP\b:\u001c+Dq\u001c_G(\u000f\u0001\u00038K^\u0007\u001fxN\u0007t\u00072Ήg陎G-\u000f=?a7`Q\u0018\\\u0017\n\u0003jD^\r|uOM>7p虄ڞ)\u001c>e\f9/$ u@+ʛK]\u0011B\u001b#\u000e\rh\u0000t$l)]E%\u0005KA\u0011g\u001c֯\u001a#\u001b \u0010k\u0014,\\4,VPQ\n\u0004/U.W-b\u000b$K]wd_.-nn$~\u001d\u001e\u00106\u0005pV)#Ck3C\ru\u0006)%F/6\n\u000fZdj^*q\u001fLCOJ-4C\u0007OO\r_OǄ\u0015}<D\b\u0000q{\u0001\u0003;66W9Riez\n\u001c?r\u0010\"=Ʌ\u00118h~W\t\u001cys\b\u001aYa. D\b뉋;\u0013U*]Eu{v\u000fzp[֫_\u0007&):6\u0000\u00054^X1\u0000\n+%#\nTg\u0001=WF\f*\b\t-\u0004'\u0002q\u0005\u0017㿎nCIt%ia\tK*$2F\",A8\u0011\u000eHV\u0013J\u001e\u001e+\u000fF-by \u0018\u0016iӉl+\u0016\u0014~\u0019~\r6\u0014꼽b\u0010\u0003`L\u001f\u001eNo>\u00175\u0006LǨS\u000f`نɵRn\u0001#LqvO)G;=xH~NeJ\u001beOx\u0015\u000e˗\u000f1e\u001ft\u0003\u0006\u0015]b\u000eHe!Pr͕pCH;\u0000W\u00066Cu@G\u0001/#K=;qǹ2\u001fx)\u0003R(@\u0007>s\u001e@=\u001e\u00188]_~\u000f}?\u0013ۘ\u0017mrmᇝjӻ2\u0014n\bRhvjo鹀\"ZU6E\u00174\t6\u0010O>:k:BW5o\u0002}z,\thg\\~\u0014Yn\u000b\u0019<Ն? \u0000>;r)p\tJɒ\u0005`$W\u0016>DC?pflHڱ\u00154\u0011aT9\\p\u001c#٣4y@U}Gw2\t\u0002|EeuYKɕlN\u001d\u001bXKKe\tsF\u001d\u00060\u0000+:Cj\u0005\u0016_\f-ˮ\u001e+@C \u0017z率\u0012}\u0006BpQF6J\u0010'6<Iգ*@\u00195[aid\u0012?jPV\u0002\u0012~&´0j$&&\u00101Z4\u0016mLn\u0002;x\u00139\"5k\u001c+\u001a\u001c5ZI 9\u0006\u0019c\u0000>\u001d`\u001bRnFK9)vUǬ\u001aP!9Ny\u0003g[ O\u000eˬ^B_ZT,zt]swPt\u001f\bf-lz\u0012!mOK\u0004@._q]\u0006νd\u0013R\u0003L\r\f\u0010M_2\\U -\fqVƞ\fB튣N%=uy{\u0002Vu\tL4\u0001@Vכ&s\u0016NY\u0002pAO&'\u0014Z[\fp9儶\u000f\tg۷\u0002,6g\u0018{aĻ(LQjq\u0014Q4ٻD7J\nϺ82ʴ;J]\u0013\u001b5q>,wdnXKҬ@՞*=Mǿq,܏\u00032Xxa\u001fS[\u0002*̮~\u0017p\u0004;#?&fWm\u0013@̕y\u000bFlZ%)\u0000=\u0003}\t<AF3V\u0005>=8֒u\u001aِѵ\u0019|\u0005D\u0017K%N1\nqYk\u001a\u0002X\u001bI1~P\u0005$dXvԹZrOo.?iHt 2k<:_b(\bu\u001b'*\u0015)\u0001p\u0002R;W\u000fNΣ*;I¡{\u001f̯\u001e2|B\u0016`u\u00041;X2CI\u001d$e$KecU\u0016\u001f(\\\u001fHF۟zԜ\u0011BfI]x\u001e\u001cpw\u001a1O)\f^\u001c{2\u0018Ű\"ϼw\n\u0011ޝ\u001d>\u00103rsET5g1*3$\u001d&S{xK\n{WY\u0014{(\u0000\u000e\u0011$Rg%>L%Kfa=@}\u001b\u0015`\u0000F1\r\nendstream\rendobj\r47 0 obj\r<</BitsPerComponent 8/ColorSpace 48 0 R/Filter[/ASCII85Decode/FlateDecode]/Height 106/Length 1243/Width 106>>stream\r\n8;Z]!9t$Q7&;=onp>TO$kq%2?36FR0jC2GVA3HodMP#>L:l='VnO/$'K*q*f087E5\n_0i$e+1ja+A;:+X9h]d'hAr$Pke0&5h9gRnA3)\\+8?_c5%sG*70^T;_#.osG?*^([\nZ*)/i7%FDD7G]Q@>H*riTfR6V'D9c_?*8Sa;)K[(dFaFAQb@RDQah'#$B9eCn\"f;>\n:`Dn_0d0E_mp(feFg3MlW6pDX=C0a\\?DtBI\\?@A3!Jj)&?9>V.'u,Z!BiW;*jA_;0\n<i4`c/#,qjZ&OT?H;Ta0\"tS>c^e0l[b2+@1Ga1%PSD%+?e)EMq4f:^Ia8j=*'\\C34\n7&Ra]P)m._5?4(!VNrHk8l_86<#Tg<FbD5DR-7E3WOAEM?EUWj4dBba;nP5Rc-ebY\n\\J(>('+TXl[FH_OA4*#,S_*[K`dKtULl(,-_tg[mLRf6*5H>@@.kUhn6F!H7-^s;*\ncJMTm^K7&5*P.8?S=h6tS3k<'3i5:oTC%5&*$Yi9gj@r`i`k2Lr$PQFM>m'C89N(%\n?lt<*[$5bJ8CYOpL!5mU6_[I6de@3&f<%;V*_G@K8sPn_<*F!m:j?#Nnb!IIk+L3A\nmod70#JIf_:[/)mV$?\\O)=N8Qk!n)n$QOtPj-g\"`JbG:SUJe#`;j.*8M:HTKd#)j=\n/\\/s):s'HJ>odfl'%Jn,Ds(+_-^N-OU*/GK#]\"\"tYVkV^*N<0Z'pITmm<4fO??_g;\n%i(9nOZL\"q7'SU)WVXsr%B'rGd$\"h*+(3@C9H*@sC8,V1]UELWSPF8R=mrtK+*o7P\nlnSI5RsM!AV+df\\Smjn4`&cT9pG?;%PpZ=o5;VS0.d,dgVbhclMffu)MnB:Y^VX.7\n11$oN0(^4L\"(<Rr*Q>UhFOFbb)pY:U8=m>35<53OiOn_g(Qp.F4fF/@J_F\"eiYR?P\n%kZ8g1>h+pV$5A\\8^HIPZ>%ne5*Y^M0ZbcOED@#LTU&.94kWo?Qi@\",?kP*#^bMFu\n9MOUk;oAP_U-mda,?+<k8\\X^?NZP'f0+,%YXti\"s#)W-cGSH@\"(8a3ZS*=#FKdtOU\nC%;cn0_\"\"u]I1&X$^Eij0:rY8KUSW1-'aF2_Z/ULa[i^Z6VSj9;k.i\"i77?ja\"\\sT\nQZO$aG3IWg?h03j.XrP*]pCE`QiN<,\"el?&P\"a?f&\"=E@pN`XW<f^,5oo'(>;meKL\nf@Ks_VQ7iSZW/c/M!/b;TDhuj4*p@U9R$-c*LZ?Z]c/a*)$#b\\Z$-~>\r\nendstream\rendobj\r48 0 obj\r[/Indexed/DeviceRGB 255 49 0 R]\rendobj\r49 0 obj\r<</Filter[/ASCII85Decode/FlateDecode]/Length 428>>stream\r\n8;X]O>EqN@%''O_@%e@?J;%+8(9e>X=MR6S?i^YgA3=].HDXF.R$lIL@\"pJ+EP(%0\nb]6ajmNZn*!='OQZeQ^Y*,=]?C.B+\\Ulg9dhD*\"iC[;*=3`oP1[!S^)?1)IZ4dup`\nE1r!/,*0[*9.aFIR2&b-C#s<Xl5FH@[<=!#6V)uDBXnIr.F>oRZ7Dl%MLY\\.?d>Mn\n6%Q2oYfNRF$$+ON<+]RUJmC0I<jlL.oXisZ;SYU[/7#<&37rclQKqeJe#,UF7Rgb1\nVNWFKf>nDZ4OTs0S!saG>GGKUlQ*Q?45:CI&4J'_2j<etJICj7e7nPMb=O6S7UOH<\nPO7r\\I.Hu&e0d&E<.')fERr/l+*W,)q^D*ai5<uuLX.7g/>$XKrcYp0n+Xl_nU*O(\nl[$6Nn+Z_Nq0]s7hs]`XX1nZ8&94a\\~>\r\nendstream\rendobj\r46 0 obj\r<</BBox[328.926 402.706 995.569 -130.626]/Group 50 0 R/Length 357/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Resources<</ExtGState<</GS0 45 0 R>>/XObject<</Fm0 51 0 R/Fm1 52 0 R/Fm2 53 0 R/Fm3 54 0 R/Fm4 55 0 R/Fm5 56 0 R/Fm6 57 0 R>>>>/Subtype/Form>>stream\r\nq\n0 Tc 0 Tw 0 Ts 100 Tz 0 Tr /GS0 gs\n0 TL/Fm0 Do\nQ\nq\n0 Tc 0 Tw 0 Ts 100 Tz 0 Tr /GS0 gs\n0 TL/Fm1 Do\nQ\nq\n0 Tc 0 Tw 0 Ts 100 Tz 0 Tr /GS0 gs\n0 TL/Fm2 Do\nQ\nq\n0 Tc 0 Tw 0 Ts 100 Tz 0 Tr /GS0 gs\n0 TL/Fm3 Do\nQ\nq\n0 Tc 0 Tw 0 Ts 100 Tz 0 Tr /GS0 gs\n0 TL/Fm4 Do\nQ\nq\n0 Tc 0 Tw 0 Ts 100 Tz 0 Tr /GS0 gs\n0 TL/Fm5 Do\nQ\nq\n0 Tc 0 Tw 0 Ts 100 Tz 0 Tr /GS0 gs\n0 TL/Fm6 Do\nQ\n\r\nendstream\rendobj\r50 0 obj\r<</I true/K false/S/Transparency/Type/Group>>\rendobj\r51 0 obj\r<</BBox[328.926 402.706 428.038 -130.626]/Group 58 0 R/Length 108/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Resources<</ExtGState<</GS0 45 0 R>>/Font<</TT0 40 0 R>>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream\r\nBT\n0 0 0 rg\n/GS0 gs\n/TT0 1 Tf\n0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 151.704 0 0 161.7572 328.9263 267.9219 Tm\n(O)Tj\nET\n\r\nendstream\rendobj\r52 0 obj\r<</BBox[427.989 402.706 512.359 -130.626]/Group 59 0 R/Length 108/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Resources<</ExtGState<</GS0 45 0 R>>/Font<</TT0 40 0 R>>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream\r\nBT\n0 0 0 rg\n/GS0 gs\n/TT0 1 Tf\n0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 151.704 0 0 161.7572 427.9888 267.9219 Tm\n(p)Tj\nET\n\r\nendstream\rendobj\r53 0 obj\r<</BBox[512.336 402.706 586.336 -130.626]/Group 60 0 R/Length 108/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Resources<</ExtGState<</GS0 45 0 R>>/Font<</TT0 40 0 R>>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream\r\nBT\n0 0 0 rg\n/GS0 gs\n/TT0 1 Tf\n0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 151.704 0 0 161.7572 512.3359 267.9219 Tm\n(e)Tj\nET\n\r\nendstream\rendobj\r54 0 obj\r<</BBox[586.367 402.706 671.034 -130.626]/Group 61 0 R/Length 108/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Resources<</ExtGState<</GS0 45 0 R>>/Font<</TT0 40 0 R>>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream\r\nBT\n0 0 0 rg\n/GS0 gs\n/TT0 1 Tf\n0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 151.704 0 0 161.7572 586.3672 267.9219 Tm\n(n)Tj\nET\n\r\nendstream\rendobj\r55 0 obj\r<</BBox[671.019 402.706 775.167 -130.626]/Group 62 0 R/Length 108/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Resources<</ExtGState<</GS0 45 0 R>>/Font<</TT0 40 0 R>>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream\r\nBT\n0 0 0 rg\n/GS0 gs\n/TT0 1 Tf\n0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 151.704 0 0 161.7572 671.0186 267.9219 Tm\n(H)Tj\nET\n\r\nendstream\rendobj\r56 0 obj\r<</BBox[775.163 402.706 855.682 -130.626]/Group 63 0 R/Length 108/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Resources<</ExtGState<</GS0 45 0 R>>/Font<</TT0 40 0 R>>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream\r\nBT\n0 0 0 rg\n/GS0 gs\n/TT0 1 Tf\n0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 151.704 0 0 161.7572 775.1631 267.9219 Tm\n(o)Tj\nET\n\r\nendstream\rendobj\r57 0 obj\r<</BBox[855.718 402.706 995.569 -130.626]/Group 64 0 R/Length 108/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Resources<</ExtGState<</GS0 45 0 R>>/Font<</TT0 40 0 R>>/ProcSet[/PDF/Text]>>/Subtype/Form>>stream\r\nBT\n0 0 0 rg\n/GS0 gs\n/TT0 1 Tf\n0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 151.704 0 0 161.7572 855.7178 267.9219 Tm\n(W)Tj\nET\n\r\nendstream\rendobj\r64 0 obj\r<</I true/K false/S/Transparency/Type/Group>>\rendobj\r40 0 obj\r<</BaseFont/QGTLBC+Cambria/Encoding/WinAnsiEncoding/FirstChar 72/FontDescriptor 65 0 R/LastChar 112/Subtype/TrueType/Type/Font/Widths[687 0 0 0 0 0 0 653 0 0 0 0 0 0 0 921 0 0 0 0 0 0 0 0 0 0 0 0 0 488 0 0 0 0 0 0 0 0 558 531 556]>>\rendobj\r65 0 obj\r<</Ascent 3117/CapHeight 667/Descent -2464/Flags 34/FontBBox[-1475 -2464 2868 3117]/FontFamily(Cambria)/FontFile2 66 0 R/FontName/QGTLBC+Cambria/FontStretch/Normal/FontWeight 400/ItalicAngle 0/StemV 84/Type/FontDescriptor/XHeight 467>>\rendobj\r66 0 obj\r<</Filter/FlateDecode/Length 30309/Length1 83058>>stream\r\nHtU\u0007XUW\u0012;<0dQ\"a\b\"\u0016%\u001a5%6\u0004Q4*\u0014DA\u0005{/\u001b\"*\u0005P)\u001e\u0013&&\u0018}1(f\u0013\u0015r\u001f9sf9s.\u0014\u0000U1\u000b\u0002{\u0005\u0004\u0007\u00177f68\"*&~X;\n&*>N\u0017B\bh@h|\u0005ԗ%螛Rs\fQ#t\u0002Ю\u0018cl+Þn11qӺ\u001fgۀ\u0018\u0015#o\u0002E\u001b\fML4{\u0000\u0011\u0005%`\u0011O\u0019K\u0011\u000fqe\u000bAiO\u001eeykaw\u0005Շpq()0y\u0011Z\u0010<M.favq\u0015&p-k\u000fk\t\u0015#L\u0011PV\u001aR\u001aDmV.P9}⸹s5bF*C:+\u000e:A>iT\u0015mk$dD,\u0013\u0001\u0001%\u001emk_TQ\r\u0006iCaL@;k?k/Rn@=X\u000fp=JSB~J?ҋ>|}6\u001ak}idsYllmV[#[mmm//^/^Y2\u001775\u001b%7\u000e#fkޥƞKPaH\u0014\f+Ns\u0013 syy\u001fK5Zg;õY!vOFU{\u001c\u001e\u000e\u0006p=Rqz\u0017\u0006'>\t\u001b5ZE㏯w\u0001\f\u0006\b\u0003?坥k*ǯ;H8*\u0017:P\u0017r\u000b޼|t\nxS\u0002}\u001b\bw\fq\f\u0006~\\NR^ds\u0006\u0003=\u001deG#aw%j\"9A\u0014\u0002\u000f<\u0013vl^ϛ]o\u0013pTw5\u0006Z\u0003\fNr:*px#b]\f=Gz&y.<y9k)yZ+mqq\u0012jkaeYP%jخ\u0002jz 5bT^S|RZ߅\nh.D\u0007[\u0016LUL&oWy\u0014+M\u0010E\u0013SD\u001dDqæ+)ߊ\u0002qP\u0014*D\u000b\u0018\u001d\n7T{*FoU\u0007<-U\u0017\b\f\u0015\r\u001aZx\u001fM\"\u0002EXXXXXH*\u001a:\u0006l&l\u0016ȤX41(:.)L5s\"DVވ\"X*\u0011-D'ΘjSVd]\"Kq\u000e4o|P\u00176Gc4A\u0010C{tl?\u0006` > a\u0018D$b\u000e~Va\u001bұ\u001d\u0019B\u000e\u000e PS838.+\r?~\u00133~xQ\u0006_\u0015;Q\u000f\u0010{\u0000h}\b@.\u0002\u001fQ\u001688\u0010\u0014!\u0018\b\u0011|hch\u000bv\u0002mcEGG'\\@g\\'.nk艛\u001b[;/\u0017KR\u0004\u0006>\u0018\u0006\u0010\u0011x\u0011\u000e\u0016Qx\u001e\u0001PLD1x\t\u0013/\u0002\u0012QXB\u001c~T(\f4\u001a&Y1!IQu\u001aK؇s]\tK\u0013N6L\u0014GS؏i*קi@ܐ\u0011M\u0019\u0001KIܘ9fl\u000e9<\\\u000ey^9^i>-ܔ\u0016q0-%܌s\u0002-\u0016\rx:Dh9\u0015C(Vq(\u000fi\rܚq\u001bZmi\u0003D\u001b\u001dm1m\u000e;R*w\tqg](vF;;=){.M{7\u0006؍p<܇q_0~i?\u000f\u0003<\u000eǃ(\u0007S\u0001\u000fB\u001exC<\u000es8\u0015p:\u0011t#\u0018\u001cE'x$Qt43<?<;\u0018:Kx\u0002\u000b<t'%LW*Ok\u001cKy\nxSRL.WrUM+tnjFUwur!7ȍrܬfYr[ʭ2M#tu.wN!3.%w=j+92[樹2W\u001e\u0007ez@=j,<,ByD\u001eqyBiyFyyA^\u0015yU^\rySޖwB~)ɯjlƟ\u0004\u0005`VG\u0016\u0006м<\\ܟCq\u00025\u0014J׻KU%\u0010'\t.-\u0012zR,rJjZzlFlflVlvp\"Xtb\u0017\u0010؃\bE$\u0010\u0018\"\u000eNq2D\u0002!\u0001H~\u001cA\u001ca\u001cQ\u001c\u0003@;\u000eCP;\u000e#H;ʎcX;Ύ\tvN_:aN\u0013wM)'9Mv9xEmUv\u000em\u001aIPa*\\V{TTQ*ZŨX\u0015⽩*A%:YN~u@\u001dTauD\u001dUquB%:Ψ:.꒺R\u00154UTY*[\\U*TTnꖺ;N;ꮺ\u0007z\u001e'z\u0017z^7\u001b\u0011^MsH?\u0005\u0003\u0005B\u0015LSh*ԚP[jO\u001di$\u0014*TQuA5\u0016զ:TQ}j@\r\u00115&ԔQsjA-\u001du!4p\u001aK3unԝzPOE}]zާ\u000f/\u000f#>O?}F\u0003i\u0010\r\u00114Fh\u001aGKn@V U\u0016wK%Rni[-w+\u0015m61v\u001166s+]v\u0003ne\u0004r\u0003E@NZ /\u001e\bdR\u0004pEi\u000fER\u0014ES\u001c>\u0018JDKh>-\u0016\u0012~h)-崂V*ZMkh-6&L[h+mvA:D\b\u001dctNP2StY:G\u0002]KtR\nUJtʠLʢlʡ\\*T@yTH\u0006ݤ[t}C\u0001=l:%#{f36ӞYͶm`sEG1\u001d'ͷmM6\u0016٫M7\t`\u0001{\u001eIb&I/.Q9 A)a\u000eIIsXJ#R\u001c2昔5ǥ9!MT0'9%i\u0019欰9'\u0001s^*\u000bbE\u0011sI`.5)\u0012joRU\t4bҥɐj&S,a29RJ\u001d'uM3\u0005R\u0014J\u0003sM\u001a\"idKcsCܒf47w+-=ieKk@ژ<v汼cH{T:g<Nt6/y%]kfHwVzH\u0014Gz\tIo_\u001b&o;о0?<53-+=;#'@r\u0006M04\u0007\u0011\f\u0015I&!%ْ#'R rMܐrKn\u001d+<H\u001e\u0013y*乼J^\u001by\u00108 \u0014((((򨀊\u0004\u000f\u001a\u0000*@\u0000XG\u0010UP\u0015P\u001d5P\u0013P\u001buP\u0017P\u001f\r\u0010\u0018M\u0014\u001c-\u0012\u001am\u0016\u000eڣ\u0003:\u0013:\u000b\u001b\u0007z\u0017z\u000f{x\u001f\u001f/C|\t>E|\u0001\u0018A\u0018!\u0018a\u0018\u0011\u0018Q\u00181\u0018q\u00181\u0001\u0013\u0005&K\u0001ğg\u0005\u0015`2?\r?/[|\u0003~O1\u00150\u001d30\u00130\u001bs0\u00170\u001f\u000b\u0010\u0018K\u0007Az\u001ez\u001e\tz,</\"/\u0014})<U_i:<CLγt\u0006֙<Gg<u\u000e/йP\"ϋu\u0001/хƿ\"^2}뛼B6wxk=^:뇼A?1oOx~[3ު6뗼C5o8Lp\u000e\u001e&b\u0015GQ\\\u0004pIR\u001cǥ9>.\t\\\u0013<'L\u000ey\u0016uoB^r\u0005\u0015\u0000W!|pre>\u0004'I>ŧ\u0018?֟yӼHo\u0017𢽙^7ˋf{q\u001c/ޛy\t|/[%N\u0010\\\u0000V]Q\u0000\u001cf핝\u000bEQAPT\f\u0011\u0010\u001bPInn`ѹ\u0018\u001bNi\u0010\u0000\u0015\u0003~O|_3\u00067,g>o\u0013V<O;$O\u0014O{4OL\u0007l}?\u000bQ?\u001fO\"/|?]gğ\u000bYȟFWFWEWGDתzzz%x5k%OuQj4NREUЭ(P\u001c+[JC.ݦ;UYUT\u0005\"\u0015XH\rX\u001aVhVjJZO\u0019=Fmfm&m\u0016P+\u001dQ\u001dW:c:jW^KzU\u001dR<j\u0016kjNhjkiF\bAt\u001b\u00155Y5U35E34MT]^={tjkE\u00057z[]}wSGW?\u0000T_SB*H~0Ds4I5Q)UU\"E\u0005ZeZ\u0012-\"=fz\\M#%B\u001d~N\u0006nS[Qk,,w:ouJ߫M\"s#\u0005A;*b#\u0019B[\u0011E\fAo/t!t\u0001ŕ#*\u0007\u0003C?~\u000e\u0011\f\n]\n]\u000e]\t\u0006U\u0018\u0017\u001fwsPm\fpV0,\u0018\u00007\rr\u00107\rs\b7ҍ\nnKrc]\u001bƻ\u0014\\p.e\u0007/AkVvNn^~Aa0<\u0018\u0011\fF\u00051AR06H\u000e\u0005oq\u0012\u0006iAz\u0011d\u0006YAv\u0013͍&G3yќXp\u000f\u001f\t\n?:z\u0006F\u0016\u001bP=ȍ=\u00175p_Y܏\u00075Csx0[kGP\u000bv\u000fc/^rcQ\u000f\u001a4@C4ch\u001c\u001cM\\\u00034?\u0015\u001a_D3<'\u00143x6&\u0016ϡ9Z%\u000bx\u0011\u001am\u0016\u001e/X X\u001fF\u0007W\u001a^\u001bx\u0013omw\u001e\u0007\u0010\u001d\u0011>'\u0014s|N\u0012\u0005]\r\u0003=\u000b\u0007}\u000f1\u0000\u00031\b1\u0004C1\f1\u0002#1\n1\u0006I\u0018dx \u0015iHG\u00062l`\u0002rɘ阁٘|\u0014`.\u0010Q\u0005(F\t\u0016b\u0011\u0016c\tb\u0019c\u0005J\u0012\u001ak\u0016\u001e\u001b\u0011\u0019[\u0015۰ݕb\u0007vb[؃؇88[\np\u0004G]\u0011+\u001cwn\u0015N$N\u0015838s8q\u0001\u0017\rwޭď\t?\u0017K;\u00157Uk2\f1e\t\u0018Jx\u0003oMa1<\u0013)FX\u0015\u0019VF\u0019c%y;+\u000e-᝼UXw\u001a\u001e\u001a\u0001|\u000f\u0011⣬:z\u0006lF|لM8\t>ɧ4|ق-<_llöl|/\u0003_|\rɷ\u000e\u001f#?3~/؉_3+;{'{7/?\u0007p \u0007q0p(q8Gp$Gq40cq\u001c\u00142`&\u001cN`.88S88388s\u0002<\u0016r>,B.b.R.r`)Wr\r\u00116Fh\u001bcI6kΒm ,2,Ӳ,rlZMI6٦Tn&fmʹY6p=7X\u0015\\g6ߊl\u0015[-EؖR[fmJ[emu6FdmmmvNem}\u000eA;d\u001dc\u001d\u0013vNi;cg휝]o[ξ\u001fG~_Wd7+e?vkv=LB(!.%M@\u0002\u0013%GJuuu$}\u001a<slw(\u0016l`ElT.]\u0011{\u0005+6\r\u000b\u0012KbXbFgNrdИ3_ri;3yV>=+j\u0005-r\nXN3y<i2?70O_g̳9yhf\u0015yͼn0o\u001dkU*l[E,\u000f˶Zb\u0015[%V)򲼭ҖkZ~V9\u0017d\u0010Q\u0001r^]}2vY.g+x\u0019u\u0019+e8\u0019%e~ϭ\u0003.\u0007el\u0014Y+eT-{elUN6\u000eY-eCrX2d\u0002ǲX4)d̑D+I2O\u0004(L\nY)Kd\f\b\u0019*d\fp\u0019,C$Rv\u0016IdhX/d,I2YH\f\u0001_\u0012[m\tP*$no\u0007\u001d@IK\u000fi\u0007I/-G\u00000,\u0000(B(\fw\u0014\u0007l\u0014\u0018\u0004J\u0014<e5ߘ]\\;v\u001df\u000fJTPUFթ\u0006դZTP]GT\u001aPCjD\t5fԜZPKjE\rvԞ\u0002\u0003\u0005RGDAԙPWFԝzPOE)B\u000f~ԟ\u0006@\nA\u0014Ni\b\ra4\"((b(FHQ4X\u001aGi\u0002MxD)TFi\u0006ͤY4P\"ͥ$Gi\u0001-ERZFi\u0005dJUZZG)6FDi\u000bVFi\u0007]^G)\u000eA:D)Q>7J\u0007(C9G\u0005ʨꨁڨ\u0007G\u00034D#4F\u00134E34G\u000bD+F\u001bE;G\u0000: \u0010\u001d\tA.n\bFw@OBo \u0014}\u0017\u001f\u00030\u0010a\u0018p\f\u0010\f0\fG\u0004\"\u0011h \u0016#0\u0012q\u0018\u0018\u0018񘀉$LF\u0002`*a:f`&fa6 \u0011sy\u0005XEX%XeX\u0015Xd`\u0015V'`\r֚\u000fo͇Xg>SwtΘyʤ+tn\u001dG\u000f\u0011=\u001f\u0019Hg(8`\"/#\u0015\u001b\u0011\u0019[؆؁؅؃؇H\u0001\u001c!\u001cF\u0006(>\b1>_)>qI\u0002%,<.\"2q\tq\u0005W\u0015:n&n6k=|xo\u0010\u001dc\rO\u0003x\u0011Ox\u0005~Kdb]87\u0017y9\u001fٕ\u0016q\u0001vrA.ąٝ\u0007\\qq.%\u0014{\u0017{sia_.eُqysEĕ\nWj\\kpMŵ\u000ez\u00017FܘpSn͹\u0005Vܚp[n9;p wN\u001cĝ\u000bwn\u001cݹ\u0007^ܛC8p_y\u0000\u000f0\u001e<P\u001e9#99cy\u00048\u001eţy\fq<'DI<\u0013x\nO+3Nwg\u0011vw\u0016u^p\u0012Ssf:;82REKU\u0016\u001f+Ӻd<.{7\u0018-F{ʧT Oe#WaM\u001f:IV5e௴ޥ\\\u001d++.\u0005RmwK?׫E#5.G9\"{GԱ?}V'a59P{\u001cVOM\u00163T\\j\u0012j=vҜ`R\u0005^jމTUjV\u001f\u0015*O)љ9ܓor+@{R\u0007\u0015.Tijjկ\u001eop\u00156Z\nUck\u0014ijګ]jg@b\u001eUy\\b^U*Kj]\u0012\u0012蘨bXng*I}y,ɟHRK)\u0012Ti#\u0011\u000b:_\u001flHQIZqF~2ʿΟAm\u0016\u001f:o:cѺ.t\u0001j\u001at߄`s\u0011{!Nw$'J\u001a+Va}\u0013Ku_MU_gWw5\u001a\u0019%S5pW|.TZ6Z5|O~w}w\u0003y\u000fԫ{i\u0014DMWkR~\u000f\fOU[/W[l\u001cW\u0019>\u0017^KM&3v\u0013;mZغi2x/zI\u0006f\u0000Y!$\u0004\u0016m\u001f J\u0004\u000fUE8\u0002ɑZD\u0011\u0011\u0010T\u0007zA\u0002\u0004E\u0010\u0002?3MS{Μ=c\f-foUmX\u0005^9v]\"^Ӵw\u0005\u001cKѹHo]\u0010_PB|\u0017$b'+i3{\u0016\u0019-#\u000f\u0010Kuziv\u0000i\r 2X\u0015vU{ŵ? Q+{{O(\f\u0015wDFEVOjo\u0003}d3ӷ\r;\u0016:\u001a^=\u0004zk%\u0016\r\"ooFHGj9\u0010<fyZd\"td(z\u0017Ы&Ы\\PX\u001b{#OG?\u001ao\u00196Π}\u0015\u0019eW>Ϝ?鳟:|sٙO~NN;#'}4V<zˎ~:|\u000f<\u0007\u001f}\u001f\u001eڷ7}{\u001aL\u0016\u001f0|.cm[\u0007z;$:㱎h$\u001c^-)Y; wd]\u00109s8~ذd})zag_@%iKr`n0+Ȏf2o`>f𼌤\u0013c3iB;;i\u001a2¯\b\u0014~c\u0015^8C4kof\u0000d\u0019<i;[[ǹPV6y\\FbG6'@%ޔl+#ܓ\":VJ\u001a\u001bMKm1\bb{=s\u001b\u001b\u000b\"_E--jr{v\u0001,%\tݕ\u0015ٹ.\u0000\u0002FW7 \u0004s\r-qHSP\"?\bx\u000fGi,HkB`7`oak+Q\flU\u001dY\u0019ҪH\u001b{Wft*S\fW@`TVJ\u0000(\f95x=,r\rjmΥ0\\\u0003Nڋ!޴\u0001Y2^>9iy\\>\u000buaM\u0011\u0004I\u0005N(d6\u0015ŪrT>^e\u0015Mx\u0007\u0001b\fLYu\u0017H\n]39ueu5+/h\u0010#\u0000\u0003qq,©ͼ)wb\n}?儑֠OVZebe\u0003hUrN\u0000\n\b0nqL btHp$Rr /\u0002ooi\fu{\u0019\u000f_O\u001aױ.Z\u00124u÷QiJ&(&'py\u0006Jդq_\u000bz^AzZ}Fp]xD;wJ\rK,,;Rwkڈ\u0010\u0014{ɒ8I*Z/\u001c16;C#\u0007(<\u001atۂd\u0002&*!\f,\u0014:a#'fU\t2\u0005\u0006eMI\u0002c!2\u001a8\u0011@!4)\u0016F'lٌqYi%J\u000b\u0004a-L\u0015[4.>^\u001f\u001cVW*Wʸ?22\t\\ߟF(X0(e\u0007b$bz\be$k\u0018\u0007\u001di9\fBE}EQ\u001de\u0003\u000eJm\u001b\u0019*\u0019 ہ\u001bDk\u0005͠Z@\u000b\\{\u0004W\u0005U;U2Lb̑[6-\u0004}Q\u0013jFΖͩ\u0018͵\u001c@L$F\u0010}n}{@#ПZvj#b݃\u001b\u0007pʖ\u001dX)c\u0004\u0019Eg\u0015*\u001bm+h|$)|9@ݙݺ\u0014.Ӯ\fe[\u0016-HX=\t]lQ>4\u001eBН=J\u0004\u0004\"]r#iGș0=G-'\u0012fdGQxװ,!\f\u0015XĔ}C\u001f+i2)hCh\u0017&\u001avajھ3/!-uGnK1KAC\u0004% m8mH$6qEo\\\u0018+lD\u0001~1\u0005`\u001am|\u001f4\u000eX\bZ\u0011>S\t脹\u0014\u001a\fluEi%B=!X@\u0017\u0001\fNz4\u0001\nN˸$M\u0006uP\u0012ކAs\"['\b\u0017?q\u0006'\u0017\u0012\f\fQzЃ5\u0004-2UiO85u(T6?}Q\u0017!&C\u00104H.17*(\u000f\u0013\u000f xLxp*+P<Ѿlfh\u000e\u0015\u0000JP7o#u\n\u00033pԀ1\u001d\u0002|Dg+\u0007%y:aq֑@\u0014e'$t\u0006\u0012@QP<C4\u0010\b\u0004\u0018H'M$s|M\u001e\u0015#cЗ\u0019\u001d\u001dOܧqGJv\u0016\tݨ(-\u000es|#\u0012|V\u00005r?FʑAu\u0019>d\u000eD95\u0000%;Ժ{\b\u00029-\u0006\u00048[hp)\u0003\u0006X\u0007\"\"T%+$f&\u0017PHi%)\u0006I\u0015+(>7 \"b\u0002\u0017}hnP\u000ek?\u0014_4=(\u0019d`\u0017\u001co3@Dۉo({n+~,*8Z\u001b0j`黟.\u0011b\u0011:VoM1\u001bp@\u000f#L^uJPD:\"\\T=N\u000bv{=yz\u0016h'P\u0018\u0019TƔ\u000b<Xmω.F)(#4\\(H\b!Q}3\b\bDW+x8V\u0002C\u0006'ɳ\r\")\u001a\t:>]?Wkp\u0013\u0015˲ݵvW\u000f[d{eV2\b`l\u00070\u0016\u000e5j\u001bp4\u00101m\u001aqLSJ)SS\u000fe)mfҌ4a\u0014\u001a\bLɐ`,ܕ\\<Dsw{ws\u001b2\u001f\n\u001f\u0004!>3J=8',\u0003g\fu &=5f<WvX\n9@BAipL\u0016h\f\u0007\u000bwRO/.\u001e[؃\u0005tpo%\u0012Dw/,\u0018>-&[\u0006$AnГ\u001a\u0004Q|B\u0007놜SG[\u001e\u000f}L+~Z\u000f\u001d\u0015\u001aa!(l\u001et\u0019\u000fj.ب\u000e+gh\u0011oa\u000fP\u0013;Otj[~M(\u0015UU.g\\3{оoşf\u0017\u0019hY\u0018qgʹKcB[F\u0017\u0000[\u000fs\u000e~F\u0006ՠ\u0010\u0004jS|$QS\u001bBJs,\bas(A'\u001bP\u001cU2=\u001cPf<\u001ex\b1\u0015\u001f3Ό\n3\u001eg.]Ed\"MKSD@\u0006)Р$o2E^J\u0012F\u000bubemJ{\u000eS[+ՋB\u0000o^ O멞\u0005_\f:\"JJjUOÕJKm R\r\u0005k*;\u001d_Nm;\r\u000eB\u001eCHG֢hpE5*[)*K<\u0014M<e\u0017'F\u0012/.IYBO,\u0005ֺ'+a|JtTF8((#HaEŞQNTdd8oȱKePNz}#%׊\u001cܔ{i2\t(C\"L\u0006^\u001epD =<\u000fwL|m81]g)\u0011\u0003aD((\u0010[8>?[@\u0012Xײ8jNWKc1&l9ճ$#X,x\u0017/x\u000bRK'l)о[^ \u000fZ%\"\u001be\u001bRQ\u00182і'v\u001f.r\r27LRd\u001bC9\u0013\rr\u0006\u0005\u0002d2\u0001\t\u0004zx\u0003L\u001aA;\u001d\u0003ӣߞ[Ξ~H[7\u001c\\\u001bdV\u0012\tuG{='ҳ#Z`O\fݰ~23$T (.9DAmDt@%\u0014ə]nh2̖We3(5ϻaqF[9;h0\u0017\u0014(\u001c.XD\u0019vEe\u0007\u0014.\u0011n9 *\u0000\nAHD6A,'\u0014\u0001B\u0006B~?%햼tc.\u0012_&t\u001fBb]\r:/~^7uNg\u001cX4*Kݍ;ȩ\u000b\u001b\u001b\u0005%\u000eyCEfnQ/Rȁ\rmu\u0017{\u0005ؗT,ˎ\u000f\u001d$r0\u000e㖃6Q\u000e\u0016(aD\u0005r\u000ffx#r1N=mL\u0002\u0011ns\t6t\u00170[2\u00137uq:n\u0000^Z\u001cJ0U\u000b\u0003:K\u000b#9<p\u0014t\u0001w\u0006]\"H(*#%_ (\b\u0005$\u0005<*\fz\u0003u@qͷw\\8\b5=oڡ[SW\u0000豍KZO\u0000j\bg\b\u001dӰj\f3\u00025Pp!QhIjj\u001akFAcFL!1\u001d\u001d\u0001+\fK\"2\t֓I\u001cD'\"\fբ\u0014Rm\u0010u$\u0017\u00003W5A\u0001  \u001e\u0014\u0016\u000f\u001aG\u0014\u0002\u000ePEA\u00184\t `#G>b,w`˚\u0000S\u00077˖oJ4m㍶@$Vyeokm%[վ<?Y\u0002!\u0017[Wԇ\"1i:N#ё[vI\u001a\u0006\u0000m\u0007M\u0000,\u0002jHV!`ܰ\u0004r\u000e\u001b\u00181\u0013\u001dB()q\n5ek3#P\u0007\u0005+u?8p\u000e330s\u0015\t\r8\u0001\nb\n mo?\u001cxo\u001f\u00035oZlڽ ѭ\u0013Wv}r=Ľ7/5\u001cZm|\u001bߚ\u001a _g\u001bY\u000b\u00050\u0015\u001eV\u0003BSR(eDbSf\u0005?\u001deyMl\u0001;\u00045V*+f\u0000WTs\u0016ki\u0007-\u00049<p2F\u0002\u0002W5bȩ\fygS\u0004\u0004\b\r\u0004\u000f\u0005\r dF\u001cbImv#]*\u0006hu,9q˿}zquﱫWڤXbږ\u0005Ԇe5N΄II\u00057OLq\u00105y.A\fH\u000fAT!3\u0017>B.#¿H#NDo^`p!<\u0000}\u0005h>Nbgmvί.4\u0003h\r}\u001b?[<\u0002uT3\u0015Ϡo-@èO~n\u001cZ\r;H \u001f#@q>o`x>6<?*\u0014Y\u0006k\u0017݀揢t\u0004U\u0011`*X\u0012Vӕj>[f}B\u0016\u001e[`\u0003,>z\u0019v\u00165٧\rc8k\u0018c\u0018빦a>0E1\u001cV=(J=ӻv}̡\u0015\u001d_5{9'\u001d\u0005AA@ QP|\u0011\t\u00125\u0010%W\u0010b\f&(A\"\u0015mGiepF-/\u0017L\u001dꈥU-HjjD﹐ACo{گu)Ve\u0013Q_C~\u001a\u001aQe\u0002C?S#Is\u0015t7iBQ\u0005\r\u001d\u000equs3Q]m\u001c\u000eq9᠏\n\u0002\u00170~Nř4A\u0007Dl;s9g>93J_\u001cֱ.%Yh|3㌸9ؚ`\u000e%|S\u0015 a\nl]7t_־=\u0007\u0010\u0010|t}J}Δ33S\u0017L\u0012关hZuѯu}YS;x^H?<[*\u000egM1^\u000f]98A=s(޿u|V0\u0013?\u000b&C09\u001b{\u0001\u0005ׅ?sN|<dskP\u001a氵<\flck\u001e[\u001c_[K㧺i@ƻQ\u001a\u001fCS+\rs#4,F6$w.N=]ڡQ\u0012*ߚ\u0007\u001a\u0015RUpq#i31\u0006\u001f(s2~]\u0015G\u000eVK)\\\u0015y'`Ҷ\u0017~BQDSEtF\u0006rw(\rRz\u0012G9\u000e3{xFVۿ]}A76?htLy\u0017l\u0015\u0016\u000f\u001fkZ\r3(g\f6ʿgx\u0006Aa\u0017S/oj:oC\r֨3B&MV\r4R/k:Kq\u0017R\u0007-9'+ݠ)!\u001e7\u001fkHX_\"O\u0011\tqk\u0003AVt;N\u001bଜ\rj\u0017\u001cpޠQa/葮\u000b7\u0010crrجB-\u000fj\u0007o-ϾIO\u0005giGc:?g\u0019\u000fͦ+K?A,Bq\u000b4í{7y@4?\u0016 IO\u0010e'^MuKU\ne&\r'2\u000b/p֩\u0013ܓ`ZoSL\r\u001d\u0013u-᝙=\u000b,\u000ex~{\u00136\u001eg|uqlLq\u0013^Ibۧ>l}(̴EU\u0019mR}wY\u001f{\\\f'ecvWs.sqFԊ\u001cvNST\u0006g|,c\u0006ϼZujf\u0014B~&|`/M^nUA\\_eGͫ]\u0010Pi[`fM8\u001b3\f)UKK^&>U~-h8;\u001ek37z\u0005]e\\Ӽ\u0019\u0005Ṝٯ\u0016\u0015~6Dgf\\\u0003s-nl\u0004\u0006ک3kOn\u0017{}u7T\u001cvc86<JhDWCܕ5|hc)~mîPIEnƇ0<|v<YE}j*cҙ\u000b\u000b*\b\u001dd\u001bU\u0017U}q>%8wH|\u0013C}TDYwb6yho1X6\u001c\u0015込ĈFpz'XEy\u001d\u0016p\fgH\u000bm#~\u001f\u0007\u0012چz\u001dy0|\\Tӱi+d\u001a]f\u001fQAR<Kn;=Sķ\"\rB#\\\u001b\u000em\rHy_\fc0\u001f41n\u000bW?2x\u0011{Pm\u0012\u0007\u0012\f\u0015p;,\u001a\u0015ĪR͇L\u0018\b`\u001aKګ`*ԙ\rC]\u0017\u001f+5?coN?+{Ѩy k,\u001fY]\u001f6]9G\u0013ptX3\f5\u001a,\u001aƞ|ΨxEKxVj\u000e_}\u0014Z\u0001լ[q\u0011VQ߃v\u0014F,y.9v_ؕ6պ\u001a\u000f|\u0007,Wh@/4w4w\u000e\u0004XB<<d}<De\f汋\u0002asY\u001ac\bk\u0000zc}Fy:Ը\tK\u001b\u0019Rǻa\u0010|뮞/إSE<y܋>>S\\X\u00070F\u000f{Eh0\u0007vq'kRW롿R7\u0018\u001eMΕ=}t\r4A>\f\"\nc\u0004g!@\u0003y\u0003К2\u000bhKc\u000b_kaz+\u0012ʯ'|\u0004_@-Y=5~&;`umR7$\u0005&,Ҿ\u0017?D,(\u001b=IM?KKDߕae?䝹dg\u0012ߌG\u000e(4c\u0017Ѵ}evl\rӨt1e\u0013VZt1M'mj\"m\u0006f75Rs,r[,lV/r/ͱYnEOn\rsq8cD1T3$V{JUp\u001a\\\u001a%\rϧ\u0003\u000e%oFGgӧ\u0015}\u001f/z'R&F-JO<zQ\\?\u0010\u0018M-q\u0007ֿ\r-(}fhH4&VpICJLn\u001dJ341|EW/r{?\u001a\u001c5]Q1wf\u0015K\u0018<g1RkZ56S\u0015թ5Z\rtubBz\u001b\rН0)N{\u001f6<wyn\u0002$\u0006HD!\u0006A4U\u001a@\n1\u0016\t)\u0001yAH4bX\u001c\u0014\"\fZ1\u0005FgDEeZ\u0014,ZŎSKQ`D(T\u0011mu\u001a\u0001)}nn\u0006ah~ٗs\u001c\u0007\u0016[zhFGw8ٶImtZ_j\u001fdmOU$7@\u001fUY6x7Am\u0006t~Ron{&\u0007C[:ՃQ\t9\"\u000b\u0006c_\u0018QOCPFA:dH6RS\u001e#'FGv/Մ64\u0004gkK\u0007'sj\\\u0004h#\u000f\u0013Ng\u001c\rqLjQM,ƂXo\u000e9w\u0015dtx!&O\\?e2뫎a\u0014^\nڍ!_IN1ٞ*\u0007E!BK\u00106ޠ!ƛ&/F\u0005`\u0013\u000efʃrtA\u001d\n\u001eQUJ1T\u001drz6\u0011* \u0015/Ck_a1mnqBsp,z<|p޽\u0000o8+7\u0013s,4!\u0010q\u0016\u000f\u0004Z_Sτ\u0012jRɗy6jx\u0007\u0003\npx\u001f*\u0003kxz\u0002q\u000e\u0012p>2TrXÎ\rmQMcU\u0000\u0006\u0013,ys)|O1\u001c\u000e\u001d7`?gM\u001f.`\u0006NNǑ|4\u000eߋ#1nz}>nWAz=>\u001f\u0000{TZoყE3\f*V'qVxo\u0019k\u0007#\u000fhvn yZt}r\u0006rt3QxK@v:o4l'ܞ@۴ۡC\u0001\u0018\u001coyxK\fe[uG\u0002v%^G[f*u6N\u001at+h\\;~z\u001f>R\u000f\u0003`\u0003W\u0000\u000b\u001br)r]\u0014<󅺘ݬfUaIaolQ&\u0015f\u0015{4[l!U*6'.\u0013/B~v.ț\u0016I!\u001dh3NB)Pg׎|/ļm\tˡAs?5nbb\u0014FՌ_\u000e\r\u001f\n5\u0010\u0007;j\u001b?{j{&\u0018YaƎ\u0003RL\r\u0018\rЧSCg\\9TtY\u001dM3i7h2]2;YE^ pn2}Af\u0018{)ல\"kՙ3#*\u001cV2\u0000w|W\u001byϐ\u001fSȜo\u000e6\u0013}\"'1Ȏ!W\u0013wv\u001bVK'r5[\u000b\u001dK\u00164KiͿgU{{i\\>7\u001fQ-\u0000\u00177rv)\u0002k7H7eP\\mnoA\u000b6\rpfWcoְaC9\u00068\u001fBhoa&;[T&\u0016\u0017\u00020\nyFNt2{%C?05\\<z\u000b}۫Ԃ1559\u001dIPfv'iCZU-\ta!Angp/w\u0004fsoݸgfMܻ7-:Y\n\\ȓxIu\u001aތ\u001c2`B\u000ef\u0012\riPd7t{b0r?Ҽ}R\u001e5\u0018=Ⱥg\u001dH+T\u0019&\u001f\u001eB~\r}\u001a]l\u0002{\rO%\u001b؞^H\u0016\u001e~)1\u001eFh\u0006\u0007\u001ag@78-VEI8D\\\u001e;Jm0˦\u0011']\\|\u001fLa7bjD\\sw:'8yv\u0007s+ǰ/{/Q7cSTc/cmDA\nL/e%i>tGCq cZB\u0017wd o\u0013|[>S_\u001f\u000by}%F*n~*4\u001b<M={\u0011>H0;|{V&]\f]Y\u000fw\u0019;aM\u0006wR.˿Lld?~xsX\n\u001dzÓ\rry*މl\u0007˩V?\"\u0005\u000b%Sol2\u0003\nm\u0016uԑ[9|\u000b{Ub\u001eÑ%Ƈ7X+w\u0012'Ͼ`X|\u0002O7oڿ@k\u00194pn3^@\u001d7\u0007?PiG2K{RiЮRbȤC\u0015\u001b{^>?N\u0012y\u0006\u000fp?+\u0004ƨ<K&\r!w5\u001cD6U0k\u0007^ݣXۋ˩\u0002䟂>g\u0016*S\u0007\t~\u001dfڭ\u001a_mݪkl15Q.e7\u001cM\u000f\u0000r3β4 ئ\u00013\r;\u001bI]}\u001d\u0005\u0016\b\b߻\\\u0005\u001e2xrHd)Dȹ{7S}N0I\u0003:\u0018_i=^LWH>`\"\u0007ki#媍\u0014)alj\u001b㳩[|{'\u001a\u001dB8\u001a\u000bka\u001f]IQag7j\u0016h 8EE))LE/58)Cx>I۫[y)&L[k\u0006mƐ\roWwh:jky\u00139w\u000e\"'Z3^AQ^g\u0018nZ\f4%\u0003*\u0013̈\u001al\u0011\u0006h\"x\u0010\u00151\u0018\u0015VKEVP !^MS-!c\bԌڑJ\u0013GNƱ8ww|syo{OCE\u00064.|ίr4*zs\u001f6O˜\u0012c8'M~R/\u001d<4\u0015k⓿ J?u@:9F5>.&O!~|\u001e\u0007R:\u0014#'h4v\u00154\u0015\u001fRL\u001drW'\u0018Z\u0013\fBmN\r\u0017\nVw\u0019\u0018锻\u0018k\u0014'^FrǾي'u3c3Y?\u0005\nگP,\u0000^Las)\u0018\u0015қQP\u000b9i\u0007w\f\u000f5A;SO[zA\u000fxg{n\b]\u0003@Ÿ?Fԑ;CA\u001aݑ|oUUi\u0010jw\u001d}4\u001b\u0019+pܗXjDo#}N\u001d\b9:OOr\\;\u001aUgM1\b5swUu\u001f?lי5G\u001dqx*\"[8nN\u0015\u001eFc[W-ćG:y&')ݚ\rrt{yN\r)Dߧ²8%&W\u000bV܈Y\u001eC&w1{\u001c'\u000fǕ<{;oSS\u001fA~x\u0003R/d}f.1~\rcXY,ÒPwK\rk&뮢'cك)|b\u0011\u0005&d|\u0018?h\u00189u9y\u0001>YJ\fF\u0016t k%\\l\u001c:FVwsl\u001b>Wi\u001fK1\u001fd};1g5|\b|3\u0010\u000b%_M:\\ԯԛvJSڕzovŖwְo5$\\>oQ]JqyӃy?\u000em׻\r-n\u0016r>\u000bܨ=礊ϴi\u00067i\u001f\u001dqF;__}\u0016x>\u001fߵv/\roŴ\u000f\u001dC6*c~3Y`)\bƀ7A\u0011\u0000\u0017RJ=$\u0013`;\u001a\u000e+\u0013.i _E \u001fL\u0006zP\u0000惙a)h\u0000+A\u00190}GE`\u0019}p\u0014Ԁwlp\u0012\u001c\u0000@%(ï\u000e\u0012]\u001b4*PϨ\u0013\u0014uX}\"ڬV[(MQB˻dg\u0018?\"+\u0016Fqg1>\u001fOQeX5Hle\u0017*;f\u0001=`28\b''T\u0007\" xحm\u0019TQ\u001b\u0016i\u000bc{\u001d_[U\u0016\u0016\u001a8yoʼ*s>3r=ci\u000f%O8Ϟ\u001a\u001fBl\u001cn\u0002E/;\u0005?$|\u001d~e\u001dwzZQ\u0016N\u00056+Ǘq-̷5S*oj{頯V޿5ҙ\u001b#\u0011>\u00073\u000b}\f\u001fp1\u001a>\u000bsbjC\u0007y̓}\u0004qʷ\u000b\u001f\u0002_\u001bs\u0017_&]t.\u001bw\u0007g\u001fcX8d\u001d\u0012+}M=i/A.lF%\u0005U\u0010sw\u0010\u001e\"o3A\u001e\u0015\u0015m}Ǟܭ\u0013M\u0003}I\u0019e\u001f\u0013\u0001\u000b<m\f\f\n9uï`Oa\u0019-\\oݬ(M#rK!Dp[IȀc|P7\u0005\u00001,ĸ*i\u0011\u001c/TUJ\\9u\rkJ\u001eX\u0012Po+C|v/֦\u001f\\9pcWGT7\u00059\\\u0017QͻI~\u0001^mC5rix}0\fc\u0015k{\u0012\u001cUc\rx\u0007?c\u0017\u0018ݖُN)̫f^\u000e>T*d\"z\u001bszr\u0018M4-t{\u001a)q\u0006?\u001b䫫ɡz*5b\u0003]vB\u0003\u0013\u00079cP\tt!?\u0010\u0001A0ԋ^4TM~R=,\u00051\u0016\u0001U)b\u0007A5n\u0012LP=>ྼ\u001e\u0006veb/4\fW9 w\u001e=.\"c\u0001ZEX\u0002\u0019t|>w3(\u0002ÙXE~\u0003L?˝O_w4i;*\u0007g5=̇7\\OM%F{W\u001bNLÅq\u001c\u0006<|5۩G\"o\u001a[Iv\u001fnEXS8wclt맑f\u001eoQ{u%%:A^^A.^M\\J]yMې7c\u001a9e|a\u000eu[\u00115\u0003noˣ\u0006ʎط?Qu]F,jר1:P\u0006.\u001d$8EeeSw4z=)/1=yN\u0011A?f\u001buǓ_n*NM\"d!w\u0015b͜,mG\u0016Ds7{\u0016n+f}\u0012k\u0013{4hRG}&O!\u0014])\u00015g1\\1>r̘ũqUƷ,sv\tΧ:ګ\f\u0010>n*w=\t\u0003:L\u001d{{\u0006)l=\u000f9D\u001d;5KeTr.RywCw\fcE\u001bGPýZ\u0014\u001d@ln|;\u0015}I;L20}ҽ3\u00015if\u000fw\r\u0001\fR)8J\tV\b\u001d\u0000:FɢƊJ\u0011Eb\u0011-uŀ6 N\u0016)X\u0006\u0011\u001f -2A@0Z8J%\u001f\u000e ޾dI֙sϹw{6>?צ\u000ev\u0006\u0013)g~\u0004>\u0002{\u00059Z)b<\u0015\u00160g\n9/WKg\u0014w\u0005*\u0016r\u0016k\fT\u0005\u0000\u0000\u0000Z\u001dǼ%_oj\u0004z\u0002=;8bO\u001cmZS\u0004\u0015D\u0012\r/\tcǢwWRۺѤ=Mb\u0004`l3eC݈g9\u001a\u000ewT{\u001fW~oUʝTT\u001craJ7*{\u0019B!N+>:y_\u0017\u001fu8g\u0004}FVeY\u001ec:\r9m\r\u001ai \u0007(7FAJY\u0013:~U\r\u001d[J\tYv_\u0017P\u001b!N(\u0019-׳\bYv6_~\u000f6s>\u001bȵ&YQd9\u001fzhT\u001c}9jj/PV}6T?y_\u001d:}gq{]u+\u0006/\u0001%UX\u001b4\u001eC?\u0016CB[Hv\u001f'ZS\u0015\u0018^$\u000f\rx+ \b\u0006\fBU4W\u0012ڀ\u001dZAUw\u001b}\u001cU2ԉ9\u00198_˼\u000eA~m}(\u0018\u001d|vJ\"O_U6܁##\u000fy **d\u0018rk[26ZΝب@:UyI9y*\u000eem58[4\u0007\u0013\u001b2˹/hVߩJ\r8TY&fX,;|~׸\u001fC>T\u0019o\"Z\u0014cV\u0012j/g\u0010oTM<\u001aR-_Au\u0016&y\u0016g!\u001b\r\u001b\u0006ٚO\u0012āJȄjʣF1wLSrG[ChQ{z/\u000f3y\u000eE~]T_>f\bP\u001e\u0003\nwB\u001b5jQO/\">=Y8|Y'A-u\u001a&sQm6ICV\u0016\u0007\u0002W47͜\u001e-[03\u000f\nxľ`\u000f픁RȌ40p\u0016kM\u0014br\"CiGqIRojL|a\u001c5m`\"M`\u001aA]4e\u000f쐰l\u0018o\u0005i|81\u001b\u0006i8\u0003q9\u001f0.-܁\u0001\r0\u0010Xn\f\u0006\u0019/9\u001f(\t4#&s]5}nu?NU_SvO4X{ș{/eo\u001fTMQ\u001duUYױ|\u0001\u001dmۿr^ߡ/3:\u00116gUd]\u000f}%Gc\bvޗ\u0010(Q\u000eP}[V[8;I)B}{F\\O!zX+r\u0016x,Bim=˙ڬj\u0003^]߬\u0001W1n:3sfZtK(ܧ\"\tjN9g2c9_X\u0011a@\u000e\u001cWԓ~\u0003[{Gzos\u0019J)E@l\u001f\u0019-g܆CnOJWzB)l;5)cY2z{-\\+WE0\u001e|.\u000eq>IeW\u0019w\\6?獖2}Y\u0007\u0019G;=r|\u0012N\\, rx\u0002((wŬxM<%v#\u0014(.\\J^Bs66!\u000fRf:Ιc\u0015L}ǾQi[\n{\u001cG\u0005\u0014y\u0011mG\u0010\u001flMcc}#n\u001fн7$gZ\u0017ؿ\u001a{\u0012\u0006~]ZMO*Uj?\u001b/{tqܙwRU`\u00132\rsb]!7UΘ\u0017j\u0007|J=\u001b=\u000fyJ\\Q.b]F:\u0017j<giv\u0017`H)ޢiy\u000bܢ#y%1PNKFȽpy~\u0015ed>Iڦ\u0013. \u001fIsx'̴\u000f\u0006w4}~%L+E\u000etg\u0006Fk5~E\u000e\u0018\neLa}Z\u001a9\u0018\t>O\"\u0000`\u001a쇕P\u000foC0\u001d>\u001fP\u00047vƯ\u000e\n(1|ǌʠ-\r\u0010}WrC~LHn\u000bn5s{}5:n<jEJ\u0010wSĄ8i[IF\u0012ChWr\u0011m.&ɷe\u001e&\u000f~X\u0013}iɮӋ!ș\bk5\fa\u001a\u001c\u0002iȋRtoe\u0007xU\u001b\u0013u;Y\rh`\u0003W@r\u0007(7FAĔk4O\u0003BY\u0019_(eCL\u0002\u001b\u000ed?!\n`65Tk\r=1XXǙqM\u001e\u0011(\u001d.ph5@GL?3_!a]r\u0015%t\u0005m[Lli:Jΰ-O OQj\u0016U\u000b\u0014Dw_?F\u000f '\u00198\u0017\u00037`Iѩ\u0006u`lC{\u0007WUq9{ι>\u00140TyX\u00070FQ+`\u001b42Hmd@\"IDM\\Ցh\u0014*\u000fIv\u0004bEK*JmpĪDpa(woS3{v뷻I\u001fO\u001dy/\"IfqnfkH\u0011\f\fj[\u000e\u0010\u00199c\u0016H4\fLV~Je\u0016\u000320)UL\u0011~l\u001fûr\u0000K,{\u000f@%ĸ\u000bG*{\u0015),汏\tyt_\u001e(1\r\u001ch-0\u0019O\u001f\fJep4\u0019\u00193\u0000&]\u0012\u0000^\u0007k8zv\u001f)}\r/PM0\u0011)ߎI܍U):zS8\r\u0006\u0016\u001coRXG񩺎+\"=t713I\\a\u000f|\u000e;\u001dIO`\u0016 i)ܺ/\u0002.O>)@GsfT\u0006\u000b.sBc'\u000e]iF:zwT[~#h\u001czSܬw,GQ}Tn޶2;S\u0010퓄薞f\fRk{}LiDԇ%;>ѽ2]>lﯻC؆ܘ)}utZ\u0017UH2q\u0012L\rnJ_x%lr\u001c\\jflp|O\u0019ZMhW\u001b{ZK\u0001}3Ln>A\u001d+FdgӍOL2N@縏\nMY\u0007\u0017Y8\u0019Qt!{}h3/eLlttop!,\u0013,\u000byIS&,\u000b\u0001W2qIS!`\u0011\u001a(DsN\u0017+a=s\u001c>\u001c\u0019K\u000f|q.Z4/ #Z{^\u0006\tN2_I\f{\u0007o20ыHQ =b}u'gIY=\b\u0003ҝ\".JxwJSuu~\u001b2Sŋ6ce0v\u0006Z\u0019\u0003:g\u0006e/U&\u0017yA#\\,UBJ\u001aڶ=^N\u0005uû}\u0001oդį\u001fKBYX])_YǴww9g^W\u0006\u0015k\u0003֒\r;\u0005q9Ά\u0015X\u0004zy\u0005q{$iԖ]ȶŏ\u001f-vBC&7\u0010WG6W:zCuz.Lߞ\u000f{7~xJKњ\u001fIuq\u0000qH\u0019{|\tmSִZF\u0005ly9؉=ɭ\nm\u001e3\u001f̋\u0006ߣ(v\u000f#w:z>o͒ol} \u0013!49\u0015ߴėac\u0013\u0002w!SwJ\u0011:FoIe;cFYN-RM𑕼mf(]L ԩM\u00156ѼYyu)IFHd\u001ec6qG2͗<ҿQT\u0012VimsGu+k-r0.\u0004Ȕ4^d>\n2s!\u0004\tr\u0002سoJk\u000fO/HB\u001ao41\u0017mM|1\u0013֯C\u0013{xi\u001e_^iV\u0002Q}EuxS\u0010w.^f[_Zjΐ\nop|W\u0006zWI\u000f|K;|G\u0016fR;nO\u001f\b=iNͦ/g~JOt\u000f;jFm]\u001f/6>׺\u000eͯi7ME;±ܽfH|\\/kTYmk3454Ket8\u0011/gPF\t\u0013qK0(n4{]a\u0010E\"\u0016[&Ȋ\u000e&*PI\u0018$f\"n\n]\u0004>v+D5\u0018ߨ\u0015S\u0016<\n\u000fv\u0001)n\fKȯ[#=\u0014կzPFA+>-1nYϜvǍ\tl[s\u0005,f\u0015m5n+ȿ\u001c\u001a-Mٯ/x\u001a<+Qa\u0007}O`LNMt\u0012\u0003}>\u0005\t*(焅MG\u0004\u0013\u000eN\\ۮ%y_@|῏)Iz5܈>9Ŀ\u0012)J\u0014KYJ85V5\u0012=em\rQƿG\u000f){e\t\u0015ǯ\u0013|אnnc\u0015u@\tߍ\u0001{lF=\u0016!G.o\u0011$|tuaˑ%:8mT\u0019\u001f\u00048uuSw~\u0017q l=l6y هX7$.ď<h}Nc4\u0016]^(2\u000eﾊ}\u0007߃׶\u001a\u0013D\rIZ>~\u000eǷ\u0001VǟS\u0013#?~6~+nJd.!k`;|wPn\u0016\u001a׮/ߟ.J\u0013=5\u001c܍r\u0016i\u0014Ky]\u0002Df%{2(Q2Rc(\u0007){ZdyV9!||\u0019\u0012x2bܪxdqȠ`\u001a)\\r{\u0016?\u0016Q>\\f(Fb.f>2\\ҘF28˺{Y\b\u001beB\t\u0016QR\u0006E\\f\u0006eY#\u0018k)zp qoF]E<\u001b=u개q2Ǝ}(w1\u0015O(\u001dи\u0011\u0007ثvI\u0018P$dg\u00011%\u0012\u0006\u001aoFl2msQ}gζR]h\u0006I|\t}2ϽMKgW\\|\f\u000bf\u0011c<%%W\u0018[\rG06V8lu3K\u001eV_J6։\nnX\u001bTk446\rN~N<t:ڮ2@U/O\tkc\u001e|\u001a&ڹr\u000fw>{C`\u001e4\u0004Ba\u0002!aAP\u0002y~\u0005,\u0002\u0011\b!7\r\u0012\"m*\u00068paah%\b8H\u00192\u000eT\nUP\u0010X\u0010\u0016\t\u0016*\f$>&\u0004{}{^{+-\"y㏠w3\\߱R2;\u001b\bY\u001aEin\u000f֣Ξ6K\u0011ǽȐop0d\u0011OS*owrd)b7x=<G̳\u00161@_ǸP}71_J^\\3]Gq\"a\u0010I~# 6ȓOb]%VUQċvXL\u000eطD%\u0017\\&s\t*0q\u0017\b\u0006byi޴u1e=}/.{ط+?G3?OH\u0019\u001b?\"\u0011].Dl&{H]6\n\u0010;.[#fJ'i\\y0_^b\u0018̺4ϯ\u001cxi\u0017iQ#ɫaޕ1!\u0006,Гѝ{v{\u0006\u0017%e?\u0012=\u00028z؆0mQ\u0004u.x\u001e_~G_\u001c\u001e<7i/+W۩IB\u0013\rrs#1~Z$O`Md\u0016'3\u0011+n \fY|\bhס2\u0007O\u000e9b\u00072\u0018,jG_qv 8\u0003a<s\u0019n\f12\u0012?\u0010\r\b^\u000eD\u0017\u0019z\u001c߻^xd5qց9j>Xk<kS>%\u000b2>+>8o!ogŌGg۬E(C'Q^\u0017bQϡ\u0016cJ'2WGE.g\u001cS5iiNdr|19o%\u0015LUqɉś1[շr\u001fr\u000b5koeao\u0019v\u001bkN givd#n!ZD7i!\u0010ڟ\"es\u000erh\fo,\u0005SۼG޽\u00043\u0018?1:\" [N@J\u000eqHSt^Կx\u0016\u001f\u0013.ƞ3B\f\u001fi#qK\b\u0011\b=X\u0019X\u0012e\u000fN?Շs#\u0006\u00127u}<;6\u0018w{\u001fB.\u0015z2.$o(!$<#D(!:ފ$ۖvc\u0010\rN{\u000e#\u0003{\u0004s?9Z◣s+\u001c9е\u0015-\u000e\u001fՆ,\u000f,\b}hCngNm˒\u0014`}R\u001f=׎rB\u000e>H\u0019/5*E!\r+a.|W\u001c\u0010*xE\u0001*HYS+˸\u0014ii\"k\u001dbOAqcR\u001d\t\u0001\u0004[m\n`3+\u0013m\u0004vײ噣2]X3@&hRH9N 6bߋy\u0019E'0P>\u000f5=\u001e\u001e,vu@\u000eB\"Z/y,|\u0006K01L\bn\"{\u000eٌ[+tٳ~c\u0015n\u000b0_7y\u001fE\u0018//\"\nhXBV\u0012V\u001e\rehE3d\u0017\u0015?N-+>V\f׹_o\\FGX`B\"\u0016ܚ5\u001fBc\u000by\u000eWk\\b\u0004.A_<\u000ee\u0005ߑ˘0~\u0013*\u0013\u0004tW4s_71wG(\u000ew\u0012įK.D\u000fYyd\u000eEA [ <>EncÜ)ɡ\u000e\u0001*!,UX\tR!:'\u0016#v^Ov9y7N`m`\u0016F\"\u0016fΠo\u000bN\u0007٭Z\t|)ۓ/\n\u0002e{ҝ%Q2JZ\u001cGYK3[\u0005c\u000f~fm\u000e;q\f\u001c#^cܴ\u000f\u0013\u0001S\u000f8`\u000f\u0018l_ͣvĮvF\u0002n\u00191:m5?\tP\u0018b%(ûŨq&̃\u001ak\u001eʭw&|\u0014ǢQ\u001e\u001c鐌\u001a\u0013<7cmti\u0011\u0018\fh\u0007\u001b\u0011ƠֳhenK\u0015_\u0016յq)@]P\u001b\u0004dPi=?<<Վ^6S\u0017\u001c+ݧQ>P\u001b5ν@ҸJt;em4r\u0017`3'i8hznjG\u001c1Z4\u0012+\u0006e\u0007(3?f<:\u0016rV>\u00066z7T;oGQ~\"|Q#hþ`?\u0007~17`ط;\u0011\"[;\u0018\u000fcBN|$\u000eQ\u001f־\u001c;2bHh\u0014B]ֆ/aoH6^lwТ\u001c֠CюX\u000fzi}C\u0002,'[yǽ8AX$Ul\u0000B<\"\u0006\u001eXv1թOǨ8r)\u0006@<\u000eN\u0014s,cq-s\u0017O\\4#\nV;D\u0003xwXhFn<+\u0018\u0016Yr~2\u0012w8ls|\u0011Yw\u0010W[#uQGx\u0006\u001c\u001fx2N\u001fMHb޴\\JyNae{\u0012\u0014\u0018$\u000b0@߉R5ns!\u0014JY\u001c\u0017\u0002\u001bu3wf\u001f^1\b+^1M`u0\b(\u0001c2I\nk{cݵy?\u0012\u0012l\u0011jE *Q\u0005y\u0014R\u0005P%J\u0004PS\u0012\u0015\u0013B\u0014S!J\u001b碀\u0010EUժѱ瞹3s\u0018\u0018\u001fk)Ծ`\u001b\u0006<AMqZc+\u0004[\u0012C<El_dUe{\u000bc!gK$7\u0015\u00187\u0007|<qRȶ1)2o*\u001aпq#:\n{\u0010.0c>9Ǿ\u0005\"j3f]\u0002F1خ;q\u0006\u0012*c[\u0016!ʐƹG\u001djF!sS\u0014M\b϶8H;4y\u0016\u0007\fW\u0011}7\u001e\u001amd\u0017] 5s J&5_.»\\\u0013ܳ&\u0018h\u0012{\u0003)丂\u0012u>\u001b)nd?1i\u0003]4ǡS\tUioN{SOw.p.ק\nz~\u0015Q\u0014#a[\u0011{Å\u001f.֌//R.&X\f.8o\"cЉ^\u0011M\u001cmƀc\u0012sE8C?︉\u0012<{\u000ef)\u001cw2=?}e&\u0007L\u001c_>\u0010\u0016z)\u001d\u0015+,R{B;h=\u001bц+\u000f>jz\u0007̶v;zO-1w㘉\u001abwcީ#\u0006>\u0013\u000fFa{_coUG\\0\f0\f0\f0\f0\f0\f0\f0\f0\f0\f0\f0\f0\f0\f0\f0\f0\f0\f0\f0\f0\f0\f0\f0\f0\f0\f0\f0\f07\u0004(\b\u0013>4\u0010:I7{\u0011\u0003jz\u0007Q0Y}h\t7,o\u000e\u001a\r7G71\u0005(C;ky\u001bבYޠ\fny;|q<b\u001aNn\u001cP*\"\u0014Z\nS\"ȕ)$\u0006\u0000\\+Gw#\u001f\u0006jD_D~vh\u001d*˰]\u000b͓u5\b:EukA\fS\u0013r~͞FdD\r݆cRյ-h\u0002r\r-(rO\u000eԆ`}]\u0016\fh ؚ57Áh\u001dGv]~ƔyjZ\u00035\u000fjY\u001dkpM&\u000eֻ!\u001cl\u000b`K5W&tDc0韊\u0006L^\u0007U}.76;Ln\u001f\u0006j\u0013݇+7en+Wen)ӭue̗\\S2_(sIϕg\\PK|̇ʜT2\u001f(2;٤Fe*2Wf2+2*3KT(3Igpe*3D)\u0013C\u0019[iLR\"nץ~)+R/I\\E\u0017I9\u001fK=-\u0003KR']NG-u_I+u]RwJ(uRI]+\u0007R_Q\u0013ݫdk\u0015RK'Rj\tRH}$_,0\u0004\u0006S@5\b`\u0013\u0001$Hj\n1C\u0013\t:)\u0005\u0013z1\u0017z1\u0017z1\u0017z1\u0017z1\\8BT\u0017\u0010Յ.Du!\u000bD:iyp\u001d\u0004\u0002A5aغ?\u0011=zz{ޠwNźb1#s\u00198N)\u0005\u0004H\u0011!%\u0003\\Bu\u0012\u000b\be\r~-iK7\u001cm\u0014)v;e!`4\u0002C^:M?ߕq,dR?\b}!%\u0004i\u000eBZӛZWӢm\u0007d4̇\u0007 Ɨ\u0017Ff/\u0006\u0002\u0002'f3*^\u0015(Al\u0010\u001b&ĵbXO\t.:S\u0000\u0001\u0000CF/(Q?C܎mJbcG0Ɨ&^\u0014˱\u001eXF6\u0015b\t^*<b\u0015*_(\u001adl\u0010U\u001d6\bu\u0016au\u001bfj_8\u0013\u000b(\u0015C&9@\u0017/ŘQXhn\u0012<V\\,fE\u001e7xhG4mVXު\"Ơ<@[5b\u0014Vx9J\u0010bTƋrPI.1F?\u000b\u000eކ\u0001?\"D\u0000[4aBk1\u001fq.F\u0018\u0012Q\u000b٠\u0012DZ苅R=\nmGq\u0001k4\u000e.\u0010b\u0004\u001d/F4ϮȪFÜeoGb_\u0018bu[q0<S\u0019\u001bF6nyH#\u0001uhEZ1F!#F4\u000fi+\u001d+\u000eⷭb]\u0015Z'SXkE[4a1\f\"\u0006T,JH\u0010N\u0011'\\rq \u001eubq8X\u0014,\u0013q?\u0007[b121R\u0016b\u001aF@Bd4\u0002⁓Jid̴r+ԾgΕ6ÊUfv\u00066\u0015/i]i\u0017إ]:YM.BG\u000b\u0017[ft\u0014\u0014X\u0006\u0017͡XŨ;t\rSёXa|\u001cTɌ;tfU,W\u001a\u0013b\u001df|.$韼lSU\u0014(ceu?lF=GanTQ@wb_\u001fl\u0006\nec\u0011'\f\u000f^;\u00130\t\u000e\u0004\f\u0001T~8P3\u001b\u0004Ň񼷍?ys=G\u0017\"d(MK^2gy<ƌ\u0005mNy%0Cͅo/\tbE\u001cg\u0003\u0002#\u0007u\\Y_^!\u000bl^zg\u0017\u0013.ŻtYMϛLD\u001ffOn`߇-̵+\u001aU\r\n|`P\u001a2sJ\u001b 5ē\faX\rLU\u0016\u001d\b\u0012́0-7Y`\u000bl%5mR\u001cIjw\u0004V\t\t\u000e\f͓I6sNٌf~ِ^؆fYY߸Syvz\u001a־A)ԓ7=G\u0017,CuOu߷hY73Ciҁ\u0015Ѓ|\bЪ+fbrD6\u0002qwܗ\u0014X\n\u000e,]*\u000fZم^n#P\tٝ`lZbn/cT\u0014{{:ڬl[h\u001fZxhkQ\"Y\u001dlD]֮%\u0019Α_K@F\u001aw7_\u0002l#j\u0003M\\jXIQ<\u0006l+l\"ɱ\u0017b1x.\u0006U1({䪒gEX)9}dr{F\u001fzn)-˚_&zYs=Y<baQVq\tقEYPJٳ\u000e-c\nNzA8m<\u0016\u0005\u000b\u000e1(ғ[GEs\u000e7\u0011>nG9\u000f\u0003WtCA+#?S̱>Y\u001f\u0013YKVzu\u0007G\\/\u0014\u001c\\\r8\nW~Q|W*JR\u0015\")9\u0015+Bar\\0\u001crtM@d~^f\u000fE\u001a\u0000d,qÚ5o!Y6\u000fs1!9-.XA@\u0014Z\u0010hΝt\u00055\u0004t9~J&-9V־j׭`SVA3\tQ\u000fF1\u001f6\f\u0001\u001a%\u001a}q\u001c?̈͏\u0016<\u0012wc6蔟juHQP}@,%a}P+\fEi@P\u001b^U(ey\u0002\u0014yEf\u0010$gY\u001eNZ\u001f\u001bD\"\r˚\u000f\u000e\u0001\u0013\u0011_qbM\u0012?\u0011\u00130\u001dqN\\ \u0013爳\u0019bH\u0013\tb\u0007I\u0011qb+\u0010kF\b\u0013!b5\u0011$V\u0011UD\u0005QN, | \u0004\rw\u000e\u0018Q\u001c[x\u0013\u0006^+x\t/\u00104A<\u0018\u000eQ<}^\u0010?\u0004vb\u0007nvlm\u0018͸\t[\u00057\u0006|\r0c\u0000p+?oO?\u0005\u0018\u0000o8\r\nendstream\rendobj\r45 0 obj\r<</AIS false/BM/Normal/CA 1.0/OP false/OPM 1/SA true/SMask/None/Type/ExtGState/ca 1.0/op false>>\rendobj\r63 0 obj\r<</I true/K false/S/Transparency/Type/Group>>\rendobj\r62 0 obj\r<</I true/K false/S/Transparency/Type/Group>>\rendobj\r61 0 obj\r<</I true/K false/S/Transparency/Type/Group>>\rendobj\r60 0 obj\r<</I true/K false/S/Transparency/Type/Group>>\rendobj\r59 0 obj\r<</I true/K false/S/Transparency/Type/Group>>\rendobj\r58 0 obj\r<</I true/K false/S/Transparency/Type/Group>>\rendobj\r41 0 obj\r<</Intent 67 0 R/Name(svg3713)/Type/OCG/Usage 68 0 R>>\rendobj\r67 0 obj\r[/View/Design]\rendobj\r68 0 obj\r<</CreatorInfo<</Creator(Adobe Illustrator 23.0)/Subtype/Artwork>>>>\rendobj\r44 0 obj\r<</LastModified(D:20191222212910+02'00')/Private 69 0 R>>\rendobj\r69 0 obj\r<</AIMetaData 70 0 R/AIPrivateData1 71 0 R/AIPrivateData2 72 0 R/ContainerVersion 11/CreatorVersion 23/NumBlock 2/RoundtripStreamType 1/RoundtripVersion 17>>\rendobj\r70 0 obj\r<</Length 1251>>stream\r\n%!PS-Adobe-3.0 \r\n%%Creator: Adobe Illustrator(R) 17.0\r\n%%AI8_CreatorVersion: 23.0.1\r\n%%For: (Nikola) ()\r\n%%Title: (OpenHoW2.ai)\r\n%%CreationDate: 12/22/2019 9:29 PM\r\n%%Canvassize: 16383\r\n%%BoundingBox: -64 -131 1334 1334\r\n%%HiResBoundingBox: -63.5531921386719 -130.625732421875 1333.33325195313 1333.33325195313\r\n%%DocumentProcessColors: Cyan Magenta Yellow Black\r\n%AI5_FileFormat 13.0\r\n%AI12_BuildNumber: 540\r\n%AI3_ColorUsage: Color\r\n%AI7_ImageSettings: 0\r\n%%RGBProcessColor: 0 0 0 ([Registration])\r\n%AI3_Cropmarks: 0 0 1333.33325195313 1333.33325195313\r\n%AI3_TemplateBox: 666.5 666.833251953125 666.5 666.833251953125\r\n%AI3_TileBox: 396.666625976565 306.666625976566 936.666625976566 1026.66662597657\r\n%AI3_DocumentPreview: None\r\n%AI5_ArtSize: 14400 14400\r\n%AI5_RulerUnits: 6\r\n%AI9_ColorModel: 1\r\n%AI5_ArtFlags: 0 0 0 1 0 0 1 0 0\r\n%AI5_TargetResolution: 800\r\n%AI5_NumLayers: 1\r\n%AI9_OpenToView: -1694.53191489362 1924.88644344249 0.326388888888889 1503 917 18 0 0 96 108 0 0 0 1 1 0 1 1 0 1\r\n%AI5_OpenViewLayers: 7\r\n%%PageOrigin:167 166.333251953125\r\n%AI7_GridSettings: 72 8 72 8 1 0 0.800000011920929 0.800000011920929 0.800000011920929 0.899999976158142 0.899999976158142 0.899999976158142\r\n%AI9_Flatten: 1\r\n%AI12_CMSettings: 00.MS\r\n%%EndComments\r\n\r\nendstream\rendobj\r71 0 obj\r<</Length 30931>>stream\r\n%%BoundingBox: -64 -131 1334 1334\r\n%%HiResBoundingBox: -63.5531921386719 -130.625732421875 1333.33325195313 1333.33325195313\r\n%AI7_Thumbnail: 124 128 8\r\n%%BeginData: 30737 Hex Bytes\r\n%0000330000660000990000CC0033000033330033660033990033CC0033FF\r\n%0066000066330066660066990066CC0066FF009900009933009966009999\r\n%0099CC0099FF00CC0000CC3300CC6600CC9900CCCC00CCFF00FF3300FF66\r\n%00FF9900FFCC3300003300333300663300993300CC3300FF333300333333\r\n%3333663333993333CC3333FF3366003366333366663366993366CC3366FF\r\n%3399003399333399663399993399CC3399FF33CC0033CC3333CC6633CC99\r\n%33CCCC33CCFF33FF0033FF3333FF6633FF9933FFCC33FFFF660000660033\r\n%6600666600996600CC6600FF6633006633336633666633996633CC6633FF\r\n%6666006666336666666666996666CC6666FF669900669933669966669999\r\n%6699CC6699FF66CC0066CC3366CC6666CC9966CCCC66CCFF66FF0066FF33\r\n%66FF6666FF9966FFCC66FFFF9900009900339900669900999900CC9900FF\r\n%9933009933339933669933999933CC9933FF996600996633996666996699\r\n%9966CC9966FF9999009999339999669999999999CC9999FF99CC0099CC33\r\n%99CC6699CC9999CCCC99CCFF99FF0099FF3399FF6699FF9999FFCC99FFFF\r\n%CC0000CC0033CC0066CC0099CC00CCCC00FFCC3300CC3333CC3366CC3399\r\n%CC33CCCC33FFCC6600CC6633CC6666CC6699CC66CCCC66FFCC9900CC9933\r\n%CC9966CC9999CC99CCCC99FFCCCC00CCCC33CCCC66CCCC99CCCCCCCCCCFF\r\n%CCFF00CCFF33CCFF66CCFF99CCFFCCCCFFFFFF0033FF0066FF0099FF00CC\r\n%FF3300FF3333FF3366FF3399FF33CCFF33FFFF6600FF6633FF6666FF6699\r\n%FF66CCFF66FFFF9900FF9933FF9966FF9999FF99CCFF99FFFFCC00FFCC33\r\n%FFCC66FFCC99FFCCCCFFCCFFFFFF33FFFF66FFFF99FFFFCC110000001100\r\n%000011111111220000002200000022222222440000004400000044444444\r\n%550000005500000055555555770000007700000077777777880000008800\r\n%000088888888AA000000AA000000AAAAAAAABB000000BB000000BBBBBBBB\r\n%DD000000DD000000DDDDDDDDEE000000EE000000EEEEEEEE0000000000FF\r\n%00FF0000FFFFFF0000FF00FFFFFF00FFFFFF\r\n%524C45FD05FFA77B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B\r\n%7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B\r\n%507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B\r\n%7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B\r\n%507B7B7B50FD05FFA7507B507B507B507B507B507B507B507B507B507B50\r\n%7B507B507B507B507B507B507B507B507B507B507B507B507B507B507B50\r\n%7B507B507B507B507B507B507B507B507B507B507B507B507B507B507B50\r\n%7B507B507B507B507B507B507B507B507B507B507B507B507B507B507B50\r\n%7B507B507B507BFD05FFA77B7B7B507B7B7B507B7B7B507B7B7B507B7B7B\r\n%507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B\r\n%7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B\r\n%507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B\r\n%7B7B507B7B7B507B7BFD05FFA7507B507B507B507B507B507B507B507B50\r\n%7B507B507B507B507B507B507B507B507B507B507B507B507B507B507B50\r\n%7B507B507B507B507B507B507B507B507B507B507B507B507B507B507B50\r\n%7B507B507B507B507B507B507B507B507B507B507B507B507B507B507B50\r\n%7B507B507B507B507B507BFD05FFA77B7B7B507B7B7B507B7B7B507B7B7B\r\n%507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B\r\n%7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B\r\n%507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B\r\n%7B7B507B7B7B507B7B7B507B7BFD05FFA7507B507B507B507B507B507B50\r\n%7B507B507B507B507B507B507B507B507B507B507B507B507B507B507B50\r\n%7B507B507B507B507B507B507B507B507B507B507B507B507B507B507B50\r\n%7B507B507B507B507B507B507B507B507B507B507B507B507B507B507B50\r\n%7B507B507B507B507B507B507B507BFD05FFA77A507B7B7B507B7B7B507B\r\n%7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B\r\n%507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B\r\n%7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B\r\n%507B7B7B507B7B7B507B7B7B507B7B7B50FD05FFA7507B507B507B507B50\r\n%7B507B507B507B507B507B507B507B507B507B507B507B507B507B507B50\r\n%7B507B507B507B507B507B507B507B507B507B507B507B507B507B507B50\r\n%7B507B507B507B507B507B507B507B507B507B507B507B507B507B507B50\r\n%7B507B507B507B507B507B507B507B507B507BFD05FFA77B507B7B7B507B\r\n%7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B\r\n%507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B\r\n%7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B\r\n%507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B50FD05FFA7507B507B50\r\n%7B507B507B507B507B507B507B507B507B507B507B507B507B507B507B50\r\n%7B507B507B507B507B507B507B507B507B507B507B507B507B507B507B50\r\n%7B507B507B507B507B507B507B507B507B507B507B507B507B507B507B50\r\n%7B507B507B507B507B507B507B507B507B507B507B507BFD05FFA77B7B7B\r\n%507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B\r\n%7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B\r\n%507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B\r\n%7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7BFD05FFA750\r\n%7B507B507B507B507B507B507B507B507B507B507B507B507B507B507B50\r\n%7B507B507B507B507B507B507B507B507B507B507B507B507B507B507B50\r\n%7B507B507B507B507B507B507B507B507B507B507B507B507B507B507B50\r\n%7B507B507B507B507B507B507B507B507B507B507B507B507B507BFD05FF\r\n%A77B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B\r\n%7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B\r\n%507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B\r\n%7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7BFD\r\n%05FFA7507B507B507B507B507B507B507B507B507B507B507B507B507B50\r\n%7B507B507B507B507B507B507B507B507B507B507B507B507B507B507B50\r\n%7B507B507B507B507B507B507B507B507B507B507B507B507B507B507B50\r\n%7B507B507B507B507B507B507B507B507B507B507B507B507B507B507B50\r\n%7BFD05FFA77A507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B\r\n%507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B\r\n%7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B\r\n%507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B\r\n%7B7B50FD05FFA7507B507B507B507B507B507B507B507B507B507B507B50\r\n%7B507B507B507B507B507B507B507B507B507B507B507B507B507B507B50\r\n%7B507B507B507B507B507B507B507B507B507B507B507B507B507B507B50\r\n%7B507B507B507B507B507B507B507B507B507B507B507B507B507B507B50\r\n%7B507B507BFD05FFA77B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B\r\n%507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B\r\n%7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B\r\n%507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B\r\n%7B7B507B7B7B50FD05FFA7507B507B507B507B507B507B507B507B507B50\r\n%7B507B507B507B507B507B507B507B507B507B507B507B507B507B507B50\r\n%7B507B507B507B507B507B507B507B507B507B507B507B507B507B507B50\r\n%7B507B507B507B507B507B507B507B507B507B507B507B507B507B507B50\r\n%7B507B507B507B507BFD05FFA77B7B7B507B7B7B507B7B7B507B7B7B507B\r\n%7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B\r\n%507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B\r\n%7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B\r\n%507B7B7B507B7B7B507B7BFD05FFA7507B507B507B507B507B507B507B50\r\n%7B507B507B507B507B507B507B507B507B507B507B507B507B507B507B50\r\n%7B507B507B507B507B507B507B507B507B507B507B7A7B507B507B507B50\r\n%7B507B507B507B507B507B507B507B507B507B507B507B507B507B507B50\r\n%7B507B507B507B507B507B507BFD05FFA77B7B7B507B7B7B507B7B7B507B\r\n%7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B\r\n%507B7B7B50FD057B505126512626F827F826F8272651507B7B7B7A7B7B7B\r\n%507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B\r\n%7B7B507B7B7B507B7B7B507B7BFD05FFA7507B507B507B507B507B507B50\r\n%7B507B507B507B507B507B507B507B507B507B507B507B507B507B507B50\r\n%7B507B507B507B5026FD11F8262651507B507B507B507B507B507B507B50\r\n%7B507B507B507B507B507B507B507B507B507B507B507B507B507B507B50\r\n%7BFD05FFA77A507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B\r\n%507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B7A7B5027FD17F826267B\r\n%7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B\r\n%507B7B7B507B7B7B507B7B7B50FD05FFA7507B507B507B507B507B507B50\r\n%7B507B507B507B507B507B507B507B507B507B507B507B507B507B507B50\r\n%7B5051FD0DF826F826FD0DF826507B507B507B507B507B507B507B507B50\r\n%7B507B507B507B507B507B507B507B507B507B507B507B507BFD05FFA77B\r\n%507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B\r\n%7B7B507B7B7B507B7B7B7A7B5027FD07F8272651507B507B7B7B507B517B\r\n%50512627FD09F8517B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B\r\n%507B7B7B507B7B7B507B7B7B507B7B7B50FD05FFA7507B507B507B507B50\r\n%7B507B507B507B507B507B507B507B507B507B507B507B507B507B507B50\r\n%7B7A7B26FD06F826507B7A7B507B507B507B507B507B507B507B50755051\r\n%26FD06F826507B507B507B507B507B507B507B507B507B507B507B507B50\r\n%7B507B507B507B507B507B507BFD05FFA77B7B7B507B7B7B507B7B7B507B\r\n%7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B7A7BFD05\r\n%F851507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B5051507B5151\r\n%26FD04F826507B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B\r\n%7B507B7B7B507B7B7B507B7BFD05FFA7507B507B507B507B507B507B507B\r\n%507B507B507B507B507B507B507B507B507B507B507B507B5050FD05F851\r\n%507B507B507B507B507B507B507B507B507B507B507B507B504A2651507B\r\n%502CFD04F8267B507B507B507B507B507B507B507B507B507B507B507B50\r\n%7B507B507B507B507B507BFD05FFA77B7B7B507B7B7B507B7B7B507B7B7B\r\n%507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B51F8F8F8272651\r\n%4A514A515075507B7B7B7A7B7B7B507B7B7B507B7B7B507B7B7B50514A51\r\n%4A7B7B7B2626F8F8267B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B\r\n%7B7B507B7B7B507B7B7B507B7BFD05FFA7507B507B507B507B507B507B50\r\n%7B507B507B507B507B507B507B507B507B507B507B507B5051F8F8F84B4A\r\n%502651264A2651264A26515075507B507B507B507B507B507B507B507B50\r\n%51264A2651507B5026F8F8507B507B507B507B507B507B507B507B507B50\r\n%7B507B507B507B507B507B507B507BFD05FFA77A507B7B7B507B7B7B507B\r\n%7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B51F8F82051\r\n%4A514A5126514A5126515051507B517B507B7B7B507B7B7B507B507B507B\r\n%7B7B50514A5126514A515051F8F8507B7B7B507B7B7B507B7B7B507B7B7B\r\n%507B7B7B507B7B7B507B7B7B507B7B7B50FD05FFA7507B507B507B507B50\r\n%7B507B507B507B507B507B507B507B507B507B507B507B507B507BF8F8F8\r\n%50264A2650264A26502650507B507B507B507B507B507B507B5051265026\r\n%505075507B5051264A2650264A5051F826507B507B507B507B507B507B50\r\n%7B507B507B507B507B507B507B507B507B507BFD05FFA77B507B7B7B507B\r\n%7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B50F8\r\n%F85150514A514A514A51507B7A7B7B7B507B7B7B507B7B7B507B7B7B5651\r\n%4A5126514A51507B51514A514A514A515051F87B7B7B507B7B7B507B7B7B\r\n%507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B50FD05FFA7507B507B50\r\n%7B507B507B507B507B507B507B507B507B507B507B507B507B507B507B50\r\n%26F8262651265026512626507B507B507B507B507B507B507B507B507B50\r\n%7B505126502651264A262626502651265026515026267B507B507B507B50\r\n%7B507B507B507B507B507B507B507B507B507B507B507BFD05FFA77B7B7B\r\n%507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B\r\n%7B7BF8F8265126514A512627507B507B7B7B507B7B7B507B7B7B507B7B7B\r\n%507B7B7B50514A5126514A512626F8514A514A51267526267A7B7B7B507B\r\n%7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7BFD05FFA750\r\n%7B507B507B507B507B507B507B507B507B507B507B507B507B507B507B50\r\n%7B507B50F8F850264A265126F8507B507B507B507B507B507B507B507B50\r\n%7B507B507B507B265126502650265026F8F84A2650264A2626F87B507B50\r\n%7B507B507B507B507B507B507B507B507B507B507B507B507B507BFD05FF\r\n%A77B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B\r\n%7B7B507B7B51F8274A514A514A26267B7B7B7A7B7B7B507B505150512627\r\n%26272626F82726272627264B26514A514A5126F826514A514A7526267A7B\r\n%7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7BFD\r\n%05FFA7507B507B507B507B507B507B507B507B507B507B507B507B507B50\r\n%7B507B507B507B50F8F85126502651F82650512626F826FD17F826202626\r\n%26F8262651264A4A26267B507B507B507B507B507B507B507B507B507B50\r\n%7B507B507B507B507B507BFD05FFA77A507B7B7B507B7B7B507B7B7B507B\r\n%7B7B507B7B7B507B7B7B507B7B7B507B7B7B507BF8F826514A514A27FD24\r\n%F8265126514A4BF8517B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B\r\n%7B507B7B7B507B7B7B50FD05FFA7507B507B507B507B507B507B507B507B\r\n%507B507B507B507B507B507B507B507B507B5050F8262650265026FD24F8\r\n%4A264A264AF8F8507B507B507B507B507B507B507B507B507B507B507B50\r\n%7B507B507B507B507BFD05FFA77B507B7B7B507B7B7B507B7B7B507B7B7B\r\n%507B7B7B507B7B7B507B7B7B507B7B7B507B5126F85150514A5126FD22F8\r\n%4B50514A51F8F8267B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B\r\n%7B507B7B7B507B7B7B50FD05FFA7507B507B507B507B507B507B507B507B\r\n%507B507B507B507B507B507B507B507B507B507B50F8F8264A50264BFD22\r\n%F826514A26F8F8F87B507B507B507B507B507B507B507B507B507B507B50\r\n%7B507B507B507B507B507BFD05FFA77B7B7B507B7B7B507B7B7B507B7B7B\r\n%507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B26F8F82626514A26\r\n%FD21F8512627F8F8F87B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B\r\n%7B7B507B7B7B507B7B7B507B7BFD05FFA7507B507B507B507B507B507B50\r\n%7B507B507B507B507B507B507B507B507B507B507B7A5126264B27F8F8F8\r\n%26FD26F8267B507B507B507B507B507B507B507B507B507B507B507B507B\r\n%507B507B507B507B507BFD05FFA77B7B7B507B7B7B507B7B7B507B7B7B50\r\n%7B7B7B507B7B7B507B7B7B507B7B7B507B7B50F87CA7FFCEA026F8F804F8\r\n%F8F827F8F8F8272626F827262726272627262726272627F8F8F827F826FD\r\n%05F826507B7A7B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B50\r\n%7B7B7B507B7B7B507B7BFD05FFA7507B507B507B507B507B507B507B507B\r\n%507B507B507B507B507B507B507B507B502627CFCFCFA6A69FC851F8F87B\r\n%507B507B507B507B507B507B507B507B507B507B50512651264A26514A26\r\n%F827A7A72726267B507B507B507B507B507B507B507B507B507B507B507B\r\n%507B507B507B507B507B507BFD05FFA77A507B7B7B507B7B7B507B7B7B50\r\n%7B7B7B507B7B7B507B7B7B507B7B7B507B502652FFCFC99FA69FA69FC820\r\n%F8507B7B7B507B7B7B507B7B7B507B50514A514A514A514A514A514A514A\r\n%5120F851CFCFCFA751267B7A7B7B7B507B7B7B507B7B7B507B7B7B507B7B\r\n%7B507B7B7B507B7B7B507B7B7B50FD05FFA7507B507B507B507B507B507B\r\n%507B507B507B507B507B507B507B507B507B50F852CFA7A69FA09FA09FA0\r\n%9F27F826507B507B507B507B507B507B504A264A2650264A2650264A2650\r\n%265026F8F87B9FA6A6CFCF7CF850507B507B507B507B507B507B507B507B\r\n%507B507B507B507B507B507B507B507BFD05FFA77B507B7B7B507B7B7B50\r\n%7B7B7B507B7B7B507B7B7B507B7B7B50FD047B2651FFC9C89FA69FC8A0A6\r\n%9FC84BF8F8517B7B507B7B7B507B7B7B50514A514A514A514A514A514A51\r\n%4A514A27F84B9FC89FA0A0CFCFA7F87B7B7B507B7B7B507B7B7B507B7B7B\r\n%507B7B7B507B7B7B507B7B7B507B7B7B50FD05FFA7507B507B507B507B50\r\n%7B507B507B507B507B507B507B507B507B507B7A50F8CFC99F9FA69FA09F\r\n%A69FA09F51F8F8F8517A7B507B7A7B7A7B745126514A5026514A5026514A\r\n%5026512626F8F87BA69FA69FA09FC9CFA1F87B507B507B507B507B507B50\r\n%7B507B507B507B507B507B507B507B507B507BFD05FFA77B7B7B507B7B7B\r\n%507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B267CCFC89FA69FA6\r\n%9FA69FA69FC826FD04F82750515051505126272626262726272651265126\r\n%5126272026F8F851C89FA69FA69FA69FC9CF52F87B7B7B507B7B7B507B7B\r\n%7B507B7B7B507B7B7B507B7B7B507B7B7B507B7BFD05FFA7507B507B507B\r\n%507B507B507B507B507B507B507B507B507B507B507B5026A7C99FA09FA0\r\n%9FA09FA09FA69F26FD1FF8759FA09FA09FA09FA09FCECE26267B507B507B\r\n%507B507B507B507B507B507B507B507B507B507B507B507BFD05FFA77B7B\r\n%7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B7A5127CFA6\r\n%C8A0A69FC8A0A69FC8A0A0FD0EF827757BA69F7B26F82027F820FD06F826\r\n%C8A0A69FC8A0A69FC8A0CF52267B7B507B7B7B507B7B7B507B7B7B507B7B\r\n%7B507B7B7B507B7B7B507B7BFD05FFA7507B507B507B507B507B507B507B\r\n%507B507B507B507B507B507B507B2652CFA69FA69FA09FA69FA09FC851FD\r\n%0AF827512751C89FA69FA69FC8752775A0757B514BFD04F875C89FA09FA6\r\n%9FA09FA0C9A7F87B507B507B507B507B507B507B507B507B507B507B507B\r\n%507B507B507BFD05FFA77A507B7B7B507B7B7B507B7B7B507B7B7B507B7B\r\n%7B507B7B7B507B7B5051CFA6A09FA07BA09FC8A0C89F27F85126FD04F827\r\n%51A09F7B7CC89FA69FA69FA6A0C8754BA0C89FC8C851F8F8F84B9FA69FA6\r\n%9FA69FA69FC9CF27507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B\r\n%7B7B507B7B7B50FD05FFA7507B507B507B507B507B507B507B507B507B50\r\n%7B507B507B507B507B26517C4BFD05F82626759F9FF8F8A7C8759F7BA09F\r\n%C89F7B51C99FA69FA09FA09FA69FC84A519FA09FC84AFD04F89F9FA69FC8\r\n%9FC89FA0A6CF2650507B507B507B507B507B507B507B507B507B507B507B\r\n%507B507B507BFD05FFA77B507B7B7B507B7B7B507B7B7B507B7B7B507B7B\r\n%7B507B7B7B507B7B7BF8262651507B517B502DF82620F827CF9FC8A0C89F\r\n%C8A0C851A7C8A075C8A0A69FC89FA09FA027C89FC8A027FD04F87BC87B75\r\n%4B514B5175C9CF27507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B\r\n%7B7B507B7B7B50FD05FFA7507B507B507B507B507B507B507B507B507B50\r\n%7B507B507B507B507B5051507B7A7B507B507B507B5026F87CCEA09FA69F\r\n%A09FA69F51A0A0F8F827C89FA67526F8519F517BC89FA0FD05F827F826F8\r\n%2626260404F851F87B507B507B507B507B507B507B507B507B507B507B50\r\n%7B507B507B507BFD05FFA77B7B7B507B7B7B507B7B7B507B7B7B507B7B7B\r\n%507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B50F851CFA6A09FA6\r\n%9FA69FC851C951F8F827A6C8A675F8F804C9264B7BA026FD05F82651507B\r\n%7B7B7A7B7B5126517B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B\r\n%507B7B7B507B7BFD05FFA7507B507B507B507B507B507B507B507B507B50\r\n%7B507B507B507B507B507B507B507B507B507B507B5051F827A7CE9F9F9F\r\n%A09FA09F51A0A0F8F851A69FA67B26F87CA626FD09F87B507B507B507B50\r\n%7B507B507B507B507B507B507B507B507B507B507B507B507B507B507B50\r\n%7B507BFD05FFA77B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B\r\n%507B7B7B507B7B7B507B7B7B507B7B7B507B7B27F8A7CFCFA6C8A0A69FC8\r\n%517CC8C8A0C89FC8A0C89FC8C8A0FD09F8517B7B507B7B7B507B7B7B507B\r\n%7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7BFD\r\n%05FFA7507B507B507B507B507B507B507B507B507B507B507B507B507B50\r\n%7B507B507B507B507B507B507B507B50F8F8CFCFCF9FA09FA6512727C99F\r\n%A69FA09FA69FA09FC826FD09F8507B507B507B507B507B507B507B507B50\r\n%7B507B507B507B507B507B507B507B507B507B507B507B507BFD05FFA77A\r\n%507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B\r\n%7B7B507B7B7B507B7B7B507B26F87CFFC9A69FA02651A7A751C99FA69FA6\r\n%9FA6A0C8515251FD07F8267B507B7B7B507B7B7B507B7B7B507B7B7B507B\r\n%7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B50FD05FFA7507B50\r\n%7B507B507B507B507B507B507B507B507B507B507B507B507B507B507B50\r\n%7B507B507B507B507B5051F8A7CFC99F51F87DCFCFCF7C27A69FC89FA69F\r\n%A04A51CECF7C27FD06F8507B507B507B507B507B507B507B507B507B507B\r\n%507B507B507B507B507B507B507B507B507B507B507BFD05FFA77B507B7B\r\n%7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B50\r\n%7B7B7B507B7B7B507B5027CFFFA0272DFD05CFA7582752517575752752FD\r\n%05CF7CFD05F8517A7B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B\r\n%7B507B7B7B507B7B7B507B7B7B507B7B7B50FD05FFA7507B507B507B507B\r\n%507B507B507B507B507B507B507B507B507B507B507B507B507B507B507B\r\n%5051507B7A26F8CF51277CCFCFCFCEA77D7D7D52F8514A20057D7D7DA7CF\r\n%CECFCFA726FD04F87B507B507B507B507B507B507B507B507B507B507B50\r\n%7B507B507B507B507B507B507B507B507B507BFD05FFA77B7B7B507B7B7B\r\n%507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B\r\n%7B7B26272651F827277CA7FFCFCFA7A87D7D525151A0A0C89F752758597D\r\n%7DFD05CF7C27F8F826512627517B507B7B7B507B7B7B507B7B7B507B7B7B\r\n%507B7B7B507B7B7B507B7B7B507B7B7B507B7BFD05FFA7507B507B507B50\r\n%7B507B507B507B507B507B507B507B507B507B507B507B507B507B507B50\r\n%7B507B26527DA7A7CFCFCFA7A77D7D525227757BC89FA09FA69F9F505127\r\n%5959837DCFCECFCEA77C7C5200267B507B507B507B507B507B507B507B50\r\n%7B507B507B507B507B507B507B507B507B507B507BFD05FFA77B7B7B507B\r\n%7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B\r\n%507B7B7B7A7B26527DA8A7A87D7D5952277575A6A0C8A0A69FC8A0A69FC8\r\n%9F7B5152527D7DA8A7AEA7CF7D52507B7B7B507B7B7B507B7B7B507B7B7B\r\n%507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7BFD05FFA7507B50\r\n%7B507B507B507B507B507B507B507B507B507B507B507B507B507B507B50\r\n%7B507B507B507B507B5027275227524B75759F9FC89FA09FA69FA09FA69F\r\n%A09FA69FC84AF8F827275252522751507B507B507B507B507B507B507B50\r\n%7B507B507B507B507B507B507B507B507B507B507B507B507BFD05FFA77A\r\n%507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B\r\n%7B7B507B7B7B507B7B7B507B7AF8F8CFCEA69FC8A0A69FA69FA69FA69FA6\r\n%9FA69FA69FC8A027F827FD05F8507A7B7B7B507B7B7B507B7B7B507B7B7B\r\n%507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B50FD05FFA750\r\n%7B507B507B507B507B507B507B507B507B507B507B507B507B507B507B50\r\n%7B507B507B507B507B507B507B26F852CFC9A09FA09FA09FA09FA09FA09F\r\n%A09FA09FA09F75F84B7BFD05F8507B507B507B507B507B507B507B507B50\r\n%7B507B507B507B507B507B507B507B507B507B507B507B507BFD05FFA77B\r\n%507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B\r\n%7B7B507B7B7B507B7B7B507B7B7BF8F8A7FFA7A69FA69FC8A0A69FC8A0A6\r\n%9FC8A0A6A0A0F8F89F75FD04F8267B507B7B7B507B7B7B507B7B7B507B7B\r\n%7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B50FD05FFA7\r\n%507B507B507B507B507B507B507B507B507B507B507B507B507B507B507B\r\n%507B507B507B507B507B507B507B7A51F827A7CFA6A09FA09FA69FA09FA6\r\n%9FA09FA69FA0F8F82675FD05F87B507B507B507B507B507B507B507B507B\r\n%507B507B507B507B507B507B507B507B507B507B507B507B507BFD05FFA7\r\n%7B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B\r\n%7B507B7B7B507B7B7B507B7B7B507B7B51F827A7FFC9C89FA69FC8A0A69F\r\n%C8A0C89FA626FD08F87B7A7B7B7B507B7B7B507B7B7B507B7B7B507B7B7B\r\n%507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7BFD05FFA7507B50\r\n%7B507B507B507B507B507B507B507B507B507B507B507B507B507B507B50\r\n%7B507B507B507B507B507B507B7A51F8F851CFCECE9F9F75A09FA07BA07B\r\n%75FD09F851507B507B507B507B507B507B507B507B507B507B507B507B50\r\n%7B507B507B507B507B507B507B507B507B507BFD05FFA77B7B7B507B7B7B\r\n%507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B\r\n%7B7B507B7B7B50FD057B26F8F8527DC97C7C2727F827FD0AF8267B7B7B50\r\n%7B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B\r\n%7B507B7B7B507B7B7B507B7BFD05FFA7507B507B507B507B507B507B507B\r\n%507B507B507B507B507B507B507B507B507B507B507B507B507B507B507B\r\n%507B507B507B5026FD11F826507B507B507B507B507B507B507B507B507B\r\n%507B507B507B507B507B507B507B507B507B507B507B507B507B507B507B\r\n%FD05FFA77A507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B50\r\n%7B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B265126\r\n%51507B507B507B5051265150517A7B7B7B507B7B7B507B7B7B507B7B7B50\r\n%7B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B\r\n%7B50FD05FFA7507B507B507B507B507B507B507B507B507B507B507B507B\r\n%507B507B507B507B507B507B507B507B507B507B507B507B507B507B507B\r\n%507B507B507B507B507B507B507B507B507B507B507B507B507B507B507B\r\n%507B507B507B507B507B507B507B507B507B507B507B507B507B507B507B\r\n%507B507BFD05FFA77B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B50\r\n%7B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B\r\n%7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B50\r\n%7B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B\r\n%7B507B7B7B50FD05FFA7507B507B507B507B507B507B507B507B507B507B\r\n%507B507B507B507B507B507B507B507B507B507B507B507B507B507B507B\r\n%507B507B507B507B507B507B507B507B507B507B507B507B507B507B507B\r\n%507B507B507B507B507B507B507B507B507B507B507B507B507B507B507B\r\n%507B507B507B507BFD05FFA77B7B7B507B7B7B507B7B7B507B7B7B507B7B\r\n%7B507B7B7B507B7B7B507B7B7B7A7B7B7B507B7B7B507B7B7B507B7B7B50\r\n%7B7B7B507B7B7B507B7B7B507B7B7B507B7B7B7A7B7B7B507B7B7B507B7B\r\n%7B507B7B7B507B7B7B7A7B7B7B507B7B7B507B7B7B507B7B7B507B7B7B50\r\n%7B7B7B507B7B7B507B7BFD05FFA7507B507B507B507B507B507B507B507B\r\n%507B507B507B507B507B507B507B505126262651507B507B507B507B507B\r\n%507B507B507B507B507B507B50512626267B50262626507B507B507B5051\r\n%2626267B5051267B50512626267B507B507B507B507B507B507B507B507B\r\n%507B507B507B507B507B507BFD05FFA77B7B7B507B7B7B507B7B7B507B7B\r\n%7B507B7B7B507B7B7B507B7B7B507B7B51F82726F8F87B7B7B7A7B7B7B50\r\n%7B7B7B507B7B7B507B7B7B507B7B7B5027F8277A7B26F8267B7B7B507B7B\r\n%7B5027F8517A7BF8F8507B50F8F87B7B7B507B7B7B507B7B7B507B7B7B50\r\n%7B7B7B507B7B7B507B7B7B507B7BFD05FFA7507B507B507B507B507B507B\r\n%507B507B507B507B507B507B507B507B507BF826507B50F8267B507B507B\r\n%507B507B507B507B507B507B507B507B507B26F8507B5051F851507B7A7B\r\n%507B507B26F8507B50F8F8507A7BF8267A7B507B507B507B507B507B507B\r\n%507B507B507B507B507B507B507B507BFD05FFA77A507B7B7B507B7B7B50\r\n%7B7B7B507B7B7B507B7B7B507B7B7B507B7B7B26F8507B507BF8F8505126\r\n%512627507B7A7B2626267B7B27F8512626267B7B51F8517B7B26F8507B50\r\n%512626267B7B51F8517B51F8F8267B5026507B507B7B7B507B7B7B507B7B\r\n%7B507B7B7B507B7B7B507B7B7B507B7B7B50FD05FFA7507B507B507B507B\r\n%507B507B507B507B507B507B507B507B507B507B5026F851507B5026F851\r\n%26F8F826F8F8267BF8F826F8F87B26F8F826F8F8507B26F826512626F851\r\n%7A50F82626F8F87B50F8F87B2626F8F85026F87B507B507B507B507B507B\r\n%507B507B507B507B507B507B507B507B507B507BFD05FFA77B507B7B7B50\r\n%7B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B26F8507B507B26\r\n%F8507BF8517B7BF82750F8507B26F8507BF8517B51F8517B51F8272627F8\r\n%F8507BF8277B7B26F8507B262750265051F87BF8517B7B507B7B7B507B7B\r\n%7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B50FD05FFA7507B507B\r\n%507B507B507B507B507B507B507B507B507B507B507B507B7A26F8517A7B\r\n%5026F87B50F8507B50F8F850F826F826F85150F8267B50F8267B26F8267B\r\n%7A50F87B50F8F87B7A26F8517A50F827F87B26F82626507B507B507B507B\r\n%507B507B507B507B507B507B507B507B507B507B507B507BFD05FFA77B7B\r\n%7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B50F826\r\n%7B7B7BF8267B51F8517B7BF82750F8507B7B7B507BF8517A51F8517A51F8\r\n%517A7B26F8507BF8267A7B26F8507B50F8F8277B7BF8F8267B507B7B7B50\r\n%7B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7BFD05FFA7\r\n%507B507B507B507B507B507B507B507B507B507B507B507B507B507B507B\r\n%F8F8507B26F8267B50F8267B50F8267BF8265051F85150F8267B26F8267B\r\n%26F8507B5051F8515026F8515026F87B507BF8F8267B5026F8267A7B507B\r\n%507B507B507B507B507B507B507B507B507B507B507B507B507B507BFD05\r\n%FFA77B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B50\r\n%7B7B51F8272626267B7B51F82726F8F87B7B51F8F8F8275051F8265027F8\r\n%275027F8267A7BF8F8267B50F8F827F8517A7B7B27F8517B7B26F8507B50\r\n%7B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B\r\n%FD05FFA7507B507B507B507B507B507B507B507B507B507B507B507B507B\r\n%507B507B7A512627507B507B50F82651267B507B50512651507B26512651\r\n%265126512651267B50512650507B502626517A7B507B5050507B5051267B\r\n%507B507B507B507B507B507B507B507B507B507B507B507B507B507B507B\r\n%507BFD05FFA77A507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B\r\n%7B507B7B7B507B7B7B7A7B7B7B7A51F8517A7B7B7B507B7B7B7A7B7B7B7A\r\n%7B7B7B7A7B7B7B7A7B7B7B7A7B7B7B507B7B7B7A7B7B7B507B7B7B507B7B\r\n%7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B50\r\n%7B7B7B50FD05FFA7507B507B507B507B507B507B507B507B507B507B507B\r\n%507B507B507B507B507B507B507B507B26F8F87B507B507B507B507B507B\r\n%507B507B507B507B507B507B507B507B507B507B507B507B507B507B507B\r\n%507B507B507B507B507B507B507B507B507B507B507B507B507B507B507B\r\n%507B507B507BFD05FFA77B507B7B7B507B7B7B507B7B7B507B7B7B507B7B\r\n%7B507B7B7B507B7B7B507B7B7B507B7B7B50515051507B7B7B507B7B7B50\r\n%7B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B\r\n%7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B50\r\n%7B7B7B507B7B7B50FD05FFA7507B507B507B507B507B507B507B507B507B\r\n%507B507B507B507B507B507B507B507B507B507B507B7A7B507B507B507B\r\n%507B507B507B507B507B507B507B507B507B507B507B507B507B507B507B\r\n%507B507B507B507B507B507B507B507B507B507B507B507B507B507B507B\r\n%507B507B507B507B507BFD05FFA77B7B7B507B7B7B507B7B7B507B7B7B50\r\n%7B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B\r\n%7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B50\r\n%7B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B\r\n%7B507B7B7B507B7B7B507B7BFD05FFA7507B507B507B507B507B507B507B\r\n%507B507B507B507B507B507B507B507B507B507B507B507B507B507B507B\r\n%507B507B507B507B507B507B507B507B507B507B507B507B507B507B507B\r\n%507B507B507B507B507B507B507B507B507B507B507B507B507B507B507B\r\n%507B507B507B507B507B507B507BFD05FFA77B7B7B507B7B7B507B7B7B50\r\n%7B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B\r\n%7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B50\r\n%7B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B\r\n%7B507B7B7B507B7B7B507B7B7B507B7BFD05FFA7507B507B507B507B507B\r\n%507B507B507B507B507B507B507B507B507B507B507B507B507B507B507B\r\n%507B507B507B507B507B507B507B507B507B507B507B507B507B507B507B\r\n%507B507B507B507B507B507B507B507B507B507B507B507B507B507B507B\r\n%507B507B507B507B507B507B507B507B507BFD05FFA77A507B7B7B507B7B\r\n%7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B50\r\n%7B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B\r\n%7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B50\r\n%7B7B7B507B7B7B507B7B7B507B7B7B507B7B7B50FD05FFA7507B507B507B\r\n%507B507B507B507B507B507B507B507B507B507B507B507B507B507B507B\r\n%507B507B507B507B507B507B507B507B507B507B507B507B507B507B507B\r\n%507B507B507B507B507B507B507B507B507B507B507B507B507B507B507B\r\n%507B507B507B507B507B507B507B507B507B507B507BFD05FFA77B507B7B\r\n%7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B50\r\n%7B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B\r\n%7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B50\r\n%7B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B50FD05FFA7507B\r\n%507B507B507B507B507B507B507B507B507B507B507B507B507B507B507B\r\n%507B507B507B507B507B507B507B507B507B507B507B507B507B507B507B\r\n%507B507B507B507B507B507B507B507B507B507B507B507B507B507B507B\r\n%507B507B507B507B507B507B507B507B507B507B507B507B507BFD05FFA7\r\n%7B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B\r\n%7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B50\r\n%7B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B\r\n%7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7BFD05\r\n%FFA7507B507B507B507B507B507B507B507B507B507B507B507B507B507B\r\n%507B507B507B507B507B507B507B507B507B507B507B507B507B507B507B\r\n%507B507B507B507B507B507B507B507B507B507B507B507B507B507B507B\r\n%507B507B507B507B507B507B507B507B507B507B507B507B507B507B507B\r\n%FD05FFA77B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B\r\n%7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B50\r\n%7B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B\r\n%7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B50\r\n%7B7BFD05FFA7507B507B507B507B507B507B507B507B507B507B507B507B\r\n%507B507B507B507B507B507B507B507B507B507B507B507B507B507B507B\r\n%507B507B507B507B507B507B507B507B507B507B507B507B507B507B507B\r\n%507B507B507B507B507B507B507B507B507B507B507B507B507B507B507B\r\n%507B507BFD05FFA77A507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B50\r\n%7B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B\r\n%7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B50\r\n%7B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B\r\n%7B507B7B7B50FD05FFA7507B507B507B507B507B507B507B507B507B507B\r\n%507B507B507B507B507B507B507B507B507B507B507B507B507B507B507B\r\n%507B507B507B507B507B507B507B507B507B507B507B507B507B507B507B\r\n%507B507B507B507B507B507B507B507B507B507B507B507B507B507B507B\r\n%507B507B507B507BFD05FFA77B507B7B7B507B7B7B507B7B7B507B7B7B50\r\n%7B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B\r\n%7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B50\r\n%7B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B\r\n%7B507B7B7B507B7B7B50FD05FFA7507B507B507B507B507B507B507B507B\r\n%507B507B507B507B507B507B507B507B507B507B507B507B507B507B507B\r\n%507B507B507B507B507B507B507B507B507B507B507B507B507B507B507B\r\n%507B507B507B507B507B507B507B507B507B507B507B507B507B507B507B\r\n%507B507B507B507B507B507BFD05FFA77B7B7B507B7B7B507B7B7B507B7B\r\n%7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B50\r\n%7B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B\r\n%7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B507B7B7B50\r\n%7B7B7B507B7B7B507B7B7B507B7BFD05FFA7507A5050507A5050507A5050\r\n%507A5050507A5050507A5050507A5050507A5050507A5050507A5050507A\r\n%5050507A5050507A5050507A5050507A5050507A5050507A5050507A5050\r\n%507A5050507A5050507A5050507A5050507A5050507A5050507A5050507A\r\n%5050507A5050507A5050507A5050507AFD05FFA8A77CA77CA77CA77CA77C\r\n%A77CA77CA77CA77CA77CA77CA77CA77CA77CA77CA77CA77CA77CA77CA77C\r\n%A77CA77CA77CA77CA77CA77CA77CA77CA77CA77CA77CA77CA77CA77CA77C\r\n%A77CA77CA77CA77CA77CA77CA77CA77CA77CA77CA77CA77CA77CA77CA77C\r\n%A77CA77CA77CA77CA77CA77CA77CA77CA77CFDFCFFFDFCFFFDFCFFFDFCFF\r\n%FDFCFFFD67FFFF\r\n%%EndData\r\n\r\nendstream\rendobj\r72 0 obj\r<</Length 42513>>stream\r\n%AI12_CompressedDataxi[\u001bI\u0012-~ `V2k6\u001dl\u0018\rް\n\u0011nχs\"Ҋ\u001e߹3M**Ȉ\u0013K\u001eN\u001f/\u0017gѼ2j=7|.[f\u001fM\u001dLgH\u001dƔozT,d4*>Sj9?gGf9§{U}t?o9[*̄\u000b:\bM-hC\n\u000el~RmUJ̼d敭2ʶ\u001dAA衳kP+;|t]֎Vm;B}\u001fju\u001dUj!j4VjYdv\u0017xϜDr{f/\\٨V_K(*FžF\u001c&#JT.\"uu\u0003\u0003A;]>Oal!B`s%=\u000b|*z\u0010]d<\u001fu~0t0\u001dE׵2XV+?6v|4veA%\u000b}܌mu}eB\u0003e'~dg\roBfZbv/כF\u001cǲA\u001c_WJ\\#O>\u000b\rwŨ7:Ml\u001738/&dZn5e\u000f\u0005^/?\"\n;9+/td\u0004@l\u0010xc;v56K0\\΄Ϩ@\u00125A{x3\u001e\u0004{dHȹ\u0010zTYP\u001ezٽnKŎ:\u0013\u001f2,\u0014\u0006m:\u001cP=\u0006|\u0012\u000e\u000blF8;m`ew\u000e9JqzMh\u0006`o\u0017\u001f\fMj?0UmF\rXE=-B\u000brz\u0015JQ\u001bQ\u001c2SOg3RQBb\"\\Tr޼\u001aJ1wX׫\u00054]ΛuȬk\u0007hO~Ǻ]6]\niyt§\\T)\u001bZӄrP\u0005ň{\u001f5z:5/W\\\n=\u000f]\ra\u000bs'RTǌ\u001b\\/\u001d+RAɝիWQ,\u000f\u0005 \nڏz<.UJ\u0015\u001c_*˕j3wv\u0019UruSx\u00178,\u0015vV#^mRk^֣WjF\u0016ϊ\u0005Vr\u0019\u001a8\u0007~\u0003\u00037\n(\bk+_;2_>7}\u001f65s\"\u000fhjZe9zn5\u001eBn]^ϭhe=zmCmNli֛]\u0010\u0017\u000b{\u0017̘]R#(S&^'\u0013zm^~zu\u0013ZD_\u0015Z#7\u001dSoMv#yaG>\u0015\u0012vDȴ\u001eu^FSQ*\u0019RR&\u0002;*ê!&c^$o%~`2LO0\u001fqn\u0001D(JJ\u00109aA\u0007\u001e%gF\u001fSZJ\u001c[яZbS\u000f\u00167eYp_nfڪmWΫ1e Kʽyx\u0019{~?Q\u0003X\u0000j74zx\u00155\u000bƟLo\u0002@*Ly1w\u0005\u0015 \u0002BWmq\u001a)'ǻgq_1N\u0003ʷ\\\u001a6t㴸_W6ӒUcU;M0j\u001e&V\rlV\u0017Fԣ7/\u0001aq\u001a͟s6qZ\\ÊbG.KJո\u001cUv\u0003{J?G|s,\tq}V-\u001anҟCKrt\u0003jU%bW*?\tz'\u0000i޹o\r\t\u000fo\u0005\u0019Gv?ǿa/\"\u0003Q@!\u000e#i\u000e硱_nبdyRĸ\u000f[fٛ\u001a=e\u0016I(\u000f;M4ji5??E3x^blA{w;У(:zafg\u000bqn:\u0007Dk8`jÔ!\b\bj?_ʤ?4t7}\u0000jzQ~_\u0005ΥRPvQf\u000e\u000fK5h乕ÏV:\u001dP\u000b8p\u0013\u000b<GAzt+C\u000bBUT<<m=o_w$y\u0014\u0003Cz\\Ȍ}\u001f\u001cL8\u00194R||\u0004c\tcV\tB*\u001e>[S\r\u0018*\u0018Q\u0004wϮ7J/<\u000fW7|_+1Gv;\u0012v-r?c\f\u001dC=/\u001c~:xI-d\"4|@\u0019䟥\u0002ٓ0\u001fX6\u001eN1˱\\NSA\\\fyw\u001f(_ޯb8<3%\u0002\u00130\u001bJzY+5j<c\u001b>Y5_/f\r^WJj\u0011\u0014RLL/@\u0007Fr1\u001cD\u0019\u0019~Q\u0004Jm\u001a\r\u0019\nefjL0*\u0003\u001dF\u00140f8O%d)w^5C\u0016\u0003ou]`\u001eJtjFA8\u0014]T.֣D\u0010t,\bch%<\"Dƾ[VRq4q%f\u001b[0^<_ȟU[=o}\u0003K\u001a.fAq\u000bfoF7r=S7\u0014\u000b\u000b\u0012Ųl\u0016rZ^V\u0017b\u0001.\u0004\\)\u0012A\u0006Gj^=yV\u0017/yo]efԹ~\n}D<X_|xz\u0001\u001f4\ti:+IU\u001aS`a\u00141ؕ&gMT+Æ5rpE?$\u0013\u0006\u0001WʟvRX6Z !ghV\u0003KEtg0A\u0011(%7\u001868\u001b\u0005Q.\u0015wԸbݴ\u0007;V$~8tKX\u001fS\u0016Jy5.;p~59zw)u\u001bcne\"昐\u001e\u0013MbCgvVm\u0002ΛI`9۠\u000eQ\u0012ɑ#9\u00075-ƑD Gc_ec^ڼ~'*Zי[V*NyL|X#gQ#jf҉/Jtvى\u001a<KLg\u0015zeլ7\u0006erb\u0005~Ƣ*Jvx\\Jhb?s\nrW94jՄL/\u0016;4Ug)3˭f=Ǆy\u001eL۞XȺjl,RFemFҳEpZGQwȤkXFUΧct.q\bYXDF3%w\u0019a\u001aqz6kF-oΪ\\KL\u001bϐ!\\U*DN4/UWòYߢQWS3grv99n:is3)+k\u000e^e_R)\u000fT:>I쯫|\u001d^\u000e[gؼr\"1l@fۙz<ʭU֛t\u001bhyJ\u0004\b\nU__=U3i4oR\u00123\u0012龖\u0002ǹ}Rc\"fxd~xƏtˉ\u001aJ(\u0019A8l\rm\u001dKU9lW_\u001bz=yn5m'\u0013ʻ\u000f\bdTQW3q\u0003:\nJ6ms#jo@;@ADeHF;\u0015Bi}L)0L]˺߈\u0006[$;si]ie\u0010h귨^c\u0011Q#\u0012\u0010~.fu\u001aʜ1B\u001fyP.ՠ\u0019v+\u0003v$1a]ep_QG[e|g.K\u0017YT\u001c\r\nvN\nUx\n\u0006Lvɦ\u0005\u0002)J\fiU.'!i\u0000O\u0013L}\u001f%Xc8JZ-@ڃ6`с{|;\u001dI/D<;|#95O\u001fu0t(4ZL+\u0012Ҥ-K\nM\u0013\u0016\u0007\t\nr]5]jQzq\u0003\u0019e\u001cB5J\u00028%X7Ҏ#XB-Xj؀9x\u0019YQ#h{\bq\u0006+q0F\u0016KFZmW\u001e*)SV\u000f\u001f\u0016V+]\nI\u000fQǋ\u000fvGS\u000eV\t\u0005\n\u001f*c\u001cB\u0003k]GzᥬN,e\u001b\u0003\b\tn\u001cgo4y\u001e\\jS\u0015\u000e-TŨ83n<0I /\u001f\bj}0Yp\u0014c\u001f&'y؏g4Oq3ٶLu<ôa$ZE_-AE\u001f\u0012H<Qq1q\"C\u0006\u0000\u0014iq\u0017Xދtӊ\t\u001b̩0|\u0013f*\u000ejʔ*oX\u0012\u001c\f\u000f\u0016nq\b\u0003o\u0016o\u0019Qv$Qu\"/ճYy'\u0013\u001e#qiU\u0016[4*Vϳ&(աrN\u001f\u001a0[\b*a67B{l2_\u0003'\u000bPD&\u0006\nR\u0004\u0003\u0000ѽV|^\r\u0002P\u0005i\nTt\u0014ʠ\t\\-h[z(zEmP$\u001fjmTr/H]\r4\n\u00053~\u001cfX\u0016Gns('\u001a<`r\u0013QT,P/fZM\u0017Qr^\u001d\u0003\u001d:btNݔN\u000e9{͔Љiԅ͂%̿EЄq}Х\u0005&F\f<kl[!۪\n⍶7z WklWSC\\\u001f@S4RF\r\rTf=caYk݆@>/o\"w=x]\u001a0#\u0003\u0004n1ZkD㫎Ԅ\u000fՍxY>R\u0016Db8Y>\\α5\u001f:LRS0߽a,!U\u000eш\u0019vэxay\u000bz\u000e^BuV.׳m0x+\u000fo NtD\u001ceI2#\u001eG\u00019^JedW\r9ѷ<%Z\u0006\u0010(``~^dXo\u001bPl<T0h1\u0012rJ\fnj\u001coхy!CA\u0011oc \u0016vw\u0012\u0017F颒\u0016AFRRm\nea<qh7gٵ_\u001cl84=eZ\u0007\f\u0005*4\u0019N4\b\u0014\u0016\u001f\u0001\u001dwd\u000b7ћPiPitBECU\u000f\u0018~FM\u0002!1WO^W*QpMR\u0011eT\u001f5\u000ei\b1\u0007%7]'B\tB\r\u000b\f6\u001a\u0007+UO7\u0003\u000e,\r}a۪\u0014:18\brBIT?\"03nPj\u0002(lM\n\u000eQoDU*hoh:?\tKո*`{+W#[]FE4\u0002J&~{WxIB2]ƛCf푵AÂ]]%\u001bͦLD\r<e\r\u000bX\u001e'rQW5_:Еzbۿ8\u001fqڤ?MK\u001e0*\u0001\u0003f`6x\\\fBwk)Y(\r\bਬpAYyklgZ|%\u0006\u0013G]Hևoю4Z٠7m\u000b3?\u0001G\u0006\u001b\u0016NR-\\֫Z{Ŝ\u00184A\rh6`֘\u0016+ǩF~\\j[ˁۥN -Jq\u0005FjfʌJ#7g\u0010tsb\u0014b^mW\n\u0018d+S\fAdg!l\u0017ɽ5cgo#e\u000eۀ,\u000bP.8k\\WMsww3\n\n^53g\nMcDG\rXU+9\u001d\u000e\u0005\u0005Yj(Hvu.FZ[Tw\f<\u000fZJnJ>\u00024\u001aWΈy\u001d\\yxU7\n@\r8#G\u001d!sâG5y\u001bЌ֢\u0006e\\3q{-z=(c\u001c_\u0005#1X&\u0019Ӷ\u0016r\u0006\u0018i\u001b#\u0013ܣv\f7\r3J87\u0011e/o0s}t*!\u001eu#\u0012N\u001cCڽiNjT\u001a\tE:UR;\u000e\u0003tTk\u0002g-_=6Z\u0015(Q8WW?j\u0000ڸ-Ukɔ{Vvr'<D׍#\u001b]\tF\u0019h\u001e1tVza?28%]7/L\u001c\n˨iQ+D\u0010\rf\r~\u001c_.f$~v7d \u0001ҵi\"_\"\\\u0006_`\u0002fM\u0014LI/r\u0007\u0013k5]\t\u001a\u0017ۮI\\ӌ\u0002\u001e0yR#Ӫ\\JئP/nU#vec,\u0015ū1h#cBJWhZ\u0016NP:\u000ecl)\u001cӮ\u001e6)íD]AhmotV\u001f\u00140HT)٧ח\u001aх|=N\u001b9_Qy?GJ\u0000}T\u001c\u0014T]'u6]\u0005=BrEuE$\u000fU-x!]+E?,gfwg.6ΓW\u000bvo౽t\\Y;\u000f7\u001f<ͯ['zw91561\u0006=:}d==n܉WNC7v0+gi\u0012؁λ~dFk[Sk4Z\u0017/g+w^-/U7f߮;F7w/Ս%Yן_[[W۽Qʔ\u0007應OG7;_\tl뺑}7|bv\"g3U\u0013Ko&ykbʉMb=9h[=̪̎d\u0017kOjb\u001f_fL+ƮƵI\u000f991d!#L.^M<X\u000br\u0013sϞ3ս݉Bv\u000f&u+\u001a\u001e\u00167Ze8gs\u0003tfVR>/'2u\u0013ÚXooZ~v]iYSٜiEө/\fؚ]|Z7Y現Y:_/\u000bʹuec۷\u001f|3ǹOw\u001et&nrOgS\u000fV&/w\u001ew\u0007۹\u0003j?\u0004\u0019zXrOg\u001fٷ:zzs;\u000b\u000fh\u0003%K'v\u0003Mqҩ9Rͨ\u000fъ\\Y2P{{XYv\u0007;c\u0016(\u001c^x\b>΢0e7n>cwkɅʣ\b$eH+60#!XYԤ~xo-ioy*\f67=vDNU\"Gzvmakcjk{[OOBvwSϧlo\\\u0003_\n|_t^nOz>\u0004\u000f>p[cv[ё6:&8\u0017{J~ԑ3t\u001f-\\GtU;\ttt\u000byx6W^G>>M^z\u001b{+~F\u000b<z*S\b\u0007QSVymZ\u0010g,M᷼J~+\u000e~\u00003l~q:A7曍{;\u001bw\u001e\\\u0015{[7g]Govc~Ja\u001a\u0001zEQ3\u0007\u0014\u0005\u0011$\u0011>\u0015[\u001b-*cuhȷ\u0013ӻb%Zاv݂b]:.\u0017'+>PYe\u0011rnyd..?\u0014\u0019Rff\"[WXuO^Γj?ҏM|շWs`z+\u001d7E9OJs\u000b\u0011ts3\u000f`~\u0011ƯZ\nPɠ_̉Vs\u0015g\"7Z|\\R/-={dBu\\a.`w=ia9\u0016A(VY=NE\u001c|Y)߫l\r\u0006L4t@\n?z4\u0007I}b\u000eNÙ;0r`WGb\u0004?N,Jgl`\u001a\u0006.>-M\nv\u001dx1\u001fhUC>\u0012.%\u001a@%^?}ٲ'K׳Kc}U[9YX2\u001c.nO~ȟ\\n(A\u001c063u3{˓gfL9\u000f&vff7'[/r\u0016+ؖLzA9O[k\u001fl1MY.h4wwrkڗɵ\tM[\rNu\u001aO\u001a?}\u0011u5-+:s\u001e:k\u001aiJ\u0003O\u000eS\rlˊ۸\\|}:\u001d4_C?FY2b~\u0017d+i\u0017ؚJ#}Q܇0\u0018\u000bs[-,o_Ŭ5\u0003sآ/g\u001e>\fyo\u0014vw*`\u0007Og\u0013\u000fb9u\u001dOənh&dO\u001e_\u001f-\u0013>o\u001e<.M\u001a\u000b/1\r\u0017Bnޗ;\u000bę\u0018\u0015En*z/c{p:˷3b}&L@7xAu0)Cv\u000f6\u001f>/^.\u0004\fG\u0010\u001bm\f\r|?~_VA\tp\u000bβ^\tX\u0016a\u0002%F>d;x[7P_9y?0<k\u0019\u0011oMt04Op<B\u00186;\u0002a4\u001dǒ6\u0018mjMU\u001a\bܹZgg\u0016mןi9Ƹ\u0013\u0007M_\u001bQ''rꑫi\u0010e\u0013t7;󤁓\u00068Pie:Da\"g\r\u0016\u001846ƍ+2 j\u0001A6?)ZW\rZ`d\u001bՉ9\u0006uTsri9)IO>%$5^kA\u0017@)铴Q:9\u0002HI4DP\u0015R\u0013))\u0011I;~r\"\u001b\u0014\u0018vҺsxw\u0018FZ7>tژx08\nH,qv\u0018W,\u001aJg\u0018\u001aںfPkk`0Dy?L̝\u0016'^2g\u001e#M;\"\u0011q08\u0015f(V_,8k%LZNYp^L<ktڄOK@9!ٝ$6_MUN$j\u0012\ň\u0011'IDw|Gkq`V8\u0019]]ѧ9r.ʆ\u0012z'rM^?]X]~=\u0004\u0004MڻЙɆ1=\u0012F\u0003\u001cvʋN?7̾~\\\u0016_;pNO;H;қJ'qr.\u00156\u0001ڳ\t^X6qG]\u000ek\t\u001b\u0016V᳞^9Qۜ᪚Y)uP|t^Yo?z̄QCHͣǍ&^ygoB+\u0007ov=<@7,:i-jӪ=\"r9l}[Oo%hJ\u001c:pv\\iq{\"\tO>\u000b\u0016PLdd$\t\u000fk1&^scYn?Rg/?m0G[?#P!\u001c\u0016`e\u0019`T\u0015\u001flZ;\u000fvft٫%c{#4p̍@\u0001]<K7/^q\u0006r6t\u001a;~vsU{\u0006nXk\u000fl\u001ez`bKO_\u001f\u0016`@:9ӹO-a.\u0004g?,>ڰ'%Ϥt`?\u000eR:Aof7I.L[]דcm#\u0001j2!GF,\u0007☍QqXy\u001c_Tj_ T*\u001c<y\u0006gjw}rt\u0012}^]\u001f\u001c}Nt\u001fWZNEXu}RD+W:eO\\{\u0019f|I\nm\u0017\u0013X[ӳã\"m#?U&;afsj@awLrէ\u0001 .X>l=(+[Ԍiq\u0007Nl}z\u0016'\u00113\n\f`s*\"'1庪fV߿cv]7X]w{m<L|=N\\\u0005#F9\u001f֘vJVXr\u0004!\t(e\r\u0016]م!aǊSJ\u000b\\xx}<IѮ]q3b;Xһ^<Z\u0014eۉ풞Gڲ\u0019*\"}\u001c-Ñ|\u0017~/Y/V@\u001d<X\u000fk\u0017s\n\u000f'g<]z5HM~`UY\bŶz}\u0016(@mg0\u0013o/&+\u0000c#\u0012\u0019 E\u0016˹G]VƟ2R_0K?\u0010;hN\u0018@OOb1\u0018@\u001ccat(\u001b\u0003q6?\u0000z\u0014\u001b\rrs:NXoV8lSXo\fGdXo\fGI5ֳ_.@\u0017w|\rk\u001a\u0007^\u0012WȖ!X/G,\u0004\b\u0015\u0002eR G<S\u0007',!j\\=Jݚ<KG+;gM\u0000.\u0016$Iر<c\u0000)N\bjO%m\u0012khF\u001f\u0004pF@i(Mx:\nK\rJsù(\u0004B\u0018CpS2rMIEs\u000eŪ..7Ȍ@;DvU5\u000e^OR\u0007k~}b<fshqQ6\u001a8UJ\u0010uE90ݧt\u0018f\rX{ڬ\u0015W<\fw;\"\u0000}9)1J\\T:U\u001er2?%g2)-盧6]ZA\u001fd\u001f\u0011OwYsZ\u0013\u001b$'?<ȕ܅Ǭ9nW\u000en\u0004u\u0003\u0000ȵ3/suo{\u0017BS\u0006FuaB\rN)\u0019A\u001d\u001bIzs#RMm8&b\u000e\u001a\u001c{.\r\u0005)iF=Yi88٩9ᾉNz\u0016\u0011k|iWk\\5.9.i6\u0005\u0017\u0017S´tXo@\u0019 -;wd\u0002(=oS0Vv>c\r[\u0017\u0017?6?e׹.\u0014T%\u0010m_Cp$)~\u0003*\"[\u001fZ{\u001ewJҳٗ\u0012);-\u001eGĤMfbҭn\f-쫢T\u0006D\u0011?^/jG˕F34ܜ.\u001c\u0012Uwܒ_hXٽZ\\:ݷp7_MvW\u0018iPD\u001a,X3\u0012\u001bvͻ罊\u001e,k\u0003Eǣ旞CG\u001eCJ_`-fͯû]}V FPٴށ0k.fvյ\u000b\u0007\u001eYR\t\u0010w<%kOZ[@=\u0007\u001dG\u001ef\u0012I\u0002\u0007O:ԧu?б~4\tފS'\u001f\n;X3\u0013/z!Q1#WmW8Nj>{+c_\u0015\u001fk^{;.c7?\u0001x&z60o\\\u0017Qwyb±¼q1\u001e\u00007\u001a.pw{d.\u001f\r\u001b6\u0007 ;\u0001P7;>\u001fWO+{y\u001e@]\u0018.u*b|pw{d׫l\u0002wGv\b)#Cٷz ;XϠ\u0014[o\u0013Av\u0002\u0007\r3p\u0019\u00018m\b뮛Fvǃ\u0016R\u0012\u001d\u0016I]ŨA;-:\tR\u0017w[$8m\u001d\u0016}3VիGg)L<Fޢ\u001d\u001a3uqǼ\u000bc\"iH\u0005c]yw@vOO[L-R\u0017w[QS\u0017w[\u0018omE_O\u0018\u00168\u0016{$VzO\u001dhitH\u0000o'Ҟ=\u0003\u001et(s>-Nl\t@dP8\u001e#F\u0003SP#O\tHةtDv\u0017A9\u0013HVq$Gb=GK\u001dd%\bخI\u001cßz⏍\\˷RǗ\u0000ngf_L\u001f|lٶkb@\u001f/V/\u000fzO\u0018YB;~p\u0014MYV[e\f\u0006K*ss|,*>\u0005!V@s;LSe4q\nKܫ«Ү:J\u0010\u000e\u0015|\u001a6rbfyp8(6\fjrP{q\u0016op\u000f1\u0013hoڠNрM%`*ۿ9m'&O\u000bro)ӟv❝~v 9M杗Çs$6,ћV7\u001eY\u0011?N\u0012~TR\u0007Ϝ\u0001yl0&H^0\u000b^l'O>6V{\u0001Ϟ\u0006M1mп4(g3@s\u001aT$mԁ\u0001\u000eA\u0013}СAv3A\u0006TR_ɻ2\u001eǗj\u0014\u001b(^1mo=K5\u0018]zC!\u0012}>$!E&\u001dmR?q\u0004^jϟ\b\u001bٍ֓;z;Kr\u001bO\u0016b؋^c>\u0002\u001fbqܜ<G{&=@5{0=dU;oWykά͆Yne]o=g;ϟ>]>ΆӥAq[_\u001f\\U8)\u0013\u000f\b'EX\u0001YKٶJ}l\\\nz7(d\"H\fRcm+rټc#2\u0000c?=\u00188gy`\"mV\u001f\u00014\u0000,\u001fd\u000f.\u001fT7B\u000f\u0016zn\u001al~ʶM|Am*zm\\v-\r<B٧_\u001a|5-\u000f 2S[,\u001b\fo\rfꪰ'\u0018s{bxx1+\u0011F\fMW8ml{_\u0006V\u001d&\u0007\u0010Sn_Y\u0016qr \u0015sʯu['YOO\u0005sx 36.+\u001e+u\fԧ\u0003\\J?O\u001f_!F:~\bKFRg|~;:\u000633\u0015'?z\u001fsfO׎\u0005g{7m-FF\u001fi\u0011\u001e}X++,\u001f\u001c}x~6L\u0012DOXkA5&U\u001cLWOvWJ,p\u0005\u001d\u001d/W?n\u001e\u001c/|ܫN\u0012].]u+{f\u0007(։3\u00058>=v,\f?to}P#q9tNl}\u0003I?|:|Y4v\u001d˽]$\f~6>z\u0007wq\u001a \u0002\u0007F\u0012uTѳ\u0006>Ń^|&Z{*V۹6v_G\u0001/Z{j-ԕhg\bŚ*$秡SEAbu\u001a㫈cؐk:w\u00162qR\t\u001euLTWY[9=\u001f3o\u0006\u001c4 عzO\u001b\u000fgGTxb\u0014pfrS@u禀ƽ\u0006$rT*!((\u0007\u001f\u001eS\u0001(ѵ9\u0012NN>Xf367\u001f\u001a\t\\f|:}\u0000a'o>m\u00128Ɯv&?\u001a\u0000\u001e8l3P7:\u001a;\u00006gc&5\u000e%\u0012C\u000f{m>\u001cwavv5\u0000\u0000HU\t\u001fO\u00054L{5L@e\u000f_W;ޅ(7s\u0000LO͎T\"mLn\u0006LHKİm񧹎bΘAwo;\u001dc\"2\u000bb!m~v\"V꼛h[rGO\u001bsӷ\r\u0017b0koP6ssC\u0018wE\u00075`%\u0019q1Υ!WSSq\u0003\u0004uYњ6`8m19t\u001bd36}ָbLA~\u001fm\\n^)\u0019\"i敻\u0002ꕴ@A\u0006JJIJrNd\u0002\u001a[rg\u0006a$-g߼;kw\rBߠ\u0012{3\u0019zg\u00071m\":;XQ+ǁ<X\u0001F:|H\u00021\u0015\u001f6\u0016ޭZ_<\"!MGřqKu2q\tح2Y_\u0019E۞ȌvҢqdF;iQWeFgiQUN];+2\u0017fF;iў of\u00165LENZ]\u0003+2WeF;iѸdF;iQͯʌv2IdF;iQ~Yf\u0016E7Ό\u001dP_<\u0002\u000f\u001fè٪\tk@?T\u000f3J\u0007\u0019/\u0001\u001a.l_ә\u0000*VfP4\\oP>;yz{-c:\u00059\u001e%_\b]_k\u0019\u0018Mu]`=\u0016IzpY*\u0017Q5'Rf5R\rf\u001bV\u0010W\u0017Q\u00125skGkV,G4|n\u000f\u001a\u000b{CH}\u0005s<+p\u001fc߳m~sNatNz|5_i\u001f/x\u0016,\u0011ߊ\u001bz痉\u0014JCr+\u0006\u0014\nM֪eB.*G\u0005.9U\u0019P\r\u0003\u001b\u0003RA[\u0006R\u0018J<P\u001f|\r'_\\5\nZd$?F.||n t^=W*[շ1 \u000bjLo{ʆ:d>Lż\u0017\u0005[s\u0019mpR0=\u000eG\u0005]q,4LY\u00189|yztYj\u001b8tiԩ\u000018.Fף \u0013;nSV\r]V\toWz~ר\u0017ץc۝ˍ\u001bѭs./mfy}OŬum\u00026\u0013z0򽡷wcgmO-86\r[ͿcRrճ/Qy'-1-xP_D~yζAGʹu{LV\u0000ʺӆO\u0005|-o^=XyAQ\u0017Iu72{\u000e\u0014}}ކ\u0003\u00027\u000fVo/\u00175\u001d,\u000f>q/Vߙ\r\u0007\u0017o3^`\u0016ߡ/Ċ\u0006~\u000ff6G<|%ݙ{p#POpnf\u0003ßte߃\u0007?'Kng+7{p5\u000b:ziΗ#\u001bnn\tAm8u7\u000eb,+j<^eZ.*ؾU΂ǟT\fUe\u001e~d Զ;ki\u0019+k;gq\u000eUyV)w,\\'vRgc(\\/϶q2\u000bn2?s\u0005}(+y\u0014\u0003>2\u0018m]\u0001}R:\u001bp\u001e\u0014-߼&\u001bc\"\u001c^b_\u001c\u00187=_W\u001e֭2\u0014j\u0012\u0015<v|U\u001f/3Fm|u}xbytmލ_L?k[8a+~\u001ek'߮\u00141V?\u001f`rYʗK\u0006?'u3fי\u001a\u0018\"\u0015í:vots]\\WJs]Y?Ȭ^hmwXU߫\u001fLA\u0015\u000fLz]ߙWY֞e])f=_iW}t'1}Q\u000b3\u001bawB=sa_=?T}XY\t\u001c3\u000f\u000bB\u000b\t,*\\e{(\u0001tk?0:V\u0000 \u0002{'}\r}\u000f_>=v,7^,m>\r\"?]\u0007 8\n` @l\u0015\u0004vֵ\u001d˲\u0003l{pw\u0017(jѡZ\u0000\u0019ˬ#g\u0006\\?c[\u0004+\u0001\u0006ㅾ\u001dh$j ]o@\u0000\u000bj\u0007\u0003\bՊQV9g\n쥗vj\u000bLt7p\u001cf\r=\u001b#q\u001c\u001dV\u0005~0G\u0017Zڷ\u0014puu\u0016ֶz@\t\u000b2WY\u0016Z\t=S,Ћ?\u000eVӱP6\u0019ۇX`=<;5'dnL\u0004\bՀܲ\u000eC<'\u0015F\u0017`BlPk+Px0C!c;\u001b\u0018K4Mn|J[\u0004`U߈gg\u001d[[\u0010E\u000e\u0014'\u0003\u001cKq\u0007\u001d(7\u000e\u0018hV8\u0000.d\u0012\u0019\bWyEpb#3=\u001bf]`W\u0001g]Gg}߇;\u001b8!(H\u001f\u0006\u0001td\u0012~\u000em\u000f\u0012gq\u001c*\b\u0000\u001cB\u0001jk,\u000eV\u000b\u0000\n+\u0011`o\u0010\u0011A*ln\u001e,1A\u0016\"^v\u0001hAf-\u000b\f,\u000e\u0013\nuem\u0006\u0007L\u0006\u0013B\u001c4\u0003\u000f@\u001b3\u001f+\u0016\u0016\rB\u0015\u000e:iG3P\u001f\t\u001d<\u0016܏Fg\u0003})A@f\u0000}_V\u0018CӜ.E@\u0001u\u0003tR@ƣx\u0018\u0016|\u0006\r\n/Z\u0002?pH?\\r㺞x$\u0012A,E\u0001UY\u0007QClaG&ؼq?\u000b`)䵏\u0013@ydP\u0000\u0001̈́v \u0016\u0019\u0005x\u00054p!U(Ӡ]#\u001c3j\u0004t BՂTP\u0013C}5-BWb}\u0002Y\u0019PQzen\u0011\u0018\u0010j=s\u001a:С\b[p\u0019z\u000eǭCn\u0000p\u00144\\Vf\u001f\u0001\u0014@ڰYC\u001c!J#ρ\u0007Є\u0004d9Ă\u0002`\u001b>\u0014'\u001f\u001a:9X\u0019G.\u0017\u0001\u0002H-hn f\u000fS>V\u001c\bb@\u0014hqh(aGT?mn8\u0019h\u001d\u00112\u0014<вp=\u0006\u0018\u000ff\u001cBN}1\"I4.d\u0019B\u001dJq\u000e7\u0013\u0016$ ~ﺎ,=m[h!l\u0017X\u000fm1\u000fh`\u001fĀX\f\u0016K\\\u0006'w\u0010,,7\f\u0015\r=.W6+:\nR6\u0002/\u0001I'^\u0012\f\u0006\nH#YÊ\n\u0005Q1U\\dbcRQЙ\u000e_$`hI+*G:\b|HG{Y0\u0004D\nSP.]\u00019uv\\[\u0014E%\r\n6\u001bܴ.Lc\u0014\u0015Z$\rD#\u0004\u0003\u0007jXqC\u0012@\u0004=\u0006\nH\\50ij~(0|\u001e\fǨ2@P(JAODOV@*q\u0002Lv`Qcd5e\u0001\u0014U\u00140] \u0010]$7\u0014\u0015 \u000fLp·\u0000\n#\u0005f3]cl+\u000b\r\u0000\u0011M\u0016Po\u0010\u0004PJl*?Q\u001983\u0013`\"2voD߈̭jI\u0011\u000bH?Dl\u0004\u000bS/G=_\n!\u0003kZ\u0003zNS3X.VϢ=)=㳿`1-á0\u0015\u0015̡'o`i_`?qW?:t3\u001ch\u001eP\u0003\u0006\u001bR]&A\u0002I\u0001ÐJ\n$\u0003/N.\u0001\u0005\u0010p\u0007A\u001d󃍆*~w0\u0000\u001efOA\t+\u0011`(A\u0000J_\u0019@L\bjǶh\u0000\u00009\u0019/Q'8\u0013ڕR\u0003g\u000bhVZ̊m14`' \u001fL\u0019<:\u0002\u0015VN\u0000}\u000b'\b\u0001|n\u0018\u0015;\u00103\u0002\u001f\u0014\u0019ע\u00027x0i>tig]\u0018z'J|\r+k5=M\u001c\t\u0016צ\r3\u001cS\t(h\u0000+<'NHb\u0013X\u001c)Gha*a`\u0014\u0001@\t+C\r\u0000\u0013\u0011L\u0015\fq\u0000k*\u0018*$\u0005,5E[Dǁ.'\"B\u001d\u0011!ё\u0005\u001cp \u0000\u0003\u0002S \u0000\u001b\t!/f\\Y \u0018A8td̢\u0005L\u0004\u0018Oj'Ư\u0013\u0016M'Kf\u0004\u0002mB\u001cFF`\u001d@\u000eN\u0007\"x8'\b\bˍ;\u001cjX`2\u001aDP\u000b\u0005@I@\f\u0002\u0014\u0000a\u001d$Yf\u0013i|l\u0006ހ=Ĉ\rx\u000b\u001a\u000f\u0019\u0011\u0000TVd:\u0010\r~\u001c]px\u0003\u0013b+\u0006P\u0018\"l\u0000pǅ$\u0007RyҚ\u000b\fh\u0000d\u0011\u0019a%tΔnJ\u00121b\u0005+3\u0018N\u001cbG؎,5v3tY\u0001\u0010Ř\r\u0011`8V\u00120:~\u001bBd\u001b5\u0015\u0012ҹe\u0002\u000048\b\u001c\u0004c\r%]\u0014P0\u0017\u0004\u000bm8w\\xjtC\u001c^<W(\u0002b\u0018YX%\u0002\u0012!\f\u00109ك\u0011)N5t rLH\\M\u0006\u0012\u001as!$P\u0010B\u0018\b#냵XYF m\u0016;p<6\u001e2|Z(\u0004P͈悻8X \u0000tJ\u001e\u0000Oi~Xg\u0018Ӗ\u0018\u000ex\u0000JG\u001f\u00146E\u0019PZvQ*\u0010\u0001%<\u00019TJ&Ht<ST\u001c\u000ef\u0001A\u00001BiF\nWjcd(\u0002\rx0_4\u0006\u0014A\u0013kDZ\">\u0007d'LW\u0010/\bCg充D4D̜<A\n8H\u0002jIFcy\n(\u0018pJSǢ~>5\u0012!c4N\u001c\u001a\u0001-\u0013\u0011\u0004H\u001fJ,#+\\V\u0006 `>t80\th\u0004F\u0006DJ:`(\fxP\u00194QBAD<\u0005z̈?iv\u0010@h\bYjǦ\u0001Q\u0010\u0006HuSFi?\u0019\u0014\nƫ7\u0007\\\u001d\u0007j\u0010\rWn4J\u000bæ3\u0007\u000f\u001bI\u0016ҋ\u0015\u000f\u001ck,H3\u0018dOǠ\u0001,`f^!m@\u0003\n8\"\u0012\u00040e\u0006\u001b\u0015\u001b\u0018\u00134f\u001d\u0018R\u00073A\u0001\u000b`-a\u000e\u0005\u0012\u0012x.\u001a\tE,42;ic%\u000bށ\u0012b\u0002zܨh\u0015h?Ȧ\u0011`pK\u0002\u001a \u0010\u0005Z;˾\u0004PV50&l#\u0000;*D<iF\f)\u001aw\u0012s>\f#\u0007 M\u001bwM\u0004\u0013.:\u001d\u00011;>cM_kKU\u0002\u001d`\u0015is04VH}\u0013v.t}\u0002f|\u0018P\u0002\u0018U*g.%4,\u0012\u0007(h6G,)\u0014ٜhDMcT&-c\u0013\u00100n\u000e\u0005jSf\t!}h6Y\u0001\u001eM=\u00010\u0002el\u0018d\u0002\".\u0018\u0004F[<,t\u0016@AE+X+n:kCŬLf%(C\tIB\u0007\u0010Q[S 5/\u0014\u0013:\u0006.U\u000fŀ\u000f\u001c\u0001\u0016\u0011.\u0014\u0012*\u0019\u0005\u0012D\u0000\u00041nއ\f)\bM0@\u0000[\u0010\u000f5\u0003oP@)\u0003ǰ(\u0003m^0\u0002\b^\u0002oUwI!@ߡ\u0001\"ea8@d$%'.\u001ev!E/Wrsж%\u00167˨7\f\u0016!a]`Iԙ=\u001b\tm\u0006a\u0002|@?\u0010ȓ8Z\u0006\u0002BH3DCW\u0019ƻE_RK\u0004 \\\u0006\u000b]7ET\u000fnK\u0012̎\u0000\u001fS+wy\u0003\u0002\u0004g2LY6[\u0004Γ@c(Y=faJvQS&`&Th ;,EǞA[&\u0012N\u0006\f\u00062?j\u0019@;\u0010d?Es\u0011жr:\u0019\u0003b\bc\u0019oW(^7+5:V\u001bk%FGTQus~\u0006\u001dktX˛STX#<\u0001\u001a#bWn\u0006l\u000f\u001d)\u001f\" Wt@ԓ\u00158|\u000b\u0000\u0014\u000fl-i,$Q:\u0003\u0001\u0010`9\u000e\t\u0001\u0011\u0000k)'\u0019.:3p[DÈ\u0012~A\u0004:~wU\u0010D\n\n\b%8\u001eoO\u000e\u0006>3M0\u001ef\u0001\u0016a,lq$08m\fǸ\rṺ,\u0013R\fZ/\u0003\u0000i_@/\u0000(KdD`8\u0006*i\u001cp\u0005\u0000\u000fЕe(U2\rVÂe=\rV/|(`q,\"%ȥ$*\tYU\u0001ZD3?$G\u0013j)\u0019\u0004V}\u0014ń\"C\u000e8\u0001\u0006\u00069P\"/\"务\u001bJ\u0010\u0010Ġ҄\u0000[\u0004JB(ʐۤ`\f\u0014AJ\u00050\u001d\u000b\u0012l\u001bฬ|\u001f\u0017k%\u0002Ђ]E+\u0012\u0001b&X\u0012C\u00106 3A\fR\u0019L09\u0014iܹI,/\u0019r=bP8V`0\u0007\u0013\u0018b \u0005\u0001JpX$52\u000b!\u0012Մ_\u0007d1\u0000m&$x\u0007̈́,\u00151Q&VE`l˗M\"\u0000X\u0004I\u000e\t07LipY!\u0000%\rS&qY>\u0003y\u0002^\u001fЌ\u0013/4f5<Dd\u0018[\f\u001c^\u001e8c,v\u001c\u000b虸\u001d\u0012q b3\u0012z*ca̶\u000f\\IƋ\u0002e\tA0\"U\u0019gO|'yde\t\u0002uA\bY\u001bgt Q`!cbi#\u0003FlW`#y`\u0010\u0005\t\u0013\t^\"\u0002J:Fa3L3k!Z\b \u0006b\u0006\u0019*(|~\u001b0,*\blw\u001c\u0013)~4V`va\u000e*@\u001cd\u0016Qqq\u001dK\nVi\u000b\\`\u0000\u0005g:yV\u0002f!p$0922\u0007\u001b\u0013\r͒ \u0002vֱ\t(( ebpBdlC`hj\u0018V2WN2j\u0019.\u001ap\u001d1\u0013&zAǖr%#ވ\u00101\u001b\u0017C\u00020.k\ri\u0003?p$}0\u0000O\u0002[W&t}ىGp9Cϔ\u0019\nD\u001c\u001a@YOO\u0012TG\u0017<&(ؗlڲcB2\ba0G\nǑQ<\u0003崱6V\f\")#g\u000b\u0006M ܦ\u0016g\u001a\u0011'\\\u0012ػ\u0017>\\[\f]qY[SĢeKi\u00075\u001b\u00039aXM[MW\u0012B\u0002\u0013P\u0007X;\u0002\u0014|VC{\u0018s$^3DC\u0006\u001ce\u001bYDYUM\u001c\u001e&R\u0002bkdf\u0012/\u0019\u0005<ąk\u0010\u000e%@A>Yg#\u0019\u001a5`ИiqIa:B\u0016U\u00139\b\u0018VaG\u000ba\u0002?\u0017\u000e;0_0\r#\u001a\u0014:T~aܗ;-gA\u000fg\"m\u0012H`[\u0007s@.p\u0011vV\u0012ҕZ\u000ee\u001f@q@ߌG]\u000b\u001f\b\u001a\u0019pSW`4\u0014c`~\u0019P\u0011E ͬ\u000bDP0Tp@~KhX&IT\u0011\u000f\u001d2\u0006\u0012c2,s\u0005Q\b\u0003EJJPR!\u0014!\\1\u0006r\ft9Cm\u0002\u0015Ǻofq\fkjm\u001aB^\r\u0001\u001b\u000b\nyxq\u00075\u000b\u000f\u0003B\u00129Z\u0001N\bx\u0001Jg\\TK3և0ȣ\u0005\fn|\u0003(س\u001f0\u0014\u001c\u0006s\u00111dT\u0013\u0000\u0015\u000fH3\fϔ;\u0011\u0010)0Ώc@5\u0013\u0001<5B\u0010\fciό#\u001a+ `wź P\"d7\fp2\u0002b\u0010\u0000g?8T1i{l>|f+ď9\u0000\u0007\u0006\u001e_\u0003\u00070#4\b86o#\t<VaS0C$<\"\bEvz_4\u0011v\u0018@\"\u0018\u0006&s/ &61}ƊlM\u0013\u0004>\u0005\"<~t\u000e<\u0001ϸqI\u0010\t bYAR \u0002P<fR\u001b^\u001fSP,L\u001aZt7\u0019mO\"\u0014L{\u000eM9;\u001cݫy'9\u0002\td8`Y\"p=\u0017\n\u0013a\u0006\u0017Yx\rO\u001b\u00129rh#M-\u0013CFد\u001e\u0013g,.(G){H\u0001!,v=\u00126\nXoB8\u0003T\u000fċ+@\u000exr\t\u0014\u000e\u00162܆\"\u00071\rL:з\u0013!aRoH\u0002I͔1DK[̜R\u001aE\u0011\u0006R\u0000wehHRp@\"7\u0007Ҝ\u0006Ν\u000f16\u0019\\i\u001c91\b&7\t=,Q<P@pf/\u000122\u0010^\u0006\u001f0$I\u001a\u0011j\u0018\u0018\u0005\u0000-I%\u0005T\r\u0014=0\u0007YQ!/Ke-\u0019i\b\u001e\u0013\u0005L;q\t\u001c\u0018\u001e3\u0002\f\u001a+ls\u0018loqB@h\u0019|\u0018b\u0019\u001dQ8#\u000b!c\u0002)b\u000eư6%\u0012Q[L滎)1\u0016p)\u0019\b{ϋU9e\u001d\u001d\u000e\u0006Q@\u0019j4$ְ\u001a\u0004\bM\u001f\u0011=\rv!\u000f3\u001as]n\bBf\u0002Cx,O;\u0019,)4g\r_xps,j\u0013vY~cQS\u0011+\t,%<\u0012P\u001a2أd!\u001d5s^A,>3kFAؗ\u0002P\f+\\cҐCJ\b\n͂3\r,W<k\u0001I\n`\u0019\"\u000b+sX-\r$d9\u000b\nXM\u0011O\b7 t\u0004\u000b\b\u001bsE\u0019ݏ^\"\u000f\u00029#@@rw`Q5\u001e3ʌ͎E۝\u0010Y`/Q}L\u0005\u0006\u0003u\f\u0000\"\u0006\u000e\u0012xK\tJ\u0011\u0003\u00187\u001bQWQGہ\u0014\u001b <+f\u0010s\u00057YJH4'\f\u00042\bDBӱ\t\u0005RiM\u00148^2&+v\u0014K\u0005)\u000bi\\r\nWv9\u001bt\u00138\b\u0006^\"%\u0005\u000bb\u000bxm5C\u0014f=V|\u0000RJ_,{\u0002<hk6v㢬6$T1\u0006d\u0007Mhm\u001f,HP\u0006\ty\u0015N`@Xka)flT|]АZ\u0001\r-]>Ky\u0012\u0018#\u0019q\u001cS\u0018(Dl` c8](8b\u0006^\b\u0011ƍV:X@\u0018J\u001dGGf_\u0000Sh\u000b3֒z$4\u0013&Gt\\!\u001fb$,PnTRC!86<\u000fE ]2\u0007fr\u0000\u001fpmY\f\u0016`hE\u001b\n7Fb\u001b9!\u0016r\u0013\u0016\u0018_jDY\u000b<KчZL&\u0017a%%\u000ec渲hXsǘ\u0014CJ\u0006\u0002b?o,f\u0010hP\f\u001b\u000bT\u0011>\u001bR(8M Ua\u0006\u001dZL4Ȍ0hB<kVI`< \u000b?[-eno\u0014PFX\u0010*΂!#ҍm\b}#.m9Od:\u0014\\\u001eۥˤ\u0002\u001d!\u000bق}\u0012\u0002K\u0010ʡ6V[p\u0012wP\u0010Xm@\u0019|\u0006KuEφ|0\u00000c#gytf><\u0001\u0014\u0016:q'k#ٽDT/\u0010\u0010\u0016\u00049X\u0003O{\u001a\\3\u001a\u000b%4\u0010=)~\u0016'\u0010\u0011<\tߊA6o)ی\u0002r\u001b#-\f9P@\u0003֞\u0007\u001a;Fen\u0010\u001al\t\u001e\tSF`VmYq<3\u001fO,lȉA\f\u001a[i\u0000V>y\u000e\"F\u0018q\u000e~+m&\u0000mVCymt? \u0003\u0017\u001b\u0019hn\u001duUS\u001b7\u001esaMǊǺ\u0000:;`_&X\u001cI_sIoCX$\u001cD\\G\u000b\bq\u0018'b;pq|\u00005 \u0006RV\u0005<G+#\u001b<{\u0006\u00108\t\nB^6\u0012@7`<5$i\\^2fd\u0005|\u0006\u0000g]&3\u0001˃!b.S}Vn\u0013\u001b%\u0002\r\u000b!1\u0004%.ٗ\u0006.@eӶԈ\u0006Q\u0019_b\u001c\u0007\u000f1^ \b9\u001b ُ\u0017F\f\u001c\u000b\u0005f,cb\u0000\u0011P9\u0014\rM\u000bT=.QOwB\u0014\u001c\tS\u0015e\u0010.\u000e\u00073>Os@2s2\u0003OU\u001e\" i\f@Z\u0000&%H\"ưLQ68Sp4\u0003\u000e/Ѽ\u0005\u0014\u0016|;μo)\u001d\rz@+`B\u0013JҠ㛎\u0000$\u0000!sмFA;p^G\"\fD`2W\u00035G\u0010~~D\u00057v4\u0000Ly%ORc\u0007)R,IԻ\u0006\u0013\u0003Fy\u000f!\\gDaUejP0\u0000ӘH\bܓr\u0015\u0017a0Fa1sL.C\u0019+#v\u0004\u0003A\bMgp\u000b-G\u0013!\u0011,OFu\t6\u0006)X(\\B\u0014*w6\u000fF \u0012\u0011hQ]n\u00185S%9D\u0014,aB\"\u0002(\u001e]\u0010p@\u001b\u0007L(-\u0019\u0002VpC\u0016\u0011 \u0007\u001a\u000b&Ёa\fx>\u001bqh$\u0016\u0002Qr\u0017pi<Ńq! }@l\u000fH\u000eIe.\u001bo\u0019 /NB1XbQ\u0019Ɲ\r=\\#\u0012g͋,9\u0005\u001e!\u0004ܗCoR\u0017f\u000e\u001dPʂO5qނ\u000fc\u0002\u0011r\r&\u001dict~\u0003l\u001b\u001eGapLtDp\u0011\npgc|\u0013d/oP{\u0010\n\u0010)2\u001bˈ{0%)x\u0000.CM\u0016%\u001c\b5C\u001f\tH\u000eK\u0001D\u0014 FF+\u00195\fY\f%ޟ=\"\u0014\"rKW4D\u0011\u000etM\u0002ԭZp ;>\u0011}7JOKE/\u0015\\c$hr\u0004X15\u0006x$\u000f$J5<WD\"\u0019܅r\f=\"z<V\\\u0011\u001e7.\n VxBD`\u0018F晵q,DU6\u0000\n\u0002M\u001b$]T/\u001b\u0011r\u00027lWt05iAQG؍a|sK\r#65JJe\u0019p\u0001|\\Ĩ,S\u0005&ihS.w+),ЬI3qn) ~\u001cݣ6Гd\u0011\u0007K6I(%\ng[r\u0001òTQtmcDxD3s\u0012&.O'[ߏ.kc47P(e\u000fg'+;d0ĕ\f\u0000m:B{V\u0007r\u0007\u0000S=\u0006Ѡ];HJ\u001cܵ\u001fܵ<~Ɍ/\u000bՋbao\bF\u001e\u00120٦6\r%A]!\u0001VIK\u0012az`\u0012\u0016&\u001a\u0006M\u0002q\u001bVg\rl\tz4<@8m,$ofX\u0001A\u0003e\u0000P\u001c\u0005[mO4hK&>\fr\u0011\rڸ\u001eDa\u000b\u0001#7\nq@2ܥq\u0004'0[\u000em+\u001aZѓGp'eaL*\u000b\u0004\u001d01\u0004\u0013\u0000\u0012ep=\u0001\u0007`9\u00167\u0003&C>\u000fy]\bcHB\u0011rS͉\u0018w\u0017e_\u0002\u0015sY\n\u0005K]|r\u0012!gxPp2\u0004\b\u0015/Bc}mOIN\fn\"Tw`be26\u0001\fY\ti\u0003C\u0011\n3!\u0006J\u0000M><Zl୊1e6\u000e!׃n\u001a\\@\u0001\u001aFovab\u0006\r|T\u001dvq\u0017\f,!ծ\u0003_(\"%}͡\u001f\u001done7tM\u0014\u0012\u0001\u00161\u0015\u0016|\u0004-\u0016U3a?\n\u0001*\u0018\u0015W@c&ҜN೅\fToq\u0002\u0007R3=+Wr7tx\u0001ώmĒe0riTH\u001f'<7(x*J*f|^\u000f~\"^\u001aK\u0019\u0015\u000f~{h\u001e\u001e\u000e$MX$8a\u000b\u0003[,\u001dZ\u0000T-W1\tَ3Op\u0010;xq(\u0003\u0017S0%e\u001f%.\u0019`W\u000f\u0016\u0017SpB\u0016\u0002a Gn\u0001\u0016fKȭ6ArL\"Q@aV\u0011a\u0017pl)O1F\u001fb\u0003o0ۚ\u001c\\],WX\u0016o@+Ԁ1<M0ʌ,\u0006\u0002S630\u001b8\rU}IqZ\"^-)y\u0002\u0011\u0016X\u0015\u000bܮ\n\u001ah\"<\u000bX*bE\u001a@\u0001\"\"C\u0007pBO\u000f\u0011O\u0010<f;K'xƏG]s(\u0005\u0015M#d= qϠ[޼͋\u0002\u0000P\bYǖ不}\u0019\u0014D<\u000ed\nW\\^n\u0014Ѭ\u0006[\u0011\u0002S)8\u0001\u0000)(\u0007<.g\u00010,\u0014-%r\u001c\n\u0015XpBX휤\u0001b\u0011\u0006|\u00147%9WJ<\u0010\u0019^W \u0005\u0003'WqB~˚ \u0006K\u001d\u001f*@\u0018\u000b\u0015=\u0014\n%\f\u000eW\n55+-\u001fy݋\u0011_9\u0011A\\D 3Qwv5P12\\S!EGGj\nBڐ\u000bV\u0004eb\\\n^5\u000b\\(\u0006`Wӑ\u001aZ\\\u0015\u000e`t[,DMR\u001a\u0018g\u000e@gx+x\u001b@aqk\u0002\u0013b'be\\Cf<\u001exR\u000e2-ۀf%bc8\u0007Fzcn%ǑSL\u001b\rO٢\u00133k{=o<j{\u0018f\u0016V\\-_Z\u001aV\u001ci-\r\u0002\u001cZr\u000f6\"E\u0003jk|\u001b\u0014P,fi(߬,4JI$\u000f\u0017\"\n<o\bu/7\u0019/\u0013fI6}l8Vy2\u0019vV\\ )\u0011P[\u000f\bN44o J\r\u0003(b\r\u000f\u000fx\u001bԌŪ|HY*e`9OQ<#o)::Fz>\u0018<zu\\ED3sW>@qI\b7kRB\u00124Qr?/\u000b\u0007\u0014\r\u000eX F[6Z(Jr$\u00146\u001c,\b`=,sY,~GS\u0003\u0016\u000e\u001b\bW\u0005A\u0011\u0005\fhV\u001cz>_:\u00158>؎ݍ0Gd,3\u0010\reYYe\u000f=D/A$!`3\u001c(|\u000bb]\u001f\u00139R\u0018$e\b\u0019@\f\u0017(\u0018\u0016HZg~3(<\u0010%\" :V\t-7u\u000e\fv_`Ϋ\u0001P!<OFu\n4\u0000f̩]L7)k6\u001dX%V\u0012ddxuX\u0007ބD̎/_'6P%\u0001\r\u0002f\u0010M.\u0002y_`Xo2<k\b!\u0000;cӔ\u000b\u0004\u00116qd0!C!ad'm\u0006\u0001\\O\u001f\u00111d\b\u0018\u0012/\u0005c\u0013t'D,\u0001xU>}\u0017H3cnmi7\u0010(\r\nmVN|M\u0006=\u0010`C\u0010R\u0018\nڼM\\SOn/x\u0002`\bȝ\u0001]rJŊV|^r\u0006Q(\u0016\u0016G$G\u0006FS`r\u000e+P˪vb\u0000~%f.JN\u0000e{{ğdnŋ5\u0011\u0006UX\u00028\u0005f`\u0000H;u\b\u000e`\\=\b\u00117E\u00126\u0003NJ{\u0003ޭ.4Oyn\u000e6\"߰\u0002\u0010A+0\u001fE\u001fW|\u0010\u000b\u0013@Ccᇬu\nM\u0018H/+W/i!f\u0007AT\u0003!\u0000I\u0007\u00138hEN!zHxK.\u001dx\u0003(l\u0016\u001dyڸaD\\\u001f+y\f*h\u0003L\u001ae\u0018Y0\u0012ӏuSx\u000f/\u0015;\u0012`VN\u0002x\u0005ӿ\n<\u0004@\u0005\u0000-BؔO\u0001~\u0013LQYioIQ\u00014F\u001c[+8\u0016򤁆\fIݓP\u0004.\u001e\r}\u0010̒]޿ɢ`\u0005sbJ!\u0002-<3\u0003wÓ/B/ ~\\E˩=~A޹X\\\u0000y!B/$EC\u0005e\u001a\u0002\f\f1m\u0010e[;YR\u001e\r\u000f\t8\u0019ok\u0015X\f~$\u0001nD'Ph<NqūԾspG׀@8]\u0000\u0006EJB\u0007mvB\u00051bю'>Z\tϱoa#\u001d\u0011\u001bŀxn=l\u0000D\u001281\u0003s\u001b@\u001b\fpqs\u0018i{[Y\u0011t@3\u000f<bb%A9\u0005:woFTfăR\u0001> @\n{h=F\u001d0d@}2슼3l&x\u0013\u001bN\u0007\"\f\u001ba?B\u001b\u001dWd<9RhM\u001a𣖕$[\u000b'C,U=>TPsb]|&yvt%\u000068y\fK.@!|=;:j\u0004\n\u001dMB}Ae6=\u0014##\u001dhb@\u0016'Z:lEʗic\u001f?Ki\u0019j=TD\"\u0001̕\u001dW \u0002]1\u000eRZTe\b9.C#\\B\u0016QF\u0013kCvs\rJHYtkH\t\t\u001eR\u0005\u001a<PkDt\u001f?teLHr#x9\u0017-P9^a'O\u0011v\u0019uF2L\u0003\"*\u001aXpHʛ. \"\u001cA\u001e;U\u0000\u0004$ײ\u001e\u001b\"0Y}6Â]\u000ef\rL$w`ݖ\u000blb 3U\u001a!\f<HJ$\u0011u\u0007\b')l\u0013z~\u000b:\u0017n\u0016^/T\rc\u001e%!~[Mn\u0012U\u0003C\u0005Br4Fb\u0016\u0018\b\u001e\u000f\u0000e\u0012\u001bC+Ϳ4^\u0019D\u0019tw*;\u0005\u0015%8vh4NH!yʹ\u0002ҕ\u001f@\"'*\u0015\r0{\t\u0018p55xNuwNn㜼\u0012\u000b\u00060q|%I\u000e\\\u001d*Lrs37`eܣ\u001bɿf#\u0011)ߍmF%Ȧ\u0003Ϥ\u0013!ܗo\u001f\r\\pUɄt3`c\u001fJ3q$G80XZ\u0018}@n\nd. ,x8j̦jMX3aA\u0013-=H׈]ZQ<\u0005w,A90{dwAV%)Z{5X>,diyl\u001d\u0005EeCkDgm\u0001\u0013\b\fD52\r\u001e4*dƃ\u0018PJ.#$-:\u0007íQ|FvRw\u0005_\u0003))G\\d\u0001e\u0005:'2C\\bA\u0003BW)lX͐LN\u0001N(+\t8Zf/4L@,jK5Q \u0014N:m\f\u001b\u0018\u0014\u0006z']$\u0017<\"0a\u0006ш\u000bvvhݴ\u00036B\u000f\u0011M\fO/Vo\u0019Ɉb4\u001a\u0011\u001a\u0015\u0001\n\ni\u001bA\u0007>qpB.M[\u0005I\b\u0013$RT76tY7L5Z#I\u001e^ɆFGo\b\u001ajz\fKۡq\u000636r\u0018ł\u001dhci'TA%e5,:\u0000i\u0003\u0003Q\u0000v\u001bWn\u0010bU\u0007j#\f\u001f\u000eY\u0001x/~?nob3hS0TZ>\f>^\u001e>eUi.8oSͽBTOƣ\u00073vzl%\r`\u0018\u0018\u00133@X\u00192\u0018D;KX#ߩ`mB;\u0012\u001d\u001e<אG.\u0016{V\u000b\u0018\u00120B\u001c$݀\fUH\tGd\u0016?D\\@&h)<\u0010\u0018X:u\u0019Z\u0012MW d~v9t9Z,Nx&\n\"X%J\u0018\u0018I\u0006\rM3ۡ4h=!Q6A\u001f\u0007|W\u0000\b`Q9ZA\u001co8sL\u0004\\!}BcfQ@7c\u0014o \u0004h#^@ydA0\u0002_\u0000Q\u0003d]di=\t8!d\u0012\u0018\u0014T{\r\u0006$\u0006<D\u0014--L}\u0004tX<G_bb(o0\u0007SF\u000b݉fNMNL'8%`\u0001M{7œXjy\u0012']0\u000et\u000f}\rۢaL`\u0007űC6fSu\u0010et6^گwݦƦ\t[Z\u0016;{TD˧y|I5_En#6F~|yݡbw\u001by\u0013\u001b&\\ö?\u0019\u000e\u0005|B±I~\u0016\u0013aZeDu\u0010L\u0002\u0018ʨ\u0006R @g2oP\\,C7G\u000b\u0000E`@Qloa\u0006ƜLX\u001c,묤zR&2\t\rz\flW\u000759c \u001b%pT;s-;G\"3oM\u0017a:\u0005?;F?Xpeã\\LCn\u001bb0Uㅤ\u001dE냌\u0010UuٲA?\u000b]-Ҥ\u0010g {f\u001d\u0016CFjs\rИ\u000b=@m |\u000b\u000b0_{\u0017/tS\u000bSy\u0000, Z\u0010tC\tw\u0014N[_\u0019xhïV*<\b\u0006ڰe x步A9PZC\u001fuI\u0019VCOv̤#\u0003Q\f@\u0012v&j#v\u0006>\u00077pQJF\u0007[LUVc\u0013J#ˬzTl4#\u00187\u0019\u0014K\r v\u0000;G9ۺ}6>ЭϜ6Oa\u0004Ϩ&P2e>\u0010|(C88 gA o\u0003j\r4 Y\u0018\u0013Amoqyc}U`\u0010ѿ\u0013\u0004ct$KmC3'\u000fI\u0003+L\u0017\n\u001a\u00131Mo\b0VX\"@\u0002>ہ&s\u00108\u0001\u00115\u001aU*b؃\u000eCmE&ǢC&T\u0010\u0007ci\f%w\u000fJ\u0000\u001117le2\u0013ApMA\rM/bGLh44\u0018\f\u0006<2\u001axHWD,2YV\"x\"\f[z\ru4@x1\nH h\u0004,&\bTh0'#v>\u0015!̽9\u00155\u0002\u0006I\u001d\nBWh=!BE5bWíNz\u0014S.$BR\u0014P\bN\"MQ\u0010VI<(+\u0010Z@[#2\u0015훕f˫\t\u0007n\r_l\n)\ne[\u0010\u0013}\u0011,\u001e (#.\\\bn#|\u0002 {Z#DպmC\f\u0012~\u000f <Nr\u0002rD:=rM]#b\fWDd\u0012.*0\r\u0014$\u0018V-\u0014=FԴ7<G,\u0013z\u0017tW\u0014\u0016\u0002\u000e@\u000bɞ~AO.mt.@RcWHX@[tX_O\u000f)\u0014\u00121tG.t{b}\u001a}Ԡ=\u0002喆ZmGൟ\u0005ˍTL+\r9*ݬHdv \u000bS\u001bNqUtaeѧ|\u001cD'\u0006G\u0013wi\"\u001f\b˙nPI19C8Q{Pzz\u0003*-v^jWd4\u0006\nFm+m sზ_)\u001fRۀ/PV\u0019@KP\u001a\u001dJ\u000bKu^\u0016\"m\b86\u001eg\u0018D\u001bv\u001d\u0010l\u0004Qy_҃]dT?Ӄ6!O7Nu\u000fIYW\u0014AMwש#U˩\u0000t8\u000eP\u0005%׎B;\bEyɨCQ\u001f4\u0000:\u000bBA\u001fҭ4@៻G\u0013m\u0003Xi\u0005\u0011p\bLRaAD*Gh.<\u0002,.`4C= \u001aG\" :\u0017gle+*Wu߁wW6ꛀ5&x\u001c\u0004>}~K*\u0014]U\u001fq\u00005(<$ĭ|q\u0001H>@\bZz(&\u00074P{Cوt\u0004\u0016i\u0003\u000fwq\u001f>8o\u001e ӓ+2\u0010dABǱև\u0019d\u0012c\u001a0tAx\u0019ĲLP:]\u0013\u0012~:qC\u0013`>~Ev+w\u000b'\u001bl\u0011I\u0015$p !R\u0001煦\u0013\u000f0ʅ9\f\u0000^n\u0017x 1ɰ P3\n49'\u001e\u0017\u00063\u001fz\"\u001af\u000b߆%$\u0015y\u0001/\u0010w\u00181h.\u001cg\u001b.B\u0005DI\u000fh \u0018\u001b]C;2d/v >$N{uj\r1\u0015(n T|HʦRij7v8Te\u00197r.tW]8'Qo ,E?D\u0004<\u0015\u0010\b9\tK\u00075<N僉/,\u000fe#3D0L7p\u0002\u0017\u0006F8HyTf\u0010/.V'\u001cuk+\\\node\u0018!^G1sX̓}\u000b\u0019>ZYs\u001e\u0003\u0013\u0000=[=(\u001bTP%NĞ\t{,\u001d+xY\u0019,)A#\u0000+\u001er:up\fL$ɞ\u0014x(\">xW|\u0006'$l#8 \u000f\u0016Z\u0019\u0006&I\u0007>׊q\u0007\u001d(\u000b\u0007\u000e\u0000Z\u001fk\u001b\u0014)+\u001eI^*\\}-߿Yr_]Mr9h4qÝ|\t-3de\"wm'9'hH+m\u0010\u0005b/xfሚ[W^+tzd$1ڦ(\u001fW4\u0010n\u001cҫ\u0012Stfa~M&< _tz}YqOQ>\u000e!^O\u0017\u0014:<\u0010\u0004@P$M\\Tl\u0005 \u0005G&!15\u0016FdCɇ~vd9q}Tm\r\u0018NG\u0007\u0007H!\fAPSLm9P MQ?2vJRI}Ƀ*#S羗>Щ\u000b\u0003ޡX\"җqe\u001c\u0019)\u0018.nkٵF\u0012\u001aHj4?QH)ɺʛ$߄k\u00063\u0019Qo\u001aS¯'J@N\u0004hn\u0013\u0003eլ|Mܩ\u0018Zv\nd̢gW2R>7Y9\u0007i7VvvS\u001e?ocPȏI\u0018nnݨ|Tgdu5,\f\u0012\\G,\u001f7sSˮD1e\u001bEq\u001b\u0006no\u0013a\u001eҲFt4\u001b\u0003F\u0016>\t)ͮ\u0007\u0019d෬7*5s\u0006~\u000bSe[\u0002>]\u0013~\u0010EWFv@t\u0004p'jB)}]m\u0013Rm!^Ħ W\u0016\u0007ue\r\"磻ؖ#T\u0010/Qom\u0005(PevO\u001eZ]ܶkS\u001f\u001fZ\u0015HGf \u00004\u0019\u001eG\u001e\u001c̚G\u000f'ͩD%U\r.KK>\u0001Eo\"\n7z3P ӸW-d2K\u001eB\u0007Կۈii5!\u001e'G\b3n4#28Qdo(.\u001dC!\u0011G͟(8HӧM\u0001'9q\u0018šŕG[\u001d^\u001bPD<.\u0017uZc^I\u0006\u0018T t\u0013}+Ł\u0003< e\u001d-kAX,\u0013Z\u0016va]\u001b\u000e\u000b \u0013Y\n\u0005\u000er\u0017Y4\\\u0019?Y7،~4~\b,D!j\"m\u0003-a\u001c\u0011+!lm[V}޾.@DmJ8\b5\u0000y%Dۭ~p^\u0003\u000eG߀\u0010=ovePS]\u0017$SHc\u0017M\u0014p;\u001d2/9o\u000e|\btoH\r\u0003\u000fBhe\u0019xd(sdY\t\u0017?>\u0005\r$!\u0004\rM䌀T{\u00075'Q\u001a\u000b)\u0001GpS@\u0014NlU|v\u0002\u001exD|dHv\r;V\u000bymoMc\\i\u0003EO3q>\u0001\u0000.8Ҫ趸\u0019vb8\u001b\u001e\"US?*A\u000fӿsm\u0000$=J\u000f+\u0001}mu8\u0001Y \u001e\u0011 \u0015\u001f)Nc\"\u0016J\n\nڍ\u0019ZP,+,C |,\u0003W 6\u00012\u001br+\n<\u0006'Q WȺSCQ-\rV\u001f<H#t(@\u00061\u0006^\rp0d:8\u00079a\u0012v2\u0012\u0013#%XBb8%&U_-\"~yɽz]DwƸGtԍ!\n\u0007;\u0006s\bVj\u001f\u0014eʑ(:M:3^Gp&`+CqZt;\n9Ft2$p\u001b<6\u001e,\u0014$yv\u0002iFdv0n/\u0007\"\u0010!l\u0011aC\u0013HǾ~\r@ZH\u0016\u0011\\ˌ3\u000f\u0002\u001e\u001b]v\u0004\u0011,>\u00136Pnd8q\u0015l1wo3#\u001a%$MB2jX'I(i\u0003I.L\tIA/h\"t2\nݎݶFw\u0006\u0005c_\tK4%e\u0007jL0\u0003Rԛ1t\u00143\u000f\u0016;f5\u0015\u0014\u0016?Z\u0001E1mVtoۂ\u0011x\u0019)+\r:\u001d\u0015*\u001e\u000fr\u0006S\u00060\u0014=\u001e\nfhG\u0019M+_p2})\u0019ُt>-H$\u0006\u000ebsN\u000eF@`>\b\u0005v(\"˿D/C\u0004|M=:L\u0003\u0016@.\u001b\u0005E\rb,s\u0013\u0004R,rx#NBN M\\\u0010AV[P\u0004\u0013ĠE]b\\\u001b\u0002\u0004\"j9\u0019 \\\u0000aB\u0003vݯNt\u00125\nEÁM$'\u000b\u0016BI3C\f\u00019MV0pG \u0003W6$\u0010^\u001c\u0004JZ5F\f>\u0015&AǕt=\"qۙ\u001e \u000b2Z\u000e\u0006o9\u00102|\",JhY\"z;\u0001mЌ60OXW\u0019\u0010.\u0019Ȇ8tv/; \u000fY\u0013i]כ,\u001aQ\u0006\u0012FƿPouԪt!ƺ>Q\rt\u001aLhѪٌk\u001ct\bu6,-\bmp\u0013rhxtw\u0006Joj4j\u0018ПNOhtUU4gwn\u000b8\n\u0010\u000fН]e2ыd\u0014\nue\u0011k2 #o)2\u001ec\u001c\u0010f\u0003/3\u001dq\\ФZ\u0006\u001cIay8r+tx\u0005X#H\u0001hp\u0015\u0007\u0005:fEtkCVp\b/\u001a8\u0010\u000ej\u0000iFt\u0011$iFB$+\u0001\">'!Cx\u0004\b\u001fj:0zZ`]!(\u0001ԛ(퀴v\u0019jb\u001b\b4c2u\rܻrRB4+B؟AO\u0000(dZ]o\u0003\\C\u0011h#t\u0015\u001by2?ٝa\u00147+\u000b\u0003mXy\u0015\u0010Om \u0013\u0015ȁlLk\u001cy䄈\u001dY\u0003\u0006A9Q\\e^L<\u0000 Fs@KZ7NH+\u0007(S=L\u0016kL\n1:47Ry8\u001a\r\\&E-@Y\u0001nvT=4b\u001b%{$\u0019s\u0019VG)\u0017\u0010陲4\b\u001c@~ENJG\u0006ZHa\tJ/kB͈n0l0 W<AϥG}+800d3\"\u0007\td]_)<\u0007 \u000f8iV}aZ\u000bO\u000b!q\u0016?\u000fDn<?F8\u0019*bK:\u001fG\u000b\u0005X\u001b,=-S-7\u0017\u001cnZ(9V\u0000|\u001cp;y\u00074\u0017\u001ceP\u000er䮀#OR\u0004UC:W7m\u0004:\t}u{U.\u001bCلCj\u001a\u0019\r3XNW\"\fU\u000e\rMz\u0013Q*\b\\M$NV\u001bǱ\rZ\u0011l\fV8-PG\u0010\u000es$*\u0006Svuze\u001b\u000f\u0019%΋Ww,ɂB+,V@v,l{\u00061X.\u000f͇z&.`C4\u0014\u0019Q8\rg\u0013葷M?oP3HOt\u0012\u001a\u0005t8yb;zx\u00159<\t\u001d \u001119 W7b.V+f7nn\u00032\u0012\b=# =XKg\u001eX\u001dP@j\u001c6DI/SdWaP92lEQ.@ʁo*%\u0001J#LI.\u001bA(\u0005\u0001S\u00041\u001cpAhb\r:\u0018\u001atFakǡ\u0002'*2r9\tB>n1u #н\ne\f\u000f.nc\u0004pP<(f\u0001B}P\u00142\t^\u0012愤\u001dB\u0007\u0010桽:\u000f:76_\u000611O`io\bt\u001fO'axb,م&A27\u000b!Z7ds(i\u0013EG>f\u0016Ka_tX^\u0017;-Qm(fܴ#Ŀ?=|TB\u0015G=F4\u001c5jK A$\u000f\u0019V\u0011\u001d4;c2O2\b`\u000fL\u001e\u001fg>׉iEA\u001b؆zm4\u0002NL\u001a$+z\t\u0011\u001aL0xx2\u000e\u000b9(!փ\b7$\u0001Ӝxt7Y1Z\u001c\u000e'x\u0002@:}Cb\nEe/X`\"etU\t*`\u0019F>㚐X2X[P\u000eG0=\u0015/\u000eB\u001e\u0014\u0003\u0014Z\u0003'PSfl\nd\bA#\"٢\u001e\u0002b-\\@\"4FPCUX\u0010mqj![tK\u0011=\u0012\u0010\u00022{\u001dCHd;ቹ-\u001d\u001aHaɤK#pxe8\nrhc\u0011Q?n\u0003y\u000e VbX\u0000\u001e9=ƻ\boGA;C\u0003ف\u0018$\u0015t+-\u001f\u000f\u001b\r&!\u0004\u0010aXsPj\u000eܟE6{Ý&\u0006}Е̰o\f>HWN熭lJW[\u000b6E^\u000f\u0003\u001e\"\b><ę&h\u001d5-r-`[i\u0004i\u00077;t&X84\\2\u001e\u001bJ\u001b\f\u0014\r$I\u0010\u0015\u0010L 2,\u00156eG\u0017\"|j\u0019`^Yak\u0004\u0010\u0006Q_\u0010st+lFRGe3,\u0016yH\u0010]HK\u0002\u0007\u0011A㗁<\u001e\f3\u000bz\u000b<ӦCNnf~C\r_OM렠\u0018jߍ<ʗFm3Iw>\n\n_wAN=Ai\u0002%\"dH\u000eY\b{\"gg\u001d&lӣ\u001b\u0014L\"-1x|V0\u000eJ}ẻkʺ'C\u001e\u0011[)!Ny\u0017Ci\u000f\u000fs\u0000\u001dcpH\u001d\u0010,:t\\\u001aY:N\u001bSpS6^\u0015P\n}DQ\u001e=\u0000\rƅ.\u0011.5\re5\"Z/\u001al`A\u0011(0 ig8\u0003ȼu+T\u000fiMQ!q6]11Zg,O$\u000b!A\u0007\u001f||\u000f\u000bLzg\rnpvHظ\u0000٦49Z8`Fc\b8)P\u0007~\u0014~Na\u0007\u0015|\u0000j)LC7\u0010C[\tAq:~9f+ZPYUWWX)\u001dӱE˶\"b\u0000Lt=`\u0013֭RHӝ\u0012>\u0017\u000e\u00045Yf 5i\"u\u0003\u000b!Qm'\u0005,@P\f\u0001\u0018\fUnIC:\u0005{\u0004=;ft1I/ns^;.\u0004H-\u001eomIMuH\u0012hǀ 2\u001c`^+uOw\u001a;u)K\u0002\u0002\u0001.Ne$\f6Jj\u000bg\roul\u0001&E}\u000e#nןUj8MڑZ~6q\u0016mU%L:V\u0014v\u000fE\u0004\n\u0001U\fԭF\u0015XjX=b\u0017cx/q\u0002\u0005:{\u0003\u0002+oCD73\u0007q@-c\u0002D#V𗖅s\n\f:\u0007~MΫ\u0002K(\u001c7\u0010@\u0000(2Jy\u0016 +XvZ\u0010\u0002~\u0000n\u0006r\rBI^vT4[z\npNH6b\u0002fȱ\u001ckAr\u0017X\u0011Wg:bbtn\tg\u00067AVd;6Bx\u0016\u00141f(OxyGQ\u0013o\u0004<=\u00036t61p\fၢ {\rC#QQN\n:\u0015.I\u0010i\u0013%$gdFz[?4SN\u0002` D&\r0u\u001c\u0010g\r8i'9猂Q;:18\u0012x8d \nuՙ:p\f\u001f\u001d=]e\u00105@8m\u000ey_1+\u0018|\u0007(_<zm[z\u0010\n=\u0017\u0007Q\u0003%pF\u0002,^N1\u0018R\u0001\u001aά>Ɋ\"ЇCYo\u001b\tɊ;I\t\\\"\rߪL\u0002&\u0007͙K\u0002NZ\u0014C\u00060JSF\"z58OHYf+'gx9zUf'\u001bdv\u001a&|Ȧ:2;\u0006iOߠv\u000eP\u0019|m\u0015P!}#d|S\u0018/KNЛ\\^6iH\u0007\u0014u\u0019J\u001e5!\u0016\bx\u001d\u0006pCOL}ÎY\u001b\\mDFO\u0012\u0015䲌<^\u0012,\n{$@Z(\u0012\u001c!\u0001\u001c\u0011Wi0\bU\u000e:qCS>^z\u0014\n-i66Iut\u0011l\u0017&iZ6\f\u001d\f NҭN]k`YFLS\"\u0004T\u000f5Ñ\"&oBPt]\u0014Z<$_PUuf\u001e@A#wB\u001f)\u0007 ̖$\rBSu5\u0014\u0016z9@\u0006\u0010Z\u0000U&`\u000fJ\u0007$\u001a0\u001fLbvhW\n%*^\u001fZ+(5dQK)\u0001k\u0010\u0001~\u0012bˠCP;0*׃jJ~\"|ͼcZmʯ^w!Ҁ\bl\u001e\u0014t\u00024K\u0017=%<\u0017)L2)g\u0013e]hFSʹS]n#\u001a<\u001b{K\u0006\u0006\u0000g4C*CI\u001cO_]9\fUh~\u0003\u001b+)uFndFF\u0015\"V\u0003F&F\rC3\u0006f\u001b\u000b\rI.s\u0000\u0011X\u001b@\f\u00031\bRdn\n{a6&UKYie\\\u000f=K|_n#\u000bJlv\tD\u0018BS37:L$\u0007~\u0005LUw@{\u0012'\u001aMn\u0002jѩ\u001f$dX|_g\u001f\u0004\u0002&+` .\r<HT\u000bTg\rbJC~5n>1\u0006\u0016)ei\u0012Y\u0013@\u0002d\u0010\u0006&s,+<\u0001\t2\u0006R\u000b5On\u001628:(H\u0019۱Q\u0013\n\b\u0004g9\u001bG9\b& nl9P}H؂4\tn\u0005\u0011\nf\f\u001242y!mhD\u0003\u001e\u0002XĲL\u0001jXrMf&2_7|\u001ag$+\u00003T |\u0006\u000e7c%`8\u0013L\u000b\u0007\u0018\u0001\u0003\u00005KW-1=b%S\u0002{}\u0001j:ΫǦF{\u0017\u001a&\"bm3t8\\\u00064(`@jV]Vlߩohg<\u0011\u0015\u001aO\u000el\n\u000fN\u0000\u001e\\\u0007u\t\"7X\u001cNLY@7!/Bp3Ūz>\"02P1\u0000L\u0007{Ga3\u0019\u000b\u001b¡\u0003hǉ*\u000flZS\u0006^4ÉA@=ݭ<\u0016d\u001a=j\u0017*\u001b\u0007tP4tu7\u000e`ϵ\u000ec}f\u0019!\u001fV\u001e*\f\rug\u001c\u0018)H@C\u0007;ҽ}lsAs,1Ru歨Ơ1/`EZ4N\u0001\u0018\u0007:\\y9x\u001c\u0014\u0015XJ\u0013xO\n*ցG'=\\6\u0011\u0005\u000fK>ε~r\u0011i\\j\u0010-d\fD\u0015Pedfۡ4FE$\u0007%%7g\t\u0002\u0016\u000bҀ\u0011\"\u0016\u0015DK䡁üxh*!Sp׻x\u001b_MpW\u001a\r.>X[\u0006b%_\u0011(\r|7\tAcB&՝H\r\u00150q.k8(\u0006Cu\u0007$(\u001a@4H)ЧNGa{#$d.qȺ\u001d\u0004,r  S/&M\u00005>|\u000bz\u0001@w\u0015\u001b\u0002n8Rw.|c@l\b\u0003}31&CP,\u0010I\u0005\u000eѺaFu]/\u0007\u0005_^g@\u0013a\u001e\u001b<<Y@;&y\"J\u0007kBkS\r\u000e4bH\u001f9&I\u000eJ&K_U\"ŰHĖ/s\u0018C\u0003h9\u0006 ]u$'+\u0001\u001c\u0004h\rB/\t@ۘXsb(Kwi\u0010jTpx\u0007(;>cc\u0000\nQ܂$\u0006[\u0002\u0007I>z[f\u0019\u0004ss4ÙA\u0010\u0002f\u0013\u001f _\u0018\u000bF\u0003LT\u0016\u000f\u0004YX77M\fVxĚt\u000f-\u000fh\u001e[P>e\u0013(\u0007\u000frX\f\u0003%3f\u000eZa^8|k\u0010\u001d\f\u001b;`WYzD[X7i\"p/#\u0000OϤtEF&3Iw]Gwk{wkXۏ;nmobm뛀~?8k1]۠SHn\fmz\u0010OL1\u0003\f``NQIsC\u0015\u0018G-N\u0010\u000eB\u0017\u0002Ma$\u000bb^FBG%\u0005\u0000\u000b\u0000O/a\u0013 \u0006{\u0001Lp\u0002^hi(պD6\u0015M%pdTG<ϖe\u001a#j#,Uzx\u0006k\t\u0007.\u0000\b\u0012\u001dǭL!42B<\u000e\u0013|M\u0003Cdoe\u0000C\u0017MS\u000bʖA7\u001fF\u001dJ.\u000b\b\b\u001d\tt9\u001cLf;WuVUiN\u0018A\u0007\ftI/\u0003%sݪ\u0006obY#}ٍ\u0017@O\u0005y\"{K3ٲ㮳\u001du5$\u0010\u0004nvJ\u0013\u0007\u000feIΨKв6\u0014\fziB\u001b2!X5\u0010k\u0004`|\u0018W\u0011ͫEGm\u0000<p\u000b\u001cyzt47\u001b708I\u0000\u0015 0̢ =ؿ\u0005Gؚ]PEGlxfDjA@LGwVTϢ\u000f-C.\u0005\r\t\nsER\u0014f\nMB\u000b@µ޺0rRD\u0004 \u00073fi6F\u0001\u0011y\u0004E\u0006J\n\u0013B\u0001u\rpNWH3\u0015\u0014IZ˄aiҗעg$Pu:|h\\\u0010^\u00078*Q1#\nNA{O\u0011Qb\u001eǽ\u00145/y@\u0013'xP@3u|\u001dḍ\u000f\u0002hCsw;pj\u0000jUp[fuñ\u0011h\u0016TXh/\u0005{\u0012JFk\u00130r\tMg>8o)rtӪ\u0002\u0002Z\rcuə;&.]|\u001b5FK\u0001lm\u001f\"%2skk$9\u0004%4\u0003[\u0003R\u0012\u000f\u0019\u0012A҆\u001bt\fa-\\]Qʰ<\rd`\\4ƨ٦A$\u0013ڶv=k*h\u0007D\nW1PHg\tNt0c8G<}\u001e\u001aaM\u001bl\\Q8GH\u0003}<W\u0003}~*WW靼~^u޷;<~ooG(\u0002^:ԧ\u0003|\u001dDLY\u0000o\u0012듭?ΑEO>F8GP\u001d\u0007x\u0015T=\u001e?Oh\u0003\\E^G|p+NVjL\u001cѕ>vyz\u001fOü?\u001f'k#\u0012\u0003L&\u001eOg:\u0010^?Ո\u000f\u000esE\\;y|\u001cpG\u001e򺗟~/}_'_/o\u0003o>Ki*N\u0018PZqXh>\u0002m\u0014:C\u0014e\u0013ޤu\u0002INL<IeT\bb\u0003,/ؠ\b>i\u000bͣ\u0016g=1Q\u0001W>\u0012ImI\u0012d73\u0013Kd:\u0006<VI0iJ^Wa\u000e,t\u001a\" /\n,\u0010? P~Q;wv5\u000eF+)B\u0003:?m\u001ej2ePWԮי-FOO\u0004\u001fK\u001e)24;z\u0000j] Ӱ\u0006,|\u001cUBvF6`;n<R<\u00150&rB\u001csw\"&n`;\\T2*`(\u0004\u0003H2Y:\u000f\ru]Z\t`3!b\b1AbI^\u001ac-_͊s2[gP0;n2@_\u0016gnG\u0019O'&\u0010U=AږH\u0006tuf\tSE\u000b\u0013IlV:\u001escڱP,m.\u0019%\u0002f\u0007\fA\u0012\u001aY\b\u0007b\u0017\u0007\u0010\u0011`::4h˅-;2aTԼ\u0019\t=wF]\u0014D\u0017*Z\"ـo(fZqg8=\rUX \u001b\u001e\f\u0012A\u001f}ԑ\u0003\u0001\u00049VW=LHXv\u0014UӶ\u000epKTQÀa\u0018\u001d4/\u001da\u00031\u000bݻA\u001b@?X4\"Ŏj\u0019چ-ܧQ}\u0006gT'\u0006Q\u0006\nFY\u001en\u000b\u0010'\u0016\u0011\"Mjx`&͢&`40ץ9\u001cy%+\u0017\u0005~m+J{<\u0003&2]Q)豎X˨C\u0007!/+7͒U4A}\ni\u0015\u000fxpb\"\u000f\u0006bG|>э\u000b ݴ=MEϚ0^sf!?\u0019\u0014ڕCìwhF.k]#ݐM\u0005C}$\u001a\u0000e\\\n\n$\\Bߏn\u0018.\"<\u0007\u0005κx[R-W+GQ',EqΞ却@H\u001e\u0017\t;,v\u0010T\u0003t\u0013ς2pԳϏw\b666\u0013ښPQ&𭌎UsNS1IYA}SJ6\u000esE'-@j\b\u0013\u0004\u0013\u001b\u0002c&J\u0005%㶚SgM&xi{`bǙ\u0016\u001eW\u001eA\u0012\u000bO딬g:cАIkwb\u0019fjēa1R\u0007+2E?o$\u0006!CAR`Wt\u0004\u0013]-eV^zA\u000b-I\u0010\u0006\u0018pIA!t\u0001\u001b\u0007=\u0005\u001btsf1,?o%@KP.g\u001a0X}XK\u000e*\u0000Ĥ\u000b&,WG&Ů\u000b\u0003\u0016\n|Q\u0001\ng\u0016zΠ\u00028!\b\u001d'Ίa\u001b\u001b8H\u000f/\u0018/<yn\r\fX2NT\t\u0012]=az8ᦙV9\u001bW7݀@\tJw\u000eM\u0004m\u0010\t\u00031yD!nG\u0002\u00056\u000e\u0002\b8\u001ed\t|%\u0002\n,9y3ED\u000eqt$n+\u001cͲ\u0003\u0015Rƨ?F\n\u0003\u001d6\u00173kB0y\u00110\u0015\fôH\u001c\u0019\u0017j=\b]uq*}Ns4}Bkaz׻Xܰ(,\u0003B\u000f\u0000Q0~\u001e\b\u0013Ԁ@j<l\u001d<dC [k%\u001bN6\u0006\u0013b\n]1\u0005;K\u00150W,\u00018\u00190\u0010v\\I\u0010@7HH\u0003=_G\u0007d4([p;{\u0016DC\"5#\u0011~0l\u001bgh0&Z\u001e+H7\u001b6Do\u0001x5݂\u0018^1}\u001er\u0013,fȄݖkI\u000f\u0005%`6\u0003\u0014}BafUF6(\u001f䁲7\bFm\u000eZW\u0013(\u000e\u001d\b\u000015_Z\u001b\u0001h VO8\u001f[)ݦ,DY}nzDg\u001a(\u001a\u0017D7\u000f\rfNՑ\u001e)ze!{<Y8A[O{\u001cq<NO(:wgD,٥ :GB\u001f\u001c\u0004y.?/;\u000blA&}m!{r_\b\u0000macY\fc^ :\u001c\t\nvW9d;d7qƛO\u0010!Lao<Ū^K\u000eٰjBD޷uȐ״TMv\\\u0003C\u0018\t~%\u0012z\u001bL:&䤩\b5\u0013c\u001czcb\u000eTwfI\f\u0019<ж|+2e\u0013\u0011H1mH\u0018Gw/7\rf\u0016O\u0003U^h<\u0011@=]\\\u001byCm`9!-~s|1\u0004\u001d]ЇI/jr׳1OneiZ!zxv'WÑIվ3ՃN^3ɮ^ή^yҼi\u0007z&z.WZ۫[y\rꐟw!6R\"UֶAήs}?߁\u001f?,4tX<\u0007jҁgx΢Ӭص\u001b\u000fe\u001a\u0010\\\u0005#J3Wng\u001a֮<o\u0003~8ϸ׋ru}z#/םw,\t?f@gw㏹'ntB!hPՐQ\u0007n/;?f36\u0012\u0019M(nz1ٗ_zV \u0003aXÑEHE\u0017؈\u0019\u0000)z\"Kߒ\r4nBL\u0016\\\u0005!^TuuX\u0006LaTE\u0007Nt\u0014[\u00025\tC\fq\r\u001d\"V޺.@mhɨ[n\u0017soE \u0000$*Ox^68\u0003)\u0002v@k4DF\u0005\tٴ΀\u0002\u0007VTQ\u0000\u001eHuC\rA?\u0015VH/ύ8\bB.'-\"A=\u0016At]\u0007B@\u000bE\u001dళK\\\u0006)Zdi\u001aQ\u0002\b5\u0002\u0000A#tE\u0019\u0014@z2s&\u001aDz\u0005\u0011X@\u0003ؕ\u0016P~\n![b\u000e9\n\u0014~\u001b4`B0ȵ@g\u0018a\u001aU\u0010üv\u0001l\b~=I(dVT\u0000PE\u0018\u0013֬-ˆ$2BJ\u001d>&\u00030@Ch!^nŪ\u000e\u0014$,@ݷ\r'{%U\n퍮:b\u0006! \u0000v<j>@% \f\u0011\u0012\u001d]YQ\\{cP3.^5܎3)BH$W&AU\u0005QJ\rufm4;G]A\\\u0005BV\u0005Qd!K:q\u0016\"ec\u0007@yA\n1\u0000qj \u001e\u001e7@\f@u\u000e[ۭe2VhmHM!|J%\u0001A\u0002A\u0017\u0005^_\u001fǟ\u000e\\\u001dzˠ.e\u0015hrc\u001e\u0010M7?\u00175v\u0007\u000e5!*V@\u0003].\u0006H=Z-&'b!V\u0015'n5ѱ\u0002\u0013ɥYy\u0011\u0012d{Ar\u001f\u0011ظ>to\u00158u\u000e*9.=,&\u0013G\u001d\r}[\u0006\u00026;\u0004\u000b﹘Ȩ[:\u0012ע\u000f\n`32{kK=\n\u000fb:<l\u0017\u0018s6]Y\u0010^d\u001dt*@\u001ci\u001c^HV4CP@\u0001TP9\u001a6}tGn+=>2uZs\u000f\u000f7А\u0019[\u0002URޞ\u001c0L\bNJR>\r1hvQأN'X\\x\u001erD\b]I?\"wܪyrK\u001ac]}z\u001eG>5̣ez\u001d(ϋA\u0016@O[]\u0000Kl8AMǄƝͧ5\u0012A^\u0007<{\u0019udІ\u0003up\bٯ\u0019$ȅFJ\u001fbZ{h#Y\u0000ڢ\r2AͧJuz _%p\u0002YoBɲh)qRh\u0005qM>\u0018Q\b;X]\u001bb\f\u0003cJ\u0011([WCg\u0006'\u0010\u0012P\u0018!0WX\u000e\u001f\u0001Ye(A\u0005\u0017\u001f\u0019\rS1P\n'Qc%:%~\u0000\u0006y\u0004(|`\"/BΣ;\"U|Mf%hj򮡸f\u001bYh.л\u0003%m\u00027\u0001%uHT-/\u0006#Ѓl&\\EcI]-\u0004.J^\u0005IN),\u00132<*\u000b(A&j`\u0014\u0005mMo;B\u001c\u0015\u0011SBdhІ8\u0006\u0018h%DF\u0004\b\fЙA\u0005f!\u000e\u0018̶0ŔS/EC\u0004huVr\u001f!D\u0004\u001c?τ۠kAn{\u0016rj\u0015=\u0001\u0003u\u0000\u0005K]mzt@&0\u0012GWƅE\u0001Y\fL\u0006eϲ{\u001dB_&A~&4Հe5\u001a:g[*\u0007ݶ\u000bxJQScl\u0019g\nj\u0012\u001e[\u000e\u0004zf6/ɐ\nPP\u001eCǰ6T\u0003\u0003$L\u00152%×*D\f\u0011#:\u0010ҾobN學\u001b<6\\AxAe㊗\u001f5.cB4~\u0016fg\u0016i5wDYeHٴ~׆\u0012e݌}WD%.ӧ2uE*3\u0019\u0019^o\u0007\t\u0011-+jmyI\u0015\t6Rɷv\u001d\n\u0019ḛ\r&\u000e\u0003:'tde\u0006>!'Ƈi\u001aqӶ!q\u0019\u001an`Y4B!@B:9@\u0002.r}(l\u0001IQ\u001b<գ\u0017$q~\u00067p&\u0018+l{t\u0000#726L$\u0007\u0003ٹNX9y\u001f\u00182\u0018_iފ\u000eY5G\u000em\b\u001bh\u001eg,\u00131:+`\u001aE$ny\u0014w\u0002\u001ack`-JZM;m\u001dN0Ye\rl{EJ'c1H`48\u000e2Hu\u0016qk>\n\u0013ιz\u0012\u001fAgC\u0018Cw#wsrFB\u0016x\u001dw\u000b3\u0019>\r\u0012\u0016tnت7S\u0010\u0004k\u0007~]˳ؘsV*ed!\u0011\f\u0003P\u0006@4\u0007z\"Nz\tw/l 9\u001aTq#GcF\u0002ȭS{\u0018bjɎXGꊮu+?`zz(A1Qz_z6O9\u0016J\"\n\u0015\"qOU9Y뻽LM \u0019\u0007MD֩\"?I띦In]WFsX\u0019LZ-ǡA11CLy5?dЈ\u0010@\u0002VQDs\u0011Ct\b#AIq\u00173\u001b0 x:sp5ҍ2LTa!eT[ǻA\u0012C\u0010CޜܾyZ\u0018tZ-x>[\b\u0007m*\u001e\"\u001bme\tӅjG\n\u000fw5\u0019T\u001eid \u001f\"\u0019s\u001a$\u001a\u0016V\u0016Lܦu}O1m+@\u0003H4\u001eby,Lw0Z0\u001d'\u00128\"\u0007;M.уwOHXQU%\u0018At}ċ^.C3i9\u0006o\u0004\"}>\bRO(J\u000e\u001b_\u0002cBjz6I[cK\\Mz b\u0016\\ʬ:faLSn\bB>j\u0003'2'r\fA\u0018f6(\u000fǱQ>Zz$\u001c2xz^\u000fë0\u0002EUk&O|d\u0003U|vV\u001fɚ\u0010'QҴ;E1pŗCۇuS8q\u000b#Dd\u0003a\u001c4H\u001fZm\r?+\"z\u0005B;˺:zcM\b]\u0010;Ǉ\\TNZJ\u0004\u0003\u0003˜8$\u0016!Gsx=\u000eo\u0006=\u000f=N\u0002\"׳J?L)#\rp.qqk|\u0018{tK^|A_a\u001fOӷ+\u0006@\u0017b<c wԬ\u000e\u0003\u0013f껤~?2\u00137\u000b\u001c\u000f~1\u000bs'}ۿׯ{'?@\u0017c;7AI1\u001eU׸/74񛿐\u000b\u001f~/\u000f|,_|?\u0017_WGW~s귿wW_?(\u001f\u000b?zԽS\u0016\r\nendstream\rendobj\r6 0 obj\r<</Intent 33 0 R/Name(svg3713)/Type/OCG/Usage 34 0 R>>\rendobj\r33 0 obj\r[/View/Design]\rendobj\r34 0 obj\r<</CreatorInfo<</Creator(Adobe Illustrator 23.0)/Subtype/Artwork>>>>\rendobj\r42 0 obj\r[41 0 R]\rendobj\r73 0 obj\r<</CreationDate(D:20191219213125+02'00')/Creator(Adobe Illustrator CC 23.0 \\(Windows\\))/ModDate(D:20191222212911+01'00')/Producer(Adobe PDF library 15.00)/Title(OpenHoW2)>>\rendobj\rxref\r\n0 74\r\n0000000004 65535 f\r\n0000000016 00000 n\r\n0000000159 00000 n\r\n0000022985 00000 n\r\n0000000000 00000 f\r\n0000000000 00000 f\r\n0000145880 00000 n\r\n0000000000 00000 f\r\n0000023036 00000 n\r\n0000000000 00000 f\r\n0000000000 00000 f\r\n0000000000 00000 f\r\n0000000000 00000 f\r\n0000000000 00000 f\r\n0000000000 00000 f\r\n0000000000 00000 f\r\n0000000000 00000 f\r\n0000000000 00000 f\r\n0000000000 00000 f\r\n0000000000 00000 f\r\n0000000000 00000 f\r\n0000000000 00000 f\r\n0000000000 00000 f\r\n0000000000 00000 f\r\n0000000000 00000 f\r\n0000000000 00000 f\r\n0000000000 00000 f\r\n0000000000 00000 f\r\n0000000000 00000 f\r\n0000000000 00000 f\r\n0000000000 00000 f\r\n0000000000 00000 f\r\n0000000000 00000 f\r\n0000145950 00000 n\r\n0000145981 00000 n\r\n0000000000 00000 f\r\n0000000000 00000 f\r\n0000000000 00000 f\r\n0000000000 00000 f\r\n0000000000 00000 f\r\n0000039211 00000 n\r\n0000070592 00000 n\r\n0000146066 00000 n\r\n0000023433 00000 n\r\n0000070779 00000 n\r\n0000070107 00000 n\r\n0000036116 00000 n\r\n0000034166 00000 n\r\n0000035554 00000 n\r\n0000035602 00000 n\r\n0000036749 00000 n\r\n0000036811 00000 n\r\n0000037145 00000 n\r\n0000037479 00000 n\r\n0000037813 00000 n\r\n0000038147 00000 n\r\n0000038481 00000 n\r\n0000038815 00000 n\r\n0000070530 00000 n\r\n0000070468 00000 n\r\n0000070406 00000 n\r\n0000070344 00000 n\r\n0000070282 00000 n\r\n0000070220 00000 n\r\n0000039149 00000 n\r\n0000039460 00000 n\r\n0000039712 00000 n\r\n0000070663 00000 n\r\n0000070694 00000 n\r\n0000070853 00000 n\r\n0000071027 00000 n\r\n0000072330 00000 n\r\n0000103314 00000 n\r\n0000146091 00000 n\r\ntrailer\r\n<</Size 74/Root 1 0 R/Info 73 0 R/ID[<26D94D6FA64FA64A98BD0A60E079893A><82C0E75C3F939741AC3A2676E3ACF29E>]>>\r\nstartxref\r\n146280\r\n%%EOF\r\n"
  },
  {
    "path": "bin/mods/README.md",
    "content": "This directory exists for any modifications you might want to add to the game.\n\nTo load a different mod, pass it as an argument to the ```mod``` flag\n\n```\n    OpenHoW.exe -mod example\n```\n\nAnd then the game will attempt to load resources from the <base>/mods/example/ first before falling back\nto the directory listed as dependency.\n"
  },
  {
    "path": "bin/mods/base/actors/misc.actor",
    "content": "[\n  {\n    \"identifier\": \"model_static\",\n    \"className\": \"AStaticModel\"\n  }\n]\n"
  },
  {
    "path": "bin/mods/base/chars/primitives/cube.mtl",
    "content": "# Blender MTL File: 'None'\n# Material Count: 1\n\nnewmtl None\nNs 500\nKa 0.8 0.8 0.8\nKd 0.8 0.8 0.8\nKs 0.8 0.8 0.8\nd 1\nillum 2\n"
  },
  {
    "path": "bin/mods/base/chars/primitives/cube.obj",
    "content": "# Blender v2.80 (sub 75) OBJ File: ''\n# www.blender.org\nmtllib cube.mtl\no Cube_Cube.001\nv -1.000000 -1.000000 1.000000\nv -1.000000 1.000000 1.000000\nv -1.000000 -1.000000 -1.000000\nv -1.000000 1.000000 -1.000000\nv 1.000000 -1.000000 1.000000\nv 1.000000 1.000000 1.000000\nv 1.000000 -1.000000 -1.000000\nv 1.000000 1.000000 -1.000000\nvt 0.375000 0.000000\nvt 0.625000 0.000000\nvt 0.625000 0.250000\nvt 0.375000 0.250000\nvt 0.625000 0.500000\nvt 0.375000 0.500000\nvt 0.625000 0.750000\nvt 0.375000 0.750000\nvt 0.625000 1.000000\nvt 0.375000 1.000000\nvt 0.125000 0.500000\nvt 0.125000 0.750000\nvt 0.875000 0.500000\nvt 0.875000 0.750000\nvn -1.0000 0.0000 0.0000\nvn 0.0000 0.0000 -1.0000\nvn 1.0000 0.0000 0.0000\nvn 0.0000 0.0000 1.0000\nvn 0.0000 -1.0000 0.0000\nvn 0.0000 1.0000 0.0000\nusemtl None\ns off\nf 1/1/1 2/2/1 4/3/1 3/4/1\nf 3/4/2 4/3/2 8/5/2 7/6/2\nf 7/6/3 8/5/3 6/7/3 5/8/3\nf 5/8/4 6/7/4 2/9/4 1/10/4\nf 3/11/5 7/6/5 5/8/5 1/12/5\nf 8/5/6 4/13/6 2/14/6 6/7/6\n"
  },
  {
    "path": "bin/mods/base/chars/primitives/icosphere.mtl",
    "content": "# Blender MTL File: 'None'\n# Material Count: 1\n\nnewmtl None\nNs 500\nKa 0.8 0.8 0.8\nKd 0.8 0.8 0.8\nKs 0.8 0.8 0.8\nd 1\nillum 2\n"
  },
  {
    "path": "bin/mods/base/chars/primitives/icosphere.obj",
    "content": "# Blender v2.80 (sub 75) OBJ File: ''\n# www.blender.org\nmtllib icosphere.mtl\no Icosphere\nv 0.000000 -1.000000 0.000000\nv 0.723607 -0.447220 0.525725\nv -0.276388 -0.447220 0.850649\nv -0.894426 -0.447216 0.000000\nv -0.276388 -0.447220 -0.850649\nv 0.723607 -0.447220 -0.525725\nv 0.276388 0.447220 0.850649\nv -0.723607 0.447220 0.525725\nv -0.723607 0.447220 -0.525725\nv 0.276388 0.447220 -0.850649\nv 0.894426 0.447216 0.000000\nv 0.000000 1.000000 0.000000\nv -0.162456 -0.850654 0.499995\nv 0.425323 -0.850654 0.309011\nv 0.262869 -0.525738 0.809012\nv 0.850648 -0.525736 0.000000\nv 0.425323 -0.850654 -0.309011\nv -0.525730 -0.850652 0.000000\nv -0.688189 -0.525736 0.499997\nv -0.162456 -0.850654 -0.499995\nv -0.688189 -0.525736 -0.499997\nv 0.262869 -0.525738 -0.809012\nv 0.951058 0.000000 0.309013\nv 0.951058 0.000000 -0.309013\nv 0.000000 0.000000 1.000000\nv 0.587786 0.000000 0.809017\nv -0.951058 0.000000 0.309013\nv -0.587786 0.000000 0.809017\nv -0.587786 0.000000 -0.809017\nv -0.951058 0.000000 -0.309013\nv 0.587786 0.000000 -0.809017\nv 0.000000 0.000000 -1.000000\nv 0.688189 0.525736 0.499997\nv -0.262869 0.525738 0.809012\nv -0.850648 0.525736 0.000000\nv -0.262869 0.525738 -0.809012\nv 0.688189 0.525736 -0.499997\nv 0.162456 0.850654 0.499995\nv 0.525730 0.850652 0.000000\nv -0.425323 0.850654 0.309011\nv -0.425323 0.850654 -0.309011\nv 0.162456 0.850654 -0.499995\nvt 0.818181 0.000000\nvt 0.772726 0.078731\nvt 0.863635 0.078731\nvt 0.727272 0.157461\nvt 0.681818 0.078731\nvt 0.636363 0.157461\nvt 0.090909 0.000000\nvt 0.045454 0.078731\nvt 0.136363 0.078731\nvt 0.272727 0.000000\nvt 0.227273 0.078731\nvt 0.318182 0.078731\nvt 0.454545 0.000000\nvt 0.409090 0.078731\nvt 0.500000 0.078731\nvt 0.681818 0.236191\nvt 0.909090 0.157461\nvt 0.818181 0.157461\nvt 0.863635 0.236191\nvt 0.181818 0.157461\nvt 0.090909 0.157461\nvt 0.136363 0.236191\nvt 0.363636 0.157461\nvt 0.272727 0.157461\nvt 0.318182 0.236191\nvt 0.545454 0.157461\nvt 0.454545 0.157461\nvt 0.500000 0.236191\nvt 0.772726 0.236191\nvt 0.954545 0.236191\nvt 0.227273 0.236191\nvt 0.409090 0.236191\nvt 0.590909 0.236191\nvt 0.818181 0.314921\nvt 0.727272 0.314921\nvt 0.772726 0.393651\nvt 1.000000 0.314921\nvt 0.909091 0.314921\nvt 0.954545 0.393651\nvt 0.272727 0.314921\nvt 0.181818 0.314921\nvt 0.227273 0.393651\nvt 0.454545 0.314921\nvt 0.363636 0.314921\nvt 0.409090 0.393651\nvt 0.636363 0.314921\nvt 0.545454 0.314921\nvt 0.590909 0.393651\nvt 0.500000 0.393651\nvt 0.545454 0.472382\nvt 0.318182 0.393651\nvt 0.363636 0.472382\nvt 0.136363 0.393651\nvt 0.181818 0.472382\nvt 0.090909 0.314921\nvt 0.863635 0.393651\nvt 0.909090 0.472382\nvt 0.681818 0.393651\nvt 0.727272 0.472382\nvt 0.045454 0.236191\nvt 0.000000 0.157461\nvt 0.590909 0.078731\nvt 0.636363 0.000000\nvn 0.1024 -0.9435 0.3151\nvn 0.7002 -0.6617 0.2680\nvn -0.2680 -0.9435 0.1947\nvn -0.2680 -0.9435 -0.1947\nvn 0.1024 -0.9435 -0.3151\nvn 0.9050 -0.3304 0.2680\nvn 0.0247 -0.3304 0.9435\nvn -0.8897 -0.3304 0.3151\nvn -0.5746 -0.3304 -0.7488\nvn 0.5346 -0.3304 -0.7779\nvn 0.8026 -0.1256 0.5831\nvn -0.3066 -0.1256 0.9435\nvn -0.9921 -0.1256 0.0000\nvn -0.3066 -0.1256 -0.9435\nvn 0.8026 -0.1256 -0.5831\nvn 0.4089 0.6617 0.6284\nvn -0.4713 0.6617 0.5831\nvn -0.7002 0.6617 -0.2680\nvn 0.0385 0.6617 -0.7488\nvn 0.7240 0.6617 -0.1947\nvn 0.2680 0.9435 -0.1947\nvn 0.4911 0.7947 -0.3568\nvn 0.4089 0.6617 -0.6284\nvn -0.1024 0.9435 -0.3151\nvn -0.1876 0.7947 -0.5773\nvn -0.4713 0.6617 -0.5831\nvn -0.3313 0.9435 0.0000\nvn -0.6071 0.7947 0.0000\nvn -0.7002 0.6617 0.2680\nvn -0.1024 0.9435 0.3151\nvn -0.1876 0.7947 0.5773\nvn 0.0385 0.6617 0.7488\nvn 0.2680 0.9435 0.1947\nvn 0.4911 0.7947 0.3568\nvn 0.7240 0.6617 0.1947\nvn 0.8897 0.3304 -0.3151\nvn 0.7947 0.1876 -0.5773\nvn 0.5746 0.3304 -0.7488\nvn -0.0247 0.3304 -0.9435\nvn -0.3035 0.1876 -0.9342\nvn -0.5346 0.3304 -0.7779\nvn -0.9050 0.3304 -0.2680\nvn -0.9822 0.1876 0.0000\nvn -0.9050 0.3304 0.2680\nvn -0.5346 0.3304 0.7779\nvn -0.3035 0.1876 0.9342\nvn -0.0247 0.3304 0.9435\nvn 0.5746 0.3304 0.7488\nvn 0.7947 0.1876 0.5773\nvn 0.8897 0.3304 0.3151\nvn 0.3066 0.1256 -0.9435\nvn 0.3035 -0.1876 -0.9342\nvn 0.0247 -0.3304 -0.9435\nvn -0.8026 0.1256 -0.5831\nvn -0.7947 -0.1876 -0.5773\nvn -0.8897 -0.3304 -0.3151\nvn -0.8026 0.1256 0.5831\nvn -0.7947 -0.1876 0.5773\nvn -0.5746 -0.3304 0.7488\nvn 0.3066 0.1256 0.9435\nvn 0.3035 -0.1876 0.9342\nvn 0.5346 -0.3304 0.7779\nvn 0.9921 0.1256 0.0000\nvn 0.9822 -0.1876 0.0000\nvn 0.9050 -0.3304 -0.2680\nvn 0.4713 -0.6617 -0.5831\nvn 0.1876 -0.7947 -0.5773\nvn -0.0385 -0.6617 -0.7488\nvn -0.4089 -0.6617 -0.6284\nvn -0.4911 -0.7947 -0.3568\nvn -0.7240 -0.6617 -0.1947\nvn -0.7240 -0.6617 0.1947\nvn -0.4911 -0.7947 0.3568\nvn -0.4089 -0.6617 0.6284\nvn 0.7002 -0.6617 -0.2680\nvn 0.6071 -0.7947 0.0000\nvn 0.3313 -0.9435 0.0000\nvn -0.0385 -0.6617 0.7488\nvn 0.1876 -0.7947 0.5773\nvn 0.4713 -0.6617 0.5831\nusemtl None\ns off\nf 1/1/1 14/2/1 13/3/1\nf 2/4/2 14/5/2 16/6/2\nf 1/7/3 13/8/3 18/9/3\nf 1/10/4 18/11/4 20/12/4\nf 1/13/5 20/14/5 17/15/5\nf 2/4/6 16/6/6 23/16/6\nf 3/17/7 15/18/7 25/19/7\nf 4/20/8 19/21/8 27/22/8\nf 5/23/9 21/24/9 29/25/9\nf 6/26/10 22/27/10 31/28/10\nf 2/4/11 23/16/11 26/29/11\nf 3/17/12 25/19/12 28/30/12\nf 4/20/13 27/22/13 30/31/13\nf 5/23/14 29/25/14 32/32/14\nf 6/26/15 31/28/15 24/33/15\nf 7/34/16 33/35/16 38/36/16\nf 8/37/17 34/38/17 40/39/17\nf 9/40/18 35/41/18 41/42/18\nf 10/43/19 36/44/19 42/45/19\nf 11/46/20 37/47/20 39/48/20\nf 39/48/21 42/49/21 12/50/21\nf 39/48/22 37/47/22 42/49/22\nf 37/47/23 10/43/23 42/49/23\nf 42/45/24 41/51/24 12/52/24\nf 42/45/25 36/44/25 41/51/25\nf 36/44/26 9/40/26 41/51/26\nf 41/42/27 40/53/27 12/54/27\nf 41/42/28 35/41/28 40/53/28\nf 35/41/29 8/55/29 40/53/29\nf 40/39/30 38/56/30 12/57/30\nf 40/39/31 34/38/31 38/56/31\nf 34/38/32 7/34/32 38/56/32\nf 38/36/33 39/58/33 12/59/33\nf 38/36/34 33/35/34 39/58/34\nf 33/35/35 11/46/35 39/58/35\nf 24/33/36 37/47/36 11/46/36\nf 24/33/37 31/28/37 37/47/37\nf 31/28/38 10/43/38 37/47/38\nf 32/32/39 36/44/39 10/43/39\nf 32/32/40 29/25/40 36/44/40\nf 29/25/41 9/40/41 36/44/41\nf 30/31/42 35/41/42 9/40/42\nf 30/31/43 27/22/43 35/41/43\nf 27/22/44 8/55/44 35/41/44\nf 28/30/45 34/38/45 8/37/45\nf 28/30/46 25/19/46 34/38/46\nf 25/19/47 7/34/47 34/38/47\nf 26/29/48 33/35/48 7/34/48\nf 26/29/49 23/16/49 33/35/49\nf 23/16/50 11/46/50 33/35/50\nf 31/28/51 32/32/51 10/43/51\nf 31/28/52 22/27/52 32/32/52\nf 22/27/53 5/23/53 32/32/53\nf 29/25/54 30/31/54 9/40/54\nf 29/25/55 21/24/55 30/31/55\nf 21/24/56 4/20/56 30/31/56\nf 27/22/57 28/60/57 8/55/57\nf 27/22/58 19/21/58 28/60/58\nf 19/21/59 3/61/59 28/60/59\nf 25/19/60 26/29/60 7/34/60\nf 25/19/61 15/18/61 26/29/61\nf 15/18/62 2/4/62 26/29/62\nf 23/16/63 24/33/63 11/46/63\nf 23/16/64 16/6/64 24/33/64\nf 16/6/65 6/26/65 24/33/65\nf 17/15/66 22/27/66 6/26/66\nf 17/15/67 20/14/67 22/27/67\nf 20/14/68 5/23/68 22/27/68\nf 20/12/69 21/24/69 5/23/69\nf 20/12/70 18/11/70 21/24/70\nf 18/11/71 4/20/71 21/24/71\nf 18/9/72 19/21/72 4/20/72\nf 18/9/73 13/8/73 19/21/73\nf 13/8/74 3/61/74 19/21/74\nf 16/6/75 17/62/75 6/26/75\nf 16/6/76 14/5/76 17/62/76\nf 14/5/77 1/63/77 17/62/77\nf 13/3/78 15/18/78 3/17/78\nf 13/3/79 14/2/79 15/18/79\nf 14/2/80 2/4/80 15/18/80\n"
  },
  {
    "path": "bin/mods/base/chars/primitives/sphere.mtl",
    "content": "# Blender MTL File: 'None'\n# Material Count: 1\n\nnewmtl None\nNs 500\nKa 0.8 0.8 0.8\nKd 0.8 0.8 0.8\nKs 0.8 0.8 0.8\nd 1\nillum 2\n"
  },
  {
    "path": "bin/mods/base/chars/primitives/sphere.obj",
    "content": "# Blender v2.80 (sub 75) OBJ File: ''\n# www.blender.org\nmtllib sphere.mtl\no Sphere\nv 0.000000 0.980785 -0.195090\nv 0.000000 0.923880 -0.382683\nv 0.000000 0.831470 -0.555570\nv 0.000000 0.707107 -0.707107\nv 0.000000 0.555570 -0.831470\nv 0.000000 0.382683 -0.923880\nv 0.000000 0.195090 -0.980785\nv 0.000000 0.000000 -1.000000\nv 0.000000 -0.195090 -0.980785\nv 0.000000 -0.831470 -0.555570\nv 0.038060 0.980785 -0.191342\nv 0.074658 0.923880 -0.375330\nv 0.108386 0.831470 -0.544895\nv 0.137950 0.707107 -0.693520\nv 0.162212 0.555570 -0.815493\nv 0.180240 0.382683 -0.906127\nv 0.191342 0.195090 -0.961940\nv 0.195090 0.000000 -0.980785\nv 0.191342 -0.195090 -0.961940\nv 0.180240 -0.382683 -0.906127\nv 0.162212 -0.555570 -0.815493\nv 0.137950 -0.707107 -0.693520\nv 0.108386 -0.831470 -0.544895\nv 0.074658 -0.923880 -0.375330\nv 0.038060 -0.980785 -0.191341\nv 0.074658 0.980785 -0.180240\nv 0.146447 0.923880 -0.353553\nv 0.212608 0.831470 -0.513280\nv 0.270598 0.707107 -0.653281\nv 0.318190 0.555570 -0.768178\nv 0.353553 0.382683 -0.853553\nv 0.375330 0.195090 -0.906127\nv 0.382684 0.000000 -0.923879\nv 0.375330 -0.195090 -0.906127\nv 0.353554 -0.382683 -0.853553\nv 0.318190 -0.555570 -0.768178\nv 0.270598 -0.707107 -0.653281\nv 0.212608 -0.831470 -0.513280\nv 0.146447 -0.923880 -0.353553\nv 0.074658 -0.980785 -0.180240\nv 0.108387 0.980785 -0.162212\nv 0.212608 0.923880 -0.318190\nv 0.308658 0.831470 -0.461940\nv 0.392848 0.707107 -0.587938\nv 0.461940 0.555570 -0.691342\nv 0.513280 0.382683 -0.768178\nv 0.544895 0.195090 -0.815493\nv 0.555570 0.000000 -0.831469\nv 0.544895 -0.195090 -0.815493\nv 0.513280 -0.382683 -0.768178\nv 0.461940 -0.555570 -0.691342\nv 0.392848 -0.707107 -0.587938\nv 0.308658 -0.831470 -0.461940\nv 0.212608 -0.923880 -0.318189\nv 0.108386 -0.980785 -0.162211\nv 0.137950 0.980785 -0.137950\nv 0.270598 0.923880 -0.270598\nv 0.392848 0.831470 -0.392847\nv 0.500000 0.707107 -0.500000\nv 0.587938 0.555570 -0.587938\nv 0.653282 0.382683 -0.653281\nv 0.693520 0.195090 -0.693520\nv 0.707107 0.000000 -0.707107\nv 0.693520 -0.195090 -0.693520\nv 0.653282 -0.382683 -0.653281\nv 0.587938 -0.555570 -0.587938\nv 0.500000 -0.707107 -0.500000\nv 0.392848 -0.831470 -0.392847\nv 0.270598 -0.923880 -0.270598\nv 0.137950 -0.980785 -0.137949\nv 0.162212 0.980785 -0.108386\nv 0.318190 0.923880 -0.212607\nv 0.461940 0.831470 -0.308658\nv 0.587938 0.707107 -0.392847\nv 0.691342 0.555570 -0.461940\nv 0.768178 0.382683 -0.513280\nv 0.815493 0.195090 -0.544895\nv 0.831470 0.000000 -0.555570\nv 0.815493 -0.195090 -0.544895\nv 0.768178 -0.382683 -0.513280\nv 0.691342 -0.555570 -0.461940\nv 0.587938 -0.707107 -0.392847\nv 0.461940 -0.831470 -0.308658\nv 0.318190 -0.923880 -0.212607\nv 0.162212 -0.980785 -0.108386\nv 0.180240 0.980785 -0.074658\nv 0.353554 0.923880 -0.146446\nv 0.513280 0.831470 -0.212607\nv 0.653282 0.707107 -0.270598\nv 0.768178 0.555570 -0.318189\nv 0.853554 0.382683 -0.353553\nv 0.906128 0.195090 -0.375330\nv 0.923880 0.000000 -0.382683\nv 0.906128 -0.195090 -0.375330\nv 0.853554 -0.382683 -0.353553\nv 0.768178 -0.555570 -0.318189\nv 0.653282 -0.707107 -0.270598\nv 0.513280 -0.831470 -0.212607\nv 0.353554 -0.923880 -0.146446\nv 0.180240 -0.980785 -0.074658\nv 0.191342 0.980785 -0.038060\nv 0.375331 0.923880 -0.074658\nv 0.544895 0.831470 -0.108386\nv 0.693520 0.707107 -0.137949\nv 0.815493 0.555570 -0.162211\nv 0.906128 0.382683 -0.180240\nv 0.961940 0.195090 -0.191341\nv 0.980785 0.000000 -0.195090\nv 0.961940 -0.195090 -0.191341\nv 0.906128 -0.382683 -0.180240\nv 0.815493 -0.555570 -0.162211\nv 0.693520 -0.707107 -0.137949\nv 0.544895 -0.831470 -0.108386\nv 0.375330 -0.923880 -0.074658\nv 0.191342 -0.980785 -0.038060\nv 0.195091 0.980785 0.000000\nv 0.382684 0.923880 0.000000\nv 0.555570 0.831470 0.000000\nv 0.707107 0.707107 0.000000\nv 0.831470 0.555570 0.000000\nv 0.923880 0.382683 0.000000\nv 0.980785 0.195090 0.000000\nv 1.000000 0.000000 0.000000\nv 0.980785 -0.195090 0.000000\nv 0.923880 -0.382683 0.000000\nv 0.831470 -0.555570 0.000000\nv 0.707107 -0.707107 0.000000\nv 0.555570 -0.831470 0.000000\nv 0.382684 -0.923880 0.000000\nv 0.195090 -0.980785 0.000000\nv 0.191342 0.980785 0.038061\nv 0.375331 0.923880 0.074658\nv 0.544895 0.831470 0.108387\nv 0.693520 0.707107 0.137950\nv 0.815493 0.555570 0.162212\nv 0.906128 0.382683 0.180240\nv 0.961940 0.195090 0.191342\nv 0.980785 0.000000 0.195091\nv 0.961940 -0.195090 0.191342\nv 0.906128 -0.382683 0.180240\nv 0.815493 -0.555570 0.162212\nv 0.693520 -0.707107 0.137950\nv 0.544895 -0.831470 0.108387\nv 0.375330 -0.923880 0.074658\nv 0.191342 -0.980785 0.038061\nv 0.180240 0.980785 0.074658\nv 0.353554 0.923880 0.146447\nv 0.513280 0.831470 0.212608\nv 0.653282 0.707107 0.270598\nv 0.768178 0.555570 0.318190\nv 0.853554 0.382683 0.353554\nv 0.906127 0.195090 0.375331\nv 0.923880 0.000000 0.382684\nv 0.906127 -0.195090 0.375331\nv 0.853554 -0.382683 0.353554\nv 0.768178 -0.555570 0.318190\nv 0.653282 -0.707107 0.270598\nv 0.513280 -0.831470 0.212608\nv 0.353553 -0.923880 0.146447\nv 0.180240 -0.980785 0.074658\nv 0.162212 0.980785 0.108387\nv 0.318190 0.923880 0.212608\nv 0.461940 0.831470 0.308659\nv 0.587938 0.707107 0.392848\nv 0.691342 0.555570 0.461940\nv 0.768178 0.382683 0.513280\nv 0.815493 0.195090 0.544895\nv 0.831470 0.000000 0.555571\nv 0.815493 -0.195090 0.544895\nv 0.768178 -0.382683 0.513280\nv 0.691342 -0.555570 0.461940\nv 0.587938 -0.707107 0.392848\nv 0.461940 -0.831470 0.308659\nv 0.318190 -0.923880 0.212608\nv 0.162212 -0.980785 0.108387\nv 0.137950 0.980785 0.137950\nv 0.270598 0.923880 0.270599\nv 0.392848 0.831470 0.392848\nv 0.500000 0.707107 0.500000\nv 0.587938 0.555570 0.587938\nv 0.653282 0.382683 0.653282\nv 0.693520 0.195090 0.693520\nv 0.707107 0.000000 0.707107\nv 0.693520 -0.195090 0.693520\nv 0.653282 -0.382683 0.653282\nv 0.587938 -0.555570 0.587938\nv 0.500000 -0.707107 0.500000\nv 0.392848 -0.831470 0.392848\nv 0.270598 -0.923880 0.270598\nv 0.137950 -0.980785 0.137950\nv 0.108386 0.980785 0.162212\nv 0.212608 0.923880 0.318190\nv 0.308658 0.831470 0.461940\nv 0.392848 0.707107 0.587938\nv 0.461940 0.555570 0.691342\nv 0.513280 0.382683 0.768178\nv 0.544895 0.195090 0.815493\nv 0.555570 0.000000 0.831470\nv 0.544895 -0.195090 0.815493\nv 0.513280 -0.382683 0.768178\nv 0.461940 -0.555570 0.691342\nv 0.392848 -0.707107 0.587938\nv 0.308658 -0.831470 0.461940\nv 0.212608 -0.923880 0.318190\nv 0.108386 -0.980785 0.162212\nv 0.000000 -1.000000 0.000000\nv 0.074658 0.980785 0.180240\nv 0.146447 0.923880 0.353554\nv 0.212608 0.831470 0.513280\nv 0.270598 0.707107 0.653282\nv 0.318190 0.555570 0.768178\nv 0.353553 0.382683 0.853554\nv 0.375330 0.195090 0.906128\nv 0.382683 0.000000 0.923880\nv 0.375330 -0.195090 0.906128\nv 0.353553 -0.382683 0.853554\nv 0.318190 -0.555570 0.768178\nv 0.270598 -0.707107 0.653282\nv 0.212608 -0.831470 0.513280\nv 0.146447 -0.923880 0.353554\nv 0.074658 -0.980785 0.180240\nv 0.038060 0.980785 0.191342\nv 0.074658 0.923880 0.375331\nv 0.108386 0.831470 0.544896\nv 0.137950 0.707107 0.693520\nv 0.162212 0.555570 0.815493\nv 0.180240 0.382683 0.906128\nv 0.191342 0.195090 0.961940\nv 0.195090 0.000000 0.980786\nv 0.191342 -0.195090 0.961940\nv 0.180240 -0.382683 0.906128\nv 0.162212 -0.555570 0.815493\nv 0.137950 -0.707107 0.693520\nv 0.108386 -0.831470 0.544895\nv 0.074658 -0.923880 0.375331\nv 0.038060 -0.980785 0.191342\nv -0.000000 0.980785 0.195091\nv 0.000000 0.923880 0.382684\nv 0.000000 0.831470 0.555571\nv -0.000000 0.707107 0.707107\nv -0.000000 0.555570 0.831470\nv 0.000000 0.382683 0.923880\nv -0.000000 0.195090 0.980785\nv -0.000000 0.000000 1.000000\nv -0.000000 -0.195090 0.980785\nv 0.000000 -0.382683 0.923880\nv -0.000000 -0.555570 0.831470\nv -0.000000 -0.707107 0.707107\nv -0.000000 -0.831470 0.555570\nv 0.000000 -0.923880 0.382684\nv 0.000000 -0.980785 0.195091\nv -0.038060 0.980785 0.191342\nv -0.074658 0.923880 0.375331\nv -0.108386 0.831470 0.544896\nv -0.137950 0.707107 0.693520\nv -0.162212 0.555570 0.815493\nv -0.180240 0.382683 0.906128\nv -0.191342 0.195090 0.961940\nv -0.195090 0.000000 0.980786\nv -0.191342 -0.195090 0.961940\nv -0.180240 -0.382683 0.906128\nv -0.162212 -0.555570 0.815493\nv -0.137950 -0.707107 0.693520\nv -0.108386 -0.831470 0.544895\nv -0.074658 -0.923880 0.375331\nv -0.038060 -0.980785 0.191342\nv -0.074658 0.980785 0.180240\nv -0.146447 0.923880 0.353554\nv -0.212608 0.831470 0.513280\nv -0.270598 0.707107 0.653282\nv -0.318190 0.555570 0.768178\nv -0.353553 0.382683 0.853554\nv -0.375330 0.195090 0.906127\nv -0.382684 0.000000 0.923880\nv -0.375330 -0.195090 0.906127\nv -0.353553 -0.382683 0.853554\nv -0.318190 -0.555570 0.768178\nv -0.270598 -0.707107 0.653282\nv -0.212608 -0.831470 0.513280\nv -0.146447 -0.923880 0.353554\nv -0.074658 -0.980785 0.180240\nv -0.108386 0.980785 0.162212\nv -0.212608 0.923880 0.318190\nv -0.308658 0.831470 0.461940\nv -0.392847 0.707107 0.587938\nv -0.461940 0.555570 0.691342\nv -0.513280 0.382683 0.768178\nv -0.544895 0.195090 0.815493\nv -0.555570 0.000000 0.831470\nv -0.544895 -0.195090 0.815493\nv -0.513280 -0.382683 0.768178\nv -0.461940 -0.555570 0.691342\nv -0.392847 -0.707107 0.587938\nv -0.308658 -0.831470 0.461940\nv -0.212607 -0.923880 0.318190\nv -0.108386 -0.980785 0.162212\nv -0.000000 1.000000 0.000001\nv -0.137950 0.980785 0.137950\nv -0.270598 0.923880 0.270598\nv -0.392848 0.831470 0.392848\nv -0.500000 0.707107 0.500000\nv -0.587938 0.555570 0.587938\nv -0.653281 0.382683 0.653282\nv -0.693520 0.195090 0.693520\nv -0.707107 0.000000 0.707107\nv -0.693520 -0.195090 0.693520\nv -0.653281 -0.382683 0.653282\nv -0.587938 -0.555570 0.587938\nv -0.500000 -0.707107 0.500000\nv -0.392847 -0.831470 0.392848\nv -0.270598 -0.923880 0.270598\nv -0.137950 -0.980785 0.137950\nv -0.162212 0.980785 0.108387\nv -0.318190 0.923880 0.212608\nv -0.461940 0.831470 0.308659\nv -0.587938 0.707107 0.392848\nv -0.691342 0.555570 0.461940\nv -0.768178 0.382683 0.513280\nv -0.815493 0.195090 0.544895\nv -0.831470 0.000000 0.555570\nv -0.815493 -0.195090 0.544895\nv -0.768178 -0.382683 0.513280\nv -0.691342 -0.555570 0.461940\nv -0.587938 -0.707107 0.392848\nv -0.461940 -0.831470 0.308658\nv -0.318190 -0.923880 0.212608\nv -0.162212 -0.980785 0.108387\nv -0.180240 0.980785 0.074658\nv -0.353553 0.923880 0.146447\nv -0.513280 0.831470 0.212608\nv -0.653281 0.707107 0.270598\nv -0.768177 0.555570 0.318190\nv -0.853553 0.382683 0.353554\nv -0.906127 0.195090 0.375330\nv -0.923880 0.000000 0.382684\nv -0.906127 -0.195090 0.375330\nv -0.853553 -0.382683 0.353554\nv -0.768177 -0.555570 0.318190\nv -0.653281 -0.707107 0.270598\nv -0.513280 -0.831470 0.212608\nv -0.353553 -0.923880 0.146447\nv -0.180240 -0.980785 0.074658\nv -0.191342 0.980785 0.038061\nv -0.375330 0.923880 0.074658\nv -0.544895 0.831470 0.108387\nv -0.693520 0.707107 0.137950\nv -0.815493 0.555570 0.162212\nv -0.906127 0.382683 0.180240\nv -0.961939 0.195090 0.191342\nv -0.980785 0.000000 0.195090\nv -0.961939 -0.195090 0.191342\nv -0.906127 -0.382683 0.180240\nv -0.815493 -0.555570 0.162212\nv -0.693520 -0.707107 0.137950\nv -0.544895 -0.831470 0.108387\nv -0.375330 -0.923880 0.074658\nv -0.191342 -0.980785 0.038061\nv -0.195090 0.980785 0.000000\nv -0.382683 0.923880 0.000000\nv -0.555570 0.831470 0.000000\nv -0.707107 0.707107 0.000000\nv -0.831469 0.555570 0.000000\nv -0.923879 0.382683 0.000000\nv -0.980785 0.195090 0.000000\nv -1.000000 0.000000 0.000000\nv -0.980785 -0.195090 0.000000\nv -0.923879 -0.382683 0.000000\nv -0.831469 -0.555570 0.000000\nv -0.707107 -0.707107 0.000000\nv -0.555570 -0.831470 0.000000\nv -0.382683 -0.923880 0.000000\nv -0.195090 -0.980785 0.000000\nv -0.191342 0.980785 -0.038060\nv -0.375330 0.923880 -0.074658\nv -0.544895 0.831470 -0.108386\nv -0.693520 0.707107 -0.137949\nv -0.815493 0.555570 -0.162211\nv -0.906127 0.382683 -0.180240\nv -0.961939 0.195090 -0.191342\nv -0.980785 0.000000 -0.195090\nv -0.961939 -0.195090 -0.191342\nv -0.906127 -0.382683 -0.180240\nv -0.815493 -0.555570 -0.162211\nv -0.693520 -0.707107 -0.137949\nv -0.544895 -0.831470 -0.108386\nv -0.375330 -0.923880 -0.074658\nv -0.191342 -0.980785 -0.038060\nv -0.180240 0.980785 -0.074658\nv -0.353553 0.923880 -0.146446\nv -0.513280 0.831470 -0.212607\nv -0.653281 0.707107 -0.270598\nv -0.768177 0.555570 -0.318189\nv -0.853553 0.382683 -0.353553\nv -0.906127 0.195090 -0.375330\nv -0.923879 0.000000 -0.382683\nv -0.906127 -0.195090 -0.375330\nv -0.853553 -0.382683 -0.353553\nv -0.768177 -0.555570 -0.318189\nv -0.653281 -0.707107 -0.270598\nv -0.513280 -0.831470 -0.212607\nv -0.353553 -0.923880 -0.146446\nv -0.180240 -0.980785 -0.074657\nv -0.162212 0.980785 -0.108386\nv -0.318190 0.923880 -0.212607\nv -0.461940 0.831470 -0.308658\nv -0.587938 0.707107 -0.392847\nv -0.691341 0.555570 -0.461939\nv -0.768178 0.382683 -0.513280\nv -0.815493 0.195090 -0.544895\nv -0.831469 0.000000 -0.555570\nv -0.815493 -0.195090 -0.544895\nv -0.768178 -0.382683 -0.513280\nv -0.691341 -0.555570 -0.461939\nv -0.587938 -0.707107 -0.392847\nv -0.461940 -0.831470 -0.308658\nv -0.318189 -0.923880 -0.212607\nv -0.162212 -0.980785 -0.108386\nv -0.137950 0.980785 -0.137949\nv -0.270598 0.923880 -0.270598\nv -0.392847 0.831470 -0.392847\nv -0.500000 0.707107 -0.500000\nv -0.587937 0.555570 -0.587937\nv -0.653281 0.382683 -0.653281\nv -0.693519 0.195090 -0.693519\nv -0.707106 0.000000 -0.707106\nv -0.693519 -0.195090 -0.693519\nv -0.653281 -0.382683 -0.653281\nv -0.587937 -0.555570 -0.587937\nv -0.500000 -0.707107 -0.500000\nv -0.392847 -0.831470 -0.392847\nv -0.270598 -0.923880 -0.270598\nv -0.137950 -0.980785 -0.137949\nv -0.108386 0.980785 -0.162211\nv -0.212607 0.923880 -0.318189\nv -0.308658 0.831470 -0.461939\nv -0.392847 0.707107 -0.587937\nv -0.461939 0.555570 -0.691341\nv -0.513280 0.382683 -0.768177\nv -0.544895 0.195090 -0.815492\nv -0.555570 0.000000 -0.831469\nv -0.544895 -0.195090 -0.815492\nv -0.513280 -0.382683 -0.768177\nv -0.461939 -0.555570 -0.691341\nv -0.392847 -0.707107 -0.587937\nv -0.308658 -0.831470 -0.461939\nv -0.212607 -0.923880 -0.318189\nv -0.108386 -0.980785 -0.162211\nv -0.074658 0.980785 -0.180240\nv -0.146447 0.923880 -0.353553\nv -0.212607 0.831470 -0.513280\nv -0.270598 0.707107 -0.653281\nv -0.318189 0.555570 -0.768177\nv -0.353553 0.382683 -0.853553\nv -0.375330 0.195090 -0.906127\nv -0.382683 0.000000 -0.923879\nv -0.375330 -0.195090 -0.906127\nv -0.353553 -0.382683 -0.853553\nv -0.318189 -0.555570 -0.768177\nv -0.270598 -0.707107 -0.653281\nv -0.212607 -0.831470 -0.513279\nv -0.146446 -0.923880 -0.353553\nv -0.074658 -0.980785 -0.180240\nv -0.038060 0.980785 -0.191342\nv -0.074658 0.923880 -0.375330\nv -0.108386 0.831470 -0.544895\nv -0.137950 0.707107 -0.693520\nv -0.162211 0.555570 -0.815492\nv -0.180240 0.382683 -0.906127\nv -0.191341 0.195090 -0.961939\nv -0.195090 0.000000 -0.980785\nv -0.191341 -0.195090 -0.961939\nv -0.180240 -0.382683 -0.906127\nv -0.162211 -0.555570 -0.815492\nv -0.137950 -0.707107 -0.693520\nv -0.108386 -0.831470 -0.544895\nv -0.074658 -0.923880 -0.375330\nv -0.038060 -0.980785 -0.191341\nv 0.000000 -0.382683 -0.923879\nv 0.000000 -0.555570 -0.831469\nv 0.000000 -0.707107 -0.707106\nv 0.000000 -0.923880 -0.382683\nv 0.000000 -0.980785 -0.195090\nvt 0.750000 0.187500\nvt 0.750000 0.250000\nvt 0.718750 0.250000\nvt 0.718750 0.187500\nvt 0.750000 0.625000\nvt 0.750000 0.687500\nvt 0.718750 0.687500\nvt 0.718750 0.625000\nvt 0.750000 0.125000\nvt 0.718750 0.125000\nvt 0.750000 0.562500\nvt 0.718750 0.562500\nvt 0.750000 0.062500\nvt 0.718750 0.062500\nvt 0.750000 0.500000\nvt 0.718750 0.500000\nvt 0.750000 0.937500\nvt 0.734375 1.000000\nvt 0.718750 0.937500\nvt 0.734375 0.000000\nvt 0.750000 0.437500\nvt 0.718750 0.437500\nvt 0.750000 0.875000\nvt 0.718750 0.875000\nvt 0.750000 0.375000\nvt 0.718750 0.375000\nvt 0.750000 0.812500\nvt 0.718750 0.812500\nvt 0.750000 0.312500\nvt 0.718750 0.312500\nvt 0.750000 0.750000\nvt 0.718750 0.750000\nvt 0.687500 0.812500\nvt 0.687500 0.750000\nvt 0.687500 0.312500\nvt 0.687500 0.250000\nvt 0.687500 0.687500\nvt 0.687500 0.187500\nvt 0.687500 0.625000\nvt 0.687500 0.125000\nvt 0.687500 0.562500\nvt 0.687500 0.062500\nvt 0.687500 0.500000\nvt 0.703125 1.000000\nvt 0.687500 0.937500\nvt 0.703125 0.000000\nvt 0.687500 0.437500\nvt 0.687500 0.875000\nvt 0.687500 0.375000\nvt 0.656250 0.562500\nvt 0.656250 0.500000\nvt 0.671875 1.000000\nvt 0.656250 0.937500\nvt 0.671875 0.000000\nvt 0.656250 0.062500\nvt 0.656250 0.437500\nvt 0.656250 0.875000\nvt 0.656250 0.375000\nvt 0.656250 0.812500\nvt 0.656250 0.312500\nvt 0.656250 0.750000\nvt 0.656250 0.250000\nvt 0.656250 0.687500\nvt 0.656250 0.187500\nvt 0.656250 0.625000\nvt 0.656250 0.125000\nvt 0.625000 0.312500\nvt 0.625000 0.250000\nvt 0.625000 0.750000\nvt 0.625000 0.687500\nvt 0.625000 0.187500\nvt 0.625000 0.625000\nvt 0.625000 0.125000\nvt 0.625000 0.562500\nvt 0.625000 0.062500\nvt 0.625000 0.500000\nvt 0.640625 1.000000\nvt 0.625000 0.937500\nvt 0.640625 0.000000\nvt 0.625000 0.437500\nvt 0.625000 0.875000\nvt 0.625000 0.375000\nvt 0.625000 0.812500\nvt 0.609375 0.000000\nvt 0.593750 0.062500\nvt 0.593750 0.500000\nvt 0.593750 0.437500\nvt 0.593750 0.937500\nvt 0.593750 0.875000\nvt 0.593750 0.375000\nvt 0.593750 0.812500\nvt 0.593750 0.312500\nvt 0.593750 0.750000\nvt 0.593750 0.250000\nvt 0.593750 0.687500\nvt 0.593750 0.187500\nvt 0.593750 0.625000\nvt 0.593750 0.125000\nvt 0.593750 0.562500\nvt 0.609375 1.000000\nvt 0.562500 0.250000\nvt 0.562500 0.187500\nvt 0.562500 0.687500\nvt 0.562500 0.625000\nvt 0.562500 0.125000\nvt 0.562500 0.562500\nvt 0.562500 0.062500\nvt 0.562500 0.500000\nvt 0.578125 1.000000\nvt 0.562500 0.937500\nvt 0.578125 0.000000\nvt 0.562500 0.437500\nvt 0.562500 0.875000\nvt 0.562500 0.375000\nvt 0.562500 0.812500\nvt 0.562500 0.312500\nvt 0.562500 0.750000\nvt 0.531250 0.937500\nvt 0.531250 0.875000\nvt 0.531250 0.437500\nvt 0.531250 0.375000\nvt 0.531250 0.812500\nvt 0.531250 0.312500\nvt 0.531250 0.750000\nvt 0.531250 0.250000\nvt 0.531250 0.687500\nvt 0.531250 0.187500\nvt 0.531250 0.625000\nvt 0.531250 0.125000\nvt 0.531250 0.562500\nvt 0.531250 0.062500\nvt 0.531250 0.500000\nvt 0.546875 1.000000\nvt 0.546875 0.000000\nvt 0.500000 0.687500\nvt 0.500000 0.625000\nvt 0.500000 0.187500\nvt 0.500000 0.125000\nvt 0.500000 0.562500\nvt 0.500000 0.062500\nvt 0.500000 0.500000\nvt 0.515625 1.000000\nvt 0.500000 0.937500\nvt 0.515625 0.000000\nvt 0.500000 0.437500\nvt 0.500000 0.875000\nvt 0.500000 0.375000\nvt 0.500000 0.812500\nvt 0.500000 0.312500\nvt 0.500000 0.750000\nvt 0.500000 0.250000\nvt 0.468750 0.437500\nvt 0.468750 0.375000\nvt 0.468750 0.875000\nvt 0.468750 0.812500\nvt 0.468750 0.312500\nvt 0.468750 0.750000\nvt 0.468750 0.250000\nvt 0.468750 0.687500\nvt 0.468750 0.187500\nvt 0.468750 0.625000\nvt 0.468750 0.125000\nvt 0.468750 0.562500\nvt 0.468750 0.062500\nvt 0.468750 0.500000\nvt 0.484374 1.000000\nvt 0.468750 0.937500\nvt 0.484375 0.000000\nvt 0.437500 0.187500\nvt 0.437500 0.125000\nvt 0.437500 0.625000\nvt 0.437500 0.562500\nvt 0.437500 0.062500\nvt 0.437500 0.500000\nvt 0.453124 1.000000\nvt 0.437500 0.937500\nvt 0.453125 0.000000\nvt 0.437500 0.437500\nvt 0.437500 0.875000\nvt 0.437500 0.375000\nvt 0.437500 0.812500\nvt 0.437500 0.312500\nvt 0.437500 0.750000\nvt 0.437500 0.250000\nvt 0.437500 0.687500\nvt 0.406250 0.875000\nvt 0.406250 0.812500\nvt 0.406250 0.375000\nvt 0.406250 0.312500\nvt 0.406250 0.750000\nvt 0.406250 0.250000\nvt 0.406250 0.687500\nvt 0.406250 0.187500\nvt 0.406250 0.625000\nvt 0.406250 0.125000\nvt 0.406250 0.562500\nvt 0.406250 0.062500\nvt 0.406250 0.500000\nvt 0.421874 1.000000\nvt 0.406250 0.937500\nvt 0.421875 0.000000\nvt 0.406250 0.437500\nvt 0.375000 0.625000\nvt 0.375000 0.562500\nvt 0.375000 0.125000\nvt 0.375000 0.062500\nvt 0.375000 0.500000\nvt 0.390625 1.000000\nvt 0.375000 0.937500\nvt 0.390625 0.000000\nvt 0.375000 0.437500\nvt 0.375000 0.875000\nvt 0.375000 0.375000\nvt 0.375000 0.812500\nvt 0.375000 0.312500\nvt 0.375000 0.750000\nvt 0.375000 0.250000\nvt 0.375000 0.687500\nvt 0.375000 0.187500\nvt 0.343750 0.375000\nvt 0.343750 0.312500\nvt 0.343750 0.812500\nvt 0.343750 0.750000\nvt 0.343750 0.250000\nvt 0.343750 0.687500\nvt 0.343750 0.187500\nvt 0.343750 0.625000\nvt 0.343750 0.125000\nvt 0.343750 0.562500\nvt 0.343750 0.062500\nvt 0.343750 0.500000\nvt 0.359375 1.000000\nvt 0.343750 0.937500\nvt 0.359375 0.000000\nvt 0.343750 0.437500\nvt 0.343750 0.875000\nvt 0.312500 0.125000\nvt 0.312500 0.062500\nvt 0.312500 0.562500\nvt 0.312500 0.500000\nvt 0.328125 1.000000\nvt 0.312500 0.937500\nvt 0.328125 0.000000\nvt 0.312500 0.437500\nvt 0.312500 0.875000\nvt 0.312500 0.375000\nvt 0.312500 0.812500\nvt 0.312500 0.312500\nvt 0.312500 0.750000\nvt 0.312500 0.250000\nvt 0.312500 0.687500\nvt 0.312500 0.187500\nvt 0.312500 0.625000\nvt 0.281250 0.312500\nvt 0.281250 0.250000\nvt 0.281250 0.750000\nvt 0.281250 0.687500\nvt 0.281250 0.187500\nvt 0.281250 0.625000\nvt 0.281250 0.125000\nvt 0.281250 0.562500\nvt 0.281250 0.062500\nvt 0.281250 0.500000\nvt 0.296875 1.000000\nvt 0.281250 0.937500\nvt 0.296875 0.000000\nvt 0.281250 0.437500\nvt 0.281250 0.875000\nvt 0.281250 0.375000\nvt 0.281250 0.812500\nvt 0.265625 1.000000\nvt 0.250000 0.937500\nvt 0.265625 0.000000\nvt 0.250000 0.062500\nvt 0.250000 0.500000\nvt 0.250000 0.437500\nvt 0.250000 0.875000\nvt 0.250000 0.375000\nvt 0.250000 0.812500\nvt 0.250000 0.312500\nvt 0.250000 0.750000\nvt 0.250000 0.250000\nvt 0.250000 0.687500\nvt 0.250000 0.187500\nvt 0.250000 0.625000\nvt 0.250000 0.125000\nvt 0.250000 0.562500\nvt 0.218750 0.750000\nvt 0.218750 0.687500\nvt 0.218750 0.250000\nvt 0.218750 0.187500\nvt 0.218750 0.625000\nvt 0.218750 0.125000\nvt 0.218750 0.562500\nvt 0.218750 0.062500\nvt 0.218750 0.500000\nvt 0.234375 1.000000\nvt 0.218750 0.937500\nvt 0.234375 0.000000\nvt 0.218750 0.437500\nvt 0.218750 0.875000\nvt 0.218750 0.375000\nvt 0.218750 0.812500\nvt 0.218750 0.312500\nvt 0.187500 0.500000\nvt 0.187500 0.437500\nvt 0.187500 0.937500\nvt 0.187500 0.875000\nvt 0.187500 0.375000\nvt 0.187500 0.812500\nvt 0.187500 0.312500\nvt 0.187500 0.750000\nvt 0.187500 0.250000\nvt 0.187500 0.687500\nvt 0.187500 0.187500\nvt 0.187500 0.625000\nvt 0.187500 0.125000\nvt 0.187500 0.562500\nvt 0.187500 0.062500\nvt 0.203125 1.000000\nvt 0.203125 0.000000\nvt 0.156250 0.250000\nvt 0.156250 0.187500\nvt 0.156250 0.687500\nvt 0.156250 0.625000\nvt 0.156250 0.125000\nvt 0.156250 0.562500\nvt 0.156250 0.062500\nvt 0.156250 0.500000\nvt 0.171875 1.000000\nvt 0.156250 0.937500\nvt 0.171875 0.000000\nvt 0.156250 0.437500\nvt 0.156250 0.875000\nvt 0.156250 0.375000\nvt 0.156250 0.812500\nvt 0.156250 0.312500\nvt 0.156250 0.750000\nvt 0.125000 0.937500\nvt 0.125000 0.875000\nvt 0.125000 0.437500\nvt 0.125000 0.375000\nvt 0.125000 0.812500\nvt 0.125000 0.312500\nvt 0.125000 0.750000\nvt 0.125000 0.250000\nvt 0.125000 0.687500\nvt 0.125000 0.187500\nvt 0.125000 0.625000\nvt 0.125000 0.125000\nvt 0.125000 0.562500\nvt 0.125000 0.062500\nvt 0.125000 0.500000\nvt 0.140625 1.000000\nvt 0.140625 0.000000\nvt 0.093750 0.687500\nvt 0.093750 0.625000\nvt 0.093750 0.187500\nvt 0.093750 0.125000\nvt 0.093750 0.562500\nvt 0.093750 0.062500\nvt 0.093750 0.500000\nvt 0.109375 1.000000\nvt 0.093750 0.937500\nvt 0.109375 0.000000\nvt 0.093750 0.437500\nvt 0.093750 0.875000\nvt 0.093750 0.375000\nvt 0.093750 0.812500\nvt 0.093750 0.312500\nvt 0.093750 0.750000\nvt 0.093750 0.250000\nvt 0.062500 0.437500\nvt 0.062500 0.375000\nvt 0.062500 0.875000\nvt 0.062500 0.812500\nvt 0.062500 0.312500\nvt 0.062500 0.750000\nvt 0.062500 0.250000\nvt 0.062500 0.687500\nvt 0.062500 0.187500\nvt 0.062500 0.625000\nvt 0.062500 0.125000\nvt 0.062500 0.562500\nvt 0.062500 0.062500\nvt 0.062500 0.500000\nvt 0.078125 1.000000\nvt 0.062500 0.937500\nvt 0.078125 0.000000\nvt 0.031250 0.187500\nvt 0.031250 0.125000\nvt 0.031250 0.625000\nvt 0.031250 0.562500\nvt 0.031250 0.062500\nvt 0.031250 0.500000\nvt 0.046875 1.000000\nvt 0.031250 0.937500\nvt 0.046875 0.000000\nvt 0.031250 0.437500\nvt 0.031250 0.875000\nvt 0.031250 0.375000\nvt 0.031250 0.812500\nvt 0.031250 0.312500\nvt 0.031250 0.750000\nvt 0.031250 0.250000\nvt 0.031250 0.687500\nvt 0.000000 0.375000\nvt 0.000000 0.312500\nvt 0.000000 0.812500\nvt 0.000000 0.750000\nvt 0.000000 0.250000\nvt 0.000000 0.687500\nvt 0.000000 0.187500\nvt 0.000000 0.625000\nvt 0.000000 0.125000\nvt 0.000000 0.562500\nvt 0.000000 0.062500\nvt 0.000000 0.500000\nvt 0.015625 1.000000\nvt 0.000000 0.937500\nvt 0.015625 0.000000\nvt 0.000000 0.437500\nvt 0.000000 0.875000\nvt 1.000000 0.062500\nvt 1.000000 0.125000\nvt 0.968750 0.125000\nvt 0.968750 0.062500\nvt 1.000000 0.500000\nvt 1.000000 0.562500\nvt 0.968750 0.562500\nvt 0.968750 0.500000\nvt 1.000000 0.937500\nvt 0.984375 1.000000\nvt 0.968750 0.937500\nvt 0.984375 0.000000\nvt 1.000000 0.437500\nvt 0.968750 0.437500\nvt 1.000000 0.875000\nvt 0.968750 0.875000\nvt 1.000000 0.375000\nvt 0.968750 0.375000\nvt 1.000000 0.812500\nvt 0.968750 0.812500\nvt 1.000000 0.312500\nvt 0.968750 0.312500\nvt 1.000000 0.750000\nvt 0.968750 0.750000\nvt 1.000000 0.250000\nvt 0.968750 0.250000\nvt 1.000000 0.687500\nvt 0.968750 0.687500\nvt 1.000000 0.187500\nvt 0.968750 0.187500\nvt 1.000000 0.625000\nvt 0.968750 0.625000\nvt 0.937500 0.812500\nvt 0.937500 0.750000\nvt 0.937500 0.312500\nvt 0.937500 0.250000\nvt 0.937500 0.687500\nvt 0.937500 0.187500\nvt 0.937500 0.625000\nvt 0.937500 0.125000\nvt 0.937500 0.562500\nvt 0.937500 0.062500\nvt 0.937500 0.500000\nvt 0.953125 1.000000\nvt 0.937500 0.937500\nvt 0.953125 0.000000\nvt 0.937500 0.437500\nvt 0.937500 0.875000\nvt 0.937500 0.375000\nvt 0.906250 0.562500\nvt 0.906250 0.500000\nvt 0.921875 1.000000\nvt 0.906250 0.937500\nvt 0.921875 0.000000\nvt 0.906250 0.062500\nvt 0.906250 0.437500\nvt 0.906250 0.875000\nvt 0.906250 0.375000\nvt 0.906250 0.812500\nvt 0.906250 0.312500\nvt 0.906250 0.750000\nvt 0.906250 0.250000\nvt 0.906250 0.687500\nvt 0.906250 0.187500\nvt 0.906250 0.625000\nvt 0.906250 0.125000\nvt 0.875000 0.312500\nvt 0.875000 0.250000\nvt 0.875000 0.750000\nvt 0.875000 0.687500\nvt 0.875000 0.187500\nvt 0.875000 0.625000\nvt 0.875000 0.125000\nvt 0.875000 0.562500\nvt 0.875000 0.062500\nvt 0.875000 0.500000\nvt 0.890625 1.000000\nvt 0.875000 0.937500\nvt 0.890625 0.000000\nvt 0.875000 0.437500\nvt 0.875000 0.875000\nvt 0.875000 0.375000\nvt 0.875000 0.812500\nvt 0.859375 1.000000\nvt 0.843750 0.937500\nvt 0.859375 0.000000\nvt 0.843750 0.062500\nvt 0.843750 0.500000\nvt 0.843750 0.437500\nvt 0.843750 0.875000\nvt 0.843750 0.375000\nvt 0.843750 0.812500\nvt 0.843750 0.312500\nvt 0.843750 0.750000\nvt 0.843750 0.250000\nvt 0.843750 0.687500\nvt 0.843750 0.187500\nvt 0.843750 0.625000\nvt 0.843750 0.125000\nvt 0.843750 0.562500\nvt 0.812500 0.750000\nvt 0.812500 0.687500\nvt 0.812500 0.250000\nvt 0.812500 0.187500\nvt 0.812500 0.625000\nvt 0.812500 0.125000\nvt 0.812500 0.562500\nvt 0.812500 0.062500\nvt 0.812500 0.500000\nvt 0.828125 1.000000\nvt 0.812500 0.937500\nvt 0.828125 0.000000\nvt 0.812500 0.437500\nvt 0.812500 0.875000\nvt 0.812500 0.375000\nvt 0.812500 0.812500\nvt 0.812500 0.312500\nvt 0.781250 0.500000\nvt 0.781250 0.437500\nvt 0.781250 0.937500\nvt 0.781250 0.875000\nvt 0.781250 0.375000\nvt 0.781250 0.812500\nvt 0.781250 0.312500\nvt 0.781250 0.750000\nvt 0.781250 0.250000\nvt 0.781250 0.687500\nvt 0.781250 0.187500\nvt 0.781250 0.625000\nvt 0.781250 0.125000\nvt 0.781250 0.562500\nvt 0.781250 0.062500\nvt 0.796875 1.000000\nvt 0.796875 0.000000\nvt 0.765625 1.000000\nvt 0.765625 0.000000\nvn 0.0624 -0.7715 -0.6332\nvn 0.0865 0.4696 -0.8786\nvn 0.0464 -0.8810 -0.4709\nvn 0.0938 0.2890 -0.9527\nvn 0.0286 -0.9565 -0.2902\nvn 0.0975 0.0975 -0.9904\nvn 0.0097 0.9951 -0.0980\nvn 0.0097 -0.9951 -0.0980\nvn 0.0976 -0.0975 -0.9904\nvn 0.0286 0.9565 -0.2902\nvn 0.0938 -0.2890 -0.9527\nvn 0.0464 0.8810 -0.4709\nvn 0.0865 -0.4696 -0.8786\nvn 0.0624 0.7715 -0.6332\nvn 0.0759 -0.6326 -0.7708\nvn 0.0759 0.6326 -0.7708\nvn 0.1847 0.7715 -0.6088\nvn 0.2248 -0.6326 -0.7412\nvn 0.2248 0.6326 -0.7412\nvn 0.1847 -0.7715 -0.6088\nvn 0.2563 0.4696 -0.8448\nvn 0.1374 -0.8810 -0.4528\nvn 0.2779 0.2890 -0.9161\nvn 0.0846 -0.9565 -0.2790\nvn 0.2889 0.0975 -0.9524\nvn 0.0286 0.9951 -0.0942\nvn 0.0286 -0.9951 -0.0942\nvn 0.2889 -0.0975 -0.9524\nvn 0.0846 0.9565 -0.2790\nvn 0.2779 -0.2890 -0.9161\nvn 0.1374 0.8810 -0.4528\nvn 0.2563 -0.4696 -0.8448\nvn 0.4691 0.0975 -0.8777\nvn 0.0464 0.9951 -0.0869\nvn 0.0464 -0.9951 -0.0869\nvn 0.4691 -0.0975 -0.8777\nvn 0.1374 0.9565 -0.2571\nvn 0.4513 -0.2890 -0.8443\nvn 0.2230 0.8810 -0.4173\nvn 0.4162 -0.4696 -0.7786\nvn 0.2999 0.7715 -0.5611\nvn 0.3651 -0.6326 -0.6831\nvn 0.3651 0.6326 -0.6831\nvn 0.2999 -0.7715 -0.5611\nvn 0.4162 0.4696 -0.7786\nvn 0.2230 -0.8810 -0.4173\nvn 0.4513 0.2890 -0.8443\nvn 0.1374 -0.9565 -0.2571\nvn 0.4913 -0.6326 -0.5987\nvn 0.4913 0.6326 -0.5987\nvn 0.4036 -0.7715 -0.4918\nvn 0.5601 0.4696 -0.6825\nvn 0.3002 -0.8810 -0.3658\nvn 0.6073 0.2890 -0.7400\nvn 0.1850 -0.9565 -0.2254\nvn 0.6314 0.0976 -0.7693\nvn 0.0625 0.9951 -0.0761\nvn 0.0625 -0.9951 -0.0761\nvn 0.6314 -0.0976 -0.7693\nvn 0.1850 0.9565 -0.2254\nvn 0.6073 -0.2890 -0.7400\nvn 0.3002 0.8810 -0.3658\nvn 0.5601 -0.4696 -0.6825\nvn 0.4036 0.7715 -0.4918\nvn 0.0761 -0.9951 -0.0625\nvn 0.7693 -0.0975 -0.6314\nvn 0.2254 0.9565 -0.1850\nvn 0.7400 -0.2890 -0.6073\nvn 0.3658 0.8810 -0.3002\nvn 0.6825 -0.4696 -0.5601\nvn 0.4918 0.7715 -0.4036\nvn 0.5987 -0.6326 -0.4913\nvn 0.5987 0.6326 -0.4913\nvn 0.4918 -0.7715 -0.4036\nvn 0.6825 0.4696 -0.5601\nvn 0.3658 -0.8810 -0.3002\nvn 0.7400 0.2890 -0.6073\nvn 0.2254 -0.9565 -0.1850\nvn 0.7693 0.0975 -0.6314\nvn 0.0761 0.9951 -0.0625\nvn 0.5611 -0.7715 -0.2999\nvn 0.7786 0.4696 -0.4162\nvn 0.4173 -0.8810 -0.2231\nvn 0.8443 0.2890 -0.4513\nvn 0.2571 -0.9565 -0.1374\nvn 0.8777 0.0976 -0.4691\nvn 0.0869 0.9951 -0.0464\nvn 0.0869 -0.9951 -0.0464\nvn 0.8777 -0.0976 -0.4691\nvn 0.2571 0.9565 -0.1374\nvn 0.8443 -0.2890 -0.4513\nvn 0.4173 0.8810 -0.2231\nvn 0.7786 -0.4696 -0.4162\nvn 0.5611 0.7715 -0.2999\nvn 0.6831 -0.6326 -0.3651\nvn 0.6831 0.6326 -0.3651\nvn 0.2790 0.9565 -0.0846\nvn 0.9161 -0.2890 -0.2779\nvn 0.4528 0.8810 -0.1374\nvn 0.8448 -0.4696 -0.2563\nvn 0.6088 0.7715 -0.1847\nvn 0.7412 -0.6326 -0.2248\nvn 0.7412 0.6326 -0.2248\nvn 0.6088 -0.7715 -0.1847\nvn 0.8448 0.4696 -0.2563\nvn 0.4528 -0.8810 -0.1374\nvn 0.9161 0.2890 -0.2779\nvn 0.2790 -0.9565 -0.0846\nvn 0.9524 0.0976 -0.2889\nvn 0.0942 0.9951 -0.0286\nvn 0.0942 -0.9951 -0.0286\nvn 0.9524 -0.0976 -0.2889\nvn 0.8786 0.4696 -0.0865\nvn 0.4709 -0.8810 -0.0464\nvn 0.9527 0.2890 -0.0938\nvn 0.2902 -0.9565 -0.0286\nvn 0.9904 0.0976 -0.0975\nvn 0.0980 0.9951 -0.0097\nvn 0.0980 -0.9951 -0.0097\nvn 0.9904 -0.0976 -0.0975\nvn 0.2902 0.9565 -0.0286\nvn 0.9527 -0.2890 -0.0938\nvn 0.4709 0.8810 -0.0464\nvn 0.8786 -0.4696 -0.0865\nvn 0.6332 0.7715 -0.0624\nvn 0.7708 -0.6326 -0.0759\nvn 0.7708 0.6326 -0.0759\nvn 0.6332 -0.7715 -0.0624\nvn 0.9527 -0.2890 0.0938\nvn 0.4709 0.8810 0.0464\nvn 0.8786 -0.4696 0.0865\nvn 0.6332 0.7715 0.0624\nvn 0.7708 -0.6326 0.0759\nvn 0.7708 0.6326 0.0759\nvn 0.6332 -0.7715 0.0624\nvn 0.8786 0.4696 0.0865\nvn 0.4709 -0.8810 0.0464\nvn 0.9527 0.2890 0.0938\nvn 0.2902 -0.9565 0.0286\nvn 0.9904 0.0976 0.0975\nvn 0.0980 0.9951 0.0097\nvn 0.0980 -0.9951 0.0097\nvn 0.9904 -0.0976 0.0975\nvn 0.2902 0.9565 0.0286\nvn 0.4528 -0.8810 0.1374\nvn 0.9161 0.2890 0.2779\nvn 0.2790 -0.9565 0.0846\nvn 0.9524 0.0976 0.2889\nvn 0.0942 0.9951 0.0286\nvn 0.0942 -0.9951 0.0286\nvn 0.9524 -0.0976 0.2889\nvn 0.2790 0.9565 0.0846\nvn 0.9161 -0.2890 0.2779\nvn 0.4528 0.8810 0.1374\nvn 0.8448 -0.4696 0.2563\nvn 0.6088 0.7715 0.1847\nvn 0.7412 -0.6326 0.2248\nvn 0.7412 0.6326 0.2248\nvn 0.6088 -0.7715 0.1847\nvn 0.8448 0.4696 0.2563\nvn 0.4173 0.8810 0.2231\nvn 0.7786 -0.4696 0.4162\nvn 0.5611 0.7715 0.2999\nvn 0.6831 -0.6326 0.3651\nvn 0.6831 0.6326 0.3651\nvn 0.5611 -0.7715 0.2999\nvn 0.7786 0.4696 0.4162\nvn 0.4173 -0.8810 0.2231\nvn 0.8443 0.2890 0.4513\nvn 0.2571 -0.9565 0.1374\nvn 0.8777 0.0976 0.4691\nvn 0.0869 0.9951 0.0464\nvn 0.0869 -0.9951 0.0464\nvn 0.8777 -0.0976 0.4691\nvn 0.2571 0.9565 0.1374\nvn 0.8443 -0.2890 0.4513\nvn 0.7400 0.2890 0.6073\nvn 0.2254 -0.9565 0.1850\nvn 0.7693 0.0976 0.6314\nvn 0.0761 0.9951 0.0625\nvn 0.0761 -0.9951 0.0625\nvn 0.7693 -0.0976 0.6314\nvn 0.2254 0.9565 0.1850\nvn 0.7400 -0.2890 0.6073\nvn 0.3658 0.8810 0.3002\nvn 0.6825 -0.4696 0.5601\nvn 0.4918 0.7715 0.4036\nvn 0.5987 -0.6326 0.4913\nvn 0.5987 0.6326 0.4913\nvn 0.4918 -0.7715 0.4036\nvn 0.6825 0.4696 0.5601\nvn 0.3658 -0.8810 0.3002\nvn 0.5601 -0.4696 0.6825\nvn 0.4036 0.7715 0.4918\nvn 0.4913 -0.6326 0.5987\nvn 0.4913 0.6326 0.5987\nvn 0.4036 -0.7715 0.4918\nvn 0.5601 0.4696 0.6825\nvn 0.3002 -0.8810 0.3658\nvn 0.6073 0.2890 0.7400\nvn 0.1850 -0.9565 0.2254\nvn 0.6314 0.0976 0.7693\nvn 0.0625 0.9951 0.0761\nvn 0.0625 -0.9951 0.0761\nvn 0.6314 -0.0976 0.7693\nvn 0.1850 0.9565 0.2254\nvn 0.6073 -0.2890 0.7400\nvn 0.3002 0.8810 0.3658\nvn 0.1374 -0.9565 0.2571\nvn 0.4691 0.0976 0.8777\nvn 0.0464 0.9951 0.0869\nvn 0.0464 -0.9951 0.0869\nvn 0.4691 -0.0976 0.8777\nvn 0.1374 0.9565 0.2571\nvn 0.4513 -0.2890 0.8443\nvn 0.2230 0.8810 0.4173\nvn 0.4162 -0.4696 0.7786\nvn 0.2999 0.7715 0.5611\nvn 0.3651 -0.6326 0.6831\nvn 0.3651 0.6326 0.6831\nvn 0.2999 -0.7715 0.5611\nvn 0.4162 0.4696 0.7786\nvn 0.2230 -0.8810 0.4173\nvn 0.4513 0.2890 0.8443\nvn 0.2248 -0.6326 0.7412\nvn 0.2248 0.6326 0.7412\nvn 0.1847 -0.7715 0.6088\nvn 0.2563 0.4696 0.8448\nvn 0.1374 -0.8810 0.4528\nvn 0.2779 0.2890 0.9161\nvn 0.0846 -0.9565 0.2790\nvn 0.2889 0.0976 0.9524\nvn 0.0286 0.9951 0.0942\nvn 0.0286 -0.9951 0.0942\nvn 0.2889 -0.0976 0.9524\nvn 0.0846 0.9565 0.2790\nvn 0.2779 -0.2890 0.9161\nvn 0.1374 0.8810 0.4528\nvn 0.2563 -0.4696 0.8448\nvn 0.1847 0.7715 0.6088\nvn 0.0097 0.9951 0.0980\nvn 0.0097 -0.9951 0.0980\nvn 0.0975 -0.0976 0.9904\nvn 0.0286 0.9565 0.2902\nvn 0.0938 -0.2890 0.9527\nvn 0.0464 0.8810 0.4709\nvn 0.0865 -0.4696 0.8786\nvn 0.0624 0.7715 0.6332\nvn 0.0759 -0.6326 0.7708\nvn 0.0759 0.6326 0.7708\nvn 0.0624 -0.7715 0.6332\nvn 0.0865 0.4696 0.8786\nvn 0.0464 -0.8810 0.4709\nvn 0.0938 0.2890 0.9527\nvn 0.0286 -0.9565 0.2902\nvn 0.0975 0.0976 0.9904\nvn -0.0759 0.6326 0.7708\nvn -0.0624 -0.7715 0.6332\nvn -0.0865 0.4696 0.8786\nvn -0.0464 -0.8810 0.4709\nvn -0.0938 0.2890 0.9527\nvn -0.0286 -0.9565 0.2902\nvn -0.0976 0.0976 0.9904\nvn -0.0097 0.9951 0.0980\nvn -0.0097 -0.9951 0.0980\nvn -0.0976 -0.0976 0.9904\nvn -0.0286 0.9565 0.2902\nvn -0.0938 -0.2890 0.9527\nvn -0.0464 0.8810 0.4709\nvn -0.0865 -0.4696 0.8786\nvn -0.0624 0.7715 0.6332\nvn -0.0759 -0.6326 0.7708\nvn -0.2889 -0.0976 0.9524\nvn -0.0846 0.9565 0.2790\nvn -0.2779 -0.2890 0.9161\nvn -0.1374 0.8810 0.4528\nvn -0.2563 -0.4696 0.8448\nvn -0.1847 0.7715 0.6088\nvn -0.2248 -0.6326 0.7412\nvn -0.2248 0.6326 0.7412\nvn -0.1847 -0.7715 0.6088\nvn -0.2563 0.4696 0.8448\nvn -0.1374 -0.8810 0.4528\nvn -0.2779 0.2890 0.9161\nvn -0.0846 -0.9565 0.2790\nvn -0.2889 0.0976 0.9524\nvn -0.0286 0.9951 0.0942\nvn -0.0286 -0.9951 0.0942\nvn -0.2999 -0.7715 0.5611\nvn -0.4162 0.4696 0.7786\nvn -0.2230 -0.8810 0.4173\nvn -0.4513 0.2890 0.8443\nvn -0.1374 -0.9565 0.2571\nvn -0.4691 0.0976 0.8777\nvn -0.0464 0.9951 0.0869\nvn -0.0464 -0.9951 0.0869\nvn -0.4691 -0.0976 0.8777\nvn -0.1374 0.9565 0.2571\nvn -0.4513 -0.2890 0.8443\nvn -0.2230 0.8810 0.4173\nvn -0.4162 -0.4696 0.7786\nvn -0.2999 0.7715 0.5611\nvn -0.3651 -0.6326 0.6831\nvn -0.3651 0.6326 0.6831\nvn -0.1850 0.9565 0.2254\nvn -0.6073 -0.2890 0.7400\nvn -0.3002 0.8810 0.3658\nvn -0.5601 -0.4696 0.6825\nvn -0.4036 0.7715 0.4918\nvn -0.4913 -0.6326 0.5987\nvn -0.4913 0.6326 0.5987\nvn -0.4036 -0.7715 0.4918\nvn -0.5601 0.4696 0.6825\nvn -0.3002 -0.8810 0.3658\nvn -0.6073 0.2890 0.7400\nvn -0.1850 -0.9565 0.2254\nvn -0.6314 0.0976 0.7693\nvn -0.0625 0.9951 0.0761\nvn -0.0625 -0.9951 0.0761\nvn -0.6314 -0.0976 0.7693\nvn -0.6825 0.4696 0.5601\nvn -0.3658 -0.8810 0.3002\nvn -0.7400 0.2890 0.6073\nvn -0.2254 -0.9565 0.1850\nvn -0.7693 0.0976 0.6314\nvn -0.0761 0.9951 0.0625\nvn -0.0761 -0.9951 0.0625\nvn -0.7693 -0.0976 0.6314\nvn -0.2254 0.9565 0.1850\nvn -0.7400 -0.2890 0.6073\nvn -0.3658 0.8810 0.3002\nvn -0.6825 -0.4696 0.5601\nvn -0.4918 0.7715 0.4036\nvn -0.5987 -0.6326 0.4913\nvn -0.5987 0.6326 0.4913\nvn -0.4918 -0.7715 0.4036\nvn -0.8443 -0.2890 0.4513\nvn -0.4173 0.8810 0.2231\nvn -0.7786 -0.4696 0.4162\nvn -0.5611 0.7715 0.2999\nvn -0.6831 -0.6326 0.3651\nvn -0.6831 0.6326 0.3651\nvn -0.5611 -0.7715 0.2999\nvn -0.7786 0.4696 0.4162\nvn -0.4173 -0.8810 0.2231\nvn -0.8443 0.2890 0.4513\nvn -0.2571 -0.9565 0.1374\nvn -0.8777 0.0976 0.4691\nvn -0.0869 0.9951 0.0464\nvn -0.0869 -0.9951 0.0464\nvn -0.8777 -0.0976 0.4691\nvn -0.2571 0.9565 0.1374\nvn -0.4528 -0.8810 0.1374\nvn -0.9161 0.2890 0.2779\nvn -0.2790 -0.9565 0.0846\nvn -0.9524 0.0976 0.2889\nvn -0.0942 0.9951 0.0286\nvn -0.0942 -0.9951 0.0286\nvn -0.9524 -0.0976 0.2889\nvn -0.2790 0.9565 0.0846\nvn -0.9161 -0.2890 0.2779\nvn -0.4528 0.8810 0.1374\nvn -0.8448 -0.4696 0.2563\nvn -0.6088 0.7715 0.1847\nvn -0.7412 -0.6326 0.2248\nvn -0.7412 0.6326 0.2248\nvn -0.6088 -0.7715 0.1847\nvn -0.8448 0.4696 0.2563\nvn -0.8786 -0.4696 0.0865\nvn -0.6332 0.7715 0.0624\nvn -0.7708 -0.6326 0.0759\nvn -0.7708 0.6326 0.0759\nvn -0.6332 -0.7715 0.0624\nvn -0.8786 0.4696 0.0865\nvn -0.4709 -0.8810 0.0464\nvn -0.9527 0.2890 0.0938\nvn -0.2902 -0.9565 0.0286\nvn -0.9904 0.0976 0.0975\nvn -0.0980 0.9951 0.0097\nvn -0.0980 -0.9951 0.0097\nvn -0.9904 -0.0976 0.0975\nvn -0.2902 0.9565 0.0286\nvn -0.9527 -0.2890 0.0938\nvn -0.4709 0.8810 0.0464\nvn -0.2902 -0.9565 -0.0286\nvn -0.9904 0.0976 -0.0976\nvn -0.0980 0.9951 -0.0097\nvn -0.0980 -0.9951 -0.0097\nvn -0.9904 -0.0976 -0.0976\nvn -0.2902 0.9565 -0.0286\nvn -0.9527 -0.2890 -0.0938\nvn -0.4709 0.8810 -0.0464\nvn -0.8786 -0.4696 -0.0865\nvn -0.6332 0.7715 -0.0624\nvn -0.7708 -0.6326 -0.0759\nvn -0.7708 0.6326 -0.0759\nvn -0.6332 -0.7715 -0.0624\nvn -0.8786 0.4696 -0.0865\nvn -0.4709 -0.8810 -0.0464\nvn -0.9527 0.2890 -0.0938\nvn -0.6088 0.7715 -0.1847\nvn -0.7412 -0.6326 -0.2248\nvn -0.7412 0.6326 -0.2248\nvn -0.6088 -0.7715 -0.1847\nvn -0.8448 0.4696 -0.2563\nvn -0.4528 -0.8810 -0.1374\nvn -0.9161 0.2890 -0.2779\nvn -0.2790 -0.9565 -0.0846\nvn -0.9524 0.0976 -0.2889\nvn -0.0942 0.9951 -0.0286\nvn -0.0942 -0.9951 -0.0286\nvn -0.9524 -0.0976 -0.2889\nvn -0.2790 0.9565 -0.0846\nvn -0.9161 -0.2890 -0.2779\nvn -0.4528 0.8810 -0.1374\nvn -0.8448 -0.4696 -0.2563\nvn -0.8777 0.0976 -0.4691\nvn -0.0869 0.9951 -0.0464\nvn -0.0869 -0.9951 -0.0464\nvn -0.8777 -0.0976 -0.4691\nvn -0.2571 0.9565 -0.1374\nvn -0.8443 -0.2890 -0.4513\nvn -0.4173 0.8810 -0.2231\nvn -0.7786 -0.4696 -0.4162\nvn -0.5611 0.7715 -0.2999\nvn -0.6831 -0.6326 -0.3651\nvn -0.6831 0.6326 -0.3651\nvn -0.5611 -0.7715 -0.2999\nvn -0.7786 0.4696 -0.4162\nvn -0.4173 -0.8810 -0.2231\nvn -0.8443 0.2890 -0.4513\nvn -0.2571 -0.9565 -0.1374\nvn -0.5987 -0.6326 -0.4913\nvn -0.5987 0.6326 -0.4913\nvn -0.4918 -0.7715 -0.4036\nvn -0.6825 0.4696 -0.5601\nvn -0.3658 -0.8810 -0.3002\nvn -0.7400 0.2890 -0.6073\nvn -0.2254 -0.9565 -0.1850\nvn -0.7693 0.0976 -0.6314\nvn -0.0761 0.9951 -0.0625\nvn -0.0761 -0.9951 -0.0625\nvn -0.7693 -0.0976 -0.6314\nvn -0.2254 0.9565 -0.1850\nvn -0.7400 -0.2890 -0.6073\nvn -0.3658 0.8810 -0.3002\nvn -0.6825 -0.4696 -0.5601\nvn -0.4918 0.7715 -0.4036\nvn -0.0625 0.9951 -0.0761\nvn -0.0625 -0.9951 -0.0761\nvn -0.6314 -0.0976 -0.7693\nvn -0.1850 0.9565 -0.2254\nvn -0.6073 -0.2890 -0.7400\nvn -0.3002 0.8810 -0.3658\nvn -0.5601 -0.4696 -0.6825\nvn -0.4036 0.7715 -0.4918\nvn -0.4913 -0.6326 -0.5987\nvn -0.4913 0.6326 -0.5987\nvn -0.4036 -0.7715 -0.4918\nvn -0.5601 0.4696 -0.6825\nvn -0.3002 -0.8810 -0.3658\nvn -0.6073 0.2890 -0.7400\nvn -0.1850 -0.9565 -0.2254\nvn -0.6314 0.0976 -0.7693\nvn -0.3651 0.6326 -0.6831\nvn -0.2999 -0.7715 -0.5611\nvn -0.4162 0.4696 -0.7786\nvn -0.2230 -0.8810 -0.4173\nvn -0.4513 0.2890 -0.8443\nvn -0.1374 -0.9565 -0.2571\nvn -0.4691 0.0976 -0.8777\nvn -0.0464 0.9951 -0.0869\nvn -0.0464 -0.9951 -0.0869\nvn -0.4691 -0.0976 -0.8777\nvn -0.1374 0.9565 -0.2571\nvn -0.4513 -0.2890 -0.8443\nvn -0.2230 0.8810 -0.4173\nvn -0.4162 -0.4696 -0.7786\nvn -0.2999 0.7715 -0.5611\nvn -0.3651 -0.6326 -0.6831\nvn -0.2889 -0.0976 -0.9524\nvn -0.0846 0.9565 -0.2790\nvn -0.2779 -0.2890 -0.9161\nvn -0.1374 0.8810 -0.4528\nvn -0.2563 -0.4696 -0.8448\nvn -0.1847 0.7715 -0.6088\nvn -0.2248 -0.6326 -0.7412\nvn -0.2248 0.6326 -0.7412\nvn -0.1847 -0.7715 -0.6088\nvn -0.2563 0.4696 -0.8448\nvn -0.1374 -0.8810 -0.4528\nvn -0.2779 0.2890 -0.9161\nvn -0.0846 -0.9565 -0.2790\nvn -0.2889 0.0976 -0.9524\nvn -0.0286 0.9951 -0.0942\nvn -0.0286 -0.9951 -0.0942\nvn -0.0624 -0.7715 -0.6332\nvn -0.0865 0.4696 -0.8786\nvn -0.0464 -0.8810 -0.4709\nvn -0.0938 0.2890 -0.9527\nvn -0.0286 -0.9565 -0.2902\nvn -0.0976 0.0976 -0.9904\nvn -0.0097 0.9951 -0.0980\nvn -0.0097 -0.9951 -0.0980\nvn -0.0976 -0.0976 -0.9904\nvn -0.0286 0.9565 -0.2902\nvn -0.0938 -0.2890 -0.9527\nvn -0.0464 0.8810 -0.4709\nvn -0.0865 -0.4696 -0.8786\nvn -0.0624 0.7715 -0.6332\nvn -0.0759 -0.6326 -0.7708\nvn -0.0759 0.6326 -0.7708\nusemtl None\ns off\nf 10/1/1 480/2/1 22/3/1 23/4/1\nf 6/5/2 5/6/2 15/7/2 16/8/2\nf 481/9/3 10/1/3 23/4/3 24/10/3\nf 7/11/4 6/5/4 16/8/4 17/12/4\nf 482/13/5 481/9/5 24/10/5 25/14/5\nf 8/15/6 7/11/6 17/12/6 18/16/6\nf 1/17/7 297/18/7 11/19/7\nf 206/20/8 482/13/8 25/14/8\nf 9/21/9 8/15/9 18/16/9 19/22/9\nf 2/23/10 1/17/10 11/19/10 12/24/10\nf 478/25/11 9/21/11 19/22/11 20/26/11\nf 3/27/12 2/23/12 12/24/12 13/28/12\nf 479/29/13 478/25/13 20/26/13 21/30/13\nf 4/31/14 3/27/14 13/28/14 14/32/14\nf 480/2/15 479/29/15 21/30/15 22/3/15\nf 5/6/16 4/31/16 14/32/16 15/7/16\nf 14/32/17 13/28/17 28/33/17 29/34/17\nf 22/3/18 21/30/18 36/35/18 37/36/18\nf 15/7/19 14/32/19 29/34/19 30/37/19\nf 23/4/20 22/3/20 37/36/20 38/38/20\nf 16/8/21 15/7/21 30/37/21 31/39/21\nf 24/10/22 23/4/22 38/38/22 39/40/22\nf 17/12/23 16/8/23 31/39/23 32/41/23\nf 25/14/24 24/10/24 39/40/24 40/42/24\nf 18/16/25 17/12/25 32/41/25 33/43/25\nf 11/19/26 297/44/26 26/45/26\nf 206/46/27 25/14/27 40/42/27\nf 19/22/28 18/16/28 33/43/28 34/47/28\nf 12/24/29 11/19/29 26/45/29 27/48/29\nf 20/26/30 19/22/30 34/47/30 35/49/30\nf 13/28/31 12/24/31 27/48/31 28/33/31\nf 21/30/32 20/26/32 35/49/32 36/35/32\nf 33/43/33 32/41/33 47/50/33 48/51/33\nf 26/45/34 297/52/34 41/53/34\nf 206/54/35 40/42/35 55/55/35\nf 34/47/36 33/43/36 48/51/36 49/56/36\nf 27/48/37 26/45/37 41/53/37 42/57/37\nf 35/49/38 34/47/38 49/56/38 50/58/38\nf 28/33/39 27/48/39 42/57/39 43/59/39\nf 36/35/40 35/49/40 50/58/40 51/60/40\nf 29/34/41 28/33/41 43/59/41 44/61/41\nf 37/36/42 36/35/42 51/60/42 52/62/42\nf 30/37/43 29/34/43 44/61/43 45/63/43\nf 38/38/44 37/36/44 52/62/44 53/64/44\nf 31/39/45 30/37/45 45/63/45 46/65/45\nf 39/40/46 38/38/46 53/64/46 54/66/46\nf 32/41/47 31/39/47 46/65/47 47/50/47\nf 40/42/48 39/40/48 54/66/48 55/55/48\nf 52/62/49 51/60/49 66/67/49 67/68/49\nf 45/63/50 44/61/50 59/69/50 60/70/50\nf 53/64/51 52/62/51 67/68/51 68/71/51\nf 46/65/52 45/63/52 60/70/52 61/72/52\nf 54/66/53 53/64/53 68/71/53 69/73/53\nf 47/50/54 46/65/54 61/72/54 62/74/54\nf 55/55/55 54/66/55 69/73/55 70/75/55\nf 48/51/56 47/50/56 62/74/56 63/76/56\nf 41/53/57 297/77/57 56/78/57\nf 206/79/58 55/55/58 70/75/58\nf 49/56/59 48/51/59 63/76/59 64/80/59\nf 42/57/60 41/53/60 56/78/60 57/81/60\nf 50/58/61 49/56/61 64/80/61 65/82/61\nf 43/59/62 42/57/62 57/81/62 58/83/62\nf 51/60/63 50/58/63 65/82/63 66/67/63\nf 44/61/64 43/59/64 58/83/64 59/69/64\nf 206/84/65 70/75/65 85/85/65\nf 64/80/66 63/76/66 78/86/66 79/87/66\nf 57/81/67 56/78/67 71/88/67 72/89/67\nf 65/82/68 64/80/68 79/87/68 80/90/68\nf 58/83/69 57/81/69 72/89/69 73/91/69\nf 66/67/70 65/82/70 80/90/70 81/92/70\nf 59/69/71 58/83/71 73/91/71 74/93/71\nf 67/68/72 66/67/72 81/92/72 82/94/72\nf 60/70/73 59/69/73 74/93/73 75/95/73\nf 68/71/74 67/68/74 82/94/74 83/96/74\nf 61/72/75 60/70/75 75/95/75 76/97/75\nf 69/73/76 68/71/76 83/96/76 84/98/76\nf 62/74/77 61/72/77 76/97/77 77/99/77\nf 70/75/78 69/73/78 84/98/78 85/85/78\nf 63/76/79 62/74/79 77/99/79 78/86/79\nf 56/78/80 297/100/80 71/88/80\nf 83/96/81 82/94/81 97/101/81 98/102/81\nf 76/97/82 75/95/82 90/103/82 91/104/82\nf 84/98/83 83/96/83 98/102/83 99/105/83\nf 77/99/84 76/97/84 91/104/84 92/106/84\nf 85/85/85 84/98/85 99/105/85 100/107/85\nf 78/86/86 77/99/86 92/106/86 93/108/86\nf 71/88/87 297/109/87 86/110/87\nf 206/111/88 85/85/88 100/107/88\nf 79/87/89 78/86/89 93/108/89 94/112/89\nf 72/89/90 71/88/90 86/110/90 87/113/90\nf 80/90/91 79/87/91 94/112/91 95/114/91\nf 73/91/92 72/89/92 87/113/92 88/115/92\nf 81/92/93 80/90/93 95/114/93 96/116/93\nf 74/93/94 73/91/94 88/115/94 89/117/94\nf 82/94/95 81/92/95 96/116/95 97/101/95\nf 75/95/96 74/93/96 89/117/96 90/103/96\nf 87/113/97 86/110/97 101/118/97 102/119/97\nf 95/114/98 94/112/98 109/120/98 110/121/98\nf 88/115/99 87/113/99 102/119/99 103/122/99\nf 96/116/100 95/114/100 110/121/100 111/123/100\nf 89/117/101 88/115/101 103/122/101 104/124/101\nf 97/101/102 96/116/102 111/123/102 112/125/102\nf 90/103/103 89/117/103 104/124/103 105/126/103\nf 98/102/104 97/101/104 112/125/104 113/127/104\nf 91/104/105 90/103/105 105/126/105 106/128/105\nf 99/105/106 98/102/106 113/127/106 114/129/106\nf 92/106/107 91/104/107 106/128/107 107/130/107\nf 100/107/108 99/105/108 114/129/108 115/131/108\nf 93/108/109 92/106/109 107/130/109 108/132/109\nf 86/110/110 297/133/110 101/118/110\nf 206/134/111 100/107/111 115/131/111\nf 94/112/112 93/108/112 108/132/112 109/120/112\nf 106/128/113 105/126/113 120/135/113 121/136/113\nf 114/129/114 113/127/114 128/137/114 129/138/114\nf 107/130/115 106/128/115 121/136/115 122/139/115\nf 115/131/116 114/129/116 129/138/116 130/140/116\nf 108/132/117 107/130/117 122/139/117 123/141/117\nf 101/118/118 297/142/118 116/143/118\nf 206/144/119 115/131/119 130/140/119\nf 109/120/120 108/132/120 123/141/120 124/145/120\nf 102/119/121 101/118/121 116/143/121 117/146/121\nf 110/121/122 109/120/122 124/145/122 125/147/122\nf 103/122/123 102/119/123 117/146/123 118/148/123\nf 111/123/124 110/121/124 125/147/124 126/149/124\nf 104/124/125 103/122/125 118/148/125 119/150/125\nf 112/125/126 111/123/126 126/149/126 127/151/126\nf 105/126/127 104/124/127 119/150/127 120/135/127\nf 113/127/128 112/125/128 127/151/128 128/137/128\nf 125/147/129 124/145/129 139/152/129 140/153/129\nf 118/148/130 117/146/130 132/154/130 133/155/130\nf 126/149/131 125/147/131 140/153/131 141/156/131\nf 119/150/132 118/148/132 133/155/132 134/157/132\nf 127/151/133 126/149/133 141/156/133 142/158/133\nf 120/135/134 119/150/134 134/157/134 135/159/134\nf 128/137/135 127/151/135 142/158/135 143/160/135\nf 121/136/136 120/135/136 135/159/136 136/161/136\nf 129/138/137 128/137/137 143/160/137 144/162/137\nf 122/139/138 121/136/138 136/161/138 137/163/138\nf 130/140/139 129/138/139 144/162/139 145/164/139\nf 123/141/140 122/139/140 137/163/140 138/165/140\nf 116/143/141 297/166/141 131/167/141\nf 206/168/142 130/140/142 145/164/142\nf 124/145/143 123/141/143 138/165/143 139/152/143\nf 117/146/144 116/143/144 131/167/144 132/154/144\nf 144/162/145 143/160/145 158/169/145 159/170/145\nf 137/163/146 136/161/146 151/171/146 152/172/146\nf 145/164/147 144/162/147 159/170/147 160/173/147\nf 138/165/148 137/163/148 152/172/148 153/174/148\nf 131/167/149 297/175/149 146/176/149\nf 206/177/150 145/164/150 160/173/150\nf 139/152/151 138/165/151 153/174/151 154/178/151\nf 132/154/152 131/167/152 146/176/152 147/179/152\nf 140/153/153 139/152/153 154/178/153 155/180/153\nf 133/155/154 132/154/154 147/179/154 148/181/154\nf 141/156/155 140/153/155 155/180/155 156/182/155\nf 134/157/156 133/155/156 148/181/156 149/183/156\nf 142/158/157 141/156/157 156/182/157 157/184/157\nf 135/159/158 134/157/158 149/183/158 150/185/158\nf 143/160/159 142/158/159 157/184/159 158/169/159\nf 136/161/160 135/159/160 150/185/160 151/171/160\nf 148/181/161 147/179/161 162/186/161 163/187/161\nf 156/182/162 155/180/162 170/188/162 171/189/162\nf 149/183/163 148/181/163 163/187/163 164/190/163\nf 157/184/164 156/182/164 171/189/164 172/191/164\nf 150/185/165 149/183/165 164/190/165 165/192/165\nf 158/169/166 157/184/166 172/191/166 173/193/166\nf 151/171/167 150/185/167 165/192/167 166/194/167\nf 159/170/168 158/169/168 173/193/168 174/195/168\nf 152/172/169 151/171/169 166/194/169 167/196/169\nf 160/173/170 159/170/170 174/195/170 175/197/170\nf 153/174/171 152/172/171 167/196/171 168/198/171\nf 146/176/172 297/199/172 161/200/172\nf 206/201/173 160/173/173 175/197/173\nf 154/178/174 153/174/174 168/198/174 169/202/174\nf 147/179/175 146/176/175 161/200/175 162/186/175\nf 155/180/176 154/178/176 169/202/176 170/188/176\nf 167/196/177 166/194/177 181/203/177 182/204/177\nf 175/197/178 174/195/178 189/205/178 190/206/178\nf 168/198/179 167/196/179 182/204/179 183/207/179\nf 161/200/180 297/208/180 176/209/180\nf 206/210/181 175/197/181 190/206/181\nf 169/202/182 168/198/182 183/207/182 184/211/182\nf 162/186/183 161/200/183 176/209/183 177/212/183\nf 170/188/184 169/202/184 184/211/184 185/213/184\nf 163/187/185 162/186/185 177/212/185 178/214/185\nf 171/189/186 170/188/186 185/213/186 186/215/186\nf 164/190/187 163/187/187 178/214/187 179/216/187\nf 172/191/188 171/189/188 186/215/188 187/217/188\nf 165/192/189 164/190/189 179/216/189 180/218/189\nf 173/193/190 172/191/190 187/217/190 188/219/190\nf 166/194/191 165/192/191 180/218/191 181/203/191\nf 174/195/192 173/193/192 188/219/192 189/205/192\nf 186/215/193 185/213/193 200/220/193 201/221/193\nf 179/216/194 178/214/194 193/222/194 194/223/194\nf 187/217/195 186/215/195 201/221/195 202/224/195\nf 180/218/196 179/216/196 194/223/196 195/225/196\nf 188/219/197 187/217/197 202/224/197 203/226/197\nf 181/203/198 180/218/198 195/225/198 196/227/198\nf 189/205/199 188/219/199 203/226/199 204/228/199\nf 182/204/200 181/203/200 196/227/200 197/229/200\nf 190/206/201 189/205/201 204/228/201 205/230/201\nf 183/207/202 182/204/202 197/229/202 198/231/202\nf 176/209/203 297/232/203 191/233/203\nf 206/234/204 190/206/204 205/230/204\nf 184/211/205 183/207/205 198/231/205 199/235/205\nf 177/212/206 176/209/206 191/233/206 192/236/206\nf 185/213/207 184/211/207 199/235/207 200/220/207\nf 178/214/208 177/212/208 192/236/208 193/222/208\nf 205/230/209 204/228/209 220/237/209 221/238/209\nf 198/231/210 197/229/210 213/239/210 214/240/210\nf 191/233/211 297/241/211 207/242/211\nf 206/243/212 205/230/212 221/238/212\nf 199/235/213 198/231/213 214/240/213 215/244/213\nf 192/236/214 191/233/214 207/242/214 208/245/214\nf 200/220/215 199/235/215 215/244/215 216/246/215\nf 193/222/216 192/236/216 208/245/216 209/247/216\nf 201/221/217 200/220/217 216/246/217 217/248/217\nf 194/223/218 193/222/218 209/247/218 210/249/218\nf 202/224/219 201/221/219 217/248/219 218/250/219\nf 195/225/220 194/223/220 210/249/220 211/251/220\nf 203/226/221 202/224/221 218/250/221 219/252/221\nf 196/227/222 195/225/222 211/251/222 212/253/222\nf 204/228/223 203/226/223 219/252/223 220/237/223\nf 197/229/224 196/227/224 212/253/224 213/239/224\nf 218/250/225 217/248/225 232/254/225 233/255/225\nf 211/251/226 210/249/226 225/256/226 226/257/226\nf 219/252/227 218/250/227 233/255/227 234/258/227\nf 212/253/228 211/251/228 226/257/228 227/259/228\nf 220/237/229 219/252/229 234/258/229 235/260/229\nf 213/239/230 212/253/230 227/259/230 228/261/230\nf 221/238/231 220/237/231 235/260/231 236/262/231\nf 214/240/232 213/239/232 228/261/232 229/263/232\nf 207/242/233 297/264/233 222/265/233\nf 206/266/234 221/238/234 236/262/234\nf 215/244/235 214/240/235 229/263/235 230/267/235\nf 208/245/236 207/242/236 222/265/236 223/268/236\nf 216/246/237 215/244/237 230/267/237 231/269/237\nf 209/247/238 208/245/238 223/268/238 224/270/238\nf 217/248/239 216/246/239 231/269/239 232/254/239\nf 210/249/240 209/247/240 224/270/240 225/256/240\nf 222/265/241 297/271/241 237/272/241\nf 206/273/242 236/262/242 251/274/242\nf 230/267/243 229/263/243 244/275/243 245/276/243\nf 223/268/244 222/265/244 237/272/244 238/277/244\nf 231/269/245 230/267/245 245/276/245 246/278/245\nf 224/270/246 223/268/246 238/277/246 239/279/246\nf 232/254/247 231/269/247 246/278/247 247/280/247\nf 225/256/248 224/270/248 239/279/248 240/281/248\nf 233/255/249 232/254/249 247/280/249 248/282/249\nf 226/257/250 225/256/250 240/281/250 241/283/250\nf 234/258/251 233/255/251 248/282/251 249/284/251\nf 227/259/252 226/257/252 241/283/252 242/285/252\nf 235/260/253 234/258/253 249/284/253 250/286/253\nf 228/261/254 227/259/254 242/285/254 243/287/254\nf 236/262/255 235/260/255 250/286/255 251/274/255\nf 229/263/256 228/261/256 243/287/256 244/275/256\nf 241/283/257 240/281/257 255/288/257 256/289/257\nf 249/284/258 248/282/258 263/290/258 264/291/258\nf 242/285/259 241/283/259 256/289/259 257/292/259\nf 250/286/260 249/284/260 264/291/260 265/293/260\nf 243/287/261 242/285/261 257/292/261 258/294/261\nf 251/274/262 250/286/262 265/293/262 266/295/262\nf 244/275/263 243/287/263 258/294/263 259/296/263\nf 237/272/264 297/297/264 252/298/264\nf 206/299/265 251/274/265 266/295/265\nf 245/276/266 244/275/266 259/296/266 260/300/266\nf 238/277/267 237/272/267 252/298/267 253/301/267\nf 246/278/268 245/276/268 260/300/268 261/302/268\nf 239/279/269 238/277/269 253/301/269 254/303/269\nf 247/280/270 246/278/270 261/302/270 262/304/270\nf 240/281/271 239/279/271 254/303/271 255/288/271\nf 248/282/272 247/280/272 262/304/272 263/290/272\nf 260/300/273 259/296/273 274/305/273 275/306/273\nf 253/301/274 252/298/274 267/307/274 268/308/274\nf 261/302/275 260/300/275 275/306/275 276/309/275\nf 254/303/276 253/301/276 268/308/276 269/310/276\nf 262/304/277 261/302/277 276/309/277 277/311/277\nf 255/288/278 254/303/278 269/310/278 270/312/278\nf 263/290/279 262/304/279 277/311/279 278/313/279\nf 256/289/280 255/288/280 270/312/280 271/314/280\nf 264/291/281 263/290/281 278/313/281 279/315/281\nf 257/292/282 256/289/282 271/314/282 272/316/282\nf 265/293/283 264/291/283 279/315/283 280/317/283\nf 258/294/284 257/292/284 272/316/284 273/318/284\nf 266/295/285 265/293/285 280/317/285 281/319/285\nf 259/296/286 258/294/286 273/318/286 274/305/286\nf 252/298/287 297/320/287 267/307/287\nf 206/321/288 266/295/288 281/319/288\nf 279/315/289 278/313/289 293/322/289 294/323/289\nf 272/316/290 271/314/290 286/324/290 287/325/290\nf 280/317/291 279/315/291 294/323/291 295/326/291\nf 273/318/292 272/316/292 287/325/292 288/327/292\nf 281/319/293 280/317/293 295/326/293 296/328/293\nf 274/305/294 273/318/294 288/327/294 289/329/294\nf 267/307/295 297/330/295 282/331/295\nf 206/332/296 281/319/296 296/328/296\nf 275/306/297 274/305/297 289/329/297 290/333/297\nf 268/308/298 267/307/298 282/331/298 283/334/298\nf 276/309/299 275/306/299 290/333/299 291/335/299\nf 269/310/300 268/308/300 283/334/300 284/336/300\nf 277/311/301 276/309/301 291/335/301 292/337/301\nf 270/312/302 269/310/302 284/336/302 285/338/302\nf 278/313/303 277/311/303 292/337/303 293/322/303\nf 271/314/304 270/312/304 285/338/304 286/324/304\nf 283/334/305 282/331/305 298/339/305 299/340/305\nf 291/335/306 290/333/306 306/341/306 307/342/306\nf 284/336/307 283/334/307 299/340/307 300/343/307\nf 292/337/308 291/335/308 307/342/308 308/344/308\nf 285/338/309 284/336/309 300/343/309 301/345/309\nf 293/322/310 292/337/310 308/344/310 309/346/310\nf 286/324/311 285/338/311 301/345/311 302/347/311\nf 294/323/312 293/322/312 309/346/312 310/348/312\nf 287/325/313 286/324/313 302/347/313 303/349/313\nf 295/326/314 294/323/314 310/348/314 311/350/314\nf 288/327/315 287/325/315 303/349/315 304/351/315\nf 296/328/316 295/326/316 311/350/316 312/352/316\nf 289/329/317 288/327/317 304/351/317 305/353/317\nf 282/331/318 297/354/318 298/339/318\nf 206/355/319 296/328/319 312/352/319\nf 290/333/320 289/329/320 305/353/320 306/341/320\nf 303/349/321 302/347/321 317/356/321 318/357/321\nf 311/350/322 310/348/322 325/358/322 326/359/322\nf 304/351/323 303/349/323 318/357/323 319/360/323\nf 312/352/324 311/350/324 326/359/324 327/361/324\nf 305/353/325 304/351/325 319/360/325 320/362/325\nf 298/339/326 297/363/326 313/364/326\nf 206/365/327 312/352/327 327/361/327\nf 306/341/328 305/353/328 320/362/328 321/366/328\nf 299/340/329 298/339/329 313/364/329 314/367/329\nf 307/342/330 306/341/330 321/366/330 322/368/330\nf 300/343/331 299/340/331 314/367/331 315/369/331\nf 308/344/332 307/342/332 322/368/332 323/370/332\nf 301/345/333 300/343/333 315/369/333 316/371/333\nf 309/346/334 308/344/334 323/370/334 324/372/334\nf 302/347/335 301/345/335 316/371/335 317/356/335\nf 310/348/336 309/346/336 324/372/336 325/358/336\nf 322/368/337 321/366/337 336/373/337 337/374/337\nf 315/369/338 314/367/338 329/375/338 330/376/338\nf 323/370/339 322/368/339 337/374/339 338/377/339\nf 316/371/340 315/369/340 330/376/340 331/378/340\nf 324/372/341 323/370/341 338/377/341 339/379/341\nf 317/356/342 316/371/342 331/378/342 332/380/342\nf 325/358/343 324/372/343 339/379/343 340/381/343\nf 318/357/344 317/356/344 332/380/344 333/382/344\nf 326/359/345 325/358/345 340/381/345 341/383/345\nf 319/360/346 318/357/346 333/382/346 334/384/346\nf 327/361/347 326/359/347 341/383/347 342/385/347\nf 320/362/348 319/360/348 334/384/348 335/386/348\nf 313/364/349 297/387/349 328/388/349\nf 206/389/350 327/361/350 342/385/350\nf 321/366/351 320/362/351 335/386/351 336/373/351\nf 314/367/352 313/364/352 328/388/352 329/375/352\nf 341/383/353 340/381/353 355/390/353 356/391/353\nf 334/384/354 333/382/354 348/392/354 349/393/354\nf 342/385/355 341/383/355 356/391/355 357/394/355\nf 335/386/356 334/384/356 349/393/356 350/395/356\nf 328/388/357 297/396/357 343/397/357\nf 206/398/358 342/385/358 357/394/358\nf 336/373/359 335/386/359 350/395/359 351/399/359\nf 329/375/360 328/388/360 343/397/360 344/400/360\nf 337/374/361 336/373/361 351/399/361 352/401/361\nf 330/376/362 329/375/362 344/400/362 345/402/362\nf 338/377/363 337/374/363 352/401/363 353/403/363\nf 331/378/364 330/376/364 345/402/364 346/404/364\nf 339/379/365 338/377/365 353/403/365 354/405/365\nf 332/380/366 331/378/366 346/404/366 347/406/366\nf 340/381/367 339/379/367 354/405/367 355/390/367\nf 333/382/368 332/380/368 347/406/368 348/392/368\nf 353/403/369 352/401/369 367/407/369 368/408/369\nf 346/404/370 345/402/370 360/409/370 361/410/370\nf 354/405/371 353/403/371 368/408/371 369/411/371\nf 347/406/372 346/404/372 361/410/372 362/412/372\nf 355/390/373 354/405/373 369/411/373 370/413/373\nf 348/392/374 347/406/374 362/412/374 363/414/374\nf 356/391/375 355/390/375 370/413/375 371/415/375\nf 349/393/376 348/392/376 363/414/376 364/416/376\nf 357/394/377 356/391/377 371/415/377 372/417/377\nf 350/395/378 349/393/378 364/416/378 365/418/378\nf 343/397/379 297/419/379 358/420/379\nf 206/421/380 357/394/380 372/417/380\nf 351/399/381 350/395/381 365/418/381 366/422/381\nf 344/400/382 343/397/382 358/420/382 359/423/382\nf 352/401/383 351/399/383 366/422/383 367/407/383\nf 345/402/384 344/400/384 359/423/384 360/409/384\nf 372/424/385 371/425/385 386/426/385 387/427/385\nf 365/428/386 364/429/386 379/430/386 380/431/386\nf 358/432/387 297/433/387 373/434/387\nf 206/435/388 372/424/388 387/427/388\nf 366/436/389 365/428/389 380/431/389 381/437/389\nf 359/438/390 358/432/390 373/434/390 374/439/390\nf 367/440/391 366/436/391 381/437/391 382/441/391\nf 360/442/392 359/438/392 374/439/392 375/443/392\nf 368/444/393 367/440/393 382/441/393 383/445/393\nf 361/446/394 360/442/394 375/443/394 376/447/394\nf 369/448/395 368/444/395 383/445/395 384/449/395\nf 362/450/396 361/446/396 376/447/396 377/451/396\nf 370/452/397 369/448/397 384/449/397 385/453/397\nf 363/454/398 362/450/398 377/451/398 378/455/398\nf 371/425/399 370/452/399 385/453/399 386/426/399\nf 364/429/400 363/454/400 378/455/400 379/430/400\nf 376/447/401 375/443/401 390/456/401 391/457/401\nf 384/449/402 383/445/402 398/458/402 399/459/402\nf 377/451/403 376/447/403 391/457/403 392/460/403\nf 385/453/404 384/449/404 399/459/404 400/461/404\nf 378/455/405 377/451/405 392/460/405 393/462/405\nf 386/426/406 385/453/406 400/461/406 401/463/406\nf 379/430/407 378/455/407 393/462/407 394/464/407\nf 387/427/408 386/426/408 401/463/408 402/465/408\nf 380/431/409 379/430/409 394/464/409 395/466/409\nf 373/434/410 297/467/410 388/468/410\nf 206/469/411 387/427/411 402/465/411\nf 381/437/412 380/431/412 395/466/412 396/470/412\nf 374/439/413 373/434/413 388/468/413 389/471/413\nf 382/441/414 381/437/414 396/470/414 397/472/414\nf 375/443/415 374/439/415 389/471/415 390/456/415\nf 383/445/416 382/441/416 397/472/416 398/458/416\nf 395/466/417 394/464/417 409/473/417 410/474/417\nf 388/468/418 297/475/418 403/476/418\nf 206/477/419 402/465/419 417/478/419\nf 396/470/420 395/466/420 410/474/420 411/479/420\nf 389/471/421 388/468/421 403/476/421 404/480/421\nf 397/472/422 396/470/422 411/479/422 412/481/422\nf 390/456/423 389/471/423 404/480/423 405/482/423\nf 398/458/424 397/472/424 412/481/424 413/483/424\nf 391/457/425 390/456/425 405/482/425 406/484/425\nf 399/459/426 398/458/426 413/483/426 414/485/426\nf 392/460/427 391/457/427 406/484/427 407/486/427\nf 400/461/428 399/459/428 414/485/428 415/487/428\nf 393/462/429 392/460/429 407/486/429 408/488/429\nf 401/463/430 400/461/430 415/487/430 416/489/430\nf 394/464/431 393/462/431 408/488/431 409/473/431\nf 402/465/432 401/463/432 416/489/432 417/478/432\nf 414/485/433 413/483/433 428/490/433 429/491/433\nf 407/486/434 406/484/434 421/492/434 422/493/434\nf 415/487/435 414/485/435 429/491/435 430/494/435\nf 408/488/436 407/486/436 422/493/436 423/495/436\nf 416/489/437 415/487/437 430/494/437 431/496/437\nf 409/473/438 408/488/438 423/495/438 424/497/438\nf 417/478/439 416/489/439 431/496/439 432/498/439\nf 410/474/440 409/473/440 424/497/440 425/499/440\nf 403/476/441 297/500/441 418/501/441\nf 206/502/442 417/478/442 432/498/442\nf 411/479/443 410/474/443 425/499/443 426/503/443\nf 404/480/444 403/476/444 418/501/444 419/504/444\nf 412/481/445 411/479/445 426/503/445 427/505/445\nf 405/482/446 404/480/446 419/504/446 420/506/446\nf 413/483/447 412/481/447 427/505/447 428/490/447\nf 406/484/448 405/482/448 420/506/448 421/492/448\nf 418/501/449 297/507/449 433/508/449\nf 206/509/450 432/498/450 447/510/450\nf 426/503/451 425/499/451 440/511/451 441/512/451\nf 419/504/452 418/501/452 433/508/452 434/513/452\nf 427/505/453 426/503/453 441/512/453 442/514/453\nf 420/506/454 419/504/454 434/513/454 435/515/454\nf 428/490/455 427/505/455 442/514/455 443/516/455\nf 421/492/456 420/506/456 435/515/456 436/517/456\nf 429/491/457 428/490/457 443/516/457 444/518/457\nf 422/493/458 421/492/458 436/517/458 437/519/458\nf 430/494/459 429/491/459 444/518/459 445/520/459\nf 423/495/460 422/493/460 437/519/460 438/521/460\nf 431/496/461 430/494/461 445/520/461 446/522/461\nf 424/497/462 423/495/462 438/521/462 439/523/462\nf 432/498/463 431/496/463 446/522/463 447/510/463\nf 425/499/464 424/497/464 439/523/464 440/511/464\nf 437/519/465 436/517/465 451/524/465 452/525/465\nf 445/520/466 444/518/466 459/526/466 460/527/466\nf 438/521/467 437/519/467 452/525/467 453/528/467\nf 446/522/468 445/520/468 460/527/468 461/529/468\nf 439/523/469 438/521/469 453/528/469 454/530/469\nf 447/510/470 446/522/470 461/529/470 462/531/470\nf 440/511/471 439/523/471 454/530/471 455/532/471\nf 433/508/472 297/533/472 448/534/472\nf 206/535/473 447/510/473 462/531/473\nf 441/512/474 440/511/474 455/532/474 456/536/474\nf 434/513/475 433/508/475 448/534/475 449/537/475\nf 442/514/476 441/512/476 456/536/476 457/538/476\nf 435/515/477 434/513/477 449/537/477 450/539/477\nf 443/516/478 442/514/478 457/538/478 458/540/478\nf 436/517/479 435/515/479 450/539/479 451/524/479\nf 444/518/480 443/516/480 458/540/480 459/526/480\nf 456/536/481 455/532/481 470/541/481 471/542/481\nf 449/537/482 448/534/482 463/543/482 464/544/482\nf 457/538/483 456/536/483 471/542/483 472/545/483\nf 450/539/484 449/537/484 464/544/484 465/546/484\nf 458/540/485 457/538/485 472/545/485 473/547/485\nf 451/524/486 450/539/486 465/546/486 466/548/486\nf 459/526/487 458/540/487 473/547/487 474/549/487\nf 452/525/488 451/524/488 466/548/488 467/550/488\nf 460/527/489 459/526/489 474/549/489 475/551/489\nf 453/528/490 452/525/490 467/550/490 468/552/490\nf 461/529/491 460/527/491 475/551/491 476/553/491\nf 454/530/492 453/528/492 468/552/492 469/554/492\nf 462/531/493 461/529/493 476/553/493 477/555/493\nf 455/532/494 454/530/494 469/554/494 470/541/494\nf 448/534/495 297/556/495 463/543/495\nf 206/557/496 462/531/496 477/555/496\nf 475/551/497 474/549/497 480/2/497 10/1/497\nf 468/552/498 467/550/498 5/6/498 6/5/498\nf 476/553/499 475/551/499 10/1/499 481/9/499\nf 469/554/500 468/552/500 6/5/500 7/11/500\nf 477/555/501 476/553/501 481/9/501 482/13/501\nf 470/541/502 469/554/502 7/11/502 8/15/502\nf 463/543/503 297/558/503 1/17/503\nf 206/559/504 477/555/504 482/13/504\nf 471/542/505 470/541/505 8/15/505 9/21/505\nf 464/544/506 463/543/506 1/17/506 2/23/506\nf 472/545/507 471/542/507 9/21/507 478/25/507\nf 465/546/508 464/544/508 2/23/508 3/27/508\nf 473/547/509 472/545/509 478/25/509 479/29/509\nf 466/548/510 465/546/510 3/27/510 4/31/510\nf 474/549/511 473/547/511 479/29/511 480/2/511\nf 467/550/512 466/548/512 4/31/512 5/6/512\n"
  },
  {
    "path": "bin/mods/base/chars/primitives/torus.mtl",
    "content": "# Blender MTL File: 'None'\n# Material Count: 1\n\nnewmtl None\nNs 500\nKa 0.8 0.8 0.8\nKd 0.8 0.8 0.8\nKs 0.8 0.8 0.8\nd 1\nillum 2\n"
  },
  {
    "path": "bin/mods/base/chars/primitives/torus.obj",
    "content": "# Blender v2.80 (sub 75) OBJ File: ''\n# www.blender.org\nmtllib torus.mtl\no Torus\nv 1.250000 0.000000 0.000000\nv 1.216506 0.125000 0.000000\nv 1.125000 0.216506 0.000000\nv 1.000000 0.250000 0.000000\nv 0.875000 0.216506 0.000000\nv 0.783494 0.125000 0.000000\nv 0.750000 0.000000 0.000000\nv 0.783494 -0.125000 0.000000\nv 0.875000 -0.216506 0.000000\nv 1.000000 -0.250000 0.000000\nv 1.125000 -0.216506 0.000000\nv 1.216506 -0.125000 0.000000\nv 1.239306 0.000000 -0.163158\nv 1.206099 0.125000 -0.158786\nv 1.115376 0.216506 -0.146842\nv 0.991445 0.250000 -0.130526\nv 0.867514 0.216506 -0.114210\nv 0.776791 0.125000 -0.102266\nv 0.743584 0.000000 -0.097895\nv 0.776791 -0.125000 -0.102266\nv 0.867514 -0.216506 -0.114210\nv 0.991445 -0.250000 -0.130526\nv 1.115376 -0.216506 -0.146842\nv 1.206099 -0.125000 -0.158786\nv 1.207407 0.000000 -0.323524\nv 1.175055 0.125000 -0.314855\nv 1.086667 0.216506 -0.291171\nv 0.965926 0.250000 -0.258819\nv 0.845185 0.216506 -0.226467\nv 0.756797 0.125000 -0.202783\nv 0.724444 0.000000 -0.194114\nv 0.756797 -0.125000 -0.202783\nv 0.845185 -0.216506 -0.226467\nv 0.965926 -0.250000 -0.258819\nv 1.086667 -0.216506 -0.291171\nv 1.175055 -0.125000 -0.314855\nv 1.154849 0.000000 -0.478354\nv 1.123905 0.125000 -0.465537\nv 1.039364 0.216506 -0.430519\nv 0.923880 0.250000 -0.382683\nv 0.808395 0.216506 -0.334848\nv 0.723854 0.125000 -0.299830\nv 0.692910 0.000000 -0.287013\nv 0.723854 -0.125000 -0.299830\nv 0.808395 -0.216506 -0.334848\nv 0.923880 -0.250000 -0.382683\nv 1.039364 -0.216506 -0.430519\nv 1.123905 -0.125000 -0.465537\nv 1.082532 0.000000 -0.625000\nv 1.053525 0.125000 -0.608253\nv 0.974279 0.216506 -0.562500\nv 0.866025 0.250000 -0.500000\nv 0.757772 0.216506 -0.437500\nv 0.678525 0.125000 -0.391747\nv 0.649519 0.000000 -0.375000\nv 0.678525 -0.125000 -0.391747\nv 0.757772 -0.216506 -0.437500\nv 0.866025 -0.250000 -0.500000\nv 0.974279 -0.216506 -0.562500\nv 1.053525 -0.125000 -0.608253\nv 0.991692 0.000000 -0.760952\nv 0.965119 0.125000 -0.740562\nv 0.892523 0.216506 -0.684856\nv 0.793353 0.250000 -0.608761\nv 0.694184 0.216506 -0.532666\nv 0.621587 0.125000 -0.476961\nv 0.595015 0.000000 -0.456571\nv 0.621587 -0.125000 -0.476961\nv 0.694184 -0.216506 -0.532666\nv 0.793353 -0.250000 -0.608761\nv 0.892523 -0.216506 -0.684856\nv 0.965119 -0.125000 -0.740562\nv 0.883883 0.000000 -0.883884\nv 0.860200 0.125000 -0.860200\nv 0.795495 0.216506 -0.795495\nv 0.707107 0.250000 -0.707107\nv 0.618718 0.216506 -0.618719\nv 0.554014 0.125000 -0.554014\nv 0.530330 0.000000 -0.530330\nv 0.554014 -0.125000 -0.554014\nv 0.618718 -0.216506 -0.618719\nv 0.707107 -0.250000 -0.707107\nv 0.795495 -0.216506 -0.795495\nv 0.860200 -0.125000 -0.860200\nv 0.760952 0.000000 -0.991691\nv 0.740562 0.125000 -0.965119\nv 0.684857 0.216506 -0.892522\nv 0.608762 0.250000 -0.793353\nv 0.532666 0.216506 -0.694184\nv 0.476961 0.125000 -0.621587\nv 0.456571 0.000000 -0.595015\nv 0.476961 -0.125000 -0.621587\nv 0.532666 -0.216506 -0.694184\nv 0.608762 -0.250000 -0.793353\nv 0.684857 -0.216506 -0.892522\nv 0.740562 -0.125000 -0.965119\nv 0.625000 0.000000 -1.082532\nv 0.608253 0.125000 -1.053525\nv 0.562500 0.216506 -0.974279\nv 0.500000 0.250000 -0.866025\nv 0.437500 0.216506 -0.757772\nv 0.391747 0.125000 -0.678525\nv 0.375000 0.000000 -0.649519\nv 0.391747 -0.125000 -0.678525\nv 0.437500 -0.216506 -0.757772\nv 0.500000 -0.250000 -0.866025\nv 0.562500 -0.216506 -0.974279\nv 0.608253 -0.125000 -1.053525\nv 0.478355 0.000000 -1.154849\nv 0.465537 0.125000 -1.123905\nv 0.430519 0.216506 -1.039364\nv 0.382684 0.250000 -0.923879\nv 0.334848 0.216506 -0.808394\nv 0.299830 0.125000 -0.723854\nv 0.287013 0.000000 -0.692910\nv 0.299830 -0.125000 -0.723854\nv 0.334848 -0.216506 -0.808394\nv 0.382684 -0.250000 -0.923879\nv 0.430519 -0.216506 -1.039364\nv 0.465537 -0.125000 -1.123905\nv 0.323524 0.000000 -1.207407\nv 0.314855 0.125000 -1.175055\nv 0.291171 0.216506 -1.086667\nv 0.258819 0.250000 -0.965926\nv 0.226467 0.216506 -0.845185\nv 0.202783 0.125000 -0.756797\nv 0.194114 0.000000 -0.724444\nv 0.202783 -0.125000 -0.756797\nv 0.226467 -0.216506 -0.845185\nv 0.258819 -0.250000 -0.965926\nv 0.291171 -0.216506 -1.086667\nv 0.314855 -0.125000 -1.175055\nv 0.163158 0.000000 -1.239306\nv 0.158786 0.125000 -1.206099\nv 0.146842 0.216506 -1.115376\nv 0.130526 0.250000 -0.991445\nv 0.114210 0.216506 -0.867514\nv 0.102266 0.125000 -0.776791\nv 0.097895 0.000000 -0.743584\nv 0.102266 -0.125000 -0.776791\nv 0.114210 -0.216506 -0.867514\nv 0.130526 -0.250000 -0.991445\nv 0.146842 -0.216506 -1.115376\nv 0.158786 -0.125000 -1.206099\nv 0.000000 0.000000 -1.250000\nv 0.000000 0.125000 -1.216506\nv 0.000000 0.216506 -1.125000\nv 0.000000 0.250000 -1.000000\nv 0.000000 0.216506 -0.875000\nv 0.000000 0.125000 -0.783494\nv 0.000000 0.000000 -0.750000\nv 0.000000 -0.125000 -0.783494\nv 0.000000 -0.216506 -0.875000\nv 0.000000 -0.250000 -1.000000\nv 0.000000 -0.216506 -1.125000\nv 0.000000 -0.125000 -1.216506\nv -0.163158 0.000000 -1.239306\nv -0.158786 0.125000 -1.206099\nv -0.146842 0.216506 -1.115375\nv -0.130526 0.250000 -0.991445\nv -0.114211 0.216506 -0.867514\nv -0.102267 0.125000 -0.776791\nv -0.097895 0.000000 -0.743584\nv -0.102267 -0.125000 -0.776791\nv -0.114211 -0.216506 -0.867514\nv -0.130526 -0.250000 -0.991445\nv -0.146842 -0.216506 -1.115375\nv -0.158786 -0.125000 -1.206099\nv -0.323524 0.000000 -1.207407\nv -0.314855 0.125000 -1.175055\nv -0.291171 0.216506 -1.086667\nv -0.258819 0.250000 -0.965926\nv -0.226467 0.216506 -0.845185\nv -0.202783 0.125000 -0.756797\nv -0.194114 0.000000 -0.724444\nv -0.202783 -0.125000 -0.756797\nv -0.226467 -0.216506 -0.845185\nv -0.258819 -0.250000 -0.965926\nv -0.291171 -0.216506 -1.086667\nv -0.314855 -0.125000 -1.175055\nv -0.478354 0.000000 -1.154849\nv -0.465537 0.125000 -1.123905\nv -0.430519 0.216506 -1.039364\nv -0.382684 0.250000 -0.923880\nv -0.334848 0.216506 -0.808395\nv -0.299830 0.125000 -0.723854\nv -0.287013 0.000000 -0.692910\nv -0.299830 -0.125000 -0.723854\nv -0.334848 -0.216506 -0.808395\nv -0.382684 -0.250000 -0.923880\nv -0.430519 -0.216506 -1.039364\nv -0.465537 -0.125000 -1.123905\nv -0.625000 0.000000 -1.082532\nv -0.608253 0.125000 -1.053526\nv -0.562500 0.216506 -0.974279\nv -0.500000 0.250000 -0.866026\nv -0.437500 0.216506 -0.757772\nv -0.391747 0.125000 -0.678525\nv -0.375000 0.000000 -0.649519\nv -0.391747 -0.125000 -0.678525\nv -0.437500 -0.216506 -0.757772\nv -0.500000 -0.250000 -0.866026\nv -0.562500 -0.216506 -0.974279\nv -0.608253 -0.125000 -1.053526\nv -0.760952 0.000000 -0.991692\nv -0.740562 0.125000 -0.965119\nv -0.684857 0.216506 -0.892522\nv -0.608761 0.250000 -0.793353\nv -0.532666 0.216506 -0.694184\nv -0.476961 0.125000 -0.621587\nv -0.456571 0.000000 -0.595015\nv -0.476961 -0.125000 -0.621587\nv -0.532666 -0.216506 -0.694184\nv -0.608761 -0.250000 -0.793353\nv -0.684857 -0.216506 -0.892522\nv -0.740562 -0.125000 -0.965119\nv -0.883884 0.000000 -0.883883\nv -0.860200 0.125000 -0.860200\nv -0.795495 0.216506 -0.795495\nv -0.707107 0.250000 -0.707107\nv -0.618719 0.216506 -0.618718\nv -0.554014 0.125000 -0.554013\nv -0.530330 0.000000 -0.530330\nv -0.554014 -0.125000 -0.554013\nv -0.618719 -0.216506 -0.618718\nv -0.707107 -0.250000 -0.707107\nv -0.795495 -0.216506 -0.795495\nv -0.860200 -0.125000 -0.860200\nv -0.991692 0.000000 -0.760952\nv -0.965119 0.125000 -0.740562\nv -0.892522 0.216506 -0.684857\nv -0.793353 0.250000 -0.608761\nv -0.694184 0.216506 -0.532666\nv -0.621587 0.125000 -0.476961\nv -0.595015 0.000000 -0.456571\nv -0.621587 -0.125000 -0.476961\nv -0.694184 -0.216506 -0.532666\nv -0.793353 -0.250000 -0.608761\nv -0.892522 -0.216506 -0.684857\nv -0.965119 -0.125000 -0.740562\nv -1.082532 0.000000 -0.625000\nv -1.053525 0.125000 -0.608253\nv -0.974278 0.216506 -0.562500\nv -0.866025 0.250000 -0.500000\nv -0.757772 0.216506 -0.437500\nv -0.678525 0.125000 -0.391747\nv -0.649519 0.000000 -0.375000\nv -0.678525 -0.125000 -0.391747\nv -0.757772 -0.216506 -0.437500\nv -0.866025 -0.250000 -0.500000\nv -0.974278 -0.216506 -0.562500\nv -1.053525 -0.125000 -0.608253\nv -1.154849 0.000000 -0.478354\nv -1.123905 0.125000 -0.465537\nv -1.039364 0.216506 -0.430519\nv -0.923880 0.250000 -0.382683\nv -0.808395 0.216506 -0.334848\nv -0.723854 0.125000 -0.299830\nv -0.692910 0.000000 -0.287013\nv -0.723854 -0.125000 -0.299830\nv -0.808395 -0.216506 -0.334848\nv -0.923880 -0.250000 -0.382683\nv -1.039364 -0.216506 -0.430519\nv -1.123905 -0.125000 -0.465537\nv -1.207407 0.000000 -0.323524\nv -1.175055 0.125000 -0.314855\nv -1.086667 0.216506 -0.291171\nv -0.965926 0.250000 -0.258819\nv -0.845185 0.216506 -0.226467\nv -0.756797 0.125000 -0.202783\nv -0.724444 0.000000 -0.194114\nv -0.756797 -0.125000 -0.202783\nv -0.845185 -0.216506 -0.226467\nv -0.965926 -0.250000 -0.258819\nv -1.086667 -0.216506 -0.291171\nv -1.175055 -0.125000 -0.314855\nv -1.239306 0.000000 -0.163158\nv -1.206099 0.125000 -0.158786\nv -1.115375 0.216506 -0.146842\nv -0.991445 0.250000 -0.130526\nv -0.867514 0.216506 -0.114211\nv -0.776791 0.125000 -0.102267\nv -0.743584 0.000000 -0.097895\nv -0.776791 -0.125000 -0.102267\nv -0.867514 -0.216506 -0.114211\nv -0.991445 -0.250000 -0.130526\nv -1.115375 -0.216506 -0.146842\nv -1.206099 -0.125000 -0.158786\nv -1.250000 0.000000 -0.000000\nv -1.216506 0.125000 -0.000000\nv -1.125000 0.216506 -0.000000\nv -1.000000 0.250000 -0.000000\nv -0.875000 0.216506 -0.000000\nv -0.783494 0.125000 -0.000000\nv -0.750000 0.000000 -0.000000\nv -0.783494 -0.125000 -0.000000\nv -0.875000 -0.216506 -0.000000\nv -1.000000 -0.250000 -0.000000\nv -1.125000 -0.216506 -0.000000\nv -1.216506 -0.125000 -0.000000\nv -1.239306 0.000000 0.163158\nv -1.206099 0.125000 0.158786\nv -1.115375 0.216506 0.146842\nv -0.991445 0.250000 0.130526\nv -0.867514 0.216506 0.114211\nv -0.776791 0.125000 0.102267\nv -0.743584 0.000000 0.097895\nv -0.776791 -0.125000 0.102267\nv -0.867514 -0.216506 0.114211\nv -0.991445 -0.250000 0.130526\nv -1.115375 -0.216506 0.146842\nv -1.206099 -0.125000 0.158786\nv -1.207407 0.000000 0.323524\nv -1.175055 0.125000 0.314855\nv -1.086667 0.216506 0.291171\nv -0.965926 0.250000 0.258819\nv -0.845185 0.216506 0.226467\nv -0.756797 0.125000 0.202783\nv -0.724444 0.000000 0.194114\nv -0.756797 -0.125000 0.202783\nv -0.845185 -0.216506 0.226467\nv -0.965926 -0.250000 0.258819\nv -1.086667 -0.216506 0.291171\nv -1.175055 -0.125000 0.314855\nv -1.154850 0.000000 0.478354\nv -1.123906 0.125000 0.465536\nv -1.039365 0.216506 0.430518\nv -0.923880 0.250000 0.382683\nv -0.808395 0.216506 0.334848\nv -0.723854 0.125000 0.299830\nv -0.692910 0.000000 0.287012\nv -0.723854 -0.125000 0.299830\nv -0.808395 -0.216506 0.334848\nv -0.923880 -0.250000 0.382683\nv -1.039365 -0.216506 0.430518\nv -1.123906 -0.125000 0.465536\nv -1.082532 0.000000 0.625000\nv -1.053526 0.125000 0.608253\nv -0.974279 0.216506 0.562500\nv -0.866026 0.250000 0.500000\nv -0.757772 0.216506 0.437500\nv -0.678525 0.125000 0.391747\nv -0.649519 0.000000 0.375000\nv -0.678525 -0.125000 0.391747\nv -0.757772 -0.216506 0.437500\nv -0.866026 -0.250000 0.500000\nv -0.974279 -0.216506 0.562500\nv -1.053526 -0.125000 0.608253\nv -0.991692 0.000000 0.760952\nv -0.965119 0.125000 0.740562\nv -0.892522 0.216506 0.684857\nv -0.793353 0.250000 0.608761\nv -0.694184 0.216506 0.532666\nv -0.621587 0.125000 0.476961\nv -0.595015 0.000000 0.456571\nv -0.621587 -0.125000 0.476961\nv -0.694184 -0.216506 0.532666\nv -0.793353 -0.250000 0.608761\nv -0.892522 -0.216506 0.684857\nv -0.965119 -0.125000 0.740562\nv -0.883884 0.000000 0.883883\nv -0.860200 0.125000 0.860200\nv -0.795495 0.216506 0.795495\nv -0.707107 0.250000 0.707107\nv -0.618719 0.216506 0.618718\nv -0.554014 0.125000 0.554013\nv -0.530330 0.000000 0.530330\nv -0.554014 -0.125000 0.554013\nv -0.618719 -0.216506 0.618718\nv -0.707107 -0.250000 0.707107\nv -0.795495 -0.216506 0.795495\nv -0.860200 -0.125000 0.860200\nv -0.760952 0.000000 0.991691\nv -0.740563 0.125000 0.965119\nv -0.684857 0.216506 0.892522\nv -0.608762 0.250000 0.793353\nv -0.532667 0.216506 0.694184\nv -0.476961 0.125000 0.621587\nv -0.456571 0.000000 0.595015\nv -0.476961 -0.125000 0.621587\nv -0.532667 -0.216506 0.694184\nv -0.608762 -0.250000 0.793353\nv -0.684857 -0.216506 0.892522\nv -0.740563 -0.125000 0.965119\nv -0.625000 0.000000 1.082532\nv -0.608253 0.125000 1.053526\nv -0.562500 0.216506 0.974279\nv -0.500000 0.250000 0.866026\nv -0.437500 0.216506 0.757772\nv -0.391747 0.125000 0.678525\nv -0.375000 0.000000 0.649519\nv -0.391747 -0.125000 0.678525\nv -0.437500 -0.216506 0.757772\nv -0.500000 -0.250000 0.866026\nv -0.562500 -0.216506 0.974279\nv -0.608253 -0.125000 1.053526\nv -0.478354 0.000000 1.154849\nv -0.465537 0.125000 1.123905\nv -0.430519 0.216506 1.039364\nv -0.382684 0.250000 0.923880\nv -0.334848 0.216506 0.808395\nv -0.299830 0.125000 0.723854\nv -0.287013 0.000000 0.692910\nv -0.299830 -0.125000 0.723854\nv -0.334848 -0.216506 0.808395\nv -0.382684 -0.250000 0.923880\nv -0.430519 -0.216506 1.039364\nv -0.465537 -0.125000 1.123905\nv -0.323524 0.000000 1.207407\nv -0.314855 0.125000 1.175055\nv -0.291172 0.216506 1.086666\nv -0.258819 0.250000 0.965926\nv -0.226467 0.216506 0.845185\nv -0.202783 0.125000 0.756797\nv -0.194115 0.000000 0.724444\nv -0.202783 -0.125000 0.756797\nv -0.226467 -0.216506 0.845185\nv -0.258819 -0.250000 0.965926\nv -0.291172 -0.216506 1.086666\nv -0.314855 -0.125000 1.175055\nv -0.163158 0.000000 1.239306\nv -0.158787 0.125000 1.206099\nv -0.146843 0.216506 1.115375\nv -0.130527 0.250000 0.991445\nv -0.114211 0.216506 0.867514\nv -0.102267 0.125000 0.776791\nv -0.097895 0.000000 0.743584\nv -0.102267 -0.125000 0.776791\nv -0.114211 -0.216506 0.867514\nv -0.130527 -0.250000 0.991445\nv -0.146843 -0.216506 1.115375\nv -0.158787 -0.125000 1.206099\nv 0.000000 0.000000 1.250000\nv 0.000000 0.125000 1.216506\nv 0.000000 0.216506 1.125000\nv 0.000000 0.250000 1.000000\nv 0.000000 0.216506 0.875000\nv 0.000000 0.125000 0.783494\nv 0.000000 0.000000 0.750000\nv 0.000000 -0.125000 0.783494\nv 0.000000 -0.216506 0.875000\nv 0.000000 -0.250000 1.000000\nv 0.000000 -0.216506 1.125000\nv 0.000000 -0.125000 1.216506\nv 0.163158 0.000000 1.239306\nv 0.158786 0.125000 1.206099\nv 0.146842 0.216506 1.115376\nv 0.130526 0.250000 0.991445\nv 0.114210 0.216506 0.867514\nv 0.102266 0.125000 0.776791\nv 0.097895 0.000000 0.743584\nv 0.102266 -0.125000 0.776791\nv 0.114210 -0.216506 0.867514\nv 0.130526 -0.250000 0.991445\nv 0.146842 -0.216506 1.115376\nv 0.158786 -0.125000 1.206099\nv 0.323523 0.000000 1.207407\nv 0.314854 0.125000 1.175055\nv 0.291171 0.216506 1.086667\nv 0.258819 0.250000 0.965926\nv 0.226466 0.216506 0.845185\nv 0.202783 0.125000 0.756797\nv 0.194114 0.000000 0.724444\nv 0.202783 -0.125000 0.756797\nv 0.226466 -0.216506 0.845185\nv 0.258819 -0.250000 0.965926\nv 0.291171 -0.216506 1.086667\nv 0.314854 -0.125000 1.175055\nv 0.478355 0.000000 1.154849\nv 0.465537 0.125000 1.123905\nv 0.430519 0.216506 1.039364\nv 0.382684 0.250000 0.923879\nv 0.334848 0.216506 0.808394\nv 0.299830 0.125000 0.723854\nv 0.287013 0.000000 0.692910\nv 0.299830 -0.125000 0.723854\nv 0.334848 -0.216506 0.808394\nv 0.382684 -0.250000 0.923879\nv 0.430519 -0.216506 1.039364\nv 0.465537 -0.125000 1.123905\nv 0.625000 0.000000 1.082532\nv 0.608253 0.125000 1.053525\nv 0.562500 0.216506 0.974279\nv 0.500000 0.250000 0.866025\nv 0.437500 0.216506 0.757772\nv 0.391747 0.125000 0.678525\nv 0.375000 0.000000 0.649519\nv 0.391747 -0.125000 0.678525\nv 0.437500 -0.216506 0.757772\nv 0.500000 -0.250000 0.866025\nv 0.562500 -0.216506 0.974279\nv 0.608253 -0.125000 1.053525\nv 0.760952 0.000000 0.991692\nv 0.740562 0.125000 0.965120\nv 0.684856 0.216506 0.892523\nv 0.608761 0.250000 0.793353\nv 0.532666 0.216506 0.694184\nv 0.476961 0.125000 0.621587\nv 0.456571 0.000000 0.595015\nv 0.476961 -0.125000 0.621587\nv 0.532666 -0.216506 0.694184\nv 0.608761 -0.250000 0.793353\nv 0.684856 -0.216506 0.892523\nv 0.740562 -0.125000 0.965120\nv 0.883883 0.000000 0.883884\nv 0.860199 0.125000 0.860200\nv 0.795495 0.216506 0.795496\nv 0.707106 0.250000 0.707107\nv 0.618718 0.216506 0.618719\nv 0.554013 0.125000 0.554014\nv 0.530330 0.000000 0.530330\nv 0.554013 -0.125000 0.554014\nv 0.618718 -0.216506 0.618719\nv 0.707106 -0.250000 0.707107\nv 0.795495 -0.216506 0.795496\nv 0.860199 -0.125000 0.860200\nv 0.991692 0.000000 0.760952\nv 0.965119 0.125000 0.740562\nv 0.892523 0.216506 0.684856\nv 0.793353 0.250000 0.608761\nv 0.694184 0.216506 0.532666\nv 0.621587 0.125000 0.476961\nv 0.595015 0.000000 0.456571\nv 0.621587 -0.125000 0.476961\nv 0.694184 -0.216506 0.532666\nv 0.793353 -0.250000 0.608761\nv 0.892523 -0.216506 0.684856\nv 0.965119 -0.125000 0.740562\nv 1.082532 0.000000 0.625000\nv 1.053525 0.125000 0.608253\nv 0.974279 0.216506 0.562500\nv 0.866025 0.250000 0.500000\nv 0.757772 0.216506 0.437500\nv 0.678525 0.125000 0.391747\nv 0.649519 0.000000 0.375000\nv 0.678525 -0.125000 0.391747\nv 0.757772 -0.216506 0.437500\nv 0.866025 -0.250000 0.500000\nv 0.974279 -0.216506 0.562500\nv 1.053525 -0.125000 0.608253\nv 1.154849 0.000000 0.478355\nv 1.123905 0.125000 0.465537\nv 1.039364 0.216506 0.430519\nv 0.923879 0.250000 0.382684\nv 0.808394 0.216506 0.334848\nv 0.723854 0.125000 0.299830\nv 0.692910 0.000000 0.287013\nv 0.723854 -0.125000 0.299830\nv 0.808394 -0.216506 0.334848\nv 0.923879 -0.250000 0.382684\nv 1.039364 -0.216506 0.430519\nv 1.123905 -0.125000 0.465537\nv 1.207407 0.000000 0.323523\nv 1.175055 0.125000 0.314855\nv 1.086667 0.216506 0.291171\nv 0.965926 0.250000 0.258819\nv 0.845185 0.216506 0.226466\nv 0.756797 0.125000 0.202783\nv 0.724444 0.000000 0.194114\nv 0.756797 -0.125000 0.202783\nv 0.845185 -0.216506 0.226466\nv 0.965926 -0.250000 0.258819\nv 1.086667 -0.216506 0.291171\nv 1.175055 -0.125000 0.314855\nv 1.239306 0.000000 0.163158\nv 1.206099 0.125000 0.158786\nv 1.115376 0.216506 0.146842\nv 0.991445 0.250000 0.130526\nv 0.867514 0.216506 0.114210\nv 0.776791 0.125000 0.102266\nv 0.743584 0.000000 0.097895\nv 0.776791 -0.125000 0.102266\nv 0.867514 -0.216506 0.114210\nv 0.991445 -0.250000 0.130526\nv 1.115376 -0.216506 0.146842\nv 1.206099 -0.125000 0.158786\nvt 0.500000 0.500000\nvt 0.520833 0.500000\nvt 0.520833 0.583333\nvt 0.500000 0.583333\nvt 0.520833 0.666667\nvt 0.500000 0.666667\nvt 0.520833 0.750000\nvt 0.500000 0.750000\nvt 0.520833 0.833333\nvt 0.500000 0.833333\nvt 0.520833 0.916667\nvt 0.500000 0.916667\nvt 0.520833 1.000000\nvt 0.500000 1.000000\nvt 0.500000 0.000000\nvt 0.520833 0.000000\nvt 0.520833 0.083333\nvt 0.500000 0.083333\nvt 0.520833 0.166667\nvt 0.500000 0.166667\nvt 0.520833 0.250000\nvt 0.500000 0.250000\nvt 0.520833 0.333333\nvt 0.500000 0.333333\nvt 0.520833 0.416667\nvt 0.500000 0.416667\nvt 0.541667 0.500000\nvt 0.541667 0.583333\nvt 0.541667 0.666667\nvt 0.541667 0.750000\nvt 0.541667 0.833333\nvt 0.541667 0.916667\nvt 0.541667 1.000000\nvt 0.541667 0.000000\nvt 0.541667 0.083333\nvt 0.541667 0.166667\nvt 0.541667 0.250000\nvt 0.541667 0.333333\nvt 0.541667 0.416667\nvt 0.562500 0.500000\nvt 0.562500 0.583333\nvt 0.562500 0.666667\nvt 0.562500 0.750000\nvt 0.562500 0.833333\nvt 0.562500 0.916667\nvt 0.562500 1.000000\nvt 0.562500 0.000000\nvt 0.562500 0.083333\nvt 0.562500 0.166667\nvt 0.562500 0.250000\nvt 0.562500 0.333333\nvt 0.562500 0.416667\nvt 0.583333 0.500000\nvt 0.583333 0.583333\nvt 0.583333 0.666667\nvt 0.583333 0.750000\nvt 0.583333 0.833333\nvt 0.583333 0.916667\nvt 0.583333 1.000000\nvt 0.583333 0.000000\nvt 0.583333 0.083333\nvt 0.583333 0.166667\nvt 0.583333 0.250000\nvt 0.583333 0.333333\nvt 0.583333 0.416667\nvt 0.604167 0.500000\nvt 0.604167 0.583333\nvt 0.604167 0.666667\nvt 0.604167 0.750000\nvt 0.604167 0.833333\nvt 0.604167 0.916667\nvt 0.604167 1.000000\nvt 0.604167 0.000000\nvt 0.604167 0.083333\nvt 0.604167 0.166667\nvt 0.604167 0.250000\nvt 0.604167 0.333333\nvt 0.604167 0.416667\nvt 0.625000 0.500000\nvt 0.625000 0.583333\nvt 0.625000 0.666667\nvt 0.625000 0.750000\nvt 0.625000 0.833333\nvt 0.625000 0.916667\nvt 0.625000 1.000000\nvt 0.625000 0.000000\nvt 0.625000 0.083333\nvt 0.625000 0.166667\nvt 0.625000 0.250000\nvt 0.625000 0.333333\nvt 0.625000 0.416667\nvt 0.645833 0.500000\nvt 0.645833 0.583333\nvt 0.645833 0.666667\nvt 0.645833 0.750000\nvt 0.645833 0.833333\nvt 0.645833 0.916667\nvt 0.645833 1.000000\nvt 0.645833 0.000000\nvt 0.645833 0.083333\nvt 0.645833 0.166667\nvt 0.645833 0.250000\nvt 0.645833 0.333333\nvt 0.645833 0.416667\nvt 0.666667 0.500000\nvt 0.666667 0.583333\nvt 0.666667 0.666667\nvt 0.666667 0.750000\nvt 0.666667 0.833333\nvt 0.666667 0.916667\nvt 0.666667 1.000000\nvt 0.666667 0.000000\nvt 0.666667 0.083333\nvt 0.666667 0.166667\nvt 0.666667 0.250000\nvt 0.666667 0.333333\nvt 0.666667 0.416667\nvt 0.687500 0.500000\nvt 0.687500 0.583333\nvt 0.687500 0.666667\nvt 0.687500 0.750000\nvt 0.687500 0.833333\nvt 0.687500 0.916667\nvt 0.687500 1.000000\nvt 0.687500 0.000000\nvt 0.687500 0.083333\nvt 0.687500 0.166667\nvt 0.687500 0.250000\nvt 0.687500 0.333333\nvt 0.687500 0.416667\nvt 0.708333 0.500000\nvt 0.708333 0.583333\nvt 0.708333 0.666667\nvt 0.708333 0.750000\nvt 0.708333 0.833333\nvt 0.708333 0.916667\nvt 0.708333 1.000000\nvt 0.708333 0.000000\nvt 0.708333 0.083333\nvt 0.708333 0.166667\nvt 0.708333 0.250000\nvt 0.708333 0.333333\nvt 0.708333 0.416667\nvt 0.729167 0.500000\nvt 0.729167 0.583333\nvt 0.729167 0.666667\nvt 0.729167 0.750000\nvt 0.729167 0.833333\nvt 0.729167 0.916667\nvt 0.729167 1.000000\nvt 0.729167 0.000000\nvt 0.729167 0.083333\nvt 0.729167 0.166667\nvt 0.729167 0.250000\nvt 0.729167 0.333333\nvt 0.729167 0.416667\nvt 0.750000 0.500000\nvt 0.750000 0.583333\nvt 0.750000 0.666667\nvt 0.750000 0.750000\nvt 0.750000 0.833333\nvt 0.750000 0.916667\nvt 0.750000 1.000000\nvt 0.750000 0.000000\nvt 0.750000 0.083333\nvt 0.750000 0.166667\nvt 0.750000 0.250000\nvt 0.750000 0.333333\nvt 0.750000 0.416667\nvt 0.770833 0.500000\nvt 0.770833 0.583333\nvt 0.770833 0.666667\nvt 0.770833 0.750000\nvt 0.770833 0.833333\nvt 0.770833 0.916667\nvt 0.770833 1.000000\nvt 0.770833 0.000000\nvt 0.770833 0.083333\nvt 0.770833 0.166667\nvt 0.770833 0.250000\nvt 0.770833 0.333333\nvt 0.770833 0.416667\nvt 0.791667 0.500000\nvt 0.791667 0.583333\nvt 0.791667 0.666667\nvt 0.791667 0.750000\nvt 0.791667 0.833333\nvt 0.791667 0.916667\nvt 0.791667 1.000000\nvt 0.791667 0.000000\nvt 0.791667 0.083333\nvt 0.791667 0.166667\nvt 0.791667 0.250000\nvt 0.791667 0.333333\nvt 0.791667 0.416667\nvt 0.812500 0.500000\nvt 0.812500 0.583333\nvt 0.812500 0.666667\nvt 0.812500 0.750000\nvt 0.812500 0.833333\nvt 0.812500 0.916667\nvt 0.812500 1.000000\nvt 0.812500 0.000000\nvt 0.812500 0.083333\nvt 0.812500 0.166667\nvt 0.812500 0.250000\nvt 0.812500 0.333333\nvt 0.812500 0.416667\nvt 0.833333 0.500000\nvt 0.833333 0.583333\nvt 0.833333 0.666667\nvt 0.833333 0.750000\nvt 0.833333 0.833333\nvt 0.833333 0.916667\nvt 0.833333 1.000000\nvt 0.833333 0.000000\nvt 0.833333 0.083333\nvt 0.833333 0.166667\nvt 0.833333 0.250000\nvt 0.833333 0.333333\nvt 0.833333 0.416667\nvt 0.854167 0.500000\nvt 0.854167 0.583333\nvt 0.854167 0.666667\nvt 0.854167 0.750000\nvt 0.854167 0.833333\nvt 0.854167 0.916667\nvt 0.854167 1.000000\nvt 0.854167 0.000000\nvt 0.854167 0.083333\nvt 0.854167 0.166667\nvt 0.854167 0.250000\nvt 0.854167 0.333333\nvt 0.854167 0.416667\nvt 0.875000 0.500000\nvt 0.875000 0.583333\nvt 0.875000 0.666667\nvt 0.875000 0.750000\nvt 0.875000 0.833333\nvt 0.875000 0.916667\nvt 0.875000 1.000000\nvt 0.875000 0.000000\nvt 0.875000 0.083333\nvt 0.875000 0.166667\nvt 0.875000 0.250000\nvt 0.875000 0.333333\nvt 0.875000 0.416667\nvt 0.895833 0.500000\nvt 0.895833 0.583333\nvt 0.895833 0.666667\nvt 0.895833 0.750000\nvt 0.895833 0.833333\nvt 0.895833 0.916667\nvt 0.895833 1.000000\nvt 0.895833 0.000000\nvt 0.895833 0.083333\nvt 0.895833 0.166667\nvt 0.895833 0.250000\nvt 0.895833 0.333333\nvt 0.895833 0.416667\nvt 0.916667 0.500000\nvt 0.916667 0.583333\nvt 0.916667 0.666667\nvt 0.916667 0.750000\nvt 0.916667 0.833333\nvt 0.916667 0.916667\nvt 0.916667 1.000000\nvt 0.916667 0.000000\nvt 0.916667 0.083333\nvt 0.916667 0.166667\nvt 0.916667 0.250000\nvt 0.916667 0.333333\nvt 0.916667 0.416667\nvt 0.937500 0.500000\nvt 0.937500 0.583333\nvt 0.937500 0.666667\nvt 0.937500 0.750000\nvt 0.937500 0.833333\nvt 0.937500 0.916667\nvt 0.937500 1.000000\nvt 0.937500 0.000000\nvt 0.937500 0.083333\nvt 0.937500 0.166667\nvt 0.937500 0.250000\nvt 0.937500 0.333333\nvt 0.937500 0.416667\nvt 0.958333 0.500000\nvt 0.958333 0.583333\nvt 0.958333 0.666667\nvt 0.958333 0.750000\nvt 0.958333 0.833333\nvt 0.958333 0.916667\nvt 0.958333 1.000000\nvt 0.958333 0.000000\nvt 0.958333 0.083333\nvt 0.958333 0.166667\nvt 0.958333 0.250000\nvt 0.958333 0.333333\nvt 0.958333 0.416667\nvt 0.979167 0.500000\nvt 0.979167 0.583333\nvt 0.979167 0.666667\nvt 0.979167 0.750000\nvt 0.979167 0.833333\nvt 0.979167 0.916667\nvt 0.979167 1.000000\nvt 0.979167 0.000000\nvt 0.979167 0.083333\nvt 0.979167 0.166667\nvt 0.979167 0.250000\nvt 0.979167 0.333333\nvt 0.979167 0.416667\nvt 1.000000 0.500000\nvt 1.000000 0.583333\nvt 1.000000 0.666667\nvt 1.000000 0.750000\nvt 1.000000 0.833333\nvt 1.000000 0.916667\nvt 1.000000 1.000000\nvt 1.000000 0.000000\nvt 1.000000 0.083333\nvt 1.000000 0.166667\nvt 1.000000 0.250000\nvt 1.000000 0.333333\nvt 1.000000 0.416667\nvt 0.000000 0.500000\nvt 0.020833 0.500000\nvt 0.020833 0.583333\nvt 0.000000 0.583333\nvt 0.020833 0.666667\nvt 0.000000 0.666667\nvt 0.020833 0.750000\nvt 0.000000 0.750000\nvt 0.020833 0.833333\nvt 0.000000 0.833333\nvt 0.020833 0.916667\nvt 0.000000 0.916667\nvt 0.020833 1.000000\nvt 0.000000 1.000000\nvt 0.000000 0.000000\nvt 0.020833 0.000000\nvt 0.020833 0.083333\nvt 0.000000 0.083333\nvt 0.020833 0.166667\nvt 0.000000 0.166667\nvt 0.020833 0.250000\nvt 0.000000 0.250000\nvt 0.020833 0.333333\nvt 0.000000 0.333333\nvt 0.020833 0.416667\nvt 0.000000 0.416667\nvt 0.041667 0.500000\nvt 0.041667 0.583333\nvt 0.041667 0.666667\nvt 0.041667 0.750000\nvt 0.041667 0.833333\nvt 0.041667 0.916667\nvt 0.041667 1.000000\nvt 0.041667 0.000000\nvt 0.041667 0.083333\nvt 0.041667 0.166667\nvt 0.041667 0.250000\nvt 0.041667 0.333333\nvt 0.041667 0.416667\nvt 0.062500 0.500000\nvt 0.062500 0.583333\nvt 0.062500 0.666667\nvt 0.062500 0.750000\nvt 0.062500 0.833333\nvt 0.062500 0.916667\nvt 0.062500 1.000000\nvt 0.062500 0.000000\nvt 0.062500 0.083333\nvt 0.062500 0.166667\nvt 0.062500 0.250000\nvt 0.062500 0.333333\nvt 0.062500 0.416667\nvt 0.083333 0.500000\nvt 0.083333 0.583333\nvt 0.083333 0.666667\nvt 0.083333 0.750000\nvt 0.083333 0.833333\nvt 0.083333 0.916667\nvt 0.083333 1.000000\nvt 0.083333 0.000000\nvt 0.083333 0.083333\nvt 0.083333 0.166667\nvt 0.083333 0.250000\nvt 0.083333 0.333333\nvt 0.083333 0.416667\nvt 0.104167 0.500000\nvt 0.104167 0.583333\nvt 0.104167 0.666667\nvt 0.104167 0.750000\nvt 0.104167 0.833333\nvt 0.104167 0.916667\nvt 0.104167 1.000000\nvt 0.104167 0.000000\nvt 0.104167 0.083333\nvt 0.104167 0.166667\nvt 0.104167 0.250000\nvt 0.104167 0.333333\nvt 0.104167 0.416667\nvt 0.125000 0.500000\nvt 0.125000 0.583333\nvt 0.125000 0.666667\nvt 0.125000 0.750000\nvt 0.125000 0.833333\nvt 0.125000 0.916667\nvt 0.125000 1.000000\nvt 0.125000 0.000000\nvt 0.125000 0.083333\nvt 0.125000 0.166667\nvt 0.125000 0.250000\nvt 0.125000 0.333333\nvt 0.125000 0.416667\nvt 0.145833 0.500000\nvt 0.145833 0.583333\nvt 0.145833 0.666667\nvt 0.145833 0.750000\nvt 0.145833 0.833333\nvt 0.145833 0.916667\nvt 0.145833 1.000000\nvt 0.145833 0.000000\nvt 0.145833 0.083333\nvt 0.145833 0.166667\nvt 0.145833 0.250000\nvt 0.145833 0.333333\nvt 0.145833 0.416667\nvt 0.166667 0.500000\nvt 0.166667 0.583333\nvt 0.166667 0.666667\nvt 0.166667 0.750000\nvt 0.166667 0.833333\nvt 0.166667 0.916667\nvt 0.166667 1.000000\nvt 0.166667 0.000000\nvt 0.166667 0.083333\nvt 0.166667 0.166667\nvt 0.166667 0.250000\nvt 0.166667 0.333333\nvt 0.166667 0.416667\nvt 0.187500 0.500000\nvt 0.187500 0.583333\nvt 0.187500 0.666667\nvt 0.187500 0.750000\nvt 0.187500 0.833333\nvt 0.187500 0.916667\nvt 0.187500 1.000000\nvt 0.187500 0.000000\nvt 0.187500 0.083333\nvt 0.187500 0.166667\nvt 0.187500 0.250000\nvt 0.187500 0.333333\nvt 0.187500 0.416667\nvt 0.208333 0.500000\nvt 0.208333 0.583333\nvt 0.208333 0.666667\nvt 0.208333 0.750000\nvt 0.208333 0.833333\nvt 0.208333 0.916667\nvt 0.208333 1.000000\nvt 0.208333 0.000000\nvt 0.208333 0.083333\nvt 0.208333 0.166667\nvt 0.208333 0.250000\nvt 0.208333 0.333333\nvt 0.208333 0.416667\nvt 0.229167 0.500000\nvt 0.229167 0.583333\nvt 0.229167 0.666667\nvt 0.229167 0.750000\nvt 0.229167 0.833333\nvt 0.229167 0.916667\nvt 0.229167 1.000000\nvt 0.229167 0.000000\nvt 0.229167 0.083333\nvt 0.229167 0.166667\nvt 0.229167 0.250000\nvt 0.229167 0.333333\nvt 0.229167 0.416667\nvt 0.250000 0.500000\nvt 0.250000 0.583333\nvt 0.250000 0.666667\nvt 0.250000 0.750000\nvt 0.250000 0.833333\nvt 0.250000 0.916667\nvt 0.250000 1.000000\nvt 0.250000 0.000000\nvt 0.250000 0.083333\nvt 0.250000 0.166667\nvt 0.250000 0.250000\nvt 0.250000 0.333333\nvt 0.250000 0.416667\nvt 0.270833 0.500000\nvt 0.270833 0.583333\nvt 0.270833 0.666667\nvt 0.270833 0.750000\nvt 0.270833 0.833333\nvt 0.270833 0.916667\nvt 0.270833 1.000000\nvt 0.270833 0.000000\nvt 0.270833 0.083333\nvt 0.270833 0.166667\nvt 0.270833 0.250000\nvt 0.270833 0.333333\nvt 0.270833 0.416667\nvt 0.291667 0.500000\nvt 0.291667 0.583333\nvt 0.291667 0.666667\nvt 0.291667 0.750000\nvt 0.291667 0.833333\nvt 0.291667 0.916667\nvt 0.291667 1.000000\nvt 0.291667 0.000000\nvt 0.291667 0.083333\nvt 0.291667 0.166667\nvt 0.291667 0.250000\nvt 0.291667 0.333333\nvt 0.291667 0.416667\nvt 0.312500 0.500000\nvt 0.312500 0.583333\nvt 0.312500 0.666667\nvt 0.312500 0.750000\nvt 0.312500 0.833333\nvt 0.312500 0.916667\nvt 0.312500 1.000000\nvt 0.312500 0.000000\nvt 0.312500 0.083333\nvt 0.312500 0.166667\nvt 0.312500 0.250000\nvt 0.312500 0.333333\nvt 0.312500 0.416667\nvt 0.333333 0.500000\nvt 0.333333 0.583333\nvt 0.333333 0.666667\nvt 0.333333 0.750000\nvt 0.333333 0.833333\nvt 0.333333 0.916667\nvt 0.333333 1.000000\nvt 0.333333 0.000000\nvt 0.333333 0.083333\nvt 0.333333 0.166667\nvt 0.333333 0.250000\nvt 0.333333 0.333333\nvt 0.333333 0.416667\nvt 0.354167 0.500000\nvt 0.354167 0.583333\nvt 0.354167 0.666667\nvt 0.354167 0.750000\nvt 0.354167 0.833333\nvt 0.354167 0.916667\nvt 0.354167 1.000000\nvt 0.354167 0.000000\nvt 0.354167 0.083333\nvt 0.354167 0.166667\nvt 0.354167 0.250000\nvt 0.354167 0.333333\nvt 0.354167 0.416667\nvt 0.375000 0.500000\nvt 0.375000 0.583333\nvt 0.375000 0.666667\nvt 0.375000 0.750000\nvt 0.375000 0.833333\nvt 0.375000 0.916667\nvt 0.375000 1.000000\nvt 0.375000 0.000000\nvt 0.375000 0.083333\nvt 0.375000 0.166667\nvt 0.375000 0.250000\nvt 0.375000 0.333333\nvt 0.375000 0.416667\nvt 0.395833 0.500000\nvt 0.395833 0.583333\nvt 0.395833 0.666667\nvt 0.395833 0.750000\nvt 0.395833 0.833333\nvt 0.395833 0.916667\nvt 0.395833 1.000000\nvt 0.395833 0.000000\nvt 0.395833 0.083333\nvt 0.395833 0.166667\nvt 0.395833 0.250000\nvt 0.395833 0.333333\nvt 0.395833 0.416667\nvt 0.416667 0.500000\nvt 0.416667 0.583333\nvt 0.416667 0.666667\nvt 0.416667 0.750000\nvt 0.416667 0.833333\nvt 0.416667 0.916667\nvt 0.416667 1.000000\nvt 0.416667 0.000000\nvt 0.416667 0.083333\nvt 0.416667 0.166667\nvt 0.416667 0.250000\nvt 0.416667 0.333333\nvt 0.416667 0.416667\nvt 0.437500 0.500000\nvt 0.437500 0.583333\nvt 0.437500 0.666667\nvt 0.437500 0.750000\nvt 0.437500 0.833333\nvt 0.437500 0.916667\nvt 0.437500 1.000000\nvt 0.437500 0.000000\nvt 0.437500 0.083333\nvt 0.437500 0.166667\nvt 0.437500 0.250000\nvt 0.437500 0.333333\nvt 0.437500 0.416667\nvt 0.458333 0.500000\nvt 0.458333 0.583333\nvt 0.458333 0.666667\nvt 0.458333 0.750000\nvt 0.458333 0.833333\nvt 0.458333 0.916667\nvt 0.458333 1.000000\nvt 0.458333 0.000000\nvt 0.458333 0.083333\nvt 0.458333 0.166667\nvt 0.458333 0.250000\nvt 0.458333 0.333333\nvt 0.458333 0.416667\nvt 0.479167 0.500000\nvt 0.479167 0.583333\nvt 0.479167 0.666667\nvt 0.479167 0.750000\nvt 0.479167 0.833333\nvt 0.479167 0.916667\nvt 0.479167 1.000000\nvt 0.479167 0.000000\nvt 0.479167 0.083333\nvt 0.479167 0.166667\nvt 0.479167 0.250000\nvt 0.479167 0.333333\nvt 0.479167 0.416667\nvn 0.9640 0.2583 -0.0632\nvn 0.7063 0.7063 -0.0463\nvn 0.2588 0.9658 -0.0170\nvn -0.2588 0.9658 0.0170\nvn -0.7063 0.7063 0.0463\nvn -0.9640 0.2583 0.0632\nvn -0.9640 -0.2583 0.0632\nvn -0.7063 -0.7063 0.0463\nvn -0.2588 -0.9658 0.0170\nvn 0.2588 -0.9658 -0.0170\nvn 0.7063 -0.7063 -0.0463\nvn 0.9640 -0.2583 -0.0632\nvn 0.9475 0.2583 -0.1885\nvn 0.6943 0.7063 -0.1381\nvn 0.2544 0.9658 -0.0506\nvn -0.2544 0.9658 0.0506\nvn -0.6943 0.7063 0.1381\nvn -0.9475 0.2583 0.1885\nvn -0.9475 -0.2583 0.1885\nvn -0.6943 -0.7063 0.1381\nvn -0.2544 -0.9658 0.0506\nvn 0.2544 -0.9658 -0.0506\nvn 0.6943 -0.7063 -0.1381\nvn 0.9475 -0.2583 -0.1885\nvn 0.9148 0.2583 -0.3105\nvn 0.6703 0.7063 -0.2275\nvn 0.2456 0.9658 -0.0834\nvn -0.2456 0.9658 0.0834\nvn -0.6703 0.7063 0.2275\nvn -0.9148 0.2583 0.3105\nvn -0.9148 -0.2583 0.3105\nvn -0.6703 -0.7063 0.2275\nvn -0.2456 -0.9658 0.0834\nvn 0.2456 -0.9658 -0.0834\nvn 0.6703 -0.7063 -0.2275\nvn 0.9148 -0.2583 -0.3105\nvn 0.8664 0.2583 -0.4273\nvn 0.6349 0.7063 -0.3131\nvn 0.2326 0.9658 -0.1147\nvn -0.2326 0.9658 0.1147\nvn -0.6349 0.7063 0.3131\nvn -0.8664 0.2583 0.4273\nvn -0.8664 -0.2583 0.4273\nvn -0.6349 -0.7063 0.3131\nvn -0.2326 -0.9658 0.1147\nvn 0.2326 -0.9658 -0.1147\nvn 0.6349 -0.7063 -0.3131\nvn 0.8664 -0.2583 -0.4273\nvn 0.8033 0.2583 -0.5367\nvn 0.5886 0.7063 -0.3933\nvn 0.2156 0.9658 -0.1441\nvn -0.2156 0.9658 0.1441\nvn -0.5886 0.7063 0.3933\nvn -0.8033 0.2583 0.5367\nvn -0.8033 -0.2583 0.5367\nvn -0.5886 -0.7063 0.3933\nvn -0.2156 -0.9658 0.1441\nvn 0.2156 -0.9658 -0.1441\nvn 0.5886 -0.7063 -0.3933\nvn 0.8033 -0.2583 -0.5367\nvn 0.7263 0.2583 -0.6370\nvn 0.5322 0.7063 -0.4667\nvn 0.1950 0.9658 -0.1710\nvn -0.1950 0.9658 0.1710\nvn -0.5322 0.7063 0.4667\nvn -0.7263 0.2583 0.6370\nvn -0.7263 -0.2583 0.6370\nvn -0.5322 -0.7063 0.4667\nvn -0.1950 -0.9658 0.1710\nvn 0.1950 -0.9658 -0.1710\nvn 0.5322 -0.7063 -0.4667\nvn 0.7263 -0.2583 -0.6370\nvn 0.6370 0.2583 -0.7263\nvn 0.4667 0.7063 -0.5322\nvn 0.1710 0.9658 -0.1950\nvn -0.1710 0.9658 0.1950\nvn -0.4667 0.7063 0.5322\nvn -0.6370 0.2583 0.7263\nvn -0.6370 -0.2583 0.7263\nvn -0.4667 -0.7063 0.5322\nvn -0.1710 -0.9658 0.1950\nvn 0.1710 -0.9658 -0.1950\nvn 0.4667 -0.7063 -0.5322\nvn 0.6370 -0.2583 -0.7263\nvn 0.5367 0.2583 -0.8033\nvn 0.3933 0.7063 -0.5886\nvn 0.1441 0.9658 -0.2156\nvn -0.1441 0.9658 0.2156\nvn -0.3933 0.7063 0.5886\nvn -0.5367 0.2583 0.8033\nvn -0.5367 -0.2583 0.8033\nvn -0.3933 -0.7063 0.5886\nvn -0.1441 -0.9658 0.2156\nvn 0.1441 -0.9658 -0.2156\nvn 0.3933 -0.7063 -0.5886\nvn 0.5367 -0.2583 -0.8033\nvn 0.4273 0.2583 -0.8664\nvn 0.3131 0.7063 -0.6349\nvn 0.1147 0.9658 -0.2326\nvn -0.1147 0.9658 0.2326\nvn -0.3131 0.7063 0.6349\nvn -0.4273 0.2583 0.8664\nvn -0.4273 -0.2583 0.8664\nvn -0.3131 -0.7063 0.6349\nvn -0.1147 -0.9658 0.2326\nvn 0.1147 -0.9658 -0.2326\nvn 0.3131 -0.7063 -0.6349\nvn 0.4273 -0.2583 -0.8664\nvn 0.3105 0.2583 -0.9148\nvn 0.2275 0.7063 -0.6703\nvn 0.0834 0.9658 -0.2456\nvn -0.0834 0.9658 0.2456\nvn -0.2275 0.7063 0.6703\nvn -0.3105 0.2583 0.9148\nvn -0.3105 -0.2583 0.9148\nvn -0.2275 -0.7063 0.6703\nvn -0.0834 -0.9658 0.2456\nvn 0.0834 -0.9658 -0.2456\nvn 0.2275 -0.7063 -0.6703\nvn 0.3105 -0.2583 -0.9148\nvn 0.1885 0.2583 -0.9475\nvn 0.1381 0.7063 -0.6943\nvn 0.0506 0.9658 -0.2544\nvn -0.0506 0.9658 0.2544\nvn -0.1381 0.7063 0.6943\nvn -0.1885 0.2583 0.9475\nvn -0.1885 -0.2583 0.9475\nvn -0.1381 -0.7063 0.6943\nvn -0.0506 -0.9658 0.2544\nvn 0.0506 -0.9658 -0.2544\nvn 0.1381 -0.7063 -0.6943\nvn 0.1885 -0.2583 -0.9475\nvn 0.0632 0.2583 -0.9640\nvn 0.0463 0.7063 -0.7063\nvn 0.0170 0.9658 -0.2588\nvn -0.0170 0.9658 0.2588\nvn -0.0463 0.7063 0.7063\nvn -0.0632 0.2583 0.9640\nvn -0.0632 -0.2583 0.9640\nvn -0.0463 -0.7063 0.7063\nvn -0.0170 -0.9658 0.2588\nvn 0.0170 -0.9658 -0.2588\nvn 0.0463 -0.7063 -0.7063\nvn 0.0632 -0.2583 -0.9640\nvn -0.0632 0.2583 -0.9640\nvn -0.0463 0.7063 -0.7063\nvn -0.0170 0.9658 -0.2588\nvn 0.0170 0.9658 0.2588\nvn 0.0463 0.7063 0.7063\nvn 0.0632 0.2583 0.9640\nvn 0.0632 -0.2583 0.9640\nvn 0.0463 -0.7063 0.7063\nvn 0.0170 -0.9658 0.2588\nvn -0.0170 -0.9658 -0.2588\nvn -0.0463 -0.7063 -0.7063\nvn -0.0632 -0.2583 -0.9640\nvn -0.1885 0.2583 -0.9475\nvn -0.1381 0.7063 -0.6943\nvn -0.0506 0.9658 -0.2544\nvn 0.0506 0.9658 0.2544\nvn 0.1381 0.7063 0.6943\nvn 0.1885 0.2583 0.9475\nvn 0.1885 -0.2583 0.9475\nvn 0.1381 -0.7063 0.6943\nvn 0.0506 -0.9658 0.2544\nvn -0.0506 -0.9658 -0.2544\nvn -0.1381 -0.7063 -0.6943\nvn -0.1885 -0.2583 -0.9475\nvn -0.3105 0.2583 -0.9148\nvn -0.2275 0.7063 -0.6703\nvn -0.0834 0.9658 -0.2456\nvn 0.0834 0.9658 0.2456\nvn 0.2275 0.7063 0.6703\nvn 0.3105 0.2583 0.9148\nvn 0.3105 -0.2583 0.9148\nvn 0.2275 -0.7063 0.6703\nvn 0.0834 -0.9658 0.2456\nvn -0.0834 -0.9658 -0.2456\nvn -0.2275 -0.7063 -0.6703\nvn -0.3105 -0.2583 -0.9148\nvn -0.4273 0.2583 -0.8664\nvn -0.3131 0.7063 -0.6349\nvn -0.1147 0.9658 -0.2326\nvn 0.1147 0.9658 0.2326\nvn 0.3131 0.7063 0.6349\nvn 0.4273 0.2583 0.8664\nvn 0.4273 -0.2583 0.8664\nvn 0.3131 -0.7063 0.6349\nvn 0.1147 -0.9658 0.2326\nvn -0.1147 -0.9658 -0.2326\nvn -0.3131 -0.7063 -0.6349\nvn -0.4273 -0.2583 -0.8664\nvn -0.5367 0.2583 -0.8033\nvn -0.3933 0.7063 -0.5886\nvn -0.1441 0.9658 -0.2156\nvn 0.1441 0.9658 0.2156\nvn 0.3933 0.7063 0.5886\nvn 0.5367 0.2583 0.8033\nvn 0.5367 -0.2583 0.8033\nvn 0.3933 -0.7063 0.5886\nvn 0.1441 -0.9658 0.2156\nvn -0.1441 -0.9658 -0.2156\nvn -0.3933 -0.7063 -0.5886\nvn -0.5367 -0.2583 -0.8033\nvn -0.6370 0.2583 -0.7263\nvn -0.4667 0.7063 -0.5322\nvn -0.1710 0.9658 -0.1950\nvn 0.1710 0.9658 0.1950\nvn 0.4667 0.7063 0.5322\nvn 0.6370 0.2583 0.7263\nvn 0.6370 -0.2583 0.7263\nvn 0.4667 -0.7063 0.5322\nvn 0.1710 -0.9658 0.1950\nvn -0.1710 -0.9658 -0.1950\nvn -0.4667 -0.7063 -0.5322\nvn -0.6370 -0.2583 -0.7263\nvn -0.7263 0.2583 -0.6370\nvn -0.5322 0.7063 -0.4667\nvn -0.1950 0.9658 -0.1710\nvn 0.1950 0.9658 0.1710\nvn 0.5322 0.7063 0.4667\nvn 0.7263 0.2583 0.6370\nvn 0.7263 -0.2583 0.6370\nvn 0.5322 -0.7063 0.4667\nvn 0.1950 -0.9658 0.1710\nvn -0.1950 -0.9658 -0.1710\nvn -0.5322 -0.7063 -0.4667\nvn -0.7263 -0.2583 -0.6370\nvn -0.8033 0.2583 -0.5367\nvn -0.5886 0.7063 -0.3933\nvn -0.2156 0.9658 -0.1441\nvn 0.2156 0.9658 0.1441\nvn 0.5886 0.7063 0.3933\nvn 0.8033 0.2583 0.5367\nvn 0.8033 -0.2583 0.5367\nvn 0.5886 -0.7063 0.3933\nvn 0.2156 -0.9658 0.1441\nvn -0.2156 -0.9658 -0.1441\nvn -0.5886 -0.7063 -0.3933\nvn -0.8033 -0.2583 -0.5367\nvn -0.8664 0.2583 -0.4273\nvn -0.6349 0.7063 -0.3131\nvn -0.2326 0.9658 -0.1147\nvn 0.2326 0.9658 0.1147\nvn 0.6349 0.7063 0.3131\nvn 0.8664 0.2583 0.4273\nvn 0.8664 -0.2583 0.4273\nvn 0.6349 -0.7063 0.3131\nvn 0.2326 -0.9658 0.1147\nvn -0.2326 -0.9658 -0.1147\nvn -0.6349 -0.7063 -0.3131\nvn -0.8664 -0.2583 -0.4273\nvn -0.9148 0.2583 -0.3105\nvn -0.6703 0.7063 -0.2275\nvn -0.2456 0.9658 -0.0834\nvn 0.2456 0.9658 0.0834\nvn 0.6703 0.7063 0.2275\nvn 0.9148 0.2583 0.3105\nvn 0.9148 -0.2583 0.3105\nvn 0.6703 -0.7063 0.2275\nvn 0.2456 -0.9658 0.0834\nvn -0.2456 -0.9658 -0.0834\nvn -0.6703 -0.7063 -0.2275\nvn -0.9148 -0.2583 -0.3105\nvn -0.9475 0.2583 -0.1885\nvn -0.6943 0.7063 -0.1381\nvn -0.2544 0.9658 -0.0506\nvn 0.2544 0.9658 0.0506\nvn 0.6943 0.7063 0.1381\nvn 0.9475 0.2583 0.1885\nvn 0.9475 -0.2583 0.1885\nvn 0.6943 -0.7063 0.1381\nvn 0.2544 -0.9658 0.0506\nvn -0.2544 -0.9658 -0.0506\nvn -0.6943 -0.7063 -0.1381\nvn -0.9475 -0.2583 -0.1885\nvn -0.9640 0.2583 -0.0632\nvn -0.7063 0.7063 -0.0463\nvn -0.2588 0.9658 -0.0170\nvn 0.2588 0.9658 0.0170\nvn 0.7063 0.7063 0.0463\nvn 0.9640 0.2583 0.0632\nvn 0.9640 -0.2583 0.0632\nvn 0.7063 -0.7063 0.0463\nvn 0.2588 -0.9658 0.0170\nvn -0.2588 -0.9658 -0.0170\nvn -0.7063 -0.7063 -0.0463\nvn -0.9640 -0.2583 -0.0632\nusemtl None\ns off\nf 1/1/1 13/2/1 14/3/1 2/4/1\nf 2/4/2 14/3/2 15/5/2 3/6/2\nf 3/6/3 15/5/3 16/7/3 4/8/3\nf 4/8/4 16/7/4 17/9/4 5/10/4\nf 5/10/5 17/9/5 18/11/5 6/12/5\nf 6/12/6 18/11/6 19/13/6 7/14/6\nf 7/15/7 19/16/7 20/17/7 8/18/7\nf 8/18/8 20/17/8 21/19/8 9/20/8\nf 9/20/9 21/19/9 22/21/9 10/22/9\nf 10/22/10 22/21/10 23/23/10 11/24/10\nf 11/24/11 23/23/11 24/25/11 12/26/11\nf 12/26/12 24/25/12 13/2/12 1/1/12\nf 13/2/13 25/27/13 26/28/13 14/3/13\nf 14/3/14 26/28/14 27/29/14 15/5/14\nf 15/5/15 27/29/15 28/30/15 16/7/15\nf 16/7/16 28/30/16 29/31/16 17/9/16\nf 17/9/17 29/31/17 30/32/17 18/11/17\nf 18/11/18 30/32/18 31/33/18 19/13/18\nf 19/16/19 31/34/19 32/35/19 20/17/19\nf 20/17/20 32/35/20 33/36/20 21/19/20\nf 21/19/21 33/36/21 34/37/21 22/21/21\nf 22/21/22 34/37/22 35/38/22 23/23/22\nf 23/23/23 35/38/23 36/39/23 24/25/23\nf 24/25/24 36/39/24 25/27/24 13/2/24\nf 25/27/25 37/40/25 38/41/25 26/28/25\nf 26/28/26 38/41/26 39/42/26 27/29/26\nf 27/29/27 39/42/27 40/43/27 28/30/27\nf 28/30/28 40/43/28 41/44/28 29/31/28\nf 29/31/29 41/44/29 42/45/29 30/32/29\nf 30/32/30 42/45/30 43/46/30 31/33/30\nf 31/34/31 43/47/31 44/48/31 32/35/31\nf 32/35/32 44/48/32 45/49/32 33/36/32\nf 33/36/33 45/49/33 46/50/33 34/37/33\nf 34/37/34 46/50/34 47/51/34 35/38/34\nf 35/38/35 47/51/35 48/52/35 36/39/35\nf 36/39/36 48/52/36 37/40/36 25/27/36\nf 37/40/37 49/53/37 50/54/37 38/41/37\nf 38/41/38 50/54/38 51/55/38 39/42/38\nf 39/42/39 51/55/39 52/56/39 40/43/39\nf 40/43/40 52/56/40 53/57/40 41/44/40\nf 41/44/41 53/57/41 54/58/41 42/45/41\nf 42/45/42 54/58/42 55/59/42 43/46/42\nf 43/47/43 55/60/43 56/61/43 44/48/43\nf 44/48/44 56/61/44 57/62/44 45/49/44\nf 45/49/45 57/62/45 58/63/45 46/50/45\nf 46/50/46 58/63/46 59/64/46 47/51/46\nf 47/51/47 59/64/47 60/65/47 48/52/47\nf 48/52/48 60/65/48 49/53/48 37/40/48\nf 49/53/49 61/66/49 62/67/49 50/54/49\nf 50/54/50 62/67/50 63/68/50 51/55/50\nf 51/55/51 63/68/51 64/69/51 52/56/51\nf 52/56/52 64/69/52 65/70/52 53/57/52\nf 53/57/53 65/70/53 66/71/53 54/58/53\nf 54/58/54 66/71/54 67/72/54 55/59/54\nf 55/60/55 67/73/55 68/74/55 56/61/55\nf 56/61/56 68/74/56 69/75/56 57/62/56\nf 57/62/57 69/75/57 70/76/57 58/63/57\nf 58/63/58 70/76/58 71/77/58 59/64/58\nf 59/64/59 71/77/59 72/78/59 60/65/59\nf 60/65/60 72/78/60 61/66/60 49/53/60\nf 61/66/61 73/79/61 74/80/61 62/67/61\nf 62/67/62 74/80/62 75/81/62 63/68/62\nf 63/68/63 75/81/63 76/82/63 64/69/63\nf 64/69/64 76/82/64 77/83/64 65/70/64\nf 65/70/65 77/83/65 78/84/65 66/71/65\nf 66/71/66 78/84/66 79/85/66 67/72/66\nf 67/73/67 79/86/67 80/87/67 68/74/67\nf 68/74/68 80/87/68 81/88/68 69/75/68\nf 69/75/69 81/88/69 82/89/69 70/76/69\nf 70/76/70 82/89/70 83/90/70 71/77/70\nf 71/77/71 83/90/71 84/91/71 72/78/71\nf 72/78/72 84/91/72 73/79/72 61/66/72\nf 73/79/73 85/92/73 86/93/73 74/80/73\nf 74/80/74 86/93/74 87/94/74 75/81/74\nf 75/81/75 87/94/75 88/95/75 76/82/75\nf 76/82/76 88/95/76 89/96/76 77/83/76\nf 77/83/77 89/96/77 90/97/77 78/84/77\nf 78/84/78 90/97/78 91/98/78 79/85/78\nf 79/86/79 91/99/79 92/100/79 80/87/79\nf 80/87/80 92/100/80 93/101/80 81/88/80\nf 81/88/81 93/101/81 94/102/81 82/89/81\nf 82/89/82 94/102/82 95/103/82 83/90/82\nf 83/90/83 95/103/83 96/104/83 84/91/83\nf 84/91/84 96/104/84 85/92/84 73/79/84\nf 85/92/85 97/105/85 98/106/85 86/93/85\nf 86/93/86 98/106/86 99/107/86 87/94/86\nf 87/94/87 99/107/87 100/108/87 88/95/87\nf 88/95/88 100/108/88 101/109/88 89/96/88\nf 89/96/89 101/109/89 102/110/89 90/97/89\nf 90/97/90 102/110/90 103/111/90 91/98/90\nf 91/99/91 103/112/91 104/113/91 92/100/91\nf 92/100/92 104/113/92 105/114/92 93/101/92\nf 93/101/93 105/114/93 106/115/93 94/102/93\nf 94/102/94 106/115/94 107/116/94 95/103/94\nf 95/103/95 107/116/95 108/117/95 96/104/95\nf 96/104/96 108/117/96 97/105/96 85/92/96\nf 97/105/97 109/118/97 110/119/97 98/106/97\nf 98/106/98 110/119/98 111/120/98 99/107/98\nf 99/107/99 111/120/99 112/121/99 100/108/99\nf 100/108/100 112/121/100 113/122/100 101/109/100\nf 101/109/101 113/122/101 114/123/101 102/110/101\nf 102/110/102 114/123/102 115/124/102 103/111/102\nf 103/112/103 115/125/103 116/126/103 104/113/103\nf 104/113/104 116/126/104 117/127/104 105/114/104\nf 105/114/105 117/127/105 118/128/105 106/115/105\nf 106/115/106 118/128/106 119/129/106 107/116/106\nf 107/116/107 119/129/107 120/130/107 108/117/107\nf 108/117/108 120/130/108 109/118/108 97/105/108\nf 109/118/109 121/131/109 122/132/109 110/119/109\nf 110/119/110 122/132/110 123/133/110 111/120/110\nf 111/120/111 123/133/111 124/134/111 112/121/111\nf 112/121/112 124/134/112 125/135/112 113/122/112\nf 113/122/113 125/135/113 126/136/113 114/123/113\nf 114/123/114 126/136/114 127/137/114 115/124/114\nf 115/125/115 127/138/115 128/139/115 116/126/115\nf 116/126/116 128/139/116 129/140/116 117/127/116\nf 117/127/117 129/140/117 130/141/117 118/128/117\nf 118/128/118 130/141/118 131/142/118 119/129/118\nf 119/129/119 131/142/119 132/143/119 120/130/119\nf 120/130/120 132/143/120 121/131/120 109/118/120\nf 121/131/121 133/144/121 134/145/121 122/132/121\nf 122/132/122 134/145/122 135/146/122 123/133/122\nf 123/133/123 135/146/123 136/147/123 124/134/123\nf 124/134/124 136/147/124 137/148/124 125/135/124\nf 125/135/125 137/148/125 138/149/125 126/136/125\nf 126/136/126 138/149/126 139/150/126 127/137/126\nf 127/138/127 139/151/127 140/152/127 128/139/127\nf 128/139/128 140/152/128 141/153/128 129/140/128\nf 129/140/129 141/153/129 142/154/129 130/141/129\nf 130/141/130 142/154/130 143/155/130 131/142/130\nf 131/142/131 143/155/131 144/156/131 132/143/131\nf 132/143/132 144/156/132 133/144/132 121/131/132\nf 133/144/133 145/157/133 146/158/133 134/145/133\nf 134/145/134 146/158/134 147/159/134 135/146/134\nf 135/146/135 147/159/135 148/160/135 136/147/135\nf 136/147/136 148/160/136 149/161/136 137/148/136\nf 137/148/137 149/161/137 150/162/137 138/149/137\nf 138/149/138 150/162/138 151/163/138 139/150/138\nf 139/151/139 151/164/139 152/165/139 140/152/139\nf 140/152/140 152/165/140 153/166/140 141/153/140\nf 141/153/141 153/166/141 154/167/141 142/154/141\nf 142/154/142 154/167/142 155/168/142 143/155/142\nf 143/155/143 155/168/143 156/169/143 144/156/143\nf 144/156/144 156/169/144 145/157/144 133/144/144\nf 145/157/145 157/170/145 158/171/145 146/158/145\nf 146/158/146 158/171/146 159/172/146 147/159/146\nf 147/159/147 159/172/147 160/173/147 148/160/147\nf 148/160/148 160/173/148 161/174/148 149/161/148\nf 149/161/149 161/174/149 162/175/149 150/162/149\nf 150/162/150 162/175/150 163/176/150 151/163/150\nf 151/164/151 163/177/151 164/178/151 152/165/151\nf 152/165/152 164/178/152 165/179/152 153/166/152\nf 153/166/153 165/179/153 166/180/153 154/167/153\nf 154/167/154 166/180/154 167/181/154 155/168/154\nf 155/168/155 167/181/155 168/182/155 156/169/155\nf 156/169/156 168/182/156 157/170/156 145/157/156\nf 157/170/157 169/183/157 170/184/157 158/171/157\nf 158/171/158 170/184/158 171/185/158 159/172/158\nf 159/172/159 171/185/159 172/186/159 160/173/159\nf 160/173/160 172/186/160 173/187/160 161/174/160\nf 161/174/161 173/187/161 174/188/161 162/175/161\nf 162/175/162 174/188/162 175/189/162 163/176/162\nf 163/177/163 175/190/163 176/191/163 164/178/163\nf 164/178/164 176/191/164 177/192/164 165/179/164\nf 165/179/165 177/192/165 178/193/165 166/180/165\nf 166/180/166 178/193/166 179/194/166 167/181/166\nf 167/181/167 179/194/167 180/195/167 168/182/167\nf 168/182/168 180/195/168 169/183/168 157/170/168\nf 169/183/169 181/196/169 182/197/169 170/184/169\nf 170/184/170 182/197/170 183/198/170 171/185/170\nf 171/185/171 183/198/171 184/199/171 172/186/171\nf 172/186/172 184/199/172 185/200/172 173/187/172\nf 173/187/173 185/200/173 186/201/173 174/188/173\nf 174/188/174 186/201/174 187/202/174 175/189/174\nf 175/190/175 187/203/175 188/204/175 176/191/175\nf 176/191/176 188/204/176 189/205/176 177/192/176\nf 177/192/177 189/205/177 190/206/177 178/193/177\nf 178/193/178 190/206/178 191/207/178 179/194/178\nf 179/194/179 191/207/179 192/208/179 180/195/179\nf 180/195/180 192/208/180 181/196/180 169/183/180\nf 181/196/181 193/209/181 194/210/181 182/197/181\nf 182/197/182 194/210/182 195/211/182 183/198/182\nf 183/198/183 195/211/183 196/212/183 184/199/183\nf 184/199/184 196/212/184 197/213/184 185/200/184\nf 185/200/185 197/213/185 198/214/185 186/201/185\nf 186/201/186 198/214/186 199/215/186 187/202/186\nf 187/203/187 199/216/187 200/217/187 188/204/187\nf 188/204/188 200/217/188 201/218/188 189/205/188\nf 189/205/189 201/218/189 202/219/189 190/206/189\nf 190/206/190 202/219/190 203/220/190 191/207/190\nf 191/207/191 203/220/191 204/221/191 192/208/191\nf 192/208/192 204/221/192 193/209/192 181/196/192\nf 193/209/193 205/222/193 206/223/193 194/210/193\nf 194/210/194 206/223/194 207/224/194 195/211/194\nf 195/211/195 207/224/195 208/225/195 196/212/195\nf 196/212/196 208/225/196 209/226/196 197/213/196\nf 197/213/197 209/226/197 210/227/197 198/214/197\nf 198/214/198 210/227/198 211/228/198 199/215/198\nf 199/216/199 211/229/199 212/230/199 200/217/199\nf 200/217/200 212/230/200 213/231/200 201/218/200\nf 201/218/201 213/231/201 214/232/201 202/219/201\nf 202/219/202 214/232/202 215/233/202 203/220/202\nf 203/220/203 215/233/203 216/234/203 204/221/203\nf 204/221/204 216/234/204 205/222/204 193/209/204\nf 205/222/205 217/235/205 218/236/205 206/223/205\nf 206/223/206 218/236/206 219/237/206 207/224/206\nf 207/224/207 219/237/207 220/238/207 208/225/207\nf 208/225/208 220/238/208 221/239/208 209/226/208\nf 209/226/209 221/239/209 222/240/209 210/227/209\nf 210/227/210 222/240/210 223/241/210 211/228/210\nf 211/229/211 223/242/211 224/243/211 212/230/211\nf 212/230/212 224/243/212 225/244/212 213/231/212\nf 213/231/213 225/244/213 226/245/213 214/232/213\nf 214/232/214 226/245/214 227/246/214 215/233/214\nf 215/233/215 227/246/215 228/247/215 216/234/215\nf 216/234/216 228/247/216 217/235/216 205/222/216\nf 217/235/217 229/248/217 230/249/217 218/236/217\nf 218/236/218 230/249/218 231/250/218 219/237/218\nf 219/237/219 231/250/219 232/251/219 220/238/219\nf 220/238/220 232/251/220 233/252/220 221/239/220\nf 221/239/221 233/252/221 234/253/221 222/240/221\nf 222/240/222 234/253/222 235/254/222 223/241/222\nf 223/242/223 235/255/223 236/256/223 224/243/223\nf 224/243/224 236/256/224 237/257/224 225/244/224\nf 225/244/225 237/257/225 238/258/225 226/245/225\nf 226/245/226 238/258/226 239/259/226 227/246/226\nf 227/246/227 239/259/227 240/260/227 228/247/227\nf 228/247/228 240/260/228 229/248/228 217/235/228\nf 229/248/229 241/261/229 242/262/229 230/249/229\nf 230/249/230 242/262/230 243/263/230 231/250/230\nf 231/250/231 243/263/231 244/264/231 232/251/231\nf 232/251/232 244/264/232 245/265/232 233/252/232\nf 233/252/233 245/265/233 246/266/233 234/253/233\nf 234/253/234 246/266/234 247/267/234 235/254/234\nf 235/255/235 247/268/235 248/269/235 236/256/235\nf 236/256/236 248/269/236 249/270/236 237/257/236\nf 237/257/237 249/270/237 250/271/237 238/258/237\nf 238/258/238 250/271/238 251/272/238 239/259/238\nf 239/259/239 251/272/239 252/273/239 240/260/239\nf 240/260/240 252/273/240 241/261/240 229/248/240\nf 241/261/241 253/274/241 254/275/241 242/262/241\nf 242/262/242 254/275/242 255/276/242 243/263/242\nf 243/263/243 255/276/243 256/277/243 244/264/243\nf 244/264/244 256/277/244 257/278/244 245/265/244\nf 245/265/245 257/278/245 258/279/245 246/266/245\nf 246/266/246 258/279/246 259/280/246 247/267/246\nf 247/268/247 259/281/247 260/282/247 248/269/247\nf 248/269/248 260/282/248 261/283/248 249/270/248\nf 249/270/249 261/283/249 262/284/249 250/271/249\nf 250/271/250 262/284/250 263/285/250 251/272/250\nf 251/272/251 263/285/251 264/286/251 252/273/251\nf 252/273/252 264/286/252 253/274/252 241/261/252\nf 253/274/253 265/287/253 266/288/253 254/275/253\nf 254/275/254 266/288/254 267/289/254 255/276/254\nf 255/276/255 267/289/255 268/290/255 256/277/255\nf 256/277/256 268/290/256 269/291/256 257/278/256\nf 257/278/257 269/291/257 270/292/257 258/279/257\nf 258/279/258 270/292/258 271/293/258 259/280/258\nf 259/281/259 271/294/259 272/295/259 260/282/259\nf 260/282/260 272/295/260 273/296/260 261/283/260\nf 261/283/261 273/296/261 274/297/261 262/284/261\nf 262/284/262 274/297/262 275/298/262 263/285/262\nf 263/285/263 275/298/263 276/299/263 264/286/263\nf 264/286/264 276/299/264 265/287/264 253/274/264\nf 265/287/265 277/300/265 278/301/265 266/288/265\nf 266/288/266 278/301/266 279/302/266 267/289/266\nf 267/289/267 279/302/267 280/303/267 268/290/267\nf 268/290/268 280/303/268 281/304/268 269/291/268\nf 269/291/269 281/304/269 282/305/269 270/292/269\nf 270/292/270 282/305/270 283/306/270 271/293/270\nf 271/294/271 283/307/271 284/308/271 272/295/271\nf 272/295/272 284/308/272 285/309/272 273/296/272\nf 273/296/273 285/309/273 286/310/273 274/297/273\nf 274/297/274 286/310/274 287/311/274 275/298/274\nf 275/298/275 287/311/275 288/312/275 276/299/275\nf 276/299/276 288/312/276 277/300/276 265/287/276\nf 277/300/277 289/313/277 290/314/277 278/301/277\nf 278/301/278 290/314/278 291/315/278 279/302/278\nf 279/302/279 291/315/279 292/316/279 280/303/279\nf 280/303/280 292/316/280 293/317/280 281/304/280\nf 281/304/281 293/317/281 294/318/281 282/305/281\nf 282/305/282 294/318/282 295/319/282 283/306/282\nf 283/307/283 295/320/283 296/321/283 284/308/283\nf 284/308/284 296/321/284 297/322/284 285/309/284\nf 285/309/285 297/322/285 298/323/285 286/310/285\nf 286/310/286 298/323/286 299/324/286 287/311/286\nf 287/311/287 299/324/287 300/325/287 288/312/287\nf 288/312/288 300/325/288 289/313/288 277/300/288\nf 289/326/6 301/327/6 302/328/6 290/329/6\nf 290/329/5 302/328/5 303/330/5 291/331/5\nf 291/331/4 303/330/4 304/332/4 292/333/4\nf 292/333/3 304/332/3 305/334/3 293/335/3\nf 293/335/2 305/334/2 306/336/2 294/337/2\nf 294/337/1 306/336/1 307/338/1 295/339/1\nf 295/340/12 307/341/12 308/342/12 296/343/12\nf 296/343/11 308/342/11 309/344/11 297/345/11\nf 297/345/10 309/344/10 310/346/10 298/347/10\nf 298/347/9 310/346/9 311/348/9 299/349/9\nf 299/349/8 311/348/8 312/350/8 300/351/8\nf 300/351/7 312/350/7 301/327/7 289/326/7\nf 301/327/18 313/352/18 314/353/18 302/328/18\nf 302/328/17 314/353/17 315/354/17 303/330/17\nf 303/330/16 315/354/16 316/355/16 304/332/16\nf 304/332/15 316/355/15 317/356/15 305/334/15\nf 305/334/14 317/356/14 318/357/14 306/336/14\nf 306/336/13 318/357/13 319/358/13 307/338/13\nf 307/341/24 319/359/24 320/360/24 308/342/24\nf 308/342/23 320/360/23 321/361/23 309/344/23\nf 309/344/22 321/361/22 322/362/22 310/346/22\nf 310/346/21 322/362/21 323/363/21 311/348/21\nf 311/348/20 323/363/20 324/364/20 312/350/20\nf 312/350/19 324/364/19 313/352/19 301/327/19\nf 313/352/30 325/365/30 326/366/30 314/353/30\nf 314/353/29 326/366/29 327/367/29 315/354/29\nf 315/354/28 327/367/28 328/368/28 316/355/28\nf 316/355/27 328/368/27 329/369/27 317/356/27\nf 317/356/26 329/369/26 330/370/26 318/357/26\nf 318/357/25 330/370/25 331/371/25 319/358/25\nf 319/359/36 331/372/36 332/373/36 320/360/36\nf 320/360/35 332/373/35 333/374/35 321/361/35\nf 321/361/34 333/374/34 334/375/34 322/362/34\nf 322/362/33 334/375/33 335/376/33 323/363/33\nf 323/363/32 335/376/32 336/377/32 324/364/32\nf 324/364/31 336/377/31 325/365/31 313/352/31\nf 325/365/42 337/378/42 338/379/42 326/366/42\nf 326/366/41 338/379/41 339/380/41 327/367/41\nf 327/367/40 339/380/40 340/381/40 328/368/40\nf 328/368/39 340/381/39 341/382/39 329/369/39\nf 329/369/38 341/382/38 342/383/38 330/370/38\nf 330/370/37 342/383/37 343/384/37 331/371/37\nf 331/372/48 343/385/48 344/386/48 332/373/48\nf 332/373/47 344/386/47 345/387/47 333/374/47\nf 333/374/46 345/387/46 346/388/46 334/375/46\nf 334/375/45 346/388/45 347/389/45 335/376/45\nf 335/376/44 347/389/44 348/390/44 336/377/44\nf 336/377/43 348/390/43 337/378/43 325/365/43\nf 337/378/54 349/391/54 350/392/54 338/379/54\nf 338/379/53 350/392/53 351/393/53 339/380/53\nf 339/380/52 351/393/52 352/394/52 340/381/52\nf 340/381/51 352/394/51 353/395/51 341/382/51\nf 341/382/50 353/395/50 354/396/50 342/383/50\nf 342/383/49 354/396/49 355/397/49 343/384/49\nf 343/385/60 355/398/60 356/399/60 344/386/60\nf 344/386/59 356/399/59 357/400/59 345/387/59\nf 345/387/58 357/400/58 358/401/58 346/388/58\nf 346/388/57 358/401/57 359/402/57 347/389/57\nf 347/389/56 359/402/56 360/403/56 348/390/56\nf 348/390/55 360/403/55 349/391/55 337/378/55\nf 349/391/66 361/404/66 362/405/66 350/392/66\nf 350/392/65 362/405/65 363/406/65 351/393/65\nf 351/393/64 363/406/64 364/407/64 352/394/64\nf 352/394/63 364/407/63 365/408/63 353/395/63\nf 353/395/62 365/408/62 366/409/62 354/396/62\nf 354/396/61 366/409/61 367/410/61 355/397/61\nf 355/398/72 367/411/72 368/412/72 356/399/72\nf 356/399/71 368/412/71 369/413/71 357/400/71\nf 357/400/70 369/413/70 370/414/70 358/401/70\nf 358/401/69 370/414/69 371/415/69 359/402/69\nf 359/402/68 371/415/68 372/416/68 360/403/68\nf 360/403/67 372/416/67 361/404/67 349/391/67\nf 361/404/78 373/417/78 374/418/78 362/405/78\nf 362/405/77 374/418/77 375/419/77 363/406/77\nf 363/406/76 375/419/76 376/420/76 364/407/76\nf 364/407/75 376/420/75 377/421/75 365/408/75\nf 365/408/74 377/421/74 378/422/74 366/409/74\nf 366/409/73 378/422/73 379/423/73 367/410/73\nf 367/411/84 379/424/84 380/425/84 368/412/84\nf 368/412/83 380/425/83 381/426/83 369/413/83\nf 369/413/82 381/426/82 382/427/82 370/414/82\nf 370/414/81 382/427/81 383/428/81 371/415/81\nf 371/415/80 383/428/80 384/429/80 372/416/80\nf 372/416/79 384/429/79 373/417/79 361/404/79\nf 373/417/90 385/430/90 386/431/90 374/418/90\nf 374/418/89 386/431/89 387/432/89 375/419/89\nf 375/419/88 387/432/88 388/433/88 376/420/88\nf 376/420/87 388/433/87 389/434/87 377/421/87\nf 377/421/86 389/434/86 390/435/86 378/422/86\nf 378/422/85 390/435/85 391/436/85 379/423/85\nf 379/424/96 391/437/96 392/438/96 380/425/96\nf 380/425/95 392/438/95 393/439/95 381/426/95\nf 381/426/94 393/439/94 394/440/94 382/427/94\nf 382/427/93 394/440/93 395/441/93 383/428/93\nf 383/428/92 395/441/92 396/442/92 384/429/92\nf 384/429/91 396/442/91 385/430/91 373/417/91\nf 385/430/102 397/443/102 398/444/102 386/431/102\nf 386/431/101 398/444/101 399/445/101 387/432/101\nf 387/432/100 399/445/100 400/446/100 388/433/100\nf 388/433/99 400/446/99 401/447/99 389/434/99\nf 389/434/98 401/447/98 402/448/98 390/435/98\nf 390/435/97 402/448/97 403/449/97 391/436/97\nf 391/437/108 403/450/108 404/451/108 392/438/108\nf 392/438/107 404/451/107 405/452/107 393/439/107\nf 393/439/106 405/452/106 406/453/106 394/440/106\nf 394/440/105 406/453/105 407/454/105 395/441/105\nf 395/441/104 407/454/104 408/455/104 396/442/104\nf 396/442/103 408/455/103 397/443/103 385/430/103\nf 397/443/114 409/456/114 410/457/114 398/444/114\nf 398/444/113 410/457/113 411/458/113 399/445/113\nf 399/445/112 411/458/112 412/459/112 400/446/112\nf 400/446/111 412/459/111 413/460/111 401/447/111\nf 401/447/110 413/460/110 414/461/110 402/448/110\nf 402/448/109 414/461/109 415/462/109 403/449/109\nf 403/450/120 415/463/120 416/464/120 404/451/120\nf 404/451/119 416/464/119 417/465/119 405/452/119\nf 405/452/118 417/465/118 418/466/118 406/453/118\nf 406/453/117 418/466/117 419/467/117 407/454/117\nf 407/454/116 419/467/116 420/468/116 408/455/116\nf 408/455/115 420/468/115 409/456/115 397/443/115\nf 409/456/126 421/469/126 422/470/126 410/457/126\nf 410/457/125 422/470/125 423/471/125 411/458/125\nf 411/458/124 423/471/124 424/472/124 412/459/124\nf 412/459/123 424/472/123 425/473/123 413/460/123\nf 413/460/122 425/473/122 426/474/122 414/461/122\nf 414/461/121 426/474/121 427/475/121 415/462/121\nf 415/463/132 427/476/132 428/477/132 416/464/132\nf 416/464/131 428/477/131 429/478/131 417/465/131\nf 417/465/130 429/478/130 430/479/130 418/466/130\nf 418/466/129 430/479/129 431/480/129 419/467/129\nf 419/467/128 431/480/128 432/481/128 420/468/128\nf 420/468/127 432/481/127 421/469/127 409/456/127\nf 421/469/138 433/482/138 434/483/138 422/470/138\nf 422/470/137 434/483/137 435/484/137 423/471/137\nf 423/471/136 435/484/136 436/485/136 424/472/136\nf 424/472/135 436/485/135 437/486/135 425/473/135\nf 425/473/134 437/486/134 438/487/134 426/474/134\nf 426/474/133 438/487/133 439/488/133 427/475/133\nf 427/476/144 439/489/144 440/490/144 428/477/144\nf 428/477/143 440/490/143 441/491/143 429/478/143\nf 429/478/142 441/491/142 442/492/142 430/479/142\nf 430/479/141 442/492/141 443/493/141 431/480/141\nf 431/480/140 443/493/140 444/494/140 432/481/140\nf 432/481/139 444/494/139 433/482/139 421/469/139\nf 433/482/150 445/495/150 446/496/150 434/483/150\nf 434/483/149 446/496/149 447/497/149 435/484/149\nf 435/484/148 447/497/148 448/498/148 436/485/148\nf 436/485/147 448/498/147 449/499/147 437/486/147\nf 437/486/146 449/499/146 450/500/146 438/487/146\nf 438/487/145 450/500/145 451/501/145 439/488/145\nf 439/489/156 451/502/156 452/503/156 440/490/156\nf 440/490/155 452/503/155 453/504/155 441/491/155\nf 441/491/154 453/504/154 454/505/154 442/492/154\nf 442/492/153 454/505/153 455/506/153 443/493/153\nf 443/493/152 455/506/152 456/507/152 444/494/152\nf 444/494/151 456/507/151 445/495/151 433/482/151\nf 445/495/162 457/508/162 458/509/162 446/496/162\nf 446/496/161 458/509/161 459/510/161 447/497/161\nf 447/497/160 459/510/160 460/511/160 448/498/160\nf 448/498/159 460/511/159 461/512/159 449/499/159\nf 449/499/158 461/512/158 462/513/158 450/500/158\nf 450/500/157 462/513/157 463/514/157 451/501/157\nf 451/502/168 463/515/168 464/516/168 452/503/168\nf 452/503/167 464/516/167 465/517/167 453/504/167\nf 453/504/166 465/517/166 466/518/166 454/505/166\nf 454/505/165 466/518/165 467/519/165 455/506/165\nf 455/506/164 467/519/164 468/520/164 456/507/164\nf 456/507/163 468/520/163 457/508/163 445/495/163\nf 457/508/174 469/521/174 470/522/174 458/509/174\nf 458/509/173 470/522/173 471/523/173 459/510/173\nf 459/510/172 471/523/172 472/524/172 460/511/172\nf 460/511/171 472/524/171 473/525/171 461/512/171\nf 461/512/170 473/525/170 474/526/170 462/513/170\nf 462/513/169 474/526/169 475/527/169 463/514/169\nf 463/515/180 475/528/180 476/529/180 464/516/180\nf 464/516/179 476/529/179 477/530/179 465/517/179\nf 465/517/178 477/530/178 478/531/178 466/518/178\nf 466/518/177 478/531/177 479/532/177 467/519/177\nf 467/519/176 479/532/176 480/533/176 468/520/176\nf 468/520/175 480/533/175 469/521/175 457/508/175\nf 469/521/186 481/534/186 482/535/186 470/522/186\nf 470/522/185 482/535/185 483/536/185 471/523/185\nf 471/523/184 483/536/184 484/537/184 472/524/184\nf 472/524/183 484/537/183 485/538/183 473/525/183\nf 473/525/182 485/538/182 486/539/182 474/526/182\nf 474/526/181 486/539/181 487/540/181 475/527/181\nf 475/528/192 487/541/192 488/542/192 476/529/192\nf 476/529/191 488/542/191 489/543/191 477/530/191\nf 477/530/190 489/543/190 490/544/190 478/531/190\nf 478/531/189 490/544/189 491/545/189 479/532/189\nf 479/532/188 491/545/188 492/546/188 480/533/188\nf 480/533/187 492/546/187 481/534/187 469/521/187\nf 481/534/198 493/547/198 494/548/198 482/535/198\nf 482/535/197 494/548/197 495/549/197 483/536/197\nf 483/536/196 495/549/196 496/550/196 484/537/196\nf 484/537/195 496/550/195 497/551/195 485/538/195\nf 485/538/194 497/551/194 498/552/194 486/539/194\nf 486/539/193 498/552/193 499/553/193 487/540/193\nf 487/541/204 499/554/204 500/555/204 488/542/204\nf 488/542/203 500/555/203 501/556/203 489/543/203\nf 489/543/202 501/556/202 502/557/202 490/544/202\nf 490/544/201 502/557/201 503/558/201 491/545/201\nf 491/545/200 503/558/200 504/559/200 492/546/200\nf 492/546/199 504/559/199 493/547/199 481/534/199\nf 493/547/210 505/560/210 506/561/210 494/548/210\nf 494/548/209 506/561/209 507/562/209 495/549/209\nf 495/549/208 507/562/208 508/563/208 496/550/208\nf 496/550/207 508/563/207 509/564/207 497/551/207\nf 497/551/206 509/564/206 510/565/206 498/552/206\nf 498/552/205 510/565/205 511/566/205 499/553/205\nf 499/554/216 511/567/216 512/568/216 500/555/216\nf 500/555/215 512/568/215 513/569/215 501/556/215\nf 501/556/214 513/569/214 514/570/214 502/557/214\nf 502/557/213 514/570/213 515/571/213 503/558/213\nf 503/558/212 515/571/212 516/572/212 504/559/212\nf 504/559/211 516/572/211 505/560/211 493/547/211\nf 505/560/222 517/573/222 518/574/222 506/561/222\nf 506/561/221 518/574/221 519/575/221 507/562/221\nf 507/562/220 519/575/220 520/576/220 508/563/220\nf 508/563/219 520/576/219 521/577/219 509/564/219\nf 509/564/218 521/577/218 522/578/218 510/565/218\nf 510/565/217 522/578/217 523/579/217 511/566/217\nf 511/567/228 523/580/228 524/581/228 512/568/228\nf 512/568/227 524/581/227 525/582/227 513/569/227\nf 513/569/226 525/582/226 526/583/226 514/570/226\nf 514/570/225 526/583/225 527/584/225 515/571/225\nf 515/571/224 527/584/224 528/585/224 516/572/224\nf 516/572/223 528/585/223 517/573/223 505/560/223\nf 517/573/234 529/586/234 530/587/234 518/574/234\nf 518/574/233 530/587/233 531/588/233 519/575/233\nf 519/575/232 531/588/232 532/589/232 520/576/232\nf 520/576/231 532/589/231 533/590/231 521/577/231\nf 521/577/230 533/590/230 534/591/230 522/578/230\nf 522/578/229 534/591/229 535/592/229 523/579/229\nf 523/580/240 535/593/240 536/594/240 524/581/240\nf 524/581/239 536/594/239 537/595/239 525/582/239\nf 525/582/238 537/595/238 538/596/238 526/583/238\nf 526/583/237 538/596/237 539/597/237 527/584/237\nf 527/584/236 539/597/236 540/598/236 528/585/236\nf 528/585/235 540/598/235 529/586/235 517/573/235\nf 529/586/246 541/599/246 542/600/246 530/587/246\nf 530/587/245 542/600/245 543/601/245 531/588/245\nf 531/588/244 543/601/244 544/602/244 532/589/244\nf 532/589/243 544/602/243 545/603/243 533/590/243\nf 533/590/242 545/603/242 546/604/242 534/591/242\nf 534/591/241 546/604/241 547/605/241 535/592/241\nf 535/593/252 547/606/252 548/607/252 536/594/252\nf 536/594/251 548/607/251 549/608/251 537/595/251\nf 537/595/250 549/608/250 550/609/250 538/596/250\nf 538/596/249 550/609/249 551/610/249 539/597/249\nf 539/597/248 551/610/248 552/611/248 540/598/248\nf 540/598/247 552/611/247 541/599/247 529/586/247\nf 541/599/258 553/612/258 554/613/258 542/600/258\nf 542/600/257 554/613/257 555/614/257 543/601/257\nf 543/601/256 555/614/256 556/615/256 544/602/256\nf 544/602/255 556/615/255 557/616/255 545/603/255\nf 545/603/254 557/616/254 558/617/254 546/604/254\nf 546/604/253 558/617/253 559/618/253 547/605/253\nf 547/606/264 559/619/264 560/620/264 548/607/264\nf 548/607/263 560/620/263 561/621/263 549/608/263\nf 549/608/262 561/621/262 562/622/262 550/609/262\nf 550/609/261 562/622/261 563/623/261 551/610/261\nf 551/610/260 563/623/260 564/624/260 552/611/260\nf 552/611/259 564/624/259 553/612/259 541/599/259\nf 553/612/270 565/625/270 566/626/270 554/613/270\nf 554/613/269 566/626/269 567/627/269 555/614/269\nf 555/614/268 567/627/268 568/628/268 556/615/268\nf 556/615/267 568/628/267 569/629/267 557/616/267\nf 557/616/266 569/629/266 570/630/266 558/617/266\nf 558/617/265 570/630/265 571/631/265 559/618/265\nf 559/619/276 571/632/276 572/633/276 560/620/276\nf 560/620/275 572/633/275 573/634/275 561/621/275\nf 561/621/274 573/634/274 574/635/274 562/622/274\nf 562/622/273 574/635/273 575/636/273 563/623/273\nf 563/623/272 575/636/272 576/637/272 564/624/272\nf 564/624/271 576/637/271 565/625/271 553/612/271\nf 565/625/282 1/1/282 2/4/282 566/626/282\nf 566/626/281 2/4/281 3/6/281 567/627/281\nf 567/627/280 3/6/280 4/8/280 568/628/280\nf 568/628/279 4/8/279 5/10/279 569/629/279\nf 569/629/278 5/10/278 6/12/278 570/630/278\nf 570/630/277 6/12/277 7/14/277 571/631/277\nf 571/632/288 7/15/288 8/18/288 572/633/288\nf 572/633/287 8/18/287 9/20/287 573/634/287\nf 573/634/286 9/20/286 10/22/286 574/635/286\nf 574/635/285 10/22/285 11/24/285 575/636/285\nf 575/636/284 11/24/284 12/26/284 576/637/284\nf 576/637/283 12/26/283 1/1/283 565/625/283\n"
  },
  {
    "path": "bin/mods/base/effects/test.effect",
    "content": "{\n  \"version\": 15052020,\n  \"emitters\": [\n    {\n      \"gravity\": 0,\n      \"randomLifeSpanFactor\": 5,\n      \"randomColourFactor\": 2,\n      \"startColour\": \"255 255 255 255\",\n      \"endColour\": \"255 0 0 255\",\n      \"startScale\": 0,\n      \"endScale\": 1.65,\n      \"spawnRadius\": 1.0,\n      \"collideWorld\": \"true\",\n      \"collideActors\": \"true\",\n      \"particleType\": \"sprite\",\n      \"blendType\": \"additive\"\n    }\n  ]\n}"
  },
  {
    "path": "bin/mods/base/fonts/LICENSE.txt",
    "content": "\n                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"[]\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright [yyyy] [name of copyright owner]\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n"
  },
  {
    "path": "bin/mods/base/languages/eng.language",
    "content": "{\n  \"dbt0\": \"Please note that OpenHoW is still heavily under development.\",\n  \"dbt1\": \"\\nBe sure to report any bugs to our GitHub page.\",\n  \"dbt2\": \"https://github.com/TalonBraveInfo/OpenHoW/\",\n  \"english\": \"ENGLISH\",\n  \"french\": \"FRANÇAIS\",\n  \"german\": \"DEUTSCH\",\n  \"italian\": \"ITALIANO\",\n  \"spanish\": \"ESPAÑOL\",\n  \"russian\": \"РУССКИЙ\",\n  \"yes\": \"YES\",\n  \"no\": \"NO\",\n  \"ok\": \"OK\",\n  \"fe_main\": \"MAIN MENU\",\n  \"fe_yn_quit\": \"ARE YOU SURE YOU WANT TO QUIT?\",\n  \"mode_sn\": \"SURVIVAL-NOVICE\",\n  \"mode_se\": \"SURVIVAL-EXPERT\",\n  \"mode_ss\": \"SURVIVAL-STRATEGY\",\n  \"mode_dm\": \"DEATH MATCH\",\n  \"mode_ge\": \"GENERATE\",\n  \"map_how_road\": \"ROUTINE PATROL\",\n  \"map_how_trench\": \"TRENCH WARFARE\",\n  \"map_how_rumble\": \"ISLAND INVASION\",\n  \"map_how_devi\": \"MORNING GLORY\",\n  \"map_how_twin\": \"COMMUNICATION BREAKDOWN\",\n  \"map_how_zulus\": \"UNDER SIEGE\",\n  \"map_how_sniper\": \"THE SPYING GAME\",\n  \"map_how_guns\": \"BANGERS 'N' MASH\",\n  \"map_how_oasis\": \"JUST DESERTS\",\n  \"map_how_mashed\": \"THE VILLAGE PEOPLE\",\n  \"map_how_camp\": \"BOOT CAMP\",\n  \"map_how_liberate\": \"SAVING PRIVATE RIND\",\n  \"map_how_medix\": \"OVER THE TOP\",\n  \"map_how_fjords\": \"GLACIER GUNS\",\n  \"map_how_eyrie\": \"BATTLE STATIONS\",\n  \"map_how_bridge\": \"GENEVA CONVENTION\",\n  \"map_how_bay\": \"FORTIFIED SWINE\",\n  \"map_how_desval\": \"I SPY...\",\n  \"map_how_snake\": \"CHEMICAL COMPOUND\",\n  \"map_how_emplace\": \"ACHILLES HEAL\",\n  \"map_how_keep\": \"ASSASSINATION\",\n  \"map_how_supline\": \"HIGH AND DRY\",\n  \"map_how_tester\": \"HERO WARSHIP\",\n  \"map_how_foot\": \"HAMBURGER HILL\",\n  \"map_how_final\": \"WELL, WELL, WELL!\",\n  \"map_how_estu\": \"THE WAR FOUNDATION\",\n  \"map_how_boom\": \"FRIENDLY FIRE\",\n  \"map_how_bhill\": \"DAM BUSTERS\",\n  \"map_how_lecprod\": \"BRIDGE THE GAP\",\n  \"map_how_dval\": \"DEATH VALLEY\",\n  \"map_how_ice\": \"CHILL HILL\",\n  \"map_how_bute\": \"MOON BUTTES\",\n  \"map_how_maze\": \"HEDGE MAZE\",\n  \"map_how_sepia1\": \"SQUARE OFF\",\n  \"map_how_dbowl\": \"DEATH BOWL\",\n  \"map_how_mlake\": \"FROST FIGHT\",\n  \"map_how_cmass\": \"CRATERMASS\",\n  \"map_how_artgun\": \"DOOMED\",\n  \"map_how_dval2\": \"DEATH VALLEY 2\",\n  \"map_how_hell3\": \"SKULDUGGERY\",\n  \"map_how_hell2\": \"PIGIN' HELL\",\n  \"map_how_lunar1\": \"PIGS IN SPACE\",\n  \"map_how_creepy2\": \"GRAVEYARD SHIFT\",\n  \"map_how_play1\": \"PLAY PEN\",\n  \"map_how_play2\": \"DUVET FUN\",\n  \"map_how_iceflow\": \"ICE-FLOW\",\n  \"map_how_ridge\": \"RIDGE BACK\",\n  \"map_how_archi\": \"YOU HILLOCK\",\n  \"map_how_demo\": \"DEMO LEVEL\",\n  \"map_how_island\": \"ISLAND HOPPER\",\n  \"map_how_lake\": \"THE LAKE\",\n  \"map_how_oneway\": \"ONE WAY SYSTEM\",\n  \"team_british\": \"TOMMY'S TROTTERS\",\n  \"team_french\": \"GARLIC GRUNTS\",\n  \"team_american\": \"UNCLE HAMS HOGS\",\n  \"team_russian\": \"PIGGYSTROIKA\",\n  \"team_japanese\": \"SUSHI-SWINE\",\n  \"team_german\": \"SOW-A-KRAUTS\",\n  \"team_lard\": \"TEAM LARD\",\n  \"pig_british_1\": \"NOBBY\",\n  \"pig_british_2\": \"GINGER\",\n  \"pig_british_3\": \"DEN\",\n  \"pig_british_4\": \"MONTY\",\n  \"pig_british_5\": \"BASIL\",\n  \"pig_british_6\": \"PONSONBY\",\n  \"pig_british_7\": \"PERCY\",\n  \"pig_british_8\": \"SMITH\",\n  \"pig_british_9\": \"JONES\",\n  \"pig_french_1\": \"BASTILLE\",\n  \"pig_french_2\": \"LE CONT\",\n  \"pig_french_3\": \"GERARD\",\n  \"pig_french_4\": \"M. CHIEN\",\n  \"pig_french_5\": \"SANGLIER\",\n  \"pig_french_6\": \"COCHON\",\n  \"pig_french_7\": \"PORC\",\n  \"pig_french_8\": \"GOINFRE\",\n  \"pig_french_9\": \"GLOUTON\",\n  \"pig_american_1\": \"CHUCKY\",\n  \"pig_american_2\": \"SLY\",\n  \"pig_american_3\": \"KEANU\",\n  \"pig_american_4\": \"ABRAHAM\",\n  \"pig_american_5\": \"JOHN-BOY\",\n  \"pig_american_6\": \"JIM-BOB\",\n  \"pig_american_7\": \"BOBBY-JIM\",\n  \"pig_american_8\": \"BOBBY-JOE\",\n  \"pig_american_9\": \"JOEY-BOB\",\n  \"pig_russian_1\": \"YEHUDI\",\n  \"pig_russian_2\": \"HUSKI\",\n  \"pig_russian_3\": \"JETSKI\",\n  \"pig_russian_4\": \"SNOWSKI\",\n  \"pig_russian_5\": \"PESSKI\",\n  \"pig_russian_6\": \"MUSKI\",\n  \"pig_russian_7\": \"DUSKI\",\n  \"pig_russian_8\": \"RIMSKI\",\n  \"pig_russian_9\": \"MULE\",\n  \"pig_japanese_1\": \"SHOGUN\",\n  \"pig_japanese_2\": \"KENDO\",\n  \"pig_japanese_3\": \"KUNG FU\",\n  \"pig_japanese_4\": \"FENG SHUI\",\n  \"pig_japanese_5\": \"NINJA\",\n  \"pig_japanese_6\": \"SUSHI\",\n  \"pig_japanese_7\": \"KEMPO\",\n  \"pig_japanese_8\": \"TENKO\",\n  \"pig_japanese_9\": \"RAW FISH\",\n  \"pig_german_1\": \"HERMAN\",\n  \"pig_german_2\": \"WOLFIE\",\n  \"pig_german_3\": \"LEDERHOS\",\n  \"pig_german_4\": \"HERR GEL\",\n  \"pig_german_5\": \"HERR KUT\",\n  \"pig_german_6\": \"SCHNITZEL\",\n  \"pig_german_7\": \"HERR DRY\",\n  \"pig_german_8\": \"HERR RAID\",\n  \"pig_german_9\": \"SCHWEIN\",\n  \"pig_lard_1\": \"SIMON\",\n  \"pig_lard_2\": \"TAPPER\",\n  \"pig_lard_3\": \"JOHN\",\n  \"pig_lard_4\": \"ANDY\",\n  \"pig_lard_5\": \"MARK\",\n  \"pig_lard_6\": \"JAKE\",\n  \"pig_lard_7\": \"MARTYN\",\n  \"pig_lard_8\": \"IZZY\",\n  \"pig_lard_9\": \"RICKI\",\n  \"pig_lard_10\": \"DOLLY\",\n  \"pig_lard_11\": \"FIL\",\n  \"pig_lard_12\": \"ADE\",\n  \"pig_lard_13\": \"SHORTY\",\n  \"pig_lard_14\": \"BEN\",\n  \"pig_lard_15\": \"BADDERS\",\n  \"pig_lard_16\": \"PHILIP\",\n  \"pig_lard_17\": \"JIM\",\n  \"pig_lard_18\": \"PAUL\",\n  \"pig_lard_19\": \"JAMES\",\n  \"pig_lard_20\": \"SWEETY\",\n  \"career\": \"CAREER PATH\",\n  \"career_heavy\": \"HEAVY WEAPONS\",\n  \"career_engineer\": \"ENGINEER\",\n  \"career_espionage\": \"ESPIONAGE\",\n  \"career_medic\": \"MEDIC\",\n  \"class_grunt\": \"GRUNT\",\n  \"class_gunner\": \"GUNNER\",\n  \"class_bombardier\": \"BOMBARDIER\",\n  \"class_pyrotechnic\": \"PYROTECHNIC\",\n  \"class_commando\": \"COMMANDO\",\n  \"class_sapper\": \"SAPPER\",\n  \"class_engineer\": \"ENGINEER\",\n  \"class_saboteur\": \"SABOTEUR\",\n  \"class_scout\": \"SCOUT\",\n  \"class_sniper\": \"SNIPER\",\n  \"class_spy\": \"SPY\",\n  \"class_orderly\": \"ORDERLY\",\n  \"class_medic\": \"MEDIC\",\n  \"class_surgeon\": \"SURGEON\",\n  \"class_hero\": \"HERO\",\n  \"class_ace\": \"ACE\",\n  \"class_legend\": \"LEGEND\",\n  \"class_grenadier\": \"GRENADIER\",\n  \"class_paratrooper\": \"PARATROOPER\",\n  \"weapon_none\": \"NONE\",\n  \"weapon_trotter\": \"TROTTER\",\n  \"weapon_knife\": \"KNIFE\",\n  \"weapon_bayonet\": \"BAYONET\",\n  \"weapon_sword\": \"SWORD\",\n  \"weapon_cattle_prod\": \"CATTLE PROD\",\n  \"weapon_pistol\": \"PISTOL\",\n  \"weapon_rifle\": \"RIFLE\",\n  \"weapon_rifle_burst\": \"RIFLE BURST\",\n  \"weapon_mg\": \"MACHINE GUN\",\n  \"weapon_mg_heavy\": \"HEAVY M-GUN\",\n  \"weapon_rifle_scope\": \"SNIPER RIFLE\",\n  \"weapon_shotgun\": \"SHOTGUN\",\n  \"weapon_shotgun_super\": \"SUPER SHOTGUN\",\n  \"weapon_flame_thrower\": \"FLAME THROWER\",\n  \"weapon_rocket_launcher\": \"ROCKET LAUNCHER\",\n  \"weapon_missile_guided\": \"GUIDED MISSILE\",\n  \"weapon_rifle_medic\": \"MEDICINE DART\",\n  \"weapon_rifle_tranq\": \"TRANQUILISER\",\n  \"weapon_grenade\": \"GRENADE\",\n  \"weapon_grenade_cluster\": \"CLUSTER GRENADE\",\n  \"weapon_grenade_hx\": \"H-EXPL. GRENADE\",\n  \"weapon_grenade_roller\": \"ROLLER GRENADE\",\n  \"weapon_gas_confusion\": \"CONFUSION GAS\",\n  \"weapon_gas_freeze\": \"FREEZE GAS\",\n  \"weapon_gas_madness\": \"MADNESS GAS\",\n  \"weapon_gas_poison\": \"POISON GAS\",\n  \"weapon_grenade_shrapnel\": \"SHRAPNEL GRENADE\",\n  \"weapon_mortar\": \"MORTAR\",\n  \"weapon_bazooka\": \"BAZOOKA\",\n  \"weapon_grenade_launcher\": \"GRENADE LAUNCHER\",\n  \"weapon_airburst\": \"AIRBURST\",\n  \"weapon_airburst_super\": \"SUPER AIRBURST\",\n  \"weapon_grenade_medic\": \"MEDICINE BALL\",\n  \"weapon_missile_homing\": \"HOMING MISSILE\",\n  \"weapon_mine\": \"MINE\",\n  \"weapon_mine_antip\": \"ANTI-P MINE\",\n  \"weapon_mine_antip\": \"TNT\",\n  \"weapon_tnt_super\": \"SUPER TNT\",\n  \"weapon_shell_long_range\": \"LONG RANGE SHELL\",\n  \"weapon_shell_mine\": \"MINE SHELL\",\n  \"weapon_shell_gas\": \"GAS SHELL\",\n  \"weapon_shell_fire_rain\": \"FIRE RAIN SHELL\",\n  \"weapon_shell_1000_lbs\": \"1000 LBS SHELL\",\n  \"weapon_shell_shock\": \"SHOCK SHELL\",\n  \"weapon_jetpack\": \"JETPACK\",\n  \"weapon_suicide\": \"SUICIDE\",\n  \"weapon_healing_hands\": \"HEALING HANDS\",\n  \"weapon_self_heal\": \"SELF HEAL\",\n  \"weapon_pick_pocket\": \"PICK POCKET\",\n  \"weapon_hide\": \"HIDE\",\n  \"weapon_shockwave\": \"SHOCKWAVE\",\n  \"weapon_special_ops\": \"SPECIAL OPS\",\n  \"weapon_airstrike\": \"AIRSTRIKE\",\n  \"weapon_airstrike_fire\": \"F-RAIN AIRSTRIKE\",\n  \"weapon_inout_vehicle\": \"VEHICLE INOUT\",\n  \"weapon_inout_building\": \"BUILDING INOUT\",\n  \"weapon_eject_pig\": \"EJECT PIG\",\n  \"weapon_map_view\": \"MAP VIEW\",\n  \"weapon_binoculars\": \"BINOCULARS\",\n  \"weapon_skip_turn\": \"SKIP TURN\",\n  \"weapon_surrender\": \"SURRENDER\",\n  \"vehicle_artillery\": \"ARTILLERY\",\n  \"vehicle_tent_medic\": \"MEDIC TENT\",\n  \"vehicle_tent_mash\": \"MASH TENT\",\n  \"vehicle_pillbox\": \"PILLBOX\",\n  \"vehicle_sandbags\": \"SANDBAGS\",\n  \"vehicle_shelter\": \"SHELTER\",\n  \"vehicle_tent\": \"TENT\",\n  \"vehicle_airship\": \"AIRSHIP\",\n  \"vehicle_duck\": \"DUCK\",\n  \"vehicle_tank_aqua\": \"AQUA-TANK\",\n  \"vehicle_boat\": \"BOAT\",\n  \"vehicle_plane\": \"PLANE\",\n  \"vehicle_tank\": \"TANK\",\n  \"vehicle_truck\": \"TRUCK\",\n  \"mp_l00\": \"%s HAS LEFT THE GAME\",\n  \"mp_l02\": \"%s HAS LEFT WITH HIS TAIL BETWEEN HIS LEGS\",\n  \"mp_l03\": \"BYE BYE %s\",\n  \"mp_l04\": \"%s COULDN'T TAKE THE PACE\",\n  \"mp_l05\": \"%s COULDN'T STAND THE HEAT\",\n  \"mp_l06\": \"%s HAS LEFT THE FORAY\",\n  \"mp_l07\": \"%s WILL BE MISSED\",\n  \"mp_l08\": \"%s RUNS LIKE A GIRL\",\n  \"mp_l09\": \"%s HAS GIVEN UP\",\n  \"mp_l10\": \"%s LEAVES QUIETLY\",\n  \"mp_l11\": \"%s HURRIEDLY RETREATS\",\n  \"mp_l12\": \"%s IS OUTTA HERE!\",\n\n  \"file\": \"File\",\n  \"open\": \"Open\",\n  \"window_particle_editor\": \"Particle Editor\",\n  \"window_model_viewer\": \"Model Viewer\"\n}"
  },
  {
    "path": "bin/mods/base/languages/fre.language",
    "content": "{\n  \"english\": \"ENGLISH\",\n  \"french\": \"FRANÇAIS\",\n  \"german\": \"DEUTSCH\",\n  \"italian\": \"ITALIANO\",\n  \"spanish\": \"ESPAÑOL\",\n  \"russian\": \"РУССКИЙ\",\n  \"yes\": \"OUI\",\n  \"no\": \"NON\",\n  \"ok\": \"OK\",\n  \"fe_main\": \"MENU PRINCIPAL\",\n  \"fe_yn_quit\": \"ETES-VOUS SUR DE VOULOIR QUITTER ?\",\n  \"mode_sn\": \"SURVIVANT-NOVICE\",\n  \"mode_se\": \"SURVIVANT-EXPERT\",\n  \"mode_ss\": \"SURVIV.-STRATEGIE\",\n  \"mode_dm\": \"DEATHMATCH\",\n  \"mode_ge\": \"GENERER\",\n  \"map_how_road\": \"LA PATROUILLE DE ROUTINE\",\n  \"map_how_trench\": \"LA GUERRE DES TRANCHEES\",\n  \"map_how_rumble\": \"L'INVASION DE L'ILE\",\n  \"map_how_devi\": \"UNE BONNE FARCE !\",\n  \"map_how_twin\": \"PROBLEMES DE COMMUNICATION\",\n  \"map_how_zulus\": \"ASSIEGES\",\n  \"map_how_sniper\": \"LA CHASSE AUX ESPIONS\",\n  \"map_how_guns\": \"SAUCISSES-PUREE\",\n  \"map_how_oasis\": \"UN PETIT DESERT ?\",\n  \"map_how_mashed\": \"VOYAGE AU CLUB\",\n  \"map_how_camp\": \"CAMP D'ENTRAINEMENT\",\n  \"map_how_liberate\": \"SAUVONS LE SOLDAT RILLETTE\",\n  \"map_how_medix\": \"TROP C'EST TROP\",\n  \"map_how_fjords\": \"PATE EN GELEE\",\n  \"map_how_eyrie\": \"POSTE DE COMBAT\",\n  \"map_how_bridge\": \"CONVENTION DE GENEVE\",\n  \"map_how_bay\": \"PORC AU VIN\",\n  \"map_how_desval\": \"ESPIONNAGE\",\n  \"map_how_snake\": \"FANGE CHIMIQUE\",\n  \"map_how_emplace\": \"LE TALON D'ACHILLE\",\n  \"map_how_keep\": \"ASSASSINAT\",\n  \"map_how_supline\": \"AU CHAUD ET AU SEC\",\n  \"map_how_tester\": \"EAU DE BOUDIN\",\n  \"map_how_foot\": \"LA COTE DU PORC\",\n  \"map_how_final\": \"LA DER DES DER !\",\n  \"map_how_estu\": \"LE FONDEMENT DE LA GUERRE\",\n  \"map_how_boom\": \"SUS A L'AMI !\",\n  \"map_how_bhill\": \"L'ESCADRON DE L'ENFER\",\n  \"map_how_lecprod\": \"JOINDRE LES DEUX BOUTS\",\n  \"map_how_dval\": \"LA VALLEE DE LA MORT\",\n  \"map_how_ice\": \"LES CIMES ENNEIGEES\",\n  \"map_how_bute\": \"LUNA PARK\",\n  \"map_how_maze\": \"DEDALE VEGETAL\",\n  \"map_how_sepia1\": \"LA TETE AU CARRE\",\n  \"map_how_dbowl\": \"LA CUVETTE DE LA MORT\",\n  \"map_how_mlake\": \"LE COMBAT DES PORCS EN GELEE\",\n  \"map_how_cmass\": \"CRATERE CONTRE CRATERE\",\n  \"map_how_artgun\": \"A L'ABATTOIR\",\n  \"map_how_dval2\": \"LA VALLEE DE LA MORT 2\",\n  \"map_how_hell3\": \"LES COCHONS PORCS !\",\n  \"map_how_hell2\": \"ROTIR EN ENFER\",\n  \"map_how_lunar1\": \"PORCS DANS L'ESPACE\",\n  \"map_how_creepy2\": \"JOUR DE DEUIL\",\n  \"map_how_play1\": \"MOSAIQUE\",\n  \"map_how_play2\": \"PATCHWORK\",\n  \"map_how_iceflow\": \"LA COULEE DE GLACE\",\n  \"map_how_ridge\": \"LA CRÊTE\",\n  \"map_how_archi\": \"SUR LA BUTTE\",\n  \"map_how_demo\": \"NIVEAU DE DEMONSTRATION\",\n  \"map_how_island\": \"LES ILES FLOTTANTES\",\n  \"map_how_lake\": \"LE LAC\",\n  \"map_how_oneway\": \"SENS UNIQUE\",\n  \"team_british\": \"PORC FORCE\",\n  \"team_french\": \"PORCS FRANCS\",\n  \"team_american\": \"GI PORCS\",\n  \"team_russian\": \"SPARTAK PORCS\",\n  \"team_japanese\": \"BANZAI PORCS\",\n  \"team_german\": \"PORCS KORPS\",\n  \"team_lard\": \"TEAM LARD\",\n  \"pig_british_1\": \"LIAM\",\n  \"pig_british_2\": \"STAN\",\n  \"pig_british_3\": \"BILLY\",\n  \"pig_british_4\": \"JOHN\",\n  \"pig_british_5\": \"BRET\",\n  \"pig_british_6\": \"ERIC\",\n  \"pig_british_7\": \"CHARLES\",\n  \"pig_british_8\": \"PAUL\",\n  \"pig_british_9\": \"SEAN\",\n  \"pig_french_1\": \"JEANMARIE\",\n  \"pig_french_2\": \"FETNAT\",\n  \"pig_french_3\": \"NONO\",\n  \"pig_french_4\": \"AHMED\",\n  \"pig_french_5\": \"PIERRE\",\n  \"pig_french_6\": \"ALEX\",\n  \"pig_french_7\": \"FRANCK\",\n  \"pig_french_8\": \"YVES\",\n  \"pig_french_9\": \"ALAIN\",\n  \"pig_american_1\": \"JIMMY\",\n  \"pig_american_2\": \"HANK\",\n  \"pig_american_3\": \"BILL\",\n  \"pig_american_4\": \"BUDDY\",\n  \"pig_american_5\": \"EMILIO\",\n  \"pig_american_6\": \"MALCOLM\",\n  \"pig_american_7\": \"BRUCE\",\n  \"pig_american_8\": \"DEMI\",\n  \"pig_american_9\": \"BOBBY\",\n  \"pig_russian_1\": \"LEONID\",\n  \"pig_russian_2\": \"MIKHAÏL\",\n  \"pig_russian_3\": \"VLADIMIR\",\n  \"pig_russian_4\": \"ALEXANDER\",\n  \"pig_russian_5\": \"BORIS\",\n  \"pig_russian_6\": \"IGOR\",\n  \"pig_russian_7\": \"FEDOR\",\n  \"pig_russian_8\": \"NICOLAÏ\",\n  \"pig_russian_9\": \"SASHA\",\n  \"pig_japanese_1\": \"MIZO\",\n  \"pig_japanese_2\": \"AKIRA\",\n  \"pig_japanese_3\": \"RUISHI\",\n  \"pig_japanese_4\": \"SUSHI\",\n  \"pig_japanese_5\": \"LEE\",\n  \"pig_japanese_6\": \"HITO\",\n  \"pig_japanese_7\": \"MIFU\",\n  \"pig_japanese_8\": \"TAKASHI\",\n  \"pig_japanese_9\": \"HIRO\",\n  \"pig_german_1\": \"SIGGY\",\n  \"pig_german_2\": \"GUNTER\",\n  \"pig_german_3\": \"THOMASS\",\n  \"pig_german_4\": \"SCHULTZ\",\n  \"pig_german_5\": \"FRANZ\",\n  \"pig_german_6\": \"ROLF\",\n  \"pig_german_7\": \"OTTO\",\n  \"pig_german_8\": \"HANS\",\n  \"pig_german_9\": \"HEINRICH\",\n  \"pig_lard_1\": \"SIMON\",\n  \"pig_lard_2\": \"TAPPER\",\n  \"pig_lard_3\": \"JOHN\",\n  \"pig_lard_4\": \"ANDY\",\n  \"pig_lard_5\": \"MARK\",\n  \"pig_lard_6\": \"JAKE\",\n  \"pig_lard_7\": \"MARTYN\",\n  \"pig_lard_8\": \"IZZY\",\n  \"pig_lard_9\": \"RICKI\",\n  \"pig_lard_10\": \"DOLLY\",\n  \"pig_lard_11\": \"FIL\",\n  \"pig_lard_12\": \"ADE\",\n  \"pig_lard_13\": \"SHORTY\",\n  \"pig_lard_14\": \"BEN\",\n  \"pig_lard_15\": \"BADDERS\",\n  \"pig_lard_16\": \"PHILIP\",\n  \"pig_lard_17\": \"JIM\",\n  \"pig_lard_18\": \"PAUL\",\n  \"pig_lard_19\": \"JAMES\",\n  \"pig_lard_20\": \"SWEETY\",\n  \"career\": \"PLAN DE CARRIERE\",\n  \"career_heavy\": \"ARTILLERIE LOURDE\",\n  \"career_engineer\": \"INGENIEUR\",\n  \"career_espionage\": \"ESPIONNAGE\",\n  \"career_medic\": \"TOUBIB\",\n  \"class_grunt\": \"TROUFION\",\n  \"class_gunner\": \"ARTILLEUR\",\n  \"class_bombardier\": \"BOMBARDIER\",\n  \"class_pyrotechnic\": \"PYROTECH.\",\n  \"class_commando\": \"COMMANDO\",\n  \"class_sapper\": \"SAPEUR\",\n  \"class_engineer\": \"INGENIEUR\",\n  \"class_saboteur\": \"SABOTEUR\",\n  \"class_scout\": \"ECLAIREUR\",\n  \"class_sniper\": \"SNIPER\",\n  \"class_spy\": \"ESPION\",\n  \"class_orderly\": \"INFIRMIER\",\n  \"class_medic\": \"TOUBIB\",\n  \"class_surgeon\": \"CHIRURGIEN\",\n  \"class_hero\": \"HEROS\",\n  \"class_ace\": \"AS\",\n  \"class_legend\": \"LEGENDE\",\n  \"class_grenadier\": \"GRENADIER\",\n  \"class_paratrooper\": \"PARACHUTISTE\",\n  \"weapon_none\": \"AUCUN\",\n  \"weapon_trotter\": \"PIED DE PORC\",\n  \"weapon_knife\": \"COUTEAU\",\n  \"weapon_bayonet\": \"BAIONNETTE\",\n  \"weapon_sword\": \"EPEE\",\n  \"weapon_cattle_prod\": \"BATON DE BERGER\",\n  \"weapon_pistol\": \"PISTOLET\",\n  \"weapon_rifle\": \"FUSIL\",\n  \"weapon_rifle_burst\": \"COUP DE FUSIL\",\n  \"weapon_mg\": \"MITRAILLETTE\",\n  \"weapon_mg_heavy\": \"GROSSE MITRAIL.\",\n  \"weapon_rifle_scope\": \"FUSIL SNIPER\",\n  \"weapon_shotgun\": \"FUSIL A POMPE\",\n  \"weapon_shotgun_super\": \"GROS FUS. POMPE\",\n  \"weapon_flame_thrower\": \"LANCE-FLAMMES\",\n  \"weapon_rocket_launcher\": \"LANCE-ROQUETTES\",\n  \"weapon_missile_guided\": \"MISS TELEGUIDE\",\n  \"weapon_rifle_medic\": \"PINCE MEDICALE\",\n  \"weapon_rifle_tranq\": \"TRANQUILLISANT\",\n  \"weapon_grenade\": \"GRENADE\",\n  \"weapon_grenade_cluster\": \"GREN FRAGMENT.\",\n  \"weapon_grenade_hx\": \"GREN SUP EXPLOS\",\n  \"weapon_grenade_roller\": \"GRENADE RAPIDE\",\n  \"weapon_gas_confusion\": \"GAZ CONFUSION\",\n  \"weapon_gas_freeze\": \"GAZ PARALYSANT\",\n  \"weapon_gas_madness\": \"GAZ FOLIE\",\n  \"weapon_gas_poison\": \"GAZ POISON\",\n  \"weapon_grenade_shrapnel\": \"GREN SHRAPNEL\",\n  \"weapon_mortar\": \"MORTIER\",\n  \"weapon_bazooka\": \"BAZOOKA\",\n  \"weapon_grenade_launcher\": \"LANCE-GRENADES\",\n  \"weapon_airburst\": \"BOMBE FRAGMENT.\",\n  \"weapon_airburst_super\": \"SUPER BMB FRAG.\",\n  \"weapon_grenade_medic\": \"GREN. MEDICALE\",\n  \"weapon_missile_homing\": \"MISS. AUTOGUIDE\",\n  \"weapon_mine\": \"MINE\",\n  \"weapon_mine_antip\": \"MINE ANTI-PERSO\",\n  \"weapon_mine_antip\": \"TNT\",\n  \"weapon_tnt_super\": \"SUPER TNT\",\n  \"weapon_shell_long_range\": \"OBUS LG PORTEE\",\n  \"weapon_shell_mine\": \"OBUS A MINES\",\n  \"weapon_shell_gas\": \"OBUS A GAZ\",\n  \"weapon_shell_fire_rain\": \"OBUS DE FEU\",\n  \"weapon_shell_1000_lbs\": \"OBUS 500 KG\",\n  \"weapon_shell_shock\": \"OBUS DE CHOC\",\n  \"weapon_jetpack\": \"JETPACK\",\n  \"weapon_suicide\": \"SUICIDE\",\n  \"weapon_healing_hands\": \"GUERISON\",\n  \"weapon_self_heal\": \"AUTOGUERISON\",\n  \"weapon_pick_pocket\": \"PICKPOCKET\",\n  \"weapon_hide\": \"CACHER\",\n  \"weapon_shockwave\": \"ONDE DE CHOC\",\n  \"weapon_special_ops\": \"OPER. SPECIALES\",\n  \"weapon_airstrike\": \"RAID AERIEN\",\n  \"weapon_airstrike_fire\": \"PLUIE DE FEU\",\n  \"weapon_inout_vehicle\": \"VEHICULE INOUT\",\n  \"weapon_inout_building\": \"BATIMENT INOUT\",\n  \"weapon_eject_pig\": \"EJECTER COCHON\",\n  \"weapon_map_view\": \"VOIR CARTE\",\n  \"weapon_binoculars\": \"JUMELLES\",\n  \"weapon_skip_turn\": \"PASSER TOUR\",\n  \"weapon_surrender\": \"SE RENDRE\",\n  \"vehicle_artillery\": \"ARTILLERIE\",\n  \"vehicle_tent_medic\": \"TENTE TOUBIB\",\n  \"vehicle_tent_mash\": \"TENTE HOPIT\",\n  \"vehicle_pillbox\": \"BLOCKHAUS\",\n  \"vehicle_sandbags\": \"SACS SABLE\",\n  \"vehicle_shelter\": \"ABRI\",\n  \"vehicle_tent\": \"TENTE\",\n  \"vehicle_airship\": \"DIRIGEABLE\",\n  \"vehicle_duck\": \"VEH AMPHIBIE\",\n  \"vehicle_tank_aqua\": \"CHAR AMPHIB.\",\n  \"vehicle_boat\": \"BATEAU\",\n  \"vehicle_plane\": \"AVION\",\n  \"vehicle_tank\": \"CHAR\",\n  \"vehicle_truck\": \"CAMION\",\n  \"mp_l00\": \"%s HAS LEFT THE GAME\",\n  \"mp_l02\": \"%s HAS LEFT WITH HIS TAIL BETWEEN HIS LEGS\",\n  \"mp_l03\": \"BYE BYE %s\",\n  \"mp_l04\": \"%s COULDN'T TAKE THE PACE\",\n  \"mp_l05\": \"%s COULDN'T STAND THE HEAT\",\n  \"mp_l06\": \"%s HAS LEFT THE FORAY\",\n  \"mp_l07\": \"%s WILL BE MISSED\",\n  \"mp_l08\": \"%s RUNS LIKE A GIRL\",\n  \"mp_l09\": \"%s HAS GIVEN UP\",\n  \"mp_l10\": \"%s LEAVES QUIETLY\",\n  \"mp_l11\": \"%s HURRIEDLY RETREATS\",\n  \"mp_l12\": \"%s IS OUTTA HERE!\"\n}"
  },
  {
    "path": "bin/mods/base/languages/ger.language",
    "content": "{\n  \"english\": \"ENGLISH\",\n  \"french\": \"FRANÇAIS\",\n  \"german\": \"DEUTSCH\",\n  \"italian\": \"ITALIANO\",\n  \"spanish\": \"ESPAÑOL\",\n  \"russian\": \"РУССКИЙ\",\n  \"yes\": \"JA\",\n  \"no\": \"NEIN\",\n  \"ok\": \"OKAY\",\n  \"fe_main\": \"HAUPTMENÜ\",\n  \"fe_yn_quit\": \"WILLST DU WIRKLICH AUFGEBEN?\",\n  \"mode_sn\": \"TEAM-FRISCHLING\",\n  \"mode_se\": \"TEAM-EXPERTE\",\n  \"mode_ss\": \"TEAM-METZGER\",\n  \"mode_dm\": \"SCHLACHT\",\n  \"mode_ge\": \"ERZEUGEN\",\n  \"map_how_road\": \"DIE PATROUILLE\",\n  \"map_how_trench\": \"GRABENKRIEG\",\n  \"map_how_rumble\": \"INSELSPRINGEN\",\n  \"map_how_devi\": \"MORGENROT\",\n  \"map_how_twin\": \"HALLO? HALLO?\",\n  \"map_how_zulus\": \"BELAGERUNGSZUSTAND\",\n  \"map_how_sniper\": \"SPION GEGEN SPION\",\n  \"map_how_guns\": \"GESCHNETZELTES\",\n  \"map_how_oasis\": \"DIE WÜSTE BEBT!\",\n  \"map_how_mashed\": \"HOCH HINAUS\",\n  \"map_how_camp\": \"TRAININGSLAGER\",\n  \"map_how_liberate\": \"RETTET DAS SCHWEIN\",\n  \"map_how_medix\": \"IM WESTEN WAS NEUES\",\n  \"map_how_fjords\": \"HEISSKALTER EINSATZ\",\n  \"map_how_eyrie\": \"AUF GEFECHTSSTATION\",\n  \"map_how_bridge\": \"SCHLACHTHAUS NUMMER 5\",\n  \"map_how_bay\": \"EIN AKT DER BARBAREI\",\n  \"map_how_desval\": \"VERSTECKSPIEL\",\n  \"map_how_snake\": \"GIFTMISCHER\",\n  \"map_how_emplace\": \"HEILPRAKTIKER\",\n  \"map_how_keep\": \"CHIRURGISCHER SCHLAG\",\n  \"map_how_supline\": \"LATRINENDIENST\",\n  \"map_how_tester\": \"HELDEN GESUCHT\",\n  \"map_how_foot\": \"SCHLACHTPLATTE\",\n  \"map_how_final\": \"AN DIE TRÖGE\",\n  \"map_how_estu\": \"DER BRÜCKENKOPF\",\n  \"map_how_boom\": \"PFAHLBÜRGER\",\n  \"map_how_bhill\": \"VERDAMMT\",\n  \"map_how_lecprod\": \"ESELSBRÜCKE\",\n  \"map_how_dval\": \"TAL DES TODES\",\n  \"map_how_ice\": \"KÜHLSCHRANK\",\n  \"map_how_bute\": \"HINTERM MOND\",\n  \"map_how_maze\": \"IRRGARTEN\",\n  \"map_how_sepia1\": \"VIER ECKEN\",\n  \"map_how_dbowl\": \"KESSELSCHLACHT\",\n  \"map_how_mlake\": \"COOLE KERLE\",\n  \"map_how_cmass\": \"KRASSE KRATER\",\n  \"map_how_artgun\": \"DUMM GELAUFEN\",\n  \"map_how_dval2\": \"TAL DES TODES 2\",\n  \"map_how_hell3\": \"KOPFNUSS\",\n  \"map_how_hell2\": \"SANDKASTEN\",\n  \"map_how_lunar1\": \"MOONWALK\",\n  \"map_how_creepy2\": \"FRIEDHOFSRUHE\",\n  \"map_how_play1\": \"KRABBELDECKE\",\n  \"map_how_play2\": \"KISSENSCHLACHT\",\n  \"map_how_iceflow\": \"EISBOMBEN\",\n  \"map_how_ridge\": \"SCHWEINERÜCKEN\",\n  \"map_how_archi\": \"BERGFEST\",\n  \"map_how_demo\": \"DEMO LEVEL\",\n  \"map_how_island\": \"AH-TOLL\",\n  \"map_how_lake\": \"OASE\",\n  \"map_how_oneway\": \"EINBAHNSTRASSE\",\n  \"team_british\": \"FISH'N'RIBS\",\n  \"team_french\": \"PORC AU VIN\",\n  \"team_american\": \"BEEFY BOYS\",\n  \"team_russian\": \"GRUNZKOVSKI\",\n  \"team_japanese\": \"BONSAI QUIEKER\",\n  \"team_german\": \"EISBEINE\",\n  \"team_lard\": \"TEAM LARD\",\n  \"pig_british_1\": \"SIR LLOYD\",\n  \"pig_british_2\": \"006\",\n  \"pig_british_3\": \"ARTI\",\n  \"pig_british_4\": \"HAGGIS\",\n  \"pig_british_5\": \"SISSY\",\n  \"pig_british_6\": \"KONGO\",\n  \"pig_british_7\": \"BEEFY\",\n  \"pig_british_8\": \"RÜSSEL\",\n  \"pig_british_9\": \"GRUNT\",\n  \"pig_french_1\": \"LABOEUF\",\n  \"pig_french_2\": \"COCHON\",\n  \"pig_french_3\": \"PIGARD\",\n  \"pig_french_4\": \"OBESE\",\n  \"pig_french_5\": \"FLAMBE\",\n  \"pig_french_6\": \"FILET\",\n  \"pig_french_7\": \"PATEE\",\n  \"pig_french_8\": \"TARTARE\",\n  \"pig_french_9\": \"JAMBON\",\n  \"pig_american_1\": \"COWPIG\",\n  \"pig_american_2\": \"DEE-JAY\",\n  \"pig_american_3\": \"DER DON\",\n  \"pig_american_4\": \"SCHWART\",\n  \"pig_american_5\": \"SPECK\",\n  \"pig_american_6\": \"WOODY\",\n  \"pig_american_7\": \"DUMBO\",\n  \"pig_american_8\": \"ARNI\",\n  \"pig_american_9\": \"TIBERIUS\",\n  \"pig_russian_1\": \"IWAN\",\n  \"pig_russian_2\": \"SPECKOV\",\n  \"pig_russian_3\": \"DJINGIS\",\n  \"pig_russian_4\": \"DIMITRI\",\n  \"pig_russian_5\": \"WLADIMIR\",\n  \"pig_russian_6\": \"FJODOR\",\n  \"pig_russian_7\": \"PJOTR\",\n  \"pig_russian_8\": \"ALEXEJ\",\n  \"pig_russian_9\": \"LEONID\",\n  \"pig_japanese_1\": \"SATE\",\n  \"pig_japanese_2\": \"GRUNZ LIE\",\n  \"pig_japanese_3\": \"SHIN KEN\",\n  \"pig_japanese_4\": \"XIAO PIG\",\n  \"pig_japanese_5\": \"BUTA\",\n  \"pig_japanese_6\": \"DUM SAU\",\n  \"pig_japanese_7\": \"WAN-TAN\",\n  \"pig_japanese_8\": \"WEI MIE\",\n  \"pig_japanese_9\": \"WOK HOG\",\n  \"pig_german_1\": \"DER GRAF\",\n  \"pig_german_2\": \"RUDI\",\n  \"pig_german_3\": \"KUTTE\",\n  \"pig_german_4\": \"RESPEKT\",\n  \"pig_german_5\": \"MANNI\",\n  \"pig_german_6\": \"EDE\",\n  \"pig_german_7\": \"ABSEITS\",\n  \"pig_german_8\": \"HAXE\",\n  \"pig_german_9\": \"KÄPT'N\",\n  \"pig_lard_1\": \"SIMON\",\n  \"pig_lard_2\": \"TAPPER\",\n  \"pig_lard_3\": \"JOHN\",\n  \"pig_lard_4\": \"ANDY\",\n  \"pig_lard_5\": \"MARK\",\n  \"pig_lard_6\": \"JAKE\",\n  \"pig_lard_7\": \"MARTYN\",\n  \"pig_lard_8\": \"IZZY\",\n  \"pig_lard_9\": \"RICKI\",\n  \"pig_lard_10\": \"DOLLY\",\n  \"pig_lard_11\": \"FIL\",\n  \"pig_lard_12\": \"ADE\",\n  \"pig_lard_13\": \"SHORTY\",\n  \"pig_lard_14\": \"BEN\",\n  \"pig_lard_15\": \"BADDERS\",\n  \"pig_lard_16\": \"PHILIP\",\n  \"pig_lard_17\": \"JIM\",\n  \"pig_lard_18\": \"PAUL\",\n  \"pig_lard_19\": \"JAMES\",\n  \"pig_lard_20\": \"SWEETY\",\n  \"career\": \"KARRIERE\",\n  \"career_heavy\": \"ARTILLERIE\",\n  \"career_engineer\": \"PIONIERE\",\n  \"career_espionage\": \"GEHEIMDIENST\",\n  \"career_medic\": \"SANITÄTER\",\n  \"class_grunt\": \"FRONTSCHWEIN\",\n  \"class_gunner\": \"SCHÜTZE\",\n  \"class_bombardier\": \"KANONIER\",\n  \"class_pyrotechnic\": \"PYROMANE\",\n  \"class_commando\": \"KAMPFKEILER\",\n  \"class_sapper\": \"PIONIER\",\n  \"class_engineer\": \"INGENIEUR\",\n  \"class_saboteur\": \"SABOTEUR\",\n  \"class_scout\": \"SCOUT\",\n  \"class_sniper\": \"SCHARFSCHÜTZE\",\n  \"class_spy\": \"SPION\",\n  \"class_orderly\": \"SANITÄTER\",\n  \"class_medic\": \"FELDARZT\",\n  \"class_surgeon\": \"CHIRURG\",\n  \"class_hero\": \"HELD\",\n  \"class_ace\": \"AS\",\n  \"class_legend\": \"LEGENDE\",\n  \"class_grenadier\": \"GRENADIER\",\n  \"class_paratrooper\": \"FALLSCHIRMSPRINGER\",\n  \"weapon_none\": \"KEINE\",\n  \"weapon_trotter\": \"HUF\",\n  \"weapon_knife\": \"MESSER\",\n  \"weapon_bayonet\": \"BAJONETT\",\n  \"weapon_sword\": \"SÄBEL\",\n  \"weapon_cattle_prod\": \"ELEKTROSCHOCK\",\n  \"weapon_pistol\": \"PISTOLE\",\n  \"weapon_rifle\": \"GEWEHR\",\n  \"weapon_rifle_burst\": \"GEWEHRSALVE\",\n  \"weapon_mg\": \"MG\",\n  \"weapon_mg_heavy\": \"SCHWERES MG\",\n  \"weapon_rifle_scope\": \"SNIPER-GEWEHR\",\n  \"weapon_shotgun\": \"SCHROTGEWEHR\",\n  \"weapon_shotgun_super\": \"SUPER-SCHROTGEW.\",\n  \"weapon_flame_thrower\": \"FLAMMENWERFER\",\n  \"weapon_rocket_launcher\": \"RAKETENWERFER\",\n  \"weapon_missile_guided\": \"LENKRAKETE\",\n  \"weapon_rifle_medic\": \"MEDIZINPFEIL\",\n  \"weapon_rifle_tranq\": \"TRANQUILISER\",\n  \"weapon_grenade\": \"GRANATE\",\n  \"weapon_grenade_cluster\": \"CLUSTERGRANATE\",\n  \"weapon_grenade_hx\": \"HX-GRANATE\",\n  \"weapon_grenade_roller\": \"KULLERGRANATE\",\n  \"weapon_gas_confusion\": \"LACHGAS\",\n  \"weapon_gas_freeze\": \"BETÄUBUNGSGAS\",\n  \"weapon_gas_madness\": \"BSE-GAS\",\n  \"weapon_gas_poison\": \"SCHWEINEPEST\",\n  \"weapon_grenade_shrapnel\": \"SPLITTERGRANATE\",\n  \"weapon_mortar\": \"MÖRSER\",\n  \"weapon_bazooka\": \"BAZOOKA\",\n  \"weapon_grenade_launcher\": \"GRANATWERFER\",\n  \"weapon_airburst\": \"AIRBURST\",\n  \"weapon_airburst_super\": \"SUPER AIRBURST\",\n  \"weapon_grenade_medic\": \"MEDIZINBALL\",\n  \"weapon_missile_homing\": \"SUCHRAKETE\",\n  \"weapon_mine\": \"MINE\",\n  \"weapon_mine_antip\": \"ANTI-S MINE\",\n  \"weapon_mine_antip\": \"TNT\",\n  \"weapon_tnt_super\": \"HX-TNT\",\n  \"weapon_shell_long_range\": \"LEICHTE GRANATE\",\n  \"weapon_shell_mine\": \"MINENLEGER\",\n  \"weapon_shell_gas\": \"PEST-GRANATE\",\n  \"weapon_shell_fire_rain\": \"GRILL-GRANATE\",\n  \"weapon_shell_1000_lbs\": \"453,6 KG-GRANATE\",\n  \"weapon_shell_shock\": \"SCHOCK-GRANATE\",\n  \"weapon_jetpack\": \"JETPACK\",\n  \"weapon_suicide\": \"KAMIKAZE\",\n  \"weapon_healing_hands\": \"HEILENDE HÄNDE\",\n  \"weapon_self_heal\": \"SELBSTHEILUNG\",\n  \"weapon_pick_pocket\": \"TASCHENDIEB\",\n  \"weapon_hide\": \"TARNEN\",\n  \"weapon_shockwave\": \"SCHOCKWELLE\",\n  \"weapon_special_ops\": \"SPEC-OPS\",\n  \"weapon_airstrike\": \"LUFTSCHLAG\",\n  \"weapon_airstrike_fire\": \"GRILL-LUFTSCHL.\",\n  \"weapon_inout_vehicle\": \"KFZ REIN/RAUS\",\n  \"weapon_inout_building\": \"GEB. REIN/RAUS\",\n  \"weapon_eject_pig\": \"AUSSTEIGEN\",\n  \"weapon_map_view\": \"KARTE ANSEHEN\",\n  \"weapon_binoculars\": \"FERNGLAS\",\n  \"weapon_skip_turn\": \"AUSSETZEN\",\n  \"weapon_surrender\": \"KAPITULATION\",\n  \"vehicle_artillery\": \"GESCHÜTZ\",\n  \"vehicle_tent_medic\": \"SANI-ZELT\",\n  \"vehicle_tent_mash\": \"FELDLAZARETT\",\n  \"vehicle_pillbox\": \"MG-STAND\",\n  \"vehicle_sandbags\": \"SANDSÄCKE\",\n  \"vehicle_shelter\": \"UNTERSTAND\",\n  \"vehicle_tent\": \"ZELT\",\n  \"vehicle_airship\": \"LUFTSCHIFF\",\n  \"vehicle_duck\": \"AMPHI-CAR\",\n  \"vehicle_tank_aqua\": \"AQUA-TANK\",\n  \"vehicle_boat\": \"BOOT\",\n  \"vehicle_plane\": \"FLUGZEUG\",\n  \"vehicle_tank\": \"PANZER\",\n  \"vehicle_truck\": \"LKW\",\n  \"mp_l00\": \"%s HAS LEFT THE GAME\",\n  \"mp_l02\": \"%s HAS LEFT WITH HIS TAIL BETWEEN HIS LEGS\",\n  \"mp_l03\": \"BYE BYE %s\",\n  \"mp_l04\": \"%s COULDN'T TAKE THE PACE\",\n  \"mp_l05\": \"%s COULDN'T STAND THE HEAT\",\n  \"mp_l06\": \"%s HAS LEFT THE FORAY\",\n  \"mp_l07\": \"%s WILL BE MISSED\",\n  \"mp_l08\": \"%s RUNS LIKE A GIRL\",\n  \"mp_l09\": \"%s HAS GIVEN UP\",\n  \"mp_l10\": \"%s LEAVES QUIETLY\",\n  \"mp_l11\": \"%s HURRIEDLY RETREATS\",\n  \"mp_l12\": \"%s IS OUTTA HERE!\"\n}"
  },
  {
    "path": "bin/mods/base/languages/ita.language",
    "content": "{\n  \"english\": \"ENGLISH\",\n  \"french\": \"FRANÇAIS\",\n  \"german\": \"DEUTSCH\",\n  \"italian\": \"ITALIANO\",\n  \"spanish\": \"ESPAÑOL\",\n  \"russian\": \"РУССКИЙ\",\n  \"yes\": \"SÌ\",\n  \"no\": \"NO\",\n  \"ok\": \"OK\",\n  \"fe_main\": \"MENU PRINCIPALE\",\n  \"fe_yn_quit\": \"VUOI VERAMENTE USCIRE?\",\n  \"mode_sn\": \"SOPRAVV.-NOVELLINO\",\n  \"mode_se\": \"SOPRAVV.-ESPERTO\",\n  \"mode_ss\": \"SOPRAVV.-STRATEGA\",\n  \"mode_dm\": \"MATCH DELLA MORTE\",\n  \"mode_ge\": \"GENERA\",\n  \"map_how_road\": \"L'IMBOSCATA\",\n  \"map_how_trench\": \"MISSIONE BONTÀ\",\n  \"map_how_rumble\": \"LO SBARCO DEI MILLE\",\n  \"map_how_devi\": \"IL DOPPIOGIOCHISTA\",\n  \"map_how_twin\": \"BLOCCO DELLE COMUNICAZIONI\",\n  \"map_how_zulus\": \"SOTTO ASSEDIO\",\n  \"map_how_sniper\": \"CONTROSPIONAGGIO\",\n  \"map_how_guns\": \"OPERAZIONE SILENZIO\",\n  \"map_how_oasis\": \"DESERT STORM\",\n  \"map_how_mashed\": \"IL TROGOLO SULLA COLLINA\",\n  \"map_how_camp\": \"CAMPO D'ADDESTRAMENTO\",\n  \"map_how_liberate\": \"SALVATE IL SOLDATO MAYAL\",\n  \"map_how_medix\": \"MAIALI DA TRINCEA\",\n  \"map_how_fjords\": \"ACCOGLIENZA GLACIALE\",\n  \"map_how_eyrie\": \"MISSIONE PALLA D'ACCIAIO\",\n  \"map_how_bridge\": \"LA CONVENZIONE DI GINEVRA\",\n  \"map_how_bay\": \"OPERAZIONE BORDEAUX\",\n  \"map_how_desval\": \"SPIE COME VOI\",\n  \"map_how_snake\": \"THE CHEMICAL BROTHER\",\n  \"map_how_emplace\": \"OP. TALLONE D'ACHILLE\",\n  \"map_how_keep\": \"MISSIONE: IMPROBABILE\",\n  \"map_how_supline\": \"LUNGA E DRITTA\",\n  \"map_how_tester\": \"OPERAZIONE TAVOLA ROTONDA\",\n  \"map_how_foot\": \"CHEESEBURGER HILL\",\n  \"map_how_final\": \"LA BATTAGLIA FINALE\",\n  \"map_how_estu\": \"GUERRA: EPISODE ONE\",\n  \"map_how_boom\": \"FUOCO AMICO\",\n  \"map_how_bhill\": \"LO SBARRAMENTO\",\n  \"map_how_lecprod\": \"IL PONTE\",\n  \"map_how_dval\": \"LA VALLE DELLA MORTE\",\n  \"map_how_ice\": \"TEXT MISSING\",\n  \"map_how_bute\": \"LUNA PIENA\",\n  \"map_how_maze\": \"IL DEDALO\",\n  \"map_how_sepia1\": \"ATTACCO QUADRATO\",\n  \"map_how_dbowl\": \"TRAPPOLA A VALLE\",\n  \"map_how_mlake\": \"SFIDA GLACIALE\",\n  \"map_how_cmass\": \"IL CRATERE\",\n  \"map_how_artgun\": \"VOTATI ALLA MORTE\",\n  \"map_how_dval2\": \"LA VALLE DELLA MORTE 2\",\n  \"map_how_hell3\": \"IL TESCHIO\",\n  \"map_how_hell2\": \"MAIALI VERDI FRITTI\",\n  \"map_how_lunar1\": \"MAIALI SPAZIALI\",\n  \"map_how_creepy2\": \"OPERAZIONE CIMITERO\",\n  \"map_how_play1\": \"LA GRANDE PIUMA\",\n  \"map_how_play2\": \"PATCHWORK\",\n  \"map_how_iceflow\": \"CAMPO FREEZER\",\n  \"map_how_ridge\": \"IN VETTA\",\n  \"map_how_archi\": \"LA COLLINA DELLA FOLLIA\",\n  \"map_how_demo\": \"DEMO\",\n  \"map_how_island\": \"L'ARCIPELAGO\",\n  \"map_how_lake\": \"GITA AL LAGO\",\n  \"map_how_oneway\": \"SENSO UNICO\",\n  \"team_british\": \"HOT HOGS\",\n  \"team_french\": \"COCHON\",\n  \"team_american\": \"NEW PORKERS\",\n  \"team_russian\": \"PORCOTROIKA\",\n  \"team_japanese\": \"SUINI BELLICI\",\n  \"team_german\": \"KRAUTENTRUPPEN\",\n  \"team_lard\": \"TEAM LARD\",\n  \"pig_british_1\": \"HOGGY\",\n  \"pig_british_2\": \"GINGER\",\n  \"pig_british_3\": \"DEN\",\n  \"pig_british_4\": \"MONTY\",\n  \"pig_british_5\": \"BASIL\",\n  \"pig_british_6\": \"PIGGY\",\n  \"pig_british_7\": \"PERCY\",\n  \"pig_british_8\": \"SMITH\",\n  \"pig_british_9\": \"JONES\",\n  \"pig_french_1\": \"BASTILLE\",\n  \"pig_french_2\": \"LE CONT\",\n  \"pig_french_3\": \"GERARD\",\n  \"pig_french_4\": \"JEANPIG\",\n  \"pig_french_5\": \"PORCON\",\n  \"pig_french_6\": \"GUSTAV\",\n  \"pig_french_7\": \"PORC\",\n  \"pig_french_8\": \"MONPORC\",\n  \"pig_french_9\": \"GLOUTON\",\n  \"pig_american_1\": \"CHUCKY\",\n  \"pig_american_2\": \"SLY\",\n  \"pig_american_3\": \"KEANU\",\n  \"pig_american_4\": \"ABRAHAM\",\n  \"pig_american_5\": \"JOHN-BOY\",\n  \"pig_american_6\": \"JIM-BOB\",\n  \"pig_american_7\": \"BOBBY-JIM\",\n  \"pig_american_8\": \"BOBBY-JOE\",\n  \"pig_american_9\": \"JOEY-BOB\",\n  \"pig_russian_1\": \"PORKOSKI\",\n  \"pig_russian_2\": \"HUSKI\",\n  \"pig_russian_3\": \"JETSKI\",\n  \"pig_russian_4\": \"STAKANOV\",\n  \"pig_russian_5\": \"GAGARIN\",\n  \"pig_russian_6\": \"TROTZKI\",\n  \"pig_russian_7\": \"TRIPPOV\",\n  \"pig_russian_8\": \"ZAMPOSKI\",\n  \"pig_russian_9\": \"SUINOV\",\n  \"pig_japanese_1\": \"BEPI\",\n  \"pig_japanese_2\": \"TOTUZZO\",\n  \"pig_japanese_3\": \"GINO\",\n  \"pig_japanese_4\": \"BARTALO\",\n  \"pig_japanese_5\": \"GIUANIN\",\n  \"pig_japanese_6\": \"ROCCHINO\",\n  \"pig_japanese_7\": \"TURIDDU\",\n  \"pig_japanese_8\": \"ROSARIO\",\n  \"pig_japanese_9\": \"SPARTACO\",\n  \"pig_german_1\": \"HERMAN\",\n  \"pig_german_2\": \"WOLFIE\",\n  \"pig_german_3\": \"VON KRAUT\",\n  \"pig_german_4\": \"VON TRIPP\",\n  \"pig_german_5\": \"HERMAYAL\",\n  \"pig_german_6\": \"SCHNITZEL\",\n  \"pig_german_7\": \"KRUDOLF\",\n  \"pig_german_8\": \"RAID\",\n  \"pig_german_9\": \"VONWURST\",\n  \"pig_lard_1\": \"SIMON\",\n  \"pig_lard_2\": \"TAPPER\",\n  \"pig_lard_3\": \"JOHN\",\n  \"pig_lard_4\": \"ANDY\",\n  \"pig_lard_5\": \"MARK\",\n  \"pig_lard_6\": \"JAKE\",\n  \"pig_lard_7\": \"MARTYN\",\n  \"pig_lard_8\": \"IZZY\",\n  \"pig_lard_9\": \"RICKI\",\n  \"pig_lard_10\": \"DOLLY\",\n  \"pig_lard_11\": \"FIL\",\n  \"pig_lard_12\": \"ADE\",\n  \"pig_lard_13\": \"SHORTY\",\n  \"pig_lard_14\": \"BEN\",\n  \"pig_lard_15\": \"BADDERS\",\n  \"pig_lard_16\": \"PHILIP\",\n  \"pig_lard_17\": \"JIM\",\n  \"pig_lard_18\": \"PAUL\",\n  \"pig_lard_19\": \"JAMES\",\n  \"pig_lard_20\": \"SWEETY\",\n  \"career\": \"CARRIERA\",\n  \"career_heavy\": \"ARMI PESANTI\",\n  \"career_engineer\": \"INGEGNERE\",\n  \"career_espionage\": \"SPIONAGGIO\",\n  \"career_medic\": \"MEDICO\",\n  \"class_grunt\": \"RECLUTA\",\n  \"class_gunner\": \"ARTIGLIERE\",\n  \"class_bombardier\": \"BOMBARDIERE\",\n  \"class_pyrotechnic\": \"SPECIALISTA\",\n  \"class_commando\": \"CAPORALE\",\n  \"class_sapper\": \"APPRENDISTA\",\n  \"class_engineer\": \"INGEGNERE\",\n  \"class_saboteur\": \"SABOTATORE\",\n  \"class_scout\": \"ESPLORATORE\",\n  \"class_sniper\": \"CECCHINO\",\n  \"class_spy\": \"SPIA\",\n  \"class_orderly\": \"INFERMIERE\",\n  \"class_medic\": \"MEDICO\",\n  \"class_surgeon\": \"CHIRURGO\",\n  \"class_hero\": \"EROE\",\n  \"class_ace\": \"ASSO\",\n  \"class_legend\": \"LEGGENDA\",\n  \"class_grenadier\": \"GRANATIERE\",\n  \"class_paratrooper\": \"PARA'\",\n  \"weapon_none\": \"NIENTE\",\n  \"weapon_trotter\": \"PUGNO\",\n  \"weapon_knife\": \"COLTELLO\",\n  \"weapon_bayonet\": \"BAIONETTA\",\n  \"weapon_sword\": \"SPADA\",\n  \"weapon_cattle_prod\": \"ELETTROSHOCK\",\n  \"weapon_pistol\": \"PISTOLA\",\n  \"weapon_rifle\": \"FUCILE\",\n  \"weapon_rifle_burst\": \"RAFFICA FUCILE\",\n  \"weapon_mg\": \"MITRAGLIATRICE\",\n  \"weapon_mg_heavy\": \"MITR. PESANTE\",\n  \"weapon_rifle_scope\": \"FUCILE DI PREC.\",\n  \"weapon_shotgun\": \"DOPPIETTA\",\n  \"weapon_shotgun_super\": \"SUPER DOPPIETTA\",\n  \"weapon_flame_thrower\": \"LANCIA FIAMME\",\n  \"weapon_rocket_launcher\": \"LANCIARAZZI\",\n  \"weapon_missile_guided\": \"MISSILE GUIDATO\",\n  \"weapon_rifle_medic\": \"DARDO MEDICO\",\n  \"weapon_rifle_tranq\": \"IMMOBILIZZATORE\",\n  \"weapon_grenade\": \"GRANATA\",\n  \"weapon_grenade_cluster\": \"GRANATA MULT.\",\n  \"weapon_grenade_hx\": \"GRANATA POTENTE\",\n  \"weapon_grenade_roller\": \"GRANATA ROTANTE\",\n  \"weapon_gas_confusion\": \"GAS FRASTORNAN.\",\n  \"weapon_gas_freeze\": \"GAS IMMOBILIZZ.\",\n  \"weapon_gas_madness\": \"GAS STORDENTE\",\n  \"weapon_gas_poison\": \"GAS VELENOSO\",\n  \"weapon_grenade_shrapnel\": \"SHRAPNEL\",\n  \"weapon_mortar\": \"MORTAIO\",\n  \"weapon_bazooka\": \"BAZOOKA\",\n  \"weapon_grenade_launcher\": \"LANCIA GRANATE\",\n  \"weapon_airburst\": \"COLPO MULTIPLO\",\n  \"weapon_airburst_super\": \"SUPERCOLPO MUL.\",\n  \"weapon_grenade_medic\": \"GRANATA MEDICA\",\n  \"weapon_missile_homing\": \"MISS. A RICERCA\",\n  \"weapon_mine\": \"MINA\",\n  \"weapon_mine_antip\": \"MINA ANTI-UOMO\",\n  \"weapon_mine_antip\": \"TNT\",\n  \"weapon_tnt_super\": \"SUPER TNT\",\n  \"weapon_shell_long_range\": \"COLPO LUNGO\",\n  \"weapon_shell_mine\": \"MULTI-MINA\",\n  \"weapon_shell_gas\": \"GAS A DISPERS.\",\n  \"weapon_shell_fire_rain\": \"PIOGG. DI FUOCO\",\n  \"weapon_shell_1000_lbs\": \"COLPO 333 KG\",\n  \"weapon_shell_shock\": \"COLPO AD ONDA\",\n  \"weapon_jetpack\": \"JETPACK\",\n  \"weapon_suicide\": \"SUICIDIO\",\n  \"weapon_healing_hands\": \"CURA\",\n  \"weapon_self_heal\": \"AUTO CURA\",\n  \"weapon_pick_pocket\": \"FURTO\",\n  \"weapon_hide\": \"MIMETIZZAZIONE\",\n  \"weapon_shockwave\": \"ONDA D'URTO\",\n  \"weapon_special_ops\": \"OPER. SPECIALI\",\n  \"weapon_airstrike\": \"ATTACCO AEREO\",\n  \"weapon_airstrike_fire\": \"PIOGGIA AEREA\",\n  \"weapon_inout_vehicle\": \"VEICOLO INOUT\",\n  \"weapon_inout_building\": \"EDIFICIO INOUT\",\n  \"weapon_eject_pig\": \"ESPULS. MAIALE\",\n  \"weapon_map_view\": \"MAPPA\",\n  \"weapon_binoculars\": \"BINOCOLO\",\n  \"weapon_skip_turn\": \"SALTARE TURNO\",\n  \"weapon_surrender\": \"ARRENDERSI\",\n  \"vehicle_artillery\": \"ARTIGLIERIA\",\n  \"vehicle_tent_medic\": \"TENDA MEDICA\",\n  \"vehicle_tent_mash\": \"SOCCORSO\",\n  \"vehicle_pillbox\": \"BUNKER\",\n  \"vehicle_sandbags\": \"SACCHI\",\n  \"vehicle_shelter\": \"RIFUGIO\",\n  \"vehicle_tent\": \"TENDA\",\n  \"vehicle_airship\": \"AERONAVE\",\n  \"vehicle_duck\": \"ANFIBIO\",\n  \"vehicle_tank_aqua\": \"ACQUA-TANK\",\n  \"vehicle_boat\": \"BARCA\",\n  \"vehicle_plane\": \"AEREO\",\n  \"vehicle_tank\": \"CARRO ARMATO\",\n  \"vehicle_truck\": \"AUTOCARRO\",\n  \"mp_l00\": \"%s HAS LEFT THE GAME\",\n  \"mp_l02\": \"%s HAS LEFT WITH HIS TAIL BETWEEN HIS LEGS\",\n  \"mp_l03\": \"BYE BYE %s\",\n  \"mp_l04\": \"%s COULDN'T TAKE THE PACE\",\n  \"mp_l05\": \"%s COULDN'T STAND THE HEAT\",\n  \"mp_l06\": \"%s HAS LEFT THE FORAY\",\n  \"mp_l07\": \"%s WILL BE MISSED\",\n  \"mp_l08\": \"%s RUNS LIKE A GIRL\",\n  \"mp_l09\": \"%s HAS GIVEN UP\",\n  \"mp_l10\": \"%s LEAVES QUIETLY\",\n  \"mp_l11\": \"%s HURRIEDLY RETREATS\",\n  \"mp_l12\": \"%s IS OUTTA HERE!\"\n}"
  },
  {
    "path": "bin/mods/base/languages/rus.language",
    "content": "{\n  \"english\": \"ENGLISH\",\n  \"french\": \"FRANÇAIS\",\n  \"german\": \"DEUTSCH\",\n  \"italian\": \"ITALIANO\",\n  \"spanish\": \"ESPAÑOL\",\n  \"russian\": \"РУССКИЙ\",\n  \"yes\": \"ДА\",\n  \"no\": \"НЕТ\",\n  \"ok\": \"ОК\",\n  \"fe_main\": \"БАЗОВОЕ МЕНЮ\",\n  \"fe_yn_quit\": \"НУ ЧТО ВАМ, УЖЕ ВЫЙТИ НУЖНО??\",\n  \"mode_sn\": \"БОЕВИТЫЙ РЕКРУТ\",\n  \"mode_se\": \"КРУТОЙ СОЛДАФОН\",\n  \"mode_ss\": \"ТОЛКОВЫЙ ОФИЦЕР\",\n  \"mode_dm\": \"ПОЕДИНОК ИГРОКОВ\",\n  \"mode_ge\": \"СДЕЛАТЬ\",\n  \"map_how_road\": \"ТИХИЙ ПАТРУЛЬ\",\n  \"map_how_trench\": \"В ТРАНШЕЕ\",\n  \"map_how_rumble\": \"ВЫСАДКА НА ОСТРОВ\",\n  \"map_how_devi\": \"ЗАРЯ СЛАВЫ\",\n  \"map_how_twin\": \"ОБРЫВ СВЯЗЕЙ\",\n  \"map_how_zulus\": \"В ОСАДЕ\",\n  \"map_how_sniper\": \"НЕЗРИМЫЙ ФРОНТ\",\n  \"map_how_guns\": \"УДАР В МЯСОРУБКУ\",\n  \"map_how_oasis\": \"ОСОБЫЙ ДЕСЕРТ\",\n  \"map_how_mashed\": \"ДЕРЕВЕНЩИНА\",\n  \"map_how_camp\": \"ОБУЧЕНИЕ\",\n  \"map_how_liberate\": \"СПАСИ САМОГО КАБАНОВА\",\n  \"map_how_medix\": \"ЧЕРЕЗ КРАЙ\",\n  \"map_how_fjords\": \"ЛЕДНИКОВЫЕ ПУШКИ\",\n  \"map_how_eyrie\": \"БОЕВАЯ СТАНЦИЯ\",\n  \"map_how_bridge\": \"ОСОБОЕ НАЗНАЧЕНИЕ\",\n  \"map_how_bay\": \"СВИНСКАЯ КРЕПОСТЬ\",\n  \"map_how_desval\": \"Я ШПИОН...\",\n  \"map_how_snake\": \"ХИМИЧЕСКОЕ ОРУЖИЕ\",\n  \"map_how_emplace\": \"АХИЛЛЕСОВО РЕШЕНИЕ\",\n  \"map_how_keep\": \"ИСТРЕБЛЕНИЕ ВРАГА\",\n  \"map_how_supline\": \"СУХО И ВЫСОКО\",\n  \"map_how_tester\": \"БРОНЕВИК ГЕРОЯ\",\n  \"map_how_foot\": \"ХОЛМ ГАМБУРГЕРА\",\n  \"map_how_final\": \"ТАК, ТАК, ТАК!\",\n  \"map_how_estu\": \"ОСНОВА ВОЙНЫ\",\n  \"map_how_boom\": \"АЛЬЯНС\",\n  \"map_how_bhill\": \"ПОДРЫВАТЬ ДАМБЫ\",\n  \"map_how_lecprod\": \"ЗАТЫКАНИЕ ДЫР\",\n  \"map_how_dval\": \"ДОЛЫ ГИБЕЛИ\",\n  \"map_how_ice\": \"ХОЛМ МОРОЗА\",\n  \"map_how_bute\": \"ЛУННЫЕ СВИНЫ\",\n  \"map_how_maze\": \"ЛАБИРИНТ В КУСТУ\",\n  \"map_how_sepia1\": \"В АТАКУ\",\n  \"map_how_dbowl\": \"ЧАША СМЕРТИ\",\n  \"map_how_mlake\": \"БИТВА НА ЛЬДИНЕ\",\n  \"map_how_cmass\": \"ВОРОНКИ\",\n  \"map_how_artgun\": \"ОБРЕЧЕН\",\n  \"map_how_dval2\": \"АЛЛЕЯ УЖАСОВ 2\",\n  \"map_how_hell3\": \"ХИТРЫЕ ТРЮКИ\",\n  \"map_how_hell2\": \"ХОЛМ ПОРОСЯТ\",\n  \"map_how_lunar1\": \"СВИНЬИ В КОСМОСЕ\",\n  \"map_how_creepy2\": \"БОЙ НА МОГИЛЕ\",\n  \"map_how_play1\": \"КАРАНДАШ ИГРОКА\",\n  \"map_how_play2\": \"ОДЕЯЛЬНЫЕ ЗАБАВЫ\",\n  \"map_how_iceflow\": \"АЙСБЕРГ\",\n  \"map_how_ridge\": \"ЗА ГОРАМИ\",\n  \"map_how_archi\": \"ТЫ СВИН...\",\n  \"map_how_demo\": \"ДЕМО ВЕРСИЯ\",\n  \"map_how_island\": \"ПРЫГАТЬ ПО ВОДАМ\",\n  \"map_how_lake\": \"ОЗЕРО\",\n  \"map_how_oneway\": \"БЕЗ ВАРИАНТОВ\",\n  \"team_british\": \"ПОРОСНЯ ТОММИ\",\n  \"team_french\": \"СВИНУШКИ ЧЕСНОКА\",\n  \"team_american\": \"КАБАНЫ ДЯДИ СЭМЮЭЛА\",\n  \"team_russian\": \"СВИНОАРМЕЙЦЫ\",\n  \"team_japanese\": \"ПОРОСЯТА СУШИ\",\n  \"team_german\": \"ХРЮКУНЫ КАЙЗЕРА\",\n  \"team_lard\": \"ОТРЯД ХРЯК\",\n  \"pig_british_1\": \"ХОБИТ\",\n  \"pig_british_2\": \"ГЕНГЕРАМ\",\n  \"pig_british_3\": \"ДАК\",\n  \"pig_british_4\": \"МУНДИ\",\n  \"pig_british_5\": \"БАЗЗИ\",\n  \"pig_british_6\": \"ПАТЕРСОН\",\n  \"pig_british_7\": \"ПАРРИ\",\n  \"pig_british_8\": \"СМИТ\",\n  \"pig_british_9\": \"ДЖИМИ\",\n  \"pig_french_1\": \"БАЗИЛЬ\",\n  \"pig_french_2\": \"ЛЕ ФЛАК\",\n  \"pig_french_3\": \"ГЕРАРДИ\",\n  \"pig_french_4\": \"У. ЧЕН\",\n  \"pig_french_5\": \"ДЮСАНГРЕ\",\n  \"pig_french_6\": \"КОШОН\",\n  \"pig_french_7\": \"ПОРК\",\n  \"pig_french_8\": \"ДЖЕФФРИ\",\n  \"pig_french_9\": \"ГЛУПОН\",\n  \"pig_american_1\": \"ЧАКО\",\n  \"pig_american_2\": \"СЛИК\",\n  \"pig_american_3\": \"ЮКОН\",\n  \"pig_american_4\": \"САМЮЭЛЬ\",\n  \"pig_american_5\": \"ДЖЕК-ГАЙ\",\n  \"pig_american_6\": \"БОСС-БИГ\",\n  \"pig_american_7\": \"ДЖИМИ-СВИН\",\n  \"pig_american_8\": \"РОННИ-РЕЙ\",\n  \"pig_american_9\": \"БАКС-МОТ\",\n  \"pig_russian_1\": \"ХРЮШЕВ\",\n  \"pig_russian_2\": \"КАБАНОВ\",\n  \"pig_russian_3\": \"СВИНОВИЧ\",\n  \"pig_russian_4\": \"ТОЛСТЯК\",\n  \"pig_russian_5\": \"ПЯТАЧОК\",\n  \"pig_russian_6\": \"ХРЯЦКО\",\n  \"pig_russian_7\": \"ЗЮЗИН\",\n  \"pig_russian_8\": \"САЛОПЯТ\",\n  \"pig_russian_9\": \"ВОЛ\",\n  \"pig_japanese_1\": \"ЛИДЭН\",\n  \"pig_japanese_2\": \"МОНДО\",\n  \"pig_japanese_3\": \"ЧАНГ ФУ\",\n  \"pig_japanese_4\": \"ФЭНЬ СУЙ\",\n  \"pig_japanese_5\": \"НИНДЗЯ\",\n  \"pig_japanese_6\": \"САЛО\",\n  \"pig_japanese_7\": \"КАРПО\",\n  \"pig_japanese_8\": \"ТЕНЧИ\",\n  \"pig_japanese_9\": \"СЕЛЕДА\",\n  \"pig_german_1\": \"ГЕРМАН\",\n  \"pig_german_2\": \"ШКРАБ\",\n  \"pig_german_3\": \"АЙСВУРСТ\",\n  \"pig_german_4\": \"ГЕРР САЛО\",\n  \"pig_german_5\": \"ГЕРР ХРЮ\",\n  \"pig_german_6\": \"ВУРСТМАН\",\n  \"pig_german_7\": \"ГЕРР ЖИР\",\n  \"pig_german_8\": \"ГЕРР ХРЯК\",\n  \"pig_german_9\": \"ШВАЙН\",\n  \"pig_lard_1\": \"ШИМОН\",\n  \"pig_lard_2\": \"АВРААМ\",\n  \"pig_lard_3\": \"ИСАК\",\n  \"pig_lard_4\": \"ДРОН\",\n  \"pig_lard_5\": \"МАРК\",\n  \"pig_lard_6\": \"НАТАН\",\n  \"pig_lard_7\": \"САМУИЛ\",\n  \"pig_lard_8\": \"ИЗЯ\",\n  \"pig_lard_9\": \"ИЛЬЯ\",\n  \"pig_lard_10\": \"ААРОН\",\n  \"pig_lard_11\": \"ЛЕВ\",\n  \"pig_lard_12\": \"ЭД\",\n  \"pig_lard_13\": \"ТОЛСТОПУЗ\",\n  \"pig_lard_14\": \"БЭН\",\n  \"pig_lard_15\": \"ГАДЕНЫШ\",\n  \"pig_lard_16\": \"ФИЛЛИ\",\n  \"pig_lard_17\": \"ДЖОК\",\n  \"pig_lard_18\": \"ПУЛ\",\n  \"pig_lard_19\": \"ДЖЕКОБ\",\n  \"pig_lard_20\": \"КАСАТИК\",\n  \"career\": \"СОЛДАТЫ\",\n  \"career_heavy\": \"АРТИЛЛЕРИСТЫ\",\n  \"career_engineer\": \"САПЕРЫ\",\n  \"career_espionage\": \"ШПИОНЫ\",\n  \"career_medic\": \"ВРАЧИ\",\n  \"class_grunt\": \"БОЕЦ\",\n  \"class_gunner\": \"ПУШКАРЬ\",\n  \"class_bombardier\": \"БОМБИСТ\",\n  \"class_pyrotechnic\": \"ПИРОМАНЬЯК\",\n  \"class_commando\": \"КОММАНДО\",\n  \"class_sapper\": \"МИНЕР\",\n  \"class_engineer\": \"САПЕР\",\n  \"class_saboteur\": \"ИНЖЕНЕР\",\n  \"class_scout\": \"ДИВЕРСАНТ\",\n  \"class_sniper\": \"СНАЙПЕР\",\n  \"class_spy\": \"ШПИОН\",\n  \"class_orderly\": \"САНИТАР\",\n  \"class_medic\": \"МЕДИК\",\n  \"class_surgeon\": \"ЛЕКАРЬ\",\n  \"class_hero\": \"ГЕРОЙ\",\n  \"class_ace\": \"АС\",\n  \"class_legend\": \"ЛЕГЕНДА\",\n  \"class_grenadier\": \"ГРЕНАДЕР\",\n  \"class_paratrooper\": \"ПАРАШЮТИСТ\",\n  \"weapon_none\": \"НЕТ\",\n  \"weapon_trotter\": \"УДАР СВИНЬИ\",\n  \"weapon_knife\": \"НОЖ\",\n  \"weapon_bayonet\": \"ШТЫК\",\n  \"weapon_sword\": \"МЕЧ\",\n  \"weapon_cattle_prod\": \"ВИЛЫ\",\n  \"weapon_pistol\": \"ПИСТОЛЕТ\",\n  \"weapon_rifle\": \"ВИНТОВКА\",\n  \"weapon_rifle_burst\": \"ВИНТОВКА С ОБОЙМОЙ\",\n  \"weapon_mg\": \"ПУЛЕМЕТ\",\n  \"weapon_mg_heavy\": \"ТЯЖЕЛЫЙ ПУЛЕМЕТ\",\n  \"weapon_rifle_scope\": \"СНАЙПЕРСКАЯ ВИНТОВКА\",\n  \"weapon_shotgun\": \"ДРОБОВИК\",\n  \"weapon_shotgun_super\": \"ДРОБОВИК ОБРЕЗ\",\n  \"weapon_flame_thrower\": \"ОГНЕМЕТ\",\n  \"weapon_rocket_launcher\": \"РАКЕТОМЕТ\",\n  \"weapon_missile_guided\": \"УПРАВЛЯЕМАЯ РАКЕТА\",\n  \"weapon_rifle_medic\": \"ШПРИЦ\",\n  \"weapon_rifle_tranq\": \"ТРАНКВИЛИЗАТОР\",\n  \"weapon_grenade\": \"ГРАНАТА\",\n  \"weapon_grenade_cluster\": \"ФУГАСНАЯ ГРАНАТА \",\n  \"weapon_grenade_hx\": \"РУЧНАЯ ГРАНАТА\",\n  \"weapon_grenade_roller\": \" БОЛЬШАЯ ГРАНАТА \",\n  \"weapon_gas_confusion\": \"ВЕСЕЛЯЩИЙ ГАЗ\",\n  \"weapon_gas_freeze\": \"ЗАМОРАЖИВАЮЩИЙ ГАЗ\",\n  \"weapon_gas_madness\": \"ПСИХОТРОПНЫЙ ГАЗ \",\n  \"weapon_gas_poison\": \" ГОРЧИЧНЫЙ ГАЗ \",\n  \"weapon_grenade_shrapnel\": \"ОСКОЛОЧНАЯ ГРАНАТА \",\n  \"weapon_mortar\": \"МИНОМЕТ\",\n  \"weapon_bazooka\": \"БАЗУКА\",\n  \"weapon_grenade_launcher\": \"ГРАНАТОМЕТ\",\n  \"weapon_airburst\": \"БОМБА\",\n  \"weapon_airburst_super\": \"СВЕРХ БОМБА\",\n  \"weapon_grenade_medic\": \"АПТЕКА\",\n  \"weapon_missile_homing\": \"САМОНАВОДЯЩАЯСЯ РАКЕТА\",\n  \"weapon_mine\": \"МИНА\",\n  \"weapon_mine_antip\": \"МАЛАЯ ПЕХОТНАЯ МИНА \",\n  \"weapon_mine_antip\": \"ТРОТИЛ\",\n  \"weapon_tnt_super\": \"СУПЕРДИНАМИТ\",\n  \"weapon_shell_long_range\": \"СВЕРХМОЩНЫЙ СНАРЯД \",\n  \"weapon_shell_mine\": \"МИНА МИНОМЕТА\",\n  \"weapon_shell_gas\": \"ЗАРЯД С ГАЗАМИ\",\n  \"weapon_shell_fire_rain\": \"ЗАРЯД С НАПАЛМОМ \",\n  \"weapon_shell_1000_lbs\": \"СУПЕРЗАРЯД\",\n  \"weapon_shell_shock\": \"УДАРНЫЙ СНАРЯД\",\n  \"weapon_jetpack\": \"КАТАПУЛЬТА\",\n  \"weapon_suicide\": \" САМОПОДРЫВ \",\n  \"weapon_healing_hands\": \" ПЕРЕВЯЗАТЬ \",\n  \"weapon_self_heal\": \"ЛЕЧИТЬ СЕБЯ\",\n  \"weapon_pick_pocket\": \"УКРАСТЬ ВЕЩЬ\",\n  \"weapon_hide\": \"МАСКИРОВКА\",\n  \"weapon_shockwave\": \"УДАРНАЯ ВОЛНА\",\n  \"weapon_special_ops\": \"ПАРАШЮТНЫЙ ДЕСАНТ\",\n  \"weapon_airstrike\": \"БОМБЕЖКА\",\n  \"weapon_airstrike_fire\": \"БОМБЕЖКА НАПАЛМОМ\",\n  \"weapon_inout_vehicle\": \"МАШИНА ВХОД И ВЫХОД\",\n  \"weapon_inout_building\": \"ЗДАНИЕ ВХОД И ВЫХОД\",\n  \"weapon_eject_pig\": \"ПОСЛАТЬ НАХРЕН\",\n  \"weapon_map_view\": \"КАРТА\",\n  \"weapon_binoculars\": \"БИНОКЛЬ\",\n  \"weapon_skip_turn\": \"ПРОСПАТЬ ЖИЗНЬ\",\n  \"weapon_surrender\": \"СДАЧА ВРАГУ\",\n  \"vehicle_artillery\": \"АРТИЛЛЕРИСТ\",\n  \"vehicle_tent_medic\": \"ПАЛАТКА ЛЕКАРЯ\",\n  \"vehicle_tent_mash\": \"САНИТАРНАЯ ПАЛАТКА\",\n  \"vehicle_pillbox\": \"ДОТ\",\n  \"vehicle_sandbags\": \"МЕШКИ С ПЕСКОМ\",\n  \"vehicle_shelter\": \"УКРЫТИЕ\",\n  \"vehicle_tent\": \"ПАЛАТКА\",\n  \"vehicle_airship\": \"ДИРИЖАБЛЬ\",\n  \"vehicle_duck\": \"АМФИБИЯ\",\n  \"vehicle_tank_aqua\": \"АКВА-ТАНК\",\n  \"vehicle_boat\": \"ЛОДКА\",\n  \"vehicle_plane\": \"САМОЛЕТ\",\n  \"vehicle_tank\": \"ТАНК\",\n  \"vehicle_truck\": \"ГРУЗОВИК\",\n  \"mp_l00\": \"%s HAS LEFT THE GAME\",\n  \"mp_l02\": \"%s HAS LEFT WITH HIS TAIL BETWEEN HIS LEGS\",\n  \"mp_l03\": \"BYE BYE %s\",\n  \"mp_l04\": \"%s COULDN'T TAKE THE PACE\",\n  \"mp_l05\": \"%s COULDN'T STAND THE HEAT\",\n  \"mp_l06\": \"%s HAS LEFT THE FORAY\",\n  \"mp_l07\": \"%s WILL BE MISSED\",\n  \"mp_l08\": \"%s RUNS LIKE A GIRL\",\n  \"mp_l09\": \"%s HAS GIVEN UP\",\n  \"mp_l10\": \"%s LEAVES QUIETLY\",\n  \"mp_l11\": \"%s HURRIEDLY RETREATS\",\n  \"mp_l12\": \"%s IS OUTTA HERE!\"\n}"
  },
  {
    "path": "bin/mods/base/languages/spa.language",
    "content": "{\n  \"english\": \"ENGLISH\",\n  \"french\": \"FRANÇAIS\",\n  \"german\": \"DEUTSCH\",\n  \"italian\": \"ITALIANO\",\n  \"spanish\": \"ESPAÑOL\",\n  \"russian\": \"РУССКИЙ\",\n  \"yes\": \"SÍ\",\n  \"no\": \"NO\",\n  \"ok\": \"ACEPTAR\",\n  \"fe_main\": \"MENÚ PRINCIPAL\",\n  \"fe_yn_quit\": \"SALIR. ¿ESTÁS SEGURO?\",\n  \"mode_sn\": \"SUPERV. - NOVATO\",\n  \"mode_se\": \"SUPERV. - EXPERTO\",\n  \"mode_ss\": \"SUPERV. - ESTRATEG.\",\n  \"mode_dm\": \"COMBATE A MUERTE\",\n  \"mode_ge\": \"GENERAR\",\n  \"map_how_road\": \"PATRULLA RUTINARIA\",\n  \"map_how_trench\": \"GUERRA DE TRINCHERAS\",\n  \"map_how_rumble\": \"INVASIÓN DE LA ISLA\",\n  \"map_how_devi\": \"MAÑANA GLORIOSA\",\n  \"map_how_twin\": \"INTERRUP. DE TRANSMISIONES\",\n  \"map_how_zulus\": \"SITIADOS\",\n  \"map_how_sniper\": \"JUEGO DE ESPÍAS\",\n  \"map_how_guns\": \"SALCHICHAS CON PATATAS\",\n  \"map_how_oasis\": \"SOL Y ARENA\",\n  \"map_how_mashed\": \"COBARDES SIN CAUSA\",\n  \"map_how_camp\": \"CAMPO DE ENTRENAMIENTO\",\n  \"map_how_liberate\": \"SALVAR AL CERDITO RYAN\",\n  \"map_how_medix\": \"PASAR LA RAYA\",\n  \"map_how_fjords\": \"LA GUERRA DE LOS GLACIARES\",\n  \"map_how_eyrie\": \"PUESTOS DE COMBATE\",\n  \"map_how_bridge\": \"LA CONVENCIÓN DE GINEBRA\",\n  \"map_how_bay\": \"LA TOMA DEL BURDEOS\",\n  \"map_how_desval\": \"VEO-VEO\",\n  \"map_how_snake\": \"COMPUESTOS QUÍMICOS\",\n  \"map_how_emplace\": \"EL TALÓN DE AQUILES\",\n  \"map_how_keep\": \"ASESINATO\",\n  \"map_how_supline\": \"ATRAPADOS\",\n  \"map_how_tester\": \"JUEGOS DE GUERRA\",\n  \"map_how_foot\": \"MONTE PORCINO\",\n  \"map_how_final\": \"BUENO, BUENO, BUENO\",\n  \"map_how_estu\": \"LA FUNDACIÓN DE LA GUERRA\",\n  \"map_how_boom\": \"FUEGO AMIGO\",\n  \"map_how_bhill\": \"LOS SALTAPRESAS\",\n  \"map_how_lecprod\": \"CERRAR EL PASO\",\n  \"map_how_dval\": \"VALLE DE LA MUERTE\",\n  \"map_how_ice\": \"COLINA GÉLIDA\",\n  \"map_how_bute\": \"CRÁTERES LUNARES\",\n  \"map_how_maze\": \"LABERINTO\",\n  \"map_how_sepia1\": \"CARA A CARA\",\n  \"map_how_dbowl\": \"HONDONADA DE LA MUERTE\",\n  \"map_how_mlake\": \"LUCHA DE LA HELADA\",\n  \"map_how_cmass\": \"MASA DEL CRATER\",\n  \"map_how_artgun\": \"CONDENADOS\",\n  \"map_how_dval2\": \"VALLE DE LA MUERTE 2\",\n  \"map_how_hell3\": \"EMBUSTES\",\n  \"map_how_hell2\": \"INFIERNO MARRANO\",\n  \"map_how_lunar1\": \"CERDOS EN ESPACIO\",\n  \"map_how_creepy2\": \"TURNO DE NOCHE\",\n  \"map_how_play1\": \"PARQUE\",\n  \"map_how_play2\": \"DIVERSIÓN DEL EDREDÓN\",\n  \"map_how_iceflow\": \"CORRIENTE DE HIELO\",\n  \"map_how_ridge\": \"VUELTA A LA CORNISA\",\n  \"map_how_archi\": \"YOU HILLOCK\",\n  \"map_how_demo\": \"MODO DEMO\",\n  \"map_how_island\": \"TURISTA ISLEÑO\",\n  \"map_how_lake\": \"EL LAGO\",\n  \"map_how_oneway\": \"CARRETERA DE IDA\",\n  \"team_british\": \"HIJOS DE G. BRETAÑA\",\n  \"team_french\": \"MARRAN. FRANCHUTES\",\n  \"team_american\": \"HAMBURG. CON PATAS\",\n  \"team_russian\": \"CERDOSTROIKA\",\n  \"team_japanese\": \"PUERCOS SUSHI\",\n  \"team_german\": \"SALCHICH. FRANKFURT\",\n  \"team_lard\": \"TEAM LARD\",\n  \"pig_british_1\": \"JOHNNY\",\n  \"pig_british_2\": \"JIMMY\",\n  \"pig_british_3\": \"TOMMY\",\n  \"pig_british_4\": \"MONTY\",\n  \"pig_british_5\": \"BASIL\",\n  \"pig_british_6\": \"BILLY\",\n  \"pig_british_7\": \"PERCY\",\n  \"pig_british_8\": \"SMITH\",\n  \"pig_british_9\": \"JONES\",\n  \"pig_french_1\": \"EIFFEL\",\n  \"pig_french_2\": \"CONDE\",\n  \"pig_french_3\": \"GERARD\",\n  \"pig_french_4\": \"M. PEGO\",\n  \"pig_french_5\": \"PUERCO\",\n  \"pig_french_6\": \"MARRANO\",\n  \"pig_french_7\": \"CERDO\",\n  \"pig_french_8\": \"TOCINO\",\n  \"pig_french_9\": \"GLOTÓN\",\n  \"pig_american_1\": \"CHUCKY\",\n  \"pig_american_2\": \"BIF\",\n  \"pig_american_3\": \"KEANU\",\n  \"pig_american_4\": \"ABRAHAM\",\n  \"pig_american_5\": \"JOHNBOY\",\n  \"pig_american_6\": \"JIMBOB\",\n  \"pig_american_7\": \"JIM\",\n  \"pig_american_8\": \"BOBBYJO\",\n  \"pig_american_9\": \"JOEBOB\",\n  \"pig_russian_1\": \"YEHUDI\",\n  \"pig_russian_2\": \"RUSKI\",\n  \"pig_russian_3\": \"LOROSKI\",\n  \"pig_russian_4\": \"NIVOSKI\",\n  \"pig_russian_5\": \"PESSKI\",\n  \"pig_russian_6\": \"HEDESKI\",\n  \"pig_russian_7\": \"SOLESKI\",\n  \"pig_russian_8\": \"RIMSKI\",\n  \"pig_russian_9\": \"MULA\",\n  \"pig_japanese_1\": \"SHOGUN\",\n  \"pig_japanese_2\": \"KENDO\",\n  \"pig_japanese_3\": \"KUNG FU\",\n  \"pig_japanese_4\": \"ORIGAMI\",\n  \"pig_japanese_5\": \"NINJA\",\n  \"pig_japanese_6\": \"SUSHI\",\n  \"pig_japanese_7\": \"IKEBANA\",\n  \"pig_japanese_8\": \"MUSHI\",\n  \"pig_japanese_9\": \"MISHIMA\",\n  \"pig_german_1\": \"HERMAN\",\n  \"pig_german_2\": \"WOLFIE\",\n  \"pig_german_3\": \"PETER\",\n  \"pig_german_4\": \"HERR AL\",\n  \"pig_german_5\": \"HERR SO\",\n  \"pig_german_6\": \"DOBER\",\n  \"pig_german_7\": \"HERR DE\",\n  \"pig_german_8\": \"ALEPH\",\n  \"pig_german_9\": \"KRAUT\",\n  \"pig_lard_1\": \"SIMON\",\n  \"pig_lard_2\": \"TAPPER\",\n  \"pig_lard_3\": \"JOHN\",\n  \"pig_lard_4\": \"ANDY\",\n  \"pig_lard_5\": \"MARK\",\n  \"pig_lard_6\": \"JAKE\",\n  \"pig_lard_7\": \"MARTYN\",\n  \"pig_lard_8\": \"IZZY\",\n  \"pig_lard_9\": \"RICKI\",\n  \"pig_lard_10\": \"DOLLY\",\n  \"pig_lard_11\": \"FIL\",\n  \"pig_lard_12\": \"ADE\",\n  \"pig_lard_13\": \"SHORTY\",\n  \"pig_lard_14\": \"BEN\",\n  \"pig_lard_15\": \"BADDERS\",\n  \"pig_lard_16\": \"PHILIP\",\n  \"pig_lard_17\": \"JIM\",\n  \"pig_lard_18\": \"PAUL\",\n  \"pig_lard_19\": \"JAMES\",\n  \"pig_lard_20\": \"SWEETY\",\n  \"career\": \"TRAYECT. DE CARRERA\",\n  \"career_heavy\": \"ARMAS PESADAS\",\n  \"career_engineer\": \"INGENIERO\",\n  \"career_espionage\": \"ESPIONAJE\",\n  \"career_medic\": \"MÉDICO\",\n  \"class_grunt\": \"SOLDADO\",\n  \"class_gunner\": \"ARTILLERO\",\n  \"class_bombardier\": \"BOMBARDERO\",\n  \"class_pyrotechnic\": \"TÉCNICO\",\n  \"class_commando\": \"COMANDO\",\n  \"class_sapper\": \"ZAPADOR\",\n  \"class_engineer\": \"INGENIERO\",\n  \"class_saboteur\": \"SABOTEADOR\",\n  \"class_scout\": \"EXPLORADOR\",\n  \"class_sniper\": \"FRANCOTIRADOR\",\n  \"class_spy\": \"ESPÍA\",\n  \"class_orderly\": \"CELADOR\",\n  \"class_medic\": \"MÉDICO\",\n  \"class_surgeon\": \"CIRUJANO\",\n  \"class_hero\": \"HÉROE\",\n  \"class_ace\": \"AS\",\n  \"class_legend\": \"LEYENDA\",\n  \"class_grenadier\": \"GRANADERO\",\n  \"class_paratrooper\": \"PARACAIDISTA\",\n  \"weapon_none\": \"NINGUNA\",\n  \"weapon_trotter\": \"MANITAS\",\n  \"weapon_knife\": \"CUCHILLO\",\n  \"weapon_bayonet\": \"BAYONETA\",\n  \"weapon_sword\": \"SABLE\",\n  \"weapon_cattle_prod\": \"PINCHO GANADO\",\n  \"weapon_pistol\": \"PISTOLA\",\n  \"weapon_rifle\": \"FUSIL\",\n  \"weapon_rifle_burst\": \"DISPARO FUSIL\",\n  \"weapon_mg\": \"AMETRALLADORA\",\n  \"weapon_mg_heavy\": \"AMET. PESADA\",\n  \"weapon_rifle_scope\": \"FUSIL FRANCOT.\",\n  \"weapon_shotgun\": \"ESCOPETA\",\n  \"weapon_shotgun_super\": \"SUPERESCOPETA\",\n  \"weapon_flame_thrower\": \"LANZALLAMAS\",\n  \"weapon_rocket_launcher\": \"LANZAMISILES\",\n  \"weapon_missile_guided\": \"MISIL GUIADO\",\n  \"weapon_rifle_medic\": \"DARDO MÉDICO\",\n  \"weapon_rifle_tranq\": \"TRANQUILIZANTE\",\n  \"weapon_grenade\": \"GRANADA\",\n  \"weapon_grenade_cluster\": \"GR. DISPERSIÓN\",\n  \"weapon_grenade_hx\": \"GR. EXPLOSIVA\",\n  \"weapon_grenade_roller\": \"GR. VOLADORA\",\n  \"weapon_gas_confusion\": \"GAS CONFUSIÓN\",\n  \"weapon_gas_freeze\": \"GAS INMÓVIL.\",\n  \"weapon_gas_madness\": \"GAS DE LOCURA\",\n  \"weapon_gas_poison\": \"GAS VENENOSO\",\n  \"weapon_grenade_shrapnel\": \"GR. METRALLA\",\n  \"weapon_mortar\": \"MORTERO\",\n  \"weapon_bazooka\": \"BAZUCA\",\n  \"weapon_grenade_launcher\": \"LANZAGRANADAS\",\n  \"weapon_airburst\": \"B. DISPERSIÓN\",\n  \"weapon_airburst_super\": \"SUPERBOMBA\",\n  \"weapon_grenade_medic\": \"GRANADA MÉDICA\",\n  \"weapon_missile_homing\": \"MISIL BUSCADOR\",\n  \"weapon_mine\": \"MINA\",\n  \"weapon_mine_antip\": \"MINA ANTIPER.\",\n  \"weapon_mine_antip\": \"TNT\",\n  \"weapon_tnt_super\": \"SUPER TNT\",\n  \"weapon_shell_long_range\": \"BOMBA ALCANCE\",\n  \"weapon_shell_mine\": \"BOMBA DE MINAS\",\n  \"weapon_shell_gas\": \"BOMBA DE GAS\",\n  \"weapon_shell_fire_rain\": \"BOMBA NAPALM\",\n  \"weapon_shell_1000_lbs\": \"BOMBA 500 KG\",\n  \"weapon_shell_shock\": \"BOMBA SONIDO\",\n  \"weapon_jetpack\": \"PROPULSOR\",\n  \"weapon_suicide\": \"SUICIDIO\",\n  \"weapon_healing_hands\": \"MANO CURATIVA\",\n  \"weapon_self_heal\": \"CURARTE\",\n  \"weapon_pick_pocket\": \"ROBAR\",\n  \"weapon_hide\": \"CAMUFLAJE\",\n  \"weapon_shockwave\": \"ONDA EXPANS.\",\n  \"weapon_special_ops\": \"OP. ESPECIALES\",\n  \"weapon_airstrike\": \"ATAQUE AÉREO\",\n  \"weapon_airstrike_fire\": \"ATAQUE NAPALM\",\n  \"weapon_inout_vehicle\": \"SAL.ENT. VEH.\",\n  \"weapon_inout_building\": \"SAL.ENT. EDF.\",\n  \"weapon_eject_pig\": \"LANZAR CERDO\",\n  \"weapon_map_view\": \"VER MAPA\",\n  \"weapon_binoculars\": \"BINOCULARES\",\n  \"weapon_skip_turn\": \"SALTAR TURNO\",\n  \"weapon_surrender\": \"RENDIRSE\",\n  \"vehicle_artillery\": \"ARTILLERÍA\",\n  \"vehicle_tent_medic\": \"TIENDA MÉDICA\",\n  \"vehicle_tent_mash\": \"HOSP. CAMPAÑA\",\n  \"vehicle_pillbox\": \"FORTÍN\",\n  \"vehicle_sandbags\": \"SACOS ARENA\",\n  \"vehicle_shelter\": \"REFUGIO\",\n  \"vehicle_tent\": \"TIENDA\",\n  \"vehicle_airship\": \"NAVE\",\n  \"vehicle_duck\": \"ANFIBIO\",\n  \"vehicle_tank_aqua\": \"TANQUE ANF.\",\n  \"vehicle_boat\": \"BOTE\",\n  \"vehicle_plane\": \"AVIÓN\",\n  \"vehicle_tank\": \"TANQUE\",\n  \"vehicle_truck\": \"CAMIÓN\",\n  \"mp_l00\": \"%s HAS LEFT THE GAME\",\n  \"mp_l02\": \"%s HAS LEFT WITH HIS TAIL BETWEEN HIS LEGS\",\n  \"mp_l03\": \"BYE BYE %s\",\n  \"mp_l04\": \"%s COULDN'T TAKE THE PACE\",\n  \"mp_l05\": \"%s COULDN'T STAND THE HEAT\",\n  \"mp_l06\": \"%s HAS LEFT THE FORAY\",\n  \"mp_l07\": \"%s WILL BE MISSED\",\n  \"mp_l08\": \"%s RUNS LIKE A GIRL\",\n  \"mp_l09\": \"%s HAS GIVEN UP\",\n  \"mp_l10\": \"%s LEAVES QUIETLY\",\n  \"mp_l11\": \"%s HURRIEDLY RETREATS\",\n  \"mp_l12\": \"%s IS OUTTA HERE!\"\n}"
  },
  {
    "path": "bin/mods/base/languages.manifest",
    "content": "[\n  {\n    \"key\": \"eng\",\n    \"name\": \"ENGLISH\"\n  },\n  {\n    \"key\": \"ger\",\n    \"name\": \"DEUTSCH\"\n  },\n  {\n    \"key\": \"fre\",\n    \"name\": \"FRANÇAIS\"\n  },\n  {\n    \"key\": \"spa\",\n    \"name\": \"ESPAÑOL\"\n  },\n  {\n    \"key\": \"ita\",\n    \"name\": \"ITALIANO\"\n  },\n  {\n    \"key\": \"rus\",\n    \"name\": \"РУССКИЙ\"\n  }\n]"
  },
  {
    "path": "bin/mods/base/scripts/classes.json",
    "content": "{\n\t\"defaultClass\": \"gr_me\",\n\t\"classes\": [\n\t\t{\n\t\t\t\"identifier\": \"ac_me\",\n\t\t\t\"label\": \"$aceClass\",\n\t\t\t\"model\": \"pigs/pcace_hi.vtx\",\n\t\t\t\"isVisibleOnMinimap\": true\n\t\t},\n\t\t{\n\t\t\t\"identifier\": \"gr_me\",\n\t\t\t\"label\": \"$gruntClass\",\n\t\t\t\"health\": \"50\",\n\t\t\t\"cost\": \"0\",\n\t\t\t\"model\": \"pigs/pcgru_hi.vtx\",\n\t\t\t\"isVisibleOnMinimap\": true,\n\t\t\t\"items\": [\n\t\t\t\t{\n\t\t\t\t\t\"identifier\": \"weapon_bayonet\",\n\t\t\t\t\t\"quantity\": \"0\"\n\t\t\t\t}\n\t\t\t]\n\t\t},\n\t\t{\n\t\t\t\"identifier\": \"hv_me\",\n\t\t\t\"label\": \"$gunnerClass\",\n\t\t\t\"health\": \"75\",\n\t\t\t\"cost\": \"1\",\n\t\t\t\"model\": \"pigs/pchvy_hi.vtx\",\n\t\t\t\"isVisibleOnMinimap\": true,\n\t\t\t\"nextStage\": \"$bombardierClass\",\n\t\t\t\"items\": [\n\t\t\t\t{\n\t\t\t\t\t\"identifier\": \"weapon_bayon\",\n\t\t\t\t\t\"quantity\": \"0\"\n\t\t\t\t}\n\t\t\t]\n\t\t},\n\t\t{\n\t\t\t\"identifier\": \"le_me\",\n\t\t\t\"model\": \"pigs/pcleg_hi.vtx\",\n\t\t\t\"isVisibleOnMinimap\": true\n\t\t},\n\t\t{\n\t\t\t\"identifier\": \"me_me\",\n\t\t\t\"model\": \"pigs/pcmed_hi.vtx\",\n\t\t\t\"isVisibleOnMinimap\": true\n\t\t},\n\t\t{\n\t\t\t\"identifier\": \"sb_me\",\n\t\t\t\"model\": \"pigs/pcsab_hi.vtx\",\n\t\t\t\"isVisibleOnMinimap\": true\n\t\t},\n\t\t{\n\t\t\t\"identifier\": \"sn_me\",\n\t\t\t\"model\": \"pigs/sn_hi.vtx\",\n\t\t\t\"isVisibleOnMinimap\": true\n\t\t},\n\t\t{\n\t\t\t\"identifier\": \"sp_me\",\n\t\t\t\"model\": \"pigs/sp_hi.vtx\",\n\t\t\t\"isVisibleOnMinimap\": false\n\t\t}\n\t]\n}\n"
  },
  {
    "path": "bin/mods/base/scripts/postprocess.json",
    "content": "{\n  \"effects\": [\n    {\n      \"name\": \"effect_base\",\n      \"frag\": \"shaders/texture.frag\",\n      \"properties\": []\n    },\n    {\n      \"name\": \"effect_bloom\",\n      \"frag\": \"shaders/bloom.frag\",\n      \"properties\": [\n        {\n          \"name\": \"Intensity\",\n          \"description\": \"\",\n          \"type\": \"float\",\n          \"uniform\": \"intensity\"\n        },\n        {\n          \"name\": \"Texture\",\n          \"type\": \"texture2d\",\n          \"uniform\": \"overlay\"\n        }\n      ]\n    }\n  ],\n  \"passes\": [\n    \"effect_base\",\n    \"effect_bloom\"\n  ]\n}\n"
  },
  {
    "path": "bin/mods/base/scripts/teams.json",
    "content": "[\n  {\n    \"name\": \"$team_british\",\n    \"colour\": \"9 155 46\",\n    \"pigTextures\": \"chars/pigs/british\",\n    \"paperTextures\": \"frontend/papers/british\",\n    \"debriefTexture\": \"frontend/debrief/unifeng\",\n    \"personalities\": [\n      {\n        \"defaultName\": \"$pig_british_01\",\n        \"portrait\": \"frontend/debrief/facepc1\",\n        \"portraitSelected\": \"frontend/debrief/facepc1\",\n        \"portraitWounded\": \"frontend/debrief/facepcw1\",\n        \"voiceLanguage\": \"en\",\n        \"voiceSet\": \"1\"\n      },\n      {\n        \"defaultName\": \"$pig_british_02\",\n        \"portrait\": \"frontend/debrief/facepc2\",\n        \"portraitSelected\": \"frontend/debrief/facepc2\",\n        \"portraitWounded\": \"frontend/debrief/facepcw2\",\n        \"voiceLanguage\": \"en\",\n        \"voiceSet\": \"2\"\n      },\n      {\n        \"defaultName\": \"$pig_british_03\",\n        \"portrait\": \"frontend/debrief/facepc3\",\n        \"portraitSelected\": \"frontend/debrief/facepc3\",\n        \"portraitWounded\": \"frontend/debrief/facepcw3\",\n        \"voiceLanguage\": \"en\",\n        \"voiceSet\": \"3\"\n      },\n      {\n        \"defaultName\": \"$pig_british_04\",\n        \"portrait\": \"frontend/debrief/facepc4\",\n        \"portraitSelected\": \"frontend/debrief/facepc4\",\n        \"portraitWounded\": \"frontend/debrief/facepcw4\",\n        \"voiceLanguage\": \"en\",\n        \"voiceSet\": \"4\"\n      },\n      {\n        \"defaultName\": \"$pig_british_05\",\n        \"portrait\": \"frontend/debrief/facepc5\",\n        \"portraitSelected\": \"frontend/debrief/facepc5\",\n        \"portraitWounded\": \"frontend/debrief/facepcw5\",\n        \"voiceLanguage\": \"en\",\n        \"voiceSet\": \"5\"\n      },\n      {\n        \"defaultName\": \"$pig_british_06\",\n        \"portrait\": \"frontend/debrief/facepc6\",\n        \"portraitSelected\": \"frontend/debrief/facepc6\",\n        \"portraitWounded\": \"frontend/debrief/facepcw6\",\n        \"voiceLanguage\": \"en\",\n        \"voiceSet\": \"6\"\n      },\n      {\n        \"defaultName\": \"$pig_british_07\",\n        \"portrait\": \"frontend/debrief/facepc7\",\n        \"portraitSelected\": \"frontend/debrief/facepc7\",\n        \"portraitWounded\": \"frontend/debrief/facepcw7\",\n        \"voiceLanguage\": \"en\",\n        \"voiceSet\": \"7\"\n      },\n      {\n        \"defaultName\": \"$pig_british_08\",\n        \"portrait\": \"frontend/debrief/facepc8\",\n        \"portraitSelected\": \"frontend/debrief/facepc8\",\n        \"portraitWounded\": \"frontend/debrief/facepcw8\",\n        \"voiceLanguage\": \"en\",\n        \"voiceSet\": \"8\"\n      },\n      {\n        \"defaultName\": \"$pig_british_09\",\n        \"portrait\": \"frontend/debrief/facepc9\",\n        \"portraitSelected\": \"frontend/debrief/facepc9\",\n        \"portraitWounded\": \"frontend/debrief/facepcw9\",\n        \"voiceLanguage\": \"en\",\n        \"voiceSet\": \"9\"\n      }\n    ]\n  },\n  {\n    \"name\": \"$team_french\",\n    \"colour\": \"0 0 196\",\n    \"pigTextures\": \"chars/pigs/french\",\n    \"paperTextures\": \"frontend/papers/french\",\n    \"debriefTexture\": \"frontend/debrief/uniffren\",\n    \"voiceSet\": \"fr\"\n  },\n  {\n    \"name\": \"$team_american\",\n    \"colour\": \"51 166 217\",\n    \"pigTextures\": \"chars/pigs/american\",\n    \"paperTextures\": \"frontend/papers/american\",\n    \"debriefTexture\": \"frontend/debrief/unifusa\",\n    \"voiceSet\": \"am\"\n  },\n  {\n    \"name\": \"$team_russian\",\n    \"colour\": \"202 0 0\",\n    \"pigTextures\": \"chars/pigs/british\",\n    \"paperTextures\": \"frontend/papers/british\",\n    \"debriefTexture\": \"frontend/debrief/unifruss\",\n    \"voiceSet\": \"ru\"\n  },\n  {\n    \"name\": \"$team_japanese\",\n    \"colour\": \"202 204 4\",\n    \"pigTextures\": \"chars/pigs/japanese\",\n    \"paperTextures\": \"frontend/papers/japanese\",\n    \"debriefTexture\": \"frontend/debrief/unifjap\",\n    \"voiceSet\": \"ja\"\n  },\n  {\n    \"name\": \"$team_german\",\n    \"colour\": \"90 80 70\",\n    \"pigTextures\": \"chars/pigs/german\",\n    \"paperTextures\": \"frontend/papers/german\",\n    \"debriefTexture\": \"frontend/debrief/unifgerm\",\n    \"voiceSet\": \"ge\"\n  },\n  {\n    \"name\": \"$team_lard\",\n    \"colour\": \"133 0 200\",\n    \"pigTextures\": \"chars/pigs/teamlard\",\n    \"paperTextures\": \"frontend/papers/teamlard\",\n    \"debriefTexture\": \"frontend/debrief/uniflard\",\n    \"voiceSet\": \"en\"\n  }\n]"
  },
  {
    "path": "bin/mods/base/shaders/alpha_test.program",
    "content": "{\n  \"gl3\": {\n    \"vertPath\": \"shaders/gl3/generic.vert\",\n    \"fragPath\": \"shaders/gl3/alpha_test_texture.frag\"\n  }\n}"
  },
  {
    "path": "bin/mods/base/shaders/debug_normals.program",
    "content": "{\n  \"gl3\": {\n    \"vertPath\": \"shaders/gl3/generic.vert\",\n    \"fragPath\": \"shaders/gl3/debug_normals.frag\"\n  }\n}"
  },
  {
    "path": "bin/mods/base/shaders/debug_test.program",
    "content": "{\n  \"gl3\": {\n    \"vertPath\": \"shaders/gl3/generic.vert\",\n    \"fragPath\": \"shaders/gl3/debug.frag\"\n  }\n}"
  },
  {
    "path": "bin/mods/base/shaders/generic_textured.program",
    "content": "{\n  \"gl3\": {\n    \"vertPath\": \"shaders/gl3/generic.vert\",\n    \"fragPath\": \"shaders/gl3/texture.frag\"\n  }\n}"
  },
  {
    "path": "bin/mods/base/shaders/generic_textured_lit.program",
    "content": "{\n  \"gl3\": {\n    \"vertPath\": \"shaders/gl3/generic.vert\",\n    \"fragPath\": \"shaders/gl3/lit_texture.frag\"\n  }\n}"
  },
  {
    "path": "bin/mods/base/shaders/generic_textured_lit_basic.program",
    "content": "{\n\t\"gl3\": {\n\t\t\"vertPath\": \"shaders/gl3/gouraud.vert\",\n\t\t\"fragPath\": \"shaders/gl3/texture.frag\"\n\t}\n}"
  },
  {
    "path": "bin/mods/base/shaders/generic_untextured.program",
    "content": "{\n  \"gl3\": {\n    \"vertPath\": \"shaders/gl3/generic.vert\",\n    \"fragPath\": \"shaders/gl3/vertex_colour.frag\"\n  }\n}"
  },
  {
    "path": "bin/mods/base/shaders/gl3/alpha_test_texture.frag",
    "content": "/* OpenHoW\n * Copyright (C) 2017-2020 TalonBrave.info and Others (see CONTRIBUTORS)\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n */\n\nuniform sampler2D diffuse;\n\nin vec2 interp_UV;\nin vec4 interp_colour;\n\nvoid main() {\n    vec4 samp = texture(diffuse, interp_UV);\n    if (samp.a < 0.1) {\n        discard;\n    }\n\n    pl_frag = interp_colour * samp;\n}"
  },
  {
    "path": "bin/mods/base/shaders/gl3/debug.frag",
    "content": "/* OpenHoW\n * Copyright (C) 2017-2020 TalonBrave.info and Others (see CONTRIBUTORS)\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n */\n\nvoid main() {\n    pl_frag = vec4(1.0, 0.0, 1.0, 1.0);\n}\n"
  },
  {
    "path": "bin/mods/base/shaders/gl3/debug_normals.frag",
    "content": "/* OpenHoW\n * Copyright (C) 2017-2020 TalonBrave.info and Others (see CONTRIBUTORS)\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n */\n\nin vec3 interp_normal;\n\nvoid main() {\n    pl_frag.xyz = normalize(interp_normal);\n    pl_frag.w = 1.0;\n}\n"
  },
  {
    "path": "bin/mods/base/shaders/gl3/generic.vert",
    "content": "/* OpenHoW\n * Copyright (C) 2017-2020 TalonBrave.info and Others (see CONTRIBUTORS)\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n */\n\nout vec3 interp_normal;\nout vec2 interp_UV;\nout vec4 interp_colour;\n\nout vec3 frag_pos;\n\nvoid main() {\n    gl_Position = pl_proj * pl_view * pl_model * vec4(pl_vposition, 1.0f);\n    interp_normal = mat3(transpose(inverse(pl_model))) * pl_vnormal;\n    interp_UV = pl_vuv;\n    interp_colour = pl_vcolour;\n\n    frag_pos = vec3(pl_model * vec4(pl_vposition, 1.0));\n}\n"
  },
  {
    "path": "bin/mods/base/shaders/gl3/global.glsl",
    "content": "/* OpenHoW\n * Copyright (C) 2017-2020 TalonBrave.info and Others (see CONTRIBUTORS)\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n// Used for adding constants and any other data shared between programs\n\nconst float someExampleConstant = 1.0;\n"
  },
  {
    "path": "bin/mods/base/shaders/gl3/gouraud.vert",
    "content": "/* OpenHoW\n * Copyright (C) 2017-2020 TalonBrave.info and Others (see CONTRIBUTORS)\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n */\n\nout vec3 interp_normal;\nout vec2 interp_UV;\nout vec4 interp_colour;\n\nout vec3 frag_pos;\n\nuniform vec4 sun_colour = vec4(1.0, 1.0, 1.0, 1.0);\nuniform vec3 sun_position = vec3(0.0, 0.0, 0.0);\nuniform vec4 ambient_colour = vec4(1.0, 1.0, 1.0, 1.0);\n\nvoid main() {\n\tgl_Position = pl_proj * pl_view * pl_model * vec4(pl_vposition, 1.0f);\n\n\tinterp_normal = mat3(transpose(inverse(pl_model))) * pl_vnormal;\n\tinterp_UV = pl_vuv;\n\n\tvec3 l = normalize( -sun_position );\n\tvec3 v = normalize( -gl_Position.xyz );\n\tvec3 n = normalize( interp_normal );\n\n\tvec3 diffuse = max( dot( n, l ), 0.0 ) * sun_colour.rgb + ambient_colour.rgb;\n\n\tinterp_colour = pl_vcolour * vec4( diffuse.rgb, 1.0 );\n\n\tfrag_pos = vec3(pl_model * vec4(pl_vposition, 1.0));\n}\n"
  },
  {
    "path": "bin/mods/base/shaders/gl3/lit_texture.frag",
    "content": "/* OpenHoW\n * Copyright (C) 2017-2020 TalonBrave.info and Others (see CONTRIBUTORS)\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n */\n\nuniform sampler2D diffuse;\n\nuniform float fog_far = 0;\nuniform float fog_near = 0;\nuniform vec4 fog_colour = vec4(1.0, 1.0, 1.0, 1.0);\n\nuniform vec4 sun_colour = vec4(1.0, 1.0, 1.0, 1.0);\nuniform vec3 sun_position = vec3(0.0, 0.0, 0.0);\n\nuniform vec4 ambient_colour = vec4(1.0, 1.0, 1.0, 1.0);\n\nin vec3 interp_normal;\nin vec2 interp_UV;\nin vec4 interp_colour;\n\nin vec3 frag_pos;\n\nvoid main() {\n    vec4 dsample = texture(diffuse, interp_UV, -2.0);\n    if (dsample.a < 0.1) {\n        discard;\n    }\n\n    vec3 normal = normalize(interp_normal);\n    vec3 light_direction = normalize(-sun_position);\n    vec4 sun_term = (max(dot(normal, light_direction), 0.0)) * sun_colour + ambient_colour;\n    vec4 diffuse_colour = sun_term * interp_colour * dsample;\n\n    // rim term\n    /*\n    vec3 viewDirection = vec3( normal * mat3( pl_proj ) );\n    vec4 rim_term = exp( ( dot( -normal, viewDirection ) * vec4( 1, 1, 1, 1) ) ); // 5.0;\n    rim_term.a = 1;\n    */\n\n    float fog_distance = (gl_FragCoord.z / gl_FragCoord.w) / (fog_far * 100.0);\n    float fog_amount = 1.0 - fog_distance;\n    fog_amount *= -(fog_near / 100.0);\n\n    //pl_frag = rim_term * diffuse_colour; //mix(rim_term + diffuse_colour, fog_colour, clamp(fog_amount, 0.0, 1.0));\n    pl_frag = mix(diffuse_colour, fog_colour, clamp(fog_amount, 0.0, 1.0));\n}\n"
  },
  {
    "path": "bin/mods/base/shaders/gl3/shadow.frag",
    "content": "/* OpenHoW\n * Copyright (C) 2017-2020 TalonBrave.info and Others (see CONTRIBUTORS)\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n */\n\nuniform sampler2D diffuse;\n\nvoid main() {\n\tpl_frag = vec4( 1.0 );\n}\n"
  },
  {
    "path": "bin/mods/base/shaders/gl3/texture.frag",
    "content": "/* OpenHoW\n * Copyright (C) 2017-2020 TalonBrave.info and Others (see CONTRIBUTORS)\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n */\n\nuniform sampler2D diffuse;\n\nin vec2 interp_UV;\nin vec4 interp_colour;\n\nvoid main() {\n    pl_frag = interp_colour * texture(diffuse, interp_UV);\n}\n"
  },
  {
    "path": "bin/mods/base/shaders/gl3/vertex_colour.frag",
    "content": "/* OpenHoW\n * Copyright (C) 2017-2020 TalonBrave.info and Others (see CONTRIBUTORS)\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n */\n\nin vec4 interp_colour;\n\nvoid main() {\n    pl_frag = interp_colour;\n}\n"
  },
  {
    "path": "bin/mods/base/shaders/gl3/water.frag",
    "content": "/* OpenHoW\n * Copyright (C) 2017-2020 TalonBrave.info and Others (see CONTRIBUTORS)\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n */\n\nuniform sampler2D diffuse;\n\nin vec2 interp_UV;\nin vec4 interp_colour;\n\nvoid main() {\n    vec4 samp = vec4( texture( diffuse, interp_UV ).rgb, 1.0 );\n    pl_frag = interp_colour * samp;\n}\n"
  },
  {
    "path": "bin/mods/base/shaders/shadow.program",
    "content": "{\n\t\"gl3\": {\n\t\t\"vertPath\": \"shaders/gl3/generic.vert\",\n\t\t\"fragPath\": \"shaders/gl3/shadow.frag\"\n\t}\n}"
  },
  {
    "path": "bin/mods/base/shaders/water.program",
    "content": "{\n  \"gl3\": {\n    \"vertPath\": \"shaders/gl3/generic.vert\",\n    \"fragPath\": \"shaders/gl3/water.frag\"\n  }\n}"
  },
  {
    "path": "bin/mods/base.mod",
    "content": "{\n\t\"name\": \"Base\",\n\t\"author\": \"TalonBrave.info\",\n\t\"version\": \"v1.0\",\n\t\"isVisible\": false\n}"
  },
  {
    "path": "bin/mods/feralwarfare/README.md",
    "content": "This is a **work-in-progress** free replacement dataset. The eventual goal is to allow players to download and play\nOpenHoW without necessarily owning Hogs of War.\n\nMore than likely we'll probably move *Feral Warfare* into it's own seperate repo\nwhen things are further along.\n\nWe're always looking for contributors, so if you're interested then please [get in touch](https://discord.gg/EdmwgVk).\n\n## Resources\n\nAnything within this directory should be assumed under GPLv3 unless stated otherwise below.\n\n* [music/track02.ogg](https://commons.wikimedia.org/wiki/File:The_Liberty_Bell_March_-_U.S._Army_Field_Band.ogg) : Public Domain \n"
  },
  {
    "path": "bin/mods/feralwarfare.mod",
    "content": "{\n\t\"name\": \"Feral Warfare\",\n\t\"author\": \"TalonBrave.info\",\n\t\"version\": \"v0.0.1\",\n\t\"isVisible\": true,\n\t\"dependencies\": [\n\t\t\"base\"\n\t]\n}"
  },
  {
    "path": "bin/mods/how/actors/pigs.actor",
    "content": "[\n  {\n    \"identifier\": \"ac_me\",\n    \"className\": \"APig\",\n    \"properties\": {\n      \"modelPath\": \"chars/pigs/pcace_hi.vtx\"\n    }\n  },\n  {\n    \"identifier\": \"gr_me\",\n    \"className\": \"APig\"\n  },\n  {\n    \"identifier\": \"hv_me\",\n    \"className\": \"APig\"\n  },\n  {\n    \"identifier\": \"le_me\",\n    \"className\": \"APig\"\n  },\n  {\n    \"identifier\": \"me_me\",\n    \"className\": \"APig\",\n    \"properties\": {\n      \"modelPath\": \"chars/pigs/pcmed_hi.vtx\"\n    }\n  },\n  {\n    \"identifier\": \"sa_me\",\n    \"className\": \"APig\"\n  },\n  {\n    \"identifier\": \"sb_me\",\n    \"className\": \"APig\",\n    \"properties\": {\n      \"modelPath\": \"chars/pigs/pcsab_hi.vtx\"\n    }\n  },\n  {\n    \"identifier\": \"sn_me\",\n    \"className\": \"APig\"\n  }\n]\n"
  },
  {
    "path": "bin/mods/how/actors/vehicles.actor",
    "content": "[\n  {\n    \"identifier\": \"vehicle_airship\",\n    \"className\": \"AAirship\"\n  }\n]\n"
  },
  {
    "path": "bin/mods/how/actors/weapons.actor",
    "content": "[\n  {\n    \"identifier\": \"weapon_parachute\",\n    \"className\": \"AParachuteWeapon\"\n  }\n]\n"
  },
  {
    "path": "bin/mods/how/maps/cold.template",
    "content": "{\n    \"name\": \"$map_how_\",\n    \"author\": \"none\",\n    \"description\": \"none\",\n    \"ambientColour\": \"188 188 188\",\n    \"skyColourTop\": \"0 104 156\",\n    \"skyColourBottom\": \"223 255 255\",\n    \"sunColour\": \"159 159 159\",\n    \"sunYaw\": \"0.523599\",\n    \"sunPitch\": \"0.872665\",\n    \"temperature\": \"cold\",\n    \"weather\": \"snow\",\n    \"time\": \"day\",\n    \"fogColour\": \"255 250 250\",\n    \"fogIntensity\": \"30.000000\",\n    \"fogDistance\": \"100.000000\"\n}"
  },
  {
    "path": "bin/mods/how/maps/desert.template",
    "content": "{\n    \"name\": \"$map_how_\",\n    \"author\": \"none\",\n    \"description\": \"none\",\n    \"ambientColour\": \"229 193 128\",\n    \"skyColourTop\": \"93 95 245\",\n    \"skyColourBottom\": \"187 146 61\",\n    \"sunColour\": \"255 255 255\",\n    \"sunYaw\": \"0.523599\",\n    \"sunPitch\": \"1.221731\",\n    \"temperature\": \"hot\",\n    \"weather\": \"clear\",\n    \"time\": \"day\",\n    \"fogColour\": \"187 146 61\",\n    \"fogIntensity\": \"30.000000\",\n    \"fogDistance\": \"100.000000\"\n}"
  },
  {
    "path": "bin/mods/how/maps/night.template",
    "content": "{\n    \"name\": \"$map_how_\",\n    \"author\": \"none\",\n    \"description\": \"none\",\n    \"ambientColour\": \"18 19 100\",\n    \"skyColourTop\": \"0 1 41\",\n    \"skyColourBottom\": \"18 19 100\",\n    \"sunColour\": \"150 150 150\",\n    \"sunYaw\": \"0.523599\",\n    \"sunPitch\": \"0.872665\",\n    \"temperature\": \"cold\",\n    \"weather\": \"clear\",\n    \"time\": \"night\",\n    \"fogColour\": \"0 0 0\",\n    \"fogIntensity\": \"30.000000\",\n    \"fogDistance\": \"70.000000\"\n}"
  },
  {
    "path": "bin/mods/how/maps/ominous.template",
    "content": "{\n    \"name\": \"$map_how_\",\n    \"author\": \"none\",\n    \"description\": \"none\",\n    \"ambientColour\": \"158 158 158\",\n    \"skyColourTop\": \"13 15 14\",\n    \"skyColourBottom\": \"99 111 120\",\n    \"sunColour\": \"131 131 131\",\n    \"sunYaw\": \"2.530727\",\n    \"sunPitch\": \"0.157080\",\n    \"temperature\": \"cold\",\n    \"weather\": \"rain\",\n    \"time\": \"day\",\n    \"fogColour\": \"99 111 120\",\n    \"fogIntensity\": \"30.000000\",\n    \"fogDistance\": \"48.000000\"\n}"
  },
  {
    "path": "bin/mods/how/maps/space.template",
    "content": "{\n    \"name\": \"$map_how_\",\n    \"author\": \"none\",\n    \"description\": \"none\",\n    \"ambientColour\": \"20 20 20\",\n    \"skyColourTop\": \"0 0 0\",\n    \"skyColourBottom\": \"0 0 0\",\n    \"sunColour\": \"255 255 255\",\n    \"sunYaw\": \"0.523599\",\n    \"sunPitch\": \"0.872665\",\n    \"temperature\": \"cold\",\n    \"weather\": \"clear\",\n    \"time\": \"night\",\n    \"fogColour\": \"0 0 0\",\n    \"fogIntensity\": \"0.000000\",\n    \"fogDistance\": \"0.000000\"\n}"
  },
  {
    "path": "bin/mods/how/maps/sunny.template",
    "content": "{\n    \"name\": \"$map_how_\",\n    \"author\": \"none\",\n    \"description\": \"none\",\n    \"ambientColour\": \"168 168 168\",\n    \"skyColourTop\": \"21 51 192\",\n    \"skyColourBottom\": \"87 201 255\",\n    \"sunColour\": \"255 255 255\",\n    \"sunYaw\": \"0.523599\",\n    \"sunPitch\": \"0.872665\",\n    \"temperature\": \"normal\",\n    \"weather\": \"clear\",\n    \"time\": \"day\",\n    \"fogColour\": \"87 187 255\",\n    \"fogIntensity\": \"30.000000\",\n    \"fogDistance\": \"100.000000\"\n}"
  },
  {
    "path": "bin/mods/how/maps/sunrise.template",
    "content": "{\n    \"name\": \"$map_how_\",\n    \"author\": \"none\",\n    \"description\": \"none\",\n    \"ambientColour\": \"206 206 206\",\n    \"skyColourTop\": \"128 175 247\",\n    \"skyColourBottom\": \"209 194 104\",\n    \"sunColour\": \"243 157 43\",\n    \"sunYaw\": \"0.523599\",\n    \"sunPitch\": \"0.523599\",\n    \"temperature\": \"normal\",\n    \"weather\": \"clear\",\n    \"time\": \"day\",\n    \"fogColour\": \"209 194 104\",\n    \"fogIntensity\": \"30.000000\",\n    \"fogDistance\": \"100.000000\"\n}"
  },
  {
    "path": "bin/mods/how/maps/sunset.template",
    "content": "{\n    \"name\": \"$map_how_\",\n    \"author\": \"none\",\n    \"description\": \"none\",\n    \"ambientColour\": \"146 143 150\",\n    \"skyColourTop\": \"11 10 92\",\n    \"skyColourBottom\": \"186 123 61\",\n    \"sunColour\": \"223 133 56\",\n    \"sunYaw\": \"0.523599\",\n    \"sunPitch\": \"0.523599\",\n    \"temperature\": \"hot\",\n    \"weather\": \"clear\",\n    \"time\": \"day\",\n    \"fogColour\": \"186 123 61\",\n    \"fogIntensity\": \"30.000000\",\n    \"fogDistance\": \"75.000000\"\n}"
  },
  {
    "path": "bin/mods/how.mod",
    "content": "{\n\t\"name\": \"HoW Campaign\",\n\t\"author\": \"Gremlin Interactive\",\n\t\"version\": \"v1.0\",\n\t\"isVisible\": true,\n\t\"dependencies\": [\n\t\t\"base\"\n\t],\n\t\"scenarios\": [\n\t\t{\n\t\t\t\"name\": \"default\",\n\t\t\t\"maps\": [\n\t\t\t\t{\n\t\t\t\t\t\"name\": \"camp\",\n\t\t\t\t\t\"timer\": \"99\",\n\t\t\t\t\t\"opponents\": [ ]\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"name\": \"estu\",\n\t\t\t\t\t\"timer\": \"99\",\n\t\t\t\t\t\"opponents\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"className\": \"grunt\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"className\": \"grunt\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"className\": \"grunt\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"className\": \"grunt\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t}\n\t\t\t]\n\t\t}\n\t]\n}"
  },
  {
    "path": "doc/Maps.md",
    "content": "# Singleplayer \n## Saustralasia\n| Idx | File     | Name                    | Sky (PC) | Sky (PSX) | Weather\n| --- | ----     | ----------------------- | -------- | --------- | -------\n| 00  | CAMP     | BOOT CAMP               | COLDSKY  | COLD1     | SNOW\n| 01  | ESTU     | THE WAR FOUNDATION      | SUNNY    | SUNNY1    | -\n| 02  | ROAD     | ROUTINE PATROL          | SUNNY    | SUNNY1    | -\n| 03  | TRENCH   | TRENCH WARFARE          | OMINOUS  | OMINOUS1  | RAIN\n| 04  | DEVI     | MORNING GLORY!          | DESERT   | DESERT1   | -\n| 05  | RUMBLE   | ISLAND INVASION         | SUNNY    | SUNNY1    | -\n| 06  | ZULUS    | UNDER SIEGE             | SUNRISE  | SUNRISE1  | -\n| 07  | TWIN     | COMMUNICATION BREAKDOWN | SUNRISE  | SUNRISE1  | -\n| 08  | SNIPER   | THE SPYING GAME         | SUNSET   | SUNSET1   | -\n| 09  | MASHED   | THE VILLAGE PEOPLE      | SUNNY    | SUNNY1    | -\n| 10  | GUNS     | BANGERS 'N' MASH        | DESERT   | DESERT1   | -\n| 11  | LIBERATE | SAVING PRIVATE RIND     | SUNRISE  | SUNRISE1  | -\n| 12  | OASIS    | JUST DESERTS            | SUNSET   | SUNSET1   | -\n| 13  | FJORDS   | GLACIER GUNS            | COLDSKY  | COLD1     | SNOW\n| 14  | EYRIE    | BATTLE STATIONS         | SUNSET   | SUNSET1   | -\n| 15  | BAY      | FORTIFIED SWINE         | NIGHT    | NIGHT1    | -\n| 16  | MEDIX    | OVER THE TOP            | OMINOUS  | OMINOUS1  | RAIN\n| 17  | BRIDGE   | GENEVA CONVENTION       | SUNNY    | SUNNY1    | -\n| 18  | DESVAL   | I SPY…                  | DESERT   | DESERT1   | -\n| 19  | SNAKE    | CHEMICAL COMPOUND       | COLDSKY  | COLD1     | SNOW\n| 20  | EMPLACE  | ACHILLES HEAL           | OMINOUS  | OMINOUS1  | RAIN\n| 21  | SUPLINE  | HIGH AND DRY            | SUNNY    | SUNNY1    | -\n| 22  | KEEP     | ASSASSINATION           | COLDSKY  | COLD1     | SNOW\n| 23  | TESTER   | HERO WARSHIP            | DESERT   | DESERT1   | -\n| 24  | FOOT     | HAMBURGER HILL          | COLDSKY  | COLD1     | SNOW\n| 25  | FINAL    | WELL, WELL, WELL!       | OMINOUS  | OMINOUS1  | RAIN\n\n\n# Multiplayer\n## Survival-Novice\n| Idx | File     | Name                    | Sky (PC) | Sky (PSX) | Weather\n| --- | -------- | ----------------------- | -------- | --------- | -------         \n| 00  | PLAY1    | PLAY PEN                | TOY      | SUNNY1    | -\n| 01  | PLAY2    | DUVET FUN               | TOY      | SUNNY1    | -\n| 02  | LUNAR1   | PIGS IN SPACE           | SPACE    | NIGHT1    | -\n| 03  | HELL3    | SKULDUGGERY             | -        | DESERT1   | -\n| 04  | HELL2    | PIGIN' HELL             | -        | DESERT1   | -\n| 05  | CREEPY2  | GRAVEYARD SHIFT         | -        | NIGHT1    | -\n\n## Survival-Expert / Death match\n| Idx | File     | Name                    | Sky (PC) | Sky (PSX) | Weather\n| --- | -------- | ----------------------- | -------- | --------- | -------   \n| 00  | ICEFLOW  | ICE-FLOW                | COLDSKY  | COLD1     | SNOW\n| 01  | ARCHI    | YOU HILLOCK             | -        | SUNSET1   | -\n| 02  | DBOWL    | DEATH BOWL              | -        | DESERT1   | -\n| 03  | MLAKE    | FROST FIGHT             | COLDSKY  | COLD1     | SNOW\n| 04  | LAKE     | THE LAKE                | -        | SUNRISE1  | -\n| 05  | ICE      | CHILL HILL              | COLDSKY  | COLD1     | SNOW\n| 06  | SEPIA1   | SQUARE OFF              | -        | SUNNY1    | -\n| 07  | ONEWAY   | ONE WAY SYSTEM          | -        | DESERT1   | -\n| 08  | RIDGE    | RIDGE BACK              | -        | SUNSET1   | -\n| 09  | ISLAND   | ISLAND HOPPER           | -        | SUNRISE1  | -\n\n## Survival-Strategy\n| Idx | File     | Name                    | Sky (PC) | Sky (PSX) | Weather\n| --- | ----     | ----------------------- | -------- | --------- | -------   \n| 00  | BOOM     | FRIENDLY FIRE           | -        | DESERT1   | -\n| 01  | LECPROD  | BRIDGE THE GAB          | COLDSKY  | COLD1     | SNOW\n| 02  | BHILL    | DAM BUSTERS             | -        | SUNRISE1  | -\n| 03  | BUTE     | MOON BUTTES             | SPACE    | NIGHT1    | -\n| 04  | MAZE     | HEDGE MAZE              | SUNNY    | SUNNY1    | -\n| 05  | CMASS    | CRATERMASS              | SPACE    | NIGHT3    | -\n| 06  | ARTGUN   | DOOMED                  | SUNNY    | SUNNY1    | -\n| 07  | DVAL     | DEATH VALLEY            | SUNNY    | SUNNY1    | -\n| 08  | DVAL2    | DEATH VALLEY 2          | SUNNY    | SUNNY1    | -\n\n## Unused (PC)\n| Idx | File     | Name                    | Sky (PC) | Sky (PSX) | Weather\n| --- | ----     | ----------------------- | -------- | --------- | -------\n| 00  | DEMO     | -                       | DESERT   | DESERT1   | -\n| 01  | DEMO2    | -                       | COLDSKY  | COLD1     | SNOW\n| 02  | EASY     | -                       | -        | -         | -\n| 03  | HILLBASE | -                       | COLDSKY  | COLD1     | SNOW\n\n## Unused (PSX)\n| Idx | File     | Name                    | Sky (PC) | Sky (PSX) | Weather\n| --- | ----     | ----------------------- | -------- | --------- | -------\n| 00  | AIRAID   | -                       | -        | -         | -\n| 01  | CANAL    | -                       | -        | -         | -\n| 02  | CLIMB    | -                       | -        | -         | -\n| 03  | FACEOFF  | -                       | -        | -         | -\n| 04  | HELL1    | -                       | -        | -         | -\n| 05  | HIROAD   | -                       | -        | -         | -\n| 06  | HWD      | -                       | -        | -         | -\n| 07  | NEWSNU   | -                       | -        | -         | -\n| 08  | PDRAG    | -                       | -        | -         | -\n| 09  | QUACK    | -                       | -        | -         | -\n| 10  | TDD      | -                       | -        | -         | -"
  },
  {
    "path": "doc/README.md",
    "content": " # Documentation\n\nThe following is a collection of documents we've written outlining the specifications for all of the formats\nused in the game, Hogs of War. These are based on our own original research.\n\nThanks to _Mikhail_ for his help on clarifying some minor points.\n"
  },
  {
    "path": "doc/Scenario.md",
    "content": "# Saustralasia\nSaustralasia is the world's name in the default scenario. \n\n## Tutorial(s)\nSaustralasia contains a tutorial map that teaches about weapon basics.\n- CAMP\n\n## Continents\nSaustralasia consists of 5 continents with 5 levels each. \nYou gain additional 5 PP after completing a continent.\n\n| Continent  | Map0     | Map1   | Map2   | Map3   | Map4    |\n| ---------- | -------- | ------ | ------ | ------ | ------- |\n| HOGSHEAD   | ESTU     | ROAD   | TRENCH | DEVI   | RUMBLE  |\n| SAUSTRALIA | ZULUS    | TWIN   | SNIPER | MASHED | GUNS    |\n| TROTSVILLE | LIBERATE | OASIS  | FJORDS | EYRIE  | BAY     |\n| BELLYPOLIS | MEDIX    | BRIDGE | DESVAL | SNAKE  | EMPLACE |\n| ARASTRIA   | SUPLINE  | KEEP   | TESTER | FOOT   | FINAL   |\n\n## Configuration\n### Regular\n| Idx | Level    | Timer | Pig0        |  Pig1       | Pig2        | Pig3        | Pig4        | Pig5        | Pig6        | Pig7        |\n| --- | -------- | ----- | ----------- |  ---------- | ----------- | ----------- | ----------- | ----------- | ----------- | ----------- |\n| 00  | CAMP     | 99    | -           |  -          | -           | -           | -           | -           | -           | -           |\n| 01  | ESTU     | 99    | GRUNT       | GRUNT       | GRUNT       | -           | -           | -           | -           | -           |\n| 02  | ROAD     | 99    | GRUNT       | GUNNER      | GRUNT       | -           | -           | -           | -           | -           |\n| 03  | TRENCH   | 60    | GRUNT       | GUNNER      | GRUNT       | GRUNT       | -           | -           | -           | -           |\n| 04  | DEVI     | 60    | GRUNT       | GRUNT       | GUNNER      | GUNNER      | GUNNER      | -           | -           | -           |\n| 05  | RUMBLE   | 60    | SAPPER      | GUNNER      | GUNNER      | ORDERLY     | SCOUT       | -           | -           | -           |\n| 06  | ZULUS    | 60    | SNIPER      | SNIPER      | BOMBARDIER  | BOMBARDIER  | -           | -           | -           | -           |\n| 07  | TWIN     | 45    | SCOUT       | ORDERLY     | BOMBARDIER  | GRUNT       | GRUNT       | -           | -           | -           |\n| 08  | SNIPER   | 45    | SNIPER      | MEDIC       | SNIPER      | SPY         | SPY         | -           | -           | -           |\n| 09  | MASHED   | 45    | BOMBARDIER  | PYROTECHNIC | BOMBARDIER  | PYROTECHNIC | -           | -           | -           | -           |\n| 10  | GUNS     | 45    | GUNNER      | GUNNER      | SCOUT       | -           | -           | -           | -           | -           |\n| 11  | LIBERATE | 45    | SNIPER      | SNIPER      | BOMBARDIER  | SNIPER      | SNIPER      | -           | -           | -           |\n| 12  | OASIS    | 45    | SPY         | SPY         | PYROTECHNIC | PYROTECHNIC | PYROTECHNIC | -           | -           | -           |\n| 13  | FJORDS   | 45    | GUNNER      | GUNNER      | GUNNER      | GUNNER      | GUNNER      | -           | -           | -           |\n| 14  | EYRIE    | 45    | PYROTECHNIC | PYROTECHNIC | PYROTECHNIC | PYROTECHNIC | -           | -           | -           | -           |\n| 15  | BAY      | 45    | SPY         | SPY         | SPY         | PYROTECHNIC | -           | -           | -           | -           |\n| 16  | MEDIX    | 45    | GRUNT       | GUNNER      | GUNNER      | COMMANDO    | GUNNER      | GUNNER      | -           | -           |\n| 17  | BRIDGE   | 45    | COMMANDO    | COMMANDO    | COMMANDO    | COMMANDO    | -           | -           | -           | -           |\n| 18  | DESVAL   | 30    | SPY         | SPY         | SPY         | SPY         | SPY         | -           | -           | -           |\n| 19  | SNAKE    | 30    | SPY         | SURGEON     | COMMANDO    | PYROTECHNIC | PYROTECHNIC | -           | -           | -           |\n| 21  | SUPLINE  | 30    | COMMANDO    | COMMANDO    | COMMANDO    | COMMANDO    | COMMANDO    | -           | -           | -           |\n| 20  | EMPLACE  | 30    | SURGEON     | SURGEON     | SURGEON     | SURGEON     | SURGEON     | SURGEON     | SURGEON     | SURGEON     |\n| 22  | KEEP     | 30    | SCOUT       | GUNNER      | GUNNER      | HERO        | COMMANDO    | COMMANDO    | -           | -           |\n| 23  | TESTER   | 30    | HERO        | HERO        | HERO        | HERO        | -           | -           | -           | -           |\n| 24  | FOOT     | 15    | PYROTECHNIC | PYROTECHNIC | PYROTECHNIC | PYROTECHNIC | PYROTECHNIC | PYROTECHNIC | PYROTECHNIC | -           |\n| 25  | FINAL    | 30    | GUNNER      | LEGEND      | LEGEND      | LEGEND      | LEGEND      | LEGEND      | -           | -           |\n\n### Challenger (Mardy Pigs)\n| Idx | Level    | Timer | Pig0        | Pig1        | Pig2        | Pig3        | Pig4        | Pig5        | Pig6        | Pig7        |\n| --- | -----    | ----- | ----------- | ----------- | ----------- | ----------- | ----------- | ----------- | ----------- | ----------- |\n| 00  | CAMP     | 99    | -           | -           | -           | -           | -           | -           | -           | -           |\n| 01  | ESTU     | 99    | GUNNER      | GUNNER      | GUNNER      | -           | -           | -           | -           | -           |\n| 02  | ROAD     | 99    | GUNNER      | BOMBARDIER  | GUNNER      | -           | -           | -           | -           | -           |\n| 03  | TRENCH   | 60    | GUNNER      | BOMBARDIER  | GUNNER      | GUNNER      | -           | -           | -           | -           |\n| 04  | DEVI     | 60    | GUNNER      | GUNNER      | BOMBARDIER  | BOMBARDIER  | BOMBARDIER  | -           | -           | -           |\n| 05  | RUMBLE   | 60    | ENGINEER    | BOMBARDIER  | BOMBARDIER  | MEDIC       | SNIPER      | -           | -           | -           |\n| 06  | ZULUS    | 60    | SPY         | SPY         | PYROTECHNIC | PYROTECHNIC | -           | -           | -           | -           |\n| 07  | TWIN     | 45    | SNIPER      | MEDIC       | PYROTECHNIC | GUNNER      | GUNNER      | -           | -           | -           |\n| 08  | SNIPER   | 45    | SPY         | SURGEON     | SPY         | SPY         | SPY         | -           | -           | -           |\n| 09  | MASHED   | 45    | PYROTECHNIC | COMMANDO    | PYROTECHNIC | COMMANDO    | -           | -           | -           | -           |\n| 10  | GUNS     | 45    | BOMBARDIER  | BOMBARDIER  | SNIPER      | -           | -           | -           | -           | -           |\n| 11  | LIBERATE | 45    | SPY         | SPY         | PYROTECHNIC | SPY         | SPY         | -           | -           | -           |\n| 12  | OASIS    | 45    | SPY         | SPY         | COMMANDO    | COMMANDO    | COMMANDO    | -           | -           | -           |\n| 13  | FJORDS   | 45    | BOMBARDIER  | BOMBARDIER  | BOMBARDIER  | BOMBARDIER  | BOMBARDIER  | -           | -           | -           |\n| 14  | EYRIE    | 45    | COMMANDO    | COMMANDO    | COMMANDO    | COMMANDO    | -           | -           | -           | -           |\n| 15  | BAY      | 45    | SPY         | SPY         | SPY         | COMMANDO    | -           | -           | -           | -           |\n| 16  | MEDIX    | 45    | GUNNER      | BOMBARDIER  | BOMBARDIER  | HERO        | BOMBARDIER  | BOMBARDIER  | -           | -           |\n| 17  | BRIDGE   | 45    | HERO        | HERO        | HERO        | HERO        | -           | -           | -           | -           |\n| 18  | DESVAL   | 30    | SPY         | SPY         | SPY         | SPY         | SPY         | -           | -           | -           |\n| 19  | SNAKE    | 30    | SPY         | SURGEON     | HERO        | COMMANDO    | COMMANDO    | -           | -           | -           |\n| 20  | EMPLACE  | 30    | SURGEON     | SURGEON     | SURGEON     | SURGEON     | SURGEON     | SURGEON     | SURGEON     | SURGEON     |\n| 21  | SUPLINE  | 30    | HERO        | HERO        | HERO        | HERO        | HERO        | -           | -           | -           |\n| 22  | KEEP     | 30    | SNIPER      | BOMBARDIER  | BOMBARDIER  | HERO        | HERO        | HERO        | -           | -           |\n| 23  | TESTER   | 30    | HERO        | HERO        | HERO        | HERO        | -           | -           | -           | -           |\n| 24  | FOOT     | 15    | COMMANDO    | COMMANDO    | COMMANDO    | COMMANDO    | COMMANDO    | COMMANDO    | COMMANDO    | -           |\n| 25  | FINAL    | 30    | BOMBARDIER  | LEGEND      | LEGEND      | LEGEND      | LEGEND      | LEGEND      | -           | -           |"
  },
  {
    "path": "doc/Speech.md",
    "content": "# Pigs\nSpeech file names for pigs are formatted as follows: `WWXXYYZZ.wav`\n\n`WW` = PigIndex (`01` - `09`)  \n\n`XX` = Team \n- `AM` = America\n- `EN` = Britsh\n- `FR` = French\n- `GE` = German\n- `JA` = Japanese\n- `RU` = Russian\n\n`YY` = Category\n- `01` = READY\n- `02` = FIRE\n- `03` = FIRE2 (for MP or NG?)\n- `04` = DEATH\n- `05` = DEATH2 (for MP or NG?)\n\n`ZZ` = LineIndex (`01` - `06`)\n\n# Sarge\nSpeech file names for the sergeants are formatted as follows: `SGENXXYY.wav`\n\nXX = Category   \n\n| Cagetory | Name                           | Description                                                                      |\n| -------- | ------------------------------ | -------------------------------------------------------------------------------- |\n| `01`     | SP_DEATH                       | Plays when a pig from your team dies. (POST TURN)                                |\n| `02`     | SP_LOSING                      | Plays when the game thinks you're loosing. (PRE TURN)                            |\n| `03`     | SP_KILLED                      | Plays when a pig from the enemy team dies. (POST TURN)                           |\n| `04`     | SP_WINNING                     | Plays when the game thinks you're winning. (PRE TURN)                            |\n| `05`     | SP_OBJECTIVE_COMPLETE_CRATE    | Plays when completing an objective that yields an item crate.                    |\n| `06`     | SP_OBJECTIVE_COMPLETE_HEALTH   | Plays when completing an objective that yields a health crate.                   |\n| `07`     | SP_OBJECTIVE_COMPLETE_PROPOINT | Plays when completing an objective that yields a propoint crate.                 |\n| `08`     | SP_OBJECTIVE_FAILED            | Plays when an object marked for protection has been destroyed.                   |\n| `09`     | SP_DROP_ZONE_CRATE             | Plays when entering a drop zone that yields an item crate.                       |\n| `10`     | SP_DROP_ZONE_PROPOINT          | Plays when entering a drop zone that yields a propoint crate.                    |\n| `11`     | SP_PROPOINT_OBJECTIVE_LINGER   | Plays when you've not completed all objectives with propoint rewards. (PRE TURN) |\n| `12`     | SP_PROPOINT_PICKUP_LINGER      | Plays when you've not picked up all dropped propoints. (PRE TURN)                |\n| `13`     | MP_TIME_LINGER                 | Plays when you've 10 seconds left.                                               |\n| `14`     | MP_TIME_LINGER_CRITICAL        |                                                                                  |\n| `15`     | MP_TEAM_BRITISH                | Plays `01` - `04` when winning, `05` - `08` when loosing. (POST TURN)            |\n| `16`     | MP_TEAM_AMERICAN               | Plays `01` - `04` when winning, `05` - `08` when loosing. (POST TURN)            |\n| `17`     | MP_TEAM_FRENCH                 | Plays `01` - `04` when winning, `05` - `08` when loosing. (POST TURN)            |\n| `18`     | MP_TEAM_GERMAN                 | Plays `01` - `04` when winning, `05` - `08` when loosing. (POST TURN)            |\n| `19`     | MP_TEAM_RUSSIAN                | Plays `01` - `04` when winning, `05` - `08` when loosing. (POST TURN)            |\n| `20`     | MP_TEAM_JAPANESE               | Plays `01` - `04` when winning, `05` - `08` when loosing. (POST TURN)            |\n| `21`     | MP_TEAM_LARD                   | Plays `01` - `04` when winning, `05` - `08` when loosing. (POST TURN)            |\n| `22`     | SP_REWARD                      | Plays in order after conquering a continent.                                     |\n\nYY = LineIndex (`01` - `08`)\n\n\n# Train1\n> Suggests there where multiple training's planned or cut.\n\nSpeech file names for Train1 are formatted as follows: `TR1_ENXX.wav`\n\nXX = LineIndex\n\n| Line | Description\n| ---- | -----------\n| `01` | Plays when spawning\n| `02` | Plays when walking first time\n| `03` | Plays when picking up `7 [CRATE1] (Bayonet)`\n| `04` | Plays when opening weapon menu first time\n| `05` | Plays when equiping bayonet first time\n| `06` | Plays when destroying group 1\n| `07` | Plays when lingering on picking crates.\n| `08` | Plays when picking up `12 [CRATE1] (Rifle)`\n| `09` | Plays when equiping rifle first time\n| `10` | Plays when destroying group 2\n| `11` | Plays when picking up `11 [CRATE1] (Sniper-Rifle)`\n| `12` | Plays when destroying group 3\n| `13` | Plays when picking up `13 [CRATE1] (Granade)`\n| `14` | Plays when destroying first object in group 4\n| `15` | Plays when destroying group 4\n| `16` | Plays when picking up `16 [CRATE1] (Granade)`\n| `17` | Plays when destroying group 5\n| `18` | Plays when picking up `18 [CRATE2] (Health)`\n| `19` | Plays when picking up `62 [CRATE2] (Health)`\n| `20` | Plays when picking up `53 [CRATE1] (TNT)`\n| `21` | Plays when triggering first mine\n| `22` | Plays when destroying group 89 (DOOR)\n| `23` | Plays when picking up `52 [CRATE2] (Health)`\n| `24` | Plays when picking up `56 [CRATE2] (Health)`\n| `25` | Plays when picking up `19 [CRATE1] (Bazooka)`\n| `26` | Plays when running out of time first time\n| `27` | Plays when destroying group 7\n| `28` | Plays when getting a record time?\n"
  },
  {
    "path": "doc/coding_style.md",
    "content": "# C/C++ Style Guide\n\n```c++\n\nstruct ThisThing {\n\tint someVar, someOtherVar;\n};\n\nclass ThatThing {\npublic:\n\n\tunsigned int GetSomeVar() const { return someVar; }\n\tvoid SetSomeVar( unsigned int inSomeVar ) {\n\t\tsomeVar = inSomeVar;\n\t}\n\nprotected:\nprivate:\n\n\t// Always use the initialisers\n\tunsigned int myVar { 0 };\n};\n\n// (OpenHoW) Actor derived class prefixed with 'A'\nclass ATank : public Actor {}\n\n// Interface class prefixed with 'I'\nclass IPhysicsBody {\npublic:\n\tvirtual void SomeMethod() = 0;\n\tvirtual void SomeOtherMethod() = 0;\n}\n\n// Template class prefixed with 'T'\ntemplate<T> class TVector {}\n\nvoid Function( void ) {\n\t// Tabs are used ( tab size = 4 )\n\t\n\tprintf( \"Hello World!\\n\" );\n\t\n\t// Variables use mixed case\n\tint castMe = 0;\n\tbool castYou = static_cast< bool >( castMe );\n\t\n\tbool fooVar = false;\n\tif ( !fooVar ) {\n\t\tprintf( \"False Var\\n\" );\n\t}\n\t\n\tvoid *fooPointer = NULL;\n\tif ( fooPointer == NULL ) {\n\t\tprintf( \"Pointer is null\\n\" );\n\t}\n\t\n\tstruct {\n\t\t// Variables are aligned by spaces\n\t\tint   someVar;\n\t\tfloat someVar2;\n\t} myStruct;\n}\n\n```\n\n## Platform Library\n\n```c\n\n// The platform library is primarily C\n\n#define PL_THING_DEFAULT_SOMETHING\t2\n\nenum {\n    PL_THING_TYPE_AWESOME,\n    PL_THING_TYPE_BAD,\n    PL_THING_TYPE_GOOD,\n};\n\n// Struct types are prefixed with 'PL'\ntypedef struct PLThing {\n\tint   someThing;\n\tfloat someThing2;\n} PLThing;\n\nPLThing *plCreateThing( int someThing, float someThing ) {\n\tPLThing *thing = pl_malloc( sizeof( PLThing ) );\n\tthing->someThing = someThing;\n\tthing->someThing2 = someThing;\n\treturn thing;\n}\n\nbool plIsValidThing( PLThing *thing ) {\n\treturn ( bool )( thing != NULL );\n}\n\n```\n"
  },
  {
    "path": "doc/file-formats/FAC.md",
    "content": "# FAC - Model faces\n\n```c\n16  char[]  reserved                    // reserved for name?\n4   int     triangleCount\nforeach(triangle) // sizeof = 32\n{\n    1   char   triangle.U_A             // U component for Vertex_A\n    1   char   triangle.V_A             // U component for Vertex_A\n\n    1   char   triangle.U_B             // U component for Vertex_B\n    1   char   triangle.V_B             // V component for Vertex_B\n\n    1   char   triangle.U_C             // U component for Vertex_C\t\n    1   char   triangle.V_C             // V component for Vertex_C\n\n    2   short  triangle.Vertex_A        // index from .VTX\n    2   short  triangle.Vertex_B        // index from .VTX\n    2   short  triangle.Vertex_C        // index from .VTX\n\n    2   short  triangle.Normal_A        // index from .NO2\n    2   short  triangle.Normal_B        // index from .NO2\n    2   short  triangle.Normal_C        // index from .NO2\n    \n    2   short  triangle.Short0\n    \n    4   int    triangle.TextureIndex    // index from .MTD\n    \n    2   short  triangle.Short1\n    2   short  triangle.Short2\n    2   short  triangle.Short3\n    2   short  triangle.Short4\n}\n\n4   int    planeCount\nforeach(plane)   //36 bytes per plane\n{\n    1   char   plane.U_A                // U component for Vertex_A\n    1   char   plane.V_A                // U component for Vertex_A\n\n    1   char   plane.U_B                // U component for Vertex_B\n    1   char   plane.V_B                // V component for Vertex_B\n\n    1   char   plane.U_C                // U component for Vertex_C\t\n    1   char   plane.V_C                // V component for Vertex_C\n\n    1   char   plane.U_D                // U component for Vertex_D\n    1   char   plane.V_D                // V component for Vertex_D\n\n    2   short  plane.Vertex_A           // index from .VTX\n    2   short  plane.Vertex_B           // index from .VTX\n    2   short  plane.Vertex_C           // index from .VTX\n    2   short  plane.Vertex_D           // index from .VTX\n\n    2   short  plane.Normal_A           // index from .NO2\n    2   short  plane.Normal_B           // index from .NO2\n    2   short  plane.Normal_C           // index from .NO2\n    2   short  plane.Normal_D           // index from .NO2    \n\n    4   int    plane.TextureIndex       // index from .MTD\n    \n    2   short  plane.Short1\n    2   short  plane.Short2\n    2   short  plane.Short3\n    2   short  plane.Short4\n}\n// EOF\n```"
  },
  {
    "path": "doc/file-formats/HIR.md",
    "content": "# HIR - Model skeleton\n\nSkeleton used for pigs\n\n```c\nforeach(bone) //sizeof = 20\n{\n    4   int     bone.ParentIndex\n\n    //Transform16\n    2   short   bone.Transform.X\n    2   short   bone.Transform.Y\n    2   short   bone.Transform.Z\n    2   short   bone.Transform.W    //padding\n\n    //Rotation16\n    2   short   bone.Rotation.X\n    2   short   bone.Rotation.Y\n    2   short   bone.Rotation.Z\n    2   short   bone.Rotation.W\n}\n// EOF\n```\n\n| Index | Bone \n| ----- | ----- \n| 0     | Hip\n| 1     | Spine\n| 2     | Head\n| 3     | UpperArm.L\n| 4     | LowerArm.L\n| 5     | Hand.L\n| 6     | UpperArm.R\n| 7     | LowerArm.R\n| 8     | Hand.R\n| 9     | UpperLeg.L\n| 10    | LowerLeg.L\n| 11    | Foot.L\n| 12    | UpperLeg.R\n| 13    | LowerLeg.R\n| 14    | Foot.R\n\n![Pig Skeleton](images/pig_skeleton.png)\n"
  },
  {
    "path": "doc/file-formats/MAD_MTD.md",
    "content": "# MAD & MTD \n\n### Most MAD & MTD packages follow the \"named structure\"\n```c\nforeach(namedFileInfo) //sizeof = 24\n{\n    16  char[]  entry.Name\n    4   int     entry.DataOffset  // within this file.\n    4   int     entry.DataSize\n}\n// DATA\n// EOF\n```\n\n### \"mcap.mad\" follows the \"raw structure\"\n```c\nforeach(rawFileInfo) //sizeof = 8\n{\n    4   int     entry.DataOffset  //within this file.\n    4   int     entry.DataSize\n}\n// DATA\n// EOF\n```"
  },
  {
    "path": "doc/file-formats/MCAP.md",
    "content": "# MCAP - Motion capture\n\n.mcap are extracted from mcap.mad\n\n```c\nforeach(keyframe) //sizeof = 272\n{\n    // World space transform\n    // Transform32 (PSX uses Transform16)\n    4   int rootTransform.X\n    4   int rootTransform.Y\n    4   int rootTransform.Z\n    4   int rootTransform.W   // padding \n    \n    // Object space transform\n    // Transform32 (PSX uses Transform16)\n    4   int objectTransform.X\n    4   int objectTransform.Y\n    4   int objectTransform.Z\n    4   int objectTransform.W   // padding\n    \n    foreach(boneRotation) //sizeof = 15\n    {        \n        // Bone quaterion rotation\n        //Rotation32 (PSX uses Rotation16)\n        4   float   rotation.X\n        4   float   rotation.Y\n        4   float   rotation.Z\n        4   float   rotation.W\n    }\n}\n// EOF\n```\n\n----\n\n```c++\nstruct CaptureRotation {\n#if 1\n    uint16_t x, y, z, w;\n#else\n    uint8_t x, y, z, w;\n#endif\n};\n\nstruct CaptureFrame {\n    uint16_t        Root[4];    // xyz(pad)\n    uint16_t        Object[4];  // xyz(pad)\n\tCaptureRotation pt[15];\n};\n```\n"
  },
  {
    "path": "doc/file-formats/MIN.md",
    "content": "# MIN - Model data\n\n**!!This page is still WIP!!<br> \nMost of this has been deduced by observation thus far as it's not a priority right now.**\n\n```c\nint8_t      u0[16];\n```\n\nThen followed by face data.\n\n```c\nuint32_t    num_faces;\nstruct {\n    char u0[24];\n} faces[num_faces];\n\nint32_t     u1;\n```\n\n32-bit integer seems to follow after faces, unsure why.\n\nThis is then followed by another block of unknown data, could\nbe vertices (however number of indices doesn't match for faces).\n\n```c\nuint32_t    num_u2;\nstruct {\n    char unknown[16];\n} u2[num_u2];\n```\n"
  },
  {
    "path": "doc/file-formats/NO2.md",
    "content": "# NO2 - Model normals\n\n```c\nforeach(normal) //sizeof = 16\n{\n    4   float   normal.X\n    4   float   normal.Y\n    4   float   normal.Z\n    4   float   normal.BoneIndex\n}\n// EOF\n```"
  },
  {
    "path": "doc/file-formats/OFS.md",
    "content": "# OFS - Text offset data\n\n```c\nforeach(text) // sizeof = 2\n{   \n    2   ushort  text.offset // index from .BIN\n}\n```"
  },
  {
    "path": "doc/file-formats/PMG.md",
    "content": "# PMG - Map mesh data\n\nA map is 32768 x 32768 units and consists of 16 x 16 blocks.  \nA block is 2048 x 2048 units and consists of 4x4 tiles.  \nA tile is 512 x 512 units.\n\n```c\nfor (int yBlock = 0; yBlock < 16; yBlock++)\n{\n    for (int xBlock = 0; xBlock < 16; xBlock++)\n    {\n        2   short  block.xOffset                   // -16384 ~ 16384\n        2   short  block.yOffset                   // unreliable?\n        2   short  block.zOffset                   // -16384 ~ 16384\n        2   short  block.Field0\n        \n        // HeightMap\n        for (int yVertex = 0; yVertex < 5; yVertex++)\n        {\n            for (int xVertex = 0; xVertex < 5; xVertex++)\n            {\n                2   short   vertex.height                // height sample\n                2   short   vertex.lighting              // <= 255\n            }\n        }\n        \n        4   int   block.Field1                  // always 0 -> obsolete tileCount?\n        \n        // TileMap\n        for (int yTile = 0; yTile < 4; yTile++)\n        {\n            for (int xTile = 0; xTile < 4; xTile++)\n            {   \n                2   short   tile.Field0          // always 0 -> obsolete xOffset?\n                2   short   tile.Field1          // always 0 -> obsolete yOffset?\n                2   short   tile.Field2          // always 0 -> obsolete zOffset?\n\n                // MapTileType\n                // (MSB)                               (LSB)\n                // | 07 | 06 | 05 | 04 | 03 | 02 | 01 | 00 |\n                // | F3 | F2 | F1 |           T1           |\n                // T1 = Type (0x1F)\n                //      Mud   = 00\n                //      Grass = 01\n                //      Metal = 02\n                //      Wood  = 03\n                //      Water = 04\n                //      Stone = 05\n                //      Rock  = 06\n                //      Sand  = 07\n                //      Ice   = 08\n                //      Snow  = 09\n                //      Quag  = 10\n                //      Lava  = 11\n                // F1 = IsWater (0x20)\n                // F2 = IsMine (0x40)\n                // F3 = IsWall (0x80)\n                1   char    tile.Type\n\n                // MapTileSlip (requires \"IsWall\"?)\n                //      Full        = 0\n                //      Bottom      = 1\n                //      Left        = 2\n                //      Top         = 3\n                //      Right       = 4\n                //      BottomRight = 5\n                //      BottomLeft  = 6\n                //      TopLeft     = 7\n                //      TopRight    = 8\n                1   char    tile.Slip\n\n                2   short   tile.Field3             // always 0\n\n                // MapTileRotateFlip\n                // FlipX     = 1\n                // Rotate90  = 2\n                // Rotate180 = 4\n                1   char    tile.RotationFlip\n\n                4   int     tile.TextureIndex       // into PTG\n                1   char    tile.Field4             // always 0\n            }\n        }\n    }\n}\n// EOF\n```"
  },
  {
    "path": "doc/file-formats/POG.md",
    "content": "# POG - Map object data\n\n```c\n\n2   ushort  objectCount\nfor(int iObject = 0; iObject < objectCount; iObject++) // sizeof = 94\n{\n    16  char[]  obj.Name                //Model name\n    16  char[]  obj.NULL                //\"NULL\"\n    2   short   obj.XOffset\n    2   short   obj.YOffset\n    2   short   obj.ZOffset\n    \n    2   short   obj.ID\n    2   short   obj.XRotation           // 4096 = 360°\n    2   short   obj.YRotation           // 4096 = 360°\n    2   short   obj.ZRotation           // 4096 = 360°\n    2   short   obj.TypeID              // Model type id (instancing)\n    \n    2   short   obj.BoundingBoxWidth\n    2   short   obj.BoundingBoxHeight\n    2   short   obj.BoundingBoxLength\n\n    // BoundingBoxType:\n    // - Box = 0\n    // - Prism = 1\n    2   short   obj.BoundingBoxType\n        \n    1   short   obj.Short0\n    1   char    obj.Byte0\n\n    // PigTeam:\n    // - Team01 = 0x01\n    // - Team02 = 0x02\n    // - Team03 = 0x04\n    // - Team04 = 0x08\n    // - Team05 = 0x10\n    // - Team06 = 0x20\n    // - Team07 = 0x40\n    // - Team08 = 0x80\n    1   char    obj.Team\n    \n    // ScriptType:\n    // - DESTROY_ITEM           = 01\n    // - DESTROY_PROPOINT       = 02\n    // - PROTECT_ITEM           = 03\n    // - PROTECT_PROPOINT       = 04\n    // - DROPZONE_ITEM          = 07\n    // - DROPZONE_PROPOINT      = 08\n    // - DESTROY_GROUP_ITEM     = 13\n    // - DESTROY_GROUP_PROPOINT = 14\n    // - PICKUP_ITEM            = 19\n    // - TUTORIAL_DESTROY       = 20\n    // - TUTORIAL_END           = 21\n    // - TUTORIAL_BLAST         = 22\n    // - TUTORIAL_DESTROY_GROUP = 23\n    2   short   obj.ScriptType\n\n    1   char    obj.ScriptGroup    \n    19  char[]  obj.ScriptParamters\n    2   short   obj.ScriptXOffset\n    2   short   obj.ScriptYOffset\n    2   short   obj.ScriptZOffset\n    \n    // ObjectFlag:\n    // - None      = 0\n    // - Player    = 1 << 0,\n    // - Bit1      = 1 << 1,\n    // - Bit2      = 1 << 2,\n    // - Bit3      = 1 << 3,\n    // - ScriptObj = 1 << 4,\n    // - Inside    = 1 << 5\n    // - Delayed   = 1 << 6\n    // - Bit7      = 1 << 7\n    2   short   obj.Flag\n\n    2   short   obj.Short1\n    2   short   obj.Short2\n}\n// EOF\n```"
  },
  {
    "path": "doc/file-formats/PTG.md",
    "content": "# PTG\n\nContains the terrain tile textures (.tim). \nAll files have to be the same size in bytes.\n\n```c\n4   int    textureCount\nforeach(texture) //sizeof = (ptgFileSize - 4) / textureCount\n{\n    *   char[]  textureBuffer\n}\n```"
  },
  {
    "path": "doc/file-formats/README.md",
    "content": "# File formats\n\n| Extension         | Description\n| ---------         | -----------\n| [MAD](MAD_MTD.md) | Model package\n| MAM               | Model package (mangled)\n| MMM               | Model package (mangled)\n| [MTD](MAD_MTD.md) | Texture package\n| MTM               | Texture package (mangled)\n| [PMG](PMG.md)     | Map mesh data\n| PMM               | Map mesh data (mangled)\n| [POG](POG.md)     | Map object data\n| POM               | Map object data (mangled)\n| [PTG](PTG.md)     | Map texture package\n| PTM               | Map texture package (mangled)\n| [MIN](MIN.md)     | Model data\n| [VTX](VTX.md)     | Model vertices\n| [NO2](NO2.md)     | Model normals\n| [FAC](FAC.md)     | Model faces\n| [HIR](HIR.md)     | Model skeleton\n| [TAB](TAB.md)     | Text art block\n| [OFS](OFS.md)     | Text offset data\n| MGL               | UI texture (mangled)"
  },
  {
    "path": "doc/file-formats/TAB.md",
    "content": "# TAB - Text art block\n\nDescribes a section within a font tim used for a letter.\n\n```c\nforeach(block) //sizeof = 8\n{\n    2   ushort  block.XOffset\n    2   ushort  block.YOffset\n    2   ushort  block.Width\n    2   ushort  block.Height    \n}\n```"
  },
  {
    "path": "doc/file-formats/VTX.md",
    "content": "# VTX - Model vertices\n\n```c\nforeach(vertex) // sizeof = 8\n{\n    2   short   vertex.XOffset\n    2   short   vertex.YOffset\n    2   short   vertex.ZOffset\n    2   short   vertex.BoneIndex\n}\n// EOF\n```"
  },
  {
    "path": "doc/game/pig_faces.md",
    "content": "# Pig Facial Animations\n\n## Frontend\n\nThis part of the implementation is specific to the frontend, which is basically the main menu for the game. \n\nSome of this may coincide with the implementation used for the main game - in which case they can be brought together under the same implementation, though the implementation for the game itself is more contextual than the frontend.\n\nApparently the commando is a special case, but I'll need to investigate this further.\n\nHere on the frontend, the pigs use the following expression groups.\n* Happy\n* Sad\n* Cheeky\n* Surprised\n* Angry\n* Thoughtful\n\n**Keep in mind I don't have access to all my notes right now so I'll be revisiting this with more details later!**\n\n### Happy\n\nThere is a 1 in 8 chance that the pig will 'blink' in this state, and then a 1 in 15 chance the pig will 'blink' for an extended period (up to 40 ticks maximum, 20 ticks minimum) otherwise they will 'blink' for just 3 ticks.\n\nIf the pig doesn't 'blink' in this state, the pig will provide a 'normal' eyes expression from 3 ticks minimum and up to 6 ticks maximum.\n\nThere is a 1 in 3 chance that the pig's mouth will be 'closed' for 30 ticks, otherwise it will be 'open' for 30 ticks.\n\n### Sad\n\nThere is a 1 in 10 chance that the pig will 'blink' in this state which will only occur for 3 ticks. Their standard 'sad' eyes expression, otherwise, will appear for 5 ticks.\n\nThe mouth will continually use the 'surprised' expression during this state until the expression state has changed.\n\n### Cheeky\n\nEyes alternate every three ticks from 'angry' to 'normal' (so 'angry' + 3 ticks, then 'normal' + 3 ticks).\n\nMouth is continuously updated to 'open' every tick, so this will switch over as soon as the expression state has changed.\n\n### Surprised\n\nThere is a 1 in 10 chance that the pig will 'blink', otherwise the pig will use their 'surprised' eyes. Either route will last for 5 ticks.\n\nThe mount is continuously updated to 'surprised' every tick, so this will switch over as soon as the expression state has changed.\n\n### Angry\n\nEyes don't blink at all while the pig is in this state - delay is set to 10 ticks before eyes are updated again.\n\nMouth is continuously updated to 'angry' every tick, so this will switch over as soon as the expression state has changed.\n\n### Thoughtful\n\nThere is a 1 in 2 chance that the pig will show a 'sad' eyes expression for 20 ticks, otherwise there is a 1 in 2 chance they will either show a 'normal' eye expression for 20 ticks or 'blink' for three ticks.\n\nThere is a 1 in 3 chance the pig's mouth will show a 'sad' expression for 30 ticks but otherwise will show a 'closed' expression for 30 ticks instead.\n\n----\n\nSome face frames are enforced by the current animation.\n\n### Sneezing\n\nIf the frame is less than 1024, the pig should show a surprised expression for both their eyes and mouth. Otherwise the eyes are set to their blink state and the mouth is closed.\n\n### Dancing\n\nThe eyes should be set to their normal state and the mouth should be surprised."
  },
  {
    "path": "setup_cmake.bat",
    "content": "echo off\ncls\nif not exist .\\build\\ mkdir .\\build\\\ncd .\\build\\\ncmake .\\..\\\npause\n"
  },
  {
    "path": "setup_libraries.bat",
    "content": "echo off\ncls\nrem Ugly ugly script to download sdl2 and setup project on Windows, wheee\nrem Ensure SDL2 is setup, if not download it and awkwardly put it together\nif not exist .\\src\\3rdparty\\sdl2\\ (\n\trem Download and extract SDL2 data\n\techo SDL2 dir not found under 3rdparty, downloading...\n\tpowershell -Command \"Invoke-WebRequest https://www.libsdl.org/release/SDL2-devel-2.0.9-mingw.tar.gz -OutFile .\\src\\3rdparty\\SDL2-devel-2.0.9-mingw.tar.gz\"\n\techo Extracting data...\n\tpowershell -Command \"tar -x -v -C .\\src\\3rdparty\\ -f .\\src\\3rdparty\\SDL2-devel-2.0.9-mingw.tar.gz\"\n\techo Deleting downloaded package...\n\tdel .\\src\\3rdparty\\SDL2-devel-2.0.9-mingw.tar.gz\n\techo Done!\n\n\trem SDL2 has been downloaded, now we have to shuffle everything\n\techo Creating sdl2 directory and copying data...\n\tmkdir .\\src\\3rdparty\\sdl2\\\n\tmkdir .\\src\\3rdparty\\sdl2\\include\\\n\tmkdir .\\src\\3rdparty\\sdl2\\lib\\\n\tXcopy /E /I .\\src\\3rdparty\\SDL2-2.0.9\\x86_64-w64-mingw32\\include .\\src\\3rdparty\\sdl2\\include\n\tXcopy /E /I .\\src\\3rdparty\\SDL2-2.0.9\\x86_64-w64-mingw32\\lib .\\src\\3rdparty\\sdl2\\lib\n\techo Done!\n\n\trem Now delete the SDL2-2.0.9 dir\n\tdel /F /Q /S .\\src\\3rdparty\\SDL2-2.0.9\\*.*\n\trmdir /S /Q .\\src\\3rdparty\\SDL2-2.0.9\\\n)\npause\n"
  },
  {
    "path": "src/engine/App.cpp",
    "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// Copyright © 2017-2022 TalonBrave.info and Others (see CONTRIBUTORS)\n\n#include \"App.h\"\n#include \"Display.h\"\n#include \"imgui_layer.h\"\n#include \"Language.h\"\n#include \"config.h\"\n#include \"Menu.h\"\n\n#define WINDOW_TITLE        \"OpenHoW\"\n\nohw::App *appInstance;\nohw::App *ohw::GetApp() {\n\treturn appInstance;\n}\n\n///////////////////////////////////////////////////////////////////\n// Memory Management\n\n// Override C++ new/delete operators, so we can track memory usage\nvoid *operator new( size_t size ) { return PlMAllocA( size ); }\nvoid *operator new[]( size_t size ) { return PlMAllocA( size ); }\nvoid operator delete( void *p ) throw() { PlFree( p ); }\nvoid operator delete[]( void *p ) throw() { PlFree( p ); }\n\n/**\n * Callback, to catch any fail within hei.\n */\nstatic void MemoryAbortCallback( size_t failSize )\n{\n\tError( \"Failed to alloc of %lu bytes!\\n\", failSize );\n}\n\nvoid *ohw::App::MAlloc( size_t size, bool abortOnFail ) {\n\treturn PlMAlloc( size, abortOnFail );\n}\n\nvoid *ohw::App::CAlloc( size_t num, size_t size, bool abortOnFail ) {\n\treturn PlCAlloc( num, size, abortOnFail );\n}\n\n///////////////////////////////////////////////////////////////////\n\nohw::App::App( int argc, char **argv ) {\n\tpl_memory_abort_cb = MemoryAbortCallback;\n\n\tif ( PlInitialize( argc, argv ) != PL_RESULT_SUCCESS ) {\n\t\tError( \"Failed to initialize Hei: %s\\n\", PlGetError() );\n\t}\n\n\tPlInitializeSubSystems( PL_SUBSYSTEM_IO );\n\n\tPlRegisterStandardPackageLoaders();\n\tPlRegisterStandardImageLoaders( PL_IMAGE_FILEFORMAT_TGA | PL_IMAGE_FILEFORMAT_PNG | PL_IMAGE_FILEFORMAT_BMP | PL_IMAGE_FILEFORMAT_TIM );\n\n\tconst char *wd = PlGetWorkingDirectory();\n\tif ( wd == nullptr ) {\n\t\tError( \"Failed to get working directory: %s\\n\", PlGetError() );\n\t}\n\n\t// Mount the working directory first (./mods/...)\n\tif ( PlMountLocalLocation( wd ) == nullptr ) {\n\t\tError( \"Failed to mount working directory: %s\\n\", PlGetError() );\n\t}\n\n\tchar appDataPath[PL_SYSTEM_MAX_PATH];\n\tPlGetApplicationDataDirectory( APP_NAME, appDataPath, PL_SYSTEM_MAX_PATH );\n\n\tif ( !PlCreatePath( appDataPath ) ) {\n\t\tDisplayMessageBox( MBErrorLevel::WARNING_MSG, \"Unable to create %s: %s\\nSettings will not be saved.\", appDataPath, PlGetError() );\n\t}\n\n\t// Then mount the app data dir so we can read from the config\n\t// or load any mods that have been placed under there\n\tif ( PlMountLocalLocation( appDataPath ) == nullptr ) {\n\t\tError( \"Failed to mount app data directory: %s\\n\", PlGetError() );\n\t}\n\n\tchar logPath[PL_SYSTEM_MAX_PATH];\n\tsnprintf( logPath, sizeof( logPath ), \"%s/debug.txt\", appDataPath );\n\tPlSetupLogOutput( logPath );\n\n\tohw::LOG_LEVEL_DEFAULT = PlAddLogLevel( \"info\", { 0, 255, 0, 255 }, true );\n\tohw::LOG_LEVEL_WARNING = PlAddLogLevel( \"warning\", { 255, 255, 0, 255 }, true );\n\tohw::LOG_LEVEL_ERROR = PlAddLogLevel( \"error\", { 255, 0, 0, 255 }, true );\n\tohw::LOG_LEVEL_DEBUG = PlAddLogLevel( \"debug\", { 0, 255, 255, 255 },\n#if !defined( NDEBUG )\n                                          true\n#else\n\t\t\tfalse\n#endif\n\t);\n\n\tPrint( \"Initializing OpenHoW %s\\n\", GetVersionString() );\n\n\tif ( SDL_Init( SDL_INIT_EVERYTHING ) != 0 ) {\n\t\tError( \"Failed to initialize SDL2!\\nSDL: %s\", SDL_GetError() );\n\t}\n\n\tSDL_DisableScreenSaver();\n\n\t/* using this to catch modified keys\n\t * without having to do the conversion\n\t * ourselves                            */\n\tSDL_StartTextInput();\n\n\tresourceManager = new ResourceManager();\n\tmodManager = new ModManager();\n\tinputManager = new InputManager();\n}\n\nvoid ohw::App::Shutdown() {\n\tConfig_Save( Config_GetUserConfigPath() );\n\n\tImGuiImpl_Shutdown();\n\n\tdelete gameManager;\n\tdelete audioManager;\n\tdelete resourceManager;\n\tdelete myDisplay;\n\n\tLanguageManager::DestroyInstance();\n\n\tSDL_StopTextInput();\n\n\tSDL_EnableScreenSaver();\n\tSDL_Quit();\n\n\tPlShutdown();\n\n\texit( EXIT_SUCCESS );\n}\n\nvoid ohw::App::DisplayMessageBox( MBErrorLevel level, const char *message, ... ) {\n\tunsigned int sdlLevel;\n\tswitch ( level ) {\n\t\tcase MBErrorLevel::INFORMATION_MSG:\n\t\t\tsdlLevel = SDL_MESSAGEBOX_INFORMATION;\n\t\t\tbreak;\n\t\tcase MBErrorLevel::WARNING_MSG:\n\t\t\tsdlLevel = SDL_MESSAGEBOX_WARNING;\n\t\t\tbreak;\n\t\tcase MBErrorLevel::ERROR_MSG:\n\t\t\tsdlLevel = SDL_MESSAGEBOX_ERROR;\n\t\t\tbreak;\n\t}\n\n\tva_list args;\n\tva_start( args, message );\n\n\tint length = pl_vscprintf( message, args ) + 1;\n\tchar *buf = static_cast<char *>(MAlloc( length, true ));\n\tvsprintf( buf, message, args );\n\tva_end( args );\n\n\tSDL_ShowSimpleMessageBox( sdlLevel, WINDOW_TITLE, buf, nullptr );\n\n\tdelete[] buf;\n}\n\nvoid ohw::App::InitializeConfig() {\n\tConsole_Initialize();\n\n\t/* this MUST be done after all vars have been\n\t * initialized, otherwise, right now, certain\n\t * vars will not be loaded/saved! */\n\tConfig_Load( CONFIG_FILENAME );\n}\n\nvoid ohw::App::InitializeDisplay() {\n\tconst char *arg;\n\n\t// check the command line for any arguments\n\n\targ = PlGetCommandLineArgumentValue( \"-msaa\" );\n\tif ( arg != nullptr ) {\n\t\tint i = std::strtol( arg, nullptr, 10 );\n\t\tSDL_GL_SetAttribute( SDL_GL_MULTISAMPLESAMPLES, i );\n\t}\n\n\tint width = cv_display_width->i_value;\n\targ = PlGetCommandLineArgumentValue( \"-width\" );\n\tif ( arg != nullptr ) {\n\t\twidth = std::strtol( arg, nullptr, 10 );\n\t}\n\n\tint height = cv_display_height->i_value;\n\targ = PlGetCommandLineArgumentValue( \"-height\" );\n\tif ( arg != nullptr ) {\n\t\theight = std::strtol( arg, nullptr, 10 );\n\t}\n\n\tbool fullscreen = cv_display_fullscreen->b_value;\n\targ = PlGetCommandLineArgumentValue( \"-fullscreen\" );\n\tif ( arg != nullptr ) {\n\t\tfullscreen = ( arg[ 0 ] == '1' );\n\t}\n\n\tint desiredDisplay = 0;\n\targ = PlGetCommandLineArgumentValue( \"-display\" );\n\tif ( arg != nullptr ) {\n\t\tdesiredDisplay = std::strtol( arg, nullptr, 10 );\n\t}\n\n\tmyDisplay = new Display( WINDOW_TITLE, width, height, desiredDisplay, fullscreen );\n\tmyDisplay->SetIcon( \"icon.png\" );\n\n\t// Fetch all the available display modes\n\tPrint( \"Querying display modes...\\n\" );\n\tint numModes = SDL_GetNumDisplayModes( desiredDisplay );\n\tfor ( int i = 0; i < numModes; ++i ) {\n\t\tSDL_DisplayMode mode;\n\t\tif ( SDL_GetDisplayMode( desiredDisplay, i, &mode ) != 0 ) {\n\t\t\tWarning( \"Failed to get display mode %d via SDL!\\nSDL: %s\\n\", i, SDL_GetError() );\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Skip any modes that are smaller than our minimum allowed sizes\n\t\tif ( mode.w < DISPLAY_MIN_WIDTH || mode.h < DISPLAY_MIN_HEIGHT ) {\n\t\t\tcontinue;\n\t\t}\n\n\t\t//Print( \" mode %d : %dx%d %d\\n\", i, mode.w, mode.h, mode.refresh_rate );\n\t\tmyDisplayPresets.push_back( DisplayPreset( mode.w, mode.h, mode.refresh_rate ) );\n\t}\n\n\tImGuiImpl_Setup();\n}\n\nvoid ohw::App::InitializeAudio() {\n\taudioManager = new AudioManager();\n\taudioManager->SetupMusicSource();\n}\n\nvoid ohw::App::InitializeGame() {\n\t// Initialize the language manager\n\tLanguageManager::GetInstance()->SetLanguage( \"eng\" );\n\n\tgameManager = new GameManager();\n\tgameManager->CachePersistentData();\n\n\tMenu_Initialize();\n}\n\n///////////////////////////////////////////////\n// Events\n\nstatic int TranslateSDLKey( int key ) {\n\tif ( key < 128 ) {\n\t\treturn key;\n\t}\n\n\tswitch ( key ) {\n\t\tcase SDLK_F1:\n\t\t\treturn ohw::InputManager::KEY_F1;\n\t\tcase SDLK_F2:\n\t\t\treturn ohw::InputManager::KEY_F2;\n\t\tcase SDLK_F3:\n\t\t\treturn ohw::InputManager::KEY_F3;\n\t\tcase SDLK_F4:\n\t\t\treturn ohw::InputManager::KEY_F4;\n\t\tcase SDLK_F5:\n\t\t\treturn ohw::InputManager::KEY_F5;\n\t\tcase SDLK_F6:\n\t\t\treturn ohw::InputManager::KEY_F6;\n\t\tcase SDLK_F7:\n\t\t\treturn ohw::InputManager::KEY_F7;\n\t\tcase SDLK_F8:\n\t\t\treturn ohw::InputManager::KEY_F8;\n\t\tcase SDLK_F9:\n\t\t\treturn ohw::InputManager::KEY_F9;\n\t\tcase SDLK_F10:\n\t\t\treturn ohw::InputManager::KEY_F10;\n\t\tcase SDLK_F11:\n\t\t\treturn ohw::InputManager::KEY_F11;\n\t\tcase SDLK_F12:\n\t\t\treturn ohw::InputManager::KEY_F12;\n\n\t\tcase SDLK_ESCAPE:\n\t\t\treturn ohw::InputManager::KEY_ESCAPE;\n\n\t\tcase SDLK_PAUSE:\n\t\t\treturn ohw::InputManager::KEY_PAUSE;\n\t\tcase SDLK_INSERT:\n\t\t\treturn ohw::InputManager::KEY_INSERT;\n\t\tcase SDLK_HOME:\n\t\t\treturn ohw::InputManager::KEY_HOME;\n\n\t\tcase SDLK_UP:\n\t\t\treturn ohw::InputManager::KEY_UP;\n\t\tcase SDLK_DOWN:\n\t\t\treturn ohw::InputManager::KEY_DOWN;\n\t\tcase SDLK_LEFT:\n\t\t\treturn ohw::InputManager::KEY_LEFT;\n\t\tcase SDLK_RIGHT:\n\t\t\treturn ohw::InputManager::KEY_RIGHT;\n\n\t\tcase SDLK_SPACE:\n\t\t\treturn ohw::InputManager::KEY_SPACE;\n\n\t\tcase SDLK_LSHIFT:\n\t\t\treturn ohw::InputManager::KEY_LSHIFT;\n\t\tcase SDLK_RSHIFT:\n\t\t\treturn ohw::InputManager::KEY_RSHIFT;\n\n\t\tcase SDLK_PAGEUP:\n\t\t\treturn ohw::InputManager::KEY_PAGEUP;\n\t\tcase SDLK_PAGEDOWN:\n\t\t\treturn ohw::InputManager::KEY_PAGEDOWN;\n\n\t\tdefault:\n\t\t\treturn -1;\n\t}\n}\n\nstatic ohw::InputManager::MouseButton TranslateSDLMouseButton( int button ) {\n\tswitch ( button ) {\n\t\tcase SDL_BUTTON_LEFT:\n\t\t\treturn ohw::InputManager::MOUSE_BUTTON_LEFT;\n\t\tcase SDL_BUTTON_RIGHT:\n\t\t\treturn ohw::InputManager::MOUSE_BUTTON_RIGHT;\n\t\tcase SDL_BUTTON_MIDDLE:\n\t\t\treturn ohw::InputManager::MOUSE_BUTTON_MIDDLE;\n\t\tdefault:\n\t\t\treturn ohw::InputManager::MOUSE_BUTTON_INVALID;\n\t}\n}\n\nvoid ohw::App::PollEvents() {\n\tSDL_Event event;\n\twhile ( SDL_PollEvent( &event ) ) {\n\t\t// Check if ImGui wants to handle the event first\n\t\tif ( ImGuiImpl_HandleEvent( event ) || myDisplay->HandleEvent( event ) ) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tswitch ( event.type ) {\n\t\t\tdefault:\n\t\t\t\tbreak;\n\n\t\t\tcase SDL_KEYUP:\n\t\t\tcase SDL_KEYDOWN: {\n\t\t\t\tint key = TranslateSDLKey( event.key.keysym.sym );\n\t\t\t\tif ( key != -1 ) {\n\t\t\t\t\tinputManager->SetKeyState( key, ( event.type == SDL_KEYDOWN ) );\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase SDL_TEXTINPUT:\n\t\t\t\tinputManager->AddTextCharacter( event.text.text );\n\t\t\t\tbreak;\n\n\t\t\tcase SDL_MOUSEBUTTONUP:\n\t\t\tcase SDL_MOUSEBUTTONDOWN: {\n\t\t\t\tohw::InputManager::MouseButton button = TranslateSDLMouseButton( event.button.button );\n\t\t\t\tinputManager->SetMouseState( event.motion.x, event.motion.y, button, event.button.state );\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase SDL_MOUSEMOTION: {\n\t\t\t\tinputManager->SetMouseState( event.motion.x, event.motion.y, ohw::InputManager::MOUSE_BUTTON_INVALID, false );\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase SDL_CONTROLLERBUTTONDOWN:\n\t\t\tcase SDL_CONTROLLERBUTTONUP: {\n\t\t\t\tinputManager->SetButtonState( ( unsigned int ) event.cbutton.which, event.cbutton.button, ( event.type == SDL_CONTROLLERBUTTONDOWN ) );\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase SDL_CONTROLLERAXISMOTION:\n#if 0 // TODO: return to this later\n\t\t\t\tif ( event.caxis.axis == SDL_CONTROLLER_AXIS_TRIGGERLEFT && event.caxis.value > 1000 ) {\n\t\t\t\t\tinputManager->SetButtonState( ( unsigned int ) event.caxis.which, INPUT_BUTTON_L2, true );\n\t\t\t\t} else if ( event.caxis.axis == SDL_CONTROLLER_AXIS_TRIGGERLEFT && event.caxis.value <= 1000 ) {\n\t\t\t\t\tinputManager->SetButtonState( ( unsigned int ) event.caxis.which, INPUT_BUTTON_L2, false );\n\t\t\t\t}\n\n\t\t\t\tif ( event.caxis.axis == SDL_CONTROLLER_AXIS_TRIGGERRIGHT && event.caxis.value > 1000 ) {\n\t\t\t\t\tinputManager->SetButtonState( ( unsigned int ) event.caxis.which, INPUT_BUTTON_R2, true );\n\t\t\t\t} else if ( event.caxis.axis == SDL_CONTROLLER_AXIS_TRIGGERRIGHT && event.caxis.value <= 1000 ) {\n\t\t\t\t\tinputManager->SetButtonState( ( unsigned int ) event.caxis.which, INPUT_BUTTON_R2, false );\n\t\t\t\t}\n\n\t\t\t\tinputManager->SetAxisState( event.caxis.which, event.caxis.axis, event.caxis.value );\n#endif\n\t\t\t\tbreak;\n\n\t\t\tcase SDL_QUIT: {\n\t\t\t\tShutdown();\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n}\n\n///////////////////////////////////////////////\n// System\n\nconst char *ohw::App::GetVersionString() {\n\tconst char *version = \"v\"\n\t                      PL_TOSTRING( APP_MAJOR_VERSION ) \".\"\n\t                      PL_TOSTRING( APP_MINOR_VERSION ) \".\"\n\t                      PL_TOSTRING( APP_PATCH_VERSION ) \"-\"\n\t                      GIT_BRANCH \":\" GIT_COMMIT_HASH \"-\" GIT_COMMIT_COUNT;\n\n\treturn version;\n}\n\n[[noreturn]] bool ohw::App::Loop() {\n\twhile ( true ) {\n\t\t// Clear all the profiling timers\n\t\tmyProfilers.clear();\n\n\t\tPollEvents();\n\n\t\tstatic unsigned int nextTick = 0;\n\t\tif ( nextTick == 0 ) {\n\t\t\tnextTick = SDL_GetTicks();\n\t\t}\n\n\t\tunsigned int loops = 0;\n\t\twhile ( SDL_GetTicks() > nextTick && loops < MAX_FRAMESKIP ) {\n\t\t\tnumSysTicks = SDL_GetTicks();\n\t\t\tnumSimTicks++;\n\n\t\t\tgameManager->Tick();\n\t\t\taudioManager->Tick();\n\n\t\t\tlastSysTick = SDL_GetTicks();\n\t\t\tnextTick += SKIP_TICKS;\n\t\t\tloops++;\n\t\t}\n\n\t\tdeltaTime = ( double ) ( SDL_GetTicks() + SKIP_TICKS - nextTick ) / ( double ) ( SKIP_TICKS );\n\n\t\tmyDisplay->Render( deltaTime );\n\t}\n}\n\n///////////////////////////////////////////////////////////////////\n\nconst char *ohw::App::GetClipboardText( void * ) {\n\tstatic char *clipboard = nullptr;\n\tif ( clipboard != nullptr ) {\n\t\tSDL_free( clipboard );\n\t}\n\n\tclipboard = SDL_GetClipboardText();\n\treturn clipboard;\n}\n\nvoid ohw::App::SetClipboardText( void *, const char *text ) {\n\tSDL_SetClipboardText( text );\n}\n\n//////////////////////////////////////////////////////\n// PROFILING\n\nvoid ohw::App::StartProfilingGroup( const char *identifier ) {\n\tmyProfilers.insert( std::pair< std::string, Timer >( identifier, Timer() ) );\n}\n\nvoid ohw::App::EndProfilingGroup( const char *identifier ) {\n\tauto i = myProfilers.find( identifier );\n\tif ( i == myProfilers.end() ) {\n\t\tWarning( \"Attempted to end an invalid timer, \\\"%s\\\"!\\n\", identifier );\n\t\treturn;\n\t}\n\n\ti->second.End();\n}\n\nint main( int argc, char **argv ) {\n#if defined( _DEBUG )\n\tsetvbuf( stdout, nullptr, _IONBF, 0 );\n#endif\n\n\tappInstance = new ohw::App( argc, argv );\n\n\t// Check the mod here, so we can add our VFS paths.\n\tconst char *var = PlGetCommandLineArgumentValue( \"-mod\" );\n\tif ( var == nullptr ) {\n\t\t// otherwise default to base campaign\n\t\tvar = \"how\";\n\t}\n\tappInstance->modManager->Mount( var );\n\n\tappInstance->InitializeConfig();\n\tappInstance->InitializeDisplay();\n\tappInstance->InitializeAudio();\n\tappInstance->InitializeGame();\n\n\tappInstance->Loop();\n}\n"
  },
  {
    "path": "src/engine/App.h",
    "content": "/* OpenHoW\n * Copyright (C) 2017-2020 TalonBrave.info and Others (see CONTRIBUTORS)\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#pragma once\n\n#include <vector>\n#include <list>\n\n#include <plcore/pl.h>\n#include <plcore/pl_string.h>\n#include <plcore/pl_image.h>\n#include <plcore/pl_package.h>\n#include <plcore/pl_console.h>\n\n#include <plmodel/plm.h>\n\n#include <plgraphics/plg.h>\n\n#define SDL_MAIN_HANDLED\n#include <SDL2/SDL.h>\n\n#include \"Utilities.h\"\n#include \"Timer.h\"\n#include \"Console.h\"\n\n#include \"graphics/Display.h\"\n\n#define APP_NAME    \"OpenHoW\"\n\n#define APP_MAJOR_VERSION    0\n#define APP_MINOR_VERSION    5\n#define APP_PATCH_VERSION    0\n\n#define TICKS_PER_SECOND    25\n#define SKIP_TICKS          (1000 / TICKS_PER_SECOND)\n#define MAX_FRAMESKIP       5\n\n#include \"ModManager.h\"\n#include \"InputManager.h\"\n#include \"ResourceManager.h\"\n#include \"GameManager.h\"\n#include \"AudioManager.h\"\n\nnamespace ohw {\n\tclass App {\n\tpublic:\n\t\tApp( int argc, char **argv );\n\n\t\tvoid Shutdown();\n\n\t\tenum class MBErrorLevel {\n\t\t\tINFORMATION_MSG,\n\t\t\tWARNING_MSG,\n\t\t\tERROR_MSG,\n\t\t};\n\t\tvoid DisplayMessageBox( MBErrorLevel level, const char *message, ... );\n\n\t\tinline unsigned int GetTicks() const {\n\t\t\treturn numSysTicks;\n\t\t}\n\t\tinline unsigned int GetSimulationTicks() const {\n\t\t\treturn numSimTicks;\n\t\t}\n\t\tinline double GetDeltaTime() const {\n\t\t\treturn deltaTime;\n\t\t}\n\n\t\tvoid InitializeConfig();\n\t\tvoid InitializeDisplay();\n\t\tvoid InitializeAudio();\n\t\tvoid InitializeGame();\n\n\t\tinline Display *GetDisplay() { return myDisplay; }\n\n\t\tstruct DisplayPreset {\n\t\t\tDisplayPreset( int w, int h, int r ) : width( w ), height( h ), refresh( r ) {}\n\n\t\t\tint width;\n\t\t\tint height;\n\t\t\tint refresh;\n\t\t};\n\t\ttypedef std::vector< DisplayPreset > DisplayPresetVector;\n\t\tinline const DisplayPresetVector *GetDisplayPresets() const {\n\t\t\treturn &myDisplayPresets;\n\t\t}\n\n\t\tstatic void SetClipboardText( void *, const char *text );\n\t\tstatic const char *GetClipboardText( void * );\n\n\t\t///////////////////////////////////////////////\n\t\t// Events\n\tpublic:\n\t\tvoid PollEvents();\n\n\t\t///////////////////////////////////////////////\n\t\t// System\n\n\t\tstatic const char *GetVersionString();\n\n\t\t[[noreturn]] bool Loop();\n\n\t\tstatic void *MAlloc( size_t size, bool abortOnFail );\n\t\tstatic void *CAlloc( size_t num, size_t size, bool abortOnFail );\n\n\t\tInputManager *inputManager;\n\t\tModManager *modManager;\n\t\tGameManager *gameManager;\n\t\tAudioManager *audioManager;\n\t\tResourceManager *resourceManager;\n\n\t\t//////////////////////////////////////////////////////\n\t\t// PROFILING\n\n\t\tvoid StartProfilingGroup( const char *identifier );\n\t\tvoid EndProfilingGroup( const char *identifier );\n\n\t\ttypedef std::map< std::string, Timer > ProfilerMap;\n\t\tconst ProfilerMap &GetProfilers() const { return myProfilers; }\n\n\tprivate:\n\t\tDisplay *myDisplay;\n\n\t\tstd::vector< DisplayPreset > myDisplayPresets;\n\n\t\tdouble deltaTime;\n\t\tunsigned int numSysTicks{ 0 };\n\t\tunsigned int lastSysTick{ 0 };\n\t\tunsigned int numSimTicks{ 0 };\n\n\t\tProfilerMap myProfilers;\n\t};\n\n\tApp *GetApp();\n}\n\n#if defined( DEBUG_BUILD )\n#   define START_MEASURE() ohw::GetApp()->StartProfilingGroup( __PRETTY_FUNCTION__ )\n#   define END_MEASURE()   ohw::GetApp()->EndProfilingGroup( __PRETTY_FUNCTION__ )\n#else\n#   define START_MEASURE()\n#   define END_MEASURE()\n#endif\n"
  },
  {
    "path": "src/engine/CMakeLists.txt",
    "content": "#[[\nThis is free and unencumbered software released into the public domain.\n\nAnyone is free to copy, modify, publish, use, compile, sell, or\ndistribute this software, either in source code form or as a compiled\nbinary, for any purpose, commercial or non-commercial, and by any\nmeans.\n\nIn jurisdictions that recognize copyright laws, the author or authors\nof this software dedicate any and all copyright interest in the\nsoftware to the public domain. We make this dedication for the benefit\nof the public at large and to the detriment of our heirs and\nsuccessors. We intend this dedication to be an overt act of\nrelinquishment in perpetuity of all present and future rights to this\nsoftware under copyright law.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR\nOTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,\nARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\nOTHER DEALINGS IN THE SOFTWARE.\n\nFor more information, please refer to <http://unlicense.org>\n]]\n\nproject(OpenHoW)\n\nadd_definitions(\n        \"-DIMGUI_IMPL_OPENGL_LOADER_GLEW\"   # Required for OpenGL3.x imgui setup\n)\n\nfile(GLOB OPENHOW_SOURCE_FILES\n        *.cpp *.c\n        *.h\n\n        script/duktape-2.2.0/*.c\n        script/duktape-2.2.0/*.h\n\n        audio/AudioManager.cpp\n\n        # Physics Sub-System\n        physics/PhysicsInterface.cpp\n        physics/PhysicsInterface.h\n\n        editor/*.*\n        graphics/*.*\n        script/*.*\n        game/*.*\n        loaders/*.*\n\n        Utilities.cpp\n\n        ################## ImGui\n\n        ../3rdparty/imgui/imgui.cpp\n        ../3rdparty/imgui/imgui_draw.cpp\n        ../3rdparty/imgui/imgui_widgets.cpp\n        ../3rdparty/imgui/imgui_demo.cpp\n        ../3rdparty/platform/extras/imgui_renderer.cpp\n        )\n\nadd_executable(OpenHoW ${OPENHOW_SOURCE_FILES} App.cpp App.h)\n\ntarget_include_directories(OpenHoW PRIVATE\n        ./\n        ./audio/\n        ./editor/\n        ./game/\n        ./graphics/\n        ./loaders/\n        ./physics/\n        ./script/)\ntarget_link_libraries(OpenHoW plcore plgraphics plmodel)\n\nif (WIN32)\n    add_dependencies(OpenHoW OpenAL)\n\n    target_include_directories(OpenHoW PRIVATE\n            ../3rdparty/SDL2/include/\n            ../3rdparty/openal-soft/include/\n            # below is hack to get imgui compiled on Windows with GLEW.\n            ../3rdparty/platform/plugins/driver_opengl/3rdparty/glew-2.2.0/include/\n            )\n    target_link_directories(OpenHoW PRIVATE\n            ../3rdparty/SDL2/lib/\n            ../3rdparty/openal-soft/lib/\n            ../../lib/\n            )\n    target_link_options(OpenHoW PRIVATE -mwindows)\n    target_link_libraries(OpenHoW -Wl,-Bstatic SDL2 OpenAL32 stdc++ winpthread -Wl,-Bdynamic -static-libstdc++ -static-libgcc\n            # Window Libraries\n            Version SetupAPI Winmm Imm32\n            glew_s)\nelseif (APPLE)\n    target_include_directories(OpenHoW PRIVATE\n            ../3rdparty/platform/plugins/driver_opengl/3rdparty/glew-2.2.0/include/)\n    target_link_libraries(OpenHoW OpenAL SDL2)\nelseif (UNIX)\n    target_link_libraries(OpenHoW openal SDL2 pthread dl)\nelse ()\n    message(\"Unsupported platform!\")\nendif ()\n\ntarget_compile_options(OpenHoW PUBLIC -fPIC)\ntarget_include_directories(OpenHoW PUBLIC ../3rdparty/imgui/ script/duktape-2.2.0/)\n"
  },
  {
    "path": "src/engine/Console.cpp",
    "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// Copyright © 2017-2022 TalonBrave.info and Others (see CONTRIBUTORS)\n\n#include \"App.h\"\n#include \"Language.h\"\n#include \"config.h\"\n\nusing namespace ohw;\n\nunsigned int ohw::LOG_LEVEL_DEFAULT = 0;\nunsigned int ohw::LOG_LEVEL_WARNING = 0;\nunsigned int ohw::LOG_LEVEL_ERROR = 0;\nunsigned int ohw::LOG_LEVEL_DEBUG = 0;\n\n/************************************************************/\n\n#define check_args( num )                                                               \\\n\tif ( argc < ( num ) ) {                                                             \\\n\t\tWarning( \"invalid number of arguments (%d < %d), ignoring!\\n\", argc, ( num ) ); \\\n\t\treturn;                                                                         \\\n\t}\n\n#if 0\nstatic void FrontendModeCommand(unsigned int argc, char* argv[]) {\n  check_args(2);\n\n  int mode = atoi(argv[1]);\n  if (mode < 0) {\n\tLogWarn(\"invalid frontend mode, \\\"%d\\\", specified!\\n\", mode);\n\treturn;\n  }\n\n  FrontEnd_SetState((unsigned int) mode);\n}\n#endif\n\nstatic void OpenCommand( unsigned int argc, char *argv[] ) {\n\tcheck_args( 2 );\n\n\tconst char *fpath = argv[ 1 ];\n\tif ( fpath == nullptr ) {\n\t\tWarning( \"invalid argument provided, ignoring!\\n\" );\n\t\treturn;\n\t}\n\n\tenum {\n\t\tTYPE_UNKNOWN,\n\t\tTYPE_MODEL,\n\t\tTYPE_PARTICLE,\n\t\tTYPE_MAP,\n\t\tTYPE_SOUND,\n\n\t\tMAX_TYPES\n\t};\n\tunsigned int type = TYPE_UNKNOWN;\n\n\t/* now we just need to figure out what kind of file it is */\n\tconst char *ext = PlGetFileExtension( fpath );\n\tif ( ext != nullptr ) {\n\t\tif ( pl_strncasecmp( ext, \"vtx\", 3 ) == 0 ||\n\t\t     pl_strncasecmp( ext, \"fac\", 3 ) == 0 ||\n\t\t     pl_strncasecmp( ext, \"no2\", 3 ) == 0 ) {\n\t\t\ttype = TYPE_MODEL;\n\t\t} else if ( pl_strncasecmp( ext, \"pmg\", 3 ) == 0 ||\n\t\t            pl_strncasecmp( ext, \"pog\", 3 ) == 0 ||\n\t\t            pl_strncasecmp( ext, \"map\", 3 ) == 0 ) {\n\t\t\ttype = TYPE_MAP;\n\t\t}\n\t}\n\n\tswitch ( type ) {\n\t\tdefault:\n\t\t\tWarning( \"unknown filetype, ignoring!\\n\" );\n\t\t\tbreak;\n\n\t\tcase TYPE_MAP: {\n\t\t\tchar map_name[ 32 ];\n\t\t\tsnprintf( map_name, sizeof( map_name ), \"%s\", PlGetFileName( fpath ) - 4 );\n\t\t\tif ( *map_name == '\\0' ) {\n\t\t\t\tWarning( \"invalid map name, ignoring!\\n\" );\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tu_assert( 0 );\n\t\t\t//Map_Load(map_name, MAP_MODE_EDITOR);\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\n/************************************************************/\n\n// todo: kill all these global cvars - use variables instead w/ reference passed into RegisterConsoleVariable\n\nPLConsoleVariable *cv_imgui = nullptr;\nPLConsoleVariable *cv_debug_skeleton = nullptr;\nPLConsoleVariable *cv_debug_bounds = nullptr;\n\nPLConsoleVariable *cv_camera_fov = nullptr;\nPLConsoleVariable *cv_camera_near = nullptr;\nPLConsoleVariable *cv_camera_far = nullptr;\n\nPLConsoleVariable *cv_display_width = nullptr;\nPLConsoleVariable *cv_display_height = nullptr;\nPLConsoleVariable *cv_display_fullscreen = nullptr;\nPLConsoleVariable *cv_display_use_window_aspect = nullptr;\nPLConsoleVariable *cv_display_ui_scale = nullptr;\nPLConsoleVariable *cv_display_vsync = nullptr;\n\nPLConsoleVariable *cv_graphics_cull = nullptr;\nPLConsoleVariable *cv_GraphicsDrawTerrain = nullptr;\nPLConsoleVariable *cv_graphics_draw_sprites = nullptr;\nPLConsoleVariable *cv_graphics_draw_audio_sources = nullptr;\nPLConsoleVariable *cv_graphics_texture_filter = nullptr;\nPLConsoleVariable *cv_graphics_alpha_to_coverage = nullptr;\nPLConsoleVariable *cv_graphics_debug_normals = nullptr;\n\nPLConsoleVariable *cv_audio_volume = nullptr;\nPLConsoleVariable *cv_audio_volume_music = nullptr;\n\nvoid Console_Initialize() {\n\tcv_imgui = PlRegisterConsoleVariable( \"imgui\", \"Enable/disable ImGui overlay.\", \"1\", PL_VAR_BOOL, nullptr, nullptr, false );\n\tcv_debug_skeleton = PlRegisterConsoleVariable( \"debug_skeleton\", \"display pig skeletons\", \"0\", PL_VAR_BOOL, nullptr, nullptr, false );\n\tcv_debug_bounds = PlRegisterConsoleVariable( \"debug_bounds\", \"Display bounding volumes of all objects.\", \"0\", PL_VAR_BOOL, nullptr, nullptr, true );\n\n\tPlRegisterConsoleVariable( \"game_language\", \"Set the language\", \"eng\", PL_VAR_STRING, nullptr, &LanguageManager::SetLanguageCallback, true );\n\n\tPlRegisterConsoleVariable( \"camera_mode\", \"0 = default, 1 = debug\", \"0\", PL_VAR_I32, nullptr, nullptr, true );\n\tcv_camera_fov = PlRegisterConsoleVariable( \"camera_fov\", \"field of view\", \"75\", PL_VAR_F32, nullptr, nullptr, true );\n\tcv_camera_near = PlRegisterConsoleVariable( \"camera_near\", \"\", \"0.1\", PL_VAR_F32, nullptr, nullptr, true );\n\tcv_camera_far = PlRegisterConsoleVariable( \"camera_far\", \"\", \"999999\", PL_VAR_F32, nullptr, nullptr, true );\n\n\tcv_display_width = PlRegisterConsoleVariable( \"display_width\", \"\", \"1024\", PL_VAR_I32, nullptr, nullptr, true );\n\tcv_display_height = PlRegisterConsoleVariable( \"display_height\", \"\", \"768\", PL_VAR_I32, nullptr, nullptr, true );\n\tcv_display_fullscreen = PlRegisterConsoleVariable( \"display_fullscreen\", \"\", \"true\", PL_VAR_BOOL, nullptr, nullptr, true );\n\tcv_display_use_window_aspect = PlRegisterConsoleVariable( \"display_use_window_aspect\", \"\", \"false\", PL_VAR_BOOL, nullptr, nullptr, true );\n\tcv_display_ui_scale = PlRegisterConsoleVariable( \"display_ui_scale\", \"0 = automatic scale\", \"0\", PL_VAR_I32, nullptr, nullptr, true );\n\tcv_display_vsync = PlRegisterConsoleVariable(\n\t        \"display_vsync\", \"Enable / Disable vertical sync\", \"false\", PL_VAR_BOOL, nullptr, []( const PLConsoleVariable *variable ) {\n\t\t        Display *display = GetApp()->GetDisplay();\n\t\t        if ( display == nullptr ) {\n\t\t\t        return;\n\t\t        }\n\n\t\t        display->SetSwapInterval( variable->b_value ? 1 : 0 );\n\t        },\n\t        true );\n\n\tcv_graphics_cull = PlRegisterConsoleVariable( \"graphics_cull\", \"Toggles culling of visible objects.\", \"true\", PL_VAR_BOOL, nullptr, nullptr, true );\n\tPlRegisterConsoleVariable( \"graphics_draw_terrain\", \"Toggles rendering of the terrain.\", \"true\", PL_VAR_BOOL, nullptr, nullptr, true );\n\tcv_graphics_draw_sprites = PlRegisterConsoleVariable( \"graphics_draw_sprites\", \"Toggles rendering of sprites.\", \"true\", PL_VAR_BOOL, nullptr, nullptr, true );\n\tcv_graphics_draw_audio_sources = PlRegisterConsoleVariable( \"graphics_draw_audio_sources\", \"toggles rendering of audio sources\", \"false\", PL_VAR_BOOL, nullptr, nullptr, true );\n\tcv_graphics_texture_filter = PlRegisterConsoleVariable( \"graphics_texture_filter\", \"Filter level/model textures?\", \"true\", PL_VAR_BOOL, nullptr, nullptr, true );\n\tcv_graphics_alpha_to_coverage = PlRegisterConsoleVariable( \"graphics_alpha_to_coverage\", \"Enable/disable alpha-to-coverage\", \"true\", PL_VAR_BOOL, nullptr, nullptr, true );\n\tcv_graphics_debug_normals = PlRegisterConsoleVariable( \"graphics_debug_normals\", \"Forces normals to be displayed\", \"false\", PL_VAR_BOOL, nullptr, nullptr, true );\n\n\tcv_audio_volume = PlRegisterConsoleVariable( \"audio_volume\", \"set global audio volume\", \"1\", PL_VAR_F32, nullptr, nullptr, true );\n\tPlRegisterConsoleVariable( \"audio_volume_sfx\", \"set sfx audio volume\", \"1\", PL_VAR_F32, nullptr, nullptr, true );\n\tcv_audio_volume_music = PlRegisterConsoleVariable( \"audio_volume_music\", \"Set the music audio volume\", \"1\", PL_VAR_F32, nullptr, nullptr, true );\n\tPlRegisterConsoleVariable( \"audio_mode\", \"0 = mono, 1 = stereo\", \"1\", PL_VAR_I32, nullptr, nullptr, true );\n\tPlRegisterConsoleVariable( \"audio_voices\", \"enable/disable pig voices\", \"true\", PL_VAR_BOOL, nullptr, nullptr, true );\n\n\tPlRegisterConsoleCommand( \"open\", \"Opens the specified file\", 1, OpenCommand );\n\n\tPlRegisterConsoleCommand( \"quit\", \"Closes the game\", 0, []( unsigned int argc, char *argv[] ) {\n\t\tGetApp()->Shutdown();\n\t} );\n\n\tPlRegisterConsoleCommand( \"loadConfig\", \"Loads the specified config\", 1, []( unsigned int argc, char **argv ) {\n\t\tConfig_Load( argv[ 1 ] );\n\t} );\n\tPlRegisterConsoleCommand( \"saveConfig\", \"Save current config\", 0, []( unsigned int argc, char **argv ) {\n\t\tconst char *name = Config_GetUserConfigPath();\n\t\tif ( argc > 1 && argv[ 1 ] != nullptr ) {\n\t\t\tname = argv[ 1 ];\n\t\t}\n\n\t\tConfig_Save( name );\n\t} );\n\n\tPlRegisterConsoleCommand( \"disconnect\", \"Disconnects and unloads current map\", 0, []( unsigned int argc, char *argv[] ) { GetApp()->gameManager->EndMode(); } );\n\t//PlRegisterConsoleCommand( \"clear\", ClearConsoleOutputBuffer, \"Clears the console output buffer\" );\n\t//PlRegisterConsoleCommand( \"cls\", ClearConsoleOutputBuffer, \"Clears the console output buffer\" );\n\n\t//ClearConsoleOutputBuffer( 0, nullptr );\n\t//plSetConsoleOutputCallback( ConsoleBufferUpdate );\n}\n"
  },
  {
    "path": "src/engine/Console.h",
    "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// Copyright © 2017-2022 TalonBrave.info and Others (see CONTRIBUTORS)\n\n#pragma once\n\nnamespace ohw {\n\textern unsigned int LOG_LEVEL_DEFAULT;\n\textern unsigned int LOG_LEVEL_WARNING;\n\textern unsigned int LOG_LEVEL_ERROR;\n\textern unsigned int LOG_LEVEL_DEBUG;\n}\n\n#define CMSGPrintWFunction( LEVEL, FORMAT, ... ) PlLogMessage((LEVEL), \"(%s) \" FORMAT, PL_FUNCTION, ## __VA_ARGS__)\n\n#if !defined( NDEBUG )\n#   define DebugMsg( ... ) CMSGPrintWFunction(ohw::LOG_LEVEL_DEBUG, __VA_ARGS__)\n#else\n#   define DebugMsg( ... )\n#endif\n\n#define Print( ... )    CMSGPrintWFunction(ohw::LOG_LEVEL_DEFAULT, __VA_ARGS__)\n#define Warning( ... )  CMSGPrintWFunction(ohw::LOG_LEVEL_WARNING, __VA_ARGS__)\n#define Error( ... ) \\\n        CMSGPrintWFunction(ohw::LOG_LEVEL_ERROR, __VA_ARGS__);                               \\\n        ohw::GetApp()->DisplayMessageBox( ohw::App::MBErrorLevel::ERROR_MSG, __VA_ARGS__ ); \\\n        ohw::GetApp()->Shutdown()\n\n/************************************************************/\n\nextern PLConsoleVariable *cv_imgui;\nextern PLConsoleVariable *cv_debug_skeleton;\nextern PLConsoleVariable *cv_debug_bounds;\n\nextern PLConsoleVariable *cv_camera_fov;\nextern PLConsoleVariable *cv_camera_near;\nextern PLConsoleVariable *cv_camera_far;\n\nextern PLConsoleVariable *cv_display_width;\nextern PLConsoleVariable *cv_display_height;\nextern PLConsoleVariable *cv_display_fullscreen;\nextern PLConsoleVariable *cv_display_use_window_aspect;\nextern PLConsoleVariable *cv_display_ui_scale;\nextern PLConsoleVariable *cv_display_vsync;\n\nextern PLConsoleVariable *cv_graphics_cull;\nextern PLConsoleVariable *cv_GraphicsDrawTerrain;\nextern PLConsoleVariable *cv_graphics_draw_sprites;\nextern PLConsoleVariable *cv_graphics_draw_audio_sources;\nextern PLConsoleVariable *cv_graphics_texture_filter;\nextern PLConsoleVariable *cv_graphics_alpha_to_coverage;\nextern PLConsoleVariable *cv_graphics_debug_normals;\n\nextern PLConsoleVariable *cv_audio_volume;\nextern PLConsoleVariable *cv_audio_volume_music;\n\n/************************************************************/\n\nvoid Console_Initialize();\n"
  },
  {
    "path": "src/engine/InputManager.cpp",
    "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// Copyright © 2017-2022 TalonBrave.info and Others (see CONTRIBUTORS)\n\n#include <SDL2/SDL_joystick.h>\n#include <SDL2/SDL_gamecontroller.h>\n#include <SDL2/SDL_events.h>\n\n#include \"App.h\"\n\nohw::InputManager::InputManager() {\n\t// Setup the default bindings\n\n\tmyBindings[ ACTION_MOVE_FORWARD ].Bind( KEY_UP );\n\tmyBindings[ ACTION_MOVE_FORWARD ].Bind( 'w' );\n\tmyBindings[ ACTION_MOVE_FORWARD ].Bind( SDL_CONTROLLER_BUTTON_DPAD_DOWN );\n\n\tmyBindings[ ACTION_MOVE_BACKWARD ].Bind( KEY_DOWN );\n\tmyBindings[ ACTION_MOVE_BACKWARD ].Bind( 's' );\n\tmyBindings[ ACTION_MOVE_BACKWARD ].Bind( SDL_CONTROLLER_BUTTON_DPAD_DOWN );\n\n\tmyBindings[ ACTION_TURN_LEFT ].Bind( KEY_LEFT );\n\tmyBindings[ ACTION_TURN_LEFT ].Bind( 'a' );\n\tmyBindings[ ACTION_TURN_LEFT ].Bind( SDL_CONTROLLER_BUTTON_DPAD_LEFT );\n\n\tmyBindings[ ACTION_TURN_RIGHT ].Bind( KEY_RIGHT );\n\tmyBindings[ ACTION_TURN_RIGHT ].Bind( 'd' );\n\tmyBindings[ ACTION_TURN_RIGHT ].Bind( SDL_CONTROLLER_BUTTON_DPAD_RIGHT );\n\n\tmyBindings[ ACTION_JUMP ].Bind( KEY_SPACE );\n\tmyBindings[ ACTION_JUMP ].Bind( SDL_CONTROLLER_BUTTON_A );\n\n\tmyBindings[ ACTION_SELECT ].Bind( KEY_TAB );\n\tmyBindings[ ACTION_SELECT ].Bind( SDL_CONTROLLER_BUTTON_B );\n\n\tmyBindings[ ACTION_AIM ].Bind( KEY_TAB );\n\tmyBindings[ ACTION_AIM ].Bind( SDL_CONTROLLER_BUTTON_LEFTSHOULDER );\n\n\tmyBindings[ ACTION_AIM_UP ].Bind( KEY_PAGEUP );\n\tmyBindings[ ACTION_AIM_UP ].Bind( 'a' );\n\tmyBindings[ ACTION_AIM_UP ].Bind( SDL_CONTROLLER_BUTTON_RIGHTSHOULDER );\n\n\tmyBindings[ ACTION_AIM_DOWN ].Bind( KEY_PAGEDOWN );\n\tmyBindings[ ACTION_AIM_UP ].Bind( 'z' );\n\n\tmyBindings[ ACTION_PAUSE ].Bind( KEY_ESCAPE );\n\tmyBindings[ ACTION_PAUSE ].Bind( SDL_CONTROLLER_BUTTON_START );\n\n\tResetStates();\n}\n\nohw::InputManager::~InputManager() {\n\tmyControllers.clear();\n}\n\nvoid ohw::InputManager::ResetStates() {\n\tmemset( myKeyStates, 0, MAX_KEYS );\n\tmemset( myMouseButtonStates, 0, MAX_MOUSE_BUTTONS );\n}\n\nvoid ohw::InputManager::SetKeyboardFocusCallback( void (*Callback)( int, bool ) ) {\n\tInputFocusCallback = Callback;\n}\n\nvoid ohw::InputManager::SetTextFocusCallback( void (*Callback)( const char * ) ) {\n\tInputTextCallback = Callback;\n}\n\nbool ohw::InputManager::GetKeyState( int input ) {\n\tu_assert( input < MAX_KEYS );\n\treturn myKeyStates[ input ];\n}\n\nbool ohw::InputManager::GetJoystickState( unsigned int slot, JoystickAxis input, float *x, float *y ) {\n\tController *controller = GetControllerForSlot( slot );\n\tif ( controller == nullptr ) {\n\t\treturn false;\n\t}\n\n\t*x = controller->axisStates[ input ].x;\n\t*y = controller->axisStates[ input ].y;\n\treturn true;\n}\n\nbool ohw::InputManager::GetButtonState( unsigned int slot, SDL_GameControllerButton input ) {\n\tController *controller = GetControllerForSlot( slot );\n\tif ( controller == nullptr ) {\n\t\treturn false;\n\t}\n\n\treturn controller->buttonStates[ input ];\n}\n\nbool ohw::InputManager::GetActionState( unsigned int slot, Action input ) {\n\tfor( auto &i : myBindings[ input ].keys ) {\n\t\tif( GetKeyState( i ) ) {\n\t\t\treturn true;\n\t\t}\n\t}\n\n\tif( !myControllers.empty() ) {\n\t\tfor ( auto &i : myBindings[ input ].buttons ) {\n\t\t\tif ( GetButtonState( slot, i ) ) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn false;\n}\n\nvoid ohw::InputManager::SetAxisState( unsigned int slot, JoystickAxis input, const hei::Vector2 &status ) {\n\tController *controller = GetControllerForSlot( slot );\n\tif ( controller == nullptr ) {\n\t\treturn;\n\t}\n\n\t// TODO: handle deadzones!!!!\n\n\tcontroller->axisStates[ input ] = status / 100.0f;\n}\n\nvoid ohw::InputManager::SetButtonState( unsigned int slot, unsigned char input, bool status ) {\n\tif ( input >= SDL_CONTROLLER_BUTTON_MAX ) {\n\t\tWarning( \"Unhandled controller button %d!\\n\", input );\n\t\treturn;\n\t}\n\n\tController *controller = GetControllerForSlot( slot );\n\tif ( controller == nullptr ) {\n\t\treturn;\n\t}\n\n\tcontroller->buttonStates[ input ] = status;\n}\n\nvoid ohw::InputManager::SetKeyState( int input, bool status ) {\n\tu_assert( input <= MAX_KEYS );\n\tif ( InputFocusCallback != nullptr ) {\n\t\tInputFocusCallback( input, status );\n\t}\n\n\tmyKeyStates[ input ] = status;\n}\n\nvoid ohw::InputManager::SetMouseState( int x, int y, MouseButton input, bool status ) {\n\tmyMouseCoords = hei::Vector2( x, y );\n\n\tif ( input != MOUSE_BUTTON_INVALID ) {\n\t\tmyMouseButtonStates[ input ] = status;\n\t}\n}\n\nvoid ohw::InputManager::AddTextCharacter( const char *c ) {\n\tif ( InputTextCallback == nullptr ) {\n\t\treturn;\n\t}\n\n\tInputTextCallback( c );\n}\n\nvoid ohw::InputManager::SetupControllers() {\n\tSDL_GameControllerEventState( SDL_ENABLE );\n\n\tint numJoysticks = SDL_NumJoysticks();\n\tif ( numJoysticks < 0 ) {\n\t\tWarning( \"%s\\n\", SDL_GetError() );\n\t\treturn;\n\t}\n\n\tif ( SDL_GameControllerAddMappingsFromFile( \"gamecontrollerdb.txt\" ) == -1 ) {\n\t\tWarning( \"%s\\n\", SDL_GetError() );\n\t\treturn;\n\t}\n\n\tfor( int i = 0; i < numJoysticks; ++i ) {\n\t\tif ( !SDL_IsGameController( i ) ) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tmyControllers.push_back( Controller( i ) );\n\t}\n}\n\n///////////////////////////////////////////\n// Controller\n\nohw::InputManager::Controller::Controller( unsigned int slot ) : inputSlot( slot ) {\n\tsdlGameController = SDL_GameControllerOpen( slot );\n\tif( sdlGameController == nullptr ) {\n\t\tWarning( \"Failed to open controller %d!\\nSDL: %s\\n\", SDL_GetError() );\n\t\treturn;\n\t}\n\n\tname = SDL_GameControllerNameForIndex( slot );\n\tif( name.empty() ) {\n\t\tname = \"unknown\";\n\t}\n\n\tPrint( \"Controller %s\\n\", name.c_str() );\n}\n\nohw::InputManager::Controller::~Controller() {\n\tif( sdlGameController != nullptr ) {\n\t\tSDL_GameControllerClose( static_cast< SDL_GameController *>( sdlGameController ) );\n\t}\n}\n"
  },
  {
    "path": "src/engine/InputManager.h",
    "content": "/* OpenHoW\n * Copyright (C) 2017-2020 TalonBrave.info and Others (see CONTRIBUTORS)\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#pragma once\n\nnamespace ohw {\n\tclass InputManager {\n\tpublic:\n\t\tInputManager();\n\t\t~InputManager();\n\n\t\tenum Key {\n\t\t\tKEY_INVALID = -1,\n\t\t\tKEY_TAB = 9,\n\t\t\tKEY_F1 = 128,\n\t\t\tKEY_F2,\n\t\t\tKEY_F3,\n\t\t\tKEY_F4,\n\t\t\tKEY_F5,\n\t\t\tKEY_F6,\n\t\t\tKEY_F7,\n\t\t\tKEY_F8,\n\t\t\tKEY_F9,\n\t\t\tKEY_F10,\n\t\t\tKEY_F11,\n\t\t\tKEY_F12,\n\t\t\tKEY_PAUSE,\n\t\t\tKEY_INSERT,\n\t\t\tKEY_HOME,\n\t\t\tKEY_UP,\n\t\t\tKEY_DOWN,\n\t\t\tKEY_LEFT,\n\t\t\tKEY_RIGHT,\n\t\t\tKEY_SPACE,\n\t\t\tKEY_PAGEUP,\n\t\t\tKEY_PAGEDOWN,\n\t\t\tKEY_LCTRL,\n\t\t\tKEY_LSHIFT,\n\t\t\tKEY_LALT,\n\t\t\tKEY_RCTRL,\n\t\t\tKEY_RSHIFT,\n\t\t\tKEY_RALT,\n\t\t\tKEY_ESCAPE,\n\t\t\tMAX_KEYS\n\t\t};\n\n\t\tenum Action {\n\t\t\tACTION_INVALID = -1,\n\t\t\tACTION_MOVE_FORWARD,\n\t\t\tACTION_MOVE_BACKWARD,\n\t\t\tACTION_TURN_LEFT,\n\t\t\tACTION_TURN_RIGHT,\n\t\t\tACTION_AIM,\n\t\t\tACTION_AIM_UP,\n\t\t\tACTION_AIM_DOWN,\n\t\t\tACTION_JUMP,\n\t\t\tACTION_PAUSE,\n\t\t\tACTION_FIRE,\n\t\t\tACTION_SELECT,\n\t\t\tACTION_DESELECT,\n\t\t\tMAX_ACTIONS\n\t\t};\n\n\t\tenum JoystickAxis {\n\t\t\tJOYSTICK_AXIS_INVALID = -1,\n\t\t\tJOYSTICK_AXIS_LEFT_STICK,\n\t\t\tJOYSTICK_AXIS_RIGHT_STICK,\n\t\t\tJOYSTICK_AXIS_LEFT_TRIGGER,\n\t\t\tJOYSTICK_AXIS_RIGHT_TRIGGER,\n\t\t\tMAX_JOYSTICK_AXIS\n\t\t};\n\n\t\tenum MouseButton {\n\t\t\tMOUSE_BUTTON_INVALID = -1,\n\t\t\tMOUSE_BUTTON_LEFT,\n\t\t\tMOUSE_BUTTON_RIGHT,\n\t\t\tMOUSE_BUTTON_MIDDLE,\n\t\t\tMAX_MOUSE_BUTTONS\n\t\t};\n\n\t\tvoid ResetStates();\n\n\t\tvoid SetKeyboardFocusCallback( void (*Callback)( int input, bool isPressed ) );\n\t\tvoid SetTextFocusCallback( void (*Callback)( const char *c ) );\n\n\t\tbool GetKeyState( int input );\n\t\tbool GetJoystickState( unsigned int slot, JoystickAxis input, float *x, float *y );\n\t\tbool GetButtonState( unsigned int slot, SDL_GameControllerButton input );\n\t\tbool GetActionState( unsigned int slot, Action input );\n\n\t\tvoid SetAxisState( unsigned int slot, JoystickAxis input, const hei::Vector2 &status );\n\t\tvoid SetButtonState( unsigned int slot, unsigned char input, bool status );\n\t\tvoid SetKeyState( int input, bool status );\n\t\tvoid SetMouseState( int x, int y, MouseButton input, bool status );\n\n\t\tvoid AddTextCharacter( const char *c );\n\n\t\tvoid SetupControllers();\n\n\tprotected:\n\tprivate:\n\t\tvoid (*InputFocusCallback)( int input, bool status ){ nullptr };\n\t\tvoid (*InputTextCallback)( const char *c ){ nullptr };\n\n\t\tPLVector2 myMouseCoords;\n\t\tbool myMouseButtonStates[MAX_MOUSE_BUTTONS];\n\t\tbool myKeyStates[MAX_KEYS];\n\n\t\tstruct ActionBinding {\n\t\t\tActionBinding() {}\n\n\t\t\tinline void Bind( int k ) {\n\t\t\t\t// Check it's not been bound already\n\t\t\t\tauto i = std::find( keys.begin(), keys.end(), k );\n\t\t\t\tif ( i != keys.end() ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tkeys.push_back( k );\n\t\t\t}\n\n\t\t\tinline void Bind( SDL_GameControllerButton b ) {\n\t\t\t\t// Check it's not been bound already\n\t\t\t\tauto i = std::find( buttons.begin(), buttons.end(), b );\n\t\t\t\tif ( i != buttons.end() ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tbuttons.push_back( b );\n\t\t\t}\n\n\t\t\tinline void Bind( MouseButton b ) {\n\t\t\t\t// Check it's not been bound already\n\t\t\t\tauto i = std::find( mouseButtons.begin(), mouseButtons.end(), b );\n\t\t\t\tif ( i != mouseButtons.end() ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tmouseButtons.push_back( b );\n\t\t\t}\n\n\t\t\tstd::vector< int > keys;\n\t\t\tstd::vector< SDL_GameControllerButton > buttons;\n\t\t\tstd::vector< MouseButton > mouseButtons;\n\t\t};\n\n\t\tActionBinding myBindings[MAX_ACTIONS];\n\n\t\tstruct Controller {\n\t\t\tController( unsigned int slot );\n\t\t\t~Controller();\n\n\t\t\tbool buttonStates[SDL_CONTROLLER_BUTTON_MAX];\n\t\t\tPLVector2 axisStates[MAX_JOYSTICK_AXIS];\n\n\t\t\tstd::string name;\n\t\t\tunsigned int inputSlot;\n\n\t\t\tvoid *sdlGameController{ nullptr };\n\t\t};\n\n\t\tstd::vector< Controller > myControllers;\n\n\t\tinline Controller *GetControllerForSlot( unsigned int slot ) {\n\t\t\tif ( myControllers.empty() ) {\n\t\t\t\treturn nullptr;\n\t\t\t}\n\n\t\t\t// If the controller doesn't exist, fallback to the first\n\t\t\tif ( slot >= myControllers.size() ) {\n\t\t\t\tslot = 0;\n\t\t\t}\n\n\t\t\treturn &myControllers[ slot ];\n\t\t}\n\t};\n}\n"
  },
  {
    "path": "src/engine/Language.cpp",
    "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// Copyright © 2017-2022 TalonBrave.info and Others (see CONTRIBUTORS)\n\n#include \"App.h\"\n#include \"Language.h\"\n#include \"JsonReader.h\"\n\n#define LNG_MANIFEST_PATH    \"languages.manifest\"\n\nohw::LanguageManager *ohw::LanguageManager::language_manager_;\n\nohw::LanguageManager::LanguageManager() {\n\tPrint( \"Loading \" LNG_MANIFEST_PATH \"\\n\" );\n\n\t// Load in the languages manifest\n\ttry {\n\t\tJsonReader manifest( LNG_MANIFEST_PATH );\n\t\tunsigned int num_keys = manifest.GetArrayLength();\n\t\tfor ( unsigned int i = 0; i < num_keys; ++i ) {\n\t\t\tIndex index;\n\t\t\tmanifest.EnterChildNode( i );\n\t\t\tindex.name = manifest.GetStringProperty( \"name\" );\n\t\t\tindex.key = manifest.GetStringProperty( \"key\" );\n\t\t\tmanifest.LeaveChildNode();\n\t\t\tlanguages_.insert( std::pair< std::string, Index >( index.key, index ) );\n\t\t}\n\t} catch ( const std::exception &e ) {\n\t\tError( \"Failed to load languages manifest, \\\"%s\\\"!\\n\", LNG_MANIFEST_PATH );\n\t}\n}\n\nohw::LanguageManager::~LanguageManager() = default;\n\nconst char *ohw::LanguageManager::GetTranslation( const char *key ) { // todo: UTF-8 pls\n\tif ( key[ 0 ] != '$' ) {\n\t\treturn key;\n\t}\n\n\tconst char *p = ++key;\n\tif ( *p == '\\0' ) {\n\t\tWarning( \"Invalid key provided\\n\" );\n\t\treturn p;\n\t}\n\n\tif ( current_language == nullptr ) {\n\t\tWarning( \"No valid language set\\n\" );\n\t\treturn p;\n\t}\n\n\tauto i = current_language->keys.find( p );\n\tif ( i == current_language->keys.end() ) {\n\t\tWarning( \"Failed to find translation key, %s\\n\", p );\n\t\treturn p;\n\t}\n\n\treturn i->second.translation.c_str();\n}\n\nvoid ohw::LanguageManager::SetLanguage( const char *key ) {\n\tif ( current_language != nullptr && current_language->key == key ) {\n\t\treturn;\n\t}\n\n\tauto language = languages_.find( key );\n\tif ( language == languages_.end() ) {\n\t\tError( \"Failed to find specified language, \\\"%s\\\"!\\n\", key );\n\t}\n\n\tcurrent_language = &language->second;\n\n\tstd::string filePath = \"languages/\" + current_language->key + \".language\";\n\ttry {\n\t\tJsonReader manifest( filePath );\n\t\tstd::list< std::string > keys = manifest.GetObjectKeys();\n\t\tfor ( const auto &idx : keys ) {\n\t\t\tcurrent_language->keys.insert( std::pair< std::string, Key >( idx, {\n\t\t\t\t\tmanifest.GetStringProperty( idx )\n\t\t\t} ) );\n\t\t}\n\t} catch ( const std::exception &e ) {\n\t\tError( \"Failed to load language manifest, \\\"%s\\\"!\\n\", filePath.c_str() );\n\t}\n}\n\nvoid ohw::LanguageManager::SetLanguageCallback( const PLConsoleVariable *var ) {\n\tLanguageManager::GetInstance()->SetLanguage( var->s_value );\n}\n"
  },
  {
    "path": "src/engine/Language.h",
    "content": "/* OpenHoW\n * Copyright (C) 2017-2020 TalonBrave.info and Others (see CONTRIBUTORS)\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#pragma once\n\nnamespace ohw {\n\tclass LanguageManager {\n\tpublic:\n\t\tstatic LanguageManager *GetInstance() {\n\t\t\tif ( language_manager_ == nullptr ) {\n\t\t\t\tlanguage_manager_ = new LanguageManager();\n\t\t\t}\n\t\t\treturn language_manager_;\n\t\t}\n\n\t\tstatic void DestroyInstance() {\n\t\t\tdelete language_manager_;\n\t\t}\n\n\t\tvoid SetLanguage( const char *key );\n\t\tconst char *GetTranslation( const char *key );\n\n\t\tstatic void SetLanguageCallback( const PLConsoleVariable *var );\n\n\tprotected:\n\tprivate:\n\t\tstatic LanguageManager *language_manager_;\n\n\t\tLanguageManager();\n\t\t~LanguageManager();\n\n\t\tstruct Key {\n\t\t\tstd::string translation;\n\t\t};\n\n\t\tstruct Index {\n\t\t\tstd::string key;\n\t\t\tstd::string name;\n\t\t\tstd::string font;\n\t\t\tstd::map< std::string, Key > keys;\n\t\t};\n\n\t\tstd::map< std::string, Index > languages_;\n\t\tIndex *current_language{ nullptr };\n\t};\n}\n\n#define lm_gtr( a ) ohw::LanguageManager::GetInstance()->GetTranslation( ( a ) )\n"
  },
  {
    "path": "src/engine/Map.cpp",
    "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// Copyright © 2017-2022 TalonBrave.info and Others (see CONTRIBUTORS)\n\n#include \"App.h\"\n#include \"Map.h\"\n\n#include \"graphics/ShaderManager.h\"\n#include \"graphics/TextureAtlas.h\"\n\nohw::Map::Map( MapManifest *manifest ) : manifest_( manifest ) {\n\tstd::string base_path = \"maps/\" + manifest_->filename + \"/\";\n\n\tstd::string tilePath = manifest_->tile_directory;\n\tif ( tilePath.empty() ) {\n\t\t// Fallback to maps/<name>/tiles/ if not specified\n\t\ttilePath = \"maps/\" + manifest_->filename + \"/tiles/\";\n\t}\n\n\t// create the terrain\n\tterrain_ = new Terrain( tilePath );\n\t// then load the Pmg if it exists otherwise\n\t// we'll just assume it's a new map (heightmap data can be imported after)\n\tstd::string pmgPath = \"maps/\" + manifest_->filename + \"/\" + manifest_->filename + \".pmg\";\n\tterrain_->LoadPmg( pmgPath );\n\n\tstd::string pogPath = \"maps/\" + manifest_->filename + \"/\" + manifest_->filename + \".pog\";\n\tLoadSpawns( pogPath );\n\n\t// Load both the bottom and top parts of the sky dome\n\tif ( skyModelTop == nullptr ) {\n\t\tskyModelTop = LoadSkyModel( \"skys/skydome.vtx\" );\n\t}\n\tif ( skyModelBottom == nullptr ) {\n\t\tskyModelBottom = LoadSkyModel( \"skys/skydomeu.vtx\" );\n\t}\n\n\tUpdateSky();\n}\n\nohw::Map::~Map() {\n\tdelete terrain_;\n}\n\nohw::SharedModelResourcePointer ohw::Map::LoadSkyModel( const std::string &path ) {\n\tSharedModelResourcePointer model = GetApp()->resourceManager->LoadModel( path, true, true );\n\n\t// Default skydome is smaller than the map, so we'll scale it\n\thei::Matrix4 mat;\n\tmat.Translate( { TERRAIN_PIXEL_WIDTH / 2.0f, 0.0f, TERRAIN_PIXEL_WIDTH / 2.0f } );\n\tmat *= hei::Vector3( 5.0f, 5.0f, 5.0f );\n\tmodel->modelMatrix = mat;\n\n\tPLGMesh *mesh = model->GetInternalMesh( 0 );\n\n\t// This is a really crap hardcoded limit, just to ensure it's what we're expecting\n\tif ( mesh->num_verts != 257 ) {\n\t\tError( \"Unexpected number of vertices for sky mesh! (%d vs 257)\\n\", mesh->num_verts );\n\t}\n\n\treturn model;\n}\n\nvoid ohw::Map::UpdateSky() {\n\tUpdateSkyModel( skyModelTop );\n\tUpdateSkyModel( skyModelBottom );\n}\n\nvoid ohw::Map::UpdateSkyModel( SharedModelResourcePointer model ) {\n\tPLGMesh *mesh = model->GetInternalMesh( 0 );\n\n\t// Below is a PSX-style gradient sky implementation\n\tconst unsigned int solid_steps = 3;\n\tconst unsigned int grad_steps = 6;\n\tPLColour top = manifest_->sky_colour_top;\n\tPLColour bottom = manifest_->sky_colour_bottom;\n\tint stepr = ( ( int ) ( bottom.r ) - ( int ) ( top.r ) ) / ( int ) ( grad_steps );\n\tint stepg = ( ( int ) ( bottom.g ) - ( int ) ( top.g ) ) / ( int ) ( grad_steps );\n\tint stepb = ( ( int ) ( bottom.b ) - ( int ) ( top.b ) ) / ( int ) ( grad_steps );\n\n\tif ( stepr < 0 ) { stepr += 255; }\n\tif ( stepg < 0 ) { stepg += 255; }\n\tif ( stepb < 0 ) { stepb += 255; }\n\n\tPLColour colour = top;\n\tfor ( unsigned int i = 0, j = 31, s = 0; i < mesh->num_verts; ++i, ++j ) {\n\t\tif ( j == 32 ) {\n\t\t\tif ( ++s >= solid_steps ) {\n\t\t\t\tcolour.r += stepr;\n\t\t\t\tcolour.g += stepg;\n\t\t\t\tcolour.b += stepb;\n\t\t\t}\n\t\t\tj = 0;\n\t\t}\n\n\t\tmesh->vertices[ i ].colour = colour;\n\t}\n\n\tPlgUploadMesh( mesh );\n}\n\n/**\n * Fetches a random spot in the playable area of the map.\n */\nPLVector2 ohw::Map::GetRandomPointInPlayArea() const {\n\treturn { TERRAIN_PLAYABLE_BORDER + PlGenerateRandomFloat( TERRAIN_PLAYABLE_AREA ),\n\t         TERRAIN_PLAYABLE_BORDER + PlGenerateRandomFloat( TERRAIN_PLAYABLE_AREA ) };\n}\n\n/**\n * Fetch the bounds of the playable area.\n */\nvoid ohw::Map::GetPlayArea( PLVector2 *min, PLVector2 *max ) const {\n\tmin->x = TERRAIN_PLAYABLE_BORDER;\n\tmax->x = TERRAIN_PLAYABLE_AREA;\n\tmin->y = TERRAIN_PLAYABLE_BORDER;\n\tmax->y = TERRAIN_PLAYABLE_AREA;\n}\n\nvoid ohw::Map::LoadSpawns( const std::string &path ) {\n\tstruct PogIndex {\n\t\tchar name[16];               // class name\n\t\tchar unused0[16];\n\t\tint16_t position[3];            // position in the world\n\t\tuint16_t index;                  // todo\n\t\tint16_t angles[3];              // angles in the world\n\t\tuint16_t type;                   // todo\n\t\tint16_t bounds[3];              // collision bounds\n\t\tuint16_t bounds_type;            // box, prism, sphere and none\n\t\tint16_t energy;\n\t\tuint8_t appearance;\n\t\tuint8_t team;                   // uk, usa, german, french, japanese, soviet\n\t\tuint16_t objective;\n\t\tuint8_t objective_actor_id;\n\t\tuint8_t objective_extra[2];\n\t\tuint8_t unused1;\n\t\tuint16_t unused2[8];\n\t\tint16_t fallback_position[3];\n\t\tint16_t extra;\n\t\tint16_t attached_actor_num;\n\t\tint16_t unused3;\n\t};\n\tstatic_assert( sizeof( PogIndex ) == 94, \"Invalid size for PogIndex, should be 94 bytes!\" );\n\n\tconst char *cPath = path.c_str();\n\tPLFile *fp = PlOpenFile( cPath, false );\n\tif ( fp == NULL ) {\n\t\tWarning( \"Failed to open actor data, \\\"%s\\\" (%s)!\\n\", cPath, PlGetError() );\n\t\treturn;\n\t}\n\n\tbool status = false;\n\tuint16_t num_indices = PlReadInt16( fp, false, &status );\n\tif ( !status ) {\n\t\tError( \"Failed to read Pog indices count in \\\"%s\\\" (%s)!\\n\", cPath, PlGetError() );\n\t}\n\n\tstd::vector< PogIndex > spawns( num_indices );\n\tif ( PlReadFile( fp, spawns.data(), sizeof( PogIndex ), num_indices ) != num_indices ) {\n\t\tError( \"Failed to read Pog spawns in \\\"%s\\\" (%s)!\\n\", cPath, PlGetError() );\n\t}\n\n\tPlCloseFile( fp );\n\n\tactorSpawns.resize( num_indices );\n\n\tfor ( unsigned int i = 0; i < num_indices; ++i ) {\n\t\tactorSpawns[ i ].position.x = static_cast<float>(spawns[ i ].position[ 0 ] + ( TERRAIN_PIXEL_WIDTH / 2 ));\n\t\tactorSpawns[ i ].position.y = static_cast<float>(spawns[ i ].position[ 1 ]);\n\t\tactorSpawns[ i ].position.z = static_cast<float>(( spawns[ i ].position[ 2 ] * -1 ) + ( TERRAIN_PIXEL_WIDTH / 2 ));\n\n#if 0\n\t\tactorSpawns[ i ].fallbackPosition.x = ( spawns[ i ].fallback_position[ 0 ] += ( TERRAIN_PIXEL_WIDTH / 2 ) );\n\t\tactorSpawns[ i ].fallbackPosition.y = ( spawns[ i ].fallback_position[ 1 ] );\n\t\tactorSpawns[ i ].fallbackPosition.z = ( spawns[ i ].fallback_position[ 2 ] += ( TERRAIN_PIXEL_WIDTH / 2 ) * -1 );\n\n\t\tactorSpawns[ i ].angles.x = ( float ) ( spawns[ i ].angles[ 0 ] ) * ( 360.f / 4096.f );\n\t\tactorSpawns[ i ].angles.y = ( float ) ( spawns[ i ].angles[ 1 ] ) * ( 360.f / 4096.f ) - 90.0f;\n\t\tactorSpawns[ i ].angles.z = ( float ) ( spawns[ i ].angles[ 2 ] ) * ( 360.f / 4096.f ) + 180.0f;\n#endif\n\n\t\tactorSpawns[ i ].className = u_stringtolower( spawns[ i ].name );\n\t\tactorSpawns[ i ].appearance = spawns[ i ].appearance;\n\n\t\ttry {\n\t\t\tactorSpawns[ i ].attachment = &actorSpawns.at( spawns[ i ].attached_actor_num );\n\t\t} catch ( const std::out_of_range &e ) {\n\t\t\tWarning( \"Failed to get valid attachment for spawn (%s, %s)!\\n\", actorSpawns[ i ].className.c_str(),\n\t\t\t         PlPrintVector3( &actorSpawns[ i ].position, PL_VAR_I32 ) );\n\t\t}\n\n\t\tactorSpawns[ i ].energy = spawns[ i ].energy;\n\t\tactorSpawns[ i ].index = spawns[ i ].index;\n\n\t\t// todo: retain or set on per-actor basis?\n\t\tfor ( unsigned int j = 0; j < 3; ++j ) {\n\t\t\tactorSpawns[ i ].bounds[ j ] = spawns[ i ].bounds[ j ];\n\t\t}\n\t\tactorSpawns[ i ].bounds_type = spawns[ i ].bounds_type;\n\t}\n}\n\nvoid ohw::Map::Draw() {\n\tShaders_SetProgramByName( \"generic_untextured\" );\n\n\tskyModelTop->Draw( false );\n\tskyModelBottom->Draw( false );\n\n#if 1\n\tPLCollisionAABB bounds;\n\n\tbounds.origin.x = TERRAIN_PLAYABLE_BORDER;\n\tbounds.origin.y = 512.0f;\n\tbounds.origin.z = TERRAIN_PLAYABLE_BORDER;\n\n\tbounds.maxs.x = TERRAIN_PLAYABLE_AREA;\n\tbounds.maxs.y = terrain_->GetMaxHeight();\n\tbounds.maxs.z = TERRAIN_PLAYABLE_AREA;\n\n\tbounds.mins.x = 0;\n\tbounds.mins.y = terrain_->GetMinHeight();\n\tbounds.mins.z = 0;\n\n\tPlgDrawBoundingVolume( &bounds, PL_COLOUR_RED );\n#endif\n\n\tif ( !cv_GraphicsDrawTerrain->b_value ) {\n\t\treturn;\n\t}\n\n\t// TODO: move this somewhere else???\n\tPLGShaderProgram *program = Shaders_GetProgram( \"generic_textured_lit\" )->GetInternalProgram();\n\tif ( program == nullptr ) {\n\t\treturn;\n\t}\n\n\tPLVector4 vColour = manifest_->fog_colour.ToVec4();\n\tPlgSetShaderUniformValue( program, \"fog_colour\", &vColour, false );\n\tPlgSetShaderUniformValue( program, \"fog_near\", &manifest_->fog_intensity, false );\n\tPlgSetShaderUniformValue( program, \"fog_far\", &manifest_->fog_distance, false );\n\n\thei::Vector3 sunPosition( 1.0f, -manifest_->sun_pitch, 0 );\n\thei::Matrix4 sunMatrix;\n\tsunMatrix.Identity();\n\tsunMatrix.Translate( sunPosition );\n\tsunMatrix.Rotate( manifest_->sun_yaw, { 0.0f, 1.0f, 0.0f } );\n\tsunPosition.x = sunMatrix.m[ 0 ];\n\tsunPosition.z = sunMatrix.m[ 8 ];\n\n\tPlgSetShaderUniformValue( program, \"sun_position\", &sunPosition, false );\n\tvColour = manifest_->sun_colour.ToVec4();\n\tPlgSetShaderUniformValue( program, \"sun_colour\", &vColour, false );\n\tvColour = manifest_->ambient_colour.ToVec4();\n\tPlgSetShaderUniformValue( program, \"ambient_colour\", &vColour, false );\n\n\tterrain_->Draw();\n}\n"
  },
  {
    "path": "src/engine/Map.h",
    "content": "/* OpenHoW\n * Copyright (C) 2017-2020 TalonBrave.info and Others (see CONTRIBUTORS)\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#pragma once\n\n#include \"Terrain.h\"\n\nstruct MapManifest;\n\n/* end format data */\n\nstruct ActorSpawn;\n\nnamespace ohw {\n\tclass Map {\n\tpublic:\n\t\texplicit Map( MapManifest *manifest );\n\t\t~Map();\n\n\t\tvoid Draw();\n\n\t\tMapManifest *GetManifest() { return manifest_; }\n\t\tTerrain *GetTerrain() { return terrain_; }\n\n\t\tconst std::vector< ActorSpawn > &GetSpawns() { return actorSpawns; }\n\n\t\tvoid UpdateSky();\n\n\t\tPLVector2 GetRandomPointInPlayArea() const;\n\t\tvoid GetPlayArea( PLVector2 *min, PLVector2 *max ) const;\n\n\tprotected:\n\tprivate:\n\t\tvoid LoadSpawns( const std::string &path );\n\t\tstatic SharedModelResourcePointer LoadSkyModel( const std::string &path );\n\n\t\tvoid UpdateSkyModel( SharedModelResourcePointer skyModel );\n\n\t\tMapManifest *manifest_{ nullptr };\n\n\t\tstd::vector< ActorSpawn > actorSpawns;\n\n\t\tSharedModelResourcePointer skyModelTop{ nullptr };\n\t\tSharedModelResourcePointer skyModelBottom{ nullptr };\n\n\t\tTerrain *terrain_{ nullptr };\n\t};\n}\n"
  },
  {
    "path": "src/engine/MathUtilities.h",
    "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// Copyright © 2017-2022 TalonBrave.info and Others (see CONTRIBUTORS)\n\n#pragma once\n\n#include <plcore/pl_math.h>\n\n/* extension of Platform's math functionality */\n\n#ifdef __cplusplus\n\ninline static void VectorClamp( hei::Vector3 *vector, float min, float max ) {\n\tfor ( unsigned int i = 0; i < 3; ++i ) {\n\t\tif ( ( *vector )[ i ] >= max ) {\n\t\t\t( *vector )[ i ] = max;\n\t\t} else if ( ( *vector )[ i ] <= min ) {\n\t\t\t( *vector )[ i ] = min;\n\t\t}\n\t}\n}\n\ninline static void VecAngleClamp( hei::Vector3 *vector ) {\n\tfor ( unsigned int i = 0; i < 3; ++i ) {\n\t\tif ( ( *vector )[ i ] >= 360 ) {\n\t\t\t( *vector )[ i ] = 0;\n\t\t} else if ( ( *vector )[ i ] <= -360 ) {\n\t\t\t( *vector )[ i ] = 0;\n\t\t}\n\t}\n}\n\n#endif\n"
  },
  {
    "path": "src/engine/Menu.cpp",
    "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// Copyright © 2017-2022 TalonBrave.info and Others (see CONTRIBUTORS)\n\n#include \"App.h\"\n#include \"Menu.h\"\n#include \"Map.h\"\n#include \"graphics/Display.h\"\n#include \"graphics/video.h\"\n#include \"graphics/Camera.h\"\n#include \"graphics/ShaderManager.h\"\n#include \"game/ActorManager.h\"\n\nstatic unsigned int frontend_state = FE_MODE_INIT;\nstatic unsigned int old_frontend_state = ( unsigned int ) -1;\n\n/* texture assets, these are loaded and free'd at runtime */\nstatic ohw::TextureResource *menuBackground = nullptr;\nstatic ohw::TextureResource *minimapIcons[ MAX_MINIMAP_ICONS ];\n\nstatic int frontend_width = 0;\nstatic int frontend_height = 0;\n\nohw::BitmapFont *g_fonts[ NUM_FONTS ];\n\nstatic PLGCamera *menuCamera;\n\nvoid Menu_Initialize() {\n\tmenuBackground = ohw::GetApp()->resourceManager->LoadTexture( \"frontend/pigbkpc1\", ohw::TextureResource::FLAG_NOMIPS, true );\n\n\t// Cache all the minimap icons\n\tminimapIcons[ MINIMAP_ICON_BOMB ] = ohw::GetApp()->resourceManager->LoadTexture( \"frontend/map/bomb\", ohw::TextureResource::FLAG_NOMIPS, true );\n\tminimapIcons[ MINIMAP_ICON_HEALTH ] = ohw::GetApp()->resourceManager->LoadTexture( \"frontend/map/iconhart\", ohw::TextureResource::FLAG_NOMIPS, true );\n\tminimapIcons[ MINIMAP_ICON_PIG ] = ohw::GetApp()->resourceManager->LoadTexture( \"frontend/map/iconpig\", ohw::TextureResource::FLAG_NOMIPS, true );\n\tminimapIcons[ MINIMAP_ICON_PICKUP ] = ohw::GetApp()->resourceManager->LoadTexture( \"frontend/map/iconpkup.png\", ohw::TextureResource::FLAG_NOMIPS, true );\n\tminimapIcons[ MINIMAP_ICON_PROP ] = ohw::GetApp()->resourceManager->LoadTexture( \"frontend/map/iconprop\", ohw::TextureResource::FLAG_NOMIPS, true );\n\n\t// Cache the default fonts\n\tstruct FontIndex {\n\t\tconst char *tab, *texture;\n\t} defaultFonts[ NUM_FONTS ] = {\n\t        { \"frontend/text/big.tab\", \"frontend/text/big.bmp\" },\n\t        { \"frontend/text/bigchars.tab\", \"frontend/text/bigchars.bmp\" },\n\t        { \"frontend/text/chars2.tab\", \"frontend/text/chars2l.bmp\" },\n\t        { \"frontend/text/chars3.tab\", \"frontend/text/chars3.bmp\" },\n\t        { \"frontend/text/gamechars.tab\", \"frontend/text/gamechars.bmp\" },\n\t        { \"frontend/text/small.tab\", \"frontend/text/small.bmp\" },\n\t};\n\tfor ( unsigned int i = 0; i < NUM_FONTS; ++i ) {\n\t\tg_fonts[ i ] = new ohw::BitmapFont();\n\t\tif ( !g_fonts[ i ]->Load( defaultFonts[ i ].tab, defaultFonts[ i ].texture ) ) {\n\t\t\tError( \"Failed to load default font!\\n\" );\n\t\t}\n\t}\n\n\t// Setup viewport\n\t// TODO: move into frontend.cpp\n\tmenuCamera = PlgCreateCamera();\n\tif ( menuCamera == nullptr ) {\n\t\tError( \"Failed to create ui camera, aborting!\\n%s\\n\", PlGetError() );\n\t}\n\tmenuCamera->mode = PLG_CAMERA_MODE_ORTHOGRAPHIC;\n\tmenuCamera->fov = 90;\n\tmenuCamera->near = 0;\n\tmenuCamera->far = 1000;\n\tmenuCamera->viewport.w = DISPLAY_MIN_WIDTH;\n\tmenuCamera->viewport.h = DISPLAY_MIN_HEIGHT;\n}\n\nvoid Menu_UpdateViewport( int x, int y, int width, int height ) {\n\t//TODO: Only adjust viewport aspect of ingame camera once ingame scene is working. Force UI camera to 4:3 viewport always.\n\t//      For now, just use the same viewport aspect for both.\n\n\tfloat current_aspect = ( float ) width / ( float ) height;\n\tfloat target_aspect = 4.0f / 3.0f;\n\tfloat relative_width = target_aspect / current_aspect;\n\tfloat relative_height = current_aspect / target_aspect;\n\trelative_width = relative_width > 1.0f ? 1.0f : relative_width;\n\trelative_height = relative_height > 1.0f ? 1.0f : relative_height;\n\n\tint newWidth = ( float ) width * relative_width;\n\tint newHeight = ( float ) height * relative_height;\n\n\tif ( FrontEnd_GetState() == FE_MODE_GAME || cv_display_use_window_aspect->b_value ) {\n\t\t//If enabled, use full window for 3d scene\n\t\tmenuCamera->viewport.x = x;\n\t\tmenuCamera->viewport.y = y;\n\t\tmenuCamera->viewport.w = width;\n\t\tmenuCamera->viewport.h = height;\n\t} else {\n\t\tmenuCamera->viewport.x = ( width - newWidth ) / 2;\n\t\tmenuCamera->viewport.y = ( height - newHeight ) / 2;\n\t\tmenuCamera->viewport.w = newWidth;\n\t\tmenuCamera->viewport.h = newHeight;\n\t}\n}\n\n/************************************************************/\n\nstatic void FrontendInputCallback( int key, bool is_pressed ) {\n\tif ( frontend_state == FE_MODE_START && is_pressed ) {\n\t\t/* todo, play 'ting' sound! */\n\n\t\t/* we've hit our key, we can take away this\n\t\t * callback now and carry on to whatever */\n\t\tohw::GetApp()->inputManager->SetKeyboardFocusCallback( nullptr );\n\t\tFrontEnd_SetState( FE_MODE_MAIN_MENU );\n\t\treturn;\n\t}\n}\n\n/************************************************************/\n\nvoid FE_Shutdown( void ) {\n\tfor ( auto &g_font : g_fonts ) {\n\t\tdelete g_font;\n\t}\n}\n\nvoid FE_ProcessInput( void ) {\n\tswitch ( frontend_state ) {\n\t\tdefault:\n\t\t\tbreak;\n\n\t\tcase FE_MODE_START:\n\t\t\t/* this is... kind of a hack... but ensures that\n\t\t\t * nothing will take away our check for a key during\n\t\t\t * the 'start' screen, e.g. bringing the console up */\n\t\t\tohw::GetApp()->inputManager->SetKeyboardFocusCallback( FrontendInputCallback );\n\t\t\tbreak;\n\n\t\tcase FE_MODE_VIDEO:\n\t\t\tif ( ohw::GetApp()->inputManager->GetKeyState( ohw::InputManager::KEY_SPACE ) || ohw::GetApp()->inputManager->GetKeyState( ohw::InputManager::KEY_ESCAPE ) ) {\n\t\t\t\tVideo_SkipCurrent();\n\t\t\t}\n\t\t\tbreak;\n\t}\n}\n\nvoid FrontEnd_Tick( void ) {}\n\n/************************************************************/\n\nchar loading_description[ 256 ];\nuint8_t loading_progress = 0;\n\n#if 0\n#\tdefine Redraw() Display_DrawInterface();\n#else\n#\tdefine Redraw()\n#endif\n\nvoid FE_SetLoadingBackground( const char *name ) {\n\tchar screen_path[ PL_SYSTEM_MAX_PATH ];\n\tsnprintf( screen_path, sizeof( screen_path ), \"frontend/briefing/%s\", name );\n\tif ( !PlFileExists( screen_path ) ) {\n\t\tsnprintf( screen_path, sizeof( screen_path ), \"frontend/briefing/loadmult\" );\n\t}\n\n\tmenuBackground = ohw::GetApp()->resourceManager->LoadTexture( screen_path, ohw::TextureResource::FLAG_NOMIPS );\n\tRedraw();\n}\n\nvoid FE_SetLoadingDescription( const char *description ) {\n\tsnprintf( loading_description, sizeof( loading_description ), \"%s ...\", description );\n\tRedraw();\n}\n\nvoid FE_SetLoadingProgress( uint8_t progress ) {\n\tif ( progress > 100 ) progress = 100;\n\tloading_progress = progress;\n\tRedraw();\n}\n\nuint8_t FE_GetLoadingProgress( void ) {\n\treturn loading_progress;\n}\n\n/************************************************************/\n\n/**\n * Draw the timer in the bottom corner of the screen.\n */\nstatic void DrawTimer() {\n\tif ( FrontEnd_GetState() != FE_MODE_GAME ) {\n\t\treturn;\n\t}\n\n\tohw::IGameMode *mode = ohw::GetApp()->gameManager->GetMode();\n\tif ( !mode->HasRoundStarted() ) {\n\t\treturn;\n\t}\n\n\tchar str[ 64 ];\n\tsnprintf( str, sizeof( str ), \"%0d\", mode->GetMaxTurnTimeSeconds() - mode->GetTurnTimeSeconds() );\n\tg_fonts[ FONT_BIG ]->DrawString( frontend_width - 256,\n\t                                 frontend_height - 100,\n\t                                 4,\n\t                                 1.0f,\n\t                                 PL_COLOUR_WHITE,\n\t                                 str );\n}\n\n/**\n * Draw the 3D minimap on the bottom left corner of the screen.\n */\nstatic void FrontEnd_DrawMinimap() {\n\tohw::Map *map = ohw::GetApp()->gameManager->GetCurrentMap();\n\tif ( map == nullptr ) {\n\t\treturn;\n\t}\n\n\tohw::Camera *camera = ohw::GetApp()->gameManager->GetActiveCamera();\n\tif ( camera == nullptr ) {\n\t\treturn;\n\t}\n\n\t// So, we need to render the minimap from the perspective here. So swap things round\n\tPLGCamera *uiCamera = menuCamera;\n\tPLGCamera save = *uiCamera;\n\n\t// Set up the camera so we can render the minimap how it needs to be\n\tuiCamera->mode = PLG_CAMERA_MODE_PERSPECTIVE;\n\tuiCamera->near = 0.1f;\n\tuiCamera->far = 100.0f;\n\tuiCamera->fov = 65.0f;\n\tuiCamera->position = { -120.0f, 64.0f, 0.0f };\n\tuiCamera->angles = { -45.0f, 0.0f, 0.0f };\n\tuiCamera->viewport.x = 0;\n\tuiCamera->viewport.y = 0;\n\tuiCamera->viewport.w = 450;\n\tuiCamera->viewport.h = 256;\n\n\tPlgSetupCamera( uiCamera );\n\n\thei::Matrix4 transform;\n\ttransform.Identity();\n\ttransform.Rotate( PlDegreesToRadians( 90.0f ), { 1, 0, 0 } );\n\ttransform.Rotate( PlDegreesToRadians( camera->GetAngles().y ), { 0, 1, 0 } );\n\n\tPlMatrixMode( PL_MODELVIEW_MATRIX );\n\tPlPushMatrix();\n\tPlLoadMatrix( &transform );\n\n\tPlgDrawTexturedRectangle( -64, -64, 128, 128, map->GetTerrain()->GetOverview() );\n\n\t// Now draw everything on top\n\tfor ( const auto &actor : ActorManager::GetInstance()->GetActors() ) {\n\t\tif ( !actor->IsVisibleOnMinimap() ) {\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Figure out what icon we're using\n\t\tPLGTexture *iconTexture = ohw::GetApp()->resourceManager->GetFallbackTexture();\n\t\tunsigned int iconStyle = actor->GetMinimapIconStyle();\n\t\tif ( iconStyle < MAX_MINIMAP_ICONS ) {\n\t\t\ticonTexture = minimapIcons[ iconStyle ]->GetInternalTexture();\n\t\t}\n\n\t\tPlgSetTexture( iconTexture, 0 );\n\n\t\t// And now figure out where relatively speaking they should be\n\t\tPLVector3 curPosition = actor->GetPosition();\n\t\tfloat x = ( curPosition.x / 256.0f ) - 64.0f;\n\t\tfloat y = ( curPosition.z / 256.0f ) - 64.0f;\n\n\t\ttransform.Identity();\n\t\t// Angle the plane towards the camera\n\t\ttransform.Rotate( PlDegreesToRadians( 135.0f ), { 1, 0, 0 } );\n\t\t// Rotate the yaw so it's always facing the camera\n\t\ttransform.Rotate( PlDegreesToRadians( -camera->GetAngles().y - 90.0f ), { 0, 1, 0 } );\n\t\t// And now position and rotate it so it appears on top of the map\n\t\ttransform.Translate( { x, 0.0f, y } );\n\t\ttransform.Rotate( PlDegreesToRadians( camera->GetAngles().y ), { 0, 1, 0 } );\n\n\t\t// Fetch the transformed distance from the camera\n\t\tPLVector3 translation = transform.GetTranslation();\n\t\thei::Vector3 distance = hei::Vector3( uiCamera->position ) - translation;\n\t\tfloat lengthDistance = distance.Length();\n\t\t// And now scale it up as it moves further away (this isn't perfect...)\n\t\tfloat scale = 8.0f * lengthDistance / 100.0f;\n\n\t\tPlLoadMatrix( &transform );\n\t\tPlgDrawRectangle( -( scale / 2 ), -( scale / 2 ), scale, scale, actor->GetMinimapIconColour() );\n\t}\n\n\tPlPopMatrix();\n\n\tPlgSetTexture( nullptr, 0 );\n\n\t// Restore what we originally had for the camera\n\t*uiCamera = save;\n\tPlgSetupCamera( uiCamera );\n}\n\n/* Hogs of War's menu was designed\n * with a fixed resolution in mind\n * and scales poorly with anything\n * else. For now we'll just keep\n * things fixed and worry about this\n * later. */\n\nstatic void DrawLoadingScreen() {\n#if 0 //todo: revisit\n\tPlgDrawTexturedRectangle( 0, 0, frontend_width, frontend_height, menuBackground->GetInternalTexture() );\n\n\t/* originally I wrote some code ensuring the menu bar\n\t * was centered... that was until I found out that on\n\t * the background, the slot for the bar ISN'T centered\n\t * at all. JOY... */\n\tstatic const int bar_w = 330;\n\tint bar_x = 151;//c_x + (FRONTEND_MENU_WIDTH / 2) - bar_w / 2;\n\tint bar_y = 450;\n\tif ( loading_progress > 0 ) {\n\t\tPLRectangle2D box = PlCreateRectangle(\n\t\t        hei::Vector2( bar_x, bar_y ),\n\t\t        hei::Vector2( ( ( float ) ( bar_w ) / 100 ) * loading_progress, 18 ),\n\t\t        PL_COLOUR_INDIAN_RED,\n\t\t        PL_COLOUR_INDIAN_RED,\n\t\t        PL_COLOUR_RED,\n\t\t        PL_COLOUR_RED );\n\t\tPlgDrawFilledRectangle( &box );\n\t}\n\n\tif ( loading_description[ 0 ] != ' ' && loading_description[ 0 ] != '\\0' ) {\n\t\tg_fonts[ FONT_CHARS2 ]->DrawString( bar_x + 2,\n\t\t                                    bar_y + 1,\n\t\t                                    4,\n\t\t                                    1.f,\n\t\t                                    PL_COLOUR_WHITE,\n\t\t                                    loading_description );\n\t}\n#endif\n}\n\nvoid Menu_Draw() {\n\tohw::Display *display = ohw::GetApp()->GetDisplay();\n\tif ( display == nullptr ) {\n\t\treturn;\n\t}\n\n\tint w, h;\n\tdisplay->GetDisplaySize( &w, &h );\n\tMenu_UpdateViewport( 0, 0, w, h );\n\n\tShaders_SetProgramByName( \"generic_textured\" );\n\n\tPlgSetupCamera( menuCamera );\n\tPlgSetDepthBufferMode( PLG_DEPTHBUFFER_DISABLE );\n\n\tfrontend_width = menuCamera->viewport.w;\n\tfrontend_height = menuCamera->viewport.h;\n\n\t/* render and handle the main menu */\n\tswitch ( frontend_state ) {\n\t\tdefault:\n\t\t\tbreak;\n\n\t\tcase FE_MODE_INIT:\n\t\tcase FE_MODE_START:\n\t\tcase FE_MODE_MAIN_MENU:\n\t\t\tPlgDrawTexturedRectangle( 0, 0, frontend_width, frontend_height, menuBackground->GetInternalTexture() );\n\t\t\tbreak;\n\n\t\tcase FE_MODE_LOADING:\n\t\t\tDrawLoadingScreen();\n\t\t\tbreak;\n\n\t\tcase FE_MODE_VIDEO:\n\t\t\tVideo_Draw();\n\t\t\tbreak;\n\n\t\tcase FE_MODE_GAME:\n\t\t\tFrontEnd_DrawMinimap();\n\t\t\tDrawTimer();\n\t\t\tbreak;\n\t}\n}\n\n/* * * * * * * * * * * * * * * * * * * * * * */\n\nvoid FE_RestoreLastState( void ) {\n\tFrontEnd_SetState( old_frontend_state );\n}\n\nunsigned int FrontEnd_GetState( void ) {\n\treturn frontend_state;\n}\n\nvoid FrontEnd_SetState( unsigned int state ) {\n\tif ( state == frontend_state ) {\n\t\tDebugMsg( \"attempted to set debug state to an already existing state!\\n\" );\n\t\treturn;\n\t}\n\n\tDebugMsg( \"changing frontend state to %u...\\n\", state );\n\tswitch ( state ) {\n\t\tdefault: {\n\t\t\tWarning( \"invalid frontend state, %u, aborting\\n\", state );\n\t\t\treturn;\n\t\t}\n\n\t\tcase FE_MODE_MAIN_MENU:\n\t\t\t// start playing the default theme\n\t\t\tohw::GetApp()->audioManager->PlayMusic( AUDIO_MUSIC_MENU );\n\t\t\tbreak;\n\n\t\tcase FE_MODE_START:\n\t\tcase FE_MODE_GAME:\n\t\t\t// game mode handles music from here?\n\t\t\tbreak;\n\n\t\tcase FE_MODE_LOADING: {\n\t\t\t// stop the music as soon as we switch to a loading screen...\n\t\t\tohw::GetApp()->audioManager->StopMusic();\n\n\t\t\tloading_description[ 0 ] = '\\0';\n\t\t\tloading_progress = 0;\n\t\t\tbreak;\n\t\t}\n\n\t\tcase FE_MODE_EDITOR:\n\t\t\tbreak;\n\t}\n\told_frontend_state = frontend_state;\n\tfrontend_state = state;\n}\n"
  },
  {
    "path": "src/engine/Menu.h",
    "content": "/* OpenHoW\n * Copyright (C) 2017-2020 TalonBrave.info and Others (see CONTRIBUTORS)\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#pragma once\n\n/*\n * Debrief > Continue / Retry\n *\n * Main Menu\n *  One Player\n *      New Game\n *          Select Team\n *              Please Name Your Team\n *                  Team Setup\n *                      Play Training Mission?\n *                          Loading Screen\n *      Load Game\n */\n\nenum MinimapIcon {\n\tMINIMAP_ICON_BOMB,\t// Unused?\n\tMINIMAP_ICON_HEALTH,\n\tMINIMAP_ICON_PIG,\n\tMINIMAP_ICON_PICKUP,\n\tMINIMAP_ICON_PROP,\t// Unused?\n\n\tMAX_MINIMAP_ICONS\n};\n\nenum {\n  FE_MODE_INIT,       /* menu shown during initialization */\n  FE_MODE_START,      /* start screen, e.g. press any key */\n  FE_MODE_LOADING,\n\n  FE_MODE_MAIN_MENU,\n\n  /* Main Menu */\n  FE_MODE_ONE_PLAYER,\n  FE_MODE_MULTI_PLAYER,\n  FE_MODE_OPTIONS,\n  FE_MODE_CONTROLS,\n\n  /* One Player */\n  FE_MODE_NEW_GAME,\n  FE_MODE_LOAD_GAME,\n\n  /* Multi-player */\n  /* todo */\n\n  /* Options */\n  /* todo */\n\n  FE_MODE_SELECT_TEAM,\n\n  FE_MODE_EDITOR, /* editor mode - either embedded or standalone */\n  FE_MODE_VIDEO,  /* playing a video - pressing escape will skip */\n  FE_MODE_GAME,   /* in-game menu... probably cut this down? */\n\n  MAX_FE_MODES\n};\n\nenum {\n\tFONT_BIG,\n\tFONT_BIG_CHARS,\n\tFONT_CHARS2,\n\tFONT_CHARS3,\n\tFONT_GAME_CHARS,\n\tFONT_SMALL,\n\n\tNUM_FONTS\n};\n\n// these are for FONT_SMALL, and probably will be made\n// redundant once we get our own icons in etc.\n#define CHAR_PSX_TRIANGLE   \"c\"\n#define CHAR_PSX_CIRCLE     \"d\"\n#define CHAR_PSX_CROSS      \"e\"\n#define CHAR_PSX_SQUARE     \"f\"\n#define CHAR_PSX_L1         \"g\"\n#define CHAR_PSX_L2         \"h\"\n#define CHAR_PSX_R1         \"i\"\n#define CHAR_PSX_R2         \"j\"\n\n#include \"BitmapFont.h\"\n\nextern ohw::BitmapFont *g_fonts[NUM_FONTS];\n\nvoid Menu_Initialize();\nvoid Menu_UpdateViewport( int x, int y, int width, int height );\nvoid FE_Shutdown();\nvoid FE_ProcessInput();\nvoid FrontEnd_Tick();\nvoid Menu_Draw();\n\nvoid FE_SetLoadingBackground(const char *name);\nvoid FE_SetLoadingDescription(const char *description);\nvoid FE_SetLoadingProgress(uint8_t progress);\nuint8_t FE_GetLoadingProgress();\n\nunsigned int FrontEnd_GetState();\nvoid FrontEnd_SetState(unsigned int state);\nvoid FE_RestoreLastState();\n"
  },
  {
    "path": "src/engine/ModManager.cpp",
    "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// Copyright © 2017-2022 TalonBrave.info and Others (see CONTRIBUTORS)\n\n#include \"App.h\"\n\n#include \"script/JsonReader.h\"\n\n/* Mod Management\n *\n * Launching games and other state management\n * of the game as a whole is dealt with here.\n */\n\nohw::ModManager::ModManager() {\n\tPlScanDirectory( \"mods\", \"mod\", RegisterMod, false, this );\n}\n\nvoid ohw::ModManager::Mount( const char *name ) {\n\t// Attempt to fetch the manifest, if it doesn't exist then attempt to load it\n\tModDescription *mod = GetModDescription( name );\n\tif ( mod == nullptr ) {\n\t\tPrint( \"Mod manifest, \\\"%s\\\", wasn't cached on launch... attempting to load!\\n\", name );\n\n\t\tchar path[PL_SYSTEM_MAX_PATH];\n\t\tsnprintf( path, sizeof( path ), \"mods/%s.mod\", name );\n\t\tif ( PlFileExists( path ) ) {\n\t\t\tRegisterMod( path, this );\n\t\t\tmod = GetModDescription( name );\n\t\t}\n\n\t\tif ( mod == nullptr ) {\n\t\t\tWarning( \"Mod \\\"%s\\\" doesn't exist!\\n\", name );\n\t\t\treturn;\n\t\t}\n\t}\n\n\tif ( myCurrentMod == mod ) {\n\t\tPrint( \"Mod already mounted!\\n\" );\n\t\treturn;\n\t}\n\n\t// Generate a list of directories to mount based on the dependencies\n\tstd::set< std::string > dirSet;\n\tFetchDependencies( mod, dirSet );\n\tdirSet.emplace( mod->directory );\n\n\tUnmount();\n\n\t// Now attempt to mount everything\n\tmyCurrentMod = mod;\n\tfor ( const auto &i: dirSet ) {\n\t\tchar mountPath[PL_SYSTEM_MAX_PATH];\n\t\tsnprintf( mountPath, sizeof( mountPath ), \"mods/%s\", i.c_str() );\n\t\tPLFileSystemMount *mount = PlMountLocation( mountPath );\n\t\tif ( mount == nullptr ) {\n\t\t\tWarning( \"Failed to mount location, \\\"%s\\\" (%s)!\\n\", i.c_str(), PlGetError() );\n\t\t\tcontinue;\n\t\t}\n\n\t\tPrint( \" Mounted location \\\"%s\\\"\\n\", mountPath );\n\t}\n\n\tPrint( \"Mod has been set to \\\"%s\\\"\\n\", mod->name.c_str() );\n\n#if defined( _DEBUG )\n\tPlParseConsoleString( \"fsListMounted\" );\n#endif\n}\n\nvoid ohw::ModManager::Unmount() {\n\t// If a modification is already mounted, unmount it\n\tif ( myCurrentMod != nullptr ) {\n\t\tfor ( const auto &i: myCurrentMod->mountList ) {\n\t\t\tPlClearMountedLocation( i );\n\t\t}\n\n\t\tmyCurrentMod->mountList.clear();\n\t}\n\n\t// Clear out all the content we've loaded, we'll need to load all our major dependencies after\n\tGetApp()->resourceManager->ClearAllResources( true );\n}\n\n/**\n * Load in the mod manifest and store it into a buffer.\n * @param path Path to the manifest file.\n */\nvoid ohw::ModManager::RegisterMod( const char *path, void *userData ) {\n\tohw::ModManager *modManager = static_cast<ModManager *>(userData);\n\n\tModDescription mod = LoadDescription( path );\n\tmodManager->myModsMap.emplace( mod.internalName, mod );\n}\n\nvoid ohw::ModManager::FetchDependencies( ModDescription *modDescription, DirectorySet &output ) {\n\tconst auto &dir = output.find( modDescription->directory );\n\tif ( dir != output.end() ) {\n\t\tPrint( \"%s is already mounted, skipping\\n\", modDescription->directory.c_str() );\n\t\treturn;\n\t}\n\n\tfor ( const auto &i: modDescription->dependencies ) {\n\t\tconst char *name = i.c_str();\n\t\tModDescription *dependency = GetModDescription( name );\n\t\tif ( dependency == nullptr ) {\n\t\t\tWarning( \"Failed to fetch dependency for mod, \\\"%s\\\"!\\n\", name );\n\t\t\treturn;\n\t\t}\n\n\t\tif ( !dependency->dependencies.empty() ) {\n\t\t\tFetchDependencies( dependency, output );\n\t\t}\n\n\t\toutput.emplace( dependency->directory );\n\t}\n}\n\nohw::ModManager::ModDescription *ohw::ModManager::GetModDescription( const char *name ) {\n\tauto campaign = myModsMap.find( name );\n\tif ( campaign != myModsMap.end() ) {\n\t\treturn &campaign->second;\n\t}\n\n\tWarning( \"Failed to find mod \\\"%s\\\"!\\n\" );\n\treturn nullptr;\n}\n\nohw::ModManager::ModDescription ohw::ModManager::LoadDescription( const char *path ) {\n\tPrint( \"Loading manifest \\\"%s\\\"...\\n\", path );\n\n\tModDescription modDescription;\n\ttry {\n\t\tJsonReader config( path );\n\n\t\tmodDescription.name = config.GetStringProperty( \"name\" );\n\t\tmodDescription.version = config.GetStringProperty( \"version\", \"Unknown\", true );\n\t\tmodDescription.author = config.GetStringProperty( \"author\", \"Unknown\", true );\n\t\tmodDescription.isVisible = config.GetBooleanProperty( \"isVisible\", false, true );\n\n\t\tchar filename[64];\n\t\tsnprintf( filename, sizeof( filename ), \"%s\", PlGetFileName( path ) );\n\t\tmodDescription.fileName = path;\n\t\tmodDescription.internalName = std::string( filename, strlen( filename ) - 4 );\n\t\tmodDescription.directory = modDescription.internalName + \"/\";\n\n\t\tmodDescription.dependencies = config.GetArrayStrings( \"dependencies\" );\n\t} catch ( const std::exception &e ) {\n\t\tError( \"Failed to read mod config, \\\"%s\\\"!\\n%s\\n\", path, e.what() );\n\t}\n\n\treturn modDescription;\n}\n"
  },
  {
    "path": "src/engine/ModManager.h",
    "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// Copyright © 2017-2022 TalonBrave.info and Others (see CONTRIBUTORS)\n\n#pragma once\n\n#include <map>\n#include <set>\n\nnamespace ohw {\n\tclass ModManager {\n\tpublic:\n\t\tModManager();\n\n\t\tvoid Mount( const char *name );\n\t\tvoid Unmount();\n\n\t\tstruct ModDescription {\n\t\t\tstd::string fileName;\n\t\t\tstd::string internalName;\n\t\t\tstd::string directory;\n\n\t\t\t// Modification Details\n\t\t\tstd::string name; /// Name of the mod\n\t\t\tstd::string version; /// The version of the mod\n\t\t\tstd::string author; /// Who created the mod\n\t\t\tstd::vector<std::string> dependencies; /// Other mods this mod depends on\n\t\t\tbool isVisible = false; /// Whether or not the mod is selectable\n\n\t\t\tstd::vector<PLFileSystemMount*> mountList; /// Pointers to the mounted directory handle\n\t\t};\n\t\ttypedef std::map< std::string, ModDescription > ModsMap;\n\t\tinline const ModsMap *GetAvailableMods() const {\n\t\t\treturn &myModsMap;\n\t\t}\n\n\t\tinline const ModDescription *GetCurrentModDescription() const {\n\t\t\treturn myCurrentMod;\n\t\t}\n\n\tprivate:\n\t\tstatic void RegisterMod( const char *path, void *userData );\n\n\t\ttypedef std::set<std::string> DirectorySet;\n\t\tvoid FetchDependencies( ModDescription *modDescription, DirectorySet &output );\n\n\t\tModDescription *GetModDescription( const char *name );\n\t\tstatic ModDescription LoadDescription( const char *path );\n\n\t\tModsMap myModsMap;\n\t\tModDescription *myCurrentMod{ nullptr };\n\t};\n}\n"
  },
  {
    "path": "src/engine/ModelResource.cpp",
    "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// Copyright © 2017-2022 TalonBrave.info and Others (see CONTRIBUTORS)\n\n#include \"App.h\"\n#include \"ModelResource.h\"\n#include \"TextureAtlas.h\"\n#include \"mesh.h\"\n#include \"WaveFrontReader.h\"\n#include \"graphics/Camera.h\"\n\n#include \"loaders/VtxLoader.h\"\n#include \"loaders/FacLoader.h\"\n#include \"loaders/No2Loader.h\"\n\nohw::ModelResource::ModelResource( const std::string &path, bool persist, bool abortOnFail ) :\n\t\tResource( path, persist ) {\n\tconst char *fileExt = PlGetFileExtension( path.c_str() );\n\tif ( fileExt == nullptr ) {\n\t\tif ( abortOnFail ) {\n\t\t\tError( \"Failed to fetch file extension, \\\"%s\\\"!\\n\", path.c_str() );\n\t\t}\n\n\t\tWarning( \"Failed to fetch file extension, \\\"%s\\\"!\\n\", path.c_str() );\n\t\treturn;\n\t}\n\n\tif ( pl_strcasecmp( fileExt, \"vtx\" ) == 0 ) {\n\t\t// It's a vtx model, so we'll be expecting a Fac and No2 as well\n\t\tLoadVtxModel( path, abortOnFail );\n\t} else if ( pl_strcasecmp( fileExt, \"min\" ) == 0 ) {\n\t\t// Min model format is used for the PSX version\n\t\tLoadMinModel( path, abortOnFail );\n\t} else if ( pl_strcasecmp( fileExt, \"obj\" ) == 0 ) {\n\t\t// Static Obj model format\n\t\tLoadObjModel( path, abortOnFail );\n\t} else {\n\t\tif ( abortOnFail ) {\n\t\t\tError( \"Unrecognised file extension, \\\"%s\\\"!\\n\", fileExt );\n\t\t}\n\n\t\tWarning( \"Unrecognised file extension, \\\"%s\\\"!\\n\", fileExt );\n\t\treturn;\n\t}\n\n\tGenerateBounds();\n}\n\nohw::ModelResource::~ModelResource() {\n\tDestroyMeshes();\n}\n\nvoid ohw::ModelResource::Tick() {\n\t// TODO: animation is handled here...\n}\n\nvoid ohw::ModelResource::Draw( bool cull, bool batchDraw ) {\n\tCamera *camera = GetApp()->gameManager->GetActiveCamera();\n\tif ( camera == nullptr ) {\n\t\treturn;\n\t}\n\n\tbounds.origin = PlGetMatrix4Translation( &modelMatrix );\n\tif ( cv_graphics_cull->b_value && cull && !camera->IsBoxVisible( &bounds ) ) {\n\t\treturn;\n\t}\n\n\tif ( cv_debug_bounds->b_value ) {\n\t\tPlgDrawBoundingVolume( &bounds, PL_COLOUR_BLUE );\n\t}\n\n\tif ( meshesVector.empty() ) {\n\t\tPLMModel *model = GetApp()->resourceManager->GetFallbackModel();\n\t\tif ( model == nullptr ) {\n\t\t\treturn;\n\t\t}\n\n\t\tmodel->modelMatrix = modelMatrix;\n\n\t\tPlmDrawModel( model );\n\t\treturn;\n\t}\n\n\t// If specified, just add it to our list and return\n\tif ( batchDraw ) {\n\t\tbatchedDrawCalls.push_back( modelMatrix );\n\t\treturn;\n\t}\n\n\tfor ( unsigned int i = 0; i < meshesVector.size(); ++i ) {\n\t\tDrawMesh( i );\n\t}\n\n\tif ( cv_graphics_debug_normals->b_value ) {\n\t\tDrawNormals();\n\t}\n}\n\nPLGMesh *ohw::ModelResource::GetInternalMesh( unsigned int i ) {\n\tu_assert( i < meshesVector.size() );\n\tif ( i >= meshesVector.size() ) {\n\t\tWarning( \"Attempted to access an invalid mesh (%d/%d)!\\n\", i, meshesVector.size() );\n\t\treturn nullptr;\n\t}\n\n\treturn meshesVector[ i ];\n}\n\nohw::TextureResource *ohw::ModelResource::GetTextureResource( unsigned int i ) {\n\tu_assert( i < texturesVector.size() );\n\tif ( i >= texturesVector.size() ) {\n\t\tWarning( \"Attempted to access an invalid texture (%d/%d)!\\n\", i, texturesVector.size() );\n\t\treturn nullptr;\n\t}\n\n\treturn texturesVector[ i ];\n}\n\nvoid ohw::ModelResource::LoadObjModel( const std::string &path, bool abortOnFail ) {\n\tWaveFrontReader obj;\n\tif ( !obj.Load( path, true ) ) {\n\t\treturn;\n\t}\n\n\t// Single material Objs are really damn easy here...\n\tif ( obj.materials.size() <= 2 ) {\n\t\tPLGMesh *mesh = PlgCreateMesh( PLG_MESH_TRIANGLES, PLG_DRAW_STATIC, obj.indices.size(), obj.vertices.size() );\n\t\tif ( mesh == nullptr ) {\n\t\t\tif ( abortOnFail ) {\n\t\t\t\tError( \"Failed to create mesh! (%s)\\n\", PlGetError() );\n\t\t\t}\n\n\t\t\tWarning( \"Failed to create mesh! (%s)\\n\", PlGetError() );\n\t\t\treturn;\n\t\t}\n\n\t\tstatic_assert( sizeof( *mesh->indices ) == sizeof( *obj.indices.data() ), \"mismatch\" );\n\t\t// Copy all of the data across\n\t\tmemcpy( mesh->indices, obj.indices.data(), sizeof( unsigned int ) * obj.indices.size() );\n\t\tmemcpy( mesh->vertices, obj.vertices.data(), sizeof( PLGVertex ) * obj.vertices.size() );\n\n\t\tstd::string textureName = obj.materials[ obj.attributes[ 0 ] ].strTexture;\n\t\tif ( obj.materials.size() > 1 && !textureName.empty() ) {\n\t\t\tSharedTextureResourcePointer texture = GetApp()->resourceManager->LoadTexture( textureName );\n\t\t\ttexturesVector.push_back( texture );\n\n\t\t\tmesh->texture = texture->GetInternalTexture();\n\t\t} else {\n\t\t\tmesh->texture = GetApp()->resourceManager->GetFallbackTexture();\n\t\t}\n\n\t\t// Push the mesh into our vector\n\t\tmeshesVector.push_back( mesh );\n\n\t\t// And done!\n\t\treturn;\n\t}\n\n\t// However we need to do some extra work for those that use multiple materials...\n\n\tstruct MeshSet {\n\t\tstd::vector< unsigned int > indices;\n\t\tWaveFrontReader::Material material;\n\t};\n\tstd::map< unsigned int, MeshSet > meshSets;\n\n\tfor ( unsigned int i = 0; i < obj.indices.size(); ++i ) {\n\t\tmeshSets[ obj.attributes[ i / 3 ] ].indices.push_back( obj.indices[ i ] );\n\t\tmeshSets[ obj.attributes[ i / 3 ] ].material = obj.materials[ obj.attributes[ i / 3 ] ];\n\t}\n\n\tmeshesVector.resize( meshSets.size() );\n\n\tauto j = meshSets.begin();\n\tfor ( unsigned int i = 0; j != meshSets.end(); ++j ) {\n\t\tmeshesVector[ i ] = PlgCreateMesh( PLG_MESH_TRIANGLES, PLG_DRAW_STATIC, j->second.indices.size(),\n\t\t                                   obj.vertices.size() );\n\t\tif ( meshesVector[ i ] == nullptr ) {\n\t\t\tif ( abortOnFail ) {\n\t\t\t\tError( \"Failed to create mesh!\\nPL: %s\\n\", PlGetError() );\n\t\t\t}\n\n\t\t\t// Destroy all the attached meshes\n\t\t\tDestroyMeshes();\n\n\t\t\tWarning( \"Failed to create mesh!\\nPL: %s\\n\", PlGetError() );\n\t\t\treturn;\n\t\t}\n\n\t\tmemcpy( meshesVector[ i ]->vertices, obj.vertices.data(), sizeof( PLGVertex ) * obj.vertices.size() );\n\t\tmemcpy( meshesVector[ i ]->indices, j->second.indices.data(),\n\t\t        sizeof( unsigned int ) * j->second.indices.size() );\n\n\t\tif ( !j->second.material.strTexture.empty() ) {\n\t\t\tSharedTextureResourcePointer texture = GetApp()->resourceManager->LoadTexture( j->second.material.strTexture );\n\t\t\ttexturesVector.push_back( texture );\n\n\t\t\tmeshesVector[ i ]->texture = texture->GetInternalTexture();\n\t\t} else {\n\t\t\tmeshesVector[ i ]->texture = GetApp()->resourceManager->GetFallbackTexture();\n\t\t}\n\n\t\t++i;\n\t}\n\n\t// Done!\n}\n\nstatic ohw::TextureAtlas *ModelResource_GenerateVtxTextureAtlas( const FacHandle *facHandle, const std::string &texturePath ) {\n\tif ( facHandle->texture_table_size == 0 ) {\n\t\tWarning( \"Empty texture table!\\n\" );\n\t\treturn nullptr;\n\t}\n\n\tohw::TextureAtlas *atlas = new ohw::TextureAtlas( 128, 128 );\n\n\tfor ( unsigned int i = 0; i < facHandle->texture_table_size; ++i ) {\n\t\tif ( facHandle->texture_table[ i ].name[ 0 ] == '\\0' ) {\n\t\t\tWarning( \"Invalid texture name in table, skipping (%d)!\\n\", i );\n\t\t\tcontinue;\n\t\t}\n\n\t\tstd::string str = texturePath;\n\t\tstd::string texture_path = str.erase( str.find_last_of( '/' ) ) + \"/\";\n\t\tif ( !atlas->AddImage( texture_path + facHandle->texture_table[ i ].name + \".png\", true ) ) {\n\t\t\tWarning( \"Failed to add texture \\\"%s\\\" to atlas!\\n\", facHandle->texture_table[ i ].name );\n\t\t}\n\t}\n\n\tatlas->Finalize();\n\n\treturn atlas;\n}\n\n/**\n * Loader for Hogs of War's PC model format\n */\nvoid ohw::ModelResource::LoadVtxModel( const std::string &path, bool abortOnFail ) {\n\t// Load in the vertices\n\tVtxHandle *vtxHandle = Vtx_LoadFile( path.c_str() );\n\tif ( vtxHandle == nullptr ) {\n\t\tif ( abortOnFail ) {\n\t\t\tError( \"Failed to load Vtx, \\\"%s\\\"!\\n\", path.c_str() );\n\t\t}\n\n\t\tWarning( \"Failed to load Vtx, \\\"%s\\\"!\\n\", path.c_str() );\n\t\treturn;\n\t}\n\n\t// Load in the faces\n\tchar facesPath[PL_SYSTEM_MAX_PATH];\n\tu_new_filename( facesPath, path.c_str(), \"fac\" );\n\tFacHandle *facHandle = Fac_LoadFile( facesPath );\n\tif ( facHandle == nullptr ) {\n\t\tif ( abortOnFail ) {\n\t\t\tError( \"Failed to load Fac, \\\"%s\\\"!\\n\", facesPath );\n\t\t}\n\n\t\tVtx_DestroyHandle( vtxHandle );\n\n\t\tWarning( \"Failed to load Fac, \\\"%s\\\"!\\n\", facesPath );\n\t\treturn;\n\t}\n\n\t// There are some special cases, so let's go ahead and deal with those...\n\tconst char *fileName = PlGetFileName( path.c_str() );\n\tif ( pl_strcasecmp( fileName, \"skydome.vtx\" ) == 0 || pl_strcasecmp( fileName, \"skydomeu.vtx\" ) == 0 ) {\n\t\tPLGMesh *mesh = PlgCreateMesh( PLG_MESH_TRIANGLES, PLG_DRAW_STATIC, facHandle->num_triangles,\n\t\t                               vtxHandle->num_vertices );\n\t\tif ( mesh == nullptr ) {\n\t\t\tif ( abortOnFail ) {\n\t\t\t\tError( \"Failed to create mesh!\\nPL: %s\\n\", PlGetError() );\n\t\t\t}\n\n\t\t\tVtx_DestroyHandle( vtxHandle );\n\t\t\tFac_DestroyHandle( facHandle );\n\n\t\t\tWarning( \"Failed to create mesh!\\nPL: %s\\n\", PlGetError() );\n\t\t\treturn;\n\t\t}\n\n\t\t// Now we can set up our mesh\n\n\t\tfor ( unsigned int j = 0; j < vtxHandle->num_vertices; ++j ) {\n\t\t\tPlgSetMeshVertexPosition( mesh, j, hei::Vector3( vtxHandle->vertices[ j ].position ) * -1.0f * 0.5f );\n\t\t}\n\n\t\tunsigned int cur_index = 0;\n\t\tfor ( unsigned int j = 0; j < facHandle->num_triangles; ++j ) {\n\t\t\tPlgSetMeshTrianglePosition( mesh, &cur_index,\n\t\t\t                            facHandle->triangles[ j ].vertex_indices[ 0 ],\n\t\t\t                            facHandle->triangles[ j ].vertex_indices[ 1 ],\n\t\t\t                            facHandle->triangles[ j ].vertex_indices[ 2 ]\n\t\t\t);\n\t\t}\n\n\t\t// All done, throw these out now\n\t\tVtx_DestroyHandle( vtxHandle );\n\t\tFac_DestroyHandle( facHandle );\n\n\t\tmesh->texture = GetApp()->resourceManager->GetFallbackTexture();\n\n\t\tmeshesVector.push_back( mesh );\n\t\treturn;\n\t}\n\n\tPLGMesh *mesh = PlgCreateMesh( PLG_MESH_TRIANGLES, PLG_DRAW_STATIC, facHandle->num_triangles,\n\t                               facHandle->num_triangles * 3 );\n\tif ( mesh == nullptr ) {\n\t\tif ( abortOnFail ) {\n\t\t\tError( \"Failed to create mesh!\\nPL: %s\\n\", PlGetError() );\n\t\t}\n\n\t\tVtx_DestroyHandle( vtxHandle );\n\t\tFac_DestroyHandle( facHandle );\n\n\t\tWarning( \"Failed to create mesh!\\nPL: %s\\n\", PlGetError() );\n\t\treturn;\n\t}\n\n\t// Attempt to load in the normals, it's fine if these don't successfully load as we'll just generate them instead later\n\tchar normalsPath[PL_SYSTEM_MAX_PATH];\n\tu_new_filename( normalsPath, path.c_str(), \"no2\" );\n\tNo2Handle *no2Handle = No2_LoadFile( normalsPath );\n\n\t// Need to scale the model up, as the models are actually a little bit smaller than our terrain :(\n\tfor ( unsigned int j = 0; j < vtxHandle->num_vertices; ++j ) {\n\t\tvtxHandle->vertices[ j ].position = PlScaleVector3F( vtxHandle->vertices[ j ].position, 0.5f );\n\t}\n\n\t// automatically returns default if failed\n\tstd::string texturePath = facesPath;\n\t// Temporary hack just to get the pig textures loaded\n\tif ( strstr( facesPath, \"pigs\" ) != nullptr ) {\n\t\ttexturePath = \"chars/pigs/british/\";\n\t}\n\n\t// Now create the atlas itself\n\tTextureAtlas *textureAtlas = ModelResource_GenerateVtxTextureAtlas( facHandle, texturePath );\n\n\tunsigned int curIndex = 0;\n\tfor ( unsigned int i = 0, nextVtxIndex = 0; i < facHandle->num_triangles; ++i ) {\n\t\tfor ( unsigned int triVtxIndex = 0; triVtxIndex < 3; ++triVtxIndex, ++nextVtxIndex ) {\n\t\t\tunsigned int triVtx = facHandle->triangles[ i ].vertex_indices[ triVtxIndex ];\n\n\t\t\tPlgSetMeshVertexColour( mesh, nextVtxIndex, PL_COLOUR_WHITE );\n\t\t\tPlgSetMeshVertexPosition( mesh, nextVtxIndex, vtxHandle->vertices[ triVtx ].position );\n\n\t\t\tif ( no2Handle != nullptr ) {\n\t\t\t\tunsigned int normalIndex = facHandle->triangles[ i ].normal_indices[ triVtxIndex ];\n\t\t\t\tPlgSetMeshVertexNormal( mesh, nextVtxIndex, no2Handle->normals[ normalIndex ] );\n\t\t\t}\n\n\t\t\t//todo\n\t\t\t//mesh->vertices[ nextVtxIndex ].bone_index = vtxHandle->vertices[ triVtx ].bone_index;\n\t\t\t//mesh->vertices[ nextVtxIndex ].bone_weight = 1.0f;\n\t\t}\n\n\t\tPlgSetMeshTrianglePosition( mesh, &curIndex, nextVtxIndex - 1, nextVtxIndex - 2, nextVtxIndex - 3 );\n\n\t\tif ( facHandle->texture_table != nullptr && textureAtlas != nullptr ) {\n\t\t\tconst char *textureName = facHandle->texture_table[ facHandle->triangles[ i ].texture_index ].name;\n\n\t\t\tfloat tX, tY, tW, tH;\n\t\t\ttextureAtlas->GetTextureCoords( textureName, &tX, &tY, &tW, &tH );\n\n\t\t\tstd::pair< unsigned int, unsigned int > textureSize = textureAtlas->GetTextureSize( textureName );\n\n\t\t\tfor ( unsigned int j = 0, u = 0; j < 3; ++j, u += 2 ) {\n\t\t\t\tPlgSetMeshVertexST( mesh, nextVtxIndex - ( 3 - j ),\n\t\t\t\t                    tX + ( tW * ( 1.0f / ( float ) ( textureSize.first ) ) *\n\t\t\t\t                           ( float ) ( facHandle->triangles[ i ].uv_coords[ u ] ) ),\n\t\t\t\t                    tY + ( tH * ( 1.0f / ( float ) ( textureSize.second ) ) *\n\t\t\t\t                           ( float ) ( facHandle->triangles[ i ].uv_coords[ u + 1 ] ) ) );\n\t\t\t}\n\t\t}\n\t}\n\n\tif ( textureAtlas != nullptr ) {\n\t\t// TODO: we have no way of cleaning this up right now...\n\t\tmesh->texture = textureAtlas->GetTexture();\n\t} else {\n\t\tmesh->texture = GetApp()->resourceManager->GetFallbackTexture();\n\t}\n\n\tdelete textureAtlas;\n\n\t// Normals weren't loaded in, so attempt to generate them\n#if 0\n\tif ( no2Handle == nullptr ) {\n\t\tstd::list< PLMesh * > meshes( &mesh, &mesh + 1 );\n\t\tMesh_GenerateFragmentedMeshNormals( meshes );\n\t} else {\n\t\tNo2_DestroyHandle( no2Handle );\n\t}\n#else\n\t// Always generate normals until we handle No2 correctly\n\tstd::list< PLGMesh * > meshes( &mesh, &mesh + 1 );\n\tMesh_GenerateFragmentedMeshNormals( meshes );\n#endif\n\n\tmeshesVector.push_back( mesh );\n\n\t// Done!\n}\n\n/**\n * Loader for Hogs of War's PSX model format\n */\nvoid ohw::ModelResource::LoadMinModel( const std::string &path, bool abortOnFail ) {\n\tu_assert( 0, \"TODO\" );\n}\n\n/**\n * Draws the specified mesh.\n */\nvoid ohw::ModelResource::DrawMesh( unsigned int i ) {\n\tu_assert( i < meshesVector.size() );\n\tif ( i >= meshesVector.size() ) {\n\t\tError( \"Attempted to access an invalid mesh (%d/%d)!\\n\", i, meshesVector.size() );\n\t}\n\n\tPLGShaderProgram *program = PlgGetCurrentShaderProgram();\n\tif ( program == nullptr ) {\n\t\tError( \"No bound shader program when drawing mesh %d!\\n\", i );\n\t}\n\n\t// TODO: This currently doesn't handle animations...\n\t// TODO: We should be batching the same things too!\n\n\tPlgSetTexture( meshesVector[ i ]->texture, 0 );\n\n\tPlgSetShaderUniformValue( program, \"pl_model\", &modelMatrix, true );\n\n\tPlgUploadMesh( meshesVector[ i ] );\n\tPlgDrawMesh( meshesVector[ i ] );\n}\n\n/**\n * Draws all the normals per mesh.\n */\nvoid ohw::ModelResource::DrawNormals() {\n\tfor ( auto i: meshesVector ) {\n\t\tPlgDrawMeshNormals( i );\n\t}\n}\n\n/**\n * Draw the model's skeleton if it's animated.\n */\nvoid ohw::ModelResource::DrawSkeleton() {\n\tif ( !isAnimated ) {\n\t\treturn;\n\t}\n\n\t// TODO: draw the bones...\n}\n\nvoid ohw::ModelResource::DestroyMeshes() {\n\tfor ( auto mesh: meshesVector ) {\n\t\tif ( mesh == nullptr ) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tPlgDestroyMesh( mesh );\n\t}\n\n\tmeshesVector.clear();\n\tmeshesVector.shrink_to_fit();\n}\n\n/**\n * Generate a bounding volume for the model. Used for visibility culling.\n */\nvoid ohw::ModelResource::GenerateBounds() {\n\tif ( meshesVector.empty() ) {\n\t\treturn;\n\t}\n\n\t// Gather all the vertices from every mesh\n\tstd::vector< PLGVertex > vertices;\n\tfor ( const auto &mesh: meshesVector ) {\n\t\tvertices.insert( vertices.end(), mesh->vertices, mesh->vertices + mesh->num_verts );\n\t}\n\n\t// And now generate the bounds\n\tbounds = PlgGenerateAabbFromVertices( vertices.data(), vertices.size(), false );\n\n\t// TODO: handle animations somehow? We might need to call this for each animation frame for animated models...\n}\n"
  },
  {
    "path": "src/engine/ModelResource.h",
    "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// Copyright © 2017-2022 TalonBrave.info and Others (see CONTRIBUTORS)\n\n#pragma once\n\n#include \"Resource.h\"\n#include \"TextureResource.h\"\n\nnamespace ohw {\n\tclass ModelResource : public Resource {\n\tpublic:\n\t\tIMPLEMENT_RESOURCE_CLASS( ModelResource )\n\n\t\texplicit ModelResource( const std::string &path, bool persist = false, bool abortOnFail = false );\n\t\t~ModelResource();\n\n\t\tstruct Keyframe {\n\t\t\tPLVector3 transforms[10];\n\t\t\tPLQuaternion rotations[15];\n\t\t};\n\n\t\tstruct Animation {\n\t\t\tunsigned int id;\n\t\t\tconst char *name;\n\n\t\t\tKeyframe *frames;\n\t\t\tunsigned int num_frames;\n\t\t};\n\n\t\tvoid Tick();\n\n\t\tvoid Draw( bool cull = true, bool batchDraw = false );\n\t\tvoid DrawNormals();\n\t\tvoid DrawSkeleton();\n\n\t\t// Batching\n\n\t\tinline void AddDrawToQueue( const PLMatrix4 &transform ) {\n\t\t\tbatchedDrawCalls.push_back( transform );\n\t\t}\n\n\t\tinline unsigned int GetNumberOfQueuedDraws() const {\n\t\t\treturn batchedDrawCalls.size();\n\t\t}\n\n\t\tinline void ClearQueuedDraws() {\n\t\t\tbatchedDrawCalls.clear();\n\t\t}\n\n\t\t// Mesh state\n\n\t\tinline unsigned int GetNumberOfMeshes() const { return meshesVector.size(); }\n\t\tPLGMesh *GetInternalMesh( unsigned int i );\n\n\t\tconst PLCollisionAABB &GetBounds() const { return bounds; }\n\n\t\tTextureResource *GetTextureResource( unsigned int i );\n\n\t\tinline bool IsAnimated() const { return isAnimated; }\n\n\t\tPLMatrix4 modelMatrix{};\n\n\tprivate:\n\t\tvoid LoadObjModel( const std::string &path, bool abortOnFail );\n\t\tvoid LoadVtxModel( const std::string &path, bool abortOnFail );\n\t\tvoid LoadMinModel( const std::string &path, bool abortOnFail );\n\n\t\tvoid DrawMesh( unsigned int i );\n\n\t\tvoid DestroyMeshes();\n\n\t\tvoid GenerateBounds();\n\n\t\tbool isAnimated{ false };\n\n\t\tstd::vector< SharedTextureResourcePointer > texturesVector; // List of textures this model depends on\n\n\t\tstd::vector< PLGMesh * > meshesVector;       // Sub-meshes that are part of this model\n\t\tstd::vector< PLMatrix4 > batchedDrawCalls;  // Draw queue. Anything queued up will be pushed to the GPU in one batch\n\n\t\tPLCollisionAABB bounds;\n\t};\n\n\tusing SharedModelResourcePointer = SharedResourcePointer< ModelResource >;\n}\n"
  },
  {
    "path": "src/engine/Physics.h",
    "content": "/* OpenHoW\n * Copyright (C) 2017-2020 TalonBrave.info and Others (see CONTRIBUTORS)\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#pragma once\n\n// Physics Declarations\n\nenum {\n    /* ...original... */\n    PHYS_BOUNDS_BOX     = 0,\n    PHYS_BOUNDS_PRISM   = 1,\n    PHYS_BOUNDS_SPHERE  = 2,\n    PHYS_BOUNDS_NONE    = 3,\n    /* ...any new types below... */\n\n    MAX_PHYS_BOUND_TYPES\n};\n"
  },
  {
    "path": "src/engine/Property.cpp",
    "content": "/* OpenHoW\n * Copyright (C) 2017-2019 Daniel Collins <solemnwarning@solemnwarning.net>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include \"App.h\"\n#include \"Property.h\"\n\nProperty::Property( PropertyOwner &po, const std::string &name, unsigned flags ) :\n\t\tname( name ),\n\t\tflags( flags ),\n\t\tpo_( po ),\n\t\tis_dirty_( false ) {\n\tauto x = po_.properties_.insert( std::make_pair( name, this ) );\n\tu_assert( x.second ); /* Check for name collision */\n}\n\nProperty::Property( PropertyOwner &po, const Property &src ) :\n\t\tname( src.name ),\n\t\tflags( src.flags ),\n\t\tpo_( po ),\n\t\tis_dirty_( src.is_dirty_ ),\n\t\tdirty_since_( src.dirty_since_ ),\n\t\tclean_serialised_( src.clean_serialised_ ) {\n\tauto x = po_.properties_.insert( std::make_pair( name, this ) );\n\tu_assert( x.second ); /* Check for name collision */\n}\n\nProperty::~Property() {\n\tpo_.properties_.erase( name );\n}\n\nvoid Property::MarkClean() {\n\tclean_serialised_ = Serialise();\n\tis_dirty_ = false;\n}\n\nvoid Property::MarkDirty() {\n\tif ( !is_dirty_ ) {\n\t\tis_dirty_ = true;\n\t\tdirty_since_ = ohw::GetApp()->GetTicks();\n\t}\n}\n\nvoid Property::ResetToClean() {\n\tDeserialise( clean_serialised_ );\n\tMarkClean();\n}\n\nunsigned int Property::DirtyTicks() const {\n\tif ( is_dirty_ ) {\n\t\treturn ohw::GetApp()->GetTicks() - dirty_since_;\n\t} else {\n\t\treturn 0;\n\t}\n}\n\nPropertyOwner::PropertyOwner() {}\nPropertyOwner::~PropertyOwner() {}\n\nstd::string PropertyOwner::SerializePropertiesAsJson() {\n\treturn \"\";\n}\n"
  },
  {
    "path": "src/engine/Property.h",
    "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// Copyright © 2017-2022 TalonBrave.info and Others (see CONTRIBUTORS)\n\n#pragma once\n\n#include <map>\n#include <sstream>\n#include <string>\n#include <string.h>\n\n/**\n * @defgroup PropertyFlags Property flags\n */\n/*@{*/\n\n#define PROP_PUSH       (1U << 0)  /**< Property changes should be pushed from client to server.\n                                        Implies PROP_IMMEDIATE. */\n\n#define PROP_IMMEDIATE  (1U << 1)  /**< Property changes should be propogated from server\n                                        immediately */\n\n#define PROP_DISCARD    (1U << 2)  /**< Property value can be discarded when saving/loading game */\n\n#define PROP_LOCAL      (1U << 3)  /**< Property value is not sync'd between peers */\n\n#define PROP_WRITE      (1U << 4)  /**< Property value can be modified locally */\n\n/*@}*/\n\n/**\n * @brief Helper macro for initialising properties.\n *\n * @param name   Name of member (bareword)\n * @param flags  PROP_XXX flags\n * @param ...    Extra parameters to property constructor\n*/\n#define INIT_PROPERTY(name, flags, ...) name(*(PropertyOwner*)this, #name, flags, ##__VA_ARGS__)\n\n/**\n * @brief Helper macro for copying-constructing properties.\n *\n * @param name  Name of member (bareword)\n * @param src   Name of source structure (bareword)\n*/\n#define COPY_PROPERTY(name, src) name(*(PropertyOwner*)this, src.name)\n\nclass JsonReader;\nclass PropertyOwner;\n\n/**\n * @brief Base class for all properties. Pure virtual.\n*/\nclass Property {\npublic:\n\tconst std::string name;\n\tconst std::string description;\n\tconst unsigned flags;\n\n\t/* No copy/assignment c'tors. */\n\tProperty( const Property& ) = delete;\n\tProperty& operator=( const Property& ) = delete;\n\n\t/**\n\t * @brief Returns the serialised form of the property's value.\n\t *\n\t * Serialises the property's value using std::string as a container. The value may\n\t * or may not be a printable string; treat it as a byte array.\n\t*/\n\t\tvirtual std::string Serialise() const = 0;\n\n        /**\n         * Returns the property formatted as Json.\n         */\n        virtual std::string SerialiseAsJson() const = 0;\n\n\t\t/**\n\t\t * @brief Set the property to the given serialised form.\n\t\t *\n\t\t * Sets the value to the given serialised one, which must have been returned from\n\t\t * a call to Serialise(). Marks the property as dirty.\n\t\t *\n\t\t * Throws XXX and makes no change to the property if the serialised form isn't\n\t\t * valid.\n\t\t*/\n\t\tvirtual void Deserialise(const std::string &serialised) = 0;\n\n\t\t/**\n\t\t * @brief Mark the property as clean and save the current value.\n\t\t*/\n\t\tvoid MarkClean();\n\n\t\t/**\n\t\t * @brief Mark the property as dirty.\n\t\t *\n\t\t * If the property is clean, records the current tick count and marks it as dirty,\n\t\t * otherwise does nothing.\n\t\t*/\n\t\tvoid MarkDirty();\n\n\t\t/**\n\t\t * @brief Restore the last clean value and mark the property clean.\n\t\t *\n\t\t * Restores the value saved in the last call to MarkClean() and marks the property\n\t\t * as clean again.\n\t\t*/\n\t\tvoid ResetToClean();\n\n\t\t/**\n\t\t * @brief Returns the number of ticks the property has been dirty for.\n\t\t*/\n\t\tunsigned int DirtyTicks() const;\n\n\tprotected:\n\t\tPropertyOwner &po_;\n\n\t\tProperty(PropertyOwner &po, const std::string &name, unsigned flags);\n\t\tProperty(PropertyOwner &po, const Property &src);\n\t\tvirtual ~Property();\n\n\tprivate:\n\t\tbool is_dirty_;\n\t\tunsigned int dirty_since_{ 0 };\n\n\t\tstd::string clean_serialised_;\n};\n\ntypedef std::map<std::string, Property*> PropertyMap;\n\n/**\n * @brief Base class for actors, game modes, etc to allow them to have properties.\n*/\nclass PropertyOwner\n{\n\tfriend Property;\n\n\tpublic:\n\t\t/* These are no-ops because copying or assigning a PropertyOwner class should just\n\t\t * assign/copy the properties under it, which will be registered when the property\n\t\t * is copy-constructed, or already registered in the case of assignment.\n\t\t*/\n\t\tPropertyOwner(const PropertyOwner&) {}\n\t\tPropertyOwner& operator=(const PropertyOwner&) { return *this; }\n\n\t\tconst PropertyMap& GetProperties() { return properties_; }\n\n\t\tvirtual std::string SerializePropertiesAsJson();\n\n\tprotected:\n\t\tPropertyOwner();\n\t\tvirtual ~PropertyOwner();\n\n\tprivate:\n\t\t/** Properties registered under this object */\n        PropertyMap properties_;\n};\n\n/**\n * @brief Template class for numeric (integer or float) properties.\n*/\ntemplate<typename T> class NumericProperty: public Property\n{\n\tprivate:\n\t\tT value_;\n\n\tpublic:\n\t\tNumericProperty(PropertyOwner &po, const std::string &name, unsigned flags, T value = 0):\n\t\t\tProperty(po, name, flags), value_(value) {}\n\n\t\tNumericProperty(PropertyOwner &po, const NumericProperty<T> &src):\n\t\t\tProperty(po, src), value_(src.value_) {}\n\n\t\t/* Implicit conversion for using as a (const) T */\n\t\toperator const T&() const\n\t\t{\n\t\t\treturn value_;\n\t\t}\n\n        const T& operator=(const NumericProperty& value)\n        {\n          this->value_ = value;\n          MarkDirty();\n          return value;\n        }\n\n\t\t/**\n\t\t * @brief Assigns value, marks property dirty.\n\t\t *\n\t\t * @return Reference to provided value\n\t\t*/\n\t\tconst T& operator=(const T& value)\n\t\t{\n\t\t\tthis->value_ = value;\n\t\t\tMarkDirty();\n\n\t\t\treturn value;\n\t\t}\n\n\t\tstd::string Serialise() const override\n\t\t{\n\t\t\treturn std::string((const char*)(&value_), sizeof(value_));\n\t\t}\n\n        std::string SerialiseAsJson() const override {\n            return std::to_string(value_);\n        }\n\n\t\tvoid Deserialise(const std::string &serialised) override\n\t\t{\n\t\t\tu_assert(serialised.length() == sizeof(value_));\n\t\t\tmemcpy(&value_, serialised.data(), sizeof(value_));\n\t\t\tMarkDirty();\n\t\t}\n};\n\nclass VectorStringProperty : public Property {\n private:\n  std::vector<std::string> value_;\n\n public:\n  VectorStringProperty(PropertyOwner& po, const std::string& name, unsigned int flags,\n                       const std::vector<std::string>& value = {}) :\n      Property(po, name, flags), value_(value) {}\n\n  operator const std::vector<std::string>&() const {\n    return value_;\n  }\n\n  const std::vector<std::string>& operator=(const std::vector<std::string>& value) {\n    value_ = value;\n    MarkDirty();\n    return value;\n  }\n\n  std::string Serialise() const override {\n    std::string value;\n    for(const auto& i : value_) {\n      uint32_t l = i.length();\n      value += std::string((const char*)(&l), sizeof(l)) + i;\n    }\n    return value;\n  }\n\n  std::string SerialiseAsJson() const override {\n    std::string str = \"[\";\n    for(size_t i = 0; i < value_.size(); ++i) {\n      if(i > 0) {\n        str += \",\";\n      }\n      str += \"\\\"\" + value_[i] + \"\\\"\";\n    }\n    str += \"]\";\n    return str;\n  }\n\n  void Deserialise(const std::string& serialised) override {\n    value_.clear();\n\n    /* TODO: Assertions should be a bad-serialised-value exception */\n    for (size_t i = 0; i < serialised.length();) {\n      assert((i + sizeof(uint32_t)) < serialised.length());\n      uint32_t l = *(uint32_t*) (serialised.data() + i);\n      i += sizeof(uint32_t);\n\n      assert((i + l) < serialised.length());\n      value_.emplace_back((serialised.data() + i), l);\n      i += l;\n    }\n\n    MarkDirty();\n  }\n};\n\nclass StringProperty : public Property {\n private:\n  std::string value_;\n\n public:\n  StringProperty(PropertyOwner& po, const std::string& name, unsigned int flags, const std::string& value = \"\") :\n      Property(po, name, flags), value_(value) {}\n\n  StringProperty(PropertyOwner& po, const StringProperty &src):\n      Property(po, src), value_(src.value_) {}\n\n  operator const std::string&() const {\n    return value_;\n  }\n\n  const char *c_str() const {\n    return value_.c_str();\n  }\n\n  size_t length() const {\n  \treturn value_.length();\n  }\n\n  const std::string& operator=(const StringProperty& value) {\n    value_ = value;\n    MarkDirty();\n    return value;\n  }\n\n  const std::string& operator=(const std::string& value) {\n    value_ = value;\n    MarkDirty();\n    return value;\n  }\n\n  std::string Serialise() const override {\n    return value_;\n  }\n\n\tstd::string SerialiseAsJson() const override {\n\t\treturn \"\\\"\" + value_ + \"\\\"\";\n\t}\n\n\tvoid Deserialise( const std::string& serialised ) override {\n\t\tvalue_ = serialised;\n\t\tMarkDirty();\n\t}\n};\n\n/**\n * @brief Property class for vector3 properties.\n */\nclass Vector3Property : public Property {\nprivate:\n\thei::Vector3 value_;\n\npublic:\n\tVector3Property( PropertyOwner& po, const std::string& name, unsigned flags,\n\t\t\t\t\t hei::Vector3 value = { 0, 0, 0 } ) :\n\t\tProperty( po, name, flags ), value_( value ) {}\n\n\toperator const hei::Vector3&() const {\n\t\treturn value_;\n\t}\n\n\tconst hei::Vector3& GetValue() const {\n\t\treturn value_;\n\t}\n\n\tconst hei::Vector3& operator=( const hei::Vector3& value ) {\n\t\tvalue_ = value;\n\t\tMarkDirty();\n\t\treturn value;\n\t}\n\n\tstd::string SerialiseAsJson() const override {\n\t\treturn std::string(\n\t\t\tstd::to_string( value_.x ) + \" \" +\n\t\t\t\tstd::to_string( value_.y ) + \" \" +\n\t\t\t\tstd::to_string( value_.z ) );\n\t}\n\n\tstd::string Serialise() const override { return \"\"; } // todo\n\tvoid Deserialise( const std::string& serialised ) override {} // todo\n};\n\n/**\n * @brief Property class for boolean properties.\n*/\nclass BooleanProperty : public Property {\nprivate:\n\tbool value_;\n\npublic:\n\t\tBooleanProperty(PropertyOwner &po, const std::string &name, unsigned flags, bool value = false):\n\t\t\tProperty(po, name, flags), value_(value) {}\n\n\t\t/* Implicit conversion for using as a (const) bool */\n\t\toperator const bool&() const\n\t\t{\n\t\t\treturn value_;\n\t\t}\n\n\t\t/**\n\t\t * @brief Assigns value, marks property dirty.\n\t\t *\n\t\t * @return Reference to provided value\n\t\t*/\n\t\tconst bool& operator=(const bool& value)\n\t\t{\n\t\t\tvalue_ = value;\n\t\t\tMarkDirty();\n\n\t\t\treturn value;\n\t\t}\n\n\t\tstd::string Serialise() const override\n\t\t{\n\t\t\treturn value_\n\t\t\t\t? \"true\"\n\t\t\t\t: \"false\";\n\t\t}\n\n\t\tstd::string SerialiseAsJson() const override {\n\t\t  return Serialise();\n\t\t}\n\n\t\tvoid Deserialise(const std::string &serialised) override\n\t\t{\n\t\t\tif(serialised == \"false\")\n\t\t\t{\n\t\t\t\tvalue_ = false;\n\t\t\t\tMarkDirty();\n\t\t\t}\n\t\t\telse if(serialised == \"true\")\n\t\t\t{\n\t\t\t\tvalue_ = true;\n\t\t\t\tMarkDirty();\n\t\t\t}\n\t\t\telse{\n\t\t\t\t/* TODO: Have a this-isn't-valid exception */\n\t\t\t\tabort();\n\t\t\t}\n\t\t}\n};\n"
  },
  {
    "path": "src/engine/Resource.cpp",
    "content": "/* OpenHoW\n * Copyright (C) 2017-2020 TalonBrave.info and Others (see CONTRIBUTORS)\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include \"App.h\"\n\nohw::Resource::Resource( const std::string &path, bool persist ) :\n\treferencePath( path ),\n\tpersist( persist ) {\n\tu_assert( !path.empty() );\n\t//DebugMsg( \"Created resource, \\\"%s\\\"\\n\", path.c_str() );\n}\n\nohw::Resource::~Resource() {\n\tDebugMsg( \"Destroyed resource, \\\"%s\\\"\\n\", referencePath.c_str() );\n}\n\n/**\n * Releases a reference to this object.\n */\nvoid ohw::Resource::Release() {\n\tif ( numReferences > 0 ) {\n\t\t--numReferences;\n\t\treturn;\n\t}\n\n\t/* originally the plan was to do this through the resource manager instead\n\t * but we could have situations where the following happens...\n\t *  Actor is spawned in the game\n\t *  Actor is almost immediately destroyed\n\t *  Actor releases reference\n\t *  Actor is then spawned back in again immediately after\n\t * And that could happen over and over - potentially causing a big chug.\n\t * For now we'll do the clean up at the end of a game for released objects,\n\t * and in the longer term we will stagger the clean-up during the game.\n\t */\n#if 0\n\tif ( !persist && numReferences == 0 ) {\n\t\t// Automatically destroy ourselves\n\t\tdelete this;\n\t}\n#endif\n}\n\n/**\n * Returns true if this object can be destroyed.\n */\nbool ohw::Resource::CanDestroy() const {\n\tif ( persist ) {\n\t\treturn false;\n\t}\n\n\treturn ( numReferences == 0 );\n}\n"
  },
  {
    "path": "src/engine/Resource.h",
    "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// Copyright © 2017-2022 TalonBrave.info and Others (see CONTRIBUTORS)\n\n#pragma once\n\n#define IMPLEMENT_RESOURCE_CLASS( A ) \\\ninline size_t GetMemoryUsage() const override { return sizeof( A ); }\n\nnamespace ohw {\n\ttemplate< typename T >\n\tclass SharedResourcePointer {\n\tprivate:\n\t\tT *ptr;\n\n\tpublic:\n\t\tSharedResourcePointer( T *p ) : ptr( p ) {\n\t\t\tif ( ptr != nullptr ) {\n\t\t\t\tptr->AddReference();\n\t\t\t}\n\t\t}\n\n\t\tSharedResourcePointer( const SharedResourcePointer< T > &src ) : ptr( src.ptr ) {\n\t\t\tif ( ptr != nullptr ) {\n\t\t\t\tptr->AddReference();\n\t\t\t}\n\t\t}\n\n\t\t~SharedResourcePointer() {\n\t\t\tif ( ptr != nullptr ) {\n\t\t\t\tptr->Release();\n\t\t\t}\n\t\t}\n\n\t\tSharedResourcePointer &operator=( const SharedResourcePointer< T > &rhs ) {\n\t\t\tif ( rhs.ptr != nullptr ) {\n\t\t\t\trhs.ptr->AddReference();\n\t\t\t}\n\n\t\t\tif ( ptr != nullptr ) {\n\t\t\t\tptr->Release();\n\t\t\t}\n\n\t\t\tptr = rhs.ptr;\n\n\t\t\treturn *this;\n\t\t}\n\n\t\toperator T *() const {\n\t\t\treturn ptr;\n\t\t}\n\n\t\tT *operator->() const {\n\t\t\treturn ptr;\n\t\t}\n\t};\n\n\tclass Resource {\n\tpublic:\n\t\texplicit Resource( const std::string &path, bool persist = false );\n\t\tvirtual ~Resource();\n\n\t\tinline unsigned int AddReference() { return ( ++numReferences ); }\n\t\tinline unsigned int GetReferenceCount() const { return numReferences; }\n\t\tvoid Release();\n\n\t\tbool CanDestroy() const;\n\n\t\tvirtual size_t GetMemoryUsage() const = 0;\n\n\t\t// TODO: GetAbsolutePath() ...\n\t\tinline const std::string &GetPath() const { return referencePath; }\n\n\tprivate:\n\t\tstd::string referencePath;\n\n\t\tunsigned int numReferences{ 0 };\n\t\tbool persist{ false };\n\t};\n}\n"
  },
  {
    "path": "src/engine/ResourceManager.cpp",
    "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// Copyright © 2017-2022 TalonBrave.info and Others (see CONTRIBUTORS)\n\n#include \"App.h\"\n#include \"ResourceManager.h\"\n#include \"ShaderManager.h\"\n\nohw::ResourceManager::ResourceManager() {\n\t// Allow users to enable support for all package formats if desired (disabled by default for security reasons)\n\tif ( PlHasCommandLineArgument( \"-rapf\" ) ) {\n\t\tPlRegisterStandardPackageLoaders();\n\t}\n\n\tPlRegisterConsoleCommand( \"ListCachedResources\", \"List all cached resources.\", 0, &ResourceManager::ListCachedResources );\n\tPlRegisterConsoleCommand( \"ClearAllResources\", \"Clears all cached resources.\", 0, &ResourceManager::ClearAllResourcesCommand );\n\tPlRegisterConsoleCommand( \"ClearResource\", \"Clears the specified resource.\", 0, &ResourceManager::ClearResourceCommand );\n}\n\nohw::ResourceManager::~ResourceManager() {\n\tClearAllResources( true );\n}\n\nohw::Resource *ohw::ResourceManager::GetCachedResource( const std::string &path ) {\n\tauto idx = resourcesMap.find( path );\n\tif ( idx != resourcesMap.end() ) {\n\t\treturn idx->second;\n\t}\n\n\treturn nullptr;\n}\n\nohw::SharedTextureResourcePointer ohw::ResourceManager::LoadTexture( const std::string &path, unsigned int flags, bool persist, bool abortOnFail ) {\n\tTextureResource *texturePtr = static_cast< TextureResource * >( GetCachedResource( path ) );\n\tif ( texturePtr != nullptr ) {\n\t\treturn texturePtr;\n\t}\n\n\ttexturePtr = new TextureResource( path, flags, persist, abortOnFail );\n\tCacheResource( path, texturePtr );\n\n\treturn texturePtr;\n}\n\nohw::SharedModelResourcePointer ohw::ResourceManager::LoadModel( const std::string &path, bool persist, bool abortOnFail ) {\n\tModelResource *modelPtr = static_cast< ModelResource * >( GetCachedResource( path ) );\n\tif ( modelPtr != nullptr ) {\n\t\treturn modelPtr;\n\t}\n\n\tmodelPtr = new ModelResource( path, persist, abortOnFail );\n\tCacheResource( path, modelPtr );\n\n\treturn modelPtr;\n}\n\nPLGTexture *ohw::ResourceManager::GetFallbackTexture() {\n\tif ( fallbackTexture != nullptr ) {\n\t\treturn fallbackTexture;\n\t}\n\n\tPLColour pixelBuffer[] = {\n\t\t\t{ 255, 255, 0,   255 },\n\t\t\t{ 0,   255, 255, 255 },\n\t\t\t{ 0,   255, 255, 255 },\n\t\t\t{ 255, 255, 0,   255 } };\n\tPLImage *image = PlCreateImage( ( uint8_t * ) pixelBuffer, 2, 2, PL_COLOURFORMAT_RGBA, PL_IMAGEFORMAT_RGBA8 );\n\tif ( image == nullptr ) {\n\t\tError( \"Failed to generate default texture (%s)!\\n\", PlGetError() );\n\t}\n\n\tfallbackTexture = PlgCreateTexture();\n\tfallbackTexture->flags &= PLG_TEXTURE_FLAG_NOMIPS;\n\tif ( !PlgUploadTextureImage( fallbackTexture, image ) ) {\n\t\tError( \"Failed to upload default texture (%s)!\\n\", PlGetError() );\n\t}\n\n\tPlDestroyImage( image );\n\n\treturn fallbackTexture;\n}\n\nPLMModel *ohw::ResourceManager::GetFallbackModel() {\n\tif ( fallbackModel != nullptr ) {\n\t\treturn fallbackModel;\n\t}\n\n\tPLGMesh *mesh = PlgCreateMesh( PLG_MESH_LINES, PLG_DRAW_DYNAMIC, 0, 6 );\n\tPlgSetMeshVertexPosition( mesh, 0, { 0, 20, 0 } );\n\tPlgSetMeshVertexPosition( mesh, 1, { 0, -20, 0 } );\n\tPlgSetMeshVertexPosition( mesh, 2, { 20, 0, 0 } );\n\tPlgSetMeshVertexPosition( mesh, 3, { -20, 0, 0 } );\n\tPlgSetMeshVertexPosition( mesh, 4, { 0, 0, 20 } );\n\tPlgSetMeshVertexPosition( mesh, 5, { 0, 0, -20 } );\n\tPlgSetMeshUniformColour( mesh, hei::Colour( 255, 0, 0, 255 ) );\n\n\tShaderProgram *shaderProgram = Shaders_GetProgram( \"generic_untextured\" );\n\tif ( shaderProgram == nullptr ) {\n\t\tError( \"Failed to get default shader program, \\\"generic_untextured\\\"!\\n\" );\n\t}\n\n\t// todo: kill this api, if we rebuild shader cache we'll die\n\tPlgSetMeshShaderProgram( mesh, shaderProgram->GetInternalProgram() );\n\tPlgUploadMesh( mesh );\n\n\treturn ( fallbackModel = PlmCreateBasicStaticModel( mesh ) );\n}\n\n/**\n * Clear the specified resource if it's ready to be freed. Use force to immediately destroy it.\n */\nvoid ohw::ResourceManager::ClearResource( const std::string &path, bool force ) {\n\tif ( resourcesMap.empty() ) {\n\t\treturn;\n\t}\n\n\tauto resourceIndex = resourcesMap.find( path );\n\tif ( resourceIndex == resourcesMap.end() ) {\n\t\treturn;\n\t}\n\n\tif ( !force && !resourceIndex->second->CanDestroy() ) {\n\t\treturn;\n\t}\n\n\tdelete resourceIndex->second;\n\tresourcesMap.erase( resourceIndex );\n\n\tDebugMsg( \"Freed resource \\\"%s\\\"\\n\", path.c_str() );\n}\n\n/**\n * Clear all cached resources that can be freed up. Use force to immediately destroy it.\n */\nvoid ohw::ResourceManager::ClearAllResources( bool force ) {\n\tfor ( auto i = resourcesMap.begin(); i != resourcesMap.end(); ) {\n\t\tif ( !force && !i->second->CanDestroy() ) {\n\t\t\t++i;\n\t\t\tcontinue;\n\t\t}\n\n\t\tdelete i->second;\n\t\ti = resourcesMap.erase( i );\n\t}\n}\n\nvoid ohw::ResourceManager::ListCachedResources( unsigned int argc, char **argv ) {\n\tu_unused( argc );\n\tu_unused( argv );\n\n\tPrint( \"Printing cache...\\n\" );\n\tfor ( auto const &i: GetApp()->resourceManager->resourcesMap ) {\n\t\tPrint(\n\t\t\t\t\" CachedName(%s)\"\n\t\t\t\t\" CanDestroy(%s)\"\n\t\t\t\t\" ReferenceCount(%u)\\n\",\n\t\t\t\ti.first.c_str(),\n\t\t\t\ti.second->CanDestroy() ? \"true\" : \"false\",\n\t\t\t\ti.second->GetReferenceCount() );\n\t}\n}\n\nvoid ohw::ResourceManager::ClearAllResourcesCommand( unsigned int argc, char **argv ) {\n\tbool force = false;\n\tif ( argc > 1 ) {\n\t\tconst char *forceParameter = argv[ 1 ];\n\t\tif ( forceParameter == nullptr ) {\n\t\t\tWarning( \"Invalid force parameter!\\n\" );\n\t\t\treturn;\n\t\t}\n\n\t\tif ( pl_strcasecmp( forceParameter, \"true\" ) == 0 ) {\n\t\t\tforce = true;\n\t\t} else if ( pl_strcasecmp( forceParameter, \"false\" ) != 0 ) {\n\t\t\tWarning( \"Invalid force parameter, should be \\\"true\\\" or \\\"false\\\", was \\\"%s\\\"!\\n\", forceParameter );\n\t\t}\n\t}\n\n\tGetApp()->resourceManager->ClearAllResources( force );\n}\n\nvoid ohw::ResourceManager::ClearResourceCommand( unsigned int argc, char **argv ) {\n\tif ( argc <= 1 ) {\n\t\tWarning( \"Invalid number of arguments!\\n\" );\n\t\treturn;\n\t}\n\n\tconst char *resourceName = argv[ 1 ];\n\tif ( resourceName == nullptr ) {\n\t\tWarning( \"Invalid resource name!\\n\" );\n\t\treturn;\n\t}\n\n\tbool force = false;\n\tif ( argc > 2 ) {\n\t\tconst char *forceParameter = argv[ 2 ];\n\t\tif ( forceParameter == nullptr ) {\n\t\t\tWarning( \"Invalid force parameter!\\n\" );\n\t\t\treturn;\n\t\t}\n\n\t\tif ( pl_strcasecmp( forceParameter, \"true\" ) == 0 ) {\n\t\t\tforce = true;\n\t\t} else if ( pl_strcasecmp( forceParameter, \"false\" ) != 0 ) {\n\t\t\tWarning( \"Invalid force parameter, should be \\\"true\\\" or \\\"false\\\", was \\\"%s\\\"!\\n\", forceParameter );\n\t\t}\n\t}\n\n\tGetApp()->resourceManager->ClearResource( resourceName, force );\n}\n"
  },
  {
    "path": "src/engine/ResourceManager.h",
    "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// Copyright © 2017-2022 TalonBrave.info and Others (see CONTRIBUTORS)\n\n#pragma once\n\n#include <map>\n\n#include \"ModelResource.h\"\n#include \"TextureResource.h\"\n\nnamespace ohw {\n\tclass ResourceManager {\n\tprivate:\n\t\tResourceManager();\n\t\t~ResourceManager();\n\n\tpublic:\n\t\tSharedTextureResourcePointer LoadTexture( const std::string &path, unsigned int flags = 0, bool persist = false, bool abortOnFail = false );\n\t\tSharedModelResourcePointer LoadModel( const std::string &path, bool persist = false, bool abortOnFail = false );\n\n\t\tvoid ClearResource( const std::string &path, bool force = false );\n\t\tvoid ClearAllResources( bool force = false );\n\n\t\tPLGTexture *GetFallbackTexture();\n\t\tPLMModel *GetFallbackModel();\n\n\tprivate:\n\t\tstatic void ListCachedResources( unsigned int argc, char **argv );\n\t\tstatic void ClearAllResourcesCommand( unsigned int argc, char **argv );\n\t\tstatic void ClearResourceCommand( unsigned int argc, char **argv );\n\n\t\tPLGTexture *fallbackTexture{ nullptr };\n\t\tPLMModel *fallbackModel{ nullptr };\n\n\t\tResource *GetCachedResource( const std::string &path );\n\t\tinline Resource *CacheResource( const std::string &path, Resource *resourcePtr, bool persist = false ) {\n\t\t\tresourcesMap.insert( std::pair< std::string, Resource* >( path, resourcePtr ) );\n\t\t\t//DebugMsg( \"Cached resource, \\\"%s\\\"\\n\", path.c_str() );\n\t\t\treturn resourcePtr;\n\t\t}\n\n\t\tstd::map< std::string, Resource* > resourcesMap;\n\n\t\tfriend class App;\n\t};\n}\n"
  },
  {
    "path": "src/engine/Terrain.cpp",
    "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// Copyright © 2017-2022 TalonBrave.info and Others (see CONTRIBUTORS)\n\n#include \"App.h\"\n#include \"Terrain.h\"\n\n#include \"graphics/mesh.h\"\n#include \"graphics/ShaderManager.h\"\n#include \"graphics/TextureAtlas.h\"\n#include \"graphics/Camera.h\"\n\n//Precalculated vertices for chunk rendering\n//TODO: Share one index buffer instance between all chunks\nconst static unsigned int chunk_indices[96] = {\n\t\t0, 2, 1, 1, 2, 3,\n\t\t4, 6, 5, 5, 6, 7,\n\t\t8, 10, 9, 9, 10, 11,\n\t\t12, 14, 13, 13, 14, 15,\n\t\t16, 18, 17, 17, 18, 19,\n\t\t20, 22, 21, 21, 22, 23,\n\t\t24, 26, 25, 25, 26, 27,\n\t\t28, 30, 29, 29, 30, 31,\n\t\t32, 34, 33, 33, 34, 35,\n\t\t36, 38, 37, 37, 38, 39,\n\t\t40, 42, 41, 41, 42, 43,\n\t\t44, 46, 45, 45, 46, 47,\n\t\t48, 50, 49, 49, 50, 51,\n\t\t52, 54, 53, 53, 54, 55,\n\t\t56, 58, 57, 57, 58, 59,\n\t\t60, 62, 61, 61, 62, 63,\n};\n\nohw::Terrain::Terrain( const std::string &tileset ) {\n\t// attempt to load in the atlas sheet\n\t// TODO: allow us to change this on the fly\n\ttextureAtlas = new ohw::TextureAtlas( 512, 8 );\n\tfor ( unsigned int i = 0; i < 256; ++i ) {\n\t\tif ( !textureAtlas->AddImage( tileset + std::to_string( i ) ) ) {\n\t\t\tbreak;\n\t\t}\n\t}\n\ttextureAtlas->Finalize();\n\n\tchunks_.resize( TERRAIN_CHUNKS );\n\n\tUpdate();\n}\n\nohw::Terrain::~Terrain() {\n\tdelete textureAtlas;\n\n\tfor ( auto &chunk: chunks_ ) {\n\t\tPlgDestroyMesh( chunk.solidMesh );\n\t}\n}\n\nohw::Terrain::Chunk *ohw::Terrain::GetChunk( const PLVector2 &pos ) {\n\tif ( pos.x < 0 || std::floor( pos.x ) >= TERRAIN_PIXEL_WIDTH || pos.y < 0 || std::floor( pos.y ) >= TERRAIN_PIXEL_WIDTH ) {\n\t\treturn nullptr;\n\t}\n\n\tunsigned int idx =\n\t\t\t( ( unsigned int ) ( pos.x ) / TERRAIN_CHUNK_PIXEL_WIDTH ) +\n\t\t\t( ( ( unsigned int ) ( pos.y ) / TERRAIN_CHUNK_PIXEL_WIDTH ) * TERRAIN_CHUNK_ROW );\n\tif ( idx >= chunks_.size() ) {\n\t\tWarning( \"Attempted to get an out of bounds chunk index (%d)!\\n\", idx );\n\t\treturn nullptr;\n\t}\n\n\treturn &chunks_[ idx ];\n}\n\nohw::Terrain::Tile *ohw::Terrain::GetTile( float x, float y ) {\n\tChunk *chunk = GetChunk( { x, y } );\n\tif ( chunk == nullptr ) {\n\t\treturn nullptr;\n\t}\n\n\tunsigned int idx =\n\t\t\t( ( ( unsigned int ) ( x ) / TERRAIN_TILE_PIXEL_WIDTH ) % TERRAIN_CHUNK_ROW_TILES ) +\n\t\t\t( ( ( ( unsigned int ) ( y ) / TERRAIN_TILE_PIXEL_WIDTH ) % TERRAIN_CHUNK_ROW_TILES ) * TERRAIN_CHUNK_ROW_TILES );\n\tif ( idx >= TERRAIN_CHUNK_TILES ) {\n\t\tWarning( \"Attempted to get an out of bounds tile index!\\n\" );\n\t\treturn nullptr;\n\t}\n\n\treturn &chunk->tiles[ idx ];\n}\n\n/**\n * Return the height at the given point. If we fail to find a tile there, we just return 0.\n */\nfloat ohw::Terrain::GetHeight( float x, float y ) {\n\tconst Tile *tile = GetTile( x, y );\n\tif ( tile == nullptr ) {\n\t\treturn 0;\n\t}\n\n\tfloat tile_x = x - std::floor( x );\n\tfloat tile_y = y - std::floor( y );\n\n\tfloat nx = tile->height[ 0 ] + ( ( tile->height[ 1 ] - tile->height[ 0 ] ) * tile_x );\n\tfloat ny = tile->height[ 2 ] + ( ( tile->height[ 3 ] - tile->height[ 2 ] ) * tile_x );\n\tfloat nz = nx + ( ( ny - nx ) * tile_y );\n\n\treturn nz;\n}\n\nvoid ohw::Terrain::GenerateChunkMesh( Chunk *chunk, const PLVector2 &offset ) {\n\t// We will need to generate the mesh for the cunk again if the terrain is modified\n\tif ( chunk->solidMesh != nullptr ) {\n\t\tPlgDestroyMesh( chunk->solidMesh );\n\t}\n\n\tchunk->solidMesh = PlgCreateMeshInit( PLG_MESH_TRIANGLES, PLG_DRAW_DYNAMIC, 32, 64, chunk_indices, nullptr );\n\tif ( chunk->solidMesh == nullptr ) {\n\t\tError( \"Unable to create map chunk mesh, aborting!\\nPL: %s\\n\", PlGetError() );\n\t}\n\n\tif ( chunk->waterMesh != nullptr ) {\n\t\tPlgDestroyMesh( chunk->waterMesh );\n\t}\n\n\tchunk->waterMesh = PlgCreateMeshInit( PLG_MESH_TRIANGLES, PLG_DRAW_DYNAMIC, 32, 64, chunk_indices, nullptr );\n\tif ( chunk->waterMesh == nullptr ) {\n\t\tError( \"Unable to create water chunk mesh, aborting!\\nPL: %s\\n\", PlGetError() );\n\t}\n\n\tint cm_idx = 0;\n\tunsigned int numWaterTiles = 0;\n\tfor ( unsigned int tile_y = 0; tile_y < TERRAIN_CHUNK_ROW_TILES; ++tile_y ) {\n\t\tfor ( unsigned int tile_x = 0; tile_x < TERRAIN_CHUNK_ROW_TILES; ++tile_x ) {\n\t\t\tconst Tile *current_tile = &chunk->tiles[ tile_x + tile_y * TERRAIN_CHUNK_ROW_TILES ];\n\n\t\t\tfloat tx_x, tx_y, tx_w, tx_h;\n\t\t\ttextureAtlas->GetTextureCoords( std::to_string( current_tile->texture ), &tx_x, &tx_y, &tx_w, &tx_h );\n\n\t\t\t// TERRAIN_FLIP_FLAG_X flips around texture sheet coords, not TERRAIN coords.\n\t\t\tif ( current_tile->rotation & Tile::ROTATION_FLAG_X ) {\n\t\t\t\ttx_x = tx_x + tx_w;\n\t\t\t\ttx_w = -tx_w;\n\t\t\t}\n\n\t\t\t// ST coords for each corner of the tile.\n\t\t\tfloat tx_Ax[] = { tx_x, tx_x + tx_w, tx_x, tx_x + tx_w };\n\t\t\tfloat tx_Ay[] = { tx_y, tx_y, tx_y + tx_h, tx_y + tx_h };\n\n\t\t\t// Rotate a quad of ST coords 90 degrees clockwise.\n\t\t\tauto rot90 = []( float *x ) {\n\t\t\t\tfloat c = x[ 0 ];\n\t\t\t\tx[ 0 ] = x[ 2 ];\n\t\t\t\tx[ 2 ] = x[ 3 ];\n\t\t\t\tx[ 3 ] = x[ 1 ];\n\t\t\t\tx[ 1 ] = c;\n\t\t\t};\n\n\t\t\tif ( current_tile->rotation & Tile::ROTATION_FLAG_ROTATE_90 ) {\n\t\t\t\trot90( tx_Ax );\n\t\t\t\trot90( tx_Ay );\n\t\t\t}\n\n\t\t\tif ( current_tile->rotation & Tile::ROTATION_FLAG_ROTATE_180 ) {\n\t\t\t\trot90( tx_Ax );\n\t\t\t\trot90( tx_Ay );\n\t\t\t\trot90( tx_Ax );\n\t\t\t\trot90( tx_Ay );\n\t\t\t}\n\n\t\t\t// MAP_FLIP_FLAG_ROTATE_270 is implemented by ORing 90 and 180 together.\n\n\t\t\tfor ( int i = 0; i < 4; ++i, ++cm_idx ) {\n\t\t\t\tfloat x = ( offset.x * TERRAIN_CHUNK_PIXEL_WIDTH ) + ( tile_x + ( i % 2 ) ) * TERRAIN_TILE_PIXEL_WIDTH;\n\t\t\t\tfloat z = ( offset.y * TERRAIN_CHUNK_PIXEL_WIDTH ) + ( tile_y + ( i / 2 ) ) * TERRAIN_TILE_PIXEL_WIDTH;\n\n\t\t\t\tPLVector3 position = hei::Vector3( x, current_tile->height[ i ], z );\n\t\t\t\tPLColour shadedColour = hei::Colour( current_tile->shading[ i ], current_tile->shading[ i ], current_tile->shading[ i ] );\n\n\t\t\t\tPlgSetMeshVertexPosition( chunk->solidMesh, cm_idx, position );\n\t\t\t\tPlgSetMeshVertexColour( chunk->solidMesh, cm_idx, shadedColour );\n\t\t\t\tPlgSetMeshVertexST( chunk->solidMesh, cm_idx, tx_Ax[ i ], tx_Ay[ i ] );\n\n\t\t\t\tif ( current_tile->behaviour == Tile::BEHAVIOUR_WATERY ) {\n\t\t\t\t\tshadedColour.a = 145;\n\t\t\t\t\tPlgSetMeshVertexPosition( chunk->waterMesh, cm_idx, position );\n\t\t\t\t\tPlgSetMeshVertexColour( chunk->waterMesh, cm_idx, shadedColour );\n\t\t\t\t\tPlgSetMeshVertexST( chunk->waterMesh, cm_idx, tx_Ax[ i ], tx_Ay[ i ] );\n\t\t\t\t\tnumWaterTiles++;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif ( numWaterTiles == 0 ) {\n\t\tPlgDestroyMesh( chunk->waterMesh );\n\t\tchunk->waterMesh = nullptr;\n\t}\n}\n\nvoid ohw::Terrain::GenerateOverview() {\n\tstatic const PLColour colours[] = {\n\t\t\t{ 60,  50,  40 },     // Mud\n\t\t\t{ 40,  70,  40 },     // Grass\n\t\t\t{ 128, 128, 128 },  // Metal\n\t\t\t{ 153, 94,  34 },    // Wood\n\t\t\t{ 90,  90,  150 },    // Water\n\t\t\t{ 50,  50,  50 },     // Stone\n\t\t\t{ 50,  50,  50 },     // Rock\n\t\t\t{ 100, 80,  30 },    // Sand\n\t\t\t{ 180, 240, 240 },  // Ice\n\t\t\t{ 100, 100, 100 },  // Snow\n\t\t\t{ 60,  50,  40 },     // Quagmire\n\t\t\t{ 100, 240, 53 }    // Lava/Poison\n\t};\n\n\t// Create our storage\n\tPLImage *image = PlCreateImage( nullptr, 64, 64, PL_COLOURFORMAT_RGB, PL_IMAGEFORMAT_RGB8 );\n\n\t// Now write into the image buffer\n\tuint8_t *buf = image->data[ 0 ];\n\tfor ( uint8_t y = 0; y < 64; ++y ) {\n\t\tfor ( uint8_t x = 0; x < 64; ++x ) {\n\t\t\thei::Vector2 position( x * ( TERRAIN_PIXEL_WIDTH / 64 ), y * ( TERRAIN_PIXEL_WIDTH / 64 ) );\n\t\t\tconst Tile *tile = GetTile( position.x, position.y );\n\t\t\tu_assert( tile != nullptr, \"Hit an invalid tile during overview generation!\\n\" );\n\t\t\tif ( tile == nullptr ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tauto mod = static_cast<int>(( GetHeight( position.x, position.y ) + ( ( GetMaxHeight() + GetMinHeight() ) / 2 ) ) / 255);\n\t\t\tPLColour rgb = hei::Colour(\n\t\t\t\t\tstd::min( ( colours[ tile->surface ].r / 9 ) * mod, 255 ),\n\t\t\t\t\tstd::min( ( colours[ tile->surface ].g / 9 ) * mod, 255 ),\n\t\t\t\t\tstd::min( ( colours[ tile->surface ].b / 9 ) * mod, 255 )\n\t\t\t);\n\t\t\tif ( tile->behaviour & Tile::BEHAVIOUR_MINE ) {\n\t\t\t\trgb = { 255, 0, 0 };\n\t\t\t}\n\n\t\t\t*( buf++ ) = rgb.r;\n\t\t\t*( buf++ ) = rgb.g;\n\t\t\t*( buf++ ) = rgb.b;\n\t\t}\n\t}\n\n#if !defined( NDEBUG )\n\tif ( PlCreatePath( \"./debug/generated/\" ) ) {\n\t\tchar path[PL_SYSTEM_MAX_PATH];\n\t\tstatic unsigned int id = 0;\n\t\tsnprintf( path, sizeof( path ) - 1, \"./debug/generated/%dx%d_%d.png\", image->width, image->height, id );\n\t\tPlWriteImage( image, path );\n\t}\n#endif\n\n\t// Allow rebuilding overview texture\n\tPlgDestroyTexture( overview_ );\n\n\tif ( ( overview_ = PlgCreateTexture() ) == nullptr ) {\n\t\tError( \"Failed to generate overview texture slot!\\n%s\\n\", PlGetError() );\n\t}\n\n\tPlgUploadTextureImage( overview_, image );\n\tPlDestroyImage( image );\n}\n\nvoid ohw::Terrain::Update() {\n\tGenerateOverview();\n\n\tfor ( unsigned int chunk_y = 0; chunk_y < TERRAIN_CHUNK_ROW; ++chunk_y ) {\n\t\tfor ( unsigned int chunk_x = 0; chunk_x < TERRAIN_CHUNK_ROW; ++chunk_x ) {\n\t\t\tGenerateChunkMesh( &chunks_[ chunk_x + chunk_y * TERRAIN_CHUNK_ROW ],\n\t\t\t                   { static_cast<float>(chunk_x), static_cast<float>(chunk_y) } );\n\t\t}\n\t}\n\n\tstd::list< PLGMesh * > meshes;\n\tfor ( auto &chunk: chunks_ ) {\n\t\tif ( chunk.solidMesh != nullptr ) {\n\t\t\tmeshes.push_back( chunk.solidMesh );\n\t\t}\n\t\tif ( chunk.waterMesh != nullptr ) {\n\t\t\tmeshes.push_back( chunk.waterMesh );\n\t\t}\n\t}\n\n\tif ( !meshes.empty() ) {\n\t\tMesh_GenerateFragmentedMeshNormals( meshes );\n\t}\n}\n\nvoid ohw::Terrain::Draw() {\n\tohw::Camera *cameraPtr = GetApp()->gameManager->GetActiveCamera();\n\tif ( cameraPtr == nullptr ) {\n\t\treturn;\n\t}\n\n\tif ( !cv_graphics_debug_normals->b_value ) {\n\t\tPlgSetTexture( textureAtlas->GetTexture(), 0 );\n\t}\n\n\tPlMatrixMode( PL_MODELVIEW_MATRIX );\n\tPlPushMatrix();\n\n\tPlLoadIdentityMatrix();\n\n\tPLGShaderProgram *program;\n\n\t// Solid\n\tprogram = Shaders_GetProgram( cv_graphics_debug_normals->b_value ? \"debug_normals\" : \"generic_textured_lit\" )->GetInternalProgram();\n\tif ( program != nullptr ) {\n\t\tPlgSetShaderProgram( program );\n\t\tPlgSetShaderUniformValue( program, \"pl_model\", PlGetMatrix( PL_MODELVIEW_MATRIX ), true );\n\n\t\tPlgSetBlendMode( PLG_BLEND_DISABLE );\n\n\t\tfor ( const auto &chunk: chunks_ ) {\n\t\t\tif ( ( cv_graphics_cull->b_value && !cameraPtr->IsBoxVisible( &chunk.bounds ) ) || chunk.solidMesh == nullptr ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tPlgUploadMesh( chunk.solidMesh );\n\t\t\tPlgDrawMesh( chunk.solidMesh );\n\t\t}\n\t}\n\n\tif ( !cv_graphics_debug_normals->b_value ) {\n\t\t// Water\n\t\tprogram = Shaders_GetProgram( \"water\" )->GetInternalProgram();\n\t\tif ( program != nullptr ) {\n\t\t\tPlgSetShaderProgram( program );\n\t\t\tPlgSetShaderUniformValue( program, \"pl_model\", PlGetMatrix( PL_MODELVIEW_MATRIX ), true );\n\n\t\t\tPlgSetBlendMode( PLG_BLEND_DEFAULT );\n\n\t\t\tfor ( const auto &chunk: chunks_ ) {\n\t\t\t\tif ( ( cv_graphics_cull->b_value && !cameraPtr->IsBoxVisible( &chunk.bounds ) ) || chunk.waterMesh == nullptr ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tPlgUploadMesh( chunk.waterMesh );\n\t\t\t\tPlgDrawMesh( chunk.waterMesh );\n\t\t\t}\n\t\t}\n\n\t\tif ( cv_debug_bounds->b_value ) {\n\t\t\tShaders_SetProgramByName( \"generic_untextured\" );\n\n\t\t\tfor ( const auto &chunk: chunks_ ) {\n\t\t\t\tif ( ( cv_graphics_cull->b_value && !cameraPtr->IsBoxVisible( &chunk.bounds ) ) ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tPlgDrawBoundingVolume( &chunk.bounds, PL_COLOUR_ORANGE );\n\t\t\t}\n\t\t}\n\t}\n\n\tif ( !cv_graphics_debug_normals->b_value ) {\n\t\tPlgSetTexture( nullptr, 0 );\n\t}\n\n\tPlPopMatrix();\n}\n\nvoid ohw::Terrain::LoadPmg( const std::string &path ) {\n\tPLFile *fh = PlOpenFile( path.c_str(), false );\n\tif ( fh == nullptr ) {\n\t\tWarning( \"Failed to open tile data, \\\"%s\\\", aborting\\n\", path.c_str() );\n\t\treturn;\n\t}\n\n\tfor ( unsigned int chunk_y = 0; chunk_y < TERRAIN_CHUNK_ROW; ++chunk_y ) {\n\t\tfor ( unsigned int chunk_x = 0; chunk_x < TERRAIN_CHUNK_ROW; ++chunk_x ) {\n\t\t\tChunk &chunk = chunks_[ chunk_x + chunk_y * TERRAIN_CHUNK_ROW ];\n\n\t\t\tbool status;\n\t\t\tchunk.x = PlReadInt16( fh, false, &status );\n\t\t\tchunk.y = PlReadInt16( fh, false, &status );\n\t\t\tchunk.z = PlReadInt16( fh, false, &status );\n\t\t\t/* int16_t unknown0 = */\n\t\t\tPlReadInt16( fh, false, &status );\n\n\t\t\tif ( !status ) {\n\t\t\t\tError( \"Failed to read in chunk descriptor in \\\"%s\\\"!\\n\", PlGetFilePath( fh ) );\n\t\t\t}\n\n\t\t\tchunk.bounds.origin = hei::Vector3( chunk_x * TERRAIN_CHUNK_PIXEL_WIDTH, 0.0f, chunk_y * TERRAIN_CHUNK_PIXEL_WIDTH );\n\t\t\tchunk.bounds.maxs.z = chunk.bounds.maxs.x = TERRAIN_CHUNK_PIXEL_WIDTH;\n\t\t\tchunk.bounds.mins.z = chunk.bounds.mins.x = -TERRAIN_CHUNK_PIXEL_WIDTH;\n\n\t\t\tstruct {\n\t\t\t\tint16_t height{ 0 };\n\t\t\t\tuint16_t lighting{ 0 };\n\t\t\t} vertices[25];\n\n\t\t\t// Find the maximum and minimum points\n\t\t\tchunk.bounds.maxs.y = INT16_MIN;\n\t\t\tchunk.bounds.mins.y = INT16_MAX;\n\t\t\tfor ( auto &vertex: vertices ) {\n\t\t\t\tvertex.height = PlReadInt16( fh, false, &status );\n\t\t\t\tvertex.lighting = PlReadInt16( fh, false, &status );\n\n\t\t\t\tif ( !status ) {\n\t\t\t\t\tError( \"Failed to read in vertex descriptor in \\\"%s\\\"!\\n\", PlGetFilePath( fh ) );\n\t\t\t\t}\n\n\t\t\t\t// Determine the maximum height and minimum height for this chunk\n\t\t\t\tif ( vertex.height > chunk.bounds.maxs.y ) {\n\t\t\t\t\tchunk.bounds.maxs.y = vertex.height;\n\t\t\t\t}\n\t\t\t\tif ( vertex.height < chunk.bounds.mins.y ) {\n\t\t\t\t\tchunk.bounds.mins.y = vertex.height;\n\t\t\t\t}\n\t\t\t\t// And now for the entire terrain\n\t\t\t\tif ( static_cast<float>(vertex.height) > max_height_ ) {\n\t\t\t\t\tmax_height_ = vertex.height;\n\t\t\t\t}\n\t\t\t\tif ( static_cast<float>(vertex.height) < min_height_ ) {\n\t\t\t\t\tmin_height_ = vertex.height;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tPlFileSeek( fh, 4, PL_SEEK_CUR );\n\n\t\t\tfor ( unsigned int tile_y = 0; tile_y < TERRAIN_CHUNK_ROW_TILES; ++tile_y ) {\n\t\t\t\tfor ( unsigned int tile_x = 0; tile_x < TERRAIN_CHUNK_ROW_TILES; ++tile_x ) {\n\t\t\t\t\tstruct {\n\t\t\t\t\t\tint8_t unused0[6]{ 0, 0, 0, 0, 0, 0 };\n\t\t\t\t\t\tuint8_t type{ 0 };\n\t\t\t\t\t\tuint8_t slip{ 0 };\n\t\t\t\t\t\tint16_t unused1{ 0 };\n\t\t\t\t\t\tuint8_t rotation{ 0 };\n\t\t\t\t\t\tuint32_t texture{ 0 };\n\t\t\t\t\t\tuint8_t unused2{ 0 };\n\t\t\t\t\t} tile;\n\n\t\t\t\t\t// Skip unused data\n\t\t\t\t\tif ( PlReadFile( fh, tile.unused0, 6, 1 ) != 1 ) {\n\t\t\t\t\t\tError( \"Failed to skip unused bytes in \\\"%s\\\"!\\n\", PlGetFilePath( fh ) );\n\t\t\t\t\t}\n\n\t\t\t\t\ttile.type = PlReadInt8( fh, &status );\n\t\t\t\t\ttile.slip = PlReadInt8( fh, &status );\n\t\t\t\t\ttile.unused1 = PlReadInt16( fh, false, &status );\n\t\t\t\t\ttile.rotation = PlReadInt8( fh, &status );\n\t\t\t\t\ttile.texture = PlReadInt32( fh, false, &status );\n\t\t\t\t\ttile.unused2 = PlReadInt8( fh, &status );\n\n\t\t\t\t\tif ( !status ) {\n\t\t\t\t\t\tError( \"Failed to read in tile descriptor in \\\"%s\\\"!\\n\", PlGetFilePath( fh ) );\n\t\t\t\t\t}\n\n\t\t\t\t\tTile *current_tile = &chunk.tiles[ tile_x + tile_y * TERRAIN_CHUNK_ROW_TILES ];\n\t\t\t\t\tcurrent_tile->surface = static_cast<Tile::Surface>(tile.type & 31U);\n\t\t\t\t\tcurrent_tile->behaviour = static_cast<Tile::Behaviour>(tile.type & ~31U);\n\t\t\t\t\tcurrent_tile->rotation = static_cast<Tile::Rotation>(tile.rotation);\n\t\t\t\t\tcurrent_tile->slip = 0;\n\t\t\t\t\tcurrent_tile->texture = tile.texture;\n\n\t\t\t\t\tcurrent_tile->height[ 0 ] = vertices[ ( tile_y * 5 ) + tile_x ].height;\n\t\t\t\t\tcurrent_tile->height[ 1 ] = vertices[ ( tile_y * 5 ) + tile_x + 1 ].height;\n\t\t\t\t\tcurrent_tile->height[ 2 ] = vertices[ ( ( tile_y + 1 ) * 5 ) + tile_x ].height;\n\t\t\t\t\tcurrent_tile->height[ 3 ] = vertices[ ( ( tile_y + 1 ) * 5 ) + tile_x + 1 ].height;\n\n\t\t\t\t\tcurrent_tile->shading[ 0 ] = vertices[ ( tile_y * 5 ) + tile_x ].lighting;\n\t\t\t\t\tcurrent_tile->shading[ 1 ] = vertices[ ( tile_y * 5 ) + tile_x + 1 ].lighting;\n\t\t\t\t\tcurrent_tile->shading[ 2 ] = vertices[ ( ( tile_y + 1 ) * 5 ) + tile_x ].lighting;\n\t\t\t\t\tcurrent_tile->shading[ 3 ] = vertices[ ( ( tile_y + 1 ) * 5 ) + tile_x + 1 ].lighting;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tPlCloseFile( fh );\n\n\tUpdate();\n}\n\nvoid ohw::Terrain::LoadHeightmap( const std::string &path, int multiplier ) {\n\tPLImage *image = PlLoadImage( path.c_str() );\n\tif ( image == nullptr ) {\n\t\tWarning( \"Failed to load the specified heightmap, \\\"%s\\\" (%s)!\\n\", path.c_str(), PlGetError() );\n\t\treturn;\n\t}\n\n\tif ( image->width < 65 || image->height < 65 ) {\n\t\tPlDestroyImage( image );\n\t\tWarning( \"Invalid image size for heightmap, %dx%d vs 65x65!\\n\", image->width, image->height );\n\t\treturn;\n\t}\n\n\t// Each channel is encoded with specific data\n\t// red = height\n\t// green = texture\n\n\tunsigned int chan_length = image->width * image->height;\n\n\tauto *rchan = static_cast<float *>(u_alloc( chan_length, sizeof( float ), true ));\n\tuint8_t *pixel = image->data[ 0 ];\n\tfor ( unsigned int i = 0; i < chan_length; ++i ) {\n\t\trchan[ i ] = static_cast<int>(*pixel) * multiplier; //(static_cast<int>(*pixel) - 127) * 256;\n\t\tpixel += 4;\n\t}\n\n\tauto *gchan = static_cast<uint8_t *>(u_alloc( chan_length, sizeof( uint8_t ), true ));\n\tpixel = image->data[ 0 ] + 1;\n\tfor ( unsigned int i = 0; i < chan_length; ++i ) {\n\t\tgchan[ i ] = *pixel;\n\t\tpixel += 4;\n\t}\n\n\tPlDestroyImage( image );\n\n\tfor ( unsigned int chunk_y = 0; chunk_y < TERRAIN_CHUNK_ROW; ++chunk_y ) {\n\t\tfor ( unsigned int chunk_x = 0; chunk_x < TERRAIN_CHUNK_ROW; ++chunk_x ) {\n\t\t\tChunk &current_chunk = chunks_[ chunk_x + chunk_y * TERRAIN_CHUNK_ROW ];\n\t\t\tfor ( unsigned int tile_y = 0; tile_y < TERRAIN_CHUNK_ROW_TILES; ++tile_y ) {\n\t\t\t\tfor ( unsigned int tile_x = 0; tile_x < TERRAIN_CHUNK_ROW_TILES; ++tile_x ) {\n\t\t\t\t\tTile *current_tile = &current_chunk.tiles[ tile_x + tile_y * TERRAIN_CHUNK_ROW_TILES ];\n\t\t\t\t\tunsigned int aaa = ( chunk_y * 4 * 65 ) + ( chunk_x * 4 );\n\t\t\t\t\tcurrent_tile->height[ 0 ] = rchan[ aaa + ( tile_y * 65 ) + tile_x ];\n\t\t\t\t\tcurrent_tile->height[ 1 ] = rchan[ aaa + ( tile_y * 65 ) + tile_x + 1 ];\n\t\t\t\t\tcurrent_tile->height[ 2 ] = rchan[ aaa + ( ( tile_y + 1 ) * 65 ) + tile_x ];\n\t\t\t\t\tcurrent_tile->height[ 3 ] = rchan[ aaa + ( ( tile_y + 1 ) * 65 ) + tile_x + 1 ];\n\n\t\t\t\t\tcurrent_tile->texture = gchan[ aaa + ( tile_y * 65 ) + tile_x ];\n\n\t\t\t\t\t// hrm...\n\t\t\t\t\tcurrent_tile->shading[ 0 ] =\n\t\t\t\t\tcurrent_tile->shading[ 1 ] =\n\t\t\t\t\tcurrent_tile->shading[ 2 ] =\n\t\t\t\t\tcurrent_tile->shading[ 3 ] = 255;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tmax_height_ = min_height_ = current_chunk.tiles[ 0 ].height[ 0 ];\n\n\t\t\t// Find the maximum and minimum points\n\t\t\tfor ( auto &tile: current_chunk.tiles ) {\n\t\t\t\tfor ( float i: tile.height ) {\n\t\t\t\t\tif ( i > max_height_ ) {\n\t\t\t\t\t\tmax_height_ = i;\n\t\t\t\t\t}\n\t\t\t\t\tif ( i < min_height_ ) {\n\t\t\t\t\t\tmin_height_ = i;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tu_free( rchan );\n\tu_free( gchan );\n\n\tUpdate();\n}\n"
  },
  {
    "path": "src/engine/Terrain.h",
    "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// Copyright © 2017-2022 TalonBrave.info and Others (see CONTRIBUTORS)\n\n#pragma once\n\n#define TERRAIN_CHUNK_ROW           16\n#define TERRAIN_CHUNKS              (TERRAIN_CHUNK_ROW * TERRAIN_CHUNK_ROW)\n#define TERRAIN_CHUNK_ROW_TILES     4\n#define TERRAIN_CHUNK_TILES         (TERRAIN_CHUNK_ROW_TILES * TERRAIN_CHUNK_ROW_TILES)\n\n#define TERRAIN_TILE_PIXEL_WIDTH    512\n#define TERRAIN_CHUNK_PIXEL_WIDTH   2048\n\n#define TERRAIN_ROW_TILES           (TERRAIN_CHUNK_ROW * TERRAIN_CHUNK_ROW_TILES)\n\n#define TERRAIN_PIXEL_WIDTH         (TERRAIN_TILE_PIXEL_WIDTH * TERRAIN_ROW_TILES)\n\n#define TERRAIN_PLAYABLE_BORDER    ( 2 * TERRAIN_CHUNK_ROW_TILES * TERRAIN_TILE_PIXEL_WIDTH )\n#define TERRAIN_PLAYABLE_AREA   ( TERRAIN_PIXEL_WIDTH - ( TERRAIN_PLAYABLE_BORDER * 2 ) )\n\nnamespace ohw {\n\tclass TextureAtlas;\n\n\tclass Terrain {\n\tpublic:\n\t\texplicit Terrain( const std::string &tileset );\n\t\t~Terrain();\n\n\t\tstruct Tile {\n\t\t\t/* surface properties */\n\t\t\tenum Surface {\n\t\t\t\tSURFACE_MUD = 0,\n\t\t\t\tSURFACE_GRASS = 1,\n\t\t\t\tSURFACE_METAL = 2,\n\t\t\t\tSURFACE_WOOD = 3,\n\t\t\t\tSURFACE_WATER = 4,\n\t\t\t\tSURFACE_STONE = 5,\n\t\t\t\tSURFACE_ROCK = 6,\n\t\t\t\tSURFACE_SAND = 7,\n\t\t\t\tSURFACE_ICE = 8,\n\t\t\t\tSURFACE_SNOW = 9,\n\t\t\t\tSURFACE_QUAGMIRE = 10,\n\t\t\t\tSURFACE_LAVA = 11,\n\t\t\t} surface{ SURFACE_MUD }; // e.g. wood\n\n\t\t\tenum Behaviour {\n\t\t\t\tBEHAVIOUR_NONE,\n\t\t\t\tBEHAVIOUR_WATERY = 32,\n\t\t\t\tBEHAVIOUR_MINE = 64,\n\t\t\t\tBEHAVIOUR_WALL = 128,\n\t\t\t} behaviour{ BEHAVIOUR_NONE }; // e.g. mine, watery\n\n\t\t\tunsigned int slip{ 0 }; // e.g. full, bottom or left?\n\n\t\t\tuint8_t texture{ 0 };\n\n\t\t\tenum Rotation {\n\t\t\t\tROTATION_FLAG_NONE,\n\t\t\t\tROTATION_FLAG_X = 1,\n\t\t\t\tROTATION_FLAG_ROTATE_90 = 2,\n\t\t\t\tROTATION_FLAG_ROTATE_180 = 4,\n\t\t\t\tROTATION_FLAG_ROTATE_270 = 6,\n\t\t\t} rotation{ ROTATION_FLAG_NONE };\n\n\t\t\tfloat height[4]{ 0, 0, 0, 0 };\n\t\t\tuint8_t shading[4]{ 255, 255, 255, 255 };\n\n\t\t\tPLVector3 origin;\n\t\t};\n\n\t\tstruct Chunk {\n\t\t\tTile tiles[16];\n\n\t\t\t// We don't currently use these...\n\t\t\tint16_t x, y, z;\n\n\t\t\tPLGMesh *solidMesh{ nullptr };\n\t\t\tPLGMesh *waterMesh{ nullptr };\n\n\t\t\t/* Bounding volume encompassing the chunk. Used for determining\n\t\t\t * what actors are currently within the chunk space and whether\n\t\t\t * the given chunk is visible. */\n\t\t\tPLCollisionAABB bounds;\n\t\t};\n\n\t\tChunk *GetChunk( const PLVector2 &pos );\n\t\tTile *GetTile( float x, float y );\n\n\t\tfloat GetHeight( float x, float y );\n\t\tfloat GetMaxHeight() { return max_height_; }\n\t\tfloat GetMinHeight() { return min_height_; }\n\n\t\tvoid LoadPmg( const std::string &path );\n\t\tvoid LoadHeightmap( const std::string &path, int multiplier );\n\n\t\tPLGTexture *GetOverview() { return overview_; }\n\n\t\tvoid Serialize( const std::string &path );\n\n\t\tvoid Draw();\n\t\tvoid Update();\n\n\tprotected:\n\tprivate:\n\t\tvoid GenerateChunkMesh( Chunk *chunk, const PLVector2 &offset );\n\t\tvoid GenerateOverview();\n\n\t\tfloat max_height_{ 0 };\n\t\tfloat min_height_{ 0 };\n\n\t\tstd::vector< Chunk > chunks_;\n\n\t\tohw::TextureAtlas *textureAtlas{ nullptr };\n\t\tPLGTexture *overview_{ nullptr };\n\t};\n}\n"
  },
  {
    "path": "src/engine/TextureResource.cpp",
    "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// Copyright © 2017-2022 TalonBrave.info and Others (see CONTRIBUTORS)\n\n#include \"App.h\"\n\n// TODO: we should be able to query the platform library for this!!\nconst char *supportedTextureFormats[] = { \"png\", \"tga\", \"bmp\", \"tim\", nullptr };\n\nohw::TextureResource::TextureResource( const std::string &path, unsigned int flags, bool persist, bool abortOnFail ) : Resource( path, persist ) {\n\tPLGTextureFilter filterMode;\n\tif ( flags & FLAG_NOMIPS ) {\n\t\tif ( flags & FLAG_NEAREST ) {\n\t\t\tfilterMode = PLG_TEXTURE_FILTER_NEAREST;\n\t\t} else {\n\t\t\tfilterMode = PLG_TEXTURE_FILTER_LINEAR;\n\t\t}\n\t} else {\n\t\tif ( flags & FLAG_NEAREST ) {\n\t\t\tfilterMode = PLG_TEXTURE_FILTER_MIPMAP_NEAREST;\n\t\t} else {\n\t\t\tfilterMode = PLG_TEXTURE_FILTER_MIPMAP_LINEAR;\n\t\t}\n\t}\n\n\tconst char *fileExtension = PlGetFileExtension( path.c_str() );\n\tif ( fileExtension[ 0 ] == '\\0' ) {\n\t\tconst char *newPath = u_find2( path.c_str(), supportedTextureFormats, abortOnFail );\n\t\tif ( newPath != nullptr ) {\n\t\t\ttexturePtr = PlgLoadTextureFromImage( newPath, filterMode );\n\t\t}\n\n\t\tif ( texturePtr == nullptr ) {\n\t\t\tif ( abortOnFail ) {\n\t\t\t\tError( \"Failed to load texture, \\\"%s\\\"!\\nPL: %s\\n\", path.c_str(), PlGetError() );\n\t\t\t}\n\n\t\t\tWarning( \"Failed to load texture, \\\"%s\\\"!\\nPL: %s\\n\", path.c_str(), PlGetError() );\n\t\t\ttexturePtr = GetApp()->resourceManager->GetFallbackTexture();\n\t\t}\n\n\t\treturn;\n\t}\n\n\tPLImage *image = PlLoadImage( path.c_str() );\n\tif ( image ) {\n\t\t// pixel format of TIM will be changed before uploading\n\t\tif ( pl_strncasecmp( fileExtension, \"tim\", 3 ) == 0 ) {\n\t\t\tPlConvertPixelFormat( image, PL_IMAGEFORMAT_RGBA8 );\n\t\t}\n\n\t\t// If discard is specified, we need to throw away the first colour\n\t\tif ( flags & FLAG_DISCARD ) {\n\t\t\tconst PLColour *firstColour = ( PLColour * ) image->data[ 0 ];\n\t\t\tPlReplaceImageColour( image, *firstColour, { 0, 0, 0, 0 } );\n\t\t}\n\n\t\ttexturePtr = PlgCreateTexture();\n\t\tif ( texturePtr != nullptr ) {\n\t\t\ttexturePtr->filter = filterMode;\n\t\t\tif ( PlgUploadTextureImage( texturePtr, image ) ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\tPlgDestroyTexture( texturePtr );\n\t}\n\n\tPlDestroyImage( image );\n\n\tif ( abortOnFail ) {\n\t\tError( \"Failed to load texture, \\\"%s\\\"!\\nPL: %s\\n\", path.c_str(), PlGetError() );\n\t}\n\n\tWarning( \"Failed to load texture, \\\"%s\\\"!\\nPL: %s\\n\", path.c_str(), PlGetError() );\n\n\ttexturePtr = GetApp()->resourceManager->GetFallbackTexture();\n}\n\nohw::TextureResource::~TextureResource() {\n\t// Don't destroy the fallback!\n\tPLGTexture *placeholderTexture = GetApp()->resourceManager->GetFallbackTexture();\n\tif ( texturePtr == placeholderTexture ) {\n\t\treturn;\n\t}\n\n\tPlgDestroyTexture( texturePtr );\n}\n"
  },
  {
    "path": "src/engine/TextureResource.h",
    "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// Copyright © 2017-2022 TalonBrave.info and Others (see CONTRIBUTORS)\n\n#pragma once\n\n#include \"Resource.h\"\n\nnamespace ohw {\n\tclass TextureResource : public Resource {\n\tpublic:\n\t\tIMPLEMENT_RESOURCE_CLASS( TextureResource )\n\n\t\texplicit TextureResource( const std::string &path, unsigned int flags = 0, bool persist = false, bool abortOnFail = false );\n\t\t~TextureResource();\n\n\t\tPLGTexture *GetInternalTexture() { return texturePtr; }\n\n\t\tinline unsigned int GetWidth() const { return texturePtr->w; }\n\t\tinline unsigned int GetHeight() const { return texturePtr->h; }\n\n\t\tinline size_t GetTextureSize() const { return texturePtr->size; }\n\n\t\tenum {\n\t\t\tFLAG_DISCARD = ( 1 << 0 ),   // Convert the background colour to alpha\n\t\t\tFLAG_NOMIPS = ( 1 << 1 ),   // Will not generate mipmaps\n\t\t\tFLAG_NEAREST = ( 1 << 2 ),   // Will use nearest filtering\n\t\t};\n\n\tprivate:\n\t\tPLGTexture *texturePtr{ nullptr };\n\t};\n\n\tusing SharedTextureResourcePointer = SharedResourcePointer< TextureResource >;\n}\n"
  },
  {
    "path": "src/engine/Timer.h",
    "content": "/* OpenHoW\n * Copyright (C) 2017-2020 TalonBrave.info and Others (see CONTRIBUTORS)\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#pragma once\n\n#include <time.h>\n\nclass Timer {\npublic:\n\tTimer() {\n\t\tclock_gettime( CLOCK_MONOTONIC, &clock );\n\t}\n\n\tvoid End() {\n\t\tstruct timespec end;\n\t\tclock_gettime( CLOCK_MONOTONIC, &end );\n\t\ttimeTaken = TimespecToDouble( TimespecSub( end, clock ) );\n\t}\n\n\tdouble GetTimeTaken() const {\n\t\treturn timeTaken;\n\t}\n\nprivate:\n#define NSEC_PER_SEC 1000000000\n\n\t/** \\fn double timespec_to_double(struct timespec ts)\n \t *  \\brief Converts a timespec to a fractional number of seconds.\n \t *  Originally written by Daniel Collins (2017), used with permission\n\t */\n\tstatic double TimespecToDouble( struct timespec ts ) {\n\t\treturn ( ( double ) ( ts.tv_sec ) + ( ( double ) ( ts.tv_nsec ) / NSEC_PER_SEC ) );\n\t}\n\n\t/** \\fn struct timespec timespec_normalise(struct timespec ts)\n\t *  \\brief Normalises a timespec structure.\n\t *\n\t * Returns a normalised version of a timespec structure, according to the\n\t * following rules:\n\t *\n\t * 1) If tv_nsec is >1,000,000,00 or <-1,000,000,000, flatten the surplus\n\t *    nanoseconds into the tv_sec field.\n\t *\n\t * 2) If tv_sec is >0 and tv_nsec is <0, decrement tv_sec and roll tv_nsec up\n\t *    to represent the same value on the positive side of the new tv_sec.\n\t *\n\t * 3) If tv_sec is <0 and tv_nsec is >0, increment tv_sec and roll tv_nsec down\n\t *    to represent the same value on the negative side of the new tv_sec.\n\t *\n\t * Originally written by Daniel Collins (2017), used with permission\n\t */\n\tstatic struct timespec TimespecNormalise( struct timespec ts ) {\n\t\twhile ( ts.tv_nsec >= NSEC_PER_SEC ) {\n\t\t\t++( ts.tv_sec );\n\t\t\tts.tv_nsec -= NSEC_PER_SEC;\n\t\t}\n\n\t\twhile ( ts.tv_nsec <= -NSEC_PER_SEC ) {\n\t\t\t--( ts.tv_sec );\n\t\t\tts.tv_nsec += NSEC_PER_SEC;\n\t\t}\n\n\t\tif ( ts.tv_nsec < 0 && ts.tv_sec > 0 ) {\n\t\t\t/* Negative nanoseconds while seconds is positive.\n\t\t\t * Decrement tv_sec and roll tv_nsec over.\n\t\t\t*/\n\n\t\t\t--( ts.tv_sec );\n\t\t\tts.tv_nsec = NSEC_PER_SEC - ( -1 * ts.tv_nsec );\n\t\t} else if ( ts.tv_nsec > 0 && ts.tv_sec < 0 ) {\n\t\t\t/* Positive nanoseconds while seconds is negative.\n\t\t\t * Increment tv_sec and roll tv_nsec over.\n\t\t\t*/\n\n\t\t\t++( ts.tv_sec );\n\t\t\tts.tv_nsec = -NSEC_PER_SEC - ( -1 * ts.tv_nsec );\n\t\t}\n\n\t\treturn ts;\n\t}\n\n\t/** \\fn struct timespec timespec_sub(struct timespec ts1, struct timespec ts2)\n \t *  \\brief Returns the result of subtracting ts2 from ts1.\n \t *  Originally written by Daniel Collins (2017), used with permission\n\t */\n\tstatic struct timespec TimespecSub( struct timespec ts1, struct timespec ts2 ) {\n\t\t/* Normalise inputs to prevent tv_nsec rollover if whole-second values\n\t\t * are packed in it.\n\t\t*/\n\t\tts1 = TimespecNormalise( ts1 );\n\t\tts2 = TimespecNormalise( ts2 );\n\n\t\tts1.tv_sec -= ts2.tv_sec;\n\t\tts1.tv_nsec -= ts2.tv_nsec;\n\n\t\treturn TimespecNormalise( ts1 );\n\t}\n\n\tstruct timespec clock;\n\tdouble timeTaken{ 0.0 };\n};\n"
  },
  {
    "path": "src/engine/Utilities.cpp",
    "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// Copyright © 2017-2022 TalonBrave.info and Others (see CONTRIBUTORS)\n\n#include \"App.h\"\n\n/****************************************************/\n/* Memory */\n\nunsigned long u_unmangle( void *source, void *destination ) {\n\t/* todo */\n\n\treturn 0;\n}\n\n/* todo: kill me */\nvoid *u_alloc( size_t num, size_t size, bool abort_on_fail ) {\n\treturn PlCAlloc( num, size, abort_on_fail );\n}\n\n/****************************************************/\n/* Filesystem */\n\nconst char *u_scan( const char *path, const char **preference ) {\n\tstatic char find[PL_SYSTEM_MAX_PATH];\n\twhile ( *preference != NULL ) {\n\t\tsnprintf( find, sizeof( find ), \"%s.%s\", path, *preference );\n\t\tif ( PlFileExists( find ) ) {\n\t\t\t//LogDebug( \"Found \\\"%s\\\"\\n\", find );\n\t\t\treturn find;\n\t\t}\n\t\tpreference++;\n\t}\n\n\tDebugMsg( \"Failed to find \\\"%s\\\"\\n\", path );\n\treturn \"\";\n}\n\nconst char *u_find2( const char *path, const char **preference, bool abort_on_fail ) {\n\tstatic char out[PL_SYSTEM_MAX_PATH];\n\tmemset( out, 0, sizeof( out ) );\n\n\tstrncpy( out, u_scan( path, preference ), sizeof( out ) );\n\tif ( *out == '\\0' ) {\n\t\tif ( abort_on_fail ) {\n\t\t\tError( \"Failed to find \\\"%s\\\"!\\n\", path );\n\t\t}\n\n\t\tWarning( \"Failed to find \\\"%s\\\"!\\n\", path );\n\t\treturn NULL;\n\t}\n\n\t//LogDebug( \"Found \\\"%s\\\"\\n\", out );\n\treturn out;\n}\n\nchar *u_new_filename( char *dst, const char *src, const char *ext ) {\n\tstrncpy( dst, src, strlen( src ) - 3 );\n\tdst[ strlen( src ) - 3 ] = '\\0';\n\tstrcat( dst, ext );\n\treturn dst;\n}\n"
  },
  {
    "path": "src/engine/Utilities.h",
    "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// Copyright © 2017-2022 TalonBrave.info and Others (see CONTRIBUTORS)\n\n#pragma once\n\n#include <string>\n#include <algorithm>\n\n#include \"MathUtilities.h\"\n\n#define u_unused( ... ) (void)( __VA_ARGS__ )\n\n#define u_fclose( FILE )  if((FILE) != NULL) { fclose((FILE)); (FILE) = NULL; }\n#define u_free( DATA )    free((DATA)); (DATA) = NULL\n\nstatic inline std::string u_stringtolower( std::string s ) {\n\tstd::transform( s.begin(), s.end(), s.begin(), ::tolower );\n\treturn s;\n}\n\nPL_EXTERN_C\n\nvoid *u_alloc( size_t num, size_t size, bool abort_on_fail );\n\nconst char *u_scan( const char *path, const char **preference );\nconst char *u_find2( const char *path, const char **preference, bool abort_on_fail );\n\nchar *u_new_filename( char *dst, const char *src, const char *ext );\n\nPL_EXTERN_C_END\n\n#ifdef _DEBUG\n#   define u_assert( a, ... ) if(!((a))) { Warning(__VA_ARGS__); Print(\"Assertion hit in \\\"%s\\\" on line %d\\n\", PL_FUNCTION, __LINE__); } assert((a))\n#else\n#   define u_assert(a, ...) if(!((a))) { LogWarn(__VA_ARGS__); }\n#endif\n"
  },
  {
    "path": "src/engine/audio/AudioManager.cpp",
    "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// Copyright © 2017-2022 TalonBrave.info and Others (see CONTRIBUTORS)\n\n#include <AL/al.h>\n#include <AL/alc.h>\n#include <AL/alext.h>\n#include <AL/efx-presets.h>\n\n#include <SDL2/SDL_audio.h>\n\n#include \"App.h\"\n#include \"Menu.h\"\n\n#include \"graphics/Camera.h\"\n\n#include \"stb_vorbis.c\"\n\nusing namespace ohw;\n\n/* todo: provide fallback to SDL2 Audio? maybe dynamically load OpenAL??\n * todo: stream music and large samples */\n\n/* Why the hell isn't this in OpenAL?! */\nstatic const char *OALErrorString( ALenum err ) {\n\tswitch ( err ) {\n\t\tcase AL_OUT_OF_MEMORY:\n\t\t\treturn \"OpenAL ran out of memory\";\n\t\tcase AL_INVALID_VALUE:\n\t\t\treturn \"Invalid value passed to OpenAL\";\n\t\tcase AL_INVALID_OPERATION:\n\t\t\treturn \"Invalid operation performed with OpenAL\";\n\t\tcase AL_INVALID_ENUM:\n\t\t\treturn \"Invalid enum passed to OpenAL\";\n\t\tcase AL_INVALID_NAME:\n\t\t\treturn \"Invalid name passed to OpenAL\";\n\n\t\tdefault:\n\t\t\treturn \"Unknown OpenAL error\";\n\t}\n}\n\n#define OALCheckErrors() \\\n{ \\\n    ALenum err = alGetError(); \\\n    if ( err != AL_NO_ERROR ) { \\\n        Error( \"%s, aborting!\\n\", OALErrorString(err) ); \\\n    } \\\n}\n\nstatic unsigned int reverb_effect_slot = 0;\nstatic unsigned int reverb_sound_slot = 0;\n\n/************************************************************/\n/* Audio Source */\n\nAudioSource::AudioSource( const AudioSample *sample, float gain, float pitch, bool looping ) :\n\t\tAudioSource( sample, { 0, 0, 0 }, { 0, 0, 0 }, false, gain, pitch, looping ) {\n\talSourcei( alSourceId, AL_SOURCE_RELATIVE, AL_TRUE );\n}\n\nAudioSource::AudioSource( const AudioSample *sample, PLVector3 pos, PLVector3 vel,\n                          bool reverb, float gain, float pitch, bool looping ) {\n\talGenSources( 1, &alSourceId );\n\tOALCheckErrors();\n\n\tSetPosition( pos );\n\tSetVelocity( vel );\n\tSetGain( gain );\n\tSetPitch( pitch );\n\tSetLooping( looping );\n\tSetReferenceDistance( 300.0F );\n\tSetRolloffFactor( 0.1F );\n\n\tif ( reverb && ohw::GetApp()->audioManager->SupportsExtension( AudioManager::ExtensionType::AUDIO_EXT_EFX ) ) {\n\t\talSource3i( alSourceId, AL_AUXILIARY_SEND_FILTER, reverb_sound_slot, 0, AL_FILTER_NULL );\n\t\tOALCheckErrors();\n\t}\n\n\tif ( sample != nullptr ) {\n\t\tSetSample( sample );\n\t}\n\n\tohw::GetApp()->audioManager->sources_.insert( this );\n}\n\nAudioSource::~AudioSource() {\n\tStopPlaying();\n\n\tif ( current_sample_ != nullptr ) {\n\t\t/* Need to clear AL_LOOPING flag before unqueueing buffer. */\n\t\talSourcei( alSourceId, AL_LOOPING, AL_FALSE );\n\t\tOALCheckErrors();\n\n\t\tunsigned int buf = current_sample_->alBufferId;\n\t\talSourceUnqueueBuffers( alSourceId, 1, &buf );\n\t\tOALCheckErrors();\n\t}\n\n\talSourcei( alSourceId, AL_BUFFER, 0 );\n\tOALCheckErrors();\n\n\talDeleteSources( 1, &alSourceId );\n\tOALCheckErrors();\n\n\tohw::GetApp()->audioManager->sources_.erase( this );\n}\n\nvoid AudioSource::SetSample( const AudioSample *sample ) {\n\tif ( sample == current_sample_ ) {\n\t\treturn;\n\t}\n\n\tif ( current_sample_ != nullptr ) {\n\t\tStopPlaying();\n\n\t\t/* Need to clear AL_LOOPING flag before unqueueing buffer. */\n\t\talSourcei( alSourceId, AL_LOOPING, AL_FALSE );\n\t\tOALCheckErrors();\n\n\t\tunsigned int buf = current_sample_->alBufferId;\n\t\talSourceUnqueueBuffers( alSourceId, 1, &buf );\n\t\tu_assert( buf == current_sample_->alBufferId );\n\t\tOALCheckErrors();\n\t}\n\n\tif ( sample != nullptr ) {\n\t\talSourceQueueBuffers( alSourceId, 1, &sample->alBufferId );\n\t\tOALCheckErrors();\n\t}\n\n\tcurrent_sample_ = sample;\n\n\tif ( sample != nullptr ) {\n\t\t/* Need to reset looping flag after queueing buffer as it can't\n\t\t * be set when no buffer is queued. */\n\t\tSetLooping( looping );\n\t}\n}\n\nconst AudioSample *AudioSource::GetSample() const {\n\treturn current_sample_;\n}\n\nvoid AudioSource::SetPosition( PLVector3 position ) {\n\talSource3f( alSourceId, AL_POSITION, position.x, position.y, position.z );\n\tOALCheckErrors();\n\tposition_ = position;\n}\n\nvoid AudioSource::SetVelocity( PLVector3 velocity ) {\n\talSource3f( alSourceId, AL_VELOCITY, velocity.x, velocity.y, velocity.z );\n\tOALCheckErrors();\n\tvelocity_ = velocity;\n}\n\nvoid AudioSource::SetGain( float gain ) {\n\talSourcef( alSourceId, AL_GAIN, gain );\n\tOALCheckErrors();\n\tgain_ = gain;\n}\n\nvoid AudioSource::SetPitch( float pitch ) {\n\talSourcef( alSourceId, AL_PITCH, pitch );\n\tOALCheckErrors();\n\tpitch_ = pitch;\n}\n\nvoid AudioSource::SetLooping( bool looping ) {\n\tthis->looping = looping;\n\n\tif ( current_sample_ != nullptr ) {\n\t\talSourcei( alSourceId, AL_LOOPING, looping ? AL_TRUE : AL_FALSE );\n\t\tOALCheckErrors();\n\t}\n}\n\nvoid AudioSource::SetReferenceDistance( float value ) {\n\talSourcef( alSourceId, AL_REFERENCE_DISTANCE, value );\n\tOALCheckErrors();\n}\n\nvoid AudioSource::SetMaximumDistance( float value ) {\n\talSourcef( alSourceId, AL_MAX_DISTANCE, value );\n\tOALCheckErrors();\n}\n\nvoid AudioSource::SetRolloffFactor( float value ) {\n\talSourcef( alSourceId, AL_ROLLOFF_FACTOR, value );\n\tOALCheckErrors();\n}\n\nvoid AudioSource::StartPlaying() {\n\talSourcePlay( alSourceId );\n\tOALCheckErrors();\n}\n\nvoid AudioSource::StopPlaying() {\n\tint state;\n\talGetSourcei( alSourceId, AL_SOURCE_STATE, &state );\n\tOALCheckErrors();\n\tif ( state != AL_PLAYING ) {\n\t\treturn;\n\t}\n\n\talSourceStop( alSourceId );\n\tOALCheckErrors();\n}\n\nbool AudioSource::IsPlaying() {\n\tint state;\n\talGetSourcei( alSourceId, AL_SOURCE_STATE, &state );\n\tOALCheckErrors();\n\n\treturn ( state == AL_PLAYING );\n}\n\nbool AudioSource::IsPaused() {\n\tint state;\n\talGetSourcei( alSourceId, AL_SOURCE_STATE, &state );\n\tOALCheckErrors();\n\n\treturn ( state == AL_PAUSED );\n}\n\nvoid AudioSource::Pause() {\n\tif ( !IsPlaying() ) {\n\t\t// nothing to pause\n\t\treturn;\n\t}\n\n\talSourcePause( alSourceId );\n\tOALCheckErrors();\n}\n\n/************************************************************/\n\nstatic LPALGENEFFECTS alGenEffects;\nstatic LPALDELETEEFFECTS alDeleteEffects;\nstatic LPALISEFFECT alIsEffect;\nstatic LPALEFFECTI alEffecti;\n//static LPALEFFECTIV alEffectiv;\nstatic LPALEFFECTF alEffectf;\n//static LPALEFFECTFV alEffectfv;\n//static LPALGETEFFECTI alGetEffecti;\n//static LPALGETEFFECTIV alGetEffectiv;\n//static LPALGETEFFECTF alGetEffectf;\n//static LPALGETEFFECTFV alGetEffectfv;\n\nstatic LPALGENAUXILIARYEFFECTSLOTS alGenAuxiliaryEffectSlots;\nstatic LPALDELETEAUXILIARYEFFECTSLOTS alDeleteAuxiliaryEffectSlots;\nstatic LPALISAUXILIARYEFFECTSLOT alIsAuxiliaryEffectSlot;\nstatic LPALAUXILIARYEFFECTSLOTI alAuxiliaryEffectSloti;\n//static LPALAUXILIARYEFFECTSLOTIV alAuxiliaryEffectSlotiv;\n//static LPALAUXILIARYEFFECTSLOTF alAuxiliaryEffectSlotf;\n//static LPALAUXILIARYEFFECTSLOTFV alAuxiliaryEffectSlotfv;\n//static LPALGETAUXILIARYEFFECTSLOTI alGetAuxiliaryEffectSloti;\n//static LPALGETAUXILIARYEFFECTSLOTIV alGetAuxiliaryEffectSlotiv;\n//static LPALGETAUXILIARYEFFECTSLOTF alGetAuxiliaryEffectSlotf;\n//static LPALGETAUXILIARYEFFECTSLOTFV alGetAuxiliaryEffectSlotfv;\n\nAudioManager::AudioManager() {\n\tALCdevice *device = alcOpenDevice( nullptr );\n\tif ( device == nullptr ) {\n\t\tError( \"failed to open audio device, aborting audio initialisation!\\n\" );\n\t}\n\n\tmemset( al_extensions_, 0, sizeof( al_extensions_ ) );\n\n\tif ( alcIsExtensionPresent( device, \"ALC_EXT_EFX\" ) ) {\n\t\tPrint( \"ALC_EXT_EFX detected\\n\" );\n\n\t\talGenEffects = ( LPALGENEFFECTS ) alGetProcAddress( \"alGenEffects\" );\n\t\talDeleteEffects = ( LPALDELETEEFFECTS ) alGetProcAddress( \"alDeleteEffects\" );\n\t\talIsEffect = ( LPALISEFFECT ) alGetProcAddress( \"alIsEffect\" );\n\t\talEffecti = ( LPALEFFECTI ) alGetProcAddress( \"alEffecti\" );\n\t\talEffectf = ( LPALEFFECTF ) alGetProcAddress( \"alEffectf\" );\n\n\t\talGenAuxiliaryEffectSlots = ( LPALGENAUXILIARYEFFECTSLOTS ) alGetProcAddress( \"alGenAuxiliaryEffectSlots\" );\n\t\talDeleteAuxiliaryEffectSlots = ( LPALDELETEAUXILIARYEFFECTSLOTS ) alGetProcAddress(\n\t\t\t\t\"alDeleteAuxiliaryEffectSlots\" );\n\t\talIsAuxiliaryEffectSlot = ( LPALISAUXILIARYEFFECTSLOT ) alGetProcAddress( \"alIsAuxiliaryEffectSlot\" );\n\t\talAuxiliaryEffectSloti = ( LPALAUXILIARYEFFECTSLOTI ) alGetProcAddress( \"alAuxiliaryEffectSloti\" );\n\n\t\tal_extensions_[ AUDIO_EXT_EFX ] = true;\n\t}\n\n\tALCcontext *context = alcCreateContext( device, nullptr );\n\tif ( context == nullptr || !alcMakeContextCurrent( context ) ) {\n\t\tError( \"Failed to create audio context, aborting audio initialisation!\\n\" );\n\t}\n\n\tif ( alIsExtensionPresent( \"AL_SOFT_buffer_samples\" ) ) {\n\t\tPrint( \"AL_SOFT_buffer_samples detected\\n\" );\n\t\tal_extensions_[ AUDIO_EXT_SOFT_BUFFER_SAMPLES ] = true;\n\t}\n\n\talDopplerFactor( 4.f );\n\talDopplerVelocity( 350.f );\n\n\tif ( al_extensions_[ AUDIO_EXT_EFX ] ) {\n\t\talGenEffects( 1, &reverb_effect_slot );\n\t\talEffecti( reverb_effect_slot, AL_EFFECT_TYPE, AL_EFFECT_REVERB );\n\t\tconst EFXEAXREVERBPROPERTIES reverb = EFX_REVERB_PRESET_OUTDOORS_DEEPCANYON;\n\t\t// EFX_REVERB_PRESET_OUTDOORS_DEEPCANYON\n\t\t// EFX_REVERB_PRESET_OUTDOORS_VALLEY\n\t\talEffectf( reverb_effect_slot, AL_REVERB_DENSITY, reverb.flDensity );\n\t\talEffectf( reverb_effect_slot, AL_REVERB_DIFFUSION, reverb.flDiffusion );\n\t\talEffectf( reverb_effect_slot, AL_REVERB_GAIN, reverb.flGain );\n\t\talEffectf( reverb_effect_slot, AL_REVERB_GAINHF, reverb.flGainHF );\n\t\talEffectf( reverb_effect_slot, AL_REVERB_DECAY_TIME, reverb.flDecayTime );\n\t\talEffectf( reverb_effect_slot, AL_REVERB_DECAY_HFRATIO, reverb.flDecayHFRatio );\n\t\talEffectf( reverb_effect_slot, AL_REVERB_REFLECTIONS_GAIN, reverb.flReflectionsGain );\n\t\talEffectf( reverb_effect_slot, AL_REVERB_REFLECTIONS_DELAY, reverb.flReflectionsDelay );\n\t\talEffectf( reverb_effect_slot, AL_REVERB_LATE_REVERB_GAIN, reverb.flLateReverbGain );\n\t\talEffectf( reverb_effect_slot, AL_REVERB_LATE_REVERB_DELAY, reverb.flLateReverbDelay );\n\t\talEffectf( reverb_effect_slot, AL_REVERB_AIR_ABSORPTION_GAINHF, reverb.flAirAbsorptionGainHF );\n\t\talEffectf( reverb_effect_slot, AL_REVERB_ROOM_ROLLOFF_FACTOR, reverb.flRoomRolloffFactor );\n\t\talEffecti( reverb_effect_slot, AL_REVERB_DECAY_HFLIMIT, reverb.iDecayHFLimit );\n\t\talGenAuxiliaryEffectSlots( 1, &reverb_sound_slot );\n\t\talAuxiliaryEffectSloti( reverb_sound_slot, AL_EFFECTSLOT_EFFECT, reverb_effect_slot );\n\t}\n\talDistanceModel( AL_EXPONENT_DISTANCE );\n\n\tPlRegisterConsoleCommand( \"stopMusic\", \"Stops the current music track.\", 0, StopMusicCommand );\n}\n\nAudioManager::~AudioManager() {\n\tPrint( \"Shutting down audio sub-system...\\n\" );\n\n\tFreeSources();\n\n\t/* FreeSources() doesn't delete musicSource. */\n\tdelete musicSource;\n\tmusicSource = nullptr;\n\n\tif ( al_extensions_[ AUDIO_EXT_EFX ] ) {\n\t\talDeleteAuxiliaryEffectSlots( 1, &reverb_sound_slot );\n\t\talDeleteEffects( 1, &reverb_effect_slot );\n\t}\n\n\tFreeSamples( true );\n\n\tALCcontext *context = alcGetCurrentContext();\n\tif ( context != nullptr ) {\n\t\tALCdevice *device = alcGetContextsDevice( context );\n\t\tif ( device != nullptr ) {\n\t\t\talcCloseDevice( device );\n\t\t}\n\n\t\talcMakeContextCurrent( nullptr );\n\t\talcDestroyContext( context );\n\t}\n}\n\nconst AudioSample *AudioManager::CacheSample( const std::string &path, bool preserve ) {\n\tauto i = samples_.find( path );\n\tif ( i != samples_.end() ) {\n\t\treturn &( i->second );\n\t}\n\n\tconst char *ext = PlGetFileExtension( path.c_str() );\n\tif ( ext == nullptr ) {\n\t\tWarning( \"Unable to identify audio format, \\\"%s\\\"!\\n\", path.c_str() );\n\t\treturn nullptr;\n\t}\n\n\tunsigned int format = 0;\n\tint freq = 0;\n\tuint32_t length;\n\tuint8_t *buffer;\n\tif ( pl_strcasecmp( ext, \"wav\" ) == 0 ) {\n\t\t// Attempt to load the Wav file\n\t\tPLFile *wavFile = PlOpenFile( path.c_str(), false );\n\t\tif ( wavFile == nullptr ) {\n\t\t\tWarning( \"Failed to load \\\"%s\\\"!\\n\", path.c_str() );\n\t\t\treturn nullptr;\n\t\t}\n\n\t\t// Allocate buffer\n\t\tint len = PlGetFileSize( wavFile );\n\t\tuint8_t *buf = static_cast<uint8_t *>(u_alloc( len, 1, true ));\n\n\t\t// For now, read the whole thing into memory\n\t\t// todo: stream!!!\n\t\tPlReadFile( wavFile, buf, 1, len );\n\t\tPlCloseFile( wavFile );\n\n\t\tSDL_AudioSpec spec;\n\t\tif ( SDL_LoadWAV_RW( SDL_RWFromMem( buf, len ), 1, &spec, &buffer, &length ) == nullptr ) {\n\t\t\tWarning( \"Failed to load \\\"%s\\\"!\\n\", path.c_str() );\n\t\t\treturn nullptr;\n\t\t}\n\n\t\tu_free( buf );\n\n\t\t/* translate the spec over to oal\n\t\t * todo: conversion... https://github.com/solemnwarning/armageddon-recorder/blob/master/src/resample.hpp#L42\n\t\t * */\n\t\tswitch ( spec.format ) {\n\t\t\tcase AUDIO_U8:\n\t\t\t\tif ( spec.channels == 1 ) {\n\t\t\t\t\tformat = AL_FORMAT_MONO8;\n\t\t\t\t} else if ( spec.channels == 2 ) {\n\t\t\t\t\tformat = AL_FORMAT_STEREO8;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase AUDIO_S16:\n\t\t\t\tif ( spec.channels == 1 ) {\n\t\t\t\t\tformat = AL_FORMAT_MONO16;\n\t\t\t\t} else if ( spec.channels == 2 ) {\n\t\t\t\t\tformat = AL_FORMAT_STEREO16;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\n\t\tif ( format == 0 ) {\n\t\t\tWarning( \"Invalid audio format for \\\"%s\\\"!\\n\", path.c_str() );\n\t\t\tSDL_FreeWAV( buffer );\n\t\t\treturn nullptr;\n\t\t}\n\n\t\tfreq = spec.freq;\n\t} else if ( pl_strcasecmp( ext, \"ogg\" ) == 0 ) {\n\t\t// Attempt to load the Ogg file\n\t\tPLFile *oggFile = PlOpenFile( path.c_str(), false );\n\t\tif ( oggFile == nullptr ) {\n\t\t\tWarning( \"Failed to load \\\"%s\\\"!\\n\", path.c_str() );\n\t\t\treturn nullptr;\n\t\t}\n\n\t\t// Allocate buffer\n\t\tint len = PlGetFileSize( oggFile );\n\t\tuint8_t *buf = static_cast<uint8_t *>(u_alloc( len, 1, true ));\n\n\t\t// For now, read the whole thing into memory (todo: stream!!!)\n\t\tPlReadFile( oggFile, buf, 1, len );\n\t\tPlCloseFile( oggFile );\n\n\t\tint vchan;\n\t\tint samples = stb_vorbis_decode_memory( buf, len, &vchan, &freq,\n\t\t                                        reinterpret_cast<short **>(&buffer) );\n\t\tif ( samples == -1 ) {\n\t\t\tWarning( \"Failed to decode ogg audio data, \\\"%s\\\"!\\n\", path.c_str() );\n\t\t\treturn nullptr;\n\t\t}\n\n\t\tlength = samples * vchan * sizeof( int16_t );\n\t\tif ( vchan == 2 ) {\n\t\t\tformat = AL_FORMAT_STEREO16;\n\t\t} else {\n\t\t\tformat = AL_FORMAT_MONO16;\n\t\t}\n\n\t\tu_free( buf );\n\t}\n\n\tauto sample = samples_.emplace(\n\t\t\tstd::piecewise_construct,\n\t\t\tstd::forward_as_tuple( path ),\n\t\t\tstd::forward_as_tuple( buffer, freq, format, length, preserve )\n\t);\n\n\treturn &( sample.first->second );\n}\n\nconst AudioSample *AudioManager::GetCachedSample( const std::string &path ) {\n\tauto i = samples_.find( path );\n\tif ( i == samples_.end() ) {\n\t\tCacheSample( path, false );\n\t\ti = samples_.find( path );\n\t\tif ( i == samples_.end() ) {\n\t\t\tError( \"Failed to load sample, \\\"%s\\\"!\\n\", path.c_str() );\n\t\t\t/* todo: in future, fall back to first loaded sound and continue? if it exists... */\n\t\t}\n\t}\n\n\treturn &( i->second );\n}\n\nAudioSource *AudioManager::CreateSource( const std::string &path, float gain, float pitch, bool looping ) {\n\treturn new AudioSource( GetCachedSample( path ), gain, pitch, looping );\n}\n\nAudioSource *AudioManager::CreateSource( const std::string &path, PLVector3 pos, PLVector3 vel, bool reverb, float gain,\n                                         float pitch, bool looping ) {\n\treturn new AudioSource( GetCachedSample( path ), pos, vel, reverb, gain, pitch, looping );\n}\n\nAudioSource *AudioManager::CreateSource( const AudioSample *sample, PLVector3 pos, PLVector3 vel, bool reverb,\n                                         float gain, float pitch, bool looping ) {\n\treturn new AudioSource( sample, pos, vel, reverb, gain, pitch, looping );\n}\n\nvoid AudioManager::SetupMusicSource() {\n\t// Setup our global music source\n\tmusicSource = new AudioSource( nullptr, cv_audio_volume_music->f_value, 1.0f, false );\n}\n\nvoid AudioManager::Tick() {\n\tPLVector3 position = { 0, 0, 0 }, angles = { 0, 0, 0 };\n\n\tCamera *camera = ohw::GetApp()->gameManager->GetActiveCamera();\n\tif ( FrontEnd_GetState() == FE_MODE_GAME && camera != nullptr ) {\n\t\tposition = camera->GetPosition();\n\t\tangles = camera->GetAngles();\n\t}\n\n\tPLVector3 forward, left, up;\n\tPlAnglesAxes( angles, &left, &up, &forward );\n\n\tfloat ori[6];\n\tori[ 0 ] = forward.z;\n\tori[ 3 ] = up.x;\n\tori[ 1 ] = forward.y;\n\tori[ 4 ] = up.y;\n\tori[ 2 ] = forward.x;\n\tori[ 5 ] = up.z;\n\n\talListener3f( AL_POSITION, position.x, position.y, position.z );\n\talListenerfv( AL_ORIENTATION, ori );\n\talListenerf( AL_GAIN, cv_audio_volume->f_value );\n\n\t// ensure destruction of temporary sources\n\tfor ( auto source = temp_sources_.begin(); source != temp_sources_.end(); ) {\n\t\tif ( ( *source )->IsPlaying() || ( *source )->IsPaused() ) {\n\t\t\t++source;\n\t\t\tcontinue;\n\t\t}\n\n\t\t// this will automatically kill it everywhere\n\t\tdelete ( *source );\n\t\tsource = temp_sources_.erase( source );\n\t}\n}\n\nvoid AudioManager::PlayGlobalSound( const std::string &path ) {\n\tconst AudioSample *sample = GetCachedSample( path );\n\tPlayGlobalSound( sample );\n}\n\nvoid AudioManager::PlayGlobalSound( const AudioSample *sample ) {\n\tif ( sample == nullptr ) {\n\t\treturn;\n\t}\n\n\tauto *source = new AudioSource( sample );\n\ttemp_sources_.insert( source );\n\tsource->StartPlaying();\n}\n\nvoid AudioManager::PlayLocalSound( const std::string &path, PLVector3 pos, PLVector3 vel, bool reverb, float gain,\n                                   float pitch ) {\n\tconst AudioSample *sample = GetCachedSample( path );\n\tPlayLocalSound( sample, pos, vel, reverb, gain, pitch );\n}\n\nvoid AudioManager::PlayLocalSound( const AudioSample *sample, PLVector3 pos, PLVector3 vel, bool reverb, float gain,\n                                   float pitch ) {\n\tif ( sample == nullptr ) {\n\t\treturn;\n\t}\n\n\tauto *source = new AudioSource( sample, pos, vel, reverb, gain, pitch );\n\ttemp_sources_.insert( source );\n\tsource->StartPlaying();\n}\n\nvoid AudioManager::SilenceSources() {\n\tfor ( auto sound: sources_ ) {\n\t\tsound->StopPlaying();\n\t}\n}\n\n/* Will invalidate ALL references to AudioSource objects.\n * Only use in contexts where this is safe. */\nvoid AudioManager::FreeSources() {\n\tPrint( \"Freeing all audio sources...\\n\" );\n\n\tfor ( auto s = sources_.begin(); s != sources_.end(); ) {\n\t\tAudioSource *source = *s;\n\t\t++s;\n\n\t\t// Don't destroy our music source, it needs to be preserved!\n\t\tif ( source == musicSource ) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tsource->StopPlaying();\n\t\tdelete source;\n\t}\n\n\ttemp_sources_.clear();\n}\n\nvoid AudioManager::FreeSamples( bool force ) {\n\tPrint( \"Freeing all audio samples...\\n\" );\n\n\tif ( force ) {\n\t\t/* clears absolutely everything */\n\t\tsamples_.clear();\n\t} else {\n\t\t/* clears only those not marked with preserve */\n\t\tfor ( auto sample = samples_.begin(); sample != samples_.end(); ) {\n\t\t\tif ( !sample->second.preserve_ ) {\n\t\t\t\tsample = samples_.erase( sample );\n\t\t\t} else {\n\t\t\t\t++sample;\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Debug function for drawing audio sources.\n */\nvoid AudioManager::DrawSources() {\n\tif ( !cv_graphics_draw_audio_sources->b_value ) {\n\t\treturn;\n\t}\n\n\tPLMModel *sprite = ohw::GetApp()->resourceManager->GetFallbackModel();\n\tPLGMesh *mesh = sprite->meshes[ 0 ];\n\tPlgSetMeshUniformColour( mesh, hei::Colour( 0, 255, 255, 255 ) );\n\tfor ( auto source: sources_ ) {\n\t\tif ( !source->IsPlaying() || source->IsPaused() ) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tsprite->modelMatrix = PlTranslateMatrix4( source->GetPosition() );\n\t\tPlmDrawModel( sprite );\n\t}\n\tPlgSetMeshUniformColour( mesh, hei::Colour( 255, 0, 0, 255 ) );\n}\n\n/**\n * Play the specified music globally.\n * @param path Path to the sample to be played.\n */\nvoid AudioManager::PlayMusic( const std::string &path ) {\n\tconst AudioSample *sample = CacheSample( path );\n\tif ( sample == nullptr ) {\n\t\treturn;\n\t}\n\n\tmusicSource->StopPlaying();\n\n\tmusicSource->SetSample( sample );\n\tmusicSource->StartPlaying();\n}\n\nvoid AudioManager::PauseMusic() {\n\tmusicSource->Pause();\n}\n\nvoid AudioManager::StopMusic() {\n\tmusicSource->StopPlaying();\n}\n\nvoid AudioManager::SetMusicVolume( float gain ) {\n\tmusicSource->SetGain( gain );\n}\n\nvoid AudioManager::SetMusicVolumeCommand( const PLConsoleVariable *var ) {\n\tohw::GetApp()->audioManager->SetMusicVolume( var->f_value );\n}\n\nvoid AudioManager::StopMusicCommand( unsigned int argc, char *argv[] ) {\n\tu_unused( argc );\n\tu_unused( argv );\n\n\tohw::GetApp()->audioManager->StopMusic();\n}\n\n/************************************************************/\n/* Audio Sample */\n\nAudioSample::~AudioSample() {\n\t/* Unbind any AudioSource objects which are using this sample.\n\t * Scanning all sources is slow, but this is only expected to be called\n\t * during game teardown.\n\t*/\n\tfor ( auto &source: ohw::GetApp()->audioManager->sources_ ) {\n\t\tif ( source->GetSample() == this ) {\n\t\t\tsource->SetSample( nullptr );\n\t\t}\n\t}\n\n\talDeleteBuffers( 1, &alBufferId );\n\tOALCheckErrors();\n\n\tSDL_FreeWAV( data_ );\n}\n\nAudioSample::AudioSample( uint8_t *data, unsigned int freq, unsigned int format, unsigned int length, bool preserve ) {\n\talGenBuffers( 1, &alBufferId );\n\tOALCheckErrors();\n\talBufferData( alBufferId, format, data, length, freq );\n\tOALCheckErrors();\n}\n"
  },
  {
    "path": "src/engine/audio/AudioManager.h",
    "content": "/* OpenHoW\n * Copyright (C) 2017-2020 TalonBrave.info and Others (see CONTRIBUTORS)\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#pragma once\n\n/* included again here just\n * so we don't have to provide\n * the OpenAL headers here.     */\ntypedef enum {\n\tAUDIO_REVERB_GENERIC,\n\tAUDIO_REVERB_PADDEDCELL,\n\tAUDIO_REVERB_ROOM,\n\tAUDIO_REVERB_BATHROOM,\n\tAUDIO_REVERB_LIVINGROOM,\n\tAUDIO_REVERB_STONEROOM,\n\tAUDIO_REVERB_AUDITORIUM,\n\tAUDIO_REVERB_CONCERTHALL,\n\tAUDIO_REVERB_CAVE,\n\tAUDIO_REVERB_ARENA,\n\tAUDIO_REVERB_HANGAR,\n\tAUDIO_REVERB_CARPETEDHALLWAY,\n\tAUDIO_REVERB_HALLWAY,\n\tAUDIO_REVERB_STONECORRIDOR,\n\tAUDIO_REVERB_ALLEY,\n\tAUDIO_REVERB_FOREST,\n\tAUDIO_REVERB_CITY,\n\tAUDIO_REVERB_MOUNTAINS,\n\tAUDIO_REVERB_QUARRY,\n\tAUDIO_REVERB_PLAIN,\n\tAUDIO_REVERB_PARKINGLOT,\n\tAUDIO_REVERB_SEWERPIPE,\n\tAUDIO_REVERB_UNDERWATER,\n\tAUDIO_REVERB_DRUGGED,\n\tAUDIO_REVERB_DIZZY,\n\tAUDIO_REVERB_PSYCHOTIC,\n\tAUDIO_REVERB_CHAPEL\n} AudioEffectReverb;\n\nclass AudioSource;\n\n#define AUDIO_MUSIC_FIELD   \"music/track01.ogg\"\n#define AUDIO_MUSIC_MENU    \"music/track02.ogg\"\n#define AUDIO_MUSIC_VICTORY \"music/track31.ogg\"\n\nstruct AudioSample {\n\tAudioSample( uint8_t *data, unsigned int freq, unsigned int format, unsigned int length, bool preserve );\n\t~AudioSample();\n\n\tunsigned int alBufferId{ 0 };\n\tuint8_t *data_{ nullptr };\n\tbool preserve_{ false };\n};\n\nclass AudioManager {\n\tfriend struct AudioSample;\n\tfriend class AudioSource;\n\npublic:\n\tAudioManager();\n\t~AudioManager();\n\n\tvoid SetupMusicSource();\n\n\tvoid Tick();\n\n\tconst AudioSample *GetCachedSample( const std::string &path );\n\tconst AudioSample *CacheSample( const std::string &path, bool preserve = false );\n\n\tAudioSource *CreateSource( const std::string &path, float gain = 1.0f, float pitch = 1.0f, bool looping = false );\n\tAudioSource *CreateSource( const std::string &path, PLVector3 pos, PLVector3 vel, bool reverb = false,\n\t\t\t\t\t\t\t   float gain = 1.0f, float pitch = 1.0f, bool looping = false );\n\tAudioSource *CreateSource( const AudioSample *sample = nullptr,\n\t\t\t\t\t\t\t   PLVector3 pos = { 0, 0, 0 },\n\t\t\t\t\t\t\t   PLVector3 vel = { 0, 0, 0 },\n\t\t\t\t\t\t\t   bool reverb = false,\n\t\t\t\t\t\t\t   float gain = 1.0f,\n\t\t\t\t\t\t\t   float pitch = 1.0f,\n\t\t\t\t\t\t\t   bool looping = false );\n\n\tvoid PlayGlobalSound( const std::string &path );\n\tvoid PlayGlobalSound( const AudioSample *sample );\n\tvoid PlayLocalSound( const std::string &path, PLVector3 pos, PLVector3 vel = { 0, 0, 0 }, bool reverb = false,\n\t\t\t\t\t\t float gain = 1.0f, float pitch = 1.0f );\n\tvoid PlayLocalSound( const AudioSample *sample, PLVector3 pos, PLVector3 vel = { 0, 0, 0 }, bool reverb = false,\n\t\t\t\t\t\t float gain = 1.0f, float pitch = 1.0f );\n\n\tvoid PlayMusic( const std::string &path );\n\tvoid PauseMusic();\n\tvoid StopMusic();\n\tvoid SetMusicVolume( float gain );\n\n\tvoid SilenceSources();\n\n\tvoid FreeSources();\n\tvoid FreeSamples( bool force = false );\n\n\tvoid DrawSources();\n\n\tenum ExtensionType {\n\t\tAUDIO_EXT_EFX,\n\t\tAUDIO_EXT_SOFT_BUFFER_SAMPLES,\n\n\t\tMAX_AUDIO_EXT_SLOTS\n\t};\n\tinline bool SupportsExtension( ExtensionType extension ) {\n\t\treturn al_extensions_[ extension ];\n\t}\n\nprotected:\nprivate:\n\tbool al_extensions_[MAX_AUDIO_EXT_SLOTS]{\n\t\tfalse, false\n\t};\n\n\tstatic void SetMusicVolumeCommand( const PLConsoleVariable *var );\n\tstatic void StopMusicCommand( unsigned int argc, char *argv[] );\n\n\tstd::map<std::string, AudioSample> samples_;\n\tstd::set<AudioSource *> sources_;\n\tstd::set<AudioSource *> temp_sources_;\n\n\tAudioSource *musicSource{ nullptr };\n};\n\nclass AudioSource {\npublic:\n\texplicit AudioSource( const AudioSample *sample, float gain = 1.0f, float pitch = 1.0f, bool looping = false );\n\tAudioSource( const AudioSample *sample,\n\t\t\t\t PLVector3 pos,\n\t\t\t\t PLVector3 vel,\n\t\t\t\t bool reverb = false,\n\t\t\t\t float gain = 1.0f,\n\t\t\t\t float pitch = 1.0f,\n\t\t\t\t bool looping = false );\n\t~AudioSource();\n\n\tvoid SetSample( const AudioSample *sample );\n\tconst AudioSample *GetSample() const;\n\tvoid SetPosition( PLVector3 position );\n\tvoid SetVelocity( PLVector3 velocity );\n\tvoid SetGain( float gain );\n\tvoid SetPitch( float pitch );\n\tvoid SetLooping( bool looping );\n\tvoid SetReferenceDistance( float value );\n\tvoid SetMaximumDistance( float value );\n\tvoid SetRolloffFactor( float value );\n\n\tPLVector3 GetPosition() { return position_; }\n\tPLVector3 GetVelocity() { return velocity_; }\n\tfloat GetGain() { return gain_; }\n\tfloat GetPitch() { return pitch_; }\n\n\tvoid StartPlaying();\n\tvoid StopPlaying();\n\tvoid Pause();\n\n\tbool IsPlaying();\n\tbool IsPaused();\n\nprivate:\n\tPLVector3 position_{ 0, 0, 0 };\n\tPLVector3 velocity_{ 0, 0, 0 };\n\n\tfloat gain_{ 1.0f };\n\tfloat pitch_{ 1.0f };\n\n\tunsigned int alSourceId{ 0 };\n\tconst AudioSample *current_sample_{ nullptr };\n\tbool looping{ false };\n};\n"
  },
  {
    "path": "src/engine/audio/stb_vorbis.c",
    "content": "// Ogg Vorbis audio decoder - v1.16 - public domain\n// http://nothings.org/stb_vorbis/\n//\n// Original version written by Sean Barrett in 2007.\n//\n// Originally sponsored by RAD Game Tools. Seeking implementation\n// sponsored by Phillip Bennefall, Marc Andersen, Aaron Baker,\n// Elias Software, Aras Pranckevicius, and Sean Barrett.\n//\n// LICENSE\n//\n//   See end of file for license information.\n//\n// Limitations:\n//\n//   - floor 0 not supported (used in old ogg vorbis files pre-2004)\n//   - lossless sample-truncation at beginning ignored\n//   - cannot concatenate multiple vorbis streams\n//   - sample positions are 32-bit, limiting seekable 192Khz\n//       files to around 6 hours (Ogg supports 64-bit)\n//\n// Feature contributors:\n//    Dougall Johnson (sample-exact seeking)\n//\n// Bugfix/warning contributors:\n//    Terje Mathisen     Niklas Frykholm     Andy Hill\n//    Casey Muratori     John Bolton         Gargaj\n//    Laurent Gomila     Marc LeBlanc        Ronny Chevalier\n//    Bernhard Wodo      Evan Balster        alxprd@github\n//    Tom Beaumont       Ingo Leitgeb        Nicolas Guillemot\n//    Phillip Bennefall  Rohit               Thiago Goulart\n//    manxorist@github   saga musix          github:infatum\n//    Timur Gagiev\n//\n// Partial history:\n//    1.16    - 2019-03-04 - fix warnings\n//    1.15    - 2019-02-07 - explicit failure if Ogg Skeleton data is found\n//    1.14    - 2018-02-11 - delete bogus dealloca usage\n//    1.13    - 2018-01-29 - fix truncation of last frame (hopefully)\n//    1.12    - 2017-11-21 - limit residue begin/end to blocksize/2 to avoid large temp allocs in bad/corrupt files\n//    1.11    - 2017-07-23 - fix MinGW compilation \n//    1.10    - 2017-03-03 - more robust seeking; fix negative ilog(); clear error in open_memory\n//    1.09    - 2016-04-04 - back out 'truncation of last frame' fix from previous version\n//    1.08    - 2016-04-02 - warnings; setup memory leaks; truncation of last frame\n//    1.07    - 2015-01-16 - fixes for crashes on invalid files; warning fixes; const\n//    1.06    - 2015-08-31 - full, correct support for seeking API (Dougall Johnson)\n//                           some crash fixes when out of memory or with corrupt files\n//                           fix some inappropriately signed shifts\n//    1.05    - 2015-04-19 - don't define __forceinline if it's redundant\n//    1.04    - 2014-08-27 - fix missing const-correct case in API\n//    1.03    - 2014-08-07 - warning fixes\n//    1.02    - 2014-07-09 - declare qsort comparison as explicitly _cdecl in Windows\n//    1.01    - 2014-06-18 - fix stb_vorbis_get_samples_float (interleaved was correct)\n//    1.0     - 2014-05-26 - fix memory leaks; fix warnings; fix bugs in >2-channel;\n//                           (API change) report sample rate for decode-full-file funcs\n//\n// See end of file for full version history.\n\n\n//////////////////////////////////////////////////////////////////////////////\n//\n//  HEADER BEGINS HERE\n//\n\n#ifndef STB_VORBIS_INCLUDE_STB_VORBIS_H\n#define STB_VORBIS_INCLUDE_STB_VORBIS_H\n\n#if defined(STB_VORBIS_NO_CRT) && !defined(STB_VORBIS_NO_STDIO)\n#define STB_VORBIS_NO_STDIO 1\n#endif\n\n#ifndef STB_VORBIS_NO_STDIO\n#include <stdio.h>\n#endif\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n///////////   THREAD SAFETY\n\n// Individual stb_vorbis* handles are not thread-safe; you cannot decode from\n// them from multiple threads at the same time. However, you can have multiple\n// stb_vorbis* handles and decode from them independently in multiple thrads.\n\n\n///////////   MEMORY ALLOCATION\n\n// normally stb_vorbis uses malloc() to allocate memory at startup,\n// and alloca() to allocate temporary memory during a frame on the\n// stack. (Memory consumption will depend on the amount of setup\n// data in the file and how you set the compile flags for speed\n// vs. size. In my test files the maximal-size usage is ~150KB.)\n//\n// You can modify the wrapper functions in the source (setup_malloc,\n// setup_temp_malloc, temp_malloc) to change this behavior, or you\n// can use a simpler allocation model: you pass in a buffer from\n// which stb_vorbis will allocate _all_ its memory (including the\n// temp memory). \"open\" may fail with a VORBIS_outofmem if you\n// do not pass in enough data; there is no way to determine how\n// much you do need except to succeed (at which point you can\n// query get_info to find the exact amount required. yes I know\n// this is lame).\n//\n// If you pass in a non-NULL buffer of the type below, allocation\n// will occur from it as described above. Otherwise just pass NULL\n// to use malloc()/alloca()\n\ntypedef struct\n{\n   char *alloc_buffer;\n   int   alloc_buffer_length_in_bytes;\n} stb_vorbis_alloc;\n\n\n///////////   FUNCTIONS USEABLE WITH ALL INPUT MODES\n\ntypedef struct stb_vorbis stb_vorbis;\n\ntypedef struct\n{\n   unsigned int sample_rate;\n   int channels;\n\n   unsigned int setup_memory_required;\n   unsigned int setup_temp_memory_required;\n   unsigned int temp_memory_required;\n\n   int max_frame_size;\n} stb_vorbis_info;\n\n// get general information about the file\nextern stb_vorbis_info stb_vorbis_get_info(stb_vorbis *f);\n\n// get the last error detected (clears it, too)\nextern int stb_vorbis_get_error(stb_vorbis *f);\n\n// close an ogg vorbis file and free all memory in use\nextern void stb_vorbis_close(stb_vorbis *f);\n\n// this function returns the offset (in samples) from the beginning of the\n// file that will be returned by the next decode, if it is known, or -1\n// otherwise. after a flush_pushdata() call, this may take a while before\n// it becomes valid again.\n// NOT WORKING YET after a seek with PULLDATA API\nextern int stb_vorbis_get_sample_offset(stb_vorbis *f);\n\n// returns the current seek point within the file, or offset from the beginning\n// of the memory buffer. In pushdata mode it returns 0.\nextern unsigned int stb_vorbis_get_file_offset(stb_vorbis *f);\n\n///////////   PUSHDATA API\n\n#ifndef STB_VORBIS_NO_PUSHDATA_API\n\n// this API allows you to get blocks of data from any source and hand\n// them to stb_vorbis. you have to buffer them; stb_vorbis will tell\n// you how much it used, and you have to give it the rest next time;\n// and stb_vorbis may not have enough data to work with and you will\n// need to give it the same data again PLUS more. Note that the Vorbis\n// specification does not bound the size of an individual frame.\n\nextern stb_vorbis *stb_vorbis_open_pushdata(\n         const unsigned char * datablock, int datablock_length_in_bytes,\n         int *datablock_memory_consumed_in_bytes,\n         int *error,\n         const stb_vorbis_alloc *alloc_buffer);\n// create a vorbis decoder by passing in the initial data block containing\n//    the ogg&vorbis headers (you don't need to do parse them, just provide\n//    the first N bytes of the file--you're told if it's not enough, see below)\n// on success, returns an stb_vorbis *, does not set error, returns the amount of\n//    data parsed/consumed on this call in *datablock_memory_consumed_in_bytes;\n// on failure, returns NULL on error and sets *error, does not change *datablock_memory_consumed\n// if returns NULL and *error is VORBIS_need_more_data, then the input block was\n//       incomplete and you need to pass in a larger block from the start of the file\n\nextern int stb_vorbis_decode_frame_pushdata(\n         stb_vorbis *f,\n         const unsigned char *datablock, int datablock_length_in_bytes,\n         int *channels,             // place to write number of float * buffers\n         float ***output,           // place to write float ** array of float * buffers\n         int *samples               // place to write number of output samples\n     );\n// decode a frame of audio sample data if possible from the passed-in data block\n//\n// return value: number of bytes we used from datablock\n//\n// possible cases:\n//     0 bytes used, 0 samples output (need more data)\n//     N bytes used, 0 samples output (resynching the stream, keep going)\n//     N bytes used, M samples output (one frame of data)\n// note that after opening a file, you will ALWAYS get one N-bytes,0-sample\n// frame, because Vorbis always \"discards\" the first frame.\n//\n// Note that on resynch, stb_vorbis will rarely consume all of the buffer,\n// instead only datablock_length_in_bytes-3 or less. This is because it wants\n// to avoid missing parts of a page header if they cross a datablock boundary,\n// without writing state-machiney code to record a partial detection.\n//\n// The number of channels returned are stored in *channels (which can be\n// NULL--it is always the same as the number of channels reported by\n// get_info). *output will contain an array of float* buffers, one per\n// channel. In other words, (*output)[0][0] contains the first sample from\n// the first channel, and (*output)[1][0] contains the first sample from\n// the second channel.\n\nextern void stb_vorbis_flush_pushdata(stb_vorbis *f);\n// inform stb_vorbis that your next datablock will not be contiguous with\n// previous ones (e.g. you've seeked in the data); future attempts to decode\n// frames will cause stb_vorbis to resynchronize (as noted above), and\n// once it sees a valid Ogg page (typically 4-8KB, as large as 64KB), it\n// will begin decoding the _next_ frame.\n//\n// if you want to seek using pushdata, you need to seek in your file, then\n// call stb_vorbis_flush_pushdata(), then start calling decoding, then once\n// decoding is returning you data, call stb_vorbis_get_sample_offset, and\n// if you don't like the result, seek your file again and repeat.\n#endif\n\n\n//////////   PULLING INPUT API\n\n#ifndef STB_VORBIS_NO_PULLDATA_API\n// This API assumes stb_vorbis is allowed to pull data from a source--\n// either a block of memory containing the _entire_ vorbis stream, or a\n// FILE * that you or it create, or possibly some other reading mechanism\n// if you go modify the source to replace the FILE * case with some kind\n// of callback to your code. (But if you don't support seeking, you may\n// just want to go ahead and use pushdata.)\n\n#if !defined(STB_VORBIS_NO_STDIO) && !defined(STB_VORBIS_NO_INTEGER_CONVERSION)\nextern int stb_vorbis_decode_filename(const char *filename, int *channels, int *sample_rate, short **output);\n#endif\n#if !defined(STB_VORBIS_NO_INTEGER_CONVERSION)\nextern int stb_vorbis_decode_memory(const unsigned char *mem, int len, int *channels, int *sample_rate, short **output);\n#endif\n// decode an entire file and output the data interleaved into a malloc()ed\n// buffer stored in *output. The return value is the number of samples\n// decoded, or -1 if the file could not be opened or was not an ogg vorbis file.\n// When you're done with it, just free() the pointer returned in *output.\n\nextern stb_vorbis * stb_vorbis_open_memory(const unsigned char *data, int len,\n                                  int *error, const stb_vorbis_alloc *alloc_buffer);\n// create an ogg vorbis decoder from an ogg vorbis stream in memory (note\n// this must be the entire stream!). on failure, returns NULL and sets *error\n\n#ifndef STB_VORBIS_NO_STDIO\nextern stb_vorbis * stb_vorbis_open_filename(const char *filename,\n                                  int *error, const stb_vorbis_alloc *alloc_buffer);\n// create an ogg vorbis decoder from a filename via fopen(). on failure,\n// returns NULL and sets *error (possibly to VORBIS_file_open_failure).\n\nextern stb_vorbis * stb_vorbis_open_file(FILE *f, int close_handle_on_close,\n                                  int *error, const stb_vorbis_alloc *alloc_buffer);\n// create an ogg vorbis decoder from an open FILE *, looking for a stream at\n// the _current_ seek point (ftell). on failure, returns NULL and sets *error.\n// note that stb_vorbis must \"own\" this stream; if you seek it in between\n// calls to stb_vorbis, it will become confused. Moreover, if you attempt to\n// perform stb_vorbis_seek_*() operations on this file, it will assume it\n// owns the _entire_ rest of the file after the start point. Use the next\n// function, stb_vorbis_open_file_section(), to limit it.\n\nextern stb_vorbis * stb_vorbis_open_file_section(FILE *f, int close_handle_on_close,\n                int *error, const stb_vorbis_alloc *alloc_buffer, unsigned int len);\n// create an ogg vorbis decoder from an open FILE *, looking for a stream at\n// the _current_ seek point (ftell); the stream will be of length 'len' bytes.\n// on failure, returns NULL and sets *error. note that stb_vorbis must \"own\"\n// this stream; if you seek it in between calls to stb_vorbis, it will become\n// confused.\n#endif\n\nextern int stb_vorbis_seek_frame(stb_vorbis *f, unsigned int sample_number);\nextern int stb_vorbis_seek(stb_vorbis *f, unsigned int sample_number);\n// these functions seek in the Vorbis file to (approximately) 'sample_number'.\n// after calling seek_frame(), the next call to get_frame_*() will include\n// the specified sample. after calling stb_vorbis_seek(), the next call to\n// stb_vorbis_get_samples_* will start with the specified sample. If you\n// do not need to seek to EXACTLY the target sample when using get_samples_*,\n// you can also use seek_frame().\n\nextern int stb_vorbis_seek_start(stb_vorbis *f);\n// this function is equivalent to stb_vorbis_seek(f,0)\n\nextern unsigned int stb_vorbis_stream_length_in_samples(stb_vorbis *f);\nextern float        stb_vorbis_stream_length_in_seconds(stb_vorbis *f);\n// these functions return the total length of the vorbis stream\n\nextern int stb_vorbis_get_frame_float(stb_vorbis *f, int *channels, float ***output);\n// decode the next frame and return the number of samples. the number of\n// channels returned are stored in *channels (which can be NULL--it is always\n// the same as the number of channels reported by get_info). *output will\n// contain an array of float* buffers, one per channel. These outputs will\n// be overwritten on the next call to stb_vorbis_get_frame_*.\n//\n// You generally should not intermix calls to stb_vorbis_get_frame_*()\n// and stb_vorbis_get_samples_*(), since the latter calls the former.\n\n#ifndef STB_VORBIS_NO_INTEGER_CONVERSION\nextern int stb_vorbis_get_frame_short_interleaved(stb_vorbis *f, int num_c, short *buffer, int num_shorts);\nextern int stb_vorbis_get_frame_short            (stb_vorbis *f, int num_c, short **buffer, int num_samples);\n#endif\n// decode the next frame and return the number of *samples* per channel.\n// Note that for interleaved data, you pass in the number of shorts (the\n// size of your array), but the return value is the number of samples per\n// channel, not the total number of samples.\n//\n// The data is coerced to the number of channels you request according to the\n// channel coercion rules (see below). You must pass in the size of your\n// buffer(s) so that stb_vorbis will not overwrite the end of the buffer.\n// The maximum buffer size needed can be gotten from get_info(); however,\n// the Vorbis I specification implies an absolute maximum of 4096 samples\n// per channel.\n\n// Channel coercion rules:\n//    Let M be the number of channels requested, and N the number of channels present,\n//    and Cn be the nth channel; let stereo L be the sum of all L and center channels,\n//    and stereo R be the sum of all R and center channels (channel assignment from the\n//    vorbis spec).\n//        M    N       output\n//        1    k      sum(Ck) for all k\n//        2    *      stereo L, stereo R\n//        k    l      k > l, the first l channels, then 0s\n//        k    l      k <= l, the first k channels\n//    Note that this is not _good_ surround etc. mixing at all! It's just so\n//    you get something useful.\n\nextern int stb_vorbis_get_samples_float_interleaved(stb_vorbis *f, int channels, float *buffer, int num_floats);\nextern int stb_vorbis_get_samples_float(stb_vorbis *f, int channels, float **buffer, int num_samples);\n// gets num_samples samples, not necessarily on a frame boundary--this requires\n// buffering so you have to supply the buffers. DOES NOT APPLY THE COERCION RULES.\n// Returns the number of samples stored per channel; it may be less than requested\n// at the end of the file. If there are no more samples in the file, returns 0.\n\n#ifndef STB_VORBIS_NO_INTEGER_CONVERSION\nextern int stb_vorbis_get_samples_short_interleaved(stb_vorbis *f, int channels, short *buffer, int num_shorts);\nextern int stb_vorbis_get_samples_short(stb_vorbis *f, int channels, short **buffer, int num_samples);\n#endif\n// gets num_samples samples, not necessarily on a frame boundary--this requires\n// buffering so you have to supply the buffers. Applies the coercion rules above\n// to produce 'channels' channels. Returns the number of samples stored per channel;\n// it may be less than requested at the end of the file. If there are no more\n// samples in the file, returns 0.\n\n#endif\n\n////////   ERROR CODES\n\nenum STBVorbisError\n{\n   VORBIS__no_error,\n\n   VORBIS_need_more_data=1,             // not a real error\n\n   VORBIS_invalid_api_mixing,           // can't mix API modes\n   VORBIS_outofmem,                     // not enough memory\n   VORBIS_feature_not_supported,        // uses floor 0\n   VORBIS_too_many_channels,            // STB_VORBIS_MAX_CHANNELS is too small\n   VORBIS_file_open_failure,            // fopen() failed\n   VORBIS_seek_without_length,          // can't seek in unknown-length file\n\n   VORBIS_unexpected_eof=10,            // file is truncated?\n   VORBIS_seek_invalid,                 // seek past EOF\n\n   // decoding errors (corrupt/invalid stream) -- you probably\n   // don't care about the exact details of these\n\n   // vorbis errors:\n   VORBIS_invalid_setup=20,\n   VORBIS_invalid_stream,\n\n   // ogg errors:\n   VORBIS_missing_capture_pattern=30,\n   VORBIS_invalid_stream_structure_version,\n   VORBIS_continued_packet_flag_invalid,\n   VORBIS_incorrect_stream_serial_number,\n   VORBIS_invalid_first_page,\n   VORBIS_bad_packet_type,\n   VORBIS_cant_find_last_page,\n   VORBIS_seek_failed,\n   VORBIS_ogg_skeleton_not_supported\n};\n\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif // STB_VORBIS_INCLUDE_STB_VORBIS_H\n//\n//  HEADER ENDS HERE\n//\n//////////////////////////////////////////////////////////////////////////////\n\n#ifndef STB_VORBIS_HEADER_ONLY\n\n// global configuration settings (e.g. set these in the project/makefile),\n// or just set them in this file at the top (although ideally the first few\n// should be visible when the header file is compiled too, although it's not\n// crucial)\n\n// STB_VORBIS_NO_PUSHDATA_API\n//     does not compile the code for the various stb_vorbis_*_pushdata()\n//     functions\n// #define STB_VORBIS_NO_PUSHDATA_API\n\n// STB_VORBIS_NO_PULLDATA_API\n//     does not compile the code for the non-pushdata APIs\n// #define STB_VORBIS_NO_PULLDATA_API\n\n// STB_VORBIS_NO_STDIO\n//     does not compile the code for the APIs that use FILE *s internally\n//     or externally (implied by STB_VORBIS_NO_PULLDATA_API)\n// #define STB_VORBIS_NO_STDIO\n\n// STB_VORBIS_NO_INTEGER_CONVERSION\n//     does not compile the code for converting audio sample data from\n//     float to integer (implied by STB_VORBIS_NO_PULLDATA_API)\n// #define STB_VORBIS_NO_INTEGER_CONVERSION\n\n// STB_VORBIS_NO_FAST_SCALED_FLOAT\n//      does not use a fast float-to-int trick to accelerate float-to-int on\n//      most platforms which requires endianness be defined correctly.\n//#define STB_VORBIS_NO_FAST_SCALED_FLOAT\n\n\n// STB_VORBIS_MAX_CHANNELS [number]\n//     globally define this to the maximum number of channels you need.\n//     The spec does not put a restriction on channels except that\n//     the count is stored in a byte, so 255 is the hard limit.\n//     Reducing this saves about 16 bytes per value, so using 16 saves\n//     (255-16)*16 or around 4KB. Plus anything other memory usage\n//     I forgot to account for. Can probably go as low as 8 (7.1 audio),\n//     6 (5.1 audio), or 2 (stereo only).\n#ifndef STB_VORBIS_MAX_CHANNELS\n#define STB_VORBIS_MAX_CHANNELS    16  // enough for anyone?\n#endif\n\n// STB_VORBIS_PUSHDATA_CRC_COUNT [number]\n//     after a flush_pushdata(), stb_vorbis begins scanning for the\n//     next valid page, without backtracking. when it finds something\n//     that looks like a page, it streams through it and verifies its\n//     CRC32. Should that validation fail, it keeps scanning. But it's\n//     possible that _while_ streaming through to check the CRC32 of\n//     one candidate page, it sees another candidate page. This #define\n//     determines how many \"overlapping\" candidate pages it can search\n//     at once. Note that \"real\" pages are typically ~4KB to ~8KB, whereas\n//     garbage pages could be as big as 64KB, but probably average ~16KB.\n//     So don't hose ourselves by scanning an apparent 64KB page and\n//     missing a ton of real ones in the interim; so minimum of 2\n#ifndef STB_VORBIS_PUSHDATA_CRC_COUNT\n#define STB_VORBIS_PUSHDATA_CRC_COUNT  4\n#endif\n\n// STB_VORBIS_FAST_HUFFMAN_LENGTH [number]\n//     sets the log size of the huffman-acceleration table.  Maximum\n//     supported value is 24. with larger numbers, more decodings are O(1),\n//     but the table size is larger so worse cache missing, so you'll have\n//     to probe (and try multiple ogg vorbis files) to find the sweet spot.\n#ifndef STB_VORBIS_FAST_HUFFMAN_LENGTH\n#define STB_VORBIS_FAST_HUFFMAN_LENGTH   10\n#endif\n\n// STB_VORBIS_FAST_BINARY_LENGTH [number]\n//     sets the log size of the binary-search acceleration table. this\n//     is used in similar fashion to the fast-huffman size to set initial\n//     parameters for the binary search\n\n// STB_VORBIS_FAST_HUFFMAN_INT\n//     The fast huffman tables are much more efficient if they can be\n//     stored as 16-bit results instead of 32-bit results. This restricts\n//     the codebooks to having only 65535 possible outcomes, though.\n//     (At least, accelerated by the huffman table.)\n#ifndef STB_VORBIS_FAST_HUFFMAN_INT\n#define STB_VORBIS_FAST_HUFFMAN_SHORT\n#endif\n\n// STB_VORBIS_NO_HUFFMAN_BINARY_SEARCH\n//     If the 'fast huffman' search doesn't succeed, then stb_vorbis falls\n//     back on binary searching for the correct one. This requires storing\n//     extra tables with the huffman codes in sorted order. Defining this\n//     symbol trades off space for speed by forcing a linear search in the\n//     non-fast case, except for \"sparse\" codebooks.\n// #define STB_VORBIS_NO_HUFFMAN_BINARY_SEARCH\n\n// STB_VORBIS_DIVIDES_IN_RESIDUE\n//     stb_vorbis precomputes the result of the scalar residue decoding\n//     that would otherwise require a divide per chunk. you can trade off\n//     space for time by defining this symbol.\n// #define STB_VORBIS_DIVIDES_IN_RESIDUE\n\n// STB_VORBIS_DIVIDES_IN_CODEBOOK\n//     vorbis VQ codebooks can be encoded two ways: with every case explicitly\n//     stored, or with all elements being chosen from a small range of values,\n//     and all values possible in all elements. By default, stb_vorbis expands\n//     this latter kind out to look like the former kind for ease of decoding,\n//     because otherwise an integer divide-per-vector-element is required to\n//     unpack the index. If you define STB_VORBIS_DIVIDES_IN_CODEBOOK, you can\n//     trade off storage for speed.\n//#define STB_VORBIS_DIVIDES_IN_CODEBOOK\n\n#ifdef STB_VORBIS_CODEBOOK_SHORTS\n#error \"STB_VORBIS_CODEBOOK_SHORTS is no longer supported as it produced incorrect results for some input formats\"\n#endif\n\n// STB_VORBIS_DIVIDE_TABLE\n//     this replaces small integer divides in the floor decode loop with\n//     table lookups. made less than 1% difference, so disabled by default.\n\n// STB_VORBIS_NO_INLINE_DECODE\n//     disables the inlining of the scalar codebook fast-huffman decode.\n//     might save a little codespace; useful for debugging\n// #define STB_VORBIS_NO_INLINE_DECODE\n\n// STB_VORBIS_NO_DEFER_FLOOR\n//     Normally we only decode the floor without synthesizing the actual\n//     full curve. We can instead synthesize the curve immediately. This\n//     requires more memory and is very likely slower, so I don't think\n//     you'd ever want to do it except for debugging.\n// #define STB_VORBIS_NO_DEFER_FLOOR\n\n\n\n\n//////////////////////////////////////////////////////////////////////////////\n\n#ifdef STB_VORBIS_NO_PULLDATA_API\n   #define STB_VORBIS_NO_INTEGER_CONVERSION\n   #define STB_VORBIS_NO_STDIO\n#endif\n\n#if defined(STB_VORBIS_NO_CRT) && !defined(STB_VORBIS_NO_STDIO)\n   #define STB_VORBIS_NO_STDIO 1\n#endif\n\n#ifndef STB_VORBIS_NO_INTEGER_CONVERSION\n#ifndef STB_VORBIS_NO_FAST_SCALED_FLOAT\n\n   // only need endianness for fast-float-to-int, which we don't\n   // use for pushdata\n\n   #ifndef STB_VORBIS_BIG_ENDIAN\n     #define STB_VORBIS_ENDIAN  0\n   #else\n     #define STB_VORBIS_ENDIAN  1\n   #endif\n\n#endif\n#endif\n\n\n#ifndef STB_VORBIS_NO_STDIO\n#include <stdio.h>\n#endif\n\n#ifndef STB_VORBIS_NO_CRT\n   #include <stdlib.h>\n   #include <string.h>\n   #include <assert.h>\n   #include <math.h>\n\n   // find definition of alloca if it's not in stdlib.h:\n   #if defined(_MSC_VER) || defined(__MINGW32__)\n      #include <malloc.h>\n   #endif\n   #if defined(__linux__) || defined(__linux) || defined(__EMSCRIPTEN__)\n      #include <alloca.h>\n   #endif\n#else // STB_VORBIS_NO_CRT\n   #define NULL 0\n   #define malloc(s)   0\n   #define free(s)     ((void) 0)\n   #define realloc(s)  0\n#endif // STB_VORBIS_NO_CRT\n\n#include <limits.h>\n\n#ifdef __MINGW32__\n   // eff you mingw:\n   //     \"fixed\":\n   //         http://sourceforge.net/p/mingw-w64/mailman/message/32882927/\n   //     \"no that broke the build, reverted, who cares about C\":\n   //         http://sourceforge.net/p/mingw-w64/mailman/message/32890381/\n   #ifdef __forceinline\n   #undef __forceinline\n   #endif\n   #define __forceinline\n   #ifndef alloca\n       #define alloca __builtin_alloca\n   #endif\n#elif !defined(_MSC_VER)\n   #if __GNUC__\n      #define __forceinline inline\n   #else\n      #define __forceinline\n   #endif\n#endif\n\n#if STB_VORBIS_MAX_CHANNELS > 256\n#error \"Value of STB_VORBIS_MAX_CHANNELS outside of allowed range\"\n#endif\n\n#if STB_VORBIS_FAST_HUFFMAN_LENGTH > 24\n#error \"Value of STB_VORBIS_FAST_HUFFMAN_LENGTH outside of allowed range\"\n#endif\n\n\n#if 0\n#include <crtdbg.h>\n#define CHECK(f)   _CrtIsValidHeapPointer(f->channel_buffers[1])\n#else\n#define CHECK(f)   ((void) 0)\n#endif\n\n#define MAX_BLOCKSIZE_LOG  13   // from specification\n#define MAX_BLOCKSIZE      (1 << MAX_BLOCKSIZE_LOG)\n\n\ntypedef unsigned char  uint8;\ntypedef   signed char   int8;\ntypedef unsigned short uint16;\ntypedef   signed short  int16;\ntypedef unsigned int   uint32;\ntypedef   signed int    int32;\n\n#ifndef TRUE\n#define TRUE 1\n#define FALSE 0\n#endif\n\ntypedef float codetype;\n\n// @NOTE\n//\n// Some arrays below are tagged \"//varies\", which means it's actually\n// a variable-sized piece of data, but rather than malloc I assume it's\n// small enough it's better to just allocate it all together with the\n// main thing\n//\n// Most of the variables are specified with the smallest size I could pack\n// them into. It might give better performance to make them all full-sized\n// integers. It should be safe to freely rearrange the structures or change\n// the sizes larger--nothing relies on silently truncating etc., nor the\n// order of variables.\n\n#define FAST_HUFFMAN_TABLE_SIZE   (1 << STB_VORBIS_FAST_HUFFMAN_LENGTH)\n#define FAST_HUFFMAN_TABLE_MASK   (FAST_HUFFMAN_TABLE_SIZE - 1)\n\ntypedef struct\n{\n   int dimensions, entries;\n   uint8 *codeword_lengths;\n   float  minimum_value;\n   float  delta_value;\n   uint8  value_bits;\n   uint8  lookup_type;\n   uint8  sequence_p;\n   uint8  sparse;\n   uint32 lookup_values;\n   codetype *multiplicands;\n   uint32 *codewords;\n   #ifdef STB_VORBIS_FAST_HUFFMAN_SHORT\n    int16  fast_huffman[FAST_HUFFMAN_TABLE_SIZE];\n   #else\n    int32  fast_huffman[FAST_HUFFMAN_TABLE_SIZE];\n   #endif\n   uint32 *sorted_codewords;\n   int    *sorted_values;\n   int     sorted_entries;\n} Codebook;\n\ntypedef struct\n{\n   uint8 order;\n   uint16 rate;\n   uint16 bark_map_size;\n   uint8 amplitude_bits;\n   uint8 amplitude_offset;\n   uint8 number_of_books;\n   uint8 book_list[16]; // varies\n} Floor0;\n\ntypedef struct\n{\n   uint8 partitions;\n   uint8 partition_class_list[32]; // varies\n   uint8 class_dimensions[16]; // varies\n   uint8 class_subclasses[16]; // varies\n   uint8 class_masterbooks[16]; // varies\n   int16 subclass_books[16][8]; // varies\n   uint16 Xlist[31*8+2]; // varies\n   uint8 sorted_order[31*8+2];\n   uint8 neighbors[31*8+2][2];\n   uint8 floor1_multiplier;\n   uint8 rangebits;\n   int values;\n} Floor1;\n\ntypedef union\n{\n   Floor0 floor0;\n   Floor1 floor1;\n} Floor;\n\ntypedef struct\n{\n   uint32 begin, end;\n   uint32 part_size;\n   uint8 classifications;\n   uint8 classbook;\n   uint8 **classdata;\n   int16 (*residue_books)[8];\n} Residue;\n\ntypedef struct\n{\n   uint8 magnitude;\n   uint8 angle;\n   uint8 mux;\n} MappingChannel;\n\ntypedef struct\n{\n   uint16 coupling_steps;\n   MappingChannel *chan;\n   uint8  submaps;\n   uint8  submap_floor[15]; // varies\n   uint8  submap_residue[15]; // varies\n} Mapping;\n\ntypedef struct\n{\n   uint8 blockflag;\n   uint8 mapping;\n   uint16 windowtype;\n   uint16 transformtype;\n} Mode;\n\ntypedef struct\n{\n   uint32  goal_crc;    // expected crc if match\n   int     bytes_left;  // bytes left in packet\n   uint32  crc_so_far;  // running crc\n   int     bytes_done;  // bytes processed in _current_ chunk\n   uint32  sample_loc;  // granule pos encoded in page\n} CRCscan;\n\ntypedef struct\n{\n   uint32 page_start, page_end;\n   uint32 last_decoded_sample;\n} ProbedPage;\n\nstruct stb_vorbis\n{\n  // user-accessible info\n   unsigned int sample_rate;\n   int channels;\n\n   unsigned int setup_memory_required;\n   unsigned int temp_memory_required;\n   unsigned int setup_temp_memory_required;\n\n  // input config\n#ifndef STB_VORBIS_NO_STDIO\n   FILE *f;\n   uint32 f_start;\n   int close_on_free;\n#endif\n\n   uint8 *stream;\n   uint8 *stream_start;\n   uint8 *stream_end;\n\n   uint32 stream_len;\n\n   uint8  push_mode;\n\n   uint32 first_audio_page_offset;\n\n   ProbedPage p_first, p_last;\n\n  // memory management\n   stb_vorbis_alloc alloc;\n   int setup_offset;\n   int temp_offset;\n\n  // run-time results\n   int eof;\n   enum STBVorbisError error;\n\n  // user-useful data\n\n  // header info\n   int blocksize[2];\n   int blocksize_0, blocksize_1;\n   int codebook_count;\n   Codebook *codebooks;\n   int floor_count;\n   uint16 floor_types[64]; // varies\n   Floor *floor_config;\n   int residue_count;\n   uint16 residue_types[64]; // varies\n   Residue *residue_config;\n   int mapping_count;\n   Mapping *mapping;\n   int mode_count;\n   Mode mode_config[64];  // varies\n\n   uint32 total_samples;\n\n  // decode buffer\n   float *channel_buffers[STB_VORBIS_MAX_CHANNELS];\n   float *outputs        [STB_VORBIS_MAX_CHANNELS];\n\n   float *previous_window[STB_VORBIS_MAX_CHANNELS];\n   int previous_length;\n\n   #ifndef STB_VORBIS_NO_DEFER_FLOOR\n   int16 *finalY[STB_VORBIS_MAX_CHANNELS];\n   #else\n   float *floor_buffers[STB_VORBIS_MAX_CHANNELS];\n   #endif\n\n   uint32 current_loc; // sample location of next frame to decode\n   int    current_loc_valid;\n\n  // per-blocksize precomputed data\n   \n   // twiddle factors\n   float *A[2],*B[2],*C[2];\n   float *window[2];\n   uint16 *bit_reverse[2];\n\n  // current page/packet/segment streaming info\n   uint32 serial; // stream serial number for verification\n   int last_page;\n   int segment_count;\n   uint8 segments[255];\n   uint8 page_flag;\n   uint8 bytes_in_seg;\n   uint8 first_decode;\n   int next_seg;\n   int last_seg;  // flag that we're on the last segment\n   int last_seg_which; // what was the segment number of the last seg?\n   uint32 acc;\n   int valid_bits;\n   int packet_bytes;\n   int end_seg_with_known_loc;\n   uint32 known_loc_for_packet;\n   int discard_samples_deferred;\n   uint32 samples_output;\n\n  // push mode scanning\n   int page_crc_tests; // only in push_mode: number of tests active; -1 if not searching\n#ifndef STB_VORBIS_NO_PUSHDATA_API\n   CRCscan scan[STB_VORBIS_PUSHDATA_CRC_COUNT];\n#endif\n\n  // sample-access\n   int channel_buffer_start;\n   int channel_buffer_end;\n};\n\n#if defined(STB_VORBIS_NO_PUSHDATA_API)\n   #define IS_PUSH_MODE(f)   FALSE\n#elif defined(STB_VORBIS_NO_PULLDATA_API)\n   #define IS_PUSH_MODE(f)   TRUE\n#else\n   #define IS_PUSH_MODE(f)   ((f)->push_mode)\n#endif\n\ntypedef struct stb_vorbis vorb;\n\nstatic int error(vorb *f, enum STBVorbisError e)\n{\n   f->error = e;\n   if (!f->eof && e != VORBIS_need_more_data) {\n      f->error=e; // breakpoint for debugging\n   }\n   return 0;\n}\n\n\n// these functions are used for allocating temporary memory\n// while decoding. if you can afford the stack space, use\n// alloca(); otherwise, provide a temp buffer and it will\n// allocate out of those.\n\n#define array_size_required(count,size)  (count*(sizeof(void *)+(size)))\n\n#define temp_alloc(f,size)              (f->alloc.alloc_buffer ? setup_temp_malloc(f,size) : alloca(size))\n#define temp_free(f,p)                  (void)(0)\n#define temp_alloc_save(f)              ((f)->temp_offset)\n#define temp_alloc_restore(f,p)         ((f)->temp_offset = (p))\n\n#define temp_block_array(f,count,size)  make_block_array(temp_alloc(f,array_size_required(count,size)), count, size)\n\n// given a sufficiently large block of memory, make an array of pointers to subblocks of it\nstatic void *make_block_array(void *mem, int count, int size)\n{\n   int i;\n   void ** p = (void **) mem;\n   char *q = (char *) (p + count);\n   for (i=0; i < count; ++i) {\n      p[i] = q;\n      q += size;\n   }\n   return p;\n}\n\nstatic void *setup_malloc(vorb *f, int sz)\n{\n   sz = (sz+3) & ~3;\n   f->setup_memory_required += sz;\n   if (f->alloc.alloc_buffer) {\n      void *p = (char *) f->alloc.alloc_buffer + f->setup_offset;\n      if (f->setup_offset + sz > f->temp_offset) return NULL;\n      f->setup_offset += sz;\n      return p;\n   }\n   return sz ? malloc(sz) : NULL;\n}\n\nstatic void setup_free(vorb *f, void *p)\n{\n   if (f->alloc.alloc_buffer) return; // do nothing; setup mem is a stack\n   free(p);\n}\n\nstatic void *setup_temp_malloc(vorb *f, int sz)\n{\n   sz = (sz+3) & ~3;\n   if (f->alloc.alloc_buffer) {\n      if (f->temp_offset - sz < f->setup_offset) return NULL;\n      f->temp_offset -= sz;\n      return (char *) f->alloc.alloc_buffer + f->temp_offset;\n   }\n   return malloc(sz);\n}\n\nstatic void setup_temp_free(vorb *f, void *p, int sz)\n{\n   if (f->alloc.alloc_buffer) {\n      f->temp_offset += (sz+3)&~3;\n      return;\n   }\n   free(p);\n}\n\n#define CRC32_POLY    0x04c11db7   // from spec\n\nstatic uint32 crc_table[256];\nstatic void crc32_init(void)\n{\n   int i,j;\n   uint32 s;\n   for(i=0; i < 256; i++) {\n      for (s=(uint32) i << 24, j=0; j < 8; ++j)\n         s = (s << 1) ^ (s >= (1U<<31) ? CRC32_POLY : 0);\n      crc_table[i] = s;\n   }\n}\n\nstatic __forceinline uint32 crc32_update(uint32 crc, uint8 byte)\n{\n   return (crc << 8) ^ crc_table[byte ^ (crc >> 24)];\n}\n\n\n// used in setup, and for huffman that doesn't go fast path\nstatic unsigned int bit_reverse(unsigned int n)\n{\n  n = ((n & 0xAAAAAAAA) >>  1) | ((n & 0x55555555) << 1);\n  n = ((n & 0xCCCCCCCC) >>  2) | ((n & 0x33333333) << 2);\n  n = ((n & 0xF0F0F0F0) >>  4) | ((n & 0x0F0F0F0F) << 4);\n  n = ((n & 0xFF00FF00) >>  8) | ((n & 0x00FF00FF) << 8);\n  return (n >> 16) | (n << 16);\n}\n\nstatic float square(float x)\n{\n   return x*x;\n}\n\n// this is a weird definition of log2() for which log2(1) = 1, log2(2) = 2, log2(4) = 3\n// as required by the specification. fast(?) implementation from stb.h\n// @OPTIMIZE: called multiple times per-packet with \"constants\"; move to setup\nstatic int ilog(int32 n)\n{\n   static signed char log2_4[16] = { 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4 };\n\n   if (n < 0) return 0; // signed n returns 0\n\n   // 2 compares if n < 16, 3 compares otherwise (4 if signed or n > 1<<29)\n   if (n < (1 << 14))\n        if (n < (1 <<  4))            return  0 + log2_4[n      ];\n        else if (n < (1 <<  9))       return  5 + log2_4[n >>  5];\n             else                     return 10 + log2_4[n >> 10];\n   else if (n < (1 << 24))\n             if (n < (1 << 19))       return 15 + log2_4[n >> 15];\n             else                     return 20 + log2_4[n >> 20];\n        else if (n < (1 << 29))       return 25 + log2_4[n >> 25];\n             else                     return 30 + log2_4[n >> 30];\n}\n\n#ifndef M_PI\n  #define M_PI  3.14159265358979323846264f  // from CRC\n#endif\n\n// code length assigned to a value with no huffman encoding\n#define NO_CODE   255\n\n/////////////////////// LEAF SETUP FUNCTIONS //////////////////////////\n//\n// these functions are only called at setup, and only a few times\n// per file\n\nstatic float float32_unpack(uint32 x)\n{\n   // from the specification\n   uint32 mantissa = x & 0x1fffff;\n   uint32 sign = x & 0x80000000;\n   uint32 exp = (x & 0x7fe00000) >> 21;\n   double res = sign ? -(double)mantissa : (double)mantissa;\n   return (float) ldexp((float)res, exp-788);\n}\n\n\n// zlib & jpeg huffman tables assume that the output symbols\n// can either be arbitrarily arranged, or have monotonically\n// increasing frequencies--they rely on the lengths being sorted;\n// this makes for a very simple generation algorithm.\n// vorbis allows a huffman table with non-sorted lengths. This\n// requires a more sophisticated construction, since symbols in\n// order do not map to huffman codes \"in order\".\nstatic void add_entry(Codebook *c, uint32 huff_code, int symbol, int count, int len, uint32 *values)\n{\n   if (!c->sparse) {\n      c->codewords      [symbol] = huff_code;\n   } else {\n      c->codewords       [count] = huff_code;\n      c->codeword_lengths[count] = len;\n      values             [count] = symbol;\n   }\n}\n\nstatic int compute_codewords(Codebook *c, uint8 *len, int n, uint32 *values)\n{\n   int i,k,m=0;\n   uint32 available[32];\n\n   memset(available, 0, sizeof(available));\n   // find the first entry\n   for (k=0; k < n; ++k) if (len[k] < NO_CODE) break;\n   if (k == n) { assert(c->sorted_entries == 0); return TRUE; }\n   // add to the list\n   add_entry(c, 0, k, m++, len[k], values);\n   // add all available leaves\n   for (i=1; i <= len[k]; ++i)\n      available[i] = 1U << (32-i);\n   // note that the above code treats the first case specially,\n   // but it's really the same as the following code, so they\n   // could probably be combined (except the initial code is 0,\n   // and I use 0 in available[] to mean 'empty')\n   for (i=k+1; i < n; ++i) {\n      uint32 res;\n      int z = len[i], y;\n      if (z == NO_CODE) continue;\n      // find lowest available leaf (should always be earliest,\n      // which is what the specification calls for)\n      // note that this property, and the fact we can never have\n      // more than one free leaf at a given level, isn't totally\n      // trivial to prove, but it seems true and the assert never\n      // fires, so!\n      while (z > 0 && !available[z]) --z;\n      if (z == 0) { return FALSE; }\n      res = available[z];\n      assert(z >= 0 && z < 32);\n      available[z] = 0;\n      add_entry(c, bit_reverse(res), i, m++, len[i], values);\n      // propagate availability up the tree\n      if (z != len[i]) {\n         assert(len[i] >= 0 && len[i] < 32);\n         for (y=len[i]; y > z; --y) {\n            assert(available[y] == 0);\n            available[y] = res + (1 << (32-y));\n         }\n      }\n   }\n   return TRUE;\n}\n\n// accelerated huffman table allows fast O(1) match of all symbols\n// of length <= STB_VORBIS_FAST_HUFFMAN_LENGTH\nstatic void compute_accelerated_huffman(Codebook *c)\n{\n   int i, len;\n   for (i=0; i < FAST_HUFFMAN_TABLE_SIZE; ++i)\n      c->fast_huffman[i] = -1;\n\n   len = c->sparse ? c->sorted_entries : c->entries;\n   #ifdef STB_VORBIS_FAST_HUFFMAN_SHORT\n   if (len > 32767) len = 32767; // largest possible value we can encode!\n   #endif\n   for (i=0; i < len; ++i) {\n      if (c->codeword_lengths[i] <= STB_VORBIS_FAST_HUFFMAN_LENGTH) {\n         uint32 z = c->sparse ? bit_reverse(c->sorted_codewords[i]) : c->codewords[i];\n         // set table entries for all bit combinations in the higher bits\n         while (z < FAST_HUFFMAN_TABLE_SIZE) {\n             c->fast_huffman[z] = i;\n             z += 1 << c->codeword_lengths[i];\n         }\n      }\n   }\n}\n\n#ifdef _MSC_VER\n#define STBV_CDECL __cdecl\n#else\n#define STBV_CDECL\n#endif\n\nstatic int STBV_CDECL uint32_compare(const void *p, const void *q)\n{\n   uint32 x = * (uint32 *) p;\n   uint32 y = * (uint32 *) q;\n   return x < y ? -1 : x > y;\n}\n\nstatic int include_in_sort(Codebook *c, uint8 len)\n{\n   if (c->sparse) { assert(len != NO_CODE); return TRUE; }\n   if (len == NO_CODE) return FALSE;\n   if (len > STB_VORBIS_FAST_HUFFMAN_LENGTH) return TRUE;\n   return FALSE;\n}\n\n// if the fast table above doesn't work, we want to binary\n// search them... need to reverse the bits\nstatic void compute_sorted_huffman(Codebook *c, uint8 *lengths, uint32 *values)\n{\n   int i, len;\n   // build a list of all the entries\n   // OPTIMIZATION: don't include the short ones, since they'll be caught by FAST_HUFFMAN.\n   // this is kind of a frivolous optimization--I don't see any performance improvement,\n   // but it's like 4 extra lines of code, so.\n   if (!c->sparse) {\n      int k = 0;\n      for (i=0; i < c->entries; ++i)\n         if (include_in_sort(c, lengths[i])) \n            c->sorted_codewords[k++] = bit_reverse(c->codewords[i]);\n      assert(k == c->sorted_entries);\n   } else {\n      for (i=0; i < c->sorted_entries; ++i)\n         c->sorted_codewords[i] = bit_reverse(c->codewords[i]);\n   }\n\n   qsort(c->sorted_codewords, c->sorted_entries, sizeof(c->sorted_codewords[0]), uint32_compare);\n   c->sorted_codewords[c->sorted_entries] = 0xffffffff;\n\n   len = c->sparse ? c->sorted_entries : c->entries;\n   // now we need to indicate how they correspond; we could either\n   //   #1: sort a different data structure that says who they correspond to\n   //   #2: for each sorted entry, search the original list to find who corresponds\n   //   #3: for each original entry, find the sorted entry\n   // #1 requires extra storage, #2 is slow, #3 can use binary search!\n   for (i=0; i < len; ++i) {\n      int huff_len = c->sparse ? lengths[values[i]] : lengths[i];\n      if (include_in_sort(c,huff_len)) {\n         uint32 code = bit_reverse(c->codewords[i]);\n         int x=0, n=c->sorted_entries;\n         while (n > 1) {\n            // invariant: sc[x] <= code < sc[x+n]\n            int m = x + (n >> 1);\n            if (c->sorted_codewords[m] <= code) {\n               x = m;\n               n -= (n>>1);\n            } else {\n               n >>= 1;\n            }\n         }\n         assert(c->sorted_codewords[x] == code);\n         if (c->sparse) {\n            c->sorted_values[x] = values[i];\n            c->codeword_lengths[x] = huff_len;\n         } else {\n            c->sorted_values[x] = i;\n         }\n      }\n   }\n}\n\n// only run while parsing the header (3 times)\nstatic int vorbis_validate(uint8 *data)\n{\n   static uint8 vorbis[6] = { 'v', 'o', 'r', 'b', 'i', 's' };\n   return memcmp(data, vorbis, 6) == 0;\n}\n\n// called from setup only, once per code book\n// (formula implied by specification)\nstatic int lookup1_values(int entries, int dim)\n{\n   int r = (int) floor(exp((float) log((float) entries) / dim));\n   if ((int) floor(pow((float) r+1, dim)) <= entries)   // (int) cast for MinGW warning;\n      ++r;                                              // floor() to avoid _ftol() when non-CRT\n   assert(pow((float) r+1, dim) > entries);\n   assert((int) floor(pow((float) r, dim)) <= entries); // (int),floor() as above\n   return r;\n}\n\n// called twice per file\nstatic void compute_twiddle_factors(int n, float *A, float *B, float *C)\n{\n   int n4 = n >> 2, n8 = n >> 3;\n   int k,k2;\n\n   for (k=k2=0; k < n4; ++k,k2+=2) {\n      A[k2  ] = (float)  cos(4*k*M_PI/n);\n      A[k2+1] = (float) -sin(4*k*M_PI/n);\n      B[k2  ] = (float)  cos((k2+1)*M_PI/n/2) * 0.5f;\n      B[k2+1] = (float)  sin((k2+1)*M_PI/n/2) * 0.5f;\n   }\n   for (k=k2=0; k < n8; ++k,k2+=2) {\n      C[k2  ] = (float)  cos(2*(k2+1)*M_PI/n);\n      C[k2+1] = (float) -sin(2*(k2+1)*M_PI/n);\n   }\n}\n\nstatic void compute_window(int n, float *window)\n{\n   int n2 = n >> 1, i;\n   for (i=0; i < n2; ++i)\n      window[i] = (float) sin(0.5 * M_PI * square((float) sin((i - 0 + 0.5) / n2 * 0.5 * M_PI)));\n}\n\nstatic void compute_bitreverse(int n, uint16 *rev)\n{\n   int ld = ilog(n) - 1; // ilog is off-by-one from normal definitions\n   int i, n8 = n >> 3;\n   for (i=0; i < n8; ++i)\n      rev[i] = (bit_reverse(i) >> (32-ld+3)) << 2;\n}\n\nstatic int init_blocksize(vorb *f, int b, int n)\n{\n   int n2 = n >> 1, n4 = n >> 2, n8 = n >> 3;\n   f->A[b] = (float *) setup_malloc(f, sizeof(float) * n2);\n   f->B[b] = (float *) setup_malloc(f, sizeof(float) * n2);\n   f->C[b] = (float *) setup_malloc(f, sizeof(float) * n4);\n   if (!f->A[b] || !f->B[b] || !f->C[b]) return error(f, VORBIS_outofmem);\n   compute_twiddle_factors(n, f->A[b], f->B[b], f->C[b]);\n   f->window[b] = (float *) setup_malloc(f, sizeof(float) * n2);\n   if (!f->window[b]) return error(f, VORBIS_outofmem);\n   compute_window(n, f->window[b]);\n   f->bit_reverse[b] = (uint16 *) setup_malloc(f, sizeof(uint16) * n8);\n   if (!f->bit_reverse[b]) return error(f, VORBIS_outofmem);\n   compute_bitreverse(n, f->bit_reverse[b]);\n   return TRUE;\n}\n\nstatic void neighbors(uint16 *x, int n, int *plow, int *phigh)\n{\n   int low = -1;\n   int high = 65536;\n   int i;\n   for (i=0; i < n; ++i) {\n      if (x[i] > low  && x[i] < x[n]) { *plow  = i; low = x[i]; }\n      if (x[i] < high && x[i] > x[n]) { *phigh = i; high = x[i]; }\n   }\n}\n\n// this has been repurposed so y is now the original index instead of y\ntypedef struct\n{\n   uint16 x,id;\n} stbv__floor_ordering;\n\nstatic int STBV_CDECL point_compare(const void *p, const void *q)\n{\n   stbv__floor_ordering *a = (stbv__floor_ordering *) p;\n   stbv__floor_ordering *b = (stbv__floor_ordering *) q;\n   return a->x < b->x ? -1 : a->x > b->x;\n}\n\n//\n/////////////////////// END LEAF SETUP FUNCTIONS //////////////////////////\n\n\n#if defined(STB_VORBIS_NO_STDIO)\n   #define USE_MEMORY(z)    TRUE\n#else\n   #define USE_MEMORY(z)    ((z)->stream)\n#endif\n\nstatic uint8 get8(vorb *z)\n{\n   if (USE_MEMORY(z)) {\n      if (z->stream >= z->stream_end) { z->eof = TRUE; return 0; }\n      return *z->stream++;\n   }\n\n   #ifndef STB_VORBIS_NO_STDIO\n   {\n   int c = fgetc(z->f);\n   if (c == EOF) { z->eof = TRUE; return 0; }\n   return c;\n   }\n   #endif\n}\n\nstatic uint32 get32(vorb *f)\n{\n   uint32 x;\n   x = get8(f);\n   x += get8(f) << 8;\n   x += get8(f) << 16;\n   x += (uint32) get8(f) << 24;\n   return x;\n}\n\nstatic int getn(vorb *z, uint8 *data, int n)\n{\n   if (USE_MEMORY(z)) {\n      if (z->stream+n > z->stream_end) { z->eof = 1; return 0; }\n      memcpy(data, z->stream, n);\n      z->stream += n;\n      return 1;\n   }\n\n   #ifndef STB_VORBIS_NO_STDIO   \n   if (fread(data, n, 1, z->f) == 1)\n      return 1;\n   else {\n      z->eof = 1;\n      return 0;\n   }\n   #endif\n}\n\nstatic void skip(vorb *z, int n)\n{\n   if (USE_MEMORY(z)) {\n      z->stream += n;\n      if (z->stream >= z->stream_end) z->eof = 1;\n      return;\n   }\n   #ifndef STB_VORBIS_NO_STDIO\n   {\n      long x = ftell(z->f);\n      fseek(z->f, x+n, SEEK_SET);\n   }\n   #endif\n}\n\nstatic int set_file_offset(stb_vorbis *f, unsigned int loc)\n{\n   #ifndef STB_VORBIS_NO_PUSHDATA_API\n   if (f->push_mode) return 0;\n   #endif\n   f->eof = 0;\n   if (USE_MEMORY(f)) {\n      if (f->stream_start + loc >= f->stream_end || f->stream_start + loc < f->stream_start) {\n         f->stream = f->stream_end;\n         f->eof = 1;\n         return 0;\n      } else {\n         f->stream = f->stream_start + loc;\n         return 1;\n      }\n   }\n   #ifndef STB_VORBIS_NO_STDIO\n   if (loc + f->f_start < loc || loc >= 0x80000000) {\n      loc = 0x7fffffff;\n      f->eof = 1;\n   } else {\n      loc += f->f_start;\n   }\n   if (!fseek(f->f, loc, SEEK_SET))\n      return 1;\n   f->eof = 1;\n   fseek(f->f, f->f_start, SEEK_END);\n   return 0;\n   #endif\n}\n\n\nstatic uint8 ogg_page_header[4] = { 0x4f, 0x67, 0x67, 0x53 };\n\nstatic int capture_pattern(vorb *f)\n{\n   if (0x4f != get8(f)) return FALSE;\n   if (0x67 != get8(f)) return FALSE;\n   if (0x67 != get8(f)) return FALSE;\n   if (0x53 != get8(f)) return FALSE;\n   return TRUE;\n}\n\n#define PAGEFLAG_continued_packet   1\n#define PAGEFLAG_first_page         2\n#define PAGEFLAG_last_page          4\n\nstatic int start_page_no_capturepattern(vorb *f)\n{\n   uint32 loc0,loc1,n;\n   // stream structure version\n   if (0 != get8(f)) return error(f, VORBIS_invalid_stream_structure_version);\n   // header flag\n   f->page_flag = get8(f);\n   // absolute granule position\n   loc0 = get32(f); \n   loc1 = get32(f);\n   // @TODO: validate loc0,loc1 as valid positions?\n   // stream serial number -- vorbis doesn't interleave, so discard\n   get32(f);\n   //if (f->serial != get32(f)) return error(f, VORBIS_incorrect_stream_serial_number);\n   // page sequence number\n   n = get32(f);\n   f->last_page = n;\n   // CRC32\n   get32(f);\n   // page_segments\n   f->segment_count = get8(f);\n   if (!getn(f, f->segments, f->segment_count))\n      return error(f, VORBIS_unexpected_eof);\n   // assume we _don't_ know any the sample position of any segments\n   f->end_seg_with_known_loc = -2;\n   if (loc0 != ~0U || loc1 != ~0U) {\n      int i;\n      // determine which packet is the last one that will complete\n      for (i=f->segment_count-1; i >= 0; --i)\n         if (f->segments[i] < 255)\n            break;\n      // 'i' is now the index of the _last_ segment of a packet that ends\n      if (i >= 0) {\n         f->end_seg_with_known_loc = i;\n         f->known_loc_for_packet   = loc0;\n      }\n   }\n   if (f->first_decode) {\n      int i,len;\n      ProbedPage p;\n      len = 0;\n      for (i=0; i < f->segment_count; ++i)\n         len += f->segments[i];\n      len += 27 + f->segment_count;\n      p.page_start = f->first_audio_page_offset;\n      p.page_end = p.page_start + len;\n      p.last_decoded_sample = loc0;\n      f->p_first = p;\n   }\n   f->next_seg = 0;\n   return TRUE;\n}\n\nstatic int start_page(vorb *f)\n{\n   if (!capture_pattern(f)) return error(f, VORBIS_missing_capture_pattern);\n   return start_page_no_capturepattern(f);\n}\n\nstatic int start_packet(vorb *f)\n{\n   while (f->next_seg == -1) {\n      if (!start_page(f)) return FALSE;\n      if (f->page_flag & PAGEFLAG_continued_packet)\n         return error(f, VORBIS_continued_packet_flag_invalid);\n   }\n   f->last_seg = FALSE;\n   f->valid_bits = 0;\n   f->packet_bytes = 0;\n   f->bytes_in_seg = 0;\n   // f->next_seg is now valid\n   return TRUE;\n}\n\nstatic int maybe_start_packet(vorb *f)\n{\n   if (f->next_seg == -1) {\n      int x = get8(f);\n      if (f->eof) return FALSE; // EOF at page boundary is not an error!\n      if (0x4f != x      ) return error(f, VORBIS_missing_capture_pattern);\n      if (0x67 != get8(f)) return error(f, VORBIS_missing_capture_pattern);\n      if (0x67 != get8(f)) return error(f, VORBIS_missing_capture_pattern);\n      if (0x53 != get8(f)) return error(f, VORBIS_missing_capture_pattern);\n      if (!start_page_no_capturepattern(f)) return FALSE;\n      if (f->page_flag & PAGEFLAG_continued_packet) {\n         // set up enough state that we can read this packet if we want,\n         // e.g. during recovery\n         f->last_seg = FALSE;\n         f->bytes_in_seg = 0;\n         return error(f, VORBIS_continued_packet_flag_invalid);\n      }\n   }\n   return start_packet(f);\n}\n\nstatic int next_segment(vorb *f)\n{\n   int len;\n   if (f->last_seg) return 0;\n   if (f->next_seg == -1) {\n      f->last_seg_which = f->segment_count-1; // in case start_page fails\n      if (!start_page(f)) { f->last_seg = 1; return 0; }\n      if (!(f->page_flag & PAGEFLAG_continued_packet)) return error(f, VORBIS_continued_packet_flag_invalid);\n   }\n   len = f->segments[f->next_seg++];\n   if (len < 255) {\n      f->last_seg = TRUE;\n      f->last_seg_which = f->next_seg-1;\n   }\n   if (f->next_seg >= f->segment_count)\n      f->next_seg = -1;\n   assert(f->bytes_in_seg == 0);\n   f->bytes_in_seg = len;\n   return len;\n}\n\n#define EOP    (-1)\n#define INVALID_BITS  (-1)\n\nstatic int get8_packet_raw(vorb *f)\n{\n   if (!f->bytes_in_seg) {  // CLANG!\n      if (f->last_seg) return EOP;\n      else if (!next_segment(f)) return EOP;\n   }\n   assert(f->bytes_in_seg > 0);\n   --f->bytes_in_seg;\n   ++f->packet_bytes;\n   return get8(f);\n}\n\nstatic int get8_packet(vorb *f)\n{\n   int x = get8_packet_raw(f);\n   f->valid_bits = 0;\n   return x;\n}\n\nstatic void flush_packet(vorb *f)\n{\n   while (get8_packet_raw(f) != EOP);\n}\n\n// @OPTIMIZE: this is the secondary bit decoder, so it's probably not as important\n// as the huffman decoder?\nstatic uint32 get_bits(vorb *f, int n)\n{\n   uint32 z;\n\n   if (f->valid_bits < 0) return 0;\n   if (f->valid_bits < n) {\n      if (n > 24) {\n         // the accumulator technique below would not work correctly in this case\n         z = get_bits(f, 24);\n         z += get_bits(f, n-24) << 24;\n         return z;\n      }\n      if (f->valid_bits == 0) f->acc = 0;\n      while (f->valid_bits < n) {\n         int z = get8_packet_raw(f);\n         if (z == EOP) {\n            f->valid_bits = INVALID_BITS;\n            return 0;\n         }\n         f->acc += z << f->valid_bits;\n         f->valid_bits += 8;\n      }\n   }\n   if (f->valid_bits < 0) return 0;\n   z = f->acc & ((1 << n)-1);\n   f->acc >>= n;\n   f->valid_bits -= n;\n   return z;\n}\n\n// @OPTIMIZE: primary accumulator for huffman\n// expand the buffer to as many bits as possible without reading off end of packet\n// it might be nice to allow f->valid_bits and f->acc to be stored in registers,\n// e.g. cache them locally and decode locally\nstatic __forceinline void prep_huffman(vorb *f)\n{\n   if (f->valid_bits <= 24) {\n      if (f->valid_bits == 0) f->acc = 0;\n      do {\n         int z;\n         if (f->last_seg && !f->bytes_in_seg) return;\n         z = get8_packet_raw(f);\n         if (z == EOP) return;\n         f->acc += (unsigned) z << f->valid_bits;\n         f->valid_bits += 8;\n      } while (f->valid_bits <= 24);\n   }\n}\n\nenum\n{\n   VORBIS_packet_id = 1,\n   VORBIS_packet_comment = 3,\n   VORBIS_packet_setup = 5\n};\n\nstatic int codebook_decode_scalar_raw(vorb *f, Codebook *c)\n{\n   int i;\n   prep_huffman(f);\n\n   if (c->codewords == NULL && c->sorted_codewords == NULL)\n      return -1;\n\n   // cases to use binary search: sorted_codewords && !c->codewords\n   //                             sorted_codewords && c->entries > 8\n   if (c->entries > 8 ? c->sorted_codewords!=NULL : !c->codewords) {\n      // binary search\n      uint32 code = bit_reverse(f->acc);\n      int x=0, n=c->sorted_entries, len;\n\n      while (n > 1) {\n         // invariant: sc[x] <= code < sc[x+n]\n         int m = x + (n >> 1);\n         if (c->sorted_codewords[m] <= code) {\n            x = m;\n            n -= (n>>1);\n         } else {\n            n >>= 1;\n         }\n      }\n      // x is now the sorted index\n      if (!c->sparse) x = c->sorted_values[x];\n      // x is now sorted index if sparse, or symbol otherwise\n      len = c->codeword_lengths[x];\n      if (f->valid_bits >= len) {\n         f->acc >>= len;\n         f->valid_bits -= len;\n         return x;\n      }\n\n      f->valid_bits = 0;\n      return -1;\n   }\n\n   // if small, linear search\n   assert(!c->sparse);\n   for (i=0; i < c->entries; ++i) {\n      if (c->codeword_lengths[i] == NO_CODE) continue;\n      if (c->codewords[i] == (f->acc & ((1 << c->codeword_lengths[i])-1))) {\n         if (f->valid_bits >= c->codeword_lengths[i]) {\n            f->acc >>= c->codeword_lengths[i];\n            f->valid_bits -= c->codeword_lengths[i];\n            return i;\n         }\n         f->valid_bits = 0;\n         return -1;\n      }\n   }\n\n   error(f, VORBIS_invalid_stream);\n   f->valid_bits = 0;\n   return -1;\n}\n\n#ifndef STB_VORBIS_NO_INLINE_DECODE\n\n#define DECODE_RAW(var, f,c)                                  \\\n   if (f->valid_bits < STB_VORBIS_FAST_HUFFMAN_LENGTH)        \\\n      prep_huffman(f);                                        \\\n   var = f->acc & FAST_HUFFMAN_TABLE_MASK;                    \\\n   var = c->fast_huffman[var];                                \\\n   if (var >= 0) {                                            \\\n      int n = c->codeword_lengths[var];                       \\\n      f->acc >>= n;                                           \\\n      f->valid_bits -= n;                                     \\\n      if (f->valid_bits < 0) { f->valid_bits = 0; var = -1; } \\\n   } else {                                                   \\\n      var = codebook_decode_scalar_raw(f,c);                  \\\n   }\n\n#else\n\nstatic int codebook_decode_scalar(vorb *f, Codebook *c)\n{\n   int i;\n   if (f->valid_bits < STB_VORBIS_FAST_HUFFMAN_LENGTH)\n      prep_huffman(f);\n   // fast huffman table lookup\n   i = f->acc & FAST_HUFFMAN_TABLE_MASK;\n   i = c->fast_huffman[i];\n   if (i >= 0) {\n      f->acc >>= c->codeword_lengths[i];\n      f->valid_bits -= c->codeword_lengths[i];\n      if (f->valid_bits < 0) { f->valid_bits = 0; return -1; }\n      return i;\n   }\n   return codebook_decode_scalar_raw(f,c);\n}\n\n#define DECODE_RAW(var,f,c)    var = codebook_decode_scalar(f,c);\n\n#endif\n\n#define DECODE(var,f,c)                                       \\\n   DECODE_RAW(var,f,c)                                        \\\n   if (c->sparse) var = c->sorted_values[var];\n\n#ifndef STB_VORBIS_DIVIDES_IN_CODEBOOK\n  #define DECODE_VQ(var,f,c)   DECODE_RAW(var,f,c)\n#else\n  #define DECODE_VQ(var,f,c)   DECODE(var,f,c)\n#endif\n\n\n\n\n\n\n// CODEBOOK_ELEMENT_FAST is an optimization for the CODEBOOK_FLOATS case\n// where we avoid one addition\n#define CODEBOOK_ELEMENT(c,off)          (c->multiplicands[off])\n#define CODEBOOK_ELEMENT_FAST(c,off)     (c->multiplicands[off])\n#define CODEBOOK_ELEMENT_BASE(c)         (0)\n\nstatic int codebook_decode_start(vorb *f, Codebook *c)\n{\n   int z = -1;\n\n   // type 0 is only legal in a scalar context\n   if (c->lookup_type == 0)\n      error(f, VORBIS_invalid_stream);\n   else {\n      DECODE_VQ(z,f,c);\n      if (c->sparse) assert(z < c->sorted_entries);\n      if (z < 0) {  // check for EOP\n         if (!f->bytes_in_seg)\n            if (f->last_seg)\n               return z;\n         error(f, VORBIS_invalid_stream);\n      }\n   }\n   return z;\n}\n\nstatic int codebook_decode(vorb *f, Codebook *c, float *output, int len)\n{\n   int i,z = codebook_decode_start(f,c);\n   if (z < 0) return FALSE;\n   if (len > c->dimensions) len = c->dimensions;\n\n#ifdef STB_VORBIS_DIVIDES_IN_CODEBOOK\n   if (c->lookup_type == 1) {\n      float last = CODEBOOK_ELEMENT_BASE(c);\n      int div = 1;\n      for (i=0; i < len; ++i) {\n         int off = (z / div) % c->lookup_values;\n         float val = CODEBOOK_ELEMENT_FAST(c,off) + last;\n         output[i] += val;\n         if (c->sequence_p) last = val + c->minimum_value;\n         div *= c->lookup_values;\n      }\n      return TRUE;\n   }\n#endif\n\n   z *= c->dimensions;\n   if (c->sequence_p) {\n      float last = CODEBOOK_ELEMENT_BASE(c);\n      for (i=0; i < len; ++i) {\n         float val = CODEBOOK_ELEMENT_FAST(c,z+i) + last;\n         output[i] += val;\n         last = val + c->minimum_value;\n      }\n   } else {\n      float last = CODEBOOK_ELEMENT_BASE(c);\n      for (i=0; i < len; ++i) {\n         output[i] += CODEBOOK_ELEMENT_FAST(c,z+i) + last;\n      }\n   }\n\n   return TRUE;\n}\n\nstatic int codebook_decode_step(vorb *f, Codebook *c, float *output, int len, int step)\n{\n   int i,z = codebook_decode_start(f,c);\n   float last = CODEBOOK_ELEMENT_BASE(c);\n   if (z < 0) return FALSE;\n   if (len > c->dimensions) len = c->dimensions;\n\n#ifdef STB_VORBIS_DIVIDES_IN_CODEBOOK\n   if (c->lookup_type == 1) {\n      int div = 1;\n      for (i=0; i < len; ++i) {\n         int off = (z / div) % c->lookup_values;\n         float val = CODEBOOK_ELEMENT_FAST(c,off) + last;\n         output[i*step] += val;\n         if (c->sequence_p) last = val;\n         div *= c->lookup_values;\n      }\n      return TRUE;\n   }\n#endif\n\n   z *= c->dimensions;\n   for (i=0; i < len; ++i) {\n      float val = CODEBOOK_ELEMENT_FAST(c,z+i) + last;\n      output[i*step] += val;\n      if (c->sequence_p) last = val;\n   }\n\n   return TRUE;\n}\n\nstatic int codebook_decode_deinterleave_repeat(vorb *f, Codebook *c, float **outputs, int ch, int *c_inter_p, int *p_inter_p, int len, int total_decode)\n{\n   int c_inter = *c_inter_p;\n   int p_inter = *p_inter_p;\n   int i,z, effective = c->dimensions;\n\n   // type 0 is only legal in a scalar context\n   if (c->lookup_type == 0)   return error(f, VORBIS_invalid_stream);\n\n   while (total_decode > 0) {\n      float last = CODEBOOK_ELEMENT_BASE(c);\n      DECODE_VQ(z,f,c);\n      #ifndef STB_VORBIS_DIVIDES_IN_CODEBOOK\n      assert(!c->sparse || z < c->sorted_entries);\n      #endif\n      if (z < 0) {\n         if (!f->bytes_in_seg)\n            if (f->last_seg) return FALSE;\n         return error(f, VORBIS_invalid_stream);\n      }\n\n      // if this will take us off the end of the buffers, stop short!\n      // we check by computing the length of the virtual interleaved\n      // buffer (len*ch), our current offset within it (p_inter*ch)+(c_inter),\n      // and the length we'll be using (effective)\n      if (c_inter + p_inter*ch + effective > len * ch) {\n         effective = len*ch - (p_inter*ch - c_inter);\n      }\n\n   #ifdef STB_VORBIS_DIVIDES_IN_CODEBOOK\n      if (c->lookup_type == 1) {\n         int div = 1;\n         for (i=0; i < effective; ++i) {\n            int off = (z / div) % c->lookup_values;\n            float val = CODEBOOK_ELEMENT_FAST(c,off) + last;\n            if (outputs[c_inter])\n               outputs[c_inter][p_inter] += val;\n            if (++c_inter == ch) { c_inter = 0; ++p_inter; }\n            if (c->sequence_p) last = val;\n            div *= c->lookup_values;\n         }\n      } else\n   #endif\n      {\n         z *= c->dimensions;\n         if (c->sequence_p) {\n            for (i=0; i < effective; ++i) {\n               float val = CODEBOOK_ELEMENT_FAST(c,z+i) + last;\n               if (outputs[c_inter])\n                  outputs[c_inter][p_inter] += val;\n               if (++c_inter == ch) { c_inter = 0; ++p_inter; }\n               last = val;\n            }\n         } else {\n            for (i=0; i < effective; ++i) {\n               float val = CODEBOOK_ELEMENT_FAST(c,z+i) + last;\n               if (outputs[c_inter])\n                  outputs[c_inter][p_inter] += val;\n               if (++c_inter == ch) { c_inter = 0; ++p_inter; }\n            }\n         }\n      }\n\n      total_decode -= effective;\n   }\n   *c_inter_p = c_inter;\n   *p_inter_p = p_inter;\n   return TRUE;\n}\n\nstatic int predict_point(int x, int x0, int x1, int y0, int y1)\n{\n   int dy = y1 - y0;\n   int adx = x1 - x0;\n   // @OPTIMIZE: force int division to round in the right direction... is this necessary on x86?\n   int err = abs(dy) * (x - x0);\n   int off = err / adx;\n   return dy < 0 ? y0 - off : y0 + off;\n}\n\n// the following table is block-copied from the specification\nstatic float inverse_db_table[256] =\n{\n  1.0649863e-07f, 1.1341951e-07f, 1.2079015e-07f, 1.2863978e-07f, \n  1.3699951e-07f, 1.4590251e-07f, 1.5538408e-07f, 1.6548181e-07f, \n  1.7623575e-07f, 1.8768855e-07f, 1.9988561e-07f, 2.1287530e-07f, \n  2.2670913e-07f, 2.4144197e-07f, 2.5713223e-07f, 2.7384213e-07f, \n  2.9163793e-07f, 3.1059021e-07f, 3.3077411e-07f, 3.5226968e-07f, \n  3.7516214e-07f, 3.9954229e-07f, 4.2550680e-07f, 4.5315863e-07f, \n  4.8260743e-07f, 5.1396998e-07f, 5.4737065e-07f, 5.8294187e-07f, \n  6.2082472e-07f, 6.6116941e-07f, 7.0413592e-07f, 7.4989464e-07f, \n  7.9862701e-07f, 8.5052630e-07f, 9.0579828e-07f, 9.6466216e-07f, \n  1.0273513e-06f, 1.0941144e-06f, 1.1652161e-06f, 1.2409384e-06f, \n  1.3215816e-06f, 1.4074654e-06f, 1.4989305e-06f, 1.5963394e-06f, \n  1.7000785e-06f, 1.8105592e-06f, 1.9282195e-06f, 2.0535261e-06f, \n  2.1869758e-06f, 2.3290978e-06f, 2.4804557e-06f, 2.6416497e-06f, \n  2.8133190e-06f, 2.9961443e-06f, 3.1908506e-06f, 3.3982101e-06f, \n  3.6190449e-06f, 3.8542308e-06f, 4.1047004e-06f, 4.3714470e-06f, \n  4.6555282e-06f, 4.9580707e-06f, 5.2802740e-06f, 5.6234160e-06f, \n  5.9888572e-06f, 6.3780469e-06f, 6.7925283e-06f, 7.2339451e-06f, \n  7.7040476e-06f, 8.2047000e-06f, 8.7378876e-06f, 9.3057248e-06f, \n  9.9104632e-06f, 1.0554501e-05f, 1.1240392e-05f, 1.1970856e-05f, \n  1.2748789e-05f, 1.3577278e-05f, 1.4459606e-05f, 1.5399272e-05f, \n  1.6400004e-05f, 1.7465768e-05f, 1.8600792e-05f, 1.9809576e-05f, \n  2.1096914e-05f, 2.2467911e-05f, 2.3928002e-05f, 2.5482978e-05f, \n  2.7139006e-05f, 2.8902651e-05f, 3.0780908e-05f, 3.2781225e-05f, \n  3.4911534e-05f, 3.7180282e-05f, 3.9596466e-05f, 4.2169667e-05f, \n  4.4910090e-05f, 4.7828601e-05f, 5.0936773e-05f, 5.4246931e-05f, \n  5.7772202e-05f, 6.1526565e-05f, 6.5524908e-05f, 6.9783085e-05f, \n  7.4317983e-05f, 7.9147585e-05f, 8.4291040e-05f, 8.9768747e-05f, \n  9.5602426e-05f, 0.00010181521f, 0.00010843174f, 0.00011547824f, \n  0.00012298267f, 0.00013097477f, 0.00013948625f, 0.00014855085f, \n  0.00015820453f, 0.00016848555f, 0.00017943469f, 0.00019109536f, \n  0.00020351382f, 0.00021673929f, 0.00023082423f, 0.00024582449f, \n  0.00026179955f, 0.00027881276f, 0.00029693158f, 0.00031622787f, \n  0.00033677814f, 0.00035866388f, 0.00038197188f, 0.00040679456f, \n  0.00043323036f, 0.00046138411f, 0.00049136745f, 0.00052329927f, \n  0.00055730621f, 0.00059352311f, 0.00063209358f, 0.00067317058f, \n  0.00071691700f, 0.00076350630f, 0.00081312324f, 0.00086596457f, \n  0.00092223983f, 0.00098217216f, 0.0010459992f,  0.0011139742f, \n  0.0011863665f,  0.0012634633f,  0.0013455702f,  0.0014330129f, \n  0.0015261382f,  0.0016253153f,  0.0017309374f,  0.0018434235f, \n  0.0019632195f,  0.0020908006f,  0.0022266726f,  0.0023713743f, \n  0.0025254795f,  0.0026895994f,  0.0028643847f,  0.0030505286f, \n  0.0032487691f,  0.0034598925f,  0.0036847358f,  0.0039241906f, \n  0.0041792066f,  0.0044507950f,  0.0047400328f,  0.0050480668f, \n  0.0053761186f,  0.0057254891f,  0.0060975636f,  0.0064938176f, \n  0.0069158225f,  0.0073652516f,  0.0078438871f,  0.0083536271f, \n  0.0088964928f,  0.009474637f,   0.010090352f,   0.010746080f, \n  0.011444421f,   0.012188144f,   0.012980198f,   0.013823725f, \n  0.014722068f,   0.015678791f,   0.016697687f,   0.017782797f, \n  0.018938423f,   0.020169149f,   0.021479854f,   0.022875735f, \n  0.024362330f,   0.025945531f,   0.027631618f,   0.029427276f, \n  0.031339626f,   0.033376252f,   0.035545228f,   0.037855157f, \n  0.040315199f,   0.042935108f,   0.045725273f,   0.048696758f, \n  0.051861348f,   0.055231591f,   0.058820850f,   0.062643361f, \n  0.066714279f,   0.071049749f,   0.075666962f,   0.080584227f, \n  0.085821044f,   0.091398179f,   0.097337747f,   0.10366330f, \n  0.11039993f,    0.11757434f,    0.12521498f,    0.13335215f, \n  0.14201813f,    0.15124727f,    0.16107617f,    0.17154380f, \n  0.18269168f,    0.19456402f,    0.20720788f,    0.22067342f, \n  0.23501402f,    0.25028656f,    0.26655159f,    0.28387361f, \n  0.30232132f,    0.32196786f,    0.34289114f,    0.36517414f, \n  0.38890521f,    0.41417847f,    0.44109412f,    0.46975890f, \n  0.50028648f,    0.53279791f,    0.56742212f,    0.60429640f, \n  0.64356699f,    0.68538959f,    0.72993007f,    0.77736504f, \n  0.82788260f,    0.88168307f,    0.9389798f,     1.0f\n};\n\n\n// @OPTIMIZE: if you want to replace this bresenham line-drawing routine,\n// note that you must produce bit-identical output to decode correctly;\n// this specific sequence of operations is specified in the spec (it's\n// drawing integer-quantized frequency-space lines that the encoder\n// expects to be exactly the same)\n//     ... also, isn't the whole point of Bresenham's algorithm to NOT\n// have to divide in the setup? sigh.\n#ifndef STB_VORBIS_NO_DEFER_FLOOR\n#define LINE_OP(a,b)   a *= b\n#else\n#define LINE_OP(a,b)   a = b\n#endif\n\n#ifdef STB_VORBIS_DIVIDE_TABLE\n#define DIVTAB_NUMER   32\n#define DIVTAB_DENOM   64\nint8 integer_divide_table[DIVTAB_NUMER][DIVTAB_DENOM]; // 2KB\n#endif\n\nstatic __forceinline void draw_line(float *output, int x0, int y0, int x1, int y1, int n)\n{\n   int dy = y1 - y0;\n   int adx = x1 - x0;\n   int ady = abs(dy);\n   int base;\n   int x=x0,y=y0;\n   int err = 0;\n   int sy;\n\n#ifdef STB_VORBIS_DIVIDE_TABLE\n   if (adx < DIVTAB_DENOM && ady < DIVTAB_NUMER) {\n      if (dy < 0) {\n         base = -integer_divide_table[ady][adx];\n         sy = base-1;\n      } else {\n         base =  integer_divide_table[ady][adx];\n         sy = base+1;\n      }\n   } else {\n      base = dy / adx;\n      if (dy < 0)\n         sy = base - 1;\n      else\n         sy = base+1;\n   }\n#else\n   base = dy / adx;\n   if (dy < 0)\n      sy = base - 1;\n   else\n      sy = base+1;\n#endif\n   ady -= abs(base) * adx;\n   if (x1 > n) x1 = n;\n   if (x < x1) {\n      LINE_OP(output[x], inverse_db_table[y]);\n      for (++x; x < x1; ++x) {\n         err += ady;\n         if (err >= adx) {\n            err -= adx;\n            y += sy;\n         } else\n            y += base;\n         LINE_OP(output[x], inverse_db_table[y]);\n      }\n   }\n}\n\nstatic int residue_decode(vorb *f, Codebook *book, float *target, int offset, int n, int rtype)\n{\n   int k;\n   if (rtype == 0) {\n      int step = n / book->dimensions;\n      for (k=0; k < step; ++k)\n         if (!codebook_decode_step(f, book, target+offset+k, n-offset-k, step))\n            return FALSE;\n   } else {\n      for (k=0; k < n; ) {\n         if (!codebook_decode(f, book, target+offset, n-k))\n            return FALSE;\n         k += book->dimensions;\n         offset += book->dimensions;\n      }\n   }\n   return TRUE;\n}\n\n// n is 1/2 of the blocksize --\n// specification: \"Correct per-vector decode length is [n]/2\"\nstatic void decode_residue(vorb *f, float *residue_buffers[], int ch, int n, int rn, uint8 *do_not_decode)\n{\n   int i,j,pass;\n   Residue *r = f->residue_config + rn;\n   int rtype = f->residue_types[rn];\n   int c = r->classbook;\n   int classwords = f->codebooks[c].dimensions;\n   unsigned int actual_size = rtype == 2 ? n*2 : n;\n   unsigned int limit_r_begin = (r->begin < actual_size ? r->begin : actual_size);\n   unsigned int limit_r_end   = (r->end   < actual_size ? r->end   : actual_size);\n   int n_read = limit_r_end - limit_r_begin;\n   int part_read = n_read / r->part_size;\n   int temp_alloc_point = temp_alloc_save(f);\n   #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE\n   uint8 ***part_classdata = (uint8 ***) temp_block_array(f,f->channels, part_read * sizeof(**part_classdata));\n   #else\n   int **classifications = (int **) temp_block_array(f,f->channels, part_read * sizeof(**classifications));\n   #endif\n\n   CHECK(f);\n\n   for (i=0; i < ch; ++i)\n      if (!do_not_decode[i])\n         memset(residue_buffers[i], 0, sizeof(float) * n);\n\n   if (rtype == 2 && ch != 1) {\n      for (j=0; j < ch; ++j)\n         if (!do_not_decode[j])\n            break;\n      if (j == ch)\n         goto done;\n\n      for (pass=0; pass < 8; ++pass) {\n         int pcount = 0, class_set = 0;\n         if (ch == 2) {\n            while (pcount < part_read) {\n               int z = r->begin + pcount*r->part_size;\n               int c_inter = (z & 1), p_inter = z>>1;\n               if (pass == 0) {\n                  Codebook *c = f->codebooks+r->classbook;\n                  int q;\n                  DECODE(q,f,c);\n                  if (q == EOP) goto done;\n                  #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE\n                  part_classdata[0][class_set] = r->classdata[q];\n                  #else\n                  for (i=classwords-1; i >= 0; --i) {\n                     classifications[0][i+pcount] = q % r->classifications;\n                     q /= r->classifications;\n                  }\n                  #endif\n               }\n               for (i=0; i < classwords && pcount < part_read; ++i, ++pcount) {\n                  int z = r->begin + pcount*r->part_size;\n                  #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE\n                  int c = part_classdata[0][class_set][i];\n                  #else\n                  int c = classifications[0][pcount];\n                  #endif\n                  int b = r->residue_books[c][pass];\n                  if (b >= 0) {\n                     Codebook *book = f->codebooks + b;\n                     #ifdef STB_VORBIS_DIVIDES_IN_CODEBOOK\n                     if (!codebook_decode_deinterleave_repeat(f, book, residue_buffers, ch, &c_inter, &p_inter, n, r->part_size))\n                        goto done;\n                     #else\n                     // saves 1%\n                     if (!codebook_decode_deinterleave_repeat(f, book, residue_buffers, ch, &c_inter, &p_inter, n, r->part_size))\n                        goto done;\n                     #endif\n                  } else {\n                     z += r->part_size;\n                     c_inter = z & 1;\n                     p_inter = z >> 1;\n                  }\n               }\n               #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE\n               ++class_set;\n               #endif\n            }\n         } else if (ch == 1) {\n            while (pcount < part_read) {\n               int z = r->begin + pcount*r->part_size;\n               int c_inter = 0, p_inter = z;\n               if (pass == 0) {\n                  Codebook *c = f->codebooks+r->classbook;\n                  int q;\n                  DECODE(q,f,c);\n                  if (q == EOP) goto done;\n                  #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE\n                  part_classdata[0][class_set] = r->classdata[q];\n                  #else\n                  for (i=classwords-1; i >= 0; --i) {\n                     classifications[0][i+pcount] = q % r->classifications;\n                     q /= r->classifications;\n                  }\n                  #endif\n               }\n               for (i=0; i < classwords && pcount < part_read; ++i, ++pcount) {\n                  int z = r->begin + pcount*r->part_size;\n                  #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE\n                  int c = part_classdata[0][class_set][i];\n                  #else\n                  int c = classifications[0][pcount];\n                  #endif\n                  int b = r->residue_books[c][pass];\n                  if (b >= 0) {\n                     Codebook *book = f->codebooks + b;\n                     if (!codebook_decode_deinterleave_repeat(f, book, residue_buffers, ch, &c_inter, &p_inter, n, r->part_size))\n                        goto done;\n                  } else {\n                     z += r->part_size;\n                     c_inter = 0;\n                     p_inter = z;\n                  }\n               }\n               #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE\n               ++class_set;\n               #endif\n            }\n         } else {\n            while (pcount < part_read) {\n               int z = r->begin + pcount*r->part_size;\n               int c_inter = z % ch, p_inter = z/ch;\n               if (pass == 0) {\n                  Codebook *c = f->codebooks+r->classbook;\n                  int q;\n                  DECODE(q,f,c);\n                  if (q == EOP) goto done;\n                  #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE\n                  part_classdata[0][class_set] = r->classdata[q];\n                  #else\n                  for (i=classwords-1; i >= 0; --i) {\n                     classifications[0][i+pcount] = q % r->classifications;\n                     q /= r->classifications;\n                  }\n                  #endif\n               }\n               for (i=0; i < classwords && pcount < part_read; ++i, ++pcount) {\n                  int z = r->begin + pcount*r->part_size;\n                  #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE\n                  int c = part_classdata[0][class_set][i];\n                  #else\n                  int c = classifications[0][pcount];\n                  #endif\n                  int b = r->residue_books[c][pass];\n                  if (b >= 0) {\n                     Codebook *book = f->codebooks + b;\n                     if (!codebook_decode_deinterleave_repeat(f, book, residue_buffers, ch, &c_inter, &p_inter, n, r->part_size))\n                        goto done;\n                  } else {\n                     z += r->part_size;\n                     c_inter = z % ch;\n                     p_inter = z / ch;\n                  }\n               }\n               #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE\n               ++class_set;\n               #endif\n            }\n         }\n      }\n      goto done;\n   }\n   CHECK(f);\n\n   for (pass=0; pass < 8; ++pass) {\n      int pcount = 0, class_set=0;\n      while (pcount < part_read) {\n         if (pass == 0) {\n            for (j=0; j < ch; ++j) {\n               if (!do_not_decode[j]) {\n                  Codebook *c = f->codebooks+r->classbook;\n                  int temp;\n                  DECODE(temp,f,c);\n                  if (temp == EOP) goto done;\n                  #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE\n                  part_classdata[j][class_set] = r->classdata[temp];\n                  #else\n                  for (i=classwords-1; i >= 0; --i) {\n                     classifications[j][i+pcount] = temp % r->classifications;\n                     temp /= r->classifications;\n                  }\n                  #endif\n               }\n            }\n         }\n         for (i=0; i < classwords && pcount < part_read; ++i, ++pcount) {\n            for (j=0; j < ch; ++j) {\n               if (!do_not_decode[j]) {\n                  #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE\n                  int c = part_classdata[j][class_set][i];\n                  #else\n                  int c = classifications[j][pcount];\n                  #endif\n                  int b = r->residue_books[c][pass];\n                  if (b >= 0) {\n                     float *target = residue_buffers[j];\n                     int offset = r->begin + pcount * r->part_size;\n                     int n = r->part_size;\n                     Codebook *book = f->codebooks + b;\n                     if (!residue_decode(f, book, target, offset, n, rtype))\n                        goto done;\n                  }\n               }\n            }\n         }\n         #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE\n         ++class_set;\n         #endif\n      }\n   }\n  done:\n   CHECK(f);\n   #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE\n   temp_free(f,part_classdata);\n   #else\n   temp_free(f,classifications);\n   #endif\n   temp_alloc_restore(f,temp_alloc_point);\n}\n\n\n#if 0\n// slow way for debugging\nvoid inverse_mdct_slow(float *buffer, int n)\n{\n   int i,j;\n   int n2 = n >> 1;\n   float *x = (float *) malloc(sizeof(*x) * n2);\n   memcpy(x, buffer, sizeof(*x) * n2);\n   for (i=0; i < n; ++i) {\n      float acc = 0;\n      for (j=0; j < n2; ++j)\n         // formula from paper:\n         //acc += n/4.0f * x[j] * (float) cos(M_PI / 2 / n * (2 * i + 1 + n/2.0)*(2*j+1));\n         // formula from wikipedia\n         //acc += 2.0f / n2 * x[j] * (float) cos(M_PI/n2 * (i + 0.5 + n2/2)*(j + 0.5));\n         // these are equivalent, except the formula from the paper inverts the multiplier!\n         // however, what actually works is NO MULTIPLIER!?!\n         //acc += 64 * 2.0f / n2 * x[j] * (float) cos(M_PI/n2 * (i + 0.5 + n2/2)*(j + 0.5));\n         acc += x[j] * (float) cos(M_PI / 2 / n * (2 * i + 1 + n/2.0)*(2*j+1));\n      buffer[i] = acc;\n   }\n   free(x);\n}\n#elif 0\n// same as above, but just barely able to run in real time on modern machines\nvoid inverse_mdct_slow(float *buffer, int n, vorb *f, int blocktype)\n{\n   float mcos[16384];\n   int i,j;\n   int n2 = n >> 1, nmask = (n << 2) -1;\n   float *x = (float *) malloc(sizeof(*x) * n2);\n   memcpy(x, buffer, sizeof(*x) * n2);\n   for (i=0; i < 4*n; ++i)\n      mcos[i] = (float) cos(M_PI / 2 * i / n);\n\n   for (i=0; i < n; ++i) {\n      float acc = 0;\n      for (j=0; j < n2; ++j)\n         acc += x[j] * mcos[(2 * i + 1 + n2)*(2*j+1) & nmask];\n      buffer[i] = acc;\n   }\n   free(x);\n}\n#elif 0\n// transform to use a slow dct-iv; this is STILL basically trivial,\n// but only requires half as many ops\nvoid dct_iv_slow(float *buffer, int n)\n{\n   float mcos[16384];\n   float x[2048];\n   int i,j;\n   int n2 = n >> 1, nmask = (n << 3) - 1;\n   memcpy(x, buffer, sizeof(*x) * n);\n   for (i=0; i < 8*n; ++i)\n      mcos[i] = (float) cos(M_PI / 4 * i / n);\n   for (i=0; i < n; ++i) {\n      float acc = 0;\n      for (j=0; j < n; ++j)\n         acc += x[j] * mcos[((2 * i + 1)*(2*j+1)) & nmask];\n      buffer[i] = acc;\n   }\n}\n\nvoid inverse_mdct_slow(float *buffer, int n, vorb *f, int blocktype)\n{\n   int i, n4 = n >> 2, n2 = n >> 1, n3_4 = n - n4;\n   float temp[4096];\n\n   memcpy(temp, buffer, n2 * sizeof(float));\n   dct_iv_slow(temp, n2);  // returns -c'-d, a-b'\n\n   for (i=0; i < n4  ; ++i) buffer[i] = temp[i+n4];            // a-b'\n   for (   ; i < n3_4; ++i) buffer[i] = -temp[n3_4 - i - 1];   // b-a', c+d'\n   for (   ; i < n   ; ++i) buffer[i] = -temp[i - n3_4];       // c'+d\n}\n#endif\n\n#ifndef LIBVORBIS_MDCT\n#define LIBVORBIS_MDCT 0\n#endif\n\n#if LIBVORBIS_MDCT\n// directly call the vorbis MDCT using an interface documented\n// by Jeff Roberts... useful for performance comparison\ntypedef struct \n{\n  int n;\n  int log2n;\n  \n  float *trig;\n  int   *bitrev;\n\n  float scale;\n} mdct_lookup;\n\nextern void mdct_init(mdct_lookup *lookup, int n);\nextern void mdct_clear(mdct_lookup *l);\nextern void mdct_backward(mdct_lookup *init, float *in, float *out);\n\nmdct_lookup M1,M2;\n\nvoid inverse_mdct(float *buffer, int n, vorb *f, int blocktype)\n{\n   mdct_lookup *M;\n   if (M1.n == n) M = &M1;\n   else if (M2.n == n) M = &M2;\n   else if (M1.n == 0) { mdct_init(&M1, n); M = &M1; }\n   else { \n      if (M2.n) __asm int 3;\n      mdct_init(&M2, n);\n      M = &M2;\n   }\n\n   mdct_backward(M, buffer, buffer);\n}\n#endif\n\n\n// the following were split out into separate functions while optimizing;\n// they could be pushed back up but eh. __forceinline showed no change;\n// they're probably already being inlined.\nstatic void imdct_step3_iter0_loop(int n, float *e, int i_off, int k_off, float *A)\n{\n   float *ee0 = e + i_off;\n   float *ee2 = ee0 + k_off;\n   int i;\n\n   assert((n & 3) == 0);\n   for (i=(n>>2); i > 0; --i) {\n      float k00_20, k01_21;\n      k00_20  = ee0[ 0] - ee2[ 0];\n      k01_21  = ee0[-1] - ee2[-1];\n      ee0[ 0] += ee2[ 0];//ee0[ 0] = ee0[ 0] + ee2[ 0];\n      ee0[-1] += ee2[-1];//ee0[-1] = ee0[-1] + ee2[-1];\n      ee2[ 0] = k00_20 * A[0] - k01_21 * A[1];\n      ee2[-1] = k01_21 * A[0] + k00_20 * A[1];\n      A += 8;\n\n      k00_20  = ee0[-2] - ee2[-2];\n      k01_21  = ee0[-3] - ee2[-3];\n      ee0[-2] += ee2[-2];//ee0[-2] = ee0[-2] + ee2[-2];\n      ee0[-3] += ee2[-3];//ee0[-3] = ee0[-3] + ee2[-3];\n      ee2[-2] = k00_20 * A[0] - k01_21 * A[1];\n      ee2[-3] = k01_21 * A[0] + k00_20 * A[1];\n      A += 8;\n\n      k00_20  = ee0[-4] - ee2[-4];\n      k01_21  = ee0[-5] - ee2[-5];\n      ee0[-4] += ee2[-4];//ee0[-4] = ee0[-4] + ee2[-4];\n      ee0[-5] += ee2[-5];//ee0[-5] = ee0[-5] + ee2[-5];\n      ee2[-4] = k00_20 * A[0] - k01_21 * A[1];\n      ee2[-5] = k01_21 * A[0] + k00_20 * A[1];\n      A += 8;\n\n      k00_20  = ee0[-6] - ee2[-6];\n      k01_21  = ee0[-7] - ee2[-7];\n      ee0[-6] += ee2[-6];//ee0[-6] = ee0[-6] + ee2[-6];\n      ee0[-7] += ee2[-7];//ee0[-7] = ee0[-7] + ee2[-7];\n      ee2[-6] = k00_20 * A[0] - k01_21 * A[1];\n      ee2[-7] = k01_21 * A[0] + k00_20 * A[1];\n      A += 8;\n      ee0 -= 8;\n      ee2 -= 8;\n   }\n}\n\nstatic void imdct_step3_inner_r_loop(int lim, float *e, int d0, int k_off, float *A, int k1)\n{\n   int i;\n   float k00_20, k01_21;\n\n   float *e0 = e + d0;\n   float *e2 = e0 + k_off;\n\n   for (i=lim >> 2; i > 0; --i) {\n      k00_20 = e0[-0] - e2[-0];\n      k01_21 = e0[-1] - e2[-1];\n      e0[-0] += e2[-0];//e0[-0] = e0[-0] + e2[-0];\n      e0[-1] += e2[-1];//e0[-1] = e0[-1] + e2[-1];\n      e2[-0] = (k00_20)*A[0] - (k01_21) * A[1];\n      e2[-1] = (k01_21)*A[0] + (k00_20) * A[1];\n\n      A += k1;\n\n      k00_20 = e0[-2] - e2[-2];\n      k01_21 = e0[-3] - e2[-3];\n      e0[-2] += e2[-2];//e0[-2] = e0[-2] + e2[-2];\n      e0[-3] += e2[-3];//e0[-3] = e0[-3] + e2[-3];\n      e2[-2] = (k00_20)*A[0] - (k01_21) * A[1];\n      e2[-3] = (k01_21)*A[0] + (k00_20) * A[1];\n\n      A += k1;\n\n      k00_20 = e0[-4] - e2[-4];\n      k01_21 = e0[-5] - e2[-5];\n      e0[-4] += e2[-4];//e0[-4] = e0[-4] + e2[-4];\n      e0[-5] += e2[-5];//e0[-5] = e0[-5] + e2[-5];\n      e2[-4] = (k00_20)*A[0] - (k01_21) * A[1];\n      e2[-5] = (k01_21)*A[0] + (k00_20) * A[1];\n\n      A += k1;\n\n      k00_20 = e0[-6] - e2[-6];\n      k01_21 = e0[-7] - e2[-7];\n      e0[-6] += e2[-6];//e0[-6] = e0[-6] + e2[-6];\n      e0[-7] += e2[-7];//e0[-7] = e0[-7] + e2[-7];\n      e2[-6] = (k00_20)*A[0] - (k01_21) * A[1];\n      e2[-7] = (k01_21)*A[0] + (k00_20) * A[1];\n\n      e0 -= 8;\n      e2 -= 8;\n\n      A += k1;\n   }\n}\n\nstatic void imdct_step3_inner_s_loop(int n, float *e, int i_off, int k_off, float *A, int a_off, int k0)\n{\n   int i;\n   float A0 = A[0];\n   float A1 = A[0+1];\n   float A2 = A[0+a_off];\n   float A3 = A[0+a_off+1];\n   float A4 = A[0+a_off*2+0];\n   float A5 = A[0+a_off*2+1];\n   float A6 = A[0+a_off*3+0];\n   float A7 = A[0+a_off*3+1];\n\n   float k00,k11;\n\n   float *ee0 = e  +i_off;\n   float *ee2 = ee0+k_off;\n\n   for (i=n; i > 0; --i) {\n      k00     = ee0[ 0] - ee2[ 0];\n      k11     = ee0[-1] - ee2[-1];\n      ee0[ 0] =  ee0[ 0] + ee2[ 0];\n      ee0[-1] =  ee0[-1] + ee2[-1];\n      ee2[ 0] = (k00) * A0 - (k11) * A1;\n      ee2[-1] = (k11) * A0 + (k00) * A1;\n\n      k00     = ee0[-2] - ee2[-2];\n      k11     = ee0[-3] - ee2[-3];\n      ee0[-2] =  ee0[-2] + ee2[-2];\n      ee0[-3] =  ee0[-3] + ee2[-3];\n      ee2[-2] = (k00) * A2 - (k11) * A3;\n      ee2[-3] = (k11) * A2 + (k00) * A3;\n\n      k00     = ee0[-4] - ee2[-4];\n      k11     = ee0[-5] - ee2[-5];\n      ee0[-4] =  ee0[-4] + ee2[-4];\n      ee0[-5] =  ee0[-5] + ee2[-5];\n      ee2[-4] = (k00) * A4 - (k11) * A5;\n      ee2[-5] = (k11) * A4 + (k00) * A5;\n\n      k00     = ee0[-6] - ee2[-6];\n      k11     = ee0[-7] - ee2[-7];\n      ee0[-6] =  ee0[-6] + ee2[-6];\n      ee0[-7] =  ee0[-7] + ee2[-7];\n      ee2[-6] = (k00) * A6 - (k11) * A7;\n      ee2[-7] = (k11) * A6 + (k00) * A7;\n\n      ee0 -= k0;\n      ee2 -= k0;\n   }\n}\n\nstatic __forceinline void iter_54(float *z)\n{\n   float k00,k11,k22,k33;\n   float y0,y1,y2,y3;\n\n   k00  = z[ 0] - z[-4];\n   y0   = z[ 0] + z[-4];\n   y2   = z[-2] + z[-6];\n   k22  = z[-2] - z[-6];\n\n   z[-0] = y0 + y2;      // z0 + z4 + z2 + z6\n   z[-2] = y0 - y2;      // z0 + z4 - z2 - z6\n\n   // done with y0,y2\n\n   k33  = z[-3] - z[-7];\n\n   z[-4] = k00 + k33;    // z0 - z4 + z3 - z7\n   z[-6] = k00 - k33;    // z0 - z4 - z3 + z7\n\n   // done with k33\n\n   k11  = z[-1] - z[-5];\n   y1   = z[-1] + z[-5];\n   y3   = z[-3] + z[-7];\n\n   z[-1] = y1 + y3;      // z1 + z5 + z3 + z7\n   z[-3] = y1 - y3;      // z1 + z5 - z3 - z7\n   z[-5] = k11 - k22;    // z1 - z5 + z2 - z6\n   z[-7] = k11 + k22;    // z1 - z5 - z2 + z6\n}\n\nstatic void imdct_step3_inner_s_loop_ld654(int n, float *e, int i_off, float *A, int base_n)\n{\n   int a_off = base_n >> 3;\n   float A2 = A[0+a_off];\n   float *z = e + i_off;\n   float *base = z - 16 * n;\n\n   while (z > base) {\n      float k00,k11;\n\n      k00   = z[-0] - z[-8];\n      k11   = z[-1] - z[-9];\n      z[-0] = z[-0] + z[-8];\n      z[-1] = z[-1] + z[-9];\n      z[-8] =  k00;\n      z[-9] =  k11 ;\n\n      k00    = z[ -2] - z[-10];\n      k11    = z[ -3] - z[-11];\n      z[ -2] = z[ -2] + z[-10];\n      z[ -3] = z[ -3] + z[-11];\n      z[-10] = (k00+k11) * A2;\n      z[-11] = (k11-k00) * A2;\n\n      k00    = z[-12] - z[ -4];  // reverse to avoid a unary negation\n      k11    = z[ -5] - z[-13];\n      z[ -4] = z[ -4] + z[-12];\n      z[ -5] = z[ -5] + z[-13];\n      z[-12] = k11;\n      z[-13] = k00;\n\n      k00    = z[-14] - z[ -6];  // reverse to avoid a unary negation\n      k11    = z[ -7] - z[-15];\n      z[ -6] = z[ -6] + z[-14];\n      z[ -7] = z[ -7] + z[-15];\n      z[-14] = (k00+k11) * A2;\n      z[-15] = (k00-k11) * A2;\n\n      iter_54(z);\n      iter_54(z-8);\n      z -= 16;\n   }\n}\n\nstatic void inverse_mdct(float *buffer, int n, vorb *f, int blocktype)\n{\n   int n2 = n >> 1, n4 = n >> 2, n8 = n >> 3, l;\n   int ld;\n   // @OPTIMIZE: reduce register pressure by using fewer variables?\n   int save_point = temp_alloc_save(f);\n   float *buf2 = (float *) temp_alloc(f, n2 * sizeof(*buf2));\n   float *u=NULL,*v=NULL;\n   // twiddle factors\n   float *A = f->A[blocktype];\n\n   // IMDCT algorithm from \"The use of multirate filter banks for coding of high quality digital audio\"\n   // See notes about bugs in that paper in less-optimal implementation 'inverse_mdct_old' after this function.\n\n   // kernel from paper\n\n\n   // merged:\n   //   copy and reflect spectral data\n   //   step 0\n\n   // note that it turns out that the items added together during\n   // this step are, in fact, being added to themselves (as reflected\n   // by step 0). inexplicable inefficiency! this became obvious\n   // once I combined the passes.\n\n   // so there's a missing 'times 2' here (for adding X to itself).\n   // this propagates through linearly to the end, where the numbers\n   // are 1/2 too small, and need to be compensated for.\n\n   {\n      float *d,*e, *AA, *e_stop;\n      d = &buf2[n2-2];\n      AA = A;\n      e = &buffer[0];\n      e_stop = &buffer[n2];\n      while (e != e_stop) {\n         d[1] = (e[0] * AA[0] - e[2]*AA[1]);\n         d[0] = (e[0] * AA[1] + e[2]*AA[0]);\n         d -= 2;\n         AA += 2;\n         e += 4;\n      }\n\n      e = &buffer[n2-3];\n      while (d >= buf2) {\n         d[1] = (-e[2] * AA[0] - -e[0]*AA[1]);\n         d[0] = (-e[2] * AA[1] + -e[0]*AA[0]);\n         d -= 2;\n         AA += 2;\n         e -= 4;\n      }\n   }\n\n   // now we use symbolic names for these, so that we can\n   // possibly swap their meaning as we change which operations\n   // are in place\n\n   u = buffer;\n   v = buf2;\n\n   // step 2    (paper output is w, now u)\n   // this could be in place, but the data ends up in the wrong\n   // place... _somebody_'s got to swap it, so this is nominated\n   {\n      float *AA = &A[n2-8];\n      float *d0,*d1, *e0, *e1;\n\n      e0 = &v[n4];\n      e1 = &v[0];\n\n      d0 = &u[n4];\n      d1 = &u[0];\n\n      while (AA >= A) {\n         float v40_20, v41_21;\n\n         v41_21 = e0[1] - e1[1];\n         v40_20 = e0[0] - e1[0];\n         d0[1]  = e0[1] + e1[1];\n         d0[0]  = e0[0] + e1[0];\n         d1[1]  = v41_21*AA[4] - v40_20*AA[5];\n         d1[0]  = v40_20*AA[4] + v41_21*AA[5];\n\n         v41_21 = e0[3] - e1[3];\n         v40_20 = e0[2] - e1[2];\n         d0[3]  = e0[3] + e1[3];\n         d0[2]  = e0[2] + e1[2];\n         d1[3]  = v41_21*AA[0] - v40_20*AA[1];\n         d1[2]  = v40_20*AA[0] + v41_21*AA[1];\n\n         AA -= 8;\n\n         d0 += 4;\n         d1 += 4;\n         e0 += 4;\n         e1 += 4;\n      }\n   }\n\n   // step 3\n   ld = ilog(n) - 1; // ilog is off-by-one from normal definitions\n\n   // optimized step 3:\n\n   // the original step3 loop can be nested r inside s or s inside r;\n   // it's written originally as s inside r, but this is dumb when r\n   // iterates many times, and s few. So I have two copies of it and\n   // switch between them halfway.\n\n   // this is iteration 0 of step 3\n   imdct_step3_iter0_loop(n >> 4, u, n2-1-n4*0, -(n >> 3), A);\n   imdct_step3_iter0_loop(n >> 4, u, n2-1-n4*1, -(n >> 3), A);\n\n   // this is iteration 1 of step 3\n   imdct_step3_inner_r_loop(n >> 5, u, n2-1 - n8*0, -(n >> 4), A, 16);\n   imdct_step3_inner_r_loop(n >> 5, u, n2-1 - n8*1, -(n >> 4), A, 16);\n   imdct_step3_inner_r_loop(n >> 5, u, n2-1 - n8*2, -(n >> 4), A, 16);\n   imdct_step3_inner_r_loop(n >> 5, u, n2-1 - n8*3, -(n >> 4), A, 16);\n\n   l=2;\n   for (; l < (ld-3)>>1; ++l) {\n      int k0 = n >> (l+2), k0_2 = k0>>1;\n      int lim = 1 << (l+1);\n      int i;\n      for (i=0; i < lim; ++i)\n         imdct_step3_inner_r_loop(n >> (l+4), u, n2-1 - k0*i, -k0_2, A, 1 << (l+3));\n   }\n\n   for (; l < ld-6; ++l) {\n      int k0 = n >> (l+2), k1 = 1 << (l+3), k0_2 = k0>>1;\n      int rlim = n >> (l+6), r;\n      int lim = 1 << (l+1);\n      int i_off;\n      float *A0 = A;\n      i_off = n2-1;\n      for (r=rlim; r > 0; --r) {\n         imdct_step3_inner_s_loop(lim, u, i_off, -k0_2, A0, k1, k0);\n         A0 += k1*4;\n         i_off -= 8;\n      }\n   }\n\n   // iterations with count:\n   //   ld-6,-5,-4 all interleaved together\n   //       the big win comes from getting rid of needless flops\n   //         due to the constants on pass 5 & 4 being all 1 and 0;\n   //       combining them to be simultaneous to improve cache made little difference\n   imdct_step3_inner_s_loop_ld654(n >> 5, u, n2-1, A, n);\n\n   // output is u\n\n   // step 4, 5, and 6\n   // cannot be in-place because of step 5\n   {\n      uint16 *bitrev = f->bit_reverse[blocktype];\n      // weirdly, I'd have thought reading sequentially and writing\n      // erratically would have been better than vice-versa, but in\n      // fact that's not what my testing showed. (That is, with\n      // j = bitreverse(i), do you read i and write j, or read j and write i.)\n\n      float *d0 = &v[n4-4];\n      float *d1 = &v[n2-4];\n      while (d0 >= v) {\n         int k4;\n\n         k4 = bitrev[0];\n         d1[3] = u[k4+0];\n         d1[2] = u[k4+1];\n         d0[3] = u[k4+2];\n         d0[2] = u[k4+3];\n\n         k4 = bitrev[1];\n         d1[1] = u[k4+0];\n         d1[0] = u[k4+1];\n         d0[1] = u[k4+2];\n         d0[0] = u[k4+3];\n         \n         d0 -= 4;\n         d1 -= 4;\n         bitrev += 2;\n      }\n   }\n   // (paper output is u, now v)\n\n\n   // data must be in buf2\n   assert(v == buf2);\n\n   // step 7   (paper output is v, now v)\n   // this is now in place\n   {\n      float *C = f->C[blocktype];\n      float *d, *e;\n\n      d = v;\n      e = v + n2 - 4;\n\n      while (d < e) {\n         float a02,a11,b0,b1,b2,b3;\n\n         a02 = d[0] - e[2];\n         a11 = d[1] + e[3];\n\n         b0 = C[1]*a02 + C[0]*a11;\n         b1 = C[1]*a11 - C[0]*a02;\n\n         b2 = d[0] + e[ 2];\n         b3 = d[1] - e[ 3];\n\n         d[0] = b2 + b0;\n         d[1] = b3 + b1;\n         e[2] = b2 - b0;\n         e[3] = b1 - b3;\n\n         a02 = d[2] - e[0];\n         a11 = d[3] + e[1];\n\n         b0 = C[3]*a02 + C[2]*a11;\n         b1 = C[3]*a11 - C[2]*a02;\n\n         b2 = d[2] + e[ 0];\n         b3 = d[3] - e[ 1];\n\n         d[2] = b2 + b0;\n         d[3] = b3 + b1;\n         e[0] = b2 - b0;\n         e[1] = b1 - b3;\n\n         C += 4;\n         d += 4;\n         e -= 4;\n      }\n   }\n\n   // data must be in buf2\n\n\n   // step 8+decode   (paper output is X, now buffer)\n   // this generates pairs of data a la 8 and pushes them directly through\n   // the decode kernel (pushing rather than pulling) to avoid having\n   // to make another pass later\n\n   // this cannot POSSIBLY be in place, so we refer to the buffers directly\n\n   {\n      float *d0,*d1,*d2,*d3;\n\n      float *B = f->B[blocktype] + n2 - 8;\n      float *e = buf2 + n2 - 8;\n      d0 = &buffer[0];\n      d1 = &buffer[n2-4];\n      d2 = &buffer[n2];\n      d3 = &buffer[n-4];\n      while (e >= v) {\n         float p0,p1,p2,p3;\n\n         p3 =  e[6]*B[7] - e[7]*B[6];\n         p2 = -e[6]*B[6] - e[7]*B[7]; \n\n         d0[0] =   p3;\n         d1[3] = - p3;\n         d2[0] =   p2;\n         d3[3] =   p2;\n\n         p1 =  e[4]*B[5] - e[5]*B[4];\n         p0 = -e[4]*B[4] - e[5]*B[5]; \n\n         d0[1] =   p1;\n         d1[2] = - p1;\n         d2[1] =   p0;\n         d3[2] =   p0;\n\n         p3 =  e[2]*B[3] - e[3]*B[2];\n         p2 = -e[2]*B[2] - e[3]*B[3]; \n\n         d0[2] =   p3;\n         d1[1] = - p3;\n         d2[2] =   p2;\n         d3[1] =   p2;\n\n         p1 =  e[0]*B[1] - e[1]*B[0];\n         p0 = -e[0]*B[0] - e[1]*B[1]; \n\n         d0[3] =   p1;\n         d1[0] = - p1;\n         d2[3] =   p0;\n         d3[0] =   p0;\n\n         B -= 8;\n         e -= 8;\n         d0 += 4;\n         d2 += 4;\n         d1 -= 4;\n         d3 -= 4;\n      }\n   }\n\n   temp_free(f,buf2);\n   temp_alloc_restore(f,save_point);\n}\n\n#if 0\n// this is the original version of the above code, if you want to optimize it from scratch\nvoid inverse_mdct_naive(float *buffer, int n)\n{\n   float s;\n   float A[1 << 12], B[1 << 12], C[1 << 11];\n   int i,k,k2,k4, n2 = n >> 1, n4 = n >> 2, n8 = n >> 3, l;\n   int n3_4 = n - n4, ld;\n   // how can they claim this only uses N words?!\n   // oh, because they're only used sparsely, whoops\n   float u[1 << 13], X[1 << 13], v[1 << 13], w[1 << 13];\n   // set up twiddle factors\n\n   for (k=k2=0; k < n4; ++k,k2+=2) {\n      A[k2  ] = (float)  cos(4*k*M_PI/n);\n      A[k2+1] = (float) -sin(4*k*M_PI/n);\n      B[k2  ] = (float)  cos((k2+1)*M_PI/n/2);\n      B[k2+1] = (float)  sin((k2+1)*M_PI/n/2);\n   }\n   for (k=k2=0; k < n8; ++k,k2+=2) {\n      C[k2  ] = (float)  cos(2*(k2+1)*M_PI/n);\n      C[k2+1] = (float) -sin(2*(k2+1)*M_PI/n);\n   }\n\n   // IMDCT algorithm from \"The use of multirate filter banks for coding of high quality digital audio\"\n   // Note there are bugs in that pseudocode, presumably due to them attempting\n   // to rename the arrays nicely rather than representing the way their actual\n   // implementation bounces buffers back and forth. As a result, even in the\n   // \"some formulars corrected\" version, a direct implementation fails. These\n   // are noted below as \"paper bug\".\n\n   // copy and reflect spectral data\n   for (k=0; k < n2; ++k) u[k] = buffer[k];\n   for (   ; k < n ; ++k) u[k] = -buffer[n - k - 1];\n   // kernel from paper\n   // step 1\n   for (k=k2=k4=0; k < n4; k+=1, k2+=2, k4+=4) {\n      v[n-k4-1] = (u[k4] - u[n-k4-1]) * A[k2]   - (u[k4+2] - u[n-k4-3])*A[k2+1];\n      v[n-k4-3] = (u[k4] - u[n-k4-1]) * A[k2+1] + (u[k4+2] - u[n-k4-3])*A[k2];\n   }\n   // step 2\n   for (k=k4=0; k < n8; k+=1, k4+=4) {\n      w[n2+3+k4] = v[n2+3+k4] + v[k4+3];\n      w[n2+1+k4] = v[n2+1+k4] + v[k4+1];\n      w[k4+3]    = (v[n2+3+k4] - v[k4+3])*A[n2-4-k4] - (v[n2+1+k4]-v[k4+1])*A[n2-3-k4];\n      w[k4+1]    = (v[n2+1+k4] - v[k4+1])*A[n2-4-k4] + (v[n2+3+k4]-v[k4+3])*A[n2-3-k4];\n   }\n   // step 3\n   ld = ilog(n) - 1; // ilog is off-by-one from normal definitions\n   for (l=0; l < ld-3; ++l) {\n      int k0 = n >> (l+2), k1 = 1 << (l+3);\n      int rlim = n >> (l+4), r4, r;\n      int s2lim = 1 << (l+2), s2;\n      for (r=r4=0; r < rlim; r4+=4,++r) {\n         for (s2=0; s2 < s2lim; s2+=2) {\n            u[n-1-k0*s2-r4] = w[n-1-k0*s2-r4] + w[n-1-k0*(s2+1)-r4];\n            u[n-3-k0*s2-r4] = w[n-3-k0*s2-r4] + w[n-3-k0*(s2+1)-r4];\n            u[n-1-k0*(s2+1)-r4] = (w[n-1-k0*s2-r4] - w[n-1-k0*(s2+1)-r4]) * A[r*k1]\n                                - (w[n-3-k0*s2-r4] - w[n-3-k0*(s2+1)-r4]) * A[r*k1+1];\n            u[n-3-k0*(s2+1)-r4] = (w[n-3-k0*s2-r4] - w[n-3-k0*(s2+1)-r4]) * A[r*k1]\n                                + (w[n-1-k0*s2-r4] - w[n-1-k0*(s2+1)-r4]) * A[r*k1+1];\n         }\n      }\n      if (l+1 < ld-3) {\n         // paper bug: ping-ponging of u&w here is omitted\n         memcpy(w, u, sizeof(u));\n      }\n   }\n\n   // step 4\n   for (i=0; i < n8; ++i) {\n      int j = bit_reverse(i) >> (32-ld+3);\n      assert(j < n8);\n      if (i == j) {\n         // paper bug: original code probably swapped in place; if copying,\n         //            need to directly copy in this case\n         int i8 = i << 3;\n         v[i8+1] = u[i8+1];\n         v[i8+3] = u[i8+3];\n         v[i8+5] = u[i8+5];\n         v[i8+7] = u[i8+7];\n      } else if (i < j) {\n         int i8 = i << 3, j8 = j << 3;\n         v[j8+1] = u[i8+1], v[i8+1] = u[j8 + 1];\n         v[j8+3] = u[i8+3], v[i8+3] = u[j8 + 3];\n         v[j8+5] = u[i8+5], v[i8+5] = u[j8 + 5];\n         v[j8+7] = u[i8+7], v[i8+7] = u[j8 + 7];\n      }\n   }\n   // step 5\n   for (k=0; k < n2; ++k) {\n      w[k] = v[k*2+1];\n   }\n   // step 6\n   for (k=k2=k4=0; k < n8; ++k, k2 += 2, k4 += 4) {\n      u[n-1-k2] = w[k4];\n      u[n-2-k2] = w[k4+1];\n      u[n3_4 - 1 - k2] = w[k4+2];\n      u[n3_4 - 2 - k2] = w[k4+3];\n   }\n   // step 7\n   for (k=k2=0; k < n8; ++k, k2 += 2) {\n      v[n2 + k2 ] = ( u[n2 + k2] + u[n-2-k2] + C[k2+1]*(u[n2+k2]-u[n-2-k2]) + C[k2]*(u[n2+k2+1]+u[n-2-k2+1]))/2;\n      v[n-2 - k2] = ( u[n2 + k2] + u[n-2-k2] - C[k2+1]*(u[n2+k2]-u[n-2-k2]) - C[k2]*(u[n2+k2+1]+u[n-2-k2+1]))/2;\n      v[n2+1+ k2] = ( u[n2+1+k2] - u[n-1-k2] + C[k2+1]*(u[n2+1+k2]+u[n-1-k2]) - C[k2]*(u[n2+k2]-u[n-2-k2]))/2;\n      v[n-1 - k2] = (-u[n2+1+k2] + u[n-1-k2] + C[k2+1]*(u[n2+1+k2]+u[n-1-k2]) - C[k2]*(u[n2+k2]-u[n-2-k2]))/2;\n   }\n   // step 8\n   for (k=k2=0; k < n4; ++k,k2 += 2) {\n      X[k]      = v[k2+n2]*B[k2  ] + v[k2+1+n2]*B[k2+1];\n      X[n2-1-k] = v[k2+n2]*B[k2+1] - v[k2+1+n2]*B[k2  ];\n   }\n\n   // decode kernel to output\n   // determined the following value experimentally\n   // (by first figuring out what made inverse_mdct_slow work); then matching that here\n   // (probably vorbis encoder premultiplies by n or n/2, to save it on the decoder?)\n   s = 0.5; // theoretically would be n4\n\n   // [[[ note! the s value of 0.5 is compensated for by the B[] in the current code,\n   //     so it needs to use the \"old\" B values to behave correctly, or else\n   //     set s to 1.0 ]]]\n   for (i=0; i < n4  ; ++i) buffer[i] = s * X[i+n4];\n   for (   ; i < n3_4; ++i) buffer[i] = -s * X[n3_4 - i - 1];\n   for (   ; i < n   ; ++i) buffer[i] = -s * X[i - n3_4];\n}\n#endif\n\nstatic float *get_window(vorb *f, int len)\n{\n   len <<= 1;\n   if (len == f->blocksize_0) return f->window[0];\n   if (len == f->blocksize_1) return f->window[1];\n   assert(0);\n   return NULL;\n}\n\n#ifndef STB_VORBIS_NO_DEFER_FLOOR\ntypedef int16 YTYPE;\n#else\ntypedef int YTYPE;\n#endif\nstatic int do_floor(vorb *f, Mapping *map, int i, int n, float *target, YTYPE *finalY, uint8 *step2_flag)\n{\n   int n2 = n >> 1;\n   int s = map->chan[i].mux, floor;\n   floor = map->submap_floor[s];\n   if (f->floor_types[floor] == 0) {\n      return error(f, VORBIS_invalid_stream);\n   } else {\n      Floor1 *g = &f->floor_config[floor].floor1;\n      int j,q;\n      int lx = 0, ly = finalY[0] * g->floor1_multiplier;\n      for (q=1; q < g->values; ++q) {\n         j = g->sorted_order[q];\n         #ifndef STB_VORBIS_NO_DEFER_FLOOR\n         if (finalY[j] >= 0)\n         #else\n         if (step2_flag[j])\n         #endif\n         {\n            int hy = finalY[j] * g->floor1_multiplier;\n            int hx = g->Xlist[j];\n            if (lx != hx)\n               draw_line(target, lx,ly, hx,hy, n2);\n            CHECK(f);\n            lx = hx, ly = hy;\n         }\n      }\n      if (lx < n2) {\n         // optimization of: draw_line(target, lx,ly, n,ly, n2);\n         for (j=lx; j < n2; ++j)\n            LINE_OP(target[j], inverse_db_table[ly]);\n         CHECK(f);\n      }\n   }\n   return TRUE;\n}\n\n// The meaning of \"left\" and \"right\"\n//\n// For a given frame:\n//     we compute samples from 0..n\n//     window_center is n/2\n//     we'll window and mix the samples from left_start to left_end with data from the previous frame\n//     all of the samples from left_end to right_start can be output without mixing; however,\n//        this interval is 0-length except when transitioning between short and long frames\n//     all of the samples from right_start to right_end need to be mixed with the next frame,\n//        which we don't have, so those get saved in a buffer\n//     frame N's right_end-right_start, the number of samples to mix with the next frame,\n//        has to be the same as frame N+1's left_end-left_start (which they are by\n//        construction)\n\nstatic int vorbis_decode_initial(vorb *f, int *p_left_start, int *p_left_end, int *p_right_start, int *p_right_end, int *mode)\n{\n   Mode *m;\n   int i, n, prev, next, window_center;\n   f->channel_buffer_start = f->channel_buffer_end = 0;\n\n  retry:\n   if (f->eof) return FALSE;\n   if (!maybe_start_packet(f))\n      return FALSE;\n   // check packet type\n   if (get_bits(f,1) != 0) {\n      if (IS_PUSH_MODE(f))\n         return error(f,VORBIS_bad_packet_type);\n      while (EOP != get8_packet(f));\n      goto retry;\n   }\n\n   if (f->alloc.alloc_buffer)\n      assert(f->alloc.alloc_buffer_length_in_bytes == f->temp_offset);\n\n   i = get_bits(f, ilog(f->mode_count-1));\n   if (i == EOP) return FALSE;\n   if (i >= f->mode_count) return FALSE;\n   *mode = i;\n   m = f->mode_config + i;\n   if (m->blockflag) {\n      n = f->blocksize_1;\n      prev = get_bits(f,1);\n      next = get_bits(f,1);\n   } else {\n      prev = next = 0;\n      n = f->blocksize_0;\n   }\n\n// WINDOWING\n\n   window_center = n >> 1;\n   if (m->blockflag && !prev) {\n      *p_left_start = (n - f->blocksize_0) >> 2;\n      *p_left_end   = (n + f->blocksize_0) >> 2;\n   } else {\n      *p_left_start = 0;\n      *p_left_end   = window_center;\n   }\n   if (m->blockflag && !next) {\n      *p_right_start = (n*3 - f->blocksize_0) >> 2;\n      *p_right_end   = (n*3 + f->blocksize_0) >> 2;\n   } else {\n      *p_right_start = window_center;\n      *p_right_end   = n;\n   }\n\n   return TRUE;\n}\n\nstatic int vorbis_decode_packet_rest(vorb *f, int *len, Mode *m, int left_start, int left_end, int right_start, int right_end, int *p_left)\n{\n   Mapping *map;\n   int i,j,k,n,n2;\n   int zero_channel[256];\n   int really_zero_channel[256];\n\n// WINDOWING\n\n   n = f->blocksize[m->blockflag];\n   map = &f->mapping[m->mapping];\n\n// FLOORS\n   n2 = n >> 1;\n\n   CHECK(f);\n\n   for (i=0; i < f->channels; ++i) {\n      int s = map->chan[i].mux, floor;\n      zero_channel[i] = FALSE;\n      floor = map->submap_floor[s];\n      if (f->floor_types[floor] == 0) {\n         return error(f, VORBIS_invalid_stream);\n      } else {\n         Floor1 *g = &f->floor_config[floor].floor1;\n         if (get_bits(f, 1)) {\n            short *finalY;\n            uint8 step2_flag[256];\n            static int range_list[4] = { 256, 128, 86, 64 };\n            int range = range_list[g->floor1_multiplier-1];\n            int offset = 2;\n            finalY = f->finalY[i];\n            finalY[0] = get_bits(f, ilog(range)-1);\n            finalY[1] = get_bits(f, ilog(range)-1);\n            for (j=0; j < g->partitions; ++j) {\n               int pclass = g->partition_class_list[j];\n               int cdim = g->class_dimensions[pclass];\n               int cbits = g->class_subclasses[pclass];\n               int csub = (1 << cbits)-1;\n               int cval = 0;\n               if (cbits) {\n                  Codebook *c = f->codebooks + g->class_masterbooks[pclass];\n                  DECODE(cval,f,c);\n               }\n               for (k=0; k < cdim; ++k) {\n                  int book = g->subclass_books[pclass][cval & csub];\n                  cval = cval >> cbits;\n                  if (book >= 0) {\n                     int temp;\n                     Codebook *c = f->codebooks + book;\n                     DECODE(temp,f,c);\n                     finalY[offset++] = temp;\n                  } else\n                     finalY[offset++] = 0;\n               }\n            }\n            if (f->valid_bits == INVALID_BITS) goto error; // behavior according to spec\n            step2_flag[0] = step2_flag[1] = 1;\n            for (j=2; j < g->values; ++j) {\n               int low, high, pred, highroom, lowroom, room, val;\n               low = g->neighbors[j][0];\n               high = g->neighbors[j][1];\n               //neighbors(g->Xlist, j, &low, &high);\n               pred = predict_point(g->Xlist[j], g->Xlist[low], g->Xlist[high], finalY[low], finalY[high]);\n               val = finalY[j];\n               highroom = range - pred;\n               lowroom = pred;\n               if (highroom < lowroom)\n                  room = highroom * 2;\n               else\n                  room = lowroom * 2;\n               if (val) {\n                  step2_flag[low] = step2_flag[high] = 1;\n                  step2_flag[j] = 1;\n                  if (val >= room)\n                     if (highroom > lowroom)\n                        finalY[j] = val - lowroom + pred;\n                     else\n                        finalY[j] = pred - val + highroom - 1;\n                  else\n                     if (val & 1)\n                        finalY[j] = pred - ((val+1)>>1);\n                     else\n                        finalY[j] = pred + (val>>1);\n               } else {\n                  step2_flag[j] = 0;\n                  finalY[j] = pred;\n               }\n            }\n\n#ifdef STB_VORBIS_NO_DEFER_FLOOR\n            do_floor(f, map, i, n, f->floor_buffers[i], finalY, step2_flag);\n#else\n            // defer final floor computation until _after_ residue\n            for (j=0; j < g->values; ++j) {\n               if (!step2_flag[j])\n                  finalY[j] = -1;\n            }\n#endif\n         } else {\n           error:\n            zero_channel[i] = TRUE;\n         }\n         // So we just defer everything else to later\n\n         // at this point we've decoded the floor into buffer\n      }\n   }\n   CHECK(f);\n   // at this point we've decoded all floors\n\n   if (f->alloc.alloc_buffer)\n      assert(f->alloc.alloc_buffer_length_in_bytes == f->temp_offset);\n\n   // re-enable coupled channels if necessary\n   memcpy(really_zero_channel, zero_channel, sizeof(really_zero_channel[0]) * f->channels);\n   for (i=0; i < map->coupling_steps; ++i)\n      if (!zero_channel[map->chan[i].magnitude] || !zero_channel[map->chan[i].angle]) {\n         zero_channel[map->chan[i].magnitude] = zero_channel[map->chan[i].angle] = FALSE;\n      }\n\n   CHECK(f);\n// RESIDUE DECODE\n   for (i=0; i < map->submaps; ++i) {\n      float *residue_buffers[STB_VORBIS_MAX_CHANNELS];\n      int r;\n      uint8 do_not_decode[256];\n      int ch = 0;\n      for (j=0; j < f->channels; ++j) {\n         if (map->chan[j].mux == i) {\n            if (zero_channel[j]) {\n               do_not_decode[ch] = TRUE;\n               residue_buffers[ch] = NULL;\n            } else {\n               do_not_decode[ch] = FALSE;\n               residue_buffers[ch] = f->channel_buffers[j];\n            }\n            ++ch;\n         }\n      }\n      r = map->submap_residue[i];\n      decode_residue(f, residue_buffers, ch, n2, r, do_not_decode);\n   }\n\n   if (f->alloc.alloc_buffer)\n      assert(f->alloc.alloc_buffer_length_in_bytes == f->temp_offset);\n   CHECK(f);\n\n// INVERSE COUPLING\n   for (i = map->coupling_steps-1; i >= 0; --i) {\n      int n2 = n >> 1;\n      float *m = f->channel_buffers[map->chan[i].magnitude];\n      float *a = f->channel_buffers[map->chan[i].angle    ];\n      for (j=0; j < n2; ++j) {\n         float a2,m2;\n         if (m[j] > 0)\n            if (a[j] > 0)\n               m2 = m[j], a2 = m[j] - a[j];\n            else\n               a2 = m[j], m2 = m[j] + a[j];\n         else\n            if (a[j] > 0)\n               m2 = m[j], a2 = m[j] + a[j];\n            else\n               a2 = m[j], m2 = m[j] - a[j];\n         m[j] = m2;\n         a[j] = a2;\n      }\n   }\n   CHECK(f);\n\n   // finish decoding the floors\n#ifndef STB_VORBIS_NO_DEFER_FLOOR\n   for (i=0; i < f->channels; ++i) {\n      if (really_zero_channel[i]) {\n         memset(f->channel_buffers[i], 0, sizeof(*f->channel_buffers[i]) * n2);\n      } else {\n         do_floor(f, map, i, n, f->channel_buffers[i], f->finalY[i], NULL);\n      }\n   }\n#else\n   for (i=0; i < f->channels; ++i) {\n      if (really_zero_channel[i]) {\n         memset(f->channel_buffers[i], 0, sizeof(*f->channel_buffers[i]) * n2);\n      } else {\n         for (j=0; j < n2; ++j)\n            f->channel_buffers[i][j] *= f->floor_buffers[i][j];\n      }\n   }\n#endif\n\n// INVERSE MDCT\n   CHECK(f);\n   for (i=0; i < f->channels; ++i)\n      inverse_mdct(f->channel_buffers[i], n, f, m->blockflag);\n   CHECK(f);\n\n   // this shouldn't be necessary, unless we exited on an error\n   // and want to flush to get to the next packet\n   flush_packet(f);\n\n   if (f->first_decode) {\n      // assume we start so first non-discarded sample is sample 0\n      // this isn't to spec, but spec would require us to read ahead\n      // and decode the size of all current frames--could be done,\n      // but presumably it's not a commonly used feature\n      f->current_loc = -n2; // start of first frame is positioned for discard\n      // we might have to discard samples \"from\" the next frame too,\n      // if we're lapping a large block then a small at the start?\n      f->discard_samples_deferred = n - right_end;\n      f->current_loc_valid = TRUE;\n      f->first_decode = FALSE;\n   } else if (f->discard_samples_deferred) {\n      if (f->discard_samples_deferred >= right_start - left_start) {\n         f->discard_samples_deferred -= (right_start - left_start);\n         left_start = right_start;\n         *p_left = left_start;\n      } else {\n         left_start += f->discard_samples_deferred;\n         *p_left = left_start;\n         f->discard_samples_deferred = 0;\n      }\n   } else if (f->previous_length == 0 && f->current_loc_valid) {\n      // we're recovering from a seek... that means we're going to discard\n      // the samples from this packet even though we know our position from\n      // the last page header, so we need to update the position based on\n      // the discarded samples here\n      // but wait, the code below is going to add this in itself even\n      // on a discard, so we don't need to do it here...\n   }\n\n   // check if we have ogg information about the sample # for this packet\n   if (f->last_seg_which == f->end_seg_with_known_loc) {\n      // if we have a valid current loc, and this is final:\n      if (f->current_loc_valid && (f->page_flag & PAGEFLAG_last_page)) {\n         uint32 current_end = f->known_loc_for_packet;\n         // then let's infer the size of the (probably) short final frame\n         if (current_end < f->current_loc + (right_end-left_start)) {\n            if (current_end < f->current_loc) {\n               // negative truncation, that's impossible!\n               *len = 0;\n            } else {\n               *len = current_end - f->current_loc;\n            }\n            *len += left_start; // this doesn't seem right, but has no ill effect on my test files\n            if (*len > right_end) *len = right_end; // this should never happen\n            f->current_loc += *len;\n            return TRUE;\n         }\n      }\n      // otherwise, just set our sample loc\n      // guess that the ogg granule pos refers to the _middle_ of the\n      // last frame?\n      // set f->current_loc to the position of left_start\n      f->current_loc = f->known_loc_for_packet - (n2-left_start);\n      f->current_loc_valid = TRUE;\n   }\n   if (f->current_loc_valid)\n      f->current_loc += (right_start - left_start);\n\n   if (f->alloc.alloc_buffer)\n      assert(f->alloc.alloc_buffer_length_in_bytes == f->temp_offset);\n   *len = right_end;  // ignore samples after the window goes to 0\n   CHECK(f);\n\n   return TRUE;\n}\n\nstatic int vorbis_decode_packet(vorb *f, int *len, int *p_left, int *p_right)\n{\n   int mode, left_end, right_end;\n   if (!vorbis_decode_initial(f, p_left, &left_end, p_right, &right_end, &mode)) return 0;\n   return vorbis_decode_packet_rest(f, len, f->mode_config + mode, *p_left, left_end, *p_right, right_end, p_left);\n}\n\nstatic int vorbis_finish_frame(stb_vorbis *f, int len, int left, int right)\n{\n   int prev,i,j;\n   // we use right&left (the start of the right- and left-window sin()-regions)\n   // to determine how much to return, rather than inferring from the rules\n   // (same result, clearer code); 'left' indicates where our sin() window\n   // starts, therefore where the previous window's right edge starts, and\n   // therefore where to start mixing from the previous buffer. 'right'\n   // indicates where our sin() ending-window starts, therefore that's where\n   // we start saving, and where our returned-data ends.\n\n   // mixin from previous window\n   if (f->previous_length) {\n      int i,j, n = f->previous_length;\n      float *w = get_window(f, n);\n      for (i=0; i < f->channels; ++i) {\n         for (j=0; j < n; ++j)\n            f->channel_buffers[i][left+j] =\n               f->channel_buffers[i][left+j]*w[    j] +\n               f->previous_window[i][     j]*w[n-1-j];\n      }\n   }\n\n   prev = f->previous_length;\n\n   // last half of this data becomes previous window\n   f->previous_length = len - right;\n\n   // @OPTIMIZE: could avoid this copy by double-buffering the\n   // output (flipping previous_window with channel_buffers), but\n   // then previous_window would have to be 2x as large, and\n   // channel_buffers couldn't be temp mem (although they're NOT\n   // currently temp mem, they could be (unless we want to level\n   // performance by spreading out the computation))\n   for (i=0; i < f->channels; ++i)\n      for (j=0; right+j < len; ++j)\n         f->previous_window[i][j] = f->channel_buffers[i][right+j];\n\n   if (!prev)\n      // there was no previous packet, so this data isn't valid...\n      // this isn't entirely true, only the would-have-overlapped data\n      // isn't valid, but this seems to be what the spec requires\n      return 0;\n\n   // truncate a short frame\n   if (len < right) right = len;\n\n   f->samples_output += right-left;\n\n   return right - left;\n}\n\nstatic int vorbis_pump_first_frame(stb_vorbis *f)\n{\n   int len, right, left, res;\n   res = vorbis_decode_packet(f, &len, &left, &right);\n   if (res)\n      vorbis_finish_frame(f, len, left, right);\n   return res;\n}\n\n#ifndef STB_VORBIS_NO_PUSHDATA_API\nstatic int is_whole_packet_present(stb_vorbis *f, int end_page)\n{\n   // make sure that we have the packet available before continuing...\n   // this requires a full ogg parse, but we know we can fetch from f->stream\n\n   // instead of coding this out explicitly, we could save the current read state,\n   // read the next packet with get8() until end-of-packet, check f->eof, then\n   // reset the state? but that would be slower, esp. since we'd have over 256 bytes\n   // of state to restore (primarily the page segment table)\n\n   int s = f->next_seg, first = TRUE;\n   uint8 *p = f->stream;\n\n   if (s != -1) { // if we're not starting the packet with a 'continue on next page' flag\n      for (; s < f->segment_count; ++s) {\n         p += f->segments[s];\n         if (f->segments[s] < 255)               // stop at first short segment\n            break;\n      }\n      // either this continues, or it ends it...\n      if (end_page)\n         if (s < f->segment_count-1)             return error(f, VORBIS_invalid_stream);\n      if (s == f->segment_count)\n         s = -1; // set 'crosses page' flag\n      if (p > f->stream_end)                     return error(f, VORBIS_need_more_data);\n      first = FALSE;\n   }\n   for (; s == -1;) {\n      uint8 *q; \n      int n;\n\n      // check that we have the page header ready\n      if (p + 26 >= f->stream_end)               return error(f, VORBIS_need_more_data);\n      // validate the page\n      if (memcmp(p, ogg_page_header, 4))         return error(f, VORBIS_invalid_stream);\n      if (p[4] != 0)                             return error(f, VORBIS_invalid_stream);\n      if (first) { // the first segment must NOT have 'continued_packet', later ones MUST\n         if (f->previous_length)\n            if ((p[5] & PAGEFLAG_continued_packet))  return error(f, VORBIS_invalid_stream);\n         // if no previous length, we're resynching, so we can come in on a continued-packet,\n         // which we'll just drop\n      } else {\n         if (!(p[5] & PAGEFLAG_continued_packet)) return error(f, VORBIS_invalid_stream);\n      }\n      n = p[26]; // segment counts\n      q = p+27;  // q points to segment table\n      p = q + n; // advance past header\n      // make sure we've read the segment table\n      if (p > f->stream_end)                     return error(f, VORBIS_need_more_data);\n      for (s=0; s < n; ++s) {\n         p += q[s];\n         if (q[s] < 255)\n            break;\n      }\n      if (end_page)\n         if (s < n-1)                            return error(f, VORBIS_invalid_stream);\n      if (s == n)\n         s = -1; // set 'crosses page' flag\n      if (p > f->stream_end)                     return error(f, VORBIS_need_more_data);\n      first = FALSE;\n   }\n   return TRUE;\n}\n#endif // !STB_VORBIS_NO_PUSHDATA_API\n\nstatic int start_decoder(vorb *f)\n{\n   uint8 header[6], x,y;\n   int len,i,j,k, max_submaps = 0;\n   int longest_floorlist=0;\n\n   // first page, first packet\n\n   if (!start_page(f))                              return FALSE;\n   // validate page flag\n   if (!(f->page_flag & PAGEFLAG_first_page))       return error(f, VORBIS_invalid_first_page);\n   if (f->page_flag & PAGEFLAG_last_page)           return error(f, VORBIS_invalid_first_page);\n   if (f->page_flag & PAGEFLAG_continued_packet)    return error(f, VORBIS_invalid_first_page);\n   // check for expected packet length\n   if (f->segment_count != 1)                       return error(f, VORBIS_invalid_first_page);\n   if (f->segments[0] != 30) {\n      // check for the Ogg skeleton fishead identifying header to refine our error\n      if (f->segments[0] == 64 &&\n          getn(f, header, 6) &&\n          header[0] == 'f' &&\n          header[1] == 'i' &&\n          header[2] == 's' &&\n          header[3] == 'h' &&\n          header[4] == 'e' &&\n          header[5] == 'a' &&\n          get8(f)   == 'd' &&\n          get8(f)   == '\\0')                        return error(f, VORBIS_ogg_skeleton_not_supported);\n      else\n                                                    return error(f, VORBIS_invalid_first_page);\n   }\n\n   // read packet\n   // check packet header\n   if (get8(f) != VORBIS_packet_id)                 return error(f, VORBIS_invalid_first_page);\n   if (!getn(f, header, 6))                         return error(f, VORBIS_unexpected_eof);\n   if (!vorbis_validate(header))                    return error(f, VORBIS_invalid_first_page);\n   // vorbis_version\n   if (get32(f) != 0)                               return error(f, VORBIS_invalid_first_page);\n   f->channels = get8(f); if (!f->channels)         return error(f, VORBIS_invalid_first_page);\n   if (f->channels > STB_VORBIS_MAX_CHANNELS)       return error(f, VORBIS_too_many_channels);\n   f->sample_rate = get32(f); if (!f->sample_rate)  return error(f, VORBIS_invalid_first_page);\n   get32(f); // bitrate_maximum\n   get32(f); // bitrate_nominal\n   get32(f); // bitrate_minimum\n   x = get8(f);\n   {\n      int log0,log1;\n      log0 = x & 15;\n      log1 = x >> 4;\n      f->blocksize_0 = 1 << log0;\n      f->blocksize_1 = 1 << log1;\n      if (log0 < 6 || log0 > 13)                       return error(f, VORBIS_invalid_setup);\n      if (log1 < 6 || log1 > 13)                       return error(f, VORBIS_invalid_setup);\n      if (log0 > log1)                                 return error(f, VORBIS_invalid_setup);\n   }\n\n   // framing_flag\n   x = get8(f);\n   if (!(x & 1))                                    return error(f, VORBIS_invalid_first_page);\n\n   // second packet!\n   if (!start_page(f))                              return FALSE;\n\n   if (!start_packet(f))                            return FALSE;\n   do {\n      len = next_segment(f);\n      skip(f, len);\n      f->bytes_in_seg = 0;\n   } while (len);\n\n   // third packet!\n   if (!start_packet(f))                            return FALSE;\n\n   #ifndef STB_VORBIS_NO_PUSHDATA_API\n   if (IS_PUSH_MODE(f)) {\n      if (!is_whole_packet_present(f, TRUE)) {\n         // convert error in ogg header to write type\n         if (f->error == VORBIS_invalid_stream)\n            f->error = VORBIS_invalid_setup;\n         return FALSE;\n      }\n   }\n   #endif\n\n   crc32_init(); // always init it, to avoid multithread race conditions\n\n   if (get8_packet(f) != VORBIS_packet_setup)       return error(f, VORBIS_invalid_setup);\n   for (i=0; i < 6; ++i) header[i] = get8_packet(f);\n   if (!vorbis_validate(header))                    return error(f, VORBIS_invalid_setup);\n\n   // codebooks\n\n   f->codebook_count = get_bits(f,8) + 1;\n   f->codebooks = (Codebook *) setup_malloc(f, sizeof(*f->codebooks) * f->codebook_count);\n   if (f->codebooks == NULL)                        return error(f, VORBIS_outofmem);\n   memset(f->codebooks, 0, sizeof(*f->codebooks) * f->codebook_count);\n   for (i=0; i < f->codebook_count; ++i) {\n      uint32 *values;\n      int ordered, sorted_count;\n      int total=0;\n      uint8 *lengths;\n      Codebook *c = f->codebooks+i;\n      CHECK(f);\n      x = get_bits(f, 8); if (x != 0x42)            return error(f, VORBIS_invalid_setup);\n      x = get_bits(f, 8); if (x != 0x43)            return error(f, VORBIS_invalid_setup);\n      x = get_bits(f, 8); if (x != 0x56)            return error(f, VORBIS_invalid_setup);\n      x = get_bits(f, 8);\n      c->dimensions = (get_bits(f, 8)<<8) + x;\n      x = get_bits(f, 8);\n      y = get_bits(f, 8);\n      c->entries = (get_bits(f, 8)<<16) + (y<<8) + x;\n      ordered = get_bits(f,1);\n      c->sparse = ordered ? 0 : get_bits(f,1);\n\n      if (c->dimensions == 0 && c->entries != 0)    return error(f, VORBIS_invalid_setup);\n\n      if (c->sparse)\n         lengths = (uint8 *) setup_temp_malloc(f, c->entries);\n      else\n         lengths = c->codeword_lengths = (uint8 *) setup_malloc(f, c->entries);\n\n      if (!lengths) return error(f, VORBIS_outofmem);\n\n      if (ordered) {\n         int current_entry = 0;\n         int current_length = get_bits(f,5) + 1;\n         while (current_entry < c->entries) {\n            int limit = c->entries - current_entry;\n            int n = get_bits(f, ilog(limit));\n            if (current_entry + n > (int) c->entries) { return error(f, VORBIS_invalid_setup); }\n            memset(lengths + current_entry, current_length, n);\n            current_entry += n;\n            ++current_length;\n         }\n      } else {\n         for (j=0; j < c->entries; ++j) {\n            int present = c->sparse ? get_bits(f,1) : 1;\n            if (present) {\n               lengths[j] = get_bits(f, 5) + 1;\n               ++total;\n               if (lengths[j] == 32)\n                  return error(f, VORBIS_invalid_setup);\n            } else {\n               lengths[j] = NO_CODE;\n            }\n         }\n      }\n\n      if (c->sparse && total >= c->entries >> 2) {\n         // convert sparse items to non-sparse!\n         if (c->entries > (int) f->setup_temp_memory_required)\n            f->setup_temp_memory_required = c->entries;\n\n         c->codeword_lengths = (uint8 *) setup_malloc(f, c->entries);\n         if (c->codeword_lengths == NULL) return error(f, VORBIS_outofmem);\n         memcpy(c->codeword_lengths, lengths, c->entries);\n         setup_temp_free(f, lengths, c->entries); // note this is only safe if there have been no intervening temp mallocs!\n         lengths = c->codeword_lengths;\n         c->sparse = 0;\n      }\n\n      // compute the size of the sorted tables\n      if (c->sparse) {\n         sorted_count = total;\n      } else {\n         sorted_count = 0;\n         #ifndef STB_VORBIS_NO_HUFFMAN_BINARY_SEARCH\n         for (j=0; j < c->entries; ++j)\n            if (lengths[j] > STB_VORBIS_FAST_HUFFMAN_LENGTH && lengths[j] != NO_CODE)\n               ++sorted_count;\n         #endif\n      }\n\n      c->sorted_entries = sorted_count;\n      values = NULL;\n\n      CHECK(f);\n      if (!c->sparse) {\n         c->codewords = (uint32 *) setup_malloc(f, sizeof(c->codewords[0]) * c->entries);\n         if (!c->codewords)                  return error(f, VORBIS_outofmem);\n      } else {\n         unsigned int size;\n         if (c->sorted_entries) {\n            c->codeword_lengths = (uint8 *) setup_malloc(f, c->sorted_entries);\n            if (!c->codeword_lengths)           return error(f, VORBIS_outofmem);\n            c->codewords = (uint32 *) setup_temp_malloc(f, sizeof(*c->codewords) * c->sorted_entries);\n            if (!c->codewords)                  return error(f, VORBIS_outofmem);\n            values = (uint32 *) setup_temp_malloc(f, sizeof(*values) * c->sorted_entries);\n            if (!values)                        return error(f, VORBIS_outofmem);\n         }\n         size = c->entries + (sizeof(*c->codewords) + sizeof(*values)) * c->sorted_entries;\n         if (size > f->setup_temp_memory_required)\n            f->setup_temp_memory_required = size;\n      }\n\n      if (!compute_codewords(c, lengths, c->entries, values)) {\n         if (c->sparse) setup_temp_free(f, values, 0);\n         return error(f, VORBIS_invalid_setup);\n      }\n\n      if (c->sorted_entries) {\n         // allocate an extra slot for sentinels\n         c->sorted_codewords = (uint32 *) setup_malloc(f, sizeof(*c->sorted_codewords) * (c->sorted_entries+1));\n         if (c->sorted_codewords == NULL) return error(f, VORBIS_outofmem);\n         // allocate an extra slot at the front so that c->sorted_values[-1] is defined\n         // so that we can catch that case without an extra if\n         c->sorted_values    = ( int   *) setup_malloc(f, sizeof(*c->sorted_values   ) * (c->sorted_entries+1));\n         if (c->sorted_values == NULL) return error(f, VORBIS_outofmem);\n         ++c->sorted_values;\n         c->sorted_values[-1] = -1;\n         compute_sorted_huffman(c, lengths, values);\n      }\n\n      if (c->sparse) {\n         setup_temp_free(f, values, sizeof(*values)*c->sorted_entries);\n         setup_temp_free(f, c->codewords, sizeof(*c->codewords)*c->sorted_entries);\n         setup_temp_free(f, lengths, c->entries);\n         c->codewords = NULL;\n      }\n\n      compute_accelerated_huffman(c);\n\n      CHECK(f);\n      c->lookup_type = get_bits(f, 4);\n      if (c->lookup_type > 2) return error(f, VORBIS_invalid_setup);\n      if (c->lookup_type > 0) {\n         uint16 *mults;\n         c->minimum_value = float32_unpack(get_bits(f, 32));\n         c->delta_value = float32_unpack(get_bits(f, 32));\n         c->value_bits = get_bits(f, 4)+1;\n         c->sequence_p = get_bits(f,1);\n         if (c->lookup_type == 1) {\n            c->lookup_values = lookup1_values(c->entries, c->dimensions);\n         } else {\n            c->lookup_values = c->entries * c->dimensions;\n         }\n         if (c->lookup_values == 0) return error(f, VORBIS_invalid_setup);\n         mults = (uint16 *) setup_temp_malloc(f, sizeof(mults[0]) * c->lookup_values);\n         if (mults == NULL) return error(f, VORBIS_outofmem);\n         for (j=0; j < (int) c->lookup_values; ++j) {\n            int q = get_bits(f, c->value_bits);\n            if (q == EOP) { setup_temp_free(f,mults,sizeof(mults[0])*c->lookup_values); return error(f, VORBIS_invalid_setup); }\n            mults[j] = q;\n         }\n\n#ifndef STB_VORBIS_DIVIDES_IN_CODEBOOK\n         if (c->lookup_type == 1) {\n            int len, sparse = c->sparse;\n            float last=0;\n            // pre-expand the lookup1-style multiplicands, to avoid a divide in the inner loop\n            if (sparse) {\n               if (c->sorted_entries == 0) goto skip;\n               c->multiplicands = (codetype *) setup_malloc(f, sizeof(c->multiplicands[0]) * c->sorted_entries * c->dimensions);\n            } else\n               c->multiplicands = (codetype *) setup_malloc(f, sizeof(c->multiplicands[0]) * c->entries        * c->dimensions);\n            if (c->multiplicands == NULL) { setup_temp_free(f,mults,sizeof(mults[0])*c->lookup_values); return error(f, VORBIS_outofmem); }\n            len = sparse ? c->sorted_entries : c->entries;\n            for (j=0; j < len; ++j) {\n               unsigned int z = sparse ? c->sorted_values[j] : j;\n               unsigned int div=1;\n               for (k=0; k < c->dimensions; ++k) {\n                  int off = (z / div) % c->lookup_values;\n                  float val = mults[off];\n                  val = mults[off]*c->delta_value + c->minimum_value + last;\n                  c->multiplicands[j*c->dimensions + k] = val;\n                  if (c->sequence_p)\n                     last = val;\n                  if (k+1 < c->dimensions) {\n                     if (div > UINT_MAX / (unsigned int) c->lookup_values) {\n                        setup_temp_free(f, mults,sizeof(mults[0])*c->lookup_values);\n                        return error(f, VORBIS_invalid_setup);\n                     }\n                     div *= c->lookup_values;\n                  }\n               }\n            }\n            c->lookup_type = 2;\n         }\n         else\n#endif\n         {\n            float last=0;\n            CHECK(f);\n            c->multiplicands = (codetype *) setup_malloc(f, sizeof(c->multiplicands[0]) * c->lookup_values);\n            if (c->multiplicands == NULL) { setup_temp_free(f, mults,sizeof(mults[0])*c->lookup_values); return error(f, VORBIS_outofmem); }\n            for (j=0; j < (int) c->lookup_values; ++j) {\n               float val = mults[j] * c->delta_value + c->minimum_value + last;\n               c->multiplicands[j] = val;\n               if (c->sequence_p)\n                  last = val;\n            }\n         }\n#ifndef STB_VORBIS_DIVIDES_IN_CODEBOOK\n        skip:;\n#endif\n         setup_temp_free(f, mults, sizeof(mults[0])*c->lookup_values);\n\n         CHECK(f);\n      }\n      CHECK(f);\n   }\n\n   // time domain transfers (notused)\n\n   x = get_bits(f, 6) + 1;\n   for (i=0; i < x; ++i) {\n      uint32 z = get_bits(f, 16);\n      if (z != 0) return error(f, VORBIS_invalid_setup);\n   }\n\n   // Floors\n   f->floor_count = get_bits(f, 6)+1;\n   f->floor_config = (Floor *)  setup_malloc(f, f->floor_count * sizeof(*f->floor_config));\n   if (f->floor_config == NULL) return error(f, VORBIS_outofmem);\n   for (i=0; i < f->floor_count; ++i) {\n      f->floor_types[i] = get_bits(f, 16);\n      if (f->floor_types[i] > 1) return error(f, VORBIS_invalid_setup);\n      if (f->floor_types[i] == 0) {\n         Floor0 *g = &f->floor_config[i].floor0;\n         g->order = get_bits(f,8);\n         g->rate = get_bits(f,16);\n         g->bark_map_size = get_bits(f,16);\n         g->amplitude_bits = get_bits(f,6);\n         g->amplitude_offset = get_bits(f,8);\n         g->number_of_books = get_bits(f,4) + 1;\n         for (j=0; j < g->number_of_books; ++j)\n            g->book_list[j] = get_bits(f,8);\n         return error(f, VORBIS_feature_not_supported);\n      } else {\n         stbv__floor_ordering p[31*8+2];\n         Floor1 *g = &f->floor_config[i].floor1;\n         int max_class = -1; \n         g->partitions = get_bits(f, 5);\n         for (j=0; j < g->partitions; ++j) {\n            g->partition_class_list[j] = get_bits(f, 4);\n            if (g->partition_class_list[j] > max_class)\n               max_class = g->partition_class_list[j];\n         }\n         for (j=0; j <= max_class; ++j) {\n            g->class_dimensions[j] = get_bits(f, 3)+1;\n            g->class_subclasses[j] = get_bits(f, 2);\n            if (g->class_subclasses[j]) {\n               g->class_masterbooks[j] = get_bits(f, 8);\n               if (g->class_masterbooks[j] >= f->codebook_count) return error(f, VORBIS_invalid_setup);\n            }\n            for (k=0; k < 1 << g->class_subclasses[j]; ++k) {\n               g->subclass_books[j][k] = get_bits(f,8)-1;\n               if (g->subclass_books[j][k] >= f->codebook_count) return error(f, VORBIS_invalid_setup);\n            }\n         }\n         g->floor1_multiplier = get_bits(f,2)+1;\n         g->rangebits = get_bits(f,4);\n         g->Xlist[0] = 0;\n         g->Xlist[1] = 1 << g->rangebits;\n         g->values = 2;\n         for (j=0; j < g->partitions; ++j) {\n            int c = g->partition_class_list[j];\n            for (k=0; k < g->class_dimensions[c]; ++k) {\n               g->Xlist[g->values] = get_bits(f, g->rangebits);\n               ++g->values;\n            }\n         }\n         // precompute the sorting\n         for (j=0; j < g->values; ++j) {\n            p[j].x = g->Xlist[j];\n            p[j].id = j;\n         }\n         qsort(p, g->values, sizeof(p[0]), point_compare);\n         for (j=0; j < g->values; ++j)\n            g->sorted_order[j] = (uint8) p[j].id;\n         // precompute the neighbors\n         for (j=2; j < g->values; ++j) {\n            int low,hi;\n            neighbors(g->Xlist, j, &low,&hi);\n            g->neighbors[j][0] = low;\n            g->neighbors[j][1] = hi;\n         }\n\n         if (g->values > longest_floorlist)\n            longest_floorlist = g->values;\n      }\n   }\n\n   // Residue\n   f->residue_count = get_bits(f, 6)+1;\n   f->residue_config = (Residue *) setup_malloc(f, f->residue_count * sizeof(f->residue_config[0]));\n   if (f->residue_config == NULL) return error(f, VORBIS_outofmem);\n   memset(f->residue_config, 0, f->residue_count * sizeof(f->residue_config[0]));\n   for (i=0; i < f->residue_count; ++i) {\n      uint8 residue_cascade[64];\n      Residue *r = f->residue_config+i;\n      f->residue_types[i] = get_bits(f, 16);\n      if (f->residue_types[i] > 2) return error(f, VORBIS_invalid_setup);\n      r->begin = get_bits(f, 24);\n      r->end = get_bits(f, 24);\n      if (r->end < r->begin) return error(f, VORBIS_invalid_setup);\n      r->part_size = get_bits(f,24)+1;\n      r->classifications = get_bits(f,6)+1;\n      r->classbook = get_bits(f,8);\n      if (r->classbook >= f->codebook_count) return error(f, VORBIS_invalid_setup);\n      for (j=0; j < r->classifications; ++j) {\n         uint8 high_bits=0;\n         uint8 low_bits=get_bits(f,3);\n         if (get_bits(f,1))\n            high_bits = get_bits(f,5);\n         residue_cascade[j] = high_bits*8 + low_bits;\n      }\n      r->residue_books = (short (*)[8]) setup_malloc(f, sizeof(r->residue_books[0]) * r->classifications);\n      if (r->residue_books == NULL) return error(f, VORBIS_outofmem);\n      for (j=0; j < r->classifications; ++j) {\n         for (k=0; k < 8; ++k) {\n            if (residue_cascade[j] & (1 << k)) {\n               r->residue_books[j][k] = get_bits(f, 8);\n               if (r->residue_books[j][k] >= f->codebook_count) return error(f, VORBIS_invalid_setup);\n            } else {\n               r->residue_books[j][k] = -1;\n            }\n         }\n      }\n      // precompute the classifications[] array to avoid inner-loop mod/divide\n      // call it 'classdata' since we already have r->classifications\n      r->classdata = (uint8 **) setup_malloc(f, sizeof(*r->classdata) * f->codebooks[r->classbook].entries);\n      if (!r->classdata) return error(f, VORBIS_outofmem);\n      memset(r->classdata, 0, sizeof(*r->classdata) * f->codebooks[r->classbook].entries);\n      for (j=0; j < f->codebooks[r->classbook].entries; ++j) {\n         int classwords = f->codebooks[r->classbook].dimensions;\n         int temp = j;\n         r->classdata[j] = (uint8 *) setup_malloc(f, sizeof(r->classdata[j][0]) * classwords);\n         if (r->classdata[j] == NULL) return error(f, VORBIS_outofmem);\n         for (k=classwords-1; k >= 0; --k) {\n            r->classdata[j][k] = temp % r->classifications;\n            temp /= r->classifications;\n         }\n      }\n   }\n\n   f->mapping_count = get_bits(f,6)+1;\n   f->mapping = (Mapping *) setup_malloc(f, f->mapping_count * sizeof(*f->mapping));\n   if (f->mapping == NULL) return error(f, VORBIS_outofmem);\n   memset(f->mapping, 0, f->mapping_count * sizeof(*f->mapping));\n   for (i=0; i < f->mapping_count; ++i) {\n      Mapping *m = f->mapping + i;      \n      int mapping_type = get_bits(f,16);\n      if (mapping_type != 0) return error(f, VORBIS_invalid_setup);\n      m->chan = (MappingChannel *) setup_malloc(f, f->channels * sizeof(*m->chan));\n      if (m->chan == NULL) return error(f, VORBIS_outofmem);\n      if (get_bits(f,1))\n         m->submaps = get_bits(f,4)+1;\n      else\n         m->submaps = 1;\n      if (m->submaps > max_submaps)\n         max_submaps = m->submaps;\n      if (get_bits(f,1)) {\n         m->coupling_steps = get_bits(f,8)+1;\n         for (k=0; k < m->coupling_steps; ++k) {\n            m->chan[k].magnitude = get_bits(f, ilog(f->channels-1));\n            m->chan[k].angle = get_bits(f, ilog(f->channels-1));\n            if (m->chan[k].magnitude >= f->channels)        return error(f, VORBIS_invalid_setup);\n            if (m->chan[k].angle     >= f->channels)        return error(f, VORBIS_invalid_setup);\n            if (m->chan[k].magnitude == m->chan[k].angle)   return error(f, VORBIS_invalid_setup);\n         }\n      } else\n         m->coupling_steps = 0;\n\n      // reserved field\n      if (get_bits(f,2)) return error(f, VORBIS_invalid_setup);\n      if (m->submaps > 1) {\n         for (j=0; j < f->channels; ++j) {\n            m->chan[j].mux = get_bits(f, 4);\n            if (m->chan[j].mux >= m->submaps)                return error(f, VORBIS_invalid_setup);\n         }\n      } else\n         // @SPECIFICATION: this case is missing from the spec\n         for (j=0; j < f->channels; ++j)\n            m->chan[j].mux = 0;\n\n      for (j=0; j < m->submaps; ++j) {\n         get_bits(f,8); // discard\n         m->submap_floor[j] = get_bits(f,8);\n         m->submap_residue[j] = get_bits(f,8);\n         if (m->submap_floor[j] >= f->floor_count)      return error(f, VORBIS_invalid_setup);\n         if (m->submap_residue[j] >= f->residue_count)  return error(f, VORBIS_invalid_setup);\n      }\n   }\n\n   // Modes\n   f->mode_count = get_bits(f, 6)+1;\n   for (i=0; i < f->mode_count; ++i) {\n      Mode *m = f->mode_config+i;\n      m->blockflag = get_bits(f,1);\n      m->windowtype = get_bits(f,16);\n      m->transformtype = get_bits(f,16);\n      m->mapping = get_bits(f,8);\n      if (m->windowtype != 0)                 return error(f, VORBIS_invalid_setup);\n      if (m->transformtype != 0)              return error(f, VORBIS_invalid_setup);\n      if (m->mapping >= f->mapping_count)     return error(f, VORBIS_invalid_setup);\n   }\n\n   flush_packet(f);\n\n   f->previous_length = 0;\n\n   for (i=0; i < f->channels; ++i) {\n      f->channel_buffers[i] = (float *) setup_malloc(f, sizeof(float) * f->blocksize_1);\n      f->previous_window[i] = (float *) setup_malloc(f, sizeof(float) * f->blocksize_1/2);\n      f->finalY[i]          = (int16 *) setup_malloc(f, sizeof(int16) * longest_floorlist);\n      if (f->channel_buffers[i] == NULL || f->previous_window[i] == NULL || f->finalY[i] == NULL) return error(f, VORBIS_outofmem);\n      memset(f->channel_buffers[i], 0, sizeof(float) * f->blocksize_1);\n      #ifdef STB_VORBIS_NO_DEFER_FLOOR\n      f->floor_buffers[i]   = (float *) setup_malloc(f, sizeof(float) * f->blocksize_1/2);\n      if (f->floor_buffers[i] == NULL) return error(f, VORBIS_outofmem);\n      #endif\n   }\n\n   if (!init_blocksize(f, 0, f->blocksize_0)) return FALSE;\n   if (!init_blocksize(f, 1, f->blocksize_1)) return FALSE;\n   f->blocksize[0] = f->blocksize_0;\n   f->blocksize[1] = f->blocksize_1;\n\n#ifdef STB_VORBIS_DIVIDE_TABLE\n   if (integer_divide_table[1][1]==0)\n      for (i=0; i < DIVTAB_NUMER; ++i)\n         for (j=1; j < DIVTAB_DENOM; ++j)\n            integer_divide_table[i][j] = i / j;\n#endif\n\n   // compute how much temporary memory is needed\n\n   // 1.\n   {\n      uint32 imdct_mem = (f->blocksize_1 * sizeof(float) >> 1);\n      uint32 classify_mem;\n      int i,max_part_read=0;\n      for (i=0; i < f->residue_count; ++i) {\n         Residue *r = f->residue_config + i;\n         unsigned int actual_size = f->blocksize_1 / 2;\n         unsigned int limit_r_begin = r->begin < actual_size ? r->begin : actual_size;\n         unsigned int limit_r_end   = r->end   < actual_size ? r->end   : actual_size;\n         int n_read = limit_r_end - limit_r_begin;\n         int part_read = n_read / r->part_size;\n         if (part_read > max_part_read)\n            max_part_read = part_read;\n      }\n      #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE\n      classify_mem = f->channels * (sizeof(void*) + max_part_read * sizeof(uint8 *));\n      #else\n      classify_mem = f->channels * (sizeof(void*) + max_part_read * sizeof(int *));\n      #endif\n\n      // maximum reasonable partition size is f->blocksize_1\n\n      f->temp_memory_required = classify_mem;\n      if (imdct_mem > f->temp_memory_required)\n         f->temp_memory_required = imdct_mem;\n   }\n\n   f->first_decode = TRUE;\n\n   if (f->alloc.alloc_buffer) {\n      assert(f->temp_offset == f->alloc.alloc_buffer_length_in_bytes);\n      // check if there's enough temp memory so we don't error later\n      if (f->setup_offset + sizeof(*f) + f->temp_memory_required > (unsigned) f->temp_offset)\n         return error(f, VORBIS_outofmem);\n   }\n\n   f->first_audio_page_offset = stb_vorbis_get_file_offset(f);\n\n   return TRUE;\n}\n\nstatic void vorbis_deinit(stb_vorbis *p)\n{\n   int i,j;\n   if (p->residue_config) {\n      for (i=0; i < p->residue_count; ++i) {\n         Residue *r = p->residue_config+i;\n         if (r->classdata) {\n            for (j=0; j < p->codebooks[r->classbook].entries; ++j)\n               setup_free(p, r->classdata[j]);\n            setup_free(p, r->classdata);\n         }\n         setup_free(p, r->residue_books);\n      }\n   }\n\n   if (p->codebooks) {\n      CHECK(p);\n      for (i=0; i < p->codebook_count; ++i) {\n         Codebook *c = p->codebooks + i;\n         setup_free(p, c->codeword_lengths);\n         setup_free(p, c->multiplicands);\n         setup_free(p, c->codewords);\n         setup_free(p, c->sorted_codewords);\n         // c->sorted_values[-1] is the first entry in the array\n         setup_free(p, c->sorted_values ? c->sorted_values-1 : NULL);\n      }\n      setup_free(p, p->codebooks);\n   }\n   setup_free(p, p->floor_config);\n   setup_free(p, p->residue_config);\n   if (p->mapping) {\n      for (i=0; i < p->mapping_count; ++i)\n         setup_free(p, p->mapping[i].chan);\n      setup_free(p, p->mapping);\n   }\n   CHECK(p);\n   for (i=0; i < p->channels && i < STB_VORBIS_MAX_CHANNELS; ++i) {\n      setup_free(p, p->channel_buffers[i]);\n      setup_free(p, p->previous_window[i]);\n      #ifdef STB_VORBIS_NO_DEFER_FLOOR\n      setup_free(p, p->floor_buffers[i]);\n      #endif\n      setup_free(p, p->finalY[i]);\n   }\n   for (i=0; i < 2; ++i) {\n      setup_free(p, p->A[i]);\n      setup_free(p, p->B[i]);\n      setup_free(p, p->C[i]);\n      setup_free(p, p->window[i]);\n      setup_free(p, p->bit_reverse[i]);\n   }\n   #ifndef STB_VORBIS_NO_STDIO\n   if (p->close_on_free) fclose(p->f);\n   #endif\n}\n\nvoid stb_vorbis_close(stb_vorbis *p)\n{\n   if (p == NULL) return;\n   vorbis_deinit(p);\n   setup_free(p,p);\n}\n\nstatic void vorbis_init(stb_vorbis *p, const stb_vorbis_alloc *z)\n{\n   memset(p, 0, sizeof(*p)); // NULL out all malloc'd pointers to start\n   if (z) {\n      p->alloc = *z;\n      p->alloc.alloc_buffer_length_in_bytes = (p->alloc.alloc_buffer_length_in_bytes+3) & ~3;\n      p->temp_offset = p->alloc.alloc_buffer_length_in_bytes;\n   }\n   p->eof = 0;\n   p->error = VORBIS__no_error;\n   p->stream = NULL;\n   p->codebooks = NULL;\n   p->page_crc_tests = -1;\n   #ifndef STB_VORBIS_NO_STDIO\n   p->close_on_free = FALSE;\n   p->f = NULL;\n   #endif\n}\n\nint stb_vorbis_get_sample_offset(stb_vorbis *f)\n{\n   if (f->current_loc_valid)\n      return f->current_loc;\n   else\n      return -1;\n}\n\nstb_vorbis_info stb_vorbis_get_info(stb_vorbis *f)\n{\n   stb_vorbis_info d;\n   d.channels = f->channels;\n   d.sample_rate = f->sample_rate;\n   d.setup_memory_required = f->setup_memory_required;\n   d.setup_temp_memory_required = f->setup_temp_memory_required;\n   d.temp_memory_required = f->temp_memory_required;\n   d.max_frame_size = f->blocksize_1 >> 1;\n   return d;\n}\n\nint stb_vorbis_get_error(stb_vorbis *f)\n{\n   int e = f->error;\n   f->error = VORBIS__no_error;\n   return e;\n}\n\nstatic stb_vorbis * vorbis_alloc(stb_vorbis *f)\n{\n   stb_vorbis *p = (stb_vorbis *) setup_malloc(f, sizeof(*p));\n   return p;\n}\n\n#ifndef STB_VORBIS_NO_PUSHDATA_API\n\nvoid stb_vorbis_flush_pushdata(stb_vorbis *f)\n{\n   f->previous_length = 0;\n   f->page_crc_tests  = 0;\n   f->discard_samples_deferred = 0;\n   f->current_loc_valid = FALSE;\n   f->first_decode = FALSE;\n   f->samples_output = 0;\n   f->channel_buffer_start = 0;\n   f->channel_buffer_end = 0;\n}\n\nstatic int vorbis_search_for_page_pushdata(vorb *f, uint8 *data, int data_len)\n{\n   int i,n;\n   for (i=0; i < f->page_crc_tests; ++i)\n      f->scan[i].bytes_done = 0;\n\n   // if we have room for more scans, search for them first, because\n   // they may cause us to stop early if their header is incomplete\n   if (f->page_crc_tests < STB_VORBIS_PUSHDATA_CRC_COUNT) {\n      if (data_len < 4) return 0;\n      data_len -= 3; // need to look for 4-byte sequence, so don't miss\n                     // one that straddles a boundary\n      for (i=0; i < data_len; ++i) {\n         if (data[i] == 0x4f) {\n            if (0==memcmp(data+i, ogg_page_header, 4)) {\n               int j,len;\n               uint32 crc;\n               // make sure we have the whole page header\n               if (i+26 >= data_len || i+27+data[i+26] >= data_len) {\n                  // only read up to this page start, so hopefully we'll\n                  // have the whole page header start next time\n                  data_len = i;\n                  break;\n               }\n               // ok, we have it all; compute the length of the page\n               len = 27 + data[i+26];\n               for (j=0; j < data[i+26]; ++j)\n                  len += data[i+27+j];\n               // scan everything up to the embedded crc (which we must 0)\n               crc = 0;\n               for (j=0; j < 22; ++j)\n                  crc = crc32_update(crc, data[i+j]);\n               // now process 4 0-bytes\n               for (   ; j < 26; ++j)\n                  crc = crc32_update(crc, 0);\n               // len is the total number of bytes we need to scan\n               n = f->page_crc_tests++;\n               f->scan[n].bytes_left = len-j;\n               f->scan[n].crc_so_far = crc;\n               f->scan[n].goal_crc = data[i+22] + (data[i+23] << 8) + (data[i+24]<<16) + (data[i+25]<<24);\n               // if the last frame on a page is continued to the next, then\n               // we can't recover the sample_loc immediately\n               if (data[i+27+data[i+26]-1] == 255)\n                  f->scan[n].sample_loc = ~0;\n               else\n                  f->scan[n].sample_loc = data[i+6] + (data[i+7] << 8) + (data[i+ 8]<<16) + (data[i+ 9]<<24);\n               f->scan[n].bytes_done = i+j;\n               if (f->page_crc_tests == STB_VORBIS_PUSHDATA_CRC_COUNT)\n                  break;\n               // keep going if we still have room for more\n            }\n         }\n      }\n   }\n\n   for (i=0; i < f->page_crc_tests;) {\n      uint32 crc;\n      int j;\n      int n = f->scan[i].bytes_done;\n      int m = f->scan[i].bytes_left;\n      if (m > data_len - n) m = data_len - n;\n      // m is the bytes to scan in the current chunk\n      crc = f->scan[i].crc_so_far;\n      for (j=0; j < m; ++j)\n         crc = crc32_update(crc, data[n+j]);\n      f->scan[i].bytes_left -= m;\n      f->scan[i].crc_so_far = crc;\n      if (f->scan[i].bytes_left == 0) {\n         // does it match?\n         if (f->scan[i].crc_so_far == f->scan[i].goal_crc) {\n            // Houston, we have page\n            data_len = n+m; // consumption amount is wherever that scan ended\n            f->page_crc_tests = -1; // drop out of page scan mode\n            f->previous_length = 0; // decode-but-don't-output one frame\n            f->next_seg = -1;       // start a new page\n            f->current_loc = f->scan[i].sample_loc; // set the current sample location\n                                    // to the amount we'd have decoded had we decoded this page\n            f->current_loc_valid = f->current_loc != ~0U;\n            return data_len;\n         }\n         // delete entry\n         f->scan[i] = f->scan[--f->page_crc_tests];\n      } else {\n         ++i;\n      }\n   }\n\n   return data_len;\n}\n\n// return value: number of bytes we used\nint stb_vorbis_decode_frame_pushdata(\n         stb_vorbis *f,                   // the file we're decoding\n         const uint8 *data, int data_len, // the memory available for decoding\n         int *channels,                   // place to write number of float * buffers\n         float ***output,                 // place to write float ** array of float * buffers\n         int *samples                     // place to write number of output samples\n     )\n{\n   int i;\n   int len,right,left;\n\n   if (!IS_PUSH_MODE(f)) return error(f, VORBIS_invalid_api_mixing);\n\n   if (f->page_crc_tests >= 0) {\n      *samples = 0;\n      return vorbis_search_for_page_pushdata(f, (uint8 *) data, data_len);\n   }\n\n   f->stream     = (uint8 *) data;\n   f->stream_end = (uint8 *) data + data_len;\n   f->error      = VORBIS__no_error;\n\n   // check that we have the entire packet in memory\n   if (!is_whole_packet_present(f, FALSE)) {\n      *samples = 0;\n      return 0;\n   }\n\n   if (!vorbis_decode_packet(f, &len, &left, &right)) {\n      // save the actual error we encountered\n      enum STBVorbisError error = f->error;\n      if (error == VORBIS_bad_packet_type) {\n         // flush and resynch\n         f->error = VORBIS__no_error;\n         while (get8_packet(f) != EOP)\n            if (f->eof) break;\n         *samples = 0;\n         return (int) (f->stream - data);\n      }\n      if (error == VORBIS_continued_packet_flag_invalid) {\n         if (f->previous_length == 0) {\n            // we may be resynching, in which case it's ok to hit one\n            // of these; just discard the packet\n            f->error = VORBIS__no_error;\n            while (get8_packet(f) != EOP)\n               if (f->eof) break;\n            *samples = 0;\n            return (int) (f->stream - data);\n         }\n      }\n      // if we get an error while parsing, what to do?\n      // well, it DEFINITELY won't work to continue from where we are!\n      stb_vorbis_flush_pushdata(f);\n      // restore the error that actually made us bail\n      f->error = error;\n      *samples = 0;\n      return 1;\n   }\n\n   // success!\n   len = vorbis_finish_frame(f, len, left, right);\n   for (i=0; i < f->channels; ++i)\n      f->outputs[i] = f->channel_buffers[i] + left;\n\n   if (channels) *channels = f->channels;\n   *samples = len;\n   *output = f->outputs;\n   return (int) (f->stream - data);\n}\n\nstb_vorbis *stb_vorbis_open_pushdata(\n         const unsigned char *data, int data_len, // the memory available for decoding\n         int *data_used,              // only defined if result is not NULL\n         int *error, const stb_vorbis_alloc *alloc)\n{\n   stb_vorbis *f, p;\n   vorbis_init(&p, alloc);\n   p.stream     = (uint8 *) data;\n   p.stream_end = (uint8 *) data + data_len;\n   p.push_mode  = TRUE;\n   if (!start_decoder(&p)) {\n      if (p.eof)\n         *error = VORBIS_need_more_data;\n      else\n         *error = p.error;\n      return NULL;\n   }\n   f = vorbis_alloc(&p);\n   if (f) {\n      *f = p;\n      *data_used = (int) (f->stream - data);\n      *error = 0;\n      return f;\n   } else {\n      vorbis_deinit(&p);\n      return NULL;\n   }\n}\n#endif // STB_VORBIS_NO_PUSHDATA_API\n\nunsigned int stb_vorbis_get_file_offset(stb_vorbis *f)\n{\n   #ifndef STB_VORBIS_NO_PUSHDATA_API\n   if (f->push_mode) return 0;\n   #endif\n   if (USE_MEMORY(f)) return (unsigned int) (f->stream - f->stream_start);\n   #ifndef STB_VORBIS_NO_STDIO\n   return (unsigned int) (ftell(f->f) - f->f_start);\n   #endif\n}\n\n#ifndef STB_VORBIS_NO_PULLDATA_API\n//\n// DATA-PULLING API\n//\n\nstatic uint32 vorbis_find_page(stb_vorbis *f, uint32 *end, uint32 *last)\n{\n   for(;;) {\n      int n;\n      if (f->eof) return 0;\n      n = get8(f);\n      if (n == 0x4f) { // page header candidate\n         unsigned int retry_loc = stb_vorbis_get_file_offset(f);\n         int i;\n         // check if we're off the end of a file_section stream\n         if (retry_loc - 25 > f->stream_len)\n            return 0;\n         // check the rest of the header\n         for (i=1; i < 4; ++i)\n            if (get8(f) != ogg_page_header[i])\n               break;\n         if (f->eof) return 0;\n         if (i == 4) {\n            uint8 header[27];\n            uint32 i, crc, goal, len;\n            for (i=0; i < 4; ++i)\n               header[i] = ogg_page_header[i];\n            for (; i < 27; ++i)\n               header[i] = get8(f);\n            if (f->eof) return 0;\n            if (header[4] != 0) goto invalid;\n            goal = header[22] + (header[23] << 8) + (header[24]<<16) + (header[25]<<24);\n            for (i=22; i < 26; ++i)\n               header[i] = 0;\n            crc = 0;\n            for (i=0; i < 27; ++i)\n               crc = crc32_update(crc, header[i]);\n            len = 0;\n            for (i=0; i < header[26]; ++i) {\n               int s = get8(f);\n               crc = crc32_update(crc, s);\n               len += s;\n            }\n            if (len && f->eof) return 0;\n            for (i=0; i < len; ++i)\n               crc = crc32_update(crc, get8(f));\n            // finished parsing probable page\n            if (crc == goal) {\n               // we could now check that it's either got the last\n               // page flag set, OR it's followed by the capture\n               // pattern, but I guess TECHNICALLY you could have\n               // a file with garbage between each ogg page and recover\n               // from it automatically? So even though that paranoia\n               // might decrease the chance of an invalid decode by\n               // another 2^32, not worth it since it would hose those\n               // invalid-but-useful files?\n               if (end)\n                  *end = stb_vorbis_get_file_offset(f);\n               if (last) {\n                  if (header[5] & 0x04)\n                     *last = 1;\n                  else\n                     *last = 0;\n               }\n               set_file_offset(f, retry_loc-1);\n               return 1;\n            }\n         }\n        invalid:\n         // not a valid page, so rewind and look for next one\n         set_file_offset(f, retry_loc);\n      }\n   }\n}\n\n\n#define SAMPLE_unknown  0xffffffff\n\n// seeking is implemented with a binary search, which narrows down the range to\n// 64K, before using a linear search (because finding the synchronization\n// pattern can be expensive, and the chance we'd find the end page again is\n// relatively high for small ranges)\n//\n// two initial interpolation-style probes are used at the start of the search\n// to try to bound either side of the binary search sensibly, while still\n// working in O(log n) time if they fail.\n\nstatic int get_seek_page_info(stb_vorbis *f, ProbedPage *z)\n{\n   uint8 header[27], lacing[255];\n   int i,len;\n\n   // record where the page starts\n   z->page_start = stb_vorbis_get_file_offset(f);\n\n   // parse the header\n   getn(f, header, 27);\n   if (header[0] != 'O' || header[1] != 'g' || header[2] != 'g' || header[3] != 'S')\n      return 0;\n   getn(f, lacing, header[26]);\n\n   // determine the length of the payload\n   len = 0;\n   for (i=0; i < header[26]; ++i)\n      len += lacing[i];\n\n   // this implies where the page ends\n   z->page_end = z->page_start + 27 + header[26] + len;\n\n   // read the last-decoded sample out of the data\n   z->last_decoded_sample = header[6] + (header[7] << 8) + (header[8] << 16) + (header[9] << 24);\n\n   // restore file state to where we were\n   set_file_offset(f, z->page_start);\n   return 1;\n}\n\n// rarely used function to seek back to the preceding page while finding the\n// start of a packet\nstatic int go_to_page_before(stb_vorbis *f, unsigned int limit_offset)\n{\n   unsigned int previous_safe, end;\n\n   // now we want to seek back 64K from the limit\n   if (limit_offset >= 65536 && limit_offset-65536 >= f->first_audio_page_offset)\n      previous_safe = limit_offset - 65536;\n   else\n      previous_safe = f->first_audio_page_offset;\n\n   set_file_offset(f, previous_safe);\n\n   while (vorbis_find_page(f, &end, NULL)) {\n      if (end >= limit_offset && stb_vorbis_get_file_offset(f) < limit_offset)\n         return 1;\n      set_file_offset(f, end);\n   }\n\n   return 0;\n}\n\n// implements the search logic for finding a page and starting decoding. if\n// the function succeeds, current_loc_valid will be true and current_loc will\n// be less than or equal to the provided sample number (the closer the\n// better).\nstatic int seek_to_sample_coarse(stb_vorbis *f, uint32 sample_number)\n{\n   ProbedPage left, right, mid;\n   int i, start_seg_with_known_loc, end_pos, page_start;\n   uint32 delta, stream_length, padding;\n   double offset, bytes_per_sample;\n   int probe = 0;\n\n   // find the last page and validate the target sample\n   stream_length = stb_vorbis_stream_length_in_samples(f);\n   if (stream_length == 0)            return error(f, VORBIS_seek_without_length);\n   if (sample_number > stream_length) return error(f, VORBIS_seek_invalid);\n\n   // this is the maximum difference between the window-center (which is the\n   // actual granule position value), and the right-start (which the spec\n   // indicates should be the granule position (give or take one)).\n   padding = ((f->blocksize_1 - f->blocksize_0) >> 2);\n   if (sample_number < padding)\n      sample_number = 0;\n   else\n      sample_number -= padding;\n\n   left = f->p_first;\n   while (left.last_decoded_sample == ~0U) {\n      // (untested) the first page does not have a 'last_decoded_sample'\n      set_file_offset(f, left.page_end);\n      if (!get_seek_page_info(f, &left)) goto error;\n   }\n\n   right = f->p_last;\n   assert(right.last_decoded_sample != ~0U);\n\n   // starting from the start is handled differently\n   if (sample_number <= left.last_decoded_sample) {\n      if (stb_vorbis_seek_start(f))\n         return 1;\n      return 0;\n   }\n\n   while (left.page_end != right.page_start) {\n      assert(left.page_end < right.page_start);\n      // search range in bytes\n      delta = right.page_start - left.page_end;\n      if (delta <= 65536) {\n         // there's only 64K left to search - handle it linearly\n         set_file_offset(f, left.page_end);\n      } else {\n         if (probe < 2) {\n            if (probe == 0) {\n               // first probe (interpolate)\n               double data_bytes = right.page_end - left.page_start;\n               bytes_per_sample = data_bytes / right.last_decoded_sample;\n               offset = left.page_start + bytes_per_sample * (sample_number - left.last_decoded_sample);\n            } else {\n               // second probe (try to bound the other side)\n               double error = ((double) sample_number - mid.last_decoded_sample) * bytes_per_sample;\n               if (error >= 0 && error <  8000) error =  8000;\n               if (error <  0 && error > -8000) error = -8000;\n               offset += error * 2;\n            }\n\n            // ensure the offset is valid\n            if (offset < left.page_end)\n               offset = left.page_end;\n            if (offset > right.page_start - 65536)\n               offset = right.page_start - 65536;\n\n            set_file_offset(f, (unsigned int) offset);\n         } else {\n            // binary search for large ranges (offset by 32K to ensure\n            // we don't hit the right page)\n            set_file_offset(f, left.page_end + (delta / 2) - 32768);\n         }\n\n         if (!vorbis_find_page(f, NULL, NULL)) goto error;\n      }\n\n      for (;;) {\n         if (!get_seek_page_info(f, &mid)) goto error;\n         if (mid.last_decoded_sample != ~0U) break;\n         // (untested) no frames end on this page\n         set_file_offset(f, mid.page_end);\n         assert(mid.page_start < right.page_start);\n      }\n\n      // if we've just found the last page again then we're in a tricky file,\n      // and we're close enough.\n      if (mid.page_start == right.page_start)\n         break;\n\n      if (sample_number < mid.last_decoded_sample)\n         right = mid;\n      else\n         left = mid;\n\n      ++probe;\n   }\n\n   // seek back to start of the last packet\n   page_start = left.page_start;\n   set_file_offset(f, page_start);\n   if (!start_page(f)) return error(f, VORBIS_seek_failed);\n   end_pos = f->end_seg_with_known_loc;\n   assert(end_pos >= 0);\n\n   for (;;) {\n      for (i = end_pos; i > 0; --i)\n         if (f->segments[i-1] != 255)\n            break;\n\n      start_seg_with_known_loc = i;\n\n      if (start_seg_with_known_loc > 0 || !(f->page_flag & PAGEFLAG_continued_packet))\n         break;\n\n      // (untested) the final packet begins on an earlier page\n      if (!go_to_page_before(f, page_start))\n         goto error;\n\n      page_start = stb_vorbis_get_file_offset(f);\n      if (!start_page(f)) goto error;\n      end_pos = f->segment_count - 1;\n   }\n\n   // prepare to start decoding\n   f->current_loc_valid = FALSE;\n   f->last_seg = FALSE;\n   f->valid_bits = 0;\n   f->packet_bytes = 0;\n   f->bytes_in_seg = 0;\n   f->previous_length = 0;\n   f->next_seg = start_seg_with_known_loc;\n\n   for (i = 0; i < start_seg_with_known_loc; i++)\n      skip(f, f->segments[i]);\n\n   // start decoding (optimizable - this frame is generally discarded)\n   if (!vorbis_pump_first_frame(f))\n      return 0;\n   if (f->current_loc > sample_number)\n      return error(f, VORBIS_seek_failed);\n   return 1;\n\nerror:\n   // try to restore the file to a valid state\n   stb_vorbis_seek_start(f);\n   return error(f, VORBIS_seek_failed);\n}\n\n// the same as vorbis_decode_initial, but without advancing\nstatic int peek_decode_initial(vorb *f, int *p_left_start, int *p_left_end, int *p_right_start, int *p_right_end, int *mode)\n{\n   int bits_read, bytes_read;\n\n   if (!vorbis_decode_initial(f, p_left_start, p_left_end, p_right_start, p_right_end, mode))\n      return 0;\n\n   // either 1 or 2 bytes were read, figure out which so we can rewind\n   bits_read = 1 + ilog(f->mode_count-1);\n   if (f->mode_config[*mode].blockflag)\n      bits_read += 2;\n   bytes_read = (bits_read + 7) / 8;\n\n   f->bytes_in_seg += bytes_read;\n   f->packet_bytes -= bytes_read;\n   skip(f, -bytes_read);\n   if (f->next_seg == -1)\n      f->next_seg = f->segment_count - 1;\n   else\n      f->next_seg--;\n   f->valid_bits = 0;\n\n   return 1;\n}\n\nint stb_vorbis_seek_frame(stb_vorbis *f, unsigned int sample_number)\n{\n   uint32 max_frame_samples;\n\n   if (IS_PUSH_MODE(f)) return error(f, VORBIS_invalid_api_mixing);\n\n   // fast page-level search\n   if (!seek_to_sample_coarse(f, sample_number))\n      return 0;\n\n   assert(f->current_loc_valid);\n   assert(f->current_loc <= sample_number);\n\n   // linear search for the relevant packet\n   max_frame_samples = (f->blocksize_1*3 - f->blocksize_0) >> 2;\n   while (f->current_loc < sample_number) {\n      int left_start, left_end, right_start, right_end, mode, frame_samples;\n      if (!peek_decode_initial(f, &left_start, &left_end, &right_start, &right_end, &mode))\n         return error(f, VORBIS_seek_failed);\n      // calculate the number of samples returned by the next frame\n      frame_samples = right_start - left_start;\n      if (f->current_loc + frame_samples > sample_number) {\n         return 1; // the next frame will contain the sample\n      } else if (f->current_loc + frame_samples + max_frame_samples > sample_number) {\n         // there's a chance the frame after this could contain the sample\n         vorbis_pump_first_frame(f);\n      } else {\n         // this frame is too early to be relevant\n         f->current_loc += frame_samples;\n         f->previous_length = 0;\n         maybe_start_packet(f);\n         flush_packet(f);\n      }\n   }\n   // the next frame will start with the sample\n   assert(f->current_loc == sample_number);\n   return 1;\n}\n\nint stb_vorbis_seek(stb_vorbis *f, unsigned int sample_number)\n{\n   if (!stb_vorbis_seek_frame(f, sample_number))\n      return 0;\n\n   if (sample_number != f->current_loc) {\n      int n;\n      uint32 frame_start = f->current_loc;\n      stb_vorbis_get_frame_float(f, &n, NULL);\n      assert(sample_number > frame_start);\n      assert(f->channel_buffer_start + (int) (sample_number-frame_start) <= f->channel_buffer_end);\n      f->channel_buffer_start += (sample_number - frame_start);\n   }\n\n   return 1;\n}\n\nint stb_vorbis_seek_start(stb_vorbis *f)\n{\n   if (IS_PUSH_MODE(f)) { return error(f, VORBIS_invalid_api_mixing); }\n   set_file_offset(f, f->first_audio_page_offset);\n   f->previous_length = 0;\n   f->first_decode = TRUE;\n   f->next_seg = -1;\n   return vorbis_pump_first_frame(f);\n}\n\nunsigned int stb_vorbis_stream_length_in_samples(stb_vorbis *f)\n{\n   unsigned int restore_offset, previous_safe;\n   unsigned int end, last_page_loc;\n\n   if (IS_PUSH_MODE(f)) return error(f, VORBIS_invalid_api_mixing);\n   if (!f->total_samples) {\n      unsigned int last;\n      uint32 lo,hi;\n      char header[6];\n\n      // first, store the current decode position so we can restore it\n      restore_offset = stb_vorbis_get_file_offset(f);\n\n      // now we want to seek back 64K from the end (the last page must\n      // be at most a little less than 64K, but let's allow a little slop)\n      if (f->stream_len >= 65536 && f->stream_len-65536 >= f->first_audio_page_offset)\n         previous_safe = f->stream_len - 65536;\n      else\n         previous_safe = f->first_audio_page_offset;\n\n      set_file_offset(f, previous_safe);\n      // previous_safe is now our candidate 'earliest known place that seeking\n      // to will lead to the final page'\n\n      if (!vorbis_find_page(f, &end, &last)) {\n         // if we can't find a page, we're hosed!\n         f->error = VORBIS_cant_find_last_page;\n         f->total_samples = 0xffffffff;\n         goto done;\n      }\n\n      // check if there are more pages\n      last_page_loc = stb_vorbis_get_file_offset(f);\n\n      // stop when the last_page flag is set, not when we reach eof;\n      // this allows us to stop short of a 'file_section' end without\n      // explicitly checking the length of the section\n      while (!last) {\n         set_file_offset(f, end);\n         if (!vorbis_find_page(f, &end, &last)) {\n            // the last page we found didn't have the 'last page' flag\n            // set. whoops!\n            break;\n         }\n         previous_safe = last_page_loc+1;\n         last_page_loc = stb_vorbis_get_file_offset(f);\n      }\n\n      set_file_offset(f, last_page_loc);\n\n      // parse the header\n      getn(f, (unsigned char *)header, 6);\n      // extract the absolute granule position\n      lo = get32(f);\n      hi = get32(f);\n      if (lo == 0xffffffff && hi == 0xffffffff) {\n         f->error = VORBIS_cant_find_last_page;\n         f->total_samples = SAMPLE_unknown;\n         goto done;\n      }\n      if (hi)\n         lo = 0xfffffffe; // saturate\n      f->total_samples = lo;\n\n      f->p_last.page_start = last_page_loc;\n      f->p_last.page_end   = end;\n      f->p_last.last_decoded_sample = lo;\n\n     done:\n      set_file_offset(f, restore_offset);\n   }\n   return f->total_samples == SAMPLE_unknown ? 0 : f->total_samples;\n}\n\nfloat stb_vorbis_stream_length_in_seconds(stb_vorbis *f)\n{\n   return stb_vorbis_stream_length_in_samples(f) / (float) f->sample_rate;\n}\n\n\n\nint stb_vorbis_get_frame_float(stb_vorbis *f, int *channels, float ***output)\n{\n   int len, right,left,i;\n   if (IS_PUSH_MODE(f)) return error(f, VORBIS_invalid_api_mixing);\n\n   if (!vorbis_decode_packet(f, &len, &left, &right)) {\n      f->channel_buffer_start = f->channel_buffer_end = 0;\n      return 0;\n   }\n\n   len = vorbis_finish_frame(f, len, left, right);\n   for (i=0; i < f->channels; ++i)\n      f->outputs[i] = f->channel_buffers[i] + left;\n\n   f->channel_buffer_start = left;\n   f->channel_buffer_end   = left+len;\n\n   if (channels) *channels = f->channels;\n   if (output)   *output = f->outputs;\n   return len;\n}\n\n#ifndef STB_VORBIS_NO_STDIO\n\nstb_vorbis * stb_vorbis_open_file_section(FILE *file, int close_on_free, int *error, const stb_vorbis_alloc *alloc, unsigned int length)\n{\n   stb_vorbis *f, p;\n   vorbis_init(&p, alloc);\n   p.f = file;\n   p.f_start = (uint32) ftell(file);\n   p.stream_len   = length;\n   p.close_on_free = close_on_free;\n   if (start_decoder(&p)) {\n      f = vorbis_alloc(&p);\n      if (f) {\n         *f = p;\n         vorbis_pump_first_frame(f);\n         return f;\n      }\n   }\n   if (error) *error = p.error;\n   vorbis_deinit(&p);\n   return NULL;\n}\n\nstb_vorbis * stb_vorbis_open_file(FILE *file, int close_on_free, int *error, const stb_vorbis_alloc *alloc)\n{\n   unsigned int len, start;\n   start = (unsigned int) ftell(file);\n   fseek(file, 0, SEEK_END);\n   len = (unsigned int) (ftell(file) - start);\n   fseek(file, start, SEEK_SET);\n   return stb_vorbis_open_file_section(file, close_on_free, error, alloc, len);\n}\n\nstb_vorbis * stb_vorbis_open_filename(const char *filename, int *error, const stb_vorbis_alloc *alloc)\n{\n   FILE *f;\n#if defined(_WIN32) && defined(__STDC_WANT_SECURE_LIB__)\n   if (0 != fopen_s(&f, filename, \"rb\"))\n      f = NULL;\n#else\n   f = fopen(filename, \"rb\");\n#endif\n   if (f) \n      return stb_vorbis_open_file(f, TRUE, error, alloc);\n   if (error) *error = VORBIS_file_open_failure;\n   return NULL;\n}\n#endif // STB_VORBIS_NO_STDIO\n\nstb_vorbis * stb_vorbis_open_memory(const unsigned char *data, int len, int *error, const stb_vorbis_alloc *alloc)\n{\n   stb_vorbis *f, p;\n   if (data == NULL) return NULL;\n   vorbis_init(&p, alloc);\n   p.stream = (uint8 *) data;\n   p.stream_end = (uint8 *) data + len;\n   p.stream_start = (uint8 *) p.stream;\n   p.stream_len = len;\n   p.push_mode = FALSE;\n   if (start_decoder(&p)) {\n      f = vorbis_alloc(&p);\n      if (f) {\n         *f = p;\n         vorbis_pump_first_frame(f);\n         if (error) *error = VORBIS__no_error;\n         return f;\n      }\n   }\n   if (error) *error = p.error;\n   vorbis_deinit(&p);\n   return NULL;\n}\n\n#ifndef STB_VORBIS_NO_INTEGER_CONVERSION\n#define PLAYBACK_MONO     1\n#define PLAYBACK_LEFT     2\n#define PLAYBACK_RIGHT    4\n\n#define L  (PLAYBACK_LEFT  | PLAYBACK_MONO)\n#define C  (PLAYBACK_LEFT  | PLAYBACK_RIGHT | PLAYBACK_MONO)\n#define R  (PLAYBACK_RIGHT | PLAYBACK_MONO)\n\nstatic int8 channel_position[7][6] =\n{\n   { 0 },\n   { C },\n   { L, R },\n   { L, C, R },\n   { L, R, L, R },\n   { L, C, R, L, R },\n   { L, C, R, L, R, C },\n};\n\n\n#ifndef STB_VORBIS_NO_FAST_SCALED_FLOAT\n   typedef union {\n      float f;\n      int i;\n   } float_conv;\n   typedef char stb_vorbis_float_size_test[sizeof(float)==4 && sizeof(int) == 4];\n   #define FASTDEF(x) float_conv x\n   // add (1<<23) to convert to int, then divide by 2^SHIFT, then add 0.5/2^SHIFT to round\n   #define MAGIC(SHIFT) (1.5f * (1 << (23-SHIFT)) + 0.5f/(1 << SHIFT))\n   #define ADDEND(SHIFT) (((150-SHIFT) << 23) + (1 << 22))\n   #define FAST_SCALED_FLOAT_TO_INT(temp,x,s) (temp.f = (x) + MAGIC(s), temp.i - ADDEND(s))\n   #define check_endianness()  \n#else\n   #define FAST_SCALED_FLOAT_TO_INT(temp,x,s) ((int) ((x) * (1 << (s))))\n   #define check_endianness()\n   #define FASTDEF(x)\n#endif\n\nstatic void copy_samples(short *dest, float *src, int len)\n{\n   int i;\n   check_endianness();\n   for (i=0; i < len; ++i) {\n      FASTDEF(temp);\n      int v = FAST_SCALED_FLOAT_TO_INT(temp, src[i],15);\n      if ((unsigned int) (v + 32768) > 65535)\n         v = v < 0 ? -32768 : 32767;\n      dest[i] = v;\n   }\n}\n\nstatic void compute_samples(int mask, short *output, int num_c, float **data, int d_offset, int len)\n{\n   #define BUFFER_SIZE  32\n   float buffer[BUFFER_SIZE];\n   int i,j,o,n = BUFFER_SIZE;\n   check_endianness();\n   for (o = 0; o < len; o += BUFFER_SIZE) {\n      memset(buffer, 0, sizeof(buffer));\n      if (o + n > len) n = len - o;\n      for (j=0; j < num_c; ++j) {\n         if (channel_position[num_c][j] & mask) {\n            for (i=0; i < n; ++i)\n               buffer[i] += data[j][d_offset+o+i];\n         }\n      }\n      for (i=0; i < n; ++i) {\n         FASTDEF(temp);\n         int v = FAST_SCALED_FLOAT_TO_INT(temp,buffer[i],15);\n         if ((unsigned int) (v + 32768) > 65535)\n            v = v < 0 ? -32768 : 32767;\n         output[o+i] = v;\n      }\n   }\n}\n\nstatic void compute_stereo_samples(short *output, int num_c, float **data, int d_offset, int len)\n{\n   #define BUFFER_SIZE  32\n   float buffer[BUFFER_SIZE];\n   int i,j,o,n = BUFFER_SIZE >> 1;\n   // o is the offset in the source data\n   check_endianness();\n   for (o = 0; o < len; o += BUFFER_SIZE >> 1) {\n      // o2 is the offset in the output data\n      int o2 = o << 1;\n      memset(buffer, 0, sizeof(buffer));\n      if (o + n > len) n = len - o;\n      for (j=0; j < num_c; ++j) {\n         int m = channel_position[num_c][j] & (PLAYBACK_LEFT | PLAYBACK_RIGHT);\n         if (m == (PLAYBACK_LEFT | PLAYBACK_RIGHT)) {\n            for (i=0; i < n; ++i) {\n               buffer[i*2+0] += data[j][d_offset+o+i];\n               buffer[i*2+1] += data[j][d_offset+o+i];\n            }\n         } else if (m == PLAYBACK_LEFT) {\n            for (i=0; i < n; ++i) {\n               buffer[i*2+0] += data[j][d_offset+o+i];\n            }\n         } else if (m == PLAYBACK_RIGHT) {\n            for (i=0; i < n; ++i) {\n               buffer[i*2+1] += data[j][d_offset+o+i];\n            }\n         }\n      }\n      for (i=0; i < (n<<1); ++i) {\n         FASTDEF(temp);\n         int v = FAST_SCALED_FLOAT_TO_INT(temp,buffer[i],15);\n         if ((unsigned int) (v + 32768) > 65535)\n            v = v < 0 ? -32768 : 32767;\n         output[o2+i] = v;\n      }\n   }\n}\n\nstatic void convert_samples_short(int buf_c, short **buffer, int b_offset, int data_c, float **data, int d_offset, int samples)\n{\n   int i;\n   if (buf_c != data_c && buf_c <= 2 && data_c <= 6) {\n      static int channel_selector[3][2] = { {0}, {PLAYBACK_MONO}, {PLAYBACK_LEFT, PLAYBACK_RIGHT} };\n      for (i=0; i < buf_c; ++i)\n         compute_samples(channel_selector[buf_c][i], buffer[i]+b_offset, data_c, data, d_offset, samples);\n   } else {\n      int limit = buf_c < data_c ? buf_c : data_c;\n      for (i=0; i < limit; ++i)\n         copy_samples(buffer[i]+b_offset, data[i]+d_offset, samples);\n      for (   ; i < buf_c; ++i)\n         memset(buffer[i]+b_offset, 0, sizeof(short) * samples);\n   }\n}\n\nint stb_vorbis_get_frame_short(stb_vorbis *f, int num_c, short **buffer, int num_samples)\n{\n   float **output;\n   int len = stb_vorbis_get_frame_float(f, NULL, &output);\n   if (len > num_samples) len = num_samples;\n   if (len)\n      convert_samples_short(num_c, buffer, 0, f->channels, output, 0, len);\n   return len;\n}\n\nstatic void convert_channels_short_interleaved(int buf_c, short *buffer, int data_c, float **data, int d_offset, int len)\n{\n   int i;\n   check_endianness();\n   if (buf_c != data_c && buf_c <= 2 && data_c <= 6) {\n      assert(buf_c == 2);\n      for (i=0; i < buf_c; ++i)\n         compute_stereo_samples(buffer, data_c, data, d_offset, len);\n   } else {\n      int limit = buf_c < data_c ? buf_c : data_c;\n      int j;\n      for (j=0; j < len; ++j) {\n         for (i=0; i < limit; ++i) {\n            FASTDEF(temp);\n            float f = data[i][d_offset+j];\n            int v = FAST_SCALED_FLOAT_TO_INT(temp, f,15);//data[i][d_offset+j],15);\n            if ((unsigned int) (v + 32768) > 65535)\n               v = v < 0 ? -32768 : 32767;\n            *buffer++ = v;\n         }\n         for (   ; i < buf_c; ++i)\n            *buffer++ = 0;\n      }\n   }\n}\n\nint stb_vorbis_get_frame_short_interleaved(stb_vorbis *f, int num_c, short *buffer, int num_shorts)\n{\n   float **output;\n   int len;\n   if (num_c == 1) return stb_vorbis_get_frame_short(f,num_c,&buffer, num_shorts);\n   len = stb_vorbis_get_frame_float(f, NULL, &output);\n   if (len) {\n      if (len*num_c > num_shorts) len = num_shorts / num_c;\n      convert_channels_short_interleaved(num_c, buffer, f->channels, output, 0, len);\n   }\n   return len;\n}\n\nint stb_vorbis_get_samples_short_interleaved(stb_vorbis *f, int channels, short *buffer, int num_shorts)\n{\n   float **outputs;\n   int len = num_shorts / channels;\n   int n=0;\n   int z = f->channels;\n   if (z > channels) z = channels;\n   while (n < len) {\n      int k = f->channel_buffer_end - f->channel_buffer_start;\n      if (n+k >= len) k = len - n;\n      if (k)\n         convert_channels_short_interleaved(channels, buffer, f->channels, f->channel_buffers, f->channel_buffer_start, k);\n      buffer += k*channels;\n      n += k;\n      f->channel_buffer_start += k;\n      if (n == len) break;\n      if (!stb_vorbis_get_frame_float(f, NULL, &outputs)) break;\n   }\n   return n;\n}\n\nint stb_vorbis_get_samples_short(stb_vorbis *f, int channels, short **buffer, int len)\n{\n   float **outputs;\n   int n=0;\n   int z = f->channels;\n   if (z > channels) z = channels;\n   while (n < len) {\n      int k = f->channel_buffer_end - f->channel_buffer_start;\n      if (n+k >= len) k = len - n;\n      if (k)\n         convert_samples_short(channels, buffer, n, f->channels, f->channel_buffers, f->channel_buffer_start, k);\n      n += k;\n      f->channel_buffer_start += k;\n      if (n == len) break;\n      if (!stb_vorbis_get_frame_float(f, NULL, &outputs)) break;\n   }\n   return n;\n}\n\n#ifndef STB_VORBIS_NO_STDIO\nint stb_vorbis_decode_filename(const char *filename, int *channels, int *sample_rate, short **output)\n{\n   int data_len, offset, total, limit, error;\n   short *data;\n   stb_vorbis *v = stb_vorbis_open_filename(filename, &error, NULL);\n   if (v == NULL) return -1;\n   limit = v->channels * 4096;\n   *channels = v->channels;\n   if (sample_rate)\n      *sample_rate = v->sample_rate;\n   offset = data_len = 0;\n   total = limit;\n   data = (short *) malloc(total * sizeof(*data));\n   if (data == NULL) {\n      stb_vorbis_close(v);\n      return -2;\n   }\n   for (;;) {\n      int n = stb_vorbis_get_frame_short_interleaved(v, v->channels, data+offset, total-offset);\n      if (n == 0) break;\n      data_len += n;\n      offset += n * v->channels;\n      if (offset + limit > total) {\n         short *data2;\n         total *= 2;\n         data2 = (short *) realloc(data, total * sizeof(*data));\n         if (data2 == NULL) {\n            free(data);\n            stb_vorbis_close(v);\n            return -2;\n         }\n         data = data2;\n      }\n   }\n   *output = data;\n   stb_vorbis_close(v);\n   return data_len;\n}\n#endif // NO_STDIO\n\nint stb_vorbis_decode_memory(const uint8 *mem, int len, int *channels, int *sample_rate, short **output)\n{\n   int data_len, offset, total, limit, error;\n   short *data;\n   stb_vorbis *v = stb_vorbis_open_memory(mem, len, &error, NULL);\n   if (v == NULL) return -1;\n   limit = v->channels * 4096;\n   *channels = v->channels;\n   if (sample_rate)\n      *sample_rate = v->sample_rate;\n   offset = data_len = 0;\n   total = limit;\n   data = (short *) malloc(total * sizeof(*data));\n   if (data == NULL) {\n      stb_vorbis_close(v);\n      return -2;\n   }\n   for (;;) {\n      int n = stb_vorbis_get_frame_short_interleaved(v, v->channels, data+offset, total-offset);\n      if (n == 0) break;\n      data_len += n;\n      offset += n * v->channels;\n      if (offset + limit > total) {\n         short *data2;\n         total *= 2;\n         data2 = (short *) realloc(data, total * sizeof(*data));\n         if (data2 == NULL) {\n            free(data);\n            stb_vorbis_close(v);\n            return -2;\n         }\n         data = data2;\n      }\n   }\n   *output = data;\n   stb_vorbis_close(v);\n   return data_len;\n}\n#endif // STB_VORBIS_NO_INTEGER_CONVERSION\n\nint stb_vorbis_get_samples_float_interleaved(stb_vorbis *f, int channels, float *buffer, int num_floats)\n{\n   float **outputs;\n   int len = num_floats / channels;\n   int n=0;\n   int z = f->channels;\n   if (z > channels) z = channels;\n   while (n < len) {\n      int i,j;\n      int k = f->channel_buffer_end - f->channel_buffer_start;\n      if (n+k >= len) k = len - n;\n      for (j=0; j < k; ++j) {\n         for (i=0; i < z; ++i)\n            *buffer++ = f->channel_buffers[i][f->channel_buffer_start+j];\n         for (   ; i < channels; ++i)\n            *buffer++ = 0;\n      }\n      n += k;\n      f->channel_buffer_start += k;\n      if (n == len)\n         break;\n      if (!stb_vorbis_get_frame_float(f, NULL, &outputs))\n         break;\n   }\n   return n;\n}\n\nint stb_vorbis_get_samples_float(stb_vorbis *f, int channels, float **buffer, int num_samples)\n{\n   float **outputs;\n   int n=0;\n   int z = f->channels;\n   if (z > channels) z = channels;\n   while (n < num_samples) {\n      int i;\n      int k = f->channel_buffer_end - f->channel_buffer_start;\n      if (n+k >= num_samples) k = num_samples - n;\n      if (k) {\n         for (i=0; i < z; ++i)\n            memcpy(buffer[i]+n, f->channel_buffers[i]+f->channel_buffer_start, sizeof(float)*k);\n         for (   ; i < channels; ++i)\n            memset(buffer[i]+n, 0, sizeof(float) * k);\n      }\n      n += k;\n      f->channel_buffer_start += k;\n      if (n == num_samples)\n         break;\n      if (!stb_vorbis_get_frame_float(f, NULL, &outputs))\n         break;\n   }\n   return n;\n}\n#endif // STB_VORBIS_NO_PULLDATA_API\n\n/* Version history\n    1.12    - 2017-11-21 - limit residue begin/end to blocksize/2 to avoid large temp allocs in bad/corrupt files\n    1.11    - 2017-07-23 - fix MinGW compilation \n    1.10    - 2017-03-03 - more robust seeking; fix negative ilog(); clear error in open_memory\n    1.09    - 2016-04-04 - back out 'avoid discarding last frame' fix from previous version\n    1.08    - 2016-04-02 - fixed multiple warnings; fix setup memory leaks;\n                           avoid discarding last frame of audio data\n    1.07    - 2015-01-16 - fixed some warnings, fix mingw, const-correct API\n                           some more crash fixes when out of memory or with corrupt files \n    1.06    - 2015-08-31 - full, correct support for seeking API (Dougall Johnson)\n                           some crash fixes when out of memory or with corrupt files\n    1.05    - 2015-04-19 - don't define __forceinline if it's redundant\n    1.04    - 2014-08-27 - fix missing const-correct case in API\n    1.03    - 2014-08-07 - Warning fixes\n    1.02    - 2014-07-09 - Declare qsort compare function _cdecl on windows\n    1.01    - 2014-06-18 - fix stb_vorbis_get_samples_float\n    1.0     - 2014-05-26 - fix memory leaks; fix warnings; fix bugs in multichannel\n                           (API change) report sample rate for decode-full-file funcs\n    0.99996 - bracket #include <malloc.h> for macintosh compilation by Laurent Gomila\n    0.99995 - use union instead of pointer-cast for fast-float-to-int to avoid alias-optimization problem\n    0.99994 - change fast-float-to-int to work in single-precision FPU mode, remove endian-dependence\n    0.99993 - remove assert that fired on legal files with empty tables\n    0.99992 - rewind-to-start\n    0.99991 - bugfix to stb_vorbis_get_samples_short by Bernhard Wodo\n    0.9999 - (should have been 0.99990) fix no-CRT support, compiling as C++\n    0.9998 - add a full-decode function with a memory source\n    0.9997 - fix a bug in the read-from-FILE case in 0.9996 addition\n    0.9996 - query length of vorbis stream in samples/seconds\n    0.9995 - bugfix to another optimization that only happened in certain files\n    0.9994 - bugfix to one of the optimizations that caused significant (but inaudible?) errors\n    0.9993 - performance improvements; runs in 99% to 104% of time of reference implementation\n    0.9992 - performance improvement of IMDCT; now performs close to reference implementation\n    0.9991 - performance improvement of IMDCT\n    0.999 - (should have been 0.9990) performance improvement of IMDCT\n    0.998 - no-CRT support from Casey Muratori\n    0.997 - bugfixes for bugs found by Terje Mathisen\n    0.996 - bugfix: fast-huffman decode initialized incorrectly for sparse codebooks; fixing gives 10% speedup - found by Terje Mathisen\n    0.995 - bugfix: fix to 'effective' overrun detection - found by Terje Mathisen\n    0.994 - bugfix: garbage decode on final VQ symbol of a non-multiple - found by Terje Mathisen\n    0.993 - bugfix: pushdata API required 1 extra byte for empty page (failed to consume final page if empty) - found by Terje Mathisen\n    0.992 - fixes for MinGW warning\n    0.991 - turn fast-float-conversion on by default\n    0.990 - fix push-mode seek recovery if you seek into the headers\n    0.98b - fix to bad release of 0.98\n    0.98 - fix push-mode seek recovery; robustify float-to-int and support non-fast mode\n    0.97 - builds under c++ (typecasting, don't use 'class' keyword)\n    0.96 - somehow MY 0.95 was right, but the web one was wrong, so here's my 0.95 rereleased as 0.96, fixes a typo in the clamping code\n    0.95 - clamping code for 16-bit functions\n    0.94 - not publically released\n    0.93 - fixed all-zero-floor case (was decoding garbage)\n    0.92 - fixed a memory leak\n    0.91 - conditional compiles to omit parts of the API and the infrastructure to support them: STB_VORBIS_NO_PULLDATA_API, STB_VORBIS_NO_PUSHDATA_API, STB_VORBIS_NO_STDIO, STB_VORBIS_NO_INTEGER_CONVERSION\n    0.90 - first public release\n*/\n\n#endif // STB_VORBIS_HEADER_ONLY\n\n\n/*\n------------------------------------------------------------------------------\nThis software is available under 2 licenses -- choose whichever you prefer.\n------------------------------------------------------------------------------\nALTERNATIVE A - MIT License\nCopyright (c) 2017 Sean Barrett\nPermission is hereby granted, free of charge, to any person obtaining a copy of \nthis software and associated documentation files (the \"Software\"), to deal in \nthe Software without restriction, including without limitation the rights to \nuse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies \nof the Software, and to permit persons to whom the Software is furnished to do \nso, subject to the following conditions:\nThe above copyright notice and this permission notice shall be included in all \ncopies or substantial portions of the Software.\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, \nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE \nSOFTWARE.\n------------------------------------------------------------------------------\nALTERNATIVE B - Public Domain (www.unlicense.org)\nThis is free and unencumbered software released into the public domain.\nAnyone is free to copy, modify, publish, use, compile, sell, or distribute this \nsoftware, either in source code form or as a compiled binary, for any purpose, \ncommercial or non-commercial, and by any means.\nIn jurisdictions that recognize copyright laws, the author or authors of this \nsoftware dedicate any and all copyright interest in the software to the public \ndomain. We make this dedication for the benefit of the public at large and to \nthe detriment of our heirs and successors. We intend this dedication to be an \novert act of relinquishment in perpetuity of all present and future rights to \nthis software under copyright law.\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \nAUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN \nACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION \nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n------------------------------------------------------------------------------\n*/\n"
  },
  {
    "path": "src/engine/config.cpp",
    "content": "/* OpenHoW\n * Copyright (C) 2017-2020 TalonBrave.info and Others (see CONTRIBUTORS)\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include \"App.h\"\n#include \"script/JsonReader.h\"\n\nconst char *Config_GetUserConfigPath() {\n\tstatic std::string config_path;\n\tif ( config_path.empty() ) {\n\t\tchar out[ PL_SYSTEM_MAX_PATH ];\n\t\tif ( PlGetApplicationDataDirectory( APP_NAME, out, PL_SYSTEM_MAX_PATH ) == nullptr ) {\n\t\t\tWarning( \"Failed to get app data directory!\\n%s\\n\", PlGetError() );\n\t\t\tconfig_path = \"./user.config\";\n\t\t} else {\n\t\t\tconfig_path = std::string( out ) + \"user.config\";\n\t\t}\n\t}\n\treturn config_path.c_str();\n}\n\nvoid Config_Save( const char *path ) {\n\tFILE *fp = fopen( path, \"wb\" );\n\tif ( fp == nullptr ) {\n\t\tWarning( \"failed to write config to \\\"%s\\\"!\\n\", path );\n\t\treturn;\n\t}\n\n\tfprintf( fp, \"{\\n\" );\n\n\t/* get access to the console variables from the platform library */\n\tsize_t num_c;\n\tPLConsoleVariable **vars;\n\tPlGetConsoleVariables( &vars, &num_c );\n\n\t/* and NOW save them! */\n\tbool first = true;\n\tfor ( PLConsoleVariable **var = vars; var < num_c + vars; ++var ) {\n\t\tif ( !( *var )->archive ) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tif ( !first ) {\n\t\t\tfprintf( fp, \",\\n\" );\n\t\t}\n\n\t\tfprintf( fp, \"\\t\\t\\\"%s\\\":\\\"%s\\\"\", ( *var )->name, ( *var )->value );\n\t\tfirst = false;\n\t}\n\n\tfprintf( fp, \"\\n}\\n\" );\n\tfclose( fp );\n}\n\nvoid Config_Load( const char *path ) {\n\ttry {\n\t\tJsonReader config( path );\n\n\t\tsize_t num_c;\n\t\tPLConsoleVariable **vars;\n\t\tPlGetConsoleVariables( &vars, &num_c );\n\n\t\tfor ( PLConsoleVariable **var = vars; var < vars + num_c; ++var ) {\n\t\t\tstd::string result = config.GetStringProperty( ( *var )->name );\n\t\t\tif ( result.empty() ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tPlSetConsoleVariable( ( *var ), result.c_str() );\n\t\t}\n\t} catch ( const std::exception &e ) {\n\t\tWarning( \"Failed to read user config, \\\"%s\\\"!\\n%s\\n\", path, e.what() );\n\t}\n}\n"
  },
  {
    "path": "src/engine/config.h",
    "content": "/* OpenHoW\n * Copyright (C) 2017-2020 TalonBrave.info and Others (see CONTRIBUTORS)\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#pragma once\n\n#define CONFIG_FILENAME    \"user.config\"\n\nconst char* Config_GetUserConfigPath();\n\nvoid Config_Save( const char* path );\nvoid Config_Load( const char* path );\n"
  },
  {
    "path": "src/engine/editor/ActorTreeWindow.cpp",
    "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// Copyright © 2017-2022 TalonBrave.info and Others (see CONTRIBUTORS)\n\n#include <imgui.h>\n\n#include \"App.h\"\n#include \"ActorTreeWindow.h\"\n#include \"ActorManager.h\"\n\nusing namespace ohw;\n\nActorTreeWindow::ActorTreeWindow() = default;\nActorTreeWindow::~ActorTreeWindow() = default;\n\nvoid ActorTreeWindow::Display() {\n\tImGui::SetNextWindowSize( ImVec2( 310, 512 ), ImGuiCond_Once );\n\tBegin( \"Actor Tree\", ED_DEFAULT_WINDOW_FLAGS );\n\n\tconst ActorSet actors = ActorManager::GetInstance()->GetActors();\n\tif ( actors.empty() ) {\n\t\tImGui::TextColored( ImVec4( 1.0f, 0, 0, 1.0f ), \"No actors loaded...\" );\n\t\tImGui::End();\n\t\treturn;\n\t}\n\n\tImGui::Text( \"%u Actors\", ( unsigned int ) actors.size() );\n\n\tImGui::PushStyleVar( ImGuiStyleVar_FramePadding, ImVec2( 2, 2 ) );\n\tfor ( auto i : actors ) {\n\t\t//ImGui::BeginGroup();\n\t\t//ImGui::EndGroup();\n\n\t\tif ( i->GetParent() != nullptr ) {\n\t\t\t// Children get shown under their parents\n\t\t\tcontinue;\n\t\t}\n\n\t\tImGui::PushID( i );\n\t\tImGui::AlignTextToFramePadding();\n\n\t\tif ( ImGui::TreeNode( \"Actor\", \"%s (%d %s)\", i->GetClassName(), i->GetNumOfChildren(),\n\t\t\t\t\t\t\t  i->GetNumOfChildren() == 1 ? \"child\" : \"children\" ) ) {\n\t\t\tDisplayActorProperties( i );\n\t\t\tImGui::TreePop();\n\t\t}\n\n\t\tImGui::PopID();\n\t}\n\tImGui::PopStyleVar();\n\n\tImGui::End();\n}\n\nvoid ActorTreeWindow::DisplayActorProperties( Actor* actor ) {\n\tconst PropertyMap& property_map = actor->GetProperties();\n\tif ( property_map.empty() ) {\n\t\t// Very unlikely, better safe than sorry...\n\t\treturn;\n\t}\n\n\tImGui::Checkbox( \"Show read only?\", &showReadOnly );\n\n\tfor ( const auto& i : property_map ) {\n\t\tProperty* property = i.second;\n\t\tif ( !( property->flags & PROP_WRITE ) && !showReadOnly ) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tImGui::PushID( property );\n\n\t\tconst char* name = property->name.c_str();\n\t\tif ( !property->description.empty() ) {\n\t\t\tname = property->description.c_str();\n\t\t}\n\n\t\tauto* stringProperty = dynamic_cast< StringProperty* >( property );\n\t\tif ( stringProperty != nullptr ) {\n\t\t\tchar *buf = new char[ stringProperty->length() + 1 ];\n\t\t\tstrcpy( buf, stringProperty->c_str() );\n\t\t\tif ( ImGui::InputText( name, buf, sizeof( buf ) ) ) {\n\t\t\t\t*stringProperty = buf;\n\t\t\t}\n\t\t\tdelete []buf;\n\t\t}\n\n\t\tauto* vectorProperty = dynamic_cast<Vector3Property*>(property);\n\t\tif ( vectorProperty != nullptr ) {\n\t\t\tPLVector3 value = *vectorProperty;\n\t\t\tfloat v[3] = { value.x, value.y, value.z };\n\t\t\tif ( ImGui::InputFloat3( name, v ) ) {\n\t\t\t\t*vectorProperty = hei::Vector3( v[ 0 ], v[ 1 ], v[ 2 ] );\n\t\t\t}\n\t\t}\n\n\t\tauto* boolean_property = dynamic_cast<BooleanProperty*>(property);\n\t\tif ( boolean_property != nullptr ) {\n\t\t\tbool value = *boolean_property;\n\t\t\tif ( ImGui::Checkbox( name, &value ) ) {\n\t\t\t\t*boolean_property = value;\n\t\t\t}\n\t\t}\n\n\t\tauto* numeric_property = dynamic_cast<NumericProperty<int>*>(property);\n\t\tif ( numeric_property != nullptr ) {\n\t\t\tint value = *numeric_property;\n\t\t\tif ( ImGui::InputInt( name, &value ) ) {\n\t\t\t\t*numeric_property = value;\n\t\t\t}\n\t\t}\n\n\t\tauto* float_property = dynamic_cast<NumericProperty<float>*>(property);\n\t\tif ( float_property != nullptr ) {\n\t\t\tfloat value = *float_property;\n\t\t\tif ( ImGui::InputFloat( name, &value ) ) {\n\t\t\t\t*float_property = value;\n\t\t\t}\n\t\t}\n\n\t\tImGui::PopID();\n\t}\n\n#if 0\n\tstatic float dummy_members[8] = { 0.0f,0.0f,1.0f,3.1416f,100.0f,999.0f };\n\tfor (int i = 0; i < 8; i++) {\n\t  ImGui::PushID(i); // Use field index as identifier.\n\t  if (i < 2) {\n\t\t//ShowDummyObject(\"Child\", 424242);\n\t  } else {\n\t\t// Here we use a TreeNode to highlight on hover (we could use e.g. Selectable as well)\n\t\tImGui::AlignTextToFramePadding();\n\t\tImGui::TreeNodeEx(\"Field\", ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen, \"Field_%d\", i);\n\t\tImGui::NextColumn();\n\t\tImGui::SetNextItemWidth(-1);\n\t\tif (i >= 5)\n\t\t  ImGui::InputFloat(\"##value\", &dummy_members[i], 1.0f);\n\t\telse\n\t\t  ImGui::DragFloat(\"##value\", &dummy_members[i], 0.01f);\n\t\tImGui::NextColumn();\n\t  }\n\t  ImGui::PopID();\n\t}\n#endif\n}\n"
  },
  {
    "path": "src/engine/editor/ActorTreeWindow.h",
    "content": "/* OpenHoW\n * Copyright (C) 2017-2020 TalonBrave.info and Others (see CONTRIBUTORS)\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#pragma once\n\n#include \"BaseWindow.h\"\n\nclass ActorTreeWindow : public BaseWindow {\npublic:\n\tActorTreeWindow();\n\t~ActorTreeWindow() override;\n\n\tvoid Display() override;\n\tvoid DisplayActorProperties( Actor* actor );\n\nprotected:\nprivate:\n\tbool showReadOnly{ false };\n};\n"
  },
  {
    "path": "src/engine/editor/BaseWindow.cpp",
    "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// Copyright © 2017-2022 TalonBrave.info and Others (see CONTRIBUTORS)\n\n#include <imgui.h>\n\n#include \"App.h\"\n#include \"BaseWindow.h\"\n\nvoid BaseWindow::Begin( const std::string &windowTitle, unsigned int flags ) {\n\tif ( IsFullscreen() ) {\n\t\tflags |= ImGuiWindowFlags_NoDecoration;\n\n\t\tohw::Display *display = ohw::GetApp()->GetDisplay();\n\t\tif ( display == nullptr ) {\n\t\t\tError( \"Attempted to setup ImGui window before display initialized!\\n\" );\n\t\t}\n\n\t\tint width, height;\n\t\tdisplay->GetDisplaySize( &width, &height );\n\n\t\tImGui::SetNextWindowPos( ImVec2( 0, 0 ) );\n\t\tImGui::SetNextWindowSize( ImVec2( static_cast< float >( width ), static_cast< float >( height ) ),\n\t\t\t\t\t\t\t\t  ImGuiCond_Always );\n\t} else if ( oldSize != 0 || oldPosition != 0 ) {\n\t\tImGui::SetNextWindowSize( ImVec2( oldSize.x, oldSize.y ), ImGuiCond_Always );\n\t\tImGui::SetNextWindowPos( ImVec2( oldPosition.x, oldPosition.y ), ImGuiCond_Always );\n\t\toldPosition = oldSize = 0;\n\t}\n\n\tImGui::Begin( dname( windowTitle ), &status_, flags );\n\n\tImVec2 size = ImGui::GetWindowSize();\n\tcurWindowSize = hei::Vector2( size.x, size.y );\n\n\tImVec2 position = ImGui::GetWindowPos();\n\tcurWindowPosition = hei::Vector2( position.x, position.y );\n}\n\nvoid BaseWindow::ToggleFullscreen() {\n\tisFullscreen = !isFullscreen;\n\tif ( isFullscreen ) {\n\t\toldSize.x = curWindowSize.x;\n\t\toldSize.y = curWindowSize.y;\n\t\toldPosition.x = curWindowPosition.x;\n\t\toldPosition.y = curWindowPosition.y;\n\t}\n}\n"
  },
  {
    "path": "src/engine/editor/BaseWindow.h",
    "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// Copyright © 2017-2022 TalonBrave.info and Others (see CONTRIBUTORS)\n\n#pragma once\n\n#define ED_DEFAULT_WINDOW_FLAGS ImGuiWindowFlags_NoSavedSettings\n\nstruct ImVec2;\n\nclass BaseWindow {\npublic:\n    explicit BaseWindow(BaseWindow *parent = nullptr, bool status = true) {\n        static unsigned int windows_id_counter = 0;\n        id_ = windows_id_counter++;\n        status_ = status;\n        parent_ = parent;\n    }\n\n    virtual ~BaseWindow() = default;\n\n    virtual void Display() = 0;\n\n    bool GetStatus() { return status_; }\n\n    void SetWindowStatus( bool status) { status_ = status; }\n\n    void Begin( const std::string &windowTitle, unsigned int flags );\n\n    virtual void ToggleFullscreen();\n    bool IsFullscreen() const { return isFullscreen; }\n\n    void ToggleStatus() {\n        status_ = !status_;\n    }\n\nprotected:\n    bool status_;\n    unsigned int id_;\n\n    BaseWindow *parent_{nullptr};\n\nprivate:\n\tbool isFullscreen{ false };\n\thei::Vector2 curWindowSize, curWindowPosition;\n\thei::Vector2 oldSize, oldPosition;\n};\n\n#define dname(a)  std::string( a + \"##\" + /* std::to_string((ptrdiff_t)(this))*/ std::to_string(id_)).c_str()\n"
  },
  {
    "path": "src/engine/editor/ConsoleWindow.cpp",
    "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// Copyright © 2017-2022 TalonBrave.info and Others (see CONTRIBUTORS)\n\n#include <imgui.h>\n\n#include \"App.h\"\n#include \"ConsoleWindow.h\"\n\nohw::ConsoleWindow::ConsoleWindow() : BaseWindow() {\n\n}\n\nohw::ConsoleWindow::~ConsoleWindow() {\n\tClear();\n}\n\nvoid ohw::ConsoleWindow::Display() {\n\tif ( !GetStatus() ) {\n\t\treturn;\n\t}\n\n\tunsigned int flags =\n\t\t\tImGuiWindowFlags_MenuBar |\n\t\t\tImGuiWindowFlags_NoScrollWithMouse |\n\t\t\tImGuiWindowFlags_NoScrollbar |\n\t\t\tImGuiWindowFlags_NoSavedSettings;\n\tImGui::SetNextWindowSize( ImVec2( 512, 256 ), ImGuiCond_Once );\n\n\tBegin( \"Console\", flags );\n\n\tif ( ImGui::BeginMenuBar() ) {\n\t\tImGui::EndMenuBar();\n\t}\n\n\tif ( ImGui::InputText( \"Input\", inputBuffer, sizeof( inputBuffer ), ImGuiInputTextFlags_EnterReturnsTrue ) && inputBuffer[ 0 ] != '\\0' ) {\n\t\tPushCommand();\n\t}\n\tImGui::SameLine();\n\tif ( ImGui::Button( \"Submit\" ) ) {\n\t\tPushCommand();\n\t}\n\tImGui::SameLine();\n\tif ( ImGui::Button( \"Clear\" ) ) {\n\t\tClear();\n\t}\n\n\tImGui::Separator();\n\n\tconst float footerHeightToReserve = ImGui::GetStyle().ItemSpacing.y + ImGui::GetFrameHeightWithSpacing(); // 1 separator, 1 input text\n\tImGui::BeginChild( \"ScrollingRegion\", ImVec2( 0, -footerHeightToReserve ), false, ImGuiWindowFlags_HorizontalScrollbar );\n\n\tfor ( const auto &i : logBuffer ) {\n\t\t// todo: just respect the original message colour instead...\n\t\tif ( i.level == ohw::LOG_LEVEL_WARNING ) {\n\t\t\tImGui::PushStyleColor( ImGuiCol_Text, ImVec4( 0.8f, 0.6f, 0.0f, 1.0f ) );\n\t\t} else if ( i.level == ohw::LOG_LEVEL_ERROR ) {\n\t\t\tImGui::PushStyleColor( ImGuiCol_Text, ImVec4( 0.8f, 0.2f, 0.0f, 1.0f ) );\n\t\t} else {\n\t\t\tImGui::PushStyleColor( ImGuiCol_Text, ImVec4( 0.0f, 0.6f, 0.8f, 1.0f ) );\n\t\t}\n\n\t\tImGui::TextUnformatted( i.buffer );\n\n\t\tImGui::PopStyleColor();\n\t}\n\n\tif ( scrollToEnd ) {\n\t\tImGui::SetScrollHereY( 1.0f );\n\t\tscrollToEnd = false;\n\t}\n\n\tImGui::EndChild();\n\n\tImGui::End();\n}\n\nvoid ohw::ConsoleWindow::PushMessage( int level, const char *msg ) {\n\tif ( logBuffer.size() > 1024 ) {\n\t\tlogBuffer.erase( logBuffer.begin() );\n\t}\n\n\tMessage message;\n\tmessage.level = level;\n\tsnprintf( message.buffer, sizeof( message.buffer ), \"%s\", msg );\n\tlogBuffer.push_back( message );\n\n\tscrollToEnd = true;\n}\n\nvoid ohw::ConsoleWindow::Clear() {\n\tlogBuffer.clear();\n}\n\nvoid ohw::ConsoleWindow::PushCommand() {\n\tPlParseConsoleString( inputBuffer );\n\tinputBuffer[ 0 ] = '\\0';\n}\n"
  },
  {
    "path": "src/engine/editor/ConsoleWindow.h",
    "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// Copyright © 2017-2022 TalonBrave.info and Others (see CONTRIBUTORS)\n\n#pragma once\n\n#include \"BaseWindow.h\"\n\nnamespace ohw {\n\tclass ConsoleWindow : public BaseWindow {\n\tpublic:\n\t\tConsoleWindow();\n\t\t~ConsoleWindow() override;\n\n\t\tvoid Display() override;\n\n\t\tvoid PushMessage( int level, const char *msg );\n\t\tvoid Clear();\n\n\t\tvoid PushCommand();\n\n\tprivate:\n\t\tstruct Message {\n\t\t\tunsigned int level{ 0 };\n\t\t\tchar buffer[ 512 ]{ '\\0' };\n\t\t};\n\t\tstd::vector< Message > logBuffer;\n\n\t\tbool scrollToEnd{ false };\n\n\t\tchar inputBuffer[ 512 ]{ '\\0' };\n\t};\n}\n"
  },
  {
    "path": "src/engine/editor/MapConfigEditor.cpp",
    "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// Copyright © 2017-2022 TalonBrave.info and Others (see CONTRIBUTORS)\n\n#include <imgui.h>\n#include <fstream>\n\n#include \"App.h\"\n#include \"Map.h\"\n#include \"MapConfigEditor.h\"\n\nohw::MapConfigEditor::MapConfigEditor() {\n\tmap_ = GetApp()->gameManager->GetCurrentMap();\n\tif ( map_ == nullptr ) {\n\t\tthrow std::runtime_error( \"Attempted to create config editor without a valid map loaded!\\n\" );\n\t}\n\n\tmanifest_ = map_->GetManifest();\n\tbackup_ = *manifest_;\n\n\tstrncpy( name_buffer, manifest_->name.c_str(), sizeof( name_buffer ) );\n\tstrncpy( author_buffer, manifest_->author.c_str(), sizeof( author_buffer ) );\n}\n\nohw::MapConfigEditor::~MapConfigEditor() {\n\tRestoreManifest();\n}\n\nvoid ohw::MapConfigEditor::DisplayTemperature() {\n\tenum {\n\t\tTEMP_NORMAL, TEMP_HOT, TEMP_COLD, MAX_TEMP\n\t};\n\tstatic const char *temperatures[MAX_TEMP] = { \"Normal\", \"Hot\", \"Cold\" };\n\tstatic int temperature_index = -1;\n\tif ( temperature_index == -1 ) {\n\t\tif ( pl_strcasecmp( manifest_->temperature.c_str(), \"hot\" ) == 0 ) {\n\t\t\ttemperature_index = TEMP_HOT;\n\t\t} else if ( pl_strcasecmp( manifest_->temperature.c_str(), \"cold\" ) == 0 ) {\n\t\t\ttemperature_index = TEMP_COLD;\n\t\t} else {\n\t\t\ttemperature_index = TEMP_NORMAL;\n\t\t}\n\t}\n\n\tif ( ImGui::BeginCombo( \"Temperature\", temperatures[ temperature_index ] ) ) {\n\t\tfor ( int i = 0; i < MAX_TEMP; ++i ) {\n\t\t\tif ( ImGui::Selectable( temperatures[ i ], ( temperature_index == i ) ) ) {\n\t\t\t\tImGui::SetItemDefaultFocus();\n\t\t\t\ttemperature_index = i;\n\t\t\t\tmanifest_->temperature = u_stringtolower( temperatures[ temperature_index ] );\n\t\t\t}\n\t\t}\n\n\t\tImGui::EndCombo();\n\t}\n}\n\nvoid ohw::MapConfigEditor::DisplayWeather() {\n\tenum {\n\t\tWEATHER_CLEAR, WEATHER_RAIN, WEATHER_SNOW, MAX_WEATHER\n\t};\n\tstatic const char *weather_labels[MAX_WEATHER] = { \"Clear\", \"Rain\", \"Snow\" };\n\tstatic int weather_index = -1;\n\tif ( weather_index == -1 ) {\n\t\tif ( pl_strcasecmp( manifest_->weather.c_str(), \"rain\" ) == 0 ) {\n\t\t\tweather_index = WEATHER_RAIN;\n\t\t} else if ( pl_strcasecmp( manifest_->weather.c_str(), \"snow\" ) == 0 ) {\n\t\t\tweather_index = WEATHER_SNOW;\n\t\t} else {\n\t\t\tweather_index = WEATHER_CLEAR;\n\t\t}\n\t}\n\n\tif ( ImGui::BeginCombo( \"Weather\", weather_labels[ weather_index ] ) ) {\n\t\tfor ( int i = 0; i < MAX_WEATHER; ++i ) {\n\t\t\tif ( ImGui::Selectable( weather_labels[ i ], ( weather_index == i ) ) ) {\n\t\t\t\tImGui::SetItemDefaultFocus();\n\t\t\t\tweather_index = i;\n\t\t\t\tmanifest_->weather = u_stringtolower( weather_labels[ weather_index ] );\n\t\t\t}\n\t\t}\n\n\t\tImGui::EndCombo();\n\t}\n}\n\nvoid ohw::MapConfigEditor::DisplayTime() {\n\tenum {\n\t\tTIME_DAY, TIME_NIGHT, MAX_TIME\n\t};\n\tstatic const char *times[MAX_TIME] = { \"Day\", \"Night\" };\n\tstatic int time_index = -1;\n\tif ( time_index == -1 ) {\n\t\tif ( pl_strcasecmp( manifest_->time.c_str(), \"day\" ) == 0 ) {\n\t\t\ttime_index = TIME_DAY;\n\t\t} else {\n\t\t\ttime_index = TIME_NIGHT;\n\t\t}\n\t}\n\n\tif ( ImGui::BeginCombo( \"Time\", times[ time_index ] ) ) {\n\t\tfor ( int i = 0; i < MAX_TIME; ++i ) {\n\t\t\tif ( ImGui::Selectable( times[ i ], ( time_index == i ) ) ) {\n\t\t\t\tImGui::SetItemDefaultFocus();\n\t\t\t\ttime_index = i;\n\t\t\t\tmanifest_->time = u_stringtolower( times[ time_index ] );\n\t\t\t}\n\t\t}\n\n\t\tImGui::EndCombo();\n\t}\n}\n\nvoid ohw::MapConfigEditor::Display() {\n\tImGui::SetNextWindowSize( ImVec2( 310, 512 ), ImGuiCond_Once );\n\tBegin( \"Map Config Editor\", ED_DEFAULT_WINDOW_FLAGS );\n\n\tImGui::InputText( \"Name\", name_buffer, sizeof( name_buffer ) );\n\tImGui::InputText( \"Author\", author_buffer, sizeof( author_buffer ) );\n\n\t// todo: mode selection - need to query wherever this ends up being implemented...\n\n\tImGui::Separator();\n\n\tDisplayTemperature();\n\tDisplayWeather();\n\tDisplayTime();\n\n\tImGui::Separator();\n\n\tImGui::Text( \"Sky Settings\" );\n\n\tfloat rgb[3];\n\trgb[ 0 ] = PlByteToFloat( manifest_->sky_colour_top.r );\n\trgb[ 1 ] = PlByteToFloat( manifest_->sky_colour_top.g );\n\trgb[ 2 ] = PlByteToFloat( manifest_->sky_colour_top.b );\n\tif ( ImGui::ColorEdit3( \"Top Colour\", rgb, ImGuiColorEditFlags_InputRGB ) ) {\n\t\tmanifest_->sky_colour_top.r = PlFloatToByte( rgb[ 0 ] );\n\t\tmanifest_->sky_colour_top.g = PlFloatToByte( rgb[ 1 ] );\n\t\tmanifest_->sky_colour_top.b = PlFloatToByte( rgb[ 2 ] );\n\t\tmap_->UpdateSky();\n\t}\n\n\trgb[ 0 ] = PlByteToFloat( manifest_->sky_colour_bottom.r );\n\trgb[ 1 ] = PlByteToFloat( manifest_->sky_colour_bottom.g );\n\trgb[ 2 ] = PlByteToFloat( manifest_->sky_colour_bottom.b );\n\tif ( ImGui::ColorEdit3( \"Bottom Colour\", rgb, ImGuiColorEditFlags_InputRGB ) ) {\n\t\tmanifest_->sky_colour_bottom.r = PlFloatToByte( rgb[ 0 ] );\n\t\tmanifest_->sky_colour_bottom.g = PlFloatToByte( rgb[ 1 ] );\n\t\tmanifest_->sky_colour_bottom.b = PlFloatToByte( rgb[ 2 ] );\n\t\tmap_->UpdateSky();\n\t}\n\n\tImGui::Separator();\n\n\tImGui::Text( \"Lighting Settings\" );\n\n\tImGui::SliderAngle( \"Sun Pitch\", &manifest_->sun_pitch, -90, 90, nullptr );\n\tImGui::SliderAngle( \"Sun Yaw\", &manifest_->sun_yaw, -180, 180, nullptr );\n\n\trgb[ 0 ] = PlByteToFloat( manifest_->sun_colour.r );\n\trgb[ 1 ] = PlByteToFloat( manifest_->sun_colour.g );\n\trgb[ 2 ] = PlByteToFloat( manifest_->sun_colour.b );\n\tif ( ImGui::ColorEdit3( \"Sun Colour\", rgb, ImGuiColorEditFlags_InputRGB ) ) {\n\t\tmanifest_->sun_colour.r = PlFloatToByte( rgb[ 0 ] );\n\t\tmanifest_->sun_colour.g = PlFloatToByte( rgb[ 1 ] );\n\t\tmanifest_->sun_colour.b = PlFloatToByte( rgb[ 2 ] );\n\t}\n\n\trgb[ 0 ] = PlByteToFloat( manifest_->ambient_colour.r );\n\trgb[ 1 ] = PlByteToFloat( manifest_->ambient_colour.g );\n\trgb[ 2 ] = PlByteToFloat( manifest_->ambient_colour.b );\n\tif ( ImGui::ColorEdit3( \"Ambient Colour\", rgb, ImGuiColorEditFlags_InputRGB ) ) {\n\t\tmanifest_->ambient_colour.r = PlFloatToByte( rgb[ 0 ] );\n\t\tmanifest_->ambient_colour.g = PlFloatToByte( rgb[ 1 ] );\n\t\tmanifest_->ambient_colour.b = PlFloatToByte( rgb[ 2 ] );\n\t}\n\n\tImGui::Separator();\n\n\t// Fog\n\t{\n\t\tImGui::Text( \"Fog Settings\" );\n\n\t\trgb[ 0 ] = PlByteToFloat( manifest_->fog_colour.r );\n\t\trgb[ 1 ] = PlByteToFloat( manifest_->fog_colour.g );\n\t\trgb[ 2 ] = PlByteToFloat( manifest_->fog_colour.b );\n\t\tif ( ImGui::ColorEdit3( \"Fog Colour\", rgb, ImGuiColorEditFlags_InputRGB ) ) {\n\t\t\tmanifest_->fog_colour.r = PlFloatToByte( rgb[ 0 ] );\n\t\t\tmanifest_->fog_colour.g = PlFloatToByte( rgb[ 1 ] );\n\t\t\tmanifest_->fog_colour.b = PlFloatToByte( rgb[ 2 ] );\n\t\t}\n\n\t\tImGui::SliderFloat( \"Fog Intensity\", &manifest_->fog_intensity, -100.0f, 100.0f, \"%.0f\" );\n\t\tImGui::SliderFloat( \"Fog Distance\", &manifest_->fog_distance, 0, 300.0f, \"%.0f\" );\n\t}\n\n\tImGui::Separator();\n\n\tif ( ImGui::Button( \"Save\" ) ) {\n\t\tSaveManifest( \"maps/\" + manifest_->filename + \".map\" );\n\t}\n\tImGui::SameLine();\n\tif ( ImGui::Button( \"Cancel\" ) ) {\n\t\tRestoreManifest();\n\n\t\t// Close the window\n\t\tSetWindowStatus( false );\n\t}\n\n\tImGui::End();\n}\n\nvoid ohw::MapConfigEditor::SaveManifest( const std::string &path ) {\n\tconst ModManager::ModDescription *currentMod = GetApp()->modManager->GetCurrentModDescription();\n\tstd::ofstream output( \"mods/\" + currentMod->directory + path );\n\tif ( !output.is_open() ) {\n\t\tWarning( \"Failed to write to \\\"%s\\\", aborting!n\\\"\\n\", filename_buffer );\n\t\treturn;\n\t}\n\n\tmanifest_->name = name_buffer;\n\tmanifest_->author = author_buffer;\n\n\toutput << manifest_->Serialize();\n\n\tPrint( \"Wrote \\\"%s\\\"!\\n\", path.c_str() );\n\tbackup_ = *manifest_;\n}\n\nvoid ohw::MapConfigEditor::RestoreManifest() {\n\t*manifest_ = backup_;\n\n\tmap_->UpdateSky();\n}\n"
  },
  {
    "path": "src/engine/editor/MapConfigEditor.h",
    "content": "/* OpenHoW\n * Copyright (C) 2017-2020 TalonBrave.info and Others (see CONTRIBUTORS)\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#pragma once\n\n#include \"BaseWindow.h\"\n\nnamespace ohw {\n\tclass Map;\n\tclass MapConfigEditor : public BaseWindow {\n\tpublic:\n\t\tMapConfigEditor();\n\t\t~MapConfigEditor() override;\n\n\t\tvoid Display() override;\n\t\tvoid SaveManifest( const std::string &path );\n\t\tvoid RestoreManifest();\n\n\tprotected:\n\tprivate:\n\t\tMapManifest backup_;\n\t\tMapManifest *manifest_;\n\t\tMap *map_{ nullptr };\n\n\t\tchar name_buffer[32]{ '\\0' };\n\t\tchar author_buffer[32]{ '\\0' };\n\t\tchar filename_buffer[32]{ '\\0' };\n\n\t\tvoid DisplayWeather();\n\t\tvoid DisplayTemperature();\n\t\tvoid DisplayTime();\n\t};\n}\n"
  },
  {
    "path": "src/engine/editor/ModelViewer.cpp",
    "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// Copyright © 2017-2022 TalonBrave.info and Others (see CONTRIBUTORS)\n\n#include \"App.h\"\n#include \"graphics/ShaderManager.h\"\n#include \"graphics/Camera.h\"\n#include \"imgui_layer.h\"\n#include \"model.h\"\n#include \"Language.h\"\n\n#include \"ModelViewer.h\"\n#include \"TextureViewer.h\"\n\n#define VIEWER_WIDTH  640\n#define VIEWER_HEIGHT 480\n\nstd::list< std::string > ohw::ModelViewer::modelList;\n\nstatic const char *supportedModelFormats[] = { \"obj\", \"vtx\", \"min\", nullptr };\n\nohw::ModelViewer::ModelViewer() : BaseWindow() {\n\tconst char **formatExtensions = supportedModelFormats;\n\twhile ( *formatExtensions != nullptr ) {\n\t\tPlScanDirectory( \"chars\", *formatExtensions, &ModelViewer::AppendModelList, true, nullptr );\n\t\tformatExtensions++;\n\t}\n\n\tmodelList.sort();\n\tmodelList.unique();\n\n\tcamera = new Camera( { -2500.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f } );\n\tcamera->SetViewport( 0, 0, 640, 480 );\n\n\tGenerateFrameBuffer( 640, 480 );\n}\n\nohw::ModelViewer::~ModelViewer() {\n\tPlgDestroyTexture( textureAttachment );\n\tPlgDestroyFrameBuffer( drawBuffer );\n}\n\nvoid ohw::ModelViewer::DrawViewport() {\n\tPlgBindFrameBuffer( drawBuffer, PLG_FRAMEBUFFER_DRAW );\n\n\tPlgSetDepthBufferMode( PLG_DEPTHBUFFER_ENABLE );\n\n\tPlgSetClearColour( { 0, 0, 0, 0 } );\n\tPlgClearBuffers( PLG_BUFFER_COLOUR | PLG_BUFFER_DEPTH );\n\n\tunsigned int bufferWidth = 0, bufferHeight = 0;\n\tPlgGetFrameBufferResolution( drawBuffer, &bufferWidth, &bufferHeight );\n\tcamera->SetViewport( 0, 0, bufferWidth, bufferHeight );\n\tcamera->MakeActive();\n\n\thei::Vector3 angles(\n\t\t\tPlDegreesToRadians( modelRotation.x ),\n\t\t\tPlDegreesToRadians( modelRotation.y ),\n\t\t\tPlDegreesToRadians( modelRotation.z ) );\n\n\tif ( viewGrid ) {\n\t\tShaderProgram *shaderProgram = Shaders_GetProgram( \"generic_untextured\" );\n\t\tshaderProgram->Enable();\n\n\t\tPlMatrixMode( PL_MODELVIEW_MATRIX );\n\t\tPlPushMatrix();\n\t\tPlLoadIdentityMatrix();\n\n\t\tPlRotateMatrix( PlDegreesToRadians( modelRotation.z + 90.0f ), 1, 0, 0 );\n\t\tPlRotateMatrix( angles.y, 0, 1, 0 );\n\t\tPlRotateMatrix( angles.x, 0, 0, 1 );\n\n\t\tPlgDrawGrid( -512, -512, 1024, 1024, 32 );\n\n\t\tPlPopMatrix();\n\t}\n\n\tif ( model == nullptr ) {\n\t\tPlgBindFrameBuffer( nullptr, PLG_FRAMEBUFFER_DRAW );\n\t\treturn;\n\t}\n\n\tShaderProgram *shaderProgram = Shaders_GetProgram( viewDebugNormals ? \"debug_normals\" : \"generic_textured_lit\" );\n\tshaderProgram->Enable();\n\n\tif ( !viewDebugNormals ) {\n\t\thei::Vector3 sunPosition( 0.5f, 0.2f, 0.6f );\n\t\tPLVector4 sunColour = { 1.0f, 1.0f, 1.0f, 1.0f };\n\t\tPLVector4 ambience = { 0.75f, 0.75f, 0.75f, 1.0f };\n\n\t\tPlgSetShaderUniformValue( shaderProgram->GetInternalProgram(), \"sun_position\", &sunPosition, false );\n\t\tPlgSetShaderUniformValue( shaderProgram->GetInternalProgram(), \"sun_colour\", &sunColour, false );\n\t\tPlgSetShaderUniformValue( shaderProgram->GetInternalProgram(), \"ambient_colour\", &ambience, false );\n\t}\n\t\n\tif ( viewRotate ) {\n\t\tmodelRotation.y += 0.01f * GetApp()->GetDeltaTime();\n\t}\n\n\thei::Matrix4 mat;\n\tmat.Identity();\n\tmat.Rotate( angles.z, { 1, 0, 0 } );\n\tmat.Rotate( angles.y, { 0, 1, 0 } );\n\tmat.Rotate( angles.x, { 0, 0, 1 } );\n\n\tmodel->modelMatrix = mat;\n\tmodel->Draw( false );\n\n\tif ( viewDebugNormals ) {\n\t\tmodel->DrawNormals();\n\t}\n\n\tif ( viewSkeleton ) {\n\t\tmodel->DrawSkeleton();\n\t}\n\n\tPlgBindFrameBuffer( nullptr, PLG_FRAMEBUFFER_DRAW );\n}\n\nvoid ohw::ModelViewer::Display() {\n\t// Draw the model view if there's a valid model\n\tDrawViewport();\n\n\tunsigned int flags =\n\t\t\tImGuiWindowFlags_MenuBar |\n\t\t\tImGuiWindowFlags_NoScrollWithMouse |\n\t\t\tImGuiWindowFlags_NoScrollbar |\n\t\t\tImGuiWindowFlags_NoSavedSettings;\n\tImGui::SetNextWindowSize( ImVec2( VIEWER_WIDTH, VIEWER_HEIGHT ), ImGuiCond_Once );\n\n\tBegin( lm_gtr( \"$window_model_viewer\" ), flags );\n\n\tif ( ImGui::BeginMenuBar() ) {\n\t\tif ( ImGui::BeginMenu( \"Models\" ) ) {\n\t\t\tstatic ImGuiTextFilter filter;\n\t\t\tfilter.Draw();\n\n\t\t\tfor ( const auto &i : modelList ) {\n\t\t\t\tif ( !filter.PassFilter( i.c_str() ) ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tbool selected = false;\n\t\t\t\tif ( model != nullptr ) {\n\t\t\t\t\tselected = ( i == model->GetPath() );\n\t\t\t\t}\n\n\t\t\t\tif ( ImGui::Selectable( i.c_str(), selected ) ) {\n\t\t\t\t\tif ( model != nullptr ) {\n\t\t\t\t\t\tmodel->Release();\n\t\t\t\t\t\tmodel = nullptr;\n\n\t\t\t\t\t\t// Force a cleanup\n\t\t\t\t\t\tGetApp()->resourceManager->ClearAllResources();\n\t\t\t\t\t}\n\n\t\t\t\t\tmodel = GetApp()->resourceManager->LoadModel( i );\n\t\t\t\t}\n\t\t\t}\n\t\t\tImGui::EndMenu();\n\t\t}\n\n\t\t// Urgh, yeah this will eventually need to change\n\t\tif ( model != nullptr && model->IsAnimated() ) {\n\t\t\tif ( ImGui::BeginMenu( \"Animations\" ) ) {\n\t\t\t\tfor ( unsigned int i = 0; static_cast<AnimationIndex>(i) < AnimationIndex::MAX_ANIMATIONS; ++i ) {\n\t\t\t\t\tconst char *animationName = Model_GetAnimationDescription( i );\n\t\t\t\t\tif ( animationName == nullptr ) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tbool selected = false;\n\t\t\t\t\tif ( ImGui::Selectable( animationName, selected ) ) {\n\t\t\t\t\t\t// todo\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tImGui::EndMenu();\n\t\t\t}\n\t\t}\n\n\t\tif ( ImGui::BeginMenu( \"View\" ) ) {\n\t\t\tif ( ImGui::MenuItem( \"Fullscreen\", nullptr, IsFullscreen() ) ) {\n\t\t\t\tToggleFullscreen();\n\t\t\t}\n\t\t\tImGui::Separator();\n\t\t\tif ( ImGui::MenuItem( \"Rotate Model\", nullptr, viewRotate ) ) {\n\t\t\t\tviewRotate = !viewRotate;\n\t\t\t}\n\t\t\tImGui::Separator();\n\t\t\tif ( ImGui::MenuItem( \"Show Normals\", nullptr, viewDebugNormals ) ) {\n\t\t\t\tviewDebugNormals = !viewDebugNormals;\n\t\t\t}\n\t\t\tif ( model != nullptr && model->IsAnimated() ) {\n\t\t\t\tif ( ImGui::MenuItem( \"Show Skeleton\", nullptr, viewSkeleton ) ) {\n\t\t\t\t\tviewSkeleton = !viewSkeleton;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif ( ImGui::MenuItem( \"Show Grid\", nullptr, viewGrid ) ) {\n\t\t\t\tviewGrid = !viewGrid;\n\t\t\t}\n\n\t\t\tif ( model != nullptr ) {\n\t\t\t\tImGui::Separator();\n\n\t\t\t\tif ( ImGui::BeginMenu( \"Textures\" ) ) {\n\t\t\t\t\tfor ( unsigned int i = 0; i < model->GetNumberOfMeshes(); ++i ) {\n\t\t\t\t\t\tPLGMesh *mesh = model->GetInternalMesh( i );\n\t\t\t\t\t\tif ( ImGui::ImageButton( reinterpret_cast<ImTextureID>( mesh->texture->internal.id ), ImVec2( 128, 128 ) ) ) {\n\t\t\t\t\t\t\t//ImGuiImpl_RegisterWindow( new TextureViewer( model->GetTextureResource( i ) ) );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tImGui::EndMenu();\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tImGui::Separator();\n\n\t\t\tImGui::Text( \"Camera Properties\" );\n\t\t\tfloat fov = camera->GetFieldOfView();\n\t\t\tif ( ImGui::SliderFloat( \"Fov\", &fov, 0.0f, 180.0f, \"%.f\" ) ) {\n\t\t\t\tcamera->SetFieldOfView( fov );\n\t\t\t}\n\n\t\t\tImGui::EndMenu();\n\t\t}\n\n\t\tImGui::Separator();\n\n\t\tconst char *labelStr = \"No model loaded\";\n\t\tif ( model != nullptr ) {\n\t\t\tlabelStr = model->GetPath().c_str();\n\t\t}\n\t\tImGui::Text( \"%s\", labelStr );\n\n\t\tImGui::Separator();\n\n\t\tunsigned int numTriangles = 0;\n\t\tunsigned int numVertices = 0;\n\t\tunsigned int numDrawCalls = 0;\n\t\tif ( model != nullptr ) {\n\t\t\tnumDrawCalls = model->GetNumberOfMeshes();\n\t\t\tfor ( unsigned int i = 0; i < numDrawCalls; ++i ) {\n\t\t\t\tPLGMesh *mesh = model->GetInternalMesh( i );\n\t\t\t\tnumTriangles += mesh->num_triangles;\n\t\t\t\tnumVertices += mesh->num_verts;\n\t\t\t}\n\t\t}\n\t\tImGui::Text( \"Batches: %d\", numDrawCalls );\n\t\tImGui::Text( \"Vertices: %d\", numVertices );\n\t\tImGui::Text( \"Triangles: %d\", numTriangles );\n\n\t\tImGui::EndMenuBar();\n\t}\n\n#if 0\n\tif ( ImGui::ListBoxHeader( \"Models\", modelList.size() ) ) {\n\n\t\tImGui::ListBoxFooter();\n\t}\n\n\tImGui::SameLine();\n#endif\n\n\tImGui::PushStyleColor( ImGuiCol_Button, ImVec4( 0, 0, 0, 0 ) );\n\tImGui::PushStyleColor( ImGuiCol_ButtonActive, ImVec4( 0, 0, 0, 0 ) );\n\tImGui::PushStyleColor( ImGuiCol_ButtonHovered, ImVec4( 0, 0, 0, 0 ) );\n\n\tImVec2 region = ImGui::GetContentRegionAvail();\n\tGenerateFrameBuffer( static_cast< unsigned int>( region.x ), static_cast< unsigned int>( region.y ) );\n\tImGui::ImageButton(\n\t\t\treinterpret_cast<ImTextureID>(textureAttachment->internal.id),\n\t\t\tregion, ImVec2( 0, 0 ), ImVec2( 1, 1 ), 0 );\n\tif ( ImGui::IsItemHovered() ) {\n\t\tfloat newXPos = ImGui::GetMousePos().x - oldMousePos[ 0 ];\n\t\tfloat newYPos = ImGui::GetMousePos().y - oldMousePos[ 1 ];\n\t\tconst static float posMod = 200.0f;\n\t\tif ( ImGui::IsMouseDown( ImGuiMouseButton_Left ) ) { // Rotation\n\t\t\tmodelRotation.x += newYPos / posMod * GetApp()->GetDeltaTime();\n\t\t\tmodelRotation.y += newXPos / posMod * GetApp()->GetDeltaTime();\n\t\t} else if ( ImGui::IsMouseDown( ImGuiMouseButton_Middle ) ) { // Panning\n\t\t\tPLVector3 position = camera->GetPosition();\n\t\t\tposition.z += newXPos / posMod * GetApp()->GetDeltaTime();\n\t\t\tposition.y += newYPos / posMod * GetApp()->GetDeltaTime();\n\t\t\tcamera->SetPosition( position );\n\t\t} else {\n\t\t\toldMousePos[ 0 ] = ImGui::GetMousePos().x;\n\t\t\toldMousePos[ 1 ] = ImGui::GetMousePos().y;\n\t\t}\n\n\t\t// Handle mouse wheel movements\n\t\tPLVector3 position = camera->GetPosition();\n\t\tposition.x += ImGui::GetIO().MouseWheel * 10;\n\t\tcamera->SetPosition( position );\n\t}\n\n\tImGui::PopStyleColor( 3 );\n\n\tImGui::End();\n}\n\nvoid ohw::ModelViewer::AppendModelList( const char *path, void *userData ) {\n\tu_unused( userData );\n\n\tmodelList.push_back( path );\n}\n\nvoid ohw::ModelViewer::GenerateFrameBuffer( unsigned int width, unsigned int height ) {\n\tunsigned int bufferWidth = 0, bufferHeight = 0;\n\tif ( drawBuffer != nullptr ) {\n\t\tPlgGetFrameBufferResolution( drawBuffer, &bufferWidth, &bufferHeight );\n\t}\n\n\tif ( bufferWidth != width || bufferHeight != height ) {\n\t\tPlgDestroyFrameBuffer( drawBuffer );\n\t\tdrawBuffer = PlgCreateFrameBuffer( width, height, PLG_BUFFER_COLOUR | PLG_BUFFER_DEPTH );\n\t\tif ( drawBuffer == nullptr ) {\n\t\t\tError( \"Failed to create framebuffer for model viewer (%s)!\\n\", PlGetError() );\n\t\t}\n\n\t\tPlgDestroyTexture( textureAttachment );\n\t\ttextureAttachment = PlgGetFrameBufferTextureAttachment( drawBuffer, PLG_BUFFER_COLOUR, PLG_TEXTURE_FILTER_LINEAR );\n\t\tif ( textureAttachment == nullptr ) {\n\t\t\tError( \"Failed to create texture attachment for buffer (%s)!\\n\", PlGetError() );\n\t\t}\n\t}\n\n\tPlgBindFrameBuffer( nullptr, PLG_FRAMEBUFFER_DRAW );\n}\n"
  },
  {
    "path": "src/engine/editor/ModelViewer.h",
    "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// Copyright © 2017-2022 TalonBrave.info and Others (see CONTRIBUTORS)\n\n#include \"BaseWindow.h\"\n\nnamespace ohw {\n\tclass Camera;\n\tclass ModelViewer : public BaseWindow {\n\tpublic:\n\t\texplicit ModelViewer();\n\t\t~ModelViewer() override;\n\n\t\tvoid Display() override;\n\n\t\tvoid DrawViewport();\n\n\tprotected:\n\tprivate:\n\t\tvoid GenerateFrameBuffer( unsigned int width, unsigned int height );\n\n\t\tSharedModelResourcePointer model{ nullptr };\n\t\tstruct PLGFrameBuffer *drawBuffer{ nullptr };\n\t\tstruct PLGTexture *textureAttachment{ nullptr };\n\n\t\tCamera *camera{ nullptr };\n\n\t\tPLVector3 modelRotation;\n\n\t\tfloat oldMousePos[ 2 ]{ 0, 0 };\n\n\t\tbool viewRotate{ true };\n\t\tbool viewDebugNormals{ false };\n\t\tbool viewSkeleton{ false };\n\t\tbool viewGrid{ true };\n\n\t\tstatic void AppendModelList( const char *path, void *userData );\n\t\tstatic std::list< std::string > modelList;\n\t};\n}\n"
  },
  {
    "path": "src/engine/editor/NewGameWindow.cpp",
    "content": "/* OpenHoW\n * Copyright (C) 2017-2020 TalonBrave.info and Others (see CONTRIBUTORS)\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include <imgui.h>\n\n#include \"App.h\"\n#include \"game/Player.h\"\n#include \"NewGameWindow.h\"\n\nusing namespace ohw;\n\nvoid NewGameWindow::Display() {\n\tImGui::SetNextWindowSize( ImVec2( 320, 400 ), ImGuiCond_Once );\n\tImGui::Begin( \"New Game\", &status_, ED_DEFAULT_WINDOW_FLAGS );\n\n\t// Team Selection\n\tImGui::Text( \"Select Team\" );\n\tGameManager::PlayerTeamVector teams = GetApp()->gameManager->GetDefaultTeams();\n\tstd::vector< const char * > options;\n\tfor ( const auto &team : teams ) {\n\t\toptions.push_back( team.name.c_str() );\n\t}\n\n\tstatic int selectedTeamNum = 0;\n\tselectedTeam = teams[ selectedTeamNum ];\n\n\tif ( ImGui::ListBox( \"Teams\", &selectedTeamNum, &options[ 0 ], options.size(), 10 ) ) {\n\t\tsnprintf( teamName, sizeof( teamName ), \"%s\", teams[ selectedTeamNum ].name.c_str() );\n\t}\n\n\tif ( ImGui::InputText( \"Team Name\", teamName, sizeof( teamName ) ) ) {\n\t\tselectedTeam.name = teamName;\n\t}\n\n\tif ( ImGui::Button( \"Configure Team\" ) ) {\n\t\t// todo\n\t}\n\n\tImGui::Separator();\n\n\tImGui::Checkbox( \"Play training mission?\", &playTrainingMission );\n\n\tif ( ImGui::Button( \"Start Game\" ) ) {\n\t\t// Setup local player\n\t\tPlayer *player = new Player( PlayerType::LOCAL );\n\t\tplayer->SetTeam( selectedTeam );\n\n\t\tPlayerPtrVector players = {\n\t\t\t\tplayer\n\t\t};\n\n\t\tGameModeDescriptor game_mode_descriptor;\n\t\tstd::string mapname;\n\t\tif ( !playTrainingMission ) {\n\t\t\tmapname = \"estu\";\n\n\t\t\t// crap for now, need to fill this in with the correct data...\n\t\t\tgame_mode_descriptor.default_health = 100;\n\t\t\tgame_mode_descriptor.desired_mode = \"sp\";\n\t\t\tgame_mode_descriptor.select_pig = false;\n\t\t\tgame_mode_descriptor.turn_time = 60;\n\t\t\tgame_mode_descriptor.sudden_death = false;\n\n\t\t\tPlayer *enemy = new Player( PlayerType::COMPUTER );\n\t\t\tunsigned int enemy_team = selectedTeamNum + 1;\n\t\t\tif ( enemy_team >= teams.size() ) {\n\t\t\t\tenemy->SetTeam( teams[ enemy_team - 2 ] );\n\t\t\t} else {\n\t\t\t\tenemy->SetTeam( teams[ enemy_team ] );\n\t\t\t}\n\n\t\t\tplayers.push_back( enemy );\n\t\t} else {\n\t\t\tmapname = \"camp\";\n\t\t\t// crap for now, need to fill this in with the correct data...\n\t\t\tgame_mode_descriptor.default_health = 100;\n\t\t\tgame_mode_descriptor.desired_mode = \"sp\";\n\t\t\tgame_mode_descriptor.select_pig = false;\n\t\t\tgame_mode_descriptor.turn_time = 60;\n\t\t\tgame_mode_descriptor.sudden_death = false;\n\t\t}\n\n\t\tGetApp()->gameManager->StartMode( mapname, players, game_mode_descriptor );\n\n\t\tSetWindowStatus( false );\n\t}\n\tImGui::SameLine();\n\tif ( ImGui::Button( \"Cancel\" ) ) {\n\t\tSetWindowStatus( false );\n\t}\n\tImGui::End();\n}\n"
  },
  {
    "path": "src/engine/editor/NewGameWindow.h",
    "content": "/* OpenHoW\n * Copyright (C) 2017-2020 TalonBrave.info and Others (see CONTRIBUTORS)\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#pragma once\n\n#include \"BaseWindow.h\"\n\nclass NewGameWindow : public BaseWindow {\npublic:\n\n\tvoid Display() override;\n\nprotected:\nprivate:\n\tchar teamName[32]{ '\\0' };\n\tbool playTrainingMission{ true };\n\n\tPlayerTeam selectedTeam;\n};\n"
  },
  {
    "path": "src/engine/editor/NewMapWindow.cpp",
    "content": "/* OpenHoW\n * Copyright (C) 2017-2020 TalonBrave.info and Others (see CONTRIBUTORS)\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include <imgui.h>\n\n#include \"App.h\"\n#include \"NewMapWindow.h\"\n\nusing namespace ohw;\n\nvoid NewMapWindow::Display() {\n\tImGui::SetNextWindowSize( ImVec2( 256, 128 ), ImGuiCond_Once );\n\tImGui::Begin( \"New Map\", &status_, ED_DEFAULT_WINDOW_FLAGS );\n\tImGui::InputText( \"Name\", name_buffer_, sizeof( name_buffer_ ) );\n\t//ImGui::InputText(\"Author\", author_buffer_, sizeof(author_buffer_));\n\tImGui::Separator();\n\tif ( ImGui::Button( \"Create\" ) ) {\n\t\tGetApp()->gameManager->CreateManifest( name_buffer_ );\n\t\tGetApp()->gameManager->LoadMap( name_buffer_ );\n\t\tSetWindowStatus( false );\n\t}\n\tImGui::SameLine();\n\tif ( ImGui::Button( \"Cancel\" ) ) {\n\t\tSetWindowStatus( false );\n\t}\n\tImGui::End();\n}\n"
  },
  {
    "path": "src/engine/editor/NewMapWindow.h",
    "content": "/* OpenHoW\n * Copyright (C) 2017-2020 TalonBrave.info and Others (see CONTRIBUTORS)\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#pragma once\n\n#include \"BaseWindow.h\"\n\nclass NewMapWindow : public BaseWindow {\n public:\n\n  void Display() override;\n\n protected:\n private:\n  char name_buffer_[32]{'\\0'};\n  char author_buffer_[32]{'\\0'};\n};\n"
  },
  {
    "path": "src/engine/editor/ParticleEditor.cpp",
    "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// Copyright © 2017-2022 TalonBrave.info and Others (see CONTRIBUTORS)\n\n#include \"App.h\"\n#include \"graphics/ShaderManager.h\"\n#include \"graphics/ParticleEffect.h\"\n#include \"graphics/ParticleEmitter.h\"\n#include \"graphics/Camera.h\"\n#include \"Language.h\"\n#include \"imgui_layer.h\"\n\n#include \"ParticleEditor.h\"\n\n#define VIEWER_WIDTH  640\n#define VIEWER_HEIGHT 480\n\nstd::list< std::string > ohw::ParticleEditor::particleList;\n\nohw::ParticleEditor::ParticleEditor() : BaseWindow() {\n\tcamera = new Camera( { -2500.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f } );\n\tcamera->SetViewport( 0, 0, VIEWER_WIDTH, VIEWER_HEIGHT );\n\n\tGenerateFrameBuffer( VIEWER_WIDTH, VIEWER_HEIGHT );\n}\n\nohw::ParticleEditor::~ParticleEditor() {\n\tdelete particleEffect;\n\n\tPlgDestroyTexture( textureAttachment );\n\tPlgDestroyFrameBuffer( drawBuffer );\n}\n\nvoid ohw::ParticleEditor::DrawViewport() {\n\tPlgBindFrameBuffer( drawBuffer, PLG_FRAMEBUFFER_DRAW );\n\n\tPlgSetDepthBufferMode( PLG_DEPTHBUFFER_ENABLE );\n\n\tPlgSetClearColour( { 0, 0, 0, 0 } );\n\tPlgClearBuffers( PLG_BUFFER_COLOUR | PLG_BUFFER_DEPTH );\n\n\tunsigned int width, height;\n\tPlgGetFrameBufferResolution( drawBuffer, &width, &height );\n\n\tcamera->SetViewport( 0, 0, width, height );\n\tcamera->MakeActive();\n\n\thei::Vector3 angles(\n\t\t\tPlDegreesToRadians( modelRotation.x ),\n\t\t\tPlDegreesToRadians( modelRotation.y ),\n\t\t\tPlDegreesToRadians( modelRotation.z ) );\n\n\tif ( viewGrid ) {\n\t\tShaderProgram *shaderProgram = Shaders_GetProgram( \"generic_untextured\" );\n\t\tshaderProgram->Enable();\n\n\t\tPlMatrixMode( PL_MODELVIEW_MATRIX );\n\t\tPlPushMatrix();\n\t\tPlLoadIdentityMatrix();\n\n\t\tPlRotateMatrix( PlDegreesToRadians( modelRotation.z + 90.0f ), 1, 0, 0 );\n\t\tPlRotateMatrix( angles.y, 0, 1, 0 );\n\t\tPlRotateMatrix( angles.x, 0, 0, 1 );\n\n\t\tPlgDrawGrid( -512, -512, 1024, 1024, 32 );\n\n\t\tPlPopMatrix();\n\t}\n\n\tif ( particleEffect == nullptr ) {\n\t\t// Fallback to default\n\t\tPlgBindFrameBuffer( nullptr, PLG_FRAMEBUFFER_DRAW );\n\t\treturn;\n\t}\n}\n\nvoid ohw::ParticleEditor::Display() {\n\tDrawViewport();\n\n\tunsigned int flags =\n\t\t\tImGuiWindowFlags_MenuBar |\n\t\t\tImGuiWindowFlags_NoScrollWithMouse |\n\t\t\tImGuiWindowFlags_NoScrollbar |\n\t\t\tImGuiWindowFlags_NoSavedSettings;\n\tImGui::SetNextWindowSize( ImVec2( VIEWER_WIDTH, VIEWER_HEIGHT ), ImGuiCond_Once );\n\n\tBegin( lm_gtr( \"$window_particle_editor\" ), flags );\n\n\tif ( ImGui::BeginMenuBar() ) {\n\t\tif ( ImGui::BeginMenu( lm_gtr( \"$file\" ) ) ) {\n\t\t\tif ( ImGui::BeginMenu( lm_gtr( \"$open\" ) ) ) {\n\t\t\t\tstatic ImGuiTextFilter filter;\n\t\t\t\tfilter.Draw();\n\n\t\t\t\tfor ( const auto &i: particleList ) {\n\t\t\t\t\tif ( !filter.PassFilter( i.c_str() ) ) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tbool selected = false;\n\t\t\t\t\tif ( particleEffect != nullptr ) {\n\t\t\t\t\t\tselected = ( i == particleEffect->GetPath() );\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( ImGui::Selectable( i.c_str(), selected ) ) {\n\t\t\t\t\t\tdelete particleEffect;\n\t\t\t\t\t\tparticleEffect = nullptr;\n\n#if 0\n\t\t\t\t\t\tmodelPtr = plLoadModel( i.c_str() );\n\t\t\t\t\t\tif ( modelPtr == nullptr ) {\n\t\t\t\t\t\t\tLogWarn( \"Failed to load \\\"%s\\\" (%s)!\\n\", i.c_str(), plGetError() );\n\t\t\t\t\t\t}\n#endif\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tImGui::EndMenu();\n\t\t\t}\n\t\t}\n\t}\n\n\tImGui::End();\n}\n\nvoid ohw::ParticleEditor::GenerateFrameBuffer( unsigned int width, unsigned int height ) {\n\tunsigned int bufferWidth = 0, bufferHeight = 0;\n\tif ( drawBuffer != nullptr ) {\n\t\tPlgGetFrameBufferResolution( drawBuffer, &bufferWidth, &bufferHeight );\n\t}\n\n\tif ( bufferWidth != width || bufferHeight != height ) {\n\t\tPlgDestroyFrameBuffer( drawBuffer );\n\t\tdrawBuffer = PlgCreateFrameBuffer( width, height, PLG_BUFFER_COLOUR | PLG_BUFFER_DEPTH );\n\t\tif ( drawBuffer == nullptr ) {\n\t\t\tError( \"Failed to create framebuffer for model viewer (%s)!\\n\", PlGetError() );\n\t\t}\n\n\t\tPlgDestroyTexture( textureAttachment );\n\t\ttextureAttachment = PlgGetFrameBufferTextureAttachment( drawBuffer, PLG_BUFFER_COLOUR, PLG_TEXTURE_FILTER_LINEAR );\n\t\tif ( textureAttachment == nullptr ) {\n\t\t\tError( \"Failed to create texture attachment for buffer (%s)!\\n\", PlGetError() );\n\t\t}\n\t}\n\n\tPlgBindFrameBuffer( nullptr, PLG_FRAMEBUFFER_DRAW );\n}\n"
  },
  {
    "path": "src/engine/editor/ParticleEditor.h",
    "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// Copyright © 2017-2022 TalonBrave.info and Others (see CONTRIBUTORS)\n\n#pragma once\n\n#include \"BaseWindow.h\"\n\nclass ParticleEffect;\n\nnamespace ohw {\n\tclass Camera;\n\n\tclass ParticleEditor : public BaseWindow {\n\tpublic:\n\t\texplicit ParticleEditor();\n\t\t~ParticleEditor() override;\n\n\t\tvoid Display() override;\n\t\tvoid DrawViewport();\n\n\tprivate:\n\t\tvoid GenerateFrameBuffer( unsigned int width, unsigned int height );\n\n\t\tParticleEffect *particleEffect{ nullptr };\n\n\t\tstruct PLGFrameBuffer *drawBuffer{ nullptr };\n\t\tstruct PLGTexture *textureAttachment{ nullptr };\n\n\t\tCamera *camera{ nullptr };\n\n\t\tPLVector3 modelRotation{ 0, 0, 0 };\n\n\t\tfloat oldMousePos[ 2 ]{ 0, 0 };\n\n\t\tbool viewRotate{ true };\n\t\tbool viewDebugNormals{ false };\n\t\tbool viewGrid{ true };\n\n\t\tstatic void AppendParticleList( const char *path );\n\t\tstatic std::list< std::string > particleList;\n\t};\n}\n"
  },
  {
    "path": "src/engine/editor/TerrainImportWindow.cpp",
    "content": "/* OpenHoW\n * Copyright (C) 2017-2020 TalonBrave.info and Others (see CONTRIBUTORS)\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include <imgui.h>\n\n#include \"App.h\"\n#include \"Map.h\"\n#include \"Terrain.h\"\n\n#include \"TerrainImportWindow.h\"\n\nusing namespace ohw;\n\nTerrainImportWindow::TerrainImportWindow() = default;\nTerrainImportWindow::~TerrainImportWindow() = default;\n\nvoid TerrainImportWindow::Display() {\n\tImGui::SetNextWindowSize( ImVec2( 310, 128 ), ImGuiCond_Once );\n\tBegin( \"Import Heightmap\", ED_DEFAULT_WINDOW_FLAGS );\n\tImGui::InputText( \"Path\", path_buffer, sizeof( path_buffer ) );\n\tImGui::InputInt( \"Multiplier\", &multiplier_ );\n\tif ( ImGui::Button( \"Import\" ) ) {\n\t\tImportTerrain();\n\t}\n\tImGui::SameLine();\n\tif ( ImGui::Button( \"Cancel\" ) ) {\n\t\tSetWindowStatus( false );\n\t}\n\tImGui::End();\n}\n\nvoid TerrainImportWindow::ImportTerrain() {\n\tMap *map = GetApp()->gameManager->GetCurrentMap();\n\tif ( map == nullptr ) {\n\t\treturn;\n\t}\n\n\tTerrain *terrain = map->GetTerrain();\n\tif ( terrain == nullptr ) {\n\t\treturn;\n\t}\n\n\tterrain->LoadHeightmap( path_buffer, multiplier_ );\n}\n"
  },
  {
    "path": "src/engine/editor/TerrainImportWindow.h",
    "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// Copyright © 2017-2022 TalonBrave.info and Others (see CONTRIBUTORS)\n\n#pragma once\n\n#include \"BaseWindow.h\"\n\nclass TerrainImportWindow : public BaseWindow {\npublic:\n\tTerrainImportWindow();\n\t~TerrainImportWindow() override;\n\n\tvoid Display() override;\n\nprotected:\nprivate:\n\tvoid ImportTerrain();\n\n\tint multiplier_{ 128 };\n\n\tchar path_buffer[32]{ '\\0' };\n};"
  },
  {
    "path": "src/engine/editor/TexturePicker.cpp",
    "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// Copyright © 2017-2022 TalonBrave.info and Others (see CONTRIBUTORS)\n\n#include \"App.h\"\n#include \"TexturePicker.h\"\n#include \"imgui_layer.h\"\n\nohw::TexturePicker::TexturePicker() : BaseWindow() {\n\tstd::string mapDir = GetApp()->gameManager->GetCurrentMapDirectory();\n\tif ( mapDir.empty() ) {\n\t\treturn;\n\t}\n\n\tmapDir.append( \"tiles/\" );\n\n\tunsigned int numFormats;\n\tconst char **formatExtensions = PlGetSupportedImageFormats( &numFormats );\n\n\tfor ( unsigned int i = 0;; ++i ) {\n\t\tbool indexLoaded = false;\n\t\tfor ( unsigned int j = 0; j < numFormats; ++j ) {\n\t\t\tstd::string texturePath = mapDir + std::to_string( i ) + \".\" + formatExtensions[ j ];\n\t\t\tif ( PlFileExists( texturePath.c_str() ) ) {\n\t\t\t\tSharedTextureResourcePointer sharedTexture = GetApp()->resourceManager->LoadTexture(\n\t\t\t\t\t\ttexturePath,\n\t\t\t\t\t\tTextureResource::FLAG_NOMIPS | TextureResource::FLAG_NEAREST\n\t\t\t\t);\n\t\t\t\ttextures.push_back( sharedTexture );\n\t\t\t\tindexLoaded = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t// Failed to load the index? Assume it's the end. (let's do this better in future)\n\t\tif ( !indexLoaded ) {\n\t\t\tPrint( \"Didn't find texture index %d. Assuming end of tiles list!\\n\", i );\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\nohw::TexturePicker::~TexturePicker() {\n\ttextures.clear();\n}\n\nvoid ohw::TexturePicker::Display() {\n\tImGui::SetNextWindowSize( ImVec2( 348, 512 ), ImGuiCond_Once );\n\n\tunsigned int flags =\n\t\t\tImGuiWindowFlags_MenuBar |\n\t\t\tImGuiWindowFlags_NoScrollWithMouse |\n\t\t\tImGuiWindowFlags_NoResize |\n\t\t\tImGuiWindowFlags_NoSavedSettings;\n\tBegin( \"Texture Picker\", flags );\n\n\tif ( ImGui::BeginMenuBar() ) {\n\t\tif ( ImGui::BeginMenu( \"Sets\" ) ) {\n#if 0\n\t\t\tstatic ImGuiTextFilter filter;\n\t\t\tfilter.Draw();\n\n\t\t\t// todo: provide a list of all available tile sets\n#endif\n\t\t\tImGui::EndMenu();\n\t\t}\n\n\t\tImGui::Separator();\n\n\t\tImGui::Text( \"Set: %s\", \"Blah\" );\n\t\tImGui::Text( \"Tiles: %u\", ( unsigned int ) textures.size() );\n\n\t\tImGui::EndMenuBar();\n\t}\n\n#define TEXTURES_PER_ROW 4\n\tfor ( unsigned int i = 0, j = 0; i < textures.size(); ++i, ++j ) {\n\t\tif ( j >= TEXTURES_PER_ROW ) {\n\t\t\tImGui::NewLine();\n\t\t\tj = 0;\n\t\t}\n\n\t\tImTextureID textureId = reinterpret_cast< ImTextureID >(textures[ i ]->GetInternalTexture()->internal.id);\n\n\t\tImGui::ImageButton( textureId, ImVec2( 64, 64 ) );\n\t\tImGui::SameLine();\n\t}\n\n\tImGui::End();\n}\n"
  },
  {
    "path": "src/engine/editor/TexturePicker.h",
    "content": "/* OpenHoW\n * Copyright (C) 2017-2020 TalonBrave.info and Others (see CONTRIBUTORS)\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#pragma once\n\n#include \"BaseWindow.h\"\n\nnamespace ohw {\n\tclass TexturePicker : public BaseWindow {\n\tpublic:\n\t\tTexturePicker();\n\t\t~TexturePicker();\n\n\t\tvoid Display() override;\n\n\tprivate:\n\t\tstd::vector< SharedTextureResourcePointer > textures;\n\t};\n}\n"
  },
  {
    "path": "src/engine/editor/TextureViewer.h",
    "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// Copyright © 2017-2022 TalonBrave.info and Others (see CONTRIBUTORS)\n\n#include \"BaseWindow.h\"\n\nclass TextureViewer : public BaseWindow {\npublic:\n\texplicit TextureViewer( ohw::TextureResource *texture ) : BaseWindow() {\n\t\ttexturePtr = texture;\n\t\ttexturePtr->AddReference();\n\t}\n\n\texplicit TextureViewer( const std::string &path ) {\n\t\ttexturePtr = ohw::GetApp()->resourceManager->LoadTexture( path, ohw::TextureResource::FLAG_NOMIPS );\n\t\tif ( texturePtr == nullptr ) {\n\t\t\tthrow std::runtime_error( \"Failed to load specified texture, \\\"\" + path + \"\\\" (\" + PlGetError() + \")!\" );\n\t\t}\n\n\t\ttexturePath = path;\n\t}\n\n\t~TextureViewer() override {\n\t\tif ( texturePtr != nullptr ) {\n\t\t\ttexturePtr->Release();\n\t\t}\n\t}\n\n\tvoid ReloadTexture( PLGTextureFilter filter_mode ) {\n\t\tif ( texturePath.empty() || filter_mode == filterMode ) {\n\t\t\treturn;\n\t\t}\n\n\t\ttexturePtr->Release();\n\t\tohw::GetApp()->resourceManager->ClearAllResources();\n\n\t\ttexturePtr = ohw::GetApp()->resourceManager->LoadTexture( texturePath, filter_mode );\n\t\tfilterMode = filter_mode;\n\t}\n\n\tvoid Display() override {\n\t\tunsigned int texWidth = texturePtr->GetWidth();\n\t\tunsigned int texHeight = texturePtr->GetHeight();\n\n\t\tImGui::SetNextWindowSize( ImVec2( texWidth + 64, texHeight + 128 ), ImGuiCond_Once );\n\t\tBegin( \"Texture Viewer\",\n\t\t\t   ImGuiWindowFlags_MenuBar |\n\t\t\t\t   ImGuiWindowFlags_HorizontalScrollbar |\n\t\t\t\t   ImGuiWindowFlags_NoSavedSettings\n\t\t);\n\n\t\tif ( ImGui::BeginMenuBar() ) {\n\t\t\tif ( ImGui::BeginMenu( \"View\" ) ) {\n\t\t\t\tImGui::SliderInt( \"Scale\", &scale_, 1, 8 );\n\t\t\t\tif ( ImGui::BeginMenu( \"Filter Mode\" ) ) {\n\t\t\t\t\tif ( ImGui::MenuItem( \"Linear\", nullptr, ( filterMode == PLG_TEXTURE_FILTER_LINEAR ) ) ) {\n\t\t\t\t\t\tReloadTexture( PLG_TEXTURE_FILTER_LINEAR );\n\t\t\t\t\t}\n\t\t\t\t\tif ( ImGui::MenuItem( \"Nearest\", nullptr, ( filterMode == PLG_TEXTURE_FILTER_NEAREST ) ) ) {\n\t\t\t\t\t\tReloadTexture( PLG_TEXTURE_FILTER_NEAREST );\n\t\t\t\t\t}\n\t\t\t\t\tImGui::EndMenu();\n\t\t\t\t}\n\t\t\t\tImGui::EndMenu();\n\t\t\t}\n\t\t\tImGui::EndMenuBar();\n\t\t}\n\n\t\tunsigned int internalId = texturePtr->GetInternalTexture()->internal.id;\n\t\tImGui::Image( reinterpret_cast<ImTextureID>( internalId ), ImVec2( texWidth * scale_, texHeight * scale_ ) );\n\t\tImGui::Separator();\n\t\tImGui::Text( \"Path: %s\", texturePath.c_str() );\n\t\tImGui::Text( \"%dx%d\", texWidth, texHeight );\n\t\tsize_t texSize = texturePtr->GetTextureSize();\n\t\tImGui::Text( \"Size: %ukB (%luB)\", ( unsigned int ) PlBytesToKilobytes( texSize ), ( long unsigned ) texSize );\n\n\t\tImGui::End();\n\t}\n\nprotected:\nprivate:\n\tohw::TextureResource *texturePtr{ nullptr };\n\tstd::string texturePath;\n\n\tPLGTextureFilter filterMode{ PLG_TEXTURE_FILTER_LINEAR };\n\n\tint scale_{ 1 };\n};\n"
  },
  {
    "path": "src/engine/game/AAirship.cpp",
    "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// Copyright © 2017-2022 TalonBrave.info and Others (see CONTRIBUTORS)\n\n#include \"App.h\"\n#include \"ActorManager.h\"\n#include \"AAirship.h\"\n#include \"Map.h\"\n\nREGISTER_ACTOR_BASIC( AAirship )\n\nusing namespace ohw;\n\n#define AIRSHIP_SPEED       16.0f\n#define AIRSHIP_TURN_LIMIT  32\n\nAAirship::AAirship() : SuperClass() {}\nAAirship::~AAirship() = default;\n\nvoid AAirship::Tick() {\n\tSuperClass::Tick();\n\n\tMap *map = ohw::GetApp()->gameManager->GetCurrentMap();\n\tif ( map == nullptr ) {\n\t\treturn;\n\t}\n\n\thei::Vector3 position = GetPosition();\n\thei::Vector3 airshipToDestination = myDestination - position;\n\tfloat distance = airshipToDestination.Length();\n\tif ( distance < myDestinationTolerance ) {\n\t\t// Set a destination for us to start heading towards.\n\t\tPLVector2 point = map->GetRandomPointInPlayArea();\n\t\tmyDestination = hei::Vector3( point.x, GetHeight(), point.y );\n\t\tDebugMsg( \"Set destination at %s\\n\", PlPrintVector3( &myDestination, PL_VAR_I32 ) );\n\n\t\tmyDestinationTolerance = 5.0f;\n\t\tmyTurnFrames = 0;\n\t\treturn;\n\t}\n\n\tPLVector3 angles = GetAngles();\n\tfloat curAngle = std::atan2( myForward.z, myForward.x );\n\tfloat targetAngle = std::atan2( airshipToDestination.z, airshipToDestination.x );\n\tfloat deltaAngle = targetAngle - curAngle;\n\tif ( std::abs( deltaAngle ) > ( PL_PI / 8.0f ) ) {\n\t\tangles.y = myTurnSpeed;\n\t\tangles.z++;\n\t\tangles.z = std::min( angles.z, 45.0f );\n\n\t\t// Increase tolerance after X frames to avoid infinite circling\n\t\tif ( ++myTurnFrames > AIRSHIP_TURN_LIMIT ) {\n\t\t\tmyDestinationTolerance *= 2.0f;\n\t\t\tmyTurnFrames = 0;\n\t\t}\n\t} else {\n\t\tangles.y = 0;\n\t\tangles.z--;\n\t\tangles.z = std::max( angles.z, -45.0f );\n\t}\n\n\tSetAngles( angles );\n\n\tposition += myForward * AIRSHIP_SPEED;\n\tSetPosition( position );\n\n\tGetApp()->GetDisplay()->DebugDrawLine( position_, myDestination, PL_COLOUR_RED );\n}\n\nvoid AAirship::Deserialize( const ActorSpawn &spawn ) {\n\tSuperClass::Deserialize( spawn );\n\n\tSetModel( \"scenery/airship1.vtx\" );\n\tSetAngles( { 180.0f, 0.0f, 0.0f } );\n\n\tShowModel( true );\n\n\tMap *map = ohw::GetApp()->gameManager->GetCurrentMap();\n\tif ( map == nullptr ) {\n\t\treturn;\n\t}\n\n\tPLVector2 point;\n\t// Set us up wherever\n\tpoint = map->GetRandomPointInPlayArea();\n\tSetPosition( hei::Vector3( point.x, map->GetTerrain()->GetMaxHeight(), point.y ) );\n\t// Set a destination for us to start heading towards.\n\tpoint = map->GetRandomPointInPlayArea();\n\tmyDestination = hei::Vector3( point.x, GetHeight(), point.y );\n}\n"
  },
  {
    "path": "src/engine/game/AAirship.h",
    "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// Copyright © 2017-2022 TalonBrave.info and Others (see CONTRIBUTORS)\n\n#pragma once\n\n#include \"AVehicle.h\"\n\nclass AAirship : public AVehicle {\n\tIMPLEMENT_ACTOR( AAirship, AVehicle )\n\npublic:\n\tAAirship();\n\t~AAirship() override;\n\n\tvoid Tick() override;\n\n\tvoid Deserialize( const ActorSpawn &spawn ) override;\n\n\tinline unsigned int GetMaxOccupants() const override { return 0; }\n\tinline const char *GetEngineIdleSound() const override { return \"audio/en_bip.wav\";\t}\n\nprotected:\nprivate:\n\thei::Vector3 myDestination;\n\tfloat myDestinationTolerance{ 0.0f };\n\tfloat myTurnSpeed{ 0.0f };\n\tunsigned int myTurnFrames{ 0 };\n};"
  },
  {
    "path": "src/engine/game/AAnimatedModel.cpp",
    "content": "/* OpenHoW\n * Copyright (C) 2017-2020 TalonBrave.info and Others (see CONTRIBUTORS)\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include \"App.h\"\n#include \"AAnimatedModel.h\"\n\nAAnimatedModel::AAnimatedModel() : SuperClass() {}\nAAnimatedModel::~AAnimatedModel() = default;\n\nvoid AAnimatedModel::Deserialize( const ActorSpawn &spawn ) {\n\tSuperClass::Deserialize( spawn );\n}\n"
  },
  {
    "path": "src/engine/game/AAnimatedModel.h",
    "content": "/* OpenHoW\n * Copyright (C) 2017-2020 TalonBrave.info and Others (see CONTRIBUTORS)\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#pragma once\n\n#include \"Actor.h\"\n#include \"AModel.h\"\n\nclass AAnimatedModel : public AModel {\n\tIMPLEMENT_ACTOR( AAnimatedModel, AModel )\n\npublic:\n\tAAnimatedModel();\n\t~AAnimatedModel() override;\n\n\tvoid Deserialize( const ActorSpawn &spawn ) override;\n\nprotected:\nprivate:\n};\n"
  },
  {
    "path": "src/engine/game/AHealthPickup.cpp",
    "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// Copyright © 2017-2022 TalonBrave.info and Others (see CONTRIBUTORS)\n\n#include \"App.h\"\n#include \"Menu.h\"\n#include \"ActorManager.h\"\n#include \"APig.h\"\n\nclass AHealthPickup : public AModel {\n\tIMPLEMENT_ACTOR( AHealthPickup, AModel )\n\npublic:\n\tAHealthPickup();\n\t~AHealthPickup() override;\n\n\tvoid Touch( Actor *other ) override;\n\n\tbool IsVisibleOnMinimap() const override { return true; }\n\tunsigned int GetMinimapIconStyle() const override { return MINIMAP_ICON_HEALTH; }\n\tPLColour GetMinimapIconColour() const override { return hei::Colour( 255, 192, 203 ); }\n\nprotected:\nprivate:\n\tunsigned int myPickupQuantity{ 0 };\n};\n\nREGISTER_ACTOR( crate2, AHealthPickup )\n\nusing namespace ohw;\n\nAHealthPickup::AHealthPickup() : SuperClass() {}\nAHealthPickup::~AHealthPickup() = default;\n\nvoid AHealthPickup::Touch( Actor *other ) {\n\tSuperClass::Touch( other );\n\n\tAPig *pig = dynamic_cast<APig *>(other);\n\tif ( pig == nullptr ) {\n\t\t// only pigs should be able to pick these up!\n\t\treturn;\n\t}\n\n\tpig->AddHealth( myPickupQuantity );\n\n\t// may want to introduce networking logic here for actor destruction\n\t// hence why it's done this way for now\n\tActorManager::GetInstance()->DestroyActor( this );\n}\n"
  },
  {
    "path": "src/engine/game/AItemPickup.cpp",
    "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// Copyright © 2017-2022 TalonBrave.info and Others (see CONTRIBUTORS)\n\n#include \"App.h\"\n#include \"Menu.h\"\n#include \"ActorManager.h\"\n#include \"Inventory.h\"\n#include \"APig.h\"\n\nclass AItemPickup : public AModel {\n\tIMPLEMENT_ACTOR( AItemPickup, AModel )\n\npublic:\n\tAItemPickup();\n\t~AItemPickup() override;\n\n\tvoid Touch( Actor *other ) override;\n\n\tbool IsVisibleOnMinimap() const override { return true; }\n\tunsigned int GetMinimapIconStyle() const override { return MINIMAP_ICON_PICKUP; }\n\tPLColour GetMinimapIconColour() const override { return hei::Colour( 210, 105, 30 ); }\n\nprivate:\n\tItemIdentifier myPickupId{ ItemIdentifier::NONE };\n\tunsigned int myPickupQuantity{ 0 };\n};\n\nAItemPickup::AItemPickup() : SuperClass() {}\nAItemPickup::~AItemPickup() = default;\n\nvoid AItemPickup::Touch( Actor *other ) {\n\tSuperClass::Touch( other );\n\n\tAPig *pig = dynamic_cast<APig *>(other);\n\tif ( pig == nullptr ) {\n\t\t// only pigs should be able to pick these up!\n\t\treturn;\n\t}\n\n\tpig->AddInventoryItem( myPickupId, myPickupQuantity );\n\n#if 0\n\t// On pickup, we'll need to pass the item into\n\t// the pig's inventory\n\tswitch(pickup_id_) {\n\t  default:break;\n\t  case ItemId::WEAPON_TROTTER:break;\n\t  case ItemId::WEAPON_KNIFE:break;\n\t  case ItemId::WEAPON_BAYONET:break;\n\t  case ItemId::WEAPON_SWORD:break;\n\t  case ItemId::WEAPON_CATTLEPROD:break;\n\t  case ItemId::WEAPON_PISTOL:break;\n\t  case ItemId::WEAPON_RIFLE:break;\n\t  case ItemId::WEAPON_RIFLE_BURST:break;\n\t  case ItemId::WEAPON_MACHINE_GUN:break;\n\t  case ItemId::WEAPON_HMG:break;\n\t  case ItemId::WEAPON_SNIPER_RIFLE:break;\n\t  case ItemId::WEAPON_SHOTGUN:break;\n\t  case ItemId::WEAPON_FLAMETHROWER:break;\n\t  case ItemId::WEAPON_ROCKET_LAUNCHER:break;\n\t  case ItemId::WEAPON_GUIDED_MISSILE:break;\n\t  case ItemId::MEDICINE_DART:break;\n\t  case ItemId::TRANQ:break;\n\t  case ItemId::GRENADE:break;\n\t  case ItemId::CLUSTER_GRENADE:break;\n\t  case ItemId::HX_GRENADE:break;\n\t  case ItemId::ROLLER_GRENADE:break;\n\t  case ItemId::CONFUSION_GAS:break;\n\t  case ItemId::FREEZE_GAS:break;\n\t  case ItemId::MADNESS_GAS:break;\n\t  case ItemId::POISON_GAS:break;\n\t  case ItemId::MORTAR:break;\n\t  case ItemId::BAZOOKA:break;\n\t  case ItemId::AIRBURST:break;\n\t  case ItemId::SUPER_AIRBURST:break;\n\t  case ItemId::MEDICINE_BALL:break;\n\t  case ItemId::HOMING_MISSILE:break;\n\t  case ItemId::MINE:break;\n\t  case ItemId::AntiPMine:break;\n\t  case ItemId::TNT:break;\n\t  case ItemId::VEHICLE_LongRangeShell:break;\n\t  case ItemId::VEHICLE_ShockShell:break;\n\t  case ItemId::VEHICLE_1000LBSShell:break;\n\t  case ItemId::VEHICLE_FireShell:break;\n\t  case ItemId::VEHICLE_GasShell:break;\n\t  case ItemId::VEHICLE_MineShell:break;\n\t  case ItemId::VEHICLE_HeavyMachineGun:break;\n\t  case ItemId::VEHICLE_Flamethrower:break;\n\t  case ItemId::VEHICLE_AIRBURST:break;\n\t  case ItemId::VEHICLE_BAZOOKA:break;\n\t  case ItemId::VEHICLE_MORTAR:break;\n\t  case ItemId::JETPACK:break;\n\t  case ItemId::SUICIDE:break;\n\t  case ItemId::HEALINGHANDS:break;\n\t  case ItemId::SELFHEAL:break;\n\t  case ItemId::PICKPOCKET:break;\n\t  case ItemId::SHOCKWAVE:break;\n\t  case ItemId::SPECIALOPS:break;\n\t  case ItemId::AIRSTRIKE:break;\n\t  case ItemId::FireRainAirstrike:break;\n\t  case ItemId::ENTERVEHICLE:break;\n\t  case ItemId::ENTERBUILDING:break;\n\t  case ItemId::EJECTPIG:break;\n\t  case ItemId::MAPVIEW:break;\n\t  case ItemId::BINOCULARS:break;\n\t  case ItemId::SKIPTURN:break;\n\t  case ItemId::SURRENDER:break;\n\t  case ItemId::SUPERTNT:break;\n\t  case ItemId::HIDE:break;\n\t  case ItemId::SUPERSHOTGUN:break;\n\t  case ItemId::SHRAPNELGRENADE:break;\n\t  case ItemId::GRENADELAUNCHER:break;\n\t  case ItemId::RANDOM:break;\n\t  case ItemId::HEALTH:break;\n\t}\n#endif\n\n\t// may want to introduce networking logic here for actor destruction\n\t// hence why it's done this way for now\n\tActorManager::GetInstance()->DestroyActor( this );\n}\n"
  },
  {
    "path": "src/engine/game/AModel.cpp",
    "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// Copyright © 2017-2022 TalonBrave.info and Others (see CONTRIBUTORS)\n\n#include \"App.h\"\n#include \"AModel.h\"\n\nusing namespace ohw;\n\nAModel::AModel() : SuperClass(),\n                   INIT_PROPERTY( modelPath, PROP_LOCAL ) {}\nAModel::~AModel() = default;\n\nvoid AModel::Draw() {\n\tSuperClass::Draw();\n\n\tif ( !show_model_ || model == nullptr ) {\n\t\treturn;\n\t}\n\n\thei::Vector3 angles(\n\t\t\tPlDegreesToRadians( myAngles.GetValue().x ),\n\t\t\tPlDegreesToRadians( myAngles.GetValue().y ),\n\t\t\tPlDegreesToRadians( myAngles.GetValue().z ) );\n\n\thei::Matrix4 mat;\n\tmat.Identity();\n\tmat.Rotate( angles.z, { 1, 0, 0 } );\n\tmat.Rotate( -angles.y, { 0, 1, 0 } );\n\tmat.Rotate( angles.x, { 0, 0, 1 } );\n\tmat.Translate( position_ );\n\n\tmodel->modelMatrix = mat;\n\tmodel->Draw();\n}\n\nvoid AModel::SetModel( const std::string &path ) {\n\tmodel = GetApp()->resourceManager->LoadModel( \"chars/\" + path, false );\n\tu_assert( model != nullptr );\n\n\t// Keep model path up-to-date\n\tmodelPath = model->GetPath();\n}\n\nvoid AModel::ShowModel( bool show ) {\n\tshow_model_ = show;\n}\n"
  },
  {
    "path": "src/engine/game/AModel.h",
    "content": "/* OpenHoW\n * Copyright (C) 2017-2020 TalonBrave.info and Others (see CONTRIBUTORS)\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#pragma once\n\n#include \"Actor.h\"\n\nclass AModel : public Actor {\n\tIMPLEMENT_ACTOR( AModel, Actor )\n\npublic:\n\tAModel();\n\t~AModel() override;\n\n\tvoid Draw() override;\n\tvoid ShowModel( bool show = true );\n\n\tvoid SetModel( const std::string &path );\n\nprotected:\n\tohw::SharedModelResourcePointer model{ nullptr };\n\nprivate:\n\tbool show_model_{ true };\n\n\tStringProperty modelPath;\n};\n"
  },
  {
    "path": "src/engine/game/AParachuteWeapon.cpp",
    "content": "/* OpenHoW\n * Copyright (C) 2017-2020 TalonBrave.info and Others (see CONTRIBUTORS)\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include \"App.h\"\n#include \"ActorManager.h\"\n#include \"AParachuteWeapon.h\"\n\n// Parachute, not really a weapon but hey ho!\n\nREGISTER_ACTOR_BASIC( AParachuteWeapon )\n\nAParachuteWeapon::AParachuteWeapon() : SuperClass() {\n\tSetModel( \"weapons/we_para.vtx\" );\n\tShowModel( false );\n}\n\nAParachuteWeapon::~AParachuteWeapon() = default;\n\nvoid AParachuteWeapon::Tick() {\n\tSuperClass::Tick();\n\n\tif ( !isWeaponDeployed ) {\n\t\treturn;\n\t}\n\n\t/* todo: make parachute noises... */\n}\n\nvoid AParachuteWeapon::Fire( const PLVector3 &pos, const PLVector3 &dir ) {\n\tSuperClass::Fire( pos, dir );\n}\n\nvoid AParachuteWeapon::Deploy() {\n\tSuperClass::Deploy();\n}\n"
  },
  {
    "path": "src/engine/game/AParachuteWeapon.h",
    "content": "/* OpenHoW\n * Copyright (C) 2017-2020 TalonBrave.info and Others (see CONTRIBUTORS)\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#pragma once\n\n#include \"AWeapon.h\"\n\nclass AParachuteWeapon : public AWeapon {\n\tIMPLEMENT_ACTOR( AParachuteWeapon, AWeapon )\n\npublic:\n\tAParachuteWeapon();\n\t~AParachuteWeapon() override;\n\n\tvoid Tick() override;\n\n\tvoid Fire( const PLVector3 &pos, const PLVector3 &dir ) override;\n\tvoid Deploy() override;\n\nprotected:\nprivate:\n};\n"
  },
  {
    "path": "src/engine/game/AParticle.cpp",
    "content": "/* OpenHoW\n * Copyright (C) 2017-2020 TalonBrave.info and Others (see CONTRIBUTORS)\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include \"App.h\"\n#include \"graphics/ParticleEffect.h\"\n#include \"graphics/ParticleEmitter.h\"\n#include \"graphics/particles.h\"\n#include \"ActorManager.h\"\n\nclass AParticleEffect : public Actor {\n\tIMPLEMENT_ACTOR( AParticleEffect, Actor )\n\npublic:\n\tAParticleEffect();\n\t~AParticleEffect() override;\n\n\tvoid Tick() override;\n\tvoid Draw() override;\n\n\tActorSpawn Serialize() override { return ActorSpawn(); }\n\tvoid Deserialize( const ActorSpawn &spawn ) override;\n\nprotected:\nprivate:\n\tohw::ParticleEffect *effect;\n};\n\nREGISTER_ACTOR_BASIC( AParticleEffect )\n\nAParticleEffect::AParticleEffect() : SuperClass() {}\nAParticleEffect::~AParticleEffect() {\n\tdelete effect;\n}\n\nvoid AParticleEffect::Tick() {\n\tSuperClass::Tick();\n\n\teffect->Tick();\n}\n\nvoid AParticleEffect::Draw() {\n\teffect->Draw();\n}\n\nvoid AParticleEffect::Deserialize( const ActorSpawn &spawn ) {\n\tSuperClass::Deserialize( spawn );\n\n\t// TODO: might need to revise the ActorSpawn structure in order for this to work\n}\n"
  },
  {
    "path": "src/engine/game/APig.cpp",
    "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// Copyright © 2017-2022 TalonBrave.info and Others (see CONTRIBUTORS)\n\n#include \"App.h\"\n#include \"Menu.h\"\n#include \"Map.h\"\n#include \"Player.h\"\n#include \"ActorManager.h\"\n#include \"APig.h\"\n\nREGISTER_ACTOR( ac_me, APig )    // Ace\nREGISTER_ACTOR( gr_me, APig )    // Grunt\nREGISTER_ACTOR( hv_me, APig )\nREGISTER_ACTOR( le_me, APig )    // Legend\nREGISTER_ACTOR( me_me, APig )    // Medic\nREGISTER_ACTOR( sa_me, APig )    // Saboteur\nREGISTER_ACTOR( sb_me, APig )    // Commando\nREGISTER_ACTOR( sn_me, APig )    // Sniper\nREGISTER_ACTOR( sp_me, APig )    // Spy\n\nREGISTER_ACTOR_BASIC( APig )\n\nusing namespace ohw;\n\nAPig::APig() : SuperClass() {\n\tspeechEmitter = GetApp()->audioManager->CreateSource();\n}\n\nAPig::~APig() {\n\tdelete speechEmitter;\n}\n\nvoid APig::HandleInput() {\n\tIGameMode *mode = GetApp()->gameManager->GetMode();\n\tif ( mode == nullptr ) {\n\t\treturn;\n\t}\n\n\tPlayer *player = mode->GetCurrentPlayer();\n\tif ( player == nullptr ) {\n\t\treturn;\n\t}\n\n\tif ( GetApp()->inputManager->GetActionState( player->GetControllerSlot(), InputManager::ACTION_JUMP ) ) {\n\t\tJump();\n\t\treturn;\n\t}\n\n\tPLVector2 cl;\n\tGetApp()->inputManager->GetJoystickState( player->GetControllerSlot(), InputManager::JOYSTICK_AXIS_LEFT_STICK, &cl.x, &cl.y );\n\tif ( GetApp()->inputManager->GetActionState( player->GetControllerSlot(), InputManager::ACTION_MOVE_FORWARD ) ) {\n\t\tforwardVelocity = 1.0f;\n\t} else if ( GetApp()->inputManager->GetActionState( player->GetControllerSlot(), InputManager::ACTION_MOVE_BACKWARD ) ) {\n\t\tforwardVelocity = -1.0f;\n\t} else {\n\t\tforwardVelocity = -cl.y / 327.0f;\n\t}\n\n\tPLVector2 cr;\n\tGetApp()->inputManager->GetJoystickState( player->GetControllerSlot(), InputManager::JOYSTICK_AXIS_RIGHT_STICK, &cr.x, &cr.y );\n\tif ( GetApp()->inputManager->GetActionState( player->GetControllerSlot(), InputManager::ACTION_TURN_LEFT ) ) {\n\t\tinputYaw = -1.0f;\n\t} else if ( GetApp()->inputManager->GetActionState( player->GetControllerSlot(), InputManager::ACTION_TURN_RIGHT ) ) {\n\t\tinputYaw = 1.0f;\n\t} else {\n\t\tinputYaw = cr.x / 327.0f;\n\t}\n\n\tif ( GetApp()->inputManager->GetActionState( player->GetControllerSlot(), InputManager::ACTION_AIM_UP ) ) {\n\t\tinputPitch = 1.0f;\n\t} else if ( GetApp()->inputManager->GetActionState( player->GetControllerSlot(), InputManager::ACTION_AIM_DOWN ) ) {\n\t\tinputPitch = -1.0f;\n\t} else {\n\t\tinputPitch = -cr.y / 327.0f;\n\t}\n}\n\nvoid APig::Tick() {\n\tSuperClass::Tick();\n\n\t//float speedModifier = 1.0f;\n\tif ( !IsOnGround() ) {\n\t\tif ( parachuteWeapon->IsDeployed() ) {\n\t\t\t//speedModifier = 10.0f;\n\t\t}\n\n\t\tvelocity.y = -75.0f;\n\t} else {\n\t\t// If we've landed, put it away\n\t\tif ( parachuteWeapon->IsDeployed() ) {\n\t\t\tparachuteWeapon->Holster();\n\t\t}\n\t}\n\n\t// a dead piggy\n\tif ( lifeState == LifeState::DEAD ) {\n\t\treturn;\n\t} else if ( lifeState == LifeState::DYING ) {\n\t\tif ( speechEmitter->IsPlaying() ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// TODO: actor that produces explosion fx (AFXExplosion / effect_explosion) ?\n\t\tGetApp()->audioManager->PlayLocalSound( \"audio/e_1.wav\", GetPosition(), PLVector3(), true );\n\n\t\tSetModel( \"scenery/boots.vtx\" );\n\t\tDropToFloor();\n\n\t\t// todo; create particle emitter and link as child to the boots!\n\t\tlifeState = LifeState::DEAD;\n\t\treturn;\n\t}\n\n\t// Update position\n\n\thei::Vector3 nPosition = GetPosition();\n\n\tPLVector3 forwardDirection;\n\tforwardDirection.x = forwardVelocity * 50.0f * myForward.x;\n\tforwardDirection.y = forwardVelocity * 50.0f * myForward.y;\n\tforwardDirection.z = forwardVelocity * 50.0f * myForward.z;\n\tnPosition += velocity + forwardDirection;\n\n\t// Clamp height based on current tile pos\n\tMap *map = GetApp()->gameManager->GetCurrentMap();\n\tfloat height = map->GetTerrain()->GetHeight( nPosition.x, nPosition.z );\n\tif ( ( nPosition.y - ( boundingBox.maxs.y / 2 ) ) < height ) {\n\t\tnPosition.y = height + ( boundingBox.maxs.y / 2 );\n\t}\n\n\tSetPosition( nPosition );\n\tspeechEmitter->SetPosition( nPosition );\n\n\t// Update angles\n\n\taimPitch += inputPitch * 2.0f;\n#define MAX_PITCH 89.f\n\tif ( aimPitch < -MAX_PITCH ) aimPitch = -MAX_PITCH;\n\tif ( aimPitch > MAX_PITCH ) aimPitch = MAX_PITCH;\n\n\thei::Vector3 nAngles = GetAngles();\n\tnAngles.y += inputYaw * 2.0f;\n\tVecAngleClamp( &nAngles );\n\n\tSetAngles( nAngles );\n}\n\nvoid APig::SetClass( const std::string &classIdentifer ) {\n\tconst CharacterClass *characterClass = GetApp()->gameManager->GetDefaultClass( classIdentifer );\n\tif ( characterClass == nullptr ) {\n\t\tWarning( \"Failed to fetch valid character class for pig!\\n\" );\n\t\treturn;\n\t}\n\n\tSetHealth( characterClass->health );\n\tSetModel( characterClass->model );\n}\n\nvoid APig::SetPersonality( unsigned int personality ) {\n\t// TODO: ensure all the necessary sounds are cached...\n}\n\nvoid APig::SetPlayerOwner( Player *owner ) {\n\tIGameMode *mode = GetApp()->gameManager->GetMode();\n\tif ( mode == nullptr ) {\n\t\tWarning( \"Attempted to set player owner without an active mode!\\n\" );\n\t\treturn;\n\t}\n\n\tmode->AssignActorToPlayer( this, owner );\n\tplayerOwnerPtr = owner;\n}\n\nconst Player *APig::GetPlayerOwner() const {\n\treturn playerOwnerPtr;\n}\n\nvoid APig::SetTeam( unsigned int team ) {\n\tmyTeam = team;\n\n#if 0\n\tPlayer* player = GetApp()->gameManager->GetPlayerByIndex(team);\n\tif(player == nullptr) {\n\t  ActorManager::GetInstance()->DestroyActor(this);\n\t  LogWarn(\"Failed to set team for pig!\\n\");\n\t  return;\n\t}\n\n\tGetApp()->gameManager->GetMode()->AssignActorToPlayer(this, player);\n#endif\n}\n\nvoid APig::Deserialize( const ActorSpawn &spawn ) {\n\tSuperClass::Deserialize( spawn );\n\n\t// Ensure pig is spawned up in the air for deployment\n\tMap *map = GetApp()->gameManager->GetCurrentMap();\n\tSetPosition( { position_.GetValue().x, map->GetTerrain()->GetMaxHeight(), position_.GetValue().z } );\n\n\tSetClass( spawn.className );\n\tSetTeam( spawn.team );\n\n\t// Create and equip our parachute, and then\n\t// link it to ensure it gets destroyed when we do\n\tparachuteWeapon = dynamic_cast<AParachuteWeapon *>(ActorManager::GetInstance()->CreateActor( \"weapon_parachute\" ));\n\tif ( parachuteWeapon == nullptr ) {\n\t\tError( \"Failed to create \\\"weapon_parachute\\\" actor, aborting!\\n\" );\n\t}\n\n\tLinkChild( parachuteWeapon );\n\tparachuteWeapon->SetPosition( GetPosition() );\n\tparachuteWeapon->Deploy();\n}\n\nbool APig::Possessed( const Player *player ) {\n\t// TODO\n\tPlayVoiceSample( VoiceCategory::READY );\n\n\treturn SuperClass::Possessed( player );\n}\n\nvoid APig::Dispossessed(const Player *player ) {\n\t// TODO\n\tSuperClass::Dispossessed(player);\n}\n\nbool APig::IsVisibleOnMinimap() const {\n\t// TODO: handle special cases\n\treturn true;\n}\n\nunsigned int APig::GetMinimapIconStyle() const {\n\treturn MINIMAP_ICON_PIG;\n}\n\nPLColour APig::GetMinimapIconColour() const {\n\tconst Player *player = GetPlayerOwner();\n\tif ( player == nullptr ) {\n\t\treturn Actor::GetMinimapIconColour();\n\t}\n\n\tconst PlayerTeam *team = player->GetTeam();\n\tif ( team == nullptr ) {\n\t\treturn Actor::GetMinimapIconColour();\n\t}\n\n\treturn team->colour;\n}\n\nvoid APig::Killed() {\n\t// TODO: queue me until camera focus, if valid (in some cases we'll insta die)\n\t//  Check if we're in water...\n\tif ( lifeState != LifeState::ALIVE ) {\n\t\treturn;\n\t}\n\n\tPlayVoiceSample( VoiceCategory::DEATH );\n\n\tClearItems();\n\n\tlifeState = LifeState::DYING;\n}\n\n/**\n * Play a randomised voice sample based on personality and team\n * @param category\n */\nvoid APig::PlayVoiceSample( VoiceCategory category ) {\n#if 0\n\tconst Player* player = GetPlayerOwner();\n\tif(player == nullptr) {\n\t  return;\n\t}\n\n\tconst Team* team = player->GetTeam();\n\tif(team == nullptr) {\n\t  return;\n\t}\n\n\tchar path[32];\n\tsnprintf(path, sizeof(path), \"speech/eng/pig%0d/%0d%s%0d%0d.wav\",\n\t\t// this is horrible, will need to revisit it...\n\t\tstatic_cast<int>(GetPersonality()),\n\t\tstatic_cast<int>(GetPersonality()),\n\t\tteam->voice_set.c_str(),\n\t\tstatic_cast<int>(category),\n\t\trand() % 6 + 1\n\t\t);\n\n\tconst AudioSample* sample = GetApp()->audioManager->CacheSample(path);\n\tif(sample == nullptr) {\n\t  return;\n\t}\n\n\tspeechEmitter->SetSample(sample);\n\tspeechEmitter->StartPlaying();\n#endif\n}\n\n/**\n * Lift that pig into the air like you just don't care!\n */\nvoid APig::Jump() {\n\tDebugMsg( \"Jumping...\\n\" );\n\n\t// Make sure we can't jump again if we're already off the ground!\n\tif ( !IsOnGround() ) {\n\t\treturn;\n\t}\n\n\tGetApp()->audioManager->PlayLocalSound( \"audio/p_snort1.wav\", GetPosition(), GetVelocity(), true );\n\n\tvelocity.y += 8.0f;\n}\n\n/**\n * Landed after a jump.\n */\nvoid APig::Land() {\n\tDebugMsg( \"Landing...\\n\" );\n\n\thei::Vector3 curVelocity = GetVelocity();\n\tif ( curVelocity.Length() > 120.0f ) {\n\t\tGetApp()->audioManager->PlayLocalSound( \"audio/p_land1.wav\", GetPosition(), GetVelocity(), true );\n\t\tDamage( nullptr, 20, PLVector3(), PLVector3() );\n\t}\n}\n"
  },
  {
    "path": "src/engine/game/APig.h",
    "content": "/* OpenHoW\n * Copyright (C) 2017-2020 TalonBrave.info and Others (see CONTRIBUTORS)\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#pragma once\n\n#include \"AModel.h\"\n#include \"AAnimatedModel.h\"\n#include \"AWeapon.h\"\n#include \"AParachuteWeapon.h\"\n#include \"Inventory.h\"\n\nclass APig : public AAnimatedModel, public InventoryManager {\n\tIMPLEMENT_ACTOR( APig, AAnimatedModel )\n\npublic:\n\tAPig();\n\t~APig() override;\n\n\tvoid HandleInput() override;\n\tvoid Tick() override;\n\n\tvoid SetClass( const std::string &classIdentier );\n\tunsigned int GetClass() { return myClass; }\n\n\tvoid SetPersonality( unsigned int personality );\n\tunsigned int GetPersonality() { return myPersonality; }\n\n\tvoid SetPlayerOwner( Player *owner );\n\tconst Player *GetPlayerOwner() const;\n\n\tvoid SetTeam( unsigned int team );\n\tunsigned int GetTeam() const { return myTeam; }\n\n\tbool Possessed( const Player *player ) override;\n\tvoid Dispossessed(const Player *player ) override;\n\n\tbool IsVisibleOnMinimap() const override;\n\tunsigned int GetMinimapIconStyle() const override;\n\tPLColour GetMinimapIconColour() const override;\n\n\tenum class VoiceCategory {\n\t\tREADY,\n\t\tFIRE,\n\t\tFIRE2,\n\t\tDEATH,\n\t\tDEATH2\n\t};\n\tvoid PlayVoiceSample( VoiceCategory category );\n\n\tenum class LifeState {\n\t\tALIVE,\n\t\tDYING,\n\t\tDEAD\n\t};\n\tvoid Killed() override;\n\n\tvoid Deserialize( const ActorSpawn &spawn ) override;\n\nprivate:\n\tvoid Jump();\n\tvoid Land();\n\n\tAWeapon *weapon_{ nullptr };\n\tAParachuteWeapon *parachuteWeapon{ nullptr };\n\n\tPlayer *playerOwnerPtr{ nullptr };\n\n\tAudioSource *speechEmitter{ nullptr };\n\n\tfloat aimPitch{ 0 };\n\n\tunsigned int myTeam{ 0 };\n\tunsigned int myPersonality{ 0 };\n\tunsigned int myClass{ 0 };\n\n\tLifeState lifeState{ LifeState::ALIVE };\n\n\tenum {\n\t\tEYES_OPEN,\n\t\tEYES_CLOSED,\n\t\tEYES_SAD,\n\t\tEYES_SURPRISED,\n\t\tEYES_ANGRY,\n\t} upper_face_frame_{ EYES_OPEN };\n\n\tenum {\n\t\tMOUTH_OPEN,\n\t\tMOUTH_CLOSED,\n\t\tMOUTH_SAD,\n\t\tMOUTH_SURPRISED,\n\t\tMOUTH_ANGRY,\n\t} lower_face_frame_{ MOUTH_OPEN };\n};\n"
  },
  {
    "path": "src/engine/game/ASprite.cpp",
    "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// Copyright © 2017-2022 TalonBrave.info and Others (see CONTRIBUTORS)\n\n#include \"App.h\"\n#include \"Sprite.h\"\n#include \"ActorManager.h\"\n\n// ASprite\n// Can be used for very basic effects etc.\n\nclass ASprite : public Actor {\n\tIMPLEMENT_ACTOR( ASprite, Actor )\n\npublic:\n\tASprite();\n\t~ASprite() override;\n\n\tvoid Tick() override;\n\tvoid Draw() override;\n\n\tvirtual void SetSpriteTexture( const std::string &path );\n\nprotected:\nprivate:\n\tohw::Sprite *spritePtr;\n};\n\nREGISTER_ACTOR_BASIC( ASprite )\n\nusing namespace ohw;\n\nASprite::ASprite() : SuperClass() {\n\tspritePtr = new Sprite( Sprite::TYPE_DEFAULT, \"materials/engine/default.png\" );\n}\n\nASprite::~ASprite() {\n\tdelete spritePtr;\n}\n\nvoid ASprite::SetSpriteTexture( const std::string &path ) {\n\tspritePtr->SetTexture( path );\n}\n\nvoid ASprite::Tick() {\n\tSuperClass::Tick();\n\n\tSetAngles( myAngles.GetValue() + 0.2f );\n\n\tspritePtr->SetPosition( position_ );\n\tspritePtr->SetAngles( myAngles );\n}\n\nvoid ASprite::Draw() {\n\tSuperClass::Draw();\n\n\tspritePtr->Draw();\n}\n"
  },
  {
    "path": "src/engine/game/AStaticModel.cpp",
    "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// Copyright © 2017-2022 TalonBrave.info and Others (see CONTRIBUTORS)\n\n#include \"App.h\"\n#include \"ActorManager.h\"\n#include \"AStaticModel.h\"\n\nREGISTER_ACTOR_BASIC( AStaticModel )\n\nAStaticModel::AStaticModel() : SuperClass() {}\nAStaticModel::~AStaticModel() = default;\n\nvoid AStaticModel::Deserialize( const ActorSpawn &spawn ) {\n\tSuperClass::Deserialize( spawn );\n\n\tSetModel( \"scenery/\" + spawn.className + \".vtx\" );\n\n\t// Some models are horrible special cases\n\tif ( spawn.className == \"brid2_s\" ) {\n\t\tSetAngles( hei::Vector3( myAngles.GetValue().x, PlDegreesToRadians( -45.f ), myAngles.GetValue().z ) );\n\t}\n}\n\nvoid AStaticModel::Draw() {\n\tSuperClass::Draw();\n}\n"
  },
  {
    "path": "src/engine/game/AStaticModel.h",
    "content": "/* OpenHoW\n * Copyright (C) 2017-2020 TalonBrave.info and Others (see CONTRIBUTORS)\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#pragma once\n\n#include \"Actor.h\"\n#include \"AModel.h\"\n\nclass AStaticModel : public AModel {\n\tIMPLEMENT_ACTOR( AStaticModel, AModel )\n\npublic:\n\tAStaticModel();\n\t~AStaticModel() override;\n\n\tvoid Draw() override;\n\n\tvoid Deserialize( const ActorSpawn &spawn ) override;\n\nprotected:\nprivate:\n};\n"
  },
  {
    "path": "src/engine/game/ATrotterWeapon.cpp",
    "content": "/* OpenHoW\n * Copyright (C) 2017-2020 TalonBrave.info and Others (see CONTRIBUTORS)\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include \"App.h\"\n#include \"ATrotterWeapon.h\"\n\n// Basic Melee Attack\n\nATrotterWeapon::ATrotterWeapon() {}\nATrotterWeapon::~ATrotterWeapon() {\n\n}\n\nvoid ATrotterWeapon::Fire( const PLVector3 &pos, const PLVector3 &dir ) {\n\tSuperClass::Fire( pos, dir );\n}\n\nvoid ATrotterWeapon::Deploy() {\n\tSuperClass::Deploy();\n}\n"
  },
  {
    "path": "src/engine/game/ATrotterWeapon.h",
    "content": "/* OpenHoW\n * Copyright (C) 2017-2020 TalonBrave.info and Others (see CONTRIBUTORS)\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#pragma once\n\n#include \"AWeapon.h\"\n\nclass ATrotterWeapon : public AWeapon {\n\tIMPLEMENT_ACTOR( ATrotterWeapon, AWeapon )\n\npublic:\n\tATrotterWeapon();\n\t~ATrotterWeapon() override;\n\n\tvoid Fire( const PLVector3 &pos, const PLVector3 &dir ) override;\n\tvoid Deploy() override;\n\nprotected:\nprivate:\n};\n"
  },
  {
    "path": "src/engine/game/AVehicle.cpp",
    "content": "/* OpenHoW\n * Copyright (C) 2017-2020 TalonBrave.info and Others (see CONTRIBUTORS)\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include \"App.h\"\n#include \"AVehicle.h\"\n\nusing namespace ohw;\n\nAVehicle::AVehicle() : SuperClass() {}\n\nAVehicle::~AVehicle() {\n\tdelete audioSource;\n\n\tmyOccupants.clear();\n}\n\nvoid AVehicle::Tick() {\n\tSuperClass::Tick();\n\n\taudioSource->SetPosition( position_ );\n}\n\nbool AVehicle::EnterVehicle( Actor *occupant ) {\n\t// TODO: pass by reference, not by pointer...\n\tif ( GetMaxOccupants() == 0 || myOccupants.size() > GetMaxOccupants() ) {\n\t\treturn false;\n\t}\n\n\tmyOccupants.push_back( occupant );\n\n\treturn true;\n}\n\nvoid AVehicle::ExitVehicle( Actor *occupant ) {\n\t// TODO: pass by reference, not by pointer...\n}\n\nbool AVehicle::IsOccupied() const {\n\treturn ( myOccupants.size() > 0 );\n}\n\nActor *AVehicle::GetOccupant( unsigned int slot ) {\n\tif ( slot > myOccupants.size() || slot >= GetMaxOccupants() ) {\n\t\tWarning( \"Invalid occupant slot, \\\"%d\\\"!\\n\", slot );\n\t\treturn nullptr;\n\t}\n\n\treturn myOccupants[ slot ];\n}\n\nvoid AVehicle::Deserialize( const ActorSpawn &spawn ) {\n\tSuperClass::Deserialize( spawn );\n\n\taudioSource = GetApp()->audioManager->CreateSource();\n\taudioSource->SetPosition( position_ );\n\taudioSource->SetLooping( true );\n\n\tconst AudioSample *audioSample = GetApp()->audioManager->CacheSample( GetEngineIdleSound() );\n\tif ( audioSample != nullptr ) {\n\t\taudioSource->SetSample( audioSample );\n\t\taudioSource->StartPlaying();\n\t}\n}\n"
  },
  {
    "path": "src/engine/game/AVehicle.h",
    "content": "/* OpenHoW\n * Copyright (C) 2017-2020 TalonBrave.info and Others (see CONTRIBUTORS)\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#pragma once\n\n#include \"AModel.h\"\n\nclass AVehicle : public AModel {\n\tIMPLEMENT_ACTOR( AVehicle, AModel )\n\npublic:\n\tAVehicle();\n\t~AVehicle();\n\n\tvoid Tick() override;\n\n\tvirtual bool EnterVehicle( Actor *occupant );\n\tvirtual void ExitVehicle( Actor *occupant );\n\n\tbool IsOccupied() const;\n\n\tActor *GetOccupant( unsigned int slot );\n\n\tvirtual inline unsigned int GetMaxOccupants() const { return 1;\t}\n\tvirtual inline const char *GetEngineIdleSound() const {\treturn \"audio/en_tank.wav\";\t}\n\n\tvoid Deserialize( const ActorSpawn &spawn ) override;\n\nprotected:\nprivate:\n\tstd::vector< Actor * > myOccupants;\n\n\tAudioSource *audioSource{ nullptr };\n};"
  },
  {
    "path": "src/engine/game/AWeapon.cpp",
    "content": "/* OpenHoW\n * Copyright (C) 2017-2020 TalonBrave.info and Others (see CONTRIBUTORS)\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include \"App.h\"\n#include \"AWeapon.h\"\n\nAWeapon::AWeapon() : SuperClass() {}\nAWeapon::~AWeapon() = default;\n\nvoid AWeapon::Tick() {\n\tSuperClass::Tick();\n\n\tActor *parent = GetParent();\n\tif ( parent != nullptr ) {\n\t\tSetPosition( parent->GetPosition() );\n\t\tSetAngles( parent->GetAngles() );\n\t}\n}\n\nvoid AWeapon::Fire( const PLVector3 &pos, const PLVector3 &dir ) {}\n\nvoid AWeapon::Deploy() {\n\tShowModel( true );\n\n\t/* todo: make deploy sound */\n\n\tisWeaponDeployed = true;\n}\n\nvoid AWeapon::Holster() {\n\tShowModel( false );\n\n\t/* todo: make holster sound */\n\n\tisWeaponDeployed = false;\n}\n"
  },
  {
    "path": "src/engine/game/AWeapon.h",
    "content": "/* OpenHoW\n * Copyright (C) 2017-2020 TalonBrave.info and Others (see CONTRIBUTORS)\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#pragma once\n\n#include \"AModel.h\"\n\nclass AWeapon : public AModel {\n\tIMPLEMENT_ACTOR( AWeapon, AModel )\n\npublic:\n\tAWeapon();\n\t~AWeapon() override;\n\n\tvoid Tick() override;\n\n\tvirtual void Fire( const PLVector3 &pos, const PLVector3 &dir );\n\tvirtual void Deploy();\n\tvirtual void Holster();\n\n\tbool IsDeployed() const { return isWeaponDeployed; }\n\nprotected:\n\n\tbool isWeaponDeployed{ false };\n\nprivate:\n};\n"
  },
  {
    "path": "src/engine/game/Actor.cpp",
    "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// Copyright © 2017-2022 TalonBrave.info and Others (see CONTRIBUTORS)\n\n#include \"App.h\"\n#include \"Map.h\"\n#include \"ActorManager.h\"\n#include \"Player.h\"\n#include \"Actor.h\"\n\n#include \"graphics/Camera.h\"\n\nusing namespace ohw;\n\nActor::Actor() :\n\tINIT_PROPERTY( forwardVelocity, PROP_PUSH, 0.00 ),\n\tINIT_PROPERTY( inputYaw, PROP_PUSH, 0.00 ),\n\tINIT_PROPERTY( inputPitch, PROP_PUSH, 0.00 ),\n\tINIT_PROPERTY( position_, PROP_LOCAL | PROP_WRITE, hei::Vector3( 0, 0, 0 ) ),\n\tINIT_PROPERTY( fallback_position_, PROP_LOCAL | PROP_WRITE, hei::Vector3( 0, 0, 0 ) ),\n\tINIT_PROPERTY( myAngles, PROP_LOCAL | PROP_WRITE, hei::Vector3( 0, 0, 0 ) ) {}\n\nActor::~Actor() {\n\tfor ( auto actor : childActors ) {\n\t\tActorManager::GetInstance()->DestroyActor( actor );\n\t\tactor = nullptr;\n\t}\n\n\tchildActors.clear();\n\tchildActors.shrink_to_fit();\n\n\tDestroyPhysicsBody();\n}\n\n/**\n * Simulation tick, called per-frame.\n */\nvoid Actor::Tick() {\n\tmyForward = CalculateForwardVector();\n}\n\nvoid Actor::SetAngles( hei::Vector3 angles ) {\n\tVecAngleClamp( &angles );\n\tmyOldAngles = myAngles;\n\tmyAngles = angles;\n}\n\nbool Actor::IsVisible() {\n\tCamera *camera = GetApp()->gameManager->GetActiveCamera();\n\treturn !( camera == nullptr || !camera->IsBoxVisible( &boundingBox ) );\n}\n\nvoid Actor::SetVelocity(PLVector3 newVelocity) {\n\told_velocity_ = velocity;\n\tvelocity = newVelocity;\n}\n\nvoid Actor::SetPosition( PLVector3 position ) {\n\told_position_ = position_;\n\tposition_ = position;\n\n\t// Ensure the bounds are kept updated...\n\tboundingBox.origin = position;\n}\n\nvoid Actor::Deserialize( const ActorSpawn &spawn ) {\n\t// Convert the original spawn bounds to those we want (TODO: do this in spawn handler)\n\tboundingBox.maxs.x = ( float ) spawn.bounds[ 0 ];\n\tboundingBox.mins.x = ( float ) -spawn.bounds[ 0 ];\n\tboundingBox.maxs.y = ( float ) spawn.bounds[ 1 ];\n\tboundingBox.mins.y = ( float ) -spawn.bounds[ 1 ];\n\tboundingBox.maxs.z = ( float ) spawn.bounds[ 2 ];\n\tboundingBox.mins.z = ( float ) -spawn.bounds[ 2 ];\n\n\tSetPosition( spawn.position );\n\tSetAngles( spawn.angles );\n}\n\nconst ohw::PhysicsBody *Actor::CreatePhysicsBody() {\n\treturn nullptr;\n}\n\nvoid Actor::DestroyPhysicsBody() {}\n\n/**\n * Used for inflicting damage upon the actor.\n * @param attacker The actor inflicting the damage.\n * @param damageInflicted The amout of health to subtract.\n * @param direction The direction of the damage.\n * @param velocity Velocity of the damage, for physics.\n * @return Returns true if the actor is killed.\n */\nbool Actor::Damage( const Actor *attacker, uint16_t damageInflicted, PLVector3 direction, PLVector3 velocity ) {\n\tif ( myHealth <= 0 ) {\n\t\treturn true;\n\t}\n\n\tmyHealth -= damageInflicted;\n\tif ( myHealth <= 0 ) {\n\t\tKilled();\n\t\treturn true;\n\t}\n\n\treturn false;\n}\n\nvoid Actor::Killed() {\n\tActorManager::GetInstance()->DestroyActor( this );\n}\n\nvoid Actor::AddHealth( int16_t health ) {\n\tif ( health <= 0 ) {\n\t\treturn;\n\t}\n\n\tmyHealth += health;\n}\n\nbool Actor::Possessed( const Player *player ) {\n\tif ( myHealth <= 0 ) {\n\t\treturn false;\n\t}\n\n\treturn true;\n}\n\nvoid Actor::Dispossessed(const Player *player ) {\n\tClearInput();\n}\n\n/**\n * Drop the actor to the ground based on it's bounding box size.\n */\nvoid Actor::DropToFloor() {\n\tMap *map = GetApp()->gameManager->GetCurrentMap();\n\tif ( map == nullptr ) {\n\t\treturn;\n\t}\n\n\tTerrain *terrain = map->GetTerrain();\n\tif ( terrain == nullptr ) {\n\t\treturn;\n\t}\n\n\t// Fetch each of the tiles we're possibly touching.\n\tconst Terrain::Tile *tiles[ 4 ];\n\ttiles[ 0 ] = terrain->GetTile( boundingBox.mins.x + position_.GetValue().x, boundingBox.mins.z + position_.GetValue().z );\n\ttiles[ 1 ] = terrain->GetTile( boundingBox.maxs.x + position_.GetValue().x, boundingBox.maxs.z + position_.GetValue().z );\n\ttiles[ 2 ] = terrain->GetTile( boundingBox.mins.x + position_.GetValue().x, boundingBox.maxs.z + position_.GetValue().z );\n\ttiles[ 3 ] = terrain->GetTile( boundingBox.mins.x + position_.GetValue().x, boundingBox.maxs.z + position_.GetValue().z );\n\n\t// Iterate through to figure out the height we should be at.\n\tfloat maxTileHeight = terrain->GetMinHeight();\n\tunsigned int tileNum = 0;\n\tfor ( ; tileNum < 4; ++tileNum ) {\n\t\tfor ( unsigned int corner = 0; corner < 4; ++corner ) {\n\t\t\tif ( tiles[ tileNum ]->height[ corner ] <= maxTileHeight ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tmaxTileHeight = tiles[ tileNum ]->height[ corner ];\n\t\t}\n\t}\n\t\n\t// And finally actually update our position\n\t//SetPosition( newPos );\n}\n\n/**\n * Get forward vector based on current angles.\n */\nPLVector3 Actor::CalculateForwardVector() {\n\tfloat rx = PlDegreesToRadians( myAngles.GetValue().x );\n\tfloat ry = PlDegreesToRadians( myAngles.GetValue().y );\n\n\tPLVector3 v;\n\tv.x = std::cos( ry ) * std::cos( rx );\n\tv.y = std::sin( rx );\n\tv.z = std::sin( ry ) * std::cos( rx );\n\n\treturn PlNormalizeVector3( v );\n}\n\n/**\n * Attach actor to self, and set self as parent. Children are automatically destroyed.\n * @param actor Child actor to link.\n */\nvoid Actor::LinkChild( Actor *actor ) {\n\tif ( actor == nullptr ) {\n\t\tWarning( \"Attempted to attach an invalid actor to self!\\n\" );\n\t\treturn;\n\t}\n\n\tchildActors.push_back( actor );\n\tactor->parentActor = this;\n}\n\n/**\n * Checks whether or not this actor is touching another actor.\n */\nbool Actor::CheckTouching() {\n\tbool touchedSomething = false;\n\n\tActorSet actorSet = ActorManager::GetInstance()->GetActors();\n\tfor ( Actor *other : actorSet ) {\n\t\t// Can't touch ourself\n\t\tif ( other == this || !other->IsActivated() ) {\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Check if it's our parent; we can't touch them\n\t\tif ( other == parentActor ) {\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Check if it's one of our children; we can't touch them either\n\t\tbool isChild = false;\n\t\tfor ( unsigned int i = 0; i < childActors.size(); ++i ) {\n\t\t\tif ( childActors[ i ] == other ) {\n\t\t\t\tisChild = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif ( isChild ) {\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Now check the AABB against that of the other actor\n\t\tif( !PlIsAabbIntersecting( &boundingBox, &other->boundingBox ) ) {\n\t\t\t// Didn't get a hit, continue onto the next\n\t\t\tcontinue;\n\t\t}\n\n\t\t// We're touching them, so go ahead and handle that case\n\t\tTouch( other );\n\n\t\ttouchedSomething = true;\n\t}\n\n\treturn touchedSomething;\n}\n\n/**\n * Called when one actor collides with another.\n * @param other The touchee.\n */\nvoid Actor::Touch( Actor *other ) {\n#if 0\n\tLogDebug( \"actor %s (%s) touched actor %s (%s)\\n\",\n\t\tGetClassName(),\n\t\tplPrintVector3( &position_.GetValue(), pl_int_var ),\n\t\tGetClassName(),\n\t\tplPrintVector3( &other->position_.GetValue(), pl_int_var ) );\n#endif\n}\n\n/**\n * Check whether or not this actor is currently on the ground.\n */\nbool Actor::IsOnGround() {\n\tMap *map = GetApp()->gameManager->GetCurrentMap();\n\tif ( map == nullptr ) {\n\t\treturn false;\n\t}\n\n\tPLVector3 nPosition = position_;\n\tfloat tileHeight = map->GetTerrain()->GetHeight( nPosition.x, nPosition.z );\n\treturn ( nPosition.y - ( boundingBox.maxs.y / 2 ) ) <= tileHeight;\n}\n"
  },
  {
    "path": "src/engine/game/Actor.h",
    "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// Copyright © 2017-2022 TalonBrave.info and Others (see CONTRIBUTORS)\n\n#pragma once\n\n#include \"../Property.h\"\n\nenum ActorFlag {\n\tACTOR_FLAG_PLAYABLE = 1,\n\tACTOR_FLAG_SCRIPTED = 16,\n\tACTOR_FLAG_INSIDE = 32,\n\tACTOR_FLAG_DELAYED = 64,\n\t/* ...any new types below... */\n};\n\nenum ActorEvent {\n\tACTOR_EVENT_NONE,                       // does nothing!\n\tACTOR_EVENT_ITEM,                       // spawns an item on destruction\n\tACTOR_EVENT_PROMOTION,                  // spawns a promotion point on destruction\n\tACTOR_EVENT_PROTECT = 4,                // spawns a promotion point if the object is not destroyed\n\tACTOR_EVENT_AIRDROP_ITEM = 7,           // spawns item airdrop on destruction\n\tACTOR_EVENT_AIRDROP_PROMOTION,          // spawns promotion point on destruction\n\tACTOR_EVENT_GROUP_ITEM = 13,            // spawns item when group is destroyed\n\tACTOR_EVENT_GROUP_PROMOTION,            // spawns promotion point when group is destroyed\n\tACTOR_EVENT_REWARD = 19,                // returns specified item on destruction to destructor\n\tACTOR_EVENT_GROUP_SPAWN,                // spawns group on destruction\n\tACTOR_EVENT_VICTORY,                    // triggers victory on destruction\n\tACTOR_EVENT_BURST,                      // spawns group upon destruction by TNT\n\tACTOR_EVENT_GROUP_OBJECT,               // spawns group when object's group is destroyed\n\t/* ...any new types below... */\n};\n\nstruct ActorSpawn {\n\tstd::string className;\n\tPLVector3 position; // position in the world\n\tuint16_t index;                  // todo\n\tPLVector3 angles; // angles in the world\n\tuint16_t type;                   // todo\n\n\tint16_t bounds[3]; // collision bounds\n\tuint16_t bounds_type; // box, prism, sphere and none\n\n\tint16_t energy;\n\tuint8_t appearance;\n\tuint8_t team; // uk, usa, german, french, japanese, soviet\n\n\tuint16_t objective;\n\tuint8_t objective_actor_id;\n\tuint8_t objective_extra[2];\n\n\tPLVector3 fallbackPosition;\n\n\tint16_t extra;\n\tActorSpawn *attachment{ nullptr };\n};\n\nnamespace ohw {\n\tclass PhysicsBody;\n}\n\n#define IMPLEMENT_SUPER( a ) typedef a SuperClass;\n#define IMPLEMENT_ACTOR( base, parent ) \\\n  IMPLEMENT_SUPER(parent) \\\n  public: inline const char* GetClassName() override { return PL_STRINGIFY(base) ; } \\\n  private:\n\nclass Player;\n\nclass Actor : public PropertyOwner {\npublic:\n\tActor();\n\t~Actor() override;\n\n\tvirtual const char *GetClassName() { return \"Actor\"; }\n\n\tvirtual void Tick();\n\tvirtual void Draw() {}  // draw tick, called per-frame\n\n\tvirtual bool Damage( const Actor *attacker,\n\t                     uint16_t damageInflicted,\n\t                     PLVector3 direction = { 0.0f, 0.0f, 0.0f },\n\t                     PLVector3 velocity = { 0.0f, 0.0f, 0.0f } );\n\tvirtual void Killed();\n\n\tvirtual void SetHealth( int16_t health ) { myHealth = health; }\n\tvirtual void AddHealth( int16_t health );\n\tint16_t GetHealth() { return myHealth; }\n\n\tvirtual bool IsVisible();\n\n\tinline PLVector3 GetVelocity() const {\n\t\treturn velocity;\n\t}\n\tvirtual void SetVelocity( PLVector3 newVelocity );\n\n\tinline PLVector3 GetPosition() const {\n\t\treturn position_;\n\t}\n\tvirtual void SetPosition( PLVector3 position );\n\n\tinline PLVector3 GetAngles() const {\n\t\treturn myAngles;\n\t}\n\tvirtual void SetAngles( hei::Vector3 angles );\n\n\tinline PLVector3 GetForward() const {\n\t\treturn myForward;\n\t}\n\n\tinline float GetHeight() const {\n\t\treturn position_.GetValue().y;\n\t}\n\n\tvirtual bool Possessed( const Player *player );\n\tvirtual void Dispossessed( const Player *player );\n\tvirtual void HandleInput() {}   // handle any player input, if applicable\n\n\tvirtual ActorSpawn Serialize() { return ActorSpawn(); }\n\tvirtual void Deserialize( const ActorSpawn &spawn );\n\n\tvirtual void Activate() { isActive = true; }\n\tvirtual void Deactivate() { isActive = false; }\n\tvirtual bool IsActivated() { return isActive; }\n\n\tvirtual bool IsVisibleOnMinimap() const { return false; }\n\tvirtual unsigned int GetMinimapIconStyle() const { return 0; }\n\tvirtual PLColour GetMinimapIconColour() const { return { 255, 255, 255, 255 }; }\n\n\tActor *GetParent() { return parentActor; }\n\tvoid LinkChild( Actor *actor );\n\tunsigned int GetNumOfChildren() { return childActors.size(); }\n\tstd::vector< Actor * > GetChildren() { return childActors; }\n\n\tbool CheckTouching();\n\tvirtual void Touch( Actor *other );\n\n\tvoid DropToFloor();\n\n\t// Physics\n\n\tconst ohw::PhysicsBody *CreatePhysicsBody();\n\tvoid DestroyPhysicsBody();\n\n\tPLCollisionAABB *GetBoundingBox() { return &boundingBox; }\n\n\t// Networking\n\n\tvoid SendUpdate();\n\tvoid ReceiveUpdate();\n\nprotected:\n\tPLVector3 CalculateForwardVector();\n\n\tbool IsOnGround();\n\n\tbool is_visible_{ false };\n\n\tNumericProperty< float > forwardVelocity;  /* -1.0 = backwards, +1.0 = forwards */\n\tNumericProperty< float > inputYaw;      /* -1.0 = left, +1.0 = right */\n\tNumericProperty< float > inputPitch;    /* -1.0 = down, +1.0 = up */\n\n\thei::Vector3 velocity{ 0, 0, 0 }, old_velocity_{ 0, 0, 0 };\n\n\tVector3Property position_;\n\thei::Vector3 old_position_{ 0, 0, 0 };\n\n\tVector3Property fallback_position_;\n\n\tVector3Property myAngles;\n\thei::Vector3 myOldAngles{ 0.0f, 0.0f, 0.0f };\n\thei::Vector3 myForward{ 0.0f, 0.0f, 0.0f };\n\n\tPLCollisionAABB boundingBox;\n\nprivate:\n\tinline void ClearInput() {\n\t\tforwardVelocity = inputPitch = inputYaw = 0.0f;\n\t}\n\n\tint16_t myHealth{ 0 };\n\n\tohw::PhysicsBody *myPhysicsBody{ nullptr };\n\n\tbool isActive{ false };\n\n\tActor *parentActor{ nullptr };\n\tstd::vector< Actor * > childActors;\n};\n"
  },
  {
    "path": "src/engine/game/ActorManager.cpp",
    "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// Copyright © 2017-2022 TalonBrave.info and Others (see CONTRIBUTORS)\n\n#include \"App.h\"\n#include \"Menu.h\"\n#include \"graphics/ShaderManager.h\"\n#include \"ActorManager.h\"\n#include \"JsonReader.h\"\n\n/************************************************************/\n\nActorSet ActorManager::actorsList;\nstd::vector< Actor * > ActorManager::destructionQueue;\nstd::map< std::string, ActorManager::actor_ctor_func > ActorManager::actorClassesRegistry\n\t\t__attribute__((init_priority (1000)));\n\nActor *ActorManager::CreateActor( const std::string &identifier, const ActorSpawn &spawnData ) {\n\tauto spawn = actorSpawnsRegistry.find( identifier );\n\tif ( spawn == actorSpawnsRegistry.end() ) {\n\t\t// TODO: make this throw an error rather than continue...\n\t\tWarning( \"Failed to find actor in spawn registry \\\"%s\\\"!\\n\", identifier.c_str() );\n\t\treturn nullptr;\n\t}\n\n\tauto classSpawn = actorClassesRegistry.find( spawn->second.className );\n\tif ( classSpawn == actorClassesRegistry.end() ) {\n\t\tError( \"Invalid class name \\\"%s\\\" provided for actor \\\"%s\\\"!\\n\",\n\t\t spawn->second.className.c_str(),\n\t\t spawn->second.identifier.c_str() );\n\t}\n\n\tActor *actor = classSpawn->second();\n\tactorsList.insert( actor );\n\n\tactor->Deserialize( spawnData );\n\n\treturn actor;\n}\n\nvoid ActorManager::DestroyActor( Actor *actor ) {\n\tu_assert( actor != nullptr, \"attempted to delete a null actor!\\n\" );\n\n\t// Ensure it's not already queued for destruction\n\tif ( std::find( destructionQueue.begin(), destructionQueue.end(), actor ) != destructionQueue.end() ) {\n\t\tDebugMsg( \"Attempted to queue actor for deletion twice, ignoring...\\n\" );\n\t\treturn;\n\t}\n\n\t// Move it into a queue for destruction\n\tdestructionQueue.push_back( actor );\n}\n\nvoid ActorManager::TickActors() {\n\tfor ( auto const &actor: actorsList ) {\n\t\tif ( !actor->IsActivated() ) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tactor->Tick();\n\t\tactor->CheckTouching();\n\t}\n\n\t// Now clean everything up that was marked for destruction\n\tfor ( auto &i : destructionQueue ) {\n\t\tassert( actorsList.find( i ) != actorsList.end() );\n\t\tactorsList.erase( i );\n\t\tdelete i;\n\t}\n\tdestructionQueue.clear();\n}\n\nvoid ActorManager::DrawActors() {\n\tif ( FrontEnd_GetState() == FE_MODE_LOADING ) {\n\t\treturn;\n\t}\n\n\tShaders_SetProgramByName( cv_graphics_debug_normals->b_value ? \"debug_normals\" : \"generic_textured_lit\" );\n\n\tfor ( auto const &actor: actorsList ) {\n\t\tactor->Draw();\n\t}\n\n\tif ( cv_debug_bounds->b_value ) {\n\t\tShaders_SetProgramByName( \"generic_untextured\" );\n\n\t\tfor ( auto const &actor: actorsList ) {\n\t\t\tPlgDrawBoundingVolume( actor->GetBoundingBox(), PL_COLOUR_GREEN );\n\t\t}\n\t}\n}\n\nvoid ActorManager::DestroyActors() {\n\tfor ( auto &actor: actorsList ) {\n\t\tdelete actor;\n\t}\n\n\tdestructionQueue.clear();\n\tactorsList.clear();\n}\n\nvoid ActorManager::ActivateActors() {\n\tfor ( auto const &actor: actorsList ) {\n\t\tactor->Activate();\n\t}\n}\n\nvoid ActorManager::DeactivateActors() {\n\tfor ( auto const &actor: actorsList ) {\n\t\tactor->Deactivate();\n\t}\n}\n\nvoid ActorManager::RegisterSpawnManifests() {\n\tPlScanDirectory( \"actors\", \"actor\", RegisterActorManifest, false, this );\n}\n\nvoid ActorManager::RegisterActorManifest( const char *path, void *userPtr ) {\n\tActorManager *actorManager = static_cast<ActorManager *>( userPtr );\n\n\ttry {\n\t\tJsonReader reader( path );\n\n\t\t// Number of actors in this particular manifest\n\t\tunsigned int numActors = reader.GetArrayLength();\n\t\tif ( numActors == 0 ) {\n\t\t\tWarning( \"Empty actor manifest!\\n\" );\n\t\t\treturn;\n\t\t}\n\n\t\tfor( unsigned int i = 0; i < numActors; ++i ) {\n\t\t\treader.EnterChildNode( i );\n\n\t\t\tActorSpawnManifest manifest;\n\n\t\t\t// Ensure it's not already been added!\n\t\t\tmanifest.identifier = reader.GetStringProperty( \"identifier\" );\n\t\t\tconst auto &find = actorManager->actorSpawnsRegistry.find( manifest.identifier );\n\t\t\tif( find != actorManager->actorSpawnsRegistry.end() ) {\n\t\t\t\tWarning( \"Actor \\\"%s\\\" has already been registered!\\n\", manifest.identifier.c_str() );\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tmanifest.className = reader.GetStringProperty( \"className\" );\n\t\t\tmanifest.description = reader.GetStringProperty( \"description\" );\n\n\t\t\t// Read in all the custom properties\n\t\t\tif ( reader.EnterChildNode( \"properties\" ) ) {\n\t\t\t\tstd::list< std::string > propertyKeys = reader.GetObjectKeys();\n\t\t\t\tfor ( const auto &property : propertyKeys ) {\n\t\t\t\t\tstd::string value = reader.GetStringProperty( property );\n\t\t\t\t\tmanifest.properties.emplace( std::pair< std::string, std::string >( property, value ) );\n\t\t\t\t}\n\t\t\t\treader.LeaveChildNode();\n\t\t\t}\n\n\t\t\tactorManager->actorSpawnsRegistry.emplace( std::pair< std::string, ActorSpawnManifest >( manifest.identifier, manifest ) );\n\n\t\t\treader.LeaveChildNode();\n\t\t}\n\t} catch( const std::exception &exception ) {\n\t\tWarning( \"Failed to load actor manifest, \\\"%s\\\"!\\nException: %s\\n\", exception.what() );\n\t\treturn;\n\t}\n}\n\nActorManager::ActorClassRegistration::ActorClassRegistration( const std::string &name, actor_ctor_func ctor_func )\n\t\t: name_( name ) {\n\tActorManager::actorClassesRegistry[ name ] = ctor_func;\n}\n\nActorManager::ActorClassRegistration::~ActorClassRegistration() {\n\tActorManager::actorClassesRegistry.erase( name_ );\n}\n"
  },
  {
    "path": "src/engine/game/ActorManager.h",
    "content": "/* OpenHoW\n * Copyright (C) 2017-2020 TalonBrave.info and Others (see CONTRIBUTORS)\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#pragma once\n\nclass Actor;\n\ntypedef std::set< Actor * > ActorSet;\n\nstruct ActorSpawnManifest {\n\tstd::string identifier;\n\tstd::string className;\n\tstd::string description;\n\tstd::map< std::string, std::string > properties;\n};\n\nclass ActorManager {\nprotected:\n\ttypedef Actor *(*actor_ctor_func)();\n\tstatic std::map< std::string, actor_ctor_func > actorClassesRegistry;\n\npublic:\n\tstatic ActorManager *GetInstance() {\n\t\tstatic ActorManager *instance = nullptr;\n\t\tif ( instance == nullptr ) {\n\t\t\tinstance = new ActorManager();\n\t\t}\n\t\treturn instance;\n\t}\n\n\tActor *CreateActor( const std::string &identifier, const ActorSpawn &spawnData = ActorSpawn() );\n\tvoid DestroyActor( Actor *actor );\n\n\tvoid TickActors();\n\tvoid DrawActors();\n\tvoid DestroyActors();\n\n\tvoid ActivateActors();\n\tvoid DeactivateActors();\n\n\tconst ActorSet &GetActors() const { return actorsList; }\n\n\tvoid RegisterSpawnManifests();\n\tstatic void RegisterActorManifest( const char *path, void *userData );\n\n\tclass ActorClassRegistration {\n\tpublic:\n\t\tconst std::string name_;\n\n\t\tActorClassRegistration( const std::string &name, actor_ctor_func ctor_func );\n\t\t~ActorClassRegistration();\n\t};\n\nprivate:\n\tstd::map< std::string, ActorSpawnManifest > actorSpawnsRegistry;\n\n\tstatic ActorSet actorsList;\n\tstatic std::vector< Actor * > destructionQueue;\n};\n\n#define REGISTER_ACTOR( NAME, CLASS ) \\\n    static Actor * NAME ## _make() { return new CLASS (); } \\\n    static ActorManager::ActorClassRegistration __attribute__ ((init_priority(2000))) \\\n    _reg_actor_ ## NAME ## _name((#NAME), NAME ## _make); // NOLINT(cert-err58-cpp)\n#define REGISTER_ACTOR_BASIC( CLASS ) REGISTER_ACTOR( CLASS, CLASS )\n"
  },
  {
    "path": "src/engine/game/GameManager.cpp",
    "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// Copyright © 2017-2022 TalonBrave.info and Others (see CONTRIBUTORS)\n\n#include <fstream>\n\n#include \"App.h\"\n#include \"Menu.h\"\n#include \"Map.h\"\n#include \"Language.h\"\n#include \"ActorManager.h\"\n#include \"GameMode.h\"\n#include \"Player.h\"\n\n#include \"graphics/Camera.h\"\n\n#include \"script/JsonReader.h\"\n\n#include \"APig.h\"\n#include \"AStaticModel.h\"\n#include \"GameManager.h\"\n\nstd::string MapManifest::Serialize() {\n\tstd::stringstream output;\n\toutput << \"{\";\n\toutput << R\"(\"name\":\")\" << name << \"\\\",\";\n\toutput << R\"(\"author\":\")\" << author << \"\\\",\";\n\toutput << R\"(\"description\":\")\" << description << \"\\\",\";\n\tif ( !modes.empty() ) {\n\t\toutput << R\"(\"modes\":[)\";\n\t\tfor ( size_t i = 0; i < modes.size(); ++i ) {\n\t\t\toutput << \"\\\"\" << modes[ i ] << \"\\\"\";\n\t\t\tif ( i != modes.size() - 1 ) {\n\t\t\t\toutput << \",\";\n\t\t\t}\n\t\t}\n\t\toutput << \"],\";\n\t}\n\toutput << R\"(\"ambientColour\":\")\" <<\n\t       std::to_string( ambient_colour.r ) << \" \" <<\n\t       std::to_string( ambient_colour.g ) << \" \" <<\n\t       std::to_string( ambient_colour.b ) << \"\\\",\";\n\toutput << R\"(\"skyColourTop\":\")\" <<\n\t       std::to_string( sky_colour_top.r ) << \" \" <<\n\t       std::to_string( sky_colour_top.g ) << \" \" <<\n\t       std::to_string( sky_colour_top.b ) << \"\\\",\";\n\toutput << R\"(\"skyColourBottom\":\")\" <<\n\t       std::to_string( sky_colour_bottom.r ) << \" \" <<\n\t       std::to_string( sky_colour_bottom.g ) << \" \" <<\n\t       std::to_string( sky_colour_bottom.b ) << \"\\\",\";\n\toutput << R\"(\"sunColour\":\")\" <<\n\t       std::to_string( sun_colour.r ) << \" \" <<\n\t       std::to_string( sun_colour.g ) << \" \" <<\n\t       std::to_string( sun_colour.b ) << \"\\\",\";\n\toutput << R\"(\"sunYaw\":\")\" << std::to_string( sun_yaw ) << \"\\\",\";\n\toutput << R\"(\"sunPitch\":\")\" << std::to_string( sun_pitch ) << \"\\\",\";\n\toutput << R\"(\"temperature\":\")\" << temperature << \"\\\",\";\n\toutput << R\"(\"weather\":\")\" << weather << \"\\\",\";\n\toutput << R\"(\"time\":\")\" << time << \"\\\",\";\n\t// Fog\n\toutput << R\"(\"fogColour\":\")\" <<\n\t       std::to_string( fog_colour.r ) << \" \" <<\n\t       std::to_string( fog_colour.g ) << \" \" <<\n\t       std::to_string( fog_colour.b ) << \"\\\",\";\n\toutput << R\"(\"fogIntensity\":\")\" << std::to_string( fog_intensity ) << \"\\\",\";\n\toutput << R\"(\"fogDistance\":\")\" << std::to_string( fog_distance ) << \"\\\"\";\n\toutput << \"}\\n\";\n\treturn output.str();\n}\n\nohw::GameManager::GameManager() {\n\tPlRegisterConsoleCommand( \"CreateMap\", \"Creates a new named map.\", 1, CreateMapCommand );\n\tPlRegisterConsoleCommand( \"OpenMap\", \"Opens the specified map.\", 1, OpenMapCommand );\n\tPlRegisterConsoleCommand( \"ListMaps\", \"Lists all of the existing maps.\", 0, ListMapsCommand );\n\tPlRegisterConsoleCommand( \"GiveItem\", \"Gives a specified item to the current occupied actor.\", 1, GiveItemCommand );\n\tPlRegisterConsoleCommand( \"SpawnModel\", \"Creates a model at your current position.\", 1, SpawnModelCommand );\n\tPlRegisterConsoleCommand( \"KillSelf\", \"Kills the currently occupied actor.\", 1, KillSelfCommand );\n\tPlRegisterConsoleCommand( \"Teleport\", \"Teleports current actor to the given destination.\", 1, TeleportCommand );\n\tPlRegisterConsoleCommand( \"FirstPerson\", \"Toggles the camera into first-person mode.\", 1, FirstPersonCommand );\n\tPlRegisterConsoleCommand( \"FreeCam\", \"Toggles the camera into fly mode.\", 1, FreeCamCommand );\n\n\tdefaultCamera = new Camera( pl_vecOrigin3, pl_vecOrigin3 );\n}\n\nohw::GameManager::~GameManager() {\n\tmapManifests.clear();\n\n\tdelete defaultCamera;\n}\n\nvoid ohw::GameManager::Tick() {\n\tif ( pauseSim && simSteps == 0 ) {\n\t\treturn;\n\t}\n\n\tFrontEnd_Tick();\n\n\tif ( currentMode == nullptr ) {\n\t\treturn;\n\t}\n\n\tif ( ambient_emit_delay_ < GetApp()->GetSimulationTicks() ) {\n\t\tconst AudioSample *sample = ambient_samples_[ rand() % MAX_AMBIENT_SAMPLES ];\n\t\tif ( sample != nullptr ) {\n\t\t\tPLVector3 position = {\n\t\t\t\t\tPlGenerateRandomFloat( TERRAIN_PIXEL_WIDTH ),\n\t\t\t\t\tcurrentMap->GetTerrain()->GetMaxHeight(),\n\t\t\t\t\tPlGenerateRandomFloat( TERRAIN_PIXEL_WIDTH )\n\t\t\t};\n\t\t\tGetApp()->audioManager->PlayLocalSound( sample, position, { 0, 0, 0 }, true, 0.5f );\n\t\t}\n\n\t\tambient_emit_delay_ = GetApp()->GetSimulationTicks() + TICKS_PER_SECOND + rand() % ( 7 * TICKS_PER_SECOND );\n\t}\n\n\tcurrentMode->Tick();\n\n\tTickCamera();\n\n\tActorManager::GetInstance()->TickActors();\n\n\tif ( simSteps > 0 ) {\n\t\tsimSteps--;\n\t}\n}\n\nvoid ohw::GameManager::SetupPlayers( const PlayerPtrVector &players ) {\n\tfor ( auto i: players ) {\n\t\tGetMode()->PlayerJoined( i );\n\t}\n\n\tplayers_ = players;\n}\n\nvoid ohw::GameManager::ClearPlayers() {\n\tfor ( auto i: players_ ) {\n\t\tdelete i;\n\t}\n\tplayers_.clear();\n}\n\nPlayer *ohw::GameManager::GetPlayerByIndex( unsigned int i ) const {\n\tif ( i >= players_.size() ) {\n\t\tWarning( \"Invalid player index, \\\"%d\\\"!\\n\", i );\n\t\treturn nullptr;\n\t}\n\n\treturn players_[ i ];\n}\n\nvoid ohw::GameManager::LoadMap( const std::string &name ) {\n\tMapManifest *manifest = GetApp()->gameManager->GetMapManifest( name );\n\tif ( manifest == nullptr ) {\n\t\tWarning( \"Failed to get map descriptor, \\\"%s\\\"\\n\", name.c_str() );\n\t\treturn;\n\t}\n\n\tMap *map = new Map( manifest );\n\tif ( currentMap != nullptr ) {\n\t\tEndMode();\n\t}\n\n\tcurrentMap = map;\n\n\t/* todo: we should actually pause here and wait for user input\n\t *       otherwise players won't have time to read the loading screen */\n\tFrontEnd_SetState( FE_MODE_GAME );\n}\n\nvoid ohw::GameManager::UnloadMap() {\n\tdelete currentMap;\n}\n\nvoid ohw::GameManager::CachePersistentData() {\n\tRegisterMapManifests();\n\tRegisterTeamManifest( \"scripts/teams.json\" );\n\tRegisterClassManifest( \"scripts/classes.json\" );\n\n\t// todo: ActorManager should be part of the GameManager class\n\tActorManager::GetInstance()->RegisterSpawnManifests();\n}\n\nvoid ohw::GameManager::RegisterTeamManifest( const std::string &path ) {\n\tPrint( \"Registering team manifest \\\"%s\\\"...\\n\", path.c_str() );\n\n\tJsonReader config( path );\n\tunsigned int numTeams = config.GetArrayLength();\n\tif ( numTeams == 0 ) {\n\t\tError( \"Failed to register teams, no teams available in \\\"%s\\\"!\\n\", path.c_str() );\n\t}\n\n\tfor ( unsigned int i = 0; i < numTeams; ++i ) {\n\t\tconfig.EnterChildNode( i );\n\n\t\tPlayerTeam team;\n\t\tteam.name = lm_gtr( config.GetStringProperty( \"name\", team.name, false ).c_str() );\n\t\tteam.colour = config.GetColourProperty( \"colour\", hei::Colour( 255, 255, 255 ), false );\n\t\tteam.debrief_texture = config.GetStringProperty( \"debriefTexture\", team.debrief_texture, false );\n\t\tteam.paper_texture = config.GetStringProperty( \"paperTextures\", team.paper_texture, false );\n\t\tteam.pig_textures = config.GetStringProperty( \"pigTextures\", team.pig_textures, false );\n\t\tteam.voice_set = config.GetStringProperty( \"voiceSet\", team.voice_set, false );\n\n\t\tdefaultTeams.push_back( team );\n\n\t\tconfig.LeaveChildNode();\n\t}\n}\n\nvoid ohw::GameManager::RegisterClassManifest( const std::string &path ) {\n\tJsonReader config( path );\n\n\tunsigned int numClasses = config.GetArrayLength( \"classes\" );\n\tif ( numClasses == 0 ) {\n\t\tError( \"Failed to register classes, no classes available in \\\"%s\\\"!\\n\", path.c_str() );\n\t}\n\n\tconfig.EnterChildNode( \"classes\" );\n\tfor ( unsigned int i = 0; i < numClasses; ++i ) {\n\t\tconfig.EnterChildNode( i );\n\n\t\tCharacterClass playerClass;\n\t\tplayerClass.identifer = config.GetStringProperty( \"identifier\" );\n\t\tplayerClass.cost = config.GetIntegerProperty( \"cost\" );\n\t\tplayerClass.health = config.GetIntegerProperty( \"health\" );\n\t\tplayerClass.model = config.GetStringProperty( \"model\" );\n\t\tplayerClass.label = lm_gtr( config.GetStringProperty( \"label\" ).c_str() );\n\n\t\tdefaultClasses.emplace( std::pair< std::string, CharacterClass >( playerClass.identifer, playerClass ) );\n\n\t\tconfig.LeaveChildNode();\n\t}\n}\n\nvoid ohw::GameManager::RegisterMapManifest( const std::string &path ) {\n\tPrint( \"Registering map \\\"%s\\\"...\\n\", path.c_str() );\n\n\tMapManifest manifest;\n\ttry {\n\t\tJsonReader config( path );\n\t\tmanifest.name = config.GetStringProperty( \"name\", manifest.name );\n\t\tmanifest.author = config.GetStringProperty( \"author\", manifest.author );\n\t\tmanifest.description = config.GetStringProperty( \"description\", manifest.description );\n\t\tmanifest.tile_directory = config.GetStringProperty( \"tileDirectory\", manifest.tile_directory );\n\t\tmanifest.modes = config.GetArrayStrings( \"modes\" );\n\t\tmanifest.ambient_colour = config.GetColourProperty( \"ambientColour\", manifest.ambient_colour );\n\t\tmanifest.sky_colour_top = config.GetColourProperty( \"skyColourTop\", manifest.sky_colour_top );\n\t\tmanifest.sky_colour_bottom = config.GetColourProperty( \"skyColourBottom\", manifest.sky_colour_bottom );\n\t\tmanifest.sun_colour = config.GetColourProperty( \"sunColour\", manifest.sun_colour );\n\t\tmanifest.sun_yaw = config.GetFloatProperty( \"sunYaw\", manifest.sun_yaw );\n\t\tmanifest.sun_pitch = config.GetFloatProperty( \"sunPitch\", manifest.sun_pitch );\n\t\tmanifest.temperature = config.GetStringProperty( \"temperature\", manifest.temperature );\n\t\tmanifest.weather = config.GetStringProperty( \"weather\", manifest.weather );\n\t\tmanifest.time = config.GetStringProperty( \"time\", manifest.time );\n\n\t\t// Fog\n\t\tmanifest.fog_colour = config.GetColourProperty( \"fogColour\", manifest.fog_colour );\n\t\tmanifest.fog_intensity = config.GetFloatProperty( \"fogIntensity\", manifest.fog_intensity );\n\t\tmanifest.fog_distance = config.GetFloatProperty( \"fogDistance\", manifest.fog_distance );\n\t} catch ( const std::exception &e ) {\n\t\tWarning( \"Failed to read map config, \\\"%s\\\"!\\n%s\\n\", path.c_str(), e.what() );\n\t}\n\n\tchar temp_buf[64];\n\tPlStripExtension( temp_buf, sizeof( temp_buf ), PlGetFileName( path.c_str() ) );\n\n\tmanifest.filepath = path;\n\tmanifest.filename = temp_buf;\n\n\tmapManifests.insert( std::make_pair( temp_buf, manifest ) );\n}\n\nstatic void RegisterManifestInterface( const char *path, void *userPtr ) {\n\tu_unused( userPtr );\n\tohw::GetApp()->gameManager->RegisterMapManifest( path );\n}\n\n/**\n * Scans the campaigns directory for .map files and indexes them.\n */\nvoid ohw::GameManager::RegisterMapManifests() {\n\tmapManifests.clear();\n\tPlScanDirectory( \"maps\", \"map\", RegisterManifestInterface, false, nullptr );\n}\n\n/**\n * Returns a pointer to the requested manifest.\n * @param name\n * @return Returns a pointer to the requested manifest, otherwise returns null.\n */\nMapManifest *ohw::GameManager::GetMapManifest( const std::string &name ) {\n\tauto manifest = mapManifests.find( name );\n\tif ( manifest != mapManifests.end() ) {\n\t\treturn &manifest->second;\n\t}\n\n\tWarning( \"Failed to get manifest for \\\"%s\\\"!\\n\", name.c_str() );\n\treturn nullptr;\n}\n\n/**\n * Creates a new map manifest and writes it into the maps directory.\n * @param name\n * @return\n */\nMapManifest *ohw::GameManager::CreateManifest( const std::string &name ) {\n\t// ensure the map doesn't exist already\n\tif ( GetApp()->gameManager->GetMapManifest( name ) != nullptr ) {\n\t\tWarning( \"Unable to create map, it already exists!\\n\" );\n\t\treturn nullptr;\n\t}\n\n\tconst ModManager::ModDescription *currentMod = GetApp()->modManager->GetCurrentModDescription();\n\tstd::string path = \"mods/\" + currentMod->directory + \"maps/\" + name + \".map\";\n\tstd::ofstream output( path );\n\tif ( !output.is_open() ) {\n\t\tWarning( \"Failed to write to \\\"%s\\\", aborting!n\\\"\\n\", path.c_str() );\n\t\treturn nullptr;\n\t}\n\n\tMapManifest manifest;\n\toutput << manifest.Serialize();\n\toutput.close();\n\n\tPrint( \"Wrote \\\"%s\\\"!\\n\", path.c_str() );\n\n\tGetApp()->gameManager->RegisterMapManifest( path );\n\treturn GetApp()->gameManager->GetMapManifest( name );\n}\n\nconst CharacterClass *ohw::GameManager::GetDefaultClass( const std::string &classIdentifer ) const {\n\tconst auto &i = defaultClasses.find( classIdentifer );\n\tif ( i == defaultClasses.end() ) {\n\t\tWarning( \"Failed to find character class \\\"%s\\\"!\\n\", classIdentifer.c_str() );\n\t\treturn nullptr;\n\t}\n\n\treturn &i->second;\n}\n\nvoid ohw::GameManager::CreateMapCommand( unsigned int argc, char **argv ) {\n\tif ( argc < 2 ) {\n\t\tWarning( \"Invalid number of arguments, ignoring!\\n\" );\n\t\treturn;\n\t}\n\n\tMapManifest *manifest = GetApp()->gameManager->CreateManifest( argv[ 1 ] );\n\tif ( manifest == nullptr ) {\n\t\treturn;\n\t}\n\n\tGetApp()->gameManager->LoadMap( argv[ 1 ] );\n}\n\n/**\n * Loads the specified map.\n */\nvoid ohw::GameManager::OpenMapCommand( unsigned int argc, char **argv ) {\n\tif ( argc < 2 ) {\n\t\tWarning( \"Invalid number of arguments, ignoring!\\n\" );\n\t\treturn;\n\t}\n\n\tstd::string modeString = \"singleplayer\";\n\tconst MapManifest *desc = GetApp()->gameManager->GetMapManifest( argv[ 1 ] );\n\tif ( desc != nullptr && !desc->modes.empty() ) {\n\t\tmodeString = desc->modes[ 0 ];\n\t}\n\n\t// Set up a mode with some defaults.\n\tGameModeDescriptor descriptor = GameModeDescriptor();\n\tGetApp()->gameManager->StartMode( argv[ 1 ], { new Player( PlayerType::LOCAL ) }, descriptor );\n}\n\n/**\n * Provide a list of all the currently registered maps.\n */\nvoid ohw::GameManager::ListMapsCommand( unsigned int argc, char **argv ) {\n\tif ( GetApp()->gameManager->mapManifests.empty() ) {\n\t\tWarning( \"No maps available!\\n\" );\n\t\treturn;\n\t}\n\n\tfor ( auto manifest: GetApp()->gameManager->mapManifests ) {\n\t\tMapManifest *desc = &manifest.second;\n\t\tstd::string out =\n\t\t\t\tdesc->name + \"/\" + manifest.first +\n\t\t\t\t\" : \" + desc->description +\n\t\t\t\t\" :\";\n\t\t// print out all the supported modes\n\t\tfor ( size_t i = 0; i < desc->modes.size(); ++i ) {\n\t\t\tout += ( i == 0 ? \" \" : \", \" ) + desc->modes[ i ];\n\t\t}\n\t\tPrint( \"%s\\n\", out.c_str() );\n\t}\n\n\tPrint( \"%u maps\\n\", GetApp()->gameManager->mapManifests.size() );\n}\n\nvoid ohw::GameManager::GiveItemCommand( unsigned int argc, char **argv ) {\n\tif ( argc < 2 ) {\n\t\tWarning( \"Invalid number of arguments, ignoring!\\n\" );\n\t\treturn;\n\t}\n\n\tGameMode *mode = dynamic_cast<GameMode *>(GetApp()->gameManager->GetMode());\n\tif ( mode == nullptr ) {\n\t\tPrint( \"Command cannot function outside of game!\\n\" );\n\t\treturn;\n\t}\n\n\tActor *actor = mode->GetPossessedActor();\n\tif ( actor == nullptr ) {\n\t\tWarning( \"No actor currently active!\\n\" );\n\t\treturn;\n\t}\n\n\tAPig *pig = dynamic_cast<APig *>(actor);\n\tif ( pig == nullptr ) {\n\t\tWarning( \"Actor is not a pig!\\n\" );\n\t\treturn;\n\t}\n\n\tauto item = static_cast<ItemIdentifier>(strtol( argv[ 1 ], nullptr, 10 ));\n\tunsigned int quantity = 1;\n\tif ( argc > 2 ) {\n\t\tquantity = strtol( argv[ 2 ], nullptr, 10 );\n\t}\n\n\tpig->AddInventoryItem( item, quantity );\n}\n\nvoid ohw::GameManager::KillSelfCommand( unsigned int argc, char **argv ) {\n\tGameMode *mode = dynamic_cast<GameMode *>(GetApp()->gameManager->GetMode());\n\tif ( mode == nullptr ) {\n\t\tPrint( \"Command cannot function outside of game!\\n\" );\n\t\treturn;\n\t}\n\n\tActor *actor = mode->GetPossessedActor();\n\tif ( actor == nullptr ) {\n\t\tWarning( \"No actor currently active!\\n\" );\n\t\treturn;\n\t}\n\n\tactor->Damage( nullptr, 9999 );\n}\n\nvoid ohw::GameManager::SpawnModelCommand( unsigned int argc, char **argv ) {\n\tif ( argc < 2 ) {\n\t\tWarning( \"Invalid number of arguments, ignoring!\\n\" );\n\t\treturn;\n\t}\n\n\tGameMode *mode = dynamic_cast<GameMode *>(GetApp()->gameManager->GetMode());\n\tif ( mode == nullptr ) {\n\t\tPrint( \"Command cannot function outside of game!\\n\" );\n\t\treturn;\n\t}\n\n\t// Fetch the player's actor, so we can get their position\n\tActor *actor = mode->GetPossessedActor();\n\tif ( actor == nullptr ) {\n\t\tWarning( \"No actor currently active!\\n\" );\n\t\treturn;\n\t}\n\n\tAStaticModel *modelActor = dynamic_cast<AStaticModel *>(ActorManager::GetInstance()->CreateActor( \"model_static\" ));\n\tif ( modelActor == nullptr ) {\n\t\tError( \"Failed to create model actor!\\n\" );\n\t\treturn;\n\t}\n\n\tmodelActor->SetModel( argv[ 1 ] );\n\tmodelActor->SetPosition( actor->GetPosition() );\n\tmodelActor->SetAngles( actor->GetAngles() );\n}\n\nvoid ohw::GameManager::TeleportCommand( unsigned int argc, char **argv ) {\n\tif ( argc < 4 ) {\n\t\tWarning( \"Invalid number of arguments, ignoring!\\n\" );\n\t\treturn;\n\t}\n\n\tGameMode *mode = dynamic_cast<GameMode *>(GetApp()->gameManager->GetMode());\n\tif ( mode == nullptr ) {\n\t\tPrint( \"Command cannot function outside of game!\\n\" );\n\t\treturn;\n\t}\n\n\t// Fetch the player's actor, so we can get their position\n\tActor *actor = mode->GetPossessedActor();\n\tif ( actor == nullptr ) {\n\t\tWarning( \"No actor currently active!\\n\" );\n\t\treturn;\n\t}\n\n\thei::Vector3 teleportDestination(\n\t\t\tstrtof( argv[ 1 ], nullptr ),\n\t\t\tstrtof( argv[ 2 ], nullptr ),\n\t\t\tstrtof( argv[ 3 ], nullptr ) );\n\tactor->SetPosition( teleportDestination );\n}\n\nvoid ohw::GameManager::FirstPersonCommand( unsigned int argc, char **argv ) {\n\tstatic CameraMode oldCameraMode = CameraMode::FOLLOW;\n\n\tif ( GetApp()->gameManager->cameraMode != CameraMode::FIRSTPERSON ) {\n\t\toldCameraMode = GetApp()->gameManager->cameraMode;\n\t\tGetApp()->gameManager->cameraMode = CameraMode::FIRSTPERSON;\n\t\treturn;\n\t}\n\n\tGetApp()->gameManager->cameraMode = oldCameraMode;\n}\n\nvoid ohw::GameManager::FreeCamCommand( unsigned int argc, char **argv ) {\n\tstatic CameraMode oldCameraMode = CameraMode::FOLLOW;\n\n\tif ( GetApp()->gameManager->cameraMode != CameraMode::FLY ) {\n\t\toldCameraMode = GetApp()->gameManager->cameraMode;\n\t\tGetApp()->gameManager->cameraMode = CameraMode::FLY;\n\t\treturn;\n\t}\n\n\tGetApp()->gameManager->cameraMode = oldCameraMode;\n}\n\nvoid ohw::GameManager::StartMode( const std::string &map,\n                                  const PlayerPtrVector &players,\n                                  const GameModeDescriptor &descriptor ) {\n\tFrontEnd_SetState( FE_MODE_LOADING );\n\n\t// Free up all our unreferenced resources\n\tGetApp()->resourceManager->ClearAllResources();\n\n\tLoadMap( map );\n\n\tif ( currentMap == nullptr ) {\n\t\tWarning( \"Failed to start mode, map wasn't loaded!\\n\" );\n\t\tEndMode();\n\t\treturn;\n\t}\n\n\tstd::string sample_ext = \"d\";\n\tif ( currentMap->GetManifest()->time != \"day\" ) {\n\t\tsample_ext = \"n\";\n\t}\n\n\tambient_emit_delay_ = GetApp()->GetSimulationTicks() + PlGenerateRandomDouble( 100 ) + 1;\n\tfor ( unsigned int i = 1, idx = 0; i < 4; ++i ) {\n\t\tstd::string snum = std::to_string( i );\n\t\tstd::string path = \"audio/amb_\";\n\t\tif ( i < 3 ) {\n\t\t\tpath += snum + sample_ext + \".wav\";\n\t\t\tambient_samples_[ idx++ ] = GetApp()->audioManager->CacheSample( path, false );\n\t\t}\n\n\t\tpath = \"audio/batt_s\" + snum + \".wav\";\n\t\tambient_samples_[ idx++ ] = GetApp()->audioManager->CacheSample( path, false );\n\t\tpath = \"audio/batt_l\" + snum + \".wav\";\n\t\tambient_samples_[ idx++ ] = GetApp()->audioManager->CacheSample( path, false );\n\t}\n\n\tFrontEnd_SetState( FE_MODE_GAME );\n\n\t// call StartRound; deals with spawning everything in and other mode specific logic\n\tcurrentMode = new GameMode( descriptor );\n\n\tSetupPlayers( players );\n\n\tcurrentMode->StartRound();\n}\n\n/**\n * End the currently active mode and flush everything.\n */\nvoid ohw::GameManager::EndMode() {\n\tdelete currentMode;\n\n\t// Clear out all the allocated players for this game\n\tClearPlayers();\n\n\tUnloadMap();\n\n\tActorManager::GetInstance()->DestroyActors();\n\n\t// Free up all our unreferenced resources\n\tGetApp()->resourceManager->ClearAllResources();\n\n\tGetApp()->audioManager->FreeSources();\n\tGetApp()->audioManager->FreeSamples();\n}\n\n/**\n * Check whether or not a mode is currently active.\n * @return Returns true if a mode is currently active.\n */\nbool ohw::GameManager::IsModeActive() {\n\treturn ( currentMode != nullptr );\n}\n\n/**\n * Handle the different camera modes.\n */\nvoid ohw::GameManager::TickCamera() {\n\tswitch ( cameraMode ) {\n\t\tcase CameraMode::FLY:\n\t\t\tbreak;\n\t\tcase CameraMode::FIRSTPERSON: {\n\t\t\tGameMode *mode = dynamic_cast<GameMode *>(GetMode());\n\t\t\tif ( mode == nullptr ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tActor *actor = mode->GetPossessedActor();\n\t\t\tif ( actor == nullptr ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tPLVector3 forward = actor->GetForward();\n\t\t\tPLVector3 pos = actor->GetPosition();\n\t\t\tdefaultCamera->SetPosition( pos.x + forward.x * -500.0f, pos.y + 500.0f, pos.z + forward.z * -500.0f );\n\t\t\tbreak;\n\t\t}\n\n\t\tcase CameraMode::FOLLOW: {\n\t\t\tGameMode *mode = dynamic_cast<GameMode *>(GetMode());\n\t\t\tif ( mode == nullptr ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tActor *actor = mode->GetPossessedActor();\n\t\t\tif ( actor == nullptr ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tPLVector3 forward = actor->GetForward();\n\t\t\tPLVector3 pos = actor->GetPosition();\n\t\t\tdefaultCamera->SetPosition( pos.x + forward.x * -500.0f, pos.y + 500.0f, pos.z + forward.z * -500.0f );\n\t\t\tdefaultCamera->SetAngles( -25.0f, actor->GetAngles().y, 0.0f );\n\t\t\tbreak;\n\t\t}\n\n\t\tcase CameraMode::FLYAROUND:\n\t\t\tbreak;\n\t}\n}\n\nstd::string ohw::GameManager::GetCurrentMapDirectory() const {\n\tif ( currentMap == nullptr ) {\n\t\treturn \"\";\n\t}\n\n\tMapManifest *manifest = currentMap->GetManifest();\n\tif ( manifest == nullptr ) {\n\t\treturn \"\";\n\t}\n\n\treturn \"maps/\" + manifest->filename + \"/\";\n}\n"
  },
  {
    "path": "src/engine/game/GameManager.h",
    "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// Copyright © 2017-2022 TalonBrave.info and Others (see CONTRIBUTORS)\n\n#pragma once\n\n#include \"Actor.h\"\n#include \"GameModeInterface.h\"\n\nenum class CharacterStatus {\n\tNONE = -1,\n\tALIVE,\n\tDEAD,\n};\n\n/* \n  NONE = -1,\n  GRUNT,\n  // Heavy Weapons\n  GUNNER,\n  BOMBARDIER,\n  PYROTECHNIC,\n  // Engineer\n  SAPPER,\n  ENGINEER,\n  SABOTEUR,\n  // Espionage\n  SCOUT,\n  SNIPER,\n  SPY,\n  // Medic\n  ORDERLY,\n  MEDIC,\n  SURGEON,\n  // High Rank\n  COMMANDO,\n  HERO,\n  ACE,\n  LEGEND,\n  // Multiplayer\n  PARATROOPER,\n  GRENADIER,\n */\n\nstruct CharacterClass : PropertyOwner {\n\tCharacterClass() :\n\t\t\tINIT_PROPERTY( identifer, 0 ),\n\t\t\tINIT_PROPERTY( label, 0 ),\n\t\t\tINIT_PROPERTY( model, 0 ),\n\t\t\tINIT_PROPERTY( nextClass, 0 ),\n\t\t\tINIT_PROPERTY( cost, 0, 0 ),\n\t\t\tINIT_PROPERTY( health, 0, 0 ) {}\n\tCharacterClass( const CharacterClass &src ) :\n\t\t\tCOPY_PROPERTY( identifer, src ),\n\t\t\tCOPY_PROPERTY( label, src ),\n\t\t\tCOPY_PROPERTY( model, src ),\n\t\t\tCOPY_PROPERTY( nextClass, src ),\n\t\t\tCOPY_PROPERTY( cost, src ),\n\t\t\tCOPY_PROPERTY( health, src ) {}\n\n\tStringProperty identifer;\n\tStringProperty label;\n\tStringProperty model;\n\tStringProperty nextClass;\n\tNumericProperty< unsigned int > cost;\n\tNumericProperty< unsigned int > health;\n\n\tstruct Item {\n\t\tstd::string key;\n\t\tstd::string classname;\n\t\tunsigned int quantity{ 0 };\n\t};\n\tstd::vector< Item > items;\n};\n\nstruct CharacterSlot : PropertyOwner {\n\tCharacterSlot() :\n\t\t\tINIT_PROPERTY( portrait, 0 ),\n\t\t\tINIT_PROPERTY( portrait_selected, 0 ),\n\t\t\tINIT_PROPERTY( portrait_wounded, 0 ),\n\t\t\tINIT_PROPERTY( voice_language, 0 ),\n\t\t\tINIT_PROPERTY( voice_set, 0, 0 ) {}\n\tCharacterSlot( const CharacterSlot &src ) :\n\t\t\tCOPY_PROPERTY( portrait, src ),\n\t\t\tCOPY_PROPERTY( portrait_selected, src ),\n\t\t\tCOPY_PROPERTY( portrait_wounded, src ),\n\t\t\tCOPY_PROPERTY( voice_language, src ),\n\t\t\tCOPY_PROPERTY( voice_set, src ),\n\t\t\tname( src.name ),\n\t\t\tclassname( src.classname ),\n\t\t\tstatus( src.status ),\n\t\t\tkill_count( src.kill_count ),\n\t\t\tdeath_count( src.death_count ) {}\n\n\t// Static\n\tStringProperty portrait;           // Face profile\n\tStringProperty portrait_selected;  // Selected face profile\n\tStringProperty portrait_wounded;   // Wounded face profile\n\tStringProperty voice_language;\n\tNumericProperty< unsigned int > voice_set;\n\n\t// Dynamic\n\tstd::string name;                               // Assigned name, e.g. Herman\n\tconst CharacterClass *classname{ nullptr };               // Ace, gunner, sapper etc.\n\tCharacterStatus status{ CharacterStatus::ALIVE };   // Pig's status (alive / dead)\n\tunsigned int kill_count{ 0 };                    // Number of other pigs we've killed\n\tunsigned int death_count{ 0 };                   // Number of times we've died\n};\n\nstruct PlayerTeam : PropertyOwner {\n\tPlayerTeam() :\n\t\t\tINIT_PROPERTY( name, 0 ),\n\t\t\tINIT_PROPERTY( description, 0 ),\n\t\t\tINIT_PROPERTY( pig_textures, 0 ),\n\t\t\tINIT_PROPERTY( paper_texture, 0 ),\n\t\t\tINIT_PROPERTY( debrief_texture, 0 ),\n\t\t\tINIT_PROPERTY( voice_set, 0 ) {}\n\tPlayerTeam( const PlayerTeam &src ) :\n\t\t\tCOPY_PROPERTY( name, src ),\n\t\t\tCOPY_PROPERTY( description, src ),\n\t\t\tCOPY_PROPERTY( pig_textures, src ),\n\t\t\tCOPY_PROPERTY( paper_texture, src ),\n\t\t\tCOPY_PROPERTY( debrief_texture, src ),\n\t\t\tCOPY_PROPERTY( voice_set, src ),\n\t\t\tcolour( src.colour ),\n\t\t\tslots( src.slots ) {}\n\n\tStringProperty name;\n\tStringProperty description;\n\n\t// data directories\n\tStringProperty pig_textures;\n\tStringProperty paper_texture;\n\tStringProperty debrief_texture;\n\tStringProperty voice_set;\n\n\tPLColour colour;\n\n\tstd::array< CharacterSlot, 8 > slots;\n};\n\nstruct MapManifest {\n\tstd::string filepath; // path to manifest\n\tstd::string filename; // name of the manifest\n\n\tstd::string name{ \"none\" };                       // 'BOOT CAMP'\n\tstd::string author{ \"none\" };                     // creator of the map\n\tstd::string description{ \"none\" };                //\n\tstd::string tile_directory;\n\tstd::vector< std::string > modes;                 // supported gameplay types\n\thei::Colour ambient_colour{ 255, 255, 255, 255 };    // ambient colour\n\t// Sky gradient\n\thei::Colour sky_colour_top{ 0, 104, 156 };\n\thei::Colour sky_colour_bottom{ 223, 255, 255 };\n\t// Sun/lighting properties\n\thei::Colour sun_colour{ 255, 255, 255 };      // directional colour\n\tfloat sun_yaw{ 0 }, sun_pitch{ 0 };       // light direction (yaw/angle)\n\t// Fog\n\thei::Colour fog_colour{ 223, 255, 255, 255 };\n\tfloat fog_intensity{ 30.0f };\n\tfloat fog_distance{ 100.0f };\n\t// Misc\n\tstd::string temperature{ \"normal\" };    // Determines idle animation set. Can be normal/hot/cold\n\tstd::string time{ \"day\" };              // Determines ambient sound set. Can be day/night\n\tstd::string weather{ \"clear\" };         // Determines weather particles. Can be clear/rain/snow\n\n\tstd::string Serialize();\n};\n\nstruct GameModeDescriptor {\n\tstd::string desired_mode{ \"survival\" };\n\n\t// Mode specific properties, probably provide these\n\t// via json going forward and then parse via the mode... somehow\n\tbool select_pig{ false };\n\tbool sudden_death{ false };\n\tunsigned int default_health{ 50 };\n\tunsigned int num_pigs{ 3 };\n\tunsigned int turn_time{ 45 };\n\tunsigned int deathmatch_limit{ 5 };\n};\n\ntypedef std::vector< Player * > PlayerPtrVector;\n\nstruct AudioSample;\n\nnamespace ohw {\n\tclass Map;\n\n\tclass Camera;\n\n\tclass GameManager {\n\tprivate:\n\t\tGameManager();\n\t\t~GameManager();\n\n\tpublic:\n\t\tvoid Tick();\n\n\t\tinline Camera *GetActiveCamera() const { return defaultCamera; }\n\n\t\tvoid StartMode( const std::string &map, const PlayerPtrVector &players, const GameModeDescriptor &descriptor );\n\t\tvoid EndMode();\n\n\t\tvoid SetupPlayers( const PlayerPtrVector &teams );\n\t\tvoid ClearPlayers();\n\t\tPlayer *GetPlayerByIndex( unsigned int i ) const;\n\t\tconst PlayerPtrVector &GetPlayers() { return players_; }\n\n\t\t// Map\n\t\tvoid LoadMap( const std::string &name );\n\t\tvoid UnloadMap();\n\n\t\tvoid CachePersistentData();\n\n\t\tvoid RegisterTeamManifest( const std::string &path );\n\t\tvoid RegisterClassManifest( const std::string &path );\n\t\tvoid RegisterMapManifest( const std::string &path );\n\t\tvoid RegisterMapManifests();\n\n\t\ttypedef std::map< std::string, MapManifest > MapManifestMap;\n\t\tMapManifest *GetMapManifest( const std::string &name );\n\t\tconst MapManifestMap &GetMapManifests() { return mapManifests; };\n\t\tMapManifest *CreateManifest( const std::string &name );\n\t\t//void SaveManifest(const std::string& name, const MapManifest& manifest);\n\n\t\ttypedef std::vector< PlayerTeam > PlayerTeamVector;\n\t\tconst PlayerTeamVector &GetDefaultTeams() const { return defaultTeams; }\n\n\t\ttypedef std::map< std::string, CharacterClass > CharacterClassMap;\n\t\tconst CharacterClass *GetDefaultClass( const std::string &classIdentifer ) const;\n\n\t\tinline Map *GetCurrentMap() const { return currentMap; }\n\t\tinline IGameMode *GetMode() const { return currentMode; }\n\n\t\tbool IsModeActive();\n\n\t\tinline void StepSimulation( unsigned int steps = 1 ) {\n\t\t\tsimSteps = steps;\n\t\t}\n\n\t\tinline void ToggleSimulation( bool paused ) {\n\t\t\tpauseSim = paused;\n\t\t}\n\n\t\tstd::string GetCurrentMapDirectory() const;\n\n\tprotected:\n\t\tvoid TickCamera();\n\n\tprivate:\n\t\tstatic void OpenMapCommand( unsigned int argc, char *argv[] );\n\t\tstatic void CreateMapCommand( unsigned int argc, char *argv[] );\n\t\tstatic void ListMapsCommand( unsigned int argc, char **argv );\n\t\tstatic void GiveItemCommand( unsigned int argc, char *argv[] );\n\t\tstatic void KillSelfCommand( unsigned int argc, char **argv );\n\t\tstatic void SpawnModelCommand( unsigned int argc, char **argv );\n\t\tstatic void TeleportCommand( unsigned int argc, char **argv );\n\t\tstatic void FirstPersonCommand( unsigned int argc, char **argv );\n\t\tstatic void FreeCamCommand( unsigned int argc, char **argv );\n\n\t\tbool pauseSim{ false };\n\t\tunsigned int simSteps{ 0 };\n\n\t\t/////////////////////////////////////////////////////////////\n\t\t// Camera\n\n\t\tenum class CameraMode {\n\t\t\t// Debugging modes\n\n\t\t\tFLY,          // Fly around\n\t\t\tFIRSTPERSON,  // First person controls\n\n\t\t\t// Gameplay\n\n\t\t\tFOLLOW,       // Follows behind a specific entity\n\t\t\tFLYAROUND,\n\t\t};\n\n\t\tCamera *defaultCamera{ nullptr };\n\t\tCameraMode cameraMode{ CameraMode::FOLLOW };\n\n\t\t/////////////////////////////////////////////////////////////\n\n\t\tMap *currentMap{ nullptr };\n\n\t\tIGameMode *currentMode{ nullptr };\n\n\t\tstd::map< std::string, MapManifest > mapManifests;\n\n\t\tPlayerTeamVector defaultTeams;\n\t\tCharacterClassMap defaultClasses;\n\n\t\tPlayerPtrVector players_;\n\n#define MAX_AMBIENT_SAMPLES 8\n\t\tdouble ambient_emit_delay_{ 0 };\n\t\tconst AudioSample *ambient_samples_[MAX_AMBIENT_SAMPLES]{};\n\n\t\tfriend class App;\n\t};\n}\n"
  },
  {
    "path": "src/engine/game/GameMode.cpp",
    "content": "/* OpenHoW\n * Copyright (C) 2017-2020 TalonBrave.info and Others (see CONTRIBUTORS)\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include \"App.h\"\n#include \"Map.h\"\n#include \"GameMode.h\"\n#include \"ActorManager.h\"\n#include \"Player.h\"\n#include \"APig.h\"\n#include \"AAirship.h\"\n#include \"graphics/Camera.h\"\n\nusing namespace ohw;\n\nGameMode::GameMode( const GameModeDescriptor &descriptor ) {\n\tmax_turn_ticks = descriptor.turn_time * TICKS_PER_SECOND;\n}\n\nGameMode::~GameMode() = default;\n\nvoid GameMode::StartRound() {\n\tif ( HasRoundStarted() ) {\n\t\tError( \"Attempted to change map in the middle of a round, aborting!\\n\" );\n\t}\n\n\tSpawnActors();\n\n\t// Play the deployment music\n\tGetApp()->audioManager->PlayMusic( \"music/track\" + std::to_string( std::rand() % 4 + 27 ) + \".ogg\" );\n\n\tStartTurn( GetCurrentPlayer() );\n\n\thasRoundStarted = true;\n}\n\nvoid GameMode::RestartRound() {\n\tDestroyActors();\n\n\tStartRound();\n}\n\nvoid GameMode::EndRound() {\n\tDestroyActors();\n}\n\nvoid GameMode::Tick() {\n\tif ( !HasRoundStarted() ) {\n\t\t// still setting the game up...\n\t\treturn;\n\t}\n\n\tPlayer *player = GetCurrentPlayer();\n\tif ( player == nullptr ) {\n\t\treturn;\n\t}\n\n\tif ( !HasTurnStarted() ) {\n\t\tStartTurn( player );\n\t\treturn;\n\t}\n\n\tActor *actor = player->GetCurrentChild();\n\tif ( actor == nullptr ) {\n\t\treturn;\n\t}\n\n\tactor->HandleInput();\n\n\tif ( HasTurnStarted() ) {\n\t\tnum_turn_ticks++;\n\t\tif ( num_turn_ticks >= max_turn_ticks ) {\n\t\t\tEndTurn( player );\n\t\t}\n\t}\n}\n\nvoid GameMode::SpawnActors() {\n\tMap *map = GetApp()->gameManager->GetCurrentMap();\n\tif ( map == nullptr ) {\n\t\tError( \"Attempted to spawn actors without having loaded a map!\\n\" );\n\t\treturn;\n\t}\n\n\tconst std::vector< ActorSpawn > &spawns = map->GetSpawns();\n\tfor ( const auto &spawn : spawns ) {\n\t\tActor *actor = ActorManager::GetInstance()->CreateActor( spawn.className, spawn );\n\t\tif ( actor == nullptr ) {\n\t\t\tactor = ActorManager::GetInstance()->CreateActor( \"model_static\", spawn );\n\t\t}\n\n\t\tAPig *pig = dynamic_cast<APig *>(actor);\n\t\tif ( pig == nullptr ) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tPlayer *player = GetApp()->gameManager->GetPlayerByIndex( pig->GetTeam() );\n\t\tif ( player == nullptr ) {\n\t\t\tWarning( \"Failed to assign pig to team!\\n\" );\n\t\t\tcontinue;\n\t\t}\n\n\t\tpig->SetPlayerOwner( player );\n\t}\n\n\tAAirship *model_actor = dynamic_cast<AAirship *>(ActorManager::GetInstance()->CreateActor( \"vehicle_airship\" ));\n\tif ( model_actor == nullptr ) {\n\t\tError( \"Failed to create model actor!\\n\" );\n\t}\n\n\tActorManager::GetInstance()->ActivateActors();\n}\n\nvoid GameMode::DestroyActors() {\n\tActorManager::GetInstance()->DestroyActors();\n}\n\nvoid GameMode::StartTurn( Player *player ) {\n\tif ( player->GetNumChildren() == 0 ) {\n\t\tWarning( \"No valid control target for player \\\"%s\\\"!\\n\", player->GetTeam()->name.c_str() );\n\t\treturn;\n\t}\n\n\tplayer->PossessCurrentChild();\n\n\tturn_started_ = true;\n}\n\nvoid GameMode::EndTurn( Player *player ) {\n\tplayer->DispossessCurrentChild();\n\tplayer->CycleChildren();\n\n\t// move onto the next player\n\tCyclePlayers();\n\n\tnum_turn_ticks = 0;\n\tturn_started_ = false;\n}\n\nvoid GameMode::PlayerJoined( Player *player ) {\n\t// todo: display prompt\n\tPrint( \"%s has joined the game\\n\", player->GetTeam()->name.c_str() );\n}\n\nvoid GameMode::PlayerLeft( Player *player ) {\n\t// todo: display prompt\n\tPrint( \"%s has left the game\\n\", player->GetTeam()->name.c_str() );\n}\n\nunsigned int GameMode::GetMaxSpectators() const {\n\treturn 0;\n}\n\nvoid GameMode::SpectatorJoined( Player *player ) {\n\t// todo: display prompt\n\tPrint( \"%s has joined the spectators\\n\", player->GetTeam()->name.c_str() );\n}\n\nvoid GameMode::SpectatorLeft( Player *player ) {\n\t// todo: display prompt\n\tPrint( \"%s has left the spectators\\n\", player->GetTeam()->name.c_str() );\n}\n\n/**\n * Maximum players allowed in this mode.\n * @return Number of players.\n */\nunsigned int GameMode::GetMaxPlayers() const {\n\treturn 4;\n}\n\nPlayer *GameMode::GetCurrentPlayer() {\n\treturn GetApp()->gameManager->GetPlayerByIndex( currentPlayer );\n}\n\nActor *GameMode::GetPossessedActor() {\n\tPlayer *player = GetCurrentPlayer();\n\tif ( player == nullptr ) {\n\t\treturn nullptr;\n\t}\n\n\treturn player->GetCurrentChild();\n}\n\nvoid GameMode::CyclePlayers() {\n\tcurrentPlayer++;\n\n\tPlayerPtrVector players = GetApp()->gameManager->GetPlayers();\n\tif ( currentPlayer >= players.size() ) {\n\t\tcurrentPlayer = 0;\n\t}\n}\n\nvoid GameMode::AssignActorToPlayer( Actor *target, Player *owner ) {\n\towner->AddChild( target );\n}\n"
  },
  {
    "path": "src/engine/game/GameMode.h",
    "content": "/* OpenHoW\n * Copyright (C) 2017-2020 TalonBrave.info and Others (see CONTRIBUTORS)\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#pragma once\n\n#include \"GameModeInterface.h\"\n\nnamespace ohw {\n\tclass GameMode : public IGameMode {\n\tpublic:\n\t\texplicit GameMode( const GameModeDescriptor &descriptor );\n\t\t~GameMode() override;\n\n\t\tvoid Tick() override;\n\n\t\tvoid StartRound() override;\n\t\tvoid RestartRound() override;\n\t\tvoid EndRound() override;\n\n\t\tvoid PlayerJoined( Player *player ) override;\n\t\tvoid PlayerLeft( Player *player ) override;\n\n\t\tvoid SpectatorJoined( Player *player ) override;\n\t\tvoid SpectatorLeft( Player *player ) override;\n\n\t\tunsigned int GetMaxSpectators() const override;\n\t\tunsigned int GetMaxPlayers() const override;\n\n\t\tPlayer *GetCurrentPlayer() override;\n\t\tActor *GetPossessedActor();\n\t\tvoid CyclePlayers();\n\n\t\tvoid AssignActorToPlayer( Actor *target, Player *owner ) override;\n\n\tprotected:\n\t\tvoid StartTurn( Player *player ) override;\n\t\tvoid EndTurn( Player *player ) override;\n\n\t\tvoid SpawnActors() override;\n\t\tvoid DestroyActors() override;\n\n\tprivate:\n\t};\n}\n"
  },
  {
    "path": "src/engine/game/GameModeInterface.h",
    "content": "/* OpenHoW\n * Copyright (C) 2017-2020 TalonBrave.info and Others (see CONTRIBUTORS)\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#pragma once\n\nstruct PlayerTeam;\n\nclass Player;\n\nnamespace ohw {\n\tclass IGameMode {\n\tpublic:\n\t\tvirtual ~IGameMode() = default;\n\n\t\tvirtual void Tick() = 0;\n\n\t\tvirtual void StartRound() = 0;\n\t\tvirtual void RestartRound() = 0;\n\t\tvirtual void EndRound() = 0;\n\n\t\tvirtual void PlayerJoined( Player *player ) = 0;\n\t\tvirtual void PlayerLeft( Player *player ) = 0;\n\n\t\tvirtual void SpectatorJoined( Player *player ) = 0;\n\t\tvirtual void SpectatorLeft( Player *player ) = 0;\n\n\t\tvirtual unsigned int GetMaxSpectators() const = 0;\n\t\tvirtual unsigned int GetMaxPlayers() const = 0;\n\n\t\tvirtual Player *GetCurrentPlayer() = 0;\n\n\t\tbool HasModeStarted() const { return mode_started_; }\n\t\tbool HasRoundStarted() const { return hasRoundStarted; }\n\t\tbool HasTurnStarted() const { return turn_started_; }\n\n\t\tunsigned int GetTurnTime() { return num_turn_ticks; }\n\t\tunsigned int GetTurnTimeSeconds() { return num_turn_ticks / TICKS_PER_SECOND; }\n\t\tunsigned int GetMaxTurnTime() { return max_turn_ticks; }\n\t\tunsigned int GetMaxTurnTimeSeconds() { return max_turn_ticks / TICKS_PER_SECOND; }\n\n\t\tvirtual void AssignActorToPlayer( Actor *target, Player *owner ) = 0;\n\n\tprotected:\n\t\tvirtual void StartTurn( Player *player ) = 0;\n\t\tvirtual void EndTurn( Player *player ) = 0;\n\n\t\tvirtual void SpawnActors() = 0;\n\t\tvirtual void DestroyActors() = 0;\n\n\t\tunsigned int max_turn_ticks{ 0 }; // Maximum ticks for a turn\n\t\tunsigned int num_turn_ticks{ 0 }; // Current number of ticks in the turn\n\n\t\tbool mode_started_{ false };\n\t\tbool hasRoundStarted{ false };\n\t\tbool turn_started_{ false };\n\n\t\tunsigned int currentPlayer{ 0 };\n\t};\n}\n"
  },
  {
    "path": "src/engine/game/Inventory.cpp",
    "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// Copyright © 2017-2022 TalonBrave.info and Others (see CONTRIBUTORS)\n\n#include \"App.h\"\n#include \"Inventory.h\"\n\n/**\n * Clear the inventory of items.\n */\nvoid InventoryManager::ClearItems() {\n\titems_.clear();\n}\n\nvoid InventoryManager::AddInventoryItem( ItemIdentifier identifier, unsigned int quantity ) {\n#if 0\n\tu_assert(identifier != InventoryItem::Identifier::INVALID_ID, \"Attempted to add a null item to inventory!\\n\");\n\n\tLogDebug(\"Added %s to inventory\\n\", item->GetInventoryDescription().c_str());\n\n\titems_.emplace(std::pair<std::string, InventoryItem*>(item->GetInventoryDescription(), item));\n#endif\n}\n\nInventoryItem *InventoryManager::GetItem( ItemIdentifier identifier ) {\n\treturn nullptr;\n}\n\n/// Inventory Items\n\nPLGTexture *InventoryItem::GetInventoryIcon() {\n\treturn nullptr;\n}\n\nvoid InventoryItem::Equipped( Actor *other ) {\n\n}\n"
  },
  {
    "path": "src/engine/game/Inventory.h",
    "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// Copyright © 2017-2022 TalonBrave.info and Others (see CONTRIBUTORS)\n\n#pragma once\n\nenum class ItemIdentifier {\n\tNONE,\n\n\tWEAPON_TROTTER,\n\tWEAPON_KNIFE,\n\tWEAPON_BAYONET,\n\tWEAPON_SWORD,\n\tWEAPON_CATTLEPROD,\n\tWEAPON_PISTOL,\n\tWEAPON_RIFLE,\n\tWEAPON_RIFLE_BURST,\n\tWEAPON_MACHINE_GUN,\n\tWEAPON_HMG,\n\tWEAPON_SNIPER_RIFLE,\n\tWEAPON_SHOTGUN,\n\tWEAPON_FLAMETHROWER,\n\tWEAPON_ROCKET_LAUNCHER,\n\tWEAPON_GUIDED_MISSILE,\n\tMEDICINE_DART = 0x10,\n\tTRANQ = 0x11,\n\tGRENADE = 0x12,\n\tCLUSTER_GRENADE = 0x13,\n\tHX_GRENADE = 0x14,\n\tROLLER_GRENADE = 0x15,\n\tCONFUSION_GAS = 0x16,\n\tFREEZE_GAS = 0x17,\n\tMADNESS_GAS = 0x18,\n\tPOISON_GAS = 0x19,\n\tMORTAR = 0x1A,\n\tBAZOOKA = 0x1B,\n\tAIRBURST = 0x1C,\n\tSUPER_AIRBURST = 0x1D,\n\tMEDICINE_BALL = 0x1E,\n\tHOMING_MISSILE = 0x1F,\n\tMINE = 0x20,\n\tAntiPMine = 0x21,\n\tTNT = 0x22,\n\tVEHICLE_LongRangeShell = 35,\n\tVEHICLE_ShockShell,\n\tVEHICLE_1000LBSShell,\n\tVEHICLE_FireShell = 0x26,\n\tVEHICLE_GasShell = 0x27,\n\tVEHICLE_MineShell = 0x28,\n\tVEHICLE_HeavyMachineGun = 0x29,\n\tVEHICLE_Flamethrower = 0x2A,\n\tVEHICLE_AIRBURST = 0x2B,\n\tVEHICLE_BAZOOKA = 0x2C,\n\tVEHICLE_MORTAR = 0x2D,\n\t//Missing 0x2E\n\t//Missing 0x2F\n\t//Missing 0x30\n\t//Missing 0x31\n\t//Missing 0x32\n\tJETPACK = 0x33,\n\tSUICIDE = 0x34,\n\tHEALINGHANDS = 0x35,\n\tSELFHEAL = 0x36,\n\tPICKPOCKET = 0x37,\n\tSHOCKWAVE = 0x38,\n\tSPECIALOPS = 0x39,\n\tAIRSTRIKE = 0x3A,\n\tFireRainAirstrike = 0x3B,\n\tENTERVEHICLE = 0x3C,\n\tENTERBUILDING = 0x3D,\n\tEJECTPIG = 0x3E,\n\tMAPVIEW = 0x3F,\n\tBINOCULARS = 64,\n\tSKIPTURN,\n\tSURRENDER,\n\tSUPERTNT,\n\tHIDE,\n\tSUPERSHOTGUN,\n\tSHRAPNELGRENADE,\n\tGRENADELAUNCHER,\n\t//Missing 0x48\n\tRANDOM = 0x49,\n\tHEALTH = 0xFF,\n\n\tMAX_ITEM_TYPES\n};\n\nclass InventoryItem {\npublic:\n\tInventoryItem() = default;\n\t~InventoryItem() = default;\n\n\tvirtual void Equipped( Actor *actor );\n\n\t// Information for frontend\n\tvirtual bool IsSelectable() { return false; }\n\tvirtual std::string GetInventoryDescription() const { return \"invalid\"; }\n\tvirtual PLGTexture *GetInventoryIcon();\n\nprotected:\n\tunsigned int quantity_{ 0 };\n\tItemIdentifier id_{ ItemIdentifier::NONE };\n\nprivate:\n};\n\nclass InventoryManager {\npublic:\n\n\tInventoryItem *GetItem( ItemIdentifier identifier );\n\tvoid AddInventoryItem( ItemIdentifier identifier, unsigned int quantity );\n\tvoid RemoveItem( ItemIdentifier identifier, unsigned int quantity );\n\n\tvoid ClearItems();\n\nprotected:\nprivate:\n\tstd::map<ItemIdentifier, InventoryItem *> items_;\n};\n"
  },
  {
    "path": "src/engine/game/Player.cpp",
    "content": "/* OpenHoW\n * Copyright (C) 2017-2020 TalonBrave.info and Others (see CONTRIBUTORS)\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include \"App.h\"\n#include \"Player.h\"\n\nPlayer::Player(PlayerType type) : myType( type) {}\nPlayer::~Player() = default;\n\nvoid Player::PossessCurrentChild() {\n\tActor* child = myChildActors[myCurrentChildActorIndex];\n\tif(child == nullptr) {\n\t\tWarning( \"Child of player is null!\\n\");\n\t\treturn;\n\t}\n\n\tif(!child->Possessed(this)) {\n\t\tWarning( \"Failed to possess actor!\\n\");\n\t\treturn;\n\t}\n\n\tDebugMsg( \"%s possessed child %d...\\n\", GetTeam()->name.c_str(), myCurrentChildActorIndex);\n}\n\nvoid Player::DispossessCurrentChild() {\n\tActor* actor_ptr = GetCurrentChild();\n\tif(actor_ptr == nullptr) {\n\t\treturn;\n\t}\n\n\tactor_ptr->Dispossessed(this);\n\n\tDebugMsg( \"%s depossed child %d...\\n\", GetTeam()->name.c_str(), myCurrentChildActorIndex);\n}\n\nActor* Player::GetCurrentChild() {\n\tif( myCurrentChildActorIndex >= myChildActors.size()) {\n\t\treturn nullptr;\n\t}\n\n\treturn myChildActors[myCurrentChildActorIndex];\n}\n\nvoid Player::CycleChildren(bool forward) {\n\tif ( forward ) {\n\t\tmyCurrentChildActorIndex++;\n\n\t\t// Check if we need to wrap it round\n\t\tif ( myCurrentChildActorIndex >= myChildActors.size() ) {\n\t\t\tmyCurrentChildActorIndex = 0;\n\t\t}\n\n\t\treturn;\n\t}\n\n\t// Else we're decrementing\n\n\tmyCurrentChildActorIndex--;\n\n\t// Check if we need to wrap it round\n\tif ( myCurrentChildActorIndex < 0 ) {\n\t\tmyCurrentChildActorIndex = myChildActors.size() - 1;\n\t}\n\n\tDebugMsg( \"%s cycled to child %d...\\n\", GetTeam()->name.c_str(), myCurrentChildActorIndex);\n}\n\nvoid Player::AddChild(Actor* actor) {\n\tu_assert(actor != nullptr, \"Attempted to pass a null actor reference to player!\\n\");\n\tmyChildActors.push_back( actor);\n\n\tDebugMsg( \"%s received child %d...\\n\", GetTeam()->name.c_str(), myChildActors.size());\n}\n\nvoid Player::RemoveChild(Actor* actor) {\n\t// todo\n}\n"
  },
  {
    "path": "src/engine/game/Player.h",
    "content": "/* OpenHoW\n * Copyright (C) 2017-2020 TalonBrave.info and Others (see CONTRIBUTORS)\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#pragma once\n\nenum class PlayerType {\n\tLOCAL,\n\tNETWORKED,\n\tCOMPUTER,\n};\n\nclass Player {\npublic:\n\tPlayer( PlayerType type );\n\t~Player();\n\n\tunsigned int GetNumChildren() { return myChildActors.size(); }\n\n\tvoid AddChild( Actor *actor );\n\tvoid RemoveChild( Actor *actor );\n\n\tvoid PossessCurrentChild();\n\tvoid DispossessCurrentChild();\n\n\tActor *GetCurrentChild();\n\n\tvoid CycleChildren( bool forward = true );\n\n\tvoid SetControllerSlot( unsigned int slot ) { myControllerSlot = slot; }\n\tunsigned int GetControllerSlot() { return myControllerSlot; }\n\n\tinline void SetTeam( const PlayerTeam &team ) {\n\t\tmyTeam = team;\n\t}\n\tinline const PlayerTeam *GetTeam() const {\n\t\treturn &myTeam;\n\t}\n\nprotected:\nprivate:\n\tunsigned int myControllerSlot{ 0 }; // Controller slot\n\n\tPlayerType myType;\n\tPlayerTeam myTeam;\n\n\tstd::vector< Actor * > myChildActors;\n\tunsigned int myCurrentChildActorIndex{ 0 };\n};\n"
  },
  {
    "path": "src/engine/graphics/BitmapFont.cpp",
    "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// Copyright © 2017-2022 TalonBrave.info and Others (see CONTRIBUTORS)\n\n#include \"App.h\"\n#include \"BitmapFont.h\"\n#include \"Display.h\"\n\nohw::BitmapFont::BitmapFont() {\n\trenderMesh = PlgCreateMesh( PLG_MESH_TRIANGLES, PLG_DRAW_DYNAMIC, 512, 256 );\n\tif ( renderMesh == nullptr ) {\n\t\tError( \"failed to create font mesh, %s, aborting!\\n\", PlGetError() );\n\t}\n}\n\nohw::BitmapFont::~BitmapFont() {\n\tPlgDestroyMesh( renderMesh );\n}\n\nbool ohw::BitmapFont::Load( const char *tabPath, const char *texturePath ) {\n\tPLFile *filePtr = PlOpenFile( tabPath, false );\n\tif ( filePtr == nullptr ) {\n\t\tWarning( \"Failed to load tab \\\"%s\\\"!\\nPL: %s\\n\", tabPath, PlGetError() );\n\t\treturn false;\n\t}\n\n\t// Don't know, don't care\n\tPlFileSeek( filePtr, 16, PL_SEEK_CUR );\n\n\tstruct {\n\t\tuint16_t x, y;\n\t\tuint16_t w, h;\n\t} tabIndices[ MAX_BITMAP_CHARS ];\n\tnumChars = ( unsigned int ) PlReadFile( filePtr, tabIndices, sizeof( tabIndices ) / MAX_BITMAP_CHARS, MAX_BITMAP_CHARS );\n\n\t// We're done with the tab file\n\tPlCloseFile( filePtr );\n\n\tif( numChars == 0 ) {\n\t\tWarning( \"No characters in tab \\\"%s\\\"!\\n\" );\n\t\treturn false;\n\t}\n\n\ttexture = GetApp()->resourceManager->LoadTexture( texturePath, TextureResource::FLAG_DISCARD | TextureResource::FLAG_NOMIPS );\n\n\t// Now setup the character table\n\tunsigned int originX = tabIndices[ 0 ].x;\n\tunsigned int originY = tabIndices[ 0 ].y;\n\tfor ( unsigned int i = 0; i < numChars; ++i ) {\n\t\tcharTable[ i ].w = tabIndices[ i ].w;\n\t\tcharTable[ i ].h = tabIndices[ i ].h;\n\t\tcharTable[ i ].x = tabIndices[ i ].x - originX;\n\t\tcharTable[ i ].y = tabIndices[ i ].y - originY;\n\t}\n\n\treturn true;\n}\n\n/**\n * Immediately draw the given character.\n */\nvoid ohw::BitmapFont::DrawCharacter( float x, float y, float scale, PLColour colour, char character ) {\n\tPLGShaderProgram *program = PlgGetCurrentShaderProgram();\n\tif ( program == nullptr ) {\n\t\treturn;\n\t}\n\n\tif ( scale <= 0.0f ) {\n\t\treturn;\n\t}\n\n\tPlgSetTexture( texture->GetInternalTexture(), 0 );\n\n\tPlgClearMesh( renderMesh );\n\n\tAddCharacterToPass( x, y, scale, colour, character );\n\n\tPLMatrix4 matrix = PlMatrix4Identity();\n\n\tPlgSetShaderUniformValue( program, \"pl_model\", &matrix, false );\n\n\tPlgUploadMesh( renderMesh );\n\tPlgDrawMesh( renderMesh );\n}\n\n/**\n * Immediately draw the given string.\n */\nvoid ohw::BitmapFont::DrawString( float x, float y, float spacing, float scale, PLColour colour, const char *msg ) {\n\tPLGShaderProgram *program = PlgGetCurrentShaderProgram();\n\tif ( program == nullptr ) {\n\t\tError( \"Attempted to draw bitmap string without a bound shader program!\\n\" );\n\t}\n\n\tif ( scale <= 0.0f ) {\n\t\treturn;\n\t}\n\n\tsize_t msgLength = strlen( msg );\n\tif ( msgLength == 0 ) {\n\t\treturn;\n\t}\n\n\tPlgSetTexture( texture->GetInternalTexture(), 0 );\n\n\tPlgClearMesh( renderMesh );\n\n\tPlMatrixMode( PL_MODELVIEW_MATRIX );\n\tPlPushMatrix();\n\n\tPlLoadIdentityMatrix();\n\n\tfloat nX = x;\n\tfloat nY = y;\n\tfor ( size_t i = 0; i < msgLength; ++i ) {\n\t\tAddCharacterToPass( nX, nY, scale, colour, msg[ i ] );\n\n\t\tif ( msg[ i ] >= 33 && msg[ i ] <= 122 ) {\n\t\t\tnX += ( float ) charTable[ msg[ i ] - 33 ].w + spacing;\n\t\t} else if ( msg[ i ] == '\\n' ) {\n\t\t\tnY += ( float ) charTable[ 0 ].h;\n\t\t\tnX = x;\n\t\t} else {\n\t\t\tnX += 5;\n\t\t}\n\t}\n\n\tPlgSetShaderUniformValue( program, \"pl_model\", PlGetMatrix( PL_MODELVIEW_MATRIX ), false );\n\n\tPlgUploadMesh( renderMesh );\n\tPlgDrawMesh( renderMesh );\n\n\tPlPopMatrix();\n}\n\n/**\n * Returns an index in the character table for the given character.\n */\nohw::BitmapFont::TableIndex *ohw::BitmapFont::GetIndexForChar( unsigned char index ) {\n\t// Fonts are sorta weird here, and only support a specific scope...\n\tif ( index < 33 || index > 138 ) {\n\t\treturn nullptr;\n\t}\n\n\treturn &charTable[ index - 33 ];\n}\n\n/**\n * Add the character onto the current draw pass - so essentially batching it.\n */\nvoid ohw::BitmapFont::AddCharacterToPass( float x, float y, float scale, PLColour colour, char character ) {\n\tTableIndex *bitmapChar = GetIndexForChar( character );\n\tif ( bitmapChar == nullptr ) {\n\t\treturn;\n\t}\n\n\tDisplay *display = GetApp()->GetDisplay();\n\tif ( display == nullptr ) {\n\t\treturn;\n\t}\n\n\t// Ensure it's on screen\n\tint dW, dH;\n\tdisplay->GetDisplaySize( &dW, &dH );\n\tif ( x > dW || y > dH || x + bitmapChar->w < 0 || y + bitmapChar->h < 0 ) {\n\t\treturn;\n\t}\n\n\tfloat tw = ( float ) bitmapChar->w / ( float ) texture->GetWidth();\n\tfloat th = ( float ) bitmapChar->h / ( float ) texture->GetHeight();\n\tfloat tx = ( float ) bitmapChar->x / ( float ) texture->GetWidth();\n\tfloat ty = ( float ) bitmapChar->y / ( float ) texture->GetHeight();\n\n\tunsigned int vX = PlgAddMeshVertex( renderMesh, hei::Vector3( x, y, 0 ), PLVector3(), colour, { tx, ty } );\n\tunsigned int vY = PlgAddMeshVertex( renderMesh, hei::Vector3( x, y + ( ( float ) bitmapChar->h * scale ), 0 ), PLVector3(), colour, { tx, ty + th } );\n\tunsigned int vZ = PlgAddMeshVertex( renderMesh, hei::Vector3( x + ( ( float ) bitmapChar->w * scale ), y, 0 ), PLVector3(), colour, { tx + tw, ty } );\n\tunsigned int vW = PlgAddMeshVertex( renderMesh, hei::Vector3( x + ( ( float ) bitmapChar->w * scale ), y + ( ( float ) bitmapChar->h * scale ), 0 ), PLVector3(), colour, { tx + tw, ty + th } );\n\n\tPlgAddMeshTriangle( renderMesh, vX, vY, vZ );\n\tPlgAddMeshTriangle( renderMesh, vZ, vY, vW );\n}\n"
  },
  {
    "path": "src/engine/graphics/BitmapFont.h",
    "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// Copyright © 2017-2022 TalonBrave.info and Others (see CONTRIBUTORS)\n\n#pragma once\n\nnamespace ohw {\n\tclass BitmapFont {\n\tpublic:\n\t\tBitmapFont();\n\t\t~BitmapFont();\n\n\t\tbool Load( const char *tabPath, const char *texturePath );\n\n\t\tvoid DrawCharacter( float x, float y, float scale, PLColour colour, char character );\n\t\tvoid DrawString( float x, float y, float spacing, float scale, PLColour colour, const char *msg );\n\n\t\tinline unsigned int GetCharacterWidth( unsigned char index ) const {\n\t\t\tu_assert( index < numChars );\n\t\t\tif ( index >= numChars ) {\n\t\t\t\treturn 0;\n\t\t\t}\n\n\t\t\treturn charTable[ index ].w;\n\t\t}\n\n\t\tinline unsigned int GetCharacterHeight( unsigned char index ) const {\n\t\t\tu_assert( index < numChars );\n\t\t\tif ( index >= numChars ) {\n\t\t\t\treturn 0;\n\t\t\t}\n\n\t\t\treturn charTable[ index ].h;\n\t\t}\n\n\t\tstruct TableIndex {\n\t\t\tunsigned int    x, y;\n\t\t\tunsigned int    w, h;\n\t\t\tchar            character;\n\t\t\tfloat           s, t;\n\t\t};\n\n\tprotected:\n\tprivate:\n\t\tTableIndex *GetIndexForChar( unsigned char index );\n\n\t\tvoid AddCharacterToPass( float x, float y, float scale, PLColour colour, char character );\n\n#define MAX_BITMAP_CHARS 256\n\t\tTableIndex charTable[ MAX_BITMAP_CHARS ];\n\t\tunsigned int numChars{ 0 };\n\n\t\tSharedTextureResourcePointer texture{ nullptr };\n\n\t\tPLGMesh *renderMesh{ nullptr };\n\t};\n}\n"
  },
  {
    "path": "src/engine/graphics/Camera.cpp",
    "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// Copyright © 2017-2022 TalonBrave.info and Others (see CONTRIBUTORS)\n\n#include \"App.h\"\n#include \"Camera.h\"\n\nohw::Camera::Camera( const PLVector3 &pos, const PLVector3 &angles ) {\n\tinternalCameraPtr = PlgCreateCamera();\n\tif ( internalCameraPtr == nullptr ) {\n\t\tError( \"Failed to create camera object!\\n%s\\n\", PlGetError() );\n\t}\n}\n\nohw::Camera::~Camera() {\n\tPlgDestroyCamera( internalCameraPtr );\n}\n\nvoid ohw::Camera::SetFieldOfView( float fov ) {\n\t// Call the platform lib function for this,\n\t// which'll do some validation for us\n\tPlgSetCameraFieldOfView( internalCameraPtr, fov );\n}\n\n/**\n * Sets the viewport position and size.\n * @param xy X and Y.\n * @param wh Width and height.\n */\nvoid ohw::Camera::SetViewport( int x, int y, int width, int height ) {\n\tinternalCameraPtr->viewport.x = x;\n\tinternalCameraPtr->viewport.y = y;\n\tinternalCameraPtr->viewport.w = width;\n\tinternalCameraPtr->viewport.h = height;\n}\n\nvoid ohw::Camera::MakeActive() {\n\tPlgSetupCamera( internalCameraPtr );\n}\n\nbool ohw::Camera::IsBoxVisible( const PLCollisionAABB *bounds ) const {\n\treturn PlgIsBoxInsideView( internalCameraPtr, bounds );\n}\n\nbool ohw::Camera::IsSphereVisible( const PLCollisionSphere *sphere ) const {\n\treturn PlgIsSphereInsideView( internalCameraPtr, sphere );\n}\n"
  },
  {
    "path": "src/engine/graphics/Camera.h",
    "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// Copyright © 2017-2022 TalonBrave.info and Others (see CONTRIBUTORS)\n\n#pragma once\n\n#include <plgraphics/plg_camera.h>\n\nnamespace ohw {\n\tclass Camera {\n\tpublic:\n\t\tCamera( const PLVector3 &pos, const PLVector3 &angles );\n\t\t~Camera();\n\n\t\tinline void SetPosition( const PLVector3 &pos ) { internalCameraPtr->position = pos; }\n\t\tinline void SetPosition( float x, float y, float z ) { internalCameraPtr->position = { x, y, z }; }\n\n\t\tinline void SetAngles( const PLVector3 &angles ) { internalCameraPtr->angles = angles; }\n\t\tinline void SetAngles( float x, float y, float z ) { internalCameraPtr->angles = { x, y, z }; }\n\n\t\tvoid SetFieldOfView( float fov );\n\t\tinline void SetNear( float near ) { internalCameraPtr->near = near; }\n\t\tinline void SetFar( float far ) { internalCameraPtr->far = far; }\n\n\t\tinline PLVector3 GetPosition() const { return internalCameraPtr->position; }\n\t\tinline PLVector3 GetAngles() const { return internalCameraPtr->angles; }\n\t\tinline PLVector3 GetForward() const { return internalCameraPtr->forward; }\n\n\t\tinline float GetFieldOfView() const { return internalCameraPtr->fov; }\n\n\t\tvoid SetViewport( int x, int y, int width, int height );\n\n\t\tinline int GetViewportWidth() const { return internalCameraPtr->viewport.w; }\n\t\tinline int GetViewportHeight() const { return internalCameraPtr->viewport.h; }\n\n\t\tvoid MakeActive();\n\n\t\tbool IsBoxVisible( const PLCollisionAABB *bounds ) const;\n\t\tbool IsSphereVisible( const PLCollisionSphere *sphere ) const;\n\n\tprotected:\n\tprivate:\n\t\tPLGCamera *internalCameraPtr{ nullptr };\n\t};\n}\n"
  },
  {
    "path": "src/engine/graphics/Display.cpp",
    "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// Copyright © 2017-2022 TalonBrave.info and Others (see CONTRIBUTORS)\n\n#include <plgraphics/plg_driver_interface.h>\n\n#include \"App.h\"\n#include \"imgui_layer.h\"\n#include \"Menu.h\"\n#include \"Map.h\"\n#include \"ShaderManager.h\"\n#include \"Camera.h\"\n\n#include \"game/ActorManager.h\"\n#include \"Display.h\"\n\n/************************************************************/\n\nvoid Display_GetFramesCount( unsigned int *fps, unsigned int *ms ) {\n\tstatic unsigned int fps_ = 0;\n\tstatic unsigned int ms_ = 0;\n\t//static unsigned int update_delay = 60;\n#if 0 // todo: revisit\n\tif ( update_delay < g_state.draw_ticks && g_state.last_draw_ms > 0 ) {\n\t\tms_ = g_state.last_draw_ms;\n\t\tfps_ = 1000 / ms_;\n\t\tupdate_delay = g_state.draw_ticks + 60;\n\t}\n#endif\n\n\t*fps = fps_;\n\t*ms = ms_;\n}\n\nstatic void Display_DrawMap() {\n\tohw::Map *map = ohw::GetApp()->gameManager->GetCurrentMap();\n\tif ( map == nullptr ) {\n\t\treturn;\n\t}\n\n\tmap->Draw();\n}\n\nohw::Display::Display( const char *title, int w, int h, unsigned int desiredScreen, bool fullscreen ) :\n\t\tmyDesiredScreen( desiredScreen ) {\n\t// Fetch the display size.\n\tSDL_Rect displayBounds;\n\tSDL_GetDisplayBounds( myDesiredScreen, &displayBounds );\n\tif ( fullscreen || w < DISPLAY_MIN_WIDTH || h < DISPLAY_MIN_HEIGHT ) {\n\t\tw = displayBounds.w;\n\t\th = displayBounds.h;\n\t}\n\n\tSDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );\n\tSDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 24 );\n\tSDL_GL_SetAttribute( SDL_GL_STENCIL_SIZE, 8 );\n#ifdef _DEBUG\n\tSDL_GL_SetAttribute( SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_DEBUG_FLAG | SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG );\n#else\n\tSDL_GL_SetAttribute( SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG );\n#endif\n\tSDL_GL_SetAttribute( SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE );\n\tSDL_GL_SetAttribute( SDL_GL_CONTEXT_MAJOR_VERSION, 3 );\n\tSDL_GL_SetAttribute( SDL_GL_CONTEXT_MINOR_VERSION, 2 );\n\n\tint defaultFlags =\n\t\t\tSDL_WINDOW_OPENGL |\n\t\t\tSDL_WINDOW_MOUSE_FOCUS |\n\t\t\tSDL_WINDOW_INPUT_FOCUS |\n\t\t\tSDL_WINDOW_ALLOW_HIGHDPI;\n\t// SDL_WINDOW_ALLOW_HIGHDPI currently does nothing on Windows,\n\t// see https://bugzilla.libsdl.org/show_bug.cgi?id=3281\n\t// Assume borderless if it matches desktop resolution.\n\tif ( w == displayBounds.w && h == displayBounds.h ) {\n\t\tdefaultFlags |= SDL_WINDOW_BORDERLESS;\n\t}\n\n\tmyWindow = SDL_CreateWindow(\n\t\t\ttitle,\n\t\t\tSDL_WINDOWPOS_CENTERED_DISPLAY( myDesiredScreen ),\n\t\t\tSDL_WINDOWPOS_CENTERED_DISPLAY( myDesiredScreen ),\n\t\t\tw, h,\n\t\t\tdefaultFlags );\n\tif ( myWindow == nullptr ) {\n\t\tError( \"Failed to create window!\\nSDL: %s\\n\", SDL_GetError() );\n\t}\n\n\tSDL_SetWindowMinimumSize( myWindow, DISPLAY_MIN_WIDTH, DISPLAY_MIN_HEIGHT );\n\n\t//SDL_SetRelativeMouseMode(SDL_TRUE);\n\tSDL_CaptureMouse( SDL_TRUE );\n\n\t// Now create the GL context\n\tmyGLContext = SDL_GL_CreateContext( myWindow );\n\tif ( myGLContext == nullptr ) {\n\t\tError( \"Failed to create OpenGL context!\\nSDL: %s\\n\", SDL_GetError() );\n\t}\n\n\t// platform library graphics subsystem can init now\n\tif ( PlInitializeSubSystems( PL_SUBSYSTEM_GRAPHICS ) != PL_RESULT_SUCCESS ||\n\t     PlgInitializeGraphics() != PL_RESULT_SUCCESS ) {\n\t\tError( \"Failed to initialize platform graphics subsystem!\\nPL: %s\\n\", PlGetError() );\n\t}\n\n\tPlgScanForDrivers( \".\" );\n\n\tunsigned int numDrivers, i;\n\tconst char **drivers = PlgGetAvailableDriverInterfaces( &numDrivers );\n\tfor ( i = 0; i < numDrivers; ++i ) {\n\t\tif ( PlgSetDriver( drivers[ i ] ) != PL_RESULT_SUCCESS ) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tbreak;\n\t}\n\n\tif ( i == numDrivers ) {\n\t\tError( \"Failed to load a valid graphics layer!\\n\" );\n\t}\n\n\tShaders_Initialize();\n}\n\nohw::Display::~Display() {\n\tShaders_Shutdown();\n\n\tPlgShutdownGraphics();\n\n\tSDL_CaptureMouse( SDL_FALSE );\n\n\tif ( myGLContext != nullptr ) {\n\t\tSDL_GL_DeleteContext( myGLContext );\n\t}\n\tif ( myWindow != nullptr ) {\n\t\tSDL_DestroyWindow( myWindow );\n\t}\n}\n\nvoid ohw::Display::SetIcon( const char *path ) {\n\tPLImage *image = PlLoadImage( path );\n\tif ( image == nullptr ) {\n\t\tWarning( \"Failed to load image, %s!\\nPL: %s\\n\", path, PlGetError() );\n\t\treturn;\n\t}\n\n\tSDL_Surface *surface = SDL_CreateRGBSurfaceFrom(\n\t\t\timage->data[ 0 ],\n\t\t\t// Casting casting casting, why o why\n\t\t\tstatic_cast<signed>( image->width ),\n\t\t\tstatic_cast<signed>( image->height ),\n\t\t\t32,\n\t\t\tstatic_cast<signed>( image->width * 4 ),\n\t\t\t0x000000ff,\n\t\t\t0x0000ff00,\n\t\t\t0x00ff0000,\n\t\t\t0xff000000\n\t);\n\tif ( surface != nullptr ) {\n\t\tSDL_SetWindowIcon( myWindow, surface );\n\t\tSDL_FreeSurface( surface );\n\t} else {\n\t\tWarning( \"Failed to create requested SDL surface!\\nSDL: %s\\n\", SDL_GetError() );\n\t}\n\n\tPlDestroyImage( image );\n}\n\nvoid ohw::Display::Render( double delta ) {\n\tSTART_MEASURE();\n\n\tnumDrawTicks = GetApp()->GetTicks();\n\n\tPlgSetCullMode( PLG_CULL_POSITIVE );\n\n\tPlgSetDepthMask( true );\n\tPlgSetDepthBufferMode( PLG_DEPTHBUFFER_ENABLE );\n\n\tPlgBindFrameBuffer( nullptr, PLG_FRAMEBUFFER_DRAW );\n\n\tPlgSetClearColour( { 0, 0, 0, 255 } );\n\tPlgClearBuffers( PLG_BUFFER_DEPTH | PLG_BUFFER_COLOUR );\n\n\tRenderScene();\n\tRenderOverlays();\n\n\tEND_MEASURE();\n\n\tRenderDebugOverlays();\n\n\tSwap();\n}\n\nvoid ohw::Display::RenderScene() {\n\tohw::Camera *camera = ohw::GetApp()->gameManager->GetActiveCamera();\n\tif ( camera == nullptr ) {\n\t\treturn;\n\t}\n\n\tSTART_MEASURE();\n\n\tint w, h;\n\tGetDisplaySize( &w, &h );\n\tcamera->SetViewport( 0, 0, w, h );\n\n\t// Sync the camera state before we make it active\n\tcamera->SetFieldOfView( cv_camera_fov->f_value );\n\tcamera->SetNear( cv_camera_near->f_value );\n\tcamera->SetFar( cv_camera_far->f_value );\n\n\tcamera->MakeActive();\n\n\tif ( cv_graphics_alpha_to_coverage->b_value ) {\n\t\tPlgEnableGraphicsState( PLG_GFX_STATE_ALPHATOCOVERAGE );\n\t}\n\n\tDisplay_DrawMap();\n\n\tActorManager::GetInstance()->DrawActors();\n\n\tif ( cv_graphics_alpha_to_coverage->b_value ) {\n\t\tPlgDisableGraphicsState( PLG_GFX_STATE_ALPHATOCOVERAGE );\n\t}\n\n\tRenderSceneDebug();\n\n\tEND_MEASURE();\n}\n\nvoid ohw::Display::RenderSceneDebug() {\n\tShaders_SetProgramByName( \"generic_untextured\" );\n\n\tohw::GetApp()->audioManager->DrawSources();\n\n\tPlPushMatrix();\n\tPlMatrixMode( PL_MODELVIEW_MATRIX );\n\tPlLoadIdentityMatrix();\n\n\tfor ( const auto &i: debugLines ) {\n\t\tPlgDrawSimpleLine( *PlGetMatrix( PL_MODELVIEW_MATRIX ), i.start, i.end, i.colour );\n\t}\n\tdebugLines.clear();\n\n\tPlPopMatrix();\n}\n\nvoid ohw::Display::RenderOverlays() {\n\tSTART_MEASURE();\n\n\tMenu_Draw();\n\n\tEND_MEASURE();\n}\n\nvoid ohw::Display::RenderDebugOverlays() {\n\tif ( cv_imgui->i_value <= 0 ) {\n\t\treturn;\n\t}\n\n\tImGuiImpl_SetupFrame();\n\n\tUI_DisplayDebugMenu(); /* aka imgui */\n\n\tImGuiImpl_Draw();\n}\n\nvoid ohw::Display::SetDisplaySize( int w, int h, bool fullscreen ) {\n\tif ( fullscreen ) {\n\t\t// Fetch the display size\n\t\tSDL_Rect displayBounds;\n\t\tSDL_GetDisplayBounds( myDesiredScreen, &displayBounds );\n\t\tw = displayBounds.w;\n\t\th = displayBounds.h;\n\n\t\tSDL_SetWindowBordered( myWindow, SDL_FALSE );\n\t} else {\n\t\tSDL_SetWindowBordered( myWindow, SDL_TRUE );\n\t}\n\n\tSDL_SetWindowSize( myWindow, w, h );\n\tSDL_SetWindowPosition( myWindow,\n\t                       SDL_WINDOWPOS_CENTERED_DISPLAY( myDesiredScreen ),\n\t                       SDL_WINDOWPOS_CENTERED_DISPLAY( myDesiredScreen ) );\n\n\tPlSetConsoleVariable( cv_display_width, std::to_string( w ).c_str() );\n\tPlSetConsoleVariable( cv_display_height, std::to_string( h ).c_str() );\n\tPlSetConsoleVariable( cv_display_fullscreen, fullscreen ? \"1\" : \"0\" );\n}\n\nvoid ohw::Display::GetDisplaySize( int *w, int *h ) {\n\tSDL_GL_GetDrawableSize( myWindow, w, h );\n}\n\nvoid ohw::Display::Swap() {\n\tSDL_GL_SwapWindow( myWindow );\n\n\t// Best place to do this?\n\tlastDrawMS = GetApp()->GetTicks() - numDrawTicks;\n}\n\nint ohw::Display::SetSwapInterval( int desiredInterval ) {\n\tif ( SDL_GL_SetSwapInterval( desiredInterval ) != 0 ) {\n\t\tWarning( \"Failed to set desired swap interval \\\"%d\\\"!\\n\", desiredInterval );\n\t}\n\n\treturn SDL_GL_GetSwapInterval();\n}\n\nbool ohw::Display::HandleEvent( const SDL_Event &event ) {\n\tswitch ( event.type ) {\n\t\tdefault:\n\t\t\tbreak;\n\t\tcase SDL_WINDOWEVENT: {\n\t\t\tswitch ( event.window.type ) {\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t\tcase SDL_WINDOWEVENT_RESIZED:\n\t\t\t\tcase SDL_WINDOWEVENT_SIZE_CHANGED:\n\t\t\t\t\tPlSetConsoleVariable( cv_display_width, std::to_string( event.window.data1 ).c_str() );\n\t\t\t\t\tPlSetConsoleVariable( cv_display_height, std::to_string( event.window.data2 ).c_str() );\n\t\t\t\t\treturn true;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn false;\n}\n\nvoid ohw::Display::SetMousePosition( int x, int y ) {\n\tSDL_WarpMouseInWindow( myWindow, x, y );\n}\n\n// Debugging\n\nvoid ohw::Display::DebugDrawLine( const PLVector3 &startPos, const PLVector3 &endPos, const PLColour &colour ) {\n\tDebugLine debugLine;\n\tdebugLine.start = startPos;\n\tdebugLine.end = endPos;\n\tdebugLine.colour = colour;\n\tdebugLines.push_back( debugLine );\n}\n"
  },
  {
    "path": "src/engine/graphics/Display.h",
    "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// Copyright © 2017-2022 TalonBrave.info and Others (see CONTRIBUTORS)\n\n#pragma once\n\n#define DISPLAY_MIN_WIDTH    640\n#define DISPLAY_MIN_HEIGHT   480\n\nnamespace ohw {\n\tclass Display {\n\tpublic:\n\t\tDisplay( const char *title, int w, int h, unsigned int desiredScreen, bool fullscreen);\n\t\t~Display();\n\n\t\tvoid SetIcon( const char *path );\n\n\t\tvoid Render( double delta );\n\n\t\tvoid SetDisplaySize( int w, int h, bool fullscreen );\n\t\tvoid GetDisplaySize( int *w, int *h );\n\n\t\tvoid Swap();\n\t\tint SetSwapInterval( int desiredInterval );\n\n\t\tbool HandleEvent( const SDL_Event &event );\n\n\t\tvoid SetMousePosition( int x, int y );\n\n\t\tvoid DebugDrawLine( const PLVector3 &startPos, const PLVector3 &endPos, const PLColour &colour );\n\n\tprotected:\n\tprivate:\n\t\tvoid RenderScene();\n\t\tvoid RenderSceneDebug();\n\t\tvoid RenderOverlays();\n\t\tvoid RenderDebugOverlays();\n\n\t\tstruct DebugLine {\n\t\t\tPLVector3 start, end;\n\t\t\tPLColour colour;\n\t\t};\n\t\tstd::vector< DebugLine > debugLines;\n\n\t\tunsigned int numDrawTicks{ 0 };\n\t\tunsigned int lastDrawTick{ 0 };\n\t\tunsigned int lastDrawMS{ 0 };\n\n\t\tint myDesiredScreen{ 0 };\n\n\t\tSDL_Window *myWindow{ nullptr };\n\t\tSDL_GLContext myGLContext{ nullptr };\n\t};\n}\n\n// debugging\nvoid Display_GetFramesCount( unsigned int *fps, unsigned int *ms );\nextern const char *supportedTextureFormats[];\n"
  },
  {
    "path": "src/engine/graphics/ParticleEffect.cpp",
    "content": "/* OpenHoW\n * Copyright (C) 2017-2020 TalonBrave.info and Others (see CONTRIBUTORS)\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include \"App.h\"\n#include \"JsonReader.h\"\n#include \"particles.h\"\n#include \"ParticleEffect.h\"\n#include \"ParticleEmitter.h\"\n\nohw::ParticleEffect::ParticleEffect( const std::string &effectPath ) {\n\ttry {\n\t\tJsonReader jsonBlob( effectPath );\n\n\t\tint version = jsonBlob.GetIntegerProperty( \"version\", 0, false );\n\t\tif ( version != PARTICLE_EFFECT_VERSION ) {\n\t\t\tWarning( \"Invalid particle effect version, %d (expected %d) in \\\"%s\\\"!\\n\",\n\t\t\t         version,\n\t\t\t         PARTICLE_EFFECT_VERSION,\n\t\t\t         effectPath.c_str());\n\t\t}\n\n\t\tunsigned int numEmitters = jsonBlob.GetArrayLength( \"emitters\" );\n\t\tif ( numEmitters == 0 ) {\n\t\t\tWarning( \"No emitters in particle effect \\\"%s\\\"!\\n\", effectPath.c_str());\n\t\t}\n\n\t\tjsonBlob.EnterChildNode( \"emitters\" );\n\t\tfor ( unsigned int i = 0; i < numEmitters; ++i ) {\n\t\t\tjsonBlob.EnterChildNode( i );\n\n\t\t\tParticleEmitter emitter( jsonBlob );\n\t\t\tmyEmitters.push_back( emitter );\n\n\t\t\tjsonBlob.LeaveChildNode();\n\t\t}\n\t\tjsonBlob.LeaveChildNode();\n\t} catch( const std::exception &exception ) {\n\n\t}\n}\n\nohw::ParticleEffect::~ParticleEffect() {\n\n}\n\nvoid ohw::ParticleEffect::Draw() {\n\tfor( auto &i : myEmitters ) {\n\t\ti.Draw();\n\t}\n}\n\nvoid ohw::ParticleEffect::Tick() {\n\tfor( auto &i : myEmitters ) {\n\t\ti.Tick();\n\t}\n}\n"
  },
  {
    "path": "src/engine/graphics/ParticleEffect.h",
    "content": "/* OpenHoW\n * Copyright (C) 2017-2020 TalonBrave.info and Others (see CONTRIBUTORS)\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#pragma once\n\nnamespace ohw {\n\tclass ParticleEmitter;\n\n#define PARTICLE_EFFECT_VERSION 15052020\n\n// On-disk representation of an effect\n\tclass ParticleEffect {\n\tpublic:\n\t\tParticleEffect( const std::string &effectPath );\n\t\t~ParticleEffect();\n\n\t\tconst std::stringstream Serialize();\n\n\t\tvoid Draw();\n\t\tvoid Tick();\n\n\t\tstd::string GetPath() const { return path; }\n\n\tprotected:\n\tprivate:\n\t\tstd::string path;\n\n\t\tPLVector3 myPosition{ 0, 0, 0 };\n\n#if 0\n\t\tstd::map<std::string, ParticleEmitter> myEmitters;\n#else\n\t\tstd::vector <ParticleEmitter> myEmitters;\n#endif\n\t};\n}\n"
  },
  {
    "path": "src/engine/graphics/ParticleEmitter.cpp",
    "content": "/* OpenHoW\n * Copyright (C) 2017-2020 TalonBrave.info and Others (see CONTRIBUTORS)\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include \"App.h\"\n#include \"script/JsonReader.h\"\n#include \"particles.h\"\n#include \"ParticleEmitter.h\"\n\nohw::ParticleEmitter::ParticleEmitter( JsonReader &jsonReader ) {\n\tmyGravity = jsonReader.GetFloatProperty( \"gravity\" );\n\n\trandomLifeSpanFactor = jsonReader.GetFloatProperty( \"randomLifeSpawnFactor\" );\n\tlifeSpan = jsonReader.GetFloatProperty( \"lifeSpan\" );\n\n\t// Colour\n\trandomColourFactor = jsonReader.GetVector4Property( \"randomColourFactor\" );\n\tstartColour = jsonReader.GetColourProperty( \"startColour\" );\n\tendColour = jsonReader.GetColourProperty( \"endColour\" );\n\n\t// Scaling\n\trandomScaleFactor = jsonReader.GetFloatProperty( \"randomScaleFactor\" );\n\tstartScale = jsonReader.GetFloatProperty( \"startScale\" );\n\tendScale = jsonReader.GetFloatProperty( \"endScale\" );\n\n\tdrawDistance = jsonReader.GetFloatProperty( \"drawDistance\", 10000.0f, true );\n\tspawnRadius = jsonReader.GetFloatProperty( \"spawnRadius\" );\n\n\tsortParticles = jsonReader.GetBooleanProperty( \"sortParticles\" );\n\tcollideActors = jsonReader.GetBooleanProperty( \"collideActors\" );\n\tcollideWorld = jsonReader.GetBooleanProperty( \"collideWorld\" );\n\n\tmaxParticles = jsonReader.GetIntegerProperty( \"maxParticles\" );\n\n\tstd::string parsedString;\n\n\t// Particle type specifies whether or not we're a model, sprite, trail or text\n\tparsedString = jsonReader.GetStringProperty( \"particleType\", \"sprite\", true );\n\tif ( parsedString == \"sprite\" ) {\n\t\tmyParticleType = ParticleType::SPRITE;\n\t} else if ( parsedString == \"model\" ) {\n\t\tmyParticleType = ParticleType::MODEL;\n\t} else if ( parsedString == \"trail\" ) {\n\t\tmyParticleType = ParticleType::TRAIL;\n\t} else if ( parsedString == \"text\" ) {\n\t\tmyParticleType = ParticleType::TEXT;\n\t} else {\n\t\tmyParticleType = ParticleType::SPRITE;\n\t\tWarning( \"Invalid particle type \\\"%s\\\" specified, defaulting to \\\"sprite\\\"!\\n\", parsedString.c_str() );\n\t}\n\n\t// And blend type specifies how we should draw ourselves\n\tparsedString = jsonReader.GetStringProperty( \"blendType\", \"additive\", true );\n\tif ( parsedString == \"additive\" ) {\n\t\tmyBlendType = BlendType::ADDITIVE;\n\t} else if ( parsedString == \"subtractive\" ) {\n\t\tmyBlendType = BlendType::SUBTRACTIVE;\n\t} else if ( parsedString == \"difference\" ) {\n\t\tmyBlendType = BlendType::DIFFERENCE;\n\t} else {\n\t\tmyBlendType = BlendType::ADDITIVE;\n\t\tWarning( \"Invalid blend type \\\"%s\\\" specified, default to \\\"additive\\\"!\\n\", parsedString.c_str() );\n\t}\n\n\tisActive = jsonReader.GetBooleanProperty( \"isActive\" );\n}\n\nvoid ohw::ParticleEmitter::Tick() {\n\tfor ( auto &i : particles ) {\n\t\ti.Tick();\n\t}\n}\n\nvoid ohw::ParticleEmitter::Draw() {\n\t// TODO: figure out how we're going to batch these depending on type...\n}\n"
  },
  {
    "path": "src/engine/graphics/ParticleEmitter.h",
    "content": "/* OpenHoW\n * Copyright (C) 2017-2020 TalonBrave.info and Others (see CONTRIBUTORS)\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#pragma once\n\n#include \"Property.h\"\n#include \"particles.h\"\n\nnamespace ohw {\n// This creates the particles\n\tclass ParticleEmitter : public PropertyOwner {\n\tpublic:\n\t\texplicit ParticleEmitter( JsonReader &jsonReader );\n\t\t~ParticleEmitter() {}\n\n\t\tvoid Tick();\n\t\tvoid Draw();\n\n\t\tvoid SetGravity( float gravity ) { myGravity = gravity; }\n\t\tfloat GetGravity() { return myGravity; }\n\n\tprotected:\n\tprivate:\n\t\tstd::vector< ohw::Particle > particles;\n\n\t\tfloat myGravity{ 0.0f };\n\n\t\tfloat randomLifeSpanFactor{ 0.0f };\n\t\tfloat lifeSpan{ 1.0f };\n\n\t\tPLVector4 randomColourFactor{ 0.0f, 0.0f, 0.0f, 0.0f };\n\t\tPLColour startColour;\n\t\tPLColour endColour;\n\n\t\tfloat randomScaleFactor{ 0.0f };\n\t\tfloat startScale{ 0.0f };\n\t\tfloat endScale{ 1.0f };\n\n\t\tfloat drawDistance{ 10000.0f };\n\n\t\tfloat spawnRadius{ 0.0f };\n\n\t\tbool sortParticles{ false };\n\n\t\t// todo; consider more typical collision mask?\n\t\tbool collideActors{ false };\n\t\tbool collideWorld{ false };\n\n\t\tunsigned int maxParticles{ 0 };\n\n\t\tenum class ParticleType {\n\t\t\tSPRITE,\n\t\t\tMODEL,\n\t\t\tTRAIL,\n\t\t\tTEXT,\n\t\t};\n\n\t\tenum class BlendType {\n\t\t\tNONE,\n\t\t\tADDITIVE,\n\t\t\tSUBTRACTIVE,\n\t\t\tDIFFERENCE\n\t\t};\n\n\t\tParticleType myParticleType{ ParticleType::SPRITE };\n\t\tBlendType myBlendType{ BlendType::ADDITIVE };\n\n\t\tbool isActive{ false };\n\n\t\tPLVector3 position;\n\t};\n}\n"
  },
  {
    "path": "src/engine/graphics/PostProcess.h",
    "content": "/* OpenHoW\n * Copyright (C) 2017-2020 TalonBrave.info and Others (see CONTRIBUTORS)\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#pragma once\n\nnamespace ohw {\n\tclass PostProcess {\n\tpublic:\n\n\t\tvirtual void Draw() = 0;\n\n\tprotected:\n\tprivate:\n\t};\n}\n"
  },
  {
    "path": "src/engine/graphics/ShaderManager.cpp",
    "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// Copyright © 2017-2022 TalonBrave.info and Others (see CONTRIBUTORS)\n\n#include \"App.h\"\n#include \"JsonReader.h\"\n#include \"ShaderManager.h\"\n\nstatic std::map< std::string, ohw::ShaderProgram * > programs;\nstatic ohw::ShaderProgram *fallbackShaderProgram = nullptr;\n\n// For resetting following rebuild\nstatic std::string lastProgramName;\n\n/**\n * Validate the default shader set has been loaded.\n */\nstatic void Shaders_ValidateDefault() {\n\tconst char *defaultShadersStrings[] = {\n\t\t\t\"generic_untextured\",\n\t\t\t\"generic_textured\",\n\t\t\t\"generic_textured_lit\",\n\n\t\t\t\"debug_normals\",\n\t\t\t\"debug_test\",\n\t};\n\n\tfor ( unsigned int i = 0; i < PL_ARRAY_ELEMENTS( defaultShadersStrings ); ++i ) {\n\t\tohw::ShaderProgram *program = Shaders_GetProgram( defaultShadersStrings[ i ] );\n\t\tif ( program == nullptr ) {\n\t\t\tError( \"Failed to fetch default shader, \\\"%s\\\"!\\n\", defaultShadersStrings[ i ] );\n\t\t}\n\n\t\tif ( i == 0 ) {\n\t\t\tfallbackShaderProgram = program;\n\t\t}\n\t}\n}\n\nstatic void Shaders_CacheShaderProgram( const char *path, void *userData ) {\n\tu_unused( userData );\n\n\tconst char *fileName = PlGetFileName( path );\n\tif ( fileName == nullptr ) {\n\t\tWarning( \"Failed to get filename for shader program, \\\"%s\\\"!\\n\", path );\n\t\treturn;\n\t}\n\n\t// Provide a copy, minus the extension\n\tstd::string shortFileName( fileName, 0, strlen( fileName ) - 8 );\n\n\ttry {\n\t\tJsonReader config( path );\n\n\t\tconfig.EnterChildNode( \"gl3\" );\n\n\t\tstd::string vertPath = config.GetStringProperty( \"vertPath\" );\n\t\tstd::string fragPath = config.GetStringProperty( \"fragPath\" );\n\n\t\tif ( vertPath.empty() || fragPath.empty() ) {\n\t\t\t// GetStringProperty throws warnings for this case, so just return\n\t\t\treturn;\n\t\t}\n\n\t\tohw::ShaderProgram *program = new ohw::ShaderProgram( vertPath, fragPath );\n\t\tprograms.insert( std::pair< std::string, ohw::ShaderProgram * >( shortFileName, program ) );\n\t} catch ( const std::exception &error ) {\n\t\tWarning( \"Failed to register shader program (%s)!\\n\", error.what() );\n\t}\n}\n\nstatic void Shaders_ClearPrograms() {\n\tfor ( const auto &program : programs ) {\n\t\tprogram.second->Disable();\n\t\tdelete program.second;\n\t}\n\n\tprograms.clear();\n}\n\nstatic void Shaders_CachePrograms() {\n\tShaders_ClearPrograms();\n\n\tPlScanDirectory( \"shaders\", \"program\", Shaders_CacheShaderProgram, false, nullptr );\n\n\tShaders_ValidateDefault();\n}\n\nstatic void Cmd_ListShaderPrograms( unsigned int argc, char *argv[] ) {\n\tu_unused( argc );\n\tu_unused( argv );\n\n\tstd::string list = \"\\n\";\n\tfor ( const auto &program : programs ) {\n\t\tlist += program.first + \"\\n\";\n\t}\n\n\tPrint( \"%s\\n\", list.c_str() );\n}\n\nstatic void Cmd_RebuildShaderProgramCache( unsigned int argc, char *argv[] ) {\n\tu_unused( argc );\n\tu_unused( argv );\n\n\tShaders_CachePrograms();\n}\n\nstatic void Cmd_RebuildShaderPrograms( unsigned int argc, char *argv[] ) {\n\tu_unused( argc );\n\tu_unused( argv );\n\n\tfor ( const auto &program : programs ) {\n\t\ttry {\n\t\t\tprogram.second->Rebuild();\n\t\t} catch ( const std::exception &exception ) {\n\t\t\tWarning( \"Failed to rebuild shader program, \\\"%s\\\" (%s)!\\n\", program.first.c_str(), exception.what() );\n\t\t}\n\t}\n\n\tShaders_SetProgramByName( lastProgramName );\n}\n\nstatic void Cmd_RebuildShaderProgram( unsigned int argc, char *argv[] ) {\n\tif ( argc == 0 ) {\n\t\tWarning( \"Please provide the name of the shader program you wish to rebuild!\\n\" );\n\t\treturn;\n\t} else if ( argc > 1 ) {\n\t\tWarning( \"Too many arguments, please provide only the name of the shader program you wish to rebuild!\\n\" );\n\t\treturn;\n\t}\n\n\tconst char *shaderProgramArg = argv[ 0 ];\n\tif ( shaderProgramArg == NULL ) {\n\t\tWarning( \"Invalid argument provided, please try again!\\n\" );\n\t\treturn;\n\t}\n\n\tohw::ShaderProgram *shaderProgram = Shaders_GetProgram( shaderProgramArg );\n\tif ( shaderProgram == nullptr ) {\n\t\treturn;\n\t}\n\n\ttry {\n\t\tshaderProgram->Rebuild();\n\t} catch ( const std::exception &exception ) {\n\t\tWarning( \"Failed to rebuild shader program, \\\"%s\\\" (%s)!\\n\", shaderProgramArg, exception.what() );\n\t}\n}\n\nvoid Shaders_Initialize() {\n\tPlRegisterConsoleCommand( \"ListShaderPrograms\", \"Lists all of the cached shader programs\", 0, Cmd_ListShaderPrograms );\n\tPlRegisterConsoleCommand( \"RebuildShaderPrograms\", \"Rebuild all shader programs\", 0, Cmd_RebuildShaderPrograms );\n\tPlRegisterConsoleCommand( \"RebuildShaderProgram\", \"Rebuild specified shader program\", 0, Cmd_RebuildShaderProgram );\n\tPlRegisterConsoleCommand( \"RebuildShaderProgramCache\", \"Rebuild shader program cache\", 0, Cmd_RebuildShaderProgramCache );\n\n\tShaders_CachePrograms();\n}\n\nvoid Shaders_Shutdown() {\n\tShaders_ClearPrograms();\n}\n\nohw::ShaderProgram *Shaders_GetProgram( const std::string &name ) {\n\tconst auto &i = programs.find( name );\n\tif ( i == programs.end() ) {\n\t\tWarning( \"Failed to find shader program, \\\"%s\\\"!\\n\", name.c_str() );\n\t\treturn nullptr;\n\t}\n\n\treturn i->second;\n}\n\nvoid Shaders_SetProgramByName( const std::string &name ) {\n\tohw::ShaderProgram *shaderProgram = Shaders_GetProgram( name );\n\tif ( shaderProgram == nullptr ) {\n\t\tshaderProgram = fallbackShaderProgram;\n\t}\n\n\tshaderProgram->Enable();\n}\n\nohw::ShaderProgram::ShaderProgram( const std::string &vertPath, const std::string &fragPath ) {\n\tshaderProgram = PlgCreateShaderProgram();\n\tif ( shaderProgram == nullptr ) {\n\t\tthrow std::runtime_error( PlGetError() );\n\t}\n\n\ttry {\n\t\tRegisterShaderStage( vertPath.c_str(), PLG_SHADER_TYPE_VERTEX );\n\t\tRegisterShaderStage( fragPath.c_str(), PLG_SHADER_TYPE_FRAGMENT );\n\t} catch ( ... ) {\n\t\tPlgDestroyShaderProgram( shaderProgram, true );\n\t\tthrow;\n\t}\n\n\tPlgLinkShaderProgram( shaderProgram );\n\n\tthis->vertPath = vertPath;\n\tthis->fragPath = fragPath;\n}\n\nohw::ShaderProgram::~ShaderProgram() {\n\tPlgDestroyShaderProgram( shaderProgram, true );\n}\n\nvoid ohw::ShaderProgram::Rebuild() {\n\tPLGShaderProgram *newShaderProgram = PlgCreateShaderProgram();\n\tif ( newShaderProgram == nullptr ) {\n\t\tthrow std::runtime_error( PlGetError() );\n\t}\n\n\tPLGShaderProgram *oldProgram = shaderProgram;\n\tshaderProgram = newShaderProgram;\n\n\ttry {\n\t\tRegisterShaderStage( vertPath.c_str(), PLG_SHADER_TYPE_VERTEX );\n\t\tRegisterShaderStage( fragPath.c_str(), PLG_SHADER_TYPE_FRAGMENT );\n\t} catch ( const std::exception &exception ) {\n\t\tPlgDestroyShaderProgram( shaderProgram, true );\n\t\tshaderProgram = oldProgram;\n\t\tthrow;\n\t}\n\n\tPlgLinkShaderProgram( shaderProgram );\n\n\tPlgDestroyShaderProgram( oldProgram, true );\n}\n\nvoid ohw::ShaderProgram::Enable() {\n\tPlgSetShaderProgram( shaderProgram );\n}\n\nvoid ohw::ShaderProgram::Disable() {\n\tPlgSetShaderProgram( nullptr );\n}\n\nvoid ohw::ShaderProgram::RegisterShaderStage( const char *path, PLGShaderStageType type ) {\n\tif ( !PlgRegisterShaderStageFromDisk( shaderProgram, path, type ) ) {\n\t\tthrow std::runtime_error( PlGetError() );\n\t}\n}\n"
  },
  {
    "path": "src/engine/graphics/ShaderManager.h",
    "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// Copyright © 2017-2022 TalonBrave.info and Others (see CONTRIBUTORS)\n\n#pragma once\n\n#include <plgraphics/plg.h>\n\nnamespace ohw {\n\tclass ShaderProgram {\n\tpublic:\n\t\tShaderProgram( const std::string &vertPath, const std::string &fragPath );\n\t\t~ShaderProgram();\n\n\t\tvoid Rebuild();\n\n\t\tvoid Enable();\n\t\tvoid Disable();\n\n\t\t// This is awful, but we need it for passing shader programs into\n\t\t// the platform library. Urgh...\n\t\tPLGShaderProgram *GetInternalProgram() const { return shaderProgram; }\n\n\tprivate:\n\t\tvoid RegisterShaderStage( const char *path, PLGShaderStageType type );\n\n\t\tstd::string vertPath;\n\t\tstd::string fragPath;\n\n\t\tPLGShaderProgram *shaderProgram{ nullptr };\n\t};\n}\n\nohw::ShaderProgram* Shaders_GetProgram( const std::string& name );\n\nvoid Shaders_SetProgramByName( const std::string& name );\n\nvoid Shaders_Initialize();\nvoid Shaders_Shutdown();\n"
  },
  {
    "path": "src/engine/graphics/Sprite.cpp",
    "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// Copyright © 2017-2022 TalonBrave.info and Others (see CONTRIBUTORS)\n\n#include \"App.h\"\n#include \"Sprite.h\"\n#include \"ShaderManager.h\"\n\nohw::Sprite::Sprite( SpriteType type, const std::string &texturePath, PLColour colour, float scale ) :\n\t\ttype_( type ), colour_( colour ), scale_( scale ) {\n\tmesh_ = PlgCreateMeshRectangle( -64, -64, 64, 64, colour_ );\n\n\t// Load in the texture we need\n\ttexture = ohw::GetApp()->resourceManager->LoadTexture( texturePath );\n\n\tdefaultProgram = Shaders_GetProgram( \"generic_textured\" );\n}\n\nohw::Sprite::~Sprite() {}\n\nvoid ohw::Sprite::Draw() {\n\tif ( !cv_graphics_draw_sprites->b_value ) {\n\t\treturn;\n\t}\n\n\tif ( scale_ <= 0 ) {\n\t\treturn;\n\t}\n\n\tdefaultProgram->Enable();\n\n\tPlgSetTexture( texture->GetInternalTexture(), 0 );\n\n\tmodelMatrix.Identity();\n\tmodelMatrix *= hei::Vector3( scale_, scale_, scale_ );\n\tmodelMatrix.Translate( { 32 * scale_, 32 * scale_, 0 } );\n\tmodelMatrix.Rotate( angles_.x, { 1, 0, 0 } );\n\tmodelMatrix.Rotate( angles_.y, { 0, 1, 0 } );\n\tmodelMatrix.Rotate( angles_.z, { 0, 0, 1 } );\n\tmodelMatrix.Translate( position_ );\n\n\tPlgSetShaderUniformValue( defaultProgram->GetInternalProgram(), \"pl_model\", &modelMatrix, true );\n\n\tPlgUploadMesh( mesh_ );\n\n\tPlgSetCullMode( PLG_CULL_NONE );\n\n\tPlgDrawMesh( mesh_ );\n\n\tPlgSetCullMode( PLG_CULL_POSITIVE );\n\n\tPlgSetTexture( nullptr, 0 );\n}\n\n#if 0\nvoid ohw::Sprite::SetAnimation(SpriteAnimation* anim) {\n  u_assert(anim != nullptr, \"Invalid pointer passed for animation!\\n\");\n  current_frame_ = 0;\n  current_animation_ = anim;\n}\n#endif\n\nvoid ohw::Sprite::SetScale( float scale ) {\n\tscale_ = scale;\n}\n\nvoid ohw::Sprite::SetPosition( const PLVector3 &position ) {\n\tposition_ = position;\n}\n\nvoid ohw::Sprite::SetAngles( const PLVector3 &angles ) {\n\tangles_ = angles;\n}\n\nvoid ohw::Sprite::SetColour( const PLColour &colour ) {\n\tPlgSetMeshUniformColour( mesh_, colour );\n\tcolour_ = colour;\n}\n\nvoid ohw::Sprite::SetTexture( const std::string &texturePath ) {\n\tif ( texture != nullptr ) {\n\t\t// TODO: this will currently fail (internal uses absolute)\n\t\tif ( texturePath == texture->GetInternalTexture()->path ) {\n\t\t\treturn;\n\t\t}\n\n\t\ttexture->Release();\n\t}\n\n\ttexture = ohw::GetApp()->resourceManager->LoadTexture( texturePath );\n}\n"
  },
  {
    "path": "src/engine/graphics/Sprite.h",
    "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// Copyright © 2017-2022 TalonBrave.info and Others (see CONTRIBUTORS)\n\n#pragma once\n\nnamespace ohw {\n\tclass ShaderProgram;\n\tclass Sprite {\n\tpublic:\n\t\tenum SpriteType {\n\t\t\tTYPE_DEFAULT,    // Depth-tested, scaled manually and oriented\n\t\t} type_{ TYPE_DEFAULT };\n\n\t\tSprite( SpriteType type, const std::string &texturePath, PLColour colour = { 255, 255, 255, 255 }, float scale = 1.0f );\n\t\t~Sprite();\n\n\t\tfloat GetScale() { return scale_; }\n\t\tvoid SetScale( float scale );\n\n\t\tPLVector3 GetPosition() { return position_; }\n\t\tvoid SetPosition( const PLVector3 &position );\n\n\t\tPLVector3 GetAngles() { return angles_; }\n\t\tvoid SetAngles( const PLVector3 &angles );\n\n\t\tPLColour GetColour() { return colour_; }\n\t\tvoid SetColour( const PLColour &colour );\n\n\t\tvoid SetTexture( const std::string &texturePath );\n\n\t\t//const SpriteAnimation* GetCurrentAnimation() { return current_animation_; }\n\t\t//void SetAnimation(SpriteAnimation* anim);\n\n\t\tvoid Draw();\n\n\tprotected:\n\tprivate:\n\t\tPLVector3 position_;\n\t\tPLVector3 angles_;\n\t\tPLColour colour_{ 255, 255, 255, 255 };\n\t\tfloat scale_{ 1.0f };\n\t\tohw::SharedTextureResourcePointer texture{ nullptr };\n\n\t\tShaderProgram *defaultProgram;\n\n\t\tunsigned int current_frame_{ 0 };\n\t\tdouble frame_delay_{ 0 };\n\n\t\tPLGMesh *mesh_{ nullptr };\n\t\thei::Matrix4 modelMatrix;\n\t};\n}\n"
  },
  {
    "path": "src/engine/graphics/TextureAtlas.cpp",
    "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// Copyright © 2017-2022 TalonBrave.info and Others (see CONTRIBUTORS)\n\n#include \"App.h\"\n#include \"Display.h\"\n#include \"TextureAtlas.h\"\n\nohw::TextureAtlas::TextureAtlas( int w, int h ) : width_( w ), height_( h ) {\n\ttexture_ = ohw::GetApp()->resourceManager->GetFallbackTexture();\n}\n\nohw::TextureAtlas::~TextureAtlas() {\n\tfor ( auto &id: images_by_name_ ) {\n\t\tPLImage *image = id.second;\n\t\tPlDestroyImage( image );\n\t\tid.second = nullptr;\n\t}\n\n\tif ( texture_ != ohw::GetApp()->resourceManager->GetFallbackTexture() ) {\n\t\t// TODO: reintroduce once we have a wrapper around PLModel to hold this!\n\t\t//plDestroyTexture(texture_);\n\t}\n}\n\nbool ohw::TextureAtlas::AddImage( const std::string &path, bool absolute ) {\n\tconst auto image = images_by_name_.find( path );\n\tif ( image != images_by_name_.end() ) {\n\t\treturn true;\n\t}\n\n\tchar full_path[PL_SYSTEM_MAX_PATH];\n\tif ( absolute ) {\n\t\tstrncpy( full_path, path.c_str(), sizeof( full_path ) - 1 );\n\t} else {\n\t\tsnprintf( full_path, sizeof( full_path ) - 1, \"%s\", u_find2( path.c_str(), supportedTextureFormats, false ) );\n\t}\n\n\tPLImage *img = PlLoadImage( full_path );\n\tif ( img == nullptr ) {\n\t\treturn false;\n\t}\n\n\tPlConvertPixelFormat( img, PL_IMAGEFORMAT_RGBA8 );\n\timages_by_name_.emplace( path, img );\n\timages_by_height_.emplace( img->height, img );\n\treturn true;\n}\n\nvoid ohw::TextureAtlas::AddImages( const std::vector< std::string > &textures ) {\n\tfor ( const auto &path: textures ) {\n\t\tAddImage( path );\n\t}\n}\n\nvoid ohw::TextureAtlas::Finalize() {\n\tif ( images_by_height_.empty() ) {\n\t\tWarning( \"Failed to finalize texture atlas, no textures loaded!\\n\" );\n\t\treturn;\n\t}\n\n\t// Figure out how we'll organise the atlas\n\tunsigned int w = width_, h = height_;\n\tunsigned int max_h = 0;\n\tunsigned int cur_y = 0, cur_x = 0;\n\tfor ( auto i = images_by_height_.rbegin(); i != images_by_height_.rend(); ++i ) {\n\t\tPLImage *image = i->second;\n\t\tif ( image->height > max_h ) {\n\t\t\tmax_h = image->height;\n\t\t}\n\n\t\tif ( cur_x == 0 && image->width > w ) {\n\t\t\tw = image->width;\n\t\t} else if ( cur_x + image->width > w ) {\n\t\t\tcur_y += max_h;\n\t\t\tcur_x = max_h = 0;\n\t\t}\n\n\t\tif ( cur_y + image->height > h ) {\n\t\t\th = cur_y + image->height;\n\t\t}\n\n\t\tu_assert( image->path[ 0 ] != '\\0', \"Invalid image name!\" );\n\t\tconst char *filename = PlGetFileName( image->path );\n\t\tconst char *extension = PlGetFileExtension( image->path );\n\t\tstd::string index_name = std::string( filename ).substr( 0, strlen( filename ) - ( strlen( extension ) + 1 ) );\n\t\ttextures_.emplace( index_name, Index{\n\t\t\t\t.x = cur_x,\n\t\t\t\t.y = cur_y,\n\t\t\t\t.w = image->width,\n\t\t\t\t.h = image->height,\n\t\t\t\t.image = image\n\t\t} );\n\n\t\tcur_x += image->width;\n\t}\n\n\t// Ensure power of two for final atlas\n\th = static_cast<unsigned int>(pow( 2, ceil( log( h ) / log( 2 ) ) ));\n\tw = static_cast<unsigned int>(pow( 2, ceil( log( w ) / log( 2 ) ) ));\n\n\t// Image pointers will be freed when we're done with textures list\n\timages_by_name_.clear();\n\timages_by_height_.clear();\n\n\t// Now create the atlas itself\n\tPLImage *cache = PlCreateImage( nullptr, w, h, PL_COLOURFORMAT_RGBA, PL_IMAGEFORMAT_RGBA8 );\n\tif ( cache == nullptr ) {\n\t\tError( \"Failed to generate image cache for texture atlas (%s)!\\n\", PlGetError() );\n\t}\n\n\t//plReplaceImageColour(cache, {0, 0, 0, 0}, {0, 0, 0, 255});\n\n\tfor ( auto &tarr: textures_ ) {\n\t\tIndex *texture = &tarr.second;\n\t\tuint8_t *pos = cache->data[ 0 ] + ( ( texture->y * cache->width ) + texture->x ) * 4;\n\t\tuint8_t *src = texture->image->data[ 0 ];\n\t\tfor ( unsigned int y = 0; y < texture->h; ++y ) {\n\t\t\tmemcpy( pos, src, ( texture->w * 4 ) );\n\t\t\tsrc += texture->w * 4;\n\t\t\tpos += cache->width * 4;\n\t\t}\n\n\t\tPlDestroyImage( texture->image );\n\t\ttexture->image = nullptr;\n\t}\n\n#ifdef _DEBUG\n\tstatic unsigned int gen_id = 0;\n\tif ( PlCreatePath( \"./debug/generated/\" ) ) {\n\t\tchar buf[PL_SYSTEM_MAX_PATH];\n\t\tsnprintf( buf, sizeof( buf ) - 1, \"./debug/generated/%dx%d_%d.png\",\n\t\t          cache->width, cache->height, gen_id++ );\n\t\tPlWriteImage( cache, buf );\n\t}\n#endif\n\n\tif ( ( texture_ = PlgCreateTexture() ) == nullptr ) {\n\t\tError( \"Failed to generate atlas texture (%s)!\\n\", PlGetError() );\n\t}\n\n\tif ( cv_graphics_texture_filter->b_value ) {\n\t\tPlgSetTextureAnisotropy( texture_, 8 );\n\t\ttexture_->filter = PLG_TEXTURE_FILTER_MIPMAP_LINEAR;\n\t} else {\n\t\tPlgSetTextureAnisotropy( texture_, 0 );\n\t\ttexture_->filter = PLG_TEXTURE_FILTER_MIPMAP_NEAREST;\n\t}\n\n\tif ( !PlgUploadTextureImage( texture_, cache ) ) {\n\t\tError( \"Failed to upload texture atlas (%s)!\\n\", PlGetError() );\n\t}\n\n\tPlDestroyImage( cache );\n}\n\nbool ohw::TextureAtlas::GetTextureCoords( const std::string &name, float *x, float *y, float *w, float *h ) {\n\tauto index = textures_.find( name );\n\tif ( index == textures_.end() ) {\n\t\t*x = *y = 0;\n\t\t*w = *h = 1.0f;\n\t\treturn false;\n\t}\n\n\t// HACK: work around texture leaking until we have a better solution!\n\tint shift = 0;\n\tif ( texture_->filter == PLG_TEXTURE_FILTER_MIPMAP_LINEAR ) {\n\t\tshift = 1;\n\t}\n\n\t*x = static_cast<float>(index->second.x + shift) / static_cast<float>(texture_->w);\n\t*y = static_cast<float>(index->second.y + shift) / static_cast<float>(texture_->h);\n\t*w = static_cast<float>(index->second.w - shift * 2) / static_cast<float>(texture_->w);\n\t*h = static_cast<float>(index->second.h - shift * 2) / static_cast<float>(texture_->h);\n\treturn true;\n}\n\nstd::pair< unsigned int, unsigned int > ohw::TextureAtlas::GetTextureSize( const std::string &name ) {\n\tauto index = textures_.find( name );\n\tif ( index == textures_.end() ) {\n\t\treturn std::make_pair( texture_->w, texture_->h );\n\t}\n\n\treturn std::make_pair( index->second.w, index->second.h );\n}\n"
  },
  {
    "path": "src/engine/graphics/TextureAtlas.h",
    "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// Copyright © 2017-2022 TalonBrave.info and Others (see CONTRIBUTORS)\n\n#pragma once\n\nnamespace ohw {\n\tclass TextureAtlas {\n\tpublic:\n\t\tTextureAtlas( int w, int h );\n\t\t~TextureAtlas();\n\n\t\tbool GetTextureCoords( const std::string &name, float *x, float *y, float *w, float *h );\n\t\tstd::pair< unsigned int, unsigned int > GetTextureSize( const std::string &name );\n\n\t\tbool AddImage( const std::string &path, bool absolute = false );\n\t\tvoid AddImages( const std::vector< std::string > &textures );\n\n\t\tvoid Finalize();\n\n\t\tPLGTexture *GetTexture() { return texture_; }\n\n\tprotected:\n\tprivate:\n\t\tstruct Index {\n\t\t\tunsigned int x, y, w, h;\n\t\t\tPLImage *image;\n\t\t};\n\n\t\tint width_{ 512 };\n\t\tint height_{ 8 };\n\n\t\tstd::map< std::string, Index > textures_;\n\t\tstd::map< std::string, PLImage * > images_by_name_;\n\t\tstd::multimap< unsigned int, PLImage * > images_by_height_;\n\n\t\tPLGTexture *texture_{ nullptr };\n\t};\n}\n"
  },
  {
    "path": "src/engine/graphics/mesh.cpp",
    "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// Copyright © 2017-2022 TalonBrave.info and Others (see CONTRIBUTORS)\n\n#include <map>\n#include <set>\n\n#include \"mesh.h\"\n\nvoid Mesh_GenerateFragmentedMeshNormals( const std::list< PLGMesh * > &meshes ) {\n\tstruct Position {\n\t\thei::Vector3 sum_normals;\n\t\tstd::set< PLGVertex * > vertices;\n\t\tunsigned int num_faces;\n\n\t\tPosition( const hei::Vector3 &normal, PLGVertex *output ) :\n\t\t\t\tsum_normals( normal ), num_faces( 1 ) {\n\t\t\tvertices.insert( output );\n\t\t}\n\t};\n\n\tstd::map< hei::Vector3, Position > positions;\n\n\tfor ( auto &mesh: meshes ) {\n\t\tfor ( unsigned int i = 0, idx = 0; i < mesh->num_triangles; ++i, idx += 3 ) {\n\t\t\tunsigned int a = mesh->indices[ idx ];\n\t\t\tunsigned int b = mesh->indices[ idx + 1 ];\n\t\t\tunsigned int c = mesh->indices[ idx + 2 ];\n\n\t\t\tPLVector3 normal = PlgGenerateVertexNormal(\n\t\t\t\t\tmesh->vertices[ a ].position,\n\t\t\t\t\tmesh->vertices[ b ].position,\n\t\t\t\t\tmesh->vertices[ c ].position\n\t\t\t);\n\n\t\t\tfor ( unsigned int j = 0; j < 3; ++j ) {\n\t\t\t\tunsigned int vi = mesh->indices[ idx + j ];\n\n\t\t\t\tPLGVertex *vertex = &( mesh->vertices[ vi ] );\n\n\t\t\t\tauto ni = positions.find( vertex->position );\n\t\t\t\tif ( ni != positions.end() ) {\n\t\t\t\t\tni->second.sum_normals += normal;\n\t\t\t\t\tni->second.vertices.insert( vertex );\n\t\t\t\t\t++( ni->second.num_faces );\n\t\t\t\t} else {\n\t\t\t\t\tpositions.insert( std::make_pair( vertex->position, Position( normal, vertex ) ) );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tfor ( auto &position: positions ) {\n\t\tfor ( PLGVertex *vertex: position.second.vertices ) {\n\t\t\t//vertex->normal = (position.second.sum_normals / position.second.num_faces).Normalize();\n\t\t\tvertex->normal = position.second.sum_normals / position.second.num_faces;\n\t\t\t//vertex->normal = position.second.sum_normals.Normalize();\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/engine/graphics/mesh.h",
    "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// Copyright © 2017-2022 TalonBrave.info and Others (see CONTRIBUTORS)\n\n#pragma once\n\n#include <list>\n\n#include <plgraphics/plg_mesh.h>\n\nvoid Mesh_GenerateFragmentedMeshNormals( const std::list< PLGMesh * > &meshes );\n"
  },
  {
    "path": "src/engine/graphics/particles.cpp",
    "content": "/* OpenHoW\n * Copyright (C) 2017-2020 TalonBrave.info and Others (see CONTRIBUTORS)\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include \"App.h\"\n#include \"particles.h\"\n\nohw::Particle::Particle( PLVector3 position, PLVector3 velocity, PLColour startColour, float lifeSpan ) :\n\tmyColour( startColour ),\n\tmyVelocity( velocity ),\n\tmyPosition( position ),\n\tmyLifeSpan( lifeSpan )\n{}\n\n// SpriteParticle\n\nohw::SpriteParticle::SpriteParticle( const std::string &texturePath, PLColour startColour, PLVector3 position, PLVector3 velocity, float lifeSpan ) :\n\tParticle( position, velocity, startColour, lifeSpan ),\n\tSprite( SpriteType::TYPE_DEFAULT, texturePath ) {}\n\nohw::SpriteParticle::~SpriteParticle() {}\n\n// ModelParticle\n\nohw::ModelParticle::ModelParticle( const std::string &modelPath, PLVector3 position, PLVector3 velocity, PLColour startColour, float lifeSpan ) : Particle( position, velocity, startColour, lifeSpan ) {\n\tmodelPtr = GetApp()->resourceManager->LoadModel( modelPath );\n}\n\nohw::ModelParticle::~ModelParticle() {}\n"
  },
  {
    "path": "src/engine/graphics/particles.h",
    "content": "/* OpenHoW\n * Copyright (C) 2017-2020 TalonBrave.info and Others (see CONTRIBUTORS)\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#pragma once\n\n#include \"Sprite.h\"\n\n// And this is the individual particle\nnamespace ohw {\n\tclass Particle {\n\tpublic:\n\t\tParticle( PLVector3 position, PLVector3 velocity, PLColour startColour, float lifeSpan );\n\n\t\tvoid Tick() {}\n\n\tprotected:\n\tprivate:\n\t\tPLColour myColour;\n\t\tPLVector3 myVelocity;\n\t\tPLVector3 myScale{ 0.0f, 0.0f, 0.0f };\n\t\tPLVector3 myPosition;\n\n\t\tfloat myLifeSpan{ 0.0f };\n\t};\n\n\tclass SpriteParticle : public Particle, Sprite {\n\t\tSpriteParticle( const std::string &texturePath, PLColour startColour, PLVector3 position, PLVector3 velocity, float lifeSpan );\n\t\t~SpriteParticle();\n\n\tprivate:\n\t};\n\n\tclass ModelParticle : public Particle {\n\t\tModelParticle( const std::string &modelPath, PLVector3 position, PLVector3 velocity, PLColour start_colour, float life_span );\n\t\t~ModelParticle();\n\n\tprivate:\n\t\tSharedModelResourcePointer modelPtr{ nullptr };\n\t};\n\n// TODO\n\tclass TrailParticle : public Particle {\n\t};\n\n\tclass TextParticle : public Particle {\n\t};\n}\n"
  },
  {
    "path": "src/engine/graphics/video.cpp",
    "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// Copyright © 2017-2022 TalonBrave.info and Others (see CONTRIBUTORS)\n\n#include \"App.h\"\n#include \"Menu.h\"\n#include \"video.h\"\n#include \"ShaderManager.h\"\n\n#if 0\n#\tinclude <libavformat/avformat.h>\n#\tinclude <libavcodec/avcodec.h>\n#\tinclude <libavfilter/avfilter.h>\n#\tinclude <libavdevice/avdevice.h>\n#endif\n\nconst char *video_paths[] = {\n        /* intro */\n        \"/streams/sheff.bik\",\n        \"/streams/infologo.bik\",\n\n        /* missions - move these into script */\n        \"/streams/fmv 01.bik\",\n        \"/streams/fmv 02.bik\",\n        \"/streams/fmv 03.bik\",\n        \"/streams/fmv 04.bik\",\n        \"/streams/fmv 05.bik\",\n        \"/streams/fmv 06.bik\",\n        \"/streams/fmv 07.bik\",\n        \"/streams/fmv 08.bik\",\n        \"/streams/fmv 09.bik\",\n};\n\n#define MAX_QUEUED_VIDEOS 4\n\ntypedef struct VideoState {\n\tbool is_playing;\n\n#if 0\n\tAVPacket        *av_packet;\n\tAVCodecContext  *av_codec_context;\n\tAVCodec         *av_codec;\n\tAVStream        *av_stream;\n\tAVFormatContext *av_format_context;\n\tAVFrame         *av_frame;\n#endif\n\n\tunsigned int stream_index;\n\n\tstruct {\n\t\tchar path[ PL_SYSTEM_MAX_PATH ];\n\t} queue[ MAX_QUEUED_VIDEOS ];\n\tunsigned int num_videos_queued; /* elements */\n\tunsigned int cur_video;         /* index */\n} VideoState;\nstatic VideoState video;\n\nvoid PlayVideoCommand( unsigned int argc, char *argv[] ) {\n\tif ( argc < 1 ) {\n\t\tWarning( \"invalid number of arguments, ignoring!\\n\"\n\t\t         \"use \\\"play_video /streams/sheff.bik /streams/infologo.bik\\\", for example.\\n\" );\n\t\treturn;\n\t}\n\n\tconst char *cmd = argv[ 1 ];\n\tVideo_QueuePlayback( &cmd, argc - 1 );\n\n\t/* immediately begin playing the videos */\n\tFrontEnd_SetState( FE_MODE_VIDEO );\n}\n\nvoid Video_Initialize( void ) {\n\tmemset( &video, 0, sizeof( VideoState ) );\n\n#if 0\n\tav_register_all();\n\tavformat_network_init();\n#endif\n\n\tPlRegisterConsoleCommand( \"play_video\", \"Play the given videos.\", 1, PlayVideoCommand );\n\tPlParseConsoleString( \"play_video \\\"streams/fmv 01.bik\\\"\" );\n}\n\nvoid Video_Shutdown( void ) {\n\tVideo_ClearQueue();\n}\n\n/************************************************************/\n\nvoid Video_ClearQueue( void ) {\n\tmemset( video.queue, 0, sizeof( video.queue ) );\n\tvideo.cur_video = 0;\n\tvideo.num_videos_queued = 0;\n}\n\nvoid Video_QueuePlayback( const char **videos, unsigned int num_videos ) {\n\tif ( num_videos == 0 ) {\n\t\treturn;\n\t}\n\n\tVideo_ClearQueue();\n\n\tfor ( unsigned int i = 0; i < num_videos; ++i ) {\n\t\tif ( videos[ i ] == nullptr ) {\n\t\t\tWarning( \"encountered invalid video path at index %u, skipping!\\n\", i );\n\t\t\tcontinue;\n\t\t}\n\n\t\tsize_t len = strlen( videos[ i ] );\n\t\tif ( len >= PL_SYSTEM_MAX_PATH ) {\n\t\t\tWarning( \"unexpected length of path - %u bytes - expect issues!\\n\", len );\n\t\t}\n\n\t\tchar n_path[ PL_SYSTEM_MAX_PATH ];\n\t\tstrncpy( n_path, videos[ i ], PL_SYSTEM_MAX_PATH );\n\t\tif ( !PlFileExists( n_path ) ) {\n\t\t\tWarning( \"failed to find video at \\\"%s\\\", skipping!\\n\", n_path );\n\t\t\tcontinue;\n\t\t}\n\n\t\tstrncpy( video.queue[ video.num_videos_queued ].path, n_path, PL_SYSTEM_MAX_PATH );\n\t\tvideo.num_videos_queued++;\n\t}\n}\n\nvoid Video_Play( const char *path ) {\n\tVideo_ClearQueue();\n\tVideo_QueuePlayback( &path, 1 );\n\tif ( video.num_videos_queued == 0 ) {\n\t\tWarning( \"failed to queue video, \\\"%s\\\", aborting playback!\\n\", path );\n\t\treturn;\n\t}\n\n\t/* immediately begin playing the videos */\n\tFrontEnd_SetState( FE_MODE_VIDEO );\n}\n\nvoid Video_SkipCurrent( void ) {\n#if 0\n\tif(video.av_packet != NULL) {\n\t\tav_packet_unref(video.av_packet);\n\t\tvideo.av_packet = NULL;\n\t}\n\n\tif(video.av_format_context != NULL) {\n\t\t/* automatically sets av_format_context to null */\n\t\tavformat_close_input(&video.av_format_context);\n\t}\n\n\tif(video.num_videos_queued > 0 && video.cur_video != video.num_videos_queued) {\n\t\tif(avformat_open_input(&video.av_format_context, video.queue[video.cur_video].path, NULL, NULL) < 0) {\n\t\t\tLogWarn(\"failed to open video, \\\"%s\\\", for playback, skipping!\\n\");\n\t\t\tVideo_SkipCurrent();\n\t\t\treturn;\n\t\t}\n\t\treturn;\n\t}\n#endif\n\n\t/* nothing left to play */\n\tFE_RestoreLastState();\n}\n\n#if 0\nstatic void ProcessVideo(void) {\n\n\tdo {\n\t\t/* decode the video */\n\n\t\tif(av_read_frame(video.av_format_context, video.av_packet) < 0) {\n\t\t\tLogWarn(\"failed to read video frame!\\n\");\n\t\t\tSkipVideo();\n\t\t\treturn;\n\t\t}\n\n\t\tif(video.av_packet->stream_index == video.stream_index) {\n\t\t\tif(avcodec_send_packet(video.av_codec_context, video.av_packet) < 0) {\n\t\t\t\tLogWarn(\"failed to send video packet!\\n\");\n\t\t\t\tSkipVideo();\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tint val = avcodec_receive_frame(video.av_codec_context, video.av_frame);\n\t\t\tif(val < 0 && val != AVERROR(EAGAIN) && val != AVERROR_EOF) {\n\t\t\t\tLogWarn(\"failed to receive video frame!\\n\");\n\t\t\t\tSkipVideo();\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t/* todo: stuff... */\n\n\t\t\tav_frame_unref(video.av_frame);\n\t\t}\n\n\t\tav_packet_unref(video.av_packet);\n\n\t\t/* and now the audio ... */\n\n\n\t} while(video.av_packet->stream_index != video.stream_index);\n}\n#endif\n\nvoid Video_Draw( void ) {\n\tstatic PLGMesh *mesh = NULL;\n\tif ( mesh == NULL ) {\n\t\tif ( ( mesh = PlgCreateMesh( PLG_MESH_TRIANGLE_STRIP, PLG_DRAW_STATIC, 2, 4 ) ) == NULL ) {\n\t\t\tError( \"failed to create mesh for video renderer, aborting!\\n%s\\n\", PlGetError() );\n\t\t}\n\n\t\tPlgClearMesh( mesh );\n\n#define x 0\n#define y 0\n#define w 640\n#define h 480\n\n\t\tPlgSetMeshVertexPosition( mesh, 0, hei::Vector3( x, y, 0 ) );\n\t\tPlgSetMeshVertexPosition( mesh, 1, hei::Vector3( x, y + h, 0 ) );\n\t\tPlgSetMeshVertexPosition( mesh, 2, hei::Vector3( x + w, y, 0 ) );\n\t\tPlgSetMeshVertexPosition( mesh, 3, hei::Vector3( x + w, y + h, 0 ) );\n\n\t\tPlgSetMeshUniformColour( mesh, PLColourRGB( 255, 255, 255 ) );\n\n\t\tPlgSetMeshVertexST( mesh, 0, 0, 0 );\n\t\tPlgSetMeshVertexST( mesh, 1, 0, 1 );\n\t\tPlgSetMeshVertexST( mesh, 2, 1, 0 );\n\t\tPlgSetMeshVertexST( mesh, 3, 1, 1 );\n\n\t\tPlgUploadMesh( mesh );\n\t}\n\n\tShaders_SetProgramByName( \"generic_textured\" );\n\n\tPLGShaderProgram *program = PlgGetCurrentShaderProgram();\n\tif ( program == nullptr ) {\n\t\treturn;\n\t}\n\n\t/* todo pass correct texture */\n\tPLMatrix4 matrix = PlMatrix4Identity();\n\tPlgSetShaderUniformValue( program, \"pl_model\", &matrix, false );\n\tPlgDrawMesh( mesh );\n}\n"
  },
  {
    "path": "src/engine/graphics/video.h",
    "content": "/* OpenHoW\n * Copyright (C) 2017-2020 TalonBrave.info and Others (see CONTRIBUTORS)\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#pragma once\n\nPL_EXTERN_C\n\nvoid Video_Initialize(void);\nvoid Video_Shutdown(void);\n\nvoid Video_ClearQueue(void);\nvoid Video_QueuePlayback(const char **videos, unsigned int num_videos);\nvoid Video_Play(const char *path);\nvoid Video_Draw(void);\nvoid Video_SkipCurrent(void);\n\nPL_EXTERN_C_END\n"
  },
  {
    "path": "src/engine/imgui_layer.cpp",
    "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// Copyright © 2017-2022 TalonBrave.info and Others (see CONTRIBUTORS)\n\n#include \"App.h\"\n#include \"imgui_layer.h\"\n#include \"graphics/Camera.h\"\n\n#include <SDL2/SDL_syswm.h>\n\n#undef far\n#undef near\n\n#include \"../3rdparty/platform/extras/imgui_renderer.h\"\n\n#include \"editor/BaseWindow.h\"\n#include \"editor/MapConfigEditor.h\"\n#include \"editor/TextureViewer.h\"\n#include \"editor/NewMapWindow.h\"\n#include \"editor/ModelViewer.h\"\n#include \"editor/TerrainImportWindow.h\"\n#include \"editor/ActorTreeWindow.h\"\n#include \"editor/NewGameWindow.h\"\n#include \"editor/ParticleEditor.h\"\n#include \"editor/TexturePicker.h\"\n#include \"editor/ConsoleWindow.h\"\n\n#include \"Language.h\"\n\nstatic bool show_quit = false;\nstatic bool show_settings = false;\n\nstatic ohw::ConsoleWindow *mainConsole = nullptr;\nstatic void ConsoleOutputCallback( int level, const char *msg, PLColour colour ) {\n\tif ( mainConsole == nullptr ) {\n\t\treturn;\n\t}\n\n\tmainConsole->PushMessage( level, msg );\n}\n\nstatic std::vector< BaseWindow * > windows;\n\nusing namespace ohw;\n\n#define IMGUI_POS_CENTER \\\n    ImVec2( \\\n    static_cast<float>(cv_display_width->i_value) * 0.5f, \\\n    static_cast<float>(cv_display_height->i_value) * 0.5f ), \\\n    ImGuiCond_Once, \\\n    ImVec2( 0.5f, 0.5f )\n\nvoid ImGuiImpl_Setup() {\n\tIMGUI_CHECKVERSION();\n\n\tImGui::CreateContext();\n\n\tImGuiIO &io = ImGui::GetIO();\n\n\tio.BackendFlags |=\n\t\t\tImGuiBackendFlags_HasMouseCursors |\n\t\t\tImGuiBackendFlags_HasSetMousePos;\n\t//io.BackendFlags |= ImGuiBackendFlags_HasGamepad;\n\n\tio.KeyMap[ ImGuiKey_Tab ] = SDL_SCANCODE_TAB;\n\tio.KeyMap[ ImGuiKey_LeftArrow ] = SDL_SCANCODE_LEFT;\n\tio.KeyMap[ ImGuiKey_RightArrow ] = SDL_SCANCODE_RIGHT;\n\tio.KeyMap[ ImGuiKey_UpArrow ] = SDL_SCANCODE_UP;\n\tio.KeyMap[ ImGuiKey_DownArrow ] = SDL_SCANCODE_DOWN;\n\tio.KeyMap[ ImGuiKey_PageUp ] = SDL_SCANCODE_PAGEUP;\n\tio.KeyMap[ ImGuiKey_PageDown ] = SDL_SCANCODE_PAGEDOWN;\n\tio.KeyMap[ ImGuiKey_Home ] = SDL_SCANCODE_HOME;\n\tio.KeyMap[ ImGuiKey_End ] = SDL_SCANCODE_END;\n\tio.KeyMap[ ImGuiKey_Insert ] = SDL_SCANCODE_INSERT;\n\tio.KeyMap[ ImGuiKey_Delete ] = SDL_SCANCODE_DELETE;\n\tio.KeyMap[ ImGuiKey_Backspace ] = SDL_SCANCODE_BACKSPACE;\n\tio.KeyMap[ ImGuiKey_Space ] = SDL_SCANCODE_SPACE;\n\tio.KeyMap[ ImGuiKey_Enter ] = SDL_SCANCODE_RETURN;\n\tio.KeyMap[ ImGuiKey_Escape ] = SDL_SCANCODE_ESCAPE;\n\tio.KeyMap[ ImGuiKey_A ] = SDL_SCANCODE_A;\n\tio.KeyMap[ ImGuiKey_C ] = SDL_SCANCODE_C;\n\tio.KeyMap[ ImGuiKey_V ] = SDL_SCANCODE_V;\n\tio.KeyMap[ ImGuiKey_X ] = SDL_SCANCODE_X;\n\tio.KeyMap[ ImGuiKey_Y ] = SDL_SCANCODE_Y;\n\tio.KeyMap[ ImGuiKey_Z ] = SDL_SCANCODE_Z;\n\n\tio.SetClipboardTextFn = GetApp()->SetClipboardText;\n\tio.GetClipboardTextFn = GetApp()->GetClipboardText;\n\tio.ClipboardUserData = nullptr;\n\n#if 0\n#ifdef _WIN32\n\tSDL_SysWMinfo wmInfo;\n\tSDL_VERSION(&wmInfo.version);\n\tSDL_GetWindowWMInfo(window, &wmInfo);\n\tio.ImeWindowHandle = wmInfo.info.win.window;\n#endif\n#endif\n\n\tPlImGui_Initialize();\n\n\tio.Fonts->Clear();\n\n\t// Load in the default font\n\n\tconst char *fontPath = \"fonts/OpenSans-SemiBold.ttf\";\n\tPLFile *fontFile = PlOpenFile( fontPath, false );\n\tif ( fontFile == nullptr ) {\n\t\tWarning( \"Failed to load font, \\\"%s\\\", for ImGui (%s)! Falling back to default...\\n\", fontPath, PlGetError() );\n\t\tio.Fonts->AddFontDefault();\n\t\treturn;\n\t}\n\n\tsize_t fileSize = PlGetFileSize( fontFile );\n\tuint8_t *buf = new uint8_t[fileSize];\n\tPlReadFile( fontFile, buf, 1, fileSize );\n\tPlCloseFile( fontFile );\n\n\tif ( io.Fonts->AddFontFromMemoryTTF( buf, fileSize, 16.f, nullptr, nullptr ) == nullptr ) {\n\t\tWarning( \"Failed to add font, \\\"%s\\\", from memory!\\n\", fontPath );\n\t\tio.Fonts->AddFontDefault();\n\t}\n\n\tmainConsole = new ohw::ConsoleWindow();\n\tmainConsole->SetWindowStatus( false );\n\n\tPlSetConsoleOutputCallback( ConsoleOutputCallback );\n}\n\nvoid ImGuiImpl_Shutdown() {\n\tPlImGui_Shutdown();\n\tImGui::DestroyContext();\n}\n\nvoid ImGuiImpl_SetupFrame() {\n\tconst PLGViewport *viewport = PlgGetCurrentViewport();\n\tif ( viewport == nullptr ) {\n\t\treturn;\n\t}\n\n\tImGuiIO &io = ImGui::GetIO();\n\tio.DisplaySize = ImVec2( viewport->w, viewport->h );\n\n\tPlImGui_NewFrame();\n\n\tImGui::NewFrame();\n}\n\nvoid ImGuiImpl_Tick( void ) {\n\tImGuiIO &io = ImGui::GetIO();\n\tif ( io.WantSetMousePos ) {\n\t\tohw::Display *display = ohw::GetApp()->GetDisplay();\n\t\tif ( display != nullptr ) {\n\t\t\tdisplay->SetMousePosition( io.MousePos.x, io.MousePos.y );\n\t\t}\n\t} else {\n\t\tio.MousePos = ImVec2( -FLT_MAX, -FLT_MAX );\n\t}\n\n\n}\n\nvoid ImGuiImpl_Draw( void ) {\n\tImGui::Render();\n\n\tPlgSetShaderProgram( nullptr );\n\n\tPlImGui_RenderDrawData( ImGui::GetDrawData() );\n}\n\n/************************************************************/\n/* Settings */\n\n#if 0 // TODO: REDO\nvoid UI_DisplaySettings() {\n\tif ( !show_settings ) {\n\t\treturn;\n\t}\n\n\tImGui::Begin( \"Settings\", &show_settings );\n\n\tstatic int item_current = 0;\n\tbool display_changed = false;\n\tconst ohw::App::DisplayPreset *mode = GetApp()->GetVideoPreset( item_current );\n\tchar s[32] = { 0 };\n\tsnprintf( s, 32, \"%dx%d\", mode->width, mode->height );\n\tif ( ImGui::BeginCombo( \"Resolution\", s, 0 ) ) {\n\t\tint num_modes = Display_GetNumVideoPresets();\n\t\tfor ( int n = 0; n < num_modes; n++ ) {\n\t\t\tmode = Display_GetVideoPreset( n );\n\t\t\tsnprintf( s, 32, \"%dx%d\", mode->width, mode->height );\n\t\t\tbool is_selected = ( item_current == n );\n\t\t\tif ( ImGui::Selectable( s, is_selected ) ) {\n\t\t\t\titem_current = n;\n\t\t\t\tdisplay_changed = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif ( is_selected )\n\t\t\t\tImGui::SetItemDefaultFocus();\n\t\t}\n\t\tImGui::EndCombo();\n\t}\n\n\tstatic bool fs;\n\tbool fs_changed = false;\n\tfs_changed |= ImGui::Checkbox( \"Fullscreen\", &fs );\n\n\tImGui::SameLine();\n\n\tbool vsync = cv_display_vsync->b_value;\n\tif ( ImGui::Checkbox( \"Vsync\", &vsync ) && vsync != cv_display_vsync->b_value ) {\n\t\tplSetConsoleVariable( cv_display_vsync, vsync ? \"true\" : \"false\" );\n\t}\n\n\tstatic int aspect_opt = 0;\n\tbool aspect_changed = false;\n\tImGui::Text( \"Aspect ratio:\" );\n\taspect_changed |= ImGui::RadioButton( \"4:3\", &aspect_opt, 0 );\n\tImGui::SameLine();\n\taspect_changed |= ImGui::RadioButton( \"Fit window\", &aspect_opt, 1 );\n\n\tstatic int ui_scale_opt = 0;\n\tbool ui_scale_changed = false;\n\tImGui::Text( \"UI scale:\" );\n\tui_scale_changed |= ImGui::RadioButton( \"Auto\", &ui_scale_opt, 0 );\n\tImGui::SameLine();\n\tui_scale_changed |= ImGui::RadioButton( \"1x\", &ui_scale_opt, 1 );\n\tImGui::SameLine();\n\tui_scale_changed |= ImGui::RadioButton( \"2x\", &ui_scale_opt, 2 );\n\tImGui::SameLine();\n\tui_scale_changed |= ImGui::RadioButton( \"3x\", &ui_scale_opt, 3 );\n\tImGui::SameLine();\n\tui_scale_changed |= ImGui::RadioButton( \"4x\", &ui_scale_opt, 4 );\n\n\tstatic int filter_textures = -1;\n\tif ( filter_textures == -1 ) { filter_textures = cv_graphics_texture_filter->b_value; }\n\tif ( ImGui::Checkbox( \"Filter textures\", reinterpret_cast<bool *>(&filter_textures) ) ) {\n\t\tplSetConsoleVariable( cv_graphics_texture_filter, filter_textures ? \"true\" : \"false\" );\n\t}\n\n\t//Apply changes\n\tchar buf[16];\n\tif ( display_changed ) {\n\t\tplSetConsoleVariable( cv_display_width, pl_itoa( mode->width, buf, 16, 10 ) );\n\t\tplSetConsoleVariable( cv_display_height, pl_itoa( mode->height, buf, 16, 10 ) );\n\t\tSystem_SetWindowSize( cv_display_width->i_value, cv_display_height->i_value, cv_display_fullscreen->b_value );\n\t}\n\tif ( fs_changed ) {\n\t\tplSetConsoleVariable( cv_display_fullscreen, fs ? \"true\" : \"false\" );\n\t\tSystem_SetWindowSize( cv_display_width->i_value, cv_display_height->i_value, cv_display_fullscreen->b_value );\n\t}\n\tif ( aspect_changed ) {\n\t\tplSetConsoleVariable( cv_display_use_window_aspect, aspect_opt ? \"true\" : \"false\" );\n\t\tDisplay_UpdateViewport( 0, 0, cv_display_width->i_value, cv_display_height->i_value );\n\t}\n\tif ( ui_scale_changed ) {\n\t\tplSetConsoleVariable( cv_display_ui_scale, pl_itoa( ui_scale_opt, buf, 16, 10 ) );\n\t}\n\n\tif ( ImGui::Button( \"Cancel\" ) ) {\n\t\tshow_settings = false;\n\t}\n\n\tImGui::End();\n}\n\n/************************************************************/\n\nenum {\n\tFILE_TYPE_UNKNOWN,\n\tFILE_TYPE_MAP_POG,\n\tFILE_TYPE_MAP_PTG,\n\tFILE_TYPE_MAP_PMG,\n\tFILE_TYPE_IMAGE,\n\tFILE_TYPE_MODEL,\n\tFILE_TYPE_AUDIO,\n\tFILE_TYPE_PARTICLE,\n};\n\ntypedef struct FileDescriptor {\n\tchar path[PL_SYSTEM_MAX_PATH];\n\tunsigned int type;\n} FileDescriptor;\n\nstatic std::vector< FileDescriptor > file_list;\n\nvoid AddFilePath( const char *path, void *userData ) {\n\tu_unused( userData );\n\n\tFileDescriptor descriptor;\n\tstrncpy( descriptor.path, path, sizeof( descriptor.path ) );\n\tdescriptor.type = FILE_TYPE_UNKNOWN;\n\n\tconst char *ext = plGetFileExtension( path );\n\tif ( ext != nullptr ) {\n\t\tif (\n\t\t\t\tstrcmp( ext, \"tim\" ) == 0 ||\n\t\t\t\tstrcmp( ext, \"bmp\" ) == 0 ||\n\t\t\t\tstrcmp( ext, \"png\" ) == 0 ) {\n\t\t\tdescriptor.type = FILE_TYPE_IMAGE;\n\t\t} else if (\n\t\t\t\tstrcmp( ext, \"pps\" ) == 0\n\t\t\t\t) {\n\t\t\tdescriptor.type = FILE_TYPE_PARTICLE;\n\t\t} else if (\n\t\t\t\tstrcmp( ext, \"wav\" ) == 0\n\t\t\t\t) {\n\t\t\tdescriptor.type = FILE_TYPE_AUDIO;\n\t\t} else if (\n\t\t\t\tstrcmp( ext, \"ptg\" ) == 0\n\t\t\t\t) {\n\t\t\tdescriptor.type = FILE_TYPE_MAP_PTG;\n\t\t} else if (\n\t\t\t\tstrcmp( ext, \"pog\" ) == 0\n\t\t\t\t) {\n\t\t\tdescriptor.type = FILE_TYPE_MAP_POG;\n\t\t} else if (\n\t\t\t\tstrcmp( ext, \"pmg\" ) == 0\n\t\t\t\t) {\n\t\t\tdescriptor.type = FILE_TYPE_MAP_PMG;\n\t\t} else if (\n\t\t\t\tpl_strcasecmp( ext, \"vtx\" ) == 0 ||\n\t\t\t\tpl_strcasecmp( ext, \"min\" ) == 0 ||\n\t\t\t\tpl_strcasecmp( ext, \"obj\" ) == 0 ) {\n\t\t\tdescriptor.type = FILE_TYPE_MODEL;\n\t\t}\n\t}\n\n\tfile_list.push_back( descriptor );\n}\n\nvoid ScanDirectories() {\n\tfile_list.clear();\n\tplScanDirectory( \".\", nullptr, AddFilePath, true, nullptr );\n}\n\nvoid UI_DisplayFileBox() {\n\tif ( !show_file ) {\n\t\treturn;\n\t}\n\n\tstatic bool has_scanned = false;\n\tif ( !has_scanned ) {\n\t\tScanDirectories();\n\t\thas_scanned = true;\n\t}\n\n\tImGui::SetNextWindowPos( IMGUI_POS_CENTER );\n\tImGui::SetNextWindowSize( ImVec2( 512, 512 ), ImGuiCond_Once );\n\tImGui::Begin( \"Open File\", &show_file );\n\n\tstatic ImGuiTextFilter filter;\n\tfilter.Draw();\n\tImGui::SameLine();\n\n\tif ( ImGui::Button( \"Rescan\", ImVec2( ImGui::GetWindowContentRegionWidth(), 0 ) ) ) {\n\t\tScanDirectories();\n\t}\n\n\tImGui::PushStyleVar( ImGuiStyleVar_ChildRounding, 5.0f );\n\tImGui::PushStyleVar( ImGuiStyleVar_ButtonTextAlign, ImVec2( -1.f, 0 ) );\n\tImGui::BeginChild( \"Child2\", ImVec2( ImGui::GetWindowContentRegionWidth(), ImGui::GetWindowHeight() - 64 ), true );\n\tImGui::Columns( 2 );\n\tfor ( auto &i : file_list ) {\n\t\tif ( filter.PassFilter( i.path ) ) {\n\t\t\tif ( ImGui::Button( i.path ) ) {\n\t\t\t\tswitch ( i.type ) {\n\t\t\t\t\tcase FILE_TYPE_IMAGE: {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tauto *viewer = new TextureViewer( i.path );\n\t\t\t\t\t\t\twindows.push_back( viewer );\n\t\t\t\t\t\t} catch ( const std::runtime_error &error ) {\n\t\t\t\t\t\t\tWarning( \"%s\\n\", error.what() );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n#if 0\n\t\t\t\t\t\tcase FILE_TYPE_MODEL:\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tauto* viewer = new ModelViewer( i.path );\n\t\t\t\t\t\t\t\twindows.push_back( viewer );\n\t\t\t\t\t\t\t} catch ( const std::runtime_error& error ) {\n\t\t\t\t\t\t\t\tLogWarn( \"%s\\n\", error.what() );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n#endif\n\t\t\t\t\tcase FILE_TYPE_AUDIO:\n\t\t\t\t\t\tEngine::Audio()->PlayGlobalSound( i.path );\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tImGui::NextColumn();\n\n\t\t\tconst char *type = \"Unknown\";\n\t\t\tswitch ( i.type ) {\n\t\t\t\tcase FILE_TYPE_AUDIO:\n\t\t\t\t\ttype = \"Audio\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase FILE_TYPE_PARTICLE:\n\t\t\t\t\ttype = \"Particle System\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase FILE_TYPE_IMAGE:\n\t\t\t\t\ttype = \"Image\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase FILE_TYPE_MAP_POG:\n\t\t\t\t\ttype = \"Map Objects\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase FILE_TYPE_MAP_PTG:\n\t\t\t\t\ttype = \"Map Textures\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase FILE_TYPE_MAP_PMG:\n\t\t\t\t\ttype = \"Map Geometry\";\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tImGui::Text( \"%s\", type );\n\n\t\t\tImGui::NextColumn();\n\t\t}\n\t}\n\tImGui::EndChild();\n\tImGui::PopStyleVar();\n\tImGui::PopStyleVar();\n\n\tImGui::End();\n}\n#endif\n\nclass QuitWindow : public BaseWindow {\npublic:\n\tvoid Display() override {\n\t\tImGui::SetNextWindowPos( IMGUI_POS_CENTER );\n\t\tImGui::Begin( \"Are you sure?\", &show_quit, ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoResize |\n\t\t                                           ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoSavedSettings );\n\t\tImGui::Text( \"Are you sure you want to quit the game?\\nAny unsaved changes will be lost!\\n\" );\n\t\tImGui::Dummy( ImVec2( 0, 5 ) );\n\t\tImGui::Separator();\n\t\tImGui::Dummy( ImVec2( 0, 5 ) );\n\n\t\tif ( ImGui::Button( \"Yes\", ImVec2( 64, 0 ) ) ) {\n\t\t\tImGui::End();\n\t\t\tGetApp()->Shutdown();\n\t\t}\n\n\t\tImGui::SameLine();\n\n\t\tif ( ImGui::Button( \"No\", ImVec2( 64, 0 ) ) ) {\n\t\t\tToggleStatus();\n\t\t}\n\n\t\tImGui::End();\n\t}\n\nprotected:\nprivate:\n};\n\nvoid UI_DisplayDebugMenu() {\n\tint dW = cv_display_width->i_value;\n\tint dH = cv_display_height->i_value;\n\n\tstatic bool show_about = false;\n\tif ( ImGui::BeginMainMenuBar() ) {\n\t\tif ( ImGui::BeginMenu( \"File\" ) ) {\n\t\t\tif ( ImGui::BeginMenu( \"One Player\" ) ) {\n\t\t\t\tif ( ImGui::MenuItem( \"New Game\" ) ) {\n\t\t\t\t\twindows.push_back( new NewGameWindow() );\n\t\t\t\t}\n\t\t\t\tif ( ImGui::MenuItem( \"Load Game\" ) ) {} // todo\n\t\t\t\tImGui::EndMenu();\n\t\t\t}\n\t\t\tif ( ImGui::MenuItem( \"Multi-Player\" ) ) {}  // todo\n\t\t\tImGui::Separator();\n\t\t\tif ( ImGui::MenuItem( \"Create Map\" ) ) {\n\t\t\t\tstatic NewMapWindow *popup = nullptr;\n\t\t\t\tif ( popup == nullptr ) {\n\t\t\t\t\twindows.push_back( ( popup = new NewMapWindow() ) );\n\t\t\t\t}\n\t\t\t}\n\t\t\tif ( ImGui::MenuItem( \"Load Map\" ) ) {} // todo\n\t\t\tImGui::Separator();\n\t\t\tif ( ImGui::MenuItem( \"Options\" ) ) { show_settings = true; }\n\t\t\tif ( ImGui::MenuItem( \"Controls\" ) ) {} // todo\n\t\t\tImGui::Separator();\n\t\t\tif ( ImGui::MenuItem( \"Quit\" ) ) {\n\t\t\t\twindows.push_back( new QuitWindow() );\n\t\t\t}\n\n\t\t\tImGui::EndMenu();\n\t\t}\n\n\t\tif ( ImGui::BeginMenu( \"Debug\" ) ) {\n\t\t\tstatic bool simStatus = false;\n\t\t\tif ( ImGui::MenuItem( \"Toggle Simulation\", \"T\", simStatus ) ) {\n\t\t\t\tGetApp()->gameManager->ToggleSimulation( ( simStatus = !simStatus ) );\n\t\t\t}\n\t\t\tif ( ImGui::MenuItem( \"Step Simulation\", \"S\" ) ) {\n\t\t\t\tGetApp()->gameManager->StepSimulation( 1 );\n\t\t\t}\n\n\t\t\tImGui::Separator();\n\n\t\t\tif ( ImGui::MenuItem( \"Show Console\", \"`\", mainConsole->GetStatus() ) ) {\n\t\t\t\tmainConsole->ToggleStatus();\n\t\t\t}\n\n\t\t\tImGui::Separator();\n\n\t\t\tif ( ImGui::MenuItem( \"Rebuild Shaders\" ) ) {\n\t\t\t\tPlParseConsoleString( \"rebuildShaderPrograms\" );\n\t\t\t}\n\n\t\t\tImGui::Separator();\n\n\t\t\tif ( ImGui::BeginMenu( \"Console Variables\" ) ) {\n\t\t\t\tsize_t num_c;\n\t\t\t\tPLConsoleVariable **vars;\n\t\t\t\tPlGetConsoleVariables( &vars, &num_c );\n\n\t\t\t\tfor ( PLConsoleVariable **var = vars; var < num_c + vars; ++var ) {\n\t\t\t\t\tswitch ( ( *var )->type ) {\n\t\t\t\t\t\tcase PL_VAR_F32:\n\t\t\t\t\t\t\tif ( ImGui::InputFloat( ( *var )->name, &( *var )->f_value, 0, 10, nullptr,\n\t\t\t\t\t\t\t                        ImGuiInputTextFlags_EnterReturnsTrue ) ) {\n\t\t\t\t\t\t\t\tPlSetConsoleVariable( ( *var ), std::to_string( ( *var )->f_value ).c_str() );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase PL_VAR_I32:\n\t\t\t\t\t\t\tif ( ImGui::InputInt( ( *var )->name, &( *var )->i_value, 1, 10,\n\t\t\t\t\t\t\t                      ImGuiInputTextFlags_EnterReturnsTrue ) ) {\n\t\t\t\t\t\t\t\tPlSetConsoleVariable( ( *var ), std::to_string( ( *var )->i_value ).c_str() );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase PL_VAR_STRING:\n\t\t\t\t\t\t\t// read-only for now\n\t\t\t\t\t\t\tImGui::LabelText( ( *var )->name, \"%s\", ( *var )->s_value );\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase PL_VAR_BOOL:\n\t\t\t\t\t\t\tbool b = ( *var )->b_value;\n\t\t\t\t\t\t\tif ( ImGui::Checkbox( ( *var )->name, &b ) ) {\n\t\t\t\t\t\t\t\tPlSetConsoleVariable( ( *var ), b ? \"true\" : \"false\" );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( ImGui::IsItemHovered() ) {\n\t\t\t\t\t\tImGui::BeginTooltip();\n\t\t\t\t\t\tImGui::TextUnformatted( ( *var )->description );\n\t\t\t\t\t\tImGui::EndTooltip();\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tImGui::EndMenu();\n\t\t\t}\n\n\t\t\tif ( ImGui::BeginMenu( \"Console Commands\" ) ) {\n\t\t\t\tsize_t num;\n\t\t\t\tPLConsoleCommand **cmds;\n\t\t\t\tPlGetConsoleCommands( &cmds, &num );\n\n\t\t\t\tfor ( PLConsoleCommand **cmd = cmds; cmd < num + cmds; ++cmd ) {\n\t\t\t\t\tif ( ImGui::MenuItem( ( *cmd )->name ) ) {\n\t\t\t\t\t\tPlParseConsoleString( ( *cmd )->name );\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( ImGui::IsItemHovered() ) {\n\t\t\t\t\t\tImGui::BeginTooltip();\n\t\t\t\t\t\tImGui::TextUnformatted( ( *cmd )->description );\n\t\t\t\t\t\tImGui::EndTooltip();\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tImGui::EndMenu();\n\t\t\t}\n\n\t\t\tImGui::EndMenu();\n\t\t}\n\n\t\t// todo: eventually this will be moved into a dedicated toolbar\n\t\tif ( ImGui::BeginMenu( \"Tools\" ) ) {\n\t\t\tif ( ImGui::MenuItem( \"Particle Editor...\" ) ) {\n\t\t\t\twindows.push_back( new ParticleEditor() );\n\t\t\t}\n\t\t\tif ( GetApp()->gameManager->IsModeActive() ) {\n\t\t\t\tif ( ImGui::MenuItem( \"Import Heightmap...\" ) ) {\n\t\t\t\t\twindows.push_back( new TerrainImportWindow() );\n\t\t\t\t}\n\t\t\t\tImGui::Separator();\n\t\t\t\tif ( ImGui::MenuItem( \"Actor Inspector...\" ) ) { windows.push_back( new ActorTreeWindow() ); }\n\t\t\t\tif ( ImGui::MenuItem( \"Map Config Editor...\" ) ) { windows.push_back( new MapConfigEditor() ); }\n\t\t\t\tif ( ImGui::MenuItem( \"Texture Picker...\" ) ) { windows.push_back( new TexturePicker() ); }\n\t\t\t}\n\t\t\tif ( ImGui::MenuItem( \"Model Viewer...\" ) ) { windows.push_back( new ModelViewer() ); }\n\t\t\tImGui::EndMenu();\n\t\t}\n\n\t\tif ( ImGui::BeginMenu( \"Help\" ) ) {\n\t\t\tImGui::MenuItem( \"About OpenHoW\", nullptr, &show_about );\n\t\t\tImGui::EndMenu();\n\t\t}\n\n\t\tImGui::Separator();\n\n\t\tunsigned int fps, ms;\n\t\tDisplay_GetFramesCount( &fps, &ms );\n\n\t\tImGui::PushItemWidth( 64 );\n\t\tImGui::Text( \"FPS %d (%dms)\", fps, ms );\n\t\tImGui::PopItemWidth();\n\n\t\tImGui::EndMainMenuBar();\n\t}\n\n\t// Prompt to notify players that games can be started\n\t// via File > New Game, until we get an actual frontend\n\t// implementation done.\n\tif ( !GetApp()->gameManager->IsModeActive() ) {\n\t\tImGui::SetNextWindowSize( ImVec2( 320, 128 ) );\n\t\tImGui::SetNextWindowPos( ImVec2( dW * 0.5f, dH * 0.5f ), ImGuiCond_Always, ImVec2( 0.5f, 0.5f ) );\n\t\tstatic bool state = false;\n\t\tif ( ImGui::Begin(\n\t\t\t\t\"InstructionMenu\",\n\t\t\t\t&state,\n\t\t\t\tImGuiWindowFlags_NoDecoration |\n\t\t\t\tImGuiWindowFlags_NoInputs |\n\t\t\t\tImGuiWindowFlags_NoSavedSettings |\n\t\t\t\tImGuiWindowFlags_NoBackground\n\t\t) ) {\n\t\t\tImGui::PushStyleColor( ImGuiCol_Text, ImVec4( 1.0f, 0.0f, 0.0f, 1.0f ) );\n\t\t\tImGui::TextWrapped( \"%s\", lm_gtr( \"$dbt0\" ) );\n\t\t\tImGui::PopStyleColor();\n\t\t\tImGui::TextWrapped( \"%s\", lm_gtr( \"$dbt1\" ) );\n\t\t\tImGui::Text( \"%s\", lm_gtr( \"$dbt2\" ) );\n\t\t\tImGui::End();\n\t\t}\n\t}\n\n#if defined( _DEBUG )\n\tstatic bool versionMenuState = false;\n\tstatic const int vW = 256, vH = 64;\n\tImGui::SetNextWindowSize( ImVec2( vW, vH ) );\n\tImGui::SetNextWindowPos( ImVec2( dW - ( vW + 2 ), dH - ( vH + 2 ) ), ImGuiCond_Always );\n\tImGui::SetNextWindowBgAlpha( 0.5f );\n\tif ( ImGui::Begin( \"VersionMenu\", &versionMenuState, ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoBackground | ImGuiWindowFlags_AlwaysAutoResize ) ) {\n\t\tImGui::Text( \"Version\\n%s\", ohw::GetApp()->GetVersionString() );\n\t\tImGui::End();\n\t}\n#endif\n\n\tmainConsole->Display();\n\n\t//ImGui::ShowDemoWindow();\n\n\tfor ( auto window = windows.begin(); window != windows.end(); ) {\n\t\tif ( ( *window )->GetStatus() ) {\n\t\t\t( *window )->Display();\n\t\t\t++window;\n\t\t\tcontinue;\n\t\t}\n\n\t\tdelete ( *window );\n\t\twindow = windows.erase( window );\n\t}\n}\n\nvoid ImGuiImpl_RegisterWindow( BaseWindow *window ) {\n\twindows.push_back( window );\n}\n\nbool ImGuiImpl_HandleEvent( const SDL_Event &event ) {\n\tImGuiIO &io = ImGui::GetIO();\n\n\tswitch ( event.type ) {\n\t\tcase SDL_KEYUP:\n\t\tcase SDL_KEYDOWN: {\n\t\t\tif ( !io.WantCaptureKeyboard ) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t// Always update if key-up; see\n\t\t\t// https://github.com/TalonBraveInfo/OpenHoW/issues/70#issuecomment-507377604\n\t\t\tint key = event.key.keysym.scancode;\n\t\t\tIM_ASSERT( key >= 0 && key < IM_ARRAYSIZE( io.KeysDown ) );\n\t\t\tio.KeysDown[ key ] = ( event.type == SDL_KEYDOWN );\n\t\t\tio.KeyShift = ( ( SDL_GetModState() & KMOD_SHIFT ) != 0 );\n\t\t\tio.KeyCtrl = ( ( SDL_GetModState() & KMOD_CTRL ) != 0 );\n\t\t\tio.KeyAlt = ( ( SDL_GetModState() & KMOD_ALT ) != 0 );\n\t\t\tio.KeySuper = ( ( SDL_GetModState() & KMOD_GUI ) != 0 );\n\t\t\tif ( event.type != SDL_KEYUP ) {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\tbreak;\n\t\t}\n\n\t\tcase SDL_TEXTINPUT: {\n\t\t\tif ( !io.WantCaptureKeyboard ) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tio.AddInputCharactersUTF8( event.text.text );\n\t\t\treturn true;\n\t\t}\n\n\t\tcase SDL_MOUSEWHEEL: {\n\t\t\tif ( !io.WantCaptureMouse ) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tif ( event.wheel.x > 0 ) {\n\t\t\t\tio.MouseWheelH += 1;\n\t\t\t} else if ( event.wheel.x < 0 ) {\n\t\t\t\tio.MouseWheelH -= 1;\n\t\t\t}\n\n\t\t\tif ( event.wheel.y > 0 ) {\n\t\t\t\tio.MouseWheel += 1;\n\t\t\t} else if ( event.wheel.y < 0 ) {\n\t\t\t\tio.MouseWheel -= 1;\n\t\t\t}\n\n\t\t\treturn true;\n\t\t}\n\n\t\tcase SDL_MOUSEBUTTONUP:\n\t\tcase SDL_MOUSEBUTTONDOWN: {\n\t\t\tif ( !io.WantCaptureMouse ) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tswitch ( event.button.button ) {\n\t\t\t\tcase SDL_BUTTON_LEFT: {\n\t\t\t\t\tio.MouseDown[ 0 ] = event.button.state;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase SDL_BUTTON_RIGHT: {\n\t\t\t\t\tio.MouseDown[ 1 ] = event.button.state;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase SDL_BUTTON_MIDDLE: {\n\t\t\t\t\tio.MouseDown[ 2 ] = event.button.state;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\treturn true;\n\t\t}\n\n\t\tcase SDL_MOUSEMOTION: {\n\t\t\tio.MousePos.x = event.motion.x;\n\t\t\tio.MousePos.y = event.motion.y;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn false;\n}\n"
  },
  {
    "path": "src/engine/imgui_layer.h",
    "content": "/* OpenHoW\n * Copyright (C) 2017-2020 TalonBrave.info and Others (see CONTRIBUTORS)\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#pragma once\n\n#ifdef __cplusplus\n\n#include <imgui.h>\n\n#endif\n\n/************************************************************/\n\nclass BaseWindow;\n\nvoid ImGuiImpl_Setup();\nvoid ImGuiImpl_Shutdown();\n\nvoid ImGuiImpl_SetupFrame();\nvoid ImGuiImpl_Draw();\n\nvoid ImGuiImpl_RegisterWindow( BaseWindow *window );\n\nbool ImGuiImpl_HandleEvent( const SDL_Event &event );\n\nvoid UI_DisplayDebugMenu();\n"
  },
  {
    "path": "src/engine/loaders/FacLoader.cpp",
    "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// Copyright © 2017-2022 TalonBrave.info and Others (see CONTRIBUTORS)\n\n#include \"App.h\"\n#include \"Utilities.h\"\n#include \"FacLoader.h\"\n\n/************************************************************/\n/* Fac Triangle/Quad Faces Format */\n\ntypedef struct FacQuad {\n\tint8_t uv_coords[8];\n\tuint16_t vertex_indices[4];\n\tuint16_t normal_indices[4];\n\tuint32_t texture_index;\n\tuint16_t unknown[4];\n} FacQuad;\n\nstatic FacQuad *Fac_LoadQuads( PLFile *filePtr, unsigned int numQuads ) {\n\tbool status = false;\n\tFacQuad *quads = ( FacQuad * ) u_alloc( numQuads, sizeof( FacQuad ), true );\n\tfor ( unsigned int i = 0; i < numQuads; ++i ) {\n\t\tfor ( unsigned int j = 0; j < 8; ++j ) {\n\t\t\tquads[ i ].uv_coords[ j ] = PlReadInt8( filePtr, &status );\n\t\t}\n\t\tfor ( unsigned int j = 0; j < 4; ++j ) {\n\t\t\tquads[ i ].vertex_indices[ j ] = PlReadInt16( filePtr, false, &status );\n\t\t}\n\t\tfor ( unsigned int j = 0; j < 4; ++j ) {\n\t\t\tquads[ i ].normal_indices[ j ] = PlReadInt16( filePtr, false, &status );\n\t\t}\n\t\tquads[ i ].texture_index = PlReadInt32( filePtr, false, &status );\n\t\tfor ( unsigned int j = 0; j < 4; ++j ) {\n\t\t\tquads[ i ].unknown[ j ] = PlReadInt16( filePtr, false, &status );\n\t\t}\n\t}\n\n\tif ( !status ) {\n\t\tPlFree( quads );\n\t}\n\n\treturn quads;\n}\n\nstatic FacTriangle *Fac_LoadTriangles( PLFile *filePtr, unsigned int numTriangles ) {\n\tbool status = false;\n\tFacTriangle *triangles = ( FacTriangle * ) u_alloc( numTriangles, sizeof( FacTriangle ), true );\n\tfor ( unsigned int i = 0; i < numTriangles; ++i ) {\n\t\tfor ( unsigned int j = 0; j < 6; ++j ) {\n\t\t\ttriangles[ i ].uv_coords[ j ] = PlReadInt8( filePtr, &status );\n\t\t}\n\t\tfor ( unsigned int j = 0; j < 3; ++j ) {\n\t\t\ttriangles[ i ].vertex_indices[ j ] = PlReadInt16( filePtr, false, &status );\n\t\t}\n\t\tfor ( unsigned int j = 0; j < 3; ++j ) {\n\t\t\ttriangles[ i ].normal_indices[ j ] = PlReadInt16( filePtr, false, &status );\n\t\t}\n\t\ttriangles[ i ].unknown0 = PlReadInt16( filePtr, false, &status );\n\t\ttriangles[ i ].texture_index = PlReadInt32( filePtr, false, &status );\n\t\tfor ( unsigned int j = 0; j < 4; ++j ) {\n\t\t\ttriangles[ i ].unknown1[ j ] = PlReadInt16( filePtr, false, &status );\n\t\t}\n\t}\n\n\tif ( !status ) {\n\t\tPlFree( triangles );\n\t}\n\n\treturn triangles;\n}\n\nFacHandle *Fac_LoadFile( const char *path ) {\n\tPLFile *filePtr = PlOpenFile( path, false );\n\tif ( filePtr == NULL ) {\n\t\tWarning( \"Failed to load Fac \\\"%s\\\", aborting!\\nPL: %s\\n\", path, PlGetError() );\n\t\treturn NULL;\n\t}\n\n\t//LogDebug( \"Opened Fac \\\"%s\\\"...\\n\", plGetFilePath( filePtr ) );\n\n\t/* 16 bytes of unknown data, just skip it for now */\n\tif ( !PlFileSeek( filePtr, 16, PL_SEEK_CUR ) ) {\n\t\tPlCloseFile( filePtr );\n\n\t\tWarning( \"Failed to find data in Fac \\\"%s\\\"!\\nPL: %s\\n\", path, PlGetError() );\n\t\treturn NULL;\n\t}\n\n\tbool status;\n\tuint32_t numTriangles = PlReadInt32( filePtr, false, &status );\n\tFacTriangle *triangles = Fac_LoadTriangles( filePtr, numTriangles );\n\tif ( triangles == NULL && numTriangles > 0 ) {\n\t\tWarning( \"Failed to read in triangles, \\\"%s\\\"!\\nPL: %s\\n\", path, PlGetError() );\n\t\tPlCloseFile( filePtr );\n\t\treturn NULL;\n\t}\n\n\tuint32_t numQuads = PlReadInt32( filePtr, false, &status );\n\tFacQuad *quads = Fac_LoadQuads( filePtr, numQuads );\n\tif ( quads == NULL && numQuads > 0 ) {\n\t\tWarning( \"Failed to read in quads, \\\"%s\\\"!\\nPL: %s\\n\", path, PlGetError() );\n\t\tPlFree( triangles );\n\t\tPlCloseFile( filePtr );\n\t\treturn NULL;\n\t}\n\n\tif ( numQuads == 0 && numTriangles == 0 ) {\n\t\tWarning( \"Fac \\\"%s\\\" contains no quads or triangles!\\n\", path );\n\t}\n\n\t// check for textures table\n\tuint8_t num_textures = PlReadInt8( filePtr, &status );\n\tFacTextureIndex *texture_table = NULL;\n\tif ( num_textures > 0 ) {\n\t\ttexture_table = ( FacTextureIndex * ) u_alloc( num_textures, sizeof( FacTextureIndex ), true );\n\t\tfor ( unsigned int i = 0; i < num_textures; ++i ) {\n\t\t\tPlReadFile( filePtr, texture_table[ i ].name, 1, sizeof( texture_table[ i ].name ) );\n\t\t}\n\t}\n\n\tPlCloseFile( filePtr );\n\n\tFacHandle *handle = ( FacHandle * ) u_alloc( 1, sizeof( FacHandle ), true );\n\thandle->num_triangles = numTriangles + ( numQuads * 2 );\n\thandle->triangles = ( FacTriangle * ) u_alloc( handle->num_triangles, sizeof( FacTriangle ), true );\n\n\tfor ( unsigned int i = 0; i < numTriangles; ++i ) {\n\t\thandle->triangles[ i ].texture_index = triangles[ i ].texture_index;\n\t\tfor ( unsigned int j = 0, u = 0; j < 3; j++, u += 2 ) {\n\t\t\thandle->triangles[ i ].vertex_indices[ j ] = triangles[ i ].vertex_indices[ j ];\n\t\t\thandle->triangles[ i ].normal_indices[ j ] = triangles[ i ].normal_indices[ j ];\n\t\t\thandle->triangles[ i ].uv_coords[ u ] = triangles[ i ].uv_coords[ u ];\n\t\t\thandle->triangles[ i ].uv_coords[ u + 1 ] = triangles[ i ].uv_coords[ u + 1 ];\n\t\t}\n\t}\n\n\tfor ( unsigned int i = 0, tri = numTriangles; i < numQuads; ++i ) {\n\t\tint quad_to_tri[2][3] = {\n\t\t\t\t{ 0, 1, 2 },\n\t\t\t\t{ 2, 3, 0 },\n\t\t};\n\n\t\tfor ( int q = 0; q < 2; ++q, ++tri ) {\n\t\t\tint *q2t = quad_to_tri[ q ];\n\n\t\t\thandle->triangles[ tri ].texture_index = quads[ i ].texture_index;\n\t\t\tfor ( unsigned int j = 0; j < 3; j++ ) {\n\t\t\t\thandle->triangles[ tri ].vertex_indices[ j ] = quads[ i ].vertex_indices[ q2t[ j ] ];\n\t\t\t\thandle->triangles[ tri ].normal_indices[ j ] = quads[ i ].normal_indices[ q2t[ j ] ];\n\t\t\t\t// todo\n\t\t\t\thandle->triangles[ tri ].uv_coords[ j * 2 ] = quads[ i ].uv_coords[ q2t[ j ] * 2 ];\n\t\t\t\thandle->triangles[ tri ].uv_coords[ j * 2 + 1 ] = quads[ i ].uv_coords[ q2t[ j ] * 2 + 1 ];\n\t\t\t}\n\t\t}\n\t}\n\n\tif ( texture_table != NULL ) {\n\t\thandle->texture_table = texture_table;\n\t\thandle->texture_table_size = num_textures;\n\t}\n\n\treturn handle;\n}\n\nvoid Fac_WriteFile( FacHandle *handle, const char *path ) {\n\tFILE *fp = fopen( path, \"wb\" );\n\tif ( fp == NULL ) {\n\t\tWarning( \"Failed to open, \\\"%s\\\"!\\n\", path );\n\t\treturn;\n\t}\n\n\t// 16 bytes of unknown data, just skip it for now\n\tchar empty[16];\n\tmemset( empty, 0, sizeof( empty ) );\n\tfwrite( empty, sizeof( empty ), 1, fp );\n\n\t// write out the triangle data\n\tfwrite( &handle->num_triangles, sizeof( uint32_t ), 1, fp );\n\tstruct __attribute__((packed)) {\n\t\tint8_t uv_coords[6];\n\t\tuint16_t vertex_indices[3];\n\t\tuint16_t normal_indices[3];\n\t\tuint16_t unknown0;\n\t\tuint32_t texture_index;\n\t\tuint16_t unknown1[4];\n\t} triangles[handle->num_triangles];\n\tmemset( triangles, 0, sizeof( *triangles ) * handle->num_triangles );\n\tfor ( unsigned int i = 0; i < handle->num_triangles; ++i ) {\n\t\ttriangles[ i ].texture_index = handle->triangles[ i ].texture_index;\n\t\tfor ( unsigned int j = 0; j < 3; ++j ) {\n\t\t\ttriangles[ i ].vertex_indices[ j ] = handle->triangles[ i ].vertex_indices[ j ];\n\t\t\ttriangles[ i ].normal_indices[ j ] = handle->triangles[ i ].normal_indices[ j ];\n\t\t}\n\t\tfor ( unsigned int j = 0; j < 6; ++j ) {\n\t\t\ttriangles[ i ].uv_coords[ j ] = handle->triangles[ i ].uv_coords[ j ];\n\t\t}\n\t}\n\tfwrite( triangles, sizeof( *triangles ), handle->num_triangles, fp );\n\n\t// we won't write any quads, so just mark it as 0\n\tuint32_t quads = 0;\n\tfwrite( &quads, sizeof( uint32_t ), 1, fp );\n\n\t// now write the string table\n\tif ( handle->texture_table_size > 0 ) {\n\t\tfwrite( &handle->texture_table_size, sizeof( uint8_t ), 1, fp );\n\t\tfor ( unsigned int i = 0; i < handle->texture_table_size; ++i ) {\n\t\t\tfwrite( handle->texture_table[ i ].name, 1, 16, fp );\n\t\t}\n\t}\n\n\t// Done!\n\tu_fclose( fp );\n}\n\nvoid Fac_DestroyHandle( FacHandle *handle ) {\n\tif ( handle == NULL ) {\n\t\treturn;\n\t}\n\n\tPlFree( handle->triangles );\n\tPlFree( handle->texture_table );\n\tPlFree( handle );\n}\n"
  },
  {
    "path": "src/engine/loaders/FacLoader.h",
    "content": "/* OpenHoW\n * Copyright (C) 2017-2020 TalonBrave.info and Others (see CONTRIBUTORS)\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#pragma once\n\nPL_EXTERN_C\n\ntypedef struct FacTriangle {\n\tint8_t uv_coords[6];\n\tuint16_t vertex_indices[3];\n\tuint16_t normal_indices[3];\n\tuint16_t unknown0;\n\tuint32_t texture_index;\n\tuint16_t unknown1[4];\n} FacTriangle;\n\ntypedef struct FacTextureIndex {\n\tchar name[16];\n} FacTextureIndex;\n\ntypedef struct FacHandle {\n\tFacTriangle *triangles;\n\tunsigned int num_triangles;\n\n\tstruct FacTextureIndex *texture_table;\n\tunsigned int texture_table_size;\n} FacHandle;\n\nFacHandle *Fac_LoadFile( const char *path );\nvoid Fac_WriteFile( FacHandle *handle, const char *path );\nvoid Fac_DestroyHandle( FacHandle *handle );\n\nPL_EXTERN_C_END\n"
  },
  {
    "path": "src/engine/loaders/HirLoader.cpp",
    "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// Copyright © 2017-2022 TalonBrave.info and Others (see CONTRIBUTORS)\n\n#include \"App.h\"\n#include \"Loaders.h\"\n\n/************************************************************/\n/* Hir Skeleton Format */\n\nHirHandle *Hir_LoadFile( const char *path ) {\n\tPLFile *file = PlOpenFile( path, false );\n\tif ( file == nullptr ) {\n\t\tWarning( \"Failed to load \\\"%s\\\", aborting!\\n\", path );\n\t\treturn nullptr;\n\t}\n\n\tsize_t hir_size = PlGetFileSize( file );\n\tif ( hir_size == 0 ) {\n\t\tPlCloseFile( file );\n\t\tWarning( \"Unexpected Hir size in \\\"%s\\\", aborting (%s)!\\n\", path, PlGetError() );\n\t\treturn nullptr;\n\t}\n\n\ttypedef struct __attribute__((packed)) HirBone {\n\t\tint32_t parent;\n\t\tint16_t coords[3];\n\t\tint8_t unknown[10];\n\t} HirBone;\n\n\tauto num_bones = ( unsigned int ) ( hir_size / sizeof( HirBone ) );\n\tHirBone bones[num_bones];\n\tunsigned int rnum_bones = PlReadFile( file, bones, sizeof( HirBone ), num_bones );\n\tPlCloseFile( file );\n\n\tif ( rnum_bones != num_bones ) {\n\t\tWarning( \"Failed to read in all bones, %d/%d, aborting!\\n\", rnum_bones, num_bones );\n\t\treturn nullptr;\n\t}\n\n\t/* for debugging */\n\tstatic const char *bone_names[static_cast<int>(HirSkeletonBone::MAX_BONES)] = {\n\t\t\t\"Pelvis\",\n\t\t\t\"Spine\",\n\t\t\t\"Head\",\n\t\t\t\"UpperArm.L\", \"LowerArm.L\", \"Hand.L\",\n\t\t\t\"UpperArm.R\", \"LowerArm.R\", \"Hand.R\",\n\t\t\t\"UpperLeg.L\", \"LowerLeg.L\", \"Foot.L\",\n\t\t\t\"UpperLeg.R\", \"LowerLeg.R\", \"Foot.R\",\n\t};\n\n\t/* in the long term, we won't have this here, we'll probably extend the format\n\t * to include the names of each bone (.skeleton format?) */\n\tif ( static_cast<HirSkeletonBone>(num_bones) >= HirSkeletonBone::MAX_BONES ) {\n\t\tWarning( \"Invalid number of bones, %d/%d, aborting!\\n\", num_bones, HirSkeletonBone::MAX_BONES );\n\t\treturn nullptr;\n\t}\n\n\tauto *handle = static_cast<HirHandle *>(u_alloc( 1, sizeof( HirHandle ), true ));\n\thandle->bones = static_cast<PLMModelBone *>(u_alloc( num_bones, sizeof( PLMModelBone ), true ));\n\tfor ( unsigned int i = 0; i < num_bones; ++i ) {\n\t\thandle->bones[ i ].position = hei::Vector3( bones[ i ].coords[ 0 ], bones[ i ].coords[ 1 ],\n\t\t                                            bones[ i ].coords[ 2 ] );\n\t\thandle->bones[ i ].parent = bones[ i ].parent;\n\t\tstrcpy( handle->bones[ i ].name, bone_names[ i ] );\n\t}\n\treturn handle;\n}\n\nvoid Hir_DestroyHandle( HirHandle *handle ) {\n\tif ( handle == nullptr ) {\n\t\treturn;\n\t}\n\n\tPlFree( handle->bones );\n\tPlFree( handle );\n}\n"
  },
  {
    "path": "src/engine/loaders/Loaders.h",
    "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// Copyright © 2017-2022 TalonBrave.info and Others (see CONTRIBUTORS)\n\n#pragma once\n\n/* Hogs of War file formats\n * -----------------------------------\n * BIN : Audio/Model/Texture data\n * DAT : Audio data\n * MAM : Mangled texture / model package\n * MAD : Texture / model package            (done)\n * MTM : Mangled model texture package\n * MTD : Texture / model package            (done)\n * MMM : Mangled model package\n * MGL : Mangled texture data\n * MIN : PSX model data\n * FAC : Model faces                        (done)\n * VTX : Model vertices                     (done)\n * NO2 : Model normals                      (done)\n * HIR : Model skeleton                     (done)\n * POM : Mangled map object data\n * POG : Map object data                    (done)\n * PTM : Mangled map textures package\n * PTG : Map textures package               (done)\n * PMM : Mangled terrain data\n * PMG : Terrain data                       (done)\n * OFF : File offset sizes                  (done)\n */\n\n#include \"FacLoader.h\"\n#include \"VtxLoader.h\"\n#include \"No2Loader.h\"\n\ntypedef enum HirSkeletonBone {\n\tPELVIS = 0,\n\tSPINE,\n\tHEAD,\n\n\tUPPER_ARM_L,\n\tLOWER_ARM_L,\n\tHAND_L,\n\n\tUPPER_ARM_R,\n\tLOWER_ARM_R,\n\tHAND_R,\n\n\tUPPER_LEG_L,\n\tLOWER_LEG_L,\n\tFOOT_L,\n\n\tUPPER_LEG_R,\n\tLOWER_LEG_R,\n\tFOOT_R,\n\n\tMAX_BONES\n} HirSkeletonBone;\n\ntypedef struct HirHandle {\n\tPLMModelBone *bones;\n\tunsigned int num_bones;\n} HirHandle;\nHirHandle *Hir_LoadFile( const char *path );\nvoid Hir_DestroyHandle( HirHandle *handle );\n\ntypedef struct MinHandle {\n\tunsigned int blah;\n} MinHandle;\nMinHandle *Min_LoadFile( const char *path );\n"
  },
  {
    "path": "src/engine/loaders/MinLoader.cpp",
    "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// Copyright © 2017-2022 TalonBrave.info and Others (see CONTRIBUTORS)\n\n#include \"App.h\"\n#include \"loaders/Loaders.h\"\n\n/************************************************************/\n/* PSX Min Model Format */\n\nMinHandle *Min_LoadFile( const char *path ) {\n\tPLFile *fp = PlOpenFile( path, false );\n\tif ( fp == NULL ) {\n\t\tWarning( \"Failed to load Min \\\"%s\\\", aborting!\\n\", path );\n\t\treturn NULL;\n\t}\n\n\tPlFileSeek( fp, 16, PL_SEEK_CUR );\n\n\tuint32_t num_triangles;\n\tif ( PlReadFile( fp, &num_triangles, sizeof( uint32_t ), 1 ) != 1 ) {\n\t\tWarning( \"Failed to get number of triangles, \\\"%s\\\"!\\n\", path );\n\t}\n\n\tstruct __attribute__((packed)) {\n#if 0\n\t\tint8_t      uv_coords[6];\n\t\tuint16_t    vertex_indices[3];\n\t\tuint16_t    normal_indices[3];\n\t\tuint16_t    unknown0;\n\t\tuint32_t    texture_index;\n\t\tuint16_t    unknown1[4];\n#else\n\t\tchar u0[24];\n#endif\n\t} triangles[num_triangles];\n\tstatic_assert( sizeof( *triangles ) == 24, \"invalid struct size\" );\n\tif ( PlReadFile( fp, triangles, sizeof( *triangles ), num_triangles ) != num_triangles ) {\n\t\tPlCloseFile( fp );\n\t\tWarning( \"Failed to get %u triangles, \\\"%s\\\", aborting!\\n\", num_triangles, path );\n\t\treturn NULL;\n\t}\n\t// todo\n\treturn NULL;\n}\n"
  },
  {
    "path": "src/engine/loaders/No2Loader.cpp",
    "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// Copyright © 2017-2022 TalonBrave.info and Others (see CONTRIBUTORS)\n\n#include \"App.h\"\n#include \"Utilities.h\"\n#include \"No2Loader.h\"\n\n/************************************************************/\n/* No2 Normals Format */\n\n/**\n * @brief Loads in vertex normal data\n * @param path Path to the NO2 file\n * @param vertex_data Pointer to an existing VtxHandle which will be filled with normal data\n * @return Returns vertex_data on success, null on fail\n */\nNo2Handle *No2_LoadFile( const char *path ) {\n\tPLFile *fp = PlOpenFile( path, false );\n\tif ( fp == NULL ) {\n\t\tWarning( \"Failed to load no2 \\\"%s\\\"!\\n\", path );\n\t\treturn NULL;\n\t}\n\n\ttypedef struct __attribute__((packed)) No2Coord {\n\t\tfloat v[3];\n\t\tfloat bone_index;\n\t} No2Coord;\n\n\tunsigned int numNormals = ( unsigned int ) ( PlGetFileSize( fp ) / sizeof( No2Coord ) );\n\tNo2Coord *normals = ( No2Coord * ) ohw::GetApp()->CAlloc( numNormals, sizeof( No2Coord ), true );\n\tunsigned int numReadNormals = PlReadFile( fp, normals, sizeof( No2Coord ), numNormals );\n\n\tPlCloseFile( fp );\n\n\tif ( numReadNormals != numNormals ) {\n\t\tfree( normals );\n\t\tWarning( \"Failed to read in all normals from \\\"%s\\\"!\\n\", path );\n\t\treturn NULL;\n\t}\n\n\tNo2Handle *handle = ( No2Handle * ) ohw::GetApp()->MAlloc( sizeof( No2Handle ), true );\n\thandle->numNormals = numNormals;\n\thandle->normals = ( PLVector3 * ) ohw::GetApp()->MAlloc( sizeof( PLVector3 ) * handle->numNormals, true );\n\tfor ( unsigned int i = 0; i < numNormals; ++i ) {\n\t\thandle->normals[ i ].x = normals->v[ 0 ];\n\t\thandle->normals[ i ].y = normals->v[ 1 ];\n\t\thandle->normals[ i ].z = normals->v[ 2 ];\n\t}\n\n\tPlFree( normals );\n\n\treturn handle;\n}\n\nvoid No2_DestroyHandle( No2Handle *handle ) {\n\tPlFree( handle->normals );\n\tPlFree( handle );\n}\n"
  },
  {
    "path": "src/engine/loaders/No2Loader.h",
    "content": "/* OpenHoW\n * Copyright (C) 2017-2020 TalonBrave.info and Others (see CONTRIBUTORS)\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#pragma once\n\nPL_EXTERN_C\n\ntypedef struct No2Handle {\n\tPLVector3 *normals;\n\tunsigned int numNormals;\n} No2Handle;\n\nNo2Handle *No2_LoadFile( const char *path );\nvoid No2_DestroyHandle( No2Handle *handle );\n\nPL_EXTERN_C_END\n"
  },
  {
    "path": "src/engine/loaders/VtxLoader.cpp",
    "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// Copyright © 2017-2022 TalonBrave.info and Others (see CONTRIBUTORS)\n\n#include \"App.h\"\n#include \"Utilities.h\"\n#include \"VtxLoader.h\"\n\n/************************************************************/\n/* Vtx Vertex Format */\n\nVtxHandle *Vtx_LoadFile( const char *path ) {\n\tPLFile *vtx_file = PlOpenFile( path, false );\n\tif ( vtx_file == NULL ) {\n\t\tWarning( \"Failed to load Vtx \\\"%s\\\", aborting!\\n\", path );\n\t\treturn NULL;\n\t}\n\n\t/* load in the vertices */\n\n\ttypedef struct __attribute__((packed)) VtxCoord {\n\t\tint16_t v[3];\n\t\tuint16_t bone_index;\n\t} VtxCoord;\n\tunsigned int num_vertices = ( unsigned int ) ( PlGetFileSize( vtx_file ) / sizeof( VtxCoord ) );\n\tif ( num_vertices >= VTX_MAX_VERTICES ) {\n\t\tPlCloseFile( vtx_file );\n\t\tWarning( \"Invalid number of vertices in \\\"%s\\\" (%d/%d)!\\n\", path, num_vertices, VTX_MAX_VERTICES );\n\t\treturn NULL;\n\t}\n\n\tVtxCoord vertices[num_vertices];\n\tunsigned int rnum_vertices = PlReadFile( vtx_file, vertices, sizeof( VtxCoord ), num_vertices );\n\tPlCloseFile( vtx_file );\n\n\tif ( num_vertices == 0 ) {\n\t\tWarning( \"No vertices found in Vtx \\\"%s\\\"!\\n\", path );\n\t\treturn NULL;\n\t}\n\n\tif ( rnum_vertices != num_vertices ) {\n\t\tWarning( \"Failed to read in all vertices from \\\"%s\\\", aborting!\\n\", path );\n\t\treturn NULL;\n\t}\n\n\tVtxHandle *handle = ( VtxHandle * ) ohw::GetApp()->CAlloc( 1, sizeof( VtxHandle ), true );\n\thandle->vertices = ( PLGVertex * ) ohw::GetApp()->CAlloc( num_vertices, sizeof( PLGVertex ), true );\n\thandle->num_vertices = num_vertices;\n\tfor ( unsigned int i = 0; i < num_vertices; ++i ) {\n\t\thandle->vertices[ i ].position = hei::Vector3( vertices[ i ].v[ 0 ], vertices[ i ].v[ 1 ], vertices[ i ].v[ 2 ] );\n\t\t//handle->vertices[ i ].bone_index = vertices[ i ].bone_index;\n\t\thandle->vertices[ i ].colour = PL_COLOUR_WHITE;\n\t}\n\treturn handle;\n}\n\nvoid Vtx_DestroyHandle( VtxHandle *handle ) {\n\tif ( handle == NULL ) {\n\t\treturn;\n\t}\n\n\tPlFree( handle->vertices );\n\tPlFree( handle );\n}\n"
  },
  {
    "path": "src/engine/loaders/VtxLoader.h",
    "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// Copyright © 2017-2022 TalonBrave.info and Others (see CONTRIBUTORS)\n\n#pragma once\n\n#define VTX_MAX_VERTICES  4096\n\nPL_EXTERN_C\n\ntypedef struct VtxHandle {\n\tstruct PLGVertex *vertices;\n\tunsigned int num_vertices;\n} VtxHandle;\n\nVtxHandle *Vtx_LoadFile( const char *path );\nvoid Vtx_DestroyHandle( VtxHandle *handle );\n\nPL_EXTERN_C_END\n"
  },
  {
    "path": "src/engine/loaders/WaveFrontReader.h",
    "content": "//--------------------------------------------------------------------------------------\n// File: WaveFrontReader.h\n//\n// Code for loading basic mesh data from a WaveFront OBJ file\n//\n// http://en.wikipedia.org/wiki/Wavefront_.obj_file\n//\n// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\n//\n// http://go.microsoft.com/fwlink/?LinkID=324981\n//--------------------------------------------------------------------------------------\n\n// Modified by Mark Sowden <markelswo@gmail.com> for OpenHoW\n\n#pragma once\n\n#include <unordered_map>\n\n#include <plcore/pl_math.h>\n#include <plcore/pl_console.h>\n#include <plcore/pl_filesystem.h>\n\nclass WaveFrontReader {\npublic:\n    typedef unsigned int index_t;\n\n    WaveFrontReader() noexcept : hasNormals(false), hasTexcoords(false) {}\n\n    bool Load(const std::string &szFilePath, bool ccw = true) {\n        Clear();\n\n        static const size_t MAX_POLY = 64;\n\n        // For now just read the whole thing into memory...\n        PLFile *filePtr = PlOpenFile( szFilePath.c_str(), true );\n        if ( filePtr == nullptr ) {\n\t\t\tWarning( \"Failed to open \\\"%s\\\"!\\n\", szFilePath.c_str());\n\t\t\treturn false;\n        }\n\n        std::stringstream InFile;\n        InFile << PlGetFileData( filePtr );\n        PlCloseFile( filePtr );\n\n        name = szFilePath;\n\n        size_t cpos = name.find_last_of(\"\\\\/\");\n        if(std::string::npos != cpos) {\n            name.erase(0, cpos + 1);\n        }\n\n        cpos = name.find_last_of('.');\n        if(std::string::npos != cpos) {\n            name.erase(cpos);\n        }\n\n        std::vector<PLVector3> positions;\n        std::vector<PLVector3> normals;\n        std::vector<PLVector2> texCoords;\n\n        VertexCache vertexCache;\n\n        Material defmat;\n        defmat.strName = \"default\";\n\n        materials.emplace_back(defmat);\n\n        uint32_t curSubset = 0;\n\n        std::string strMaterialFilename;\n        for (;;) {\n            std::string strCommand;\n            InFile >> strCommand;\n            if (!InFile) {\n                break;\n            }\n\n            if (*strCommand.c_str() == '#') {\n                // Comment\n            } else if (strCommand == \"o\") {\n                // Object name ignored\n            } else if (strCommand == \"g\") {\n                // Group name ignored\n            } else if (strCommand == \"s\") {\n                // Smoothing group ignored\n            } else if (strCommand == \"v\") {\n                // Vertex Position\n                float x, y, z;\n                InFile >> x >> y >> z;\n                positions.emplace_back(hei::Vector3(x, y, z));\n            } else if (strCommand == \"vt\") {\n                // Vertex TexCoord\n                float u, v;\n                InFile >> u >> v;\n                texCoords.emplace_back(hei::Vector2(u, 1.0f - v));\n\n                hasTexcoords = true;\n            } else if (strCommand == \"vn\") {\n                // Vertex Normal\n                float x, y, z;\n                InFile >> x >> y >> z;\n                normals.emplace_back(hei::Vector3(x, y, z));\n\n                hasNormals = true;\n            } else if (strCommand == \"f\") {\n                // Face\n                int iPosition, iTexCoord, iNormal;\n                PLGVertex vertex;\n\n                uint32_t faceIndex[MAX_POLY];\n                size_t iFace = 0;\n                for (;;) {\n                    if (iFace >= MAX_POLY) {\n                        // Too many polygon verts for the reader\n                        Warning( \"Too many polygon vertices for the reader (%dvs%d)!\\n\", iFace, MAX_POLY);\n                        return false;\n                    }\n\n                    InFile >> iPosition;\n\n                    uint32_t vertexIndex = 0;\n                    if (!iPosition) {\n                        // 0 is not allowed for index\n                        Warning( \"0 is not allowed for index!\\n\");\n                        return false;\n                    } else if (iPosition < 0) {\n                        // Negative values are relative indices\n                        vertexIndex = uint32_t(positions.size() + iPosition);\n                    } else {\n                        // OBJ format uses 1-based arrays\n                        vertexIndex = iPosition - 1;\n                    }\n\n                    if (vertexIndex >= positions.size())\n                        return false;\n\n                    vertex.position = positions[vertexIndex];\n\n                    if ('/' == InFile.peek()) {\n                        InFile.ignore();\n\n                        if ('/' != InFile.peek()) {\n                            // Optional texture coordinate\n                            InFile >> iTexCoord;\n\n                            uint32_t coordIndex = 0;\n                            if (!iTexCoord) {\n                                // 0 is not allowed for index\n                                return false;\n                            } else if (iTexCoord < 0) {\n                                // Negative values are relative indices\n                                coordIndex = uint32_t(texCoords.size() + iTexCoord);\n                            } else {\n                                // OBJ format uses 1-based arrays\n                                coordIndex = iTexCoord - 1;\n                            }\n\n                            if (coordIndex >= texCoords.size())\n                                return false;\n\n                            vertex.st[0] = texCoords[coordIndex];\n                        }\n\n                        if ('/' == InFile.peek()) {\n                            InFile.ignore();\n\n                            // Optional vertex normal\n                            InFile >> iNormal;\n\n                            uint32_t normIndex = 0;\n                            if (!iNormal) {\n                                // 0 is not allowed for index\n                                return false;\n                            } else if (iNormal < 0) {\n                                // Negative values are relative indices\n                                normIndex = uint32_t(normals.size() + iNormal);\n                            } else {\n                                // OBJ format uses 1-based arrays\n                                normIndex = iNormal - 1;\n                            }\n\n                            if (normIndex >= normals.size()) {\n                                // Some Objs we tested provide normal indices, but no normals\n                                // ... GREAT!\n                                Warning( \"Out of range normal, ignoring!\\n\");\n                                vertex.normal = {0, 0, 0};\n                            } else {\n                                vertex.normal = normals[normIndex];\n                            }\n                        }\n                    }\n\n                    // If a duplicate vertex doesn't exist, add this vertex to the Vertices\n                    // list. Store the index in the Indices array. The Vertices and Indices\n                    // lists will eventually become the Vertex Buffer and Index Buffer for\n                    // the mesh.\n                    uint32_t index = AddVertex(vertexIndex, &vertex, vertexCache);\n                    if (index == uint32_t(-1)) {\n                        return false;\n                    }\n\n                    if (index >= 0xFFFFFFFF) {\n                        // Too many indices for 32-bit IB!\n                        return false;\n                    }\n\n                    faceIndex[iFace] = index;\n                    ++iFace;\n\n                    // Check for more face data or end of the face statement\n                    bool faceEnd = false;\n                    for (;;) {\n                        wchar_t p = InFile.peek();\n                        if ('\\n' == p || !InFile) {\n                            faceEnd = true;\n                            break;\n                        } else if (isdigit(p) || p == '-' || p == '+')\n                            break;\n\n                        InFile.ignore();\n                    }\n\n                    if (faceEnd)\n                        break;\n                }\n\n                if (iFace < 3) {\n                    // Need at least 3 points to form a triangle\n                    Warning( \"Invalid number of points to form a triangle (%dvs3)\\n\", iFace);\n                    return false;\n                }\n\n                // Convert polygons to triangles\n                uint32_t i0 = faceIndex[0];\n                uint32_t i1 = faceIndex[1];\n\n                for (size_t j = 2; j < iFace; ++j) {\n                    uint32_t index = faceIndex[j];\n                    indices.emplace_back(static_cast<index_t>(i0));\n                    if (ccw) {\n                        indices.emplace_back(static_cast<index_t>(i1));\n                        indices.emplace_back(static_cast<index_t>(index));\n                    } else {\n                        indices.emplace_back(static_cast<index_t>(index));\n                        indices.emplace_back(static_cast<index_t>(i1));\n                    }\n\n                    attributes.emplace_back(curSubset);\n\n                    i1 = index;\n                }\n\n                assert(attributes.size() * 3 == indices.size());\n            } else if (strCommand == \"mtllib\") {\n                // Material library\n                InFile >> strMaterialFilename;\n            } else if (strCommand == \"usemtl\") {\n                // Material\n                char strName[PL_SYSTEM_MAX_PATH] = {};\n                InFile >> strName;\n\n                bool bFound = false;\n                uint32_t count = 0;\n                for (auto it = materials.cbegin(); it != materials.cend(); ++it, ++count) {\n                    if (it->strName == strName) {\n                        bFound = true;\n                        curSubset = count;\n                        break;\n                    }\n                }\n\n                if (!bFound) {\n                    Material mat;\n                    curSubset = static_cast<uint32_t>(materials.size());\n                    mat.strName = strName;\n                    materials.emplace_back(mat);\n                }\n            } else {\n                Warning(\"Unrecognised command in Obj \\\"%s\\\"!\\n\", szFilePath.c_str());\n            }\n\n            InFile.ignore(1000, L'\\n');\n        }\n\n        if (positions.empty()) {\n            return false;\n        }\n\n        // If an associated material file was found, read that in as well.\n        if (!strMaterialFilename.empty()) {\n            const std::string& strMaterialFilePath = szFilePath.substr(0, szFilePath.find_last_of(\"\\\\/\")) +\n                    \"/\" + strMaterialFilename;\n            if(!LoadMTL(strMaterialFilePath)) {\n                Warning( \"Failed to load material, \\\"%s\\\"!\\n\", strMaterialFilename.c_str());\n            }\n        }\n\n        return true;\n    }\n\n    bool LoadMTL(const std::string &szFilePath) {\n        // Assumes MTL is in CWD along with OBJ\n        PLFile *filePtr = PlOpenFile( szFilePath.c_str(), true );\n        if ( filePtr == nullptr ) {\n\t\t\tWarning( \"Failed to open material, \\\"%s\\\"!\\n\", szFilePath.c_str());\n\t\t\treturn false;\n        }\n\n\t\tstd::stringstream InFile;\n\t\tInFile << PlGetFileData( filePtr );\n\t\tPlCloseFile( filePtr );\n\n        auto curMaterial = materials.end();\n\n        for (;;) {\n            std::string strCommand;\n            InFile >> strCommand;\n            if (!InFile) {\n                break;\n            }\n\n            if (strCommand == \"newmtl\") {\n                // Switching active materials\n                char strName[PL_SYSTEM_MAX_PATH] = {};\n                InFile >> strName;\n\n                curMaterial = materials.end();\n                for (auto it = materials.begin(); it != materials.end(); ++it) {\n                    if (it->strName == strName) {\n                        curMaterial = it;\n                        break;\n                    }\n                }\n            }\n\n            // The rest of the commands rely on an active material\n            if (curMaterial == materials.end())\n                continue;\n\n            if (strCommand == \"#\") {\n                // Comment\n            } else if (strCommand == \"Ka\") {\n                // Ambient color\n                float r, g, b;\n                InFile >> r >> g >> b;\n                curMaterial->vAmbient = (r, g, b);\n            } else if (strCommand == \"Kd\") {\n                // Diffuse color\n                float r, g, b;\n                InFile >> r >> g >> b;\n                curMaterial->vDiffuse = (r, g, b);\n            } else if (strCommand == \"Ks\") {\n                // Specular color\n                float r, g, b;\n                InFile >> r >> g >> b;\n                curMaterial->vSpecular = (r, g, b);\n            } else if (strCommand == \"Ke\") {\n                // Emissive color\n                float r, g, b;\n                InFile >> r >> g >> b;\n                curMaterial->vEmissive = (r, g, b);\n                if (r > 0.f || g > 0.f || b > 0.f) {\n                    curMaterial->bEmissive = true;\n                }\n            } else if (strCommand == \"d\") {\n                // Alpha\n                float alpha;\n                InFile >> alpha;\n                curMaterial->fAlpha = std::min(1.f, std::max(0.f, alpha));\n            } else if (strCommand == \"Tr\") {\n                // Transparency (inverse of alpha)\n                float invAlpha;\n                InFile >> invAlpha;\n                curMaterial->fAlpha = std::min(1.f, std::max(0.f, 1.f - invAlpha));\n            } else if (strCommand == \"Ns\") {\n                // Shininess\n                int nShininess;\n                InFile >> nShininess;\n                curMaterial->nShininess = nShininess;\n            } else if (strCommand == \"illum\") {\n                // Specular on/off\n                int illumination;\n                InFile >> illumination;\n                curMaterial->bSpecular = (illumination == 2);\n            } else if (strCommand == \"map_Kd\" || strCommand == \"map_Ka\") {\n                // Diffuse texture\n                curMaterial->strTexture = szFilePath.substr(0, szFilePath.find_last_of(\"\\\\/\")) +\n                                          \"/\" + LoadTexturePath(InFile);\n            } else if (strCommand == \"map_Ks\") {\n                // Specular texture\n                curMaterial->strSpecularTexture = LoadTexturePath(InFile);\n            } else if (strCommand == \"map_Kn\" || strCommand == \"norm\") {\n                // Normal texture\n                curMaterial->strNormalTexture = LoadTexturePath(InFile);\n            } else if (strCommand == \"map_Ke\" || strCommand == \"map_emissive\") {\n                // Emissive texture\n                curMaterial->strEmissiveTexture = LoadTexturePath(InFile);\n                curMaterial->bEmissive = true;\n            } else if (strCommand == \"map_RMA\" || strCommand == \"map_ORM\") {\n                // RMA texture\n                curMaterial->strRMATexture = LoadTexturePath(InFile);\n            } else {\n                // Unimplemented or unrecognized command\n            }\n\n            InFile.ignore(1000, L'\\n');\n        }\n\n        return true;\n    }\n\n    void Clear() {\n        vertices.clear();\n        indices.clear();\n        attributes.clear();\n        materials.clear();\n        name.clear();\n        hasNormals = false;\n        hasTexcoords = false;\n    }\n\n    struct Material {\n        hei::Vector3 vAmbient;\n        hei::Vector3 vDiffuse;\n        hei::Vector3 vSpecular;\n        hei::Vector3 vEmissive;\n        uint32_t nShininess;\n        float fAlpha;\n\n        bool bSpecular;\n        bool bEmissive;\n\n        std::string strName;\n        std::string strTexture;\n        std::string strNormalTexture;\n        std::string strSpecularTexture;\n        std::string strEmissiveTexture;\n        std::string strRMATexture;\n\n        Material() noexcept :\n                vAmbient(0.2f, 0.2f, 0.2f),\n                vDiffuse(0.8f, 0.8f, 0.8f),\n                vSpecular(1.0f, 1.0f, 1.0f),\n                vEmissive(0.f, 0.f, 0.f),\n                nShininess(0),\n                fAlpha(1.f),\n                bSpecular(false),\n                bEmissive(false),\n                strName{},\n                strTexture{},\n                strNormalTexture{},\n                strSpecularTexture{},\n                strEmissiveTexture{},\n                strRMATexture{} {\n        }\n    };\n\n    std::vector<PLGVertex> vertices;\n    std::vector<index_t> indices;\n    std::vector<uint32_t> attributes;\n    std::vector<Material> materials;\n\n    std::string name;\n    bool hasNormals;\n    bool hasTexcoords;\n\nprivate:\n    typedef std::unordered_multimap<uint32_t, uint32_t> VertexCache;\n    uint32_t AddVertex(uint32_t hash, const PLGVertex *pVertex, VertexCache &cache) {\n        auto f = cache.equal_range(hash);\n        for (auto it = f.first; it != f.second; ++it) {\n            auto &tv = vertices[it->second];\n            if (0 == memcmp(pVertex, &tv, sizeof(PLGVertex))) {\n                return it->second;\n            }\n        }\n\n        auto index = static_cast<uint32_t>(vertices.size());\n        vertices.emplace_back(*pVertex);\n\n        VertexCache::value_type entry(hash, index);\n        cache.insert(entry);\n        return index;\n    }\n\n    static std::string LoadTexturePath(std::stringstream &InFile) {\n        char buff[1024] = {};\n        InFile.getline(buff, 1024, L'\\n');\n        InFile.putback(L'\\n');\n\n        std::string path = buff;\n\n        // Ignore any end-of-line comment\n        size_t pos = path.find_first_of(L'#');\n        if (pos != std::string::npos) {\n            path = path.substr(0, pos);\n        }\n\n        // Texture path should be last element in line\n        pos = path.find_last_of(' ');\n        if (pos != std::string::npos) {\n            path = path.substr(pos + 1);\n        }\n\n        // Trim any trailing whitespace\n        pos = path.find_last_not_of(\" \\t\\r\\n\");\n        if (pos != std::string::npos) {\n            path = path.substr(0, pos + 1);\n        }\n\n        return path;\n    }\n};\n"
  },
  {
    "path": "src/engine/model.cpp",
    "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// Copyright © 2017-2022 TalonBrave.info and Others (see CONTRIBUTORS)\n\n#include <plcore/pl.h>\n\n#include \"model.h\"\n\nconst char *Model_GetAnimationDescription( unsigned int i ) {\n\tstatic const char *animationNames[] = {\n\t\t\"Run cycle (normal)\",\n\t\t\"Run cycle (wounded)\",\n\t\t\"Run cycle (more wounded)\",\n\t\t\"Walk cycle (backwards)\",\n\t\t\"Turning on Spot\",\n\t\t\"Swimming\",\n\t\t\"Swimming like Rick\",\n\t\t\"Getting into Vehicles\",\n\t\t\"Jumping - Start\",\n\t\t\"Jumping - Middle\",\n\t\t\"Jumping - End\",\n\t\t\"Scramble\",\n\t\t\"Getting out Handgun\",\n\t\t\"Getting out Rifle\",\n\t\t\"Getting out Machine gun\",\n\t\t\"Getting out Heavy weapon\",\n\t\t\"Getting out Punch\",\n\t\t\"Getting out Grenade\",\n\t\t\"Getting out Sword / Knife\",\n\t\t\"Using Grenade\",\n\t\t\"Using Punch\",\n\t\t\"Sword / Knife\",\n\t\t\"Bayonet\",\n\t\t\"Aiming Handgun\",\n\t\t\"Aiming Rifle\",\n\t\t\"Aiming Machine gun\",\n\t\t\"Aiming Heavy weapon\",\n\t\t\"Standing around cycle 1\",\n\t\t\"Standing around cycle 2\",\n\t\t\"Very Wounded\",\n\t\t\"Lord Flash-Heart Pose\",\n\t\t\"Looking around\",\n\t\t\"Looking gormless\",\n\t\t\"Cowering\",\n\t\t\"Brushoff 1\",\n\t\t\"Brushoff 2\",\n\t\t\"Brushoff 3\",\n\t\t\"Sneeze\",\n\t\t\"Flying through air/falling\",\n\t\t\"Bouncing on B-Hind\",\n\t\t\"Getting to feet\",\n\t\t\"Celebration #1\",\n\t\t\"Celebration #2\",\n\t\t\"Celebration #3\",\n\t\t\"Salute\",\n\t\t\"Look back\",\n\t\t\"Thinking\",\n\t\t\"Dying #1\",\n\t\t\"Dying #2\",\n\t\t\"Dying #3\",\n\t\t\"Drowning\",\n\t\t\"Idle Cold\",\n\t\t\"Idle Hot\",\n\t\t\"Lay Mine\",\n\t\t\"Heal\",\n\t\t\"Pick pocket\",\n\t\t\"Air strike\",\n\t\t\"Hari Kiri\",\n\t\t\"Parachuting\",\n\t};\n\n\tif ( i >= PL_ARRAY_ELEMENTS( animationNames ) ) {\n\t\treturn nullptr;\n\t}\n\n\treturn animationNames[ i ];\n}\n\n/************************************************************/\n\n#if 0\n/* cache the pigs data into memory, since we\n * share it between all of them anyway :) */\nvoid CacheModelData() {\n  memset(&model_cache, 0, sizeof(model_cache));\n\n  model_cache.pig_skeleton = Hir_LoadFile(u_find(\"chars/pig.hir\"));\n  if (model_cache.pig_skeleton == nullptr) {\n\tError(\"Failed to load skeleton, aborting!\\n\")\n  }\n\n  // animations\n\n  LogInfo(\"Caching mcap.mad\\n\");\n\n  char mcap_path[PL_SYSTEM_MAX_PATH];\n  strncpy(mcap_path, u_find(\"chars/mcap.mad\"), sizeof(mcap_path));\n\n  // check the number of bytes making up the mcap; we'll use this\n  // to determine the length of animations later\n  size_t mcap_bytes = plGetFileSize(mcap_path);\n  if (mcap_bytes < 272) {\n\tError(\"Unexpected \\\"mcap.mad\\\" size, %d, aborting!\\n\", mcap_bytes)\n  }\n\n  FILE *file = fopen(mcap_path, \"rb\");\n  if (file == nullptr) {\n\tError(\"Failed to load \\\"%s\\\", aborting!\\n\", mcap_path)\n  }\n\n  // run through each animation and copy it\n  // into our global animation list\n  for (unsigned int i = 0; i < MAX_ANIMATIONS; ++i) {\n\t// basically a MAD package, but without the\n\t// file name\n\tstruct __attribute__((packed)) {\n\t  uint32_t offset;\n\t  uint32_t length;\n\t} index{};\n\tif (fread(&index, sizeof(index), 1, file) != 1) {\n\t  Error(\"Failed to read index, aborting!\\n\")\n\t}\n\n\t// position we'll return to for the next index\n\tlong position = ftell(file);\n\n\t/* MCAP Format Specification\n\t * Used to store our piggy animations. */\n\ttypedef struct __attribute__((packed)) McapKeyframe {\n\t  int16_t unused;\n\n\t  struct __attribute__((packed)) {\n\t\tint8_t x;\n\t\tint8_t y;\n\t\tint8_t z;\n\t  } transforms[10];\n\n\t  struct __attribute__((packed)) {\n\t\tfloat x;\n\t\tfloat y;\n\t\tfloat z;\n\t\tfloat w;\n\t  } rotations[15];\n\t} McapKeyframe;\n\n\tauto num_keyframes = (unsigned int) (index.length / sizeof(McapKeyframe));\n\tif (num_keyframes == 0) {\n\t  Error(\"Odd keyframe at index, aborting!\\n\")\n\t}\n\n\t// copy everything into our global animations array\n\n\tmodel_cache.animations[i].frames = static_cast<Keyframe *>(u_alloc(num_keyframes, sizeof(Keyframe), true));\n\n\t// move to where the first keyframe is\n\tif (fseek(file, index.offset, SEEK_SET) != 0) {\n\t  Error(\"Failed to seek to offset %d in file, aborting!\\n\", index.offset)\n\t}\n\n\tfor (unsigned int j = 0; j < num_keyframes; ++j) {\n\t  // read in the keyframe data\n\t  McapKeyframe frame;\n\t  if (fread(&frame, sizeof(McapKeyframe), 1, file) != 1) {\n\t\tError(\"Failed to read animation keyframe, aborting!\\n\")\n\t  }\n\n\t  // copy transforms\n\t  for (unsigned int k = 0; k < 10; ++k) {\n\t\tmodel_cache.animations[i].frames[j].transforms[k].x = frame.transforms[k].x;\n\t\tmodel_cache.animations[i].frames[j].transforms[k].y = frame.transforms[k].y;\n\t\tmodel_cache.animations[i].frames[j].transforms[k].z = frame.transforms[k].z;\n\t  }\n\n\t  // copy rotations\n\t  for (unsigned int k = 0; k < 15; ++k) {\n\t\tmodel_cache.animations[i].frames[j].rotations[k].x = frame.rotations[k].x;\n\t\tmodel_cache.animations[i].frames[j].rotations[k].y = frame.rotations[k].y;\n\t\tmodel_cache.animations[i].frames[j].rotations[k].z = frame.rotations[k].z;\n\t\tmodel_cache.animations[i].frames[j].rotations[k].w = frame.rotations[k].w;\n\t  }\n\t}\n\n\tmodel_cache.animations[i].num_frames = num_keyframes;\n\tif (i < plArrayElements(animation_names)) {\n\t  model_cache.animations[i].name = animation_names[i];\n\t}\n\n\t// return us from whence we came\n\tif (fseek(file, position, SEEK_SET) != 0) {\n\t  Error(\"Failed to seek back to original position %d in file, aborting!\\n\", position)\n\t}\n  }\n  u_fclose(file)\n\n#if 0 // debug\n  for(unsigned int i = 0; i < ANI_END; ++i) {\n\t  for(unsigned int j = 0; j < g_model_cache.animations[i].num_frames; ++j) {\n\t\t  print_debug(\"anim(%s) frame(%d) transformation(x:%d y:%d z:%d) angles(%d %d %d %d)\\n\",\n\t\t\t\t\t  g_model_cache.animations[i].name, j,\n\n\t\t\t\t\t  // print out the first transform\n\t\t\t\t\t  (int)model_cache.animations[i].frames[j].transforms[0].x,\n\t\t\t\t\t  (int)model_cache.animations[i].frames[j].transforms[0].y,\n\t\t\t\t\t  (int)model_cache.animations[i].frames[j].transforms[0].z,\n\n\t\t\t\t\t  // print out first rotation\n\t\t\t\t\t  (int)model_cache.animations[i].frames[j].rotations[0].x,\n\t\t\t\t\t  (int)model_cache.animations[i].frames[j].rotations[0].y,\n\t\t\t\t\t  (int)model_cache.animations[i].frames[j].rotations[0].z,\n\t\t\t\t\t  (int)model_cache.animations[i].frames[j].rotations[0].w\n\t\t  );\n\t  }\n  }\n#endif\n}\n#endif\n\n#if 0\nvoid DEBUGDrawSkeleton() {\n  if (!cv_debug_skeleton->b_value) {\n\treturn;\n  }\n\n  static PLMesh* skeleton_mesh = nullptr;\n  if (skeleton_mesh == nullptr) {\n\tskeleton_mesh = plCreateMesh(PL_MESH_LINES, PL_DRAW_DYNAMIC, 0, model_cache.pig_skeleton->num_bones * 2);\n  }\n\n#if 0\n  glPushMatrix();\n\n  static float rotation = 90;\n  rotation += 0.5f;\n  glRotatef(0, 1, 0, 0);\n  glRotatef(rotation, 0, 1, 0);\n  glRotatef(180.f, 0, 0, 1);\n#endif\n\n  plClearMesh(skeleton_mesh);\n\n  static unsigned int frame = 0;\n  static double delay = 20;\n  if (g_state.sys_ticks > delay) {\n\tframe++;\n\tdelay = g_state.sys_ticks + 20;\n  }\n\n  if (frame == model_cache.animations[0].num_frames) {\n\tframe = 0;\n  }\n\n  for (unsigned int i = 0, vert = 0; i < model_cache.pig_skeleton->num_bones; ++i, vert += 2) {\n\tPLModelBone* bone = &model_cache.pig_skeleton->bones[i];\n\n\t//start\n\tplSetMeshVertexPosition(skeleton_mesh, vert, bone->position);\n\tplSetMeshVertexColour(skeleton_mesh, vert, PLColour(255, 0, 0, 255));\n\n\t//end\n\tplSetMeshVertexPosition(skeleton_mesh, vert + 1, model_cache.pig_skeleton->bones[bone->parent].position);\n\tplSetMeshVertexColour(skeleton_mesh, vert + 1, PLColour(0, 255, 0, 255));\n  }\n\n  plSetNamedShaderUniformMatrix4(NULL, \"pl_model\", plMatrix4Identity(), false);\n  plUploadMesh(skeleton_mesh);\n  plDrawMesh(skeleton_mesh);\n\n#if 0\n  glPopMatrix();\n#endif\n}\n#endif\n"
  },
  {
    "path": "src/engine/model.h",
    "content": "/* OpenHoW\n * Copyright (C) 2017-2020 TalonBrave.info and Others (see CONTRIBUTORS)\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#pragma once\n\n//////////////////////////////////////////////////////////////////////////////////////////////////////\n// Animations\n\nenum class AnimationIndex {\n\t//MCAP (in-game)\n\tANI_RUN_NORMAL = 0,         // Run cycle (normal)\n\tANI_RUN_WOUNDED1 = 1,       // Run cycle (wounded)\n\tANI_RUN_WOUNDED2 = 2,       // Run cycle (more wounded)\n\tANI_WALK_BACKWARD = 3,      // Walk cycle (backwards)\n\tANI_TURN = 4,               // Turning on Spot\n\tANI_SWIM1 = 5,              // Swimming\n\tANI_SWIM2 = 6,              // Swimming like Rick\n\tANI_ENTER = 7,              // Getting into Vehicles\n\tANI_JUMP_START = 8,         // Jumping - Start\n\tANI_JUMP_LOOP = 9,          // Jumping - Middle\n\tANI_JUMP_END = 10,          // Jumping - End\n\tANI_CLIMB = 11,             // Scramble\n\tANI_EQUIP_HANDGUN = 12,     // Getting out Handgun\n\tANI_EQUIP_RIFLE = 13,       // Getting out Rifle\n\tANI_EQUIP_MG = 14,          // Getting out Machine gun\n\tANI_EQUIP_HEAVY = 15,       // Getting out Heavy weapon\n\tANI_EQUIP_PUNCH = 16,       // Getting out Punch\n\tANI_EQUIP_THROW = 17,       // Getting out Grenade\n\tANI_EQUIP_MEELE = 18,       // Getting out Sword / Knife\n\tANI_USE_THROW = 19,         // Using Grenade\n\tANI_USE_PUNCH = 20,         // Using Punch\n\tANI_USE_MEELE = 21,         // Sword / Knife\n\tANI_USE_BAYONET = 22,       // Bayonet\n\tANI_USE_HANDGUN = 23,       // Aiming Handgun\n\tANI_USE_RIFLE = 24,         // Aiming Rifle\n\tANI_USE_MG = 25,            // Aiming Machine gun\n\tANI_USE_HEAVY = 26,         // Aiming Heavy weapon\n\tANI_IDLE1 = 27,             // Standing around cycle 1\n\tANI_IDLE2 = 28,             // Standing around cycle 2\n\tANI_HURT = 29,              // Very Wounded\n\tANI_PROUD = 30,             // Lord Flash-Heart Pose\n\tANI_LOOK = 31,              // Looking around\n\tANI_STUPID = 32,            // Looking gormless\n\tANI_FEAR = 33,              // Cowering\n\tANI_CLEAN1 = 34,            // Brushoff 1\n\tANI_CLEAN2 = 35,            // Brushoff 2\n\tANI_CLEAN3 = 36,            // Brushoff 3\n\tANI_SNEEZE = 37,            // Sneeze\n\tANI_FALL = 38,              // Flying through air/falling\n\tANI_BOUNCE = 39,            // Bouncing on B-Hind\n\tANI_STANDUP = 40,           // Getting to feet\n\tANI_CELEBRATE1 = 41,        // Celebration #1\n\tANI_CELEBRATE2 = 42,        // Celebration #2\n\tANI_CELEBRATE3 = 43,        // Celebration #3\n\tANI_SALUTE = 44,            // Salute\n\tANI_LOOK_BACK = 45,         // Look back\n\tANI_THINK = 46,             // Thinking\n\tANI_DEATH1 = 47,            // Dying #1\n\tANI_DEATH2 = 48,            // Dying #2\n\tANI_DEATH3 = 49,            // Dying #3\n\tANI_DROWN = 50,             // Drowning\n\tANI_IDLE_COLD = 51,         // Idle Cold\n\tANI_IDLE_HOT = 52,          // Idle Hot\n\tANI_USE_MINE = 53,          // Lay Mine\n\tANI_USE_HEAL = 54,          // Heal\n\tANI_USE_STEAL = 55,         // Pick pocket\n\tANI_USE_AIRSHIP = 56,       // Air strike\n\tANI_USE_SUICIDE = 57,       // Hari Kiri\n\tANI_PARACHUTE = 58,         // Parachuting\n\n\t//FEMCAP (front-end)\n\tANI_59 = 59,                //\n\tANI_60 = 60,                //\n\tANI_61 = 61,                //\n\tANI_62 = 62,                //\n\tANI_63 = 63,                //\n\tANI_64 = 64,                //\n\tANI_65 = 65,                //\n\tANI_66 = 66,                //\n\tANI_67 = 67,                //\n\tANI_68 = 68,                //\n\tANI_69 = 69,                //\n\tANI_70 = 70,                //\n\tANI_71 = 71,                //\n\tANI_72 = 72,                //\n\tANI_73 = 73,                //\n\tANI_74 = 74,                //\n\tANI_75 = 75,                //\n\tANI_76 = 76,                //\n\tANI_77 = 77,                //\n\tANI_78 = 78,                //\n\tANI_79 = 79,                //\n\tANI_80 = 80,                //\n\tANI_81 = 81,                //\n\tANI_82 = 82,                //\n\tANI_83 = 83,                //\n\tANI_84 = 84,                //\n\tANI_85 = 85,                //\n\tANI_86 = 86,                //\n\tANI_87 = 87,                //\n\tANI_88 = 88,                //\n\tANI_89 = 89,                //\n\tANI_90 = 90,                //\n\tANI_91 = 91,                //\n\tANI_92 = 92,                //\n\n\tMAX_ANIMATIONS\n};\n\nclass TextureAtlas;\n\nconst char *Model_GetAnimationDescription( unsigned int i );\n"
  },
  {
    "path": "src/engine/physics/PhysicsInterface.cpp",
    "content": "/* OpenHoW\n * Copyright (C) 2017-2020 TalonBrave.info and Others (see CONTRIBUTORS)\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include \"App.h\"\n#include \"PhysicsInterface.h\"\n\nvoid ohw::PhysicsInterface::Tick() {\n\n}\n\nohw::PhysicsBody *ohw::PhysicsInterface::CreatePhysicsBody() {\n\treturn nullptr;\n}\n\nvoid ohw::PhysicsInterface::DestroyPhysicsBody( ohw::PhysicsBody *body ) {\n\n}\n\nvoid ohw::PhysicsInterface::GenerateTerrainCollision( std::vector<float> vertices ) {\n\n}\n\nvoid ohw::PhysicsInterface::DestroyTerrainCollision() {\n\n}\n"
  },
  {
    "path": "src/engine/physics/PhysicsInterface.h",
    "content": "/* OpenHoW\n * Copyright (C) 2017-2020 TalonBrave.info and Others (see CONTRIBUTORS)\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#pragma once\n\nnamespace ohw {\n\nenum class PhysicsPrimitiveType {\n\tSPHERE,\n\tBOX,\n\tCAPSULE,\n\tCYLINDER,\n\tCONE,\n\tCHAMFER_CYLINDER,\n\tRANDOM_CONVEX_HULL,\n\tREGULAR_CONVEX_HULL,\n\tCOMPOUND_CONVEX_CRUZ,\n};\n\nclass PhysicsBody {\npublic:\nprotected:\n\tPhysicsBody() = default;\n\tvirtual ~PhysicsBody() = default;\n\nprivate:\n};\n\nclass PhysicsInterface {\npublic:\n\tPhysicsInterface() = default;\n\tvirtual ~PhysicsInterface() = default;\n\n\tvirtual void Tick();\n\n\tvirtual PhysicsBody *CreatePhysicsBody();\n\tvirtual void DestroyPhysicsBody( PhysicsBody *body );\n\n\tvirtual void GenerateTerrainCollision( std::vector<float> vertices );\n\tvirtual void DestroyTerrainCollision();\n\nprotected:\nprivate:\n};\n\n}\n"
  },
  {
    "path": "src/engine/script/JsonReader.cpp",
    "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// Copyright © 2017-2022 TalonBrave.info and Others (see CONTRIBUTORS)\n\n#include <duktape.h>\n#include <sstream>\n\n#include \"App.h\"\n#include \"JsonReader.h\"\n\n#define LogMissingProperty( P )   Warning(\"Failed to get JSON property \\\"%s\\\"!\\n\", (P))\n#define LogInvalidArray( P )      Warning(\"Invalid JSON array for property \\\"%s\\\"!\\n\", (P))\n\nJsonReader::JsonReader( const std::string &path ) : JsonReader() {\n\tif ( path.empty() ) {\n\t\tthrow std::runtime_error( \"Empty path for config, aborting!\\n\" );\n\t}\n\n\tPLFile *filePtr = PlOpenFile( path.c_str(), false );\n\tif ( filePtr == nullptr ) {\n\t\tthrow std::runtime_error( \"Failed to load file!\\n\" );\n\t}\n\n\tsize_t sz = PlGetFileSize( filePtr );\n\tif ( sz == 0 ) {\n\t\tPlCloseFile( filePtr );\n\t\tthrow std::runtime_error( \"Failed to load file, empty config!\\n\" );\n\t}\n\n\tstd::vector<char> buf( sz + 1 );\n\tPlReadFile( filePtr, buf.data(), sizeof( char ), sz );\n\tbuf[ sz ] = '\\0';\n\tPlCloseFile( filePtr );\n\tParseBuffer( buf.data() );\n}\n\nJsonReader::JsonReader() {\n\tif ( ( ctx_ = duk_create_heap_default() ) == nullptr ) {\n\t\tthrow std::bad_alloc();\n\t}\n}\n\nJsonReader::~JsonReader() {\n\tif ( ctx_ != nullptr ) {\n\t\tduk_destroy_heap( static_cast<duk_context *>(ctx_) );\n\t}\n}\n\nstd::string JsonReader::GetStringProperty( const std::string &property, const std::string &def, bool silent ) {\n\tauto *context = static_cast<duk_context *>(ctx_);\n\n\tconst char *p = property.c_str();\n\tif ( !duk_get_prop_string( context, -1, p ) ) {\n\t\tduk_pop( context );\n\t\tif ( !silent ) {\n\t\t\tLogMissingProperty( p );\n\t\t}\n\t\treturn def;\n\t}\n\n\tstd::string str = duk_safe_to_string( context, -1 );\n\tduk_pop( context );\n\n\treturn str;\n}\n\nint JsonReader::GetIntegerProperty( const std::string &property, int def, bool silent ) {\n\tauto *context = static_cast<duk_context *>(ctx_);\n\n\tconst char *p = property.c_str();\n\tif ( !duk_get_prop_string( context, -1, p ) ) {\n\t\tduk_pop( context );\n\t\tif ( !silent ) {\n\t\t\tLogMissingProperty( p );\n\t\t}\n\t\treturn def;\n\t}\n\n\tint var = duk_to_int32( context, -1 );\n\tduk_pop( context );\n\n\treturn var;\n}\n\nbool JsonReader::GetBooleanProperty( const std::string &property, bool def, bool silent ) {\n\tauto *context = static_cast<duk_context *>(ctx_);\n\n\tconst char *p = property.c_str();\n\tif ( !duk_get_prop_string( context, -1, p ) ) {\n\t\tduk_pop( context );\n\t\tif ( !silent ) {\n\t\t\tLogMissingProperty( p );\n\t\t}\n\t\treturn def;\n\t}\n\n\tauto var = static_cast<bool>(duk_to_boolean( context, -1 ));\n\tduk_pop( context );\n\n\treturn var;\n}\n\nfloat JsonReader::GetFloatProperty( const std::string &property, float def, bool silent ) {\n\tauto *context = static_cast<duk_context *>(ctx_);\n\n\tconst char *p = property.c_str();\n\tif ( !duk_get_prop_string( context, -1, p ) ) {\n\t\tduk_pop( context );\n\t\tif ( !silent ) {\n\t\t\tLogMissingProperty( p );\n\t\t}\n\t\treturn def;\n\t}\n\n\tfloat var = duk_to_number( context, -1 );\n\tduk_pop( context );\n\n\treturn var;\n}\n\n// https://stackoverflow.com/a/23305012\ntemplate< char C >\nstd::istream &expect( std::istream &in ) {\n\tif ( in.peek() == C ) {\n\t\tin.ignore();\n\t} else {\n\t\tin.setstate( std::ios_base::failbit );\n\t}\n\treturn in;\n}\n\nhei::Colour JsonReader::GetColourProperty( const std::string &property, const hei::Colour &def, bool silent ) {\n\tauto *context = static_cast<duk_context *>(ctx_);\n\n\tconst char *p = property.c_str();\n\tif ( !duk_get_prop_string( context, -1, p ) ) {\n\t\tduk_pop( context );\n\t\tif ( !silent ) {\n\t\t\tLogMissingProperty( p );\n\t\t}\n\t\treturn def;\n\t}\n\n\tstd::string str = duk_safe_to_string( context, -1 );\n\tduk_pop( context );\n\n\tstd::stringstream stream( str );\n\tint r, g, b, a;\n\tstream >> r >> expect<' '> >> g >> expect<' '> >> b;\n\tif ( !( stream.rdstate() & std::stringstream::failbit ) ) {\n\t\tstream >> expect<' '> >> a;\n\t\tif ( stream.rdstate() & std::stringstream::failbit ) {\n\t\t\t// can still ignore alpha channel\n\t\t\ta = 255;\n\t\t}\n\t} else {\n\t\tthrow std::runtime_error( \"Failed to parse entirety of colour from JSON property, \\\"\" + property + \"\\\"!\\n\" );\n\t}\n\n\treturn hei::Colour( r, g, b, a );\n}\n\nPLVector4 JsonReader::GetVector4Property( const std::string &property, PLVector4 def, bool silent ) {\n\tauto *context = static_cast<duk_context *>(ctx_);\n\n\tconst char *p = property.c_str();\n\tif ( !duk_get_prop_string( context, -1, p ) ) {\n\t\tduk_pop( context );\n\t\tif ( !silent ) {\n\t\t\tLogMissingProperty( p );\n\t\t}\n\t\treturn def;\n\t}\n\n\tstd::string str = duk_safe_to_string( context, -1 );\n\tduk_pop( context );\n\n\tPLVector4 out;\n\tstd::stringstream stream( str );\n\tstream >> out.x >> expect<' '> >> out.y >> expect<' '> >> out.z >> expect< ' ' > >> out.w;\n\tif ( stream.rdstate() & std::stringstream::failbit ) {\n\t\tthrow std::runtime_error( \"Failed to parse entirety of vector from JSON property, \\\"\" + property + \"\\\"!\\n\" );\n\t}\n\n\treturn out;\n}\n\nPLVector3 JsonReader::GetVector3Property( const std::string &property, PLVector3 def, bool silent ) {\n\tauto *context = static_cast<duk_context *>(ctx_);\n\n\tconst char *p = property.c_str();\n\tif ( !duk_get_prop_string( context, -1, p ) ) {\n\t\tduk_pop( context );\n\t\tif ( !silent ) {\n\t\t\tLogMissingProperty( p );\n\t\t}\n\t\treturn def;\n\t}\n\n\tstd::string str = duk_safe_to_string( context, -1 );\n\tduk_pop( context );\n\n\tPLVector3 out;\n\tstd::stringstream stream( str );\n\tstream >> out.x >> expect<' '> >> out.y >> expect<' '> >> out.z;\n\tif ( stream.rdstate() & std::stringstream::failbit ) {\n\t\tthrow std::runtime_error( \"Failed to parse entirety of vector from JSON property, \\\"\" + property + \"\\\"!\\n\" );\n\t}\n\n\treturn out;\n}\n\nunsigned int JsonReader::GetArrayLength( const std::string &property, bool silent ) {\n\tauto *context = static_cast<duk_context *>(ctx_);\n\n\tif ( !property.empty() ) {\n\t\tconst char *p = property.c_str();\n\t\tif ( !duk_get_prop_string( context, -1, p ) ) {\n\t\t\tduk_pop( context );\n\t\t\tif ( !silent ) {\n\t\t\t\tLogMissingProperty( p );\n\t\t\t}\n\t\t\treturn 0;\n\t\t}\n\t}\n\n\tif ( !duk_is_array( context, -1 ) ) {\n\t\tif ( !property.empty() ) {\n\t\t\tduk_pop( context );\n\t\t}\n\t\tif ( !silent ) {\n\t\t\tWarning( \"Invalid array node!\\n\" );\n\t\t}\n\t\treturn 0;\n\t}\n\n\tduk_size_t len = duk_get_length( context, -1 );\n\n\tif ( !property.empty() ) {\n\t\tduk_pop( context );\n\t}\n\n\treturn static_cast<unsigned int>(len);\n}\n\nstd::string JsonReader::GetArrayStringProperty( const std::string &property, unsigned int index ) {\n\tauto *context = static_cast<duk_context *>(ctx_);\n\n\tconst char *p = property.c_str();\n\tif ( !duk_get_prop_string( context, -1, p ) ) {\n\t\tduk_pop( context );\n\t\tLogMissingProperty( p );\n\t\treturn \"\";\n\t}\n\n\tif ( !duk_is_array( context, -1 ) ) {\n\t\tduk_pop( context );\n\t\tLogInvalidArray( p );\n\t\treturn \"\";\n\t}\n\n\tduk_size_t length = duk_get_length( context, -1 );\n\tif ( index >= length ) {\n\t\tWarning( \"Invalid index, %d (%d), in array!\\n\", index, length );\n\t\treturn \"\";\n\t}\n\n\tduk_get_prop_string( context, -1, p );\n\tduk_get_prop_index( context, -1, index );\n\tconst char *str = duk_get_string( context, index );\n\tduk_pop( context );\n\n\treturn str;\n}\n\nstd::vector<std::string> JsonReader::GetArrayStrings( const std::string &property, bool silent ) {\n\tauto *context = static_cast<duk_context *>(ctx_);\n\n\tconst char *p = property.c_str();\n\tif ( !duk_get_prop_string( context, -1, p ) ) {\n\t\tduk_pop( context );\n\t\tif ( !silent ) {\n\t\t\tLogMissingProperty( p );\n\t\t}\n\t\treturn {};\n\t}\n\n\tif ( !duk_is_array( context, -1 ) ) {\n\t\tduk_pop( context );\n\t\tif ( !silent ) {\n\t\t\tLogMissingProperty( p );\n\t\t}\n\t\treturn {};\n\t}\n\n\tduk_size_t length = duk_get_length( context, -1 );\n\n\tstd::vector<std::string> strings;\n\tstrings.reserve( length );\n\n\tfor ( size_t i = 0; i < length; ++i ) {\n\t\tduk_get_prop_index( context, -1, i );\n\t\tconst char *c = duk_get_string( context, -1 );\n\t\tu_assert( c != nullptr, \"Null string passed by duk_get_string!\\n\" );\n\t\tstrings.emplace_back( c );\n\t\tduk_pop( context );\n\t}\n\n\tduk_pop( context );\n\n\treturn strings;\n}\n\nvoid JsonReader::ParseBuffer( const char *buf ) {\n\tif ( buf == nullptr ) {\n\t\tError( \"Invalid buffer length!\\n\" );\n\t}\n\n\tauto *context = static_cast<duk_context *>(ctx_);\n\tduk_push_string( context, buf );\n\tduk_json_decode( context, -1 );\n}\n\nbool JsonReader::EnterChildNode( const std::string &property, bool silent ) {\n\tauto *context = static_cast<duk_context *>(ctx_);\n\tconst char *p = property.c_str();\n\tif ( !duk_get_prop_string( context, -1, p ) ) {\n\t\tduk_pop( context );\n\t\tif ( !silent ) {\n\t\t\tLogMissingProperty( p );\n\t\t}\n\t\treturn false;\n\t}\n\n\treturn true;\n}\n\nvoid JsonReader::EnterChildNode( unsigned int index ) {\n\tauto *context = static_cast<duk_context *>(ctx_);\n\tif ( !duk_is_array( context, -1 ) ) {\n\t\tduk_pop( context );\n\t\tWarning( \"Node is not an array!\\n\" );\n\t\treturn;\n\t}\n\n\tduk_size_t length = duk_get_length( context, -1 );\n\tif ( index >= length ) {\n\t\tWarning( \"Invalid index, %d (%d), in array!\\n\", index, length );\n\t\treturn;\n\t}\n\n\tduk_get_prop_index( context, -1, index );\n}\n\nvoid JsonReader::LeaveChildNode() {\n\tauto *context = static_cast<duk_context *>(ctx_);\n\tduk_pop( context );\n}\n\nstd::list<std::string> JsonReader::GetObjectKeys() {\n\tstd::list<std::string> lst;\n\n\tauto *context = static_cast<duk_context *>(ctx_);\n\tduk_enum( context, -1, 0 );\n\twhile ( duk_next( context, -1, 1 ) ) {\n\t\tlst.emplace_back( duk_safe_to_string( context, -2 ) );\n\t\tduk_pop_2( context );\n\t}\n\tduk_pop( context );\n\n\treturn lst;\n}\n"
  },
  {
    "path": "src/engine/script/JsonReader.h",
    "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n// Copyright © 2017-2022 TalonBrave.info and Others (see CONTRIBUTORS)\n\n#pragma once\n\nclass JsonReader {\npublic:\n\texplicit JsonReader( const std::string &path );\n\tJsonReader();\n\t~JsonReader();\n\n\tvoid ParseBuffer( const char *buf );\n\n\tbool EnterChildNode( const std::string &property, bool silent = true );\n\tvoid EnterChildNode( unsigned int index );\n\tvoid LeaveChildNode();\n\n\tstd::string GetStringProperty( const std::string &property, const std::string &def = \"\", bool silent = true );\n\tint GetIntegerProperty( const std::string &property, int def = 0, bool silent = true );\n\tbool GetBooleanProperty( const std::string &property, bool def = false, bool silent = true );\n\tfloat GetFloatProperty( const std::string &property, float def = 0.0f, bool silent = true );\n\thei::Colour GetColourProperty( const std::string &property, const hei::Colour &def = { 0, 0, 0 }, bool silent = true );\n\tPLVector3 GetVector3Property( const std::string &property, PLVector3 def = { 0, 0, 0 }, bool silent = true );\n\tPLVector4 GetVector4Property( const std::string &property, PLVector4 def = { 0, 0, 0, 0 }, bool silent = true );\n\n\tstd::list<std::string> GetObjectKeys();\n\n\tunsigned int GetArrayLength( const std::string &property = \"\", bool silent = true );\n\tstd::vector<std::string> GetArrayStrings( const std::string &property, bool silent = true );\n\tstd::string GetArrayStringProperty( const std::string &property, unsigned int index );\n\nprotected:\nprivate:\n\tvoid *ctx_{ nullptr };\n};\n"
  },
  {
    "path": "src/engine/script/duktape-2.2.0/duk_config.h",
    "content": "/*\n *  duk_config.h configuration header generated by genconfig.py.\n *\n *  Git commit: a459cf3c9bd1779fc01b435d69302b742675a08f\n *  Git describe: v2.2.0\n *  Git branch: master\n *\n *  Supported platforms:\n *      - Mac OSX, iPhone, Darwin\n *      - Orbis\n *      - OpenBSD\n *      - Generic BSD\n *      - Atari ST TOS\n *      - AmigaOS\n *      - Durango (XboxOne)\n *      - Windows\n *      - Flashplayer (Crossbridge)\n *      - QNX\n *      - TI-Nspire\n *      - Emscripten\n *      - Linux\n *      - Solaris\n *      - AIX\n *      - HPUX\n *      - Generic POSIX\n *      - Cygwin\n *      - Generic UNIX\n *      - Generic fallback\n *\n *  Supported architectures:\n *      - x86\n *      - x64\n *      - x32\n *      - ARM 32-bit\n *      - ARM 64-bit\n *      - MIPS 32-bit\n *      - MIPS 64-bit\n *      - PowerPC 32-bit\n *      - PowerPC 64-bit\n *      - SPARC 32-bit\n *      - SPARC 64-bit\n *      - SuperH\n *      - Motorola 68k\n *      - Emscripten\n *      - Generic\n *\n *  Supported compilers:\n *      - Clang\n *      - GCC\n *      - MSVC\n *      - Emscripten\n *      - TinyC\n *      - VBCC\n *      - Bruce's C compiler\n *      - Generic\n *\n */\n\n#if !defined(DUK_CONFIG_H_INCLUDED)\n#define DUK_CONFIG_H_INCLUDED\n\n/*\n *  Intermediate helper defines\n */\n\n/* DLL build detection */\n/* not configured for DLL build */\n#undef DUK_F_DLL_BUILD\n\n/* Apple OSX, iOS */\n#if defined(__APPLE__)\n#define DUK_F_APPLE\n#endif\n\n/* FreeBSD */\n#if defined(__FreeBSD__) || defined(__FreeBSD)\n#define DUK_F_FREEBSD\n#endif\n\n/* Orbis (PS4) variant */\n#if defined(DUK_F_FREEBSD) && defined(__ORBIS__)\n#define DUK_F_ORBIS\n#endif\n\n/* OpenBSD */\n#if defined(__OpenBSD__) || defined(__OpenBSD)\n#define DUK_F_OPENBSD\n#endif\n\n/* NetBSD */\n#if defined(__NetBSD__) || defined(__NetBSD)\n#define DUK_F_NETBSD\n#endif\n\n/* BSD variant */\n#if defined(DUK_F_FREEBSD) || defined(DUK_F_NETBSD) || defined(DUK_F_OPENBSD) || \\\n    defined(__bsdi__) || defined(__DragonFly__)\n#define DUK_F_BSD\n#endif\n\n/* Atari ST TOS.  __TOS__ defined by PureC.  No platform define in VBCC\n * apparently, so to use with VBCC user must define __TOS__ manually.\n  */\n#if defined(__TOS__)\n#define DUK_F_TOS\n#endif\n\n/* Motorola 68K.  Not defined by VBCC, so user must define one of these\n * manually when using VBCC.\n */\n#if defined(__m68k__) || defined(M68000) || defined(__MC68K__)\n#define DUK_F_M68K\n#endif\n\n/* AmigaOS.  Neither AMIGA nor __amigaos__ is defined on VBCC, so user must\n * define 'AMIGA' manually when using VBCC.\n */\n#if defined(AMIGA) || defined(__amigaos__)\n#define DUK_F_AMIGAOS\n#endif\n\n/* PowerPC */\n#if defined(__powerpc) || defined(__powerpc__) || defined(__PPC__)\n#define DUK_F_PPC\n#if defined(__PPC64__) || defined(__LP64__) || defined(_LP64)\n#define DUK_F_PPC64\n#else\n#define DUK_F_PPC32\n#endif\n#endif\n\n/* Durango (Xbox One) */\n#if defined(_DURANGO) || defined(_XBOX_ONE)\n#define DUK_F_DURANGO\n#endif\n\n/* Windows, both 32-bit and 64-bit */\n#if defined(_WIN32) || defined(WIN32) || defined(_WIN64) || defined(WIN64) || \\\n    defined(__WIN32__) || defined(__TOS_WIN__) || defined(__WINDOWS__)\n#define DUK_F_WINDOWS\n#if defined(_WIN64) || defined(WIN64)\n#define DUK_F_WIN64\n#else\n#define DUK_F_WIN32\n#endif\n#endif\n\n/* Flash player (e.g. Crossbridge) */\n#if defined(__FLASHPLAYER__)\n#define DUK_F_FLASHPLAYER\n#endif\n\n/* QNX */\n#if defined(__QNX__)\n#define DUK_F_QNX\n#endif\n\n/* TI-Nspire (using Ndless) */\n#if defined(_TINSPIRE)\n#define DUK_F_TINSPIRE\n#endif\n\n/* Emscripten (provided explicitly by user), improve if possible */\n#if defined(EMSCRIPTEN)\n#define DUK_F_EMSCRIPTEN\n#endif\n\n/* BCC (Bruce's C compiler): this is a \"torture target\" for compilation */\n#if defined(__BCC__) || defined(__BCC_VERSION__)\n#define DUK_F_BCC\n#endif\n\n/* Linux */\n#if defined(__linux) || defined(__linux__) || defined(linux)\n#define DUK_F_LINUX\n#endif\n\n/* illumos / Solaris */\n#if defined(__sun) && defined(__SVR4)\n#define DUK_F_SUN\n#if defined(__SUNPRO_C) && (__SUNPRO_C < 0x550)\n#define DUK_F_OLD_SOLARIS\n/* Defines _ILP32 / _LP64 required by DUK_F_X86/DUK_F_X64.  Platforms\n * are processed before architectures, so this happens before the\n * DUK_F_X86/DUK_F_X64 detection is emitted.\n */\n#include <sys/isa_defs.h>\n#endif\n#endif\n\n/* AIX */\n#if defined(_AIX)\n/* defined(__xlc__) || defined(__IBMC__): works but too wide */\n#define DUK_F_AIX\n#endif\n\n/* HPUX */\n#if defined(__hpux)\n#define DUK_F_HPUX\n#if defined(__ia64)\n#define DUK_F_HPUX_ITANIUM\n#endif\n#endif\n\n/* POSIX */\n#if defined(__posix)\n#define DUK_F_POSIX\n#endif\n\n/* Cygwin */\n#if defined(__CYGWIN__)\n#define DUK_F_CYGWIN\n#endif\n\n/* Generic Unix (includes Cygwin) */\n#if defined(__unix) || defined(__unix__) || defined(unix) || \\\n    defined(DUK_F_LINUX) || defined(DUK_F_BSD)\n#define DUK_F_UNIX\n#endif\n\n/* C++ */\n#undef DUK_F_CPP\n#if defined(__cplusplus)\n#define DUK_F_CPP\n#endif\n\n/* Intel x86 (32-bit), x64 (64-bit) or x32 (64-bit but 32-bit pointers),\n * define only one of DUK_F_X86, DUK_F_X64, DUK_F_X32.\n * https://sites.google.com/site/x32abi/\n *\n * With DUK_F_OLD_SOLARIS the <sys/isa_defs.h> header must be included\n * before this.\n */\n#if defined(__amd64__) || defined(__amd64) || \\\n    defined(__x86_64__) || defined(__x86_64) || \\\n    defined(_M_X64) || defined(_M_AMD64)\n#if defined(__ILP32__) || defined(_ILP32)\n#define DUK_F_X32\n#else\n#define DUK_F_X64\n#endif\n#elif defined(i386) || defined(__i386) || defined(__i386__) || \\\n      defined(__i486__) || defined(__i586__) || defined(__i686__) || \\\n      defined(__IA32__) || defined(_M_IX86) || defined(__X86__) || \\\n      defined(_X86_) || defined(__THW_INTEL__) || defined(__I86__)\n#if defined(__LP64__) || defined(_LP64)\n/* This should not really happen, but would indicate x64. */\n#define DUK_F_X64\n#else\n#define DUK_F_X86\n#endif\n#endif\n\n/* ARM */\n#if defined(__arm__) || defined(__thumb__) || defined(_ARM) || defined(_M_ARM) || defined(__aarch64__)\n#define DUK_F_ARM\n#if defined(__LP64__) || defined(_LP64) || defined(__arm64) || defined(__arm64__) || defined(__aarch64__)\n#define DUK_F_ARM64\n#else\n#define DUK_F_ARM32\n#endif\n#endif\n\n/* MIPS.  Related defines: __MIPSEB__, __MIPSEL__, __mips_isa_rev, __LP64__ */\n#if defined(__mips__) || defined(mips) || defined(_MIPS_ISA) || \\\n    defined(_R3000) || defined(_R4000) || defined(_R5900) || \\\n    defined(_MIPS_ISA_MIPS1) || defined(_MIPS_ISA_MIPS2) || \\\n    defined(_MIPS_ISA_MIPS3) || defined(_MIPS_ISA_MIPS4) || \\\n    defined(__mips) || defined(__MIPS__)\n#define DUK_F_MIPS\n#if defined(__LP64__) || defined(_LP64) || defined(__mips64) || \\\n    defined(__mips64__) || defined(__mips_n64)\n#define DUK_F_MIPS64\n#else\n#define DUK_F_MIPS32\n#endif\n#endif\n\n/* SPARC */\n#if defined(sparc) || defined(__sparc) || defined(__sparc__)\n#define DUK_F_SPARC\n#if defined(__LP64__) || defined(_LP64)\n#define DUK_F_SPARC64\n#else\n#define DUK_F_SPARC32\n#endif\n#endif\n\n/* SuperH */\n#if defined(__sh__) || \\\n    defined(__sh1__) || defined(__SH1__) || \\\n    defined(__sh2__) || defined(__SH2__) || \\\n    defined(__sh3__) || defined(__SH3__) || \\\n    defined(__sh4__) || defined(__SH4__) || \\\n    defined(__sh5__) || defined(__SH5__)\n#define DUK_F_SUPERH\n#endif\n\n/* Clang */\n#if defined(__clang__)\n#define DUK_F_CLANG\n#endif\n\n/* C99 or above */\n#undef DUK_F_C99\n#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)\n#define DUK_F_C99\n#endif\n\n/* C++11 or above */\n#undef DUK_F_CPP11\n#if defined(__cplusplus) && (__cplusplus >= 201103L)\n#define DUK_F_CPP11\n#endif\n\n/* GCC.  Clang also defines __GNUC__ so don't detect GCC if using Clang. */\n#if defined(__GNUC__) && !defined(__clang__) && !defined(DUK_F_CLANG)\n#define DUK_F_GCC\n#if defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__)\n/* Convenience, e.g. gcc 4.5.1 == 40501; http://stackoverflow.com/questions/6031819/emulating-gccs-builtin-unreachable */\n#define DUK_F_GCC_VERSION  (__GNUC__ * 10000L + __GNUC_MINOR__ * 100L + __GNUC_PATCHLEVEL__)\n#else\n#error cannot figure out gcc version\n#endif\n#endif\n\n/* MinGW.  Also GCC flags (DUK_F_GCC) are enabled now. */\n#if defined(__MINGW32__) || defined(__MINGW64__)\n#define DUK_F_MINGW\n#endif\n\n/* MSVC */\n#if defined(_MSC_VER)\n/* MSVC preprocessor defines: http://msdn.microsoft.com/en-us/library/b0084kay.aspx\n * _MSC_FULL_VER includes the build number, but it has at least two formats, see e.g.\n * BOOST_MSVC_FULL_VER in http://www.boost.org/doc/libs/1_52_0/boost/config/compiler/visualc.hpp\n */\n#define DUK_F_MSVC\n#if defined(_MSC_FULL_VER)\n#if (_MSC_FULL_VER > 100000000)\n#define DUK_F_MSVC_FULL_VER _MSC_FULL_VER\n#else\n#define DUK_F_MSCV_FULL_VER (_MSC_FULL_VER * 10)\n#endif\n#endif\n#endif  /* _MSC_VER */\n\n/* TinyC */\n#if defined(__TINYC__)\n/* http://bellard.org/tcc/tcc-doc.html#SEC9 */\n#define DUK_F_TINYC\n#endif\n\n/* VBCC */\n#if defined(__VBCC__)\n#define DUK_F_VBCC\n#endif\n\n#if defined(ANDROID) || defined(__ANDROID__)\n#define DUK_F_ANDROID\n#endif\n\n/* Atari Mint */\n#if defined(__MINT__)\n#define DUK_F_MINT\n#endif\n\n/*\n *  Platform autodetection\n */\n\n/* Workaround for older C++ compilers before including <inttypes.h>,\n * see e.g.: https://sourceware.org/bugzilla/show_bug.cgi?id=15366\n */\n#if defined(__cplusplus) && !defined(__STDC_LIMIT_MACROS)\n#define __STDC_LIMIT_MACROS\n#endif\n#if defined(__cplusplus) && !defined(__STDC_CONSTANT_MACROS)\n#define __STDC_CONSTANT_MACROS\n#endif\n\n#if defined(DUK_F_APPLE)\n/* --- Mac OSX, iPhone, Darwin --- */\n#define DUK_USE_DATE_NOW_GETTIMEOFDAY\n#define DUK_USE_DATE_TZO_GMTIME_R\n#define DUK_USE_DATE_PRS_STRPTIME\n#define DUK_USE_DATE_FMT_STRFTIME\n#include <TargetConditionals.h>\n#include <architecture/byte_order.h>\n#include <sys/param.h>\n#include <sys/time.h>\n#include <time.h>\n\n/* http://stackoverflow.com/questions/5919996/how-to-detect-reliably-mac-os-x-ios-linux-windows-in-c-preprocessor */\n#if TARGET_IPHONE_SIMULATOR\n#define DUK_USE_OS_STRING \"iphone-sim\"\n#elif TARGET_OS_IPHONE\n#define DUK_USE_OS_STRING \"iphone\"\n#elif TARGET_OS_MAC\n#define DUK_USE_OS_STRING \"osx\"\n#else\n#define DUK_USE_OS_STRING \"osx-unknown\"\n#endif\n\n/* Use _setjmp() on Apple by default, see GH-55. */\n#define DUK_JMPBUF_TYPE       jmp_buf\n#define DUK_SETJMP(jb)        _setjmp((jb))\n#define DUK_LONGJMP(jb)       _longjmp((jb), 1)\n#elif defined(DUK_F_ORBIS)\n/* --- Orbis --- */\n/* Orbis = PS4 */\n#define DUK_USE_DATE_NOW_GETTIMEOFDAY\n#define DUK_USE_DATE_TZO_GMTIME_S\n/* no parsing (not an error) */\n#define DUK_USE_DATE_FMT_STRFTIME\n#include <sys/types.h>\n#include <machine/endian.h>\n#include <sys/param.h>\n#include <sys/time.h>\n#include <time.h>\n\n#define DUK_USE_OS_STRING  \"orbis\"\n#elif defined(DUK_F_OPENBSD)\n/* --- OpenBSD --- */\n/* http://www.monkey.org/openbsd/archive/ports/0401/msg00089.html */\n#define DUK_USE_DATE_NOW_GETTIMEOFDAY\n#define DUK_USE_DATE_TZO_GMTIME_R\n#define DUK_USE_DATE_PRS_STRPTIME\n#define DUK_USE_DATE_FMT_STRFTIME\n#include <sys/types.h>\n#include <sys/endian.h>\n#include <sys/param.h>\n#include <sys/time.h>\n#include <time.h>\n\n#define DUK_USE_OS_STRING  \"openbsd\"\n#elif defined(DUK_F_BSD)\n/* --- Generic BSD --- */\n#define DUK_USE_DATE_NOW_GETTIMEOFDAY\n#define DUK_USE_DATE_TZO_GMTIME_R\n#define DUK_USE_DATE_PRS_STRPTIME\n#define DUK_USE_DATE_FMT_STRFTIME\n#include <sys/types.h>\n#include <sys/endian.h>\n#include <sys/param.h>\n#include <sys/time.h>\n#include <time.h>\n\n#define DUK_USE_OS_STRING  \"bsd\"\n#elif defined(DUK_F_TOS)\n/* --- Atari ST TOS --- */\n#define DUK_USE_DATE_NOW_TIME\n#define DUK_USE_DATE_TZO_GMTIME\n/* no parsing (not an error) */\n#define DUK_USE_DATE_FMT_STRFTIME\n#include <time.h>\n\n#define DUK_USE_OS_STRING  \"tos\"\n\n/* TOS on M68K is always big endian. */\n#if !defined(DUK_USE_BYTEORDER) && defined(DUK_F_M68K)\n#define DUK_USE_BYTEORDER 3\n#endif\n#elif defined(DUK_F_AMIGAOS)\n/* --- AmigaOS --- */\n#if defined(DUK_F_M68K)\n/* AmigaOS on M68k */\n#define DUK_USE_DATE_NOW_TIME\n#define DUK_USE_DATE_TZO_GMTIME\n/* no parsing (not an error) */\n#define DUK_USE_DATE_FMT_STRFTIME\n#include <time.h>\n#elif defined(DUK_F_PPC)\n#define DUK_USE_DATE_NOW_GETTIMEOFDAY\n#define DUK_USE_DATE_TZO_GMTIME_R\n#define DUK_USE_DATE_PRS_STRPTIME\n#define DUK_USE_DATE_FMT_STRFTIME\n#include <time.h>\n#if !defined(UINTPTR_MAX)\n#define UINTPTR_MAX UINT_MAX\n#endif\n#else\n#error AmigaOS but not M68K/PPC, not supported now\n#endif\n\n#define DUK_USE_OS_STRING \"amigaos\"\n\n/* AmigaOS on M68K or PPC is always big endian. */\n#if !defined(DUK_USE_BYTEORDER) && (defined(DUK_F_M68K) || defined(DUK_F_PPC))\n#define DUK_USE_BYTEORDER 3\n#endif\n#elif defined(DUK_F_DURANGO)\n/* --- Durango (XboxOne) --- */\n/* Durango = XboxOne\n * Configuration is nearly identical to Windows, except for\n * DUK_USE_DATE_TZO_WINDOWS.\n */\n\n/* Initial fix: disable secure CRT related warnings when compiling Duktape\n * itself (must be defined before including Windows headers).  Don't define\n * for user code including duktape.h.\n */\n#if defined(DUK_COMPILING_DUKTAPE) && !defined(_CRT_SECURE_NO_WARNINGS)\n#define _CRT_SECURE_NO_WARNINGS\n#endif\n\n/* MSVC does not have sys/param.h */\n#define DUK_USE_DATE_NOW_WINDOWS\n#define DUK_USE_DATE_TZO_WINDOWS_NO_DST\n/* Note: PRS and FMT are intentionally left undefined for now.  This means\n * there is no platform specific date parsing/formatting but there is still\n * the ISO 8601 standard format.\n */\n#if defined(DUK_COMPILING_DUKTAPE)\n/* Only include when compiling Duktape to avoid polluting application build\n * with a lot of unnecessary defines.\n */\n#include <windows.h>\n#endif\n\n#define DUK_USE_OS_STRING \"durango\"\n\n#if !defined(DUK_USE_BYTEORDER)\n#define DUK_USE_BYTEORDER 1\n#endif\n#elif defined(DUK_F_WINDOWS)\n/* --- Windows --- */\n/* Windows version can't obviously be determined at compile time,\n * but _WIN32_WINNT indicates the minimum version targeted:\n * - https://msdn.microsoft.com/en-us/library/6sehtctf.aspx\n */\n\n/* Initial fix: disable secure CRT related warnings when compiling Duktape\n * itself (must be defined before including Windows headers).  Don't define\n * for user code including duktape.h.\n */\n#if defined(DUK_COMPILING_DUKTAPE) && !defined(_CRT_SECURE_NO_WARNINGS)\n#define _CRT_SECURE_NO_WARNINGS\n#endif\n\n/* Windows 32-bit and 64-bit are currently the same. */\n/* MSVC does not have sys/param.h */\n\n#if defined(DUK_COMPILING_DUKTAPE)\n/* Only include when compiling Duktape to avoid polluting application build\n * with a lot of unnecessary defines.\n */\n#include <windows.h>\n#endif\n\n/* GetSystemTimePreciseAsFileTime() available from Windows 8:\n * https://msdn.microsoft.com/en-us/library/windows/desktop/hh706895(v=vs.85).aspx\n */\n#if defined(DUK_USE_DATE_NOW_WINDOWS_SUBMS) || defined(DUK_USE_DATE_NOW_WINDOWS)\n/* User forced provider. */\n#else\n#if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0602)\n#define DUK_USE_DATE_NOW_WINDOWS_SUBMS\n#else\n#define DUK_USE_DATE_NOW_WINDOWS\n#endif\n#endif\n\n#define DUK_USE_DATE_TZO_WINDOWS\n\n/* Note: PRS and FMT are intentionally left undefined for now.  This means\n * there is no platform specific date parsing/formatting but there is still\n * the ISO 8601 standard format.\n */\n\n/* QueryPerformanceCounter() may go backwards in Windows XP, so enable for\n * Vista and later: https://msdn.microsoft.com/en-us/library/windows/desktop/dn553408(v=vs.85).aspx#qpc_support_in_windows_versions\n */\n#if !defined(DUK_USE_GET_MONOTONIC_TIME_WINDOWS_QPC) && \\\n    defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0600)\n#define DUK_USE_GET_MONOTONIC_TIME_WINDOWS_QPC\n#endif\n\n#define DUK_USE_OS_STRING \"windows\"\n\n/* On Windows, assume we're little endian.  Even Itanium which has a\n * configurable endianness runs little endian in Windows.\n */\n#if !defined(DUK_USE_BYTEORDER)\n#define DUK_USE_BYTEORDER 1\n#endif\n#elif defined(DUK_F_FLASHPLAYER)\n/* --- Flashplayer (Crossbridge) --- */\n#define DUK_USE_DATE_NOW_GETTIMEOFDAY\n#define DUK_USE_DATE_TZO_GMTIME_R\n#define DUK_USE_DATE_PRS_STRPTIME\n#define DUK_USE_DATE_FMT_STRFTIME\n#include <endian.h>\n#include <sys/param.h>\n#include <sys/time.h>\n#include <time.h>\n\n#define DUK_USE_OS_STRING \"flashplayer\"\n\n#if !defined(DUK_USE_BYTEORDER) && defined(DUK_F_FLASHPLAYER)\n#define DUK_USE_BYTEORDER 1\n#endif\n#elif defined(DUK_F_QNX)\n/* --- QNX --- */\n#if defined(DUK_F_QNX) && defined(DUK_COMPILING_DUKTAPE)\n/* See: /opt/qnx650/target/qnx6/usr/include/sys/platform.h */\n#define _XOPEN_SOURCE    600\n#define _POSIX_C_SOURCE  200112L\n#endif\n\n#define DUK_USE_DATE_NOW_GETTIMEOFDAY\n#define DUK_USE_DATE_TZO_GMTIME_R\n#define DUK_USE_DATE_PRS_STRPTIME\n#define DUK_USE_DATE_FMT_STRFTIME\n#include <sys/types.h>\n#include <sys/param.h>\n#include <sys/time.h>\n#include <time.h>\n\n#define DUK_USE_OS_STRING \"qnx\"\n#elif defined(DUK_F_TINSPIRE)\n/* --- TI-Nspire --- */\n#if defined(DUK_COMPILING_DUKTAPE) && !defined(_XOPEN_SOURCE)\n#define _XOPEN_SOURCE    /* e.g. strptime */\n#endif\n\n#define DUK_USE_DATE_NOW_GETTIMEOFDAY\n#define DUK_USE_DATE_TZO_GMTIME_R\n#define DUK_USE_DATE_PRS_STRPTIME\n#define DUK_USE_DATE_FMT_STRFTIME\n#include <sys/types.h>\n#include <sys/param.h>\n#include <sys/time.h>\n#include <time.h>\n\n#define DUK_USE_OS_STRING \"tinspire\"\n#elif defined(DUK_F_EMSCRIPTEN)\n/* --- Emscripten --- */\n#if defined(DUK_COMPILING_DUKTAPE)\n#if !defined(_POSIX_C_SOURCE)\n#define _POSIX_C_SOURCE  200809L\n#endif\n#if !defined(_GNU_SOURCE)\n#define _GNU_SOURCE      /* e.g. getdate_r */\n#endif\n#if !defined(_XOPEN_SOURCE)\n#define _XOPEN_SOURCE    /* e.g. strptime */\n#endif\n#endif  /* DUK_COMPILING_DUKTAPE */\n\n#include <sys/types.h>\n#if defined(DUK_F_BCC)\n/* no endian.h */\n#else\n#include <endian.h>\n#endif  /* DUK_F_BCC */\n#include <sys/param.h>\n#include <sys/time.h>\n#include <time.h>\n#include <stdint.h>\n\n#define DUK_USE_DATE_NOW_GETTIMEOFDAY\n#define DUK_USE_DATE_TZO_GMTIME_R\n#define DUK_USE_DATE_PRS_STRPTIME\n#define DUK_USE_DATE_FMT_STRFTIME\n\n#define DUK_USE_OS_STRING \"emscripten\"\n#elif defined(DUK_F_LINUX)\n/* --- Linux --- */\n#if defined(DUK_COMPILING_DUKTAPE)\n#if !defined(_POSIX_C_SOURCE)\n#define _POSIX_C_SOURCE  200809L\n#endif\n#if !defined(_GNU_SOURCE)\n#define _GNU_SOURCE      /* e.g. getdate_r */\n#endif\n#if !defined(_XOPEN_SOURCE)\n#define _XOPEN_SOURCE    /* e.g. strptime */\n#endif\n#endif  /* DUK_COMPILING_DUKTAPE */\n\n#include <sys/types.h>\n#if defined(DUK_F_BCC)\n/* no endian.h or stdint.h */\n#else\n#include <endian.h>\n#include <stdint.h>\n#endif  /* DUK_F_BCC */\n#include <sys/param.h>\n#include <sys/time.h>\n#include <time.h>\n\n#define DUK_USE_DATE_NOW_GETTIMEOFDAY\n#define DUK_USE_DATE_TZO_GMTIME_R\n#define DUK_USE_DATE_PRS_STRPTIME\n#define DUK_USE_DATE_FMT_STRFTIME\n\n#if 0  /* XXX: safe condition? */\n#define DUK_USE_GET_MONOTONIC_TIME_CLOCK_GETTIME\n#endif\n\n#define DUK_USE_OS_STRING \"linux\"\n#elif defined(DUK_F_SUN)\n/* --- Solaris --- */\n#define DUK_USE_DATE_NOW_GETTIMEOFDAY\n#define DUK_USE_DATE_TZO_GMTIME_R\n#define DUK_USE_DATE_PRS_STRPTIME\n#define DUK_USE_DATE_FMT_STRFTIME\n\n#include <sys/types.h>\n#if defined(DUK_F_OLD_SOLARIS)\n/* Old Solaris with no endian.h, stdint.h */\n#define DUK_F_NO_STDINT_H\n#if !defined(DUK_USE_BYTEORDER)\n#define DUK_USE_BYTEORDER 3\n#endif\n#else  /* DUK_F_OLD_SOLARIS */\n#include <ast/endian.h>\n#endif  /* DUK_F_OLD_SOLARIS */\n\n#include <sys/param.h>\n#include <sys/time.h>\n#include <time.h>\n\n#define DUK_USE_OS_STRING \"solaris\"\n#elif defined(DUK_F_AIX)\n/* --- AIX --- */\n#if !defined(DUK_USE_BYTEORDER)\n#define DUK_USE_BYTEORDER 3\n#endif\n#define DUK_USE_DATE_NOW_GETTIMEOFDAY\n#define DUK_USE_DATE_TZO_GMTIME_R\n#define DUK_USE_DATE_PRS_STRPTIME\n#define DUK_USE_DATE_FMT_STRFTIME\n#include <sys/param.h>\n#include <sys/time.h>\n#include <time.h>\n\n#define DUK_USE_OS_STRING \"aix\"\n#elif defined(DUK_F_HPUX)\n/* --- HPUX --- */\n#define DUK_F_NO_STDINT_H\n#if !defined(DUK_USE_BYTEORDER)\n#define DUK_USE_BYTEORDER 3\n#endif\n#define DUK_USE_DATE_NOW_GETTIMEOFDAY\n#define DUK_USE_DATE_TZO_GMTIME_R\n#define DUK_USE_DATE_PRS_STRPTIME\n#define DUK_USE_DATE_FMT_STRFTIME\n#include <sys/param.h>\n#include <sys/time.h>\n#include <time.h>\n\n#define DUK_USE_OS_STRING \"hpux\"\n#elif defined(DUK_F_POSIX)\n/* --- Generic POSIX --- */\n#define DUK_USE_DATE_NOW_GETTIMEOFDAY\n#define DUK_USE_DATE_TZO_GMTIME_R\n#define DUK_USE_DATE_PRS_STRPTIME\n#define DUK_USE_DATE_FMT_STRFTIME\n#include <sys/types.h>\n#include <endian.h>\n#include <sys/param.h>\n#include <sys/time.h>\n#include <time.h>\n\n#define DUK_USE_OS_STRING \"posix\"\n#elif defined(DUK_F_CYGWIN)\n/* --- Cygwin --- */\n/* don't use strptime() for now */\n#define DUK_USE_DATE_NOW_GETTIMEOFDAY\n#define DUK_USE_DATE_TZO_GMTIME_R\n#define DUK_USE_DATE_FMT_STRFTIME\n#include <sys/types.h>\n#include <endian.h>\n#include <sys/param.h>\n#include <sys/time.h>\n#include <time.h>\n\n#define DUK_JMPBUF_TYPE       jmp_buf\n#define DUK_SETJMP(jb)        _setjmp((jb))\n#define DUK_LONGJMP(jb)       _longjmp((jb), 1)\n\n#define DUK_USE_OS_STRING \"windows\"\n#elif defined(DUK_F_UNIX)\n/* --- Generic UNIX --- */\n#define DUK_USE_DATE_NOW_GETTIMEOFDAY\n#define DUK_USE_DATE_TZO_GMTIME_R\n#define DUK_USE_DATE_PRS_STRPTIME\n#define DUK_USE_DATE_FMT_STRFTIME\n#include <time.h>\n#include <sys/time.h>\n#define DUK_USE_OS_STRING \"unknown\"\n#else\n/* --- Generic fallback --- */\n/* The most portable current time provider is time(), but it only has a\n * one second resolution.\n */\n#define DUK_USE_DATE_NOW_TIME\n\n/* The most portable way to figure out local time offset is gmtime(),\n * but it's not thread safe so use with caution.\n */\n#define DUK_USE_DATE_TZO_GMTIME\n\n/* Avoid custom date parsing and formatting for portability. */\n#undef DUK_USE_DATE_PRS_STRPTIME\n#undef DUK_USE_DATE_FMT_STRFTIME\n\n/* Rely on C89 headers only; time.h must be here. */\n#include <time.h>\n\n#define DUK_USE_OS_STRING \"unknown\"\n#endif  /* autodetect platform */\n\n/* Shared includes: C89 */\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <stdarg.h>  /* varargs */\n#include <setjmp.h>\n#include <stddef.h>  /* e.g. ptrdiff_t */\n#include <math.h>\n#include <limits.h>\n\n/* date.h is omitted, and included per platform */\n\n/* Shared includes: stdint.h is C99 */\n#if defined(DUK_F_NO_STDINT_H)\n/* stdint.h not available */\n#else\n/* Technically C99 (C++11) but found in many systems.  On some systems\n * __STDC_LIMIT_MACROS and __STDC_CONSTANT_MACROS must be defined before\n * including stdint.h (see above).\n */\n#include <stdint.h>\n#endif\n\n#if defined(DUK_F_CPP)\n#include <exception>  /* std::exception */\n#endif\n\n/*\n *  Architecture autodetection\n */\n\n#if defined(DUK_F_X86)\n/* --- x86 --- */\n#define DUK_USE_ARCH_STRING \"x86\"\n#if !defined(DUK_USE_BYTEORDER)\n#define DUK_USE_BYTEORDER 1\n#endif\n/* XXX: This is technically not guaranteed because it's possible to configure\n * an x86 to require aligned accesses with Alignment Check (AC) flag.\n */\n#if !defined(DUK_USE_ALIGN_BY)\n#define DUK_USE_ALIGN_BY 1\n#endif\n#define DUK_USE_PACKED_TVAL\n#define DUK_F_PACKED_TVAL_PROVIDED\n#elif defined(DUK_F_X64)\n/* --- x64 --- */\n#define DUK_USE_ARCH_STRING \"x64\"\n#if !defined(DUK_USE_BYTEORDER)\n#define DUK_USE_BYTEORDER 1\n#endif\n/* XXX: This is technically not guaranteed because it's possible to configure\n * an x86 to require aligned accesses with Alignment Check (AC) flag.\n */\n#if !defined(DUK_USE_ALIGN_BY)\n#define DUK_USE_ALIGN_BY 1\n#endif\n#undef DUK_USE_PACKED_TVAL\n#define DUK_F_PACKED_TVAL_PROVIDED\n#elif defined(DUK_F_X32)\n/* --- x32 --- */\n#define DUK_USE_ARCH_STRING \"x32\"\n#if !defined(DUK_USE_BYTEORDER)\n#define DUK_USE_BYTEORDER 1\n#endif\n/* XXX: This is technically not guaranteed because it's possible to configure\n * an x86 to require aligned accesses with Alignment Check (AC) flag.\n */\n#if !defined(DUK_USE_ALIGN_BY)\n#define DUK_USE_ALIGN_BY 1\n#endif\n#define DUK_USE_PACKED_TVAL\n#define DUK_F_PACKED_TVAL_PROVIDED\n#elif defined(DUK_F_ARM32)\n/* --- ARM 32-bit --- */\n#define DUK_USE_ARCH_STRING \"arm32\"\n/* Byte order varies, so rely on autodetect. */\n#if !defined(DUK_USE_ALIGN_BY)\n#define DUK_USE_ALIGN_BY 4\n#endif\n#define DUK_USE_PACKED_TVAL\n#define DUK_F_PACKED_TVAL_PROVIDED\n#elif defined(DUK_F_ARM64)\n/* --- ARM 64-bit --- */\n#define DUK_USE_ARCH_STRING \"arm64\"\n/* Byte order varies, so rely on autodetect. */\n#if !defined(DUK_USE_ALIGN_BY)\n#define DUK_USE_ALIGN_BY 8\n#endif\n#undef DUK_USE_PACKED_TVAL\n#define DUK_F_PACKED_TVAL_PROVIDED\n#elif defined(DUK_F_MIPS32)\n/* --- MIPS 32-bit --- */\n#define DUK_USE_ARCH_STRING \"mips32\"\n/* MIPS byte order varies so rely on autodetection. */\n#if !defined(DUK_USE_ALIGN_BY)\n#define DUK_USE_ALIGN_BY 8\n#endif\n#define DUK_USE_PACKED_TVAL\n#define DUK_F_PACKED_TVAL_PROVIDED\n#elif defined(DUK_F_MIPS64)\n/* --- MIPS 64-bit --- */\n#define DUK_USE_ARCH_STRING \"mips64\"\n/* MIPS byte order varies so rely on autodetection. */\n#if !defined(DUK_USE_ALIGN_BY)\n#define DUK_USE_ALIGN_BY 8\n#endif\n#undef DUK_USE_PACKED_TVAL\n#define DUK_F_PACKED_TVAL_PROVIDED\n#elif defined(DUK_F_PPC32)\n/* --- PowerPC 32-bit --- */\n#define DUK_USE_ARCH_STRING \"ppc32\"\n#if !defined(DUK_USE_BYTEORDER)\n#define DUK_USE_BYTEORDER 3\n#endif\n#if !defined(DUK_USE_ALIGN_BY)\n#define DUK_USE_ALIGN_BY 8\n#endif\n#define DUK_USE_PACKED_TVAL\n#define DUK_F_PACKED_TVAL_PROVIDED\n#elif defined(DUK_F_PPC64)\n/* --- PowerPC 64-bit --- */\n#define DUK_USE_ARCH_STRING \"ppc64\"\n#if !defined(DUK_USE_BYTEORDER)\n#define DUK_USE_BYTEORDER 3\n#endif\n#if !defined(DUK_USE_ALIGN_BY)\n#define DUK_USE_ALIGN_BY 8\n#endif\n#undef DUK_USE_PACKED_TVAL\n#define DUK_F_PACKED_TVAL_PROVIDED\n#elif defined(DUK_F_SPARC32)\n/* --- SPARC 32-bit --- */\n#define DUK_USE_ARCH_STRING \"sparc32\"\n/* SPARC byte order varies so rely on autodetection. */\n#if !defined(DUK_USE_ALIGN_BY)\n#define DUK_USE_ALIGN_BY 8\n#endif\n#define DUK_USE_PACKED_TVAL\n#define DUK_F_PACKED_TVAL_PROVIDED\n#elif defined(DUK_F_SPARC64)\n/* --- SPARC 64-bit --- */\n#define DUK_USE_ARCH_STRING \"sparc64\"\n/* SPARC byte order varies so rely on autodetection. */\n#if !defined(DUK_USE_ALIGN_BY)\n#define DUK_USE_ALIGN_BY 8\n#endif\n#undef DUK_USE_PACKED_TVAL\n#define DUK_F_PACKED_TVAL_PROVIDED\n#elif defined(DUK_F_SUPERH)\n/* --- SuperH --- */\n#define DUK_USE_ARCH_STRING \"sh\"\n/* Byte order varies, rely on autodetection. */\n/* Based on 'make checkalign' there are no alignment requirements on\n * Linux SH4, but align by 4 is probably a good basic default.\n */\n#if !defined(DUK_USE_ALIGN_BY)\n#define DUK_USE_ALIGN_BY 4\n#endif\n#define DUK_USE_PACKED_TVAL\n#define DUK_F_PACKED_TVAL_PROVIDED\n#elif defined(DUK_F_M68K)\n/* --- Motorola 68k --- */\n#define DUK_USE_ARCH_STRING \"m68k\"\n#if !defined(DUK_USE_BYTEORDER)\n#define DUK_USE_BYTEORDER 3\n#endif\n#if !defined(DUK_USE_ALIGN_BY)\n#define DUK_USE_ALIGN_BY 8\n#endif\n#define DUK_USE_PACKED_TVAL\n#define DUK_F_PACKED_TVAL_PROVIDED\n#elif defined(DUK_F_EMSCRIPTEN)\n/* --- Emscripten --- */\n#define DUK_USE_ARCH_STRING \"emscripten\"\n#if !defined(DUK_USE_BYTEORDER)\n#define DUK_USE_BYTEORDER 1\n#endif\n#if !defined(DUK_USE_ALIGN_BY)\n#define DUK_USE_ALIGN_BY 8\n#endif\n#undef DUK_USE_PACKED_TVAL\n#define DUK_F_PACKED_TVAL_PROVIDED\n#else\n/* --- Generic --- */\n/* These are necessary wild guesses. */\n#define DUK_USE_ARCH_STRING \"generic\"\n/* Rely on autodetection for byte order, alignment, and packed tval. */\n#endif  /* autodetect architecture */\n\n/*\n *  Compiler autodetection\n */\n\n#if defined(DUK_F_CLANG)\n/* --- Clang --- */\n#if defined(DUK_F_C99) || defined(DUK_F_CPP11)\n/* C99 / C++11 and above: rely on va_copy() which is required. */\n#define DUK_VA_COPY(dest,src) va_copy(dest,src)\n#else\n/* Clang: assume we have __va_copy() in non-C99 mode. */\n#define DUK_VA_COPY(dest,src) __va_copy(dest,src)\n#endif\n\n#define DUK_NORETURN(decl)  decl __attribute__((noreturn))\n\n#if defined(__clang__) && defined(__has_builtin)\n#if __has_builtin(__builtin_unreachable)\n#define DUK_UNREACHABLE()  do { __builtin_unreachable(); } while (0)\n#endif\n#endif\n\n#define DUK_USE_BRANCH_HINTS\n#define DUK_LIKELY(x)    __builtin_expect((x), 1)\n#define DUK_UNLIKELY(x)  __builtin_expect((x), 0)\n#if defined(__clang__) && defined(__has_builtin)\n#if __has_builtin(__builtin_unpredictable)\n#define DUK_UNPREDICTABLE(x)  __builtin_unpredictable((x))\n#endif\n#endif\n\n#if defined(DUK_F_C99) || defined(DUK_F_CPP11)\n#define DUK_NOINLINE        __attribute__((noinline))\n#define DUK_INLINE          inline\n#define DUK_ALWAYS_INLINE   inline __attribute__((always_inline))\n#endif\n\n/* DUK_HOT */\n/* DUK_COLD */\n\n#if defined(DUK_F_DLL_BUILD) && defined(DUK_F_WINDOWS)\n/* MSVC dllexport/dllimport: appropriate __declspec depends on whether we're\n * compiling Duktape or the application.\n */\n#if defined(DUK_COMPILING_DUKTAPE)\n#define DUK_EXTERNAL_DECL  extern __declspec(dllexport)\n#define DUK_EXTERNAL       __declspec(dllexport)\n#else\n#define DUK_EXTERNAL_DECL  extern __declspec(dllimport)\n#define DUK_EXTERNAL       should_not_happen\n#endif\n#if defined(DUK_SINGLE_FILE)\n#define DUK_INTERNAL_DECL  static\n#define DUK_INTERNAL       static\n#else\n#define DUK_INTERNAL_DECL  extern\n#define DUK_INTERNAL       /*empty*/\n#endif\n#define DUK_LOCAL_DECL     static\n#define DUK_LOCAL          static\n#else\n#define DUK_EXTERNAL_DECL  __attribute__ ((visibility(\"default\"))) extern\n#define DUK_EXTERNAL       __attribute__ ((visibility(\"default\")))\n#if defined(DUK_SINGLE_FILE)\n#if (defined(DUK_F_GCC_VERSION) && DUK_F_GCC_VERSION >= 30101) || defined(DUK_F_CLANG)\n/* Minimize warnings for unused internal functions with GCC >= 3.1.1 and\n * Clang.  Based on documentation it should suffice to have the attribute\n * in the declaration only, but in practice some warnings are generated unless\n * the attribute is also applied to the definition.\n */\n#define DUK_INTERNAL_DECL  static __attribute__ ((unused))\n#define DUK_INTERNAL       static __attribute__ ((unused))\n#else\n#define DUK_INTERNAL_DECL  static\n#define DUK_INTERNAL       static\n#endif\n#else\n#if (defined(DUK_F_GCC_VERSION) && DUK_F_GCC_VERSION >= 30101) || defined(DUK_F_CLANG)\n#define DUK_INTERNAL_DECL  __attribute__ ((visibility(\"hidden\"))) __attribute__ ((unused)) extern\n#define DUK_INTERNAL       __attribute__ ((visibility(\"hidden\"))) __attribute__ ((unused))\n#else\n#define DUK_INTERNAL_DECL  __attribute__ ((visibility(\"hidden\"))) extern\n#define DUK_INTERNAL       __attribute__ ((visibility(\"hidden\")))\n#endif\n#endif\n#define DUK_LOCAL_DECL     static\n#define DUK_LOCAL          static\n#endif\n\n#if defined(DUK_F_CPP)\n#define DUK_USE_COMPILER_STRING \"clang\"\n#else\n#define DUK_USE_COMPILER_STRING \"clang\"\n#endif\n\n#undef DUK_USE_VARIADIC_MACROS\n#if defined(DUK_F_C99) || defined(DUK_F_CPP11)\n#define DUK_USE_VARIADIC_MACROS\n#endif\n\n#define DUK_USE_UNION_INITIALIZERS\n\n#undef DUK_USE_FLEX_C99\n#undef DUK_USE_FLEX_ZEROSIZE\n#undef DUK_USE_FLEX_ONESIZE\n#if defined(DUK_F_C99)\n#define DUK_USE_FLEX_C99\n#else\n#define DUK_USE_FLEX_ZEROSIZE\n#endif\n\n#undef DUK_USE_GCC_PRAGMAS\n#define DUK_USE_PACK_CLANG_ATTR\n#elif defined(DUK_F_GCC)\n/* --- GCC --- */\n#if defined(DUK_F_C99) || defined(DUK_F_CPP11)\n/* C99 / C++11 and above: rely on va_copy() which is required. */\n#define DUK_VA_COPY(dest,src) va_copy(dest,src)\n#else\n/* GCC: assume we have __va_copy() in non-C99 mode. */\n#define DUK_VA_COPY(dest,src) __va_copy(dest,src)\n#endif\n\n#if defined(DUK_F_GCC_VERSION) && (DUK_F_GCC_VERSION >= 20500L)\n/* since gcc-2.5 */\n#define DUK_NORETURN(decl)  decl __attribute__((noreturn))\n#endif\n\n#if defined(DUK_F_GCC_VERSION) && (DUK_F_GCC_VERSION >= 40500L)\n/* since gcc-4.5 */\n#define DUK_UNREACHABLE()  do { __builtin_unreachable(); } while (0)\n#endif\n\n#define DUK_USE_BRANCH_HINTS\n#if defined(DUK_F_GCC_VERSION) && (DUK_F_GCC_VERSION >= 40500L)\n/* GCC: test not very accurate; enable only in relatively recent builds\n * because of bugs in gcc-4.4 (http://lists.debian.org/debian-gcc/2010/04/msg00000.html)\n */\n#define DUK_LIKELY(x)    __builtin_expect((x), 1)\n#define DUK_UNLIKELY(x)  __builtin_expect((x), 0)\n#endif\n/* XXX: equivalent of clang __builtin_unpredictable? */\n\n#if (defined(DUK_F_C99) || defined(DUK_F_CPP11)) && \\\n    defined(DUK_F_GCC_VERSION) && (DUK_F_GCC_VERSION >= 30101)\n#define DUK_NOINLINE        __attribute__((noinline))\n#define DUK_INLINE          inline\n#define DUK_ALWAYS_INLINE   inline __attribute__((always_inline))\n#endif\n\n#if (defined(DUK_F_C99) || defined(DUK_F_CPP11)) && \\\n    defined(DUK_F_GCC_VERSION) && (DUK_F_GCC_VERSION >= 40300)\n#define DUK_HOT             __attribute__((hot))\n#define DUK_COLD            __attribute__((cold))\n#endif\n\n#if defined(DUK_F_DLL_BUILD) && defined(DUK_F_WINDOWS)\n/* MSVC dllexport/dllimport: appropriate __declspec depends on whether we're\n * compiling Duktape or the application.\n */\n#if defined(DUK_COMPILING_DUKTAPE)\n#define DUK_EXTERNAL_DECL  extern __declspec(dllexport)\n#define DUK_EXTERNAL       __declspec(dllexport)\n#else\n#define DUK_EXTERNAL_DECL  extern __declspec(dllimport)\n#define DUK_EXTERNAL       should_not_happen\n#endif\n#if defined(DUK_SINGLE_FILE)\n#define DUK_INTERNAL_DECL  static\n#define DUK_INTERNAL       static\n#else\n#define DUK_INTERNAL_DECL  extern\n#define DUK_INTERNAL       /*empty*/\n#endif\n#define DUK_LOCAL_DECL     static\n#define DUK_LOCAL          static\n#elif defined(DUK_F_GCC_VERSION) && (DUK_F_GCC_VERSION >= 40000)\n#define DUK_EXTERNAL_DECL  __attribute__ ((visibility(\"default\"))) extern\n#define DUK_EXTERNAL       __attribute__ ((visibility(\"default\")))\n#if defined(DUK_SINGLE_FILE)\n#if (defined(DUK_F_GCC_VERSION) && DUK_F_GCC_VERSION >= 30101) || defined(DUK_F_CLANG)\n/* Minimize warnings for unused internal functions with GCC >= 3.1.1 and\n * Clang.  Based on documentation it should suffice to have the attribute\n * in the declaration only, but in practice some warnings are generated unless\n * the attribute is also applied to the definition.\n */\n#define DUK_INTERNAL_DECL  static __attribute__ ((unused))\n#define DUK_INTERNAL       static __attribute__ ((unused))\n#else\n#define DUK_INTERNAL_DECL  static\n#define DUK_INTERNAL       static\n#endif\n#else\n#if (defined(DUK_F_GCC_VERSION) && DUK_F_GCC_VERSION >= 30101) || defined(DUK_F_CLANG)\n#define DUK_INTERNAL_DECL  __attribute__ ((visibility(\"hidden\"))) __attribute__ ((unused)) extern\n#define DUK_INTERNAL       __attribute__ ((visibility(\"hidden\"))) __attribute__ ((unused))\n#else\n#define DUK_INTERNAL_DECL  __attribute__ ((visibility(\"hidden\"))) extern\n#define DUK_INTERNAL       __attribute__ ((visibility(\"hidden\")))\n#endif\n#endif\n#define DUK_LOCAL_DECL     static\n#define DUK_LOCAL          static\n#endif\n\n#if defined(DUK_F_MINGW)\n#if defined(DUK_F_CPP)\n#define DUK_USE_COMPILER_STRING \"mingw++\"\n#else\n#define DUK_USE_COMPILER_STRING \"mingw\"\n#endif\n#else\n#if defined(DUK_F_CPP)\n#define DUK_USE_COMPILER_STRING \"g++\"\n#else\n#define DUK_USE_COMPILER_STRING \"gcc\"\n#endif\n#endif\n\n#undef DUK_USE_VARIADIC_MACROS\n#if defined(DUK_F_C99) || (defined(DUK_F_CPP11) && defined(__GNUC__))\n#define DUK_USE_VARIADIC_MACROS\n#endif\n\n#define DUK_USE_UNION_INITIALIZERS\n\n#undef DUK_USE_FLEX_C99\n#undef DUK_USE_FLEX_ZEROSIZE\n#undef DUK_USE_FLEX_ONESIZE\n#if defined(DUK_F_C99)\n#define DUK_USE_FLEX_C99\n#else\n#define DUK_USE_FLEX_ZEROSIZE\n#endif\n\n#if defined(DUK_F_GCC_VERSION) && (DUK_F_GCC_VERSION >= 40600)\n#define DUK_USE_GCC_PRAGMAS\n#else\n#undef DUK_USE_GCC_PRAGMAS\n#endif\n\n#define DUK_USE_PACK_GCC_ATTR\n#elif defined(DUK_F_MSVC)\n/* --- MSVC --- */\n/* http://msdn.microsoft.com/en-us/library/aa235362(VS.60).aspx */\n#define DUK_NORETURN(decl)  __declspec(noreturn) decl\n\n/* XXX: DUK_UNREACHABLE for msvc? */\n\n#undef DUK_USE_BRANCH_HINTS\n\n/* XXX: DUK_LIKELY, DUK_UNLIKELY for msvc? */\n/* XXX: DUK_NOINLINE, DUK_INLINE, DUK_ALWAYS_INLINE for msvc? */\n\n#if defined(DUK_F_DLL_BUILD) && defined(DUK_F_WINDOWS)\n/* MSVC dllexport/dllimport: appropriate __declspec depends on whether we're\n * compiling Duktape or the application.\n */\n#if defined(DUK_COMPILING_DUKTAPE)\n#define DUK_EXTERNAL_DECL  extern __declspec(dllexport)\n#define DUK_EXTERNAL       __declspec(dllexport)\n#else\n#define DUK_EXTERNAL_DECL  extern __declspec(dllimport)\n#define DUK_EXTERNAL       should_not_happen\n#endif\n#if defined(DUK_SINGLE_FILE)\n#define DUK_INTERNAL_DECL  static\n#define DUK_INTERNAL       static\n#else\n#define DUK_INTERNAL_DECL  extern\n#define DUK_INTERNAL       /*empty*/\n#endif\n#define DUK_LOCAL_DECL     static\n#define DUK_LOCAL          static\n#endif\n\n#if defined(DUK_F_CPP)\n#define DUK_USE_COMPILER_STRING \"msvc++\"\n#else\n#define DUK_USE_COMPILER_STRING \"msvc\"\n#endif\n\n#undef DUK_USE_VARIADIC_MACROS\n#if defined(DUK_F_C99)\n#define DUK_USE_VARIADIC_MACROS\n#elif defined(_MSC_VER) && (_MSC_VER >= 1400)\n/* VS2005+ should have variadic macros even when they're not C99. */\n#define DUK_USE_VARIADIC_MACROS\n#endif\n\n#undef DUK_USE_UNION_INITIALIZERS\n#if defined(_MSC_VER) && (_MSC_VER >= 1800)\n/* VS2013+ supports union initializers but there's a bug involving union-inside-struct:\n * https://connect.microsoft.com/VisualStudio/feedback/details/805981\n * The bug was fixed (at least) in VS2015 so check for VS2015 for now:\n * https://blogs.msdn.microsoft.com/vcblog/2015/07/01/c-compiler-front-end-fixes-in-vs2015/\n * Manually tested using VS2013, CL reports 18.00.31101, so enable for VS2013 too.\n */\n#define DUK_USE_UNION_INITIALIZERS\n#endif\n\n#undef DUK_USE_FLEX_C99\n#undef DUK_USE_FLEX_ZEROSIZE\n#undef DUK_USE_FLEX_ONESIZE\n#if defined(DUK_F_C99)\n#define DUK_USE_FLEX_C99\n#else\n#define DUK_USE_FLEX_ZEROSIZE\n#endif\n\n#undef DUK_USE_GCC_PRAGMAS\n\n#define DUK_USE_PACK_MSVC_PRAGMA\n\n/* These have been tested from VS2008 onwards; may work in older VS versions\n * too but not enabled by default.\n */\n#if defined(_MSC_VER) && (_MSC_VER >= 1500)\n#define DUK_NOINLINE        __declspec(noinline)\n#define DUK_INLINE          __inline\n#define DUK_ALWAYS_INLINE   __forceinline\n#endif\n\n#if defined(_MSC_VER) && (_MSC_VER >= 1900)\n#define DUK_SNPRINTF     snprintf\n#define DUK_VSNPRINTF    vsnprintf\n#else\n/* (v)snprintf() is missing before MSVC 2015.  Note that _(v)snprintf() does\n * NOT NUL terminate on truncation, but Duktape code never assumes that.\n * http://stackoverflow.com/questions/2915672/snprintf-and-visual-studio-2010\n */\n#define DUK_SNPRINTF     _snprintf\n#define DUK_VSNPRINTF    _vsnprintf\n#endif\n\n/* Avoid warning when doing DUK_UNREF(some_function). */\n#if defined(_MSC_VER) && (_MSC_VER < 1500)\n#pragma warning(disable: 4100 4101 4550 4551)\n#define DUK_UNREF(x)\n#else\n#define DUK_UNREF(x)  do { __pragma(warning(suppress:4100 4101 4550 4551)) (x); } while (0)\n#endif\n\n/* Older versions of MSVC don't support the LL/ULL suffix. */\n#define DUK_U64_CONSTANT(x) x##ui64\n#define DUK_I64_CONSTANT(x) x##i64\n#elif defined(DUK_F_EMSCRIPTEN)\n/* --- Emscripten --- */\n#define DUK_NORETURN(decl)  decl __attribute__((noreturn))\n\n#if defined(__clang__) && defined(__has_builtin)\n#if __has_builtin(__builtin_unreachable)\n#define DUK_UNREACHABLE()  do { __builtin_unreachable(); } while (0)\n#endif\n#endif\n\n#define DUK_USE_BRANCH_HINTS\n#define DUK_LIKELY(x)    __builtin_expect((x), 1)\n#define DUK_UNLIKELY(x)  __builtin_expect((x), 0)\n#if defined(__clang__) && defined(__has_builtin)\n#if __has_builtin(__builtin_unpredictable)\n#define DUK_UNPREDICTABLE(x)  __builtin_unpredictable((x))\n#endif\n#endif\n\n#if defined(DUK_F_C99) || defined(DUK_F_CPP11)\n#define DUK_NOINLINE        __attribute__((noinline))\n#define DUK_INLINE          inline\n#define DUK_ALWAYS_INLINE   inline __attribute__((always_inline))\n#endif\n\n#define DUK_EXTERNAL_DECL  __attribute__ ((visibility(\"default\"))) extern\n#define DUK_EXTERNAL       __attribute__ ((visibility(\"default\")))\n#if defined(DUK_SINGLE_FILE)\n#if (defined(DUK_F_GCC_VERSION) && DUK_F_GCC_VERSION >= 30101) || defined(DUK_F_CLANG)\n/* Minimize warnings for unused internal functions with GCC >= 3.1.1 and\n * Clang.  Based on documentation it should suffice to have the attribute\n * in the declaration only, but in practice some warnings are generated unless\n * the attribute is also applied to the definition.\n */\n#define DUK_INTERNAL_DECL  static __attribute__ ((unused))\n#define DUK_INTERNAL       static __attribute__ ((unused))\n#else\n#define DUK_INTERNAL_DECL  static\n#define DUK_INTERNAL       static\n#endif\n#else\n#if (defined(DUK_F_GCC_VERSION) && DUK_F_GCC_VERSION >= 30101) || defined(DUK_F_CLANG)\n#define DUK_INTERNAL_DECL  __attribute__ ((visibility(\"hidden\"))) __attribute__ ((unused)) extern\n#define DUK_INTERNAL       __attribute__ ((visibility(\"hidden\"))) __attribute__ ((unused))\n#else\n#define DUK_INTERNAL_DECL  __attribute__ ((visibility(\"hidden\"))) extern\n#define DUK_INTERNAL       __attribute__ ((visibility(\"hidden\")))\n#endif\n#endif\n#define DUK_LOCAL_DECL     static\n#define DUK_LOCAL          static\n\n#define DUK_USE_COMPILER_STRING \"emscripten\"\n\n#undef DUK_USE_VARIADIC_MACROS\n#if defined(DUK_F_C99) || defined(DUK_F_CPP11)\n#define DUK_USE_VARIADIC_MACROS\n#endif\n\n#define DUK_USE_UNION_INITIALIZERS\n\n#undef DUK_USE_FLEX_C99\n#undef DUK_USE_FLEX_ZEROSIZE\n#undef DUK_USE_FLEX_ONESIZE\n#if defined(DUK_F_C99)\n#define DUK_USE_FLEX_C99\n#else\n#define DUK_USE_FLEX_ZEROSIZE\n#endif\n\n#undef DUK_USE_GCC_PRAGMAS\n#define DUK_USE_PACK_CLANG_ATTR\n#elif defined(DUK_F_TINYC)\n/* --- TinyC --- */\n#undef DUK_USE_BRANCH_HINTS\n\n#if defined(DUK_F_CPP)\n#define DUK_USE_COMPILER_STRING \"tinyc++\"\n#else\n#define DUK_USE_COMPILER_STRING \"tinyc\"\n#endif\n\n/* http://bellard.org/tcc/tcc-doc.html#SEC7 */\n#define DUK_USE_VARIADIC_MACROS\n\n#define DUK_USE_UNION_INITIALIZERS\n\n/* Most portable, wastes space */\n#define DUK_USE_FLEX_ONESIZE\n\n/* Most portable, potentially wastes space */\n#define DUK_USE_PACK_DUMMY_MEMBER\n#elif defined(DUK_F_VBCC)\n/* --- VBCC --- */\n#undef DUK_USE_BRANCH_HINTS\n\n#if defined(DUK_F_CPP)\n#define DUK_USE_COMPILER_STRING \"vbcc-c++\"\n#else\n#define DUK_USE_COMPILER_STRING \"vbcc\"\n#endif\n\n#undef DUK_USE_VARIADIC_MACROS\n#if defined(DUK_F_C99) || defined(DUK_F_CPP11)\n#define DUK_USE_VARIADIC_MACROS\n#endif\n\n/* VBCC supports C99 so check only for C99 for union initializer support.\n * Designated union initializers would possibly work even without a C99 check.\n */\n#undef DUK_USE_UNION_INITIALIZERS\n#if defined(DUK_F_C99)\n#define DUK_USE_UNION_INITIALIZERS\n#endif\n\n#define DUK_USE_FLEX_ZEROSIZE\n#define DUK_USE_PACK_DUMMY_MEMBER\n#elif defined(DUK_F_BCC)\n/* --- Bruce's C compiler --- */\n#undef DUK_USE_BRANCH_HINTS\n\n#if defined(DUK_F_CPP)\n#define DUK_USE_COMPILER_STRING \"bcc++\"\n#else\n#define DUK_USE_COMPILER_STRING \"bcc\"\n#endif\n\n/* Most portable */\n#undef DUK_USE_VARIADIC_MACROS\n\n/* Most portable, wastes space */\n#undef DUK_USE_UNION_INITIALIZERS\n\n/* Most portable, wastes space */\n#define DUK_USE_FLEX_ONESIZE\n\n/* Most portable, potentially wastes space */\n#define DUK_USE_PACK_DUMMY_MEMBER\n\n/* BCC, assume we're on x86. */\n#if !defined(DUK_USE_BYTEORDER)\n#define DUK_USE_BYTEORDER 1\n#endif\n#else\n/* --- Generic --- */\n#undef DUK_USE_BRANCH_HINTS\n\n#if defined(DUK_F_CPP)\n#define DUK_USE_COMPILER_STRING \"generic-c++\"\n#else\n#define DUK_USE_COMPILER_STRING \"generic\"\n#endif\n\n#undef DUK_USE_VARIADIC_MACROS\n#if defined(DUK_F_C99) || defined(DUK_F_CPP11)\n#define DUK_USE_VARIADIC_MACROS\n#endif\n\n/* C++ doesn't have standard designated union initializers ({ .foo = 1 }). */\n#undef DUK_USE_UNION_INITIALIZERS\n#if defined(DUK_F_C99)\n#define DUK_USE_UNION_INITIALIZERS\n#endif\n\n/* Most portable, wastes space */\n#define DUK_USE_FLEX_ONESIZE\n\n/* Most portable, potentially wastes space */\n#define DUK_USE_PACK_DUMMY_MEMBER\n#endif  /* autodetect compiler */\n\n/* uclibc */\n#if defined(__UCLIBC__)\n#define DUK_F_UCLIBC\n#endif\n\n/*\n *  Wrapper typedefs and constants for integer types, also sanity check types.\n *\n *  C99 typedefs are quite good but not always available, and we want to avoid\n *  forcibly redefining the C99 typedefs.  So, there are Duktape wrappers for\n *  all C99 typedefs and Duktape code should only use these typedefs.  Type\n *  detection when C99 is not supported is best effort and may end up detecting\n *  some types incorrectly.\n *\n *  Pointer sizes are a portability problem: pointers to different types may\n *  have a different size and function pointers are very difficult to manage\n *  portably.\n *\n *  http://en.wikipedia.org/wiki/C_data_types#Fixed-width_integer_types\n *\n *  Note: there's an interesting corner case when trying to define minimum\n *  signed integer value constants which leads to the current workaround of\n *  defining e.g. -0x80000000 as (-0x7fffffffL - 1L).  See doc/code-issues.txt\n *  for a longer discussion.\n *\n *  Note: avoid typecasts and computations in macro integer constants as they\n *  can then no longer be used in macro relational expressions (such as\n *  #if DUK_SIZE_MAX < 0xffffffffUL).  There is internal code which relies on\n *  being able to compare DUK_SIZE_MAX against a limit.\n */\n\n/* XXX: add feature options to force basic types from outside? */\n\n#if !defined(INT_MAX)\n#error INT_MAX not defined\n#endif\n\n/* Check that architecture is two's complement, standard C allows e.g.\n * INT_MIN to be -2**31+1 (instead of -2**31).\n */\n#if defined(INT_MAX) && defined(INT_MIN)\n#if INT_MAX != -(INT_MIN + 1)\n#error platform does not seem complement of two\n#endif\n#else\n#error cannot check complement of two\n#endif\n\n/* Pointer size determination based on __WORDSIZE or architecture when\n * that's not available.\n */\n#if defined(DUK_F_X86) || defined(DUK_F_X32) || \\\n    defined(DUK_F_M68K) || defined(DUK_F_PPC32) || \\\n    defined(DUK_F_BCC) || \\\n    (defined(__WORDSIZE) && (__WORDSIZE == 32)) || \\\n    ((defined(DUK_F_OLD_SOLARIS) || defined(DUK_F_AIX) || \\\n      defined(DUK_F_HPUX)) && defined(_ILP32)) || \\\n    defined(DUK_F_ARM32)\n#define DUK_F_32BIT_PTRS\n#elif defined(DUK_F_X64) || \\\n      (defined(__WORDSIZE) && (__WORDSIZE == 64)) || \\\n   ((defined(DUK_F_OLD_SOLARIS) || defined(DUK_F_AIX) || \\\n     defined(DUK_F_HPUX)) && defined(_LP64)) || \\\n    defined(DUK_F_ARM64)\n#define DUK_F_64BIT_PTRS\n#else\n/* not sure, not needed with C99 anyway */\n#endif\n\n/* Intermediate define for 'have inttypes.h' */\n#undef DUK_F_HAVE_INTTYPES\n#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \\\n    !(defined(DUK_F_AMIGAOS) && defined(DUK_F_VBCC))\n/* vbcc + AmigaOS has C99 but no inttypes.h */\n#define DUK_F_HAVE_INTTYPES\n#elif defined(__cplusplus) && (__cplusplus >= 201103L)\n/* C++11 apparently ratified stdint.h */\n#define DUK_F_HAVE_INTTYPES\n#endif\n\n/* Basic integer typedefs and limits, preferably from inttypes.h, otherwise\n * through automatic detection.\n */\n#if defined(DUK_F_HAVE_INTTYPES)\n/* C99 or compatible */\n\n#define DUK_F_HAVE_64BIT\n#include <inttypes.h>\n\ntypedef uint8_t duk_uint8_t;\ntypedef int8_t duk_int8_t;\ntypedef uint16_t duk_uint16_t;\ntypedef int16_t duk_int16_t;\ntypedef uint32_t duk_uint32_t;\ntypedef int32_t duk_int32_t;\ntypedef uint64_t duk_uint64_t;\ntypedef int64_t duk_int64_t;\ntypedef uint_least8_t duk_uint_least8_t;\ntypedef int_least8_t duk_int_least8_t;\ntypedef uint_least16_t duk_uint_least16_t;\ntypedef int_least16_t duk_int_least16_t;\ntypedef uint_least32_t duk_uint_least32_t;\ntypedef int_least32_t duk_int_least32_t;\ntypedef uint_least64_t duk_uint_least64_t;\ntypedef int_least64_t duk_int_least64_t;\ntypedef uint_fast8_t duk_uint_fast8_t;\ntypedef int_fast8_t duk_int_fast8_t;\ntypedef uint_fast16_t duk_uint_fast16_t;\ntypedef int_fast16_t duk_int_fast16_t;\ntypedef uint_fast32_t duk_uint_fast32_t;\ntypedef int_fast32_t duk_int_fast32_t;\ntypedef uint_fast64_t duk_uint_fast64_t;\ntypedef int_fast64_t duk_int_fast64_t;\ntypedef uintptr_t duk_uintptr_t;\ntypedef intptr_t duk_intptr_t;\ntypedef uintmax_t duk_uintmax_t;\ntypedef intmax_t duk_intmax_t;\n\n#define DUK_UINT8_MIN         0\n#define DUK_UINT8_MAX         UINT8_MAX\n#define DUK_INT8_MIN          INT8_MIN\n#define DUK_INT8_MAX          INT8_MAX\n#define DUK_UINT_LEAST8_MIN   0\n#define DUK_UINT_LEAST8_MAX   UINT_LEAST8_MAX\n#define DUK_INT_LEAST8_MIN    INT_LEAST8_MIN\n#define DUK_INT_LEAST8_MAX    INT_LEAST8_MAX\n#define DUK_UINT_FAST8_MIN    0\n#define DUK_UINT_FAST8_MAX    UINT_FAST8_MAX\n#define DUK_INT_FAST8_MIN     INT_FAST8_MIN\n#define DUK_INT_FAST8_MAX     INT_FAST8_MAX\n#define DUK_UINT16_MIN        0\n#define DUK_UINT16_MAX        UINT16_MAX\n#define DUK_INT16_MIN         INT16_MIN\n#define DUK_INT16_MAX         INT16_MAX\n#define DUK_UINT_LEAST16_MIN  0\n#define DUK_UINT_LEAST16_MAX  UINT_LEAST16_MAX\n#define DUK_INT_LEAST16_MIN   INT_LEAST16_MIN\n#define DUK_INT_LEAST16_MAX   INT_LEAST16_MAX\n#define DUK_UINT_FAST16_MIN   0\n#define DUK_UINT_FAST16_MAX   UINT_FAST16_MAX\n#define DUK_INT_FAST16_MIN    INT_FAST16_MIN\n#define DUK_INT_FAST16_MAX    INT_FAST16_MAX\n#define DUK_UINT32_MIN        0\n#define DUK_UINT32_MAX        UINT32_MAX\n#define DUK_INT32_MIN         INT32_MIN\n#define DUK_INT32_MAX         INT32_MAX\n#define DUK_UINT_LEAST32_MIN  0\n#define DUK_UINT_LEAST32_MAX  UINT_LEAST32_MAX\n#define DUK_INT_LEAST32_MIN   INT_LEAST32_MIN\n#define DUK_INT_LEAST32_MAX   INT_LEAST32_MAX\n#define DUK_UINT_FAST32_MIN   0\n#define DUK_UINT_FAST32_MAX   UINT_FAST32_MAX\n#define DUK_INT_FAST32_MIN    INT_FAST32_MIN\n#define DUK_INT_FAST32_MAX    INT_FAST32_MAX\n#define DUK_UINT64_MIN        0\n#define DUK_UINT64_MAX        UINT64_MAX\n#define DUK_INT64_MIN         INT64_MIN\n#define DUK_INT64_MAX         INT64_MAX\n#define DUK_UINT_LEAST64_MIN  0\n#define DUK_UINT_LEAST64_MAX  UINT_LEAST64_MAX\n#define DUK_INT_LEAST64_MIN   INT_LEAST64_MIN\n#define DUK_INT_LEAST64_MAX   INT_LEAST64_MAX\n#define DUK_UINT_FAST64_MIN   0\n#define DUK_UINT_FAST64_MAX   UINT_FAST64_MAX\n#define DUK_INT_FAST64_MIN    INT_FAST64_MIN\n#define DUK_INT_FAST64_MAX    INT_FAST64_MAX\n\n#define DUK_UINTPTR_MIN       0\n#define DUK_UINTPTR_MAX       UINTPTR_MAX\n#define DUK_INTPTR_MIN        INTPTR_MIN\n#define DUK_INTPTR_MAX        INTPTR_MAX\n\n#define DUK_UINTMAX_MIN       0\n#define DUK_UINTMAX_MAX       UINTMAX_MAX\n#define DUK_INTMAX_MIN        INTMAX_MIN\n#define DUK_INTMAX_MAX        INTMAX_MAX\n\n#define DUK_SIZE_MIN          0\n#define DUK_SIZE_MAX          SIZE_MAX\n#undef DUK_SIZE_MAX_COMPUTED\n\n#else  /* C99 types */\n\n/* When C99 types are not available, we use heuristic detection to get\n * the basic 8, 16, 32, and (possibly) 64 bit types.  The fast/least\n * types are then assumed to be exactly the same for now: these could\n * be improved per platform but C99 types are very often now available.\n * 64-bit types are not available on all platforms; this is OK at least\n * on 32-bit platforms.\n *\n * This detection code is necessarily a bit hacky and can provide typedefs\n * and defines that won't work correctly on some exotic platform.\n */\n\n#if (defined(CHAR_BIT) && (CHAR_BIT == 8)) || \\\n    (defined(UCHAR_MAX) && (UCHAR_MAX == 255))\ntypedef unsigned char duk_uint8_t;\ntypedef signed char duk_int8_t;\n#else\n#error cannot detect 8-bit type\n#endif\n\n#if defined(USHRT_MAX) && (USHRT_MAX == 65535UL)\ntypedef unsigned short duk_uint16_t;\ntypedef signed short duk_int16_t;\n#elif defined(UINT_MAX) && (UINT_MAX == 65535UL)\n/* On some platforms int is 16-bit but long is 32-bit (e.g. PureC) */\ntypedef unsigned int duk_uint16_t;\ntypedef signed int duk_int16_t;\n#else\n#error cannot detect 16-bit type\n#endif\n\n#if defined(UINT_MAX) && (UINT_MAX == 4294967295UL)\ntypedef unsigned int duk_uint32_t;\ntypedef signed int duk_int32_t;\n#elif defined(ULONG_MAX) && (ULONG_MAX == 4294967295UL)\n/* On some platforms int is 16-bit but long is 32-bit (e.g. PureC) */\ntypedef unsigned long duk_uint32_t;\ntypedef signed long duk_int32_t;\n#else\n#error cannot detect 32-bit type\n#endif\n\n/* 64-bit type detection is a bit tricky.\n *\n * ULLONG_MAX is a standard define.  __LONG_LONG_MAX__ and __ULONG_LONG_MAX__\n * are used by at least GCC (even if system headers don't provide ULLONG_MAX).\n * Some GCC variants may provide __LONG_LONG_MAX__ but not __ULONG_LONG_MAX__.\n *\n * ULL / LL constants are rejected / warned about by some compilers, even if\n * the compiler has a 64-bit type and the compiler/system headers provide an\n * unsupported constant (ULL/LL)!  Try to avoid using ULL / LL constants.\n * As a side effect we can only check that e.g. ULONG_MAX is larger than 32\n * bits but can't be sure it is exactly 64 bits.  Self tests will catch such\n * cases.\n */\n#undef DUK_F_HAVE_64BIT\n#if !defined(DUK_F_HAVE_64BIT) && defined(ULONG_MAX)\n#if (ULONG_MAX > 4294967295UL)\n#define DUK_F_HAVE_64BIT\ntypedef unsigned long duk_uint64_t;\ntypedef signed long duk_int64_t;\n#endif\n#endif\n#if !defined(DUK_F_HAVE_64BIT) && defined(ULLONG_MAX)\n#if (ULLONG_MAX > 4294967295UL)\n#define DUK_F_HAVE_64BIT\ntypedef unsigned long long duk_uint64_t;\ntypedef signed long long duk_int64_t;\n#endif\n#endif\n#if !defined(DUK_F_HAVE_64BIT) && defined(__ULONG_LONG_MAX__)\n#if (__ULONG_LONG_MAX__ > 4294967295UL)\n#define DUK_F_HAVE_64BIT\ntypedef unsigned long long duk_uint64_t;\ntypedef signed long long duk_int64_t;\n#endif\n#endif\n#if !defined(DUK_F_HAVE_64BIT) && defined(__LONG_LONG_MAX__)\n#if (__LONG_LONG_MAX__ > 2147483647L)\n#define DUK_F_HAVE_64BIT\ntypedef unsigned long long duk_uint64_t;\ntypedef signed long long duk_int64_t;\n#endif\n#endif\n#if !defined(DUK_F_HAVE_64BIT) && defined(DUK_F_MINGW)\n#define DUK_F_HAVE_64BIT\ntypedef unsigned long duk_uint64_t;\ntypedef signed long duk_int64_t;\n#endif\n#if !defined(DUK_F_HAVE_64BIT) && defined(DUK_F_MSVC)\n#define DUK_F_HAVE_64BIT\ntypedef unsigned __int64 duk_uint64_t;\ntypedef signed __int64 duk_int64_t;\n#endif\n#if !defined(DUK_F_HAVE_64BIT)\n/* cannot detect 64-bit type, not always needed so don't error */\n#endif\n\ntypedef duk_uint8_t duk_uint_least8_t;\ntypedef duk_int8_t duk_int_least8_t;\ntypedef duk_uint16_t duk_uint_least16_t;\ntypedef duk_int16_t duk_int_least16_t;\ntypedef duk_uint32_t duk_uint_least32_t;\ntypedef duk_int32_t duk_int_least32_t;\ntypedef duk_uint8_t duk_uint_fast8_t;\ntypedef duk_int8_t duk_int_fast8_t;\ntypedef duk_uint16_t duk_uint_fast16_t;\ntypedef duk_int16_t duk_int_fast16_t;\ntypedef duk_uint32_t duk_uint_fast32_t;\ntypedef duk_int32_t duk_int_fast32_t;\n#if defined(DUK_F_HAVE_64BIT)\ntypedef duk_uint64_t duk_uint_least64_t;\ntypedef duk_int64_t duk_int_least64_t;\ntypedef duk_uint64_t duk_uint_fast64_t;\ntypedef duk_int64_t duk_int_fast64_t;\n#endif\n#if defined(DUK_F_HAVE_64BIT)\ntypedef duk_uint64_t duk_uintmax_t;\ntypedef duk_int64_t duk_intmax_t;\n#else\ntypedef duk_uint32_t duk_uintmax_t;\ntypedef duk_int32_t duk_intmax_t;\n#endif\n\n/* Note: the funny looking computations for signed minimum 16-bit, 32-bit, and\n * 64-bit values are intentional as the obvious forms (e.g. -0x80000000L) are\n * -not- portable.  See code-issues.txt for a detailed discussion.\n */\n#define DUK_UINT8_MIN         0UL\n#define DUK_UINT8_MAX         0xffUL\n#define DUK_INT8_MIN          (-0x80L)\n#define DUK_INT8_MAX          0x7fL\n#define DUK_UINT_LEAST8_MIN   0UL\n#define DUK_UINT_LEAST8_MAX   0xffUL\n#define DUK_INT_LEAST8_MIN    (-0x80L)\n#define DUK_INT_LEAST8_MAX    0x7fL\n#define DUK_UINT_FAST8_MIN    0UL\n#define DUK_UINT_FAST8_MAX    0xffUL\n#define DUK_INT_FAST8_MIN     (-0x80L)\n#define DUK_INT_FAST8_MAX     0x7fL\n#define DUK_UINT16_MIN        0UL\n#define DUK_UINT16_MAX        0xffffUL\n#define DUK_INT16_MIN         (-0x7fffL - 1L)\n#define DUK_INT16_MAX         0x7fffL\n#define DUK_UINT_LEAST16_MIN  0UL\n#define DUK_UINT_LEAST16_MAX  0xffffUL\n#define DUK_INT_LEAST16_MIN   (-0x7fffL - 1L)\n#define DUK_INT_LEAST16_MAX   0x7fffL\n#define DUK_UINT_FAST16_MIN   0UL\n#define DUK_UINT_FAST16_MAX   0xffffUL\n#define DUK_INT_FAST16_MIN    (-0x7fffL - 1L)\n#define DUK_INT_FAST16_MAX    0x7fffL\n#define DUK_UINT32_MIN        0UL\n#define DUK_UINT32_MAX        0xffffffffUL\n#define DUK_INT32_MIN         (-0x7fffffffL - 1L)\n#define DUK_INT32_MAX         0x7fffffffL\n#define DUK_UINT_LEAST32_MIN  0UL\n#define DUK_UINT_LEAST32_MAX  0xffffffffUL\n#define DUK_INT_LEAST32_MIN   (-0x7fffffffL - 1L)\n#define DUK_INT_LEAST32_MAX   0x7fffffffL\n#define DUK_UINT_FAST32_MIN   0UL\n#define DUK_UINT_FAST32_MAX   0xffffffffUL\n#define DUK_INT_FAST32_MIN    (-0x7fffffffL - 1L)\n#define DUK_INT_FAST32_MAX    0x7fffffffL\n\n/* 64-bit constants.  Since LL / ULL constants are not always available,\n * use computed values.  These values can't be used in preprocessor\n * comparisons; flag them as such.\n */\n#if defined(DUK_F_HAVE_64BIT)\n#define DUK_UINT64_MIN        ((duk_uint64_t) 0)\n#define DUK_UINT64_MAX        ((duk_uint64_t) -1)\n#define DUK_INT64_MIN         ((duk_int64_t) (~(DUK_UINT64_MAX >> 1)))\n#define DUK_INT64_MAX         ((duk_int64_t) (DUK_UINT64_MAX >> 1))\n#define DUK_UINT_LEAST64_MIN  DUK_UINT64_MIN\n#define DUK_UINT_LEAST64_MAX  DUK_UINT64_MAX\n#define DUK_INT_LEAST64_MIN   DUK_INT64_MIN\n#define DUK_INT_LEAST64_MAX   DUK_INT64_MAX\n#define DUK_UINT_FAST64_MIN   DUK_UINT64_MIN\n#define DUK_UINT_FAST64_MAX   DUK_UINT64_MAX\n#define DUK_INT_FAST64_MIN    DUK_INT64_MIN\n#define DUK_INT_FAST64_MAX    DUK_INT64_MAX\n#define DUK_UINT64_MIN_COMPUTED\n#define DUK_UINT64_MAX_COMPUTED\n#define DUK_INT64_MIN_COMPUTED\n#define DUK_INT64_MAX_COMPUTED\n#define DUK_UINT_LEAST64_MIN_COMPUTED\n#define DUK_UINT_LEAST64_MAX_COMPUTED\n#define DUK_INT_LEAST64_MIN_COMPUTED\n#define DUK_INT_LEAST64_MAX_COMPUTED\n#define DUK_UINT_FAST64_MIN_COMPUTED\n#define DUK_UINT_FAST64_MAX_COMPUTED\n#define DUK_INT_FAST64_MIN_COMPUTED\n#define DUK_INT_FAST64_MAX_COMPUTED\n#endif\n\n#if defined(DUK_F_HAVE_64BIT)\n#define DUK_UINTMAX_MIN       DUK_UINT64_MIN\n#define DUK_UINTMAX_MAX       DUK_UINT64_MAX\n#define DUK_INTMAX_MIN        DUK_INT64_MIN\n#define DUK_INTMAX_MAX        DUK_INT64_MAX\n#define DUK_UINTMAX_MIN_COMPUTED\n#define DUK_UINTMAX_MAX_COMPUTED\n#define DUK_INTMAX_MIN_COMPUTED\n#define DUK_INTMAX_MAX_COMPUTED\n#else\n#define DUK_UINTMAX_MIN       0UL\n#define DUK_UINTMAX_MAX       0xffffffffUL\n#define DUK_INTMAX_MIN        (-0x7fffffffL - 1L)\n#define DUK_INTMAX_MAX        0x7fffffffL\n#endif\n\n/* This detection is not very reliable. */\n#if defined(DUK_F_32BIT_PTRS)\ntypedef duk_int32_t duk_intptr_t;\ntypedef duk_uint32_t duk_uintptr_t;\n#define DUK_UINTPTR_MIN       DUK_UINT32_MIN\n#define DUK_UINTPTR_MAX       DUK_UINT32_MAX\n#define DUK_INTPTR_MIN        DUK_INT32_MIN\n#define DUK_INTPTR_MAX        DUK_INT32_MAX\n#elif defined(DUK_F_64BIT_PTRS) && defined(DUK_F_HAVE_64BIT)\ntypedef duk_int64_t duk_intptr_t;\ntypedef duk_uint64_t duk_uintptr_t;\n#define DUK_UINTPTR_MIN       DUK_UINT64_MIN\n#define DUK_UINTPTR_MAX       DUK_UINT64_MAX\n#define DUK_INTPTR_MIN        DUK_INT64_MIN\n#define DUK_INTPTR_MAX        DUK_INT64_MAX\n#define DUK_UINTPTR_MIN_COMPUTED\n#define DUK_UINTPTR_MAX_COMPUTED\n#define DUK_INTPTR_MIN_COMPUTED\n#define DUK_INTPTR_MAX_COMPUTED\n#else\n#error cannot determine intptr type\n#endif\n\n/* SIZE_MAX may be missing so use an approximate value for it. */\n#undef DUK_SIZE_MAX_COMPUTED\n#if !defined(SIZE_MAX)\n#define DUK_SIZE_MAX_COMPUTED\n#define SIZE_MAX              ((size_t) (-1))\n#endif\n#define DUK_SIZE_MIN          0\n#define DUK_SIZE_MAX          SIZE_MAX\n\n#endif  /* C99 types */\n\n/* A few types are assumed to always exist. */\ntypedef size_t duk_size_t;\ntypedef ptrdiff_t duk_ptrdiff_t;\n\n/* The best type for an \"all around int\" in Duktape internals is \"at least\n * 32 bit signed integer\" which is most convenient.  Same for unsigned type.\n * Prefer 'int' when large enough, as it is almost always a convenient type.\n */\n#if defined(UINT_MAX) && (UINT_MAX >= 0xffffffffUL)\ntypedef int duk_int_t;\ntypedef unsigned int duk_uint_t;\n#define DUK_INT_MIN           INT_MIN\n#define DUK_INT_MAX           INT_MAX\n#define DUK_UINT_MIN          0\n#define DUK_UINT_MAX          UINT_MAX\n#else\ntypedef duk_int_fast32_t duk_int_t;\ntypedef duk_uint_fast32_t duk_uint_t;\n#define DUK_INT_MIN           DUK_INT_FAST32_MIN\n#define DUK_INT_MAX           DUK_INT_FAST32_MAX\n#define DUK_UINT_MIN          DUK_UINT_FAST32_MIN\n#define DUK_UINT_MAX          DUK_UINT_FAST32_MAX\n#endif\n\n/* Same as 'duk_int_t' but guaranteed to be a 'fast' variant if this\n * distinction matters for the CPU.  These types are used mainly in the\n * executor where it might really matter.\n */\ntypedef duk_int_fast32_t duk_int_fast_t;\ntypedef duk_uint_fast32_t duk_uint_fast_t;\n#define DUK_INT_FAST_MIN      DUK_INT_FAST32_MIN\n#define DUK_INT_FAST_MAX      DUK_INT_FAST32_MAX\n#define DUK_UINT_FAST_MIN     DUK_UINT_FAST32_MIN\n#define DUK_UINT_FAST_MAX     DUK_UINT_FAST32_MAX\n\n/* Small integers (16 bits or more) can fall back to the 'int' type, but\n * have a typedef so they are marked \"small\" explicitly.\n */\ntypedef int duk_small_int_t;\ntypedef unsigned int duk_small_uint_t;\n#define DUK_SMALL_INT_MIN     INT_MIN\n#define DUK_SMALL_INT_MAX     INT_MAX\n#define DUK_SMALL_UINT_MIN    0\n#define DUK_SMALL_UINT_MAX    UINT_MAX\n\n/* Fast variants of small integers, again for really fast paths like the\n * executor.\n */\ntypedef duk_int_fast16_t duk_small_int_fast_t;\ntypedef duk_uint_fast16_t duk_small_uint_fast_t;\n#define DUK_SMALL_INT_FAST_MIN    DUK_INT_FAST16_MIN\n#define DUK_SMALL_INT_FAST_MAX    DUK_INT_FAST16_MAX\n#define DUK_SMALL_UINT_FAST_MIN   DUK_UINT_FAST16_MIN\n#define DUK_SMALL_UINT_FAST_MAX   DUK_UINT_FAST16_MAX\n\n/* Boolean values are represented with the platform 'unsigned int'. */\ntypedef duk_small_uint_t duk_bool_t;\n#define DUK_BOOL_MIN              DUK_SMALL_INT_MIN\n#define DUK_BOOL_MAX              DUK_SMALL_INT_MAX\n\n/* Index values must have at least 32-bit signed range. */\ntypedef duk_int_t duk_idx_t;\n#define DUK_IDX_MIN               DUK_INT_MIN\n#define DUK_IDX_MAX               DUK_INT_MAX\n\n/* Unsigned index variant. */\ntypedef duk_uint_t duk_uidx_t;\n#define DUK_UIDX_MIN              DUK_UINT_MIN\n#define DUK_UIDX_MAX              DUK_UINT_MAX\n\n/* Array index values, could be exact 32 bits.\n * Currently no need for signed duk_arridx_t.\n */\ntypedef duk_uint_t duk_uarridx_t;\n#define DUK_UARRIDX_MIN           DUK_UINT_MIN\n#define DUK_UARRIDX_MAX           DUK_UINT_MAX\n\n/* Duktape/C function return value, platform int is enough for now to\n * represent 0, 1, or negative error code.  Must be compatible with\n * assigning truth values (e.g. duk_ret_t rc = (foo == bar);).\n */\ntypedef duk_small_int_t duk_ret_t;\n#define DUK_RET_MIN               DUK_SMALL_INT_MIN\n#define DUK_RET_MAX               DUK_SMALL_INT_MAX\n\n/* Error codes are represented with platform int.  High bits are used\n * for flags and such, so 32 bits are needed.\n */\ntypedef duk_int_t duk_errcode_t;\n#define DUK_ERRCODE_MIN           DUK_INT_MIN\n#define DUK_ERRCODE_MAX           DUK_INT_MAX\n\n/* Codepoint type.  Must be 32 bits or more because it is used also for\n * internal codepoints.  The type is signed because negative codepoints\n * are used as internal markers (e.g. to mark EOF or missing argument).\n * (X)UTF-8/CESU-8 encode/decode take and return an unsigned variant to\n * ensure duk_uint32_t casts back and forth nicely.  Almost everything\n * else uses the signed one.\n */\ntypedef duk_int_t duk_codepoint_t;\ntypedef duk_uint_t duk_ucodepoint_t;\n#define DUK_CODEPOINT_MIN         DUK_INT_MIN\n#define DUK_CODEPOINT_MAX         DUK_INT_MAX\n#define DUK_UCODEPOINT_MIN        DUK_UINT_MIN\n#define DUK_UCODEPOINT_MAX        DUK_UINT_MAX\n\n/* IEEE float/double typedef. */\ntypedef float duk_float_t;\ntypedef double duk_double_t;\n\n/* We're generally assuming that we're working on a platform with a 32-bit\n * address space.  If DUK_SIZE_MAX is a typecast value (which is necessary\n * if SIZE_MAX is missing), the check must be avoided because the\n * preprocessor can't do a comparison.\n */\n#if !defined(DUK_SIZE_MAX)\n#error DUK_SIZE_MAX is undefined, probably missing SIZE_MAX\n#elif !defined(DUK_SIZE_MAX_COMPUTED)\n#if DUK_SIZE_MAX < 0xffffffffUL\n/* On some systems SIZE_MAX can be smaller than max unsigned 32-bit value\n * which seems incorrect if size_t is (at least) an unsigned 32-bit type.\n * However, it doesn't seem useful to error out compilation if this is the\n * case.\n */\n#endif\n#endif\n\n/* Type used in public API declarations and user code.  Typedef maps to\n * 'struct duk_hthread' like the 'duk_hthread' typedef which is used\n * exclusively in internals.\n */\ntypedef struct duk_hthread duk_context;\n\n/* Check whether we should use 64-bit integers or not.\n *\n * Quite incomplete now.  Use 64-bit types if detected (C99 or other detection)\n * unless they are known to be unreliable.  For instance, 64-bit types are\n * available on VBCC but seem to misbehave.\n */\n#if defined(DUK_F_HAVE_64BIT) && !defined(DUK_F_VBCC)\n#define DUK_USE_64BIT_OPS\n#else\n#undef DUK_USE_64BIT_OPS\n#endif\n\n/*\n *  Fill-ins for platform, architecture, and compiler\n */\n\n/* An abort()-like primitive is needed by the default fatal error handler. */\n#if !defined(DUK_ABORT)\n#define DUK_ABORT             abort\n#endif\n\n#if !defined(DUK_SETJMP)\n#define DUK_JMPBUF_TYPE       jmp_buf\n#define DUK_SETJMP(jb)        setjmp((jb))\n#define DUK_LONGJMP(jb)       longjmp((jb), 1)\n#endif\n\n#if 0\n/* sigsetjmp() alternative */\n#define DUK_JMPBUF_TYPE       sigjmp_buf\n#define DUK_SETJMP(jb)        sigsetjmp((jb))\n#define DUK_LONGJMP(jb)       siglongjmp((jb), 1)\n#endif\n\n/* Special naming to avoid conflict with e.g. DUK_FREE() in duk_heap.h\n * (which is unfortunately named).  May sometimes need replacement, e.g.\n * some compilers don't handle zero length or NULL correctly in realloc().\n */\n#if !defined(DUK_ANSI_MALLOC)\n#define DUK_ANSI_MALLOC      malloc\n#endif\n#if !defined(DUK_ANSI_REALLOC)\n#define DUK_ANSI_REALLOC     realloc\n#endif\n#if !defined(DUK_ANSI_CALLOC)\n#define DUK_ANSI_CALLOC      calloc\n#endif\n#if !defined(DUK_ANSI_FREE)\n#define DUK_ANSI_FREE        free\n#endif\n\n/* ANSI C (various versions) and some implementations require that the\n * pointer arguments to memset(), memcpy(), and memmove() be valid values\n * even when byte size is 0 (even a NULL pointer is considered invalid in\n * this context).  Zero-size operations as such are allowed, as long as their\n * pointer arguments point to a valid memory area.  The DUK_MEMSET(),\n * DUK_MEMCPY(), and DUK_MEMMOVE() macros require this same behavior, i.e.:\n * (1) pointers must be valid and non-NULL, (2) zero size must otherwise be\n * allowed.  If these are not fulfilled, a macro wrapper is needed.\n *\n *   http://stackoverflow.com/questions/5243012/is-it-guaranteed-to-be-safe-to-perform-memcpy0-0-0\n *   http://lists.cs.uiuc.edu/pipermail/llvmdev/2007-October/011065.html\n *\n * Not sure what's the required behavior when a pointer points just past the\n * end of a buffer, which often happens in practice (e.g. zero size memmoves).\n * For example, if allocation size is 3, the following pointer would not\n * technically point to a valid memory byte:\n *\n *   <-- alloc -->\n *   | 0 | 1 | 2 | .....\n *                 ^-- p=3, points after last valid byte (2)\n */\n#if !defined(DUK_MEMCPY)\n#if defined(DUK_F_UCLIBC)\n/* Old uclibcs have a broken memcpy so use memmove instead (this is overly wide\n * now on purpose): http://lists.uclibc.org/pipermail/uclibc-cvs/2008-October/025511.html\n */\n#define DUK_MEMCPY       memmove\n#else\n#define DUK_MEMCPY       memcpy\n#endif\n#endif\n#if !defined(DUK_MEMMOVE)\n#define DUK_MEMMOVE      memmove\n#endif\n#if !defined(DUK_MEMCMP)\n#define DUK_MEMCMP       memcmp\n#endif\n#if !defined(DUK_MEMSET)\n#define DUK_MEMSET       memset\n#endif\n#if !defined(DUK_STRLEN)\n#define DUK_STRLEN       strlen\n#endif\n#if !defined(DUK_STRCMP)\n#define DUK_STRCMP       strcmp\n#endif\n#if !defined(DUK_STRNCMP)\n#define DUK_STRNCMP      strncmp\n#endif\n#if !defined(DUK_SPRINTF)\n#define DUK_SPRINTF      sprintf\n#endif\n#if !defined(DUK_SNPRINTF)\n/* snprintf() is technically not part of C89 but usually available. */\n#define DUK_SNPRINTF     snprintf\n#endif\n#if !defined(DUK_VSPRINTF)\n#define DUK_VSPRINTF     vsprintf\n#endif\n#if !defined(DUK_VSNPRINTF)\n/* vsnprintf() is technically not part of C89 but usually available. */\n#define DUK_VSNPRINTF    vsnprintf\n#endif\n#if !defined(DUK_SSCANF)\n#define DUK_SSCANF       sscanf\n#endif\n#if !defined(DUK_VSSCANF)\n#define DUK_VSSCANF      vsscanf\n#endif\n#if !defined(DUK_MEMZERO)\n#define DUK_MEMZERO(p,n) DUK_MEMSET((p), 0, (n))\n#endif\n\n#if !defined(DUK_DOUBLE_INFINITY)\n#undef DUK_USE_COMPUTED_INFINITY\n#if defined(DUK_F_GCC_VERSION) && (DUK_F_GCC_VERSION < 40600)\n/* GCC older than 4.6: avoid overflow warnings related to using INFINITY */\n#define DUK_DOUBLE_INFINITY  (__builtin_inf())\n#elif defined(INFINITY)\n#define DUK_DOUBLE_INFINITY  ((double) INFINITY)\n#elif !defined(DUK_F_VBCC) && !defined(DUK_F_MSVC) && !defined(DUK_F_BCC) && \\\n      !defined(DUK_F_OLD_SOLARIS) && !defined(DUK_F_AIX)\n#define DUK_DOUBLE_INFINITY  (1.0 / 0.0)\n#else\n/* In VBCC (1.0 / 0.0) results in a warning and 0.0 instead of infinity.\n * Use a computed infinity (initialized when a heap is created at the\n * latest).\n */\n#define DUK_USE_COMPUTED_INFINITY\n#define DUK_DOUBLE_INFINITY  duk_computed_infinity\n#endif\n#endif\n\n#if !defined(DUK_DOUBLE_NAN)\n#undef DUK_USE_COMPUTED_NAN\n#if defined(NAN)\n#define DUK_DOUBLE_NAN       NAN\n#elif !defined(DUK_F_VBCC) && !defined(DUK_F_MSVC) && !defined(DUK_F_BCC) && \\\n      !defined(DUK_F_OLD_SOLARIS) && !defined(DUK_F_AIX)\n#define DUK_DOUBLE_NAN       (0.0 / 0.0)\n#else\n/* In VBCC (0.0 / 0.0) results in a warning and 0.0 instead of NaN.\n * In MSVC (VS2010 Express) (0.0 / 0.0) results in a compile error.\n * Use a computed NaN (initialized when a heap is created at the\n * latest).\n */\n#define DUK_USE_COMPUTED_NAN\n#define DUK_DOUBLE_NAN       duk_computed_nan\n#endif\n#endif\n\n/* Many platforms are missing fpclassify() and friends, so use replacements\n * if necessary.  The replacement constants (FP_NAN etc) can be anything but\n * match Linux constants now.\n */\n#undef DUK_USE_REPL_FPCLASSIFY\n#undef DUK_USE_REPL_SIGNBIT\n#undef DUK_USE_REPL_ISFINITE\n#undef DUK_USE_REPL_ISNAN\n#undef DUK_USE_REPL_ISINF\n\n/* Complex condition broken into separate parts. */\n#undef DUK_F_USE_REPL_ALL\n#if !(defined(FP_NAN) && defined(FP_INFINITE) && defined(FP_ZERO) && \\\n      defined(FP_SUBNORMAL) && defined(FP_NORMAL))\n/* Missing some obvious constants. */\n#define DUK_F_USE_REPL_ALL\n#elif defined(DUK_F_AMIGAOS) && defined(DUK_F_VBCC)\n/* VBCC is missing the built-ins even in C99 mode (perhaps a header issue). */\n#define DUK_F_USE_REPL_ALL\n#elif defined(DUK_F_AMIGAOS) && defined(DUK_F_M68K)\n/* AmigaOS + M68K seems to have math issues even when using GCC cross\n * compilation.  Use replacements for all AmigaOS versions on M68K\n * regardless of compiler.\n */\n#define DUK_F_USE_REPL_ALL\n#elif defined(DUK_F_FREEBSD) && defined(DUK_F_CLANG)\n/* Placeholder fix for (detection is wider than necessary):\n * http://llvm.org/bugs/show_bug.cgi?id=17788\n */\n#define DUK_F_USE_REPL_ALL\n#elif defined(DUK_F_UCLIBC)\n/* At least some uclibc versions have broken floating point math.  For\n * example, fpclassify() can incorrectly classify certain NaN formats.\n * To be safe, use replacements.\n */\n#define DUK_F_USE_REPL_ALL\n#elif defined(DUK_F_AIX)\n/* Older versions may be missing isnan(), etc. */\n#define DUK_F_USE_REPL_ALL\n#endif\n\n#if defined(DUK_F_USE_REPL_ALL)\n#define DUK_USE_REPL_FPCLASSIFY\n#define DUK_USE_REPL_SIGNBIT\n#define DUK_USE_REPL_ISFINITE\n#define DUK_USE_REPL_ISNAN\n#define DUK_USE_REPL_ISINF\n#define DUK_FPCLASSIFY       duk_repl_fpclassify\n#define DUK_SIGNBIT          duk_repl_signbit\n#define DUK_ISFINITE         duk_repl_isfinite\n#define DUK_ISNAN            duk_repl_isnan\n#define DUK_ISINF            duk_repl_isinf\n#define DUK_FP_NAN           0\n#define DUK_FP_INFINITE      1\n#define DUK_FP_ZERO          2\n#define DUK_FP_SUBNORMAL     3\n#define DUK_FP_NORMAL        4\n#else\n#define DUK_FPCLASSIFY       fpclassify\n#define DUK_SIGNBIT          signbit\n#define DUK_ISFINITE         isfinite\n#define DUK_ISNAN            isnan\n#define DUK_ISINF            isinf\n#define DUK_FP_NAN           FP_NAN\n#define DUK_FP_INFINITE      FP_INFINITE\n#define DUK_FP_ZERO          FP_ZERO\n#define DUK_FP_SUBNORMAL     FP_SUBNORMAL\n#define DUK_FP_NORMAL        FP_NORMAL\n#endif\n\n#if defined(DUK_F_USE_REPL_ALL)\n#undef DUK_F_USE_REPL_ALL\n#endif\n\n/* These functions don't currently need replacement but are wrapped for\n * completeness.  Because these are used as function pointers, they need\n * to be defined as concrete C functions (not macros).\n */\n#if !defined(DUK_FABS)\n#define DUK_FABS             fabs\n#endif\n#if !defined(DUK_FLOOR)\n#define DUK_FLOOR            floor\n#endif\n#if !defined(DUK_CEIL)\n#define DUK_CEIL             ceil\n#endif\n#if !defined(DUK_FMOD)\n#define DUK_FMOD             fmod\n#endif\n#if !defined(DUK_POW)\n#define DUK_POW              pow\n#endif\n#if !defined(DUK_ACOS)\n#define DUK_ACOS             acos\n#endif\n#if !defined(DUK_ASIN)\n#define DUK_ASIN             asin\n#endif\n#if !defined(DUK_ATAN)\n#define DUK_ATAN             atan\n#endif\n#if !defined(DUK_ATAN2)\n#define DUK_ATAN2            atan2\n#endif\n#if !defined(DUK_SIN)\n#define DUK_SIN              sin\n#endif\n#if !defined(DUK_COS)\n#define DUK_COS              cos\n#endif\n#if !defined(DUK_TAN)\n#define DUK_TAN              tan\n#endif\n#if !defined(DUK_EXP)\n#define DUK_EXP              exp\n#endif\n#if !defined(DUK_LOG)\n#define DUK_LOG              log\n#endif\n#if !defined(DUK_SQRT)\n#define DUK_SQRT             sqrt\n#endif\n\n/* The functions below exist only in C99/C++11 or later and need a workaround\n * for platforms that don't include them.  MSVC isn't detected as C99, but\n * these functions also exist in MSVC 2013 and later so include a clause for\n * that too.  Android doesn't have log2; disable all of these for Android.\n */\n#if (defined(DUK_F_C99) || defined(DUK_F_CPP11) || (defined(_MSC_VER) && (_MSC_VER >= 1800))) && \\\n    !defined(DUK_F_ANDROID) && !defined(DUK_F_MINT)\n#if !defined(DUK_CBRT)\n#define DUK_CBRT             cbrt\n#endif\n#if !defined(DUK_LOG2)\n#define DUK_LOG2             log2\n#endif\n#if !defined(DUK_LOG10)\n#define DUK_LOG10            log10\n#endif\n#if !defined(DUK_TRUNC)\n#define DUK_TRUNC            trunc\n#endif\n#endif  /* DUK_F_C99 etc */\n\n/* NetBSD 6.0 x86 (at least) has a few problems with pow() semantics,\n * see test-bug-netbsd-math-pow.js.  MinGW has similar (but different)\n * issues, see test-bug-mingw-math-issues.js.  Enable pow() workarounds\n * for these targets.\n */\n#undef DUK_USE_POW_WORKAROUNDS\n#if defined(DUK_F_NETBSD) || defined(DUK_F_MINGW)\n#define DUK_USE_POW_WORKAROUNDS\n#endif\n\n/* Similar workarounds for atan2() semantics issues.  MinGW issues are\n * documented in test-bug-mingw-math-issues.js.\n */\n#undef DUK_USE_ATAN2_WORKAROUNDS\n#if defined(DUK_F_MINGW)\n#define DUK_USE_ATAN2_WORKAROUNDS\n#endif\n\n/* Rely as little as possible on compiler behavior for NaN comparison,\n * signed zero handling, etc.  Currently never activated but may be needed\n * for broken compilers.\n */\n#undef DUK_USE_PARANOID_MATH\n\n/* There was a curious bug where test-bi-date-canceling.js would fail e.g.\n * on 64-bit Ubuntu, gcc-4.8.1, -m32, and no -std=c99.  Some date computations\n * using doubles would be optimized which then broke some corner case tests.\n * The problem goes away by adding 'volatile' to the datetime computations.\n * Not sure what the actual triggering conditions are, but using this on\n * non-C99 systems solves the known issues and has relatively little cost\n * on other platforms.\n */\n#undef DUK_USE_PARANOID_DATE_COMPUTATION\n#if !defined(DUK_F_C99)\n#define DUK_USE_PARANOID_DATE_COMPUTATION\n#endif\n\n/*\n *  Byte order and double memory layout detection\n *\n *  Endianness detection is a major portability hassle because the macros\n *  and headers are not standardized.  There's even variance across UNIX\n *  platforms.  Even with \"standard\" headers, details like underscore count\n *  varies between platforms, e.g. both __BYTE_ORDER and _BYTE_ORDER are used\n *  (Crossbridge has a single underscore, for instance).\n *\n *  The checks below are structured with this in mind: several approaches are\n *  used, and at the end we check if any of them worked.  This allows generic\n *  approaches to be tried first, and platform/compiler specific hacks tried\n *  last.  As a last resort, the user can force a specific endianness, as it's\n *  not likely that automatic detection will work on the most exotic platforms.\n *\n *  Duktape supports little and big endian machines.  There's also support\n *  for a hybrid used by some ARM machines where integers are little endian\n *  but IEEE double values use a mixed order (12345678 -> 43218765).  This\n *  byte order for doubles is referred to as \"mixed endian\".\n */\n\n/* GCC and Clang provide endianness defines as built-in predefines, with\n * leading and trailing double underscores (e.g. __BYTE_ORDER__).  See\n * output of \"make gccpredefs\" and \"make clangpredefs\".  Clang doesn't\n * seem to provide __FLOAT_WORD_ORDER__; assume not mixed endian for clang.\n * http://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html\n */\n#if !defined(DUK_USE_BYTEORDER) && defined(__BYTE_ORDER__)\n#if defined(__ORDER_LITTLE_ENDIAN__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)\n#if defined(__FLOAT_WORD_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && (__FLOAT_WORD_ORDER__ == __ORDER_LITTLE_ENDIAN__)\n#define DUK_USE_BYTEORDER 1\n#elif defined(__FLOAT_WORD_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && (__FLOAT_WORD_ORDER__ == __ORDER_BIG_ENDIAN__)\n#define DUK_USE_BYTEORDER 2\n#elif !defined(__FLOAT_WORD_ORDER__)\n/* Float word order not known, assume not a hybrid. */\n#define DUK_USE_BYTEORDER 1\n#else\n/* Byte order is little endian but cannot determine IEEE double word order. */\n#endif  /* float word order */\n#elif defined(__ORDER_BIG_ENDIAN__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)\n#if defined(__FLOAT_WORD_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && (__FLOAT_WORD_ORDER__ == __ORDER_BIG_ENDIAN__)\n#define DUK_USE_BYTEORDER 3\n#elif !defined(__FLOAT_WORD_ORDER__)\n/* Float word order not known, assume not a hybrid. */\n#define DUK_USE_BYTEORDER 3\n#else\n/* Byte order is big endian but cannot determine IEEE double word order. */\n#endif  /* float word order */\n#else\n/* Cannot determine byte order; __ORDER_PDP_ENDIAN__ is related to 32-bit\n * integer ordering and is not relevant.\n */\n#endif  /* integer byte order */\n#endif  /* !defined(DUK_USE_BYTEORDER) && defined(__BYTE_ORDER__) */\n\n/* More or less standard endianness predefines provided by header files.\n * The ARM hybrid case is detected by assuming that __FLOAT_WORD_ORDER\n * will be big endian, see: http://lists.mysql.com/internals/443.\n * On some platforms some defines may be present with an empty value which\n * causes comparisons to fail: https://github.com/svaarala/duktape/issues/453.\n */\n#if !defined(DUK_USE_BYTEORDER)\n#if defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && (__BYTE_ORDER == __LITTLE_ENDIAN) || \\\n    defined(_BYTE_ORDER) && defined(_LITTLE_ENDIAN) && (_BYTE_ORDER == _LITTLE_ENDIAN) || \\\n    defined(__LITTLE_ENDIAN__)\n#if defined(__FLOAT_WORD_ORDER) && defined(__LITTLE_ENDIAN) && (__FLOAT_WORD_ORDER == __LITTLE_ENDIAN) || \\\n    defined(_FLOAT_WORD_ORDER) && defined(_LITTLE_ENDIAN) && (_FLOAT_WORD_ORDER == _LITTLE_ENDIAN)\n#define DUK_USE_BYTEORDER 1\n#elif defined(__FLOAT_WORD_ORDER) && defined(__BIG_ENDIAN) && (__FLOAT_WORD_ORDER == __BIG_ENDIAN) || \\\n      defined(_FLOAT_WORD_ORDER) && defined(_BIG_ENDIAN) && (_FLOAT_WORD_ORDER == _BIG_ENDIAN)\n#define DUK_USE_BYTEORDER 2\n#elif !defined(__FLOAT_WORD_ORDER) && !defined(_FLOAT_WORD_ORDER)\n/* Float word order not known, assume not a hybrid. */\n#define DUK_USE_BYTEORDER 1\n#else\n/* Byte order is little endian but cannot determine IEEE double word order. */\n#endif  /* float word order */\n#elif defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && (__BYTE_ORDER == __BIG_ENDIAN) || \\\n      defined(_BYTE_ORDER) && defined(_BIG_ENDIAN) && (_BYTE_ORDER == _BIG_ENDIAN) || \\\n      defined(__BIG_ENDIAN__)\n#if defined(__FLOAT_WORD_ORDER) && defined(__BIG_ENDIAN) && (__FLOAT_WORD_ORDER == __BIG_ENDIAN) || \\\n    defined(_FLOAT_WORD_ORDER) && defined(_BIG_ENDIAN) && (_FLOAT_WORD_ORDER == _BIG_ENDIAN)\n#define DUK_USE_BYTEORDER 3\n#elif !defined(__FLOAT_WORD_ORDER) && !defined(_FLOAT_WORD_ORDER)\n/* Float word order not known, assume not a hybrid. */\n#define DUK_USE_BYTEORDER 3\n#else\n/* Byte order is big endian but cannot determine IEEE double word order. */\n#endif  /* float word order */\n#else\n/* Cannot determine byte order. */\n#endif  /* integer byte order */\n#endif  /* !defined(DUK_USE_BYTEORDER) */\n\n/* QNX gcc cross compiler seems to define e.g. __LITTLEENDIAN__ or __BIGENDIAN__:\n *  $ /opt/qnx650/host/linux/x86/usr/bin/i486-pc-nto-qnx6.5.0-gcc -dM -E - </dev/null | grep -ni endian\n *  67:#define __LITTLEENDIAN__ 1\n *  $ /opt/qnx650/host/linux/x86/usr/bin/mips-unknown-nto-qnx6.5.0-gcc -dM -E - </dev/null | grep -ni endian\n *  81:#define __BIGENDIAN__ 1\n *  $ /opt/qnx650/host/linux/x86/usr/bin/arm-unknown-nto-qnx6.5.0-gcc -dM -E - </dev/null | grep -ni endian\n *  70:#define __LITTLEENDIAN__ 1\n */\n#if !defined(DUK_USE_BYTEORDER)\n#if defined(__LITTLEENDIAN__)\n#define DUK_USE_BYTEORDER 1\n#elif defined(__BIGENDIAN__)\n#define DUK_USE_BYTEORDER 3\n#endif\n#endif\n\n/*\n *  Alignment requirement and support for unaligned accesses\n *\n *  Assume unaligned accesses are not supported unless specifically allowed\n *  in the target platform.  Some platforms may support unaligned accesses\n *  but alignment to 4 or 8 may still be desirable.\n */\n\n/* If not provided, use safe default for alignment. */\n#if !defined(DUK_USE_ALIGN_BY)\n#define DUK_USE_ALIGN_BY 8\n#endif\n\n/* Compiler specific hackery needed to force struct size to match aligment,\n * see e.g. duk_hbuffer.h.\n *\n * http://stackoverflow.com/questions/11130109/c-struct-size-alignment\n * http://stackoverflow.com/questions/10951039/specifying-64-bit-alignment\n */\n#if !(defined(DUK_USE_PACK_MSVC_PRAGMA) || defined(DUK_USE_PACK_GCC_ATTR) || \\\n      defined(DUK_USE_PACK_CLANG_ATTR) || defined(DUK_USE_PACK_DUMMY_MEMBER))\n#define DUK_USE_PACK_DUMMY_MEMBER\n#endif\n\n#if !defined(DUK_VA_COPY)\n/* We need va_copy() which is defined in C99 / C++11, so an awkward\n * replacement is needed for pre-C99 / pre-C++11 environments.  This\n * will quite likely need portability hacks for some non-C99\n * environments.\n */\n#if defined(DUK_F_C99) || defined(DUK_F_CPP11)\n/* C99 / C++11 and above: rely on va_copy() which is required.\n * Omit parenthesis on macro right side on purpose to minimize differences\n * to direct use.\n */\n#define DUK_VA_COPY(dest,src) va_copy(dest,src)\n#else\n/* Pre-C99: va_list type is implementation dependent.  This replacement\n * assumes it is a plain value so that a simple assignment will work.\n * This is not the case on all platforms (it may be a single-array element,\n * for instance).\n */\n#define DUK_VA_COPY(dest,src) do { (dest) = (src); } while (0)\n#endif\n#endif\n\n#if !defined(DUK_MACRO_STRINGIFY)\n/* Macro hackery to convert e.g. __LINE__ to a string without formatting,\n * see: http://stackoverflow.com/questions/240353/convert-a-preprocessor-token-to-a-string\n */\n#define DUK_MACRO_STRINGIFY_HELPER(x)  #x\n#define DUK_MACRO_STRINGIFY(x)  DUK_MACRO_STRINGIFY_HELPER(x)\n#endif\n\n#if !defined(DUK_CAUSE_SEGFAULT)\n/* This can be used for testing; valgrind will then indicate the C call stack\n * leading to the call site.\n */\n#define DUK_CAUSE_SEGFAULT()  do { *((volatile duk_uint32_t *) NULL) = (duk_uint32_t) 0xdeadbeefUL; } while (0)\n#endif\n#if !defined(DUK_UNREF)\n/* Macro for suppressing warnings for potentially unreferenced variables.\n * The variables can be actually unreferenced or unreferenced in some\n * specific cases only; for instance, if a variable is only debug printed,\n * it is unreferenced when debug printing is disabled.  May cause warnings\n * for volatile arguments.\n */\n#define DUK_UNREF(x)  do { (void) (x); } while (0)\n#endif\n#if !defined(DUK_NORETURN)\n#define DUK_NORETURN(decl)  decl\n#endif\n#if !defined(DUK_UNREACHABLE)\n/* Don't know how to declare unreachable point, so don't do it; this\n * may cause some spurious compilation warnings (e.g. \"variable used\n * uninitialized\").\n */\n#define DUK_UNREACHABLE()  do { } while (0)\n#endif\n#if !defined(DUK_LOSE_CONST)\n/* Convert any input pointer into a \"void *\", losing a const qualifier.\n * This is not fully portable because casting through duk_uintptr_t may\n * not work on all architectures (e.g. those with long, segmented pointers).\n */\n#define DUK_LOSE_CONST(src) ((void *) (duk_uintptr_t) (src))\n#endif\n\n#if !defined(DUK_LIKELY)\n#define DUK_LIKELY(x)    (x)\n#endif\n#if !defined(DUK_UNLIKELY)\n#define DUK_UNLIKELY(x)  (x)\n#endif\n#if !defined(DUK_UNPREDICTABLE)\n#define DUK_UNPREDICTABLE(x)  (x)\n#endif\n\n#if !defined(DUK_NOINLINE)\n#define DUK_NOINLINE       /*nop*/\n#endif\n#if !defined(DUK_INLINE)\n#define DUK_INLINE         /*nop*/\n#endif\n#if !defined(DUK_ALWAYS_INLINE)\n#define DUK_ALWAYS_INLINE  /*nop*/\n#endif\n\n#if !defined(DUK_HOT)\n#define DUK_HOT            /*nop*/\n#endif\n#if !defined(DUK_COLD)\n#define DUK_COLD           /*nop*/\n#endif\n\n#if !defined(DUK_EXTERNAL_DECL)\n#define DUK_EXTERNAL_DECL  extern\n#endif\n#if !defined(DUK_EXTERNAL)\n#define DUK_EXTERNAL       /*empty*/\n#endif\n#if !defined(DUK_INTERNAL_DECL)\n#if defined(DUK_SINGLE_FILE)\n#define DUK_INTERNAL_DECL  static\n#else\n#define DUK_INTERNAL_DECL  extern\n#endif\n#endif\n#if !defined(DUK_INTERNAL)\n#if defined(DUK_SINGLE_FILE)\n#define DUK_INTERNAL       static\n#else\n#define DUK_INTERNAL       /*empty*/\n#endif\n#endif\n#if !defined(DUK_LOCAL_DECL)\n#define DUK_LOCAL_DECL     static\n#endif\n#if !defined(DUK_LOCAL)\n#define DUK_LOCAL          static\n#endif\n\n#if !defined(DUK_FILE_MACRO)\n#define DUK_FILE_MACRO  __FILE__\n#endif\n#if !defined(DUK_LINE_MACRO)\n#define DUK_LINE_MACRO  __LINE__\n#endif\n#if !defined(DUK_FUNC_MACRO)\n#if defined(DUK_F_C99) || defined(DUK_F_CPP11)\n#define DUK_FUNC_MACRO  __func__\n#elif defined(__FUNCTION__)\n#define DUK_FUNC_MACRO  __FUNCTION__\n#else\n#define DUK_FUNC_MACRO  \"unknown\"\n#endif\n#endif\n\n#if !defined(DUK_BSWAP32)\n#define DUK_BSWAP32(x) \\\n\t((((duk_uint32_t) (x)) >> 24) | \\\n\t ((((duk_uint32_t) (x)) >> 8) & 0xff00UL) | \\\n\t ((((duk_uint32_t) (x)) << 8) & 0xff0000UL) | \\\n\t (((duk_uint32_t) (x)) << 24))\n#endif\n#if !defined(DUK_BSWAP16)\n#define DUK_BSWAP16(x) \\\n\t((duk_uint16_t) (x) >> 8) | \\\n\t((duk_uint16_t) (x) << 8)\n#endif\n\n/* DUK_USE_VARIADIC_MACROS: required from compilers, so no fill-in. */\n/* DUK_USE_UNION_INITIALIZERS: required from compilers, so no fill-in. */\n\n#if !(defined(DUK_USE_FLEX_C99) || defined(DUK_USE_FLEX_ZEROSIZE) || defined(DUK_USE_FLEX_ONESIZE))\n#if defined(DUK_F_C99)\n#define DUK_USE_FLEX_C99\n#else\n#define DUK_USE_FLEX_ZEROSIZE  /* Not standard but common enough */\n#endif\n#endif\n\n#if !(defined(DUK_USE_PACK_GCC_ATTR) || defined(DUK_USE_PACK_CLANG_ATTR) || \\\n      defined(DUK_USE_PACK_MSVC_PRAGMA) || defined(DUK_USE_PACK_DUMMY_MEMBER))\n#define DUK_USE_PACK_DUMMY_MEMBER\n#endif\n\n#if 0  /* not defined by default */\n#undef DUK_USE_GCC_PRAGMAS\n#endif\n\n#if !defined(DUK_U64_CONSTANT)\n#define DUK_U64_CONSTANT(x) x##ULL\n#endif\n#if !defined(DUK_I64_CONSTANT)\n#define DUK_I64_CONSTANT(x) x##LL\n#endif\n\n/* Workaround for GH-323: avoid inlining control when compiling from\n * multiple sources, as it causes compiler portability trouble.\n */\n#if !defined(DUK_SINGLE_FILE)\n#undef DUK_NOINLINE\n#undef DUK_INLINE\n#undef DUK_ALWAYS_INLINE\n#define DUK_NOINLINE       /*nop*/\n#define DUK_INLINE         /*nop*/\n#define DUK_ALWAYS_INLINE  /*nop*/\n#endif\n\n/*\n *  Check whether or not a packed duk_tval representation is possible.\n *  What's basically required is that pointers are 32-bit values\n *  (sizeof(void *) == 4).  Best effort check, not always accurate.\n *  If guess goes wrong, crashes may result; self tests also verify\n *  the guess.\n */\n\n/* Explicit marker needed; may be 'defined', 'undefined, 'or 'not provided'. */\n#if !defined(DUK_F_PACKED_TVAL_PROVIDED)\n#undef DUK_F_PACKED_TVAL_POSSIBLE\n\n/* Strict C99 case: DUK_UINTPTR_MAX (= UINTPTR_MAX) should be very reliable */\n#if !defined(DUK_F_PACKED_TVAL_POSSIBLE) && defined(DUK_UINTPTR_MAX)\n#if (DUK_UINTPTR_MAX <= 0xffffffffUL)\n#define DUK_F_PACKED_TVAL_POSSIBLE\n#endif\n#endif\n\n/* Non-C99 case, still relying on DUK_UINTPTR_MAX, as long as it is not a computed value */\n#if !defined(DUK_F_PACKED_TVAL_POSSIBLE) && defined(DUK_UINTPTR_MAX) && !defined(DUK_UINTPTR_MAX_COMPUTED)\n#if (DUK_UINTPTR_MAX <= 0xffffffffUL)\n#define DUK_F_PACKED_TVAL_POSSIBLE\n#endif\n#endif\n\n/* DUK_SIZE_MAX (= SIZE_MAX) is often reliable */\n#if !defined(DUK_F_PACKED_TVAL_POSSIBLE) && defined(DUK_SIZE_MAX) && !defined(DUK_SIZE_MAX_COMPUTED)\n#if (DUK_SIZE_MAX <= 0xffffffffUL)\n#define DUK_F_PACKED_TVAL_POSSIBLE\n#endif\n#endif\n\n#undef DUK_USE_PACKED_TVAL\n#if defined(DUK_F_PACKED_TVAL_POSSIBLE)\n#define DUK_USE_PACKED_TVAL\n#endif\n\n#undef DUK_F_PACKED_TVAL_POSSIBLE\n#endif  /* DUK_F_PACKED_TVAL_PROVIDED */\n/* Object property allocation layout has implications for memory and code\n * footprint and generated code size/speed.  The best layout also depends\n * on whether the platform has alignment requirements or benefits from\n * having mostly aligned accesses.\n */\n#undef DUK_USE_HOBJECT_LAYOUT_1\n#undef DUK_USE_HOBJECT_LAYOUT_2\n#undef DUK_USE_HOBJECT_LAYOUT_3\n#if (DUK_USE_ALIGN_BY == 1)\n/* On platforms without any alignment issues, layout 1 is preferable\n * because it compiles to slightly less code and provides direct access\n * to property keys.\n */\n#define DUK_USE_HOBJECT_LAYOUT_1\n#else\n/* On other platforms use layout 2, which requires some padding but\n * is a bit more natural than layout 3 in ordering the entries.  Layout\n * 3 is currently not used.\n */\n#define DUK_USE_HOBJECT_LAYOUT_2\n#endif\n\n/* GCC/clang inaccurate math would break compliance and probably duk_tval,\n * so refuse to compile.  Relax this if -ffast-math is tested to work.\n */\n#if defined(__FAST_MATH__)\n#error __FAST_MATH__ defined, refusing to compile\n#endif\n\n/*\n *  Autogenerated defaults\n */\n\n#define DUK_USE_ARRAY_BUILTIN\n#define DUK_USE_ARRAY_FASTPATH\n#define DUK_USE_ARRAY_PROP_FASTPATH\n#undef DUK_USE_ASSERTIONS\n#define DUK_USE_AUGMENT_ERROR_CREATE\n#define DUK_USE_AUGMENT_ERROR_THROW\n#define DUK_USE_AVOID_PLATFORM_FUNCPTRS\n#define DUK_USE_BASE64_FASTPATH\n#define DUK_USE_BOOLEAN_BUILTIN\n#define DUK_USE_BUFFEROBJECT_SUPPORT\n#undef DUK_USE_BUFLEN16\n#define DUK_USE_BYTECODE_DUMP_SUPPORT\n#define DUK_USE_CACHE_ACTIVATION\n#define DUK_USE_CACHE_CATCHER\n#define DUK_USE_CALLSTACK_LIMIT 10000\n#define DUK_USE_COMMONJS_MODULES\n#define DUK_USE_COMPILER_RECLIMIT 2500\n#define DUK_USE_COROUTINE_SUPPORT\n#undef DUK_USE_CPP_EXCEPTIONS\n#undef DUK_USE_DATAPTR16\n#undef DUK_USE_DATAPTR_DEC16\n#undef DUK_USE_DATAPTR_ENC16\n#define DUK_USE_DATE_BUILTIN\n#undef DUK_USE_DATE_FORMAT_STRING\n#undef DUK_USE_DATE_GET_LOCAL_TZOFFSET\n#undef DUK_USE_DATE_GET_NOW\n#undef DUK_USE_DATE_PARSE_STRING\n#undef DUK_USE_DATE_PRS_GETDATE\n#undef DUK_USE_DEBUG\n#undef DUK_USE_DEBUGGER_DUMPHEAP\n#undef DUK_USE_DEBUGGER_INSPECT\n#undef DUK_USE_DEBUGGER_PAUSE_UNCAUGHT\n#undef DUK_USE_DEBUGGER_SUPPORT\n#define DUK_USE_DEBUGGER_THROW_NOTIFY\n#undef DUK_USE_DEBUGGER_TRANSPORT_TORTURE\n#define DUK_USE_DEBUG_BUFSIZE 65536L\n#define DUK_USE_DEBUG_LEVEL 0\n#undef DUK_USE_DEBUG_WRITE\n#define DUK_USE_DOUBLE_LINKED_HEAP\n#define DUK_USE_DUKTAPE_BUILTIN\n#define DUK_USE_ENCODING_BUILTINS\n#define DUK_USE_ERRCREATE\n#define DUK_USE_ERRTHROW\n#define DUK_USE_ES6\n#define DUK_USE_ES6_OBJECT_PROTO_PROPERTY\n#define DUK_USE_ES6_OBJECT_SETPROTOTYPEOF\n#define DUK_USE_ES6_PROXY\n#define DUK_USE_ES6_REGEXP_SYNTAX\n#define DUK_USE_ES6_UNICODE_ESCAPE\n#define DUK_USE_ES7\n#define DUK_USE_ES7_EXP_OPERATOR\n#define DUK_USE_ES8\n#define DUK_USE_ES9\n#define DUK_USE_ESBC_LIMITS\n#define DUK_USE_ESBC_MAX_BYTES 2147418112L\n#define DUK_USE_ESBC_MAX_LINENUMBER 2147418112L\n#undef DUK_USE_EXEC_FUN_LOCAL\n#undef DUK_USE_EXEC_INDIRECT_BOUND_CHECK\n#undef DUK_USE_EXEC_PREFER_SIZE\n#define DUK_USE_EXEC_REGCONST_OPTIMIZE\n#undef DUK_USE_EXEC_TIMEOUT_CHECK\n#undef DUK_USE_EXPLICIT_NULL_INIT\n#undef DUK_USE_EXTSTR_FREE\n#undef DUK_USE_EXTSTR_INTERN_CHECK\n#undef DUK_USE_FASTINT\n#define DUK_USE_FAST_REFCOUNT_DEFAULT\n#undef DUK_USE_FATAL_HANDLER\n#define DUK_USE_FATAL_MAXLEN 128\n#define DUK_USE_FINALIZER_SUPPORT\n#undef DUK_USE_FINALIZER_TORTURE\n#undef DUK_USE_FUNCPTR16\n#undef DUK_USE_FUNCPTR_DEC16\n#undef DUK_USE_FUNCPTR_ENC16\n#define DUK_USE_FUNCTION_BUILTIN\n#define DUK_USE_FUNC_FILENAME_PROPERTY\n#define DUK_USE_FUNC_NAME_PROPERTY\n#undef DUK_USE_GC_TORTURE\n#undef DUK_USE_GET_MONOTONIC_TIME\n#undef DUK_USE_GET_RANDOM_DOUBLE\n#undef DUK_USE_GLOBAL_BINDING\n#define DUK_USE_GLOBAL_BUILTIN\n#undef DUK_USE_HEAPPTR16\n#undef DUK_USE_HEAPPTR_DEC16\n#undef DUK_USE_HEAPPTR_ENC16\n#define DUK_USE_HEX_FASTPATH\n#define DUK_USE_HOBJECT_ARRAY_ABANDON_LIMIT 2\n#define DUK_USE_HOBJECT_ARRAY_FAST_RESIZE_LIMIT 9\n#define DUK_USE_HOBJECT_ARRAY_MINGROW_ADD 16\n#define DUK_USE_HOBJECT_ARRAY_MINGROW_DIVISOR 8\n#define DUK_USE_HOBJECT_ENTRY_MINGROW_ADD 16\n#define DUK_USE_HOBJECT_ENTRY_MINGROW_DIVISOR 8\n#define DUK_USE_HOBJECT_HASH_PART\n#define DUK_USE_HOBJECT_HASH_PROP_LIMIT 8\n#define DUK_USE_HSTRING_ARRIDX\n#define DUK_USE_HSTRING_CLEN\n#undef DUK_USE_HSTRING_EXTDATA\n#define DUK_USE_HSTRING_LAZY_CLEN\n#define DUK_USE_HTML_COMMENTS\n#define DUK_USE_IDCHAR_FASTPATH\n#undef DUK_USE_INJECT_HEAP_ALLOC_ERROR\n#undef DUK_USE_INTERRUPT_COUNTER\n#undef DUK_USE_INTERRUPT_DEBUG_FIXUP\n#define DUK_USE_JC\n#define DUK_USE_JSON_BUILTIN\n#define DUK_USE_JSON_DECNUMBER_FASTPATH\n#define DUK_USE_JSON_DECSTRING_FASTPATH\n#define DUK_USE_JSON_DEC_RECLIMIT 1000\n#define DUK_USE_JSON_EATWHITE_FASTPATH\n#define DUK_USE_JSON_ENC_RECLIMIT 1000\n#define DUK_USE_JSON_QUOTESTRING_FASTPATH\n#undef DUK_USE_JSON_STRINGIFY_FASTPATH\n#define DUK_USE_JSON_SUPPORT\n#define DUK_USE_JX\n#define DUK_USE_LEXER_SLIDING_WINDOW\n#undef DUK_USE_LIGHTFUNC_BUILTINS\n#define DUK_USE_MARK_AND_SWEEP_RECLIMIT 256\n#define DUK_USE_MATH_BUILTIN\n#define DUK_USE_NATIVE_CALL_RECLIMIT 1000\n#define DUK_USE_NONSTD_ARRAY_CONCAT_TRAILER\n#define DUK_USE_NONSTD_ARRAY_MAP_TRAILER\n#define DUK_USE_NONSTD_ARRAY_SPLICE_DELCOUNT\n#undef DUK_USE_NONSTD_FUNC_CALLER_PROPERTY\n#undef DUK_USE_NONSTD_FUNC_SOURCE_PROPERTY\n#define DUK_USE_NONSTD_FUNC_STMT\n#define DUK_USE_NONSTD_GETTER_KEY_ARGUMENT\n#define DUK_USE_NONSTD_JSON_ESC_U2028_U2029\n#define DUK_USE_NONSTD_SETTER_KEY_ARGUMENT\n#define DUK_USE_NONSTD_STRING_FROMCHARCODE_32BIT\n#define DUK_USE_NUMBER_BUILTIN\n#define DUK_USE_OBJECT_BUILTIN\n#undef DUK_USE_OBJSIZES16\n#undef DUK_USE_PARANOID_ERRORS\n#define DUK_USE_PC2LINE\n#define DUK_USE_PERFORMANCE_BUILTIN\n#undef DUK_USE_PREFER_SIZE\n#undef DUK_USE_PROMISE_BUILTIN\n#define DUK_USE_PROVIDE_DEFAULT_ALLOC_FUNCTIONS\n#undef DUK_USE_REFCOUNT16\n#define DUK_USE_REFCOUNT32\n#define DUK_USE_REFERENCE_COUNTING\n#define DUK_USE_REFLECT_BUILTIN\n#define DUK_USE_REGEXP_CANON_BITMAP\n#undef DUK_USE_REGEXP_CANON_WORKAROUND\n#define DUK_USE_REGEXP_COMPILER_RECLIMIT 10000\n#define DUK_USE_REGEXP_EXECUTOR_RECLIMIT 10000\n#define DUK_USE_REGEXP_SUPPORT\n#undef DUK_USE_ROM_GLOBAL_CLONE\n#undef DUK_USE_ROM_GLOBAL_INHERIT\n#undef DUK_USE_ROM_OBJECTS\n#define DUK_USE_ROM_PTRCOMP_FIRST 63488L\n#undef DUK_USE_ROM_STRINGS\n#define DUK_USE_SECTION_B\n#undef DUK_USE_SELF_TESTS\n#define DUK_USE_SHEBANG_COMMENTS\n#undef DUK_USE_SHUFFLE_TORTURE\n#define DUK_USE_SOURCE_NONBMP\n#undef DUK_USE_STRHASH16\n#undef DUK_USE_STRHASH_DENSE\n#define DUK_USE_STRHASH_SKIP_SHIFT 5\n#define DUK_USE_STRICT_DECL\n#undef DUK_USE_STRICT_UTF8_SOURCE\n#define DUK_USE_STRING_BUILTIN\n#undef DUK_USE_STRLEN16\n#define DUK_USE_STRTAB_GROW_LIMIT 17\n#define DUK_USE_STRTAB_MAXSIZE 268435456L\n#define DUK_USE_STRTAB_MINSIZE 1024\n#undef DUK_USE_STRTAB_PTRCOMP\n#define DUK_USE_STRTAB_RESIZE_CHECK_MASK 255\n#define DUK_USE_STRTAB_SHRINK_LIMIT 6\n#undef DUK_USE_STRTAB_TORTURE\n#undef DUK_USE_SYMBOL_BUILTIN\n#define DUK_USE_TAILCALL\n#define DUK_USE_TARGET_INFO \"unknown\"\n#define DUK_USE_TRACEBACKS\n#define DUK_USE_TRACEBACK_DEPTH 10\n#define DUK_USE_USER_DECLARE() /* no user declarations */\n#define DUK_USE_VALSTACK_GROW_SHIFT 2\n#define DUK_USE_VALSTACK_LIMIT 1000000L\n#define DUK_USE_VALSTACK_SHRINK_CHECK_SHIFT 2\n#define DUK_USE_VALSTACK_SHRINK_SLACK_SHIFT 4\n#undef DUK_USE_VALSTACK_UNSAFE\n#define DUK_USE_VERBOSE_ERRORS\n#define DUK_USE_VERBOSE_EXECUTOR_ERRORS\n#define DUK_USE_VOLUNTARY_GC\n#define DUK_USE_ZERO_BUFFER_DATA\n\n/*\n *  You may add overriding #define/#undef directives below for\n *  customization.  You of course cannot un-#include or un-typedef\n *  anything; these require direct changes above.\n */\n\n/* __OVERRIDE_DEFINES__ */\n\n/*\n *  Date provider selection\n *\n *  User may define DUK_USE_DATE_GET_NOW() etc directly, in which case we'll\n *  rely on an external provider.  If this is not done, revert to previous\n *  behavior and use Unix/Windows built-in provider.\n */\n\n#if defined(DUK_COMPILING_DUKTAPE)\n\n#if defined(DUK_USE_DATE_GET_NOW)\n/* External provider already defined. */\n#elif defined(DUK_USE_DATE_NOW_GETTIMEOFDAY)\n#define DUK_USE_DATE_GET_NOW(ctx)            duk_bi_date_get_now_gettimeofday()\n#elif defined(DUK_USE_DATE_NOW_TIME)\n#define DUK_USE_DATE_GET_NOW(ctx)            duk_bi_date_get_now_time()\n#elif defined(DUK_USE_DATE_NOW_WINDOWS)\n#define DUK_USE_DATE_GET_NOW(ctx)            duk_bi_date_get_now_windows()\n#elif defined(DUK_USE_DATE_NOW_WINDOWS_SUBMS)\n#define DUK_USE_DATE_GET_NOW(ctx)            duk_bi_date_get_now_windows_subms()\n#else\n#error no provider for DUK_USE_DATE_GET_NOW()\n#endif\n\n#if defined(DUK_USE_DATE_GET_LOCAL_TZOFFSET)\n/* External provider already defined. */\n#elif defined(DUK_USE_DATE_TZO_GMTIME_R) || defined(DUK_USE_DATE_TZO_GMTIME_S) || defined(DUK_USE_DATE_TZO_GMTIME)\n#define DUK_USE_DATE_GET_LOCAL_TZOFFSET(d)   duk_bi_date_get_local_tzoffset_gmtime((d))\n#elif defined(DUK_USE_DATE_TZO_WINDOWS)\n#define DUK_USE_DATE_GET_LOCAL_TZOFFSET(d)   duk_bi_date_get_local_tzoffset_windows((d))\n#elif defined(DUK_USE_DATE_TZO_WINDOWS_NO_DST)\n#define DUK_USE_DATE_GET_LOCAL_TZOFFSET(d)   duk_bi_date_get_local_tzoffset_windows_no_dst((d))\n#else\n#error no provider for DUK_USE_DATE_GET_LOCAL_TZOFFSET()\n#endif\n\n#if defined(DUK_USE_DATE_PARSE_STRING)\n/* External provider already defined. */\n#elif defined(DUK_USE_DATE_PRS_STRPTIME)\n#define DUK_USE_DATE_PARSE_STRING(ctx,str)   duk_bi_date_parse_string_strptime((ctx), (str))\n#elif defined(DUK_USE_DATE_PRS_GETDATE)\n#define DUK_USE_DATE_PARSE_STRING(ctx,str)   duk_bi_date_parse_string_getdate((ctx), (str))\n#else\n/* No provider for DUK_USE_DATE_PARSE_STRING(), fall back to ISO 8601 only. */\n#endif\n\n#if defined(DUK_USE_DATE_FORMAT_STRING)\n/* External provider already defined. */\n#elif defined(DUK_USE_DATE_FMT_STRFTIME)\n#define DUK_USE_DATE_FORMAT_STRING(ctx,parts,tzoffset,flags) \\\n\tduk_bi_date_format_parts_strftime((ctx), (parts), (tzoffset), (flags))\n#else\n/* No provider for DUK_USE_DATE_FORMAT_STRING(), fall back to ISO 8601 only. */\n#endif\n\n#if defined(DUK_USE_GET_MONOTONIC_TIME)\n/* External provider already defined. */\n#elif defined(DUK_USE_GET_MONOTONIC_TIME_CLOCK_GETTIME)\n#define DUK_USE_GET_MONOTONIC_TIME(ctx)  duk_bi_date_get_monotonic_time_clock_gettime()\n#elif defined(DUK_USE_GET_MONOTONIC_TIME_WINDOWS_QPC)\n#define DUK_USE_GET_MONOTONIC_TIME(ctx)  duk_bi_date_get_monotonic_time_windows_qpc()\n#else\n/* No provider for DUK_USE_GET_MONOTONIC_TIME(), fall back to DUK_USE_DATE_GET_NOW(). */\n#endif\n\n#endif  /* DUK_COMPILING_DUKTAPE */\n\n/*\n *  Checks for legacy feature options (DUK_OPT_xxx)\n */\n\n#if defined(DUK_OPT_ASSERTIONS)\n#error unsupported legacy feature option DUK_OPT_ASSERTIONS used\n#endif\n#if defined(DUK_OPT_BUFFEROBJECT_SUPPORT)\n#error unsupported legacy feature option DUK_OPT_BUFFEROBJECT_SUPPORT used\n#endif\n#if defined(DUK_OPT_BUFLEN16)\n#error unsupported legacy feature option DUK_OPT_BUFLEN16 used\n#endif\n#if defined(DUK_OPT_DATAPTR16)\n#error unsupported legacy feature option DUK_OPT_DATAPTR16 used\n#endif\n#if defined(DUK_OPT_DATAPTR_DEC16)\n#error unsupported legacy feature option DUK_OPT_DATAPTR_DEC16 used\n#endif\n#if defined(DUK_OPT_DATAPTR_ENC16)\n#error unsupported legacy feature option DUK_OPT_DATAPTR_ENC16 used\n#endif\n#if defined(DUK_OPT_DDDPRINT)\n#error unsupported legacy feature option DUK_OPT_DDDPRINT used\n#endif\n#if defined(DUK_OPT_DDPRINT)\n#error unsupported legacy feature option DUK_OPT_DDPRINT used\n#endif\n#if defined(DUK_OPT_DEBUG)\n#error unsupported legacy feature option DUK_OPT_DEBUG used\n#endif\n#if defined(DUK_OPT_DEBUGGER_DUMPHEAP)\n#error unsupported legacy feature option DUK_OPT_DEBUGGER_DUMPHEAP used\n#endif\n#if defined(DUK_OPT_DEBUGGER_FWD_LOGGING)\n#error unsupported legacy feature option DUK_OPT_DEBUGGER_FWD_LOGGING used\n#endif\n#if defined(DUK_OPT_DEBUGGER_FWD_PRINTALERT)\n#error unsupported legacy feature option DUK_OPT_DEBUGGER_FWD_PRINTALERT used\n#endif\n#if defined(DUK_OPT_DEBUGGER_SUPPORT)\n#error unsupported legacy feature option DUK_OPT_DEBUGGER_SUPPORT used\n#endif\n#if defined(DUK_OPT_DEBUGGER_TRANSPORT_TORTURE)\n#error unsupported legacy feature option DUK_OPT_DEBUGGER_TRANSPORT_TORTURE used\n#endif\n#if defined(DUK_OPT_DEBUG_BUFSIZE)\n#error unsupported legacy feature option DUK_OPT_DEBUG_BUFSIZE used\n#endif\n#if defined(DUK_OPT_DECLARE)\n#error unsupported legacy feature option DUK_OPT_DECLARE used\n#endif\n#if defined(DUK_OPT_DEEP_C_STACK)\n#error unsupported legacy feature option DUK_OPT_DEEP_C_STACK used\n#endif\n#if defined(DUK_OPT_DLL_BUILD)\n#error unsupported legacy feature option DUK_OPT_DLL_BUILD used\n#endif\n#if defined(DUK_OPT_DPRINT)\n#error unsupported legacy feature option DUK_OPT_DPRINT used\n#endif\n#if defined(DUK_OPT_DPRINT_COLORS)\n#error unsupported legacy feature option DUK_OPT_DPRINT_COLORS used\n#endif\n#if defined(DUK_OPT_DPRINT_RDTSC)\n#error unsupported legacy feature option DUK_OPT_DPRINT_RDTSC used\n#endif\n#if defined(DUK_OPT_EXEC_TIMEOUT_CHECK)\n#error unsupported legacy feature option DUK_OPT_EXEC_TIMEOUT_CHECK used\n#endif\n#if defined(DUK_OPT_EXTERNAL_STRINGS)\n#error unsupported legacy feature option DUK_OPT_EXTERNAL_STRINGS used\n#endif\n#if defined(DUK_OPT_EXTSTR_FREE)\n#error unsupported legacy feature option DUK_OPT_EXTSTR_FREE used\n#endif\n#if defined(DUK_OPT_EXTSTR_INTERN_CHECK)\n#error unsupported legacy feature option DUK_OPT_EXTSTR_INTERN_CHECK used\n#endif\n#if defined(DUK_OPT_FASTINT)\n#error unsupported legacy feature option DUK_OPT_FASTINT used\n#endif\n#if defined(DUK_OPT_FORCE_ALIGN)\n#error unsupported legacy feature option DUK_OPT_FORCE_ALIGN used\n#endif\n#if defined(DUK_OPT_FORCE_BYTEORDER)\n#error unsupported legacy feature option DUK_OPT_FORCE_BYTEORDER used\n#endif\n#if defined(DUK_OPT_FUNCPTR16)\n#error unsupported legacy feature option DUK_OPT_FUNCPTR16 used\n#endif\n#if defined(DUK_OPT_FUNCPTR_DEC16)\n#error unsupported legacy feature option DUK_OPT_FUNCPTR_DEC16 used\n#endif\n#if defined(DUK_OPT_FUNCPTR_ENC16)\n#error unsupported legacy feature option DUK_OPT_FUNCPTR_ENC16 used\n#endif\n#if defined(DUK_OPT_FUNC_NONSTD_CALLER_PROPERTY)\n#error unsupported legacy feature option DUK_OPT_FUNC_NONSTD_CALLER_PROPERTY used\n#endif\n#if defined(DUK_OPT_FUNC_NONSTD_SOURCE_PROPERTY)\n#error unsupported legacy feature option DUK_OPT_FUNC_NONSTD_SOURCE_PROPERTY used\n#endif\n#if defined(DUK_OPT_GC_TORTURE)\n#error unsupported legacy feature option DUK_OPT_GC_TORTURE used\n#endif\n#if defined(DUK_OPT_HAVE_CUSTOM_H)\n#error unsupported legacy feature option DUK_OPT_HAVE_CUSTOM_H used\n#endif\n#if defined(DUK_OPT_HEAPPTR16)\n#error unsupported legacy feature option DUK_OPT_HEAPPTR16 used\n#endif\n#if defined(DUK_OPT_HEAPPTR_DEC16)\n#error unsupported legacy feature option DUK_OPT_HEAPPTR_DEC16 used\n#endif\n#if defined(DUK_OPT_HEAPPTR_ENC16)\n#error unsupported legacy feature option DUK_OPT_HEAPPTR_ENC16 used\n#endif\n#if defined(DUK_OPT_INTERRUPT_COUNTER)\n#error unsupported legacy feature option DUK_OPT_INTERRUPT_COUNTER used\n#endif\n#if defined(DUK_OPT_JSON_STRINGIFY_FASTPATH)\n#error unsupported legacy feature option DUK_OPT_JSON_STRINGIFY_FASTPATH used\n#endif\n#if defined(DUK_OPT_LIGHTFUNC_BUILTINS)\n#error unsupported legacy feature option DUK_OPT_LIGHTFUNC_BUILTINS used\n#endif\n#if defined(DUK_OPT_NONSTD_FUNC_CALLER_PROPERTY)\n#error unsupported legacy feature option DUK_OPT_NONSTD_FUNC_CALLER_PROPERTY used\n#endif\n#if defined(DUK_OPT_NONSTD_FUNC_SOURCE_PROPERTY)\n#error unsupported legacy feature option DUK_OPT_NONSTD_FUNC_SOURCE_PROPERTY used\n#endif\n#if defined(DUK_OPT_NO_ARRAY_SPLICE_NONSTD_DELCOUNT)\n#error unsupported legacy feature option DUK_OPT_NO_ARRAY_SPLICE_NONSTD_DELCOUNT used\n#endif\n#if defined(DUK_OPT_NO_AUGMENT_ERRORS)\n#error unsupported legacy feature option DUK_OPT_NO_AUGMENT_ERRORS used\n#endif\n#if defined(DUK_OPT_NO_BROWSER_LIKE)\n#error unsupported legacy feature option DUK_OPT_NO_BROWSER_LIKE used\n#endif\n#if defined(DUK_OPT_NO_BUFFEROBJECT_SUPPORT)\n#error unsupported legacy feature option DUK_OPT_NO_BUFFEROBJECT_SUPPORT used\n#endif\n#if defined(DUK_OPT_NO_BYTECODE_DUMP_SUPPORT)\n#error unsupported legacy feature option DUK_OPT_NO_BYTECODE_DUMP_SUPPORT used\n#endif\n#if defined(DUK_OPT_NO_COMMONJS_MODULES)\n#error unsupported legacy feature option DUK_OPT_NO_COMMONJS_MODULES used\n#endif\n#if defined(DUK_OPT_NO_ES6_OBJECT_PROTO_PROPERTY)\n#error unsupported legacy feature option DUK_OPT_NO_ES6_OBJECT_PROTO_PROPERTY used\n#endif\n#if defined(DUK_OPT_NO_ES6_OBJECT_SETPROTOTYPEOF)\n#error unsupported legacy feature option DUK_OPT_NO_ES6_OBJECT_SETPROTOTYPEOF used\n#endif\n#if defined(DUK_OPT_NO_ES6_PROXY)\n#error unsupported legacy feature option DUK_OPT_NO_ES6_PROXY used\n#endif\n#if defined(DUK_OPT_NO_FILE_IO)\n#error unsupported legacy feature option DUK_OPT_NO_FILE_IO used\n#endif\n#if defined(DUK_OPT_NO_FUNC_STMT)\n#error unsupported legacy feature option DUK_OPT_NO_FUNC_STMT used\n#endif\n#if defined(DUK_OPT_NO_JC)\n#error unsupported legacy feature option DUK_OPT_NO_JC used\n#endif\n#if defined(DUK_OPT_NO_JSONC)\n#error unsupported legacy feature option DUK_OPT_NO_JSONC used\n#endif\n#if defined(DUK_OPT_NO_JSONX)\n#error unsupported legacy feature option DUK_OPT_NO_JSONX used\n#endif\n#if defined(DUK_OPT_NO_JX)\n#error unsupported legacy feature option DUK_OPT_NO_JX used\n#endif\n#if defined(DUK_OPT_NO_MARK_AND_SWEEP)\n#error unsupported legacy feature option DUK_OPT_NO_MARK_AND_SWEEP used\n#endif\n#if defined(DUK_OPT_NO_MS_STRINGTABLE_RESIZE)\n#error unsupported legacy feature option DUK_OPT_NO_MS_STRINGTABLE_RESIZE used\n#endif\n#if defined(DUK_OPT_NO_NONSTD_ACCESSOR_KEY_ARGUMENT)\n#error unsupported legacy feature option DUK_OPT_NO_NONSTD_ACCESSOR_KEY_ARGUMENT used\n#endif\n#if defined(DUK_OPT_NO_NONSTD_ARRAY_CONCAT_TRAILER)\n#error unsupported legacy feature option DUK_OPT_NO_NONSTD_ARRAY_CONCAT_TRAILER used\n#endif\n#if defined(DUK_OPT_NO_NONSTD_ARRAY_MAP_TRAILER)\n#error unsupported legacy feature option DUK_OPT_NO_NONSTD_ARRAY_MAP_TRAILER used\n#endif\n#if defined(DUK_OPT_NO_NONSTD_ARRAY_SPLICE_DELCOUNT)\n#error unsupported legacy feature option DUK_OPT_NO_NONSTD_ARRAY_SPLICE_DELCOUNT used\n#endif\n#if defined(DUK_OPT_NO_NONSTD_FUNC_STMT)\n#error unsupported legacy feature option DUK_OPT_NO_NONSTD_FUNC_STMT used\n#endif\n#if defined(DUK_OPT_NO_NONSTD_JSON_ESC_U2028_U2029)\n#error unsupported legacy feature option DUK_OPT_NO_NONSTD_JSON_ESC_U2028_U2029 used\n#endif\n#if defined(DUK_OPT_NO_NONSTD_STRING_FROMCHARCODE_32BIT)\n#error unsupported legacy feature option DUK_OPT_NO_NONSTD_STRING_FROMCHARCODE_32BIT used\n#endif\n#if defined(DUK_OPT_NO_OBJECT_ES6_PROTO_PROPERTY)\n#error unsupported legacy feature option DUK_OPT_NO_OBJECT_ES6_PROTO_PROPERTY used\n#endif\n#if defined(DUK_OPT_NO_OBJECT_ES6_SETPROTOTYPEOF)\n#error unsupported legacy feature option DUK_OPT_NO_OBJECT_ES6_SETPROTOTYPEOF used\n#endif\n#if defined(DUK_OPT_NO_OCTAL_SUPPORT)\n#error unsupported legacy feature option DUK_OPT_NO_OCTAL_SUPPORT used\n#endif\n#if defined(DUK_OPT_NO_PACKED_TVAL)\n#error unsupported legacy feature option DUK_OPT_NO_PACKED_TVAL used\n#endif\n#if defined(DUK_OPT_NO_PC2LINE)\n#error unsupported legacy feature option DUK_OPT_NO_PC2LINE used\n#endif\n#if defined(DUK_OPT_NO_REFERENCE_COUNTING)\n#error unsupported legacy feature option DUK_OPT_NO_REFERENCE_COUNTING used\n#endif\n#if defined(DUK_OPT_NO_REGEXP_SUPPORT)\n#error unsupported legacy feature option DUK_OPT_NO_REGEXP_SUPPORT used\n#endif\n#if defined(DUK_OPT_NO_SECTION_B)\n#error unsupported legacy feature option DUK_OPT_NO_SECTION_B used\n#endif\n#if defined(DUK_OPT_NO_SOURCE_NONBMP)\n#error unsupported legacy feature option DUK_OPT_NO_SOURCE_NONBMP used\n#endif\n#if defined(DUK_OPT_NO_STRICT_DECL)\n#error unsupported legacy feature option DUK_OPT_NO_STRICT_DECL used\n#endif\n#if defined(DUK_OPT_NO_TRACEBACKS)\n#error unsupported legacy feature option DUK_OPT_NO_TRACEBACKS used\n#endif\n#if defined(DUK_OPT_NO_VERBOSE_ERRORS)\n#error unsupported legacy feature option DUK_OPT_NO_VERBOSE_ERRORS used\n#endif\n#if defined(DUK_OPT_NO_VOLUNTARY_GC)\n#error unsupported legacy feature option DUK_OPT_NO_VOLUNTARY_GC used\n#endif\n#if defined(DUK_OPT_NO_ZERO_BUFFER_DATA)\n#error unsupported legacy feature option DUK_OPT_NO_ZERO_BUFFER_DATA used\n#endif\n#if defined(DUK_OPT_OBJSIZES16)\n#error unsupported legacy feature option DUK_OPT_OBJSIZES16 used\n#endif\n#if defined(DUK_OPT_PANIC_HANDLER)\n#error unsupported legacy feature option DUK_OPT_PANIC_HANDLER used\n#endif\n#if defined(DUK_OPT_REFCOUNT16)\n#error unsupported legacy feature option DUK_OPT_REFCOUNT16 used\n#endif\n#if defined(DUK_OPT_SEGFAULT_ON_PANIC)\n#error unsupported legacy feature option DUK_OPT_SEGFAULT_ON_PANIC used\n#endif\n#if defined(DUK_OPT_SELF_TESTS)\n#error unsupported legacy feature option DUK_OPT_SELF_TESTS used\n#endif\n#if defined(DUK_OPT_SETJMP)\n#error unsupported legacy feature option DUK_OPT_SETJMP used\n#endif\n#if defined(DUK_OPT_SHUFFLE_TORTURE)\n#error unsupported legacy feature option DUK_OPT_SHUFFLE_TORTURE used\n#endif\n#if defined(DUK_OPT_SIGSETJMP)\n#error unsupported legacy feature option DUK_OPT_SIGSETJMP used\n#endif\n#if defined(DUK_OPT_STRHASH16)\n#error unsupported legacy feature option DUK_OPT_STRHASH16 used\n#endif\n#if defined(DUK_OPT_STRICT_UTF8_SOURCE)\n#error unsupported legacy feature option DUK_OPT_STRICT_UTF8_SOURCE used\n#endif\n#if defined(DUK_OPT_STRLEN16)\n#error unsupported legacy feature option DUK_OPT_STRLEN16 used\n#endif\n#if defined(DUK_OPT_STRTAB_CHAIN)\n#error unsupported legacy feature option DUK_OPT_STRTAB_CHAIN used\n#endif\n#if defined(DUK_OPT_STRTAB_CHAIN_SIZE)\n#error unsupported legacy feature option DUK_OPT_STRTAB_CHAIN_SIZE used\n#endif\n#if defined(DUK_OPT_TARGET_INFO)\n#error unsupported legacy feature option DUK_OPT_TARGET_INFO used\n#endif\n#if defined(DUK_OPT_TRACEBACK_DEPTH)\n#error unsupported legacy feature option DUK_OPT_TRACEBACK_DEPTH used\n#endif\n#if defined(DUK_OPT_UNDERSCORE_SETJMP)\n#error unsupported legacy feature option DUK_OPT_UNDERSCORE_SETJMP used\n#endif\n#if defined(DUK_OPT_USER_INITJS)\n#error unsupported legacy feature option DUK_OPT_USER_INITJS used\n#endif\n\n/*\n *  Checks for config option consistency (DUK_USE_xxx)\n */\n\n#if defined(DUK_USE_32BIT_PTRS)\n#error unsupported config option used (option has been removed): DUK_USE_32BIT_PTRS\n#endif\n#if defined(DUK_USE_ALIGN_4)\n#error unsupported config option used (option has been removed): DUK_USE_ALIGN_4\n#endif\n#if defined(DUK_USE_ALIGN_8)\n#error unsupported config option used (option has been removed): DUK_USE_ALIGN_8\n#endif\n#if defined(DUK_USE_BROWSER_LIKE)\n#error unsupported config option used (option has been removed): DUK_USE_BROWSER_LIKE\n#endif\n#if defined(DUK_USE_BUILTIN_INITJS)\n#error unsupported config option used (option has been removed): DUK_USE_BUILTIN_INITJS\n#endif\n#if defined(DUK_USE_BYTEORDER_FORCED)\n#error unsupported config option used (option has been removed): DUK_USE_BYTEORDER_FORCED\n#endif\n#if defined(DUK_USE_DATAPTR_DEC16) && !defined(DUK_USE_DATAPTR16)\n#error config option DUK_USE_DATAPTR_DEC16 requires option DUK_USE_DATAPTR16 (which is missing)\n#endif\n#if defined(DUK_USE_DATAPTR_ENC16) && !defined(DUK_USE_DATAPTR16)\n#error config option DUK_USE_DATAPTR_ENC16 requires option DUK_USE_DATAPTR16 (which is missing)\n#endif\n#if defined(DUK_USE_DDDPRINT)\n#error unsupported config option used (option has been removed): DUK_USE_DDDPRINT\n#endif\n#if defined(DUK_USE_DDPRINT)\n#error unsupported config option used (option has been removed): DUK_USE_DDPRINT\n#endif\n#if defined(DUK_USE_DEBUGGER_FWD_LOGGING)\n#error unsupported config option used (option has been removed): DUK_USE_DEBUGGER_FWD_LOGGING\n#endif\n#if defined(DUK_USE_DEBUGGER_FWD_PRINTALERT)\n#error unsupported config option used (option has been removed): DUK_USE_DEBUGGER_FWD_PRINTALERT\n#endif\n#if defined(DUK_USE_DEBUGGER_SUPPORT) && !defined(DUK_USE_INTERRUPT_COUNTER)\n#error config option DUK_USE_DEBUGGER_SUPPORT requires option DUK_USE_INTERRUPT_COUNTER (which is missing)\n#endif\n#if defined(DUK_USE_DEEP_C_STACK)\n#error unsupported config option used (option has been removed): DUK_USE_DEEP_C_STACK\n#endif\n#if defined(DUK_USE_DOUBLE_BE)\n#error unsupported config option used (option has been removed): DUK_USE_DOUBLE_BE\n#endif\n#if defined(DUK_USE_DOUBLE_BE) && defined(DUK_USE_DOUBLE_LE)\n#error config option DUK_USE_DOUBLE_BE conflicts with option DUK_USE_DOUBLE_LE (which is also defined)\n#endif\n#if defined(DUK_USE_DOUBLE_BE) && defined(DUK_USE_DOUBLE_ME)\n#error config option DUK_USE_DOUBLE_BE conflicts with option DUK_USE_DOUBLE_ME (which is also defined)\n#endif\n#if defined(DUK_USE_DOUBLE_LE)\n#error unsupported config option used (option has been removed): DUK_USE_DOUBLE_LE\n#endif\n#if defined(DUK_USE_DOUBLE_LE) && defined(DUK_USE_DOUBLE_BE)\n#error config option DUK_USE_DOUBLE_LE conflicts with option DUK_USE_DOUBLE_BE (which is also defined)\n#endif\n#if defined(DUK_USE_DOUBLE_LE) && defined(DUK_USE_DOUBLE_ME)\n#error config option DUK_USE_DOUBLE_LE conflicts with option DUK_USE_DOUBLE_ME (which is also defined)\n#endif\n#if defined(DUK_USE_DOUBLE_ME)\n#error unsupported config option used (option has been removed): DUK_USE_DOUBLE_ME\n#endif\n#if defined(DUK_USE_DOUBLE_ME) && defined(DUK_USE_DOUBLE_LE)\n#error config option DUK_USE_DOUBLE_ME conflicts with option DUK_USE_DOUBLE_LE (which is also defined)\n#endif\n#if defined(DUK_USE_DOUBLE_ME) && defined(DUK_USE_DOUBLE_BE)\n#error config option DUK_USE_DOUBLE_ME conflicts with option DUK_USE_DOUBLE_BE (which is also defined)\n#endif\n#if defined(DUK_USE_DPRINT)\n#error unsupported config option used (option has been removed): DUK_USE_DPRINT\n#endif\n#if defined(DUK_USE_DPRINT) && !defined(DUK_USE_DEBUG)\n#error config option DUK_USE_DPRINT requires option DUK_USE_DEBUG (which is missing)\n#endif\n#if defined(DUK_USE_DPRINT_COLORS)\n#error unsupported config option used (option has been removed): DUK_USE_DPRINT_COLORS\n#endif\n#if defined(DUK_USE_DPRINT_RDTSC)\n#error unsupported config option used (option has been removed): DUK_USE_DPRINT_RDTSC\n#endif\n#if defined(DUK_USE_ES6_REGEXP_BRACES)\n#error unsupported config option used (option has been removed): DUK_USE_ES6_REGEXP_BRACES\n#endif\n#if defined(DUK_USE_ESBC_MAX_BYTES) && !defined(DUK_USE_ESBC_LIMITS)\n#error config option DUK_USE_ESBC_MAX_BYTES requires option DUK_USE_ESBC_LIMITS (which is missing)\n#endif\n#if defined(DUK_USE_ESBC_MAX_LINENUMBER) && !defined(DUK_USE_ESBC_LIMITS)\n#error config option DUK_USE_ESBC_MAX_LINENUMBER requires option DUK_USE_ESBC_LIMITS (which is missing)\n#endif\n#if defined(DUK_USE_EXEC_TIMEOUT_CHECK) && !defined(DUK_USE_INTERRUPT_COUNTER)\n#error config option DUK_USE_EXEC_TIMEOUT_CHECK requires option DUK_USE_INTERRUPT_COUNTER (which is missing)\n#endif\n#if defined(DUK_USE_EXTSTR_FREE) && !defined(DUK_USE_HSTRING_EXTDATA)\n#error config option DUK_USE_EXTSTR_FREE requires option DUK_USE_HSTRING_EXTDATA (which is missing)\n#endif\n#if defined(DUK_USE_EXTSTR_INTERN_CHECK) && !defined(DUK_USE_HSTRING_EXTDATA)\n#error config option DUK_USE_EXTSTR_INTERN_CHECK requires option DUK_USE_HSTRING_EXTDATA (which is missing)\n#endif\n#if defined(DUK_USE_FASTINT) && !defined(DUK_USE_64BIT_OPS)\n#error config option DUK_USE_FASTINT requires option DUK_USE_64BIT_OPS (which is missing)\n#endif\n#if defined(DUK_USE_FILE_IO)\n#error unsupported config option used (option has been removed): DUK_USE_FILE_IO\n#endif\n#if defined(DUK_USE_FULL_TVAL)\n#error unsupported config option used (option has been removed): DUK_USE_FULL_TVAL\n#endif\n#if defined(DUK_USE_FUNCPTR_DEC16) && !defined(DUK_USE_FUNCPTR16)\n#error config option DUK_USE_FUNCPTR_DEC16 requires option DUK_USE_FUNCPTR16 (which is missing)\n#endif\n#if defined(DUK_USE_FUNCPTR_ENC16) && !defined(DUK_USE_FUNCPTR16)\n#error config option DUK_USE_FUNCPTR_ENC16 requires option DUK_USE_FUNCPTR16 (which is missing)\n#endif\n#if defined(DUK_USE_HASHBYTES_UNALIGNED_U32_ACCESS)\n#error unsupported config option used (option has been removed): DUK_USE_HASHBYTES_UNALIGNED_U32_ACCESS\n#endif\n#if defined(DUK_USE_HEAPPTR16) && defined(DUK_USE_DEBUG)\n#error config option DUK_USE_HEAPPTR16 conflicts with option DUK_USE_DEBUG (which is also defined)\n#endif\n#if defined(DUK_USE_HEAPPTR_DEC16) && !defined(DUK_USE_HEAPPTR16)\n#error config option DUK_USE_HEAPPTR_DEC16 requires option DUK_USE_HEAPPTR16 (which is missing)\n#endif\n#if defined(DUK_USE_HEAPPTR_ENC16) && !defined(DUK_USE_HEAPPTR16)\n#error config option DUK_USE_HEAPPTR_ENC16 requires option DUK_USE_HEAPPTR16 (which is missing)\n#endif\n#if defined(DUK_USE_INTEGER_BE)\n#error unsupported config option used (option has been removed): DUK_USE_INTEGER_BE\n#endif\n#if defined(DUK_USE_INTEGER_BE) && defined(DUK_USE_INTEGER_LE)\n#error config option DUK_USE_INTEGER_BE conflicts with option DUK_USE_INTEGER_LE (which is also defined)\n#endif\n#if defined(DUK_USE_INTEGER_BE) && defined(DUK_USE_INTEGER_ME)\n#error config option DUK_USE_INTEGER_BE conflicts with option DUK_USE_INTEGER_ME (which is also defined)\n#endif\n#if defined(DUK_USE_INTEGER_LE)\n#error unsupported config option used (option has been removed): DUK_USE_INTEGER_LE\n#endif\n#if defined(DUK_USE_INTEGER_LE) && defined(DUK_USE_INTEGER_BE)\n#error config option DUK_USE_INTEGER_LE conflicts with option DUK_USE_INTEGER_BE (which is also defined)\n#endif\n#if defined(DUK_USE_INTEGER_LE) && defined(DUK_USE_INTEGER_ME)\n#error config option DUK_USE_INTEGER_LE conflicts with option DUK_USE_INTEGER_ME (which is also defined)\n#endif\n#if defined(DUK_USE_INTEGER_ME)\n#error unsupported config option used (option has been removed): DUK_USE_INTEGER_ME\n#endif\n#if defined(DUK_USE_INTEGER_ME) && defined(DUK_USE_INTEGER_LE)\n#error config option DUK_USE_INTEGER_ME conflicts with option DUK_USE_INTEGER_LE (which is also defined)\n#endif\n#if defined(DUK_USE_INTEGER_ME) && defined(DUK_USE_INTEGER_BE)\n#error config option DUK_USE_INTEGER_ME conflicts with option DUK_USE_INTEGER_BE (which is also defined)\n#endif\n#if defined(DUK_USE_MARKANDSWEEP_FINALIZER_TORTURE)\n#error unsupported config option used (option has been removed): DUK_USE_MARKANDSWEEP_FINALIZER_TORTURE\n#endif\n#if defined(DUK_USE_MARK_AND_SWEEP)\n#error unsupported config option used (option has been removed): DUK_USE_MARK_AND_SWEEP\n#endif\n#if defined(DUK_USE_MATH_FMAX)\n#error unsupported config option used (option has been removed): DUK_USE_MATH_FMAX\n#endif\n#if defined(DUK_USE_MATH_FMIN)\n#error unsupported config option used (option has been removed): DUK_USE_MATH_FMIN\n#endif\n#if defined(DUK_USE_MATH_ROUND)\n#error unsupported config option used (option has been removed): DUK_USE_MATH_ROUND\n#endif\n#if defined(DUK_USE_MS_STRINGTABLE_RESIZE)\n#error unsupported config option used (option has been removed): DUK_USE_MS_STRINGTABLE_RESIZE\n#endif\n#if defined(DUK_USE_NONSTD_REGEXP_DOLLAR_ESCAPE)\n#error unsupported config option used (option has been removed): DUK_USE_NONSTD_REGEXP_DOLLAR_ESCAPE\n#endif\n#if defined(DUK_USE_NO_DOUBLE_ALIASING_SELFTEST)\n#error unsupported config option used (option has been removed): DUK_USE_NO_DOUBLE_ALIASING_SELFTEST\n#endif\n#if defined(DUK_USE_OCTAL_SUPPORT)\n#error unsupported config option used (option has been removed): DUK_USE_OCTAL_SUPPORT\n#endif\n#if defined(DUK_USE_PACKED_TVAL_POSSIBLE)\n#error unsupported config option used (option has been removed): DUK_USE_PACKED_TVAL_POSSIBLE\n#endif\n#if defined(DUK_USE_PANIC_ABORT)\n#error unsupported config option used (option has been removed): DUK_USE_PANIC_ABORT\n#endif\n#if defined(DUK_USE_PANIC_EXIT)\n#error unsupported config option used (option has been removed): DUK_USE_PANIC_EXIT\n#endif\n#if defined(DUK_USE_PANIC_HANDLER)\n#error unsupported config option used (option has been removed): DUK_USE_PANIC_HANDLER\n#endif\n#if defined(DUK_USE_PANIC_SEGFAULT)\n#error unsupported config option used (option has been removed): DUK_USE_PANIC_SEGFAULT\n#endif\n#if defined(DUK_USE_POW_NETBSD_WORKAROUND)\n#error unsupported config option used (option has been removed): DUK_USE_POW_NETBSD_WORKAROUND\n#endif\n#if defined(DUK_USE_RDTSC)\n#error unsupported config option used (option has been removed): DUK_USE_RDTSC\n#endif\n#if defined(DUK_USE_REFZERO_FINALIZER_TORTURE)\n#error unsupported config option used (option has been removed): DUK_USE_REFZERO_FINALIZER_TORTURE\n#endif\n#if defined(DUK_USE_ROM_GLOBAL_CLONE) && !defined(DUK_USE_ROM_STRINGS)\n#error config option DUK_USE_ROM_GLOBAL_CLONE requires option DUK_USE_ROM_STRINGS (which is missing)\n#endif\n#if defined(DUK_USE_ROM_GLOBAL_CLONE) && !defined(DUK_USE_ROM_OBJECTS)\n#error config option DUK_USE_ROM_GLOBAL_CLONE requires option DUK_USE_ROM_OBJECTS (which is missing)\n#endif\n#if defined(DUK_USE_ROM_GLOBAL_CLONE) && defined(DUK_USE_ROM_GLOBAL_INHERIT)\n#error config option DUK_USE_ROM_GLOBAL_CLONE conflicts with option DUK_USE_ROM_GLOBAL_INHERIT (which is also defined)\n#endif\n#if defined(DUK_USE_ROM_GLOBAL_INHERIT) && !defined(DUK_USE_ROM_STRINGS)\n#error config option DUK_USE_ROM_GLOBAL_INHERIT requires option DUK_USE_ROM_STRINGS (which is missing)\n#endif\n#if defined(DUK_USE_ROM_GLOBAL_INHERIT) && !defined(DUK_USE_ROM_OBJECTS)\n#error config option DUK_USE_ROM_GLOBAL_INHERIT requires option DUK_USE_ROM_OBJECTS (which is missing)\n#endif\n#if defined(DUK_USE_ROM_GLOBAL_INHERIT) && defined(DUK_USE_ROM_GLOBAL_CLONE)\n#error config option DUK_USE_ROM_GLOBAL_INHERIT conflicts with option DUK_USE_ROM_GLOBAL_CLONE (which is also defined)\n#endif\n#if defined(DUK_USE_ROM_OBJECTS) && !defined(DUK_USE_ROM_STRINGS)\n#error config option DUK_USE_ROM_OBJECTS requires option DUK_USE_ROM_STRINGS (which is missing)\n#endif\n#if defined(DUK_USE_ROM_STRINGS) && !defined(DUK_USE_ROM_OBJECTS)\n#error config option DUK_USE_ROM_STRINGS requires option DUK_USE_ROM_OBJECTS (which is missing)\n#endif\n#if defined(DUK_USE_SETJMP)\n#error unsupported config option used (option has been removed): DUK_USE_SETJMP\n#endif\n#if defined(DUK_USE_SIGSETJMP)\n#error unsupported config option used (option has been removed): DUK_USE_SIGSETJMP\n#endif\n#if defined(DUK_USE_STRTAB_CHAIN)\n#error unsupported config option used (option has been removed): DUK_USE_STRTAB_CHAIN\n#endif\n#if defined(DUK_USE_STRTAB_CHAIN_SIZE)\n#error unsupported config option used (option has been removed): DUK_USE_STRTAB_CHAIN_SIZE\n#endif\n#if defined(DUK_USE_STRTAB_CHAIN_SIZE) && !defined(DUK_USE_STRTAB_CHAIN)\n#error config option DUK_USE_STRTAB_CHAIN_SIZE requires option DUK_USE_STRTAB_CHAIN (which is missing)\n#endif\n#if defined(DUK_USE_STRTAB_PROBE)\n#error unsupported config option used (option has been removed): DUK_USE_STRTAB_PROBE\n#endif\n#if defined(DUK_USE_STRTAB_PTRCOMP) && !defined(DUK_USE_HEAPPTR16)\n#error config option DUK_USE_STRTAB_PTRCOMP requires option DUK_USE_HEAPPTR16 (which is missing)\n#endif\n#if defined(DUK_USE_TAILCALL) && defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)\n#error config option DUK_USE_TAILCALL conflicts with option DUK_USE_NONSTD_FUNC_CALLER_PROPERTY (which is also defined)\n#endif\n#if defined(DUK_USE_UNALIGNED_ACCESSES_POSSIBLE)\n#error unsupported config option used (option has been removed): DUK_USE_UNALIGNED_ACCESSES_POSSIBLE\n#endif\n#if defined(DUK_USE_UNDERSCORE_SETJMP)\n#error unsupported config option used (option has been removed): DUK_USE_UNDERSCORE_SETJMP\n#endif\n#if defined(DUK_USE_USER_INITJS)\n#error unsupported config option used (option has been removed): DUK_USE_USER_INITJS\n#endif\n\n#if defined(DUK_USE_CPP_EXCEPTIONS) && !defined(__cplusplus)\n#error DUK_USE_CPP_EXCEPTIONS enabled but not compiling with a C++ compiler\n#endif\n\n/*\n *  Convert DUK_USE_BYTEORDER, from whatever source, into currently used\n *  internal defines.  If detection failed, #error out.\n */\n\n#if defined(DUK_USE_BYTEORDER)\n#if (DUK_USE_BYTEORDER == 1)\n#define DUK_USE_INTEGER_LE\n#define DUK_USE_DOUBLE_LE\n#elif (DUK_USE_BYTEORDER == 2)\n#define DUK_USE_INTEGER_LE  /* integer endianness is little on purpose */\n#define DUK_USE_DOUBLE_ME\n#elif (DUK_USE_BYTEORDER == 3)\n#define DUK_USE_INTEGER_BE\n#define DUK_USE_DOUBLE_BE\n#else\n#error unsupported: byte order invalid\n#endif  /* byte order */\n#else\n#error unsupported: byte order detection failed\n#endif  /* defined(DUK_USE_BYTEORDER) */\n\n#endif  /* DUK_CONFIG_H_INCLUDED */\n"
  },
  {
    "path": "src/engine/script/duktape-2.2.0/duk_module_duktape.c",
    "content": "/*\n *  Duktape 1.x compatible module loading framework\n */\n\n#include \"duktape.h\"\n#include \"duk_module_duktape.h\"\n\n/* (v)snprintf() is missing before MSVC 2015.  Note that _(v)snprintf() does\n * NOT NUL terminate on truncation, but that's OK here.\n * http://stackoverflow.com/questions/2915672/snprintf-and-visual-studio-2010\n */\n#if defined(_MSC_VER) && (_MSC_VER < 1900)\n#define snprintf _snprintf\n#endif\n\n#if 0  /* Enable manually */\n#define DUK__ASSERT(x) do { \\\n\t\tif (!(x)) { \\\n\t\t\tfprintf(stderr, \"ASSERTION FAILED at %s:%d: \" #x \"\\n\", __FILE__, __LINE__); \\\n\t\t\tfflush(stderr);  \\\n\t\t} \\\n\t} while (0)\n#define DUK__ASSERT_TOP(ctx,val) do { \\\n\t\tDUK__ASSERT(duk_get_top((ctx)) == (val)); \\\n\t} while (0)\n#else\n#define DUK__ASSERT(x) do { (void) (x); } while (0)\n#define DUK__ASSERT_TOP(ctx,val) do { (void) ctx; (void) (val); } while (0)\n#endif\n\nstatic void duk__resolve_module_id(duk_context *ctx, const char *req_id, const char *mod_id) {\n\tduk_uint8_t buf[DUK_COMMONJS_MODULE_ID_LIMIT];\n\tduk_uint8_t *p;\n\tduk_uint8_t *q;\n\tduk_uint8_t *q_last;  /* last component */\n\tduk_int_t int_rc;\n\n\tDUK__ASSERT(req_id != NULL);\n\t/* mod_id may be NULL */\n\n\t/*\n\t *  A few notes on the algorithm:\n\t *\n\t *    - Terms are not allowed to begin with a period unless the term\n\t *      is either '.' or '..'.  This simplifies implementation (and\n\t *      is within CommonJS modules specification).\n\t *\n\t *    - There are few output bound checks here.  This is on purpose:\n\t *      the resolution input is length checked and the output is never\n\t *      longer than the input.  The resolved output is written directly\n\t *      over the input because it's never longer than the input at any\n\t *      point in the algorithm.\n\t *\n\t *    - Non-ASCII characters are processed as individual bytes and\n\t *      need no special treatment.  However, U+0000 terminates the\n\t *      algorithm; this is not an issue because U+0000 is not a\n\t *      desirable term character anyway.\n\t */\n\n\t/*\n\t *  Set up the resolution input which is the requested ID directly\n\t *  (if absolute or no current module path) or with current module\n\t *  ID prepended (if relative and current module path exists).\n\t *\n\t *  Suppose current module is 'foo/bar' and relative path is './quux'.\n\t *  The 'bar' component must be replaced so the initial input here is\n\t *  'foo/bar/.././quux'.\n\t */\n\n\tif (mod_id != NULL && req_id[0] == '.') {\n\t\tint_rc = snprintf((char *) buf, sizeof(buf), \"%s/../%s\", mod_id, req_id);\n\t} else {\n\t\tint_rc = snprintf((char *) buf, sizeof(buf), \"%s\", req_id);\n\t}\n\tif (int_rc >= (duk_int_t) sizeof(buf) || int_rc < 0) {\n\t\t/* Potentially truncated, NUL not guaranteed in any case.\n\t\t * The (int_rc < 0) case should not occur in practice.\n\t\t */\n\t\tgoto resolve_error;\n\t}\n\tDUK__ASSERT(strlen((const char *) buf) < sizeof(buf));  /* at most sizeof(buf) - 1 */\n\n\t/*\n\t *  Resolution loop.  At the top of the loop we're expecting a valid\n\t *  term: '.', '..', or a non-empty identifier not starting with a period.\n\t */\n\n\tp = buf;\n\tq = buf;\n\tfor (;;) {\n\t\tduk_uint_fast8_t c;\n\n\t\t/* Here 'p' always points to the start of a term.\n\t\t *\n\t\t * We can also unconditionally reset q_last here: if this is\n\t\t * the last (non-empty) term q_last will have the right value\n\t\t * on loop exit.\n\t\t */\n\n\t\tDUK__ASSERT(p >= q);  /* output is never longer than input during resolution */\n\n\t\tq_last = q;\n\n\t\tc = *p++;\n\t\tif (c == 0) {\n\t\t\tgoto resolve_error;\n\t\t} else if (c == '.') {\n\t\t\tc = *p++;\n\t\t\tif (c == '/') {\n\t\t\t\t/* Term was '.' and is eaten entirely (including dup slashes). */\n\t\t\t\tgoto eat_dup_slashes;\n\t\t\t}\n\t\t\tif (c == '.' && *p == '/') {\n\t\t\t\t/* Term was '..', backtrack resolved name by one component.\n\t\t\t\t *  q[-1] = previous slash (or beyond start of buffer)\n\t\t\t\t *  q[-2] = last char of previous component (or beyond start of buffer)\n\t\t\t\t */\n\t\t\t\tp++;  /* eat (first) input slash */\n\t\t\t\tDUK__ASSERT(q >= buf);\n\t\t\t\tif (q == buf) {\n\t\t\t\t\tgoto resolve_error;\n\t\t\t\t}\n\t\t\t\tDUK__ASSERT(*(q - 1) == '/');\n\t\t\t\tq--;  /* Backtrack to last output slash (dups already eliminated). */\n\t\t\t\tfor (;;) {\n\t\t\t\t\t/* Backtrack to previous slash or start of buffer. */\n\t\t\t\t\tDUK__ASSERT(q >= buf);\n\t\t\t\t\tif (q == buf) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tif (*(q - 1) == '/') {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tq--;\n\t\t\t\t}\n\t\t\t\tgoto eat_dup_slashes;\n\t\t\t}\n\t\t\tgoto resolve_error;\n\t\t} else if (c == '/') {\n\t\t\t/* e.g. require('/foo'), empty terms not allowed */\n\t\t\tgoto resolve_error;\n\t\t} else {\n\t\t\tfor (;;) {\n\t\t\t\t/* Copy term name until end or '/'. */\n\t\t\t\t*q++ = c;\n\t\t\t\tc = *p++;\n\t\t\t\tif (c == 0) {\n\t\t\t\t\t/* This was the last term, and q_last was\n\t\t\t\t\t * updated to match this term at loop top.\n\t\t\t\t\t */\n\t\t\t\t\tgoto loop_done;\n\t\t\t\t} else if (c == '/') {\n\t\t\t\t\t*q++ = '/';\n\t\t\t\t\tbreak;\n\t\t\t\t} else {\n\t\t\t\t\t/* write on next loop */\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t eat_dup_slashes:\n\t\tfor (;;) {\n\t\t\t/* eat dup slashes */\n\t\t\tc = *p;\n\t\t\tif (c != '/') {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tp++;\n\t\t}\n\t}\n loop_done:\n\t/* Output #1: resolved absolute name. */\n\tDUK__ASSERT(q >= buf);\n\tduk_push_lstring(ctx, (const char *) buf, (size_t) (q - buf));\n\n\t/* Output #2: last component name. */\n\tDUK__ASSERT(q >= q_last);\n\tDUK__ASSERT(q_last >= buf);\n\tduk_push_lstring(ctx, (const char *) q_last, (size_t) (q - q_last));\n\treturn;\n\n resolve_error:\n\t(void) duk_type_error(ctx, \"cannot resolve module id: %s\", (const char *) req_id);\n}\n\n/* Stack indices for better readability. */\n#define DUK__IDX_REQUESTED_ID   0   /* module id requested */\n#define DUK__IDX_REQUIRE        1   /* current require() function */\n#define DUK__IDX_REQUIRE_ID     2   /* the base ID of the current require() function, resolution base */\n#define DUK__IDX_RESOLVED_ID    3   /* resolved, normalized absolute module ID */\n#define DUK__IDX_LASTCOMP       4   /* last component name in resolved path */\n#define DUK__IDX_DUKTAPE        5   /* Duktape object */\n#define DUK__IDX_MODLOADED      6   /* Duktape.modLoaded[] module cache */\n#define DUK__IDX_UNDEFINED      7   /* 'undefined', artifact of lookup */\n#define DUK__IDX_FRESH_REQUIRE  8   /* new require() function for module, updated resolution base */\n#define DUK__IDX_EXPORTS        9   /* default exports table */\n#define DUK__IDX_MODULE         10  /* module object containing module.exports, etc */\n\nstatic duk_ret_t duk__require(duk_context *ctx) {\n\tconst char *str_req_id;  /* requested identifier */\n\tconst char *str_mod_id;  /* require.id of current module */\n\tduk_int_t pcall_rc;\n\n\t/* NOTE: we try to minimize code size by avoiding unnecessary pops,\n\t * so the stack looks a bit cluttered in this function.  DUK__ASSERT_TOP()\n\t * assertions are used to ensure stack configuration is correct at each\n\t * step.\n\t */\n\n\t/*\n\t *  Resolve module identifier into canonical absolute form.\n\t */\n\n\tstr_req_id = duk_require_string(ctx, DUK__IDX_REQUESTED_ID);\n\tduk_push_current_function(ctx);\n\tduk_get_prop_string(ctx, -1, \"id\");\n\tstr_mod_id = duk_get_string(ctx, DUK__IDX_REQUIRE_ID);  /* ignore non-strings */\n\tduk__resolve_module_id(ctx, str_req_id, str_mod_id);\n\tstr_req_id = NULL;\n\tstr_mod_id = NULL;\n\n\t/* [ requested_id require require.id resolved_id last_comp ] */\n\tDUK__ASSERT_TOP(ctx, DUK__IDX_LASTCOMP + 1);\n\n\t/*\n\t *  Cached module check.\n\t *\n\t *  If module has been loaded or its loading has already begun without\n\t *  finishing, return the same cached value (module.exports).  The\n\t *  value is registered when module load starts so that circular\n\t *  references can be supported to some extent.\n\t */\n\n\tduk_push_global_stash(ctx);\n\tduk_get_prop_string(ctx, -1, \"\\xff\" \"module:Duktape\");\n\tduk_remove(ctx, -2);  /* Lookup stashed, original 'Duktape' object. */\n\tduk_get_prop_string(ctx, DUK__IDX_DUKTAPE, \"modLoaded\");  /* Duktape.modLoaded */\n\tduk_require_type_mask(ctx, DUK__IDX_MODLOADED, DUK_TYPE_MASK_OBJECT);\n\tDUK__ASSERT_TOP(ctx, DUK__IDX_MODLOADED + 1);\n\n\tduk_dup(ctx, DUK__IDX_RESOLVED_ID);\n\tif (duk_get_prop(ctx, DUK__IDX_MODLOADED)) {\n\t\t/* [ requested_id require require.id resolved_id last_comp Duktape Duktape.modLoaded Duktape.modLoaded[id] ] */\n\t\tduk_get_prop_string(ctx, -1, \"exports\");  /* return module.exports */\n\t\treturn 1;\n\t}\n\tDUK__ASSERT_TOP(ctx, DUK__IDX_UNDEFINED + 1);\n\n\t/* [ requested_id require require.id resolved_id last_comp Duktape Duktape.modLoaded undefined ] */\n\n\t/*\n\t *  Module not loaded (and loading not started previously).\n\t *\n\t *  Create a new require() function with 'id' set to resolved ID\n\t *  of module being loaded.  Also create 'exports' and 'module'\n\t *  tables but don't register exports to the loaded table yet.\n\t *  We don't want to do that unless the user module search callbacks\n\t *  succeeds in finding the module.\n\t */\n\n\t/* Fresh require: require.id is left configurable (but not writable)\n\t * so that is not easy to accidentally tweak it, but it can still be\n\t * done with Object.defineProperty().\n\t *\n\t * XXX: require.id could also be just made non-configurable, as there\n\t * is no practical reason to touch it (at least from Ecmascript code).\n\t */\n\tduk_push_c_function(ctx, duk__require, 1 /*nargs*/);\n\tduk_push_string(ctx, \"name\");\n\tduk_push_string(ctx, \"require\");\n\tduk_def_prop(ctx, DUK__IDX_FRESH_REQUIRE, DUK_DEFPROP_HAVE_VALUE);  /* not writable, not enumerable, not configurable */\n\tduk_push_string(ctx, \"id\");\n\tduk_dup(ctx, DUK__IDX_RESOLVED_ID);\n\tduk_def_prop(ctx, DUK__IDX_FRESH_REQUIRE, DUK_DEFPROP_HAVE_VALUE | DUK_DEFPROP_SET_CONFIGURABLE);  /* a fresh require() with require.id = resolved target module id */\n\n\t/* Module table:\n\t * - module.exports: initial exports table (may be replaced by user)\n\t * - module.id is non-writable and non-configurable, as the CommonJS\n\t *   spec suggests this if possible\n\t * - module.filename: not set, defaults to resolved ID if not explicitly\n\t *   set by modSearch() (note capitalization, not .fileName, matches Node.js)\n\t * - module.name: not set, defaults to last component of resolved ID if\n\t *   not explicitly set by modSearch()\n\t */\n\tduk_push_object(ctx);  /* exports */\n\tduk_push_object(ctx);  /* module */\n\tduk_push_string(ctx, \"exports\");\n\tduk_dup(ctx, DUK__IDX_EXPORTS);\n\tduk_def_prop(ctx, DUK__IDX_MODULE, DUK_DEFPROP_HAVE_VALUE | DUK_DEFPROP_SET_WRITABLE | DUK_DEFPROP_SET_CONFIGURABLE);  /* module.exports = exports */\n\tduk_push_string(ctx, \"id\");\n\tduk_dup(ctx, DUK__IDX_RESOLVED_ID);  /* resolved id: require(id) must return this same module */\n\tduk_def_prop(ctx, DUK__IDX_MODULE, DUK_DEFPROP_HAVE_VALUE);  /* module.id = resolved_id; not writable, not enumerable, not configurable */\n\tduk_compact(ctx, DUK__IDX_MODULE);  /* module table remains registered to modLoaded, minimize its size */\n\tDUK__ASSERT_TOP(ctx, DUK__IDX_MODULE + 1);\n\n\t/* [ requested_id require require.id resolved_id last_comp Duktape Duktape.modLoaded undefined fresh_require exports module ] */\n\n\t/* Register the module table early to modLoaded[] so that we can\n\t * support circular references even in modSearch().  If an error\n\t * is thrown, we'll delete the reference.\n\t */\n\tduk_dup(ctx, DUK__IDX_RESOLVED_ID);\n\tduk_dup(ctx, DUK__IDX_MODULE);\n\tduk_put_prop(ctx, DUK__IDX_MODLOADED);  /* Duktape.modLoaded[resolved_id] = module */\n\n\t/*\n\t *  Call user provided module search function and build the wrapped\n\t *  module source code (if necessary).  The module search function\n\t *  can be used to implement pure Ecmacsript, pure C, and mixed\n\t *  Ecmascript/C modules.\n\t *\n\t *  The module search function can operate on the exports table directly\n\t *  (e.g. DLL code can register values to it).  It can also return a\n\t *  string which is interpreted as module source code (if a non-string\n\t *  is returned the module is assumed to be a pure C one).  If a module\n\t *  cannot be found, an error must be thrown by the user callback.\n\t *\n\t *  Because Duktape.modLoaded[] already contains the module being\n\t *  loaded, circular references for C modules should also work\n\t *  (although expected to be quite rare).\n\t */\n\n\tduk_push_string(ctx, \"(function(require,exports,module){\");\n\n\t/* Duktape.modSearch(resolved_id, fresh_require, exports, module). */\n\tduk_get_prop_string(ctx, DUK__IDX_DUKTAPE, \"modSearch\");  /* Duktape.modSearch */\n\tduk_dup(ctx, DUK__IDX_RESOLVED_ID);\n\tduk_dup(ctx, DUK__IDX_FRESH_REQUIRE);\n\tduk_dup(ctx, DUK__IDX_EXPORTS);\n\tduk_dup(ctx, DUK__IDX_MODULE);  /* [ ... Duktape.modSearch resolved_id last_comp fresh_require exports module ] */\n\tpcall_rc = duk_pcall(ctx, 4 /*nargs*/);  /* -> [ ... source ] */\n\tDUK__ASSERT_TOP(ctx, DUK__IDX_MODULE + 3);\n\n\tif (pcall_rc != DUK_EXEC_SUCCESS) {\n\t\t/* Delete entry in Duktape.modLoaded[] and rethrow. */\n\t\tgoto delete_rethrow;\n\t}\n\n\t/* If user callback did not return source code, module loading\n\t * is finished (user callback initialized exports table directly).\n\t */\n\tif (!duk_is_string(ctx, -1)) {\n\t\t/* User callback did not return source code, so module loading\n\t\t * is finished: just update modLoaded with final module.exports\n\t\t * and we're done.\n\t\t */\n\t\tgoto return_exports;\n\t}\n\n\t/* Finish the wrapped module source.  Force module.filename as the\n\t * function .fileName so it gets set for functions defined within a\n\t * module.  This also ensures loggers created within the module get\n\t * the module ID (or overridden filename) as their default logger name.\n\t * (Note capitalization: .filename matches Node.js while .fileName is\n\t * used elsewhere in Duktape.)\n\t */\n\tduk_push_string(ctx, \"\\n})\");  /* Newline allows module last line to contain a // comment. */\n\tduk_concat(ctx, 3);\n\tif (!duk_get_prop_string(ctx, DUK__IDX_MODULE, \"filename\")) {\n\t\t/* module.filename for .fileName, default to resolved ID if\n\t\t * not present.\n\t\t */\n\t\tduk_pop(ctx);\n\t\tduk_dup(ctx, DUK__IDX_RESOLVED_ID);\n\t}\n\tpcall_rc = duk_pcompile(ctx, DUK_COMPILE_EVAL);\n\tif (pcall_rc != DUK_EXEC_SUCCESS) {\n\t\tgoto delete_rethrow;\n\t}\n\tpcall_rc = duk_pcall(ctx, 0);  /* -> eval'd function wrapper (not called yet) */\n\tif (pcall_rc != DUK_EXEC_SUCCESS) {\n\t\tgoto delete_rethrow;\n\t}\n\n\t/* Module has now evaluated to a wrapped module function.  Force its\n\t * .name to match module.name (defaults to last component of resolved\n\t * ID) so that it is shown in stack traces too.  Note that we must not\n\t * introduce an actual name binding into the function scope (which is\n\t * usually the case with a named function) because it would affect the\n\t * scope seen by the module and shadow accesses to globals of the same name.\n\t * This is now done by compiling the function as anonymous and then forcing\n\t * its .name without setting a \"has name binding\" flag.\n\t */\n\n\tduk_push_string(ctx, \"name\");\n\tif (!duk_get_prop_string(ctx, DUK__IDX_MODULE, \"name\")) {\n\t\t/* module.name for .name, default to last component if\n\t\t * not present.\n\t\t */\n\t\tduk_pop(ctx);\n\t\tduk_dup(ctx, DUK__IDX_LASTCOMP);\n\t}\n\tduk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_VALUE | DUK_DEFPROP_FORCE);\n\n\t/*\n\t *  Call the wrapped module function.\n\t *\n\t *  Use a protected call so that we can update Duktape.modLoaded[resolved_id]\n\t *  even if the module throws an error.\n\t */\n\n\t/* [ requested_id require require.id resolved_id last_comp Duktape Duktape.modLoaded undefined fresh_require exports module mod_func ] */\n\tDUK__ASSERT_TOP(ctx, DUK__IDX_MODULE + 2);\n\n\tduk_dup(ctx, DUK__IDX_EXPORTS);  /* exports (this binding) */\n\tduk_dup(ctx, DUK__IDX_FRESH_REQUIRE);  /* fresh require (argument) */\n\tduk_get_prop_string(ctx, DUK__IDX_MODULE, \"exports\");  /* relookup exports from module.exports in case it was changed by modSearch */\n\tduk_dup(ctx, DUK__IDX_MODULE);  /* module (argument) */\n\tDUK__ASSERT_TOP(ctx, DUK__IDX_MODULE + 6);\n\n\t/* [ requested_id require require.id resolved_id last_comp Duktape Duktape.modLoaded undefined fresh_require exports module mod_func exports fresh_require exports module ] */\n\n\tpcall_rc = duk_pcall_method(ctx, 3 /*nargs*/);\n\tif (pcall_rc != DUK_EXEC_SUCCESS) {\n\t\t/* Module loading failed.  Node.js will forget the module\n\t\t * registration so that another require() will try to load\n\t\t * the module again.  Mimic that behavior.\n\t\t */\n\t\tgoto delete_rethrow;\n\t}\n\n\t/* [ requested_id require require.id resolved_id last_comp Duktape Duktape.modLoaded undefined fresh_require exports module result(ignored) ] */\n\tDUK__ASSERT_TOP(ctx, DUK__IDX_MODULE + 2);\n\n\t/* fall through */\n\n return_exports:\n\tduk_get_prop_string(ctx, DUK__IDX_MODULE, \"exports\");\n\tduk_compact(ctx, -1);  /* compact the exports table */\n\treturn 1;  /* return module.exports */\n\n delete_rethrow:\n\tduk_dup(ctx, DUK__IDX_RESOLVED_ID);\n\tduk_del_prop(ctx, DUK__IDX_MODLOADED);  /* delete Duktape.modLoaded[resolved_id] */\n\t(void) duk_throw(ctx);  /* rethrow original error */\n\treturn 0;  /* not reachable */\n}\n\nvoid duk_module_duktape_init(duk_context *ctx) {\n\t/* Stash 'Duktape' in case it's modified. */\n\tduk_push_global_stash(ctx);\n\tduk_get_global_string(ctx, \"Duktape\");\n\tduk_put_prop_string(ctx, -2, \"\\xff\" \"module:Duktape\");\n\tduk_pop(ctx);\n\n\t/* Register `require` as a global function. */\n\tduk_eval_string(ctx,\n\t\t\"(function(req){\"\n\t\t\"var D=Object.defineProperty;\"\n\t\t\"D(req,'name',{value:'require'});\"\n\t\t\"D(this,'require',{value:req,writable:true,configurable:true});\"\n\t\t\"D(Duktape,'modLoaded',{value:Object.create(null),writable:true,configurable:true});\"\n\t\t\"})\");\n\tduk_push_c_function(ctx, duk__require, 1 /*nargs*/);\n\tduk_call(ctx, 1);\n\tduk_pop(ctx);\n}\n\n#undef DUK__ASSERT\n#undef DUK__ASSERT_TOP\n#undef DUK__IDX_REQUESTED_ID\n#undef DUK__IDX_REQUIRE\n#undef DUK__IDX_REQUIRE_ID\n#undef DUK__IDX_RESOLVED_ID\n#undef DUK__IDX_LASTCOMP\n#undef DUK__IDX_DUKTAPE\n#undef DUK__IDX_MODLOADED\n#undef DUK__IDX_UNDEFINED\n#undef DUK__IDX_FRESH_REQUIRE\n#undef DUK__IDX_EXPORTS\n#undef DUK__IDX_MODULE\n"
  },
  {
    "path": "src/engine/script/duktape-2.2.0/duk_module_duktape.h",
    "content": "#if !defined(DUK_MODULE_DUKTAPE_H_INCLUDED)\n#define DUK_MODULE_DUKTAPE_H_INCLUDED\n\n#include \"duktape.h\"\n\n/* Maximum length of CommonJS module identifier to resolve.  Length includes\n * both current module ID, requested (possibly relative) module ID, and a\n * slash in between.\n */\n#define  DUK_COMMONJS_MODULE_ID_LIMIT  256\n\nextern void duk_module_duktape_init(duk_context *ctx);\n\n#endif  /* DUK_MODULE_DUKTAPE_H_INCLUDED */\n"
  },
  {
    "path": "src/engine/script/duktape-2.2.0/duktape.c",
    "content": "/*\n *  Single source autogenerated distributable for Duktape 2.2.0.\n *\n *  Git commit a459cf3c9bd1779fc01b435d69302b742675a08f (v2.2.0).\n *  Git branch master.\n *\n *  See Duktape AUTHORS.rst and LICENSE.txt for copyright and\n *  licensing information.\n */\n\n/* LICENSE.txt */\n/*\n*  ===============\n*  Duktape license\n*  ===============\n*\n*  (http://opensource.org/licenses/MIT)\n*\n*  Copyright (c) 2013-2017 by Duktape authors (see AUTHORS.rst)\n*\n*  Permission is hereby granted, free of charge, to any person obtaining a copy\n*  of this software and associated documentation files (the \"Software\"), to deal\n*  in the Software without restriction, including without limitation the rights\n*  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n*  copies of the Software, and to permit persons to whom the Software is\n*  furnished to do so, subject to the following conditions:\n*\n*  The above copyright notice and this permission notice shall be included in\n*  all copies or substantial portions of the Software.\n*\n*  THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n*  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n*  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n*  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n*  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n*  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n*  THE SOFTWARE.\n*/\n\n/* AUTHORS.rst */\n/*\n*  ===============\n*  Duktape authors\n*  ===============\n*\n*  Copyright\n*  =========\n*\n*  Duktape copyrights are held by its authors.  Each author has a copyright\n*  to their contribution, and agrees to irrevocably license the contribution\n*  under the Duktape ``LICENSE.txt``.\n*\n*  Authors\n*  =======\n*\n*  Please include an e-mail address, a link to your GitHub profile, or something\n*  similar to allow your contribution to be identified accurately.\n*\n*  The following people have contributed code, website contents, or Wiki contents,\n*  and agreed to irrevocably license their contributions under the Duktape\n*  ``LICENSE.txt`` (in order of appearance):\n*\n*  * Sami Vaarala <sami.vaarala@iki.fi>\n*  * Niki Dobrev\n*  * Andreas \\u00d6man <andreas@lonelycoder.com>\n*  * L\\u00e1szl\\u00f3 Lang\\u00f3 <llango.u-szeged@partner.samsung.com>\n*  * Legimet <legimet.calc@gmail.com>\n*  * Karl Skomski <karl@skomski.com>\n*  * Bruce Pascoe <fatcerberus1@gmail.com>\n*  * Ren\\u00e9 Hollander <rene@rene8888.at>\n*  * Julien Hamaide (https://github.com/crazyjul)\n*  * Sebastian G\\u00f6tte (https://github.com/jaseg)\n*  * Tomasz Magulski (https://github.com/magul)\n*  * \\D. Bohdan (https://github.com/dbohdan)\n*  * Ond\\u0159ej Jirman (https://github.com/megous)\n*  * Sa\\u00fal Ibarra Corretg\\u00e9 <saghul@gmail.com>\n*  * Jeremy HU <huxingyi@msn.com>\n*  * Ole Andr\\u00e9 Vadla Ravn\\u00e5s (https://github.com/oleavr)\n*  * Harold Brenes (https://github.com/harold-b)\n*  * Oliver Crow (https://github.com/ocrow)\n*  * Jakub Ch\\u0142api\\u0144ski (https://github.com/jchlapinski)\n*  * Brett Vickers (https://github.com/beevik)\n*  * Dominik Okwieka (https://github.com/okitec)\n*  * Remko Tron\\u00e7on (https://el-tramo.be)\n*  * Romero Malaquias (rbsm@ic.ufal.br)\n*  * Michael Drake <michael.drake@codethink.co.uk>\n*  * Steven Don (https://github.com/shdon)\n*  * Simon Stone (https://github.com/sstone1)\n*  * \\J. McC. (https://github.com/jmhmccr)\n*\n*  Other contributions\n*  ===================\n*\n*  The following people have contributed something other than code (e.g. reported\n*  bugs, provided ideas, etc; roughly in order of appearance):\n*\n*  * Greg Burns\n*  * Anthony Rabine\n*  * Carlos Costa\n*  * Aur\\u00e9lien Bouilland\n*  * Preet Desai (Pris Matic)\n*  * judofyr (http://www.reddit.com/user/judofyr)\n*  * Jason Woofenden\n*  * Micha\\u0142 Przyby\\u015b\n*  * Anthony Howe\n*  * Conrad Pankoff\n*  * Jim Schimpf\n*  * Rajaran Gaunker (https://github.com/zimbabao)\n*  * Andreas \\u00d6man\n*  * Doug Sanden\n*  * Josh Engebretson (https://github.com/JoshEngebretson)\n*  * Remo Eichenberger (https://github.com/remoe)\n*  * Mamod Mehyar (https://github.com/mamod)\n*  * David Demelier (https://github.com/markand)\n*  * Tim Caswell (https://github.com/creationix)\n*  * Mitchell Blank Jr (https://github.com/mitchblank)\n*  * https://github.com/yushli\n*  * Seo Sanghyeon (https://github.com/sanxiyn)\n*  * Han ChoongWoo (https://github.com/tunz)\n*  * Joshua Peek (https://github.com/josh)\n*  * Bruce E. Pascoe (https://github.com/fatcerberus)\n*  * https://github.com/Kelledin\n*  * https://github.com/sstruchtrup\n*  * Michael Drake (https://github.com/tlsa)\n*  * https://github.com/chris-y\n*  * Laurent Zubiaur (https://github.com/lzubiaur)\n*  * Neil Kolban (https://github.com/nkolban)\n*\n*  If you are accidentally missing from this list, send me an e-mail\n*  (``sami.vaarala@iki.fi``) and I'll fix the omission.\n*/\n\n#line 1 \"duk_replacements.c\"\n/*\n *  Replacements for missing platform functions.\n *\n *  Unlike the originals, fpclassify() and signbit() replacements don't\n *  work on any floating point types, only doubles.  The C typing here\n *  mimics the standard prototypes.\n */\n\n/* #include duk_internal.h */\n#line 1 \"duk_internal.h\"\n/*\n *  Top-level include file to be used for all (internal) source files.\n *\n *  Source files should not include individual header files, as they\n *  have not been designed to be individually included.\n */\n\n#if !defined(DUK_INTERNAL_H_INCLUDED)\n#define DUK_INTERNAL_H_INCLUDED\n\n/*\n *  The 'duktape.h' header provides the public API, but also handles all\n *  compiler and platform specific feature detection, Duktape feature\n *  resolution, inclusion of system headers, etc.  These have been merged\n *  because the public API is also dependent on e.g. detecting appropriate\n *  C types which is quite platform/compiler specific especially for a non-C99\n *  build.  The public API is also dependent on the resolved feature set.\n *\n *  Some actions taken by the merged header (such as including system headers)\n *  are not appropriate for building a user application.  The define\n *  DUK_COMPILING_DUKTAPE allows the merged header to skip/include some\n *  sections depending on what is being built.\n */\n\n#define DUK_COMPILING_DUKTAPE\n#include \"duktape.h\"\n\n/*\n *  User declarations, e.g. prototypes for user functions used by Duktape\n *  macros.\n */\n\nDUK_USE_USER_DECLARE()\n\n/*\n *  Duktape includes (other than duk_features.h)\n *\n *  The header files expect to be included in an order which satisfies header\n *  dependencies correctly (the headers themselves don't include any other\n *  includes).  Forward declarations are used to break circular struct/typedef\n *  dependencies.\n */\n\n/* #include duk_dblunion.h */\n#line 1 \"duk_dblunion.h\"\n/*\n *  Union to access IEEE double memory representation, indexes for double\n *  memory representation, and some macros for double manipulation.\n *\n *  Also used by packed duk_tval.  Use a union for bit manipulation to\n *  minimize aliasing issues in practice.  The C99 standard does not\n *  guarantee that this should work, but it's a very widely supported\n *  practice for low level manipulation.\n *\n *  IEEE double format summary:\n *\n *    seeeeeee eeeeffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff\n *       A        B        C        D        E        F        G        H\n *\n *    s       sign bit\n *    eee...  exponent field\n *    fff...  fraction\n *\n *  See http://en.wikipedia.org/wiki/Double_precision_floating-point_format.\n *\n *  NaNs are represented as exponent 0x7ff and mantissa != 0.  The NaN is a\n *  signaling NaN when the highest bit of the mantissa is zero, and a quiet\n *  NaN when the highest bit is set.\n *\n *  At least three memory layouts are relevant here:\n *\n *    A B C D E F G H    Big endian (e.g. 68k)           DUK_USE_DOUBLE_BE\n *    H G F E D C B A    Little endian (e.g. x86)        DUK_USE_DOUBLE_LE\n *    D C B A H G F E    Mixed/cross endian (e.g. ARM)   DUK_USE_DOUBLE_ME\n *\n *  ARM is a special case: ARM double values are in mixed/cross endian\n *  format while ARM duk_uint64_t values are in standard little endian\n *  format (H G F E D C B A).  When a double is read as a duk_uint64_t\n *  from memory, the register will contain the (logical) value\n *  E F G H A B C D.  This requires some special handling below.\n *\n *  Indexes of various types (8-bit, 16-bit, 32-bit) in memory relative to\n *  the logical (big endian) order:\n *\n *  byte order      duk_uint8_t    duk_uint16_t     duk_uint32_t\n *    BE             01234567         0123               01\n *    LE             76543210         3210               10\n *    ME (ARM)       32107654         1032               01\n *\n *  Some processors may alter NaN values in a floating point load+store.\n *  For instance, on X86 a FLD + FSTP may convert a signaling NaN to a\n *  quiet one.  This is catastrophic when NaN space is used in packed\n *  duk_tval values.  See: misc/clang_aliasing.c.\n */\n\n#if !defined(DUK_DBLUNION_H_INCLUDED)\n#define DUK_DBLUNION_H_INCLUDED\n\n/*\n *  Union for accessing double parts, also serves as packed duk_tval\n */\n\nunion duk_double_union {\n\tdouble d;\n\tfloat f[2];\n#if defined(DUK_USE_64BIT_OPS)\n\tduk_uint64_t ull[1];\n#endif\n\tduk_uint32_t ui[2];\n\tduk_uint16_t us[4];\n\tduk_uint8_t uc[8];\n#if defined(DUK_USE_PACKED_TVAL)\n\tvoid *vp[2];  /* used by packed duk_tval, assumes sizeof(void *) == 4 */\n#endif\n};\n\ntypedef union duk_double_union duk_double_union;\n\n/*\n *  Indexes of various types with respect to big endian (logical) layout\n */\n\n#if defined(DUK_USE_DOUBLE_LE)\n#if defined(DUK_USE_64BIT_OPS)\n#define DUK_DBL_IDX_ULL0   0\n#endif\n#define DUK_DBL_IDX_UI0    1\n#define DUK_DBL_IDX_UI1    0\n#define DUK_DBL_IDX_US0    3\n#define DUK_DBL_IDX_US1    2\n#define DUK_DBL_IDX_US2    1\n#define DUK_DBL_IDX_US3    0\n#define DUK_DBL_IDX_UC0    7\n#define DUK_DBL_IDX_UC1    6\n#define DUK_DBL_IDX_UC2    5\n#define DUK_DBL_IDX_UC3    4\n#define DUK_DBL_IDX_UC4    3\n#define DUK_DBL_IDX_UC5    2\n#define DUK_DBL_IDX_UC6    1\n#define DUK_DBL_IDX_UC7    0\n#define DUK_DBL_IDX_VP0    DUK_DBL_IDX_UI0  /* packed tval */\n#define DUK_DBL_IDX_VP1    DUK_DBL_IDX_UI1  /* packed tval */\n#elif defined(DUK_USE_DOUBLE_BE)\n#if defined(DUK_USE_64BIT_OPS)\n#define DUK_DBL_IDX_ULL0   0\n#endif\n#define DUK_DBL_IDX_UI0    0\n#define DUK_DBL_IDX_UI1    1\n#define DUK_DBL_IDX_US0    0\n#define DUK_DBL_IDX_US1    1\n#define DUK_DBL_IDX_US2    2\n#define DUK_DBL_IDX_US3    3\n#define DUK_DBL_IDX_UC0    0\n#define DUK_DBL_IDX_UC1    1\n#define DUK_DBL_IDX_UC2    2\n#define DUK_DBL_IDX_UC3    3\n#define DUK_DBL_IDX_UC4    4\n#define DUK_DBL_IDX_UC5    5\n#define DUK_DBL_IDX_UC6    6\n#define DUK_DBL_IDX_UC7    7\n#define DUK_DBL_IDX_VP0    DUK_DBL_IDX_UI0  /* packed tval */\n#define DUK_DBL_IDX_VP1    DUK_DBL_IDX_UI1  /* packed tval */\n#elif defined(DUK_USE_DOUBLE_ME)\n#if defined(DUK_USE_64BIT_OPS)\n#define DUK_DBL_IDX_ULL0   0  /* not directly applicable, byte order differs from a double */\n#endif\n#define DUK_DBL_IDX_UI0    0\n#define DUK_DBL_IDX_UI1    1\n#define DUK_DBL_IDX_US0    1\n#define DUK_DBL_IDX_US1    0\n#define DUK_DBL_IDX_US2    3\n#define DUK_DBL_IDX_US3    2\n#define DUK_DBL_IDX_UC0    3\n#define DUK_DBL_IDX_UC1    2\n#define DUK_DBL_IDX_UC2    1\n#define DUK_DBL_IDX_UC3    0\n#define DUK_DBL_IDX_UC4    7\n#define DUK_DBL_IDX_UC5    6\n#define DUK_DBL_IDX_UC6    5\n#define DUK_DBL_IDX_UC7    4\n#define DUK_DBL_IDX_VP0    DUK_DBL_IDX_UI0  /* packed tval */\n#define DUK_DBL_IDX_VP1    DUK_DBL_IDX_UI1  /* packed tval */\n#else\n#error internal error\n#endif\n\n/*\n *  Helper macros for reading/writing memory representation parts, used\n *  by duk_numconv.c and duk_tval.h.\n */\n\n#define DUK_DBLUNION_SET_DOUBLE(u,v)  do {  \\\n\t\t(u)->d = (v); \\\n\t} while (0)\n\n#define DUK_DBLUNION_SET_HIGH32(u,v)  do {  \\\n\t\t(u)->ui[DUK_DBL_IDX_UI0] = (duk_uint32_t) (v); \\\n\t} while (0)\n\n#if defined(DUK_USE_64BIT_OPS)\n#if defined(DUK_USE_DOUBLE_ME)\n#define DUK_DBLUNION_SET_HIGH32_ZERO_LOW32(u,v)  do { \\\n\t\t(u)->ull[DUK_DBL_IDX_ULL0] = (duk_uint64_t) (v); \\\n\t} while (0)\n#else\n#define DUK_DBLUNION_SET_HIGH32_ZERO_LOW32(u,v)  do { \\\n\t\t(u)->ull[DUK_DBL_IDX_ULL0] = ((duk_uint64_t) (v)) << 32; \\\n\t} while (0)\n#endif\n#else  /* DUK_USE_64BIT_OPS */\n#define DUK_DBLUNION_SET_HIGH32_ZERO_LOW32(u,v)  do { \\\n\t\t(u)->ui[DUK_DBL_IDX_UI0] = (duk_uint32_t) (v); \\\n\t\t(u)->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) 0; \\\n\t} while (0)\n#endif  /* DUK_USE_64BIT_OPS */\n\n#define DUK_DBLUNION_SET_LOW32(u,v)  do {  \\\n\t\t(u)->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) (v); \\\n\t} while (0)\n\n#define DUK_DBLUNION_GET_DOUBLE(u)  ((u)->d)\n#define DUK_DBLUNION_GET_HIGH32(u)  ((u)->ui[DUK_DBL_IDX_UI0])\n#define DUK_DBLUNION_GET_LOW32(u)   ((u)->ui[DUK_DBL_IDX_UI1])\n\n#if defined(DUK_USE_64BIT_OPS)\n#if defined(DUK_USE_DOUBLE_ME)\n#define DUK_DBLUNION_SET_UINT64(u,v)  do { \\\n\t\t(u)->ui[DUK_DBL_IDX_UI0] = (duk_uint32_t) ((v) >> 32); \\\n\t\t(u)->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) (v); \\\n\t} while (0)\n#define DUK_DBLUNION_GET_UINT64(u) \\\n\t((((duk_uint64_t) (u)->ui[DUK_DBL_IDX_UI0]) << 32) | \\\n\t ((duk_uint64_t) (u)->ui[DUK_DBL_IDX_UI1]))\n#else\n#define DUK_DBLUNION_SET_UINT64(u,v)  do { \\\n\t\t(u)->ull[DUK_DBL_IDX_ULL0] = (duk_uint64_t) (v); \\\n\t} while (0)\n#define DUK_DBLUNION_GET_UINT64(u)  ((u)->ull[DUK_DBL_IDX_ULL0])\n#endif\n#define DUK_DBLUNION_SET_INT64(u,v) DUK_DBLUNION_SET_UINT64((u), (duk_uint64_t) (v))\n#define DUK_DBLUNION_GET_INT64(u)   ((duk_int64_t) DUK_DBLUNION_GET_UINT64((u)))\n#endif  /* DUK_USE_64BIT_OPS */\n\n/*\n *  Double NaN manipulation macros related to NaN normalization needed when\n *  using the packed duk_tval representation.  NaN normalization is necessary\n *  to keep double values compatible with the duk_tval format.\n *\n *  When packed duk_tval is used, the NaN space is used to store pointers\n *  and other tagged values in addition to NaNs.  Actual NaNs are normalized\n *  to a specific quiet NaN.  The macros below are used by the implementation\n *  to check and normalize NaN values when they might be created.  The macros\n *  are essentially NOPs when the non-packed duk_tval representation is used.\n *\n *  A FULL check is exact and checks all bits.  A NOTFULL check is used by\n *  the packed duk_tval and works correctly for all NaNs except those that\n *  begin with 0x7ff0.  Since the 'normalized NaN' values used with packed\n *  duk_tval begin with 0x7ff8, the partial check is reliable when packed\n *  duk_tval is used.  The 0x7ff8 prefix means the normalized NaN will be a\n *  quiet NaN regardless of its remaining lower bits.\n *\n *  The ME variant below is specifically for ARM byte order, which has the\n *  feature that while doubles have a mixed byte order (32107654), unsigned\n *  long long values has a little endian byte order (76543210).  When writing\n *  a logical double value through a ULL pointer, the 32-bit words need to be\n *  swapped; hence the #if defined()s below for ULL writes with DUK_USE_DOUBLE_ME.\n *  This is not full ARM support but suffices for some environments.\n */\n\n#if defined(DUK_USE_64BIT_OPS)\n#if defined(DUK_USE_DOUBLE_ME)\n/* Macros for 64-bit ops + mixed endian doubles. */\n#define DUK__DBLUNION_SET_NAN_FULL(u)  do { \\\n\t\t(u)->ull[DUK_DBL_IDX_ULL0] = DUK_U64_CONSTANT(0x000000007ff80000); \\\n\t} while (0)\n#define DUK__DBLUNION_IS_NAN_FULL(u) \\\n\t((((u)->ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x000000007ff00000)) == DUK_U64_CONSTANT(0x000000007ff00000)) && \\\n\t ((((u)->ull[DUK_DBL_IDX_ULL0]) & DUK_U64_CONSTANT(0xffffffff000fffff)) != 0))\n#define DUK__DBLUNION_IS_NORMALIZED_NAN_FULL(u) \\\n\t((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0x000000007ff80000))\n#define DUK__DBLUNION_IS_ANYINF(u) \\\n\t(((u)->ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0xffffffff7fffffff)) == DUK_U64_CONSTANT(0x000000007ff00000))\n#define DUK__DBLUNION_IS_POSINF(u) \\\n\t((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0x000000007ff00000))\n#define DUK__DBLUNION_IS_NEGINF(u) \\\n\t((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0x00000000fff00000))\n#define DUK__DBLUNION_IS_ANYZERO(u) \\\n\t(((u)->ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0xffffffff7fffffff)) == DUK_U64_CONSTANT(0x0000000000000000))\n#define DUK__DBLUNION_IS_POSZERO(u) \\\n\t((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0x0000000000000000))\n#define DUK__DBLUNION_IS_NEGZERO(u) \\\n\t((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0x0000000080000000))\n#else\n/* Macros for 64-bit ops + big/little endian doubles. */\n#define DUK__DBLUNION_SET_NAN_FULL(u)  do { \\\n\t\t(u)->ull[DUK_DBL_IDX_ULL0] = DUK_U64_CONSTANT(0x7ff8000000000000); \\\n\t} while (0)\n#define DUK__DBLUNION_IS_NAN_FULL(u) \\\n\t((((u)->ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x7ff0000000000000)) == DUK_U64_CONSTANT(0x7ff0000000000000)) && \\\n\t ((((u)->ull[DUK_DBL_IDX_ULL0]) & DUK_U64_CONSTANT(0x000fffffffffffff)) != 0))\n#define DUK__DBLUNION_IS_NORMALIZED_NAN_FULL(u) \\\n\t((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0x7ff8000000000000))\n#define DUK__DBLUNION_IS_ANYINF(u) \\\n\t(((u)->ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x7fffffffffffffff)) == DUK_U64_CONSTANT(0x7ff0000000000000))\n#define DUK__DBLUNION_IS_POSINF(u) \\\n\t((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0x7ff0000000000000))\n#define DUK__DBLUNION_IS_NEGINF(u) \\\n\t((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0xfff0000000000000))\n#define DUK__DBLUNION_IS_ANYZERO(u) \\\n\t(((u)->ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x7fffffffffffffff)) == DUK_U64_CONSTANT(0x0000000000000000))\n#define DUK__DBLUNION_IS_POSZERO(u) \\\n\t((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0x0000000000000000))\n#define DUK__DBLUNION_IS_NEGZERO(u) \\\n\t((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0x8000000000000000))\n#endif\n#else  /* DUK_USE_64BIT_OPS */\n/* Macros for no 64-bit ops, any endianness. */\n#define DUK__DBLUNION_SET_NAN_FULL(u)  do { \\\n\t\t(u)->ui[DUK_DBL_IDX_UI0] = (duk_uint32_t) 0x7ff80000UL; \\\n\t\t(u)->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) 0x00000000UL; \\\n\t} while (0)\n#define DUK__DBLUNION_IS_NAN_FULL(u) \\\n\t((((u)->ui[DUK_DBL_IDX_UI0] & 0x7ff00000UL) == 0x7ff00000UL) && \\\n\t (((u)->ui[DUK_DBL_IDX_UI0] & 0x000fffffUL) != 0 || \\\n          (u)->ui[DUK_DBL_IDX_UI1] != 0))\n#define DUK__DBLUNION_IS_NORMALIZED_NAN_FULL(u) \\\n\t(((u)->ui[DUK_DBL_IDX_UI0] == 0x7ff80000UL) && \\\n\t ((u)->ui[DUK_DBL_IDX_UI1] == 0x00000000UL))\n#define DUK__DBLUNION_IS_ANYINF(u) \\\n\t((((u)->ui[DUK_DBL_IDX_UI0] & 0x7fffffffUL) == 0x7ff00000UL) && \\\n\t ((u)->ui[DUK_DBL_IDX_UI1] == 0x00000000UL))\n#define DUK__DBLUNION_IS_POSINF(u) \\\n\t(((u)->ui[DUK_DBL_IDX_UI0] == 0x7ff00000UL) && \\\n\t ((u)->ui[DUK_DBL_IDX_UI1] == 0x00000000UL))\n#define DUK__DBLUNION_IS_NEGINF(u) \\\n\t(((u)->ui[DUK_DBL_IDX_UI0] == 0xfff00000UL) && \\\n\t ((u)->ui[DUK_DBL_IDX_UI1] == 0x00000000UL))\n#define DUK__DBLUNION_IS_ANYZERO(u) \\\n\t((((u)->ui[DUK_DBL_IDX_UI0] & 0x7fffffffUL) == 0x00000000UL) && \\\n\t ((u)->ui[DUK_DBL_IDX_UI1] == 0x00000000UL))\n#define DUK__DBLUNION_IS_POSZERO(u) \\\n\t(((u)->ui[DUK_DBL_IDX_UI0] == 0x00000000UL) && \\\n\t ((u)->ui[DUK_DBL_IDX_UI1] == 0x00000000UL))\n#define DUK__DBLUNION_IS_NEGZERO(u) \\\n\t(((u)->ui[DUK_DBL_IDX_UI0] == 0x80000000UL) && \\\n\t ((u)->ui[DUK_DBL_IDX_UI1] == 0x00000000UL))\n#endif  /* DUK_USE_64BIT_OPS */\n\n#define DUK__DBLUNION_SET_NAN_NOTFULL(u)  do { \\\n\t\t(u)->us[DUK_DBL_IDX_US0] = 0x7ff8UL; \\\n\t} while (0)\n\n#define DUK__DBLUNION_IS_NAN_NOTFULL(u) \\\n\t/* E == 0x7ff, topmost four bits of F != 0 => assume NaN */ \\\n\t((((u)->us[DUK_DBL_IDX_US0] & 0x7ff0UL) == 0x7ff0UL) && \\\n\t (((u)->us[DUK_DBL_IDX_US0] & 0x000fUL) != 0x0000UL))\n\n#define DUK__DBLUNION_IS_NORMALIZED_NAN_NOTFULL(u) \\\n\t/* E == 0x7ff, F == 8 => normalized NaN */ \\\n\t((u)->us[DUK_DBL_IDX_US0] == 0x7ff8UL)\n\n#define DUK__DBLUNION_NORMALIZE_NAN_CHECK_FULL(u)  do { \\\n\t\tif (DUK__DBLUNION_IS_NAN_FULL((u))) { \\\n\t\t\tDUK__DBLUNION_SET_NAN_FULL((u)); \\\n\t\t} \\\n\t} while (0)\n\n#define DUK__DBLUNION_NORMALIZE_NAN_CHECK_NOTFULL(u)  do { \\\n\t\tif (DUK__DBLUNION_IS_NAN_NOTFULL((u))) { \\\n\t\t\tDUK__DBLUNION_SET_NAN_NOTFULL((u)); \\\n\t\t} \\\n\t} while (0)\n\n/* Concrete macros for NaN handling used by the implementation internals.\n * Chosen so that they match the duk_tval representation: with a packed\n * duk_tval, ensure NaNs are properly normalized; with a non-packed duk_tval\n * these are essentially NOPs.\n */\n\n#if defined(DUK_USE_PACKED_TVAL)\n#if defined(DUK_USE_FULL_TVAL)\n#define DUK_DBLUNION_NORMALIZE_NAN_CHECK(u)  DUK__DBLUNION_NORMALIZE_NAN_CHECK_FULL((u))\n#define DUK_DBLUNION_IS_NAN(u)               DUK__DBLUNION_IS_NAN_FULL((u))\n#define DUK_DBLUNION_IS_NORMALIZED_NAN(u)    DUK__DBLUNION_IS_NORMALIZED_NAN_FULL((u))\n#define DUK_DBLUNION_SET_NAN(d)              DUK__DBLUNION_SET_NAN_FULL((d))\n#else\n#define DUK_DBLUNION_NORMALIZE_NAN_CHECK(u)  DUK__DBLUNION_NORMALIZE_NAN_CHECK_NOTFULL((u))\n#define DUK_DBLUNION_IS_NAN(u)               DUK__DBLUNION_IS_NAN_NOTFULL((u))\n#define DUK_DBLUNION_IS_NORMALIZED_NAN(u)    DUK__DBLUNION_IS_NORMALIZED_NAN_NOTFULL((u))\n#define DUK_DBLUNION_SET_NAN(d)              DUK__DBLUNION_SET_NAN_NOTFULL((d))\n#endif\n#define DUK_DBLUNION_IS_NORMALIZED(u) \\\n\t(!DUK_DBLUNION_IS_NAN((u)) ||  /* either not a NaN */ \\\n\t DUK_DBLUNION_IS_NORMALIZED_NAN((u)))  /* or is a normalized NaN */\n#else  /* DUK_USE_PACKED_TVAL */\n#define DUK_DBLUNION_NORMALIZE_NAN_CHECK(u)  /* nop: no need to normalize */\n#define DUK_DBLUNION_IS_NAN(u)               DUK__DBLUNION_IS_NAN_FULL((u))  /* (DUK_ISNAN((u)->d)) */\n#define DUK_DBLUNION_IS_NORMALIZED_NAN(u)    DUK__DBLUNION_IS_NAN_FULL((u))  /* (DUK_ISNAN((u)->d)) */\n#define DUK_DBLUNION_IS_NORMALIZED(u)        1  /* all doubles are considered normalized */\n#define DUK_DBLUNION_SET_NAN(u)  do { \\\n\t\t/* in non-packed representation we don't care about which NaN is used */ \\\n\t\t(u)->d = DUK_DOUBLE_NAN; \\\n\t} while (0)\n#endif  /* DUK_USE_PACKED_TVAL */\n\n#define DUK_DBLUNION_IS_ANYINF(u) DUK__DBLUNION_IS_ANYINF((u))\n#define DUK_DBLUNION_IS_POSINF(u) DUK__DBLUNION_IS_POSINF((u))\n#define DUK_DBLUNION_IS_NEGINF(u) DUK__DBLUNION_IS_NEGINF((u))\n\n#define DUK_DBLUNION_IS_ANYZERO(u) DUK__DBLUNION_IS_ANYZERO((u))\n#define DUK_DBLUNION_IS_POSZERO(u) DUK__DBLUNION_IS_POSZERO((u))\n#define DUK_DBLUNION_IS_NEGZERO(u) DUK__DBLUNION_IS_NEGZERO((u))\n\n/* XXX: native 64-bit byteswaps when available */\n\n/* 64-bit byteswap, same operation independent of target endianness. */\n#define DUK_DBLUNION_BSWAP64(u) do { \\\n\t\tduk_uint32_t duk__bswaptmp1, duk__bswaptmp2; \\\n\t\tduk__bswaptmp1 = (u)->ui[0]; \\\n\t\tduk__bswaptmp2 = (u)->ui[1]; \\\n\t\tduk__bswaptmp1 = DUK_BSWAP32(duk__bswaptmp1); \\\n\t\tduk__bswaptmp2 = DUK_BSWAP32(duk__bswaptmp2); \\\n\t\t(u)->ui[0] = duk__bswaptmp2; \\\n\t\t(u)->ui[1] = duk__bswaptmp1; \\\n\t} while (0)\n\n/* Byteswap an IEEE double in the duk_double_union from host to network\n * order.  For a big endian target this is a no-op.\n */\n#if defined(DUK_USE_DOUBLE_LE)\n#define DUK_DBLUNION_DOUBLE_HTON(u) do { \\\n\t\tduk_uint32_t duk__bswaptmp1, duk__bswaptmp2; \\\n\t\tduk__bswaptmp1 = (u)->ui[0]; \\\n\t\tduk__bswaptmp2 = (u)->ui[1]; \\\n\t\tduk__bswaptmp1 = DUK_BSWAP32(duk__bswaptmp1); \\\n\t\tduk__bswaptmp2 = DUK_BSWAP32(duk__bswaptmp2); \\\n\t\t(u)->ui[0] = duk__bswaptmp2; \\\n\t\t(u)->ui[1] = duk__bswaptmp1; \\\n\t} while (0)\n#elif defined(DUK_USE_DOUBLE_ME)\n#define DUK_DBLUNION_DOUBLE_HTON(u) do { \\\n\t\tduk_uint32_t duk__bswaptmp1, duk__bswaptmp2; \\\n\t\tduk__bswaptmp1 = (u)->ui[0]; \\\n\t\tduk__bswaptmp2 = (u)->ui[1]; \\\n\t\tduk__bswaptmp1 = DUK_BSWAP32(duk__bswaptmp1); \\\n\t\tduk__bswaptmp2 = DUK_BSWAP32(duk__bswaptmp2); \\\n\t\t(u)->ui[0] = duk__bswaptmp1; \\\n\t\t(u)->ui[1] = duk__bswaptmp2; \\\n\t} while (0)\n#elif defined(DUK_USE_DOUBLE_BE)\n#define DUK_DBLUNION_DOUBLE_HTON(u) do { } while (0)\n#else\n#error internal error, double endianness insane\n#endif\n\n/* Reverse operation is the same. */\n#define DUK_DBLUNION_DOUBLE_NTOH(u) DUK_DBLUNION_DOUBLE_HTON((u))\n\n/* Some sign bit helpers. */\n#if defined(DUK_USE_64BIT_OPS)\n#define DUK_DBLUNION_HAS_SIGNBIT(u) (((u)->ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x8000000000000000)) != 0)\n#define DUK_DBLUNION_GET_SIGNBIT(u) (((u)->ull[DUK_DBL_IDX_ULL0] >> 63U))\n#else\n#define DUK_DBLUNION_HAS_SIGNBIT(u) (((u)->ui[DUK_DBL_IDX_UI0] & 0x80000000UL) != 0)\n#define DUK_DBLUNION_GET_SIGNBIT(u) (((u)->ui[DUK_DBL_IDX_UI0] >> 31U))\n#endif\n\n#endif  /* DUK_DBLUNION_H_INCLUDED */\n/* #include duk_replacements.h */\n#line 1 \"duk_replacements.h\"\n#if !defined(DUK_REPLACEMENTS_H_INCLUDED)\n#define DUK_REPLACEMENTS_H_INCLUDED\n\n#if !defined(DUK_SINGLE_FILE)\n#if defined(DUK_USE_COMPUTED_INFINITY)\nDUK_INTERNAL_DECL double duk_computed_infinity;\n#endif\n#if defined(DUK_USE_COMPUTED_NAN)\nDUK_INTERNAL_DECL double duk_computed_nan;\n#endif\n#endif  /* !DUK_SINGLE_FILE */\n\n#if defined(DUK_USE_REPL_FPCLASSIFY)\nDUK_INTERNAL_DECL int duk_repl_fpclassify(double x);\n#endif\n#if defined(DUK_USE_REPL_SIGNBIT)\nDUK_INTERNAL_DECL int duk_repl_signbit(double x);\n#endif\n#if defined(DUK_USE_REPL_ISFINITE)\nDUK_INTERNAL_DECL int duk_repl_isfinite(double x);\n#endif\n#if defined(DUK_USE_REPL_ISNAN)\nDUK_INTERNAL_DECL int duk_repl_isnan(double x);\n#endif\n#if defined(DUK_USE_REPL_ISINF)\nDUK_INTERNAL_DECL int duk_repl_isinf(double x);\n#endif\n\n#endif  /* DUK_REPLACEMENTS_H_INCLUDED */\n/* #include duk_jmpbuf.h */\n#line 1 \"duk_jmpbuf.h\"\n/*\n *  Wrapper for jmp_buf.\n *\n *  This is used because jmp_buf is an array type for backward compatibility.\n *  Wrapping jmp_buf in a struct makes pointer references, sizeof, etc,\n *  behave more intuitively.\n *\n *  http://en.wikipedia.org/wiki/Setjmp.h#Member_types\n */\n\n#if !defined(DUK_JMPBUF_H_INCLUDED)\n#define DUK_JMPBUF_H_INCLUDED\n\n#if defined(DUK_USE_CPP_EXCEPTIONS)\nstruct duk_jmpbuf {\n\tduk_small_int_t dummy;  /* unused */\n};\n#else\nstruct duk_jmpbuf {\n\tDUK_JMPBUF_TYPE jb;\n};\n#endif\n\n#endif  /* DUK_JMPBUF_H_INCLUDED */\n/* #include duk_exception.h */\n#line 1 \"duk_exception.h\"\n/*\n *  Exception for Duktape internal throws when C++ exceptions are used\n *  for long control transfers.\n *\n *  Doesn't inherit from any exception base class to minimize the chance\n *  that user code would accidentally catch this exception.\n */\n\n#if !defined(DUK_EXCEPTION_H_INCLUDED)\n#define DUK_EXCEPTION_H_INCLUDED\n\n#if defined(DUK_USE_CPP_EXCEPTIONS)\nclass duk_internal_exception {\n\t/* intentionally empty */\n};\n#endif\n\n#endif  /* DUK_EXCEPTION_H_INCLUDED */\n/* #include duk_forwdecl.h */\n#line 1 \"duk_forwdecl.h\"\n/*\n *  Forward declarations for all Duktape structures.\n */\n\n#if !defined(DUK_FORWDECL_H_INCLUDED)\n#define DUK_FORWDECL_H_INCLUDED\n\n/*\n *  Forward declarations\n */\n\n#if defined(DUK_USE_CPP_EXCEPTIONS)\nclass duk_internal_exception;\n#else\nstruct duk_jmpbuf;\n#endif\n\n/* duk_tval intentionally skipped */\nstruct duk_heaphdr;\nstruct duk_heaphdr_string;\nstruct duk_harray;\nstruct duk_hstring;\nstruct duk_hstring_external;\nstruct duk_hobject;\nstruct duk_hcompfunc;\nstruct duk_hnatfunc;\nstruct duk_hboundfunc;\nstruct duk_hthread;\nstruct duk_hbufobj;\nstruct duk_hdecenv;\nstruct duk_hobjenv;\nstruct duk_hproxy;\nstruct duk_hbuffer;\nstruct duk_hbuffer_fixed;\nstruct duk_hbuffer_dynamic;\nstruct duk_hbuffer_external;\n\nstruct duk_propaccessor;\nunion duk_propvalue;\nstruct duk_propdesc;\n\nstruct duk_heap;\nstruct duk_breakpoint;\n\nstruct duk_activation;\nstruct duk_catcher;\nstruct duk_strcache;\nstruct duk_ljstate;\nstruct duk_strtab_entry;\n\n#if defined(DUK_USE_DEBUG)\nstruct duk_fixedbuffer;\n#endif\n\nstruct duk_bitdecoder_ctx;\nstruct duk_bitencoder_ctx;\nstruct duk_bufwriter_ctx;\n\nstruct duk_token;\nstruct duk_re_token;\nstruct duk_lexer_point;\nstruct duk_lexer_ctx;\nstruct duk_lexer_codepoint;\n\nstruct duk_compiler_instr;\nstruct duk_compiler_func;\nstruct duk_compiler_ctx;\n\nstruct duk_re_matcher_ctx;\nstruct duk_re_compiler_ctx;\n\n#if defined(DUK_USE_CPP_EXCEPTIONS)\n/* no typedef */\n#else\ntypedef struct duk_jmpbuf duk_jmpbuf;\n#endif\n\n/* duk_tval intentionally skipped */\ntypedef struct duk_heaphdr duk_heaphdr;\ntypedef struct duk_heaphdr_string duk_heaphdr_string;\ntypedef struct duk_harray duk_harray;\ntypedef struct duk_hstring duk_hstring;\ntypedef struct duk_hstring_external duk_hstring_external;\ntypedef struct duk_hobject duk_hobject;\ntypedef struct duk_hcompfunc duk_hcompfunc;\ntypedef struct duk_hnatfunc duk_hnatfunc;\ntypedef struct duk_hboundfunc duk_hboundfunc;\ntypedef struct duk_hthread duk_hthread;\ntypedef struct duk_hbufobj duk_hbufobj;\ntypedef struct duk_hdecenv duk_hdecenv;\ntypedef struct duk_hobjenv duk_hobjenv;\ntypedef struct duk_hproxy duk_hproxy;\ntypedef struct duk_hbuffer duk_hbuffer;\ntypedef struct duk_hbuffer_fixed duk_hbuffer_fixed;\ntypedef struct duk_hbuffer_dynamic duk_hbuffer_dynamic;\ntypedef struct duk_hbuffer_external duk_hbuffer_external;\n\ntypedef struct duk_propaccessor duk_propaccessor;\ntypedef union duk_propvalue duk_propvalue;\ntypedef struct duk_propdesc duk_propdesc;\n\ntypedef struct duk_heap duk_heap;\ntypedef struct duk_breakpoint duk_breakpoint;\n\ntypedef struct duk_activation duk_activation;\ntypedef struct duk_catcher duk_catcher;\ntypedef struct duk_strcache duk_strcache;\ntypedef struct duk_ljstate duk_ljstate;\ntypedef struct duk_strtab_entry duk_strtab_entry;\n\n#if defined(DUK_USE_DEBUG)\ntypedef struct duk_fixedbuffer duk_fixedbuffer;\n#endif\n\ntypedef struct duk_bitdecoder_ctx duk_bitdecoder_ctx;\ntypedef struct duk_bitencoder_ctx duk_bitencoder_ctx;\ntypedef struct duk_bufwriter_ctx duk_bufwriter_ctx;\n\ntypedef struct duk_token duk_token;\ntypedef struct duk_re_token duk_re_token;\ntypedef struct duk_lexer_point duk_lexer_point;\ntypedef struct duk_lexer_ctx duk_lexer_ctx;\ntypedef struct duk_lexer_codepoint duk_lexer_codepoint;\n\ntypedef struct duk_compiler_instr duk_compiler_instr;\ntypedef struct duk_compiler_func duk_compiler_func;\ntypedef struct duk_compiler_ctx duk_compiler_ctx;\n\ntypedef struct duk_re_matcher_ctx duk_re_matcher_ctx;\ntypedef struct duk_re_compiler_ctx duk_re_compiler_ctx;\n\n#endif  /* DUK_FORWDECL_H_INCLUDED */\n/* #include duk_tval.h */\n#line 1 \"duk_tval.h\"\n/*\n *  Tagged type definition (duk_tval) and accessor macros.\n *\n *  Access all fields through the accessor macros, as the representation\n *  is quite tricky.\n *\n *  There are two packed type alternatives: an 8-byte representation\n *  based on an IEEE double (preferred for compactness), and a 12-byte\n *  representation (portability).  The latter is needed also in e.g.\n *  64-bit environments (it usually pads to 16 bytes per value).\n *\n *  Selecting the tagged type format involves many trade-offs (memory\n *  use, size and performance of generated code, portability, etc).\n *\n *  NB: because macro arguments are often expressions, macros should\n *  avoid evaluating their argument more than once.\n */\n\n#if !defined(DUK_TVAL_H_INCLUDED)\n#define DUK_TVAL_H_INCLUDED\n\n/* sanity */\n#if !defined(DUK_USE_DOUBLE_LE) && !defined(DUK_USE_DOUBLE_ME) && !defined(DUK_USE_DOUBLE_BE)\n#error unsupported: cannot determine byte order variant\n#endif\n\n#if defined(DUK_USE_PACKED_TVAL)\n/* ======================================================================== */\n\n/*\n *  Packed 8-byte representation\n */\n\n/* use duk_double_union as duk_tval directly */\ntypedef union duk_double_union duk_tval;\ntypedef struct {\n\tduk_uint16_t a;\n\tduk_uint16_t b;\n\tduk_uint16_t c;\n\tduk_uint16_t d;\n} duk_tval_unused;\n\n/* tags */\n#define DUK_TAG_NORMALIZED_NAN    0x7ff8UL   /* the NaN variant we use */\n/* avoid tag 0xfff0, no risk of confusion with negative infinity */\n#define DUK_TAG_MIN               0xfff1UL\n#if defined(DUK_USE_FASTINT)\n#define DUK_TAG_FASTINT           0xfff1UL   /* embed: integer value */\n#endif\n#define DUK_TAG_UNUSED            0xfff2UL   /* marker; not actual tagged value */\n#define DUK_TAG_UNDEFINED         0xfff3UL   /* embed: nothing */\n#define DUK_TAG_NULL              0xfff4UL   /* embed: nothing */\n#define DUK_TAG_BOOLEAN           0xfff5UL   /* embed: 0 or 1 (false or true) */\n/* DUK_TAG_NUMBER would logically go here, but it has multiple 'tags' */\n#define DUK_TAG_POINTER           0xfff6UL   /* embed: void ptr */\n#define DUK_TAG_LIGHTFUNC         0xfff7UL   /* embed: func ptr */\n#define DUK_TAG_STRING            0xfff8UL   /* embed: duk_hstring ptr */\n#define DUK_TAG_OBJECT            0xfff9UL   /* embed: duk_hobject ptr */\n#define DUK_TAG_BUFFER            0xfffaUL   /* embed: duk_hbuffer ptr */\n#define DUK_TAG_MAX               0xfffaUL\n\n/* for convenience */\n#define DUK_XTAG_BOOLEAN_FALSE    0xfff50000UL\n#define DUK_XTAG_BOOLEAN_TRUE     0xfff50001UL\n\n#define DUK_TVAL_IS_VALID_TAG(tv) \\\n\t(DUK_TVAL_GET_TAG((tv)) - DUK_TAG_MIN <= DUK_TAG_MAX - DUK_TAG_MIN)\n\n/* DUK_TVAL_UNUSED initializer for duk_tval_unused, works for any endianness. */\n#define DUK_TVAL_UNUSED_INITIALIZER() \\\n\t{ DUK_TAG_UNUSED, DUK_TAG_UNUSED, DUK_TAG_UNUSED, DUK_TAG_UNUSED }\n\n/* two casts to avoid gcc warning: \"warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]\" */\n#if defined(DUK_USE_64BIT_OPS)\n#if defined(DUK_USE_DOUBLE_ME)\n#define DUK__TVAL_SET_TAGGEDPOINTER(tv,h,tag)  do { \\\n\t\t(tv)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) (tag)) << 16) | (((duk_uint64_t) (duk_uint32_t) (h)) << 32); \\\n\t} while (0)\n#else\n#define DUK__TVAL_SET_TAGGEDPOINTER(tv,h,tag)  do { \\\n\t\t(tv)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) (tag)) << 48) | ((duk_uint64_t) (duk_uint32_t) (h)); \\\n\t} while (0)\n#endif\n#else  /* DUK_USE_64BIT_OPS */\n#define DUK__TVAL_SET_TAGGEDPOINTER(tv,h,tag)  do { \\\n\t\tduk_tval *duk__tv; \\\n\t\tduk__tv = (tv); \\\n\t\tduk__tv->ui[DUK_DBL_IDX_UI0] = ((duk_uint32_t) (tag)) << 16; \\\n\t\tduk__tv->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) (h); \\\n\t} while (0)\n#endif  /* DUK_USE_64BIT_OPS */\n\n#if defined(DUK_USE_64BIT_OPS)\n/* Double casting for pointer to avoid gcc warning (cast from pointer to integer of different size) */\n#if defined(DUK_USE_DOUBLE_ME)\n#define DUK__TVAL_SET_LIGHTFUNC(tv,fp,flags)  do { \\\n\t\t(tv)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) DUK_TAG_LIGHTFUNC) << 16) | \\\n\t\t                              ((duk_uint64_t) (flags)) | \\\n\t\t                              (((duk_uint64_t) (duk_uint32_t) (fp)) << 32); \\\n\t} while (0)\n#else\n#define DUK__TVAL_SET_LIGHTFUNC(tv,fp,flags)  do { \\\n\t\t(tv)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) DUK_TAG_LIGHTFUNC) << 48) | \\\n\t\t                              (((duk_uint64_t) (flags)) << 32) | \\\n\t\t                              ((duk_uint64_t) (duk_uint32_t) (fp)); \\\n\t} while (0)\n#endif\n#else  /* DUK_USE_64BIT_OPS */\n#define DUK__TVAL_SET_LIGHTFUNC(tv,fp,flags)  do { \\\n\t\tduk_tval *duk__tv; \\\n\t\tduk__tv = (tv); \\\n\t\tduk__tv->ui[DUK_DBL_IDX_UI0] = (((duk_uint32_t) DUK_TAG_LIGHTFUNC) << 16) | ((duk_uint32_t) (flags)); \\\n\t\tduk__tv->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) (fp); \\\n\t} while (0)\n#endif  /* DUK_USE_64BIT_OPS */\n\n#if defined(DUK_USE_FASTINT)\n/* Note: masking is done for 'i' to deal with negative numbers correctly */\n#if defined(DUK_USE_DOUBLE_ME)\n#define DUK__TVAL_SET_I48(tv,i)  do { \\\n\t\tduk_tval *duk__tv; \\\n\t\tduk__tv = (tv); \\\n\t\tduk__tv->ui[DUK_DBL_IDX_UI0] = ((duk_uint32_t) DUK_TAG_FASTINT) << 16 | (((duk_uint32_t) ((i) >> 32)) & 0x0000ffffUL); \\\n\t\tduk__tv->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) (i); \\\n\t} while (0)\n#define DUK__TVAL_SET_U32(tv,i)  do { \\\n\t\tduk_tval *duk__tv; \\\n\t\tduk__tv = (tv); \\\n\t\tduk__tv->ui[DUK_DBL_IDX_UI0] = ((duk_uint32_t) DUK_TAG_FASTINT) << 16; \\\n\t\tduk__tv->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) (i); \\\n\t} while (0)\n#else\n#define DUK__TVAL_SET_I48(tv,i)  do { \\\n\t\t(tv)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) DUK_TAG_FASTINT) << 48) | (((duk_uint64_t) (i)) & DUK_U64_CONSTANT(0x0000ffffffffffff)); \\\n\t} while (0)\n#define DUK__TVAL_SET_U32(tv,i)  do { \\\n\t\t(tv)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) DUK_TAG_FASTINT) << 48) | (duk_uint64_t) (i); \\\n\t} while (0)\n#endif\n\n/* This needs to go through a cast because sign extension is needed. */\n#define DUK__TVAL_SET_I32(tv,i)  do { \\\n\t\tduk_int64_t duk__tmp = (duk_int64_t) (i); \\\n\t\tDUK_TVAL_SET_I48((tv), duk__tmp); \\\n\t} while (0)\n\n/* XXX: Clumsy sign extend and masking of 16 topmost bits. */\n#if defined(DUK_USE_DOUBLE_ME)\n#define DUK__TVAL_GET_FASTINT(tv)      (((duk_int64_t) ((((duk_uint64_t) (tv)->ui[DUK_DBL_IDX_UI0]) << 32) | ((duk_uint64_t) (tv)->ui[DUK_DBL_IDX_UI1]))) << 16 >> 16)\n#else\n#define DUK__TVAL_GET_FASTINT(tv)      ((((duk_int64_t) (tv)->ull[DUK_DBL_IDX_ULL0]) << 16) >> 16)\n#endif\n#define DUK__TVAL_GET_FASTINT_U32(tv)  ((tv)->ui[DUK_DBL_IDX_UI1])\n#define DUK__TVAL_GET_FASTINT_I32(tv)  ((duk_int32_t) (tv)->ui[DUK_DBL_IDX_UI1])\n#endif  /* DUK_USE_FASTINT */\n\n#define DUK_TVAL_SET_UNDEFINED(tv)  do { \\\n\t\t(tv)->us[DUK_DBL_IDX_US0] = (duk_uint16_t) DUK_TAG_UNDEFINED; \\\n\t} while (0)\n#define DUK_TVAL_SET_UNUSED(tv)  do { \\\n\t\t(tv)->us[DUK_DBL_IDX_US0] = (duk_uint16_t) DUK_TAG_UNUSED; \\\n\t} while (0)\n#define DUK_TVAL_SET_NULL(tv)  do { \\\n\t\t(tv)->us[DUK_DBL_IDX_US0] = (duk_uint16_t) DUK_TAG_NULL; \\\n\t} while (0)\n\n#define DUK_TVAL_SET_BOOLEAN(tv,val)         DUK_DBLUNION_SET_HIGH32((tv), (((duk_uint32_t) DUK_TAG_BOOLEAN) << 16) | ((duk_uint32_t) (val)))\n\n#define DUK_TVAL_SET_NAN(tv)                 DUK_DBLUNION_SET_NAN_FULL((tv))\n\n/* Assumes that caller has normalized NaNs, otherwise trouble ahead. */\n#if defined(DUK_USE_FASTINT)\n#define DUK_TVAL_SET_DOUBLE(tv,d)  do { \\\n\t\tduk_double_t duk__dblval; \\\n\t\tduk__dblval = (d); \\\n\t\tDUK_ASSERT_DOUBLE_IS_NORMALIZED(duk__dblval); \\\n\t\tDUK_DBLUNION_SET_DOUBLE((tv), duk__dblval); \\\n\t} while (0)\n#define DUK_TVAL_SET_I48(tv,i)               DUK__TVAL_SET_I48((tv), (i))\n#define DUK_TVAL_SET_I32(tv,i)               DUK__TVAL_SET_I32((tv), (i))\n#define DUK_TVAL_SET_U32(tv,i)               DUK__TVAL_SET_U32((tv), (i))\n#define DUK_TVAL_SET_NUMBER_CHKFAST_FAST(tv,d)  duk_tval_set_number_chkfast_fast((tv), (d))\n#define DUK_TVAL_SET_NUMBER_CHKFAST_SLOW(tv,d)  duk_tval_set_number_chkfast_slow((tv), (d))\n#define DUK_TVAL_SET_NUMBER(tv,d)            DUK_TVAL_SET_DOUBLE((tv), (d))\n#define DUK_TVAL_CHKFAST_INPLACE_FAST(tv)  do { \\\n\t\tduk_tval *duk__tv; \\\n\t\tduk_double_t duk__d; \\\n\t\tduk__tv = (tv); \\\n\t\tif (DUK_TVAL_IS_DOUBLE(duk__tv)) { \\\n\t\t\tduk__d = DUK_TVAL_GET_DOUBLE(duk__tv); \\\n\t\t\tDUK_TVAL_SET_NUMBER_CHKFAST_FAST(duk__tv, duk__d); \\\n\t\t} \\\n\t} while (0)\n#define DUK_TVAL_CHKFAST_INPLACE_SLOW(tv)  do { \\\n\t\tduk_tval *duk__tv; \\\n\t\tduk_double_t duk__d; \\\n\t\tduk__tv = (tv); \\\n\t\tif (DUK_TVAL_IS_DOUBLE(duk__tv)) { \\\n\t\t\tduk__d = DUK_TVAL_GET_DOUBLE(duk__tv); \\\n\t\t\tDUK_TVAL_SET_NUMBER_CHKFAST_SLOW(duk__tv, duk__d); \\\n\t\t} \\\n\t} while (0)\n#else  /* DUK_USE_FASTINT */\n#define DUK_TVAL_SET_DOUBLE(tv,d)  do { \\\n\t\tduk_double_t duk__dblval; \\\n\t\tduk__dblval = (d); \\\n\t\tDUK_ASSERT_DOUBLE_IS_NORMALIZED(duk__dblval); \\\n\t\tDUK_DBLUNION_SET_DOUBLE((tv), duk__dblval); \\\n\t} while (0)\n#define DUK_TVAL_SET_I48(tv,i)               DUK_TVAL_SET_DOUBLE((tv), (duk_double_t) (i))  /* XXX: fast int-to-double */\n#define DUK_TVAL_SET_I32(tv,i)               DUK_TVAL_SET_DOUBLE((tv), (duk_double_t) (i))\n#define DUK_TVAL_SET_U32(tv,i)               DUK_TVAL_SET_DOUBLE((tv), (duk_double_t) (i))\n#define DUK_TVAL_SET_NUMBER_CHKFAST_FAST(tv,d)    DUK_TVAL_SET_DOUBLE((tv), (d))\n#define DUK_TVAL_SET_NUMBER_CHKFAST_SLOW(tv,d)    DUK_TVAL_SET_DOUBLE((tv), (d))\n#define DUK_TVAL_SET_NUMBER(tv,d)            DUK_TVAL_SET_DOUBLE((tv), (d))\n#define DUK_TVAL_CHKFAST_INPLACE_FAST(tv)  do { } while (0)\n#define DUK_TVAL_CHKFAST_INPLACE_SLOW(tv)  do { } while (0)\n#endif  /* DUK_USE_FASTINT */\n\n#define DUK_TVAL_SET_FASTINT(tv,i)           DUK_TVAL_SET_I48((tv), (i))  /* alias */\n\n#define DUK_TVAL_SET_LIGHTFUNC(tv,fp,flags)  DUK__TVAL_SET_LIGHTFUNC((tv), (fp), (flags))\n#define DUK_TVAL_SET_STRING(tv,h)            DUK__TVAL_SET_TAGGEDPOINTER((tv), (h), DUK_TAG_STRING)\n#define DUK_TVAL_SET_OBJECT(tv,h)            DUK__TVAL_SET_TAGGEDPOINTER((tv), (h), DUK_TAG_OBJECT)\n#define DUK_TVAL_SET_BUFFER(tv,h)            DUK__TVAL_SET_TAGGEDPOINTER((tv), (h), DUK_TAG_BUFFER)\n#define DUK_TVAL_SET_POINTER(tv,p)           DUK__TVAL_SET_TAGGEDPOINTER((tv), (p), DUK_TAG_POINTER)\n\n#define DUK_TVAL_SET_TVAL(tv,x)              do { *(tv) = *(x); } while (0)\n\n/* getters */\n#define DUK_TVAL_GET_BOOLEAN(tv)             ((duk_small_uint_t) (tv)->us[DUK_DBL_IDX_US1])\n#if defined(DUK_USE_FASTINT)\n#define DUK_TVAL_GET_DOUBLE(tv)              ((tv)->d)\n#define DUK_TVAL_GET_FASTINT(tv)             DUK__TVAL_GET_FASTINT((tv))\n#define DUK_TVAL_GET_FASTINT_U32(tv)         DUK__TVAL_GET_FASTINT_U32((tv))\n#define DUK_TVAL_GET_FASTINT_I32(tv)         DUK__TVAL_GET_FASTINT_I32((tv))\n#define DUK_TVAL_GET_NUMBER(tv)              duk_tval_get_number_packed((tv))\n#else\n#define DUK_TVAL_GET_NUMBER(tv)              ((tv)->d)\n#define DUK_TVAL_GET_DOUBLE(tv)              ((tv)->d)\n#endif\n#define DUK_TVAL_GET_LIGHTFUNC(tv,out_fp,out_flags)  do { \\\n\t\t(out_flags) = (tv)->ui[DUK_DBL_IDX_UI0] & 0xffffUL; \\\n\t\t(out_fp) = (duk_c_function) (tv)->ui[DUK_DBL_IDX_UI1]; \\\n\t} while (0)\n#define DUK_TVAL_GET_LIGHTFUNC_FUNCPTR(tv)   ((duk_c_function) ((tv)->ui[DUK_DBL_IDX_UI1]))\n#define DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv)     (((duk_small_uint_t) (tv)->ui[DUK_DBL_IDX_UI0]) & 0xffffUL)\n#define DUK_TVAL_GET_STRING(tv)              ((duk_hstring *) (tv)->vp[DUK_DBL_IDX_VP1])\n#define DUK_TVAL_GET_OBJECT(tv)              ((duk_hobject *) (tv)->vp[DUK_DBL_IDX_VP1])\n#define DUK_TVAL_GET_BUFFER(tv)              ((duk_hbuffer *) (tv)->vp[DUK_DBL_IDX_VP1])\n#define DUK_TVAL_GET_POINTER(tv)             ((void *) (tv)->vp[DUK_DBL_IDX_VP1])\n#define DUK_TVAL_GET_HEAPHDR(tv)             ((duk_heaphdr *) (tv)->vp[DUK_DBL_IDX_VP1])\n\n/* decoding */\n#define DUK_TVAL_GET_TAG(tv)                 ((duk_small_uint_t) (tv)->us[DUK_DBL_IDX_US0])\n\n#define DUK_TVAL_IS_UNDEFINED(tv)            (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_UNDEFINED)\n#define DUK_TVAL_IS_UNUSED(tv)               (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_UNUSED)\n#define DUK_TVAL_IS_NULL(tv)                 (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_NULL)\n#define DUK_TVAL_IS_BOOLEAN(tv)              (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_BOOLEAN)\n#define DUK_TVAL_IS_BOOLEAN_TRUE(tv)         ((tv)->ui[DUK_DBL_IDX_UI0] == DUK_XTAG_BOOLEAN_TRUE)\n#define DUK_TVAL_IS_BOOLEAN_FALSE(tv)        ((tv)->ui[DUK_DBL_IDX_UI0] == DUK_XTAG_BOOLEAN_FALSE)\n#define DUK_TVAL_IS_LIGHTFUNC(tv)            (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_LIGHTFUNC)\n#define DUK_TVAL_IS_STRING(tv)               (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_STRING)\n#define DUK_TVAL_IS_OBJECT(tv)               (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_OBJECT)\n#define DUK_TVAL_IS_BUFFER(tv)               (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_BUFFER)\n#define DUK_TVAL_IS_POINTER(tv)              (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_POINTER)\n#if defined(DUK_USE_FASTINT)\n/* 0xfff0 is -Infinity */\n#define DUK_TVAL_IS_DOUBLE(tv)               (DUK_TVAL_GET_TAG((tv)) <= 0xfff0UL)\n#define DUK_TVAL_IS_FASTINT(tv)              (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_FASTINT)\n#define DUK_TVAL_IS_NUMBER(tv)               (DUK_TVAL_GET_TAG((tv)) <= 0xfff1UL)\n#else\n#define DUK_TVAL_IS_NUMBER(tv)               (DUK_TVAL_GET_TAG((tv)) <= 0xfff0UL)\n#define DUK_TVAL_IS_DOUBLE(tv)               DUK_TVAL_IS_NUMBER((tv))\n#endif\n\n/* This is performance critical because it appears in every DECREF. */\n#define DUK_TVAL_IS_HEAP_ALLOCATED(tv)       (DUK_TVAL_GET_TAG((tv)) >= DUK_TAG_STRING)\n\n#if defined(DUK_USE_FASTINT)\nDUK_INTERNAL_DECL duk_double_t duk_tval_get_number_packed(duk_tval *tv);\n#endif\n\n#else  /* DUK_USE_PACKED_TVAL */\n/* ======================================================================== */\n\n/*\n *  Portable 12-byte representation\n */\n\n/* Note: not initializing all bytes is normally not an issue: Duktape won't\n * read or use the uninitialized bytes so valgrind won't issue warnings.\n * In some special cases a harmless valgrind warning may be issued though.\n * For example, the DumpHeap debugger command writes out a compiled function's\n * 'data' area as is, including any uninitialized bytes, which causes a\n * valgrind warning.\n */\n\ntypedef struct duk_tval_struct duk_tval;\n\nstruct duk_tval_struct {\n\tduk_small_uint_t t;\n\tduk_small_uint_t v_extra;\n\tunion {\n\t\tduk_double_t d;\n\t\tduk_small_int_t i;\n#if defined(DUK_USE_FASTINT)\n\t\tduk_int64_t fi;  /* if present, forces 16-byte duk_tval */\n#endif\n\t\tvoid *voidptr;\n\t\tduk_hstring *hstring;\n\t\tduk_hobject *hobject;\n\t\tduk_hcompfunc *hcompfunc;\n\t\tduk_hnatfunc *hnatfunc;\n\t\tduk_hthread *hthread;\n\t\tduk_hbuffer *hbuffer;\n\t\tduk_heaphdr *heaphdr;\n\t\tduk_c_function lightfunc;\n\t} v;\n};\n\ntypedef struct {\n\tduk_small_uint_t t;\n\tduk_small_uint_t v_extra;\n\t/* The rest of the fields don't matter except for debug dumps and such\n\t * for which a partial initializer may trigger out-ot-bounds memory\n\t * reads.  Include a double field which is usually as large or larger\n\t * than pointers (not always however).\n\t */\n\tduk_double_t d;\n} duk_tval_unused;\n\n#define DUK_TVAL_UNUSED_INITIALIZER() \\\n\t{ DUK_TAG_UNUSED, 0, 0.0 }\n\n#define DUK_TAG_MIN                   0\n#define DUK_TAG_NUMBER                0  /* DUK_TAG_NUMBER only defined for non-packed duk_tval */\n#if defined(DUK_USE_FASTINT)\n#define DUK_TAG_FASTINT               1\n#endif\n#define DUK_TAG_UNDEFINED             2\n#define DUK_TAG_NULL                  3\n#define DUK_TAG_BOOLEAN               4\n#define DUK_TAG_POINTER               5\n#define DUK_TAG_LIGHTFUNC             6\n#define DUK_TAG_UNUSED                7  /* marker; not actual tagged type */\n#define DUK_TAG_STRING                8  /* first heap allocated, match bit boundary */\n#define DUK_TAG_OBJECT                9\n#define DUK_TAG_BUFFER                10\n#define DUK_TAG_MAX                   10\n\n#define DUK_TVAL_IS_VALID_TAG(tv) \\\n\t(DUK_TVAL_GET_TAG((tv)) - DUK_TAG_MIN <= DUK_TAG_MAX - DUK_TAG_MIN)\n\n/* DUK_TAG_NUMBER is intentionally first, as it is the default clause in code\n * to support the 8-byte representation.  Further, it is a non-heap-allocated\n * type so it should come before DUK_TAG_STRING.  Finally, it should not break\n * the tag value ranges covered by case-clauses in a switch-case.\n */\n\n/* setters */\n#define DUK_TVAL_SET_UNDEFINED(tv)  do { \\\n\t\tduk_tval *duk__tv; \\\n\t\tduk__tv = (tv); \\\n\t\tduk__tv->t = DUK_TAG_UNDEFINED; \\\n\t} while (0)\n\n#define DUK_TVAL_SET_UNUSED(tv)  do { \\\n\t\tduk_tval *duk__tv; \\\n\t\tduk__tv = (tv); \\\n\t\tduk__tv->t = DUK_TAG_UNUSED; \\\n\t} while (0)\n\n#define DUK_TVAL_SET_NULL(tv)  do { \\\n\t\tduk_tval *duk__tv; \\\n\t\tduk__tv = (tv); \\\n\t\tduk__tv->t = DUK_TAG_NULL; \\\n\t} while (0)\n\n#define DUK_TVAL_SET_BOOLEAN(tv,val)  do { \\\n\t\tduk_tval *duk__tv; \\\n\t\tduk__tv = (tv); \\\n\t\tduk__tv->t = DUK_TAG_BOOLEAN; \\\n\t\tduk__tv->v.i = (duk_small_int_t) (val); \\\n\t} while (0)\n\n#if defined(DUK_USE_FASTINT)\n#define DUK_TVAL_SET_DOUBLE(tv,val)  do { \\\n\t\tduk_tval *duk__tv; \\\n\t\tduk_double_t duk__dblval; \\\n\t\tduk__dblval = (val); \\\n\t\tDUK_ASSERT_DOUBLE_IS_NORMALIZED(duk__dblval); /* nop for unpacked duk_tval */ \\\n\t\tduk__tv = (tv); \\\n\t\tduk__tv->t = DUK_TAG_NUMBER; \\\n\t\tduk__tv->v.d = duk__dblval; \\\n\t} while (0)\n#define DUK_TVAL_SET_I48(tv,val)  do { \\\n\t\tduk_tval *duk__tv; \\\n\t\tduk__tv = (tv); \\\n\t\tduk__tv->t = DUK_TAG_FASTINT; \\\n\t\tduk__tv->v.fi = (val); \\\n\t} while (0)\n#define DUK_TVAL_SET_U32(tv,val)  do { \\\n\t\tduk_tval *duk__tv; \\\n\t\tduk__tv = (tv); \\\n\t\tduk__tv->t = DUK_TAG_FASTINT; \\\n\t\tduk__tv->v.fi = (duk_int64_t) (val); \\\n\t} while (0)\n#define DUK_TVAL_SET_I32(tv,val)  do { \\\n\t\tduk_tval *duk__tv; \\\n\t\tduk__tv = (tv); \\\n\t\tduk__tv->t = DUK_TAG_FASTINT; \\\n\t\tduk__tv->v.fi = (duk_int64_t) (val); \\\n\t} while (0)\n#define DUK_TVAL_SET_NUMBER_CHKFAST_FAST(tv,d) \\\n\tduk_tval_set_number_chkfast_fast((tv), (d))\n#define DUK_TVAL_SET_NUMBER_CHKFAST_SLOW(tv,d) \\\n\tduk_tval_set_number_chkfast_slow((tv), (d))\n#define DUK_TVAL_SET_NUMBER(tv,val) \\\n\tDUK_TVAL_SET_DOUBLE((tv), (val))\n#define DUK_TVAL_CHKFAST_INPLACE_FAST(tv)  do { \\\n\t\tduk_tval *duk__tv; \\\n\t\tduk_double_t duk__d; \\\n\t\tduk__tv = (tv); \\\n\t\tif (DUK_TVAL_IS_DOUBLE(duk__tv)) { \\\n\t\t\tduk__d = DUK_TVAL_GET_DOUBLE(duk__tv); \\\n\t\t\tDUK_TVAL_SET_NUMBER_CHKFAST_FAST(duk__tv, duk__d); \\\n\t\t} \\\n\t} while (0)\n#define DUK_TVAL_CHKFAST_INPLACE_SLOW(tv)  do { \\\n\t\tduk_tval *duk__tv; \\\n\t\tduk_double_t duk__d; \\\n\t\tduk__tv = (tv); \\\n\t\tif (DUK_TVAL_IS_DOUBLE(duk__tv)) { \\\n\t\t\tduk__d = DUK_TVAL_GET_DOUBLE(duk__tv); \\\n\t\t\tDUK_TVAL_SET_NUMBER_CHKFAST_SLOW(duk__tv, duk__d); \\\n\t\t} \\\n\t} while (0)\n#else  /* DUK_USE_FASTINT */\n#define DUK_TVAL_SET_DOUBLE(tv,d) \\\n\tDUK_TVAL_SET_NUMBER((tv), (d))\n#define DUK_TVAL_SET_I48(tv,val) \\\n\tDUK_TVAL_SET_NUMBER((tv), (duk_double_t) (val))  /* XXX: fast int-to-double */\n#define DUK_TVAL_SET_U32(tv,val) \\\n\tDUK_TVAL_SET_NUMBER((tv), (duk_double_t) (val))\n#define DUK_TVAL_SET_I32(tv,val) \\\n\tDUK_TVAL_SET_NUMBER((tv), (duk_double_t) (val))\n#define DUK_TVAL_SET_NUMBER(tv,val)  do { \\\n\t\tduk_tval *duk__tv; \\\n\t\tduk_double_t duk__dblval; \\\n\t\tduk__dblval = (val); \\\n\t\tDUK_ASSERT_DOUBLE_IS_NORMALIZED(duk__dblval); /* nop for unpacked duk_tval */ \\\n\t\tduk__tv = (tv); \\\n\t\tduk__tv->t = DUK_TAG_NUMBER; \\\n\t\tduk__tv->v.d = duk__dblval; \\\n\t} while (0)\n#define DUK_TVAL_SET_NUMBER_CHKFAST_FAST(tv,d) \\\n\tDUK_TVAL_SET_NUMBER((tv), (d))\n#define DUK_TVAL_SET_NUMBER_CHKFAST_SLOW(tv,d) \\\n\tDUK_TVAL_SET_NUMBER((tv), (d))\n#define DUK_TVAL_CHKFAST_INPLACE_FAST(tv)  do { } while (0)\n#define DUK_TVAL_CHKFAST_INPLACE_SLOW(tv)  do { } while (0)\n#endif  /* DUK_USE_FASTINT */\n\n#define DUK_TVAL_SET_FASTINT(tv,i) \\\n\tDUK_TVAL_SET_I48((tv), (i))  /* alias */\n\n#define DUK_TVAL_SET_POINTER(tv,hptr)  do { \\\n\t\tduk_tval *duk__tv; \\\n\t\tduk__tv = (tv); \\\n\t\tduk__tv->t = DUK_TAG_POINTER; \\\n\t\tduk__tv->v.voidptr = (hptr); \\\n\t} while (0)\n\n#define DUK_TVAL_SET_LIGHTFUNC(tv,fp,flags)  do { \\\n\t\tduk_tval *duk__tv; \\\n\t\tduk__tv = (tv); \\\n\t\tduk__tv->t = DUK_TAG_LIGHTFUNC; \\\n\t\tduk__tv->v_extra = (flags); \\\n\t\tduk__tv->v.lightfunc = (duk_c_function) (fp); \\\n\t} while (0)\n\n#define DUK_TVAL_SET_STRING(tv,hptr)  do { \\\n\t\tduk_tval *duk__tv; \\\n\t\tduk__tv = (tv); \\\n\t\tduk__tv->t = DUK_TAG_STRING; \\\n\t\tduk__tv->v.hstring = (hptr); \\\n\t} while (0)\n\n#define DUK_TVAL_SET_OBJECT(tv,hptr)  do { \\\n\t\tduk_tval *duk__tv; \\\n\t\tduk__tv = (tv); \\\n\t\tduk__tv->t = DUK_TAG_OBJECT; \\\n\t\tduk__tv->v.hobject = (hptr); \\\n\t} while (0)\n\n#define DUK_TVAL_SET_BUFFER(tv,hptr)  do { \\\n\t\tduk_tval *duk__tv; \\\n\t\tduk__tv = (tv); \\\n\t\tduk__tv->t = DUK_TAG_BUFFER; \\\n\t\tduk__tv->v.hbuffer = (hptr); \\\n\t} while (0)\n\n#define DUK_TVAL_SET_NAN(tv)  do { \\\n\t\t/* in non-packed representation we don't care about which NaN is used */ \\\n\t\tduk_tval *duk__tv; \\\n\t\tduk__tv = (tv); \\\n\t\tduk__tv->t = DUK_TAG_NUMBER; \\\n\t\tduk__tv->v.d = DUK_DOUBLE_NAN; \\\n\t} while (0)\n\n#define DUK_TVAL_SET_TVAL(tv,x)            do { *(tv) = *(x); } while (0)\n\n/* getters */\n#define DUK_TVAL_GET_BOOLEAN(tv)           ((duk_small_uint_t) (tv)->v.i)\n#if defined(DUK_USE_FASTINT)\n#define DUK_TVAL_GET_DOUBLE(tv)            ((tv)->v.d)\n#define DUK_TVAL_GET_FASTINT(tv)           ((tv)->v.fi)\n#define DUK_TVAL_GET_FASTINT_U32(tv)       ((duk_uint32_t) ((tv)->v.fi))\n#define DUK_TVAL_GET_FASTINT_I32(tv)       ((duk_int32_t) ((tv)->v.fi))\n#if 0\n#define DUK_TVAL_GET_NUMBER(tv)            (DUK_TVAL_IS_FASTINT((tv)) ? \\\n                                               (duk_double_t) DUK_TVAL_GET_FASTINT((tv)) : \\\n                                               DUK_TVAL_GET_DOUBLE((tv)))\n#define DUK_TVAL_GET_NUMBER(tv)            duk_tval_get_number_unpacked((tv))\n#else\n/* This seems reasonable overall. */\n#define DUK_TVAL_GET_NUMBER(tv)            (DUK_TVAL_IS_FASTINT((tv)) ? \\\n                                               duk_tval_get_number_unpacked_fastint((tv)) : \\\n                                               DUK_TVAL_GET_DOUBLE((tv)))\n#endif\n#else\n#define DUK_TVAL_GET_NUMBER(tv)            ((tv)->v.d)\n#define DUK_TVAL_GET_DOUBLE(tv)            ((tv)->v.d)\n#endif  /* DUK_USE_FASTINT */\n#define DUK_TVAL_GET_POINTER(tv)           ((tv)->v.voidptr)\n#define DUK_TVAL_GET_LIGHTFUNC(tv,out_fp,out_flags)  do { \\\n\t\t(out_flags) = (duk_uint32_t) (tv)->v_extra; \\\n\t\t(out_fp) = (tv)->v.lightfunc; \\\n\t} while (0)\n#define DUK_TVAL_GET_LIGHTFUNC_FUNCPTR(tv) ((tv)->v.lightfunc)\n#define DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv)   ((duk_small_uint_t) ((tv)->v_extra))\n#define DUK_TVAL_GET_STRING(tv)            ((tv)->v.hstring)\n#define DUK_TVAL_GET_OBJECT(tv)            ((tv)->v.hobject)\n#define DUK_TVAL_GET_BUFFER(tv)            ((tv)->v.hbuffer)\n#define DUK_TVAL_GET_HEAPHDR(tv)           ((tv)->v.heaphdr)\n\n/* decoding */\n#define DUK_TVAL_GET_TAG(tv)               ((tv)->t)\n#define DUK_TVAL_IS_UNDEFINED(tv)          ((tv)->t == DUK_TAG_UNDEFINED)\n#define DUK_TVAL_IS_UNUSED(tv)             ((tv)->t == DUK_TAG_UNUSED)\n#define DUK_TVAL_IS_NULL(tv)               ((tv)->t == DUK_TAG_NULL)\n#define DUK_TVAL_IS_BOOLEAN(tv)            ((tv)->t == DUK_TAG_BOOLEAN)\n#define DUK_TVAL_IS_BOOLEAN_TRUE(tv)       (((tv)->t == DUK_TAG_BOOLEAN) && ((tv)->v.i != 0))\n#define DUK_TVAL_IS_BOOLEAN_FALSE(tv)      (((tv)->t == DUK_TAG_BOOLEAN) && ((tv)->v.i == 0))\n#if defined(DUK_USE_FASTINT)\n#define DUK_TVAL_IS_DOUBLE(tv)             ((tv)->t == DUK_TAG_NUMBER)\n#define DUK_TVAL_IS_FASTINT(tv)            ((tv)->t == DUK_TAG_FASTINT)\n#define DUK_TVAL_IS_NUMBER(tv)             ((tv)->t == DUK_TAG_NUMBER || \\\n                                            (tv)->t == DUK_TAG_FASTINT)\n#else\n#define DUK_TVAL_IS_NUMBER(tv)             ((tv)->t == DUK_TAG_NUMBER)\n#define DUK_TVAL_IS_DOUBLE(tv)             DUK_TVAL_IS_NUMBER((tv))\n#endif  /* DUK_USE_FASTINT */\n#define DUK_TVAL_IS_POINTER(tv)            ((tv)->t == DUK_TAG_POINTER)\n#define DUK_TVAL_IS_LIGHTFUNC(tv)          ((tv)->t == DUK_TAG_LIGHTFUNC)\n#define DUK_TVAL_IS_STRING(tv)             ((tv)->t == DUK_TAG_STRING)\n#define DUK_TVAL_IS_OBJECT(tv)             ((tv)->t == DUK_TAG_OBJECT)\n#define DUK_TVAL_IS_BUFFER(tv)             ((tv)->t == DUK_TAG_BUFFER)\n\n/* This is performance critical because it's needed for every DECREF.\n * Take advantage of the fact that the first heap allocated tag is 8,\n * so that bit 3 is set for all heap allocated tags (and never set for\n * non-heap-allocated tags).\n */\n#if 0\n#define DUK_TVAL_IS_HEAP_ALLOCATED(tv)     ((tv)->t >= DUK_TAG_STRING)\n#endif\n#define DUK_TVAL_IS_HEAP_ALLOCATED(tv)     ((tv)->t & 0x08)\n\n#if defined(DUK_USE_FASTINT)\n#if 0\nDUK_INTERNAL_DECL duk_double_t duk_tval_get_number_unpacked(duk_tval *tv);\n#endif\nDUK_INTERNAL_DECL duk_double_t duk_tval_get_number_unpacked_fastint(duk_tval *tv);\n#endif\n\n#endif  /* DUK_USE_PACKED_TVAL */\n\n/*\n *  Convenience (independent of representation)\n */\n\n#define DUK_TVAL_SET_BOOLEAN_TRUE(tv)        DUK_TVAL_SET_BOOLEAN((tv), 1)\n#define DUK_TVAL_SET_BOOLEAN_FALSE(tv)       DUK_TVAL_SET_BOOLEAN((tv), 0)\n\n#define DUK_TVAL_STRING_IS_SYMBOL(tv) \\\n\tDUK_HSTRING_HAS_SYMBOL(DUK_TVAL_GET_STRING((tv)))\n\n/* Lightfunc flags packing and unpacking. */\n/* Sign extend: 0x0000##00 -> 0x##000000 -> sign extend to 0xssssss##.\n * Avoid signed shifts due to portability limitations.\n */\n#define DUK_LFUNC_FLAGS_GET_MAGIC(lf_flags) \\\n\t((duk_int32_t) (duk_int8_t) (((duk_uint16_t) (lf_flags)) >> 8))\n#define DUK_LFUNC_FLAGS_GET_LENGTH(lf_flags) \\\n\t(((lf_flags) >> 4) & 0x0fU)\n#define DUK_LFUNC_FLAGS_GET_NARGS(lf_flags) \\\n\t((lf_flags) & 0x0fU)\n#define DUK_LFUNC_FLAGS_PACK(magic,length,nargs) \\\n\t((((duk_small_uint_t) (magic)) & 0xffU) << 8) | ((length) << 4) | (nargs)\n\n#define DUK_LFUNC_NARGS_VARARGS             0x0f   /* varargs marker */\n#define DUK_LFUNC_NARGS_MIN                 0x00\n#define DUK_LFUNC_NARGS_MAX                 0x0e   /* max, excl. varargs marker */\n#define DUK_LFUNC_LENGTH_MIN                0x00\n#define DUK_LFUNC_LENGTH_MAX                0x0f\n#define DUK_LFUNC_MAGIC_MIN                 (-0x80)\n#define DUK_LFUNC_MAGIC_MAX                 0x7f\n\n/* fastint constants etc */\n#if defined(DUK_USE_FASTINT)\n#define DUK_FASTINT_MIN           (DUK_I64_CONSTANT(-0x800000000000))\n#define DUK_FASTINT_MAX           (DUK_I64_CONSTANT(0x7fffffffffff))\n#define DUK_FASTINT_BITS          48\n\nDUK_INTERNAL_DECL void duk_tval_set_number_chkfast_fast(duk_tval *tv, duk_double_t x);\nDUK_INTERNAL_DECL void duk_tval_set_number_chkfast_slow(duk_tval *tv, duk_double_t x);\n#endif\n\n#endif  /* DUK_TVAL_H_INCLUDED */\n/* #include duk_builtins.h */\n#line 1 \"duk_builtins.h\"\n/*\n *  Automatically generated by genbuiltins.py, do not edit!\n */\n\n#if !defined(DUK_BUILTINS_H_INCLUDED)\n#define DUK_BUILTINS_H_INCLUDED\n\n#if defined(DUK_USE_ROM_STRINGS)\n#error ROM support not enabled, rerun configure.py with --rom-support\n#else  /* DUK_USE_ROM_STRINGS */\n#define DUK_STRIDX_UC_UNDEFINED                                       0                              /* 'Undefined' */\n#define DUK_HEAP_STRING_UC_UNDEFINED(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_UNDEFINED)\n#define DUK_HTHREAD_STRING_UC_UNDEFINED(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_UNDEFINED)\n#define DUK_STRIDX_UC_NULL                                            1                              /* 'Null' */\n#define DUK_HEAP_STRING_UC_NULL(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_NULL)\n#define DUK_HTHREAD_STRING_UC_NULL(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_NULL)\n#define DUK_STRIDX_UC_SYMBOL                                          2                              /* 'Symbol' */\n#define DUK_HEAP_STRING_UC_SYMBOL(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_SYMBOL)\n#define DUK_HTHREAD_STRING_UC_SYMBOL(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_SYMBOL)\n#define DUK_STRIDX_UC_ARGUMENTS                                       3                              /* 'Arguments' */\n#define DUK_HEAP_STRING_UC_ARGUMENTS(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_ARGUMENTS)\n#define DUK_HTHREAD_STRING_UC_ARGUMENTS(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_ARGUMENTS)\n#define DUK_STRIDX_UC_OBJECT                                          4                              /* 'Object' */\n#define DUK_HEAP_STRING_UC_OBJECT(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_OBJECT)\n#define DUK_HTHREAD_STRING_UC_OBJECT(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_OBJECT)\n#define DUK_STRIDX_UC_FUNCTION                                        5                              /* 'Function' */\n#define DUK_HEAP_STRING_UC_FUNCTION(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_FUNCTION)\n#define DUK_HTHREAD_STRING_UC_FUNCTION(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_FUNCTION)\n#define DUK_STRIDX_ARRAY                                              6                              /* 'Array' */\n#define DUK_HEAP_STRING_ARRAY(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ARRAY)\n#define DUK_HTHREAD_STRING_ARRAY(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ARRAY)\n#define DUK_STRIDX_UC_STRING                                          7                              /* 'String' */\n#define DUK_HEAP_STRING_UC_STRING(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_STRING)\n#define DUK_HTHREAD_STRING_UC_STRING(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_STRING)\n#define DUK_STRIDX_UC_BOOLEAN                                         8                              /* 'Boolean' */\n#define DUK_HEAP_STRING_UC_BOOLEAN(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_BOOLEAN)\n#define DUK_HTHREAD_STRING_UC_BOOLEAN(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_BOOLEAN)\n#define DUK_STRIDX_UC_NUMBER                                          9                              /* 'Number' */\n#define DUK_HEAP_STRING_UC_NUMBER(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_NUMBER)\n#define DUK_HTHREAD_STRING_UC_NUMBER(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_NUMBER)\n#define DUK_STRIDX_DATE                                               10                             /* 'Date' */\n#define DUK_HEAP_STRING_DATE(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DATE)\n#define DUK_HTHREAD_STRING_DATE(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DATE)\n#define DUK_STRIDX_REG_EXP                                            11                             /* 'RegExp' */\n#define DUK_HEAP_STRING_REG_EXP(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_REG_EXP)\n#define DUK_HTHREAD_STRING_REG_EXP(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_REG_EXP)\n#define DUK_STRIDX_UC_ERROR                                           12                             /* 'Error' */\n#define DUK_HEAP_STRING_UC_ERROR(heap)                                DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_ERROR)\n#define DUK_HTHREAD_STRING_UC_ERROR(thr)                              DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_ERROR)\n#define DUK_STRIDX_MATH                                               13                             /* 'Math' */\n#define DUK_HEAP_STRING_MATH(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_MATH)\n#define DUK_HTHREAD_STRING_MATH(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_MATH)\n#define DUK_STRIDX_JSON                                               14                             /* 'JSON' */\n#define DUK_HEAP_STRING_JSON(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON)\n#define DUK_HTHREAD_STRING_JSON(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON)\n#define DUK_STRIDX_EMPTY_STRING                                       15                             /* '' */\n#define DUK_HEAP_STRING_EMPTY_STRING(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_EMPTY_STRING)\n#define DUK_HTHREAD_STRING_EMPTY_STRING(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_EMPTY_STRING)\n#define DUK_STRIDX_ARRAY_BUFFER                                       16                             /* 'ArrayBuffer' */\n#define DUK_HEAP_STRING_ARRAY_BUFFER(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ARRAY_BUFFER)\n#define DUK_HTHREAD_STRING_ARRAY_BUFFER(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ARRAY_BUFFER)\n#define DUK_STRIDX_DATA_VIEW                                          17                             /* 'DataView' */\n#define DUK_HEAP_STRING_DATA_VIEW(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DATA_VIEW)\n#define DUK_HTHREAD_STRING_DATA_VIEW(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DATA_VIEW)\n#define DUK_STRIDX_INT8_ARRAY                                         18                             /* 'Int8Array' */\n#define DUK_HEAP_STRING_INT8_ARRAY(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT8_ARRAY)\n#define DUK_HTHREAD_STRING_INT8_ARRAY(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT8_ARRAY)\n#define DUK_STRIDX_UINT8_ARRAY                                        19                             /* 'Uint8Array' */\n#define DUK_HEAP_STRING_UINT8_ARRAY(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UINT8_ARRAY)\n#define DUK_HTHREAD_STRING_UINT8_ARRAY(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UINT8_ARRAY)\n#define DUK_STRIDX_UINT8_CLAMPED_ARRAY                                20                             /* 'Uint8ClampedArray' */\n#define DUK_HEAP_STRING_UINT8_CLAMPED_ARRAY(heap)                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UINT8_CLAMPED_ARRAY)\n#define DUK_HTHREAD_STRING_UINT8_CLAMPED_ARRAY(thr)                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UINT8_CLAMPED_ARRAY)\n#define DUK_STRIDX_INT16_ARRAY                                        21                             /* 'Int16Array' */\n#define DUK_HEAP_STRING_INT16_ARRAY(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT16_ARRAY)\n#define DUK_HTHREAD_STRING_INT16_ARRAY(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT16_ARRAY)\n#define DUK_STRIDX_UINT16_ARRAY                                       22                             /* 'Uint16Array' */\n#define DUK_HEAP_STRING_UINT16_ARRAY(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UINT16_ARRAY)\n#define DUK_HTHREAD_STRING_UINT16_ARRAY(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UINT16_ARRAY)\n#define DUK_STRIDX_INT32_ARRAY                                        23                             /* 'Int32Array' */\n#define DUK_HEAP_STRING_INT32_ARRAY(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT32_ARRAY)\n#define DUK_HTHREAD_STRING_INT32_ARRAY(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT32_ARRAY)\n#define DUK_STRIDX_UINT32_ARRAY                                       24                             /* 'Uint32Array' */\n#define DUK_HEAP_STRING_UINT32_ARRAY(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UINT32_ARRAY)\n#define DUK_HTHREAD_STRING_UINT32_ARRAY(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UINT32_ARRAY)\n#define DUK_STRIDX_FLOAT32_ARRAY                                      25                             /* 'Float32Array' */\n#define DUK_HEAP_STRING_FLOAT32_ARRAY(heap)                           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FLOAT32_ARRAY)\n#define DUK_HTHREAD_STRING_FLOAT32_ARRAY(thr)                         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FLOAT32_ARRAY)\n#define DUK_STRIDX_FLOAT64_ARRAY                                      26                             /* 'Float64Array' */\n#define DUK_HEAP_STRING_FLOAT64_ARRAY(heap)                           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FLOAT64_ARRAY)\n#define DUK_HTHREAD_STRING_FLOAT64_ARRAY(thr)                         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FLOAT64_ARRAY)\n#define DUK_STRIDX_GLOBAL                                             27                             /* 'global' */\n#define DUK_HEAP_STRING_GLOBAL(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_GLOBAL)\n#define DUK_HTHREAD_STRING_GLOBAL(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_GLOBAL)\n#define DUK_STRIDX_OBJ_ENV                                            28                             /* 'ObjEnv' */\n#define DUK_HEAP_STRING_OBJ_ENV(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_OBJ_ENV)\n#define DUK_HTHREAD_STRING_OBJ_ENV(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_OBJ_ENV)\n#define DUK_STRIDX_DEC_ENV                                            29                             /* 'DecEnv' */\n#define DUK_HEAP_STRING_DEC_ENV(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DEC_ENV)\n#define DUK_HTHREAD_STRING_DEC_ENV(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DEC_ENV)\n#define DUK_STRIDX_UC_BUFFER                                          30                             /* 'Buffer' */\n#define DUK_HEAP_STRING_UC_BUFFER(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_BUFFER)\n#define DUK_HTHREAD_STRING_UC_BUFFER(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_BUFFER)\n#define DUK_STRIDX_UC_POINTER                                         31                             /* 'Pointer' */\n#define DUK_HEAP_STRING_UC_POINTER(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_POINTER)\n#define DUK_HTHREAD_STRING_UC_POINTER(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_POINTER)\n#define DUK_STRIDX_UC_THREAD                                          32                             /* 'Thread' */\n#define DUK_HEAP_STRING_UC_THREAD(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_THREAD)\n#define DUK_HTHREAD_STRING_UC_THREAD(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_THREAD)\n#define DUK_STRIDX_EVAL                                               33                             /* 'eval' */\n#define DUK_HEAP_STRING_EVAL(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_EVAL)\n#define DUK_HTHREAD_STRING_EVAL(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_EVAL)\n#define DUK_STRIDX_VALUE                                              34                             /* 'value' */\n#define DUK_HEAP_STRING_VALUE(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_VALUE)\n#define DUK_HTHREAD_STRING_VALUE(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_VALUE)\n#define DUK_STRIDX_WRITABLE                                           35                             /* 'writable' */\n#define DUK_HEAP_STRING_WRITABLE(heap)                                DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITABLE)\n#define DUK_HTHREAD_STRING_WRITABLE(thr)                              DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITABLE)\n#define DUK_STRIDX_CONFIGURABLE                                       36                             /* 'configurable' */\n#define DUK_HEAP_STRING_CONFIGURABLE(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CONFIGURABLE)\n#define DUK_HTHREAD_STRING_CONFIGURABLE(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CONFIGURABLE)\n#define DUK_STRIDX_ENUMERABLE                                         37                             /* 'enumerable' */\n#define DUK_HEAP_STRING_ENUMERABLE(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ENUMERABLE)\n#define DUK_HTHREAD_STRING_ENUMERABLE(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ENUMERABLE)\n#define DUK_STRIDX_JOIN                                               38                             /* 'join' */\n#define DUK_HEAP_STRING_JOIN(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JOIN)\n#define DUK_HTHREAD_STRING_JOIN(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JOIN)\n#define DUK_STRIDX_TO_LOCALE_STRING                                   39                             /* 'toLocaleString' */\n#define DUK_HEAP_STRING_TO_LOCALE_STRING(heap)                        DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TO_LOCALE_STRING)\n#define DUK_HTHREAD_STRING_TO_LOCALE_STRING(thr)                      DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TO_LOCALE_STRING)\n#define DUK_STRIDX_VALUE_OF                                           40                             /* 'valueOf' */\n#define DUK_HEAP_STRING_VALUE_OF(heap)                                DUK_HEAP_GET_STRING((heap),DUK_STRIDX_VALUE_OF)\n#define DUK_HTHREAD_STRING_VALUE_OF(thr)                              DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_VALUE_OF)\n#define DUK_STRIDX_TO_UTC_STRING                                      41                             /* 'toUTCString' */\n#define DUK_HEAP_STRING_TO_UTC_STRING(heap)                           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TO_UTC_STRING)\n#define DUK_HTHREAD_STRING_TO_UTC_STRING(thr)                         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TO_UTC_STRING)\n#define DUK_STRIDX_TO_ISO_STRING                                      42                             /* 'toISOString' */\n#define DUK_HEAP_STRING_TO_ISO_STRING(heap)                           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TO_ISO_STRING)\n#define DUK_HTHREAD_STRING_TO_ISO_STRING(thr)                         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TO_ISO_STRING)\n#define DUK_STRIDX_TO_GMT_STRING                                      43                             /* 'toGMTString' */\n#define DUK_HEAP_STRING_TO_GMT_STRING(heap)                           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TO_GMT_STRING)\n#define DUK_HTHREAD_STRING_TO_GMT_STRING(thr)                         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TO_GMT_STRING)\n#define DUK_STRIDX_SOURCE                                             44                             /* 'source' */\n#define DUK_HEAP_STRING_SOURCE(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SOURCE)\n#define DUK_HTHREAD_STRING_SOURCE(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SOURCE)\n#define DUK_STRIDX_IGNORE_CASE                                        45                             /* 'ignoreCase' */\n#define DUK_HEAP_STRING_IGNORE_CASE(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_IGNORE_CASE)\n#define DUK_HTHREAD_STRING_IGNORE_CASE(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_IGNORE_CASE)\n#define DUK_STRIDX_MULTILINE                                          46                             /* 'multiline' */\n#define DUK_HEAP_STRING_MULTILINE(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_MULTILINE)\n#define DUK_HTHREAD_STRING_MULTILINE(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_MULTILINE)\n#define DUK_STRIDX_LAST_INDEX                                         47                             /* 'lastIndex' */\n#define DUK_HEAP_STRING_LAST_INDEX(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LAST_INDEX)\n#define DUK_HTHREAD_STRING_LAST_INDEX(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LAST_INDEX)\n#define DUK_STRIDX_FLAGS                                              48                             /* 'flags' */\n#define DUK_HEAP_STRING_FLAGS(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FLAGS)\n#define DUK_HTHREAD_STRING_FLAGS(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FLAGS)\n#define DUK_STRIDX_INDEX                                              49                             /* 'index' */\n#define DUK_HEAP_STRING_INDEX(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INDEX)\n#define DUK_HTHREAD_STRING_INDEX(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INDEX)\n#define DUK_STRIDX_PROTOTYPE                                          50                             /* 'prototype' */\n#define DUK_HEAP_STRING_PROTOTYPE(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_PROTOTYPE)\n#define DUK_HTHREAD_STRING_PROTOTYPE(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_PROTOTYPE)\n#define DUK_STRIDX_CONSTRUCTOR                                        51                             /* 'constructor' */\n#define DUK_HEAP_STRING_CONSTRUCTOR(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CONSTRUCTOR)\n#define DUK_HTHREAD_STRING_CONSTRUCTOR(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CONSTRUCTOR)\n#define DUK_STRIDX_MESSAGE                                            52                             /* 'message' */\n#define DUK_HEAP_STRING_MESSAGE(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_MESSAGE)\n#define DUK_HTHREAD_STRING_MESSAGE(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_MESSAGE)\n#define DUK_STRIDX_LC_BOOLEAN                                         53                             /* 'boolean' */\n#define DUK_HEAP_STRING_LC_BOOLEAN(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_BOOLEAN)\n#define DUK_HTHREAD_STRING_LC_BOOLEAN(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_BOOLEAN)\n#define DUK_STRIDX_LC_NUMBER                                          54                             /* 'number' */\n#define DUK_HEAP_STRING_LC_NUMBER(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_NUMBER)\n#define DUK_HTHREAD_STRING_LC_NUMBER(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_NUMBER)\n#define DUK_STRIDX_LC_STRING                                          55                             /* 'string' */\n#define DUK_HEAP_STRING_LC_STRING(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_STRING)\n#define DUK_HTHREAD_STRING_LC_STRING(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_STRING)\n#define DUK_STRIDX_LC_SYMBOL                                          56                             /* 'symbol' */\n#define DUK_HEAP_STRING_LC_SYMBOL(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_SYMBOL)\n#define DUK_HTHREAD_STRING_LC_SYMBOL(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_SYMBOL)\n#define DUK_STRIDX_LC_OBJECT                                          57                             /* 'object' */\n#define DUK_HEAP_STRING_LC_OBJECT(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_OBJECT)\n#define DUK_HTHREAD_STRING_LC_OBJECT(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_OBJECT)\n#define DUK_STRIDX_LC_UNDEFINED                                       58                             /* 'undefined' */\n#define DUK_HEAP_STRING_LC_UNDEFINED(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_UNDEFINED)\n#define DUK_HTHREAD_STRING_LC_UNDEFINED(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_UNDEFINED)\n#define DUK_STRIDX_NAN                                                59                             /* 'NaN' */\n#define DUK_HEAP_STRING_NAN(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_NAN)\n#define DUK_HTHREAD_STRING_NAN(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_NAN)\n#define DUK_STRIDX_INFINITY                                           60                             /* 'Infinity' */\n#define DUK_HEAP_STRING_INFINITY(heap)                                DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INFINITY)\n#define DUK_HTHREAD_STRING_INFINITY(thr)                              DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INFINITY)\n#define DUK_STRIDX_MINUS_INFINITY                                     61                             /* '-Infinity' */\n#define DUK_HEAP_STRING_MINUS_INFINITY(heap)                          DUK_HEAP_GET_STRING((heap),DUK_STRIDX_MINUS_INFINITY)\n#define DUK_HTHREAD_STRING_MINUS_INFINITY(thr)                        DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_MINUS_INFINITY)\n#define DUK_STRIDX_MINUS_ZERO                                         62                             /* '-0' */\n#define DUK_HEAP_STRING_MINUS_ZERO(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_MINUS_ZERO)\n#define DUK_HTHREAD_STRING_MINUS_ZERO(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_MINUS_ZERO)\n#define DUK_STRIDX_COMMA                                              63                             /* ',' */\n#define DUK_HEAP_STRING_COMMA(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_COMMA)\n#define DUK_HTHREAD_STRING_COMMA(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_COMMA)\n#define DUK_STRIDX_NEWLINE_4SPACE                                     64                             /* '\\n    ' */\n#define DUK_HEAP_STRING_NEWLINE_4SPACE(heap)                          DUK_HEAP_GET_STRING((heap),DUK_STRIDX_NEWLINE_4SPACE)\n#define DUK_HTHREAD_STRING_NEWLINE_4SPACE(thr)                        DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_NEWLINE_4SPACE)\n#define DUK_STRIDX_BRACKETED_ELLIPSIS                                 65                             /* '[...]' */\n#define DUK_HEAP_STRING_BRACKETED_ELLIPSIS(heap)                      DUK_HEAP_GET_STRING((heap),DUK_STRIDX_BRACKETED_ELLIPSIS)\n#define DUK_HTHREAD_STRING_BRACKETED_ELLIPSIS(thr)                    DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_BRACKETED_ELLIPSIS)\n#define DUK_STRIDX_INVALID_DATE                                       66                             /* 'Invalid Date' */\n#define DUK_HEAP_STRING_INVALID_DATE(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INVALID_DATE)\n#define DUK_HTHREAD_STRING_INVALID_DATE(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INVALID_DATE)\n#define DUK_STRIDX_LC_ARGUMENTS                                       67                             /* 'arguments' */\n#define DUK_HEAP_STRING_LC_ARGUMENTS(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_ARGUMENTS)\n#define DUK_HTHREAD_STRING_LC_ARGUMENTS(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_ARGUMENTS)\n#define DUK_STRIDX_CALLEE                                             68                             /* 'callee' */\n#define DUK_HEAP_STRING_CALLEE(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CALLEE)\n#define DUK_HTHREAD_STRING_CALLEE(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CALLEE)\n#define DUK_STRIDX_CALLER                                             69                             /* 'caller' */\n#define DUK_HEAP_STRING_CALLER(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CALLER)\n#define DUK_HTHREAD_STRING_CALLER(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CALLER)\n#define DUK_STRIDX_APPLY                                              70                             /* 'apply' */\n#define DUK_HEAP_STRING_APPLY(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_APPLY)\n#define DUK_HTHREAD_STRING_APPLY(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_APPLY)\n#define DUK_STRIDX_CONSTRUCT                                          71                             /* 'construct' */\n#define DUK_HEAP_STRING_CONSTRUCT(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CONSTRUCT)\n#define DUK_HTHREAD_STRING_CONSTRUCT(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CONSTRUCT)\n#define DUK_STRIDX_DELETE_PROPERTY                                    72                             /* 'deleteProperty' */\n#define DUK_HEAP_STRING_DELETE_PROPERTY(heap)                         DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DELETE_PROPERTY)\n#define DUK_HTHREAD_STRING_DELETE_PROPERTY(thr)                       DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DELETE_PROPERTY)\n#define DUK_STRIDX_GET                                                73                             /* 'get' */\n#define DUK_HEAP_STRING_GET(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_GET)\n#define DUK_HTHREAD_STRING_GET(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_GET)\n#define DUK_STRIDX_HAS                                                74                             /* 'has' */\n#define DUK_HEAP_STRING_HAS(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_HAS)\n#define DUK_HTHREAD_STRING_HAS(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_HAS)\n#define DUK_STRIDX_OWN_KEYS                                           75                             /* 'ownKeys' */\n#define DUK_HEAP_STRING_OWN_KEYS(heap)                                DUK_HEAP_GET_STRING((heap),DUK_STRIDX_OWN_KEYS)\n#define DUK_HTHREAD_STRING_OWN_KEYS(thr)                              DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_OWN_KEYS)\n#define DUK_STRIDX_SET_PROTOTYPE_OF                                   76                             /* 'setPrototypeOf' */\n#define DUK_HEAP_STRING_SET_PROTOTYPE_OF(heap)                        DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SET_PROTOTYPE_OF)\n#define DUK_HTHREAD_STRING_SET_PROTOTYPE_OF(thr)                      DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SET_PROTOTYPE_OF)\n#define DUK_STRIDX___PROTO__                                          77                             /* '__proto__' */\n#define DUK_HEAP_STRING___PROTO__(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX___PROTO__)\n#define DUK_HTHREAD_STRING___PROTO__(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX___PROTO__)\n#define DUK_STRIDX_TO_STRING                                          78                             /* 'toString' */\n#define DUK_HEAP_STRING_TO_STRING(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TO_STRING)\n#define DUK_HTHREAD_STRING_TO_STRING(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TO_STRING)\n#define DUK_STRIDX_TO_JSON                                            79                             /* 'toJSON' */\n#define DUK_HEAP_STRING_TO_JSON(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TO_JSON)\n#define DUK_HTHREAD_STRING_TO_JSON(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TO_JSON)\n#define DUK_STRIDX_TYPE                                               80                             /* 'type' */\n#define DUK_HEAP_STRING_TYPE(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TYPE)\n#define DUK_HTHREAD_STRING_TYPE(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TYPE)\n#define DUK_STRIDX_DATA                                               81                             /* 'data' */\n#define DUK_HEAP_STRING_DATA(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DATA)\n#define DUK_HTHREAD_STRING_DATA(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DATA)\n#define DUK_STRIDX_LENGTH                                             82                             /* 'length' */\n#define DUK_HEAP_STRING_LENGTH(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LENGTH)\n#define DUK_HTHREAD_STRING_LENGTH(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LENGTH)\n#define DUK_STRIDX_SET                                                83                             /* 'set' */\n#define DUK_HEAP_STRING_SET(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SET)\n#define DUK_HTHREAD_STRING_SET(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SET)\n#define DUK_STRIDX_STACK                                              84                             /* 'stack' */\n#define DUK_HEAP_STRING_STACK(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_STACK)\n#define DUK_HTHREAD_STRING_STACK(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_STACK)\n#define DUK_STRIDX_PC                                                 85                             /* 'pc' */\n#define DUK_HEAP_STRING_PC(heap)                                      DUK_HEAP_GET_STRING((heap),DUK_STRIDX_PC)\n#define DUK_HTHREAD_STRING_PC(thr)                                    DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_PC)\n#define DUK_STRIDX_LINE_NUMBER                                        86                             /* 'lineNumber' */\n#define DUK_HEAP_STRING_LINE_NUMBER(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LINE_NUMBER)\n#define DUK_HTHREAD_STRING_LINE_NUMBER(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LINE_NUMBER)\n#define DUK_STRIDX_INT_TRACEDATA                                      87                             /* '\\x82Tracedata' */\n#define DUK_HEAP_STRING_INT_TRACEDATA(heap)                           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_TRACEDATA)\n#define DUK_HTHREAD_STRING_INT_TRACEDATA(thr)                         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_TRACEDATA)\n#define DUK_STRIDX_NAME                                               88                             /* 'name' */\n#define DUK_HEAP_STRING_NAME(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_NAME)\n#define DUK_HTHREAD_STRING_NAME(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_NAME)\n#define DUK_STRIDX_FILE_NAME                                          89                             /* 'fileName' */\n#define DUK_HEAP_STRING_FILE_NAME(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FILE_NAME)\n#define DUK_HTHREAD_STRING_FILE_NAME(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FILE_NAME)\n#define DUK_STRIDX_LC_POINTER                                         90                             /* 'pointer' */\n#define DUK_HEAP_STRING_LC_POINTER(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_POINTER)\n#define DUK_HTHREAD_STRING_LC_POINTER(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_POINTER)\n#define DUK_STRIDX_INT_TARGET                                         91                             /* '\\x82Target' */\n#define DUK_HEAP_STRING_INT_TARGET(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_TARGET)\n#define DUK_HTHREAD_STRING_INT_TARGET(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_TARGET)\n#define DUK_STRIDX_INT_NEXT                                           92                             /* '\\x82Next' */\n#define DUK_HEAP_STRING_INT_NEXT(heap)                                DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_NEXT)\n#define DUK_HTHREAD_STRING_INT_NEXT(thr)                              DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_NEXT)\n#define DUK_STRIDX_INT_BYTECODE                                       93                             /* '\\x82Bytecode' */\n#define DUK_HEAP_STRING_INT_BYTECODE(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_BYTECODE)\n#define DUK_HTHREAD_STRING_INT_BYTECODE(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_BYTECODE)\n#define DUK_STRIDX_INT_FORMALS                                        94                             /* '\\x82Formals' */\n#define DUK_HEAP_STRING_INT_FORMALS(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_FORMALS)\n#define DUK_HTHREAD_STRING_INT_FORMALS(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_FORMALS)\n#define DUK_STRIDX_INT_VARMAP                                         95                             /* '\\x82Varmap' */\n#define DUK_HEAP_STRING_INT_VARMAP(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_VARMAP)\n#define DUK_HTHREAD_STRING_INT_VARMAP(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_VARMAP)\n#define DUK_STRIDX_INT_SOURCE                                         96                             /* '\\x82Source' */\n#define DUK_HEAP_STRING_INT_SOURCE(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_SOURCE)\n#define DUK_HTHREAD_STRING_INT_SOURCE(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_SOURCE)\n#define DUK_STRIDX_INT_PC2LINE                                        97                             /* '\\x82Pc2line' */\n#define DUK_HEAP_STRING_INT_PC2LINE(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_PC2LINE)\n#define DUK_HTHREAD_STRING_INT_PC2LINE(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_PC2LINE)\n#define DUK_STRIDX_INT_MAP                                            98                             /* '\\x82Map' */\n#define DUK_HEAP_STRING_INT_MAP(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_MAP)\n#define DUK_HTHREAD_STRING_INT_MAP(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_MAP)\n#define DUK_STRIDX_INT_VARENV                                         99                             /* '\\x82Varenv' */\n#define DUK_HEAP_STRING_INT_VARENV(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_VARENV)\n#define DUK_HTHREAD_STRING_INT_VARENV(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_VARENV)\n#define DUK_STRIDX_INT_FINALIZER                                      100                            /* '\\x82Finalizer' */\n#define DUK_HEAP_STRING_INT_FINALIZER(heap)                           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_FINALIZER)\n#define DUK_HTHREAD_STRING_INT_FINALIZER(thr)                         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_FINALIZER)\n#define DUK_STRIDX_INT_VALUE                                          101                            /* '\\x82Value' */\n#define DUK_HEAP_STRING_INT_VALUE(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_VALUE)\n#define DUK_HTHREAD_STRING_INT_VALUE(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_VALUE)\n#define DUK_STRIDX_COMPILE                                            102                            /* 'compile' */\n#define DUK_HEAP_STRING_COMPILE(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_COMPILE)\n#define DUK_HTHREAD_STRING_COMPILE(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_COMPILE)\n#define DUK_STRIDX_INPUT                                              103                            /* 'input' */\n#define DUK_HEAP_STRING_INPUT(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INPUT)\n#define DUK_HTHREAD_STRING_INPUT(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INPUT)\n#define DUK_STRIDX_ERR_CREATE                                         104                            /* 'errCreate' */\n#define DUK_HEAP_STRING_ERR_CREATE(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ERR_CREATE)\n#define DUK_HTHREAD_STRING_ERR_CREATE(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ERR_CREATE)\n#define DUK_STRIDX_ERR_THROW                                          105                            /* 'errThrow' */\n#define DUK_HEAP_STRING_ERR_THROW(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ERR_THROW)\n#define DUK_HTHREAD_STRING_ERR_THROW(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ERR_THROW)\n#define DUK_STRIDX_ENV                                                106                            /* 'env' */\n#define DUK_HEAP_STRING_ENV(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ENV)\n#define DUK_HTHREAD_STRING_ENV(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ENV)\n#define DUK_STRIDX_HEX                                                107                            /* 'hex' */\n#define DUK_HEAP_STRING_HEX(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_HEX)\n#define DUK_HTHREAD_STRING_HEX(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_HEX)\n#define DUK_STRIDX_BASE64                                             108                            /* 'base64' */\n#define DUK_HEAP_STRING_BASE64(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_BASE64)\n#define DUK_HTHREAD_STRING_BASE64(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_BASE64)\n#define DUK_STRIDX_JX                                                 109                            /* 'jx' */\n#define DUK_HEAP_STRING_JX(heap)                                      DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JX)\n#define DUK_HTHREAD_STRING_JX(thr)                                    DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JX)\n#define DUK_STRIDX_JC                                                 110                            /* 'jc' */\n#define DUK_HEAP_STRING_JC(heap)                                      DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JC)\n#define DUK_HTHREAD_STRING_JC(thr)                                    DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JC)\n#define DUK_STRIDX_JSON_EXT_UNDEFINED                                 111                            /* '{\"_undef\":true}' */\n#define DUK_HEAP_STRING_JSON_EXT_UNDEFINED(heap)                      DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON_EXT_UNDEFINED)\n#define DUK_HTHREAD_STRING_JSON_EXT_UNDEFINED(thr)                    DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON_EXT_UNDEFINED)\n#define DUK_STRIDX_JSON_EXT_NAN                                       112                            /* '{\"_nan\":true}' */\n#define DUK_HEAP_STRING_JSON_EXT_NAN(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON_EXT_NAN)\n#define DUK_HTHREAD_STRING_JSON_EXT_NAN(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON_EXT_NAN)\n#define DUK_STRIDX_JSON_EXT_POSINF                                    113                            /* '{\"_inf\":true}' */\n#define DUK_HEAP_STRING_JSON_EXT_POSINF(heap)                         DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON_EXT_POSINF)\n#define DUK_HTHREAD_STRING_JSON_EXT_POSINF(thr)                       DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON_EXT_POSINF)\n#define DUK_STRIDX_JSON_EXT_NEGINF                                    114                            /* '{\"_ninf\":true}' */\n#define DUK_HEAP_STRING_JSON_EXT_NEGINF(heap)                         DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON_EXT_NEGINF)\n#define DUK_HTHREAD_STRING_JSON_EXT_NEGINF(thr)                       DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON_EXT_NEGINF)\n#define DUK_STRIDX_JSON_EXT_FUNCTION1                                 115                            /* '{\"_func\":true}' */\n#define DUK_HEAP_STRING_JSON_EXT_FUNCTION1(heap)                      DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON_EXT_FUNCTION1)\n#define DUK_HTHREAD_STRING_JSON_EXT_FUNCTION1(thr)                    DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON_EXT_FUNCTION1)\n#define DUK_STRIDX_JSON_EXT_FUNCTION2                                 116                            /* '{_func:true}' */\n#define DUK_HEAP_STRING_JSON_EXT_FUNCTION2(heap)                      DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON_EXT_FUNCTION2)\n#define DUK_HTHREAD_STRING_JSON_EXT_FUNCTION2(thr)                    DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON_EXT_FUNCTION2)\n#define DUK_STRIDX_BREAK                                              117                            /* 'break' */\n#define DUK_HEAP_STRING_BREAK(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_BREAK)\n#define DUK_HTHREAD_STRING_BREAK(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_BREAK)\n#define DUK_STRIDX_CASE                                               118                            /* 'case' */\n#define DUK_HEAP_STRING_CASE(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CASE)\n#define DUK_HTHREAD_STRING_CASE(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CASE)\n#define DUK_STRIDX_CATCH                                              119                            /* 'catch' */\n#define DUK_HEAP_STRING_CATCH(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CATCH)\n#define DUK_HTHREAD_STRING_CATCH(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CATCH)\n#define DUK_STRIDX_CONTINUE                                           120                            /* 'continue' */\n#define DUK_HEAP_STRING_CONTINUE(heap)                                DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CONTINUE)\n#define DUK_HTHREAD_STRING_CONTINUE(thr)                              DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CONTINUE)\n#define DUK_STRIDX_DEBUGGER                                           121                            /* 'debugger' */\n#define DUK_HEAP_STRING_DEBUGGER(heap)                                DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DEBUGGER)\n#define DUK_HTHREAD_STRING_DEBUGGER(thr)                              DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DEBUGGER)\n#define DUK_STRIDX_DEFAULT                                            122                            /* 'default' */\n#define DUK_HEAP_STRING_DEFAULT(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DEFAULT)\n#define DUK_HTHREAD_STRING_DEFAULT(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DEFAULT)\n#define DUK_STRIDX_DELETE                                             123                            /* 'delete' */\n#define DUK_HEAP_STRING_DELETE(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DELETE)\n#define DUK_HTHREAD_STRING_DELETE(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DELETE)\n#define DUK_STRIDX_DO                                                 124                            /* 'do' */\n#define DUK_HEAP_STRING_DO(heap)                                      DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DO)\n#define DUK_HTHREAD_STRING_DO(thr)                                    DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DO)\n#define DUK_STRIDX_ELSE                                               125                            /* 'else' */\n#define DUK_HEAP_STRING_ELSE(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ELSE)\n#define DUK_HTHREAD_STRING_ELSE(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ELSE)\n#define DUK_STRIDX_FINALLY                                            126                            /* 'finally' */\n#define DUK_HEAP_STRING_FINALLY(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FINALLY)\n#define DUK_HTHREAD_STRING_FINALLY(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FINALLY)\n#define DUK_STRIDX_FOR                                                127                            /* 'for' */\n#define DUK_HEAP_STRING_FOR(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FOR)\n#define DUK_HTHREAD_STRING_FOR(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FOR)\n#define DUK_STRIDX_LC_FUNCTION                                        128                            /* 'function' */\n#define DUK_HEAP_STRING_LC_FUNCTION(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_FUNCTION)\n#define DUK_HTHREAD_STRING_LC_FUNCTION(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_FUNCTION)\n#define DUK_STRIDX_IF                                                 129                            /* 'if' */\n#define DUK_HEAP_STRING_IF(heap)                                      DUK_HEAP_GET_STRING((heap),DUK_STRIDX_IF)\n#define DUK_HTHREAD_STRING_IF(thr)                                    DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_IF)\n#define DUK_STRIDX_IN                                                 130                            /* 'in' */\n#define DUK_HEAP_STRING_IN(heap)                                      DUK_HEAP_GET_STRING((heap),DUK_STRIDX_IN)\n#define DUK_HTHREAD_STRING_IN(thr)                                    DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_IN)\n#define DUK_STRIDX_INSTANCEOF                                         131                            /* 'instanceof' */\n#define DUK_HEAP_STRING_INSTANCEOF(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INSTANCEOF)\n#define DUK_HTHREAD_STRING_INSTANCEOF(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INSTANCEOF)\n#define DUK_STRIDX_NEW                                                132                            /* 'new' */\n#define DUK_HEAP_STRING_NEW(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_NEW)\n#define DUK_HTHREAD_STRING_NEW(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_NEW)\n#define DUK_STRIDX_RETURN                                             133                            /* 'return' */\n#define DUK_HEAP_STRING_RETURN(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_RETURN)\n#define DUK_HTHREAD_STRING_RETURN(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_RETURN)\n#define DUK_STRIDX_SWITCH                                             134                            /* 'switch' */\n#define DUK_HEAP_STRING_SWITCH(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SWITCH)\n#define DUK_HTHREAD_STRING_SWITCH(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SWITCH)\n#define DUK_STRIDX_THIS                                               135                            /* 'this' */\n#define DUK_HEAP_STRING_THIS(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_THIS)\n#define DUK_HTHREAD_STRING_THIS(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_THIS)\n#define DUK_STRIDX_THROW                                              136                            /* 'throw' */\n#define DUK_HEAP_STRING_THROW(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_THROW)\n#define DUK_HTHREAD_STRING_THROW(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_THROW)\n#define DUK_STRIDX_TRY                                                137                            /* 'try' */\n#define DUK_HEAP_STRING_TRY(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TRY)\n#define DUK_HTHREAD_STRING_TRY(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TRY)\n#define DUK_STRIDX_TYPEOF                                             138                            /* 'typeof' */\n#define DUK_HEAP_STRING_TYPEOF(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TYPEOF)\n#define DUK_HTHREAD_STRING_TYPEOF(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TYPEOF)\n#define DUK_STRIDX_VAR                                                139                            /* 'var' */\n#define DUK_HEAP_STRING_VAR(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_VAR)\n#define DUK_HTHREAD_STRING_VAR(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_VAR)\n#define DUK_STRIDX_CONST                                              140                            /* 'const' */\n#define DUK_HEAP_STRING_CONST(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CONST)\n#define DUK_HTHREAD_STRING_CONST(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CONST)\n#define DUK_STRIDX_VOID                                               141                            /* 'void' */\n#define DUK_HEAP_STRING_VOID(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_VOID)\n#define DUK_HTHREAD_STRING_VOID(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_VOID)\n#define DUK_STRIDX_WHILE                                              142                            /* 'while' */\n#define DUK_HEAP_STRING_WHILE(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WHILE)\n#define DUK_HTHREAD_STRING_WHILE(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WHILE)\n#define DUK_STRIDX_WITH                                               143                            /* 'with' */\n#define DUK_HEAP_STRING_WITH(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WITH)\n#define DUK_HTHREAD_STRING_WITH(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WITH)\n#define DUK_STRIDX_CLASS                                              144                            /* 'class' */\n#define DUK_HEAP_STRING_CLASS(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CLASS)\n#define DUK_HTHREAD_STRING_CLASS(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CLASS)\n#define DUK_STRIDX_ENUM                                               145                            /* 'enum' */\n#define DUK_HEAP_STRING_ENUM(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ENUM)\n#define DUK_HTHREAD_STRING_ENUM(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ENUM)\n#define DUK_STRIDX_EXPORT                                             146                            /* 'export' */\n#define DUK_HEAP_STRING_EXPORT(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_EXPORT)\n#define DUK_HTHREAD_STRING_EXPORT(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_EXPORT)\n#define DUK_STRIDX_EXTENDS                                            147                            /* 'extends' */\n#define DUK_HEAP_STRING_EXTENDS(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_EXTENDS)\n#define DUK_HTHREAD_STRING_EXTENDS(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_EXTENDS)\n#define DUK_STRIDX_IMPORT                                             148                            /* 'import' */\n#define DUK_HEAP_STRING_IMPORT(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_IMPORT)\n#define DUK_HTHREAD_STRING_IMPORT(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_IMPORT)\n#define DUK_STRIDX_SUPER                                              149                            /* 'super' */\n#define DUK_HEAP_STRING_SUPER(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SUPER)\n#define DUK_HTHREAD_STRING_SUPER(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SUPER)\n#define DUK_STRIDX_LC_NULL                                            150                            /* 'null' */\n#define DUK_HEAP_STRING_LC_NULL(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_NULL)\n#define DUK_HTHREAD_STRING_LC_NULL(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_NULL)\n#define DUK_STRIDX_TRUE                                               151                            /* 'true' */\n#define DUK_HEAP_STRING_TRUE(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TRUE)\n#define DUK_HTHREAD_STRING_TRUE(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TRUE)\n#define DUK_STRIDX_FALSE                                              152                            /* 'false' */\n#define DUK_HEAP_STRING_FALSE(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FALSE)\n#define DUK_HTHREAD_STRING_FALSE(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FALSE)\n#define DUK_STRIDX_IMPLEMENTS                                         153                            /* 'implements' */\n#define DUK_HEAP_STRING_IMPLEMENTS(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_IMPLEMENTS)\n#define DUK_HTHREAD_STRING_IMPLEMENTS(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_IMPLEMENTS)\n#define DUK_STRIDX_INTERFACE                                          154                            /* 'interface' */\n#define DUK_HEAP_STRING_INTERFACE(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INTERFACE)\n#define DUK_HTHREAD_STRING_INTERFACE(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INTERFACE)\n#define DUK_STRIDX_LET                                                155                            /* 'let' */\n#define DUK_HEAP_STRING_LET(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LET)\n#define DUK_HTHREAD_STRING_LET(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LET)\n#define DUK_STRIDX_PACKAGE                                            156                            /* 'package' */\n#define DUK_HEAP_STRING_PACKAGE(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_PACKAGE)\n#define DUK_HTHREAD_STRING_PACKAGE(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_PACKAGE)\n#define DUK_STRIDX_PRIVATE                                            157                            /* 'private' */\n#define DUK_HEAP_STRING_PRIVATE(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_PRIVATE)\n#define DUK_HTHREAD_STRING_PRIVATE(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_PRIVATE)\n#define DUK_STRIDX_PROTECTED                                          158                            /* 'protected' */\n#define DUK_HEAP_STRING_PROTECTED(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_PROTECTED)\n#define DUK_HTHREAD_STRING_PROTECTED(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_PROTECTED)\n#define DUK_STRIDX_PUBLIC                                             159                            /* 'public' */\n#define DUK_HEAP_STRING_PUBLIC(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_PUBLIC)\n#define DUK_HTHREAD_STRING_PUBLIC(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_PUBLIC)\n#define DUK_STRIDX_STATIC                                             160                            /* 'static' */\n#define DUK_HEAP_STRING_STATIC(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_STATIC)\n#define DUK_HTHREAD_STRING_STATIC(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_STATIC)\n#define DUK_STRIDX_YIELD                                              161                            /* 'yield' */\n#define DUK_HEAP_STRING_YIELD(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_YIELD)\n#define DUK_HTHREAD_STRING_YIELD(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_YIELD)\n\n#define DUK_HEAP_NUM_STRINGS                                          162\n#define DUK_STRIDX_START_RESERVED                                     117\n#define DUK_STRIDX_START_STRICT_RESERVED                              153\n#define DUK_STRIDX_END_RESERVED                                       162                            /* exclusive endpoint */\n\n/* To convert a heap stridx to a token number, subtract\n * DUK_STRIDX_START_RESERVED and add DUK_TOK_START_RESERVED.\n */\n#if !defined(DUK_SINGLE_FILE)\nDUK_INTERNAL_DECL const duk_uint8_t duk_strings_data[892];\n#endif  /* !DUK_SINGLE_FILE */\n#define DUK_STRDATA_MAX_STRLEN                                        17\n#define DUK_STRDATA_DATA_LENGTH                                       892\n#endif  /* DUK_USE_ROM_STRINGS */\n\n#if defined(DUK_USE_ROM_OBJECTS)\n#error RAM support not enabled, rerun configure.py with --ram-support\n#else  /* DUK_USE_ROM_OBJECTS */\nDUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_function_constructor(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_array_constructor(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_string_constructor(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_boolean_constructor(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_number_constructor(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_date_constructor(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_regexp_constructor(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_error_constructor_shared(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_type_error_thrower(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_thread_constructor(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_pointer_constructor(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_proxy_constructor(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_arraybuffer_constructor(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_dataview_constructor(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_typedarray_constructor(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_constructor(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_textencoder_constructor(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_textdecoder_constructor(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_eval(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_parse_int(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_parse_float(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_is_nan(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_is_finite(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_decode_uri(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_decode_uri_component(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_encode_uri(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_encode_uri_component(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_escape(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_unescape(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_object_getprototype_shared(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_object_setprototype_shared(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_get_own_property_descriptor(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_keys_shared(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_assign(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_create(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_define_property(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_define_properties(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_seal_freeze_shared(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_prevent_extensions(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_is_sealed_frozen_shared(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_is_extensible(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_is(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_to_string(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_to_locale_string(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_value_of(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_has_own_property(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_is_prototype_of(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_property_is_enumerable(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_defineaccessor(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_lookupaccessor(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype_to_string(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype_apply(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype_call(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype_bind(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_native_function_length(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_native_function_name(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_array_constructor_is_array(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_to_string(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_join_shared(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_concat(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_pop(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_push(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_reverse(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_shift(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_slice(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_sort(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_splice(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_unshift(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_indexof_shared(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_iter_shared(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_reduce_shared(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_string_constructor_from_char_code(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_string_constructor_from_code_point(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_to_string(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_char_at(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_char_code_at(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_concat(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_indexof_shared(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_locale_compare(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_match(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_replace(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_search(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_slice(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_split(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_substring(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_caseconv_shared(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_trim(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_repeat(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_startswith_endswith(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_includes(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_substr(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_boolean_prototype_tostring_shared(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_number_prototype_to_string(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_number_prototype_to_locale_string(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_number_prototype_value_of(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_number_prototype_to_fixed(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_number_prototype_to_exponential(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_number_prototype_to_precision(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_date_constructor_parse(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_date_constructor_utc(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_date_constructor_now(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_tostring_shared(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_to_json(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_value_of(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_get_shared(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_get_timezone_offset(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_set_time(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_set_shared(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_regexp_prototype_exec(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_regexp_prototype_test(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_regexp_prototype_tostring(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_regexp_prototype_flags(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_regexp_prototype_shared_getter(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_stack_getter(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_stack_setter(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_filename_getter(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_filename_setter(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_linenumber_getter(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_linenumber_setter(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_to_string(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_onearg_shared(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_twoarg_shared(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_clz32(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_hypot(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_imul(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_max(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_min(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_random(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_sign(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_json_object_parse(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_json_object_stringify(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_info(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_act(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_gc(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_fin(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_enc(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_dec(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_compact(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_thread_yield(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_thread_resume(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_thread_current(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_pointer_prototype_tostring_shared(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_reflect_apply(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_reflect_construct(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_reflect_object_delete_property(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_reflect_object_get(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_reflect_object_has(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_reflect_object_set(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_arraybuffer_isview(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_typedarray_bytelength_getter(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_buffer_slice_shared(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_typedarray_byteoffset_getter(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_typedarray_buffer_getter(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_buffer_readfield(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_buffer_writefield(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_typedarray_set(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_uint8array_allocplain(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_uint8array_plainof(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_concat(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_is_encoding(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_is_buffer(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_byte_length(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_buffer_compare_shared(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_tostring(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_tojson(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_fill(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_copy(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_write(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_textencoder_prototype_encoding_getter(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_textencoder_prototype_encode(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_textdecoder_prototype_shared_getter(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_textdecoder_prototype_decode(duk_context *ctx);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_performance_now(duk_context *ctx);\n#if !defined(DUK_SINGLE_FILE)\nDUK_INTERNAL_DECL const duk_c_function duk_bi_native_functions[176];\n#endif  /* !DUK_SINGLE_FILE */\n#define DUK_BIDX_GLOBAL                                               0\n#define DUK_BIDX_GLOBAL_ENV                                           1\n#define DUK_BIDX_OBJECT_CONSTRUCTOR                                   2\n#define DUK_BIDX_OBJECT_PROTOTYPE                                     3\n#define DUK_BIDX_FUNCTION_CONSTRUCTOR                                 4\n#define DUK_BIDX_FUNCTION_PROTOTYPE                                   5\n#define DUK_BIDX_NATIVE_FUNCTION_PROTOTYPE                            6\n#define DUK_BIDX_ARRAY_CONSTRUCTOR                                    7\n#define DUK_BIDX_ARRAY_PROTOTYPE                                      8\n#define DUK_BIDX_STRING_CONSTRUCTOR                                   9\n#define DUK_BIDX_STRING_PROTOTYPE                                     10\n#define DUK_BIDX_BOOLEAN_CONSTRUCTOR                                  11\n#define DUK_BIDX_BOOLEAN_PROTOTYPE                                    12\n#define DUK_BIDX_NUMBER_CONSTRUCTOR                                   13\n#define DUK_BIDX_NUMBER_PROTOTYPE                                     14\n#define DUK_BIDX_DATE_CONSTRUCTOR                                     15\n#define DUK_BIDX_DATE_PROTOTYPE                                       16\n#define DUK_BIDX_REGEXP_CONSTRUCTOR                                   17\n#define DUK_BIDX_REGEXP_PROTOTYPE                                     18\n#define DUK_BIDX_ERROR_CONSTRUCTOR                                    19\n#define DUK_BIDX_ERROR_PROTOTYPE                                      20\n#define DUK_BIDX_EVAL_ERROR_CONSTRUCTOR                               21\n#define DUK_BIDX_EVAL_ERROR_PROTOTYPE                                 22\n#define DUK_BIDX_RANGE_ERROR_CONSTRUCTOR                              23\n#define DUK_BIDX_RANGE_ERROR_PROTOTYPE                                24\n#define DUK_BIDX_REFERENCE_ERROR_CONSTRUCTOR                          25\n#define DUK_BIDX_REFERENCE_ERROR_PROTOTYPE                            26\n#define DUK_BIDX_SYNTAX_ERROR_CONSTRUCTOR                             27\n#define DUK_BIDX_SYNTAX_ERROR_PROTOTYPE                               28\n#define DUK_BIDX_TYPE_ERROR_CONSTRUCTOR                               29\n#define DUK_BIDX_TYPE_ERROR_PROTOTYPE                                 30\n#define DUK_BIDX_URI_ERROR_CONSTRUCTOR                                31\n#define DUK_BIDX_URI_ERROR_PROTOTYPE                                  32\n#define DUK_BIDX_TYPE_ERROR_THROWER                                   33\n#define DUK_BIDX_DUKTAPE                                              34\n#define DUK_BIDX_THREAD_PROTOTYPE                                     35\n#define DUK_BIDX_POINTER_PROTOTYPE                                    36\n#define DUK_BIDX_DOUBLE_ERROR                                         37\n#define DUK_BIDX_SYMBOL_PROTOTYPE                                     38\n#define DUK_BIDX_ARRAYBUFFER_PROTOTYPE                                39\n#define DUK_BIDX_DATAVIEW_PROTOTYPE                                   40\n#define DUK_BIDX_INT8ARRAY_PROTOTYPE                                  41\n#define DUK_BIDX_UINT8ARRAY_PROTOTYPE                                 42\n#define DUK_BIDX_UINT8CLAMPEDARRAY_PROTOTYPE                          43\n#define DUK_BIDX_INT16ARRAY_PROTOTYPE                                 44\n#define DUK_BIDX_UINT16ARRAY_PROTOTYPE                                45\n#define DUK_BIDX_INT32ARRAY_PROTOTYPE                                 46\n#define DUK_BIDX_UINT32ARRAY_PROTOTYPE                                47\n#define DUK_BIDX_FLOAT32ARRAY_PROTOTYPE                               48\n#define DUK_BIDX_FLOAT64ARRAY_PROTOTYPE                               49\n#define DUK_BIDX_NODEJS_BUFFER_PROTOTYPE                              50\n#define DUK_NUM_BUILTINS                                              51\n#define DUK_NUM_BIDX_BUILTINS                                         51\n#define DUK_NUM_ALL_BUILTINS                                          76\n#if defined(DUK_USE_DOUBLE_LE)\n#if !defined(DUK_SINGLE_FILE)\nDUK_INTERNAL_DECL const duk_uint8_t duk_builtins_data[3972];\n#endif  /* !DUK_SINGLE_FILE */\n#define DUK_BUILTINS_DATA_LENGTH                                      3972\n#elif defined(DUK_USE_DOUBLE_BE)\n#if !defined(DUK_SINGLE_FILE)\nDUK_INTERNAL_DECL const duk_uint8_t duk_builtins_data[3972];\n#endif  /* !DUK_SINGLE_FILE */\n#define DUK_BUILTINS_DATA_LENGTH                                      3972\n#elif defined(DUK_USE_DOUBLE_ME)\n#if !defined(DUK_SINGLE_FILE)\nDUK_INTERNAL_DECL const duk_uint8_t duk_builtins_data[3972];\n#endif  /* !DUK_SINGLE_FILE */\n#define DUK_BUILTINS_DATA_LENGTH                                      3972\n#else\n#error invalid endianness defines\n#endif\n#endif  /* DUK_USE_ROM_OBJECTS */\n#endif  /* DUK_BUILTINS_H_INCLUDED */\n#line 51 \"duk_internal.h\"\n\n/* #include duk_util.h */\n#line 1 \"duk_util.h\"\n/*\n *  Utilities\n */\n\n#if !defined(DUK_UTIL_H_INCLUDED)\n#define DUK_UTIL_H_INCLUDED\n\n#if defined(DUK_USE_GET_RANDOM_DOUBLE)\n#define DUK_UTIL_GET_RANDOM_DOUBLE(thr) DUK_USE_GET_RANDOM_DOUBLE((thr)->heap_udata)\n#else\n#define DUK_UTIL_GET_RANDOM_DOUBLE(thr) duk_util_tinyrandom_get_double(thr)\n#endif\n\n/*\n *  Some useful constants\n */\n\n#define DUK_DOUBLE_2TO32     4294967296.0\n#define DUK_DOUBLE_2TO31     2147483648.0\n#define DUK_DOUBLE_LOG2E     1.4426950408889634\n#define DUK_DOUBLE_LOG10E    0.4342944819032518\n\n/*\n *  Endian conversion\n */\n\n#if defined(DUK_USE_INTEGER_LE)\n#define DUK_HTON32(x) DUK_BSWAP32((x))\n#define DUK_NTOH32(x) DUK_BSWAP32((x))\n#define DUK_HTON16(x) DUK_BSWAP16((x))\n#define DUK_NTOH16(x) DUK_BSWAP16((x))\n#elif defined(DUK_USE_INTEGER_BE)\n#define DUK_HTON32(x) (x)\n#define DUK_NTOH32(x) (x)\n#define DUK_HTON16(x) (x)\n#define DUK_NTOH16(x) (x)\n#else\n#error internal error, endianness defines broken\n#endif\n\n/*\n *  Bitstream decoder\n */\n\nstruct duk_bitdecoder_ctx {\n\tconst duk_uint8_t *data;\n\tduk_size_t offset;\n\tduk_size_t length;\n\tduk_uint32_t currval;\n\tduk_small_int_t currbits;\n};\n\n#define DUK_BD_BITPACKED_STRING_MAXLEN 256\n\n/*\n *  Bitstream encoder\n */\n\nstruct duk_bitencoder_ctx {\n\tduk_uint8_t *data;\n\tduk_size_t offset;\n\tduk_size_t length;\n\tduk_uint32_t currval;\n\tduk_small_int_t currbits;\n\tduk_small_int_t truncated;\n};\n\n/*\n *  Raw write/read macros for big endian, unaligned basic values.\n *  Caller ensures there's enough space.  The macros update the pointer\n *  argument automatically on resizes.  The idiom seems a bit odd, but\n *  leads to compact code.\n */\n\n#define DUK_RAW_WRITE_U8(ptr,val)  do { \\\n\t\t*(ptr)++ = (duk_uint8_t) (val); \\\n\t} while (0)\n#define DUK_RAW_WRITE_U16_BE(ptr,val) duk_raw_write_u16_be(&(ptr), (duk_uint16_t) (val))\n#define DUK_RAW_WRITE_U32_BE(ptr,val) duk_raw_write_u32_be(&(ptr), (duk_uint32_t) (val))\n#define DUK_RAW_WRITE_DOUBLE_BE(ptr,val) duk_raw_write_double_be(&(ptr), (duk_double_t) (val))\n#define DUK_RAW_WRITE_XUTF8(ptr,val)  do { \\\n\t\t/* 'ptr' is evaluated both as LHS and RHS. */ \\\n\t\tduk_uint8_t *duk__ptr; \\\n\t\tduk_small_int_t duk__len; \\\n\t\tduk__ptr = (duk_uint8_t *) (ptr); \\\n\t\tduk__len = duk_unicode_encode_xutf8((duk_ucodepoint_t) (val), duk__ptr); \\\n\t\tduk__ptr += duk__len; \\\n\t\t(ptr) = duk__ptr; \\\n\t} while (0)\n#define DUK_RAW_WRITE_CESU8(ptr,val)  do { \\\n\t\t/* 'ptr' is evaluated both as LHS and RHS. */ \\\n\t\tduk_uint8_t *duk__ptr; \\\n\t\tduk_small_int_t duk__len; \\\n\t\tduk__ptr = (duk_uint8_t *) (ptr); \\\n\t\tduk__len = duk_unicode_encode_cesu8((duk_ucodepoint_t) (val), duk__ptr); \\\n\t\tduk__ptr += duk__len; \\\n\t\t(ptr) = duk__ptr; \\\n\t} while (0)\n\n#define DUK_RAW_READ_U8(ptr) ((duk_uint8_t) (*(ptr)++))\n#define DUK_RAW_READ_U16_BE(ptr) duk_raw_read_u16_be(&(ptr));\n#define DUK_RAW_READ_U32_BE(ptr) duk_raw_read_u32_be(&(ptr));\n#define DUK_RAW_READ_DOUBLE_BE(ptr) duk_raw_read_double_be(&(ptr));\n\n/*\n *  Buffer writer (dynamic buffer only)\n *\n *  Helper for writing to a dynamic buffer with a concept of a \"slack\" area\n *  to reduce resizes.  You can ensure there is enough space beforehand and\n *  then write for a while without further checks, relying on a stable data\n *  pointer.  Slack handling is automatic so call sites only indicate how\n *  much data they need right now.\n *\n *  There are several ways to write using bufwriter.  The best approach\n *  depends mainly on how much performance matters over code footprint.\n *  The key issues are (1) ensuring there is space and (2) keeping the\n *  pointers consistent.  Fast code should ensure space for multiple writes\n *  with one ensure call.  Fastest inner loop code can temporarily borrow\n *  the 'p' pointer but must write it back eventually.\n *\n *  Be careful to ensure all macro arguments (other than static pointers like\n *  'thr' and 'bw_ctx') are evaluated exactly once, using temporaries if\n *  necessary (if that's not possible, there should be a note near the macro).\n *  Buffer write arguments often contain arithmetic etc so this is\n *  particularly important here.\n */\n\n/* XXX: Migrate bufwriter and other read/write helpers to its own header? */\n\nstruct duk_bufwriter_ctx {\n\tduk_uint8_t *p;\n\tduk_uint8_t *p_base;\n\tduk_uint8_t *p_limit;\n\tduk_hbuffer_dynamic *buf;\n};\n\n#if defined(DUK_USE_PREFER_SIZE)\n#define DUK_BW_SLACK_ADD           64\n#define DUK_BW_SLACK_SHIFT         4    /* 2^4 -> 1/16 = 6.25% slack */\n#else\n#define DUK_BW_SLACK_ADD           64\n#define DUK_BW_SLACK_SHIFT         2    /* 2^2 -> 1/4 = 25% slack */\n#endif\n\n/* Initialization and finalization (compaction), converting to other types. */\n\n#define DUK_BW_INIT_PUSHBUF(thr,bw_ctx,sz) do { \\\n\t\tduk_bw_init_pushbuf((thr), (bw_ctx), (sz)); \\\n\t} while (0)\n#define DUK_BW_INIT_WITHBUF(thr,bw_ctx,buf) do { \\\n\t\tduk_bw_init((thr), (bw_ctx), (buf)); \\\n\t} while (0)\n#define DUK_BW_COMPACT(thr,bw_ctx) do { \\\n\t\t/* Make underlying buffer compact to match DUK_BW_GET_SIZE(). */ \\\n\t\tduk_bw_compact((thr), (bw_ctx)); \\\n\t} while (0)\n#define DUK_BW_PUSH_AS_STRING(thr,bw_ctx) do { \\\n\t\tduk_push_lstring((thr), \\\n\t\t                 (const char *) (bw_ctx)->p_base, \\\n\t\t                 (duk_size_t) ((bw_ctx)->p - (bw_ctx)->p_base)); \\\n\t} while (0)\n/* Pointers may be NULL for a while when 'buf' size is zero and before any\n * ENSURE calls have been made.  Once an ENSURE has been made, the pointers\n * are required to be non-NULL so that it's always valid to use memcpy() and\n * memmove(), even for zero size.\n */\n#define DUK_BW_ASSERT_VALID_EXPR(thr,bw_ctx) \\\n\tDUK_ASSERT_EXPR((bw_ctx) != NULL && \\\n\t                (bw_ctx)->buf != NULL && \\\n\t\t\t((DUK_HBUFFER_DYNAMIC_GET_SIZE((bw_ctx)->buf) == 0) || \\\n\t\t\t\t((bw_ctx)->p != NULL && \\\n\t\t                 (bw_ctx)->p_base != NULL && \\\n\t\t                 (bw_ctx)->p_limit != NULL && \\\n\t\t                 (bw_ctx)->p_limit >= (bw_ctx)->p_base && \\\n\t\t                 (bw_ctx)->p >= (bw_ctx)->p_base && \\\n\t\t                 (bw_ctx)->p <= (bw_ctx)->p_limit)))\n#define DUK_BW_ASSERT_VALID(thr,bw_ctx) do { \\\n\t\tDUK_BW_ASSERT_VALID_EXPR((thr), (bw_ctx)); \\\n\t} while (0)\n\n/* Working with the pointer and current size. */\n\n#define DUK_BW_GET_PTR(thr,bw_ctx) \\\n\t((bw_ctx)->p)\n#define DUK_BW_SET_PTR(thr,bw_ctx,ptr) do { \\\n\t\t(bw_ctx)->p = (ptr); \\\n\t} while (0)\n#define DUK_BW_ADD_PTR(thr,bw_ctx,delta) do { \\\n\t\t(bw_ctx)->p += (delta); \\\n\t} while (0)\n#define DUK_BW_GET_BASEPTR(thr,bw_ctx) \\\n\t((bw_ctx)->p_base)\n#define DUK_BW_GET_LIMITPTR(thr,bw_ctx) \\\n\t((bw_ctx)->p_limit)\n#define DUK_BW_GET_SIZE(thr,bw_ctx) \\\n\t((duk_size_t) ((bw_ctx)->p - (bw_ctx)->p_base))\n#define DUK_BW_SET_SIZE(thr,bw_ctx,sz) do { \\\n\t\tDUK_ASSERT((duk_size_t) (sz) <= (duk_size_t) ((bw_ctx)->p - (bw_ctx)->p_base)); \\\n\t\t(bw_ctx)->p = (bw_ctx)->p_base + (sz); \\\n\t} while (0)\n#define DUK_BW_RESET_SIZE(thr,bw_ctx) do { \\\n\t\t/* Reset to zero size, keep current limit. */ \\\n\t\t(bw_ctx)->p = (bw_ctx)->p_base; \\\n\t} while (0)\n#define DUK_BW_GET_BUFFER(thr,bw_ctx) \\\n\t((bw_ctx)->buf)\n\n/* Ensuring (reserving) space. */\n\n#define DUK_BW_ENSURE(thr,bw_ctx,sz) do { \\\n\t\tduk_size_t duk__sz, duk__space; \\\n\t\tDUK_BW_ASSERT_VALID((thr), (bw_ctx)); \\\n\t\tduk__sz = (sz); \\\n\t\tduk__space = (duk_size_t) ((bw_ctx)->p_limit - (bw_ctx)->p); \\\n\t\tif (duk__space < duk__sz) { \\\n\t\t\t(void) duk_bw_resize((thr), (bw_ctx), duk__sz); \\\n\t\t} \\\n\t} while (0)\n/* NOTE: Multiple evaluation of 'ptr' in this macro. */\n/* XXX: Rework to use an always-inline function? */\n#define DUK_BW_ENSURE_RAW(thr,bw_ctx,sz,ptr) \\\n\t(((duk_size_t) ((bw_ctx)->p_limit - (ptr)) >= (sz)) ? \\\n\t (ptr) : \\\n\t ((bw_ctx)->p = (ptr), duk_bw_resize((thr),(bw_ctx),(sz))))\n#define DUK_BW_ENSURE_GETPTR(thr,bw_ctx,sz) \\\n\tDUK_BW_ENSURE_RAW((thr), (bw_ctx), (sz), (bw_ctx)->p)\n#define DUK_BW_ASSERT_SPACE_EXPR(thr,bw_ctx,sz) \\\n\t(DUK_BW_ASSERT_VALID_EXPR((thr), (bw_ctx)), \\\n\t DUK_ASSERT_EXPR((duk_size_t) ((bw_ctx)->p_limit - (bw_ctx)->p) >= (duk_size_t) (sz)))\n#define DUK_BW_ASSERT_SPACE(thr,bw_ctx,sz) do { \\\n\t\tDUK_BW_ASSERT_SPACE_EXPR((thr), (bw_ctx), (sz)); \\\n\t} while (0)\n\n/* Miscellaneous. */\n\n#define DUK_BW_SETPTR_AND_COMPACT(thr,bw_ctx,ptr) do { \\\n\t\t(bw_ctx)->p = (ptr); \\\n\t\tduk_bw_compact((thr), (bw_ctx)); \\\n\t} while (0)\n\n/* Fast write calls which assume you control the slack beforehand.\n * Multibyte write variants exist and use a temporary write pointer\n * because byte writes alias with anything: with a stored pointer\n * explicit pointer load/stores get generated (e.g. gcc -Os).\n */\n\n#define DUK_BW_WRITE_RAW_U8(thr,bw_ctx,val) do { \\\n\t\tDUK_BW_ASSERT_SPACE((thr), (bw_ctx), 1); \\\n\t\t*(bw_ctx)->p++ = (duk_uint8_t) (val); \\\n\t} while (0)\n#define DUK_BW_WRITE_RAW_U8_2(thr,bw_ctx,val1,val2) do { \\\n\t\tduk_uint8_t *duk__p; \\\n\t\tDUK_BW_ASSERT_SPACE((thr), (bw_ctx), 2); \\\n\t\tduk__p = (bw_ctx)->p; \\\n\t\t*duk__p++ = (duk_uint8_t) (val1); \\\n\t\t*duk__p++ = (duk_uint8_t) (val2); \\\n\t\t(bw_ctx)->p = duk__p; \\\n\t} while (0)\n#define DUK_BW_WRITE_RAW_U8_3(thr,bw_ctx,val1,val2,val3) do { \\\n\t\tduk_uint8_t *duk__p; \\\n\t\tDUK_BW_ASSERT_SPACE((thr), (bw_ctx), 3); \\\n\t\tduk__p = (bw_ctx)->p; \\\n\t\t*duk__p++ = (duk_uint8_t) (val1); \\\n\t\t*duk__p++ = (duk_uint8_t) (val2); \\\n\t\t*duk__p++ = (duk_uint8_t) (val3); \\\n\t\t(bw_ctx)->p = duk__p; \\\n\t} while (0)\n#define DUK_BW_WRITE_RAW_U8_4(thr,bw_ctx,val1,val2,val3,val4) do { \\\n\t\tduk_uint8_t *duk__p; \\\n\t\tDUK_BW_ASSERT_SPACE((thr), (bw_ctx), 4); \\\n\t\tduk__p = (bw_ctx)->p; \\\n\t\t*duk__p++ = (duk_uint8_t) (val1); \\\n\t\t*duk__p++ = (duk_uint8_t) (val2); \\\n\t\t*duk__p++ = (duk_uint8_t) (val3); \\\n\t\t*duk__p++ = (duk_uint8_t) (val4); \\\n\t\t(bw_ctx)->p = duk__p; \\\n\t} while (0)\n#define DUK_BW_WRITE_RAW_U8_5(thr,bw_ctx,val1,val2,val3,val4,val5) do { \\\n\t\tduk_uint8_t *duk__p; \\\n\t\tDUK_BW_ASSERT_SPACE((thr), (bw_ctx), 5); \\\n\t\tduk__p = (bw_ctx)->p; \\\n\t\t*duk__p++ = (duk_uint8_t) (val1); \\\n\t\t*duk__p++ = (duk_uint8_t) (val2); \\\n\t\t*duk__p++ = (duk_uint8_t) (val3); \\\n\t\t*duk__p++ = (duk_uint8_t) (val4); \\\n\t\t*duk__p++ = (duk_uint8_t) (val5); \\\n\t\t(bw_ctx)->p = duk__p; \\\n\t} while (0)\n#define DUK_BW_WRITE_RAW_U8_6(thr,bw_ctx,val1,val2,val3,val4,val5,val6) do { \\\n\t\tduk_uint8_t *duk__p; \\\n\t\tDUK_BW_ASSERT_SPACE((thr), (bw_ctx), 6); \\\n\t\tduk__p = (bw_ctx)->p; \\\n\t\t*duk__p++ = (duk_uint8_t) (val1); \\\n\t\t*duk__p++ = (duk_uint8_t) (val2); \\\n\t\t*duk__p++ = (duk_uint8_t) (val3); \\\n\t\t*duk__p++ = (duk_uint8_t) (val4); \\\n\t\t*duk__p++ = (duk_uint8_t) (val5); \\\n\t\t*duk__p++ = (duk_uint8_t) (val6); \\\n\t\t(bw_ctx)->p = duk__p; \\\n\t} while (0)\n#define DUK_BW_WRITE_RAW_XUTF8(thr,bw_ctx,cp) do { \\\n\t\tduk_ucodepoint_t duk__cp; \\\n\t\tduk_small_int_t duk__enc_len; \\\n\t\tduk__cp = (duk_ucodepoint_t) (cp); \\\n\t\tDUK_BW_ASSERT_SPACE((thr), (bw_ctx), duk_unicode_get_xutf8_length(duk__cp)); \\\n\t\tduk__enc_len = duk_unicode_encode_xutf8(duk__cp, (bw_ctx)->p); \\\n\t\t(bw_ctx)->p += duk__enc_len; \\\n\t} while (0)\n#define DUK_BW_WRITE_RAW_CESU8(thr,bw_ctx,cp) do { \\\n\t\tduk_ucodepoint_t duk__cp; \\\n\t\tduk_small_int_t duk__enc_len; \\\n\t\tduk__cp = (duk_ucodepoint_t) (cp); \\\n\t\tDUK_BW_ASSERT_SPACE((thr), (bw_ctx), duk_unicode_get_cesu8_length(duk__cp)); \\\n\t\tduk__enc_len = duk_unicode_encode_cesu8(duk__cp, (bw_ctx)->p); \\\n\t\t(bw_ctx)->p += duk__enc_len; \\\n\t} while (0)\n/* XXX: add temporary duk__p pointer here too; sharing */\n#define DUK_BW_WRITE_RAW_BYTES(thr,bw_ctx,valptr,valsz) do { \\\n\t\tconst void *duk__valptr; \\\n\t\tduk_size_t duk__valsz; \\\n\t\tduk__valptr = (const void *) (valptr); \\\n\t\tduk__valsz = (duk_size_t) (valsz); \\\n\t\tDUK_MEMCPY((void *) ((bw_ctx)->p), duk__valptr, duk__valsz); \\\n\t\t(bw_ctx)->p += duk__valsz; \\\n\t} while (0)\n#define DUK_BW_WRITE_RAW_CSTRING(thr,bw_ctx,val) do { \\\n\t\tconst duk_uint8_t *duk__val; \\\n\t\tduk_size_t duk__val_len; \\\n\t\tduk__val = (const duk_uint8_t *) (val); \\\n\t\tduk__val_len = DUK_STRLEN((const char *) duk__val); \\\n\t\tDUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) duk__val, duk__val_len); \\\n\t\t(bw_ctx)->p += duk__val_len; \\\n\t} while (0)\n#define DUK_BW_WRITE_RAW_HSTRING(thr,bw_ctx,val) do { \\\n\t\tduk_size_t duk__val_len; \\\n\t\tduk__val_len = DUK_HSTRING_GET_BYTELEN((val)); \\\n\t\tDUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) DUK_HSTRING_GET_DATA((val)), duk__val_len); \\\n\t\t(bw_ctx)->p += duk__val_len; \\\n\t} while (0)\n#define DUK_BW_WRITE_RAW_HBUFFER(thr,bw_ctx,val) do { \\\n\t\tduk_size_t duk__val_len; \\\n\t\tduk__val_len = DUK_HBUFFER_GET_SIZE((val)); \\\n\t\tDUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \\\n\t\t(bw_ctx)->p += duk__val_len; \\\n\t} while (0)\n#define DUK_BW_WRITE_RAW_HBUFFER_FIXED(thr,bw_ctx,val) do { \\\n\t\tduk_size_t duk__val_len; \\\n\t\tduk__val_len = DUK_HBUFFER_FIXED_GET_SIZE((val)); \\\n\t\tDUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_FIXED_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \\\n\t\t(bw_ctx)->p += duk__val_len; \\\n\t} while (0)\n#define DUK_BW_WRITE_RAW_HBUFFER_DYNAMIC(thr,bw_ctx,val) do { \\\n\t\tduk_size_t duk__val_len; \\\n\t\tduk__val_len = DUK_HBUFFER_DYNAMIC_GET_SIZE((val)); \\\n\t\tDUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \\\n\t\t(bw_ctx)->p += duk__val_len; \\\n\t} while (0)\n\n/* Append bytes from a slice already in the buffer. */\n#define DUK_BW_WRITE_RAW_SLICE(thr,bw,dst_off,dst_len) \\\n\tduk_bw_write_raw_slice((thr), (bw), (dst_off), (dst_len))\n\n/* Insert bytes in the middle of the buffer from an external buffer. */\n#define DUK_BW_INSERT_RAW_BYTES(thr,bw,dst_off,buf,len) \\\n\tduk_bw_insert_raw_bytes((thr), (bw), (dst_off), (buf), (len))\n\n/* Insert bytes in the middle of the buffer from a slice already\n * in the buffer.  Source offset is interpreted \"before\" the operation.\n */\n#define DUK_BW_INSERT_RAW_SLICE(thr,bw,dst_off,src_off,len) \\\n\tduk_bw_insert_raw_slice((thr), (bw), (dst_off), (src_off), (len))\n\n/* Insert a reserved area somewhere in the buffer; caller fills it.\n * Evaluates to a (duk_uint_t *) pointing to the start of the reserved\n * area for convenience.\n */\n#define DUK_BW_INSERT_RAW_AREA(thr,bw,off,len) \\\n\tduk_bw_insert_raw_area((thr), (bw), (off), (len))\n\n/* Remove a slice from inside buffer. */\n#define DUK_BW_REMOVE_RAW_SLICE(thr,bw,off,len) \\\n\tduk_bw_remove_raw_slice((thr), (bw), (off), (len))\n\n/* Safe write calls which will ensure space first. */\n\n#define DUK_BW_WRITE_ENSURE_U8(thr,bw_ctx,val) do { \\\n\t\tDUK_BW_ENSURE((thr), (bw_ctx), 1); \\\n\t\tDUK_BW_WRITE_RAW_U8((thr), (bw_ctx), (val)); \\\n\t} while (0)\n#define DUK_BW_WRITE_ENSURE_U8_2(thr,bw_ctx,val1,val2) do { \\\n\t\tDUK_BW_ENSURE((thr), (bw_ctx), 2); \\\n\t\tDUK_BW_WRITE_RAW_U8_2((thr), (bw_ctx), (val1), (val2)); \\\n\t} while (0)\n#define DUK_BW_WRITE_ENSURE_U8_3(thr,bw_ctx,val1,val2,val3) do { \\\n\t\tDUK_BW_ENSURE((thr), (bw_ctx), 3); \\\n\t\tDUK_BW_WRITE_RAW_U8_3((thr), (bw_ctx), (val1), (val2), (val3)); \\\n\t} while (0)\n#define DUK_BW_WRITE_ENSURE_U8_4(thr,bw_ctx,val1,val2,val3,val4) do { \\\n\t\tDUK_BW_ENSURE((thr), (bw_ctx), 4); \\\n\t\tDUK_BW_WRITE_RAW_U8_4((thr), (bw_ctx), (val1), (val2), (val3), (val4)); \\\n\t} while (0)\n#define DUK_BW_WRITE_ENSURE_U8_5(thr,bw_ctx,val1,val2,val3,val4,val5) do { \\\n\t\tDUK_BW_ENSURE((thr), (bw_ctx), 5); \\\n\t\tDUK_BW_WRITE_RAW_U8_5((thr), (bw_ctx), (val1), (val2), (val3), (val4), (val5)); \\\n\t} while (0)\n#define DUK_BW_WRITE_ENSURE_U8_6(thr,bw_ctx,val1,val2,val3,val4,val5,val6) do { \\\n\t\tDUK_BW_ENSURE((thr), (bw_ctx), 6); \\\n\t\tDUK_BW_WRITE_RAW_U8_6((thr), (bw_ctx), (val1), (val2), (val3), (val4), (val5), (val6)); \\\n\t} while (0)\n#define DUK_BW_WRITE_ENSURE_XUTF8(thr,bw_ctx,cp) do { \\\n\t\tDUK_BW_ENSURE((thr), (bw_ctx), DUK_UNICODE_MAX_XUTF8_LENGTH); \\\n\t\tDUK_BW_WRITE_RAW_XUTF8((thr), (bw_ctx), (cp)); \\\n\t} while (0)\n#define DUK_BW_WRITE_ENSURE_CESU8(thr,bw_ctx,cp) do { \\\n\t\tDUK_BW_ENSURE((thr), (bw_ctx), DUK_UNICODE_MAX_CESU8_LENGTH); \\\n\t\tDUK_BW_WRITE_RAW_CESU8((thr), (bw_ctx), (cp)); \\\n\t} while (0)\n/* XXX: add temporary duk__p pointer here too; sharing */\n#define DUK_BW_WRITE_ENSURE_BYTES(thr,bw_ctx,valptr,valsz) do { \\\n\t\tconst void *duk__valptr; \\\n\t\tduk_size_t duk__valsz; \\\n\t\tduk__valptr = (const void *) (valptr); \\\n\t\tduk__valsz = (duk_size_t) (valsz); \\\n\t\tDUK_BW_ENSURE((thr), (bw_ctx), duk__valsz); \\\n\t\tDUK_MEMCPY((void *) ((bw_ctx)->p), duk__valptr, duk__valsz); \\\n\t\t(bw_ctx)->p += duk__valsz; \\\n\t} while (0)\n#define DUK_BW_WRITE_ENSURE_CSTRING(thr,bw_ctx,val) do { \\\n\t\tconst duk_uint8_t *duk__val; \\\n\t\tduk_size_t duk__val_len; \\\n\t\tduk__val = (const duk_uint8_t *) (val); \\\n\t\tduk__val_len = DUK_STRLEN((const char *) duk__val); \\\n\t\tDUK_BW_ENSURE((thr), (bw_ctx), duk__val_len); \\\n\t\tDUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) duk__val, duk__val_len); \\\n\t\t(bw_ctx)->p += duk__val_len; \\\n\t} while (0)\n#define DUK_BW_WRITE_ENSURE_HSTRING(thr,bw_ctx,val) do { \\\n\t\tduk_size_t duk__val_len; \\\n\t\tduk__val_len = DUK_HSTRING_GET_BYTELEN((val)); \\\n\t\tDUK_BW_ENSURE((thr), (bw_ctx), duk__val_len); \\\n\t\tDUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) DUK_HSTRING_GET_DATA((val)), duk__val_len); \\\n\t\t(bw_ctx)->p += duk__val_len; \\\n\t} while (0)\n#define DUK_BW_WRITE_ENSURE_HBUFFER(thr,bw_ctx,val) do { \\\n\t\tduk_size_t duk__val_len; \\\n\t\tduk__val_len = DUK_HBUFFER_GET_SIZE((val)); \\\n\t\tDUK_BW_ENSURE((thr), (bw_ctx), duk__val_len); \\\n\t\tDUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \\\n\t\t(bw_ctx)->p += duk__val_len; \\\n\t} while (0)\n#define DUK_BW_WRITE_ENSURE_HBUFFER_FIXED(thr,bw_ctx,val) do { \\\n\t\tduk_size_t duk__val_len; \\\n\t\tduk__val_len = DUK_HBUFFER_FIXED_GET_SIZE((val)); \\\n\t\tDUK_BW_ENSURE((thr), (bw_ctx), duk__val_len); \\\n\t\tDUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_FIXED_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \\\n\t\t(bw_ctx)->p += duk__val_len; \\\n\t} while (0)\n#define DUK_BW_WRITE_ENSURE_HBUFFER_DYNAMIC(thr,bw_ctx,val) do { \\\n\t\tduk_size_t duk__val_len; \\\n\t\tduk__val_len = DUK_HBUFFER_DYNAMIC_GET_SIZE((val)); \\\n\t\tDUK_BW_ENSURE((thr), (bw_ctx), duk__val_len); \\\n\t\tDUK_MEMCPY((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \\\n\t\t(bw_ctx)->p += duk__val_len; \\\n\t} while (0)\n\n#define DUK_BW_WRITE_ENSURE_SLICE(thr,bw,dst_off,dst_len) \\\n\tduk_bw_write_ensure_slice((thr), (bw), (dst_off), (dst_len))\n#define DUK_BW_INSERT_ENSURE_BYTES(thr,bw,dst_off,buf,len) \\\n\tduk_bw_insert_ensure_bytes((thr), (bw), (dst_off), (buf), (len))\n#define DUK_BW_INSERT_ENSURE_SLICE(thr,bw,dst_off,src_off,len) \\\n\tduk_bw_insert_ensure_slice((thr), (bw), (dst_off), (src_off), (len))\n#define DUK_BW_INSERT_ENSURE_AREA(thr,bw,off,len) \\\n\t/* Evaluates to (duk_uint8_t *) pointing to start of area. */ \\\n\tduk_bw_insert_ensure_area((thr), (bw), (off), (len))\n#define DUK_BW_REMOVE_ENSURE_SLICE(thr,bw,off,len) \\\n\t/* No difference between raw/ensure because the buffer shrinks. */ \\\n\tDUK_BW_REMOVE_RAW_SLICE((thr), (bw), (off), (len))\n\n/*\n *  Externs and prototypes\n */\n\n#if !defined(DUK_SINGLE_FILE)\nDUK_INTERNAL_DECL const duk_uint8_t duk_lc_digits[36];\nDUK_INTERNAL_DECL const duk_uint8_t duk_uc_nybbles[16];\nDUK_INTERNAL_DECL const duk_int8_t duk_hex_dectab[256];\n#if defined(DUK_USE_HEX_FASTPATH)\nDUK_INTERNAL_DECL const duk_int16_t duk_hex_dectab_shift4[256];\nDUK_INTERNAL_DECL const duk_uint16_t duk_hex_enctab[256];\n#endif\n#if defined(DUK_USE_BASE64_FASTPATH)\nDUK_INTERNAL_DECL const duk_uint8_t duk_base64_enctab[64];\nDUK_INTERNAL_DECL const duk_int8_t duk_base64_dectab[256];\n#endif\n#endif  /* !DUK_SINGLE_FILE */\n\n/* Note: assumes that duk_util_probe_steps size is 32 */\n#if defined(DUK_USE_HOBJECT_HASH_PART)\n#if !defined(DUK_SINGLE_FILE)\nDUK_INTERNAL_DECL duk_uint8_t duk_util_probe_steps[32];\n#endif  /* !DUK_SINGLE_FILE */\n#endif\n\n#if defined(DUK_USE_STRHASH_DENSE)\nDUK_INTERNAL_DECL duk_uint32_t duk_util_hashbytes(const duk_uint8_t *data, duk_size_t len, duk_uint32_t seed);\n#endif\n\nDUK_INTERNAL_DECL duk_uint32_t duk_bd_decode(duk_bitdecoder_ctx *ctx, duk_small_int_t bits);\nDUK_INTERNAL_DECL duk_small_uint_t duk_bd_decode_flag(duk_bitdecoder_ctx *ctx);\nDUK_INTERNAL_DECL duk_uint32_t duk_bd_decode_flagged(duk_bitdecoder_ctx *ctx, duk_small_int_t bits, duk_uint32_t def_value);\nDUK_INTERNAL_DECL duk_int32_t duk_bd_decode_flagged_signed(duk_bitdecoder_ctx *ctx, duk_small_int_t bits, duk_int32_t def_value);\nDUK_INTERNAL_DECL duk_uint32_t duk_bd_decode_varuint(duk_bitdecoder_ctx *ctx);\nDUK_INTERNAL_DECL duk_small_uint_t duk_bd_decode_bitpacked_string(duk_bitdecoder_ctx *bd, duk_uint8_t *out);\n\nDUK_INTERNAL_DECL void duk_be_encode(duk_bitencoder_ctx *ctx, duk_uint32_t data, duk_small_int_t bits);\nDUK_INTERNAL_DECL void duk_be_finish(duk_bitencoder_ctx *ctx);\n\n#if !defined(DUK_USE_GET_RANDOM_DOUBLE)\nDUK_INTERNAL_DECL duk_double_t duk_util_tinyrandom_get_double(duk_hthread *thr);\nDUK_INTERNAL_DECL void duk_util_tinyrandom_prepare_seed(duk_hthread *thr);\n#endif\n\nDUK_INTERNAL_DECL void duk_bw_init(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, duk_hbuffer_dynamic *h_buf);\nDUK_INTERNAL_DECL void duk_bw_init_pushbuf(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, duk_size_t buf_size);\nDUK_INTERNAL_DECL duk_uint8_t *duk_bw_resize(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, duk_size_t sz);\nDUK_INTERNAL_DECL void duk_bw_compact(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx);\nDUK_INTERNAL_DECL void duk_bw_write_raw_slice(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t src_off, duk_size_t len);\nDUK_INTERNAL_DECL void duk_bw_write_ensure_slice(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t src_off, duk_size_t len);\nDUK_INTERNAL_DECL void duk_bw_insert_raw_bytes(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t dst_off, const duk_uint8_t *buf, duk_size_t len);\nDUK_INTERNAL_DECL void duk_bw_insert_ensure_bytes(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t dst_off, const duk_uint8_t *buf, duk_size_t len);\nDUK_INTERNAL_DECL void duk_bw_insert_raw_slice(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t dst_off, duk_size_t src_off, duk_size_t len);\nDUK_INTERNAL_DECL void duk_bw_insert_ensure_slice(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t dst_off, duk_size_t src_off, duk_size_t len);\nDUK_INTERNAL_DECL duk_uint8_t *duk_bw_insert_raw_area(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t off, duk_size_t len);\nDUK_INTERNAL_DECL duk_uint8_t *duk_bw_insert_ensure_area(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t off, duk_size_t len);\nDUK_INTERNAL_DECL void duk_bw_remove_raw_slice(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t off, duk_size_t len);\n/* No duk_bw_remove_ensure_slice(), functionality would be identical. */\n\nDUK_INTERNAL_DECL duk_uint16_t duk_raw_read_u16_be(duk_uint8_t **p);\nDUK_INTERNAL_DECL duk_uint32_t duk_raw_read_u32_be(duk_uint8_t **p);\nDUK_INTERNAL_DECL duk_double_t duk_raw_read_double_be(duk_uint8_t **p);\nDUK_INTERNAL_DECL void duk_raw_write_u16_be(duk_uint8_t **p, duk_uint16_t val);\nDUK_INTERNAL_DECL void duk_raw_write_u32_be(duk_uint8_t **p, duk_uint32_t val);\nDUK_INTERNAL_DECL void duk_raw_write_double_be(duk_uint8_t **p, duk_double_t val);\n\n#if defined(DUK_USE_DEBUGGER_SUPPORT)  /* For now only needed by the debugger. */\nDUK_INTERNAL_DECL void duk_byteswap_bytes(duk_uint8_t *p, duk_small_uint_t len);\n#endif\n\nDUK_INTERNAL_DECL duk_bool_t duk_is_whole_get_int32_nonegzero(duk_double_t x, duk_int32_t *ival);\nDUK_INTERNAL_DECL duk_bool_t duk_is_whole_get_int32(duk_double_t x, duk_int32_t *ival);\nDUK_INTERNAL_DECL duk_bool_t duk_double_is_anyinf(duk_double_t x);\nDUK_INTERNAL_DECL duk_bool_t duk_double_is_posinf(duk_double_t x);\nDUK_INTERNAL_DECL duk_bool_t duk_double_is_neginf(duk_double_t x);\nDUK_INTERNAL_DECL duk_bool_t duk_double_is_nan(duk_double_t x);\nDUK_INTERNAL_DECL duk_bool_t duk_double_is_nan_or_zero(duk_double_t x);\nDUK_INTERNAL_DECL duk_bool_t duk_double_is_nan_or_inf(duk_double_t x);\nDUK_INTERNAL_DECL duk_bool_t duk_double_is_nan_zero_inf(duk_double_t x);\nDUK_INTERNAL_DECL duk_small_uint_t duk_double_signbit(duk_double_t x);\nDUK_INTERNAL_DECL duk_double_t duk_double_trunc_towards_zero(duk_double_t x);\nDUK_INTERNAL_DECL duk_bool_t duk_double_same_sign(duk_double_t x, duk_double_t y);\nDUK_INTERNAL_DECL duk_double_t duk_double_fmin(duk_double_t x, duk_double_t y);\nDUK_INTERNAL_DECL duk_double_t duk_double_fmax(duk_double_t x, duk_double_t y);\n\n#endif  /* DUK_UTIL_H_INCLUDED */\n/* #include duk_strings.h */\n#line 1 \"duk_strings.h\"\n/*\n *  Shared string macros.\n *\n *  Using shared macros helps minimize strings data size because it's easy\n *  to check if an existing string could be used.  String constants don't\n *  need to be all defined here; defining a string here makes sense if there's\n *  a high chance the string could be reused.  Also, using macros allows\n *  a call site express the exact string needed, but the macro may map to an\n *  approximate string to reduce unique string count.  Macros can also be\n *  more easily tuned for low memory targets than #if defined()s throughout\n *  the code base.\n *\n *  Because format strings behave differently in the call site (they need to\n *  be followed by format arguments), they use a special prefix DUK_STR_FMT_.\n *\n *  On some compilers using explicit shared strings is preferable; on others\n *  it may be better to use straight literals because the compiler will combine\n *  them anyway, and such strings won't end up unnecessarily in a symbol table.\n */\n\n#if !defined(DUK_ERRMSG_H_INCLUDED)\n#define DUK_ERRMSG_H_INCLUDED\n\n/* Mostly API and built-in method related */\n#define DUK_STR_INTERNAL_ERROR                   \"internal error\"\n#define DUK_STR_UNSUPPORTED                      \"unsupported\"\n#define DUK_STR_INVALID_COUNT                    \"invalid count\"\n#define DUK_STR_INVALID_ARGS                     \"invalid args\"\n#define DUK_STR_INVALID_STATE                    \"invalid state\"\n#define DUK_STR_INVALID_INPUT                    \"invalid input\"\n#define DUK_STR_INVALID_LENGTH                   \"invalid length\"\n#define DUK_STR_NOT_CONSTRUCTABLE                \"not constructable\"\n#define DUK_STR_CONSTRUCT_ONLY                   \"constructor requires 'new'\"\n#define DUK_STR_NOT_CALLABLE                     \"not callable\"\n#define DUK_STR_NOT_EXTENSIBLE                   \"not extensible\"\n#define DUK_STR_NOT_WRITABLE                     \"not writable\"\n#define DUK_STR_NOT_CONFIGURABLE                 \"not configurable\"\n#define DUK_STR_INVALID_CONTEXT                  \"invalid context\"\n#define DUK_STR_INVALID_INDEX                    \"invalid args\"\n#define DUK_STR_PUSH_BEYOND_ALLOC_STACK          \"cannot push beyond allocated stack\"\n#define DUK_STR_NOT_UNDEFINED                    \"unexpected type\"\n#define DUK_STR_NOT_NULL                         \"unexpected type\"\n#define DUK_STR_NOT_BOOLEAN                      \"unexpected type\"\n#define DUK_STR_NOT_NUMBER                       \"unexpected type\"\n#define DUK_STR_NOT_STRING                       \"unexpected type\"\n#define DUK_STR_NOT_OBJECT                       \"unexpected type\"\n#define DUK_STR_NOT_POINTER                      \"unexpected type\"\n#define DUK_STR_NOT_BUFFER                       \"not buffer\"  /* still in use with verbose messages */\n#define DUK_STR_UNEXPECTED_TYPE                  \"unexpected type\"\n#define DUK_STR_NOT_THREAD                       \"unexpected type\"\n#define DUK_STR_NOT_COMPFUNC                     \"unexpected type\"\n#define DUK_STR_NOT_NATFUNC                      \"unexpected type\"\n#define DUK_STR_NOT_C_FUNCTION                   \"unexpected type\"\n#define DUK_STR_NOT_FUNCTION                     \"unexpected type\"\n#define DUK_STR_NOT_REGEXP                       \"unexpected type\"\n#define DUK_STR_TOPRIMITIVE_FAILED               \"coercion to primitive failed\"\n#define DUK_STR_NUMBER_OUTSIDE_RANGE             \"number outside range\"\n#define DUK_STR_NOT_OBJECT_COERCIBLE             \"not object coercible\"\n#define DUK_STR_CANNOT_NUMBER_COERCE_SYMBOL      \"cannot number coerce Symbol\"\n#define DUK_STR_CANNOT_STRING_COERCE_SYMBOL      \"cannot string coerce Symbol\"\n#define DUK_STR_STRING_TOO_LONG                  \"string too long\"\n#define DUK_STR_BUFFER_TOO_LONG                  \"buffer too long\"\n#define DUK_STR_ALLOC_FAILED                     \"alloc failed\"\n#define DUK_STR_WRONG_BUFFER_TYPE                \"wrong buffer type\"\n#define DUK_STR_BASE64_ENCODE_FAILED             \"base64 encode failed\"\n#define DUK_STR_SOURCE_DECODE_FAILED             \"source decode failed\"\n#define DUK_STR_UTF8_DECODE_FAILED               \"utf-8 decode failed\"\n#define DUK_STR_BASE64_DECODE_FAILED             \"base64 decode failed\"\n#define DUK_STR_HEX_DECODE_FAILED                \"hex decode failed\"\n#define DUK_STR_INVALID_BYTECODE                 \"invalid bytecode\"\n#define DUK_STR_NO_SOURCECODE                    \"no sourcecode\"\n#define DUK_STR_RESULT_TOO_LONG                  \"result too long\"\n#define DUK_STR_INVALID_CFUNC_RC                 \"invalid C function rc\"\n#define DUK_STR_INVALID_INSTANCEOF_RVAL          \"invalid instanceof rval\"\n#define DUK_STR_INVALID_INSTANCEOF_RVAL_NOPROTO  \"instanceof rval has no .prototype\"\n\n/* JSON */\n#define DUK_STR_FMT_PTR                          \"%p\"\n#define DUK_STR_FMT_INVALID_JSON                 \"invalid json (at offset %ld)\"\n#define DUK_STR_JSONDEC_RECLIMIT                 \"json decode recursion limit\"\n#define DUK_STR_JSONENC_RECLIMIT                 \"json encode recursion limit\"\n#define DUK_STR_CYCLIC_INPUT                     \"cyclic input\"\n\n/* Object property access */\n#define DUK_STR_INVALID_BASE                     \"invalid base value\"\n#define DUK_STR_STRICT_CALLER_READ               \"cannot read strict 'caller'\"\n#define DUK_STR_PROXY_REJECTED                   \"proxy rejected\"\n#define DUK_STR_INVALID_ARRAY_LENGTH             \"invalid array length\"\n#define DUK_STR_SETTER_UNDEFINED                 \"setter undefined\"\n#define DUK_STR_INVALID_DESCRIPTOR               \"invalid descriptor\"\n\n/* Proxy */\n#define DUK_STR_PROXY_REVOKED                    \"proxy revoked\"\n#define DUK_STR_INVALID_TRAP_RESULT              \"invalid trap result\"\n\n/* Variables */\n\n/* Lexer */\n#define DUK_STR_INVALID_ESCAPE                   \"invalid escape\"\n#define DUK_STR_UNTERMINATED_STRING              \"unterminated string\"\n#define DUK_STR_UNTERMINATED_COMMENT             \"unterminated comment\"\n#define DUK_STR_UNTERMINATED_REGEXP              \"unterminated regexp\"\n#define DUK_STR_TOKEN_LIMIT                      \"token limit\"\n#define DUK_STR_REGEXP_SUPPORT_DISABLED          \"regexp support disabled\"\n#define DUK_STR_INVALID_NUMBER_LITERAL           \"invalid number literal\"\n#define DUK_STR_INVALID_TOKEN                    \"invalid token\"\n\n/* Compiler */\n#define DUK_STR_PARSE_ERROR                      \"parse error\"\n#define DUK_STR_DUPLICATE_LABEL                  \"duplicate label\"\n#define DUK_STR_INVALID_LABEL                    \"invalid label\"\n#define DUK_STR_INVALID_ARRAY_LITERAL            \"invalid array literal\"\n#define DUK_STR_INVALID_OBJECT_LITERAL           \"invalid object literal\"\n#define DUK_STR_INVALID_VAR_DECLARATION          \"invalid variable declaration\"\n#define DUK_STR_CANNOT_DELETE_IDENTIFIER         \"cannot delete identifier\"\n#define DUK_STR_INVALID_EXPRESSION               \"invalid expression\"\n#define DUK_STR_INVALID_LVALUE                   \"invalid lvalue\"\n#define DUK_STR_INVALID_NEWTARGET                \"invalid new.target\"\n#define DUK_STR_EXPECTED_IDENTIFIER              \"expected identifier\"\n#define DUK_STR_EMPTY_EXPR_NOT_ALLOWED           \"empty expression not allowed\"\n#define DUK_STR_INVALID_FOR                      \"invalid for statement\"\n#define DUK_STR_INVALID_SWITCH                   \"invalid switch statement\"\n#define DUK_STR_INVALID_BREAK_CONT_LABEL         \"invalid break/continue label\"\n#define DUK_STR_INVALID_RETURN                   \"invalid return\"\n#define DUK_STR_INVALID_TRY                      \"invalid try\"\n#define DUK_STR_INVALID_THROW                    \"invalid throw\"\n#define DUK_STR_WITH_IN_STRICT_MODE              \"with in strict mode\"\n#define DUK_STR_FUNC_STMT_NOT_ALLOWED            \"function statement not allowed\"\n#define DUK_STR_UNTERMINATED_STMT                \"unterminated statement\"\n#define DUK_STR_INVALID_ARG_NAME                 \"invalid argument name\"\n#define DUK_STR_INVALID_FUNC_NAME                \"invalid function name\"\n#define DUK_STR_INVALID_GETSET_NAME              \"invalid getter/setter name\"\n#define DUK_STR_FUNC_NAME_REQUIRED               \"function name required\"\n\n/* RegExp */\n#define DUK_STR_INVALID_QUANTIFIER               \"invalid regexp quantifier\"\n#define DUK_STR_INVALID_QUANTIFIER_NO_ATOM       \"quantifier without preceding atom\"\n#define DUK_STR_INVALID_QUANTIFIER_VALUES        \"quantifier values invalid (qmin > qmax)\"\n#define DUK_STR_QUANTIFIER_TOO_MANY_COPIES       \"quantifier requires too many atom copies\"\n#define DUK_STR_UNEXPECTED_CLOSING_PAREN         \"unexpected closing parenthesis\"\n#define DUK_STR_UNEXPECTED_END_OF_PATTERN        \"unexpected end of pattern\"\n#define DUK_STR_UNEXPECTED_REGEXP_TOKEN          \"unexpected token in regexp\"\n#define DUK_STR_INVALID_REGEXP_FLAGS             \"invalid regexp flags\"\n#define DUK_STR_INVALID_REGEXP_ESCAPE            \"invalid regexp escape\"\n#define DUK_STR_INVALID_BACKREFS                 \"invalid backreference(s)\"\n#define DUK_STR_INVALID_REGEXP_CHARACTER         \"invalid regexp character\"\n#define DUK_STR_INVALID_REGEXP_GROUP             \"invalid regexp group\"\n#define DUK_STR_UNTERMINATED_CHARCLASS           \"unterminated character class\"\n#define DUK_STR_INVALID_RANGE                    \"invalid range\"\n\n/* Limits */\n#define DUK_STR_VALSTACK_LIMIT                   \"valstack limit\"\n#define DUK_STR_CALLSTACK_LIMIT                  \"callstack limit\"\n#define DUK_STR_PROTOTYPE_CHAIN_LIMIT            \"prototype chain limit\"\n#define DUK_STR_BOUND_CHAIN_LIMIT                \"function call bound chain limit\"\n#define DUK_STR_C_CALLSTACK_LIMIT                \"C call stack depth limit\"\n#define DUK_STR_COMPILER_RECURSION_LIMIT         \"compiler recursion limit\"\n#define DUK_STR_BYTECODE_LIMIT                   \"bytecode limit\"\n#define DUK_STR_REG_LIMIT                        \"register limit\"\n#define DUK_STR_TEMP_LIMIT                       \"temp limit\"\n#define DUK_STR_CONST_LIMIT                      \"const limit\"\n#define DUK_STR_FUNC_LIMIT                       \"function limit\"\n#define DUK_STR_REGEXP_COMPILER_RECURSION_LIMIT  \"regexp compiler recursion limit\"\n#define DUK_STR_REGEXP_EXECUTOR_RECURSION_LIMIT  \"regexp executor recursion limit\"\n#define DUK_STR_REGEXP_EXECUTOR_STEP_LIMIT       \"regexp step limit\"\n\n#endif  /* DUK_ERRMSG_H_INCLUDED */\n/* #include duk_js_bytecode.h */\n#line 1 \"duk_js_bytecode.h\"\n/*\n *  Ecmascript bytecode\n */\n\n#if !defined(DUK_JS_BYTECODE_H_INCLUDED)\n#define DUK_JS_BYTECODE_H_INCLUDED\n\n/*\n *  Bytecode instruction layout\n *  ===========================\n *\n *  Instructions are unsigned 32-bit integers divided as follows:\n *\n *  !3!3!2!2!2!2!2!2!2!2!2!2!1!1!1!1!1!1!1!1!1!1! ! ! ! ! ! ! ! ! ! !\n *  !1!0!9!8!7!6!5!4!3!2!1!0!9!8!7!6!5!4!3!2!1!0!9!8!7!6!5!4!3!2!1!0!\n *  +-----------------------------------------------+---------------+\n *  !       C       !       B       !       A       !       OP      !\n *  +-----------------------------------------------+---------------+\n *\n *  OP (8 bits):  opcode (DUK_OP_*), access should be fastest\n *                consecutive opcodes allocated when opcode needs flags\n *   A (8 bits):  typically a target register number\n *   B (8 bits):  typically first source register/constant number\n *   C (8 bits):  typically second source register/constant number\n *\n *  Some instructions combine BC or ABC together for larger parameter values.\n *  Signed integers (e.g. jump offsets) are encoded as unsigned, with an\n *  opcode specific bias.\n *\n *  Some opcodes have flags which are handled by allocating consecutive\n *  opcodes to make space for 1-N flags.  Flags can also be e.g. in the 'A'\n *  field when there's room for the specific opcode.\n *\n *  For example, if three flags were needed, they could be allocated from\n *  the opcode field as follows:\n *\n *  !3!3!2!2!2!2!2!2!2!2!2!2!1!1!1!1!1!1!1!1!1!1! ! ! ! ! ! ! ! ! ! !\n *  !1!0!9!8!7!6!5!4!3!2!1!0!9!8!7!6!5!4!3!2!1!0!9!8!7!6!5!4!3!2!1!0!\n *  +-----------------------------------------------+---------------+\n *  !       C       !       B       !       A       !    OP   !Z!Y!X!\n *  +-----------------------------------------------+---------------+\n *\n *  Some opcodes accept a reg/const argument which is handled by allocating\n *  flags in the OP field, see DUK_BC_ISREG() and DUK_BC_ISCONST().  The\n *  following convention is shared by most opcodes, so that the compiler\n *  can handle reg/const flagging without opcode specific code paths:\n *\n *  !3!3!2!2!2!2!2!2!2!2!2!2!1!1!1!1!1!1!1!1!1!1! ! ! ! ! ! ! ! ! ! !\n *  !1!0!9!8!7!6!5!4!3!2!1!0!9!8!7!6!5!4!3!2!1!0!9!8!7!6!5!4!3!2!1!0!\n *  +-----------------------------------------------+---------------+\n *  !       C       !       B       !       A       !     OP    !Y!X!\n *  +-----------------------------------------------+---------------+\n *\n *    X  1=B is const, 0=B is reg\n *    Y  1=C is const, 0=C is reg\n *\n *    In effect OP, OP + 1, OP + 2, and OP + 3 are allocated from the\n *    8-bit opcode space for a single logical opcode.  The base opcode\n *    number should be divisible by 4.  If the opcode is called 'FOO'\n *    the following opcode constants would be defined:\n *\n *      DUK_OP_FOO     100       // base opcode number\n *      DUK_OP_FOO_RR  100       // FOO, B=reg, C=reg\n *      DUK_OP_FOO_CR  101       // FOO, B=const, C=reg\n *      DUK_OP_FOO_RC  102       // FOO, B=reg, C=const\n *      DUK_OP_FOO_CC  103       // FOO, B=const, C=const\n *\n *  If only B or C is a reg/const, the unused opcode combinations can be\n *  used for other opcodes (which take no reg/const argument).  However,\n *  such opcode values are initially reserved, at least while opcode space\n *  is available.  For example, if 'BAR' uses B for a register field and\n *  C is a reg/const:\n *\n *      DUK_OP_BAR            116    // base opcode number\n *      DUK_OP_BAR_RR         116    // BAR, B=reg, C=reg\n *      DUK_OP_BAR_CR_UNUSED  117    // unused, could be repurposed\n *      DUK_OP_BAR_RC         118    // BAR, B=reg, C=const\n *      DUK_OP_BAR_CC_UNUSED  119    // unused, could be repurposed\n *\n *  Macro naming is a bit misleading, e.g. \"ABC\" in macro name but the\n *  field layout is concretely \"CBA\" in the register.\n */\n\ntypedef duk_uint32_t duk_instr_t;\n\n#define DUK_BC_SHIFT_OP             0\n#define DUK_BC_SHIFT_A              8\n#define DUK_BC_SHIFT_B              16\n#define DUK_BC_SHIFT_C              24\n#define DUK_BC_SHIFT_BC             DUK_BC_SHIFT_B\n#define DUK_BC_SHIFT_ABC            DUK_BC_SHIFT_A\n\n#define DUK_BC_UNSHIFTED_MASK_OP    0xffUL\n#define DUK_BC_UNSHIFTED_MASK_A     0xffUL\n#define DUK_BC_UNSHIFTED_MASK_B     0xffUL\n#define DUK_BC_UNSHIFTED_MASK_C     0xffUL\n#define DUK_BC_UNSHIFTED_MASK_BC    0xffffUL\n#define DUK_BC_UNSHIFTED_MASK_ABC   0xffffffUL\n\n#define DUK_BC_SHIFTED_MASK_OP      (DUK_BC_UNSHIFTED_MASK_OP << DUK_BC_SHIFT_OP)\n#define DUK_BC_SHIFTED_MASK_A       (DUK_BC_UNSHIFTED_MASK_A << DUK_BC_SHIFT_A)\n#define DUK_BC_SHIFTED_MASK_B       (DUK_BC_UNSHIFTED_MASK_B << DUK_BC_SHIFT_B)\n#define DUK_BC_SHIFTED_MASK_C       (DUK_BC_UNSHIFTED_MASK_C << DUK_BC_SHIFT_C)\n#define DUK_BC_SHIFTED_MASK_BC      (DUK_BC_UNSHIFTED_MASK_BC << DUK_BC_SHIFT_BC)\n#define DUK_BC_SHIFTED_MASK_ABC     (DUK_BC_UNSHIFTED_MASK_ABC << DUK_BC_SHIFT_ABC)\n\n#define DUK_DEC_OP(x)               ((x) & 0xffUL)\n#define DUK_DEC_A(x)                (((x) >> 8) & 0xffUL)\n#define DUK_DEC_B(x)                (((x) >> 16) & 0xffUL)\n#define DUK_DEC_C(x)                (((x) >> 24) & 0xffUL)\n#define DUK_DEC_BC(x)               (((x) >> 16) & 0xffffUL)\n#define DUK_DEC_ABC(x)              (((x) >> 8) & 0xffffffUL)\n\n#define DUK_ENC_OP(op)              ((duk_instr_t) (op))\n#define DUK_ENC_OP_ABC(op,abc)      ((duk_instr_t) ( \\\n                                        (((duk_instr_t) (abc)) << 8) | \\\n                                        ((duk_instr_t) (op)) \\\n                                    ))\n#define DUK_ENC_OP_A_BC(op,a,bc)    ((duk_instr_t) ( \\\n                                        (((duk_instr_t) (bc)) << 16) | \\\n                                        (((duk_instr_t) (a)) << 8) | \\\n                                        ((duk_instr_t) (op)) \\\n                                    ))\n#define DUK_ENC_OP_A_B_C(op,a,b,c)  ((duk_instr_t) ( \\\n                                        (((duk_instr_t) (c)) << 24) | \\\n                                        (((duk_instr_t) (b)) << 16) | \\\n                                        (((duk_instr_t) (a)) << 8) | \\\n                                        ((duk_instr_t) (op)) \\\n                                    ))\n#define DUK_ENC_OP_A_B(op,a,b)      DUK_ENC_OP_A_B_C((op),(a),(b),0)\n#define DUK_ENC_OP_A(op,a)          DUK_ENC_OP_A_B_C((op),(a),0,0)\n#define DUK_ENC_OP_BC(op,bc)        DUK_ENC_OP_A_BC((op),0,(bc))\n\n/* Get opcode base value with B/C reg/const flags cleared. */\n#define DUK_BC_NOREGCONST_OP(op)    ((op) & 0xfc)\n\n/* Constants should be signed so that signed arithmetic involving them\n * won't cause values to be coerced accidentally to unsigned.\n */\n#define DUK_BC_OP_MIN               0\n#define DUK_BC_OP_MAX               0xffL\n#define DUK_BC_A_MIN                0\n#define DUK_BC_A_MAX                0xffL\n#define DUK_BC_B_MIN                0\n#define DUK_BC_B_MAX                0xffL\n#define DUK_BC_C_MIN                0\n#define DUK_BC_C_MAX                0xffL\n#define DUK_BC_BC_MIN               0\n#define DUK_BC_BC_MAX               0xffffL\n#define DUK_BC_ABC_MIN              0\n#define DUK_BC_ABC_MAX              0xffffffL\n\n/* Masks for B/C reg/const indicator in opcode field. */\n#define DUK_BC_REGCONST_B           (0x01UL)\n#define DUK_BC_REGCONST_C           (0x02UL)\n\n/* Misc. masks for opcode field. */\n#define DUK_BC_INCDECP_FLAG_DEC     (0x04UL)\n#define DUK_BC_INCDECP_FLAG_POST    (0x08UL)\n\n/* Opcodes. */\n#define DUK_OP_LDREG                0\n#define DUK_OP_STREG                1\n#define DUK_OP_JUMP                 2\n#define DUK_OP_LDCONST              3\n#define DUK_OP_LDINT                4\n#define DUK_OP_LDINTX               5\n#define DUK_OP_LDTHIS               6\n#define DUK_OP_LDUNDEF              7\n#define DUK_OP_LDNULL               8\n#define DUK_OP_LDTRUE               9\n#define DUK_OP_LDFALSE              10\n#define DUK_OP_GETVAR               11\n#define DUK_OP_BNOT                 12\n#define DUK_OP_LNOT                 13\n#define DUK_OP_UNM                  14\n#define DUK_OP_UNP                  15\n#define DUK_OP_EQ                   16\n#define DUK_OP_EQ_RR                16\n#define DUK_OP_EQ_CR                17\n#define DUK_OP_EQ_RC                18\n#define DUK_OP_EQ_CC                19\n#define DUK_OP_NEQ                  20\n#define DUK_OP_NEQ_RR               20\n#define DUK_OP_NEQ_CR               21\n#define DUK_OP_NEQ_RC               22\n#define DUK_OP_NEQ_CC               23\n#define DUK_OP_SEQ                  24\n#define DUK_OP_SEQ_RR               24\n#define DUK_OP_SEQ_CR               25\n#define DUK_OP_SEQ_RC               26\n#define DUK_OP_SEQ_CC               27\n#define DUK_OP_SNEQ                 28\n#define DUK_OP_SNEQ_RR              28\n#define DUK_OP_SNEQ_CR              29\n#define DUK_OP_SNEQ_RC              30\n#define DUK_OP_SNEQ_CC              31\n#define DUK_OP_GT                   32\n#define DUK_OP_GT_RR                32\n#define DUK_OP_GT_CR                33\n#define DUK_OP_GT_RC                34\n#define DUK_OP_GT_CC                35\n#define DUK_OP_GE                   36\n#define DUK_OP_GE_RR                36\n#define DUK_OP_GE_CR                37\n#define DUK_OP_GE_RC                38\n#define DUK_OP_GE_CC                39\n#define DUK_OP_LT                   40\n#define DUK_OP_LT_RR                40\n#define DUK_OP_LT_CR                41\n#define DUK_OP_LT_RC                42\n#define DUK_OP_LT_CC                43\n#define DUK_OP_LE                   44\n#define DUK_OP_LE_RR                44\n#define DUK_OP_LE_CR                45\n#define DUK_OP_LE_RC                46\n#define DUK_OP_LE_CC                47\n#define DUK_OP_IFTRUE               48\n#define DUK_OP_IFTRUE_R             48\n#define DUK_OP_IFTRUE_C             49\n#define DUK_OP_IFFALSE              50\n#define DUK_OP_IFFALSE_R            50\n#define DUK_OP_IFFALSE_C            51\n#define DUK_OP_ADD                  52\n#define DUK_OP_ADD_RR               52\n#define DUK_OP_ADD_CR               53\n#define DUK_OP_ADD_RC               54\n#define DUK_OP_ADD_CC               55\n#define DUK_OP_SUB                  56\n#define DUK_OP_SUB_RR               56\n#define DUK_OP_SUB_CR               57\n#define DUK_OP_SUB_RC               58\n#define DUK_OP_SUB_CC               59\n#define DUK_OP_MUL                  60\n#define DUK_OP_MUL_RR               60\n#define DUK_OP_MUL_CR               61\n#define DUK_OP_MUL_RC               62\n#define DUK_OP_MUL_CC               63\n#define DUK_OP_DIV                  64\n#define DUK_OP_DIV_RR               64\n#define DUK_OP_DIV_CR               65\n#define DUK_OP_DIV_RC               66\n#define DUK_OP_DIV_CC               67\n#define DUK_OP_MOD                  68\n#define DUK_OP_MOD_RR               68\n#define DUK_OP_MOD_CR               69\n#define DUK_OP_MOD_RC               70\n#define DUK_OP_MOD_CC               71\n#define DUK_OP_EXP                  72\n#define DUK_OP_EXP_RR               72\n#define DUK_OP_EXP_CR               73\n#define DUK_OP_EXP_RC               74\n#define DUK_OP_EXP_CC               75\n#define DUK_OP_BAND                 76\n#define DUK_OP_BAND_RR              76\n#define DUK_OP_BAND_CR              77\n#define DUK_OP_BAND_RC              78\n#define DUK_OP_BAND_CC              79\n#define DUK_OP_BOR                  80\n#define DUK_OP_BOR_RR               80\n#define DUK_OP_BOR_CR               81\n#define DUK_OP_BOR_RC               82\n#define DUK_OP_BOR_CC               83\n#define DUK_OP_BXOR                 84\n#define DUK_OP_BXOR_RR              84\n#define DUK_OP_BXOR_CR              85\n#define DUK_OP_BXOR_RC              86\n#define DUK_OP_BXOR_CC              87\n#define DUK_OP_BASL                 88\n#define DUK_OP_BASL_RR              88\n#define DUK_OP_BASL_CR              89\n#define DUK_OP_BASL_RC              90\n#define DUK_OP_BASL_CC              91\n#define DUK_OP_BLSR                 92\n#define DUK_OP_BLSR_RR              92\n#define DUK_OP_BLSR_CR              93\n#define DUK_OP_BLSR_RC              94\n#define DUK_OP_BLSR_CC              95\n#define DUK_OP_BASR                 96\n#define DUK_OP_BASR_RR              96\n#define DUK_OP_BASR_CR              97\n#define DUK_OP_BASR_RC              98\n#define DUK_OP_BASR_CC              99\n#define DUK_OP_INSTOF               100\n#define DUK_OP_INSTOF_RR            100\n#define DUK_OP_INSTOF_CR            101\n#define DUK_OP_INSTOF_RC            102\n#define DUK_OP_INSTOF_CC            103\n#define DUK_OP_IN                   104\n#define DUK_OP_IN_RR                104\n#define DUK_OP_IN_CR                105\n#define DUK_OP_IN_RC                106\n#define DUK_OP_IN_CC                107\n#define DUK_OP_GETPROP              108\n#define DUK_OP_GETPROP_RR           108\n#define DUK_OP_GETPROP_CR           109\n#define DUK_OP_GETPROP_RC           110\n#define DUK_OP_GETPROP_CC           111\n#define DUK_OP_PUTPROP              112\n#define DUK_OP_PUTPROP_RR           112\n#define DUK_OP_PUTPROP_CR           113\n#define DUK_OP_PUTPROP_RC           114\n#define DUK_OP_PUTPROP_CC           115\n#define DUK_OP_DELPROP              116\n#define DUK_OP_DELPROP_RR           116\n#define DUK_OP_DELPROP_CR_UNUSED    117  /* unused now */\n#define DUK_OP_DELPROP_RC           118\n#define DUK_OP_DELPROP_CC_UNUSED    119  /* unused now */\n#define DUK_OP_PREINCR              120  /* pre/post opcode values have constraints, */\n#define DUK_OP_PREDECR              121  /* see duk_js_executor.c and duk_js_compiler.c. */\n#define DUK_OP_POSTINCR             122\n#define DUK_OP_POSTDECR             123\n#define DUK_OP_PREINCV              124\n#define DUK_OP_PREDECV              125\n#define DUK_OP_POSTINCV             126\n#define DUK_OP_POSTDECV             127\n#define DUK_OP_PREINCP              128  /* pre/post inc/dec prop opcodes have constraints */\n#define DUK_OP_PREINCP_RR           128\n#define DUK_OP_PREINCP_CR           129\n#define DUK_OP_PREINCP_RC           130\n#define DUK_OP_PREINCP_CC           131\n#define DUK_OP_PREDECP              132\n#define DUK_OP_PREDECP_RR           132\n#define DUK_OP_PREDECP_CR           133\n#define DUK_OP_PREDECP_RC           134\n#define DUK_OP_PREDECP_CC           135\n#define DUK_OP_POSTINCP             136\n#define DUK_OP_POSTINCP_RR          136\n#define DUK_OP_POSTINCP_CR          137\n#define DUK_OP_POSTINCP_RC          138\n#define DUK_OP_POSTINCP_CC          139\n#define DUK_OP_POSTDECP             140\n#define DUK_OP_POSTDECP_RR          140\n#define DUK_OP_POSTDECP_CR          141\n#define DUK_OP_POSTDECP_RC          142\n#define DUK_OP_POSTDECP_CC          143\n#define DUK_OP_DECLVAR              144\n#define DUK_OP_DECLVAR_RR           144\n#define DUK_OP_DECLVAR_CR           145\n#define DUK_OP_DECLVAR_RC           146\n#define DUK_OP_DECLVAR_CC           147\n#define DUK_OP_REGEXP               148\n#define DUK_OP_REGEXP_RR            148\n#define DUK_OP_REGEXP_CR            149\n#define DUK_OP_REGEXP_RC            150\n#define DUK_OP_REGEXP_CC            151\n#define DUK_OP_CLOSURE              152\n#define DUK_OP_TYPEOF               153\n#define DUK_OP_TYPEOFID             154\n#define DUK_OP_PUTVAR               155\n#define DUK_OP_DELVAR               156\n#define DUK_OP_RETREG               157\n#define DUK_OP_RETUNDEF             158\n#define DUK_OP_RETCONST             159\n#define DUK_OP_RETCONSTN            160  /* return const without incref (e.g. number) */\n#define DUK_OP_LABEL                161\n#define DUK_OP_ENDLABEL             162\n#define DUK_OP_BREAK                163\n#define DUK_OP_CONTINUE             164\n#define DUK_OP_TRYCATCH             165\n#define DUK_OP_ENDTRY               166\n#define DUK_OP_ENDCATCH             167\n#define DUK_OP_ENDFIN               168\n#define DUK_OP_THROW                169\n#define DUK_OP_INVLHS               170\n#define DUK_OP_CSREG                171\n#define DUK_OP_CSVAR                172\n#define DUK_OP_CSVAR_RR             172\n#define DUK_OP_CSVAR_CR             173\n#define DUK_OP_CSVAR_RC             174\n#define DUK_OP_CSVAR_CC             175\n#define DUK_OP_CALL0                176  /* DUK_OP_CALL0 & 0x0F must be zero. */\n#define DUK_OP_CALL1                177\n#define DUK_OP_CALL2                178\n#define DUK_OP_CALL3                179\n#define DUK_OP_CALL4                180\n#define DUK_OP_CALL5                181\n#define DUK_OP_CALL6                182\n#define DUK_OP_CALL7                183\n#define DUK_OP_CALL8                184\n#define DUK_OP_CALL9                185\n#define DUK_OP_CALL10               186\n#define DUK_OP_CALL11               187\n#define DUK_OP_CALL12               188\n#define DUK_OP_CALL13               189\n#define DUK_OP_CALL14               190\n#define DUK_OP_CALL15               191\n#define DUK_OP_NEWOBJ               192\n#define DUK_OP_NEWARR               193\n#define DUK_OP_MPUTOBJ              194\n#define DUK_OP_MPUTOBJI             195\n#define DUK_OP_INITSET              196\n#define DUK_OP_INITGET              197\n#define DUK_OP_MPUTARR              198\n#define DUK_OP_MPUTARRI             199\n#define DUK_OP_SETALEN              200\n#define DUK_OP_INITENUM             201\n#define DUK_OP_NEXTENUM             202\n#define DUK_OP_NEWTARGET            203\n#define DUK_OP_DEBUGGER             204\n#define DUK_OP_NOP                  205\n#define DUK_OP_INVALID              206\n#define DUK_OP_UNUSED207            207\n#define DUK_OP_GETPROPC             208\n#define DUK_OP_GETPROPC_RR          208\n#define DUK_OP_GETPROPC_CR          209\n#define DUK_OP_GETPROPC_RC          210\n#define DUK_OP_GETPROPC_CC          211\n#define DUK_OP_UNUSED212            212\n#define DUK_OP_UNUSED213            213\n#define DUK_OP_UNUSED214            214\n#define DUK_OP_UNUSED215            215\n#define DUK_OP_UNUSED216            216\n#define DUK_OP_UNUSED217            217\n#define DUK_OP_UNUSED218            218\n#define DUK_OP_UNUSED219            219\n#define DUK_OP_UNUSED220            220\n#define DUK_OP_UNUSED221            221\n#define DUK_OP_UNUSED222            222\n#define DUK_OP_UNUSED223            223\n#define DUK_OP_UNUSED224            224\n#define DUK_OP_UNUSED225            225\n#define DUK_OP_UNUSED226            226\n#define DUK_OP_UNUSED227            227\n#define DUK_OP_UNUSED228            228\n#define DUK_OP_UNUSED229            229\n#define DUK_OP_UNUSED230            230\n#define DUK_OP_UNUSED231            231\n#define DUK_OP_UNUSED232            232\n#define DUK_OP_UNUSED233            233\n#define DUK_OP_UNUSED234            234\n#define DUK_OP_UNUSED235            235\n#define DUK_OP_UNUSED236            236\n#define DUK_OP_UNUSED237            237\n#define DUK_OP_UNUSED238            238\n#define DUK_OP_UNUSED239            239\n#define DUK_OP_UNUSED240            240\n#define DUK_OP_UNUSED241            241\n#define DUK_OP_UNUSED242            242\n#define DUK_OP_UNUSED243            243\n#define DUK_OP_UNUSED244            244\n#define DUK_OP_UNUSED245            245\n#define DUK_OP_UNUSED246            246\n#define DUK_OP_UNUSED247            247\n#define DUK_OP_UNUSED248            248\n#define DUK_OP_UNUSED249            249\n#define DUK_OP_UNUSED250            250\n#define DUK_OP_UNUSED251            251\n#define DUK_OP_UNUSED252            252\n#define DUK_OP_UNUSED253            253\n#define DUK_OP_UNUSED254            254\n#define DUK_OP_UNUSED255            255\n#define DUK_OP_NONE                 256  /* dummy value used as marker (doesn't fit in 8-bit field) */\n\n/* XXX: Allocate flags from opcode field?  Would take 16 opcode slots\n * but avoids shuffling in more cases.  Maybe not worth it.\n */\n/* DUK_OP_TRYCATCH flags in A. */\n#define DUK_BC_TRYCATCH_FLAG_HAVE_CATCH     (1U << 0)\n#define DUK_BC_TRYCATCH_FLAG_HAVE_FINALLY   (1U << 1)\n#define DUK_BC_TRYCATCH_FLAG_CATCH_BINDING  (1U << 2)\n#define DUK_BC_TRYCATCH_FLAG_WITH_BINDING   (1U << 3)\n\n/* DUK_OP_DECLVAR flags in A; bottom bits are reserved for propdesc flags\n * (DUK_PROPDESC_FLAG_XXX).\n */\n#define DUK_BC_DECLVAR_FLAG_FUNC_DECL       (1U << 4)  /* function declaration */\n\n/* DUK_OP_CALLn flags, part of opcode field.  Three lowest bits must match\n * DUK_CALL_FLAG_xxx directly.\n */\n#define DUK_BC_CALL_FLAG_TAILCALL           (1U << 0)\n#define DUK_BC_CALL_FLAG_CONSTRUCT          (1U << 1)\n#define DUK_BC_CALL_FLAG_CALLED_AS_EVAL     (1U << 2)\n#define DUK_BC_CALL_FLAG_INDIRECT           (1U << 3)\n\n/* Misc constants and helper macros. */\n#define DUK_BC_LDINT_BIAS           (1L << 15)\n#define DUK_BC_LDINTX_SHIFT         16\n#define DUK_BC_JUMP_BIAS            (1L << 23)\n\n#endif  /* DUK_JS_BYTECODE_H_INCLUDED */\n/* #include duk_lexer.h */\n#line 1 \"duk_lexer.h\"\n/*\n *  Lexer defines.\n */\n\n#if !defined(DUK_LEXER_H_INCLUDED)\n#define DUK_LEXER_H_INCLUDED\n\ntypedef void (*duk_re_range_callback)(void *user, duk_codepoint_t r1, duk_codepoint_t r2, duk_bool_t direct);\n\n/*\n *  A token is interpreted as any possible production of InputElementDiv\n *  and InputElementRegExp, see E5 Section 7 in its entirety.  Note that\n *  the E5 \"Token\" production does not cover all actual tokens of the\n *  language (which is explicitly stated in the specification, Section 7.5).\n *  Null and boolean literals are defined as part of both ReservedWord\n *  (E5 Section 7.6.1) and Literal (E5 Section 7.8) productions.  Here,\n *  null and boolean values have literal tokens, and are not reserved\n *  words.\n *\n *  Decimal literal negative/positive sign is -not- part of DUK_TOK_NUMBER.\n *  The number tokens always have a non-negative value.  The unary minus\n *  operator in \"-1.0\" is optimized during compilation to yield a single\n *  negative constant.\n *\n *  Token numbering is free except that reserved words are required to be\n *  in a continuous range and in a particular order.  See genstrings.py.\n */\n\n#define DUK_LEXER_INITCTX(ctx)        duk_lexer_initctx((ctx))\n\n#define DUK_LEXER_SETPOINT(ctx,pt)    duk_lexer_setpoint((ctx), (pt))\n\n#define DUK_LEXER_GETPOINT(ctx,pt)    duk_lexer_getpoint((ctx), (pt))\n\n/* Currently 6 characters of lookup are actually needed (duk_lexer.c). */\n#define DUK_LEXER_WINDOW_SIZE                     6\n#if defined(DUK_USE_LEXER_SLIDING_WINDOW)\n#define DUK_LEXER_BUFFER_SIZE                     64\n#endif\n\n#define DUK_TOK_MINVAL                            0\n\n/* returned after EOF (infinite amount) */\n#define DUK_TOK_EOF                               0\n\n/* identifier names (E5 Section 7.6) */\n#define DUK_TOK_IDENTIFIER                        1\n\n/* reserved words: keywords */\n#define DUK_TOK_START_RESERVED                    2\n#define DUK_TOK_BREAK                             2\n#define DUK_TOK_CASE                              3\n#define DUK_TOK_CATCH                             4\n#define DUK_TOK_CONTINUE                          5\n#define DUK_TOK_DEBUGGER                          6\n#define DUK_TOK_DEFAULT                           7\n#define DUK_TOK_DELETE                            8\n#define DUK_TOK_DO                                9\n#define DUK_TOK_ELSE                              10\n#define DUK_TOK_FINALLY                           11\n#define DUK_TOK_FOR                               12\n#define DUK_TOK_FUNCTION                          13\n#define DUK_TOK_IF                                14\n#define DUK_TOK_IN                                15\n#define DUK_TOK_INSTANCEOF                        16\n#define DUK_TOK_NEW                               17\n#define DUK_TOK_RETURN                            18\n#define DUK_TOK_SWITCH                            19\n#define DUK_TOK_THIS                              20\n#define DUK_TOK_THROW                             21\n#define DUK_TOK_TRY                               22\n#define DUK_TOK_TYPEOF                            23\n#define DUK_TOK_VAR                               24\n#define DUK_TOK_CONST                             25\n#define DUK_TOK_VOID                              26\n#define DUK_TOK_WHILE                             27\n#define DUK_TOK_WITH                              28\n\n/* reserved words: future reserved words */\n#define DUK_TOK_CLASS                             29\n#define DUK_TOK_ENUM                              30\n#define DUK_TOK_EXPORT                            31\n#define DUK_TOK_EXTENDS                           32\n#define DUK_TOK_IMPORT                            33\n#define DUK_TOK_SUPER                             34\n\n/* \"null\", \"true\", and \"false\" are always reserved words.\n * Note that \"get\" and \"set\" are not!\n */\n#define DUK_TOK_NULL                              35\n#define DUK_TOK_TRUE                              36\n#define DUK_TOK_FALSE                             37\n\n/* reserved words: additional future reserved words in strict mode */\n#define DUK_TOK_START_STRICT_RESERVED             38  /* inclusive */\n#define DUK_TOK_IMPLEMENTS                        38\n#define DUK_TOK_INTERFACE                         39\n#define DUK_TOK_LET                               40\n#define DUK_TOK_PACKAGE                           41\n#define DUK_TOK_PRIVATE                           42\n#define DUK_TOK_PROTECTED                         43\n#define DUK_TOK_PUBLIC                            44\n#define DUK_TOK_STATIC                            45\n#define DUK_TOK_YIELD                             46\n\n#define DUK_TOK_END_RESERVED                      47  /* exclusive */\n\n/* \"get\" and \"set\" are tokens but NOT ReservedWords.  They are currently\n * parsed and identifiers and these defines are actually now unused.\n */\n#define DUK_TOK_GET                               47\n#define DUK_TOK_SET                               48\n\n/* punctuators (unlike the spec, also includes \"/\" and \"/=\") */\n#define DUK_TOK_LCURLY                            49\n#define DUK_TOK_RCURLY                            50\n#define DUK_TOK_LBRACKET                          51\n#define DUK_TOK_RBRACKET                          52\n#define DUK_TOK_LPAREN                            53\n#define DUK_TOK_RPAREN                            54\n#define DUK_TOK_PERIOD                            55\n#define DUK_TOK_SEMICOLON                         56\n#define DUK_TOK_COMMA                             57\n#define DUK_TOK_LT                                58\n#define DUK_TOK_GT                                59\n#define DUK_TOK_LE                                60\n#define DUK_TOK_GE                                61\n#define DUK_TOK_EQ                                62\n#define DUK_TOK_NEQ                               63\n#define DUK_TOK_SEQ                               64\n#define DUK_TOK_SNEQ                              65\n#define DUK_TOK_ADD                               66\n#define DUK_TOK_SUB                               67\n#define DUK_TOK_MUL                               68\n#define DUK_TOK_DIV                               69\n#define DUK_TOK_MOD                               70\n#define DUK_TOK_EXP                               71\n#define DUK_TOK_INCREMENT                         72\n#define DUK_TOK_DECREMENT                         73\n#define DUK_TOK_ALSHIFT                           74   /* named \"arithmetic\" because result is signed */\n#define DUK_TOK_ARSHIFT                           75\n#define DUK_TOK_RSHIFT                            76\n#define DUK_TOK_BAND                              77\n#define DUK_TOK_BOR                               78\n#define DUK_TOK_BXOR                              79\n#define DUK_TOK_LNOT                              80\n#define DUK_TOK_BNOT                              81\n#define DUK_TOK_LAND                              82\n#define DUK_TOK_LOR                               83\n#define DUK_TOK_QUESTION                          84\n#define DUK_TOK_COLON                             85\n#define DUK_TOK_EQUALSIGN                         86\n#define DUK_TOK_ADD_EQ                            87\n#define DUK_TOK_SUB_EQ                            88\n#define DUK_TOK_MUL_EQ                            89\n#define DUK_TOK_DIV_EQ                            90\n#define DUK_TOK_MOD_EQ                            91\n#define DUK_TOK_EXP_EQ                            92\n#define DUK_TOK_ALSHIFT_EQ                        93\n#define DUK_TOK_ARSHIFT_EQ                        94\n#define DUK_TOK_RSHIFT_EQ                         95\n#define DUK_TOK_BAND_EQ                           96\n#define DUK_TOK_BOR_EQ                            97\n#define DUK_TOK_BXOR_EQ                           98\n\n/* literals (E5 Section 7.8), except null, true, false, which are treated\n * like reserved words (above).\n */\n#define DUK_TOK_NUMBER                            99\n#define DUK_TOK_STRING                            100\n#define DUK_TOK_REGEXP                            101\n\n#define DUK_TOK_MAXVAL                            101  /* inclusive */\n\n#define DUK_TOK_INVALID                           DUK_SMALL_UINT_MAX\n\n/* Convert heap string index to a token (reserved words) */\n#define DUK_STRIDX_TO_TOK(x)                        ((x) - DUK_STRIDX_START_RESERVED + DUK_TOK_START_RESERVED)\n\n/* Sanity check */\n#if (DUK_TOK_MAXVAL > 255)\n#error DUK_TOK_MAXVAL too large, code assumes it fits into 8 bits\n#endif\n\n/* Sanity checks for string and token defines */\n#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_BREAK) != DUK_TOK_BREAK)\n#error mismatch in token defines\n#endif\n#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_CASE) != DUK_TOK_CASE)\n#error mismatch in token defines\n#endif\n#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_CATCH) != DUK_TOK_CATCH)\n#error mismatch in token defines\n#endif\n#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_CONTINUE) != DUK_TOK_CONTINUE)\n#error mismatch in token defines\n#endif\n#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_DEBUGGER) != DUK_TOK_DEBUGGER)\n#error mismatch in token defines\n#endif\n#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_DEFAULT) != DUK_TOK_DEFAULT)\n#error mismatch in token defines\n#endif\n#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_DELETE) != DUK_TOK_DELETE)\n#error mismatch in token defines\n#endif\n#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_DO) != DUK_TOK_DO)\n#error mismatch in token defines\n#endif\n#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_ELSE) != DUK_TOK_ELSE)\n#error mismatch in token defines\n#endif\n#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_FINALLY) != DUK_TOK_FINALLY)\n#error mismatch in token defines\n#endif\n#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_FOR) != DUK_TOK_FOR)\n#error mismatch in token defines\n#endif\n#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_LC_FUNCTION) != DUK_TOK_FUNCTION)\n#error mismatch in token defines\n#endif\n#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_IF) != DUK_TOK_IF)\n#error mismatch in token defines\n#endif\n#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_IN) != DUK_TOK_IN)\n#error mismatch in token defines\n#endif\n#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_INSTANCEOF) != DUK_TOK_INSTANCEOF)\n#error mismatch in token defines\n#endif\n#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_NEW) != DUK_TOK_NEW)\n#error mismatch in token defines\n#endif\n#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_RETURN) != DUK_TOK_RETURN)\n#error mismatch in token defines\n#endif\n#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_SWITCH) != DUK_TOK_SWITCH)\n#error mismatch in token defines\n#endif\n#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_THIS) != DUK_TOK_THIS)\n#error mismatch in token defines\n#endif\n#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_THROW) != DUK_TOK_THROW)\n#error mismatch in token defines\n#endif\n#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_TRY) != DUK_TOK_TRY)\n#error mismatch in token defines\n#endif\n#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_TYPEOF) != DUK_TOK_TYPEOF)\n#error mismatch in token defines\n#endif\n#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_VAR) != DUK_TOK_VAR)\n#error mismatch in token defines\n#endif\n#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_VOID) != DUK_TOK_VOID)\n#error mismatch in token defines\n#endif\n#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_WHILE) != DUK_TOK_WHILE)\n#error mismatch in token defines\n#endif\n#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_WITH) != DUK_TOK_WITH)\n#error mismatch in token defines\n#endif\n#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_CLASS) != DUK_TOK_CLASS)\n#error mismatch in token defines\n#endif\n#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_CONST) != DUK_TOK_CONST)\n#error mismatch in token defines\n#endif\n#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_ENUM) != DUK_TOK_ENUM)\n#error mismatch in token defines\n#endif\n#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_EXPORT) != DUK_TOK_EXPORT)\n#error mismatch in token defines\n#endif\n#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_EXTENDS) != DUK_TOK_EXTENDS)\n#error mismatch in token defines\n#endif\n#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_IMPORT) != DUK_TOK_IMPORT)\n#error mismatch in token defines\n#endif\n#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_SUPER) != DUK_TOK_SUPER)\n#error mismatch in token defines\n#endif\n#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_LC_NULL) != DUK_TOK_NULL)\n#error mismatch in token defines\n#endif\n#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_TRUE) != DUK_TOK_TRUE)\n#error mismatch in token defines\n#endif\n#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_FALSE) != DUK_TOK_FALSE)\n#error mismatch in token defines\n#endif\n#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_IMPLEMENTS) != DUK_TOK_IMPLEMENTS)\n#error mismatch in token defines\n#endif\n#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_INTERFACE) != DUK_TOK_INTERFACE)\n#error mismatch in token defines\n#endif\n#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_LET) != DUK_TOK_LET)\n#error mismatch in token defines\n#endif\n#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_PACKAGE) != DUK_TOK_PACKAGE)\n#error mismatch in token defines\n#endif\n#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_PRIVATE) != DUK_TOK_PRIVATE)\n#error mismatch in token defines\n#endif\n#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_PROTECTED) != DUK_TOK_PROTECTED)\n#error mismatch in token defines\n#endif\n#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_PUBLIC) != DUK_TOK_PUBLIC)\n#error mismatch in token defines\n#endif\n#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_STATIC) != DUK_TOK_STATIC)\n#error mismatch in token defines\n#endif\n#if (DUK_STRIDX_TO_TOK(DUK_STRIDX_YIELD) != DUK_TOK_YIELD)\n#error mismatch in token defines\n#endif\n\n/* Regexp tokens */\n#define DUK_RETOK_EOF                              0\n#define DUK_RETOK_DISJUNCTION                      1\n#define DUK_RETOK_QUANTIFIER                       2\n#define DUK_RETOK_ASSERT_START                     3\n#define DUK_RETOK_ASSERT_END                       4\n#define DUK_RETOK_ASSERT_WORD_BOUNDARY             5\n#define DUK_RETOK_ASSERT_NOT_WORD_BOUNDARY         6\n#define DUK_RETOK_ASSERT_START_POS_LOOKAHEAD       7\n#define DUK_RETOK_ASSERT_START_NEG_LOOKAHEAD       8\n#define DUK_RETOK_ATOM_PERIOD                      9\n#define DUK_RETOK_ATOM_CHAR                        10\n#define DUK_RETOK_ATOM_DIGIT                       11  /* assumptions in regexp compiler */\n#define DUK_RETOK_ATOM_NOT_DIGIT                   12  /* -\"\"- */\n#define DUK_RETOK_ATOM_WHITE                       13  /* -\"\"- */\n#define DUK_RETOK_ATOM_NOT_WHITE                   14  /* -\"\"- */\n#define DUK_RETOK_ATOM_WORD_CHAR                   15  /* -\"\"- */\n#define DUK_RETOK_ATOM_NOT_WORD_CHAR               16  /* -\"\"- */\n#define DUK_RETOK_ATOM_BACKREFERENCE               17\n#define DUK_RETOK_ATOM_START_CAPTURE_GROUP         18\n#define DUK_RETOK_ATOM_START_NONCAPTURE_GROUP      19\n#define DUK_RETOK_ATOM_START_CHARCLASS             20\n#define DUK_RETOK_ATOM_START_CHARCLASS_INVERTED    21\n#define DUK_RETOK_ATOM_END_GROUP                   22\n\n/* Constants for duk_lexer_ctx.buf. */\n#define DUK_LEXER_TEMP_BUF_LIMIT                   256\n\n/* A token value.  Can be memcpy()'d, but note that slot1/slot2 values are on the valstack.\n * Some fields (like num, str1, str2) are only valid for specific token types and may have\n * stale values otherwise.\n */\nstruct duk_token {\n\tduk_small_uint_t t;           /* token type (with reserved word identification) */\n\tduk_small_uint_t t_nores;     /* token type (with reserved words as DUK_TOK_IDENTIFER) */\n\tduk_double_t num;             /* numeric value of token */\n\tduk_hstring *str1;            /* string 1 of token (borrowed, stored to ctx->slot1_idx) */\n\tduk_hstring *str2;            /* string 2 of token (borrowed, stored to ctx->slot2_idx) */\n\tduk_size_t start_offset;      /* start byte offset of token in lexer input */\n\tduk_int_t start_line;         /* start line of token (first char) */\n\tduk_int_t num_escapes;        /* number of escapes and line continuations (for directive prologue) */\n\tduk_bool_t lineterm;          /* token was preceded by a lineterm */\n\tduk_bool_t allow_auto_semi;   /* token allows automatic semicolon insertion (eof or preceded by newline) */\n};\n\n#define DUK_RE_QUANTIFIER_INFINITE         ((duk_uint32_t) 0xffffffffUL)\n\n/* A regexp token value. */\nstruct duk_re_token {\n\tduk_small_uint_t t;          /* token type */\n\tduk_small_uint_t greedy;\n\tduk_uint32_t num;            /* numeric value (character, count) */\n\tduk_uint32_t qmin;\n\tduk_uint32_t qmax;\n};\n\n/* A structure for 'snapshotting' a point for rewinding */\nstruct duk_lexer_point {\n\tduk_size_t offset;\n\tduk_int_t line;\n};\n\n/* Lexer codepoint with additional info like offset/line number */\nstruct duk_lexer_codepoint {\n\tduk_codepoint_t codepoint;\n\tduk_size_t offset;\n\tduk_int_t line;\n};\n\n/* Lexer context.  Same context is used for Ecmascript and Regexp parsing. */\nstruct duk_lexer_ctx {\n#if defined(DUK_USE_LEXER_SLIDING_WINDOW)\n\tduk_lexer_codepoint *window; /* unicode code points, window[0] is always next, points to 'buffer' */\n\tduk_lexer_codepoint buffer[DUK_LEXER_BUFFER_SIZE];\n#else\n\tduk_lexer_codepoint window[DUK_LEXER_WINDOW_SIZE]; /* unicode code points, window[0] is always next */\n#endif\n\n\tduk_hthread *thr;                              /* thread; minimizes argument passing */\n\n\tconst duk_uint8_t *input;                      /* input string (may be a user pointer) */\n\tduk_size_t input_length;                       /* input byte length */\n\tduk_size_t input_offset;                       /* input offset for window leading edge (not window[0]) */\n\tduk_int_t input_line;                          /* input linenumber at input_offset (not window[0]), init to 1 */\n\n\tduk_idx_t slot1_idx;                           /* valstack slot for 1st token value */\n\tduk_idx_t slot2_idx;                           /* valstack slot for 2nd token value */\n\tduk_idx_t buf_idx;                             /* valstack slot for temp buffer */\n\tduk_hbuffer_dynamic *buf;                      /* temp accumulation buffer */\n\tduk_bufwriter_ctx bw;                          /* bufwriter for temp accumulation */\n\n\tduk_int_t token_count;                         /* number of tokens parsed */\n\tduk_int_t token_limit;                         /* maximum token count before error (sanity backstop) */\n\n\tduk_small_uint_t flags;                        /* lexer flags, use compiler flag defines for now */\n};\n\n/*\n *  Prototypes\n */\n\nDUK_INTERNAL_DECL void duk_lexer_initctx(duk_lexer_ctx *lex_ctx);\n\nDUK_INTERNAL_DECL void duk_lexer_getpoint(duk_lexer_ctx *lex_ctx, duk_lexer_point *pt);\nDUK_INTERNAL_DECL void duk_lexer_setpoint(duk_lexer_ctx *lex_ctx, duk_lexer_point *pt);\n\nDUK_INTERNAL_DECL\nvoid duk_lexer_parse_js_input_element(duk_lexer_ctx *lex_ctx,\n                                      duk_token *out_token,\n                                      duk_bool_t strict_mode,\n                                      duk_bool_t regexp_mode);\n#if defined(DUK_USE_REGEXP_SUPPORT)\nDUK_INTERNAL_DECL void duk_lexer_parse_re_token(duk_lexer_ctx *lex_ctx, duk_re_token *out_token);\nDUK_INTERNAL_DECL void duk_lexer_parse_re_ranges(duk_lexer_ctx *lex_ctx, duk_re_range_callback gen_range, void *userdata);\n#endif  /* DUK_USE_REGEXP_SUPPORT */\n\n#endif  /* DUK_LEXER_H_INCLUDED */\n/* #include duk_js_compiler.h */\n#line 1 \"duk_js_compiler.h\"\n/*\n *  Ecmascript compiler.\n */\n\n#if !defined(DUK_JS_COMPILER_H_INCLUDED)\n#define DUK_JS_COMPILER_H_INCLUDED\n\n/* ecmascript compiler limits */\n#define DUK_COMPILER_TOKEN_LIMIT           100000000L  /* 1e8: protects against deeply nested inner functions */\n\n/* maximum loopcount for peephole optimization */\n#define DUK_COMPILER_PEEPHOLE_MAXITER      3\n\n/* maximum bytecode length in instructions */\n#define DUK_COMPILER_MAX_BYTECODE_LENGTH   (256L * 1024L * 1024L)  /* 1 GB */\n\n/*\n *  Compiler intermediate values\n *\n *  Intermediate values describe either plain values (e.g. strings or\n *  numbers) or binary operations which have not yet been coerced into\n *  either a left-hand-side or right-hand-side role (e.g. object property).\n */\n\n#define DUK_IVAL_NONE          0   /* no value */\n#define DUK_IVAL_PLAIN         1   /* register, constant, or value */\n#define DUK_IVAL_ARITH         2   /* binary arithmetic; DUK_OP_ADD, DUK_OP_EQ, other binary ops */\n#define DUK_IVAL_PROP          3   /* property access */\n#define DUK_IVAL_VAR           4   /* variable access */\n\n#define DUK_ISPEC_NONE         0   /* no value */\n#define DUK_ISPEC_VALUE        1   /* value resides in 'valstack_idx' */\n#define DUK_ISPEC_REGCONST     2   /* value resides in a register or constant */\n\n/* Bit mask which indicates that a regconst is a constant instead of a register.\n * Chosen so that when a regconst is cast to duk_int32_t, all consts are\n * negative values.\n */\n#define DUK_REGCONST_CONST_MARKER    DUK_INT32_MIN  /* = -0x80000000 */\n\n/* Type to represent a reg/const reference during compilation, with <0\n * indicating a constant.  Some call sites also use -1 to indicate 'none'.\n */\ntypedef duk_int32_t duk_regconst_t;\n\ntypedef struct {\n\tduk_small_uint_t t;          /* DUK_ISPEC_XXX */\n\tduk_regconst_t regconst;\n\tduk_idx_t valstack_idx;      /* always set; points to a reserved valstack slot */\n} duk_ispec;\n\ntypedef struct {\n\t/*\n\t *  PLAIN: x1\n\t *  ARITH: x1 <op> x2\n\t *  PROP: x1.x2\n\t *  VAR: x1 (name)\n\t */\n\n\t/* XXX: can be optimized for smaller footprint esp. on 32-bit environments */\n\tduk_small_uint_t t;          /* DUK_IVAL_XXX */\n\tduk_small_uint_t op;         /* bytecode opcode for binary ops */\n\tduk_ispec x1;\n\tduk_ispec x2;\n} duk_ivalue;\n\n/*\n *  Bytecode instruction representation during compilation\n *\n *  Contains the actual instruction and (optionally) debug info.\n */\n\nstruct duk_compiler_instr {\n\tduk_instr_t ins;\n#if defined(DUK_USE_PC2LINE)\n\tduk_uint32_t line;\n#endif\n};\n\n/*\n *  Compiler state\n */\n\n#define DUK_LABEL_FLAG_ALLOW_BREAK       (1U << 0)\n#define DUK_LABEL_FLAG_ALLOW_CONTINUE    (1U << 1)\n\n#define DUK_DECL_TYPE_VAR                0\n#define DUK_DECL_TYPE_FUNC               1\n\n/* XXX: optimize to 16 bytes */\ntypedef struct {\n\tduk_small_uint_t flags;\n\tduk_int_t label_id;          /* numeric label_id (-1 reserved as marker) */\n\tduk_hstring *h_label;        /* borrowed label name */\n\tduk_int_t catch_depth;       /* catch depth at point of definition */\n\tduk_int_t pc_label;          /* pc of label statement:\n\t                              * pc+1: break jump site\n\t                              * pc+2: continue jump site\n\t                              */\n\n\t/* Fast jumps (which avoid longjmp) jump directly to the jump sites\n\t * which are always known even while the iteration/switch statement\n\t * is still being parsed.  A final peephole pass \"straightens out\"\n\t * the jumps.\n\t */\n} duk_labelinfo;\n\n/* Compiling state of one function, eventually converted to duk_hcompfunc */\nstruct duk_compiler_func {\n\t/* These pointers are at the start of the struct so that they pack\n\t * nicely.  Mixing pointers and integer values is bad on some\n\t * platforms (e.g. if int is 32 bits and pointers are 64 bits).\n\t */\n\n\tduk_bufwriter_ctx bw_code;          /* bufwriter for code */\n\n\tduk_hstring *h_name;                /* function name (borrowed reference), ends up in _name */\n\t/* h_code: held in bw_code */\n\tduk_hobject *h_consts;              /* array */\n\tduk_hobject *h_funcs;               /* array of function templates: [func1, offset1, line1, func2, offset2, line2]\n\t                                     * offset/line points to closing brace to allow skipping on pass 2\n\t                                     */\n\tduk_hobject *h_decls;               /* array of declarations: [ name1, val1, name2, val2, ... ]\n\t                                     * valN = (typeN) | (fnum << 8), where fnum is inner func number (0 for vars)\n\t                                     * record function and variable declarations in pass 1\n\t                                     */\n\tduk_hobject *h_labelnames;          /* array of active label names */\n\tduk_hbuffer_dynamic *h_labelinfos;  /* C array of duk_labelinfo */\n\tduk_hobject *h_argnames;            /* array of formal argument names (-> _Formals) */\n\tduk_hobject *h_varmap;              /* variable map for pass 2 (identifier -> register number or null (unmapped)) */\n\n\t/* Value stack indices for tracking objects. */\n\t/* code_idx: not needed */\n\tduk_idx_t consts_idx;\n\tduk_idx_t funcs_idx;\n\tduk_idx_t decls_idx;\n\tduk_idx_t labelnames_idx;\n\tduk_idx_t labelinfos_idx;\n\tduk_idx_t argnames_idx;\n\tduk_idx_t varmap_idx;\n\n\t/* Temp reg handling. */\n\tduk_regconst_t temp_first;           /* first register that is a temporary (below: variables) */\n\tduk_regconst_t temp_next;            /* next temporary register to allocate */\n\tduk_regconst_t temp_max;             /* highest value of temp_reg (temp_max - 1 is highest used reg) */\n\n\t/* Shuffle registers if large number of regs/consts. */\n\tduk_regconst_t shuffle1;\n\tduk_regconst_t shuffle2;\n\tduk_regconst_t shuffle3;\n\n\t/* Stats for current expression being parsed. */\n\tduk_int_t nud_count;\n\tduk_int_t led_count;\n\tduk_int_t paren_level;              /* parenthesis count, 0 = top level */\n\tduk_bool_t expr_lhs;                /* expression is left-hand-side compatible */\n\tduk_bool_t allow_in;                /* current paren level allows 'in' token */\n\n\t/* Misc. */\n\tduk_int_t stmt_next;                /* statement id allocation (running counter) */\n\tduk_int_t label_next;               /* label id allocation (running counter) */\n\tduk_int_t catch_depth;              /* catch stack depth */\n\tduk_int_t with_depth;               /* with stack depth (affects identifier lookups) */\n\tduk_int_t fnum_next;                /* inner function numbering */\n\tduk_int_t num_formals;              /* number of formal arguments */\n\tduk_regconst_t reg_stmt_value;      /* register for writing value of 'non-empty' statements (global or eval code), -1 is marker */\n#if defined(DUK_USE_DEBUGGER_SUPPORT)\n\tduk_int_t min_line;                 /* XXX: typing (duk_hcompfunc has duk_uint32_t) */\n\tduk_int_t max_line;\n#endif\n\n\t/* Status booleans. */\n\tduk_uint8_t is_function;             /* is an actual function (not global/eval code) */\n\tduk_uint8_t is_eval;                 /* is eval code */\n\tduk_uint8_t is_global;               /* is global code */\n\tduk_uint8_t is_namebinding;          /* needs a name binding */\n\tduk_uint8_t is_constructable;        /* result is constructable */\n\tduk_uint8_t is_setget;               /* is a setter/getter */\n\tduk_uint8_t is_strict;               /* function is strict */\n\tduk_uint8_t is_notail;               /* function must not be tail called */\n\tduk_uint8_t in_directive_prologue;   /* parsing in \"directive prologue\", recognize directives */\n\tduk_uint8_t in_scanning;             /* parsing in \"scanning\" phase (first pass) */\n\tduk_uint8_t may_direct_eval;         /* function may call direct eval */\n\tduk_uint8_t id_access_arguments;     /* function refers to 'arguments' identifier */\n\tduk_uint8_t id_access_slow;          /* function makes one or more slow path accesses that won't match own static variables */\n\tduk_uint8_t id_access_slow_own;      /* function makes one or more slow path accesses that may match own static variables */\n\tduk_uint8_t is_arguments_shadowed;   /* argument/function declaration shadows 'arguments' */\n\tduk_uint8_t needs_shuffle;           /* function needs shuffle registers */\n\tduk_uint8_t reject_regexp_in_adv;    /* reject RegExp literal on next advance() call; needed for handling IdentifierName productions */\n};\n\nstruct duk_compiler_ctx {\n\tduk_hthread *thr;\n\n\t/* filename being compiled (ends up in functions' '_filename' property) */\n\tduk_hstring *h_filename;            /* borrowed reference */\n\n\t/* lexing (tokenization) state (contains two valstack slot indices) */\n\tduk_lexer_ctx lex;\n\n\t/* current and previous token for parsing */\n\tduk_token prev_token;\n\tduk_token curr_token;\n\tduk_idx_t tok11_idx;                /* curr_token slot1 (matches 'lex' slot1_idx) */\n\tduk_idx_t tok12_idx;                /* curr_token slot2 (matches 'lex' slot2_idx) */\n\tduk_idx_t tok21_idx;                /* prev_token slot1 */\n\tduk_idx_t tok22_idx;                /* prev_token slot2 */\n\n\t/* recursion limit */\n\tduk_int_t recursion_depth;\n\tduk_int_t recursion_limit;\n\n\t/* code emission temporary */\n\tduk_int_t emit_jumpslot_pc;\n\n\t/* current function being compiled (embedded instead of pointer for more compact access) */\n\tduk_compiler_func curr_func;\n};\n\n/*\n *  Prototypes\n */\n\nDUK_INTERNAL_DECL void duk_js_compile(duk_hthread *thr, const duk_uint8_t *src_buffer, duk_size_t src_length, duk_small_uint_t flags);\n\n#endif  /* DUK_JS_COMPILER_H_INCLUDED */\n/* #include duk_regexp.h */\n#line 1 \"duk_regexp.h\"\n/*\n *  Regular expression structs, constants, and bytecode defines.\n */\n\n#if !defined(DUK_REGEXP_H_INCLUDED)\n#define DUK_REGEXP_H_INCLUDED\n\n/* maximum bytecode copies for {n,m} quantifiers */\n#define DUK_RE_MAX_ATOM_COPIES             1000\n\n/* regexp compilation limits */\n#define DUK_RE_COMPILE_TOKEN_LIMIT         100000000L   /* 1e8 */\n\n/* regexp execution limits */\n#define DUK_RE_EXECUTE_STEPS_LIMIT         1000000000L  /* 1e9 */\n\n/* regexp opcodes */\n#define DUK_REOP_MATCH                     1\n#define DUK_REOP_CHAR                      2\n#define DUK_REOP_PERIOD                    3\n#define DUK_REOP_RANGES                    4\n#define DUK_REOP_INVRANGES                 5\n#define DUK_REOP_JUMP                      6\n#define DUK_REOP_SPLIT1                    7\n#define DUK_REOP_SPLIT2                    8\n#define DUK_REOP_SQMINIMAL                 9\n#define DUK_REOP_SQGREEDY                  10\n#define DUK_REOP_SAVE                      11\n#define DUK_REOP_WIPERANGE                 12\n#define DUK_REOP_LOOKPOS                   13\n#define DUK_REOP_LOOKNEG                   14\n#define DUK_REOP_BACKREFERENCE             15\n#define DUK_REOP_ASSERT_START              16\n#define DUK_REOP_ASSERT_END                17\n#define DUK_REOP_ASSERT_WORD_BOUNDARY      18\n#define DUK_REOP_ASSERT_NOT_WORD_BOUNDARY  19\n\n/* flags */\n#define DUK_RE_FLAG_GLOBAL                 (1U << 0)\n#define DUK_RE_FLAG_IGNORE_CASE            (1U << 1)\n#define DUK_RE_FLAG_MULTILINE              (1U << 2)\n\nstruct duk_re_matcher_ctx {\n\tduk_hthread *thr;\n\n\tduk_uint32_t re_flags;\n\tconst duk_uint8_t *input;\n\tconst duk_uint8_t *input_end;\n\tconst duk_uint8_t *bytecode;\n\tconst duk_uint8_t *bytecode_end;\n\tconst duk_uint8_t **saved;  /* allocated from valstack (fixed buffer) */\n\tduk_uint32_t nsaved;\n\tduk_uint32_t recursion_depth;\n\tduk_uint32_t recursion_limit;\n\tduk_uint32_t steps_count;\n\tduk_uint32_t steps_limit;\n};\n\nstruct duk_re_compiler_ctx {\n\tduk_hthread *thr;\n\n\tduk_uint32_t re_flags;\n\tduk_lexer_ctx lex;\n\tduk_re_token curr_token;\n\tduk_bufwriter_ctx bw;\n\tduk_uint32_t captures;  /* highest capture number emitted so far (used as: ++captures) */\n\tduk_uint32_t highest_backref;\n\tduk_uint32_t recursion_depth;\n\tduk_uint32_t recursion_limit;\n\tduk_uint32_t nranges;  /* internal temporary value, used for char classes */\n};\n\n/*\n *  Prototypes\n */\n\n#if defined(DUK_USE_REGEXP_SUPPORT)\nDUK_INTERNAL_DECL void duk_regexp_compile(duk_hthread *thr);\nDUK_INTERNAL_DECL void duk_regexp_create_instance(duk_hthread *thr);\nDUK_INTERNAL_DECL void duk_regexp_match(duk_hthread *thr);\nDUK_INTERNAL_DECL void duk_regexp_match_force_global(duk_hthread *thr);  /* hacky helper for String.prototype.split() */\n#endif\n\n#endif  /* DUK_REGEXP_H_INCLUDED */\n/* #include duk_heaphdr.h */\n#line 1 \"duk_heaphdr.h\"\n/*\n *  Heap header definition and assorted macros, including ref counting.\n *  Access all fields through the accessor macros.\n */\n\n#if !defined(DUK_HEAPHDR_H_INCLUDED)\n#define DUK_HEAPHDR_H_INCLUDED\n\n/*\n *  Common heap header\n *\n *  All heap objects share the same flags and refcount fields.  Objects other\n *  than strings also need to have a single or double linked list pointers\n *  for insertion into the \"heap allocated\" list.  Strings have single linked\n *  list pointers for string table chaining.\n *\n *  Technically, 'h_refcount' must be wide enough to guarantee that it cannot\n *  wrap; otherwise objects might be freed incorrectly after wrapping.  The\n *  default refcount field is 32 bits even on 64-bit systems: while that's in\n *  theory incorrect, the Duktape heap needs to be larger than 64GB for the\n *  count to actually wrap (assuming 16-byte duk_tvals).  This is very unlikely\n *  to ever be an issue, but if it is, disabling DUK_USE_REFCOUNT32 causes\n *  Duktape to use size_t for refcounts which should always be safe.\n *\n *  Heap header size on 32-bit platforms: 8 bytes without reference counting,\n *  16 bytes with reference counting.\n *\n *  Note that 'raw' macros such as DUK_HEAPHDR_GET_REFCOUNT() are not\n *  defined without DUK_USE_REFERENCE_COUNTING, so caller must #if defined()\n *  around them.\n */\n\n/* XXX: macro for shared header fields (avoids some padding issues) */\n\nstruct duk_heaphdr {\n\tduk_uint32_t h_flags;\n\n#if defined(DUK_USE_REFERENCE_COUNTING)\n#if defined(DUK_USE_ASSERTIONS)\n\t/* When assertions enabled, used by mark-and-sweep for refcount\n\t * validation.  Largest reasonable type; also detects overflows.\n\t */\n\tduk_size_t h_assert_refcount;\n#endif\n#if defined(DUK_USE_REFCOUNT16)\n\tduk_uint16_t h_refcount;\n#elif defined(DUK_USE_REFCOUNT32)\n\tduk_uint32_t h_refcount;\n#else\n\tduk_size_t h_refcount;\n#endif\n#endif  /* DUK_USE_REFERENCE_COUNTING */\n\n#if defined(DUK_USE_HEAPPTR16)\n\tduk_uint16_t h_next16;\n#else\n\tduk_heaphdr *h_next;\n#endif\n\n#if defined(DUK_USE_DOUBLE_LINKED_HEAP)\n\t/* refcounting requires direct heap frees, which in turn requires a dual linked heap */\n#if defined(DUK_USE_HEAPPTR16)\n\tduk_uint16_t h_prev16;\n#else\n\tduk_heaphdr *h_prev;\n#endif\n#endif\n\n\t/* When DUK_USE_HEAPPTR16 (and DUK_USE_REFCOUNT16) is in use, the\n\t * struct won't align nicely to 4 bytes.  This 16-bit extra field\n\t * is added to make the alignment clean; the field can be used by\n\t * heap objects when 16-bit packing is used.  This field is now\n\t * conditional to DUK_USE_HEAPPTR16 only, but it is intended to be\n\t * used with DUK_USE_REFCOUNT16 and DUK_USE_DOUBLE_LINKED_HEAP;\n\t * this only matter to low memory environments anyway.\n\t */\n#if defined(DUK_USE_HEAPPTR16)\n\tduk_uint16_t h_extra16;\n#endif\n};\n\nstruct duk_heaphdr_string {\n\t/* 16 bits would be enough for shared heaphdr flags and duk_hstring\n\t * flags.  The initial parts of duk_heaphdr_string and duk_heaphdr\n\t * must match so changing the flags field size here would be quite\n\t * awkward.  However, to minimize struct size, we can pack at least\n\t * 16 bits of duk_hstring data into the flags field.\n\t */\n\tduk_uint32_t h_flags;\n\n#if defined(DUK_USE_REFERENCE_COUNTING)\n#if defined(DUK_USE_ASSERTIONS)\n\t/* When assertions enabled, used by mark-and-sweep for refcount\n\t * validation.  Largest reasonable type; also detects overflows.\n\t */\n\tduk_size_t h_assert_refcount;\n#endif\n#if defined(DUK_USE_REFCOUNT16)\n\tduk_uint16_t h_refcount;\n\tduk_uint16_t h_strextra16;  /* round out to 8 bytes */\n#elif defined(DUK_USE_REFCOUNT32)\n\tduk_uint32_t h_refcount;\n#else\n\tduk_size_t h_refcount;\n#endif\n#else\n\tduk_uint16_t h_strextra16;\n#endif  /* DUK_USE_REFERENCE_COUNTING */\n\n\tduk_hstring *h_next;\n\t/* No 'h_prev' pointer for strings. */\n};\n\n#define DUK_HEAPHDR_FLAGS_TYPE_MASK      0x00000003UL\n#define DUK_HEAPHDR_FLAGS_FLAG_MASK      (~DUK_HEAPHDR_FLAGS_TYPE_MASK)\n\n                                             /* 2 bits for heap type */\n#define DUK_HEAPHDR_FLAGS_HEAP_START     2   /* 5 heap flags */\n#define DUK_HEAPHDR_FLAGS_USER_START     7   /* 25 user flags */\n\n#define DUK_HEAPHDR_HEAP_FLAG_NUMBER(n)  (DUK_HEAPHDR_FLAGS_HEAP_START + (n))\n#define DUK_HEAPHDR_USER_FLAG_NUMBER(n)  (DUK_HEAPHDR_FLAGS_USER_START + (n))\n#define DUK_HEAPHDR_HEAP_FLAG(n)         (1UL << (DUK_HEAPHDR_FLAGS_HEAP_START + (n)))\n#define DUK_HEAPHDR_USER_FLAG(n)         (1UL << (DUK_HEAPHDR_FLAGS_USER_START + (n)))\n\n#define DUK_HEAPHDR_FLAG_REACHABLE       DUK_HEAPHDR_HEAP_FLAG(0)  /* mark-and-sweep: reachable */\n#define DUK_HEAPHDR_FLAG_TEMPROOT        DUK_HEAPHDR_HEAP_FLAG(1)  /* mark-and-sweep: children not processed */\n#define DUK_HEAPHDR_FLAG_FINALIZABLE     DUK_HEAPHDR_HEAP_FLAG(2)  /* mark-and-sweep: finalizable (on current pass) */\n#define DUK_HEAPHDR_FLAG_FINALIZED       DUK_HEAPHDR_HEAP_FLAG(3)  /* mark-and-sweep: finalized (on previous pass) */\n#define DUK_HEAPHDR_FLAG_READONLY        DUK_HEAPHDR_HEAP_FLAG(4)  /* read-only object, in code section */\n\n#define DUK_HTYPE_MIN                    0\n#define DUK_HTYPE_STRING                 0\n#define DUK_HTYPE_OBJECT                 1\n#define DUK_HTYPE_BUFFER                 2\n#define DUK_HTYPE_MAX                    2\n\n#if defined(DUK_USE_HEAPPTR16)\n#define DUK_HEAPHDR_GET_NEXT(heap,h) \\\n\t((duk_heaphdr *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->h_next16))\n#define DUK_HEAPHDR_SET_NEXT(heap,h,val)   do { \\\n\t\t(h)->h_next16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) val); \\\n\t} while (0)\n#else\n#define DUK_HEAPHDR_GET_NEXT(heap,h)  ((h)->h_next)\n#define DUK_HEAPHDR_SET_NEXT(heap,h,val)   do { \\\n\t\t(h)->h_next = (val); \\\n\t} while (0)\n#endif\n\n#if defined(DUK_USE_DOUBLE_LINKED_HEAP)\n#if defined(DUK_USE_HEAPPTR16)\n#define DUK_HEAPHDR_GET_PREV(heap,h) \\\n\t((duk_heaphdr *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->h_prev16))\n#define DUK_HEAPHDR_SET_PREV(heap,h,val)   do { \\\n\t\t(h)->h_prev16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (val)); \\\n\t} while (0)\n#else\n#define DUK_HEAPHDR_GET_PREV(heap,h)       ((h)->h_prev)\n#define DUK_HEAPHDR_SET_PREV(heap,h,val)   do { \\\n\t\t(h)->h_prev = (val); \\\n\t} while (0)\n#endif\n#endif\n\n#if defined(DUK_USE_REFERENCE_COUNTING)\n#define DUK_HEAPHDR_GET_REFCOUNT(h)   ((h)->h_refcount)\n#define DUK_HEAPHDR_SET_REFCOUNT(h,val)  do { \\\n\t\t(h)->h_refcount = (val); \\\n\t\tDUK_ASSERT((h)->h_refcount == (val));  /* No truncation. */ \\\n\t} while (0)\n#define DUK_HEAPHDR_PREINC_REFCOUNT(h)  (++(h)->h_refcount)  /* result: updated refcount */\n#define DUK_HEAPHDR_PREDEC_REFCOUNT(h)  (--(h)->h_refcount)  /* result: updated refcount */\n#else\n/* refcount macros not defined without refcounting, caller must #if defined() now */\n#endif  /* DUK_USE_REFERENCE_COUNTING */\n\n/*\n *  Note: type is treated as a field separate from flags, so some masking is\n *  involved in the macros below.\n */\n\n#define DUK_HEAPHDR_GET_FLAGS_RAW(h)  ((h)->h_flags)\n#define DUK_HEAPHDR_SET_FLAGS_RAW(h,val)  do { \\\n\t\t(h)->h_flags = (val); } \\\n\t}\n#define DUK_HEAPHDR_GET_FLAGS(h)      ((h)->h_flags & DUK_HEAPHDR_FLAGS_FLAG_MASK)\n#define DUK_HEAPHDR_SET_FLAGS(h,val)  do { \\\n\t\t(h)->h_flags = ((h)->h_flags & ~(DUK_HEAPHDR_FLAGS_FLAG_MASK)) | (val); \\\n\t} while (0)\n#define DUK_HEAPHDR_GET_TYPE(h)       ((h)->h_flags & DUK_HEAPHDR_FLAGS_TYPE_MASK)\n#define DUK_HEAPHDR_SET_TYPE(h,val)   do { \\\n\t\t(h)->h_flags = ((h)->h_flags & ~(DUK_HEAPHDR_FLAGS_TYPE_MASK)) | (val); \\\n\t} while (0)\n\n/* Comparison for type >= DUK_HTYPE_MIN skipped; because DUK_HTYPE_MIN is zero\n * and the comparison is unsigned, it's always true and generates warnings.\n */\n#define DUK_HEAPHDR_HTYPE_VALID(h)    ( \\\n\tDUK_HEAPHDR_GET_TYPE((h)) <= DUK_HTYPE_MAX \\\n\t)\n\n#define DUK_HEAPHDR_SET_TYPE_AND_FLAGS(h,tval,fval)  do { \\\n\t\t(h)->h_flags = ((tval) & DUK_HEAPHDR_FLAGS_TYPE_MASK) | \\\n\t\t               ((fval) & DUK_HEAPHDR_FLAGS_FLAG_MASK); \\\n\t} while (0)\n\n#define DUK_HEAPHDR_SET_FLAG_BITS(h,bits)  do { \\\n\t\tDUK_ASSERT(((bits) & ~(DUK_HEAPHDR_FLAGS_FLAG_MASK)) == 0); \\\n\t\t(h)->h_flags |= (bits); \\\n\t} while (0)\n\n#define DUK_HEAPHDR_CLEAR_FLAG_BITS(h,bits)  do { \\\n\t\tDUK_ASSERT(((bits) & ~(DUK_HEAPHDR_FLAGS_FLAG_MASK)) == 0); \\\n\t\t(h)->h_flags &= ~((bits)); \\\n\t} while (0)\n\n#define DUK_HEAPHDR_CHECK_FLAG_BITS(h,bits)  (((h)->h_flags & (bits)) != 0)\n\n#define DUK_HEAPHDR_SET_REACHABLE(h)      DUK_HEAPHDR_SET_FLAG_BITS((h),DUK_HEAPHDR_FLAG_REACHABLE)\n#define DUK_HEAPHDR_CLEAR_REACHABLE(h)    DUK_HEAPHDR_CLEAR_FLAG_BITS((h),DUK_HEAPHDR_FLAG_REACHABLE)\n#define DUK_HEAPHDR_HAS_REACHABLE(h)      DUK_HEAPHDR_CHECK_FLAG_BITS((h),DUK_HEAPHDR_FLAG_REACHABLE)\n\n#define DUK_HEAPHDR_SET_TEMPROOT(h)       DUK_HEAPHDR_SET_FLAG_BITS((h),DUK_HEAPHDR_FLAG_TEMPROOT)\n#define DUK_HEAPHDR_CLEAR_TEMPROOT(h)     DUK_HEAPHDR_CLEAR_FLAG_BITS((h),DUK_HEAPHDR_FLAG_TEMPROOT)\n#define DUK_HEAPHDR_HAS_TEMPROOT(h)       DUK_HEAPHDR_CHECK_FLAG_BITS((h),DUK_HEAPHDR_FLAG_TEMPROOT)\n\n#define DUK_HEAPHDR_SET_FINALIZABLE(h)    DUK_HEAPHDR_SET_FLAG_BITS((h),DUK_HEAPHDR_FLAG_FINALIZABLE)\n#define DUK_HEAPHDR_CLEAR_FINALIZABLE(h)  DUK_HEAPHDR_CLEAR_FLAG_BITS((h),DUK_HEAPHDR_FLAG_FINALIZABLE)\n#define DUK_HEAPHDR_HAS_FINALIZABLE(h)    DUK_HEAPHDR_CHECK_FLAG_BITS((h),DUK_HEAPHDR_FLAG_FINALIZABLE)\n\n#define DUK_HEAPHDR_SET_FINALIZED(h)      DUK_HEAPHDR_SET_FLAG_BITS((h),DUK_HEAPHDR_FLAG_FINALIZED)\n#define DUK_HEAPHDR_CLEAR_FINALIZED(h)    DUK_HEAPHDR_CLEAR_FLAG_BITS((h),DUK_HEAPHDR_FLAG_FINALIZED)\n#define DUK_HEAPHDR_HAS_FINALIZED(h)      DUK_HEAPHDR_CHECK_FLAG_BITS((h),DUK_HEAPHDR_FLAG_FINALIZED)\n\n#define DUK_HEAPHDR_SET_READONLY(h)       DUK_HEAPHDR_SET_FLAG_BITS((h),DUK_HEAPHDR_FLAG_READONLY)\n#define DUK_HEAPHDR_CLEAR_READONLY(h)     DUK_HEAPHDR_CLEAR_FLAG_BITS((h),DUK_HEAPHDR_FLAG_READONLY)\n#define DUK_HEAPHDR_HAS_READONLY(h)       DUK_HEAPHDR_CHECK_FLAG_BITS((h),DUK_HEAPHDR_FLAG_READONLY)\n\n/* get or set a range of flags; m=first bit number, n=number of bits */\n#define DUK_HEAPHDR_GET_FLAG_RANGE(h,m,n)  (((h)->h_flags >> (m)) & ((1UL << (n)) - 1UL))\n\n#define DUK_HEAPHDR_SET_FLAG_RANGE(h,m,n,v)  do { \\\n\t\t(h)->h_flags = \\\n\t\t\t((h)->h_flags & (~(((1UL << (n)) - 1UL) << (m)))) \\\n\t\t\t| ((v) << (m)); \\\n\t} while (0)\n\n/* init pointer fields to null */\n#if defined(DUK_USE_DOUBLE_LINKED_HEAP)\n#define DUK_HEAPHDR_INIT_NULLS(h)       do { \\\n\t\tDUK_HEAPHDR_SET_NEXT((h), (void *) NULL); \\\n\t\tDUK_HEAPHDR_SET_PREV((h), (void *) NULL); \\\n\t} while (0)\n#else\n#define DUK_HEAPHDR_INIT_NULLS(h)       do { \\\n\t\tDUK_HEAPHDR_SET_NEXT((h), (void *) NULL); \\\n\t} while (0)\n#endif\n\n#define DUK_HEAPHDR_STRING_INIT_NULLS(h)  do { \\\n\t\t(h)->h_next = NULL; \\\n\t} while (0)\n\n/*\n *  Type tests\n */\n\n/* Take advantage of the fact that for DUK_HTYPE_xxx numbers the lowest bit\n * is only set for DUK_HTYPE_OBJECT (= 1).\n */\n#if 0\n#define DUK_HEAPHDR_IS_OBJECT(h) (DUK_HEAPHDR_GET_TYPE((h)) == DUK_HTYPE_OBJECT)\n#endif\n#define DUK_HEAPHDR_IS_OBJECT(h) ((h)->h_flags & 0x01UL)\n#define DUK_HEAPHDR_IS_STRING(h) (DUK_HEAPHDR_GET_TYPE((h)) == DUK_HTYPE_STRING)\n#define DUK_HEAPHDR_IS_BUFFER(h) (DUK_HEAPHDR_GET_TYPE((h)) == DUK_HTYPE_BUFFER)\n\n/*\n *  Assert helpers\n */\n\n/* Check that prev/next links are consistent: if e.g. h->prev is != NULL,\n * h->prev->next should point back to h.\n */\n#if defined(DUK_USE_DOUBLE_LINKED_HEAP) && defined(DUK_USE_ASSERTIONS)\n#define DUK_ASSERT_HEAPHDR_LINKS(heap,h) do { \\\n\t\tif ((h) != NULL) { \\\n\t\t\tduk_heaphdr *h__prev, *h__next; \\\n\t\t\th__prev = DUK_HEAPHDR_GET_PREV((heap), (h)); \\\n\t\t\th__next = DUK_HEAPHDR_GET_NEXT((heap), (h)); \\\n\t\t\tDUK_ASSERT(h__prev == NULL || (DUK_HEAPHDR_GET_NEXT((heap), h__prev) == (h))); \\\n\t\t\tDUK_ASSERT(h__next == NULL || (DUK_HEAPHDR_GET_PREV((heap), h__next) == (h))); \\\n\t\t} \\\n\t} while (0)\n#else\n#define DUK_ASSERT_HEAPHDR_LINKS(heap,h) do {} while (0)\n#endif\n\n#define DUK_ASSERT_HEAPHDR_VALID(h) do { \\\n\t\tDUK_ASSERT((h) != NULL); \\\n\t\tDUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID((h))); \\\n\t} while (0)\n\n#endif  /* DUK_HEAPHDR_H_INCLUDED */\n/* #include duk_refcount.h */\n#line 1 \"duk_refcount.h\"\n/*\n *  Reference counting helper macros.  The macros take a thread argument\n *  and must thus always be executed in a specific thread context.  The\n *  thread argument is not really needed anymore: DECREF can operate with\n *  a heap pointer only, and INCREF needs neither.\n */\n\n#if !defined(DUK_REFCOUNT_H_INCLUDED)\n#define DUK_REFCOUNT_H_INCLUDED\n\n#if defined(DUK_USE_REFERENCE_COUNTING)\n\n#if defined(DUK_USE_ROM_OBJECTS)\n/* With ROM objects \"needs refcount update\" is true when the value is\n * heap allocated and is not a ROM object.\n */\n/* XXX: double evaluation for 'tv' argument. */\n#define DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv) \\\n\t(DUK_TVAL_IS_HEAP_ALLOCATED((tv)) && !DUK_HEAPHDR_HAS_READONLY(DUK_TVAL_GET_HEAPHDR((tv))))\n#define DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE(h)  (!DUK_HEAPHDR_HAS_READONLY((h)))\n#else  /* DUK_USE_ROM_OBJECTS */\n/* Without ROM objects \"needs refcount update\" == is heap allocated. */\n#define DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv)    DUK_TVAL_IS_HEAP_ALLOCATED((tv))\n#define DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE(h)  1\n#endif  /* DUK_USE_ROM_OBJECTS */\n\n/* Fast variants, inline refcount operations except for refzero handling.\n * Can be used explicitly when speed is always more important than size.\n * For a good compiler and a single file build, these are basically the\n * same as a forced inline.\n */\n#define DUK_TVAL_INCREF_FAST(thr,tv) do { \\\n\t\tduk_tval *duk__tv = (tv); \\\n\t\tDUK_ASSERT(duk__tv != NULL); \\\n\t\tif (DUK_TVAL_NEEDS_REFCOUNT_UPDATE(duk__tv)) { \\\n\t\t\tduk_heaphdr *duk__h = DUK_TVAL_GET_HEAPHDR(duk__tv); \\\n\t\t\tDUK_ASSERT(duk__h != NULL); \\\n\t\t\tDUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(duk__h)); \\\n\t\t\tDUK_HEAPHDR_PREINC_REFCOUNT(duk__h); \\\n\t\t\tDUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(duk__h) != 0);  /* No wrapping. */ \\\n\t\t} \\\n\t} while (0)\n#define DUK_TVAL_DECREF_FAST(thr,tv) do { \\\n\t\tduk_tval *duk__tv = (tv); \\\n\t\tDUK_ASSERT(duk__tv != NULL); \\\n\t\tif (DUK_TVAL_NEEDS_REFCOUNT_UPDATE(duk__tv)) { \\\n\t\t\tduk_heaphdr *duk__h = DUK_TVAL_GET_HEAPHDR(duk__tv); \\\n\t\t\tDUK_ASSERT(duk__h != NULL); \\\n\t\t\tDUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(duk__h)); \\\n\t\t\tDUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(duk__h) > 0); \\\n\t\t\tif (DUK_HEAPHDR_PREDEC_REFCOUNT(duk__h) == 0) { \\\n\t\t\t\tduk_heaphdr_refzero((thr), duk__h); \\\n\t\t\t} \\\n\t\t} \\\n\t} while (0)\n#define DUK_TVAL_DECREF_NORZ_FAST(thr,tv) do { \\\n\t\tduk_tval *duk__tv = (tv); \\\n\t\tDUK_ASSERT(duk__tv != NULL); \\\n\t\tif (DUK_TVAL_NEEDS_REFCOUNT_UPDATE(duk__tv)) { \\\n\t\t\tduk_heaphdr *duk__h = DUK_TVAL_GET_HEAPHDR(duk__tv); \\\n\t\t\tDUK_ASSERT(duk__h != NULL); \\\n\t\t\tDUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(duk__h)); \\\n\t\t\tDUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(duk__h) > 0); \\\n\t\t\tif (DUK_HEAPHDR_PREDEC_REFCOUNT(duk__h) == 0) { \\\n\t\t\t\tduk_heaphdr_refzero_norz((thr), duk__h); \\\n\t\t\t} \\\n\t\t} \\\n\t} while (0)\n#define DUK_HEAPHDR_INCREF_FAST(thr,h) do { \\\n\t\tduk_heaphdr *duk__h = (duk_heaphdr *) (h); \\\n\t\tDUK_ASSERT(duk__h != NULL); \\\n\t\tDUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(duk__h)); \\\n\t\tif (DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE(duk__h)) { \\\n\t\t\tDUK_HEAPHDR_PREINC_REFCOUNT(duk__h); \\\n\t\t\tDUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(duk__h) != 0);  /* No wrapping. */ \\\n\t\t} \\\n\t} while (0)\n#define DUK_HEAPHDR_DECREF_FAST_RAW(thr,h,rzcall,rzcast) do { \\\n\t\tduk_heaphdr *duk__h = (duk_heaphdr *) (h); \\\n\t\tDUK_ASSERT(duk__h != NULL); \\\n\t\tDUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(duk__h)); \\\n\t\tDUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(duk__h) > 0); \\\n\t\tif (DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE(duk__h)) { \\\n\t\t\tif (DUK_HEAPHDR_PREDEC_REFCOUNT(duk__h) == 0) { \\\n\t\t\t\t(rzcall)((thr), (rzcast) duk__h); \\\n\t\t\t} \\\n\t\t} \\\n\t} while (0)\n#define DUK_HEAPHDR_DECREF_FAST(thr,h) \\\n\tDUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_heaphdr_refzero,duk_heaphdr *)\n#define DUK_HEAPHDR_DECREF_NORZ_FAST(thr,h) \\\n\tDUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_heaphdr_refzero_norz,duk_heaphdr *)\n\n/* Slow variants, call to a helper to reduce code size.\n * Can be used explicitly when size is always more important than speed.\n */\n#define DUK_TVAL_INCREF_SLOW(thr,tv)         do { duk_tval_incref((tv)); } while (0)\n#define DUK_TVAL_DECREF_SLOW(thr,tv)         do { duk_tval_decref((thr), (tv)); } while (0)\n#define DUK_TVAL_DECREF_NORZ_SLOW(thr,tv)    do { duk_tval_decref_norz((thr), (tv)); } while (0)\n#define DUK_HEAPHDR_INCREF_SLOW(thr,h)       do { duk_heaphdr_incref((duk_heaphdr *) (h)); } while (0)\n#define DUK_HEAPHDR_DECREF_SLOW(thr,h)       do { duk_heaphdr_decref((thr), (duk_heaphdr *) (h)); } while (0)\n#define DUK_HEAPHDR_DECREF_NORZ_SLOW(thr,h)  do { duk_heaphdr_decref_norz((thr), (duk_heaphdr *) (h)); } while (0)\n#define DUK_HSTRING_INCREF_SLOW(thr,h)       do { duk_heaphdr_incref((duk_heaphdr *) (h)); } while (0)\n#define DUK_HSTRING_DECREF_SLOW(thr,h)       do { duk_heaphdr_decref((thr), (duk_heaphdr *) (h)); } while (0)\n#define DUK_HSTRING_DECREF_NORZ_SLOW(thr,h)  do { duk_heaphdr_decref_norz((thr), (duk_heaphdr *) (h)); } while (0)\n#define DUK_HBUFFER_INCREF_SLOW(thr,h)       do { duk_heaphdr_incref((duk_heaphdr *) (h)); } while (0)\n#define DUK_HBUFFER_DECREF_SLOW(thr,h)       do { duk_heaphdr_decref((thr), (duk_heaphdr *) (h)); } while (0)\n#define DUK_HBUFFER_DECREF_NORZ_SLOW(thr,h)  do { duk_heaphdr_decref_norz((thr), (duk_heaphdr *) (h)); } while (0)\n#define DUK_HOBJECT_INCREF_SLOW(thr,h)       do { duk_heaphdr_incref((duk_heaphdr *) (h)); } while (0)\n#define DUK_HOBJECT_DECREF_SLOW(thr,h)       do { duk_heaphdr_decref((thr), (duk_heaphdr *) (h)); } while (0)\n#define DUK_HOBJECT_DECREF_NORZ_SLOW(thr,h)  do { duk_heaphdr_decref_norz((thr), (duk_heaphdr *) (h)); } while (0)\n\n/* Default variants.  Selection depends on speed/size preference.\n * Concretely: with gcc 4.8.1 -Os x64 the difference in final binary\n * is about +1kB for _FAST variants.\n */\n#if defined(DUK_USE_FAST_REFCOUNT_DEFAULT)\n/* XXX: It would be nice to specialize for specific duk_hobject subtypes\n * but current refzero queue handling prevents that.\n */\n#define DUK_TVAL_INCREF(thr,tv)                DUK_TVAL_INCREF_FAST((thr),(tv))\n#define DUK_TVAL_DECREF(thr,tv)                DUK_TVAL_DECREF_FAST((thr),(tv))\n#define DUK_TVAL_DECREF_NORZ(thr,tv)           DUK_TVAL_DECREF_NORZ_FAST((thr),(tv))\n#define DUK_HEAPHDR_INCREF(thr,h)              DUK_HEAPHDR_INCREF_FAST((thr),(h))\n#define DUK_HEAPHDR_DECREF(thr,h)              DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_heaphdr_refzero,duk_heaphdr *)\n#define DUK_HEAPHDR_DECREF_NORZ(thr,h)         DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_heaphdr_refzero_norz,duk_heaphdr *)\n#define DUK_HSTRING_INCREF(thr,h)              DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) (h))\n#define DUK_HSTRING_DECREF(thr,h)              DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hstring_refzero,duk_hstring *)\n#define DUK_HSTRING_DECREF_NORZ(thr,h)         DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hstring_refzero,duk_hstring *)  /* no 'norz' variant */\n#define DUK_HOBJECT_INCREF(thr,h)              DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) (h))\n#define DUK_HOBJECT_DECREF(thr,h)              DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero,duk_hobject *)\n#define DUK_HOBJECT_DECREF_NORZ(thr,h)         DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero_norz,duk_hobject *)\n#define DUK_HBUFFER_INCREF(thr,h)              DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) (h))\n#define DUK_HBUFFER_DECREF(thr,h)              DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hbuffer_refzero,duk_hbuffer *)\n#define DUK_HBUFFER_DECREF_NORZ(thr,h)         DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hbuffer_refzero,duk_hbuffer *)  /* no 'norz' variant */\n#define DUK_HCOMPFUNC_INCREF(thr,h)            DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj)\n#define DUK_HCOMPFUNC_DECREF(thr,h)            DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero,duk_hobject *)\n#define DUK_HCOMPFUNC_DECREF_NORZ(thr,h)       DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero_norz,duk_hobject *)\n#define DUK_HNATFUNC_INCREF(thr,h)             DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj)\n#define DUK_HNATFUNC_DECREF(thr,h)             DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero,duk_hobject *)\n#define DUK_HNATFUNC_DECREF_NORZ(thr,h)        DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero_norz,duk_hobject *)\n#define DUK_HBUFOBJ_INCREF(thr,h)              DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj)\n#define DUK_HBUFOBJ_DECREF(thr,h)              DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero,duk_hobject *)\n#define DUK_HBUFOBJ_DECREF_NORZ(thr,h)         DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero_norz,duk_hobject *)\n#define DUK_HTHREAD_INCREF(thr,h)              DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj)\n#define DUK_HTHREAD_DECREF(thr,h)              DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero,duk_hobject *)\n#define DUK_HTHREAD_DECREF_NORZ(thr,h)         DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero_norz,duk_hobject *)\n#else\n#define DUK_TVAL_INCREF(thr,tv)                DUK_TVAL_INCREF_SLOW((thr),(tv))\n#define DUK_TVAL_DECREF(thr,tv)                DUK_TVAL_DECREF_SLOW((thr),(tv))\n#define DUK_TVAL_DECREF_NORZ(thr,tv)           DUK_TVAL_DECREF_NORZ_SLOW((thr),(tv))\n#define DUK_HEAPHDR_INCREF(thr,h)              DUK_HEAPHDR_INCREF_SLOW((thr),(h))\n#define DUK_HEAPHDR_DECREF(thr,h)              DUK_HEAPHDR_DECREF_SLOW((thr),(h))\n#define DUK_HEAPHDR_DECREF_NORZ(thr,h)         DUK_HEAPHDR_DECREF_NORZ_SLOW((thr),(h))\n#define DUK_HSTRING_INCREF(thr,h)              DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) (h))\n#define DUK_HSTRING_DECREF(thr,h)              DUK_HSTRING_DECREF_SLOW((thr),(h))\n#define DUK_HSTRING_DECREF_NORZ(thr,h)         DUK_HSTRING_DECREF_NORZ_SLOW((thr),(h))\n#define DUK_HOBJECT_INCREF(thr,h)              DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) (h))\n#define DUK_HOBJECT_DECREF(thr,h)              DUK_HOBJECT_DECREF_SLOW((thr),(h))\n#define DUK_HOBJECT_DECREF_NORZ(thr,h)         DUK_HOBJECT_DECREF_NORZ_SLOW((thr),(h))\n#define DUK_HBUFFER_INCREF(thr,h)              DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) (h))\n#define DUK_HBUFFER_DECREF(thr,h)              DUK_HBUFFER_DECREF_SLOW((thr),(h))\n#define DUK_HBUFFER_DECREF_NORZ(thr,h)         DUK_HBUFFER_DECREF_NORZ_SLOW((thr),(h))\n#define DUK_HCOMPFUNC_INCREF(thr,h)            DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj)\n#define DUK_HCOMPFUNC_DECREF(thr,h)            DUK_HOBJECT_DECREF_SLOW((thr),(duk_hobject *) &(h)->obj)\n#define DUK_HCOMPFUNC_DECREF_NORZ(thr,h)       DUK_HOBJECT_DECREF_NORZ_SLOW((thr),(duk_hobject *) &(h)->obj)\n#define DUK_HNATFUNC_INCREF(thr,h)             DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj)\n#define DUK_HNATFUNC_DECREF(thr,h)             DUK_HOBJECT_DECREF_SLOW((thr),(duk_hobject *) &(h)->obj)\n#define DUK_HNATFUNC_DECREF_NORZ(thr,h)        DUK_HOBJECT_DECREF_NORZ_SLOW((thr),(duk_hobject *) &(h)->obj)\n#define DUK_HBUFOBJ_INCREF(thr,h)              DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj)\n#define DUK_HBUFOBJ_DECREF(thr,h)              DUK_HOBJECT_DECREF_SLOW((thr),(duk_hobject *) &(h)->obj)\n#define DUK_HBUFOB_DECREF_NORZ(thr,h)          DUK_HOBJECT_DECREF_NORZ_SLOW((thr),(duk_hobject *) &(h)->obj)\n#define DUK_HTHREAD_INCREF(thr,h)              DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj)\n#define DUK_HTHREAD_DECREF(thr,h)              DUK_HOBJECT_DECREF_SLOW((thr),(duk_hobject *) &(h)->obj)\n#define DUK_HTHREAD_DECREF_NORZ(thr,h)         DUK_HOBJECT_DECREF_NORZ_SLOW((thr),(duk_hobject *) &(h)->obj)\n#endif\n\n/* Convenience for some situations; the above macros don't allow NULLs\n * for performance reasons.  Macros cover only actually needed cases.\n */\n#define DUK_HEAPHDR_INCREF_ALLOWNULL(thr,h) do { \\\n\t\tif ((h) != NULL) { \\\n\t\t\tDUK_HEAPHDR_INCREF((thr), (duk_heaphdr *) (h)); \\\n\t\t} \\\n\t} while (0)\n#define DUK_HEAPHDR_DECREF_ALLOWNULL(thr,h) do { \\\n\t\tif ((h) != NULL) { \\\n\t\t\tDUK_HEAPHDR_DECREF((thr), (duk_heaphdr *) (h)); \\\n\t\t} \\\n\t} while (0)\n#define DUK_HEAPHDR_DECREF_NORZ_ALLOWNULL(thr,h) do { \\\n\t\tif ((h) != NULL) { \\\n\t\t\tDUK_HEAPHDR_DECREF_NORZ((thr), (duk_heaphdr *) (h)); \\\n\t\t} \\\n\t} while (0)\n#define DUK_HOBJECT_INCREF_ALLOWNULL(thr,h) do { \\\n\t\tif ((h) != NULL) { \\\n\t\t\tDUK_HOBJECT_INCREF((thr), (h)); \\\n\t\t} \\\n\t} while (0)\n#define DUK_HOBJECT_DECREF_ALLOWNULL(thr,h) do { \\\n\t\tif ((h) != NULL) { \\\n\t\t\tDUK_HOBJECT_DECREF((thr), (h)); \\\n\t\t} \\\n\t} while (0)\n#define DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr,h) do { \\\n\t\tif ((h) != NULL) { \\\n\t\t\tDUK_HOBJECT_DECREF_NORZ((thr), (h)); \\\n\t\t} \\\n\t} while (0)\n#define DUK_HBUFFER_INCREF_ALLOWNULL(thr,h) do { \\\n\t\tif ((h) != NULL) { \\\n\t\t\tDUK_HBUFFER_INCREF((thr), (h)); \\\n\t\t} \\\n\t} while (0)\n#define DUK_HBUFFER_DECREF_ALLOWNULL(thr,h) do { \\\n\t\tif ((h) != NULL) { \\\n\t\t\tDUK_HBUFFER_DECREF((thr), (h)); \\\n\t\t} \\\n\t} while (0)\n#define DUK_HBUFFER_DECREF_NORZ_ALLOWNULL(thr,h) do { \\\n\t\tif ((h) != NULL) { \\\n\t\t\tDUK_HBUFFER_DECREF_NORZ((thr), (h)); \\\n\t\t} \\\n\t} while (0)\n#define DUK_HTHREAD_INCREF_ALLOWNULL(thr,h) do { \\\n\t\tif ((h) != NULL) { \\\n\t\t\tDUK_HTHREAD_INCREF((thr), (h)); \\\n\t\t} \\\n\t} while (0)\n#define DUK_HTHREAD_DECREF_ALLOWNULL(thr,h) do { \\\n\t\tif ((h) != NULL) { \\\n\t\t\tDUK_HTHREAD_DECREF((thr), (h)); \\\n\t\t} \\\n\t} while (0)\n#define DUK_HTHREAD_DECREF_NORZ_ALLOWNULL(thr,h) do { \\\n\t\tif ((h) != NULL) { \\\n\t\t\tDUK_HTHREAD_DECREF_NORZ((thr), (h)); \\\n\t\t} \\\n\t} while (0)\n\n/* Called after one or more DECREF NORZ calls to handle pending side effects.\n * At present DECREF NORZ does freeing inline but doesn't execute finalizers,\n * so these macros check for pending finalizers and execute them.  The FAST\n * variant is performance critical.\n */\n#if defined(DUK_USE_FINALIZER_SUPPORT)\n#define DUK_REFZERO_CHECK_FAST(thr) do { \\\n\t\tduk_refzero_check_fast((thr)); \\\n\t} while (0)\n#define DUK_REFZERO_CHECK_SLOW(thr) do { \\\n\t\tduk_refzero_check_slow((thr)); \\\n\t} while (0)\n#else  /* DUK_USE_FINALIZER_SUPPORT */\n#define DUK_REFZERO_CHECK_FAST(thr) do { } while (0)\n#define DUK_REFZERO_CHECK_SLOW(thr) do { } while (0)\n#endif  /* DUK_USE_FINALIZER_SUPPORT */\n\n/*\n *  Macros to set a duk_tval and update refcount of the target (decref the\n *  old value and incref the new value if necessary).  This is both performance\n *  and footprint critical; any changes made should be measured for size/speed.\n */\n\n#define DUK_TVAL_SET_UNDEFINED_UPDREF_ALT0(thr,tvptr_dst) do { \\\n\t\tduk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \\\n\t\tDUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \\\n\t\tDUK_TVAL_SET_UNDEFINED(tv__dst); \\\n\t\tDUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \\\n\t} while (0)\n\n#define DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ_ALT0(thr,tvptr_dst) do { \\\n\t\tduk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \\\n\t\tDUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \\\n\t\tDUK_TVAL_SET_UNDEFINED(tv__dst); \\\n\t\tDUK_TVAL_DECREF_NORZ((thr), &tv__tmp); \\\n\t} while (0)\n\n#define DUK_TVAL_SET_UNUSED_UPDREF_ALT0(thr,tvptr_dst) do { \\\n\t\tduk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \\\n\t\tDUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \\\n\t\tDUK_TVAL_SET_UNUSED(tv__dst); \\\n\t\tDUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \\\n\t} while (0)\n\n#define DUK_TVAL_SET_NULL_UPDREF_ALT0(thr,tvptr_dst) do { \\\n\t\tduk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \\\n\t\tDUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \\\n\t\tDUK_TVAL_SET_NULL(tv__dst); \\\n\t\tDUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \\\n\t} while (0)\n\n#define DUK_TVAL_SET_BOOLEAN_UPDREF_ALT0(thr,tvptr_dst,newval) do { \\\n\t\tduk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \\\n\t\tDUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \\\n\t\tDUK_TVAL_SET_BOOLEAN(tv__dst, (newval)); \\\n\t\tDUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \\\n\t} while (0)\n\n#define DUK_TVAL_SET_NUMBER_UPDREF_ALT0(thr,tvptr_dst,newval) do { \\\n\t\tduk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \\\n\t\tDUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \\\n\t\tDUK_TVAL_SET_NUMBER(tv__dst, (newval)); \\\n\t\tDUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \\\n\t} while (0)\n#define DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF_ALT0(thr,tvptr_dst,newval) do { \\\n\t\tduk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \\\n\t\tDUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \\\n\t\tDUK_TVAL_SET_NUMBER_CHKFAST_FAST(tv__dst, (newval)); \\\n\t\tDUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \\\n\t} while (0)\n#define DUK_TVAL_SET_DOUBLE_UPDREF_ALT0(thr,tvptr_dst,newval) do { \\\n\t\tduk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \\\n\t\tDUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \\\n\t\tDUK_TVAL_SET_DOUBLE(tv__dst, (newval)); \\\n\t\tDUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \\\n\t} while (0)\n#define DUK_TVAL_SET_NAN_UPDREF_ALT0(thr,tvptr_dst) do { \\\n\t\tduk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \\\n\t\tDUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \\\n\t\tDUK_TVAL_SET_NAN(tv__dst); \\\n\t\tDUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \\\n\t} while (0)\n#if defined(DUK_USE_FASTINT)\n#define DUK_TVAL_SET_I48_UPDREF_ALT0(thr,tvptr_dst,newval) do { \\\n\t\tduk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \\\n\t\tDUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \\\n\t\tDUK_TVAL_SET_I48(tv__dst, (newval)); \\\n\t\tDUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \\\n\t} while (0)\n#define DUK_TVAL_SET_I32_UPDREF_ALT0(thr,tvptr_dst,newval) do { \\\n\t\tduk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \\\n\t\tDUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \\\n\t\tDUK_TVAL_SET_I32(tv__dst, (newval)); \\\n\t\tDUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \\\n\t} while (0)\n#define DUK_TVAL_SET_U32_UPDREF_ALT0(thr,tvptr_dst,newval) do { \\\n\t\tduk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \\\n\t\tDUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \\\n\t\tDUK_TVAL_SET_U32(tv__dst, (newval)); \\\n\t\tDUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \\\n\t} while (0)\n#else\n#define DUK_TVAL_SET_DOUBLE_CAST_UPDREF(thr,tvptr_dst,newval) \\\n\tDUK_TVAL_SET_DOUBLE_UPDREF((thr), (tvptr_dst), (duk_double_t) (newval))\n#endif  /* DUK_USE_FASTINT */\n\n#define DUK_TVAL_SET_LIGHTFUNC_UPDREF_ALT0(thr,tvptr_dst,lf_v,lf_fp,lf_flags) do { \\\n\t\tduk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \\\n\t\tDUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \\\n\t\tDUK_TVAL_SET_LIGHTFUNC(tv__dst, (lf_v), (lf_fp), (lf_flags)); \\\n\t\tDUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \\\n\t} while (0)\n\n#define DUK_TVAL_SET_STRING_UPDREF_ALT0(thr,tvptr_dst,newval) do { \\\n\t\tduk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \\\n\t\tDUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \\\n\t\tDUK_TVAL_SET_STRING(tv__dst, (newval)); \\\n\t\tDUK_HSTRING_INCREF((thr), (newval)); \\\n\t\tDUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \\\n\t} while (0)\n\n#define DUK_TVAL_SET_OBJECT_UPDREF_ALT0(thr,tvptr_dst,newval) do { \\\n\t\tduk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \\\n\t\tDUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \\\n\t\tDUK_TVAL_SET_OBJECT(tv__dst, (newval)); \\\n\t\tDUK_HOBJECT_INCREF((thr), (newval)); \\\n\t\tDUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \\\n\t} while (0)\n\n#define DUK_TVAL_SET_BUFFER_UPDREF_ALT0(thr,tvptr_dst,newval) do { \\\n\t\tduk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \\\n\t\tDUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \\\n\t\tDUK_TVAL_SET_BUFFER(tv__dst, (newval)); \\\n\t\tDUK_HBUFFER_INCREF((thr), (newval)); \\\n\t\tDUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \\\n\t} while (0)\n\n#define DUK_TVAL_SET_POINTER_UPDREF_ALT0(thr,tvptr_dst,newval) do { \\\n\t\tduk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \\\n\t\tDUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \\\n\t\tDUK_TVAL_SET_POINTER(tv__dst, (newval)); \\\n\t\tDUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \\\n\t} while (0)\n\n/* DUK_TVAL_SET_TVAL_UPDREF() is used a lot in executor, property lookups,\n * etc, so it's very important for performance.  Measure when changing.\n *\n * NOTE: the source and destination duk_tval pointers may be the same, and\n * the macros MUST deal with that correctly.\n */\n\n/* Original idiom used, minimal code size. */\n#define DUK_TVAL_SET_TVAL_UPDREF_ALT0(thr,tvptr_dst,tvptr_src) do { \\\n\t\tduk_tval *tv__dst, *tv__src; duk_tval tv__tmp; \\\n\t\ttv__dst = (tvptr_dst); tv__src = (tvptr_src); \\\n\t\tDUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \\\n\t\tDUK_TVAL_SET_TVAL(tv__dst, tv__src); \\\n\t\tDUK_TVAL_INCREF((thr), tv__src); \\\n\t\tDUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \\\n\t} while (0)\n\n/* Faster alternative: avoid making a temporary copy of tvptr_dst and use\n * fast incref/decref macros.\n */\n#define DUK_TVAL_SET_TVAL_UPDREF_ALT1(thr,tvptr_dst,tvptr_src) do { \\\n\t\tduk_tval *tv__dst, *tv__src; duk_heaphdr *h__obj; \\\n\t\ttv__dst = (tvptr_dst); tv__src = (tvptr_src); \\\n\t\tDUK_TVAL_INCREF_FAST((thr), tv__src); \\\n\t\tif (DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv__dst)) { \\\n\t\t\th__obj = DUK_TVAL_GET_HEAPHDR(tv__dst); \\\n\t\t\tDUK_ASSERT(h__obj != NULL); \\\n\t\t\tDUK_TVAL_SET_TVAL(tv__dst, tv__src); \\\n\t\t\tDUK_HEAPHDR_DECREF_FAST((thr), h__obj);  /* side effects */ \\\n\t\t} else { \\\n\t\t\tDUK_TVAL_SET_TVAL(tv__dst, tv__src); \\\n\t\t} \\\n\t} while (0)\n\n/* XXX: no optimized variants yet */\n#define DUK_TVAL_SET_UNDEFINED_UPDREF         DUK_TVAL_SET_UNDEFINED_UPDREF_ALT0\n#define DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ    DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ_ALT0\n#define DUK_TVAL_SET_UNUSED_UPDREF            DUK_TVAL_SET_UNUSED_UPDREF_ALT0\n#define DUK_TVAL_SET_NULL_UPDREF              DUK_TVAL_SET_NULL_UPDREF_ALT0\n#define DUK_TVAL_SET_BOOLEAN_UPDREF           DUK_TVAL_SET_BOOLEAN_UPDREF_ALT0\n#define DUK_TVAL_SET_NUMBER_UPDREF            DUK_TVAL_SET_NUMBER_UPDREF_ALT0\n#define DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF    DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF_ALT0\n#define DUK_TVAL_SET_DOUBLE_UPDREF            DUK_TVAL_SET_DOUBLE_UPDREF_ALT0\n#define DUK_TVAL_SET_NAN_UPDREF               DUK_TVAL_SET_NAN_UPDREF_ALT0\n#if defined(DUK_USE_FASTINT)\n#define DUK_TVAL_SET_I48_UPDREF               DUK_TVAL_SET_I48_UPDREF_ALT0\n#define DUK_TVAL_SET_I32_UPDREF               DUK_TVAL_SET_I32_UPDREF_ALT0\n#define DUK_TVAL_SET_U32_UPDREF               DUK_TVAL_SET_U32_UPDREF_ALT0\n#else\n#define DUK_TVAL_SET_I48_UPDREF               DUK_TVAL_SET_DOUBLE_CAST_UPDREF  /* XXX: fast int-to-double */\n#define DUK_TVAL_SET_I32_UPDREF               DUK_TVAL_SET_DOUBLE_CAST_UPDREF\n#define DUK_TVAL_SET_U32_UPDREF               DUK_TVAL_SET_DOUBLE_CAST_UPDREF\n#endif  /* DUK_USE_FASTINT */\n#define DUK_TVAL_SET_FASTINT_UPDREF           DUK_TVAL_SET_I48_UPDREF  /* convenience */\n#define DUK_TVAL_SET_LIGHTFUNC_UPDREF         DUK_TVAL_SET_LIGHTFUNC_UPDREF_ALT0\n#define DUK_TVAL_SET_STRING_UPDREF            DUK_TVAL_SET_STRING_UPDREF_ALT0\n#define DUK_TVAL_SET_OBJECT_UPDREF            DUK_TVAL_SET_OBJECT_UPDREF_ALT0\n#define DUK_TVAL_SET_BUFFER_UPDREF            DUK_TVAL_SET_BUFFER_UPDREF_ALT0\n#define DUK_TVAL_SET_POINTER_UPDREF           DUK_TVAL_SET_POINTER_UPDREF_ALT0\n\n#if defined(DUK_USE_FAST_REFCOUNT_DEFAULT)\n/* Optimized for speed. */\n#define DUK_TVAL_SET_TVAL_UPDREF              DUK_TVAL_SET_TVAL_UPDREF_ALT1\n#define DUK_TVAL_SET_TVAL_UPDREF_FAST         DUK_TVAL_SET_TVAL_UPDREF_ALT1\n#define DUK_TVAL_SET_TVAL_UPDREF_SLOW         DUK_TVAL_SET_TVAL_UPDREF_ALT0\n#else\n/* Optimized for size. */\n#define DUK_TVAL_SET_TVAL_UPDREF              DUK_TVAL_SET_TVAL_UPDREF_ALT0\n#define DUK_TVAL_SET_TVAL_UPDREF_FAST         DUK_TVAL_SET_TVAL_UPDREF_ALT0\n#define DUK_TVAL_SET_TVAL_UPDREF_SLOW         DUK_TVAL_SET_TVAL_UPDREF_ALT0\n#endif\n\n#else  /* DUK_USE_REFERENCE_COUNTING */\n\n#define DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv)     0\n#define DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE(h)   0\n\n#define DUK_TVAL_INCREF_FAST(thr,v)            do {} while (0) /* nop */\n#define DUK_TVAL_DECREF_FAST(thr,v)            do {} while (0) /* nop */\n#define DUK_TVAL_DECREF_NORZ_FAST(thr,v)       do {} while (0) /* nop */\n#define DUK_TVAL_INCREF_SLOW(thr,v)            do {} while (0) /* nop */\n#define DUK_TVAL_DECREF_SLOW(thr,v)            do {} while (0) /* nop */\n#define DUK_TVAL_DECREF_NORZ_SLOW(thr,v)       do {} while (0) /* nop */\n#define DUK_TVAL_INCREF(thr,v)                 do {} while (0) /* nop */\n#define DUK_TVAL_DECREF(thr,v)                 do {} while (0) /* nop */\n#define DUK_TVAL_DECREF_NORZ(thr,v)            do {} while (0) /* nop */\n#define DUK_HEAPHDR_INCREF_FAST(thr,h)         do {} while (0) /* nop */\n#define DUK_HEAPHDR_DECREF_FAST(thr,h)         do {} while (0) /* nop */\n#define DUK_HEAPHDR_DECREF_NORZ_FAST(thr,h)    do {} while (0) /* nop */\n#define DUK_HEAPHDR_INCREF_SLOW(thr,h)         do {} while (0) /* nop */\n#define DUK_HEAPHDR_DECREF_SLOW(thr,h)         do {} while (0) /* nop */\n#define DUK_HEAPHDR_DECREF_NORZ_SLOW(thr,h)    do {} while (0) /* nop */\n#define DUK_HEAPHDR_INCREF(thr,h)              do {} while (0) /* nop */\n#define DUK_HEAPHDR_DECREF(thr,h)              do {} while (0) /* nop */\n#define DUK_HEAPHDR_DECREF_NORZ(thr,h)         do {} while (0) /* nop */\n#define DUK_HSTRING_INCREF_FAST(thr,h)         do {} while (0) /* nop */\n#define DUK_HSTRING_DECREF_FAST(thr,h)         do {} while (0) /* nop */\n#define DUK_HSTRING_DECREF_NORZ_FAST(thr,h)    do {} while (0) /* nop */\n#define DUK_HSTRING_INCREF_SLOW(thr,h)         do {} while (0) /* nop */\n#define DUK_HSTRING_DECREF_SLOW(thr,h)         do {} while (0) /* nop */\n#define DUK_HSTRING_DECREF_NORZ_SLOW(thr,h)    do {} while (0) /* nop */\n#define DUK_HSTRING_INCREF(thr,h)              do {} while (0) /* nop */\n#define DUK_HSTRING_DECREF(thr,h)              do {} while (0) /* nop */\n#define DUK_HSTRING_DECREF_NORZ(thr,h)         do {} while (0) /* nop */\n#define DUK_HOBJECT_INCREF_FAST(thr,h)         do {} while (0) /* nop */\n#define DUK_HOBJECT_DECREF_FAST(thr,h)         do {} while (0) /* nop */\n#define DUK_HOBJECT_DECREF_NORZ_FAST(thr,h)    do {} while (0) /* nop */\n#define DUK_HOBJECT_INCREF_SLOW(thr,h)         do {} while (0) /* nop */\n#define DUK_HOBJECT_DECREF_SLOW(thr,h)         do {} while (0) /* nop */\n#define DUK_HOBJECT_DECREF_NORZ_SLOW(thr,h)    do {} while (0) /* nop */\n#define DUK_HOBJECT_INCREF(thr,h)              do {} while (0) /* nop */\n#define DUK_HOBJECT_DECREF(thr,h)              do {} while (0) /* nop */\n#define DUK_HOBJECT_DECREF_NORZ(thr,h)         do {} while (0) /* nop */\n#define DUK_HBUFFER_INCREF_FAST(thr,h)         do {} while (0) /* nop */\n#define DUK_HBUFFER_DECREF_FAST(thr,h)         do {} while (0) /* nop */\n#define DUK_HBUFFER_DECREF_NORZ_FAST(thr,h)    do {} while (0) /* nop */\n#define DUK_HBUFFER_INCREF_SLOW(thr,h)         do {} while (0) /* nop */\n#define DUK_HBUFFER_DECREF_SLOW(thr,h)         do {} while (0) /* nop */\n#define DUK_HBUFFER_DECREF_NORZ_SLOW(thr,h)    do {} while (0) /* nop */\n#define DUK_HBUFFER_INCREF(thr,h)              do {} while (0) /* nop */\n#define DUK_HBUFFER_DECREF(thr,h)              do {} while (0) /* nop */\n#define DUK_HBUFFER_DECREF_NORZ(thr,h)         do {} while (0) /* nop */\n\n#define DUK_HCOMPFUNC_INCREF(thr,h)            do {} while (0) /* nop */\n#define DUK_HCOMPFUNC_DECREF(thr,h)            do {} while (0) /* nop */\n#define DUK_HCOMPFUNC_DECREF_NORZ(thr,h)       do {} while (0) /* nop */\n#define DUK_HNATFUNC_INCREF(thr,h)             do {} while (0) /* nop */\n#define DUK_HNATFUNC_DECREF(thr,h)             do {} while (0) /* nop */\n#define DUK_HNATFUNC_DECREF_NORZ(thr,h)        do {} while (0) /* nop */\n#define DUK_HBUFOBJ_INCREF(thr,h)              do {} while (0) /* nop */\n#define DUK_HBUFOBJ_DECREF(thr,h)              do {} while (0) /* nop */\n#define DUK_HBUFOBJ_DECREF_NORZ(thr,h)         do {} while (0) /* nop */\n#define DUK_HTHREAD_INCREF(thr,h)              do {} while (0) /* nop */\n#define DUK_HTHREAD_DECREF(thr,h)              do {} while (0) /* nop */\n#define DUK_HTHREAD_DECREF_NORZ(thr,h)         do {} while (0) /* nop */\n#define DUK_HOBJECT_INCREF_ALLOWNULL(thr,h)    do {} while (0) /* nop */\n#define DUK_HOBJECT_DECREF_ALLOWNULL(thr,h)    do {} while (0) /* nop */\n#define DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr,h)  do {} while (0) /* nop */\n#define DUK_HBUFFER_INCREF_ALLOWNULL(thr,h)    do {} while (0) /* nop */\n#define DUK_HBUFFER_DECREF_ALLOWNULL(thr,h)    do {} while (0) /* nop */\n#define DUK_HBUFFER_DECREF_NORZ_ALLOWNULL(thr,h)  do {} while (0) /* nop */\n\n#define DUK_REFZERO_CHECK_FAST(thr)            do {} while (0) /* nop */\n#define DUK_REFZERO_CHECK_SLOW(thr)            do {} while (0) /* nop */\n\n#define DUK_TVAL_SET_UNDEFINED_UPDREF_ALT0(thr,tvptr_dst) do { \\\n\t\tduk_tval *tv__dst; tv__dst = (tvptr_dst); \\\n\t\tDUK_TVAL_SET_UNDEFINED(tv__dst); \\\n\t\tDUK_UNREF((thr)); \\\n\t} while (0)\n\n#define DUK_TVAL_SET_UNUSED_UPDREF_ALT0(thr,tvptr_dst) do { \\\n\t\tduk_tval *tv__dst; tv__dst = (tvptr_dst); \\\n\t\tDUK_TVAL_SET_UNUSED(tv__dst); \\\n\t\tDUK_UNREF((thr)); \\\n\t} while (0)\n\n#define DUK_TVAL_SET_NULL_UPDREF_ALT0(thr,tvptr_dst) do { \\\n\t\tduk_tval *tv__dst; tv__dst = (tvptr_dst); \\\n\t\tDUK_TVAL_SET_NULL(tv__dst); \\\n\t\tDUK_UNREF((thr)); \\\n\t} while (0)\n\n#define DUK_TVAL_SET_BOOLEAN_UPDREF_ALT0(thr,tvptr_dst,newval) do { \\\n\t\tduk_tval *tv__dst; tv__dst = (tvptr_dst); \\\n\t\tDUK_TVAL_SET_BOOLEAN(tv__dst, (newval)); \\\n\t\tDUK_UNREF((thr)); \\\n\t} while (0)\n\n#define DUK_TVAL_SET_NUMBER_UPDREF_ALT0(thr,tvptr_dst,newval) do { \\\n\t\tduk_tval *tv__dst; tv__dst = (tvptr_dst); \\\n\t\tDUK_TVAL_SET_NUMBER(tv__dst, (newval)); \\\n\t\tDUK_UNREF((thr)); \\\n\t} while (0)\n#define DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF_ALT0(thr,tvptr_dst,newval) do { \\\n\t\tduk_tval *tv__dst; tv__dst = (tvptr_dst); \\\n\t\tDUK_TVAL_SET_NUMBER_CHKFAST_FAST(tv__dst, (newval)); \\\n\t\tDUK_UNREF((thr)); \\\n\t} while (0)\n#define DUK_TVAL_SET_DOUBLE_UPDREF_ALT0(thr,tvptr_dst,newval) do { \\\n\t\tduk_tval *tv__dst; tv__dst = (tvptr_dst); \\\n\t\tDUK_TVAL_SET_DOUBLE(tv__dst, (newval)); \\\n\t\tDUK_UNREF((thr)); \\\n\t} while (0)\n#define DUK_TVAL_SET_NAN_UPDREF_ALT0(thr,tvptr_dst) do { \\\n\t\tduk_tval *tv__dst; tv__dst = (tvptr_dst); \\\n\t\tDUK_TVAL_SET_NAN(tv__dst); \\\n\t\tDUK_UNREF((thr)); \\\n\t} while (0)\n#if defined(DUK_USE_FASTINT)\n#define DUK_TVAL_SET_I48_UPDREF_ALT0(thr,tvptr_dst,newval) do { \\\n\t\tduk_tval *tv__dst; tv__dst = (tvptr_dst); \\\n\t\tDUK_TVAL_SET_I48(tv__dst, (newval)); \\\n\t\tDUK_UNREF((thr)); \\\n\t} while (0)\n#define DUK_TVAL_SET_I32_UPDREF_ALT0(thr,tvptr_dst,newval) do { \\\n\t\tduk_tval *tv__dst; tv__dst = (tvptr_dst); \\\n\t\tDUK_TVAL_SET_I32(tv__dst, (newval)); \\\n\t\tDUK_UNREF((thr)); \\\n\t} while (0)\n#define DUK_TVAL_SET_U32_UPDREF_ALT0(thr,tvptr_dst,newval) do { \\\n\t\tduk_tval *tv__dst; tv__dst = (tvptr_dst); \\\n\t\tDUK_TVAL_SET_U32(tv__dst, (newval)); \\\n\t\tDUK_UNREF((thr)); \\\n\t} while (0)\n#else\n#define DUK_TVAL_SET_DOUBLE_CAST_UPDREF(thr,tvptr_dst,newval) \\\n\tDUK_TVAL_SET_DOUBLE_UPDREF((thr), (tvptr_dst), (duk_double_t) (newval))\n#endif  /* DUK_USE_FASTINT */\n\n#define DUK_TVAL_SET_LIGHTFUNC_UPDREF_ALT0(thr,tvptr_dst,lf_v,lf_fp,lf_flags) do { \\\n\t\tduk_tval *tv__dst; tv__dst = (tvptr_dst); \\\n\t\tDUK_TVAL_SET_LIGHTFUNC(tv__dst, (lf_v), (lf_fp), (lf_flags)); \\\n\t\tDUK_UNREF((thr)); \\\n\t} while (0)\n\n#define DUK_TVAL_SET_STRING_UPDREF_ALT0(thr,tvptr_dst,newval) do { \\\n\t\tduk_tval *tv__dst; tv__dst = (tvptr_dst); \\\n\t\tDUK_TVAL_SET_STRING(tv__dst, (newval)); \\\n\t\tDUK_UNREF((thr)); \\\n\t} while (0)\n\n#define DUK_TVAL_SET_OBJECT_UPDREF_ALT0(thr,tvptr_dst,newval) do { \\\n\t\tduk_tval *tv__dst; tv__dst = (tvptr_dst); \\\n\t\tDUK_TVAL_SET_OBJECT(tv__dst, (newval)); \\\n\t\tDUK_UNREF((thr)); \\\n\t} while (0)\n\n#define DUK_TVAL_SET_BUFFER_UPDREF_ALT0(thr,tvptr_dst,newval) do { \\\n\t\tduk_tval *tv__dst; tv__dst = (tvptr_dst); \\\n\t\tDUK_TVAL_SET_BUFFER(tv__dst, (newval)); \\\n\t\tDUK_UNREF((thr)); \\\n\t} while (0)\n\n#define DUK_TVAL_SET_POINTER_UPDREF_ALT0(thr,tvptr_dst,newval) do { \\\n\t\tduk_tval *tv__dst; tv__dst = (tvptr_dst); \\\n\t\tDUK_TVAL_SET_POINTER(tv__dst, (newval)); \\\n\t\tDUK_UNREF((thr)); \\\n\t} while (0)\n\n#define DUK_TVAL_SET_TVAL_UPDREF_ALT0(thr,tvptr_dst,tvptr_src) do { \\\n\t\tduk_tval *tv__dst, *tv__src; \\\n\t\ttv__dst = (tvptr_dst); tv__src = (tvptr_src); \\\n\t\tDUK_TVAL_SET_TVAL(tv__dst, tv__src); \\\n\t\tDUK_UNREF((thr)); \\\n\t} while (0)\n\n#define DUK_TVAL_SET_UNDEFINED_UPDREF         DUK_TVAL_SET_UNDEFINED_UPDREF_ALT0\n#define DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ    DUK_TVAL_SET_UNDEFINED_UPDREF_ALT0\n#define DUK_TVAL_SET_UNUSED_UPDREF            DUK_TVAL_SET_UNUSED_UPDREF_ALT0\n#define DUK_TVAL_SET_NULL_UPDREF              DUK_TVAL_SET_NULL_UPDREF_ALT0\n#define DUK_TVAL_SET_BOOLEAN_UPDREF           DUK_TVAL_SET_BOOLEAN_UPDREF_ALT0\n#define DUK_TVAL_SET_NUMBER_UPDREF            DUK_TVAL_SET_NUMBER_UPDREF_ALT0\n#define DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF    DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF_ALT0\n#define DUK_TVAL_SET_DOUBLE_UPDREF            DUK_TVAL_SET_DOUBLE_UPDREF_ALT0\n#define DUK_TVAL_SET_NAN_UPDREF               DUK_TVAL_SET_NAN_UPDREF_ALT0\n#if defined(DUK_USE_FASTINT)\n#define DUK_TVAL_SET_I48_UPDREF               DUK_TVAL_SET_I48_UPDREF_ALT0\n#define DUK_TVAL_SET_I32_UPDREF               DUK_TVAL_SET_I32_UPDREF_ALT0\n#define DUK_TVAL_SET_U32_UPDREF               DUK_TVAL_SET_U32_UPDREF_ALT0\n#else\n#define DUK_TVAL_SET_I48_UPDREF               DUK_TVAL_SET_DOUBLE_CAST_UPDREF  /* XXX: fast-int-to-double */\n#define DUK_TVAL_SET_I32_UPDREF               DUK_TVAL_SET_DOUBLE_CAST_UPDREF\n#define DUK_TVAL_SET_U32_UPDREF               DUK_TVAL_SET_DOUBLE_CAST_UPDREF\n#endif  /* DUK_USE_FASTINT */\n#define DUK_TVAL_SET_FASTINT_UPDREF           DUK_TVAL_SET_I48_UPDREF  /* convenience */\n#define DUK_TVAL_SET_LIGHTFUNC_UPDREF         DUK_TVAL_SET_LIGHTFUNC_UPDREF_ALT0\n#define DUK_TVAL_SET_STRING_UPDREF            DUK_TVAL_SET_STRING_UPDREF_ALT0\n#define DUK_TVAL_SET_OBJECT_UPDREF            DUK_TVAL_SET_OBJECT_UPDREF_ALT0\n#define DUK_TVAL_SET_BUFFER_UPDREF            DUK_TVAL_SET_BUFFER_UPDREF_ALT0\n#define DUK_TVAL_SET_POINTER_UPDREF           DUK_TVAL_SET_POINTER_UPDREF_ALT0\n\n#define DUK_TVAL_SET_TVAL_UPDREF              DUK_TVAL_SET_TVAL_UPDREF_ALT0\n#define DUK_TVAL_SET_TVAL_UPDREF_FAST         DUK_TVAL_SET_TVAL_UPDREF_ALT0\n#define DUK_TVAL_SET_TVAL_UPDREF_SLOW         DUK_TVAL_SET_TVAL_UPDREF_ALT0\n\n#endif  /* DUK_USE_REFERENCE_COUNTING */\n\n/*\n *  Some convenience macros that don't have optimized implementations now.\n */\n\n#define DUK_TVAL_SET_TVAL_UPDREF_NORZ(thr,tv_dst,tv_src) do { \\\n\t\tduk_hthread *duk__thr = (thr); \\\n\t\tduk_tval *duk__dst = (tv_dst); \\\n\t\tduk_tval *duk__src = (tv_src); \\\n\t\tDUK_UNREF(duk__thr); \\\n\t\tDUK_TVAL_DECREF_NORZ(thr, duk__dst); \\\n\t\tDUK_TVAL_SET_TVAL(duk__dst, duk__src); \\\n\t\tDUK_TVAL_INCREF(thr, duk__dst); \\\n\t} while (0)\n\n#define DUK_TVAL_SET_U32_UPDREF_NORZ(thr,tv_dst,val) do { \\\n\t\tduk_hthread *duk__thr = (thr); \\\n\t\tduk_tval *duk__dst = (tv_dst); \\\n\t\tduk_uint32_t duk__val = (duk_uint32_t) (val); \\\n\t\tDUK_UNREF(duk__thr); \\\n\t\tDUK_TVAL_DECREF_NORZ(thr, duk__dst); \\\n\t\tDUK_TVAL_SET_U32(duk__dst, duk__val); \\\n\t} while (0)\n\n/*\n *  Prototypes\n */\n\n#if defined(DUK_USE_REFERENCE_COUNTING)\n#if defined(DUK_USE_FINALIZER_SUPPORT)\nDUK_INTERNAL_DECL void duk_refzero_check_slow(duk_hthread *thr);\nDUK_INTERNAL_DECL void duk_refzero_check_fast(duk_hthread *thr);\n#endif\nDUK_INTERNAL_DECL void duk_heaphdr_refcount_finalize_norz(duk_heap *heap, duk_heaphdr *hdr);\nDUK_INTERNAL_DECL void duk_hobject_refcount_finalize_norz(duk_heap *heap, duk_hobject *h);\n#if 0  /* Not needed: fast path handles inline; slow path uses duk_heaphdr_decref() which is needed anyway. */\nDUK_INTERNAL_DECL void duk_hstring_decref(duk_hthread *thr, duk_hstring *h);\nDUK_INTERNAL_DECL void duk_hstring_decref_norz(duk_hthread *thr, duk_hstring *h);\nDUK_INTERNAL_DECL void duk_hbuffer_decref(duk_hthread *thr, duk_hbuffer *h);\nDUK_INTERNAL_DECL void duk_hbuffer_decref_norz(duk_hthread *thr, duk_hbuffer *h);\nDUK_INTERNAL_DECL void duk_hobject_decref(duk_hthread *thr, duk_hobject *h);\nDUK_INTERNAL_DECL void duk_hobject_decref_norz(duk_hthread *thr, duk_hobject *h);\n#endif\nDUK_INTERNAL_DECL void duk_heaphdr_refzero(duk_hthread *thr, duk_heaphdr *h);\nDUK_INTERNAL_DECL void duk_heaphdr_refzero_norz(duk_hthread *thr, duk_heaphdr *h);\n#if defined(DUK_USE_FAST_REFCOUNT_DEFAULT)\nDUK_INTERNAL_DECL void duk_hstring_refzero(duk_hthread *thr, duk_hstring *h);  /* no 'norz' variant */\nDUK_INTERNAL_DECL void duk_hbuffer_refzero(duk_hthread *thr, duk_hbuffer *h);  /* no 'norz' variant */\nDUK_INTERNAL_DECL void duk_hobject_refzero(duk_hthread *thr, duk_hobject *h);\nDUK_INTERNAL_DECL void duk_hobject_refzero_norz(duk_hthread *thr, duk_hobject *h);\n#else\nDUK_INTERNAL_DECL void duk_tval_incref(duk_tval *tv);\nDUK_INTERNAL_DECL void duk_tval_decref(duk_hthread *thr, duk_tval *tv);\nDUK_INTERNAL_DECL void duk_tval_decref_norz(duk_hthread *thr, duk_tval *tv);\nDUK_INTERNAL_DECL void duk_heaphdr_incref(duk_heaphdr *h);\nDUK_INTERNAL_DECL void duk_heaphdr_decref(duk_hthread *thr, duk_heaphdr *h);\nDUK_INTERNAL_DECL void duk_heaphdr_decref_norz(duk_hthread *thr, duk_heaphdr *h);\n#endif\n#else  /* DUK_USE_REFERENCE_COUNTING */\n/* no refcounting */\n#endif  /* DUK_USE_REFERENCE_COUNTING */\n\n#endif  /* DUK_REFCOUNT_H_INCLUDED */\n/* #include duk_api_internal.h */\n#line 1 \"duk_api_internal.h\"\n/*\n *  Internal API calls which have (stack and other) semantics similar\n *  to the public API.\n */\n\n#if !defined(DUK_API_INTERNAL_H_INCLUDED)\n#define DUK_API_INTERNAL_H_INCLUDED\n\n#define DUK_INTERNAL_SYMBOL(x)     (\"\\x82\" x)\n\n/* duk_push_sprintf constants */\n#define DUK_PUSH_SPRINTF_INITIAL_SIZE  256L\n#define DUK_PUSH_SPRINTF_SANITY_LIMIT  (1L * 1024L * 1024L * 1024L)\n\n/* Flag ORed to err_code to indicate __FILE__ / __LINE__ is not\n * blamed as source of error for error fileName / lineNumber.\n */\n#define DUK_ERRCODE_FLAG_NOBLAME_FILELINE  (1L << 24)\n\n/* Current convention is to use duk_size_t for value stack sizes and global indices,\n * and duk_idx_t for local frame indices.\n */\nDUK_INTERNAL_DECL void duk_valstack_grow_check_throw(duk_hthread *thr, duk_size_t min_bytes);\nDUK_INTERNAL_DECL duk_bool_t duk_valstack_grow_check_nothrow(duk_hthread *thr, duk_size_t min_bytes);\nDUK_INTERNAL_DECL void duk_valstack_shrink_check_nothrow(duk_hthread *thr, duk_bool_t snug);\n\nDUK_INTERNAL_DECL void duk_copy_tvals_incref(duk_hthread *thr, duk_tval *tv_dst, duk_tval *tv_src, duk_size_t count);\n\nDUK_INTERNAL_DECL duk_tval *duk_reserve_gap(duk_hthread *thr, duk_idx_t idx_base, duk_idx_t count);\n\nDUK_INTERNAL_DECL void duk_set_top_unsafe(duk_hthread *thr, duk_idx_t idx);\nDUK_INTERNAL_DECL void duk_set_top_and_wipe(duk_hthread *thr, duk_idx_t top, duk_idx_t idx_wipe_start);\n\nDUK_INTERNAL_DECL void duk_dup_0(duk_hthread *thr);\nDUK_INTERNAL_DECL void duk_dup_1(duk_hthread *thr);\nDUK_INTERNAL_DECL void duk_dup_2(duk_hthread *thr);\n/* duk_dup_m1() would be same as duk_dup_top() */\nDUK_INTERNAL_DECL void duk_dup_m2(duk_hthread *thr);\nDUK_INTERNAL_DECL void duk_dup_m3(duk_hthread *thr);\nDUK_INTERNAL_DECL void duk_dup_m4(duk_hthread *thr);\n\nDUK_INTERNAL_DECL void duk_remove_unsafe(duk_hthread *thr, duk_idx_t idx);\nDUK_INTERNAL_DECL void duk_remove_m2(duk_hthread *thr);\nDUK_INTERNAL_DECL void duk_remove_n(duk_hthread *thr, duk_idx_t idx, duk_idx_t count);\nDUK_INTERNAL_DECL void duk_remove_n_unsafe(duk_hthread *thr, duk_idx_t idx, duk_idx_t count);\n\nDUK_INTERNAL_DECL duk_int_t duk_get_type_tval(duk_tval *tv);\nDUK_INTERNAL_DECL duk_uint_t duk_get_type_mask_tval(duk_tval *tv);\n\n#if defined(DUK_USE_VERBOSE_ERRORS) && defined(DUK_USE_PARANOID_ERRORS)\nDUK_INTERNAL_DECL const char *duk_get_type_name(duk_hthread *thr, duk_idx_t idx);\n#endif\nDUK_INTERNAL_DECL duk_small_uint_t duk_get_class_number(duk_hthread *thr, duk_idx_t idx);\n\nDUK_INTERNAL_DECL duk_tval *duk_get_tval(duk_hthread *thr, duk_idx_t idx);\nDUK_INTERNAL_DECL duk_tval *duk_get_tval_or_unused(duk_hthread *thr, duk_idx_t idx);\nDUK_INTERNAL_DECL duk_tval *duk_require_tval(duk_hthread *thr, duk_idx_t idx);\nDUK_INTERNAL_DECL void duk_push_tval(duk_hthread *thr, duk_tval *tv);\n\n/* Push the current 'this' binding; throw TypeError if binding is not object\n * coercible (CheckObjectCoercible).\n */\nDUK_INTERNAL_DECL void duk_push_this_check_object_coercible(duk_hthread *thr);\n\n/* duk_push_this() + CheckObjectCoercible() + duk_to_object() */\nDUK_INTERNAL_DECL duk_hobject *duk_push_this_coercible_to_object(duk_hthread *thr);\n\n/* duk_push_this() + CheckObjectCoercible() + duk_to_string() */\nDUK_INTERNAL_DECL duk_hstring *duk_push_this_coercible_to_string(duk_hthread *thr);\n\nDUK_INTERNAL_DECL duk_hstring *duk_push_uint_to_hstring(duk_hthread *thr, duk_uint_t i);\n\n/* Get a borrowed duk_tval pointer to the current 'this' binding.  Caller must\n * make sure there's an active callstack entry.  Note that the returned pointer\n * is unstable with regards to side effects.\n */\nDUK_INTERNAL_DECL duk_tval *duk_get_borrowed_this_tval(duk_hthread *thr);\n\n/* XXX: add fastint support? */\n#define duk_push_u64(thr,val) \\\n\tduk_push_number((thr), (duk_double_t) (val))\n#define duk_push_i64(thr,val) \\\n\tduk_push_number((thr), (duk_double_t) (val))\n\n/* duk_push_(u)int() is guaranteed to support at least (un)signed 32-bit range */\n#define duk_push_u32(thr,val) \\\n\tduk_push_uint((thr), (duk_uint_t) (val))\n#define duk_push_i32(thr,val) \\\n\tduk_push_int((thr), (duk_int_t) (val))\n\n/* sometimes stack and array indices need to go on the stack */\n#define duk_push_idx(thr,val) \\\n\tduk_push_int((thr), (duk_int_t) (val))\n#define duk_push_uarridx(thr,val) \\\n\tduk_push_uint((thr), (duk_uint_t) (val))\n#define duk_push_size_t(thr,val) \\\n\tduk_push_uint((thr), (duk_uint_t) (val))  /* XXX: assumed to fit for now */\n\nDUK_INTERNAL_DECL duk_bool_t duk_is_string_notsymbol(duk_hthread *thr, duk_idx_t idx);\n\nDUK_INTERNAL_DECL duk_bool_t duk_is_callable_tval(duk_hthread *thr, duk_tval *tv);\n\nDUK_INTERNAL_DECL duk_hstring *duk_get_hstring(duk_hthread *thr, duk_idx_t idx);\nDUK_INTERNAL_DECL duk_hstring *duk_get_hstring_notsymbol(duk_hthread *thr, duk_idx_t idx);\nDUK_INTERNAL_DECL const char *duk_get_string_notsymbol(duk_hthread *thr, duk_idx_t idx);\nDUK_INTERNAL_DECL duk_hobject *duk_get_hobject(duk_hthread *thr, duk_idx_t idx);\nDUK_INTERNAL_DECL duk_hbuffer *duk_get_hbuffer(duk_hthread *thr, duk_idx_t idx);\nDUK_INTERNAL_DECL duk_hthread *duk_get_hthread(duk_hthread *thr, duk_idx_t idx);\nDUK_INTERNAL_DECL duk_hcompfunc *duk_get_hcompfunc(duk_hthread *thr, duk_idx_t idx);\nDUK_INTERNAL_DECL duk_hnatfunc *duk_get_hnatfunc(duk_hthread *thr, duk_idx_t idx);\n\nDUK_INTERNAL_DECL void *duk_get_buffer_data_raw(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_size, void *def_ptr, duk_size_t def_len, duk_bool_t throw_flag, duk_bool_t *out_isbuffer);\n\nDUK_INTERNAL_DECL duk_hobject *duk_get_hobject_with_class(duk_hthread *thr, duk_idx_t idx, duk_small_uint_t classnum);\n\nDUK_INTERNAL_DECL duk_hobject *duk_get_hobject_promote_mask(duk_hthread *thr, duk_idx_t idx, duk_uint_t type_mask);\nDUK_INTERNAL_DECL duk_hobject *duk_require_hobject_promote_mask(duk_hthread *thr, duk_idx_t idx, duk_uint_t type_mask);\nDUK_INTERNAL_DECL duk_hobject *duk_require_hobject_accept_mask(duk_hthread *thr, duk_idx_t idx, duk_uint_t type_mask);\n#define duk_require_hobject_promote_lfunc(thr,idx) \\\n\tduk_require_hobject_promote_mask((thr), (idx), DUK_TYPE_MASK_LIGHTFUNC)\n#define duk_get_hobject_promote_lfunc(thr,idx) \\\n\tduk_get_hobject_promote_mask((thr), (idx), DUK_TYPE_MASK_LIGHTFUNC)\n\n#if 0  /*unused*/\nDUK_INTERNAL_DECL void *duk_get_voidptr(duk_hthread *thr, duk_idx_t idx);\n#endif\n\nDUK_INTERNAL_DECL duk_hstring *duk_known_hstring(duk_hthread *thr, duk_idx_t idx);\nDUK_INTERNAL_DECL duk_hobject *duk_known_hobject(duk_hthread *thr, duk_idx_t idx);\nDUK_INTERNAL_DECL duk_hbuffer *duk_known_hbuffer(duk_hthread *thr, duk_idx_t idx);\nDUK_INTERNAL_DECL duk_hcompfunc *duk_known_hcompfunc(duk_hthread *thr, duk_idx_t idx);\nDUK_INTERNAL_DECL duk_hnatfunc *duk_known_hnatfunc(duk_hthread *thr, duk_idx_t idx);\n\nDUK_INTERNAL_DECL duk_double_t duk_to_number_tval(duk_hthread *thr, duk_tval *tv);\n\nDUK_INTERNAL_DECL duk_hstring *duk_to_hstring(duk_hthread *thr, duk_idx_t idx);\nDUK_INTERNAL_DECL duk_hstring *duk_to_hstring_m1(duk_hthread *thr);\nDUK_INTERNAL_DECL duk_hstring *duk_to_hstring_acceptsymbol(duk_hthread *thr, duk_idx_t idx);\n\nDUK_INTERNAL_DECL duk_hobject *duk_to_hobject(duk_hthread *thr, duk_idx_t idx);\n\nDUK_INTERNAL_DECL duk_double_t duk_to_number_m1(duk_hthread *thr);\nDUK_INTERNAL_DECL duk_double_t duk_to_number_m2(duk_hthread *thr);\n\n#if defined(DUK_USE_DEBUGGER_SUPPORT)  /* only needed by debugger for now */\nDUK_INTERNAL_DECL duk_hstring *duk_safe_to_hstring(duk_hthread *thr, duk_idx_t idx);\n#endif\nDUK_INTERNAL_DECL void duk_push_class_string_tval(duk_hthread *thr, duk_tval *tv);\n\nDUK_INTERNAL_DECL duk_int_t duk_to_int_clamped_raw(duk_hthread *thr, duk_idx_t idx, duk_int_t minval, duk_int_t maxval, duk_bool_t *out_clamped);  /* out_clamped=NULL, RangeError if outside range */\nDUK_INTERNAL_DECL duk_int_t duk_to_int_clamped(duk_hthread *thr, duk_idx_t idx, duk_int_t minval, duk_int_t maxval);\nDUK_INTERNAL_DECL duk_int_t duk_to_int_check_range(duk_hthread *thr, duk_idx_t idx, duk_int_t minval, duk_int_t maxval);\n#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)\nDUK_INTERNAL_DECL duk_uint8_t duk_to_uint8clamped(duk_hthread *thr, duk_idx_t idx);\n#endif\nDUK_INTERNAL_DECL duk_hstring *duk_to_property_key_hstring(duk_hthread *thr, duk_idx_t idx);\n\nDUK_INTERNAL_DECL duk_hstring *duk_require_hstring(duk_hthread *thr, duk_idx_t idx);\nDUK_INTERNAL_DECL duk_hstring *duk_require_hstring_notsymbol(duk_hthread *thr, duk_idx_t idx);\nDUK_INTERNAL_DECL const char *duk_require_lstring_notsymbol(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_len);\nDUK_INTERNAL_DECL const char *duk_require_string_notsymbol(duk_hthread *thr, duk_idx_t idx);\nDUK_INTERNAL_DECL duk_hobject *duk_require_hobject(duk_hthread *thr, duk_idx_t idx);\nDUK_INTERNAL_DECL duk_hbuffer *duk_require_hbuffer(duk_hthread *thr, duk_idx_t idx);\nDUK_INTERNAL_DECL duk_hthread *duk_require_hthread(duk_hthread *thr, duk_idx_t idx);\nDUK_INTERNAL_DECL duk_hcompfunc *duk_require_hcompfunc(duk_hthread *thr, duk_idx_t idx);\nDUK_INTERNAL_DECL duk_hnatfunc *duk_require_hnatfunc(duk_hthread *thr, duk_idx_t idx);\n\nDUK_INTERNAL_DECL duk_hobject *duk_require_hobject_with_class(duk_hthread *thr, duk_idx_t idx, duk_small_uint_t classnum);\n\nDUK_INTERNAL_DECL void duk_push_hstring(duk_hthread *thr, duk_hstring *h);\nDUK_INTERNAL_DECL void duk_push_hstring_stridx(duk_hthread *thr, duk_small_uint_t stridx);\nDUK_INTERNAL_DECL void duk_push_hstring_empty(duk_hthread *thr);\nDUK_INTERNAL_DECL void duk_push_hobject(duk_hthread *thr, duk_hobject *h);\nDUK_INTERNAL_DECL void duk_push_hbuffer(duk_hthread *thr, duk_hbuffer *h);\n#define duk_push_hthread(thr,h) \\\n\tduk_push_hobject((thr), (duk_hobject *) (h))\n#define duk_push_hnatfunc(thr,h) \\\n\tduk_push_hobject((thr), (duk_hobject *) (h))\nDUK_INTERNAL_DECL void duk_push_hobject_bidx(duk_hthread *thr, duk_small_int_t builtin_idx);\nDUK_INTERNAL_DECL duk_hobject *duk_push_object_helper(duk_hthread *thr, duk_uint_t hobject_flags_and_class, duk_small_int_t prototype_bidx);\nDUK_INTERNAL_DECL duk_hobject *duk_push_object_helper_proto(duk_hthread *thr, duk_uint_t hobject_flags_and_class, duk_hobject *proto);\nDUK_INTERNAL_DECL duk_hcompfunc *duk_push_hcompfunc(duk_hthread *thr);\nDUK_INTERNAL_DECL duk_hboundfunc *duk_push_hboundfunc(duk_hthread *thr);\nDUK_INTERNAL_DECL void duk_push_c_function_builtin(duk_hthread *thr, duk_c_function func, duk_int_t nargs);\nDUK_INTERNAL_DECL void duk_push_c_function_builtin_noconstruct(duk_hthread *thr, duk_c_function func, duk_int_t nargs);\n\n/* XXX: duk_push_harray() and duk_push_hcompfunc() are inconsistent with\n * duk_push_hobject() etc which don't create a new value.\n */\nDUK_INTERNAL_DECL duk_harray *duk_push_harray(duk_hthread *thr);\nDUK_INTERNAL_DECL duk_harray *duk_push_harray_with_size(duk_hthread *thr, duk_uint32_t size);\nDUK_INTERNAL_DECL duk_tval *duk_push_harray_with_size_outptr(duk_hthread *thr, duk_uint32_t size);\n\nDUK_INTERNAL_DECL void duk_push_string_funcptr(duk_hthread *thr, duk_uint8_t *ptr, duk_size_t sz);\nDUK_INTERNAL_DECL void duk_push_lightfunc_name_raw(duk_hthread *thr, duk_c_function func, duk_small_uint_t lf_flags);\nDUK_INTERNAL_DECL void duk_push_lightfunc_name(duk_hthread *thr, duk_tval *tv);\nDUK_INTERNAL_DECL void duk_push_lightfunc_tostring(duk_hthread *thr, duk_tval *tv);\n#if 0  /* not used yet */\nDUK_INTERNAL_DECL void duk_push_hnatfunc_name(duk_hthread *thr, duk_hnatfunc *h);\n#endif\n#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)\nDUK_INTERNAL_DECL duk_hbufobj *duk_push_bufobj_raw(duk_hthread *thr, duk_uint_t hobject_flags_and_class, duk_small_int_t prototype_bidx);\n#endif\n\nDUK_INTERNAL_DECL void *duk_push_fixed_buffer_nozero(duk_hthread *thr, duk_size_t len);\nDUK_INTERNAL_DECL void *duk_push_fixed_buffer_zero(duk_hthread *thr, duk_size_t len);\n\nDUK_INTERNAL_DECL const char *duk_push_string_readable(duk_hthread *thr, duk_idx_t idx);\nDUK_INTERNAL_DECL const char *duk_push_string_tval_readable(duk_hthread *thr, duk_tval *tv);\nDUK_INTERNAL_DECL const char *duk_push_string_tval_readable_error(duk_hthread *thr, duk_tval *tv);\n\n/* The duk_xxx_prop_stridx_short() variants expect their arguments to be short\n * enough to be packed into a single 32-bit integer argument.  Argument limits\n * vary per call; typically 16 bits are assigned to the signed value stack index\n * and the stridx.  In practice these work well for footprint with constant\n * arguments and such call sites are also easiest to verify to be correct.\n */\n\nDUK_INTERNAL_DECL duk_bool_t duk_get_prop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx);     /* [] -> [val] */\nDUK_INTERNAL_DECL duk_bool_t duk_get_prop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args);\n#define duk_get_prop_stridx_short(thr,obj_idx,stridx) \\\n\t(DUK_ASSERT_EXPR((duk_int_t) (obj_idx) >= -0x8000L && (duk_int_t) (obj_idx) <= 0x7fffL), \\\n\t DUK_ASSERT_EXPR((duk_int_t) (stridx) >= 0 && (duk_int_t) (stridx) <= 0xffffL), \\\n\t duk_get_prop_stridx_short_raw((thr), (((duk_uint_t) (obj_idx)) << 16) + ((duk_uint_t) (stridx))))\nDUK_INTERNAL_DECL duk_bool_t duk_get_prop_stridx_boolean(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx, duk_bool_t *out_has_prop);  /* [] -> [] */\n\nDUK_INTERNAL_DECL duk_bool_t duk_put_prop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx);     /* [val] -> [] */\nDUK_INTERNAL_DECL duk_bool_t duk_put_prop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args);\n#define duk_put_prop_stridx_short(thr,obj_idx,stridx) \\\n\t(DUK_ASSERT_EXPR((duk_int_t) (obj_idx) >= -0x8000L && (duk_int_t) (obj_idx) <= 0x7fffL), \\\n\t DUK_ASSERT_EXPR((duk_int_t) (stridx) >= 0 && (duk_int_t) (stridx) <= 0xffffL), \\\n\t duk_put_prop_stridx_short_raw((thr), (((duk_uint_t) (obj_idx)) << 16) + ((duk_uint_t) (stridx))))\n\nDUK_INTERNAL_DECL duk_bool_t duk_del_prop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx);     /* [] -> [] */\n#if 0  /* Too few call sites to be useful. */\nDUK_INTERNAL_DECL duk_bool_t duk_del_prop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args);\n#define duk_del_prop_stridx_short(thr,obj_idx,stridx) \\\n\t(DUK_ASSERT_EXPR((obj_idx) >= -0x8000L && (obj_idx) <= 0x7fffL), \\\n\t DUK_ASSERT_EXPR((stridx) >= 0 && (stridx) <= 0xffffL), \\\n\t duk_del_prop_stridx_short_raw((thr), (((duk_uint_t) (obj_idx)) << 16) + ((duk_uint_t) (stridx))))\n#endif\n#define duk_del_prop_stridx_short(thr,obj_idx,stridx) \\\n\tduk_del_prop_stridx((thr), (obj_idx), (stridx))\n\nDUK_INTERNAL_DECL duk_bool_t duk_has_prop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx);     /* [] -> [] */\n#if 0  /* Too few call sites to be useful. */\nDUK_INTERNAL_DECL duk_bool_t duk_has_prop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args);\n#define duk_has_prop_stridx_short(thr,obj_idx,stridx) \\\n\t(DUK_ASSERT_EXPR((obj_idx) >= -0x8000L && (obj_idx) <= 0x7fffL), \\\n\t DUK_ASSERT_EXPR((stridx) >= 0 && (stridx) <= 0xffffL), \\\n\t duk_has_prop_stridx_short_raw((thr), (((duk_uint_t) (obj_idx)) << 16) + ((duk_uint_t) (stridx))))\n#endif\n#define duk_has_prop_stridx_short(thr,obj_idx,stridx) \\\n\tduk_has_prop_stridx((thr), (obj_idx), (stridx))\n\nDUK_INTERNAL_DECL void duk_xdef_prop(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t desc_flags);  /* [key val] -> [] */\n\nDUK_INTERNAL_DECL void duk_xdef_prop_index(duk_hthread *thr, duk_idx_t obj_idx, duk_uarridx_t arr_idx, duk_small_uint_t desc_flags);  /* [val] -> [] */\n\n/* XXX: Because stridx and desc_flags have a limited range, this call could\n * always pack stridx and desc_flags into a single argument.\n */\nDUK_INTERNAL_DECL void duk_xdef_prop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx, duk_small_uint_t desc_flags);  /* [val] -> [] */\nDUK_INTERNAL_DECL void duk_xdef_prop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args);\n#define duk_xdef_prop_stridx_short(thr,obj_idx,stridx,desc_flags) \\\n\t(DUK_ASSERT_EXPR((duk_int_t) (obj_idx) >= -0x80L && (duk_int_t) (obj_idx) <= 0x7fL), \\\n\t DUK_ASSERT_EXPR((duk_int_t) (stridx) >= 0 && (duk_int_t) (stridx) <= 0xffffL), \\\n\t DUK_ASSERT_EXPR((duk_int_t) (desc_flags) >= 0 && (duk_int_t) (desc_flags) <= 0xffL), \\\n\t duk_xdef_prop_stridx_short_raw((thr), (((duk_uint_t) (obj_idx)) << 24) + (((duk_uint_t) (stridx)) << 8) + (duk_uint_t) (desc_flags)))\n\n#define duk_xdef_prop_wec(thr,obj_idx) \\\n\tduk_xdef_prop((thr), (obj_idx), DUK_PROPDESC_FLAGS_WEC)\n#define duk_xdef_prop_index_wec(thr,obj_idx,arr_idx) \\\n\tduk_xdef_prop_index((thr), (obj_idx), (arr_idx), DUK_PROPDESC_FLAGS_WEC)\n#define duk_xdef_prop_stridx_wec(thr,obj_idx,stridx) \\\n\tduk_xdef_prop_stridx((thr), (obj_idx), (stridx), DUK_PROPDESC_FLAGS_WEC)\n#define duk_xdef_prop_stridx_short_wec(thr,obj_idx,stridx) \\\n\tduk_xdef_prop_stridx_short((thr), (obj_idx), (stridx), DUK_PROPDESC_FLAGS_WEC)\n\n#if 0  /*unused*/\nDUK_INTERNAL_DECL void duk_xdef_prop_stridx_builtin(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx, duk_small_int_t builtin_idx, duk_small_uint_t desc_flags);  /* [] -> [] */\n#endif\n\nDUK_INTERNAL_DECL void duk_xdef_prop_stridx_thrower(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx);  /* [] -> [] */\n\nDUK_INTERNAL_DECL void duk_pack(duk_hthread *thr, duk_idx_t count);\nDUK_INTERNAL_DECL duk_idx_t duk_unpack_array_like(duk_hthread *thr, duk_idx_t idx);\n#if 0\nDUK_INTERNAL_DECL void duk_unpack(duk_hthread *thr);\n#endif\n\nDUK_INTERNAL_DECL void duk_require_constructor_call(duk_hthread *thr);\nDUK_INTERNAL_DECL void duk_require_constructable(duk_hthread *thr, duk_idx_t idx);\nDUK_INTERNAL_DECL void duk_push_symbol_descriptive_string(duk_hthread *thr, duk_hstring *h);\n\nDUK_INTERNAL_DECL void duk_resolve_nonbound_function(duk_hthread *thr);\n\nDUK_INTERNAL_DECL duk_idx_t duk_get_top_require_min(duk_hthread *thr, duk_idx_t min_top);\nDUK_INTERNAL_DECL duk_idx_t duk_get_top_index_unsafe(duk_hthread *thr);\n\nDUK_INTERNAL_DECL void duk_pop_n_unsafe(duk_hthread *thr, duk_idx_t count);\nDUK_INTERNAL_DECL void duk_pop_unsafe(duk_hthread *thr);\nDUK_INTERNAL_DECL void duk_pop_2_unsafe(duk_hthread *thr);\nDUK_INTERNAL_DECL void duk_pop_3_unsafe(duk_hthread *thr);\nDUK_INTERNAL_DECL void duk_pop_n_nodecref_unsafe(duk_hthread *thr, duk_idx_t count);\nDUK_INTERNAL_DECL void duk_pop_nodecref_unsafe(duk_hthread *thr);\nDUK_INTERNAL_DECL void duk_pop_2_nodecref_unsafe(duk_hthread *thr);\nDUK_INTERNAL_DECL void duk_pop_3_nodecref_unsafe(duk_hthread *thr);\nDUK_INTERNAL_DECL void duk_pop_undefined(duk_hthread *thr);\n\nDUK_INTERNAL_DECL void duk_compact_m1(duk_hthread *thr);\n\nDUK_INTERNAL_DECL void duk_seal_freeze_raw(duk_hthread *thr, duk_idx_t obj_idx, duk_bool_t is_freeze);\n\nDUK_INTERNAL_DECL void duk_insert_undefined(duk_hthread *thr, duk_idx_t idx);\nDUK_INTERNAL_DECL void duk_insert_undefined_n(duk_hthread *thr, duk_idx_t idx, duk_idx_t count);\n\nDUK_INTERNAL_DECL void duk_concat_2(duk_hthread *thr);\n\nDUK_INTERNAL_DECL duk_int_t duk_pcall_method_flags(duk_hthread *thr, duk_idx_t nargs, duk_small_uint_t call_flags);\n\n/* Raw internal valstack access macros: access is unsafe so call site\n * must have a guarantee that the index is valid.  When that is the case,\n * using these macro results in faster and smaller code than duk_get_tval().\n * Both 'ctx' and 'idx' are evaluted multiple times, but only for asserts.\n */\n#define DUK_ASSERT_VALID_NEGIDX(thr,idx) \\\n\t(DUK_ASSERT_EXPR((duk_int_t) (idx) < 0), DUK_ASSERT_EXPR(duk_is_valid_index((thr), (idx))))\n#define DUK_ASSERT_VALID_POSIDX(thr,idx) \\\n\t(DUK_ASSERT_EXPR((duk_int_t) (idx) >= 0), DUK_ASSERT_EXPR(duk_is_valid_index((thr), (idx))))\n#define DUK_GET_TVAL_NEGIDX(thr,idx) \\\n\t(DUK_ASSERT_VALID_NEGIDX((thr),(idx)), ((duk_hthread *) (thr))->valstack_top + (idx))\n#define DUK_GET_TVAL_POSIDX(thr,idx) \\\n\t(DUK_ASSERT_VALID_POSIDX((thr),(idx)), ((duk_hthread *) (thr))->valstack_bottom + (idx))\n#define DUK_GET_HOBJECT_NEGIDX(thr,idx) \\\n\t(DUK_ASSERT_VALID_NEGIDX((thr),(idx)), DUK_TVAL_GET_OBJECT(((duk_hthread *) (thr))->valstack_top + (idx)))\n#define DUK_GET_HOBJECT_POSIDX(thr,idx) \\\n\t(DUK_ASSERT_VALID_POSIDX((thr),(idx)), DUK_TVAL_GET_OBJECT(((duk_hthread *) (thr))->valstack_bottom + (idx)))\n\n#define DUK_GET_THIS_TVAL_PTR(thr) \\\n\t(DUK_ASSERT_EXPR((thr)->valstack_bottom > (thr)->valstack), \\\n\t (thr)->valstack_bottom - 1)\n\nDUK_INTERNAL_DECL duk_double_t duk_time_get_ecmascript_time(duk_hthread *thr);\nDUK_INTERNAL_DECL duk_double_t duk_time_get_ecmascript_time_nofrac(duk_hthread *thr);\nDUK_INTERNAL_DECL duk_double_t duk_time_get_monotonic_time(duk_hthread *thr);\n\n#endif  /* DUK_API_INTERNAL_H_INCLUDED */\n/* #include duk_hstring.h */\n#line 1 \"duk_hstring.h\"\n/*\n *  Heap string representation.\n *\n *  Strings are byte sequences ordinarily stored in extended UTF-8 format,\n *  allowing values larger than the official UTF-8 range (used internally)\n *  and also allowing UTF-8 encoding of surrogate pairs (CESU-8 format).\n *  Strings may also be invalid UTF-8 altogether which is the case e.g. with\n *  strings used as internal property names and raw buffers converted to\n *  strings.  In such cases the 'clen' field contains an inaccurate value.\n *\n *  Ecmascript requires support for 32-bit long strings.  However, since each\n *  16-bit codepoint can take 3 bytes in CESU-8, this representation can only\n *  support about 1.4G codepoint long strings in extreme cases.  This is not\n *  really a practical issue.\n */\n\n#if !defined(DUK_HSTRING_H_INCLUDED)\n#define DUK_HSTRING_H_INCLUDED\n\n/* Impose a maximum string length for now.  Restricted artificially to\n * ensure adding a heap header length won't overflow size_t.  The limit\n * should be synchronized with DUK_HBUFFER_MAX_BYTELEN.\n *\n * E5.1 makes provisions to support strings longer than 4G characters.\n * This limit should be eliminated on 64-bit platforms (and increased\n * closer to maximum support on 32-bit platforms).\n */\n\n#if defined(DUK_USE_STRLEN16)\n#define DUK_HSTRING_MAX_BYTELEN                     (0x0000ffffUL)\n#else\n#define DUK_HSTRING_MAX_BYTELEN                     (0x7fffffffUL)\n#endif\n\n/* XXX: could add flags for \"is valid CESU-8\" (Ecmascript compatible strings),\n * \"is valid UTF-8\", \"is valid extended UTF-8\" (internal strings are not,\n * regexp bytecode is), and \"contains non-BMP characters\".  These are not\n * needed right now.\n */\n\n#define DUK_HSTRING_FLAG_ASCII                      DUK_HEAPHDR_USER_FLAG(0)  /* string is ASCII, clen == blen */\n#define DUK_HSTRING_FLAG_ARRIDX                     DUK_HEAPHDR_USER_FLAG(1)  /* string is a valid array index */\n#define DUK_HSTRING_FLAG_SYMBOL                     DUK_HEAPHDR_USER_FLAG(2)  /* string is a symbol (invalid utf-8) */\n#define DUK_HSTRING_FLAG_HIDDEN                     DUK_HEAPHDR_USER_FLAG(3)  /* string is a hidden symbol (implies symbol, Duktape 1.x internal string) */\n#define DUK_HSTRING_FLAG_RESERVED_WORD              DUK_HEAPHDR_USER_FLAG(4)  /* string is a reserved word (non-strict) */\n#define DUK_HSTRING_FLAG_STRICT_RESERVED_WORD       DUK_HEAPHDR_USER_FLAG(5)  /* string is a reserved word (strict) */\n#define DUK_HSTRING_FLAG_EVAL_OR_ARGUMENTS          DUK_HEAPHDR_USER_FLAG(6)  /* string is 'eval' or 'arguments' */\n#define DUK_HSTRING_FLAG_EXTDATA                    DUK_HEAPHDR_USER_FLAG(7)  /* string data is external (duk_hstring_external) */\n\n#define DUK_HSTRING_HAS_ASCII(x)                    DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ASCII)\n#define DUK_HSTRING_HAS_ARRIDX(x)                   DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ARRIDX)\n#define DUK_HSTRING_HAS_SYMBOL(x)                   DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_SYMBOL)\n#define DUK_HSTRING_HAS_HIDDEN(x)                   DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_HIDDEN)\n#define DUK_HSTRING_HAS_RESERVED_WORD(x)            DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_RESERVED_WORD)\n#define DUK_HSTRING_HAS_STRICT_RESERVED_WORD(x)     DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_STRICT_RESERVED_WORD)\n#define DUK_HSTRING_HAS_EVAL_OR_ARGUMENTS(x)        DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EVAL_OR_ARGUMENTS)\n#define DUK_HSTRING_HAS_EXTDATA(x)                  DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EXTDATA)\n\n#define DUK_HSTRING_SET_ASCII(x)                    DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ASCII)\n#define DUK_HSTRING_SET_ARRIDX(x)                   DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ARRIDX)\n#define DUK_HSTRING_SET_SYMBOL(x)                   DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_SYMBOL)\n#define DUK_HSTRING_SET_HIDDEN(x)                   DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_HIDDEN)\n#define DUK_HSTRING_SET_RESERVED_WORD(x)            DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_RESERVED_WORD)\n#define DUK_HSTRING_SET_STRICT_RESERVED_WORD(x)     DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_STRICT_RESERVED_WORD)\n#define DUK_HSTRING_SET_EVAL_OR_ARGUMENTS(x)        DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EVAL_OR_ARGUMENTS)\n#define DUK_HSTRING_SET_EXTDATA(x)                  DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EXTDATA)\n\n#define DUK_HSTRING_CLEAR_ASCII(x)                  DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ASCII)\n#define DUK_HSTRING_CLEAR_ARRIDX(x)                 DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ARRIDX)\n#define DUK_HSTRING_CLEAR_SYMBOL(x)                 DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_SYMBOL)\n#define DUK_HSTRING_CLEAR_HIDDEN(x)                 DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_HIDDEN)\n#define DUK_HSTRING_CLEAR_RESERVED_WORD(x)          DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_RESERVED_WORD)\n#define DUK_HSTRING_CLEAR_STRICT_RESERVED_WORD(x)   DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_STRICT_RESERVED_WORD)\n#define DUK_HSTRING_CLEAR_EVAL_OR_ARGUMENTS(x)      DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EVAL_OR_ARGUMENTS)\n#define DUK_HSTRING_CLEAR_EXTDATA(x)                DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EXTDATA)\n\n#if 0  /* Slightly smaller code without explicit flag, but explicit flag\n        * is very useful when 'clen' is dropped.\n        */\n#define DUK_HSTRING_IS_ASCII(x)                     (DUK_HSTRING_GET_BYTELEN((x)) == DUK_HSTRING_GET_CHARLEN((x)))\n#endif\n#define DUK_HSTRING_IS_ASCII(x)                     DUK_HSTRING_HAS_ASCII((x))  /* lazily set! */\n#define DUK_HSTRING_IS_EMPTY(x)                     (DUK_HSTRING_GET_BYTELEN((x)) == 0)\n\n#if defined(DUK_USE_STRHASH16)\n#define DUK_HSTRING_GET_HASH(x)                     ((x)->hdr.h_flags >> 16)\n#define DUK_HSTRING_SET_HASH(x,v) do { \\\n\t\t(x)->hdr.h_flags = ((x)->hdr.h_flags & 0x0000ffffUL) | ((v) << 16); \\\n\t} while (0)\n#else\n#define DUK_HSTRING_GET_HASH(x)                     ((x)->hash)\n#define DUK_HSTRING_SET_HASH(x,v) do { \\\n\t\t(x)->hash = (v); \\\n\t} while (0)\n#endif\n\n#if defined(DUK_USE_STRLEN16)\n#define DUK_HSTRING_GET_BYTELEN(x)                  ((x)->hdr.h_strextra16)\n#define DUK_HSTRING_SET_BYTELEN(x,v) do { \\\n\t\t(x)->hdr.h_strextra16 = (v); \\\n\t} while (0)\n#if defined(DUK_USE_HSTRING_CLEN)\n#define DUK_HSTRING_GET_CHARLEN(x)                  duk_hstring_get_charlen((x))\n#define DUK_HSTRING_SET_CHARLEN(x,v) do { \\\n\t\t(x)->clen16 = (v); \\\n\t} while (0)\n#else\n#define DUK_HSTRING_GET_CHARLEN(x)                  duk_hstring_get_charlen((x))\n#define DUK_HSTRING_SET_CHARLEN(x,v) do { \\\n\t\tDUK_ASSERT(0);  /* should never be called */ \\\n\t} while (0)\n#endif\n#else\n#define DUK_HSTRING_GET_BYTELEN(x)                  ((x)->blen)\n#define DUK_HSTRING_SET_BYTELEN(x,v) do { \\\n\t\t(x)->blen = (v); \\\n\t} while (0)\n#define DUK_HSTRING_GET_CHARLEN(x)                  duk_hstring_get_charlen((x))\n#define DUK_HSTRING_SET_CHARLEN(x,v) do { \\\n\t\t(x)->clen = (v); \\\n\t} while (0)\n#endif\n\n#if defined(DUK_USE_HSTRING_EXTDATA)\n#define DUK_HSTRING_GET_EXTDATA(x) \\\n\t((x)->extdata)\n#define DUK_HSTRING_GET_DATA(x) \\\n\t(DUK_HSTRING_HAS_EXTDATA((x)) ? \\\n\t\tDUK_HSTRING_GET_EXTDATA((const duk_hstring_external *) (x)) : ((const duk_uint8_t *) ((x) + 1)))\n#else\n#define DUK_HSTRING_GET_DATA(x) \\\n\t((const duk_uint8_t *) ((x) + 1))\n#endif\n\n#define DUK_HSTRING_GET_DATA_END(x) \\\n\t(DUK_HSTRING_GET_DATA((x)) + (x)->blen)\n\n/* Marker value; in E5 2^32-1 is not a valid array index (2^32-2 is highest\n * valid).\n */\n#define DUK_HSTRING_NO_ARRAY_INDEX  (0xffffffffUL)\n\n#if defined(DUK_USE_HSTRING_ARRIDX)\n#define DUK_HSTRING_GET_ARRIDX_FAST(h)  ((h)->arridx)\n#define DUK_HSTRING_GET_ARRIDX_SLOW(h)  ((h)->arridx)\n#else\n/* Get array index related to string (or return DUK_HSTRING_NO_ARRAY_INDEX);\n * avoids helper call if string has no array index value.\n */\n#define DUK_HSTRING_GET_ARRIDX_FAST(h)  \\\n\t(DUK_HSTRING_HAS_ARRIDX((h)) ? duk_js_to_arrayindex_hstring_fast_known((h)) : DUK_HSTRING_NO_ARRAY_INDEX)\n\n/* Slower but more compact variant. */\n#define DUK_HSTRING_GET_ARRIDX_SLOW(h)  \\\n\t(duk_js_to_arrayindex_hstring_fast((h)))\n#endif\n\n/* XXX: these actually fit into duk_hstring */\n#define DUK_SYMBOL_TYPE_HIDDEN 0\n#define DUK_SYMBOL_TYPE_GLOBAL 1\n#define DUK_SYMBOL_TYPE_LOCAL 2\n#define DUK_SYMBOL_TYPE_WELLKNOWN 3\n\n/*\n *  Misc\n */\n\nstruct duk_hstring {\n\t/* Smaller heaphdr than for other objects, because strings are held\n\t * in string intern table which requires no link pointers.  Much of\n\t * the 32-bit flags field is unused by flags, so we can stuff a 16-bit\n\t * field in there.\n\t */\n\tduk_heaphdr_string hdr;\n\n\t/* String hash. */\n#if defined(DUK_USE_STRHASH16)\n\t/* If 16-bit hash is in use, stuff it into duk_heaphdr_string flags. */\n#else\n\tduk_uint32_t hash;\n#endif\n\n\t/* Precomputed array index (or DUK_HSTRING_NO_ARRAY_INDEX). */\n#if defined(DUK_USE_HSTRING_ARRIDX)\n\tduk_uarridx_t arridx;\n#endif\n\n\t/* Length in bytes (not counting NUL term). */\n#if defined(DUK_USE_STRLEN16)\n\t/* placed in duk_heaphdr_string */\n#else\n\tduk_uint32_t blen;\n#endif\n\n\t/* Length in codepoints (must be E5 compatible). */\n#if defined(DUK_USE_STRLEN16)\n#if defined(DUK_USE_HSTRING_CLEN)\n\tduk_uint16_t clen16;\n#else\n\t/* computed live */\n#endif\n#else\n\tduk_uint32_t clen;\n#endif\n\n\t/*\n\t *  String data of 'blen+1' bytes follows (+1 for NUL termination\n\t *  convenience for C API).  No alignment needs to be guaranteed\n\t *  for strings, but fields above should guarantee alignment-by-4\n\t *  (but not alignment-by-8).\n\t */\n};\n\n/* The external string struct is defined even when the feature is inactive. */\nstruct duk_hstring_external {\n\tduk_hstring str;\n\n\t/*\n\t *  For an external string, the NUL-terminated string data is stored\n\t *  externally.  The user must guarantee that data behind this pointer\n\t *  doesn't change while it's used.\n\t */\n\n\tconst duk_uint8_t *extdata;\n};\n\n/*\n *  Prototypes\n */\n\nDUK_INTERNAL_DECL duk_ucodepoint_t duk_hstring_char_code_at_raw(duk_hthread *thr, duk_hstring *h, duk_uint_t pos, duk_bool_t surrogate_aware);\nDUK_INTERNAL_DECL duk_bool_t duk_hstring_equals_ascii_cstring(duk_hstring *h, const char *cstr);\nDUK_INTERNAL_DECL duk_size_t duk_hstring_get_charlen(duk_hstring *h);\n#if !defined(DUK_USE_HSTRING_LAZY_CLEN)\nDUK_INTERNAL_DECL void duk_hstring_init_charlen(duk_hstring *h);\n#endif\n\n#endif  /* DUK_HSTRING_H_INCLUDED */\n/* #include duk_hobject.h */\n#line 1 \"duk_hobject.h\"\n/*\n *  Heap object representation.\n *\n *  Heap objects are used for Ecmascript objects, arrays, and functions,\n *  but also for internal control like declarative and object environment\n *  records.  Compiled functions, native functions, and threads are also\n *  objects but with an extended C struct.\n *\n *  Objects provide the required Ecmascript semantics and exotic behaviors\n *  especially for property access.\n *\n *  Properties are stored in three conceptual parts:\n *\n *    1. A linear 'entry part' contains ordered key-value-attributes triples\n *       and is the main method of string properties.\n *\n *    2. An optional linear 'array part' is used for array objects to store a\n *       (dense) range of [0,N[ array indexed entries with default attributes\n *       (writable, enumerable, configurable).  If the array part would become\n *       sparse or non-default attributes are required, the array part is\n *       abandoned and moved to the 'entry part'.\n *\n *    3. An optional 'hash part' is used to optimize lookups of the entry\n *       part; it is used only for objects with sufficiently many properties\n *       and can be abandoned without loss of information.\n *\n *  These three conceptual parts are stored in a single memory allocated area.\n *  This minimizes memory allocation overhead but also means that all three\n *  parts are resized together, and makes property access a bit complicated.\n */\n\n#if !defined(DUK_HOBJECT_H_INCLUDED)\n#define DUK_HOBJECT_H_INCLUDED\n\n/* Object flags.  Make sure this stays in sync with debugger object\n * inspection code.\n */\n\n/* XXX: some flags are object subtype specific (e.g. common to all function\n * subtypes, duk_harray, etc) and could be reused for different subtypes.\n */\n#define DUK_HOBJECT_FLAG_EXTENSIBLE            DUK_HEAPHDR_USER_FLAG(0)   /* object is extensible */\n#define DUK_HOBJECT_FLAG_CONSTRUCTABLE         DUK_HEAPHDR_USER_FLAG(1)   /* object is constructable */\n#define DUK_HOBJECT_FLAG_CALLABLE              DUK_HEAPHDR_USER_FLAG(2)   /* object is callable */\n#define DUK_HOBJECT_FLAG_BOUNDFUNC             DUK_HEAPHDR_USER_FLAG(3)   /* object established using Function.prototype.bind() */\n#define DUK_HOBJECT_FLAG_COMPFUNC              DUK_HEAPHDR_USER_FLAG(4)   /* object is a compiled function (duk_hcompfunc) */\n#define DUK_HOBJECT_FLAG_NATFUNC               DUK_HEAPHDR_USER_FLAG(5)   /* object is a native function (duk_hnatfunc) */\n#define DUK_HOBJECT_FLAG_BUFOBJ                DUK_HEAPHDR_USER_FLAG(6)   /* object is a buffer object (duk_hbufobj) (always exotic) */\n#define DUK_HOBJECT_FLAG_FASTREFS              DUK_HEAPHDR_USER_FLAG(7)   /* object has no fields needing DECREF/marking beyond base duk_hobject header */\n#define DUK_HOBJECT_FLAG_ARRAY_PART            DUK_HEAPHDR_USER_FLAG(8)   /* object has an array part (a_size may still be 0) */\n#define DUK_HOBJECT_FLAG_STRICT                DUK_HEAPHDR_USER_FLAG(9)   /* function: function object is strict */\n#define DUK_HOBJECT_FLAG_NOTAIL                DUK_HEAPHDR_USER_FLAG(10)  /* function: function must not be tail called */\n#define DUK_HOBJECT_FLAG_NEWENV                DUK_HEAPHDR_USER_FLAG(11)  /* function: create new environment when called (see duk_hcompfunc) */\n#define DUK_HOBJECT_FLAG_NAMEBINDING           DUK_HEAPHDR_USER_FLAG(12)  /* function: create binding for func name (function templates only, used for named function expressions) */\n#define DUK_HOBJECT_FLAG_CREATEARGS            DUK_HEAPHDR_USER_FLAG(13)  /* function: create an arguments object on function call */\n#define DUK_HOBJECT_FLAG_HAVE_FINALIZER        DUK_HEAPHDR_USER_FLAG(14)  /* object has a callable (own) finalizer property */\n#define DUK_HOBJECT_FLAG_EXOTIC_ARRAY          DUK_HEAPHDR_USER_FLAG(15)  /* 'Array' object, array length and index exotic behavior */\n#define DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ      DUK_HEAPHDR_USER_FLAG(16)  /* 'String' object, array index exotic behavior */\n#define DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS      DUK_HEAPHDR_USER_FLAG(17)  /* 'Arguments' object and has arguments exotic behavior (non-strict callee) */\n#define DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ       DUK_HEAPHDR_USER_FLAG(18)  /* 'Proxy' object */\n#define DUK_HOBJECT_FLAG_SPECIAL_CALL          DUK_HEAPHDR_USER_FLAG(19)  /* special casing in call behavior, for .call(), .apply(), etc. */\n\n#define DUK_HOBJECT_FLAG_CLASS_BASE            DUK_HEAPHDR_USER_FLAG_NUMBER(20)\n#define DUK_HOBJECT_FLAG_CLASS_BITS            5\n\n#define DUK_HOBJECT_GET_CLASS_NUMBER(h)        \\\n\tDUK_HEAPHDR_GET_FLAG_RANGE(&(h)->hdr, DUK_HOBJECT_FLAG_CLASS_BASE, DUK_HOBJECT_FLAG_CLASS_BITS)\n#define DUK_HOBJECT_SET_CLASS_NUMBER(h,v)      \\\n\tDUK_HEAPHDR_SET_FLAG_RANGE(&(h)->hdr, DUK_HOBJECT_FLAG_CLASS_BASE, DUK_HOBJECT_FLAG_CLASS_BITS, (v))\n\n#define DUK_HOBJECT_GET_CLASS_MASK(h)          \\\n\t(1UL << DUK_HEAPHDR_GET_FLAG_RANGE(&(h)->hdr, DUK_HOBJECT_FLAG_CLASS_BASE, DUK_HOBJECT_FLAG_CLASS_BITS))\n\n/* Macro for creating flag initializer from a class number.\n * Unsigned type cast is needed to avoid warnings about coercing\n * a signed integer to an unsigned one; the largest class values\n * have the highest bit (bit 31) set which causes this.\n */\n#define DUK_HOBJECT_CLASS_AS_FLAGS(v)          (((duk_uint_t) (v)) << DUK_HOBJECT_FLAG_CLASS_BASE)\n\n/* E5 Section 8.6.2 + custom classes */\n#define DUK_HOBJECT_CLASS_NONE                 0\n#define DUK_HOBJECT_CLASS_OBJECT               1\n#define DUK_HOBJECT_CLASS_ARRAY                2\n#define DUK_HOBJECT_CLASS_FUNCTION             3\n#define DUK_HOBJECT_CLASS_ARGUMENTS            4\n#define DUK_HOBJECT_CLASS_BOOLEAN              5\n#define DUK_HOBJECT_CLASS_DATE                 6\n#define DUK_HOBJECT_CLASS_ERROR                7\n#define DUK_HOBJECT_CLASS_JSON                 8\n#define DUK_HOBJECT_CLASS_MATH                 9\n#define DUK_HOBJECT_CLASS_NUMBER               10\n#define DUK_HOBJECT_CLASS_REGEXP               11\n#define DUK_HOBJECT_CLASS_STRING               12\n#define DUK_HOBJECT_CLASS_GLOBAL               13\n#define DUK_HOBJECT_CLASS_SYMBOL               14\n#define DUK_HOBJECT_CLASS_OBJENV               15  /* custom */\n#define DUK_HOBJECT_CLASS_DECENV               16  /* custom */\n#define DUK_HOBJECT_CLASS_POINTER              17  /* custom */\n#define DUK_HOBJECT_CLASS_THREAD               18  /* custom; implies DUK_HOBJECT_IS_THREAD */\n#define DUK_HOBJECT_CLASS_BUFOBJ_MIN           19\n#define DUK_HOBJECT_CLASS_ARRAYBUFFER          19  /* implies DUK_HOBJECT_IS_BUFOBJ */\n#define DUK_HOBJECT_CLASS_DATAVIEW             20\n#define DUK_HOBJECT_CLASS_INT8ARRAY            21\n#define DUK_HOBJECT_CLASS_UINT8ARRAY           22\n#define DUK_HOBJECT_CLASS_UINT8CLAMPEDARRAY    23\n#define DUK_HOBJECT_CLASS_INT16ARRAY           24\n#define DUK_HOBJECT_CLASS_UINT16ARRAY          25\n#define DUK_HOBJECT_CLASS_INT32ARRAY           26\n#define DUK_HOBJECT_CLASS_UINT32ARRAY          27\n#define DUK_HOBJECT_CLASS_FLOAT32ARRAY         28\n#define DUK_HOBJECT_CLASS_FLOAT64ARRAY         29\n#define DUK_HOBJECT_CLASS_BUFOBJ_MAX           29\n#define DUK_HOBJECT_CLASS_MAX                  29\n\n/* Class masks. */\n#define DUK_HOBJECT_CMASK_ALL                  ((1UL << (DUK_HOBJECT_CLASS_MAX + 1)) - 1UL)\n#define DUK_HOBJECT_CMASK_NONE                 (1UL << DUK_HOBJECT_CLASS_NONE)\n#define DUK_HOBJECT_CMASK_ARGUMENTS            (1UL << DUK_HOBJECT_CLASS_ARGUMENTS)\n#define DUK_HOBJECT_CMASK_ARRAY                (1UL << DUK_HOBJECT_CLASS_ARRAY)\n#define DUK_HOBJECT_CMASK_BOOLEAN              (1UL << DUK_HOBJECT_CLASS_BOOLEAN)\n#define DUK_HOBJECT_CMASK_DATE                 (1UL << DUK_HOBJECT_CLASS_DATE)\n#define DUK_HOBJECT_CMASK_ERROR                (1UL << DUK_HOBJECT_CLASS_ERROR)\n#define DUK_HOBJECT_CMASK_FUNCTION             (1UL << DUK_HOBJECT_CLASS_FUNCTION)\n#define DUK_HOBJECT_CMASK_JSON                 (1UL << DUK_HOBJECT_CLASS_JSON)\n#define DUK_HOBJECT_CMASK_MATH                 (1UL << DUK_HOBJECT_CLASS_MATH)\n#define DUK_HOBJECT_CMASK_NUMBER               (1UL << DUK_HOBJECT_CLASS_NUMBER)\n#define DUK_HOBJECT_CMASK_OBJECT               (1UL << DUK_HOBJECT_CLASS_OBJECT)\n#define DUK_HOBJECT_CMASK_REGEXP               (1UL << DUK_HOBJECT_CLASS_REGEXP)\n#define DUK_HOBJECT_CMASK_STRING               (1UL << DUK_HOBJECT_CLASS_STRING)\n#define DUK_HOBJECT_CMASK_GLOBAL               (1UL << DUK_HOBJECT_CLASS_GLOBAL)\n#define DUK_HOBJECT_CMASK_SYMBOL               (1UL << DUK_HOBJECT_CLASS_SYMBOL)\n#define DUK_HOBJECT_CMASK_OBJENV               (1UL << DUK_HOBJECT_CLASS_OBJENV)\n#define DUK_HOBJECT_CMASK_DECENV               (1UL << DUK_HOBJECT_CLASS_DECENV)\n#define DUK_HOBJECT_CMASK_POINTER              (1UL << DUK_HOBJECT_CLASS_POINTER)\n#define DUK_HOBJECT_CMASK_ARRAYBUFFER          (1UL << DUK_HOBJECT_CLASS_ARRAYBUFFER)\n#define DUK_HOBJECT_CMASK_DATAVIEW             (1UL << DUK_HOBJECT_CLASS_DATAVIEW)\n#define DUK_HOBJECT_CMASK_INT8ARRAY            (1UL << DUK_HOBJECT_CLASS_INT8ARRAY)\n#define DUK_HOBJECT_CMASK_UINT8ARRAY           (1UL << DUK_HOBJECT_CLASS_UINT8ARRAY)\n#define DUK_HOBJECT_CMASK_UINT8CLAMPEDARRAY    (1UL << DUK_HOBJECT_CLASS_UINT8CLAMPEDARRAY)\n#define DUK_HOBJECT_CMASK_INT16ARRAY           (1UL << DUK_HOBJECT_CLASS_INT16ARRAY)\n#define DUK_HOBJECT_CMASK_UINT16ARRAY          (1UL << DUK_HOBJECT_CLASS_UINT16ARRAY)\n#define DUK_HOBJECT_CMASK_INT32ARRAY           (1UL << DUK_HOBJECT_CLASS_INT32ARRAY)\n#define DUK_HOBJECT_CMASK_UINT32ARRAY          (1UL << DUK_HOBJECT_CLASS_UINT32ARRAY)\n#define DUK_HOBJECT_CMASK_FLOAT32ARRAY         (1UL << DUK_HOBJECT_CLASS_FLOAT32ARRAY)\n#define DUK_HOBJECT_CMASK_FLOAT64ARRAY         (1UL << DUK_HOBJECT_CLASS_FLOAT64ARRAY)\n\n#define DUK_HOBJECT_CMASK_ALL_BUFOBJS \\\n\t(DUK_HOBJECT_CMASK_ARRAYBUFFER | \\\n\t DUK_HOBJECT_CMASK_DATAVIEW | \\\n\t DUK_HOBJECT_CMASK_INT8ARRAY | \\\n\t DUK_HOBJECT_CMASK_UINT8ARRAY | \\\n\t DUK_HOBJECT_CMASK_UINT8CLAMPEDARRAY | \\\n\t DUK_HOBJECT_CMASK_INT16ARRAY | \\\n\t DUK_HOBJECT_CMASK_UINT16ARRAY | \\\n\t DUK_HOBJECT_CMASK_INT32ARRAY | \\\n\t DUK_HOBJECT_CMASK_UINT32ARRAY | \\\n\t DUK_HOBJECT_CMASK_FLOAT32ARRAY | \\\n\t DUK_HOBJECT_CMASK_FLOAT64ARRAY)\n\n#define DUK_HOBJECT_IS_OBJENV(h)               (DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_OBJENV)\n#define DUK_HOBJECT_IS_DECENV(h)               (DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_DECENV)\n#define DUK_HOBJECT_IS_ENV(h)                  (DUK_HOBJECT_IS_OBJENV((h)) || DUK_HOBJECT_IS_DECENV((h)))\n#define DUK_HOBJECT_IS_ARRAY(h)                DUK_HOBJECT_HAS_EXOTIC_ARRAY((h))  /* Rely on class Array <=> exotic Array */\n#define DUK_HOBJECT_IS_BOUNDFUNC(h)            DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BOUNDFUNC)\n#define DUK_HOBJECT_IS_COMPFUNC(h)             DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_COMPFUNC)\n#define DUK_HOBJECT_IS_NATFUNC(h)              DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NATFUNC)\n#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)\n#define DUK_HOBJECT_IS_BUFOBJ(h)               DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BUFOBJ)\n#else\n#define DUK_HOBJECT_IS_BUFOBJ(h)               0\n#endif\n#define DUK_HOBJECT_IS_THREAD(h)               (DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_THREAD)\n#if defined(DUK_USE_ES6_PROXY)\n#define DUK_HOBJECT_IS_PROXY(h)                DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ((h))\n#else\n#define DUK_HOBJECT_IS_PROXY(h)                0\n#endif\n\n#define DUK_HOBJECT_IS_NONBOUND_FUNCTION(h)    DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, \\\n                                                        DUK_HOBJECT_FLAG_COMPFUNC | \\\n                                                        DUK_HOBJECT_FLAG_NATFUNC)\n\n#define DUK_HOBJECT_IS_FUNCTION(h)             DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, \\\n                                                        DUK_HOBJECT_FLAG_BOUNDFUNC | \\\n                                                        DUK_HOBJECT_FLAG_COMPFUNC | \\\n                                                        DUK_HOBJECT_FLAG_NATFUNC)\n\n#define DUK_HOBJECT_IS_CALLABLE(h)             DUK_HOBJECT_HAS_CALLABLE((h))\n\n/* Object has any exotic behavior(s). */\n#define DUK_HOBJECT_EXOTIC_BEHAVIOR_FLAGS      (DUK_HOBJECT_FLAG_EXOTIC_ARRAY | \\\n                                                DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS | \\\n                                                DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ | \\\n                                                DUK_HOBJECT_FLAG_BUFOBJ | \\\n                                                DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ)\n#define DUK_HOBJECT_HAS_EXOTIC_BEHAVIOR(h)     DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_EXOTIC_BEHAVIOR_FLAGS)\n\n/* Object has any virtual properties (not counting Proxy behavior). */\n#define DUK_HOBJECT_VIRTUAL_PROPERTY_FLAGS     (DUK_HOBJECT_FLAG_EXOTIC_ARRAY | \\\n                                                DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ | \\\n                                                DUK_HOBJECT_FLAG_BUFOBJ)\n#define DUK_HOBJECT_HAS_VIRTUAL_PROPERTIES(h)  DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_VIRTUAL_PROPERTY_FLAGS)\n\n#define DUK_HOBJECT_HAS_EXTENSIBLE(h)          DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXTENSIBLE)\n#define DUK_HOBJECT_HAS_CONSTRUCTABLE(h)       DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CONSTRUCTABLE)\n#define DUK_HOBJECT_HAS_CALLABLE(h)            DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CALLABLE)\n#define DUK_HOBJECT_HAS_BOUNDFUNC(h)           DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BOUNDFUNC)\n#define DUK_HOBJECT_HAS_COMPFUNC(h)            DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_COMPFUNC)\n#define DUK_HOBJECT_HAS_NATFUNC(h)             DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NATFUNC)\n#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)\n#define DUK_HOBJECT_HAS_BUFOBJ(h)              DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BUFOBJ)\n#else\n#define DUK_HOBJECT_HAS_BUFOBJ(h)              0\n#endif\n#define DUK_HOBJECT_HAS_FASTREFS(h)            DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_FASTREFS)\n#define DUK_HOBJECT_HAS_ARRAY_PART(h)          DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_ARRAY_PART)\n#define DUK_HOBJECT_HAS_STRICT(h)              DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_STRICT)\n#define DUK_HOBJECT_HAS_NOTAIL(h)              DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NOTAIL)\n#define DUK_HOBJECT_HAS_NEWENV(h)              DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NEWENV)\n#define DUK_HOBJECT_HAS_NAMEBINDING(h)         DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NAMEBINDING)\n#define DUK_HOBJECT_HAS_CREATEARGS(h)          DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CREATEARGS)\n#define DUK_HOBJECT_HAS_HAVE_FINALIZER(h)      DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_HAVE_FINALIZER)\n#define DUK_HOBJECT_HAS_EXOTIC_ARRAY(h)        DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARRAY)\n#define DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(h)    DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ)\n#define DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(h)    DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS)\n#if defined(DUK_USE_ES6_PROXY)\n#define DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(h)     DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ)\n#else\n#define DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(h)     0\n#endif\n#define DUK_HOBJECT_HAS_SPECIAL_CALL(h)        DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_SPECIAL_CALL)\n\n#define DUK_HOBJECT_SET_EXTENSIBLE(h)          DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXTENSIBLE)\n#define DUK_HOBJECT_SET_CONSTRUCTABLE(h)       DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CONSTRUCTABLE)\n#define DUK_HOBJECT_SET_CALLABLE(h)            DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CALLABLE)\n#define DUK_HOBJECT_SET_BOUNDFUNC(h)           DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BOUNDFUNC)\n#define DUK_HOBJECT_SET_COMPFUNC(h)            DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_COMPFUNC)\n#define DUK_HOBJECT_SET_NATFUNC(h)             DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NATFUNC)\n#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)\n#define DUK_HOBJECT_SET_BUFOBJ(h)              DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BUFOBJ)\n#endif\n#define DUK_HOBJECT_SET_FASTREFS(h)            DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_FASTREFS)\n#define DUK_HOBJECT_SET_ARRAY_PART(h)          DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_ARRAY_PART)\n#define DUK_HOBJECT_SET_STRICT(h)              DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_STRICT)\n#define DUK_HOBJECT_SET_NOTAIL(h)              DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NOTAIL)\n#define DUK_HOBJECT_SET_NEWENV(h)              DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NEWENV)\n#define DUK_HOBJECT_SET_NAMEBINDING(h)         DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NAMEBINDING)\n#define DUK_HOBJECT_SET_CREATEARGS(h)          DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CREATEARGS)\n#define DUK_HOBJECT_SET_HAVE_FINALIZER(h)      DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_HAVE_FINALIZER)\n#define DUK_HOBJECT_SET_EXOTIC_ARRAY(h)        DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARRAY)\n#define DUK_HOBJECT_SET_EXOTIC_STRINGOBJ(h)    DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ)\n#define DUK_HOBJECT_SET_EXOTIC_ARGUMENTS(h)    DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS)\n#if defined(DUK_USE_ES6_PROXY)\n#define DUK_HOBJECT_SET_EXOTIC_PROXYOBJ(h)     DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ)\n#endif\n#define DUK_HOBJECT_SET_SPECIAL_CALL(h)        DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_SPECIAL_CALL)\n\n#define DUK_HOBJECT_CLEAR_EXTENSIBLE(h)        DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXTENSIBLE)\n#define DUK_HOBJECT_CLEAR_CONSTRUCTABLE(h)     DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CONSTRUCTABLE)\n#define DUK_HOBJECT_CLEAR_CALLABLE(h)          DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CALLABLE)\n#define DUK_HOBJECT_CLEAR_BOUNDFUNC(h)         DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BOUNDFUNC)\n#define DUK_HOBJECT_CLEAR_COMPFUNC(h)          DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_COMPFUNC)\n#define DUK_HOBJECT_CLEAR_NATFUNC(h)           DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NATFUNC)\n#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)\n#define DUK_HOBJECT_CLEAR_BUFOBJ(h)            DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BUFOBJ)\n#endif\n#define DUK_HOBJECT_CLEAR_FASTREFS(h)          DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_FASTREFS)\n#define DUK_HOBJECT_CLEAR_ARRAY_PART(h)        DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_ARRAY_PART)\n#define DUK_HOBJECT_CLEAR_STRICT(h)            DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_STRICT)\n#define DUK_HOBJECT_CLEAR_NOTAIL(h)            DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NOTAIL)\n#define DUK_HOBJECT_CLEAR_NEWENV(h)            DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NEWENV)\n#define DUK_HOBJECT_CLEAR_NAMEBINDING(h)       DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NAMEBINDING)\n#define DUK_HOBJECT_CLEAR_CREATEARGS(h)        DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CREATEARGS)\n#define DUK_HOBJECT_CLEAR_HAVE_FINALIZER(h)    DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_HAVE_FINALIZER)\n#define DUK_HOBJECT_CLEAR_EXOTIC_ARRAY(h)      DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARRAY)\n#define DUK_HOBJECT_CLEAR_EXOTIC_STRINGOBJ(h)  DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ)\n#define DUK_HOBJECT_CLEAR_EXOTIC_ARGUMENTS(h)  DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS)\n#if defined(DUK_USE_ES6_PROXY)\n#define DUK_HOBJECT_CLEAR_EXOTIC_PROXYOBJ(h)   DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ)\n#endif\n#define DUK_HOBJECT_CLEAR_SPECIAL_CALL(h)      DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_SPECIAL_CALL)\n\n/* Object can/cannot use FASTREFS, i.e. has no strong reference fields beyond\n * duk_hobject base header.  This is used just for asserts so doesn't need to\n * be optimized.\n */\n#define DUK_HOBJECT_PROHIBITS_FASTREFS(h) \\\n\t(DUK_HOBJECT_IS_COMPFUNC((h)) || DUK_HOBJECT_IS_DECENV((h)) || DUK_HOBJECT_IS_OBJENV((h)) || \\\n\t DUK_HOBJECT_IS_BUFOBJ((h)) || DUK_HOBJECT_IS_THREAD((h)) || DUK_HOBJECT_IS_PROXY((h)) || \\\n\t DUK_HOBJECT_IS_BOUNDFUNC((h)))\n#define DUK_HOBJECT_ALLOWS_FASTREFS(h) (!DUK_HOBJECT_PROHIBITS_FASTREFS((h)))\n\n/* Flags used for property attributes in duk_propdesc and packed flags.\n * Must fit into 8 bits.\n */\n#define DUK_PROPDESC_FLAG_WRITABLE              (1U << 0)    /* E5 Section 8.6.1 */\n#define DUK_PROPDESC_FLAG_ENUMERABLE            (1U << 1)    /* E5 Section 8.6.1 */\n#define DUK_PROPDESC_FLAG_CONFIGURABLE          (1U << 2)    /* E5 Section 8.6.1 */\n#define DUK_PROPDESC_FLAG_ACCESSOR              (1U << 3)    /* accessor */\n#define DUK_PROPDESC_FLAG_VIRTUAL               (1U << 4)    /* property is virtual: used in duk_propdesc, never stored\n                                                             * (used by e.g. buffer virtual properties)\n                                                             */\n#define DUK_PROPDESC_FLAGS_MASK                 (DUK_PROPDESC_FLAG_WRITABLE | \\\n                                                 DUK_PROPDESC_FLAG_ENUMERABLE | \\\n                                                 DUK_PROPDESC_FLAG_CONFIGURABLE | \\\n                                                 DUK_PROPDESC_FLAG_ACCESSOR)\n\n/* Additional flags which are passed in the same flags argument as property\n * flags but are not stored in object properties.\n */\n#define DUK_PROPDESC_FLAG_NO_OVERWRITE          (1U << 4)    /* internal define property: skip write silently if exists */\n\n/* Convenience defines for property attributes. */\n#define DUK_PROPDESC_FLAGS_NONE                 0\n#define DUK_PROPDESC_FLAGS_W                    (DUK_PROPDESC_FLAG_WRITABLE)\n#define DUK_PROPDESC_FLAGS_E                    (DUK_PROPDESC_FLAG_ENUMERABLE)\n#define DUK_PROPDESC_FLAGS_C                    (DUK_PROPDESC_FLAG_CONFIGURABLE)\n#define DUK_PROPDESC_FLAGS_WE                   (DUK_PROPDESC_FLAG_WRITABLE | DUK_PROPDESC_FLAG_ENUMERABLE)\n#define DUK_PROPDESC_FLAGS_WC                   (DUK_PROPDESC_FLAG_WRITABLE | DUK_PROPDESC_FLAG_CONFIGURABLE)\n#define DUK_PROPDESC_FLAGS_EC                   (DUK_PROPDESC_FLAG_ENUMERABLE | DUK_PROPDESC_FLAG_CONFIGURABLE)\n#define DUK_PROPDESC_FLAGS_WEC                  (DUK_PROPDESC_FLAG_WRITABLE | \\\n                                                 DUK_PROPDESC_FLAG_ENUMERABLE | \\\n                                                 DUK_PROPDESC_FLAG_CONFIGURABLE)\n\n/* Flags for duk_hobject_get_own_propdesc() and variants. */\n#define DUK_GETDESC_FLAG_PUSH_VALUE          (1U << 0)  /* push value to stack */\n#define DUK_GETDESC_FLAG_IGNORE_PROTOLOOP    (1U << 1)  /* don't throw for prototype loop */\n\n/*\n *  Macro for object validity check\n *\n *  Assert for currently guaranteed relations between flags, for instance.\n */\n\n#define DUK_ASSERT_HOBJECT_VALID(h) do { \\\n\t\tDUK_ASSERT((h) != NULL); \\\n\t\tDUK_ASSERT(!DUK_HOBJECT_IS_CALLABLE((h)) || \\\n\t\t           DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_FUNCTION); \\\n\t\tDUK_ASSERT(!DUK_HOBJECT_IS_BUFOBJ((h)) || \\\n\t\t           (DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_ARRAYBUFFER || \\\n\t\t            DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_DATAVIEW || \\\n\t\t            DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_INT8ARRAY || \\\n\t\t            DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_UINT8ARRAY || \\\n\t\t            DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_UINT8CLAMPEDARRAY || \\\n\t\t            DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_INT16ARRAY || \\\n\t\t            DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_UINT16ARRAY || \\\n\t\t            DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_INT32ARRAY || \\\n\t\t            DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_UINT32ARRAY || \\\n\t\t            DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_FLOAT32ARRAY || \\\n\t\t            DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_FLOAT64ARRAY)); \\\n\t\t/* Object is an Array <=> object has exotic array behavior */ \\\n\t\tDUK_ASSERT((DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_ARRAY && DUK_HOBJECT_HAS_EXOTIC_ARRAY((h))) || \\\n\t\t           (DUK_HOBJECT_GET_CLASS_NUMBER((h)) != DUK_HOBJECT_CLASS_ARRAY && !DUK_HOBJECT_HAS_EXOTIC_ARRAY((h)))); \\\n\t} while (0)\n\n/*\n *  Macros to access the 'props' allocation.\n */\n\n#if defined(DUK_USE_HEAPPTR16)\n#define DUK_HOBJECT_GET_PROPS(heap,h) \\\n\t((duk_uint8_t *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, ((duk_heaphdr *) (h))->h_extra16))\n#define DUK_HOBJECT_SET_PROPS(heap,h,x) do { \\\n\t\t((duk_heaphdr *) (h))->h_extra16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (x)); \\\n\t} while (0)\n#else\n#define DUK_HOBJECT_GET_PROPS(heap,h) \\\n\t((h)->props)\n#define DUK_HOBJECT_SET_PROPS(heap,h,x) do { \\\n\t\t(h)->props = (duk_uint8_t *) (x); \\\n\t} while (0)\n#endif\n\n#if defined(DUK_USE_HOBJECT_LAYOUT_1)\n/* LAYOUT 1 */\n#define DUK_HOBJECT_E_GET_KEY_BASE(heap,h) \\\n\t((duk_hstring **) (void *) ( \\\n\t\tDUK_HOBJECT_GET_PROPS((heap), (h)) \\\n\t))\n#define DUK_HOBJECT_E_GET_VALUE_BASE(heap,h) \\\n\t((duk_propvalue *) (void *) ( \\\n\t\tDUK_HOBJECT_GET_PROPS((heap), (h)) + \\\n\t\t\tDUK_HOBJECT_GET_ESIZE((h)) * sizeof(duk_hstring *) \\\n\t))\n#define DUK_HOBJECT_E_GET_FLAGS_BASE(heap,h) \\\n\t((duk_uint8_t *) (void *) ( \\\n\t\tDUK_HOBJECT_GET_PROPS((heap), (h)) + DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue)) \\\n\t))\n#define DUK_HOBJECT_A_GET_BASE(heap,h) \\\n\t((duk_tval *) (void *) ( \\\n\t\tDUK_HOBJECT_GET_PROPS((heap), (h)) + \\\n\t\t\tDUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) \\\n\t))\n#define DUK_HOBJECT_H_GET_BASE(heap,h) \\\n\t((duk_uint32_t *) (void *) ( \\\n\t\tDUK_HOBJECT_GET_PROPS((heap), (h)) + \\\n\t\t\tDUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) + \\\n\t\t\tDUK_HOBJECT_GET_ASIZE((h)) * sizeof(duk_tval) \\\n\t))\n#define DUK_HOBJECT_P_COMPUTE_SIZE(n_ent,n_arr,n_hash) \\\n\t( \\\n\t\t(n_ent) * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) + \\\n\t\t(n_arr) * sizeof(duk_tval) + \\\n\t\t(n_hash) * sizeof(duk_uint32_t) \\\n\t)\n#define DUK_HOBJECT_P_SET_REALLOC_PTRS(p_base,set_e_k,set_e_pv,set_e_f,set_a,set_h,n_ent,n_arr,n_hash)  do { \\\n\t\t(set_e_k) = (duk_hstring **) (void *) (p_base); \\\n\t\t(set_e_pv) = (duk_propvalue *) (void *) ((set_e_k) + (n_ent)); \\\n\t\t(set_e_f) = (duk_uint8_t *) (void *) ((set_e_pv) + (n_ent)); \\\n\t\t(set_a) = (duk_tval *) (void *) ((set_e_f) + (n_ent)); \\\n\t\t(set_h) = (duk_uint32_t *) (void *) ((set_a) + (n_arr)); \\\n\t} while (0)\n#elif defined(DUK_USE_HOBJECT_LAYOUT_2)\n/* LAYOUT 2 */\n#if (DUK_USE_ALIGN_BY == 4)\n#define DUK_HOBJECT_E_FLAG_PADDING(e_sz) ((4 - (e_sz)) & 0x03)\n#elif (DUK_USE_ALIGN_BY == 8)\n#define DUK_HOBJECT_E_FLAG_PADDING(e_sz) ((8 - (e_sz)) & 0x07)\n#elif (DUK_USE_ALIGN_BY == 1)\n#define DUK_HOBJECT_E_FLAG_PADDING(e_sz) 0\n#else\n#error invalid DUK_USE_ALIGN_BY\n#endif\n#define DUK_HOBJECT_E_GET_KEY_BASE(heap,h) \\\n\t((duk_hstring **) (void *) ( \\\n\t\tDUK_HOBJECT_GET_PROPS((heap), (h)) + \\\n\t\t\tDUK_HOBJECT_GET_ESIZE((h)) * sizeof(duk_propvalue) \\\n\t))\n#define DUK_HOBJECT_E_GET_VALUE_BASE(heap,h) \\\n\t((duk_propvalue *) (void *) ( \\\n\t\tDUK_HOBJECT_GET_PROPS((heap), (h)) \\\n\t))\n#define DUK_HOBJECT_E_GET_FLAGS_BASE(heap,h) \\\n\t((duk_uint8_t *) (void *) ( \\\n\t\tDUK_HOBJECT_GET_PROPS((heap), (h)) + DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue)) \\\n\t))\n#define DUK_HOBJECT_A_GET_BASE(heap,h) \\\n\t((duk_tval *) (void *) ( \\\n\t\tDUK_HOBJECT_GET_PROPS((heap), (h)) + \\\n\t\t\tDUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) + \\\n\t\t\tDUK_HOBJECT_E_FLAG_PADDING(DUK_HOBJECT_GET_ESIZE((h))) \\\n\t))\n#define DUK_HOBJECT_H_GET_BASE(heap,h) \\\n\t((duk_uint32_t *) (void *) ( \\\n\t\tDUK_HOBJECT_GET_PROPS((heap), (h)) + \\\n\t\t\tDUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) + \\\n\t\t\tDUK_HOBJECT_E_FLAG_PADDING(DUK_HOBJECT_GET_ESIZE((h))) + \\\n\t\t\tDUK_HOBJECT_GET_ASIZE((h)) * sizeof(duk_tval) \\\n\t))\n#define DUK_HOBJECT_P_COMPUTE_SIZE(n_ent,n_arr,n_hash) \\\n\t( \\\n\t\t(n_ent) * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) + \\\n\t\tDUK_HOBJECT_E_FLAG_PADDING((n_ent)) + \\\n\t\t(n_arr) * sizeof(duk_tval) + \\\n\t\t(n_hash) * sizeof(duk_uint32_t) \\\n\t)\n#define DUK_HOBJECT_P_SET_REALLOC_PTRS(p_base,set_e_k,set_e_pv,set_e_f,set_a,set_h,n_ent,n_arr,n_hash)  do { \\\n\t\t(set_e_pv) = (duk_propvalue *) (void *) (p_base); \\\n\t\t(set_e_k) = (duk_hstring **) (void *) ((set_e_pv) + (n_ent)); \\\n\t\t(set_e_f) = (duk_uint8_t *) (void *) ((set_e_k) + (n_ent)); \\\n\t\t(set_a) = (duk_tval *) (void *) (((duk_uint8_t *) (set_e_f)) + \\\n\t\t                                 sizeof(duk_uint8_t) * (n_ent) + \\\n\t\t                                 DUK_HOBJECT_E_FLAG_PADDING((n_ent))); \\\n\t\t(set_h) = (duk_uint32_t *) (void *) ((set_a) + (n_arr)); \\\n\t} while (0)\n#elif defined(DUK_USE_HOBJECT_LAYOUT_3)\n/* LAYOUT 3 */\n#define DUK_HOBJECT_E_GET_KEY_BASE(heap,h) \\\n\t((duk_hstring **) (void *) ( \\\n\t\tDUK_HOBJECT_GET_PROPS((heap), (h)) + \\\n\t\t\tDUK_HOBJECT_GET_ESIZE((h)) * sizeof(duk_propvalue) + \\\n\t\t\tDUK_HOBJECT_GET_ASIZE((h)) * sizeof(duk_tval) \\\n\t))\n#define DUK_HOBJECT_E_GET_VALUE_BASE(heap,h) \\\n\t((duk_propvalue *) (void *) ( \\\n\t\tDUK_HOBJECT_GET_PROPS((heap), (h)) \\\n\t))\n#define DUK_HOBJECT_E_GET_FLAGS_BASE(heap,h) \\\n\t((duk_uint8_t *) (void *) ( \\\n\t\tDUK_HOBJECT_GET_PROPS((heap), (h)) + \\\n\t\t\tDUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_propvalue) + sizeof(duk_hstring *)) + \\\n\t\t\tDUK_HOBJECT_GET_ASIZE((h)) * sizeof(duk_tval) + \\\n\t\t\tDUK_HOBJECT_GET_HSIZE((h)) * sizeof(duk_uint32_t) \\\n\t))\n#define DUK_HOBJECT_A_GET_BASE(heap,h) \\\n\t((duk_tval *) (void *) ( \\\n\t\tDUK_HOBJECT_GET_PROPS((heap), (h)) + \\\n\t\t\tDUK_HOBJECT_GET_ESIZE((h)) * sizeof(duk_propvalue) \\\n\t))\n#define DUK_HOBJECT_H_GET_BASE(heap,h) \\\n\t((duk_uint32_t *) (void *) ( \\\n\t\tDUK_HOBJECT_GET_PROPS((heap), (h)) + \\\n\t\t\tDUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_propvalue) + sizeof(duk_hstring *)) + \\\n\t\t\tDUK_HOBJECT_GET_ASIZE((h)) * sizeof(duk_tval) \\\n\t))\n#define DUK_HOBJECT_P_COMPUTE_SIZE(n_ent,n_arr,n_hash) \\\n\t( \\\n\t\t(n_ent) * (sizeof(duk_propvalue) + sizeof(duk_hstring *) + sizeof(duk_uint8_t)) + \\\n\t\t(n_arr) * sizeof(duk_tval) + \\\n\t\t(n_hash) * sizeof(duk_uint32_t) \\\n\t)\n#define DUK_HOBJECT_P_SET_REALLOC_PTRS(p_base,set_e_k,set_e_pv,set_e_f,set_a,set_h,n_ent,n_arr,n_hash)  do { \\\n\t\t(set_e_pv) = (duk_propvalue *) (void *) (p_base); \\\n\t\t(set_a) = (duk_tval *) (void *) ((set_e_pv) + (n_ent)); \\\n\t\t(set_e_k) = (duk_hstring **) (void *) ((set_a) + (n_arr)); \\\n\t\t(set_h) = (duk_uint32_t *) (void *) ((set_e_k) + (n_ent)); \\\n\t\t(set_e_f) = (duk_uint8_t *) (void *) ((set_h) + (n_hash)); \\\n\t} while (0)\n#else\n#error invalid hobject layout defines\n#endif  /* hobject property layout */\n\n#define DUK_HOBJECT_P_ALLOC_SIZE(h) \\\n\tDUK_HOBJECT_P_COMPUTE_SIZE(DUK_HOBJECT_GET_ESIZE((h)), DUK_HOBJECT_GET_ASIZE((h)), DUK_HOBJECT_GET_HSIZE((h)))\n\n#define DUK_HOBJECT_E_GET_KEY(heap,h,i)              (DUK_HOBJECT_E_GET_KEY_BASE((heap), (h))[(i)])\n#define DUK_HOBJECT_E_GET_KEY_PTR(heap,h,i)          (&DUK_HOBJECT_E_GET_KEY_BASE((heap), (h))[(i)])\n#define DUK_HOBJECT_E_GET_VALUE(heap,h,i)            (DUK_HOBJECT_E_GET_VALUE_BASE((heap), (h))[(i)])\n#define DUK_HOBJECT_E_GET_VALUE_PTR(heap,h,i)        (&DUK_HOBJECT_E_GET_VALUE_BASE((heap), (h))[(i)])\n#define DUK_HOBJECT_E_GET_VALUE_TVAL(heap,h,i)       (DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).v)\n#define DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(heap,h,i)   (&DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).v)\n#define DUK_HOBJECT_E_GET_VALUE_GETTER(heap,h,i)     (DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.get)\n#define DUK_HOBJECT_E_GET_VALUE_GETTER_PTR(heap,h,i) (&DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.get)\n#define DUK_HOBJECT_E_GET_VALUE_SETTER(heap,h,i)     (DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.set)\n#define DUK_HOBJECT_E_GET_VALUE_SETTER_PTR(heap,h,i) (&DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.set)\n#define DUK_HOBJECT_E_GET_FLAGS(heap,h,i)            (DUK_HOBJECT_E_GET_FLAGS_BASE((heap), (h))[(i)])\n#define DUK_HOBJECT_E_GET_FLAGS_PTR(heap,h,i)        (&DUK_HOBJECT_E_GET_FLAGS_BASE((heap), (h))[(i)])\n#define DUK_HOBJECT_A_GET_VALUE(heap,h,i)            (DUK_HOBJECT_A_GET_BASE((heap), (h))[(i)])\n#define DUK_HOBJECT_A_GET_VALUE_PTR(heap,h,i)        (&DUK_HOBJECT_A_GET_BASE((heap), (h))[(i)])\n#define DUK_HOBJECT_H_GET_INDEX(heap,h,i)            (DUK_HOBJECT_H_GET_BASE((heap), (h))[(i)])\n#define DUK_HOBJECT_H_GET_INDEX_PTR(heap,h,i)        (&DUK_HOBJECT_H_GET_BASE((heap), (h))[(i)])\n\n#define DUK_HOBJECT_E_SET_KEY(heap,h,i,k)  do { \\\n\t\tDUK_HOBJECT_E_GET_KEY((heap), (h), (i)) = (k); \\\n\t} while (0)\n#define DUK_HOBJECT_E_SET_VALUE(heap,h,i,v)  do { \\\n\t\tDUK_HOBJECT_E_GET_VALUE((heap), (h), (i)) = (v); \\\n\t} while (0)\n#define DUK_HOBJECT_E_SET_VALUE_TVAL(heap,h,i,v)  do { \\\n\t\tDUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).v = (v); \\\n\t} while (0)\n#define DUK_HOBJECT_E_SET_VALUE_GETTER(heap,h,i,v)  do { \\\n\t\tDUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.get = (v); \\\n\t} while (0)\n#define DUK_HOBJECT_E_SET_VALUE_SETTER(heap,h,i,v)  do { \\\n\t\tDUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.set = (v); \\\n\t} while (0)\n#define DUK_HOBJECT_E_SET_FLAGS(heap,h,i,f)  do { \\\n\t\tDUK_HOBJECT_E_GET_FLAGS((heap), (h), (i)) = (duk_uint8_t) (f); \\\n\t} while (0)\n#define DUK_HOBJECT_A_SET_VALUE(heap,h,i,v)  do { \\\n\t\tDUK_HOBJECT_A_GET_VALUE((heap), (h), (i)) = (v); \\\n\t} while (0)\n#define DUK_HOBJECT_A_SET_VALUE_TVAL(heap,h,i,v) \\\n\tDUK_HOBJECT_A_SET_VALUE((heap), (h), (i), (v))  /* alias for above */\n#define DUK_HOBJECT_H_SET_INDEX(heap,h,i,v)  do { \\\n\t\tDUK_HOBJECT_H_GET_INDEX((heap), (h), (i)) = (v); \\\n\t} while (0)\n\n#define DUK_HOBJECT_E_SET_FLAG_BITS(heap,h,i,mask)  do { \\\n\t\tDUK_HOBJECT_E_GET_FLAGS_BASE((heap), (h))[(i)] |= (mask); \\\n\t} while (0)\n\n#define DUK_HOBJECT_E_CLEAR_FLAG_BITS(heap,h,i,mask)  do { \\\n\t\tDUK_HOBJECT_E_GET_FLAGS_BASE((heap), (h))[(i)] &= ~(mask); \\\n\t} while (0)\n\n#define DUK_HOBJECT_E_SLOT_IS_WRITABLE(heap,h,i)     ((DUK_HOBJECT_E_GET_FLAGS((heap), (h), (i)) & DUK_PROPDESC_FLAG_WRITABLE) != 0)\n#define DUK_HOBJECT_E_SLOT_IS_ENUMERABLE(heap,h,i)   ((DUK_HOBJECT_E_GET_FLAGS((heap), (h), (i)) & DUK_PROPDESC_FLAG_ENUMERABLE) != 0)\n#define DUK_HOBJECT_E_SLOT_IS_CONFIGURABLE(heap,h,i) ((DUK_HOBJECT_E_GET_FLAGS((heap), (h), (i)) & DUK_PROPDESC_FLAG_CONFIGURABLE) != 0)\n#define DUK_HOBJECT_E_SLOT_IS_ACCESSOR(heap,h,i)     ((DUK_HOBJECT_E_GET_FLAGS((heap), (h), (i)) & DUK_PROPDESC_FLAG_ACCESSOR) != 0)\n\n#define DUK_HOBJECT_E_SLOT_SET_WRITABLE(heap,h,i)        DUK_HOBJECT_E_SET_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_WRITABLE)\n#define DUK_HOBJECT_E_SLOT_SET_ENUMERABLE(heap,h,i)      DUK_HOBJECT_E_SET_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_ENUMERABLE)\n#define DUK_HOBJECT_E_SLOT_SET_CONFIGURABLE(heap,h,i)    DUK_HOBJECT_E_SET_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_CONFIGURABLE)\n#define DUK_HOBJECT_E_SLOT_SET_ACCESSOR(heap,h,i)        DUK_HOBJECT_E_SET_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_ACCESSOR)\n\n#define DUK_HOBJECT_E_SLOT_CLEAR_WRITABLE(heap,h,i)      DUK_HOBJECT_E_CLEAR_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_WRITABLE)\n#define DUK_HOBJECT_E_SLOT_CLEAR_ENUMERABLE(heap,h,i)    DUK_HOBJECT_E_CLEAR_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_ENUMERABLE)\n#define DUK_HOBJECT_E_SLOT_CLEAR_CONFIGURABLE(heap,h,i)  DUK_HOBJECT_E_CLEAR_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_CONFIGURABLE)\n#define DUK_HOBJECT_E_SLOT_CLEAR_ACCESSOR(heap,h,i)      DUK_HOBJECT_E_CLEAR_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_ACCESSOR)\n\n#define DUK_PROPDESC_IS_WRITABLE(p)             (((p)->flags & DUK_PROPDESC_FLAG_WRITABLE) != 0)\n#define DUK_PROPDESC_IS_ENUMERABLE(p)           (((p)->flags & DUK_PROPDESC_FLAG_ENUMERABLE) != 0)\n#define DUK_PROPDESC_IS_CONFIGURABLE(p)         (((p)->flags & DUK_PROPDESC_FLAG_CONFIGURABLE) != 0)\n#define DUK_PROPDESC_IS_ACCESSOR(p)             (((p)->flags & DUK_PROPDESC_FLAG_ACCESSOR) != 0)\n\n#define DUK_HOBJECT_HASHIDX_UNUSED              0xffffffffUL\n#define DUK_HOBJECT_HASHIDX_DELETED             0xfffffffeUL\n\n/*\n *  Macros for accessing size fields\n */\n\n#if defined(DUK_USE_OBJSIZES16)\n#define DUK_HOBJECT_GET_ESIZE(h) ((h)->e_size16)\n#define DUK_HOBJECT_SET_ESIZE(h,v) do { (h)->e_size16 = (v); } while (0)\n#define DUK_HOBJECT_GET_ENEXT(h) ((h)->e_next16)\n#define DUK_HOBJECT_SET_ENEXT(h,v) do { (h)->e_next16 = (v); } while (0)\n#define DUK_HOBJECT_POSTINC_ENEXT(h) ((h)->e_next16++)\n#define DUK_HOBJECT_GET_ASIZE(h) ((h)->a_size16)\n#define DUK_HOBJECT_SET_ASIZE(h,v) do { (h)->a_size16 = (v); } while (0)\n#if defined(DUK_USE_HOBJECT_HASH_PART)\n#define DUK_HOBJECT_GET_HSIZE(h) ((h)->h_size16)\n#define DUK_HOBJECT_SET_HSIZE(h,v) do { (h)->h_size16 = (v); } while (0)\n#else\n#define DUK_HOBJECT_GET_HSIZE(h) 0\n#define DUK_HOBJECT_SET_HSIZE(h,v) do { DUK_ASSERT((v) == 0); } while (0)\n#endif\n#else\n#define DUK_HOBJECT_GET_ESIZE(h) ((h)->e_size)\n#define DUK_HOBJECT_SET_ESIZE(h,v) do { (h)->e_size = (v); } while (0)\n#define DUK_HOBJECT_GET_ENEXT(h) ((h)->e_next)\n#define DUK_HOBJECT_SET_ENEXT(h,v) do { (h)->e_next = (v); } while (0)\n#define DUK_HOBJECT_POSTINC_ENEXT(h) ((h)->e_next++)\n#define DUK_HOBJECT_GET_ASIZE(h) ((h)->a_size)\n#define DUK_HOBJECT_SET_ASIZE(h,v) do { (h)->a_size = (v); } while (0)\n#if defined(DUK_USE_HOBJECT_HASH_PART)\n#define DUK_HOBJECT_GET_HSIZE(h) ((h)->h_size)\n#define DUK_HOBJECT_SET_HSIZE(h,v) do { (h)->h_size = (v); } while (0)\n#else\n#define DUK_HOBJECT_GET_HSIZE(h) 0\n#define DUK_HOBJECT_SET_HSIZE(h,v) do { DUK_ASSERT((v) == 0); } while (0)\n#endif\n#endif\n\n/*\n *  Misc\n */\n\n/* Maximum prototype traversal depth.  Sanity limit which handles e.g.\n * prototype loops (even complex ones like 1->2->3->4->2->3->4->2->3->4).\n */\n#define DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY      10000L\n\n/*\n *  Ecmascript [[Class]]\n */\n\n/* range check not necessary because all 4-bit values are mapped */\n#define DUK_HOBJECT_CLASS_NUMBER_TO_STRIDX(n)  duk_class_number_to_stridx[(n)]\n\n#define DUK_HOBJECT_GET_CLASS_STRING(heap,h)          \\\n\tDUK_HEAP_GET_STRING( \\\n\t\t(heap), \\\n\t\tDUK_HOBJECT_CLASS_NUMBER_TO_STRIDX(DUK_HOBJECT_GET_CLASS_NUMBER((h))) \\\n\t)\n\n/*\n *  Macros for property handling\n */\n\n#if defined(DUK_USE_HEAPPTR16)\n#define DUK_HOBJECT_GET_PROTOTYPE(heap,h) \\\n\t((duk_hobject *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->prototype16))\n#define DUK_HOBJECT_SET_PROTOTYPE(heap,h,x) do { \\\n\t\t(h)->prototype16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (x)); \\\n\t} while (0)\n#else\n#define DUK_HOBJECT_GET_PROTOTYPE(heap,h) \\\n\t((h)->prototype)\n#define DUK_HOBJECT_SET_PROTOTYPE(heap,h,x) do { \\\n\t\t(h)->prototype = (x); \\\n\t} while (0)\n#endif\n\n/* Set prototype, DECREF earlier value, INCREF new value (tolerating NULLs). */\n#define DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr,h,p)       duk_hobject_set_prototype_updref((thr), (h), (p))\n\n/* Set initial prototype, assume NULL previous prototype, INCREF new value,\n * tolerate NULL.\n */\n#define DUK_HOBJECT_SET_PROTOTYPE_INIT_INCREF(thr,h,proto) do { \\\n\t\tduk_hthread *duk__thr = (thr); \\\n\t\tduk_hobject *duk__obj = (h); \\\n\t\tduk_hobject *duk__proto = (proto); \\\n\t\tDUK_UNREF(duk__thr); \\\n\t\tDUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(duk__thr->heap, duk__obj) == NULL); \\\n\t\tDUK_HOBJECT_SET_PROTOTYPE(duk__thr->heap, duk__obj, duk__proto); \\\n\t\tDUK_HOBJECT_INCREF_ALLOWNULL(duk__thr, duk__proto); \\\n\t} while (0)\n\n/*\n *  Finalizer check\n */\n\n#if defined(DUK_USE_HEAPPTR16)\n#define DUK_HOBJECT_HAS_FINALIZER_FAST(heap,h) duk_hobject_has_finalizer_fast_raw((heap), (h))\n#else\n#define DUK_HOBJECT_HAS_FINALIZER_FAST(heap,h) duk_hobject_has_finalizer_fast_raw((h))\n#endif\n\n/*\n *  Resizing and hash behavior\n */\n\n/* Sanity limit on max number of properties (allocated, not necessarily used).\n * This is somewhat arbitrary, but if we're close to 2**32 properties some\n * algorithms will fail (e.g. hash size selection, next prime selection).\n * Also, we use negative array/entry table indices to indicate 'not found',\n * so anything above 0x80000000 will cause trouble now.\n */\n#if defined(DUK_USE_OBJSIZES16)\n#define DUK_HOBJECT_MAX_PROPERTIES       0x0000ffffUL\n#else\n#define DUK_HOBJECT_MAX_PROPERTIES       0x3fffffffUL   /* 2**30-1 ~= 1G properties */\n#endif\n\n/* internal align target for props allocation, must be 2*n for some n */\n#if (DUK_USE_ALIGN_BY == 4)\n#define DUK_HOBJECT_ALIGN_TARGET         4\n#elif (DUK_USE_ALIGN_BY == 8)\n#define DUK_HOBJECT_ALIGN_TARGET         8\n#elif (DUK_USE_ALIGN_BY == 1)\n#define DUK_HOBJECT_ALIGN_TARGET         1\n#else\n#error invalid DUK_USE_ALIGN_BY\n#endif\n\n/*\n *  PC-to-line constants\n */\n\n#define DUK_PC2LINE_SKIP    64\n\n/* maximum length for a SKIP-1 diffstream: 35 bits per entry, rounded up to bytes */\n#define DUK_PC2LINE_MAX_DIFF_LENGTH    (((DUK_PC2LINE_SKIP - 1) * 35 + 7) / 8)\n\n/*\n *  Struct defs\n */\n\nstruct duk_propaccessor {\n\tduk_hobject *get;\n\tduk_hobject *set;\n};\n\nunion duk_propvalue {\n\t/* The get/set pointers could be 16-bit pointer compressed but it\n\t * would make no difference on 32-bit platforms because duk_tval is\n\t * 8 bytes or more anyway.\n\t */\n\tduk_tval v;\n\tduk_propaccessor a;\n};\n\nstruct duk_propdesc {\n\t/* read-only values 'lifted' for ease of use */\n\tduk_small_uint_t flags;\n\tduk_hobject *get;\n\tduk_hobject *set;\n\n\t/* for updating (all are set to < 0 for virtual properties) */\n\tduk_int_t e_idx;  /* prop index in 'entry part', < 0 if not there */\n\tduk_int_t h_idx;  /* prop index in 'hash part', < 0 if not there */\n\tduk_int_t a_idx;  /* prop index in 'array part', < 0 if not there */\n};\n\nstruct duk_hobject {\n\tduk_heaphdr hdr;\n\n\t/*\n\t *  'props' contains {key,value,flags} entries, optional array entries, and\n\t *  an optional hash lookup table for non-array entries in a single 'sliced'\n\t *  allocation.  There are several layout options, which differ slightly in\n\t *  generated code size/speed and alignment/padding; duk_features.h selects\n\t *  the layout used.\n\t *\n\t *  Layout 1 (DUK_USE_HOBJECT_LAYOUT_1):\n\t *\n\t *    e_size * sizeof(duk_hstring *)         bytes of   entry keys (e_next gc reachable)\n\t *    e_size * sizeof(duk_propvalue)         bytes of   entry values (e_next gc reachable)\n\t *    e_size * sizeof(duk_uint8_t)           bytes of   entry flags (e_next gc reachable)\n\t *    a_size * sizeof(duk_tval)              bytes of   (opt) array values (plain only) (all gc reachable)\n\t *    h_size * sizeof(duk_uint32_t)          bytes of   (opt) hash indexes to entries (e_size),\n\t *                                                      0xffffffffUL = unused, 0xfffffffeUL = deleted\n\t *\n\t *  Layout 2 (DUK_USE_HOBJECT_LAYOUT_2):\n\t *\n\t *    e_size * sizeof(duk_propvalue)         bytes of   entry values (e_next gc reachable)\n\t *    e_size * sizeof(duk_hstring *)         bytes of   entry keys (e_next gc reachable)\n\t *    e_size * sizeof(duk_uint8_t) + pad     bytes of   entry flags (e_next gc reachable)\n\t *    a_size * sizeof(duk_tval)              bytes of   (opt) array values (plain only) (all gc reachable)\n\t *    h_size * sizeof(duk_uint32_t)          bytes of   (opt) hash indexes to entries (e_size),\n\t *                                                      0xffffffffUL = unused, 0xfffffffeUL = deleted\n\t *\n\t *  Layout 3 (DUK_USE_HOBJECT_LAYOUT_3):\n\t *\n\t *    e_size * sizeof(duk_propvalue)         bytes of   entry values (e_next gc reachable)\n\t *    a_size * sizeof(duk_tval)              bytes of   (opt) array values (plain only) (all gc reachable)\n\t *    e_size * sizeof(duk_hstring *)         bytes of   entry keys (e_next gc reachable)\n\t *    h_size * sizeof(duk_uint32_t)          bytes of   (opt) hash indexes to entries (e_size),\n\t *                                                      0xffffffffUL = unused, 0xfffffffeUL = deleted\n\t *    e_size * sizeof(duk_uint8_t)           bytes of   entry flags (e_next gc reachable)\n\t *\n\t *  In layout 1, the 'e_next' count is rounded to 4 or 8 on platforms\n\t *  requiring 4 or 8 byte alignment.  This ensures proper alignment\n\t *  for the entries, at the cost of memory footprint.  However, it's\n\t *  probably preferable to use another layout on such platforms instead.\n\t *\n\t *  In layout 2, the key and value parts are swapped to avoid padding\n\t *  the key array on platforms requiring alignment by 8.  The flags part\n\t *  is padded to get alignment for array entries.  The 'e_next' count does\n\t *  not need to be rounded as in layout 1.\n\t *\n\t *  In layout 3, entry values and array values are always aligned properly,\n\t *  and assuming pointers are at most 8 bytes, so are the entry keys.  Hash\n\t *  indices will be properly aligned (assuming pointers are at least 4 bytes).\n\t *  Finally, flags don't need additional alignment.  This layout provides\n\t *  compact allocations without padding (even on platforms with alignment\n\t *  requirements) at the cost of a bit slower lookups.\n\t *\n\t *  Objects with few keys don't have a hash index; keys are looked up linearly,\n\t *  which is cache efficient because the keys are consecutive.  Larger objects\n\t *  have a hash index part which contains integer indexes to the entries part.\n\t *\n\t *  A single allocation reduces memory allocation overhead but requires more\n\t *  work when any part needs to be resized.  A sliced allocation for entries\n\t *  makes linear key matching faster on most platforms (more locality) and\n\t *  skimps on flags size (which would be followed by 3 bytes of padding in\n\t *  most architectures if entries were placed in a struct).\n\t *\n\t *  'props' also contains internal properties distinguished with a non-BMP\n\t *  prefix.  Often used properties should be placed early in 'props' whenever\n\t *  possible to make accessing them as fast a possible.\n\t */\n\n#if defined(DUK_USE_HEAPPTR16)\n\t/* Located in duk_heaphdr h_extra16.  Subclasses of duk_hobject (like\n\t * duk_hcompfunc) are not free to use h_extra16 for this reason.\n\t */\n#else\n\tduk_uint8_t *props;\n#endif\n\n\t/* prototype: the only internal property lifted outside 'e' as it is so central */\n#if defined(DUK_USE_HEAPPTR16)\n\tduk_uint16_t prototype16;\n#else\n\tduk_hobject *prototype;\n#endif\n\n#if defined(DUK_USE_OBJSIZES16)\n\tduk_uint16_t e_size16;\n\tduk_uint16_t e_next16;\n\tduk_uint16_t a_size16;\n#if defined(DUK_USE_HOBJECT_HASH_PART)\n\tduk_uint16_t h_size16;\n#endif\n#else\n\tduk_uint32_t e_size;  /* entry part size */\n\tduk_uint32_t e_next;  /* index for next new key ([0,e_next[ are gc reachable) */\n\tduk_uint32_t a_size;  /* array part size (entirely gc reachable) */\n#if defined(DUK_USE_HOBJECT_HASH_PART)\n\tduk_uint32_t h_size;  /* hash part size or 0 if unused */\n#endif\n#endif\n};\n\n/*\n *  Exposed data\n */\n\n#if !defined(DUK_SINGLE_FILE)\nDUK_INTERNAL_DECL duk_uint8_t duk_class_number_to_stridx[32];\n#endif  /* !DUK_SINGLE_FILE */\n\n/*\n *  Prototypes\n */\n\n/* alloc and init */\nDUK_INTERNAL_DECL duk_hobject *duk_hobject_alloc_unchecked(duk_heap *heap, duk_uint_t hobject_flags);\nDUK_INTERNAL_DECL duk_hobject *duk_hobject_alloc(duk_hthread *thr, duk_uint_t hobject_flags);\nDUK_INTERNAL_DECL duk_harray *duk_harray_alloc(duk_hthread *thr, duk_uint_t hobject_flags);\nDUK_INTERNAL_DECL duk_hcompfunc *duk_hcompfunc_alloc(duk_hthread *thr, duk_uint_t hobject_flags);\nDUK_INTERNAL_DECL duk_hnatfunc *duk_hnatfunc_alloc(duk_hthread *thr, duk_uint_t hobject_flags);\nDUK_INTERNAL_DECL duk_hboundfunc *duk_hboundfunc_alloc(duk_heap *heap, duk_uint_t hobject_flags);\n#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)\nDUK_INTERNAL_DECL duk_hbufobj *duk_hbufobj_alloc(duk_hthread *thr, duk_uint_t hobject_flags);\n#endif\nDUK_INTERNAL_DECL duk_hthread *duk_hthread_alloc_unchecked(duk_heap *heap, duk_uint_t hobject_flags);\nDUK_INTERNAL_DECL duk_hthread *duk_hthread_alloc(duk_hthread *thr, duk_uint_t hobject_flags);\nDUK_INTERNAL_DECL duk_hdecenv *duk_hdecenv_alloc(duk_hthread *thr, duk_uint_t hobject_flags);\nDUK_INTERNAL_DECL duk_hobjenv *duk_hobjenv_alloc(duk_hthread *thr, duk_uint_t hobject_flags);\nDUK_INTERNAL_DECL duk_hproxy *duk_hproxy_alloc(duk_hthread *thr, duk_uint_t hobject_flags);\n\n/* resize */\nDUK_INTERNAL_DECL void duk_hobject_realloc_props(duk_hthread *thr,\n                                                 duk_hobject *obj,\n                                                 duk_uint32_t new_e_size,\n                                                 duk_uint32_t new_a_size,\n                                                 duk_uint32_t new_h_size,\n                                                 duk_bool_t abandon_array);\nDUK_INTERNAL_DECL void duk_hobject_resize_entrypart(duk_hthread *thr,\n                                                    duk_hobject *obj,\n                                                    duk_uint32_t new_e_size);\n#if 0  /*unused*/\nDUK_INTERNAL_DECL void duk_hobject_resize_arraypart(duk_hthread *thr,\n                                                    duk_hobject *obj,\n                                                    duk_uint32_t new_a_size);\n#endif\n\n/* low-level property functions */\nDUK_INTERNAL_DECL duk_bool_t duk_hobject_find_existing_entry(duk_heap *heap, duk_hobject *obj, duk_hstring *key, duk_int_t *e_idx, duk_int_t *h_idx);\nDUK_INTERNAL_DECL duk_tval *duk_hobject_find_existing_entry_tval_ptr(duk_heap *heap, duk_hobject *obj, duk_hstring *key);\nDUK_INTERNAL_DECL duk_tval *duk_hobject_find_existing_entry_tval_ptr_and_attrs(duk_heap *heap, duk_hobject *obj, duk_hstring *key, duk_uint_t *out_attrs);\nDUK_INTERNAL_DECL duk_tval *duk_hobject_find_existing_array_entry_tval_ptr(duk_heap *heap, duk_hobject *obj, duk_uarridx_t i);\nDUK_INTERNAL_DECL duk_bool_t duk_hobject_get_own_propdesc(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_propdesc *out_desc, duk_small_uint_t flags);\n\n/* XXX: when optimizing for guaranteed property slots, use a guaranteed\n * slot for internal value; this call can then access it directly.\n */\n#define duk_hobject_get_internal_value_tval_ptr(heap,obj) \\\n\tduk_hobject_find_existing_entry_tval_ptr((heap), (obj), DUK_HEAP_STRING_INT_VALUE((heap)))\n\n/* core property functions */\nDUK_INTERNAL_DECL duk_bool_t duk_hobject_getprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key);\nDUK_INTERNAL_DECL duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key, duk_tval *tv_val, duk_bool_t throw_flag);\nDUK_INTERNAL_DECL duk_bool_t duk_hobject_delprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key, duk_bool_t throw_flag);\nDUK_INTERNAL_DECL duk_bool_t duk_hobject_hasprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key);\n\n/* internal property functions */\n#define DUK_DELPROP_FLAG_THROW  (1U << 0)\n#define DUK_DELPROP_FLAG_FORCE  (1U << 1)\nDUK_INTERNAL_DECL duk_bool_t duk_hobject_delprop_raw(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_small_uint_t flags);\nDUK_INTERNAL_DECL duk_bool_t duk_hobject_hasprop_raw(duk_hthread *thr, duk_hobject *obj, duk_hstring *key);\nDUK_INTERNAL_DECL void duk_hobject_define_property_internal(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_small_uint_t flags);\nDUK_INTERNAL_DECL void duk_hobject_define_property_internal_arridx(duk_hthread *thr, duk_hobject *obj, duk_uarridx_t arr_idx, duk_small_uint_t flags);\nDUK_INTERNAL_DECL duk_size_t duk_hobject_get_length(duk_hthread *thr, duk_hobject *obj);\n#if defined(DUK_USE_HEAPPTR16)\nDUK_INTERNAL_DECL duk_bool_t duk_hobject_has_finalizer_fast_raw(duk_heap *heap, duk_hobject *obj);\n#else\nDUK_INTERNAL_DECL duk_bool_t duk_hobject_has_finalizer_fast_raw(duk_hobject *obj);\n#endif\n\n/* helpers for defineProperty() and defineProperties() */\nDUK_INTERNAL_DECL void duk_hobject_prepare_property_descriptor(duk_hthread *thr,\n                                                               duk_idx_t idx_in,\n                                                               duk_uint_t *out_defprop_flags,\n                                                               duk_idx_t *out_idx_value,\n                                                               duk_hobject **out_getter,\n                                                               duk_hobject **out_setter);\nDUK_INTERNAL_DECL duk_bool_t duk_hobject_define_property_helper(duk_hthread *thr,\n                                                                duk_uint_t defprop_flags,\n                                                                duk_hobject *obj,\n                                                                duk_hstring *key,\n                                                                duk_idx_t idx_value,\n                                                                duk_hobject *get,\n                                                                duk_hobject *set,\n                                                                duk_bool_t throw_flag);\n\n/* Object built-in methods */\nDUK_INTERNAL_DECL void duk_hobject_object_get_own_property_descriptor(duk_hthread *thr, duk_idx_t obj_idx);\nDUK_INTERNAL_DECL void duk_hobject_object_seal_freeze_helper(duk_hthread *thr, duk_hobject *obj, duk_bool_t is_freeze);\nDUK_INTERNAL_DECL duk_bool_t duk_hobject_object_is_sealed_frozen_helper(duk_hthread *thr, duk_hobject *obj, duk_bool_t is_frozen);\nDUK_INTERNAL_DECL duk_bool_t duk_hobject_object_ownprop_helper(duk_hthread *thr, duk_small_uint_t required_desc_flags);\n\n/* internal properties */\nDUK_INTERNAL_DECL duk_bool_t duk_hobject_get_internal_value(duk_heap *heap, duk_hobject *obj, duk_tval *tv);\nDUK_INTERNAL_DECL duk_hstring *duk_hobject_get_internal_value_string(duk_heap *heap, duk_hobject *obj);\n\n/* hobject management functions */\nDUK_INTERNAL_DECL void duk_hobject_compact_props(duk_hthread *thr, duk_hobject *obj);\n\n/* ES2015 proxy */\n#if defined(DUK_USE_ES6_PROXY)\nDUK_INTERNAL_DECL duk_bool_t duk_hobject_proxy_check(duk_hobject *obj, duk_hobject **out_target, duk_hobject **out_handler);\nDUK_INTERNAL_DECL duk_hobject *duk_hobject_resolve_proxy_target(duk_hobject *obj);\n#endif\n\n/* enumeration */\nDUK_INTERNAL_DECL void duk_hobject_enumerator_create(duk_hthread *thr, duk_small_uint_t enum_flags);\nDUK_INTERNAL_DECL duk_ret_t duk_hobject_get_enumerated_keys(duk_hthread *thr, duk_small_uint_t enum_flags);\nDUK_INTERNAL_DECL duk_bool_t duk_hobject_enumerator_next(duk_hthread *thr, duk_bool_t get_value);\n\n/* macros */\nDUK_INTERNAL_DECL void duk_hobject_set_prototype_updref(duk_hthread *thr, duk_hobject *h, duk_hobject *p);\n\n/* pc2line */\n#if defined(DUK_USE_PC2LINE)\nDUK_INTERNAL_DECL void duk_hobject_pc2line_pack(duk_hthread *thr, duk_compiler_instr *instrs, duk_uint_fast32_t length);\nDUK_INTERNAL_DECL duk_uint_fast32_t duk_hobject_pc2line_query(duk_hthread *thr, duk_idx_t idx_func, duk_uint_fast32_t pc);\n#endif\n\n/* misc */\nDUK_INTERNAL_DECL duk_bool_t duk_hobject_prototype_chain_contains(duk_hthread *thr, duk_hobject *h, duk_hobject *p, duk_bool_t ignore_loop);\n\n#if !defined(DUK_USE_OBJECT_BUILTIN)\n/* These declarations are needed when related built-in is disabled and\n * genbuiltins.py won't automatically emit the declerations.\n */\nDUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_to_string(duk_hthread *thr);\nDUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype(duk_hthread *thr);\n#endif\n\n#endif  /* DUK_HOBJECT_H_INCLUDED */\n/* #include duk_hcompfunc.h */\n#line 1 \"duk_hcompfunc.h\"\n/*\n *  Heap compiled function (Ecmascript function) representation.\n *\n *  There is a single data buffer containing the Ecmascript function's\n *  bytecode, constants, and inner functions.\n */\n\n#if !defined(DUK_HCOMPFUNC_H_INCLUDED)\n#define DUK_HCOMPFUNC_H_INCLUDED\n\n/*\n *  Field accessor macros\n */\n\n/* XXX: casts could be improved, especially for GET/SET DATA */\n\n#if defined(DUK_USE_HEAPPTR16)\n#define DUK_HCOMPFUNC_GET_DATA(heap,h) \\\n\t((duk_hbuffer_fixed *) (void *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->data16))\n#define DUK_HCOMPFUNC_SET_DATA(heap,h,v) do { \\\n\t\t(h)->data16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \\\n\t} while (0)\n#define DUK_HCOMPFUNC_GET_FUNCS(heap,h)  \\\n\t((duk_hobject **) (void *) (DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->funcs16)))\n#define DUK_HCOMPFUNC_SET_FUNCS(heap,h,v)  do { \\\n\t\t(h)->funcs16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \\\n\t} while (0)\n#define DUK_HCOMPFUNC_GET_BYTECODE(heap,h)  \\\n\t((duk_instr_t *) (void *) (DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->bytecode16)))\n#define DUK_HCOMPFUNC_SET_BYTECODE(heap,h,v)  do { \\\n\t\t(h)->bytecode16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \\\n\t} while (0)\n#define DUK_HCOMPFUNC_GET_LEXENV(heap,h)  \\\n\t((duk_hobject *) (void *) (DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->lex_env16)))\n#define DUK_HCOMPFUNC_SET_LEXENV(heap,h,v)  do { \\\n\t\t(h)->lex_env16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \\\n\t} while (0)\n#define DUK_HCOMPFUNC_GET_VARENV(heap,h)  \\\n\t((duk_hobject *) (void *) (DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->var_env16)))\n#define DUK_HCOMPFUNC_SET_VARENV(heap,h,v)  do { \\\n\t\t(h)->var_env16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \\\n\t} while (0)\n#else\n#define DUK_HCOMPFUNC_GET_DATA(heap,h)  ((duk_hbuffer_fixed *) (void *) (h)->data)\n#define DUK_HCOMPFUNC_SET_DATA(heap,h,v) do { \\\n\t\t(h)->data = (duk_hbuffer *) (v); \\\n\t} while (0)\n#define DUK_HCOMPFUNC_GET_FUNCS(heap,h)  ((h)->funcs)\n#define DUK_HCOMPFUNC_SET_FUNCS(heap,h,v)  do { \\\n\t\t(h)->funcs = (v); \\\n\t} while (0)\n#define DUK_HCOMPFUNC_GET_BYTECODE(heap,h)  ((h)->bytecode)\n#define DUK_HCOMPFUNC_SET_BYTECODE(heap,h,v)  do { \\\n\t\t(h)->bytecode = (v); \\\n\t} while (0)\n#define DUK_HCOMPFUNC_GET_LEXENV(heap,h)  ((h)->lex_env)\n#define DUK_HCOMPFUNC_SET_LEXENV(heap,h,v)  do { \\\n\t\t(h)->lex_env = (v); \\\n\t} while (0)\n#define DUK_HCOMPFUNC_GET_VARENV(heap,h)  ((h)->var_env)\n#define DUK_HCOMPFUNC_SET_VARENV(heap,h,v)  do { \\\n\t\t(h)->var_env = (v); \\\n\t} while (0)\n#endif\n\n/*\n *  Accessor macros for function specific data areas\n */\n\n/* Note: assumes 'data' is always a fixed buffer */\n#define DUK_HCOMPFUNC_GET_BUFFER_BASE(heap,h)  \\\n\tDUK_HBUFFER_FIXED_GET_DATA_PTR((heap), DUK_HCOMPFUNC_GET_DATA((heap), (h)))\n\n#define DUK_HCOMPFUNC_GET_CONSTS_BASE(heap,h)  \\\n\t((duk_tval *) (void *) DUK_HCOMPFUNC_GET_BUFFER_BASE((heap), (h)))\n\n#define DUK_HCOMPFUNC_GET_FUNCS_BASE(heap,h)  \\\n\tDUK_HCOMPFUNC_GET_FUNCS((heap), (h))\n\n#define DUK_HCOMPFUNC_GET_CODE_BASE(heap,h)  \\\n\tDUK_HCOMPFUNC_GET_BYTECODE((heap), (h))\n\n#define DUK_HCOMPFUNC_GET_CONSTS_END(heap,h)  \\\n\t((duk_tval *) (void *) DUK_HCOMPFUNC_GET_FUNCS((heap), (h)))\n\n#define DUK_HCOMPFUNC_GET_FUNCS_END(heap,h)  \\\n\t((duk_hobject **) (void *) DUK_HCOMPFUNC_GET_BYTECODE((heap), (h)))\n\n/* XXX: double evaluation of DUK_HCOMPFUNC_GET_DATA() */\n#define DUK_HCOMPFUNC_GET_CODE_END(heap,h)  \\\n\t((duk_instr_t *) (void *) (DUK_HBUFFER_FIXED_GET_DATA_PTR((heap), DUK_HCOMPFUNC_GET_DATA((heap), (h))) + \\\n\t                DUK_HBUFFER_GET_SIZE((duk_hbuffer *) DUK_HCOMPFUNC_GET_DATA((heap), h))))\n\n#define DUK_HCOMPFUNC_GET_CONSTS_SIZE(heap,h)  \\\n\t( \\\n\t (duk_size_t) \\\n\t ( \\\n\t   ((const duk_uint8_t *) DUK_HCOMPFUNC_GET_CONSTS_END((heap), (h))) - \\\n\t   ((const duk_uint8_t *) DUK_HCOMPFUNC_GET_CONSTS_BASE((heap), (h))) \\\n\t ) \\\n\t)\n\n#define DUK_HCOMPFUNC_GET_FUNCS_SIZE(heap,h)  \\\n\t( \\\n\t (duk_size_t) \\\n\t ( \\\n\t   ((const duk_uint8_t *) DUK_HCOMPFUNC_GET_FUNCS_END((heap), (h))) - \\\n\t   ((const duk_uint8_t *) DUK_HCOMPFUNC_GET_FUNCS_BASE((heap), (h))) \\\n\t ) \\\n\t)\n\n#define DUK_HCOMPFUNC_GET_CODE_SIZE(heap,h)  \\\n\t( \\\n\t (duk_size_t) \\\n\t ( \\\n\t   ((const duk_uint8_t *) DUK_HCOMPFUNC_GET_CODE_END((heap),(h))) - \\\n\t   ((const duk_uint8_t *) DUK_HCOMPFUNC_GET_CODE_BASE((heap),(h))) \\\n\t ) \\\n\t)\n\n#define DUK_HCOMPFUNC_GET_CONSTS_COUNT(heap,h)  \\\n\t((duk_size_t) (DUK_HCOMPFUNC_GET_CONSTS_SIZE((heap), (h)) / sizeof(duk_tval)))\n\n#define DUK_HCOMPFUNC_GET_FUNCS_COUNT(heap,h)  \\\n\t((duk_size_t) (DUK_HCOMPFUNC_GET_FUNCS_SIZE((heap), (h)) / sizeof(duk_hobject *)))\n\n#define DUK_HCOMPFUNC_GET_CODE_COUNT(heap,h)  \\\n\t((duk_size_t) (DUK_HCOMPFUNC_GET_CODE_SIZE((heap), (h)) / sizeof(duk_instr_t)))\n\n/*\n *  Validity assert\n */\n\n#define DUK_ASSERT_HCOMPFUNC_VALID(h) do { \\\n\t\tDUK_ASSERT((h) != NULL); \\\n\t} while (0)\n\n/*\n *  Main struct\n */\n\nstruct duk_hcompfunc {\n\t/* shared object part */\n\tduk_hobject obj;\n\n\t/*\n\t *  Pointers to function data area for faster access.  Function\n\t *  data is a buffer shared between all closures of the same\n\t *  \"template\" function.  The data buffer is always fixed (non-\n\t *  dynamic, hence stable), with a layout as follows:\n\t *\n\t *    constants (duk_tval)\n\t *    inner functions (duk_hobject *)\n\t *    bytecode (duk_instr_t)\n\t *\n\t *  Note: bytecode end address can be computed from 'data' buffer\n\t *  size.  It is not strictly necessary functionally, assuming\n\t *  bytecode never jumps outside its allocated area.  However,\n\t *  it's a safety/robustness feature for avoiding the chance of\n\t *  executing random data as bytecode due to a compiler error.\n\t *\n\t *  Note: values in the data buffer must be incref'd (they will\n\t *  be decref'd on release) for every compiledfunction referring\n\t *  to the 'data' element.\n\t */\n\n\t/* Data area, fixed allocation, stable data ptrs. */\n#if defined(DUK_USE_HEAPPTR16)\n\tduk_uint16_t data16;\n#else\n\tduk_hbuffer *data;\n#endif\n\n\t/* No need for constants pointer (= same as data).\n\t *\n\t * When using 16-bit packing alignment to 4 is nice.  'funcs' will be\n\t * 4-byte aligned because 'constants' are duk_tvals.  For now the\n\t * inner function pointers are not compressed, so that 'bytecode' will\n\t * also be 4-byte aligned.\n\t */\n#if defined(DUK_USE_HEAPPTR16)\n\tduk_uint16_t funcs16;\n\tduk_uint16_t bytecode16;\n#else\n\tduk_hobject **funcs;\n\tduk_instr_t *bytecode;\n#endif\n\n\t/* Lexenv: lexical environment of closure, NULL for templates.\n\t * Varenv: variable environment of closure, NULL for templates.\n\t */\n#if defined(DUK_USE_HEAPPTR16)\n\tduk_uint16_t lex_env16;\n\tduk_uint16_t var_env16;\n#else\n\tduk_hobject *lex_env;\n\tduk_hobject *var_env;\n#endif\n\n\t/*\n\t *  'nregs' registers are allocated on function entry, at most 'nargs'\n\t *  are initialized to arguments, and the rest to undefined.  Arguments\n\t *  above 'nregs' are not mapped to registers.  All registers in the\n\t *  active stack range must be initialized because they are GC reachable.\n\t *  'nargs' is needed so that if the function is given more than 'nargs'\n\t *  arguments, the additional arguments do not 'clobber' registers\n\t *  beyond 'nregs' which must be consistently initialized to undefined.\n\t *\n\t *  Usually there is no need to know which registers are mapped to\n\t *  local variables.  Registers may be allocated to variable in any\n\t *  way (even including gaps).  However, a register-variable mapping\n\t *  must be the same for the duration of the function execution and\n\t *  the register cannot be used for anything else.\n\t *\n\t *  When looking up variables by name, the '_Varmap' map is used.\n\t *  When an activation closes, registers mapped to arguments are\n\t *  copied into the environment record based on the same map.  The\n\t *  reverse map (from register to variable) is not currently needed\n\t *  at run time, except for debugging, so it is not maintained.\n\t */\n\n\tduk_uint16_t nregs;                /* regs to allocate */\n\tduk_uint16_t nargs;                /* number of arguments allocated to regs */\n\n\t/*\n\t *  Additional control information is placed into the object itself\n\t *  as internal properties to avoid unnecessary fields for the\n\t *  majority of functions.  The compiler tries to omit internal\n\t *  control fields when possible.\n\t *\n\t *  Function templates:\n\t *\n\t *    {\n\t *      name: \"func\",    // declaration, named function expressions\n\t *      fileName: <debug info for creating nice errors>\n\t *      _Varmap: { \"arg1\": 0, \"arg2\": 1, \"varname\": 2 },\n\t *      _Formals: [ \"arg1\", \"arg2\" ],\n\t *      _Source: \"function func(arg1, arg2) { ... }\",\n\t *      _Pc2line: <debug info for pc-to-line mapping>,\n\t *    }\n\t *\n\t *  Function instances:\n\t *\n\t *    {\n\t *      length: 2,\n\t *      prototype: { constructor: <func> },\n\t *      caller: <thrower>,\n\t *      arguments: <thrower>,\n\t *      name: \"func\",    // declaration, named function expressions\n\t *      fileName: <debug info for creating nice errors>\n\t *      _Varmap: { \"arg1\": 0, \"arg2\": 1, \"varname\": 2 },\n\t *      _Formals: [ \"arg1\", \"arg2\" ],\n\t *      _Source: \"function func(arg1, arg2) { ... }\",\n\t *      _Pc2line: <debug info for pc-to-line mapping>,\n\t *    }\n\t *\n\t *  More detailed description of these properties can be found\n\t *  in the documentation.\n\t */\n\n#if defined(DUK_USE_DEBUGGER_SUPPORT)\n\t/* Line number range for function.  Needed during debugging to\n\t * determine active breakpoints.\n\t */\n\tduk_uint32_t start_line;\n\tduk_uint32_t end_line;\n#endif\n};\n\n#endif  /* DUK_HCOMPFUNC_H_INCLUDED */\n/* #include duk_hnatfunc.h */\n#line 1 \"duk_hnatfunc.h\"\n/*\n *  Heap native function representation.\n */\n\n#if !defined(DUK_HNATFUNC_H_INCLUDED)\n#define DUK_HNATFUNC_H_INCLUDED\n\n#define DUK_HNATFUNC_NARGS_VARARGS  ((duk_int16_t) -1)\n#define DUK_HNATFUNC_NARGS_MAX      ((duk_int16_t) 0x7fff)\n\nstruct duk_hnatfunc {\n\t/* shared object part */\n\tduk_hobject obj;\n\n\tduk_c_function func;\n\tduk_int16_t nargs;\n\tduk_int16_t magic;\n\n\t/* The 'magic' field allows an opaque 16-bit field to be accessed by the\n\t * Duktape/C function.  This allows, for instance, the same native function\n\t * to be used for a set of very similar functions, with the 'magic' field\n\t * providing the necessary non-argument flags / values to guide the behavior\n\t * of the native function.  The value is signed on purpose: it is easier to\n\t * convert a signed value to unsigned (simply AND with 0xffff) than vice\n\t * versa.\n\t *\n\t * Note: cannot place nargs/magic into the heaphdr flags, because\n\t * duk_hobject takes almost all flags already.\n\t */\n};\n\n#endif  /* DUK_HNATFUNC_H_INCLUDED */\n/* #include duk_hboundfunc.h */\n#line 1 \"duk_hboundfunc.h\"\n/*\n *  Bound function representation.\n */\n\n#if !defined(DUK_HBOUNDFUNC_H_INCLUDED)\n#define DUK_HBOUNDFUNC_H_INCLUDED\n\n/* Artificial limit for args length.  Ensures arithmetic won't overflow\n * 32 bits when combining bound functions.\n */\n#define DUK_HBOUNDFUNC_MAX_ARGS 0x20000000UL\n\n#define DUK_ASSERT_HBOUNDFUNC_VALID(h) do { \\\n\t\tDUK_ASSERT((h) != NULL); \\\n\t\tDUK_ASSERT(DUK_HOBJECT_IS_BOUNDFUNC((duk_hobject *) (h))); \\\n\t\tDUK_ASSERT(DUK_TVAL_IS_LIGHTFUNC(&(h)->target) || \\\n\t\t           (DUK_TVAL_IS_OBJECT(&(h)->target) && \\\n\t\t            DUK_HOBJECT_IS_CALLABLE(DUK_TVAL_GET_OBJECT(&(h)->target)))); \\\n\t\tDUK_ASSERT(!DUK_TVAL_IS_UNUSED(&(h)->this_binding)); \\\n\t\tDUK_ASSERT((h)->nargs == 0 || (h)->args != NULL); \\\n\t} while (0)\n\nstruct duk_hboundfunc {\n\t/* Shared object part. */\n\tduk_hobject obj;\n\n\t/* Final target function, stored as duk_tval so that lightfunc can be\n\t * represented too.\n\t */\n\tduk_tval target;\n\n\t/* This binding. */\n\tduk_tval this_binding;\n\n\t/* Arguments to prepend. */\n\tduk_tval *args;  /* Separate allocation. */\n\tduk_idx_t nargs;\n};\n\n#endif  /* DUK_HBOUNDFUNC_H_INCLUDED */\n/* #include duk_hbufobj.h */\n#line 1 \"duk_hbufobj.h\"\n/*\n *  Heap Buffer object representation.  Used for all Buffer variants.\n */\n\n#if !defined(DUK_HBUFOBJ_H_INCLUDED)\n#define DUK_HBUFOBJ_H_INCLUDED\n\n#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)\n\n/* All element accessors are host endian now (driven by TypedArray spec). */\n#define DUK_HBUFOBJ_ELEM_UINT8           0\n#define DUK_HBUFOBJ_ELEM_UINT8CLAMPED    1\n#define DUK_HBUFOBJ_ELEM_INT8            2\n#define DUK_HBUFOBJ_ELEM_UINT16          3\n#define DUK_HBUFOBJ_ELEM_INT16           4\n#define DUK_HBUFOBJ_ELEM_UINT32          5\n#define DUK_HBUFOBJ_ELEM_INT32           6\n#define DUK_HBUFOBJ_ELEM_FLOAT32         7\n#define DUK_HBUFOBJ_ELEM_FLOAT64         8\n#define DUK_HBUFOBJ_ELEM_MAX             8\n\n#define DUK_ASSERT_HBUFOBJ_VALID(h) do { \\\n\t\tDUK_ASSERT((h) != NULL); \\\n\t\tDUK_ASSERT((h)->shift <= 3); \\\n\t\tDUK_ASSERT((h)->elem_type <= DUK_HBUFOBJ_ELEM_MAX); \\\n\t\tDUK_ASSERT(((h)->shift == 0 && (h)->elem_type == DUK_HBUFOBJ_ELEM_UINT8) || \\\n\t\t           ((h)->shift == 0 && (h)->elem_type == DUK_HBUFOBJ_ELEM_UINT8CLAMPED) || \\\n\t\t           ((h)->shift == 0 && (h)->elem_type == DUK_HBUFOBJ_ELEM_INT8) || \\\n\t\t           ((h)->shift == 1 && (h)->elem_type == DUK_HBUFOBJ_ELEM_UINT16) || \\\n\t\t           ((h)->shift == 1 && (h)->elem_type == DUK_HBUFOBJ_ELEM_INT16) || \\\n\t\t           ((h)->shift == 2 && (h)->elem_type == DUK_HBUFOBJ_ELEM_UINT32) || \\\n\t\t           ((h)->shift == 2 && (h)->elem_type == DUK_HBUFOBJ_ELEM_INT32) || \\\n\t\t           ((h)->shift == 2 && (h)->elem_type == DUK_HBUFOBJ_ELEM_FLOAT32) || \\\n\t\t           ((h)->shift == 3 && (h)->elem_type == DUK_HBUFOBJ_ELEM_FLOAT64)); \\\n\t\tDUK_ASSERT((h)->is_typedarray == 0 || (h)->is_typedarray == 1); \\\n\t\tDUK_ASSERT(DUK_HOBJECT_IS_BUFOBJ((duk_hobject *) (h))); \\\n\t\tif ((h)->buf == NULL) { \\\n\t\t\tDUK_ASSERT((h)->offset == 0); \\\n\t\t\tDUK_ASSERT((h)->length == 0); \\\n\t\t} else { \\\n\t\t\t/* No assertions for offset or length; in particular, \\\n\t\t\t * it's OK for length to be longer than underlying \\\n\t\t\t * buffer.  Just ensure they don't wrap when added. \\\n\t\t\t */ \\\n\t\t\tDUK_ASSERT((h)->offset + (h)->length >= (h)->offset); \\\n\t\t} \\\n\t} while (0)\n\n/* Get the current data pointer (caller must ensure buf != NULL) as a\n * duk_uint8_t ptr.\n */\n#define DUK_HBUFOBJ_GET_SLICE_BASE(heap,h) \\\n\t(DUK_ASSERT_EXPR((h) != NULL), DUK_ASSERT_EXPR((h)->buf != NULL), \\\n\t(((duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR((heap), (h)->buf)) + (h)->offset))\n\n/* True if slice is full, i.e. offset is zero and length covers the entire\n * buffer.  This status may change independently of the duk_hbufobj if\n * the underlying buffer is dynamic and changes without the hbufobj\n * being changed.\n */\n#define DUK_HBUFOBJ_FULL_SLICE(h) \\\n\t(DUK_ASSERT_EXPR((h) != NULL), DUK_ASSERT_EXPR((h)->buf != NULL), \\\n\t((h)->offset == 0 && (h)->length == DUK_HBUFFER_GET_SIZE((h)->buf)))\n\n/* Validate that the whole slice [0,length[ is contained in the underlying\n * buffer.  Caller must ensure 'buf' != NULL.\n */\n#define DUK_HBUFOBJ_VALID_SLICE(h) \\\n\t(DUK_ASSERT_EXPR((h) != NULL), DUK_ASSERT_EXPR((h)->buf != NULL), \\\n\t((h)->offset + (h)->length <= DUK_HBUFFER_GET_SIZE((h)->buf)))\n\n/* Validate byte read/write for virtual 'offset', i.e. check that the\n * offset, taking into account h->offset, is within the underlying\n * buffer size.  This is a safety check which is needed to ensure\n * that even a misconfigured duk_hbufobj never causes memory unsafe\n * behavior (e.g. if an underlying dynamic buffer changes after being\n * setup).  Caller must ensure 'buf' != NULL.\n */\n#define DUK_HBUFOBJ_VALID_BYTEOFFSET_INCL(h,off) \\\n\t(DUK_ASSERT_EXPR((h) != NULL), DUK_ASSERT_EXPR((h)->buf != NULL), \\\n\t((h)->offset + (off) < DUK_HBUFFER_GET_SIZE((h)->buf)))\n\n#define DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h,off) \\\n\t(DUK_ASSERT_EXPR((h) != NULL), DUK_ASSERT_EXPR((h)->buf != NULL), \\\n\t((h)->offset + (off) <= DUK_HBUFFER_GET_SIZE((h)->buf)))\n\n/* Clamp an input byte length (already assumed to be within the nominal\n * duk_hbufobj 'length') to the current dynamic buffer limits to yield\n * a byte length limit that's safe for memory accesses.  This value can\n * be invalidated by any side effect because it may trigger a user\n * callback that resizes the underlying buffer.\n */\n#define DUK_HBUFOBJ_CLAMP_BYTELENGTH(h,len) \\\n\t(DUK_ASSERT_EXPR((h) != NULL), \\\n\tduk_hbufobj_clamp_bytelength((h), (len)))\n\n/* Typed arrays have virtual indices, ArrayBuffer and DataView do not. */\n#define DUK_HBUFOBJ_HAS_VIRTUAL_INDICES(h)  ((h)->is_typedarray)\n\nstruct duk_hbufobj {\n\t/* Shared object part. */\n\tduk_hobject obj;\n\n\t/* Underlying buffer (refcounted), may be NULL. */\n\tduk_hbuffer *buf;\n\n\t/* .buffer reference to an ArrayBuffer, may be NULL. */\n\tduk_hobject *buf_prop;\n\n\t/* Slice and accessor information.\n\t *\n\t * Because the underlying buffer may be dynamic, these may be\n\t * invalidated by the buffer being modified so that both offset\n\t * and length should be validated before every access.  Behavior\n\t * when the underlying buffer has changed doesn't need to be clean:\n\t * virtual 'length' doesn't need to be affected, reads can return\n\t * zero/NaN, and writes can be ignored.\n\t *\n\t * Note that a data pointer cannot be precomputed because 'buf' may\n\t * be dynamic and its pointer unstable.\n\t */\n\n\tduk_uint_t offset;       /* byte offset to buf */\n\tduk_uint_t length;       /* byte index limit for element access, exclusive */\n\tduk_uint8_t shift;       /* element size shift:\n\t                          *   0 = u8/i8\n\t                          *   1 = u16/i16\n\t                          *   2 = u32/i32/float\n\t                          *   3 = double\n\t                          */\n\tduk_uint8_t elem_type;   /* element type */\n\tduk_uint8_t is_typedarray;\n};\n\nDUK_INTERNAL_DECL duk_uint_t duk_hbufobj_clamp_bytelength(duk_hbufobj *h_bufobj, duk_uint_t len);\nDUK_INTERNAL_DECL void duk_hbufobj_push_uint8array_from_plain(duk_hthread *thr, duk_hbuffer *h_buf);\nDUK_INTERNAL_DECL void duk_hbufobj_push_validated_read(duk_hthread *thr, duk_hbufobj *h_bufobj, duk_uint8_t *p, duk_small_uint_t elem_size);\nDUK_INTERNAL_DECL void duk_hbufobj_validated_write(duk_hthread *thr, duk_hbufobj *h_bufobj, duk_uint8_t *p, duk_small_uint_t elem_size);\nDUK_INTERNAL_DECL void duk_hbufobj_promote_plain(duk_hthread *thr, duk_idx_t idx);\n\n#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */\n#endif  /* DUK_HBUFOBJ_H_INCLUDED */\n/* #include duk_hthread.h */\n#line 1 \"duk_hthread.h\"\n/*\n *  Heap thread object representation.\n *\n *  duk_hthread is also the 'context' for public API functions via a\n *  different typedef.  Most API calls operate on the topmost frame\n *  of the value stack only.\n */\n\n#if !defined(DUK_HTHREAD_H_INCLUDED)\n#define DUK_HTHREAD_H_INCLUDED\n\n/*\n *  Stack constants\n */\n\n/* Initial valstack size, roughly 0.7kiB. */\n#define DUK_VALSTACK_INITIAL_SIZE       96U\n\n/* Internal extra elements assumed on function entry, always added to\n * user-defined 'extra' for e.g. the duk_check_stack() call.\n */\n#define DUK_VALSTACK_INTERNAL_EXTRA     32U\n\n/* Number of elements guaranteed to be user accessible (in addition to call\n * arguments) on Duktape/C function entry.  This is the major public API\n * commitment.\n */\n#define DUK_VALSTACK_API_ENTRY_MINIMUM  DUK_API_ENTRY_STACK\n\n/*\n *  Activation defines\n */\n\n#define DUK_ACT_FLAG_STRICT             (1U << 0)  /* function executes in strict mode */\n#define DUK_ACT_FLAG_TAILCALLED         (1U << 1)  /* activation has tail called one or more times */\n#define DUK_ACT_FLAG_CONSTRUCT          (1U << 2)  /* function executes as a constructor (called via \"new\") */\n#define DUK_ACT_FLAG_PREVENT_YIELD      (1U << 3)  /* activation prevents yield (native call or \"new\") */\n#define DUK_ACT_FLAG_DIRECT_EVAL        (1U << 4)  /* activation is a direct eval call */\n#define DUK_ACT_FLAG_CONSTRUCT_PROXY    (1U << 5)  /* activation is for Proxy 'construct' call, special return value handling */\n#define DUK_ACT_FLAG_BREAKPOINT_ACTIVE  (1U << 6)  /* activation has active breakpoint(s) */\n\n#define DUK_ACT_GET_FUNC(act)           ((act)->func)\n\n/*\n *  Flags for __FILE__ / __LINE__ registered into tracedata\n */\n\n#define DUK_TB_FLAG_NOBLAME_FILELINE    (1U << 0)  /* don't report __FILE__ / __LINE__ as fileName/lineNumber */\n\n/*\n *  Catcher defines\n */\n\n/* XXX: remove catcher type entirely */\n\n/* flags field: LLLLLLFT, L = label (24 bits), F = flags (4 bits), T = type (4 bits) */\n#define DUK_CAT_TYPE_MASK            0x0000000fUL\n#define DUK_CAT_TYPE_BITS            4\n#define DUK_CAT_LABEL_MASK           0xffffff00UL\n#define DUK_CAT_LABEL_BITS           24\n#define DUK_CAT_LABEL_SHIFT          8\n\n#define DUK_CAT_FLAG_CATCH_ENABLED          (1U << 4)   /* catch part will catch */\n#define DUK_CAT_FLAG_FINALLY_ENABLED        (1U << 5)   /* finally part will catch */\n#define DUK_CAT_FLAG_CATCH_BINDING_ENABLED  (1U << 6)   /* request to create catch binding */\n#define DUK_CAT_FLAG_LEXENV_ACTIVE          (1U << 7)   /* catch or with binding is currently active */\n\n#define DUK_CAT_TYPE_UNKNOWN         0\n#define DUK_CAT_TYPE_TCF             1\n#define DUK_CAT_TYPE_LABEL           2\n\n#define DUK_CAT_GET_TYPE(c)          ((c)->flags & DUK_CAT_TYPE_MASK)\n#define DUK_CAT_GET_LABEL(c)         (((c)->flags & DUK_CAT_LABEL_MASK) >> DUK_CAT_LABEL_SHIFT)\n\n#define DUK_CAT_HAS_CATCH_ENABLED(c)           ((c)->flags & DUK_CAT_FLAG_CATCH_ENABLED)\n#define DUK_CAT_HAS_FINALLY_ENABLED(c)         ((c)->flags & DUK_CAT_FLAG_FINALLY_ENABLED)\n#define DUK_CAT_HAS_CATCH_BINDING_ENABLED(c)   ((c)->flags & DUK_CAT_FLAG_CATCH_BINDING_ENABLED)\n#define DUK_CAT_HAS_LEXENV_ACTIVE(c)           ((c)->flags & DUK_CAT_FLAG_LEXENV_ACTIVE)\n\n#define DUK_CAT_SET_CATCH_ENABLED(c)    do { \\\n\t\t(c)->flags |= DUK_CAT_FLAG_CATCH_ENABLED; \\\n\t} while (0)\n#define DUK_CAT_SET_FINALLY_ENABLED(c)  do { \\\n\t\t(c)->flags |= DUK_CAT_FLAG_FINALLY_ENABLED; \\\n\t} while (0)\n#define DUK_CAT_SET_CATCH_BINDING_ENABLED(c)    do { \\\n\t\t(c)->flags |= DUK_CAT_FLAG_CATCH_BINDING_ENABLED; \\\n\t} while (0)\n#define DUK_CAT_SET_LEXENV_ACTIVE(c)    do { \\\n\t\t(c)->flags |= DUK_CAT_FLAG_LEXENV_ACTIVE; \\\n\t} while (0)\n\n#define DUK_CAT_CLEAR_CATCH_ENABLED(c)    do { \\\n\t\t(c)->flags &= ~DUK_CAT_FLAG_CATCH_ENABLED; \\\n\t} while (0)\n#define DUK_CAT_CLEAR_FINALLY_ENABLED(c)  do { \\\n\t\t(c)->flags &= ~DUK_CAT_FLAG_FINALLY_ENABLED; \\\n\t} while (0)\n#define DUK_CAT_CLEAR_CATCH_BINDING_ENABLED(c)    do { \\\n\t\t(c)->flags &= ~DUK_CAT_FLAG_CATCH_BINDING_ENABLED; \\\n\t} while (0)\n#define DUK_CAT_CLEAR_LEXENV_ACTIVE(c)    do { \\\n\t\t(c)->flags &= ~DUK_CAT_FLAG_LEXENV_ACTIVE; \\\n\t} while (0)\n\n/*\n *  Thread defines\n */\n\n#if defined(DUK_USE_ROM_STRINGS)\n#define DUK_HTHREAD_GET_STRING(thr,idx) \\\n\t((duk_hstring *) DUK_LOSE_CONST(duk_rom_strings_stridx[(idx)]))\n#else  /* DUK_USE_ROM_STRINGS */\n#if defined(DUK_USE_HEAPPTR16)\n#define DUK_HTHREAD_GET_STRING(thr,idx) \\\n\t((duk_hstring *) DUK_USE_HEAPPTR_DEC16((thr)->heap->heap_udata, (thr)->strs16[(idx)]))\n#else\n#define DUK_HTHREAD_GET_STRING(thr,idx) \\\n\t((thr)->strs[(idx)])\n#endif\n#endif  /* DUK_USE_ROM_STRINGS */\n\n/* values for the state field */\n#define DUK_HTHREAD_STATE_INACTIVE     1   /* thread not currently running */\n#define DUK_HTHREAD_STATE_RUNNING      2   /* thread currently running (only one at a time) */\n#define DUK_HTHREAD_STATE_RESUMED      3   /* thread resumed another thread (active but not running) */\n#define DUK_HTHREAD_STATE_YIELDED      4   /* thread has yielded */\n#define DUK_HTHREAD_STATE_TERMINATED   5   /* thread has terminated */\n\n/* Executor interrupt default interval when nothing else requires a\n * smaller value.  The default interval must be small enough to allow\n * for reasonable execution timeout checking but large enough to keep\n * impact on execution performance low.\n */\n#if defined(DUK_USE_INTERRUPT_COUNTER)\n#define DUK_HTHREAD_INTCTR_DEFAULT     (256L * 1024L)\n#endif\n\n/*\n *  Assert context is valid: non-NULL pointer, fields look sane.\n *\n *  This is used by public API call entrypoints to catch invalid 'ctx' pointers\n *  as early as possible; invalid 'ctx' pointers cause very odd and difficult to\n *  diagnose behavior so it's worth checking even when the check is not 100%.\n */\n\n/* Assertions for internals. */\n#define DUK_ASSERT_HTHREAD_VALID(thr) do { \\\n\t\tDUK_ASSERT((thr) != NULL); \\\n\t\tDUK_ASSERT(DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) (thr)) == DUK_HTYPE_OBJECT); \\\n\t\tDUK_ASSERT(DUK_HOBJECT_IS_THREAD((duk_hobject *) (thr))); \\\n\t\tDUK_ASSERT((thr)->unused1 == 0); \\\n\t\tDUK_ASSERT((thr)->unused2 == 0); \\\n\t} while (0)\n\n/* Assertions for public API calls; a bit stronger. */\n#define DUK_ASSERT_CTX_VALID(thr) do { \\\n\t\tDUK_ASSERT((thr) != NULL); \\\n\t\tDUK_ASSERT_HTHREAD_VALID((thr)); \\\n\t\tDUK_ASSERT((thr)->valstack != NULL); \\\n\t\tDUK_ASSERT((thr)->valstack_bottom != NULL); \\\n\t\tDUK_ASSERT((thr)->valstack_top != NULL); \\\n\t\tDUK_ASSERT((thr)->valstack_end != NULL); \\\n\t\tDUK_ASSERT((thr)->valstack_alloc_end != NULL); \\\n\t\tDUK_ASSERT((thr)->valstack_alloc_end >= (thr)->valstack); \\\n\t\tDUK_ASSERT((thr)->valstack_end >= (thr)->valstack); \\\n\t\tDUK_ASSERT((thr)->valstack_top >= (thr)->valstack); \\\n\t\tDUK_ASSERT((thr)->valstack_top >= (thr)->valstack_bottom); \\\n\t\tDUK_ASSERT((thr)->valstack_end >= (thr)->valstack_top); \\\n\t\tDUK_ASSERT((thr)->valstack_alloc_end >= (thr)->valstack_end); \\\n\t} while (0)\n\n/* Assertions for API call entry specifically.  Checks 'ctx' but also may\n * check internal state (e.g. not in a debugger transport callback).\n */\n#define DUK_ASSERT_API_ENTRY(thr) do { \\\n\t\tDUK_ASSERT_CTX_VALID((thr)); \\\n\t\tDUK_ASSERT((thr)->heap != NULL); \\\n\t\tDUK_ASSERT((thr)->heap->dbg_calling_transport == 0); \\\n\t} while (0)\n\n/*\n *  Assertion helpers.\n */\n\n#define DUK_ASSERT_STRIDX_VALID(val) \\\n\tDUK_ASSERT((duk_uint_t) (val) < DUK_HEAP_NUM_STRINGS)\n\n#define DUK_ASSERT_BIDX_VALID(val) \\\n\tDUK_ASSERT((duk_uint_t) (val) < DUK_NUM_BUILTINS)\n\n/*\n *  Misc\n */\n\n/* Fast access to 'this' binding.  Assumes there's a call in progress. */\n#define DUK_HTHREAD_THIS_PTR(thr) \\\n\t(DUK_ASSERT_EXPR((thr) != NULL), \\\n\t DUK_ASSERT_EXPR((thr)->valstack_bottom > (thr)->valstack), \\\n\t (thr)->valstack_bottom - 1)\n\n/*\n *  Struct defines\n */\n\n/* Fields are ordered for alignment/packing. */\nstruct duk_activation {\n\tduk_tval tv_func;       /* borrowed: full duk_tval for function being executed; for lightfuncs */\n\tduk_hobject *func;      /* borrowed: function being executed; for bound function calls, this is the final, real function, NULL for lightfuncs */\n\tduk_activation *parent; /* previous (parent) activation (or NULL if none) */\n\tduk_hobject *var_env;   /* current variable environment (may be NULL if delayed) */\n\tduk_hobject *lex_env;   /* current lexical environment (may be NULL if delayed) */\n\tduk_catcher *cat;       /* current catcher (or NULL) */\n\n#if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)\n\t/* Previous value of 'func' caller, restored when unwound.  Only in use\n\t * when 'func' is non-strict.\n\t */\n\tduk_hobject *prev_caller;\n#endif\n\n\tduk_instr_t *curr_pc;   /* next instruction to execute (points to 'func' bytecode, stable pointer), NULL for native calls */\n\n\t/* bottom_byteoff and retval_byteoff are only used for book-keeping\n\t * of Ecmascript-initiated calls, to allow returning to an Ecmascript\n\t * function properly.\n\t */\n\n\t/* Bottom of valstack for this activation, used to reset\n\t * valstack_bottom on return; offset is absolute.  There's\n\t * no need to track 'top' because native call handling deals\n\t * with that using locals, and for Ecmascript returns 'nregs'\n\t * indicates the necessary top.\n\t */\n\tduk_size_t bottom_byteoff;\n\n\t/* Return value when returning to this activation (points to caller\n\t * reg, not callee reg); offset is absolute (only set if activation is\n\t * not topmost).\n\t *\n\t * Note: bottom_byteoff is always set, while retval_byteoff is only\n\t * applicable for activations below the topmost one.  Currently\n\t * retval_byteoff for the topmost activation is considered garbage\n\t * (and it not initialized on entry or cleared on return; may contain\n\t * previous or garbage values).\n\t */\n\tduk_size_t retval_byteoff;\n\n\t/* Current 'this' binding is the value just below bottom.\n\t * Previously, 'this' binding was handled with an index to the\n\t * (calling) valstack.  This works for everything except tail\n\t * calls, which must not \"accumulate\" valstack temps.\n\t */\n\n\t/* Value stack reserve (valstack_end) byte offset to be restored\n\t * when returning to this activation.  Only used by the bytecode\n\t * executor.\n\t */\n\tduk_size_t reserve_byteoff;\n\n#if defined(DUK_USE_DEBUGGER_SUPPORT)\n\tduk_uint32_t prev_line; /* needed for stepping */\n#endif\n\n\tduk_small_uint_t flags;\n};\n\nstruct duk_catcher {\n\tduk_catcher *parent;            /* previous (parent) catcher (or NULL if none) */\n\tduk_hstring *h_varname;         /* borrowed reference to catch variable name (or NULL if none) */\n\t                                /* (reference is valid as long activation exists) */\n\tduk_instr_t *pc_base;           /* resume execution from pc_base or pc_base+1 (points to 'func' bytecode, stable pointer) */\n\tduk_size_t idx_base;            /* idx_base and idx_base+1 get completion value and type */\n\tduk_uint32_t flags;             /* type and control flags, label number */\n\t/* XXX: could pack 'flags' and 'idx_base' to same value in practice,\n\t * on 32-bit targets this would make duk_catcher 16 bytes.\n\t */\n};\n\nstruct duk_hthread {\n\t/* Shared object part */\n\tduk_hobject obj;\n\n\t/* Pointer to bytecode executor's 'curr_pc' variable.  Used to copy\n\t * the current PC back into the topmost activation when activation\n\t * state is about to change (or \"syncing\" is otherwise needed).  This\n\t * is rather awkward but important for performance, see execution.rst.\n\t */\n\tduk_instr_t **ptr_curr_pc;\n\n\t/* Backpointers. */\n\tduk_heap *heap;\n\n\t/* Current strictness flag: affects API calls. */\n\tduk_uint8_t strict;\n\n\t/* Thread state. */\n\tduk_uint8_t state;\n\tduk_uint8_t unused1;\n\tduk_uint8_t unused2;\n\n\t/* XXX: Valstack and callstack are currently assumed to have non-NULL\n\t * pointers.  Relaxing this would not lead to big benefits (except\n\t * perhaps for terminated threads).\n\t */\n\n\t/* Value stack: these are expressed as pointers for faster stack\n\t * manipulation.  [valstack,valstack_top[ is GC-reachable,\n\t * [valstack_top,valstack_alloc_end[ is not GC-reachable but kept\n\t * initialized as 'undefined'.  [valstack,valstack_end[ is the\n\t * guaranteed/reserved space and the valstack cannot be resized to\n\t * a smaller size.  [valstack_end,valstack_alloc_end[ is currently\n\t * allocated slack that can be used to grow the current guaranteed\n\t * space but may be shrunk away without notice.\n\t *\n\t *\n\t * <----------------------- guaranteed --->\n\t *                                        <---- slack --->\n\t *               <--- frame --->\n\t * .-------------+=============+----------+--------------.\n\t * |xxxxxxxxxxxxx|yyyyyyyyyyyyy|uuuuuuuuuu|uuuuuuuuuuuuuu|\n\t * `-------------+=============+----------+--------------'\n\t *\n\t * ^             ^             ^          ^              ^\n\t * |             |             |          |              |\n\t * valstack      bottom        top        end            alloc_end\n\t *\n\t *     xxx = arbitrary values, below current frame\n\t *     yyy = arbitrary values, inside current frame\n\t *     uuu = outside active value stack, initialized to 'undefined'\n\t */\n\tduk_tval *valstack;                     /* start of valstack allocation */\n\tduk_tval *valstack_end;                 /* end of valstack reservation/guarantee (exclusive) */\n\tduk_tval *valstack_alloc_end;           /* end of valstack allocation */\n\tduk_tval *valstack_bottom;              /* bottom of current frame */\n\tduk_tval *valstack_top;                 /* top of current frame (exclusive) */\n\n\t/* Call stack, represented as a linked list starting from the current\n\t * activation (or NULL if nothing is active).\n\t */\n\tduk_activation *callstack_curr;         /* current activation (or NULL if none) */\n\tduk_size_t callstack_top;               /* number of activation records in callstack (0 if none) */\n\tduk_size_t callstack_preventcount;      /* number of activation records in callstack preventing a yield */\n\n\t/* Yield/resume book-keeping. */\n\tduk_hthread *resumer;                   /* who resumed us (if any) */\n\n\t/* Current compiler state (if any), used for augmenting SyntaxErrors. */\n\tduk_compiler_ctx *compile_ctx;\n\n#if defined(DUK_USE_INTERRUPT_COUNTER)\n\t/* Interrupt counter for triggering a slow path check for execution\n\t * timeout, debugger interaction such as breakpoints, etc.  The value\n\t * is valid for the current running thread, and both the init and\n\t * counter values are copied whenever a thread switch occurs.  It's\n\t * important for the counter to be conveniently accessible for the\n\t * bytecode executor inner loop for performance reasons.\n\t */\n\tduk_int_t interrupt_counter;    /* countdown state */\n\tduk_int_t interrupt_init;       /* start value for current countdown */\n#endif\n\n\t/* Builtin-objects; may or may not be shared with other threads,\n\t * threads existing in different \"compartments\" will have different\n\t * built-ins.  Must be stored on a per-thread basis because there\n\t * is no intermediate structure for a thread group / compartment.\n\t * This takes quite a lot of space, currently 43x4 = 172 bytes on\n\t * 32-bit platforms.\n\t *\n\t * In some cases the builtins array could be ROM based, but it's\n\t * sometimes edited (e.g. for sandboxing) so it's better to keep\n\t * this array in RAM.\n\t */\n\tduk_hobject *builtins[DUK_NUM_BUILTINS];\n\n\t/* Convenience copies from heap/vm for faster access. */\n#if defined(DUK_USE_ROM_STRINGS)\n\t/* No field needed when strings are in ROM. */\n#else\n#if defined(DUK_USE_HEAPPTR16)\n\tduk_uint16_t *strs16;\n#else\n\tduk_hstring **strs;\n#endif\n#endif\n};\n\n/*\n *  Prototypes\n */\n\nDUK_INTERNAL_DECL void duk_hthread_copy_builtin_objects(duk_hthread *thr_from, duk_hthread *thr_to);\nDUK_INTERNAL_DECL void duk_hthread_create_builtin_objects(duk_hthread *thr);\nDUK_INTERNAL_DECL duk_bool_t duk_hthread_init_stacks(duk_heap *heap, duk_hthread *thr);\nDUK_INTERNAL_DECL void duk_hthread_terminate(duk_hthread *thr);\n\nDUK_INTERNAL_DECL duk_activation *duk_hthread_activation_alloc(duk_hthread *thr);\nDUK_INTERNAL_DECL void duk_hthread_activation_free(duk_hthread *thr, duk_activation *act);\nDUK_INTERNAL_DECL void duk_hthread_activation_unwind_norz(duk_hthread *thr);\nDUK_INTERNAL_DECL void duk_hthread_activation_unwind_reuse_norz(duk_hthread *thr);\nDUK_INTERNAL_DECL duk_activation *duk_hthread_get_activation_for_level(duk_hthread *thr, duk_int_t level);\n\nDUK_INTERNAL_DECL duk_catcher *duk_hthread_catcher_alloc(duk_hthread *thr);\nDUK_INTERNAL_DECL void duk_hthread_catcher_free(duk_hthread *thr, duk_catcher *cat);\nDUK_INTERNAL_DECL void duk_hthread_catcher_unwind_norz(duk_hthread *thr, duk_activation *act);\nDUK_INTERNAL_DECL void duk_hthread_catcher_unwind_nolexenv_norz(duk_hthread *thr, duk_activation *act);\n\n#if defined(DUK_USE_FINALIZER_TORTURE)\nDUK_INTERNAL_DECL void duk_hthread_valstack_torture_realloc(duk_hthread *thr);\n#endif\n\nDUK_INTERNAL_DECL void *duk_hthread_get_valstack_ptr(duk_heap *heap, void *ud);  /* indirect allocs */\n\n#if defined(DUK_USE_DEBUGGER_SUPPORT)\nDUK_INTERNAL_DECL duk_uint_fast32_t duk_hthread_get_act_curr_pc(duk_hthread *thr, duk_activation *act);\n#endif\nDUK_INTERNAL_DECL duk_uint_fast32_t duk_hthread_get_act_prev_pc(duk_hthread *thr, duk_activation *act);\nDUK_INTERNAL_DECL void duk_hthread_sync_currpc(duk_hthread *thr);\nDUK_INTERNAL_DECL void duk_hthread_sync_and_null_currpc(duk_hthread *thr);\n\n#endif  /* DUK_HTHREAD_H_INCLUDED */\n/* #include duk_harray.h */\n#line 1 \"duk_harray.h\"\n/*\n *  Array object representation, used for actual Array instances.\n *\n *  All objects with the exotic array behavior (which must coincide with having\n *  internal class array) MUST be duk_harrays.  No other object can be a\n *  duk_harray.  However, duk_harrays may not always have an array part.\n */\n\n#if !defined(DUK_HARRAY_H_INCLUDED)\n#define DUK_HARRAY_H_INCLUDED\n\n#define DUK_ASSERT_HARRAY_VALID(h) do { \\\n\t\tDUK_ASSERT((h) != NULL); \\\n\t\tDUK_ASSERT(DUK_HOBJECT_IS_ARRAY((duk_hobject *) (h))); \\\n\t\tDUK_ASSERT(DUK_HOBJECT_HAS_EXOTIC_ARRAY((duk_hobject *) (h))); \\\n\t} while (0)\n\n#define DUK_HARRAY_LENGTH_WRITABLE(h)         (!(h)->length_nonwritable)\n#define DUK_HARRAY_LENGTH_NONWRITABLE(h)      ((h)->length_nonwritable)\n#define DUK_HARRAY_SET_LENGTH_WRITABLE(h)     do { (h)->length_nonwritable = 0; } while (0)\n#define DUK_HARRAY_SET_LENGTH_NONWRITABLE(h)  do { (h)->length_nonwritable = 1; } while (0)\n\nstruct duk_harray {\n\t/* Shared object part. */\n\tduk_hobject obj;\n\n\t/* Array .length.\n\t *\n\t * At present Array .length may be smaller, equal, or even larger\n\t * than the allocated underlying array part.  Fast path code must\n\t * always take this into account carefully.\n\t */\n\tduk_uint32_t length;\n\n\t/* Array .length property attributes.  The property is always\n\t * non-enumerable and non-configurable.  It's initially writable\n\t * but per Object.defineProperty() rules it can be made non-writable\n\t * even if it is non-configurable.  Thus we need to track the\n\t * writability explicitly.\n\t *\n\t * XXX: this field to be eliminated and moved into duk_hobject\n\t * flags field to save space.\n\t */\n\tduk_bool_t length_nonwritable;\n};\n\n#endif  /* DUK_HARRAY_H_INCLUDED */\n/* #include duk_henv.h */\n#line 1 \"duk_henv.h\"\n/*\n *  Environment object representation.\n */\n\n#if !defined(DUK_HENV_H_INCLUDED)\n#define DUK_HENV_H_INCLUDED\n\n#define DUK_ASSERT_HDECENV_VALID(h) do { \\\n\t\tDUK_ASSERT((h) != NULL); \\\n\t\tDUK_ASSERT(DUK_HOBJECT_IS_DECENV((duk_hobject *) (h))); \\\n\t\tDUK_ASSERT((h)->thread == NULL || (h)->varmap != NULL); \\\n\t} while (0)\n\n#define DUK_ASSERT_HOBJENV_VALID(h) do { \\\n\t\tDUK_ASSERT((h) != NULL); \\\n\t\tDUK_ASSERT(DUK_HOBJECT_IS_OBJENV((duk_hobject *) (h))); \\\n\t\tDUK_ASSERT((h)->target != NULL); \\\n\t\tDUK_ASSERT((h)->has_this == 0 || (h)->has_this == 1); \\\n\t} while (0)\n\nstruct duk_hdecenv {\n\t/* Shared object part. */\n\tduk_hobject obj;\n\n\t/* These control variables provide enough information to access live\n\t * variables for a closure that is still open.  If thread == NULL,\n\t * the record is closed and the identifiers are in the property table.\n\t */\n\tduk_hthread *thread;\n\tduk_hobject *varmap;\n\tduk_size_t regbase_byteoff;\n};\n\nstruct duk_hobjenv {\n\t/* Shared object part. */\n\tduk_hobject obj;\n\n\t/* Target object and 'this' binding for object binding. */\n\tduk_hobject *target;\n\n\t/* The 'target' object is used as a this binding in only some object\n\t * environments.  For example, the global environment does not provide\n\t * a this binding, but a with statement does.\n\t */\n\tduk_bool_t has_this;\n};\n\n#endif  /* DUK_HENV_H_INCLUDED */\n/* #include duk_hbuffer.h */\n#line 1 \"duk_hbuffer.h\"\n/*\n *  Heap buffer representation.\n *\n *  Heap allocated user data buffer which is either:\n *\n *    1. A fixed size buffer (data follows header statically)\n *    2. A dynamic size buffer (data pointer follows header)\n *\n *  The data pointer for a variable size buffer of zero size may be NULL.\n */\n\n#if !defined(DUK_HBUFFER_H_INCLUDED)\n#define DUK_HBUFFER_H_INCLUDED\n\n/*\n *  Flags\n *\n *  Fixed buffer:     0\n *  Dynamic buffer:   DUK_HBUFFER_FLAG_DYNAMIC\n *  External buffer:  DUK_HBUFFER_FLAG_DYNAMIC | DUK_HBUFFER_FLAG_EXTERNAL\n */\n\n#define DUK_HBUFFER_FLAG_DYNAMIC                  DUK_HEAPHDR_USER_FLAG(0)    /* buffer is behind a pointer, dynamic or external */\n#define DUK_HBUFFER_FLAG_EXTERNAL                 DUK_HEAPHDR_USER_FLAG(1)    /* buffer pointer is to an externally allocated buffer */\n\n#define DUK_HBUFFER_HAS_DYNAMIC(x)                DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_DYNAMIC)\n#define DUK_HBUFFER_HAS_EXTERNAL(x)               DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_EXTERNAL)\n\n#define DUK_HBUFFER_SET_DYNAMIC(x)                DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_DYNAMIC)\n#define DUK_HBUFFER_SET_EXTERNAL(x)               DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_EXTERNAL)\n\n#define DUK_HBUFFER_CLEAR_DYNAMIC(x)              DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_DYNAMIC)\n#define DUK_HBUFFER_CLEAR_EXTERNAL(x)             DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_EXTERNAL)\n\n/*\n *  Misc defines\n */\n\n/* Impose a maximum buffer length for now.  Restricted artificially to\n * ensure resize computations or adding a heap header length won't\n * overflow size_t and that a signed duk_int_t can hold a buffer\n * length.  The limit should be synchronized with DUK_HSTRING_MAX_BYTELEN.\n */\n\n#if defined(DUK_USE_BUFLEN16)\n#define DUK_HBUFFER_MAX_BYTELEN                   (0x0000ffffUL)\n#else\n/* Intentionally not 0x7fffffffUL; at least JSON code expects that\n * 2*len + 2 fits in 32 bits.\n */\n#define DUK_HBUFFER_MAX_BYTELEN                   (0x7ffffffeUL)\n#endif\n\n/*\n *  Field access\n */\n\n#if defined(DUK_USE_BUFLEN16)\n/* size stored in duk_heaphdr unused flag bits */\n#define DUK_HBUFFER_GET_SIZE(x)     ((x)->hdr.h_flags >> 16)\n#define DUK_HBUFFER_SET_SIZE(x,v)   do { \\\n\t\tduk_size_t duk__v; \\\n\t\tduk__v = (v); \\\n\t\tDUK_ASSERT(duk__v <= 0xffffUL); \\\n\t\t(x)->hdr.h_flags = ((x)->hdr.h_flags & 0x0000ffffUL) | (((duk_uint32_t) duk__v) << 16); \\\n\t} while (0)\n#define DUK_HBUFFER_ADD_SIZE(x,dv)  do { \\\n\t\t(x)->hdr.h_flags += ((dv) << 16); \\\n\t} while (0)\n#define DUK_HBUFFER_SUB_SIZE(x,dv)  do { \\\n\t\t(x)->hdr.h_flags -= ((dv) << 16); \\\n\t} while (0)\n#else\n#define DUK_HBUFFER_GET_SIZE(x)     (((duk_hbuffer *) (x))->size)\n#define DUK_HBUFFER_SET_SIZE(x,v)   do { \\\n\t\t((duk_hbuffer *) (x))->size = (v); \\\n\t} while (0)\n#define DUK_HBUFFER_ADD_SIZE(x,dv)  do { \\\n\t\t(x)->size += (dv); \\\n\t} while (0)\n#define DUK_HBUFFER_SUB_SIZE(x,dv)  do { \\\n\t\t(x)->size -= (dv); \\\n\t} while (0)\n#endif\n\n#define DUK_HBUFFER_FIXED_GET_SIZE(x)       DUK_HBUFFER_GET_SIZE((duk_hbuffer *) (x))\n#define DUK_HBUFFER_FIXED_SET_SIZE(x,v)     DUK_HBUFFER_SET_SIZE((duk_hbuffer *) (x))\n\n#define DUK_HBUFFER_DYNAMIC_GET_SIZE(x)     DUK_HBUFFER_GET_SIZE((duk_hbuffer *) (x))\n#define DUK_HBUFFER_DYNAMIC_SET_SIZE(x,v)   DUK_HBUFFER_SET_SIZE((duk_hbuffer *) (x), (v))\n#define DUK_HBUFFER_DYNAMIC_ADD_SIZE(x,dv)  DUK_HBUFFER_ADD_SIZE((duk_hbuffer *) (x), (dv))\n#define DUK_HBUFFER_DYNAMIC_SUB_SIZE(x,dv)  DUK_HBUFFER_SUB_SIZE((duk_hbuffer *) (x), (dv))\n\n#define DUK_HBUFFER_EXTERNAL_GET_SIZE(x)    DUK_HBUFFER_GET_SIZE((duk_hbuffer *) (x))\n#define DUK_HBUFFER_EXTERNAL_SET_SIZE(x,v)  DUK_HBUFFER_SET_SIZE((duk_hbuffer *) (x), (v))\n\n#define DUK_HBUFFER_FIXED_GET_DATA_PTR(heap,x)    ((duk_uint8_t *) (((duk_hbuffer_fixed *) (x)) + 1))\n\n#if defined(DUK_USE_HEAPPTR16)\n#define DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(heap,x) \\\n\t((void *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, ((duk_heaphdr *) (x))->h_extra16))\n#define DUK_HBUFFER_DYNAMIC_SET_DATA_PTR(heap,x,v)     do { \\\n\t\t((duk_heaphdr *) (x))->h_extra16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \\\n\t} while (0)\n#define DUK_HBUFFER_DYNAMIC_SET_DATA_PTR_NULL(heap,x)  do { \\\n\t\t((duk_heaphdr *) (x))->h_extra16 = 0;  /* assume 0 <=> NULL */ \\\n\t} while (0)\n#else\n#define DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(heap,x)       ((x)->curr_alloc)\n#define DUK_HBUFFER_DYNAMIC_SET_DATA_PTR(heap,x,v)     do { \\\n\t\t(x)->curr_alloc = (void *) (v); \\\n\t} while (0)\n#define DUK_HBUFFER_DYNAMIC_SET_DATA_PTR_NULL(heap,x)  do { \\\n\t\t(x)->curr_alloc = (void *) NULL; \\\n\t} while (0)\n#endif\n\n/* No pointer compression because pointer is potentially outside of\n * Duktape heap.\n */\n#if defined(DUK_USE_HEAPPTR16)\n#define DUK_HBUFFER_EXTERNAL_GET_DATA_PTR(heap,x) \\\n\t((void *) (x)->curr_alloc)\n#define DUK_HBUFFER_EXTERNAL_SET_DATA_PTR(heap,x,v)     do { \\\n\t\t(x)->curr_alloc = (void *) (v); \\\n\t} while (0)\n#define DUK_HBUFFER_EXTERNAL_SET_DATA_PTR_NULL(heap,x)  do { \\\n\t\t(x)->curr_alloc = (void *) NULL; \\\n\t} while (0)\n#else\n#define DUK_HBUFFER_EXTERNAL_GET_DATA_PTR(heap,x) \\\n\t((void *) (x)->curr_alloc)\n#define DUK_HBUFFER_EXTERNAL_SET_DATA_PTR(heap,x,v)     do { \\\n\t\t(x)->curr_alloc = (void *) (v); \\\n\t} while (0)\n#define DUK_HBUFFER_EXTERNAL_SET_DATA_PTR_NULL(heap,x)  do { \\\n\t\t(x)->curr_alloc = (void *) NULL; \\\n\t} while (0)\n#endif\n\n/* Get a pointer to the current buffer contents (matching current allocation\n * size).  May be NULL for zero size dynamic/external buffer.\n */\n#if defined(DUK_USE_HEAPPTR16)\n#define DUK_HBUFFER_GET_DATA_PTR(heap,x)  ( \\\n\tDUK_HBUFFER_HAS_DYNAMIC((x)) ? \\\n\t\t( \\\n\t\t\tDUK_HBUFFER_HAS_EXTERNAL((x)) ? \\\n\t\t\t\tDUK_HBUFFER_EXTERNAL_GET_DATA_PTR((heap), (duk_hbuffer_external *) (x)) : \\\n\t\t\t\tDUK_HBUFFER_DYNAMIC_GET_DATA_PTR((heap), (duk_hbuffer_dynamic *) (x)) \\\n\t\t) : \\\n\t\tDUK_HBUFFER_FIXED_GET_DATA_PTR((heap), (duk_hbuffer_fixed *) (x)) \\\n\t)\n#else\n/* Without heap pointer compression duk_hbuffer_dynamic and duk_hbuffer_external\n * have the same layout so checking for fixed vs. dynamic (or external) is enough.\n */\n#define DUK_HBUFFER_GET_DATA_PTR(heap,x)  ( \\\n\tDUK_HBUFFER_HAS_DYNAMIC((x)) ? \\\n\t\tDUK_HBUFFER_DYNAMIC_GET_DATA_PTR((heap), (duk_hbuffer_dynamic *) (x)) : \\\n\t\tDUK_HBUFFER_FIXED_GET_DATA_PTR((heap), (duk_hbuffer_fixed *) (x)) \\\n\t)\n#endif\n\n/*\n *  Structs\n */\n\n/* Shared prefix for all buffer types. */\nstruct duk_hbuffer {\n\tduk_heaphdr hdr;\n\n\t/* It's not strictly necessary to track the current size, but\n\t * it is useful for writing robust native code.\n\t */\n\n\t/* Current size. */\n#if defined(DUK_USE_BUFLEN16)\n\t/* Stored in duk_heaphdr unused flags. */\n#else\n\tduk_size_t size;\n#endif\n\n\t/*\n\t *  Data following the header depends on the DUK_HBUFFER_FLAG_DYNAMIC\n\t *  flag.\n\t *\n\t *  If the flag is clear (the buffer is a fixed size one), the buffer\n\t *  data follows the header directly, consisting of 'size' bytes.\n\t *\n\t *  If the flag is set, the actual buffer is allocated separately, and\n\t *  a few control fields follow the header.  Specifically:\n\t *\n\t *    - a \"void *\" pointing to the current allocation\n\t *    - a duk_size_t indicating the full allocated size (always >= 'size')\n\t *\n\t *  If DUK_HBUFFER_FLAG_EXTERNAL is set, the buffer has been allocated\n\t *  by user code, so that Duktape won't be able to resize it and won't\n\t *  free it.  This allows buffers to point to e.g. an externally\n\t *  allocated structure such as a frame buffer.\n\t *\n\t *  Unlike strings, no terminator byte (NUL) is guaranteed after the\n\t *  data.  This would be convenient, but would pad aligned user buffers\n\t *  unnecessarily upwards in size.  For instance, if user code requested\n\t *  a 64-byte dynamic buffer, 65 bytes would actually be allocated which\n\t *  would then potentially round upwards to perhaps 68 or 72 bytes.\n\t */\n};\n\n/* Fixed buffer; data follows struct, with proper alignment guaranteed by\n * struct size.\n */\n#if (DUK_USE_ALIGN_BY == 8) && defined(DUK_USE_PACK_MSVC_PRAGMA)\n#pragma pack(push, 8)\n#endif\nstruct duk_hbuffer_fixed {\n\t/* A union is used here as a portable struct size / alignment trick:\n\t * by adding a 32-bit or a 64-bit (unused) union member, the size of\n\t * the struct is effectively forced to be a multiple of 4 or 8 bytes\n\t * (respectively) without increasing the size of the struct unless\n\t * necessary.\n\t */\n\tunion {\n\t\tstruct {\n\t\t\tduk_heaphdr hdr;\n#if defined(DUK_USE_BUFLEN16)\n\t\t\t/* Stored in duk_heaphdr unused flags. */\n#else\n\t\t\tduk_size_t size;\n#endif\n\t\t} s;\n#if (DUK_USE_ALIGN_BY == 4)\n\t\tduk_uint32_t dummy_for_align4;\n#elif (DUK_USE_ALIGN_BY == 8)\n\t\tduk_double_t dummy_for_align8;\n#elif (DUK_USE_ALIGN_BY == 1)\n\t\t/* no extra padding */\n#else\n#error invalid DUK_USE_ALIGN_BY\n#endif\n\t} u;\n\n\t/*\n\t *  Data follows the struct header.  The struct size is padded by the\n\t *  compiler based on the struct members.  This guarantees that the\n\t *  buffer data will be aligned-by-4 but not necessarily aligned-by-8.\n\t *\n\t *  On platforms where alignment does not matter, the struct padding\n\t *  could be removed (if there is any).  On platforms where alignment\n\t *  by 8 is required, the struct size must be forced to be a multiple\n\t *  of 8 by some means.  Without it, some user code may break, and also\n\t *  Duktape itself breaks (e.g. the compiler stores duk_tvals in a\n\t *  dynamic buffer).\n\t */\n}\n#if (DUK_USE_ALIGN_BY == 8) && defined(DUK_USE_PACK_GCC_ATTR)\n__attribute__ ((aligned (8)))\n#elif (DUK_USE_ALIGN_BY == 8) && defined(DUK_USE_PACK_CLANG_ATTR)\n__attribute__ ((aligned (8)))\n#endif\n;\n#if (DUK_USE_ALIGN_BY == 8) && defined(DUK_USE_PACK_MSVC_PRAGMA)\n#pragma pack(pop)\n#endif\n\n/* Dynamic buffer with 'curr_alloc' pointing to a dynamic area allocated using\n * heap allocation primitives.  Also used for external buffers when low memory\n * options are not used.\n */\nstruct duk_hbuffer_dynamic {\n\tduk_heaphdr hdr;\n\n#if defined(DUK_USE_BUFLEN16)\n\t/* Stored in duk_heaphdr unused flags. */\n#else\n\tduk_size_t size;\n#endif\n\n#if defined(DUK_USE_HEAPPTR16)\n\t/* Stored in duk_heaphdr h_extra16. */\n#else\n\tvoid *curr_alloc;  /* may be NULL if alloc_size == 0 */\n#endif\n\n\t/*\n\t *  Allocation size for 'curr_alloc' is alloc_size.  There is no\n\t *  automatic NUL terminator for buffers (see above for rationale).\n\t *\n\t *  'curr_alloc' is explicitly allocated with heap allocation\n\t *  primitives and will thus always have alignment suitable for\n\t *  e.g. duk_tval and an IEEE double.\n\t */\n};\n\n/* External buffer with 'curr_alloc' managed by user code and pointing to an\n * arbitrary address.  When heap pointer compression is not used, this struct\n * has the same layout as duk_hbuffer_dynamic.\n */\nstruct duk_hbuffer_external {\n\tduk_heaphdr hdr;\n\n#if defined(DUK_USE_BUFLEN16)\n\t/* Stored in duk_heaphdr unused flags. */\n#else\n\tduk_size_t size;\n#endif\n\n\t/* Cannot be compressed as a heap pointer because may point to\n\t * an arbitrary address.\n\t */\n\tvoid *curr_alloc;  /* may be NULL if alloc_size == 0 */\n};\n\n/*\n *  Prototypes\n */\n\nDUK_INTERNAL_DECL duk_hbuffer *duk_hbuffer_alloc(duk_heap *heap, duk_size_t size, duk_small_uint_t flags, void **out_bufdata);\nDUK_INTERNAL_DECL void *duk_hbuffer_get_dynalloc_ptr(duk_heap *heap, void *ud);  /* indirect allocs */\n\n/* dynamic buffer ops */\nDUK_INTERNAL_DECL void duk_hbuffer_resize(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_size_t new_size);\nDUK_INTERNAL_DECL void duk_hbuffer_reset(duk_hthread *thr, duk_hbuffer_dynamic *buf);\n\n#endif  /* DUK_HBUFFER_H_INCLUDED */\n/* #include duk_hproxy.h */\n#line 1 \"duk_hproxy.h\"\n/*\n *  Proxy object representation.\n */\n\n#if !defined(DUK_HPROXY_H_INCLUDED)\n#define DUK_HPROXY_H_INCLUDED\n\n#define DUK_ASSERT_HPROXY_VALID(h) do { \\\n\t\tDUK_ASSERT((h) != NULL); \\\n\t\tDUK_ASSERT((h)->target != NULL); \\\n\t\tDUK_ASSERT((h)->handler != NULL); \\\n\t\tDUK_ASSERT(DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ((duk_hobject *) (h))); \\\n\t} while (0)\n\nstruct duk_hproxy {\n\t/* Shared object part. */\n\tduk_hobject obj;\n\n\t/* Proxy target object. */\n\tduk_hobject *target;\n\n\t/* Proxy handlers (traps). */\n\tduk_hobject *handler;\n};\n\n#endif  /* DUK_HPROXY_H_INCLUDED */\n/* #include duk_heap.h */\n#line 1 \"duk_heap.h\"\n/*\n *  Heap structure.\n *\n *  Heap contains allocated heap objects, interned strings, and built-in\n *  strings for one or more threads.\n */\n\n#if !defined(DUK_HEAP_H_INCLUDED)\n#define DUK_HEAP_H_INCLUDED\n\n/* alloc function typedefs in duktape.h */\n\n/*\n *  Heap flags\n */\n\n#define DUK_HEAP_FLAG_MARKANDSWEEP_RECLIMIT_REACHED            (1U << 0)  /* mark-and-sweep marking reached a recursion limit and must use multi-pass marking */\n#define DUK_HEAP_FLAG_INTERRUPT_RUNNING                        (1U << 1)  /* executor interrupt running (used to avoid nested interrupts) */\n#define DUK_HEAP_FLAG_FINALIZER_NORESCUE                       (1U << 2)  /* heap destruction ongoing, finalizer rescue no longer possible */\n#define DUK_HEAP_FLAG_DEBUGGER_PAUSED                          (1U << 3)  /* debugger is paused: talk with debug client until step/resume */\n\n#define DUK__HEAP_HAS_FLAGS(heap,bits)               ((heap)->flags & (bits))\n#define DUK__HEAP_SET_FLAGS(heap,bits)  do { \\\n\t\t(heap)->flags |= (bits); \\\n\t} while (0)\n#define DUK__HEAP_CLEAR_FLAGS(heap,bits)  do { \\\n\t\t(heap)->flags &= ~(bits); \\\n\t} while (0)\n\n#define DUK_HEAP_HAS_MARKANDSWEEP_RECLIMIT_REACHED(heap)   DUK__HEAP_HAS_FLAGS((heap), DUK_HEAP_FLAG_MARKANDSWEEP_RECLIMIT_REACHED)\n#define DUK_HEAP_HAS_INTERRUPT_RUNNING(heap)               DUK__HEAP_HAS_FLAGS((heap), DUK_HEAP_FLAG_INTERRUPT_RUNNING)\n#define DUK_HEAP_HAS_FINALIZER_NORESCUE(heap)              DUK__HEAP_HAS_FLAGS((heap), DUK_HEAP_FLAG_FINALIZER_NORESCUE)\n#define DUK_HEAP_HAS_DEBUGGER_PAUSED(heap)                 DUK__HEAP_HAS_FLAGS((heap), DUK_HEAP_FLAG_DEBUGGER_PAUSED)\n\n#define DUK_HEAP_SET_MARKANDSWEEP_RECLIMIT_REACHED(heap)   DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_MARKANDSWEEP_RECLIMIT_REACHED)\n#define DUK_HEAP_SET_INTERRUPT_RUNNING(heap)               DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_INTERRUPT_RUNNING)\n#define DUK_HEAP_SET_FINALIZER_NORESCUE(heap)              DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_FINALIZER_NORESCUE)\n#define DUK_HEAP_SET_DEBUGGER_PAUSED(heap)                 DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_DEBUGGER_PAUSED)\n\n#define DUK_HEAP_CLEAR_MARKANDSWEEP_RECLIMIT_REACHED(heap) DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_MARKANDSWEEP_RECLIMIT_REACHED)\n#define DUK_HEAP_CLEAR_INTERRUPT_RUNNING(heap)             DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_INTERRUPT_RUNNING)\n#define DUK_HEAP_CLEAR_FINALIZER_NORESCUE(heap)            DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_FINALIZER_NORESCUE)\n#define DUK_HEAP_CLEAR_DEBUGGER_PAUSED(heap)               DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_DEBUGGER_PAUSED)\n\n/*\n *  Longjmp types, also double as identifying continuation type for a rethrow (in 'finally')\n */\n\n#define DUK_LJ_TYPE_UNKNOWN      0    /* unused */\n#define DUK_LJ_TYPE_THROW        1    /* value1 -> error object */\n#define DUK_LJ_TYPE_YIELD        2    /* value1 -> yield value, iserror -> error / normal */\n#define DUK_LJ_TYPE_RESUME       3    /* value1 -> resume value, value2 -> resumee thread, iserror -> error/normal */\n#define DUK_LJ_TYPE_BREAK        4    /* value1 -> label number, pseudo-type to indicate a break continuation (for ENDFIN) */\n#define DUK_LJ_TYPE_CONTINUE     5    /* value1 -> label number, pseudo-type to indicate a continue continuation (for ENDFIN) */\n#define DUK_LJ_TYPE_RETURN       6    /* value1 -> return value, pseudo-type to indicate a return continuation (for ENDFIN) */\n#define DUK_LJ_TYPE_NORMAL       7    /* no value, pseudo-type to indicate a normal continuation (for ENDFIN) */\n\n/*\n *  Mark-and-sweep flags\n *\n *  These are separate from heap level flags now but could be merged.\n *  The heap structure only contains a 'base mark-and-sweep flags'\n *  field and the GC caller can impose further flags.\n */\n\n/* Emergency mark-and-sweep: try extra hard, even at the cost of\n * performance.\n */\n#define DUK_MS_FLAG_EMERGENCY                (1U << 0)\n\n/* Voluntary mark-and-sweep: triggered periodically. */\n#define DUK_MS_FLAG_VOLUNTARY                (1U << 1)\n\n/* Postpone rescue decisions for reachable objects with FINALIZED set.\n * Used during finalize_list processing to avoid incorrect rescue\n * decisions due to finalize_list being a reachability root.\n */\n#define DUK_MS_FLAG_POSTPONE_RESCUE          (1U << 2)\n\n/* Don't compact objects; needed during object property table resize\n * to prevent a recursive resize.  It would suffice to protect only the\n * current object being resized, but this is not yet implemented.\n */\n#define DUK_MS_FLAG_NO_OBJECT_COMPACTION     (1U << 3)\n\n/*\n *  Thread switching\n *\n *  To switch heap->curr_thread, use the macro below so that interrupt counters\n *  get updated correctly.  The macro allows a NULL target thread because that\n *  happens e.g. in call handling.\n */\n\n#if defined(DUK_USE_INTERRUPT_COUNTER)\n#define DUK_HEAP_SWITCH_THREAD(heap,newthr)  duk_heap_switch_thread((heap), (newthr))\n#else\n#define DUK_HEAP_SWITCH_THREAD(heap,newthr)  do { \\\n\t\t(heap)->curr_thread = (newthr); \\\n\t} while (0)\n#endif\n\n/*\n *  Stats\n */\n\n#if defined(DUK_USE_DEBUG)\n#define DUK_STATS_INC(heap,fieldname) do { \\\n\t\t(heap)->fieldname += 1; \\\n\t} while (0)\n#else\n#define DUK_STATS_INC(heap,fieldname) do {} while (0)\n#endif\n\n/*\n *  Other heap related defines\n */\n\n/* Mark-and-sweep interval is relative to combined count of objects and\n * strings kept in the heap during the latest mark-and-sweep pass.\n * Fixed point .8 multiplier and .0 adder.  Trigger count (interval) is\n * decreased by each (re)allocation attempt (regardless of size), and each\n * refzero processed object.\n *\n * 'SKIP' indicates how many (re)allocations to wait until a retry if\n * GC is skipped because there is no thread do it with yet (happens\n * only during init phases).\n */\n#if defined(DUK_USE_REFERENCE_COUNTING)\n#define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_MULT              12800L  /* 50x heap size */\n#define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_ADD               1024L\n#define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_SKIP              256L\n#else\n#define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_MULT              256L    /* 1x heap size */\n#define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_ADD               1024L\n#define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_SKIP              256L\n#endif\n\n/* GC torture. */\n#if defined(DUK_USE_GC_TORTURE)\n#define DUK_GC_TORTURE(heap) do { duk_heap_mark_and_sweep((heap), 0); } while (0)\n#else\n#define DUK_GC_TORTURE(heap) do { } while (0)\n#endif\n\n/* Stringcache is used for speeding up char-offset-to-byte-offset\n * translations for non-ASCII strings.\n */\n#define DUK_HEAP_STRCACHE_SIZE                            4\n#define DUK_HEAP_STRINGCACHE_NOCACHE_LIMIT                16  /* strings up to the this length are not cached */\n\n/* Some list management macros. */\n#define DUK_HEAP_INSERT_INTO_HEAP_ALLOCATED(heap,hdr)     duk_heap_insert_into_heap_allocated((heap), (hdr))\n#if defined(DUK_USE_REFERENCE_COUNTING)\n#define DUK_HEAP_REMOVE_FROM_HEAP_ALLOCATED(heap,hdr)     duk_heap_remove_from_heap_allocated((heap), (hdr))\n#endif\n#if defined(DUK_USE_FINALIZER_SUPPORT)\n#define DUK_HEAP_INSERT_INTO_FINALIZE_LIST(heap,hdr)      duk_heap_insert_into_finalize_list((heap), (hdr))\n#define DUK_HEAP_REMOVE_FROM_FINALIZE_LIST(heap,hdr)      duk_heap_remove_from_finalize_list((heap), (hdr))\n#endif\n\n/*\n *  Built-in strings\n */\n\n/* heap string indices are autogenerated in duk_strings.h */\n#if defined(DUK_USE_ROM_STRINGS)\n#define DUK_HEAP_GET_STRING(heap,idx) \\\n\t((duk_hstring *) DUK_LOSE_CONST(duk_rom_strings_stridx[(idx)]))\n#else  /* DUK_USE_ROM_STRINGS */\n#if defined(DUK_USE_HEAPPTR16)\n#define DUK_HEAP_GET_STRING(heap,idx) \\\n\t((duk_hstring *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (heap)->strs16[(idx)]))\n#else\n#define DUK_HEAP_GET_STRING(heap,idx) \\\n\t((heap)->strs[(idx)])\n#endif\n#endif  /* DUK_USE_ROM_STRINGS */\n\n/*\n *  Raw memory calls: relative to heap, but no GC interaction\n */\n\n#define DUK_ALLOC_RAW(heap,size) \\\n\t((heap)->alloc_func((heap)->heap_udata, (size)))\n\n#define DUK_REALLOC_RAW(heap,ptr,newsize) \\\n\t((heap)->realloc_func((heap)->heap_udata, (void *) (ptr), (newsize)))\n\n#define DUK_FREE_RAW(heap,ptr) \\\n\t((heap)->free_func((heap)->heap_udata, (void *) (ptr)))\n\n/*\n *  Memory calls: relative to heap, GC interaction, but no error throwing.\n *\n *  XXX: Currently a mark-and-sweep triggered by memory allocation will run\n *  using the heap->heap_thread.  This thread is also used for running\n *  mark-and-sweep finalization; this is not ideal because it breaks the\n *  isolation between multiple global environments.\n *\n *  Notes:\n *\n *    - DUK_FREE() is required to ignore NULL and any other possible return\n *      value of a zero-sized alloc/realloc (same as ANSI C free()).\n *\n *    - There is no DUK_REALLOC_ZEROED because we don't assume to know the\n *      old size.  Caller must zero the reallocated memory.\n *\n *    - DUK_REALLOC_INDIRECT() must be used when a mark-and-sweep triggered\n *      by an allocation failure might invalidate the original 'ptr', thus\n *      causing a realloc retry to use an invalid pointer.  Example: we're\n *      reallocating the value stack and a finalizer resizes the same value\n *      stack during mark-and-sweep.  The indirect variant requests for the\n *      current location of the pointer being reallocated using a callback\n *      right before every realloc attempt; this circuitous approach is used\n *      to avoid strict aliasing issues in a more straightforward indirect\n *      pointer (void **) approach.  Note: the pointer in the storage\n *      location is read but is NOT updated; the caller must do that.\n */\n\n/* callback for indirect reallocs, request for current pointer */\ntypedef void *(*duk_mem_getptr)(duk_heap *heap, void *ud);\n\n#define DUK_ALLOC(heap,size)                            duk_heap_mem_alloc((heap), (size))\n#define DUK_ALLOC_ZEROED(heap,size)                     duk_heap_mem_alloc_zeroed((heap), (size))\n#define DUK_REALLOC(heap,ptr,newsize)                   duk_heap_mem_realloc((heap), (ptr), (newsize))\n#define DUK_REALLOC_INDIRECT(heap,cb,ud,newsize)        duk_heap_mem_realloc_indirect((heap), (cb), (ud), (newsize))\n#define DUK_FREE(heap,ptr)                              duk_heap_mem_free((heap), (ptr))\n\n/*\n *  Checked allocation, relative to a thread\n *\n *  DUK_FREE_CHECKED() doesn't actually throw, but accepts a 'thr' argument\n *  for convenience.\n */\n\n#define DUK_ALLOC_CHECKED(thr,size)                     duk_heap_mem_alloc_checked((thr), (size))\n#define DUK_ALLOC_CHECKED_ZEROED(thr,size)              duk_heap_mem_alloc_checked_zeroed((thr), (size))\n#define DUK_FREE_CHECKED(thr,ptr)                       duk_heap_mem_free((thr)->heap, (ptr))\n\n/*\n *  Memory constants\n */\n\n#define DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_LIMIT           10  /* Retry allocation after mark-and-sweep for this\n                                                              * many times.  A single mark-and-sweep round is\n                                                              * not guaranteed to free all unreferenced memory\n                                                              * because of finalization (in fact, ANY number of\n                                                              * rounds is strictly not enough).\n                                                              */\n\n#define DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_EMERGENCY_LIMIT  3  /* Starting from this round, use emergency mode\n                                                              * for mark-and-sweep.\n                                                              */\n\n/*\n *  Debugger support\n */\n\n/* Maximum number of breakpoints.  Only breakpoints that are set are\n * consulted so increasing this has no performance impact.\n */\n#define DUK_HEAP_MAX_BREAKPOINTS          16\n\n/* Opcode interval for a Date-based status/peek rate limit check.  Only\n * relevant when debugger is attached.  Requesting a timestamp may be a\n * slow operation on some platforms so this shouldn't be too low.  On the\n * other hand a high value makes Duktape react to a pause request slowly.\n */\n#define DUK_HEAP_DBG_RATELIMIT_OPCODES    4000\n\n/* Milliseconds between status notify and transport peeks. */\n#define DUK_HEAP_DBG_RATELIMIT_MILLISECS  200\n\n/* Debugger pause flags. */\n#define DUK_PAUSE_FLAG_ONE_OPCODE        (1U << 0)   /* pause when a single opcode has been executed */\n#define DUK_PAUSE_FLAG_ONE_OPCODE_ACTIVE (1U << 1)   /* one opcode pause actually active; artifact of current implementation */\n#define DUK_PAUSE_FLAG_LINE_CHANGE       (1U << 2)   /* pause when current line number changes */\n#define DUK_PAUSE_FLAG_FUNC_ENTRY        (1U << 3)   /* pause when entering a function */\n#define DUK_PAUSE_FLAG_FUNC_EXIT         (1U << 4)   /* pause when exiting current function */\n#define DUK_PAUSE_FLAG_CAUGHT_ERROR      (1U << 5)   /* pause when about to throw an error that is caught */\n#define DUK_PAUSE_FLAG_UNCAUGHT_ERROR    (1U << 6)   /* pause when about to throw an error that won't be caught */\n\nstruct duk_breakpoint {\n\tduk_hstring *filename;\n\tduk_uint32_t line;\n};\n\n/*\n *  String cache should ideally be at duk_hthread level, but that would\n *  cause string finalization to slow down relative to the number of\n *  threads; string finalization must check the string cache for \"weak\"\n *  references to the string being finalized to avoid dead pointers.\n *\n *  Thus, string caches are now at the heap level now.\n */\n\nstruct duk_strcache {\n\tduk_hstring *h;\n\tduk_uint32_t bidx;\n\tduk_uint32_t cidx;\n};\n\n/*\n *  Longjmp state, contains the information needed to perform a longjmp.\n *  Longjmp related values are written to value1, value2, and iserror.\n */\n\nstruct duk_ljstate {\n\tduk_jmpbuf *jmpbuf_ptr;   /* current setjmp() catchpoint */\n\tduk_small_uint_t type;    /* longjmp type */\n\tduk_bool_t iserror;       /* isError flag for yield */\n\tduk_tval value1;          /* 1st related value (type specific) */\n\tduk_tval value2;          /* 2nd related value (type specific) */\n};\n\n#define DUK_ASSERT_LJSTATE_UNSET(heap) do { \\\n\t\tDUK_ASSERT(heap != NULL); \\\n\t\tDUK_ASSERT(heap->lj.type == DUK_LJ_TYPE_UNKNOWN); \\\n\t\tDUK_ASSERT(heap->lj.iserror == 0); \\\n\t\tDUK_ASSERT(DUK_TVAL_IS_UNDEFINED(&heap->lj.value1)); \\\n\t\tDUK_ASSERT(DUK_TVAL_IS_UNDEFINED(&heap->lj.value2)); \\\n\t} while (0)\n#define DUK_ASSERT_LJSTATE_SET(heap) do { \\\n\t\tDUK_ASSERT(heap != NULL); \\\n\t\tDUK_ASSERT(heap->lj.type != DUK_LJ_TYPE_UNKNOWN); \\\n\t} while (0)\n\n/*\n *  Main heap structure\n */\n\nstruct duk_heap {\n\tduk_small_uint_t flags;\n\n\t/* Allocator functions. */\n\tduk_alloc_function alloc_func;\n\tduk_realloc_function realloc_func;\n\tduk_free_function free_func;\n\n\t/* Heap udata, used for allocator functions but also for other heap\n\t * level callbacks like fatal function, pointer compression, etc.\n\t */\n\tvoid *heap_udata;\n\n\t/* Fatal error handling, called e.g. when a longjmp() is needed but\n\t * lj.jmpbuf_ptr is NULL.  fatal_func must never return; it's not\n\t * declared as \"noreturn\" because doing that for typedefs is a bit\n\t * challenging portability-wise.\n\t */\n\tduk_fatal_function fatal_func;\n\n\t/* Main list of allocated heap objects.  Objects are either here,\n\t * in finalize_list waiting for processing, or in refzero_list\n\t * temporarily while a DECREF refzero cascade finishes.\n\t */\n\tduk_heaphdr *heap_allocated;\n\n\t/* Temporary work list for freeing a cascade of objects when a DECREF\n\t * (or DECREF_NORZ) encounters a zero refcount.  Using a work list\n\t * allows fixed C stack size when refcounts go to zero for a chain of\n\t * objects.  Outside of DECREF this is always a NULL because DECREF is\n\t * processed without side effects (only memory free calls).\n\t */\n#if defined(DUK_USE_REFERENCE_COUNTING)\n\tduk_heaphdr *refzero_list;\n#endif\n\n#if defined(DUK_USE_FINALIZER_SUPPORT)\n\t/* Work list for objects to be finalized. */\n\tduk_heaphdr *finalize_list;\n#if defined(DUK_USE_ASSERTIONS)\n\t/* Object whose finalizer is executing right now (no nesting). */\n\tduk_heaphdr *currently_finalizing;\n#endif\n#endif\n\n\t/* Freelist for duk_activations and duk_catchers. */\n#if defined(DUK_USE_CACHE_ACTIVATION)\n\tduk_activation *activation_free;\n#endif\n#if defined(DUK_USE_CACHE_CATCHER)\n\tduk_catcher *catcher_free;\n#endif\n\n\t/* Voluntary mark-and-sweep trigger counter.  Intentionally signed\n\t * because we continue decreasing the value when voluntary GC cannot\n\t * run.\n\t */\n#if defined(DUK_USE_VOLUNTARY_GC)\n\tduk_int_t ms_trigger_counter;\n#endif\n\n\t/* Mark-and-sweep recursion control: too deep recursion causes\n\t * multi-pass processing to avoid growing C stack without bound.\n\t */\n\tduk_uint_t ms_recursion_depth;\n\n\t/* Mark-and-sweep flags automatically active (used for critical sections). */\n\tduk_small_uint_t ms_base_flags;\n\n\t/* Mark-and-sweep running flag.  Prevents re-entry, and also causes\n\t * refzero events to be ignored (= objects won't be queued to refzero_list).\n\t */\n\tduk_uint_t ms_running;\n\n\t/* Mark-and-sweep prevent count, stacking.  Used to avoid M&S side\n\t * effects (besides finalizers which are controlled separately) such\n\t * as compacting the string table or object property tables.  This\n\t * is also bumped when ms_running is set to prevent recursive re-entry.\n\t * Can also be bumped when mark-and-sweep is not running.\n\t */\n\tduk_uint_t ms_prevent_count;\n\n\t/* Finalizer processing prevent count, stacking.  Bumped when finalizers\n\t * are processed to prevent recursive finalizer processing (first call site\n\t * processing finalizers handles all finalizers until the list is empty).\n\t * Can also be bumped explicitly to prevent finalizer execution.\n\t */\n\tduk_uint_t pf_prevent_count;\n\n\t/* When processing finalize_list, don't actually run finalizers but\n\t * queue finalizable objects back to heap_allocated as is.  This is\n\t * used during heap destruction to deal with finalizers that keep\n\t * on creating more finalizable garbage.\n\t */\n\tduk_uint_t pf_skip_finalizers;\n\n#if defined(DUK_USE_ASSERTIONS)\n\t/* Set when we're in a critical path where an error throw would cause\n\t * e.g. sandboxing/protected call violations or state corruption.  This\n\t * is just used for asserts.\n\t */\n\tduk_bool_t error_not_allowed;\n#endif\n\n#if defined(DUK_USE_ASSERTIONS)\n\t/* Set when heap is still being initialized, helps with writing\n\t * some assertions.\n\t */\n\tduk_bool_t heap_initializing;\n#endif\n\n\t/* Marker for detecting internal \"double faults\", errors thrown when\n\t * we're trying to create an error object, see duk_error_throw.c.\n\t */\n\tduk_bool_t creating_error;\n\n\t/* Marker for indicating we're calling a user error augmentation\n\t * (errCreate/errThrow) function.  Errors created/thrown during\n\t * such a call are not augmented.\n\t */\n#if defined(DUK_USE_AUGMENT_ERROR_THROW) || defined(DUK_USE_AUGMENT_ERROR_CREATE)\n\tduk_bool_t augmenting_error;\n#endif\n\n\t/* Longjmp state. */\n\tduk_ljstate lj;\n\n\t/* Heap thread, used internally and for finalization. */\n\tduk_hthread *heap_thread;\n\n\t/* Current running thread. */\n\tduk_hthread *curr_thread;\n\n\t/* Heap level \"stash\" object (e.g., various reachability roots). */\n\tduk_hobject *heap_object;\n\n\t/* duk_handle_call / duk_handle_safe_call recursion depth limiting */\n\tduk_int_t call_recursion_depth;\n\tduk_int_t call_recursion_limit;\n\n\t/* Mix-in value for computing string hashes; should be reasonably unpredictable. */\n\tduk_uint32_t hash_seed;\n\n\t/* Random number state for duk_util_tinyrandom.c. */\n#if !defined(DUK_USE_GET_RANDOM_DOUBLE)\n#if defined(DUK_USE_PREFER_SIZE) || !defined(DUK_USE_64BIT_OPS)\n\tduk_uint32_t rnd_state;  /* State for Shamir's three-op algorithm */\n#else\n\tduk_uint64_t rnd_state[2];  /* State for xoroshiro128+ */\n#endif\n#endif\n\n\t/* Counter for unique local symbol creation. */\n\t/* XXX: When 64-bit types are available, it would be more efficient to\n\t * use a duk_uint64_t at least for incrementing but maybe also for\n\t * string formatting in the Symbol constructor.\n\t */\n\tduk_uint32_t sym_counter[2];\n\n\t/* For manual debugging: instruction count based on executor and\n\t * interrupt counter book-keeping.  Inspect debug logs to see how\n\t * they match up.\n\t */\n#if defined(DUK_USE_INTERRUPT_COUNTER) && defined(DUK_USE_DEBUG)\n\tduk_int_t inst_count_exec;\n\tduk_int_t inst_count_interrupt;\n#endif\n\n\t/* Debugger state. */\n#if defined(DUK_USE_DEBUGGER_SUPPORT)\n\t/* Callbacks and udata; dbg_read_cb != NULL is used to indicate attached state. */\n\tduk_debug_read_function dbg_read_cb;                /* required, NULL implies detached */\n\tduk_debug_write_function dbg_write_cb;              /* required */\n\tduk_debug_peek_function dbg_peek_cb;\n\tduk_debug_read_flush_function dbg_read_flush_cb;\n\tduk_debug_write_flush_function dbg_write_flush_cb;\n\tduk_debug_request_function dbg_request_cb;\n\tduk_debug_detached_function dbg_detached_cb;\n\tvoid *dbg_udata;\n\n\t/* The following are only relevant when debugger is attached. */\n\tduk_bool_t dbg_processing;              /* currently processing messages or breakpoints: don't enter message processing recursively (e.g. no breakpoints when processing debugger eval) */\n\tduk_bool_t dbg_state_dirty;             /* resend state next time executor is about to run */\n\tduk_bool_t dbg_force_restart;           /* force executor restart to recheck breakpoints; used to handle function returns (see GH-303) */\n\tduk_bool_t dbg_detaching;               /* debugger detaching; used to avoid calling detach handler recursively */\n\tduk_small_uint_t dbg_pause_flags;       /* flags for automatic pause behavior */\n\tduk_activation *dbg_pause_act;          /* activation related to pause behavior (pause on line change, function entry/exit) */\n\tduk_uint32_t dbg_pause_startline;       /* starting line number for line change related pause behavior */\n\tduk_breakpoint dbg_breakpoints[DUK_HEAP_MAX_BREAKPOINTS];  /* breakpoints: [0,breakpoint_count[ gc reachable */\n\tduk_small_uint_t dbg_breakpoint_count;\n\tduk_breakpoint *dbg_breakpoints_active[DUK_HEAP_MAX_BREAKPOINTS + 1];  /* currently active breakpoints: NULL term, borrowed pointers */\n\t/* XXX: make active breakpoints actual copies instead of pointers? */\n\n\t/* These are for rate limiting Status notifications and transport peeking. */\n\tduk_uint_t dbg_exec_counter;            /* cumulative opcode execution count (overflows are OK) */\n\tduk_uint_t dbg_last_counter;            /* value of dbg_exec_counter when we last did a Date-based check */\n\tduk_double_t dbg_last_time;             /* time when status/peek was last done (Date-based rate limit) */\n\n\t/* Used to support single-byte stream lookahead. */\n\tduk_bool_t dbg_have_next_byte;\n\tduk_uint8_t dbg_next_byte;\n#endif  /* DUK_USE_DEBUGGER_SUPPORT */\n#if defined(DUK_USE_ASSERTIONS)\n\tduk_bool_t dbg_calling_transport;       /* transport call in progress, calling into Duktape forbidden */\n#endif\n\n\t/* String intern table (weak refs). */\n#if defined(DUK_USE_STRTAB_PTRCOMP)\n\tduk_uint16_t *strtable16;\n#else\n\tduk_hstring **strtable;\n#endif\n\tduk_uint32_t st_mask;    /* mask for lookup, st_size - 1 */\n\tduk_uint32_t st_size;    /* stringtable size */\n#if (DUK_USE_STRTAB_MINSIZE != DUK_USE_STRTAB_MAXSIZE)\n\tduk_uint32_t st_count;   /* string count for resize load factor checks */\n#endif\n\tduk_bool_t st_resizing;  /* string table is being resized; avoid recursive resize */\n\n\t/* String access cache (codepoint offset -> byte offset) for fast string\n\t * character looping; 'weak' reference which needs special handling in GC.\n\t */\n\tduk_strcache strcache[DUK_HEAP_STRCACHE_SIZE];\n\n\t/* Built-in strings. */\n#if defined(DUK_USE_ROM_STRINGS)\n\t/* No field needed when strings are in ROM. */\n#else\n#if defined(DUK_USE_HEAPPTR16)\n\tduk_uint16_t strs16[DUK_HEAP_NUM_STRINGS];\n#else\n\tduk_hstring *strs[DUK_HEAP_NUM_STRINGS];\n#endif\n#endif\n\n\t/* Stats. */\n#if defined(DUK_USE_DEBUG)\n\tduk_int_t stats_exec_opcodes;\n\tduk_int_t stats_exec_interrupt;\n\tduk_int_t stats_exec_throw;\n\tduk_int_t stats_call_all;\n\tduk_int_t stats_call_tailcall;\n\tduk_int_t stats_call_ecmatoecma;\n\tduk_int_t stats_safecall_all;\n\tduk_int_t stats_safecall_nothrow;\n\tduk_int_t stats_safecall_throw;\n\tduk_int_t stats_ms_try_count;\n\tduk_int_t stats_ms_skip_count;\n\tduk_int_t stats_ms_emergency_count;\n\tduk_int_t stats_strtab_intern_hit;\n\tduk_int_t stats_strtab_intern_miss;\n\tduk_int_t stats_strtab_resize_check;\n\tduk_int_t stats_strtab_resize_grow;\n\tduk_int_t stats_strtab_resize_shrink;\n\tduk_int_t stats_object_realloc_props;\n\tduk_int_t stats_object_abandon_array;\n\tduk_int_t stats_getownpropdesc_count;\n\tduk_int_t stats_getownpropdesc_hit;\n\tduk_int_t stats_getownpropdesc_miss;\n\tduk_int_t stats_getpropdesc_count;\n\tduk_int_t stats_getpropdesc_hit;\n\tduk_int_t stats_getpropdesc_miss;\n\tduk_int_t stats_getprop_all;\n\tduk_int_t stats_getprop_arrayidx;\n\tduk_int_t stats_getprop_bufobjidx;\n\tduk_int_t stats_getprop_bufferidx;\n\tduk_int_t stats_getprop_bufferlen;\n\tduk_int_t stats_getprop_stringidx;\n\tduk_int_t stats_getprop_stringlen;\n\tduk_int_t stats_getprop_proxy;\n\tduk_int_t stats_getprop_arguments;\n\tduk_int_t stats_putprop_all;\n\tduk_int_t stats_putprop_arrayidx;\n\tduk_int_t stats_putprop_bufobjidx;\n\tduk_int_t stats_putprop_bufferidx;\n\tduk_int_t stats_putprop_proxy;\n\tduk_int_t stats_getvar_all;\n\tduk_int_t stats_putvar_all;\n#endif\n};\n\n/*\n *  Prototypes\n */\n\nDUK_INTERNAL_DECL\nduk_heap *duk_heap_alloc(duk_alloc_function alloc_func,\n                         duk_realloc_function realloc_func,\n                         duk_free_function free_func,\n                         void *heap_udata,\n                         duk_fatal_function fatal_func);\nDUK_INTERNAL_DECL void duk_heap_free(duk_heap *heap);\nDUK_INTERNAL_DECL void duk_free_hobject(duk_heap *heap, duk_hobject *h);\nDUK_INTERNAL_DECL void duk_free_hbuffer(duk_heap *heap, duk_hbuffer *h);\nDUK_INTERNAL_DECL void duk_free_hstring(duk_heap *heap, duk_hstring *h);\nDUK_INTERNAL_DECL void duk_heap_free_heaphdr_raw(duk_heap *heap, duk_heaphdr *hdr);\n\nDUK_INTERNAL_DECL void duk_heap_insert_into_heap_allocated(duk_heap *heap, duk_heaphdr *hdr);\n#if defined(DUK_USE_REFERENCE_COUNTING)\nDUK_INTERNAL_DECL void duk_heap_remove_from_heap_allocated(duk_heap *heap, duk_heaphdr *hdr);\n#endif\n#if defined(DUK_USE_FINALIZER_SUPPORT)\nDUK_INTERNAL_DECL void duk_heap_insert_into_finalize_list(duk_heap *heap, duk_heaphdr *hdr);\nDUK_INTERNAL_DECL void duk_heap_remove_from_finalize_list(duk_heap *heap, duk_heaphdr *hdr);\n#endif\n#if defined(DUK_USE_ASSERTIONS)\nDUK_INTERNAL_DECL duk_bool_t duk_heap_in_heap_allocated(duk_heap *heap, duk_heaphdr *ptr);\n#endif\n#if defined(DUK_USE_INTERRUPT_COUNTER)\nDUK_INTERNAL_DECL void duk_heap_switch_thread(duk_heap *heap, duk_hthread *new_thr);\n#endif\n\nDUK_INTERNAL_DECL duk_hstring *duk_heap_strtable_intern(duk_heap *heap, const duk_uint8_t *str, duk_uint32_t blen);\nDUK_INTERNAL_DECL duk_hstring *duk_heap_strtable_intern_checked(duk_hthread *thr, const duk_uint8_t *str, duk_uint32_t len);\nDUK_INTERNAL_DECL duk_hstring *duk_heap_strtable_intern_u32(duk_heap *heap, duk_uint32_t val);\nDUK_INTERNAL_DECL duk_hstring *duk_heap_strtable_intern_u32_checked(duk_hthread *thr, duk_uint32_t val);\n#if defined(DUK_USE_REFERENCE_COUNTING)\nDUK_INTERNAL_DECL void duk_heap_strtable_unlink(duk_heap *heap, duk_hstring *h);\n#endif\nDUK_INTERNAL_DECL void duk_heap_strtable_unlink_prev(duk_heap *heap, duk_hstring *h, duk_hstring *prev);\nDUK_INTERNAL_DECL void duk_heap_strtable_force_resize(duk_heap *heap);\nDUK_INTERNAL void duk_heap_strtable_free(duk_heap *heap);\n#if defined(DUK_USE_DEBUG)\nDUK_INTERNAL void duk_heap_strtable_dump(duk_heap *heap);\n#endif\n\nDUK_INTERNAL_DECL void duk_heap_strcache_string_remove(duk_heap *heap, duk_hstring *h);\nDUK_INTERNAL_DECL duk_uint_fast32_t duk_heap_strcache_offset_char2byte(duk_hthread *thr, duk_hstring *h, duk_uint_fast32_t char_offset);\n\n#if defined(DUK_USE_PROVIDE_DEFAULT_ALLOC_FUNCTIONS)\nDUK_INTERNAL_DECL void *duk_default_alloc_function(void *udata, duk_size_t size);\nDUK_INTERNAL_DECL void *duk_default_realloc_function(void *udata, void *ptr, duk_size_t newsize);\nDUK_INTERNAL_DECL void duk_default_free_function(void *udata, void *ptr);\n#endif\n\nDUK_INTERNAL_DECL void *duk_heap_mem_alloc(duk_heap *heap, duk_size_t size);\nDUK_INTERNAL_DECL void *duk_heap_mem_alloc_zeroed(duk_heap *heap, duk_size_t size);\nDUK_INTERNAL_DECL void *duk_heap_mem_alloc_checked(duk_hthread *thr, duk_size_t size);\nDUK_INTERNAL_DECL void *duk_heap_mem_alloc_checked_zeroed(duk_hthread *thr, duk_size_t size);\nDUK_INTERNAL_DECL void *duk_heap_mem_realloc(duk_heap *heap, void *ptr, duk_size_t newsize);\nDUK_INTERNAL_DECL void *duk_heap_mem_realloc_indirect(duk_heap *heap, duk_mem_getptr cb, void *ud, duk_size_t newsize);\nDUK_INTERNAL_DECL void duk_heap_mem_free(duk_heap *heap, void *ptr);\n\nDUK_INTERNAL_DECL void duk_heap_free_freelists(duk_heap *heap);\n\n#if defined(DUK_USE_FINALIZER_SUPPORT)\nDUK_INTERNAL_DECL void duk_heap_run_finalizer(duk_heap *heap, duk_hobject *obj);\nDUK_INTERNAL_DECL void duk_heap_process_finalize_list(duk_heap *heap);\n#endif  /* DUK_USE_FINALIZER_SUPPORT */\n\nDUK_INTERNAL_DECL void duk_heap_mark_and_sweep(duk_heap *heap, duk_small_uint_t flags);\n\nDUK_INTERNAL_DECL duk_uint32_t duk_heap_hashstring(duk_heap *heap, const duk_uint8_t *str, duk_size_t len);\n\n#endif  /* DUK_HEAP_H_INCLUDED */\n/* #include duk_debugger.h */\n#line 1 \"duk_debugger.h\"\n#if !defined(DUK_DEBUGGER_H_INCLUDED)\n#define DUK_DEBUGGER_H_INCLUDED\n\n/* Debugger protocol version is defined in the public API header. */\n\n/* Initial bytes for markers. */\n#define DUK_DBG_IB_EOM                   0x00\n#define DUK_DBG_IB_REQUEST               0x01\n#define DUK_DBG_IB_REPLY                 0x02\n#define DUK_DBG_IB_ERROR                 0x03\n#define DUK_DBG_IB_NOTIFY                0x04\n\n/* Other initial bytes. */\n#define DUK_DBG_IB_INT4                  0x10\n#define DUK_DBG_IB_STR4                  0x11\n#define DUK_DBG_IB_STR2                  0x12\n#define DUK_DBG_IB_BUF4                  0x13\n#define DUK_DBG_IB_BUF2                  0x14\n#define DUK_DBG_IB_UNUSED                0x15\n#define DUK_DBG_IB_UNDEFINED             0x16\n#define DUK_DBG_IB_NULL                  0x17\n#define DUK_DBG_IB_TRUE                  0x18\n#define DUK_DBG_IB_FALSE                 0x19\n#define DUK_DBG_IB_NUMBER                0x1a\n#define DUK_DBG_IB_OBJECT                0x1b\n#define DUK_DBG_IB_POINTER               0x1c\n#define DUK_DBG_IB_LIGHTFUNC             0x1d\n#define DUK_DBG_IB_HEAPPTR               0x1e\n/* The short string/integer initial bytes starting from 0x60 don't have\n * defines now.\n */\n\n/* Error codes. */\n#define DUK_DBG_ERR_UNKNOWN              0x00\n#define DUK_DBG_ERR_UNSUPPORTED          0x01\n#define DUK_DBG_ERR_TOOMANY              0x02\n#define DUK_DBG_ERR_NOTFOUND             0x03\n#define DUK_DBG_ERR_APPLICATION          0x04\n\n/* Commands and notifys initiated by Duktape. */\n#define DUK_DBG_CMD_STATUS               0x01\n#define DUK_DBG_CMD_UNUSED_2             0x02  /* Duktape 1.x: print notify */\n#define DUK_DBG_CMD_UNUSED_3             0x03  /* Duktape 1.x: alert notify */\n#define DUK_DBG_CMD_UNUSED_4             0x04  /* Duktape 1.x: log notify */\n#define DUK_DBG_CMD_THROW                0x05\n#define DUK_DBG_CMD_DETACHING            0x06\n#define DUK_DBG_CMD_APPNOTIFY            0x07\n\n/* Commands initiated by debug client. */\n#define DUK_DBG_CMD_BASICINFO            0x10\n#define DUK_DBG_CMD_TRIGGERSTATUS        0x11\n#define DUK_DBG_CMD_PAUSE                0x12\n#define DUK_DBG_CMD_RESUME               0x13\n#define DUK_DBG_CMD_STEPINTO             0x14\n#define DUK_DBG_CMD_STEPOVER             0x15\n#define DUK_DBG_CMD_STEPOUT              0x16\n#define DUK_DBG_CMD_LISTBREAK            0x17\n#define DUK_DBG_CMD_ADDBREAK             0x18\n#define DUK_DBG_CMD_DELBREAK             0x19\n#define DUK_DBG_CMD_GETVAR               0x1a\n#define DUK_DBG_CMD_PUTVAR               0x1b\n#define DUK_DBG_CMD_GETCALLSTACK         0x1c\n#define DUK_DBG_CMD_GETLOCALS            0x1d\n#define DUK_DBG_CMD_EVAL                 0x1e\n#define DUK_DBG_CMD_DETACH               0x1f\n#define DUK_DBG_CMD_DUMPHEAP             0x20\n#define DUK_DBG_CMD_GETBYTECODE          0x21\n#define DUK_DBG_CMD_APPREQUEST           0x22\n#define DUK_DBG_CMD_GETHEAPOBJINFO       0x23\n#define DUK_DBG_CMD_GETOBJPROPDESC       0x24\n#define DUK_DBG_CMD_GETOBJPROPDESCRANGE  0x25\n\n/* The low 8 bits map directly to duk_hobject.h DUK_PROPDESC_FLAG_xxx.\n * The remaining flags are specific to the debugger.\n */\n#define DUK_DBG_PROPFLAG_SYMBOL          (1U << 8)\n#define DUK_DBG_PROPFLAG_HIDDEN          (1U << 9)\n\n#if defined(DUK_USE_DEBUGGER_SUPPORT)\nDUK_INTERNAL_DECL void duk_debug_do_detach(duk_heap *heap);\n\nDUK_INTERNAL_DECL duk_bool_t duk_debug_read_peek(duk_hthread *thr);\nDUK_INTERNAL_DECL void duk_debug_write_flush(duk_hthread *thr);\n\nDUK_INTERNAL_DECL void duk_debug_skip_bytes(duk_hthread *thr, duk_size_t length);\nDUK_INTERNAL_DECL void duk_debug_skip_byte(duk_hthread *thr);\n\nDUK_INTERNAL_DECL void duk_debug_read_bytes(duk_hthread *thr, duk_uint8_t *data, duk_size_t length);\nDUK_INTERNAL_DECL duk_uint8_t duk_debug_read_byte(duk_hthread *thr);\nDUK_INTERNAL_DECL duk_int32_t duk_debug_read_int(duk_hthread *thr);\nDUK_INTERNAL_DECL duk_hstring *duk_debug_read_hstring(duk_hthread *thr);\n/* XXX: exposed duk_debug_read_pointer */\n/* XXX: exposed duk_debug_read_buffer */\n/* XXX: exposed duk_debug_read_hbuffer */\n#if 0\nDUK_INTERNAL_DECL duk_heaphdr *duk_debug_read_heapptr(duk_hthread *thr);\n#endif\n#if defined(DUK_USE_DEBUGGER_INSPECT)\nDUK_INTERNAL_DECL duk_heaphdr *duk_debug_read_any_ptr(duk_hthread *thr);\n#endif\nDUK_INTERNAL_DECL duk_tval *duk_debug_read_tval(duk_hthread *thr);\n\nDUK_INTERNAL_DECL void duk_debug_write_bytes(duk_hthread *thr, const duk_uint8_t *data, duk_size_t length);\nDUK_INTERNAL_DECL void duk_debug_write_byte(duk_hthread *thr, duk_uint8_t x);\nDUK_INTERNAL_DECL void duk_debug_write_unused(duk_hthread *thr);\nDUK_INTERNAL_DECL void duk_debug_write_undefined(duk_hthread *thr);\n#if defined(DUK_USE_DEBUGGER_INSPECT)\nDUK_INTERNAL_DECL void duk_debug_write_null(duk_hthread *thr);\n#endif\nDUK_INTERNAL_DECL void duk_debug_write_boolean(duk_hthread *thr, duk_uint_t val);\nDUK_INTERNAL_DECL void duk_debug_write_int(duk_hthread *thr, duk_int32_t x);\nDUK_INTERNAL_DECL void duk_debug_write_uint(duk_hthread *thr, duk_uint32_t x);\nDUK_INTERNAL_DECL void duk_debug_write_string(duk_hthread *thr, const char *data, duk_size_t length);\nDUK_INTERNAL_DECL void duk_debug_write_cstring(duk_hthread *thr, const char *data);\nDUK_INTERNAL_DECL void duk_debug_write_hstring(duk_hthread *thr, duk_hstring *h);\nDUK_INTERNAL_DECL void duk_debug_write_buffer(duk_hthread *thr, const char *data, duk_size_t length);\nDUK_INTERNAL_DECL void duk_debug_write_hbuffer(duk_hthread *thr, duk_hbuffer *h);\nDUK_INTERNAL_DECL void duk_debug_write_pointer(duk_hthread *thr, void *ptr);\n#if defined(DUK_USE_DEBUGGER_DUMPHEAP) || defined(DUK_USE_DEBUGGER_INSPECT)\nDUK_INTERNAL_DECL void duk_debug_write_heapptr(duk_hthread *thr, duk_heaphdr *h);\n#endif\nDUK_INTERNAL_DECL void duk_debug_write_hobject(duk_hthread *thr, duk_hobject *obj);\nDUK_INTERNAL_DECL void duk_debug_write_tval(duk_hthread *thr, duk_tval *tv);\n#if 0  /* unused */\nDUK_INTERNAL_DECL void duk_debug_write_request(duk_hthread *thr, duk_small_uint_t command);\n#endif\nDUK_INTERNAL_DECL void duk_debug_write_reply(duk_hthread *thr);\nDUK_INTERNAL_DECL void duk_debug_write_error_eom(duk_hthread *thr, duk_small_uint_t err_code, const char *msg);\nDUK_INTERNAL_DECL void duk_debug_write_notify(duk_hthread *thr, duk_small_uint_t command);\nDUK_INTERNAL_DECL void duk_debug_write_eom(duk_hthread *thr);\n\nDUK_INTERNAL_DECL duk_uint_fast32_t duk_debug_curr_line(duk_hthread *thr);\nDUK_INTERNAL_DECL void duk_debug_send_status(duk_hthread *thr);\n#if defined(DUK_USE_DEBUGGER_THROW_NOTIFY)\nDUK_INTERNAL_DECL void duk_debug_send_throw(duk_hthread *thr, duk_bool_t fatal);\n#endif\n\nDUK_INTERNAL_DECL void duk_debug_halt_execution(duk_hthread *thr, duk_bool_t use_prev_pc);\nDUK_INTERNAL_DECL duk_bool_t duk_debug_process_messages(duk_hthread *thr, duk_bool_t no_block);\n\nDUK_INTERNAL_DECL duk_small_int_t duk_debug_add_breakpoint(duk_hthread *thr, duk_hstring *filename, duk_uint32_t line);\nDUK_INTERNAL_DECL duk_bool_t duk_debug_remove_breakpoint(duk_hthread *thr, duk_small_uint_t breakpoint_index);\n\nDUK_INTERNAL_DECL duk_bool_t duk_debug_is_attached(duk_heap *heap);\nDUK_INTERNAL_DECL duk_bool_t duk_debug_is_paused(duk_heap *heap);\nDUK_INTERNAL_DECL void duk_debug_set_paused(duk_heap *heap);\nDUK_INTERNAL_DECL void duk_debug_clear_paused(duk_heap *heap);\nDUK_INTERNAL_DECL void duk_debug_clear_pause_state(duk_heap *heap);\n#endif  /* DUK_USE_DEBUGGER_SUPPORT */\n\n#endif  /* DUK_DEBUGGER_H_INCLUDED */\n/* #include duk_debug.h */\n#line 1 \"duk_debug.h\"\n/*\n *  Debugging macros, DUK_DPRINT() and its variants in particular.\n *\n *  DUK_DPRINT() allows formatted debug prints, and supports standard\n *  and Duktape specific formatters.  See duk_debug_vsnprintf.c for details.\n *\n *  DUK_D(x), DUK_DD(x), and DUK_DDD(x) are used together with log macros\n *  for technical reasons.  They are concretely used to hide 'x' from the\n *  compiler when the corresponding log level is disabled.  This allows\n *  clean builds on non-C99 compilers, at the cost of more verbose code.\n *  Examples:\n *\n *    DUK_D(DUK_DPRINT(\"foo\"));\n *    DUK_DD(DUK_DDPRINT(\"foo\"));\n *    DUK_DDD(DUK_DDDPRINT(\"foo\"));\n *\n *  This approach is preferable to the old \"double parentheses\" hack because\n *  double parentheses make the C99 solution worse: __FILE__ and __LINE__ can\n *  no longer be added transparently without going through globals, which\n *  works poorly with threading.\n */\n\n#if !defined(DUK_DEBUG_H_INCLUDED)\n#define DUK_DEBUG_H_INCLUDED\n\n#if defined(DUK_USE_DEBUG)\n\n#if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 0)\n#define DUK_D(x) x\n#else\n#define DUK_D(x) do { } while (0) /* omit */\n#endif\n\n#if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 1)\n#define DUK_DD(x) x\n#else\n#define DUK_DD(x) do { } while (0) /* omit */\n#endif\n\n#if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)\n#define DUK_DDD(x) x\n#else\n#define DUK_DDD(x) do { } while (0) /* omit */\n#endif\n\n/*\n *  Exposed debug macros: debugging enabled\n */\n\n#if defined(DUK_USE_VARIADIC_MACROS)\n\n/* Note: combining __FILE__, __LINE__, and __func__ into fmt would be\n * possible compile time, but waste some space with shared function names.\n */\n#define DUK__DEBUG_LOG(lev,...)  duk_debug_log((duk_int_t) (lev), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, DUK_FUNC_MACRO, __VA_ARGS__);\n\n#if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 0)\n#define DUK_DPRINT(...)          DUK__DEBUG_LOG(DUK_LEVEL_DEBUG, __VA_ARGS__)\n#else\n#define DUK_DPRINT(...)\n#endif\n\n#if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 1)\n#define DUK_DDPRINT(...)         DUK__DEBUG_LOG(DUK_LEVEL_DDEBUG, __VA_ARGS__)\n#else\n#define DUK_DDPRINT(...)\n#endif\n\n#if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)\n#define DUK_DDDPRINT(...)        DUK__DEBUG_LOG(DUK_LEVEL_DDDEBUG, __VA_ARGS__)\n#else\n#define DUK_DDDPRINT(...)\n#endif\n\n#else  /* DUK_USE_VARIADIC_MACROS */\n\n#define DUK__DEBUG_STASH(lev)    \\\n\t(void) DUK_SNPRINTF(duk_debug_file_stash, DUK_DEBUG_STASH_SIZE, \"%s\", (const char *) DUK_FILE_MACRO), \\\n\t(void) (duk_debug_file_stash[DUK_DEBUG_STASH_SIZE - 1] = (char) 0), \\\n\t(void) (duk_debug_line_stash = (duk_int_t) DUK_LINE_MACRO), \\\n\t(void) DUK_SNPRINTF(duk_debug_func_stash, DUK_DEBUG_STASH_SIZE, \"%s\", (const char *) DUK_FUNC_MACRO), \\\n\t(void) (duk_debug_func_stash[DUK_DEBUG_STASH_SIZE - 1] = (char) 0), \\\n\t(void) (duk_debug_level_stash = (lev))\n\n/* Without variadic macros resort to comma expression trickery to handle debug\n * prints.  This generates a lot of harmless warnings.  These hacks are not\n * needed normally because DUK_D() and friends will hide the entire debug log\n * statement from the compiler.\n */\n\n#if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 0)\n#define DUK_DPRINT  DUK__DEBUG_STASH(DUK_LEVEL_DEBUG), (void) duk_debug_log  /* args go here in parens */\n#else\n#define DUK_DPRINT  0 && /* args go here as a comma expression in parens */\n#endif\n\n#if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 1)\n#define DUK_DDPRINT  DUK__DEBUG_STASH(DUK_LEVEL_DDEBUG), (void) duk_debug_log  /* args go here in parens */\n#else\n#define DUK_DDPRINT  0 && /* args */\n#endif\n\n#if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)\n#define DUK_DDDPRINT  DUK__DEBUG_STASH(DUK_LEVEL_DDDEBUG), (void) duk_debug_log  /* args go here in parens */\n#else\n#define DUK_DDDPRINT  0 && /* args */\n#endif\n\n#endif  /* DUK_USE_VARIADIC_MACROS */\n\n#else  /* DUK_USE_DEBUG */\n\n/*\n *  Exposed debug macros: debugging disabled\n */\n\n#define DUK_D(x) do { } while (0) /* omit */\n#define DUK_DD(x) do { } while (0) /* omit */\n#define DUK_DDD(x) do { } while (0) /* omit */\n\n#if defined(DUK_USE_VARIADIC_MACROS)\n\n#define DUK_DPRINT(...)\n#define DUK_DDPRINT(...)\n#define DUK_DDDPRINT(...)\n\n#else  /* DUK_USE_VARIADIC_MACROS */\n\n#define DUK_DPRINT    0 && /* args go here as a comma expression in parens */\n#define DUK_DDPRINT   0 && /* args */\n#define DUK_DDDPRINT  0 && /* args */\n\n#endif  /* DUK_USE_VARIADIC_MACROS */\n\n#endif  /* DUK_USE_DEBUG */\n\n/*\n *  Structs\n */\n\n#if defined(DUK_USE_DEBUG)\nstruct duk_fixedbuffer {\n\tduk_uint8_t *buffer;\n\tduk_size_t length;\n\tduk_size_t offset;\n\tduk_bool_t truncated;\n};\n#endif\n\n/*\n *  Prototypes\n */\n\n#if defined(DUK_USE_DEBUG)\nDUK_INTERNAL_DECL duk_int_t duk_debug_vsnprintf(char *str, duk_size_t size, const char *format, va_list ap);\n#if 0  /*unused*/\nDUK_INTERNAL_DECL duk_int_t duk_debug_snprintf(char *str, duk_size_t size, const char *format, ...);\n#endif\nDUK_INTERNAL_DECL void duk_debug_format_funcptr(char *buf, duk_size_t buf_size, duk_uint8_t *fptr, duk_size_t fptr_size);\n\n#if defined(DUK_USE_VARIADIC_MACROS)\nDUK_INTERNAL_DECL void duk_debug_log(duk_int_t level, const char *file, duk_int_t line, const char *func, const char *fmt, ...);\n#else  /* DUK_USE_VARIADIC_MACROS */\n/* parameter passing, not thread safe */\n#define DUK_DEBUG_STASH_SIZE  128\n#if !defined(DUK_SINGLE_FILE)\nDUK_INTERNAL_DECL char duk_debug_file_stash[DUK_DEBUG_STASH_SIZE];\nDUK_INTERNAL_DECL duk_int_t duk_debug_line_stash;\nDUK_INTERNAL_DECL char duk_debug_func_stash[DUK_DEBUG_STASH_SIZE];\nDUK_INTERNAL_DECL duk_int_t duk_debug_level_stash;\n#endif\nDUK_INTERNAL_DECL void duk_debug_log(const char *fmt, ...);\n#endif  /* DUK_USE_VARIADIC_MACROS */\n\nDUK_INTERNAL_DECL void duk_fb_put_bytes(duk_fixedbuffer *fb, const duk_uint8_t *buffer, duk_size_t length);\nDUK_INTERNAL_DECL void duk_fb_put_byte(duk_fixedbuffer *fb, duk_uint8_t x);\nDUK_INTERNAL_DECL void duk_fb_put_cstring(duk_fixedbuffer *fb, const char *x);\nDUK_INTERNAL_DECL void duk_fb_sprintf(duk_fixedbuffer *fb, const char *fmt, ...);\nDUK_INTERNAL_DECL void duk_fb_put_funcptr(duk_fixedbuffer *fb, duk_uint8_t *fptr, duk_size_t fptr_size);\nDUK_INTERNAL_DECL duk_bool_t duk_fb_is_full(duk_fixedbuffer *fb);\n\n#endif  /* DUK_USE_DEBUG */\n\n#endif  /* DUK_DEBUG_H_INCLUDED */\n/* #include duk_error.h */\n#line 1 \"duk_error.h\"\n/*\n *  Error handling macros, assertion macro, error codes.\n *\n *  There are three types of 'errors':\n *\n *    1. Ordinary errors relative to a thread, cause a longjmp, catchable.\n *    2. Fatal errors relative to a heap, cause fatal handler to be called.\n *    3. Fatal errors without context, cause the default (not heap specific)\n *       fatal handler to be called.\n *\n *  Fatal errors without context are used by debug code such as assertions.\n *  By providing a fatal error handler for a Duktape heap, user code can\n *  avoid fatal errors without context in non-debug builds.\n */\n\n#if !defined(DUK_ERROR_H_INCLUDED)\n#define DUK_ERROR_H_INCLUDED\n\n/*\n *  Error codes: defined in duktape.h\n *\n *  Error codes are used as a shorthand to throw exceptions from inside\n *  the implementation.  The appropriate Ecmascript object is constructed\n *  based on the code.  Ecmascript code throws objects directly.  The error\n *  codes are defined in the public API header because they are also used\n *  by calling code.\n */\n\n/*\n *  Normal error\n *\n *  Normal error is thrown with a longjmp() through the current setjmp()\n *  catchpoint record in the duk_heap.  The 'curr_thread' of the duk_heap\n *  identifies the throwing thread.\n *\n *  Error formatting is usually unnecessary.  The error macros provide a\n *  zero argument version (no formatting) and separate macros for small\n *  argument counts.  Variadic macros are not used to avoid portability\n *  issues and avoid the need for stash-based workarounds when they're not\n *  available.  Vararg calls are avoided for non-formatted error calls\n *  because vararg call sites are larger than normal, and there are a lot\n *  of call sites with no formatting.\n *\n *  Note that special formatting provided by debug macros is NOT available.\n *\n *  The _RAW variants allow the caller to specify file and line.  This makes\n *  it easier to write checked calls which want to use the call site of the\n *  checked function, not the error macro call inside the checked function.\n */\n\n#if defined(DUK_USE_VERBOSE_ERRORS)\n\n/* Because there are quite many call sites, pack error code (require at most\n * 8-bit) into a single argument.\n */\n#define DUK_ERROR(thr,err,msg) do { \\\n\t\tduk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) DUK_LINE_MACRO; \\\n\t\tDUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \\\n\t\tduk_err_handle_error((thr), DUK_FILE_MACRO, (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (msg)); \\\n\t} while (0)\n#define DUK_ERROR_RAW(thr,file,line,err,msg) do { \\\n\t\tduk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) (line); \\\n\t\tDUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \\\n\t\tduk_err_handle_error((thr), (file), (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (msg)); \\\n\t} while (0)\n\n#define DUK_ERROR_FMT1(thr,err,fmt,arg1) do { \\\n\t\tduk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) DUK_LINE_MACRO; \\\n\t\tDUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \\\n\t\tduk_err_handle_error_fmt((thr), DUK_FILE_MACRO, (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (fmt), (arg1)); \\\n\t} while (0)\n#define DUK_ERROR_RAW_FMT1(thr,file,line,err,fmt,arg1) do { \\\n\t\tduk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) (line); \\\n\t\tDUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \\\n\t\tduk_err_handle_error_fmt((thr), (file), (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (fmt), (arg1)); \\\n\t} while (0)\n\n#define DUK_ERROR_FMT2(thr,err,fmt,arg1,arg2) do { \\\n\t\tduk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) DUK_LINE_MACRO; \\\n\t\tDUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \\\n\t\tduk_err_handle_error_fmt((thr), DUK_FILE_MACRO, (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (fmt), (arg1), (arg2)); \\\n\t} while (0)\n#define DUK_ERROR_RAW_FMT2(thr,file,line,err,fmt,arg1,arg2) do { \\\n\t\tduk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) (line); \\\n\t\tDUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \\\n\t\tduk_err_handle_error_fmt((thr), (file), (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (fmt), (arg1), (arg2)); \\\n\t} while (0)\n\n#define DUK_ERROR_FMT3(thr,err,fmt,arg1,arg2,arg3) do { \\\n\t\tduk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) DUK_LINE_MACRO; \\\n\t\tDUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \\\n\t\tduk_err_handle_error_fmt((thr), DUK_FILE_MACRO, (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (fmt), (arg1), (arg2), (arg3)); \\\n\t} while (0)\n#define DUK_ERROR_RAW_FMT3(thr,file,line,err,fmt,arg1,arg2,arg3) do { \\\n\t\tduk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) (line); \\\n\t\tDUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \\\n\t\tduk_err_handle_error_fmt((thr), (file), (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (fmt), (arg1), (arg2), (arg3)); \\\n\t} while (0)\n\n#define DUK_ERROR_FMT4(thr,err,fmt,arg1,arg2,arg3,arg4) do { \\\n\t\tduk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) DUK_LINE_MACRO; \\\n\t\tDUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \\\n\t\tduk_err_handle_error_fmt((thr), DUK_FILE_MACRO, (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (fmt), (arg1), (arg2), (arg3), (arg4)); \\\n\t} while (0)\n#define DUK_ERROR_RAW_FMT4(thr,file,line,err,fmt,arg1,arg2,arg3,arg4) do { \\\n\t\tduk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) (line); \\\n\t\tDUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \\\n\t\tduk_err_handle_error_fmt((thr), (file), (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (fmt), (arg1), (arg2), (arg3), (arg4)); \\\n\t} while (0)\n\n#else  /* DUK_USE_VERBOSE_ERRORS */\n\n#define DUK_ERROR(thr,err,msg)                    duk_err_handle_error((thr), (err))\n#define DUK_ERROR_RAW(thr,file,line,err,msg)      duk_err_handle_error((thr), (err))\n\n#define DUK_ERROR_FMT1(thr,err,fmt,arg1) DUK_ERROR((thr),(err),(fmt))\n#define DUK_ERROR_RAW_FMT1(thr,file,line,err,fmt,arg1) DUK_ERROR_RAW((thr),(file),(line),(err),(fmt))\n\n#define DUK_ERROR_FMT2(thr,err,fmt,arg1,arg2) DUK_ERROR((thr),(err),(fmt))\n#define DUK_ERROR_RAW_FMT2(thr,file,line,err,fmt,arg1,arg2) DUK_ERROR_RAW((thr),(file),(line),(err),(fmt))\n\n#define DUK_ERROR_FMT3(thr,err,fmt,arg1,arg2,arg3) DUK_ERROR((thr),(err),(fmt))\n#define DUK_ERROR_RAW_FMT3(thr,file,line,err,fmt,arg1,arg2,arg3) DUK_ERROR_RAW((thr),(file),(line),(err),(fmt))\n\n#define DUK_ERROR_FMT4(thr,err,fmt,arg1,arg2,arg3,arg4) DUK_ERROR((thr),(err),(fmt))\n#define DUK_ERROR_RAW_FMT4(thr,file,line,err,fmt,arg1,arg2,arg3,arg4) DUK_ERROR_RAW((thr),(file),(line),(err),(fmt))\n\n#endif  /* DUK_USE_VERBOSE_ERRORS */\n\n/*\n *  Fatal error without context\n *\n *  The macro is an expression to make it compatible with DUK_ASSERT_EXPR().\n */\n\n#define DUK_FATAL_WITHOUT_CONTEXT(msg) \\\n\tduk_default_fatal_handler(NULL, (msg))\n\n/*\n *  Error throwing helpers\n *\n *  The goal is to provide verbose and configurable error messages.  Call\n *  sites should be clean in source code and compile to a small footprint.\n *  Small footprint is also useful for performance because small cold paths\n *  reduce code cache pressure.  Adding macros here only makes sense if there\n *  are enough call sites to get concrete benefits.\n *\n *  DUK_ERROR_xxx() macros are generic and can be used anywhere.\n *\n *  DUK_DCERROR_xxx() macros can only be used in Duktape/C functions where\n *  the \"return DUK_RET_xxx;\" shorthand is available for low memory targets.\n *  The DUK_DCERROR_xxx() macros always either throw or perform a\n *  'return DUK_RET_xxx' from the calling function.\n */\n\n#if defined(DUK_USE_VERBOSE_ERRORS)\n/* Verbose errors with key/value summaries (non-paranoid) or without key/value\n * summaries (paranoid, for some security sensitive environments), the paranoid\n * vs. non-paranoid distinction affects only a few specific errors.\n */\n#if defined(DUK_USE_PARANOID_ERRORS)\n#define DUK_ERROR_REQUIRE_TYPE_INDEX(thr,idx,expectname,lowmemstr) do { \\\n\t\tduk_err_require_type_index((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, (idx), (expectname)); \\\n\t} while (0)\n#else  /* DUK_USE_PARANOID_ERRORS */\n#define DUK_ERROR_REQUIRE_TYPE_INDEX(thr,idx,expectname,lowmemstr) do { \\\n\t\tduk_err_require_type_index((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, (idx), (expectname)); \\\n\t} while (0)\n#endif  /* DUK_USE_PARANOID_ERRORS */\n\n#define DUK_ERROR_INTERNAL(thr) do { \\\n\t\tduk_err_error_internal((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO); \\\n\t} while (0)\n#define DUK_DCERROR_INTERNAL(thr) do { \\\n\t\tDUK_ERROR_INTERNAL((thr)); \\\n\t\treturn 0; \\\n\t} while (0)\n#define DUK_ERROR_ALLOC_FAILED(thr) do { \\\n\t\tduk_err_error_alloc_failed((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO); \\\n\t} while (0)\n#define DUK_ERROR_UNSUPPORTED(thr) do { \\\n\t\tDUK_ERROR((thr), DUK_ERR_ERROR, DUK_STR_UNSUPPORTED); \\\n\t} while (0)\n#define DUK_ERROR_ERROR(thr,msg) do { \\\n\t\tduk_err_error((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, (msg)); \\\n\t} while (0)\n#define DUK_ERROR_RANGE_INDEX(thr,idx) do { \\\n\t\tduk_err_range_index((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, (idx)); \\\n\t} while (0)\n#define DUK_ERROR_RANGE_PUSH_BEYOND(thr) do { \\\n\t\tduk_err_range_push_beyond((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO); \\\n\t} while (0)\n#define DUK_ERROR_RANGE_INVALID_ARGS(thr) do { \\\n\t\tDUK_ERROR_RANGE((thr), DUK_STR_INVALID_ARGS); \\\n\t} while (0)\n#define DUK_DCERROR_RANGE_INVALID_ARGS(thr) do { \\\n\t\tDUK_ERROR_RANGE_INVALID_ARGS((thr)); \\\n\t\treturn 0; \\\n\t} while (0)\n#define DUK_ERROR_RANGE_INVALID_COUNT(thr) do { \\\n\t\tDUK_ERROR_RANGE((thr), DUK_STR_INVALID_COUNT); \\\n\t} while (0)\n#define DUK_DCERROR_RANGE_INVALID_COUNT(thr) do { \\\n\t\tDUK_ERROR_RANGE_INVALID_COUNT((thr)); \\\n\t\treturn 0; \\\n\t} while (0)\n#define DUK_ERROR_RANGE_INVALID_LENGTH(thr) do { \\\n\t\tDUK_ERROR_RANGE((thr), DUK_STR_INVALID_LENGTH); \\\n\t} while (0)\n#define DUK_DCERROR_RANGE_INVALID_LENGTH(thr) do { \\\n\t\tDUK_ERROR_RANGE_INVALID_LENGTH((thr)); \\\n\t\treturn 0; \\\n\t} while (0)\n#define DUK_ERROR_RANGE(thr,msg) do { \\\n\t\tduk_err_range((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, (msg)); \\\n\t} while (0)\n#define DUK_ERROR_EVAL(thr,msg) do { \\\n\t\tDUK_ERROR((thr), DUK_ERR_EVAL_ERROR, (msg)); \\\n\t} while (0)\n#define DUK_ERROR_REFERENCE(thr,msg) do { \\\n\t\tDUK_ERROR((thr), DUK_ERR_REFERENCE_ERROR, (msg)); \\\n\t} while (0)\n#define DUK_ERROR_SYNTAX(thr,msg) do { \\\n\t\tDUK_ERROR((thr), DUK_ERR_SYNTAX_ERROR, (msg)); \\\n\t} while (0)\n#define DUK_ERROR_TYPE_INVALID_ARGS(thr) do { \\\n\t\tduk_err_type_invalid_args((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO); \\\n\t} while (0)\n#define DUK_DCERROR_TYPE_INVALID_ARGS(thr) do { \\\n\t\tDUK_ERROR_TYPE_INVALID_ARGS((thr)); \\\n\t\treturn 0; \\\n\t} while (0)\n#define DUK_ERROR_TYPE_INVALID_STATE(thr) do { \\\n\t\tduk_err_type_invalid_state((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO); \\\n\t} while (0)\n#define DUK_DCERROR_TYPE_INVALID_STATE(thr) do { \\\n\t\tDUK_ERROR_TYPE_INVALID_STATE((thr)); \\\n\t\treturn 0; \\\n\t} while (0)\n#define DUK_ERROR_TYPE_INVALID_TRAP_RESULT(thr) do { \\\n\t\tduk_err_type_invalid_trap_result((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO); \\\n\t} while (0)\n#define DUK_DCERROR_TYPE_INVALID_TRAP_RESULT(thr) do { \\\n\t\tDUK_ERROR_TYPE((thr), DUK_STR_INVALID_TRAP_RESULT); \\\n\t} while (0)\n#define DUK_ERROR_TYPE(thr,msg) do { \\\n\t\tDUK_ERROR((thr), DUK_ERR_TYPE_ERROR, (msg)); \\\n\t} while (0)\n#define DUK_ERROR_URI(thr,msg) do { \\\n\t\tDUK_ERROR((thr), DUK_ERR_URI_ERROR, (msg)); \\\n\t} while (0)\n#else  /* DUK_USE_VERBOSE_ERRORS */\n/* Non-verbose errors for low memory targets: no file, line, or message. */\n\n#define DUK_ERROR_REQUIRE_TYPE_INDEX(thr,idx,expectname,lowmemstr) do { \\\n\t\tduk_err_type((thr)); \\\n\t} while (0)\n\n#define DUK_ERROR_INTERNAL(thr) do { \\\n\t\tduk_err_error((thr)); \\\n\t} while (0)\n#define DUK_DCERROR_INTERNAL(thr) do { \\\n\t\tDUK_UNREF((thr)); \\\n\t\treturn DUK_RET_ERROR; \\\n\t} while (0)\n#define DUK_ERROR_ALLOC_FAILED(thr) do { \\\n\t\tduk_err_error((thr)); \\\n\t} while (0)\n#define DUK_ERROR_UNSUPPORTED(thr) do { \\\n\t\tduk_err_error((thr)); \\\n\t} while (0)\n#define DUK_ERROR_ERROR(thr,msg) do { \\\n\t\tduk_err_error((thr)); \\\n\t} while (0)\n#define DUK_ERROR_RANGE_INDEX(thr,idx) do { \\\n\t\tduk_err_range((thr)); \\\n\t} while (0)\n#define DUK_ERROR_RANGE_PUSH_BEYOND(thr) do { \\\n\t\tduk_err_range((thr)); \\\n\t} while (0)\n#define DUK_ERROR_RANGE_INVALID_ARGS(thr) do { \\\n\t\tduk_err_range((thr)); \\\n\t} while (0)\n#define DUK_DCERROR_RANGE_INVALID_ARGS(thr) do { \\\n\t\tDUK_UNREF((thr)); \\\n\t\treturn DUK_RET_RANGE_ERROR; \\\n\t} while (0)\n#define DUK_ERROR_RANGE_INVALID_COUNT(thr) do { \\\n\t\tduk_err_range((thr)); \\\n\t} while (0)\n#define DUK_DCERROR_RANGE_INVALID_COUNT(thr) do { \\\n\t\tDUK_UNREF((thr)); \\\n\t\treturn DUK_RET_RANGE_ERROR; \\\n\t} while (0)\n#define DUK_ERROR_RANGE_INVALID_LENGTH(thr) do { \\\n\t\tduk_err_range((thr)); \\\n\t} while (0)\n#define DUK_DCERROR_RANGE_INVALID_LENGTH(thr) do { \\\n\t\tDUK_UNREF((thr)); \\\n\t\treturn DUK_RET_RANGE_ERROR; \\\n\t} while (0)\n#define DUK_ERROR_RANGE(thr,msg) do { \\\n\t\tduk_err_range((thr)); \\\n\t} while (0)\n#define DUK_ERROR_EVAL(thr,msg) do { \\\n\t\tduk_err_eval((thr)); \\\n\t} while (0)\n#define DUK_ERROR_REFERENCE(thr,msg) do { \\\n\t\tduk_err_reference((thr)); \\\n\t} while (0)\n#define DUK_ERROR_SYNTAX(thr,msg) do { \\\n\t\tduk_err_syntax((thr)); \\\n\t} while (0)\n#define DUK_ERROR_TYPE_INVALID_ARGS(thr) do { \\\n\t\tduk_err_type((thr)); \\\n\t} while (0)\n#define DUK_DCERROR_TYPE_INVALID_ARGS(thr) do { \\\n\t\tDUK_UNREF((thr)); \\\n\t\treturn DUK_RET_TYPE_ERROR; \\\n\t} while (0)\n#define DUK_ERROR_TYPE_INVALID_STATE(thr) do { \\\n\t\tduk_err_type((thr)); \\\n\t} while (0)\n#define DUK_DCERROR_TYPE_INVALID_STATE(thr) do { \\\n\t\tduk_err_type((thr)); \\\n\t} while (0)\n#define DUK_ERROR_TYPE_INVALID_TRAP_RESULT(thr) do { \\\n\t\tduk_err_type((thr)); \\\n\t} while (0)\n#define DUK_DCERROR_TYPE_INVALID_TRAP_RESULT(thr) do { \\\n\t\tDUK_UNREF((thr)); \\\n\t\treturn DUK_RET_TYPE_ERROR; \\\n\t} while (0)\n#define DUK_ERROR_TYPE_INVALID_TRAP_RESULT(thr) do { \\\n\t\tduk_err_type((thr)); \\\n\t} while (0)\n#define DUK_ERROR_TYPE(thr,msg) do { \\\n\t\tduk_err_type((thr)); \\\n\t} while (0)\n#define DUK_ERROR_URI(thr,msg) do { \\\n\t\tduk_err_uri((thr)); \\\n\t} while (0)\n#endif  /* DUK_USE_VERBOSE_ERRORS */\n\n/*\n *  Assert macro: failure causes a fatal error.\n *\n *  NOTE: since the assert macro doesn't take a heap/context argument, there's\n *  no way to look up a heap/context specific fatal error handler which may have\n *  been given by the application.  Instead, assertion failures always use the\n *  internal default fatal error handler; it can be replaced via duk_config.h\n *  and then applies to all Duktape heaps.\n */\n\n#if defined(DUK_USE_ASSERTIONS)\n\n/* The message should be a compile time constant without formatting (less risk);\n * we don't care about assertion text size because they're not used in production\n * builds.\n */\n#define DUK_ASSERT(x)  do { \\\n\tif (!(x)) { \\\n\t\tDUK_FATAL_WITHOUT_CONTEXT(\"assertion failed: \" #x \\\n\t\t\t\" (\" DUK_FILE_MACRO \":\" DUK_MACRO_STRINGIFY(DUK_LINE_MACRO) \")\"); \\\n\t} \\\n\t} while (0)\n\n/* Assertion compatible inside a comma expression, evaluates to void. */\n#define DUK_ASSERT_EXPR(x) \\\n\t((void) ((x) ? 0 : (DUK_FATAL_WITHOUT_CONTEXT(\"assertion failed: \" #x \\\n\t\t\t\t\" (\" DUK_FILE_MACRO \":\" DUK_MACRO_STRINGIFY(DUK_LINE_MACRO) \")\"), 0)))\n\n#else  /* DUK_USE_ASSERTIONS */\n\n#define DUK_ASSERT(x)  do { /* assertion omitted */ } while (0)\n\n#define DUK_ASSERT_EXPR(x)  ((void) 0)\n\n#endif  /* DUK_USE_ASSERTIONS */\n\n/* this variant is used when an assert would generate a compile warning by\n * being always true (e.g. >= 0 comparison for an unsigned value\n */\n#define DUK_ASSERT_DISABLE(x)  do { /* assertion disabled */ } while (0)\n\n/*\n *  Assertion helpers\n */\n\n#if defined(DUK_USE_ASSERTIONS) && defined(DUK_USE_REFERENCE_COUNTING)\n#define DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(h)  do { \\\n\t\tDUK_ASSERT((h) == NULL || DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) (h)) > 0); \\\n\t} while (0)\n#define DUK_ASSERT_REFCOUNT_NONZERO_TVAL(tv)  do { \\\n\t\tif ((tv) != NULL && DUK_TVAL_IS_HEAP_ALLOCATED((tv))) { \\\n\t\t\tDUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(DUK_TVAL_GET_HEAPHDR((tv))) > 0); \\\n\t\t} \\\n\t} while (0)\n#else\n#define DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(h)  /* no refcount check */\n#define DUK_ASSERT_REFCOUNT_NONZERO_TVAL(tv)    /* no refcount check */\n#endif\n\n#define DUK_ASSERT_TOP(ctx,n)  DUK_ASSERT((duk_idx_t) duk_get_top((ctx)) == (duk_idx_t) (n))\n\n#if defined(DUK_USE_ASSERTIONS) && defined(DUK_USE_PACKED_TVAL)\n#define DUK_ASSERT_DOUBLE_IS_NORMALIZED(dval)  do { \\\n\t\tduk_double_union duk__assert_tmp_du; \\\n\t\tduk__assert_tmp_du.d = (dval); \\\n\t\tDUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&duk__assert_tmp_du)); \\\n\t} while (0)\n#else\n#define DUK_ASSERT_DOUBLE_IS_NORMALIZED(dval)  /* nop */\n#endif\n\n#define DUK_ASSERT_VS_SPACE(thr) \\\n\tDUK_ASSERT(thr->valstack_top < thr->valstack_end)\n\n/*\n *  Helper to initialize a memory area (e.g. struct) with garbage when\n *  assertions enabled.\n */\n\n#if defined(DUK_USE_ASSERTIONS)\n#define DUK_ASSERT_SET_GARBAGE(ptr,size) do { \\\n\t\tDUK_MEMSET((void *) (ptr), 0x5a, size); \\\n\t} while (0)\n#else\n#define DUK_ASSERT_SET_GARBAGE(ptr,size) do {} while (0)\n#endif\n\n/*\n *  Helper for valstack space\n *\n *  Caller of DUK_ASSERT_VALSTACK_SPACE() estimates the number of free stack entries\n *  required for its own use, and any child calls which are not (a) Duktape API calls\n *  or (b) Duktape calls which involve extending the valstack (e.g. getter call).\n */\n\n#define DUK_VALSTACK_ASSERT_EXTRA  5  /* this is added to checks to allow for Duktape\n                                       * API calls in addition to function's own use\n                                       */\n#if defined(DUK_USE_ASSERTIONS)\n#define DUK_ASSERT_VALSTACK_SPACE(thr,n)   do { \\\n\t\tDUK_ASSERT((thr) != NULL); \\\n\t\tDUK_ASSERT((thr)->valstack_end - (thr)->valstack_top >= (n) + DUK_VALSTACK_ASSERT_EXTRA); \\\n\t} while (0)\n#else\n#define DUK_ASSERT_VALSTACK_SPACE(thr,n)   /* no valstack space check */\n#endif\n\n/*\n *  Prototypes\n */\n\n#if defined(DUK_USE_VERBOSE_ERRORS)\nDUK_NORETURN(DUK_INTERNAL_DECL void duk_err_handle_error(duk_hthread *thr, const char *filename, duk_uint_t line_and_code, const char *msg));\nDUK_NORETURN(DUK_INTERNAL_DECL void duk_err_handle_error_fmt(duk_hthread *thr, const char *filename, duk_uint_t line_and_code, const char *fmt, ...));\n#else  /* DUK_USE_VERBOSE_ERRORS */\nDUK_NORETURN(DUK_INTERNAL_DECL void duk_err_handle_error(duk_hthread *thr, duk_errcode_t code));\n#endif  /* DUK_USE_VERBOSE_ERRORS */\n\n#if defined(DUK_USE_VERBOSE_ERRORS)\nDUK_NORETURN(DUK_INTERNAL_DECL void duk_err_create_and_throw(duk_hthread *thr, duk_errcode_t code, const char *msg, const char *filename, duk_int_t line));\n#else\nDUK_NORETURN(DUK_INTERNAL_DECL void duk_err_create_and_throw(duk_hthread *thr, duk_errcode_t code));\n#endif\n\nDUK_NORETURN(DUK_INTERNAL_DECL void duk_error_throw_from_negative_rc(duk_hthread *thr, duk_ret_t rc));\n\n#define DUK_AUGMENT_FLAG_NOBLAME_FILELINE  (1U << 0)  /* if set, don't blame C file/line for .fileName and .lineNumber */\n#define DUK_AUGMENT_FLAG_SKIP_ONE          (1U << 1)  /* if set, skip topmost activation in traceback construction */\n\n#if defined(DUK_USE_AUGMENT_ERROR_CREATE)\nDUK_INTERNAL_DECL void duk_err_augment_error_create(duk_hthread *thr, duk_hthread *thr_callstack, const char *filename, duk_int_t line, duk_small_uint_t flags);\n#endif\n#if defined(DUK_USE_AUGMENT_ERROR_THROW)\nDUK_INTERNAL_DECL void duk_err_augment_error_throw(duk_hthread *thr);\n#endif\n\n#if defined(DUK_USE_VERBOSE_ERRORS)\n#if defined(DUK_USE_PARANOID_ERRORS)\nDUK_NORETURN(DUK_INTERNAL_DECL void duk_err_require_type_index(duk_hthread *thr, const char *filename, duk_int_t linenumber, duk_idx_t idx, const char *expect_name));\n#else\nDUK_NORETURN(DUK_INTERNAL_DECL void duk_err_require_type_index(duk_hthread *thr, const char *filename, duk_int_t linenumber, duk_idx_t idx, const char *expect_name));\n#endif\nDUK_NORETURN(DUK_INTERNAL_DECL void duk_err_error_internal(duk_hthread *thr, const char *filename, duk_int_t linenumber));\nDUK_NORETURN(DUK_INTERNAL_DECL void duk_err_error_alloc_failed(duk_hthread *thr, const char *filename, duk_int_t linenumber));\nDUK_NORETURN(DUK_INTERNAL_DECL void duk_err_error(duk_hthread *thr, const char *filename, duk_int_t linenumber, const char *message));\nDUK_NORETURN(DUK_INTERNAL_DECL void duk_err_range_index(duk_hthread *thr, const char *filename, duk_int_t linenumber, duk_idx_t idx));\nDUK_NORETURN(DUK_INTERNAL_DECL void duk_err_range_push_beyond(duk_hthread *thr, const char *filename, duk_int_t linenumber));\nDUK_NORETURN(DUK_INTERNAL_DECL void duk_err_range(duk_hthread *thr, const char *filename, duk_int_t linenumber, const char *message));\nDUK_NORETURN(DUK_INTERNAL_DECL void duk_err_type_invalid_args(duk_hthread *thr, const char *filename, duk_int_t linenumber));\nDUK_NORETURN(DUK_INTERNAL_DECL void duk_err_type_invalid_state(duk_hthread *thr, const char *filename, duk_int_t linenumber));\nDUK_NORETURN(DUK_INTERNAL_DECL void duk_err_type_invalid_trap_result(duk_hthread *thr, const char *filename, duk_int_t linenumber));\n#else  /* DUK_VERBOSE_ERRORS */\nDUK_NORETURN(DUK_INTERNAL_DECL void duk_err_error(duk_hthread *thr));\nDUK_NORETURN(DUK_INTERNAL_DECL void duk_err_range(duk_hthread *thr));\nDUK_NORETURN(DUK_INTERNAL_DECL void duk_err_eval(duk_hthread *thr));\nDUK_NORETURN(DUK_INTERNAL_DECL void duk_err_reference(duk_hthread *thr));\nDUK_NORETURN(DUK_INTERNAL_DECL void duk_err_syntax(duk_hthread *thr));\nDUK_NORETURN(DUK_INTERNAL_DECL void duk_err_type(duk_hthread *thr));\nDUK_NORETURN(DUK_INTERNAL_DECL void duk_err_uri(duk_hthread *thr));\n#endif /* DUK_VERBOSE_ERRORS */\n\nDUK_NORETURN(DUK_INTERNAL_DECL void duk_err_longjmp(duk_hthread *thr));\n\nDUK_NORETURN(DUK_INTERNAL_DECL void duk_default_fatal_handler(void *udata, const char *msg));\n\nDUK_INTERNAL_DECL void duk_err_setup_ljstate1(duk_hthread *thr, duk_small_uint_t lj_type, duk_tval *tv_val);\n#if defined(DUK_USE_DEBUGGER_SUPPORT)\nDUK_INTERNAL_DECL void duk_err_check_debugger_integration(duk_hthread *thr);\n#endif\n\nDUK_INTERNAL_DECL duk_hobject *duk_error_prototype_from_code(duk_hthread *thr, duk_errcode_t err_code);\n\n#endif  /* DUK_ERROR_H_INCLUDED */\n/* #include duk_unicode.h */\n#line 1 \"duk_unicode.h\"\n/*\n *  Unicode helpers\n */\n\n#if !defined(DUK_UNICODE_H_INCLUDED)\n#define DUK_UNICODE_H_INCLUDED\n\n/*\n *  UTF-8 / XUTF-8 / CESU-8 constants\n */\n\n#define DUK_UNICODE_MAX_XUTF8_LENGTH      7   /* up to 36 bit codepoints */\n#define DUK_UNICODE_MAX_XUTF8_BMP_LENGTH  3   /* all codepoints up to U+FFFF */\n#define DUK_UNICODE_MAX_CESU8_LENGTH      6   /* all codepoints up to U+10FFFF */\n#define DUK_UNICODE_MAX_CESU8_BMP_LENGTH  3   /* all codepoints up to U+FFFF */\n\n/*\n *  Useful Unicode codepoints\n *\n *  Integer constants must be signed to avoid unexpected coercions\n *  in comparisons.\n */\n\n#define DUK_UNICODE_CP_ZWNJ                   0x200cL  /* zero-width non-joiner */\n#define DUK_UNICODE_CP_ZWJ                    0x200dL  /* zero-width joiner */\n#define DUK_UNICODE_CP_REPLACEMENT_CHARACTER  0xfffdL  /* http://en.wikipedia.org/wiki/Replacement_character#Replacement_character */\n\n/*\n *  ASCII character constants\n *\n *  C character literals like 'x' have a platform specific value and do\n *  not match ASCII (UTF-8) values on e.g. EBCDIC platforms.  So, use\n *  these (admittedly awkward) constants instead.  These constants must\n *  also have signed values to avoid unexpected coercions in comparisons.\n *\n *  http://en.wikipedia.org/wiki/ASCII\n */\n\n#define DUK_ASC_NUL              0x00\n#define DUK_ASC_SOH              0x01\n#define DUK_ASC_STX              0x02\n#define DUK_ASC_ETX              0x03\n#define DUK_ASC_EOT              0x04\n#define DUK_ASC_ENQ              0x05\n#define DUK_ASC_ACK              0x06\n#define DUK_ASC_BEL              0x07\n#define DUK_ASC_BS               0x08\n#define DUK_ASC_HT               0x09\n#define DUK_ASC_LF               0x0a\n#define DUK_ASC_VT               0x0b\n#define DUK_ASC_FF               0x0c\n#define DUK_ASC_CR               0x0d\n#define DUK_ASC_SO               0x0e\n#define DUK_ASC_SI               0x0f\n#define DUK_ASC_DLE              0x10\n#define DUK_ASC_DC1              0x11\n#define DUK_ASC_DC2              0x12\n#define DUK_ASC_DC3              0x13\n#define DUK_ASC_DC4              0x14\n#define DUK_ASC_NAK              0x15\n#define DUK_ASC_SYN              0x16\n#define DUK_ASC_ETB              0x17\n#define DUK_ASC_CAN              0x18\n#define DUK_ASC_EM               0x19\n#define DUK_ASC_SUB              0x1a\n#define DUK_ASC_ESC              0x1b\n#define DUK_ASC_FS               0x1c\n#define DUK_ASC_GS               0x1d\n#define DUK_ASC_RS               0x1e\n#define DUK_ASC_US               0x1f\n#define DUK_ASC_SPACE            0x20\n#define DUK_ASC_EXCLAMATION      0x21\n#define DUK_ASC_DOUBLEQUOTE      0x22\n#define DUK_ASC_HASH             0x23\n#define DUK_ASC_DOLLAR           0x24\n#define DUK_ASC_PERCENT          0x25\n#define DUK_ASC_AMP              0x26\n#define DUK_ASC_SINGLEQUOTE      0x27\n#define DUK_ASC_LPAREN           0x28\n#define DUK_ASC_RPAREN           0x29\n#define DUK_ASC_STAR             0x2a\n#define DUK_ASC_PLUS             0x2b\n#define DUK_ASC_COMMA            0x2c\n#define DUK_ASC_MINUS            0x2d\n#define DUK_ASC_PERIOD           0x2e\n#define DUK_ASC_SLASH            0x2f\n#define DUK_ASC_0                0x30\n#define DUK_ASC_1                0x31\n#define DUK_ASC_2                0x32\n#define DUK_ASC_3                0x33\n#define DUK_ASC_4                0x34\n#define DUK_ASC_5                0x35\n#define DUK_ASC_6                0x36\n#define DUK_ASC_7                0x37\n#define DUK_ASC_8                0x38\n#define DUK_ASC_9                0x39\n#define DUK_ASC_COLON            0x3a\n#define DUK_ASC_SEMICOLON        0x3b\n#define DUK_ASC_LANGLE           0x3c\n#define DUK_ASC_EQUALS           0x3d\n#define DUK_ASC_RANGLE           0x3e\n#define DUK_ASC_QUESTION         0x3f\n#define DUK_ASC_ATSIGN           0x40\n#define DUK_ASC_UC_A             0x41\n#define DUK_ASC_UC_B             0x42\n#define DUK_ASC_UC_C             0x43\n#define DUK_ASC_UC_D             0x44\n#define DUK_ASC_UC_E             0x45\n#define DUK_ASC_UC_F             0x46\n#define DUK_ASC_UC_G             0x47\n#define DUK_ASC_UC_H             0x48\n#define DUK_ASC_UC_I             0x49\n#define DUK_ASC_UC_J             0x4a\n#define DUK_ASC_UC_K             0x4b\n#define DUK_ASC_UC_L             0x4c\n#define DUK_ASC_UC_M             0x4d\n#define DUK_ASC_UC_N             0x4e\n#define DUK_ASC_UC_O             0x4f\n#define DUK_ASC_UC_P             0x50\n#define DUK_ASC_UC_Q             0x51\n#define DUK_ASC_UC_R             0x52\n#define DUK_ASC_UC_S             0x53\n#define DUK_ASC_UC_T             0x54\n#define DUK_ASC_UC_U             0x55\n#define DUK_ASC_UC_V             0x56\n#define DUK_ASC_UC_W             0x57\n#define DUK_ASC_UC_X             0x58\n#define DUK_ASC_UC_Y             0x59\n#define DUK_ASC_UC_Z             0x5a\n#define DUK_ASC_LBRACKET         0x5b\n#define DUK_ASC_BACKSLASH        0x5c\n#define DUK_ASC_RBRACKET         0x5d\n#define DUK_ASC_CARET            0x5e\n#define DUK_ASC_UNDERSCORE       0x5f\n#define DUK_ASC_GRAVE            0x60\n#define DUK_ASC_LC_A             0x61\n#define DUK_ASC_LC_B             0x62\n#define DUK_ASC_LC_C             0x63\n#define DUK_ASC_LC_D             0x64\n#define DUK_ASC_LC_E             0x65\n#define DUK_ASC_LC_F             0x66\n#define DUK_ASC_LC_G             0x67\n#define DUK_ASC_LC_H             0x68\n#define DUK_ASC_LC_I             0x69\n#define DUK_ASC_LC_J             0x6a\n#define DUK_ASC_LC_K             0x6b\n#define DUK_ASC_LC_L             0x6c\n#define DUK_ASC_LC_M             0x6d\n#define DUK_ASC_LC_N             0x6e\n#define DUK_ASC_LC_O             0x6f\n#define DUK_ASC_LC_P             0x70\n#define DUK_ASC_LC_Q             0x71\n#define DUK_ASC_LC_R             0x72\n#define DUK_ASC_LC_S             0x73\n#define DUK_ASC_LC_T             0x74\n#define DUK_ASC_LC_U             0x75\n#define DUK_ASC_LC_V             0x76\n#define DUK_ASC_LC_W             0x77\n#define DUK_ASC_LC_X             0x78\n#define DUK_ASC_LC_Y             0x79\n#define DUK_ASC_LC_Z             0x7a\n#define DUK_ASC_LCURLY           0x7b\n#define DUK_ASC_PIPE             0x7c\n#define DUK_ASC_RCURLY           0x7d\n#define DUK_ASC_TILDE            0x7e\n#define DUK_ASC_DEL              0x7f\n\n/*\n *  Miscellaneous\n */\n\n/* Uppercase A is 0x41, lowercase a is 0x61; OR 0x20 to convert uppercase\n * to lowercase.\n */\n#define DUK_LOWERCASE_CHAR_ASCII(x)  ((x) | 0x20)\n\n/*\n *  Unicode tables\n */\n\n#if defined(DUK_USE_SOURCE_NONBMP)\n/*\n *  Automatically generated by extract_chars.py, do not edit!\n */\n\nextern const duk_uint8_t duk_unicode_ids_noa[1036];\n#else\n/*\n *  Automatically generated by extract_chars.py, do not edit!\n */\n\nextern const duk_uint8_t duk_unicode_ids_noabmp[625];\n#endif\n\n#if defined(DUK_USE_SOURCE_NONBMP)\n/*\n *  Automatically generated by extract_chars.py, do not edit!\n */\n\nextern const duk_uint8_t duk_unicode_ids_m_let_noa[42];\n#else\n/*\n *  Automatically generated by extract_chars.py, do not edit!\n */\n\nextern const duk_uint8_t duk_unicode_ids_m_let_noabmp[24];\n#endif\n\n#if defined(DUK_USE_SOURCE_NONBMP)\n/*\n *  Automatically generated by extract_chars.py, do not edit!\n */\n\nextern const duk_uint8_t duk_unicode_idp_m_ids_noa[530];\n#else\n/*\n *  Automatically generated by extract_chars.py, do not edit!\n */\n\nextern const duk_uint8_t duk_unicode_idp_m_ids_noabmp[357];\n#endif\n\n/*\n *  Automatically generated by extract_caseconv.py, do not edit!\n */\n\nextern const duk_uint8_t duk_unicode_caseconv_uc[1386];\nextern const duk_uint8_t duk_unicode_caseconv_lc[680];\n\n#if defined(DUK_USE_REGEXP_CANON_WORKAROUND)\n/*\n *  Automatically generated by extract_caseconv.py, do not edit!\n */\n\nextern const duk_uint16_t duk_unicode_re_canon_lookup[65536];\n#endif\n\n#if defined(DUK_USE_REGEXP_CANON_BITMAP)\n/*\n *  Automatically generated by extract_caseconv.py, do not edit!\n */\n\n#define DUK_CANON_BITMAP_BLKSIZE                                      32\n#define DUK_CANON_BITMAP_BLKSHIFT                                     5\n#define DUK_CANON_BITMAP_BLKMASK                                      31\nextern const duk_uint8_t duk_unicode_re_canon_bitmap[256];\n#endif\n\n/*\n *  Extern\n */\n\n/* duk_unicode_support.c */\n#if !defined(DUK_SINGLE_FILE)\nDUK_INTERNAL_DECL const duk_uint8_t duk_unicode_xutf8_markers[7];\nDUK_INTERNAL_DECL const duk_uint16_t duk_unicode_re_ranges_digit[2];\nDUK_INTERNAL_DECL const duk_uint16_t duk_unicode_re_ranges_white[22];\nDUK_INTERNAL_DECL const duk_uint16_t duk_unicode_re_ranges_wordchar[8];\nDUK_INTERNAL_DECL const duk_uint16_t duk_unicode_re_ranges_not_digit[4];\nDUK_INTERNAL_DECL const duk_uint16_t duk_unicode_re_ranges_not_white[24];\nDUK_INTERNAL_DECL const duk_uint16_t duk_unicode_re_ranges_not_wordchar[10];\nDUK_INTERNAL_DECL const duk_int8_t duk_is_idchar_tab[128];\n#endif  /* !DUK_SINGLE_FILE */\n\n/*\n *  Prototypes\n */\n\nDUK_INTERNAL_DECL duk_small_int_t duk_unicode_get_xutf8_length(duk_ucodepoint_t cp);\n#if defined(DUK_USE_ASSERTIONS)\nDUK_INTERNAL_DECL duk_small_int_t duk_unicode_get_cesu8_length(duk_ucodepoint_t cp);\n#endif\nDUK_INTERNAL_DECL duk_small_int_t duk_unicode_encode_xutf8(duk_ucodepoint_t cp, duk_uint8_t *out);\nDUK_INTERNAL_DECL duk_small_int_t duk_unicode_encode_cesu8(duk_ucodepoint_t cp, duk_uint8_t *out);\nDUK_INTERNAL_DECL duk_small_int_t duk_unicode_decode_xutf8(duk_hthread *thr, const duk_uint8_t **ptr, const duk_uint8_t *ptr_start, const duk_uint8_t *ptr_end, duk_ucodepoint_t *out_cp);\nDUK_INTERNAL_DECL duk_ucodepoint_t duk_unicode_decode_xutf8_checked(duk_hthread *thr, const duk_uint8_t **ptr, const duk_uint8_t *ptr_start, const duk_uint8_t *ptr_end);\nDUK_INTERNAL_DECL duk_size_t duk_unicode_unvalidated_utf8_length(const duk_uint8_t *data, duk_size_t blen);\nDUK_INTERNAL_DECL duk_small_int_t duk_unicode_is_whitespace(duk_codepoint_t cp);\nDUK_INTERNAL_DECL duk_small_int_t duk_unicode_is_line_terminator(duk_codepoint_t cp);\nDUK_INTERNAL_DECL duk_small_int_t duk_unicode_is_identifier_start(duk_codepoint_t cp);\nDUK_INTERNAL_DECL duk_small_int_t duk_unicode_is_identifier_part(duk_codepoint_t cp);\nDUK_INTERNAL_DECL duk_small_int_t duk_unicode_is_letter(duk_codepoint_t cp);\nDUK_INTERNAL_DECL void duk_unicode_case_convert_string(duk_hthread *thr, duk_bool_t uppercase);\n#if defined(DUK_USE_REGEXP_SUPPORT)\nDUK_INTERNAL_DECL duk_codepoint_t duk_unicode_re_canonicalize_char(duk_hthread *thr, duk_codepoint_t cp);\nDUK_INTERNAL_DECL duk_small_int_t duk_unicode_re_is_wordchar(duk_codepoint_t cp);\n#endif\n\n#endif  /* DUK_UNICODE_H_INCLUDED */\n/* #include duk_json.h */\n#line 1 \"duk_json.h\"\n/*\n *  Defines for JSON, especially duk_bi_json.c.\n */\n\n#if !defined(DUK_JSON_H_INCLUDED)\n#define DUK_JSON_H_INCLUDED\n\n/* Encoding/decoding flags */\n#define DUK_JSON_FLAG_ASCII_ONLY              (1U << 0)  /* escape any non-ASCII characters */\n#define DUK_JSON_FLAG_AVOID_KEY_QUOTES        (1U << 1)  /* avoid key quotes when key is an ASCII Identifier */\n#define DUK_JSON_FLAG_EXT_CUSTOM              (1U << 2)  /* extended types: custom encoding */\n#define DUK_JSON_FLAG_EXT_COMPATIBLE          (1U << 3)  /* extended types: compatible encoding */\n\n/* How much stack to require on entry to object/array encode */\n#define DUK_JSON_ENC_REQSTACK                 32\n\n/* How much stack to require on entry to object/array decode */\n#define DUK_JSON_DEC_REQSTACK                 32\n\n/* How large a loop detection stack to use */\n#define DUK_JSON_ENC_LOOPARRAY                64\n\n/* Encoding state.  Heap object references are all borrowed. */\ntypedef struct {\n\tduk_hthread *thr;\n\tduk_bufwriter_ctx bw;        /* output bufwriter */\n\tduk_hobject *h_replacer;     /* replacer function */\n\tduk_hstring *h_gap;          /* gap (if empty string, NULL) */\n\tduk_idx_t idx_proplist;      /* explicit PropertyList */\n\tduk_idx_t idx_loop;          /* valstack index of loop detection object */\n\tduk_small_uint_t flags;\n\tduk_small_uint_t flag_ascii_only;\n\tduk_small_uint_t flag_avoid_key_quotes;\n#if defined(DUK_USE_JX) || defined(DUK_USE_JC)\n\tduk_small_uint_t flag_ext_custom;\n\tduk_small_uint_t flag_ext_compatible;\n\tduk_small_uint_t flag_ext_custom_or_compatible;\n#endif\n\tduk_uint_t recursion_depth;\n\tduk_uint_t recursion_limit;\n\tduk_uint_t mask_for_undefined;      /* type bit mask: types which certainly produce 'undefined' */\n#if defined(DUK_USE_JX) || defined(DUK_USE_JC)\n\tduk_small_uint_t stridx_custom_undefined;\n\tduk_small_uint_t stridx_custom_nan;\n\tduk_small_uint_t stridx_custom_neginf;\n\tduk_small_uint_t stridx_custom_posinf;\n\tduk_small_uint_t stridx_custom_function;\n#endif\n\tduk_hobject *visiting[DUK_JSON_ENC_LOOPARRAY];  /* indexed by recursion_depth */\n} duk_json_enc_ctx;\n\ntypedef struct {\n\tduk_hthread *thr;\n\tconst duk_uint8_t *p;\n\tconst duk_uint8_t *p_start;\n\tconst duk_uint8_t *p_end;\n\tduk_idx_t idx_reviver;\n\tduk_small_uint_t flags;\n#if defined(DUK_USE_JX) || defined(DUK_USE_JC)\n\tduk_small_uint_t flag_ext_custom;\n\tduk_small_uint_t flag_ext_compatible;\n\tduk_small_uint_t flag_ext_custom_or_compatible;\n#endif\n\tduk_int_t recursion_depth;\n\tduk_int_t recursion_limit;\n} duk_json_dec_ctx;\n\n#endif  /* DUK_JSON_H_INCLUDED */\n/* #include duk_js.h */\n#line 1 \"duk_js.h\"\n/*\n *  Ecmascript execution, support primitives.\n */\n\n#if !defined(DUK_JS_H_INCLUDED)\n#define DUK_JS_H_INCLUDED\n\n/* Flags for call handling.  Lowest flags must match bytecode DUK_BC_CALL_FLAG_xxx 1:1. */\n#define DUK_CALL_FLAG_TAILCALL                 (1U << 0)  /* setup for a tail call */\n#define DUK_CALL_FLAG_CONSTRUCT                (1U << 1)  /* constructor call (i.e. called as 'new Foo()') */\n#define DUK_CALL_FLAG_CALLED_AS_EVAL           (1U << 2)  /* call was made using the identifier 'eval' */\n#define DUK_CALL_FLAG_ALLOW_ECMATOECMA         (1U << 3)  /* ecma-to-ecma call with executor reuse is possible */\n#define DUK_CALL_FLAG_DIRECT_EVAL              (1U << 4)  /* call is a direct eval call */\n#define DUK_CALL_FLAG_CONSTRUCT_PROXY          (1U << 5)  /* handled via 'construct' proxy trap, check return value invariant(s) */\n#define DUK_CALL_FLAG_DEFAULT_INSTANCE_UPDATED (1U << 6)  /* prototype of 'default instance' updated, temporary flag in call handling */\n\n/* Flags for duk_js_equals_helper(). */\n#define DUK_EQUALS_FLAG_SAMEVALUE            (1U << 0)  /* use SameValue instead of non-strict equality */\n#define DUK_EQUALS_FLAG_STRICT               (1U << 1)  /* use strict equality instead of non-strict equality */\n\n/* Flags for duk_js_compare_helper(). */\n#define DUK_COMPARE_FLAG_NEGATE              (1U << 0)  /* negate result */\n#define DUK_COMPARE_FLAG_EVAL_LEFT_FIRST     (1U << 1)  /* eval left argument first */\n\n/* conversions, coercions, comparison, etc */\nDUK_INTERNAL_DECL duk_bool_t duk_js_toboolean(duk_tval *tv);\nDUK_INTERNAL_DECL duk_double_t duk_js_tonumber(duk_hthread *thr, duk_tval *tv);\nDUK_INTERNAL_DECL duk_double_t duk_js_tointeger_number(duk_double_t x);\nDUK_INTERNAL_DECL duk_double_t duk_js_tointeger(duk_hthread *thr, duk_tval *tv);\nDUK_INTERNAL_DECL duk_uint32_t duk_js_touint32(duk_hthread *thr, duk_tval *tv);\nDUK_INTERNAL_DECL duk_int32_t duk_js_toint32(duk_hthread *thr, duk_tval *tv);\nDUK_INTERNAL_DECL duk_uint16_t duk_js_touint16(duk_hthread *thr, duk_tval *tv);\nDUK_INTERNAL_DECL duk_uarridx_t duk_js_to_arrayindex_string(const duk_uint8_t *str, duk_uint32_t blen);\n#if !defined(DUK_USE_HSTRING_ARRIDX)\nDUK_INTERNAL_DECL duk_uarridx_t duk_js_to_arrayindex_hstring_fast_known(duk_hstring *h);\nDUK_INTERNAL_DECL duk_uarridx_t duk_js_to_arrayindex_hstring_fast(duk_hstring *h);\n#endif\nDUK_INTERNAL_DECL duk_bool_t duk_js_equals_helper(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y, duk_small_uint_t flags);\nDUK_INTERNAL_DECL duk_small_int_t duk_js_data_compare(const duk_uint8_t *buf1, const duk_uint8_t *buf2, duk_size_t len1, duk_size_t len2);\nDUK_INTERNAL_DECL duk_small_int_t duk_js_string_compare(duk_hstring *h1, duk_hstring *h2);\n#if 0  /* unused */\nDUK_INTERNAL_DECL duk_small_int_t duk_js_buffer_compare(duk_heap *heap, duk_hbuffer *h1, duk_hbuffer *h2);\n#endif\nDUK_INTERNAL_DECL duk_bool_t duk_js_compare_helper(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y, duk_small_uint_t flags);\nDUK_INTERNAL_DECL duk_bool_t duk_js_instanceof(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y);\nDUK_INTERNAL_DECL duk_bool_t duk_js_in(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y);\nDUK_INTERNAL_DECL duk_small_uint_t duk_js_typeof_stridx(duk_tval *tv_x);\n\n/* arithmetic */\nDUK_INTERNAL_DECL double duk_js_arith_pow(double x, double y);\nDUK_INTERNAL_DECL double duk_js_arith_mod(double x, double y);\n\n#define duk_js_equals(thr,tv_x,tv_y) \\\n\tduk_js_equals_helper((thr), (tv_x), (tv_y), 0)\n#define duk_js_strict_equals(tv_x,tv_y) \\\n\tduk_js_equals_helper(NULL, (tv_x), (tv_y), DUK_EQUALS_FLAG_STRICT)\n#define duk_js_samevalue(tv_x,tv_y) \\\n\tduk_js_equals_helper(NULL, (tv_x), (tv_y), DUK_EQUALS_FLAG_SAMEVALUE)\n\n/* E5 Sections 11.8.1, 11.8.5; x < y */\n#define duk_js_lessthan(thr,tv_x,tv_y) \\\n\tduk_js_compare_helper((thr), (tv_x), (tv_Y), DUK_COMPARE_FLAG_EVAL_LEFT_FIRST)\n\n/* E5 Sections 11.8.2, 11.8.5; x > y  -->  y < x */\n#define duk_js_greaterthan(thr,tv_x,tv_y) \\\n\tduk_js_compare_helper((thr), (tv_y), (tv_x), 0)\n\n/* E5 Sections 11.8.3, 11.8.5; x <= y  -->  not (x > y)  -->  not (y < x) */\n#define duk_js_lessthanorequal(thr,tv_x,tv_y) \\\n\tduk_js_compare_helper((thr), (tv_y), (tv_x), DUK_COMPARE_FLAG_NEGATE)\n\n/* E5 Sections 11.8.4, 11.8.5; x >= y  -->  not (x < y) */\n#define duk_js_greaterthanorequal(thr,tv_x,tv_y) \\\n\tduk_js_compare_helper((thr), (tv_x), (tv_y), DUK_COMPARE_FLAG_EVAL_LEFT_FIRST | DUK_COMPARE_FLAG_NEGATE)\n\n/* identifiers and environment handling */\n#if 0  /*unused*/\nDUK_INTERNAL duk_bool_t duk_js_hasvar_envrec(duk_hthread *thr, duk_hobject *env, duk_hstring *name);\n#endif\nDUK_INTERNAL_DECL duk_bool_t duk_js_getvar_envrec(duk_hthread *thr, duk_hobject *env, duk_hstring *name, duk_bool_t throw_flag);\nDUK_INTERNAL_DECL duk_bool_t duk_js_getvar_activation(duk_hthread *thr, duk_activation *act, duk_hstring *name, duk_bool_t throw_flag);\nDUK_INTERNAL_DECL void duk_js_putvar_envrec(duk_hthread *thr, duk_hobject *env, duk_hstring *name, duk_tval *val, duk_bool_t strict);\nDUK_INTERNAL_DECL void duk_js_putvar_activation(duk_hthread *thr, duk_activation *act, duk_hstring *name, duk_tval *val, duk_bool_t strict);\n#if 0  /*unused*/\nDUK_INTERNAL_DECL duk_bool_t duk_js_delvar_envrec(duk_hthread *thr, duk_hobject *env, duk_hstring *name);\n#endif\nDUK_INTERNAL_DECL duk_bool_t duk_js_delvar_activation(duk_hthread *thr, duk_activation *act, duk_hstring *name);\nDUK_INTERNAL_DECL duk_bool_t duk_js_declvar_activation(duk_hthread *thr, duk_activation *act, duk_hstring *name, duk_tval *val, duk_small_uint_t prop_flags, duk_bool_t is_func_decl);\nDUK_INTERNAL_DECL void duk_js_init_activation_environment_records_delayed(duk_hthread *thr, duk_activation *act);\nDUK_INTERNAL_DECL void duk_js_close_environment_record(duk_hthread *thr, duk_hobject *env);\nDUK_INTERNAL_DECL duk_hobject *duk_create_activation_environment_record(duk_hthread *thr, duk_hobject *func, duk_size_t bottom_byteoff);\nDUK_INTERNAL_DECL void duk_js_push_closure(duk_hthread *thr,\n                                           duk_hcompfunc *fun_temp,\n                                           duk_hobject *outer_var_env,\n                                           duk_hobject *outer_lex_env,\n                                           duk_bool_t add_auto_proto);\n\n/* call handling */\nDUK_INTERNAL_DECL duk_int_t duk_handle_call_unprotected(duk_hthread *thr, duk_idx_t idx_func, duk_small_uint_t call_flags);\nDUK_INTERNAL_DECL duk_int_t duk_handle_call_unprotected_nargs(duk_hthread *thr, duk_idx_t nargs, duk_small_uint_t call_flags);\nDUK_INTERNAL_DECL duk_int_t duk_handle_safe_call(duk_hthread *thr, duk_safe_call_function func, void *udata, duk_idx_t num_stack_args, duk_idx_t num_stack_res);\nDUK_INTERNAL_DECL void duk_call_construct_postprocess(duk_hthread *thr, duk_small_uint_t proxy_invariant);\n#if defined(DUK_USE_VERBOSE_ERRORS)\nDUK_INTERNAL_DECL void duk_call_setup_propcall_error(duk_hthread *thr, duk_tval *tv_targ, duk_tval *tv_base, duk_tval *tv_key);\n#endif\n\n/* bytecode execution */\nDUK_INTERNAL_DECL void duk_js_execute_bytecode(duk_hthread *exec_thr);\n\n#endif  /* DUK_JS_H_INCLUDED */\n/* #include duk_numconv.h */\n#line 1 \"duk_numconv.h\"\n/*\n *  Number-to-string conversion.  The semantics of these is very tightly\n *  bound with the Ecmascript semantics required for call sites.\n */\n\n#if !defined(DUK_NUMCONV_H_INCLUDED)\n#define DUK_NUMCONV_H_INCLUDED\n\n/* Output a specified number of digits instead of using the shortest\n * form.  Used for toPrecision() and toFixed().\n */\n#define DUK_N2S_FLAG_FIXED_FORMAT         (1U << 0)\n\n/* Force exponential format.  Used for toExponential(). */\n#define DUK_N2S_FLAG_FORCE_EXP            (1U << 1)\n\n/* If number would need zero padding (for whole number part), use\n * exponential format instead.  E.g. if input number is 12300, 3\n * digits are generated (\"123\"), output \"1.23e+4\" instead of \"12300\".\n * Used for toPrecision().\n */\n#define DUK_N2S_FLAG_NO_ZERO_PAD          (1U << 2)\n\n/* Digit count indicates number of fractions (i.e. an absolute\n * digit index instead of a relative one).  Used together with\n * DUK_N2S_FLAG_FIXED_FORMAT for toFixed().\n */\n#define DUK_N2S_FLAG_FRACTION_DIGITS      (1U << 3)\n\n/*\n *  String-to-number conversion\n */\n\n/* Maximum exponent value when parsing numbers.  This is not strictly\n * compliant as there should be no upper limit, but as we parse the\n * exponent without a bigint, impose some limit.\n */\n#define DUK_S2N_MAX_EXPONENT              1000000000\n\n/* Trim white space (= allow leading and trailing whitespace) */\n#define DUK_S2N_FLAG_TRIM_WHITE           (1U << 0)\n\n/* Allow exponent */\n#define DUK_S2N_FLAG_ALLOW_EXP            (1U << 1)\n\n/* Allow trailing garbage (e.g. treat \"123foo\" as \"123) */\n#define DUK_S2N_FLAG_ALLOW_GARBAGE        (1U << 2)\n\n/* Allow leading plus sign */\n#define DUK_S2N_FLAG_ALLOW_PLUS           (1U << 3)\n\n/* Allow leading minus sign */\n#define DUK_S2N_FLAG_ALLOW_MINUS          (1U << 4)\n\n/* Allow 'Infinity' */\n#define DUK_S2N_FLAG_ALLOW_INF            (1U << 5)\n\n/* Allow fraction part */\n#define DUK_S2N_FLAG_ALLOW_FRAC           (1U << 6)\n\n/* Allow naked fraction (e.g. \".123\") */\n#define DUK_S2N_FLAG_ALLOW_NAKED_FRAC     (1U << 7)\n\n/* Allow empty fraction (e.g. \"123.\") */\n#define DUK_S2N_FLAG_ALLOW_EMPTY_FRAC     (1U << 8)\n\n/* Allow empty string to be interpreted as 0 */\n#define DUK_S2N_FLAG_ALLOW_EMPTY_AS_ZERO  (1U << 9)\n\n/* Allow leading zeroes (e.g. \"0123\" -> \"123\") */\n#define DUK_S2N_FLAG_ALLOW_LEADING_ZERO   (1U << 10)\n\n/* Allow automatic detection of hex base (\"0x\" or \"0X\" prefix),\n * overrides radix argument and forces integer mode.\n */\n#define DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT   (1U << 11)\n\n/* Allow automatic detection of legacy octal base (\"0n\"),\n * overrides radix argument and forces integer mode.\n */\n#define DUK_S2N_FLAG_ALLOW_AUTO_LEGACY_OCT_INT   (1U << 12)\n\n/* Allow automatic detection of ES2015 octal base (\"0o123\"),\n * overrides radix argument and forces integer mode.\n */\n#define DUK_S2N_FLAG_ALLOW_AUTO_OCT_INT   (1U << 13)\n\n/* Allow automatic detection of ES2015 binary base (\"0b10001\"),\n * overrides radix argument and forces integer mode.\n */\n#define DUK_S2N_FLAG_ALLOW_AUTO_BIN_INT   (1U << 14)\n\n/*\n *  Prototypes\n */\n\nDUK_INTERNAL_DECL void duk_numconv_stringify(duk_hthread *thr, duk_small_int_t radix, duk_small_int_t digits, duk_small_uint_t flags);\nDUK_INTERNAL_DECL void duk_numconv_parse(duk_hthread *thr, duk_small_int_t radix, duk_small_uint_t flags);\n\n#endif  /* DUK_NUMCONV_H_INCLUDED */\n/* #include duk_bi_protos.h */\n#line 1 \"duk_bi_protos.h\"\n/*\n *  Prototypes for built-in functions not automatically covered by the\n *  header declarations emitted by genbuiltins.py.\n */\n\n#if !defined(DUK_BUILTIN_PROTOS_H_INCLUDED)\n#define DUK_BUILTIN_PROTOS_H_INCLUDED\n\n/* Buffer size needed for ISO 8601 formatting.\n * Accurate value is 32 + 1 for NUL termination:\n *   >>> len('+123456-01-23T12:34:56.123+12:34')\n *   32\n * Include additional space to be safe.\n */\n#define  DUK_BI_DATE_ISO8601_BUFSIZE  40\n\n/* Helpers exposed for internal use */\nDUK_INTERNAL_DECL void duk_bi_date_timeval_to_parts(duk_double_t d, duk_int_t *parts, duk_double_t *dparts, duk_small_uint_t flags);\nDUK_INTERNAL_DECL duk_double_t duk_bi_date_get_timeval_from_dparts(duk_double_t *dparts, duk_small_uint_t flags);\nDUK_INTERNAL_DECL duk_bool_t duk_bi_date_is_leap_year(duk_int_t year);\nDUK_INTERNAL_DECL duk_bool_t duk_bi_date_timeval_in_valid_range(duk_double_t x);\nDUK_INTERNAL_DECL duk_bool_t duk_bi_date_year_in_valid_range(duk_double_t year);\nDUK_INTERNAL_DECL duk_bool_t duk_bi_date_timeval_in_leeway_range(duk_double_t x);\n/* Built-in providers */\n#if defined(DUK_USE_DATE_NOW_GETTIMEOFDAY)\nDUK_INTERNAL_DECL duk_double_t duk_bi_date_get_now_gettimeofday(void);\n#endif\n#if defined(DUK_USE_DATE_NOW_TIME)\nDUK_INTERNAL_DECL duk_double_t duk_bi_date_get_now_time(void);\n#endif\n#if defined(DUK_USE_DATE_NOW_WINDOWS)\nDUK_INTERNAL_DECL duk_double_t duk_bi_date_get_now_windows(void);\n#endif\n#if defined(DUK_USE_DATE_NOW_WINDOWS_SUBMS)\nDUK_INTERNAL_DECL duk_double_t duk_bi_date_get_now_windows_subms(void);\n#endif\n#if defined(DUK_USE_DATE_TZO_GMTIME_R) || defined(DUK_USE_DATE_TZO_GMTIME_S) || defined(DUK_USE_DATE_TZO_GMTIME)\nDUK_INTERNAL_DECL duk_int_t duk_bi_date_get_local_tzoffset_gmtime(duk_double_t d);\n#endif\n#if defined(DUK_USE_DATE_TZO_WINDOWS)\nDUK_INTERNAL_DECL duk_int_t duk_bi_date_get_local_tzoffset_windows(duk_double_t d);\n#endif\n#if defined(DUK_USE_DATE_TZO_WINDOWS_NO_DST)\nDUK_INTERNAL_DECL duk_int_t duk_bi_date_get_local_tzoffset_windows_no_dst(duk_double_t d);\n#endif\n#if defined(DUK_USE_DATE_PRS_STRPTIME)\nDUK_INTERNAL_DECL duk_bool_t duk_bi_date_parse_string_strptime(duk_hthread *thr, const char *str);\n#endif\n#if defined(DUK_USE_DATE_PRS_GETDATE)\nDUK_INTERNAL_DECL duk_bool_t duk_bi_date_parse_string_getdate(duk_hthread *thr, const char *str);\n#endif\n#if defined(DUK_USE_DATE_FMT_STRFTIME)\nDUK_INTERNAL_DECL duk_bool_t duk_bi_date_format_parts_strftime(duk_hthread *thr, duk_int_t *parts, duk_int_t tzoffset, duk_small_uint_t flags);\n#endif\n\n#if defined(DUK_USE_GET_MONOTONIC_TIME_CLOCK_GETTIME)\nDUK_INTERNAL_DECL duk_double_t duk_bi_date_get_monotonic_time_clock_gettime(void);\n#endif\n#if defined(DUK_USE_GET_MONOTONIC_TIME_WINDOWS_QPC)\nDUK_INTERNAL_DECL duk_double_t duk_bi_date_get_monotonic_time_windows_qpc(void);\n#endif\n\nDUK_INTERNAL_DECL\nvoid duk_bi_json_parse_helper(duk_hthread *thr,\n                              duk_idx_t idx_value,\n                              duk_idx_t idx_reviver,\n                              duk_small_uint_t flags);\nDUK_INTERNAL_DECL\nvoid duk_bi_json_stringify_helper(duk_hthread *thr,\n                                  duk_idx_t idx_value,\n                                  duk_idx_t idx_replacer,\n                                  duk_idx_t idx_space,\n                                  duk_small_uint_t flags);\n\nDUK_INTERNAL_DECL duk_ret_t duk_textdecoder_decode_utf8_nodejs(duk_hthread *thr);\n\n#if defined(DUK_USE_ES6_PROXY)\nDUK_INTERNAL_DECL void duk_proxy_ownkeys_postprocess(duk_hthread *thr, duk_hobject *h_proxy_target, duk_uint_t flags);\n#endif\n\n#endif  /* DUK_BUILTIN_PROTOS_H_INCLUDED */\n/* #include duk_selftest.h */\n#line 1 \"duk_selftest.h\"\n/*\n *  Selftest code\n */\n\n#if !defined(DUK_SELFTEST_H_INCLUDED)\n#define DUK_SELFTEST_H_INCLUDED\n\n#if defined(DUK_USE_SELF_TESTS)\nDUK_INTERNAL_DECL duk_uint_t duk_selftest_run_tests(duk_alloc_function alloc_func,\n                                                    duk_realloc_function realloc_func,\n                                                    duk_free_function free_func,\n                                                    void *udata);\n#endif\n\n#endif  /* DUK_SELFTEST_H_INCLUDED */\n#line 82 \"duk_internal.h\"\n\n#endif  /* DUK_INTERNAL_H_INCLUDED */\n#line 10 \"duk_replacements.c\"\n\n#if defined(DUK_USE_COMPUTED_NAN)\nDUK_INTERNAL double duk_computed_nan;\n#endif\n\n#if defined(DUK_USE_COMPUTED_INFINITY)\nDUK_INTERNAL double duk_computed_infinity;\n#endif\n\n#if defined(DUK_USE_REPL_FPCLASSIFY)\nDUK_INTERNAL int duk_repl_fpclassify(double x) {\n\tduk_double_union u;\n\tduk_uint_fast16_t expt;\n\tduk_small_int_t mzero;\n\n\tu.d = x;\n\texpt = (duk_uint_fast16_t) (u.us[DUK_DBL_IDX_US0] & 0x7ff0UL);\n\tif (expt > 0x0000UL && expt < 0x7ff0UL) {\n\t\t/* expt values [0x001,0x7fe] = normal */\n\t\treturn DUK_FP_NORMAL;\n\t}\n\n\tmzero = (u.ui[DUK_DBL_IDX_UI1] == 0 && (u.ui[DUK_DBL_IDX_UI0] & 0x000fffffUL) == 0);\n\tif (expt == 0x0000UL) {\n\t\t/* expt 0x000 is zero/subnormal */\n\t\tif (mzero) {\n\t\t\treturn DUK_FP_ZERO;\n\t\t} else {\n\t\t\treturn DUK_FP_SUBNORMAL;\n\t\t}\n\t} else {\n\t\t/* expt 0xfff is infinite/nan */\n\t\tif (mzero) {\n\t\t\treturn DUK_FP_INFINITE;\n\t\t} else {\n\t\t\treturn DUK_FP_NAN;\n\t\t}\n\t}\n}\n#endif\n\n#if defined(DUK_USE_REPL_SIGNBIT)\nDUK_INTERNAL int duk_repl_signbit(double x) {\n\tduk_double_union u;\n\tu.d = x;\n\treturn (int) (u.uc[DUK_DBL_IDX_UC0] & 0x80UL);\n}\n#endif\n\n#if defined(DUK_USE_REPL_ISFINITE)\nDUK_INTERNAL int duk_repl_isfinite(double x) {\n\tint c = DUK_FPCLASSIFY(x);\n\tif (c == DUK_FP_NAN || c == DUK_FP_INFINITE) {\n\t\treturn 0;\n\t} else {\n\t\treturn 1;\n\t}\n}\n#endif\n\n#if defined(DUK_USE_REPL_ISNAN)\nDUK_INTERNAL int duk_repl_isnan(double x) {\n\tint c = DUK_FPCLASSIFY(x);\n\treturn (c == DUK_FP_NAN);\n}\n#endif\n\n#if defined(DUK_USE_REPL_ISINF)\nDUK_INTERNAL int duk_repl_isinf(double x) {\n\tint c = DUK_FPCLASSIFY(x);\n\treturn (c == DUK_FP_INFINITE);\n}\n#endif\n#line 1 \"duk_debug_macros.c\"\n/*\n *  Debugging macro calls.\n */\n\n/* #include duk_internal.h -> already included */\n\n#if defined(DUK_USE_DEBUG)\n\n/*\n *  Debugging enabled\n */\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <stdarg.h>\n\n#if !defined(DUK_USE_DEBUG_WRITE)\n#error debugging enabled (DUK_USE_DEBUG) but DUK_USE_DEBUG_WRITE not defined\n#endif\n\n#define DUK__DEBUG_BUFSIZE  DUK_USE_DEBUG_BUFSIZE\n\n#if defined(DUK_USE_VARIADIC_MACROS)\n\nDUK_INTERNAL void duk_debug_log(duk_int_t level, const char *file, duk_int_t line, const char *func, const char *fmt, ...) {\n\tva_list ap;\n\tlong arg_level;\n\tconst char *arg_file;\n\tlong arg_line;\n\tconst char *arg_func;\n\tconst char *arg_msg;\n\tchar buf[DUK__DEBUG_BUFSIZE];\n\n\tva_start(ap, fmt);\n\n\tDUK_MEMZERO((void *) buf, (size_t) DUK__DEBUG_BUFSIZE);\n\tduk_debug_vsnprintf(buf, DUK__DEBUG_BUFSIZE - 1, fmt, ap);\n\n\targ_level = (long) level;\n\targ_file = (const char *) file;\n\targ_line = (long) line;\n\targ_func = (const char *) func;\n\targ_msg = (const char *) buf;\n\tDUK_USE_DEBUG_WRITE(arg_level, arg_file, arg_line, arg_func, arg_msg);\n\n\tva_end(ap);\n}\n\n#else  /* DUK_USE_VARIADIC_MACROS */\n\nDUK_INTERNAL char duk_debug_file_stash[DUK_DEBUG_STASH_SIZE];\nDUK_INTERNAL duk_int_t duk_debug_line_stash;\nDUK_INTERNAL char duk_debug_func_stash[DUK_DEBUG_STASH_SIZE];\nDUK_INTERNAL duk_int_t duk_debug_level_stash;\n\nDUK_INTERNAL void duk_debug_log(const char *fmt, ...) {\n\tva_list ap;\n\tlong arg_level;\n\tconst char *arg_file;\n\tlong arg_line;\n\tconst char *arg_func;\n\tconst char *arg_msg;\n\tchar buf[DUK__DEBUG_BUFSIZE];\n\n\tva_start(ap, fmt);\n\n\tDUK_MEMZERO((void *) buf, (size_t) DUK__DEBUG_BUFSIZE);\n\tduk_debug_vsnprintf(buf, DUK__DEBUG_BUFSIZE - 1, fmt, ap);\n\n\targ_level = (long) duk_debug_level_stash;\n\targ_file = (const char *) duk_debug_file_stash;\n\targ_line = (long) duk_debug_line_stash;\n\targ_func = (const char *) duk_debug_func_stash;\n\targ_msg = (const char *) buf;\n\tDUK_USE_DEBUG_WRITE(arg_level, arg_file, arg_line, arg_func, arg_msg);\n\n\tva_end(ap);\n}\n\n#endif  /* DUK_USE_VARIADIC_MACROS */\n\n#else  /* DUK_USE_DEBUG */\n\n/*\n *  Debugging disabled\n */\n\n#endif  /* DUK_USE_DEBUG */\n\n/* automatic undefs */\n#undef DUK__DEBUG_BUFSIZE\n#line 1 \"duk_builtins.c\"\n/*\n *  Automatically generated by genbuiltins.py, do not edit!\n */\n\n/* #include duk_internal.h -> already included */\n\n#if defined(DUK_USE_ASSERTIONS)\n#define DUK__REFCINIT(refc) 0 /*h_assert_refcount*/, (refc) /*actual*/\n#else\n#define DUK__REFCINIT(refc) (refc) /*actual*/\n#endif\n\n#if defined(DUK_USE_ROM_STRINGS)\n#error ROM support not enabled, rerun configure.py with --rom-support\n#else  /* DUK_USE_ROM_STRINGS */\nDUK_INTERNAL const duk_uint8_t duk_strings_data[892] = {\n79,40,209,144,168,105,6,78,54,139,89,185,44,48,46,90,120,8,154,140,35,103,\n35,113,193,73,5,52,112,180,104,166,135,52,188,4,98,12,27,146,156,80,211,31,\n129,115,150,64,52,220,109,24,18,68,156,24,38,67,114,36,55,9,119,151,132,\n140,93,18,113,128,153,201,212,201,205,2,248,8,196,24,224,104,82,146,40,224,\n193,48,114,168,37,147,196,54,123,28,4,98,12,43,148,67,103,177,192,70,32,\n196,121,68,54,123,28,18,192,199,144,124,4,98,12,43,136,108,244,117,184,8,\n196,24,95,40,134,207,71,91,128,140,65,133,113,13,158,158,151,1,24,131,11,\n229,16,217,233,233,112,17,136,48,206,21,110,4,244,244,184,8,196,24,103,10,\n183,2,122,218,156,4,98,12,24,203,112,64,179,113,193,79,8,218,155,131,32,\n184,70,212,220,13,10,82,68,252,123,144,217,146,38,228,207,18,0,100,37,64,\n178,212,11,161,17,104,162,96,10,200,193,57,165,65,169,16,5,100,81,27,70,18,\n32,10,200,68,185,13,116,221,197,184,64,89,57,41,197,13,49,234,5,208,156,\n113,87,55,118,147,20,187,56,161,166,92,221,212,73,210,236,226,134,153,115,\n119,76,201,203,179,138,26,99,73,212,136,136,164,25,174,137,56,32,72,137,\n101,23,52,45,13,34,86,9,79,136,104,201,114,149,96,52,138,134,140,151,75,\n226,233,186,120,121,22,39,54,83,141,5,55,68,236,36,164,3,16,225,115,150,64,\n52,205,163,2,72,154,83,138,26,99,75,12,11,150,103,5,36,20,211,70,140,133,\n67,72,49,241,160,227,81,196,52,168,106,39,132,252,183,136,105,80,212,79,2,\n249,110,128,126,88,95,133,109,237,237,237,151,235,127,46,249,119,203,190,\n186,206,33,181,2,208,61,190,12,19,34,65,19,81,132,108,228,97,1,107,33,12,\n32,45,100,137,64,247,175,9,19,155,41,198,130,155,134,69,146,100,227,226,\n231,146,51,192,204,73,140,224,145,221,102,241,68,196,157,34,79,143,139,166,\n233,225,228,227,138,157,173,167,197,211,118,214,210,38,238,74,113,67,76,\n105,187,169,147,154,73,225,228,32,193,48,25,100,105,166,113,200,147,44,166,\n1,40,79,18,150,134,147,141,163,2,72,171,115,147,136,4,65,130,96,35,64,194,\n32,168,89,56,208,48,135,123,144,217,146,39,220,228,193,19,18,101,220,227,\n73,121,167,115,129,196,200,39,12,136,220,225,93,22,1,114,62,231,42,8,176,\n15,62,231,36,234,68,68,70,231,30,45,37,161,164,38,231,24,7,159,115,149,4,\n72,218,171,115,133,67,64,180,100,145,54,231,42,5,208,135,19,152,244,44,133,\n67,95,73,164,145,143,5,18,2,100,65,35,30,76,241,117,134,70,212,103,37,204,\n16,72,154,218,130,77,196,145,63,127,123,106,141,25,11,189,243,169,198,132,\n251,235,119,247,182,154,6,239,124,234,113,161,62,250,221,253,237,164,52,\n187,223,58,156,104,79,190,187,127,123,105,168,105,119,190,117,56,208,159,\n125,118,254,246,209,104,209,111,124,234,113,161,62,250,205,253,162,209,162,\n249,212,227,66,125,244,161,137,0,162,8,18,33,68,9,136,232,19,155,52,54,132,\n64,200,26,24,196,137,198,66,130,139,153,134,69,146,100,16,220,66,46,68,57,\n80,208,45,120,25,93,20,22,141,20,208,230,137,5,18,26,164,54,83,3,68,71,20,\n109,37,141,18,78,145,105,165,100,76,71,36,206,137,22,103,139,172,57,199,6,\n158,30,71,20,117,4,74,39,54,83,37,92,129,150,199,66,200,75,34,103,40,150,9,\n72,132,109,24,98,93,238,140,206,75,204,141,28,140,134,61,209,153,101,71,\n146,36,109,22,178,78,52,33,74,5,200,138,67,30,178,48,141,156,146,134,204,\n145,40,4,65,172,147,59,192,37,0,196,59,226,138,130,100,75,226,233,144,83,\n32,204,250,5,104,17,165,48,77,2,46,16,69,140,\n};\n#endif  /* DUK_USE_ROM_STRINGS */\n\n#if defined(DUK_USE_ROM_OBJECTS)\n#error ROM support not enabled, rerun configure.py with --rom-support\n#else  /* DUK_USE_ROM_OBJECTS */\n/* native functions: 176 */\nDUK_INTERNAL const duk_c_function duk_bi_native_functions[176] = {\n\tNULL,\n\tduk_bi_array_constructor,\n\tduk_bi_array_constructor_is_array,\n\tduk_bi_array_prototype_concat,\n\tduk_bi_array_prototype_indexof_shared,\n\tduk_bi_array_prototype_iter_shared,\n\tduk_bi_array_prototype_join_shared,\n\tduk_bi_array_prototype_pop,\n\tduk_bi_array_prototype_push,\n\tduk_bi_array_prototype_reduce_shared,\n\tduk_bi_array_prototype_reverse,\n\tduk_bi_array_prototype_shift,\n\tduk_bi_array_prototype_slice,\n\tduk_bi_array_prototype_sort,\n\tduk_bi_array_prototype_splice,\n\tduk_bi_array_prototype_to_string,\n\tduk_bi_array_prototype_unshift,\n\tduk_bi_arraybuffer_constructor,\n\tduk_bi_arraybuffer_isview,\n\tduk_bi_boolean_constructor,\n\tduk_bi_boolean_prototype_tostring_shared,\n\tduk_bi_buffer_compare_shared,\n\tduk_bi_buffer_readfield,\n\tduk_bi_buffer_slice_shared,\n\tduk_bi_buffer_writefield,\n\tduk_bi_dataview_constructor,\n\tduk_bi_date_constructor,\n\tduk_bi_date_constructor_now,\n\tduk_bi_date_constructor_parse,\n\tduk_bi_date_constructor_utc,\n\tduk_bi_date_prototype_get_shared,\n\tduk_bi_date_prototype_get_timezone_offset,\n\tduk_bi_date_prototype_set_shared,\n\tduk_bi_date_prototype_set_time,\n\tduk_bi_date_prototype_to_json,\n\tduk_bi_date_prototype_tostring_shared,\n\tduk_bi_date_prototype_value_of,\n\tduk_bi_duktape_object_act,\n\tduk_bi_duktape_object_compact,\n\tduk_bi_duktape_object_dec,\n\tduk_bi_duktape_object_enc,\n\tduk_bi_duktape_object_fin,\n\tduk_bi_duktape_object_gc,\n\tduk_bi_duktape_object_info,\n\tduk_bi_error_constructor_shared,\n\tduk_bi_error_prototype_filename_getter,\n\tduk_bi_error_prototype_filename_setter,\n\tduk_bi_error_prototype_linenumber_getter,\n\tduk_bi_error_prototype_linenumber_setter,\n\tduk_bi_error_prototype_stack_getter,\n\tduk_bi_error_prototype_stack_setter,\n\tduk_bi_error_prototype_to_string,\n\tduk_bi_function_constructor,\n\tduk_bi_function_prototype,\n\tduk_bi_function_prototype_apply,\n\tduk_bi_function_prototype_bind,\n\tduk_bi_function_prototype_call,\n\tduk_bi_function_prototype_to_string,\n\tduk_bi_global_object_decode_uri,\n\tduk_bi_global_object_decode_uri_component,\n\tduk_bi_global_object_encode_uri,\n\tduk_bi_global_object_encode_uri_component,\n\tduk_bi_global_object_escape,\n\tduk_bi_global_object_eval,\n\tduk_bi_global_object_is_finite,\n\tduk_bi_global_object_is_nan,\n\tduk_bi_global_object_parse_float,\n\tduk_bi_global_object_parse_int,\n\tduk_bi_global_object_unescape,\n\tduk_bi_json_object_parse,\n\tduk_bi_json_object_stringify,\n\tduk_bi_math_object_clz32,\n\tduk_bi_math_object_hypot,\n\tduk_bi_math_object_imul,\n\tduk_bi_math_object_max,\n\tduk_bi_math_object_min,\n\tduk_bi_math_object_onearg_shared,\n\tduk_bi_math_object_random,\n\tduk_bi_math_object_sign,\n\tduk_bi_math_object_twoarg_shared,\n\tduk_bi_native_function_length,\n\tduk_bi_native_function_name,\n\tduk_bi_nodejs_buffer_byte_length,\n\tduk_bi_nodejs_buffer_concat,\n\tduk_bi_nodejs_buffer_constructor,\n\tduk_bi_nodejs_buffer_copy,\n\tduk_bi_nodejs_buffer_fill,\n\tduk_bi_nodejs_buffer_is_buffer,\n\tduk_bi_nodejs_buffer_is_encoding,\n\tduk_bi_nodejs_buffer_tojson,\n\tduk_bi_nodejs_buffer_tostring,\n\tduk_bi_nodejs_buffer_write,\n\tduk_bi_number_constructor,\n\tduk_bi_number_prototype_to_exponential,\n\tduk_bi_number_prototype_to_fixed,\n\tduk_bi_number_prototype_to_locale_string,\n\tduk_bi_number_prototype_to_precision,\n\tduk_bi_number_prototype_to_string,\n\tduk_bi_number_prototype_value_of,\n\tduk_bi_object_constructor,\n\tduk_bi_object_constructor_assign,\n\tduk_bi_object_constructor_create,\n\tduk_bi_object_constructor_define_properties,\n\tduk_bi_object_constructor_define_property,\n\tduk_bi_object_constructor_get_own_property_descriptor,\n\tduk_bi_object_constructor_is,\n\tduk_bi_object_constructor_is_extensible,\n\tduk_bi_object_constructor_is_sealed_frozen_shared,\n\tduk_bi_object_constructor_keys_shared,\n\tduk_bi_object_constructor_prevent_extensions,\n\tduk_bi_object_constructor_seal_freeze_shared,\n\tduk_bi_object_getprototype_shared,\n\tduk_bi_object_prototype_defineaccessor,\n\tduk_bi_object_prototype_has_own_property,\n\tduk_bi_object_prototype_is_prototype_of,\n\tduk_bi_object_prototype_lookupaccessor,\n\tduk_bi_object_prototype_property_is_enumerable,\n\tduk_bi_object_prototype_to_locale_string,\n\tduk_bi_object_prototype_to_string,\n\tduk_bi_object_prototype_value_of,\n\tduk_bi_object_setprototype_shared,\n\tduk_bi_performance_now,\n\tduk_bi_pointer_constructor,\n\tduk_bi_pointer_prototype_tostring_shared,\n\tduk_bi_proxy_constructor,\n\tduk_bi_reflect_apply,\n\tduk_bi_reflect_construct,\n\tduk_bi_reflect_object_delete_property,\n\tduk_bi_reflect_object_get,\n\tduk_bi_reflect_object_has,\n\tduk_bi_reflect_object_set,\n\tduk_bi_regexp_constructor,\n\tduk_bi_regexp_prototype_exec,\n\tduk_bi_regexp_prototype_flags,\n\tduk_bi_regexp_prototype_shared_getter,\n\tduk_bi_regexp_prototype_test,\n\tduk_bi_regexp_prototype_tostring,\n\tduk_bi_string_constructor,\n\tduk_bi_string_constructor_from_char_code,\n\tduk_bi_string_constructor_from_code_point,\n\tduk_bi_string_prototype_caseconv_shared,\n\tduk_bi_string_prototype_char_at,\n\tduk_bi_string_prototype_char_code_at,\n\tduk_bi_string_prototype_concat,\n\tduk_bi_string_prototype_includes,\n\tduk_bi_string_prototype_indexof_shared,\n\tduk_bi_string_prototype_locale_compare,\n\tduk_bi_string_prototype_match,\n\tduk_bi_string_prototype_repeat,\n\tduk_bi_string_prototype_replace,\n\tduk_bi_string_prototype_search,\n\tduk_bi_string_prototype_slice,\n\tduk_bi_string_prototype_split,\n\tduk_bi_string_prototype_startswith_endswith,\n\tduk_bi_string_prototype_substr,\n\tduk_bi_string_prototype_substring,\n\tduk_bi_string_prototype_to_string,\n\tduk_bi_string_prototype_trim,\n\tduk_bi_textdecoder_constructor,\n\tduk_bi_textdecoder_prototype_decode,\n\tduk_bi_textdecoder_prototype_shared_getter,\n\tduk_bi_textencoder_constructor,\n\tduk_bi_textencoder_prototype_encode,\n\tduk_bi_textencoder_prototype_encoding_getter,\n\tduk_bi_thread_constructor,\n\tduk_bi_thread_current,\n\tduk_bi_thread_resume,\n\tduk_bi_thread_yield,\n\tduk_bi_type_error_thrower,\n\tduk_bi_typedarray_buffer_getter,\n\tduk_bi_typedarray_bytelength_getter,\n\tduk_bi_typedarray_byteoffset_getter,\n\tduk_bi_typedarray_constructor,\n\tduk_bi_typedarray_set,\n\tduk_bi_uint8array_allocplain,\n\tduk_bi_uint8array_plainof,\n};\n#if defined(DUK_USE_DOUBLE_LE)\nDUK_INTERNAL const duk_uint8_t duk_builtins_data[3972] = {\n144,148,105,223,160,68,52,228,62,12,104,200,165,132,52,167,194,138,105,242,\n252,57,28,211,57,18,64,52,238,62,44,138,111,171,241,164,19,87,125,30,33,\n167,16,145,159,8,211,136,9,225,42,5,240,145,139,163,163,8,211,136,10,228,\n64,211,19,132,140,93,29,56,70,156,64,119,34,66,146,36,104,137,194,70,46,\n142,172,35,78,32,47,146,195,102,11,240,145,139,163,175,8,211,136,9,228,240,\n242,112,145,139,163,179,8,211,136,8,237,34,130,118,49,116,118,225,26,48,0,\n1,80,29,201,158,46,183,39,135,147,132,140,93,16,132,76,66,33,8,66,16,132,\n33,8,66,34,33,154,112,0,1,73,247,35,79,91,237,198,174,192,47,31,23,95,17,\n13,51,19,35,93,68,216,209,128,0,10,192,174,79,15,32,248,8,196,24,8,107,192,\n0,5,98,118,27,94,0,0,43,19,227,94,0,0,43,20,46,215,128,0,10,197,28,198,188,\n0,0,86,41,100,53,224,0,2,177,79,85,175,0,0,21,138,154,45,120,0,0,172,85,\n217,107,192,0,5,98,182,243,86,193,106,52,127,66,249,50,94,124,35,68,225,\n146,49,13,31,170,23,201,146,243,224,200,39,12,145,136,67,134,11,49,0,0,0,0,\n0,0,3,225,255,51,0,0,0,0,0,0,3,193,255,47,18,1,172,19,120,71,10,25,196,136,\n113,162,156,136,199,42,57,204,144,115,132,240,149,2,248,72,197,209,58,2,\n185,16,52,196,225,35,23,68,233,14,228,72,82,68,141,17,56,72,197,209,58,130,\n249,44,54,96,191,9,24,186,39,88,79,39,135,147,132,140,93,19,176,35,180,138,\n9,216,197,209,59,82,79,31,40,242,1,248,58,42,96,121,14,232,94,62,46,190,15,\n38,31,145,33,86,65,76,242,150,143,69,48,242,179,79,45,56,243,51,207,53,64,\n243,116,79,57,72,243,180,207,61,80,243,245,79,65,88,244,34,249,50,94,124,\n35,68,225,146,39,163,23,201,146,243,224,200,39,12,145,61,40,183,146,37,116,\n88,6,136,158,244,241,174,230,202,80,135,130,50,39,16,217,231,208,20,240,70,\n68,225,86,224,79,60,64,84,75,141,7,27,157,32,66,37,194,161,168,153,51,132,\n9,25,4,225,147,180,138,50,196,18,25,4,225,147,180,138,5,215,49,238,105,27,\n60,185,2,72,209,56,100,237,34,140,193,4,136,209,56,100,237,34,129,117,204,\n123,154,70,207,50,64,98,72,64,121,51,68,8,163,73,33,1,228,208,16,0,65,112,\n152,56,196,159,31,23,77,211,195,201,199,23,150,73,169,234,34,24,49,39,199,\n89,188,124,92,242,70,120,224,201,33,69,15,155,163,196,64,153,137,62,58,205,\n227,226,231,146,51,199,26,6,18,92,130,64,192,148,144,102,240,23,129,133,18,\n2,100,224,160,56,100,42,26,78,62,46,121,35,60,112,216,32,50,21,13,39,31,23,\n60,145,154,9,46,18,1,36,64,47,148,64,98,196,132,201,57,68,132,95,18,84,141,\n159,9,121,145,178,67,155,46,73,2,17,46,72,128,89,7,199,32,66,37,194,197,\n217,35,120,228,131,17,46,18,243,35,100,128,172,156,98,2,40,152,151,32,130,\n166,36,248,235,55,143,139,158,72,207,28,150,24,23,46,92,130,80,72,151,21,0,\n100,213,103,229,245,8,186,190,144,24,78,136,24,94,152,3,142,9,113,214,111,\n31,23,60,145,158,57,164,13,68,184,248,186,110,158,30,78,56,188,226,10,62,\n46,121,35,60,113,18,225,27,70,18,32,10,201,208,32,134,214,208,200,84,52,\n156,49,39,50,71,107,107,152,129,13,173,161,144,168,105,57,34,78,100,142,\n214,215,49,16,134,214,210,220,229,81,252,49,39,50,71,107,107,158,65,13,173,\n165,185,202,163,249,34,78,100,142,214,215,60,146,12,16,28,128,62,175,42,6,\n143,36,136,16,64,90,242,135,192,129,67,71,147,62,65,5,215,231,214,6,215,62,\n180,8,49,1,3,162,92,4,98,12,41,14,67,40,106,229,1,132,130,8,24,78,104,129,\n54,62,96,224,144,13,238,124,32,2,62,146,60,51,224,120,146,164,140,137,20,0,\n178,58,11,56,192,5,146,208,34,71,64,36,157,25,200,32,52,158,180,8,146,87,\n129,232,217,29,5,156,179,224,116,52,100,191,28,87,62,130,214,9,79,136,104,\n201,126,56,174,127,0,31,255,225,73,82,71,16,13,1,36,230,18,1,164,14,87,71,\n132,0,143,0,210,131,96,31,0,211,6,42,23,50,70,1,167,13,18,14,130,36,67,232,\n46,36,29,4,78,69,6,60,226,31,192,7,255,252,24,192,163,11,23,51,130,56,35,\n193,56,100,243,31,6,150,46,103,4,225,147,143,114,27,63,57,241,200,169,194,\n133,42,166,175,240,6,23,240,0,97,28,17,224,39,233,32,80,142,8,240,78,25,56,\n9,250,136,22,39,12,156,123,144,217,240,19,245,18,6,19,154,32,79,214,124,14,\n134,140,151,227,139,237,52,11,88,37,62,33,163,37,248,226,251,77,32,213,184,\n64,89,56,39,49,224,137,61,196,5,96,38,35,251,200,15,18,61,96,17,62,40,6,\n145,1,17,31,228,64,89,45,2,39,205,0,178,122,209,63,162,2,101,64,202,113,67,\n77,247,64,92,221,197,186,196,143,4,9,19,208,1,25,187,139,112,128,178,113,\n110,177,35,193,2,68,244,0,46,110,229,30,242,71,130,4,137,232,4,35,55,113,\n110,16,22,78,81,239,36,120,32,72,158,128,64,147,138,25,249,0,52,72,242,2,\n127,2,5,74,96,140,229,203,34,103,250,154,4,17,163,151,44,137,159,234,105,4,\n33,162,93,6,73,123,13,1,165,64,202,113,251,33,6,64,14,71,78,20,101,213,207,\n4,194,207,2,12,162,0,158,176,23,218,168,23,66,64,255,255,255,255,255,255,\n239,127,19,214,33,187,85,2,232,72,0,32,0,0,0,0,0,0,25,136,0,0,0,0,0,0,31,\n15,228,122,247,73,19,69,73,180,134,149,13,68,241,0,0,0,0,0,0,3,193,252,143,\n90,67,2,104,169,54,144,210,161,168,158,32,0,0,0,0,0,0,120,127,142,73,78,20,\n0,0,0,0,0,0,0,0,8,58,189,233,24,77,217,24,93,240,1,230,238,21,23,32,247,68,\n13,155,184,75,189,205,35,102,128,47,114,64,185,187,143,137,4,137,33,205,\n222,17,6,96,48,87,130,50,37,114,1,246,147,21,143,224,54,186,213,128,114,90,\n112,164,0,0,0,0,0,0,124,63,226,117,119,128,25,55,112,96,153,57,41,197,13,\n53,224,65,147,119,38,134,19,146,156,80,211,94,5,194,94,6,37,55,113,110,16,\n22,78,12,19,39,37,56,161,166,188,14,74,110,226,220,32,44,156,154,24,78,74,\n113,67,77,120,32,97,175,4,28,61,224,133,172,186,70,22,248,1,204,73,242,104,\n97,47,128,44,196,159,11,69,175,152,32,35,100,33,142,49,39,218,76,69,237,22,\n190,96,128,141,144,136,32,196,159,24,230,204,246,66,40,179,18,125,164,196,\n206,185,179,61,144,140,28,196,159,6,9,146,200,71,20,98,79,180,152,135,208,\n76,150,66,64,99,18,124,24,49,100,36,137,49,39,218,76,67,232,49,100,37,8,49,\n39,195,186,145,149,144,150,44,196,159,105,49,31,174,164,101,100,38,10,49,\n39,198,33,180,153,37,100,38,141,49,39,218,76,76,234,27,73,146,86,66,112,\n163,18,124,145,4,230,142,86,66,120,211,18,125,164,197,46,144,78,104,229,\n100,40,15,49,39,198,33,107,68,136,39,52,114,178,20,73,24,147,237,38,38,117,\n11,90,36,65,57,163,149,144,164,68,196,159,38,134,19,46,105,56,226,150,68,\n157,160,3,200,147,228,208,194,92,32,124,137,62,49,11,90,36,65,57,163,149,\n178,166,74,68,159,105,49,51,168,90,209,34,9,205,28,173,149,65,82,36,249,34,\n9,205,28,173,175,170,54,68,159,105,49,75,164,19,154,57,91,95,88,84,137,62,\n49,13,164,201,43,111,235,141,145,39,218,76,76,234,27,73,146,86,223,216,17,\n34,79,135,117,35,43,115,236,139,145,39,218,76,71,235,169,25,91,159,104,60,\n137,62,12,19,37,178,182,42,68,159,105,49,15,160,153,45,149,193,18,36,248,\n199,54,103,182,190,232,185,18,125,164,196,206,185,179,61,181,247,133,200,\n147,225,104,181,243,4,4,109,191,190,58,68,159,105,49,23,180,90,249,130,2,\n54,223,224,67,152,147,230,8,8,217,12,16,121,18,124,193,1,27,101,131,131,56,\n7,38,193,198,72,0,0,0,0,0,0,0,0,198,231,240,134,39,63,136,151,95,63,136,49,\n89,252,66,98,243,248,133,96,132,185,5,224,32,36,201,41,248,200,213,249,0,\n131,64,7,39,192,218,148,124,137,74,216,231,198,227,141,182,124,78,40,217,\n231,197,227,4,213,227,192,159,72,10,5,21,218,138,120,74,129,124,36,98,232,\n228,74,81,62,160,20,10,107,181,21,114,32,105,137,194,70,46,142,68,165,19,\n235,1,64,170,187,81,119,34,66,146,36,104,137,194,70,46,142,68,165,19,236,1,\n64,174,187,81,95,37,134,204,23,225,35,23,71,34,82,137,246,128,160,89,93,\n168,167,147,195,201,194,70,46,142,68,165,19,238,1,64,182,187,81,71,105,20,\n19,177,139,163,145,41,68,16,7,6,15,82,70,72,115,96,0,0,0,0,0,93,105,160,91,\n60,149,195,200,194,8,134,149,216,114,1,128,83,192,144,8,194,195,16,12,168,\n110,20,120,12,141,22,16,120,12,100,22,12,120,28,78,99,192,41,224,136,115,\n36,14,100,197,213,245,193,48,189,112,40,2,237,96,175,131,117,2,178,112,145,\n139,163,145,131,114,70,46,142,218,27,182,72,197,209,219,56,26,53,161,166,\n28,1,204,178,10,14,38,78,44,141,52,207,31,0,0,21,64,129,100,180,8,148,145,\n92,203,176,160,226,100,226,200,211,76,241,240,0,1,84,2,131,137,147,142,41,\n100,73,199,192,0,5,88,6,13,10,82,70,62,0,0,42,66,88,115,18,124,67,103,177,\n69,49,130,12,73,242,136,108,246,40,165,177,6,36,248,134,207,71,90,138,99,\n68,152,147,229,16,217,232,235,81,75,130,12,73,241,13,158,158,149,20,199,9,\n49,39,202,33,179,211,210,162,151,69,24,147,225,86,224,79,79,74,138,94,20,\n98,79,133,91,129,61,109,74,41,124,60,137,62,33,179,216,166,216,193,18,36,\n249,68,54,123,20,218,216,137,18,124,67,103,163,173,77,177,162,100,73,242,\n136,108,244,117,169,181,193,18,36,248,134,207,79,74,155,99,132,200,147,229,\n16,217,233,233,83,107,162,164,73,240,171,112,39,167,165,77,175,10,145,39,\n194,173,192,158,182,165,54,191,153,51,72,71,161,196,201,45,167,146,59,68,\n89,24,70,206,0,0,0,0,0,0,7,129,249,153,51,104,71,161,196,201,45,167,146,59,\n68,89,24,70,206,0,0,0,0,0,0,7,129,249,153,51,136,71,161,196,201,45,167,146,\n59,68,89,24,70,206,0,0,0,0,0,0,7,129,249,153,51,168,71,161,196,201,45,167,\n146,59,68,89,24,70,206,0,0,0,0,0,0,0,2,1,153,51,200,71,161,196,201,45,167,\n146,59,68,89,24,70,206,0,0,0,0,0,0,0,2,1,153,51,232,71,161,196,201,45,167,\n146,59,68,89,24,70,206,0,0,0,0,0,0,0,130,1,153,52,8,71,161,196,201,45,167,\n146,59,68,89,24,70,206,0,0,0,0,0,0,0,130,1,153,52,40,71,161,196,201,45,167,\n146,59,68,89,24,70,206,0,0,0,0,0,0,0,130,1,153,52,72,71,161,196,201,45,167,\n146,59,68,89,24,70,206,0,0,0,0,0,0,1,2,1,135,52,102,32,76,72,1,246,136,235,\n103,177,69,1,17,32,7,196,54,123,20,82,88,200,144,3,237,17,214,207,71,91,\n171,37,20,65,145,32,7,218,35,173,158,142,183,66,74,41,16,92,72,1,241,13,\n158,142,183,86,74,41,48,92,72,1,241,13,158,142,183,66,74,41,80,100,72,1,\n246,136,235,103,167,165,213,146,138,40,200,144,3,237,17,214,207,79,75,161,\n37,20,138,46,36,0,248,134,207,79,75,171,37,20,154,46,36,0,248,134,207,79,\n75,161,37,20,170,46,36,0,248,85,184,19,234,201,69,24,92,72,1,240,171,112,\n39,208,146,138,70,25,18,0,124,27,168,21,147,171,37,20,113,145,32,7,193,186,\n129,89,58,18,81,72,226,162,64,15,180,71,91,62,172,148,90,0,168,144,3,237,\n17,214,207,161,37,22,144,38,36,0,248,134,207,171,37,22,160,38,36,0,248,134,\n207,161,37,22,176,42,209,68,201,218,35,173,158,197,54,4,218,40,153,56,134,\n207,98,155,75,27,104,162,100,237,17,214,207,71,91,171,37,54,65,182,138,38,\n78,209,29,108,244,117,186,18,83,104,131,45,20,76,156,67,103,163,173,213,\n146,155,76,25,104,162,100,226,27,61,29,110,132,148,218,160,219,69,19,39,\n104,142,182,122,122,93,89,41,178,141,180,81,50,118,136,235,103,167,165,208,\n146,155,69,25,104,162,100,226,27,61,61,46,172,148,218,104,203,69,19,39,16,\n217,233,233,116,36,166,213,70,90,40,153,56,85,184,19,234,201,77,152,101,\n162,137,147,133,91,129,62,132,148,218,48,219,69,19,39,6,234,5,100,234,201,\n77,156,109,162,137,147,131,117,2,178,116,36,166,209,197,218,40,153,59,68,\n117,179,234,201,78,32,11,180,81,50,118,136,235,103,208,146,156,72,21,104,\n162,100,226,27,62,172,148,226,128,171,69,19,39,16,217,244,36,167,22,53,123,\n102,53,155,80,2,21,11,94,201,128,196,133,0,185,80,32,56,156,199,130,36,160,\n72,16,78,126,54,48,5,146,208,34,82,72,1,109,20,76,155,120,28,34,1,225,32,\n52,171,138,69,133,95,130,160,4,234,219,163,161,0,89,86,214,238,197,172,9,0,\n31,86,221,40,29,231,63,95,200,69,220,199,225,122,183,27,72,144,63,160,138,\n217,81,197,125,207,195,117,110,54,142,129,32,7,114,147,10,189,229,237,159,\n130,235,209,0,96,181,17,83,236,132,37,0,63,101,8,207,71,107,74,6,105,219,\n251,52,245,7,49,248,94,202,17,158,148,12,211,183,246,105,234,15,99,242,159,\n129,228,176,192,185,127,46,155,185,41,197,13,55,38,3,127,255,20,138,160,\n192,25,106,8,8,1,58,90,130,64,128,146,27,168,37,8,9,129,186,130,96,160,152,\n27,165,171,64,32,131,25,234,10,64,65,17,11,212,19,133,18,243,167,165,163,\n32,24,157,45,65,64,6,75,191,80,80,66,149,110,116,117,5,8,41,240,247,79,72,\n188,8,134,81,122,84,1,173,198,212,20,48,139,113,180,181,5,36,42,220,109,29,\n13,65,74,6,192,95,76,188,6,196,55,78,188,6,247,91,86,136,26,32,104,220,205,\n72,1,98,234,52,122,130,136,18,72,51,117,68,3,146,27,168,40,161,37,8,207,80,\n81,129,204,13,212,20,112,179,141,26,45,65,75,112,20,43,193,25,19,66,128,\n153,78,40,105,144,92,104,152,131,124,27,253,128,0,10,116,3,68,146,163,9,\n128,0,10,102,3,138,145,137,27,60,0,0,82,129,7,2,4,16,7,2,70,143,178,203,\n164,237,35,14,25,10,134,147,143,139,158,72,207,28,54,77,47,109,13,55,113,\n120,96,196,159,29,102,241,241,115,201,25,227,131,36,133,20,62,110,143,17,\n16,113,137,62,62,46,155,167,135,147,142,47,44,151,79,221,64,98,37,194,94,\n100,108,144,21,147,140,73,168,228,19,17,124,73,82,54,124,37,230,70,201,14,\n108,185,36,155,14,243,243,83,212,69,131,132,4,12,137,114,168,37,166,145,7,\n10,4,28,200,14,12,40,56,153,56,178,52,211,60,124,0,0,85,0,160,226,100,227,\n138,89,18,113,240,0,1,86,1,131,66,148,145,143,128,0,10,144,93,134,0,0,43,\n80,17,42,4,17,136,49,73,19,49,134,16,143,67,137,146,91,79,36,118,136,178,\n48,141,156,0,0,0,0,0,0,15,3,243,49,135,16,143,67,137,146,91,79,36,118,136,\n178,48,141,156,0,0,0,0,0,0,15,3,245,20,5,173,194,227,214,4,55,0,0,21,196,7,\n122,192,134,241,197,192,0,5,121,25,140,64,132,122,28,76,146,218,121,35,180,\n69,145,132,108,224,0,0,0,0,0,0,120,31,153,140,72,132,122,28,76,146,218,121,\n35,180,69,145,132,108,224,0,0,0,0,0,0,0,32,25,140,80,132,122,28,76,146,218,\n121,35,180,69,145,132,108,224,0,0,0,0,0,0,0,32,25,140,88,132,122,28,76,146,\n218,121,35,180,69,145,132,108,224,0,0,0,0,0,0,8,32,25,140,96,132,122,28,76,\n146,218,121,35,180,69,145,132,108,224,0,0,0,0,0,0,8,32,25,140,104,132,122,\n28,76,146,218,121,35,180,69,145,132,108,224,0,0,0,0,0,0,8,32,25,140,112,\n132,122,28,76,146,218,121,35,180,69,145,132,108,224,0,0,0,0,0,0,16,32,16,\n113,225,0,48,156,209,2,122,244,5,34,92,35,68,225,161,166,218,16,33,18,224,\n104,82,146,59,50,5,7,19,39,22,70,154,103,215,32,28,78,99,193,18,80,70,131,\n165,1,205,34,8,35,68,225,161,166,239,255,4,12,70,137,195,39,248,73,7,78,3,\n154,102,16,70,137,195,67,77,223,248,1,74,9,129,125,255,130,9,65,154,232,\n147,161,115,59,255,5,64,195,32,156,50,126,197,14,2,3,107,173,213,0,\n};\n#elif defined(DUK_USE_DOUBLE_BE)\nDUK_INTERNAL const duk_uint8_t duk_builtins_data[3972] = {\n144,148,105,223,160,68,52,228,62,12,104,200,165,132,52,167,194,138,105,242,\n252,57,28,211,57,18,64,52,238,62,44,138,111,171,241,164,19,87,125,30,33,\n167,16,145,159,8,211,136,9,225,42,5,240,145,139,163,163,8,211,136,10,228,\n64,211,19,132,140,93,29,56,70,156,64,119,34,66,146,36,104,137,194,70,46,\n142,172,35,78,32,47,146,195,102,11,240,145,139,163,175,8,211,136,9,228,240,\n242,112,145,139,163,179,8,211,136,8,237,34,130,118,49,116,118,225,26,48,0,\n1,80,29,201,158,46,183,39,135,147,132,140,93,16,132,76,66,33,8,66,16,132,\n33,8,66,34,33,154,112,0,1,73,247,35,79,91,237,198,174,192,47,31,23,95,17,\n13,51,19,35,93,68,216,209,128,0,10,192,174,79,15,32,248,8,196,24,8,107,192,\n0,5,98,118,27,94,0,0,43,19,227,94,0,0,43,20,46,215,128,0,10,197,28,198,188,\n0,0,86,41,100,53,224,0,2,177,79,85,175,0,0,21,138,154,45,120,0,0,172,85,\n217,107,192,0,5,98,182,243,86,193,106,52,127,66,249,50,94,124,35,68,225,\n146,49,13,31,170,23,201,146,243,224,200,39,12,145,136,67,134,11,49,1,255,\n224,0,0,0,0,0,3,51,1,255,192,0,0,0,0,0,3,47,18,1,172,19,120,71,10,25,196,\n136,113,162,156,136,199,42,57,204,144,115,132,240,149,2,248,72,197,209,58,\n2,185,16,52,196,225,35,23,68,233,14,228,72,82,68,141,17,56,72,197,209,58,\n130,249,44,54,96,191,9,24,186,39,88,79,39,135,147,132,140,93,19,176,35,180,\n138,9,216,197,209,59,82,79,31,40,242,1,248,58,42,96,121,14,232,94,62,46,\n190,15,38,31,145,33,86,65,76,242,150,143,69,48,242,179,79,45,56,243,51,207,\n53,64,243,116,79,57,72,243,180,207,61,80,243,245,79,65,88,244,34,249,50,94,\n124,35,68,225,146,39,163,23,201,146,243,224,200,39,12,145,61,40,183,146,37,\n116,88,6,136,158,244,241,174,230,202,80,135,130,50,39,16,217,231,208,20,\n240,70,68,225,86,224,79,60,64,84,75,141,7,27,157,32,66,37,194,161,168,153,\n51,132,9,25,4,225,147,180,138,50,196,18,25,4,225,147,180,138,5,215,49,238,\n105,27,60,185,2,72,209,56,100,237,34,140,193,4,136,209,56,100,237,34,129,\n117,204,123,154,70,207,50,64,98,72,64,121,51,68,8,163,73,33,1,228,208,16,0,\n65,112,152,56,196,159,31,23,77,211,195,201,199,23,150,73,169,234,34,24,49,\n39,199,89,188,124,92,242,70,120,224,201,33,69,15,155,163,196,64,153,137,62,\n58,205,227,226,231,146,51,199,26,6,18,92,130,64,192,148,144,102,240,23,129,\n133,18,2,100,224,160,56,100,42,26,78,62,46,121,35,60,112,216,32,50,21,13,\n39,31,23,60,145,154,9,46,18,1,36,64,47,148,64,98,196,132,201,57,68,132,95,\n18,84,141,159,9,121,145,178,67,155,46,73,2,17,46,72,128,89,7,199,32,66,37,\n194,197,217,35,120,228,131,17,46,18,243,35,100,128,172,156,98,2,40,152,151,\n32,130,166,36,248,235,55,143,139,158,72,207,28,150,24,23,46,92,130,80,72,\n151,21,0,100,213,103,229,245,8,186,190,144,24,78,136,24,94,152,3,142,9,113,\n214,111,31,23,60,145,158,57,164,13,68,184,248,186,110,158,30,78,56,188,226,\n10,62,46,121,35,60,113,18,225,27,70,18,32,10,201,208,32,134,214,208,200,84,\n52,156,49,39,50,71,107,107,152,129,13,173,161,144,168,105,57,34,78,100,142,\n214,215,49,16,134,214,210,220,229,81,252,49,39,50,71,107,107,158,65,13,173,\n165,185,202,163,249,34,78,100,142,214,215,60,146,12,16,28,128,62,175,42,6,\n143,36,136,16,64,90,242,135,192,129,67,71,147,62,65,5,215,231,214,6,215,62,\n180,8,49,1,3,162,92,4,98,12,41,14,67,40,106,229,1,132,130,8,24,78,104,129,\n54,62,96,224,144,13,238,124,32,2,62,146,60,51,224,120,146,164,140,137,20,0,\n178,58,11,56,192,5,146,208,34,71,64,36,157,25,200,32,52,158,180,8,146,87,\n129,232,217,29,5,156,179,224,116,52,100,191,28,87,62,130,214,9,79,136,104,\n201,126,56,174,127,0,31,255,225,73,82,71,16,13,1,36,230,18,1,164,14,87,71,\n132,0,143,0,210,131,96,31,0,211,6,42,23,50,70,1,167,13,18,14,130,36,67,232,\n46,36,29,4,78,69,6,60,226,31,192,7,255,252,24,192,163,11,23,51,130,56,35,\n193,56,100,243,31,6,150,46,103,4,225,147,143,114,27,63,57,241,200,169,194,\n133,42,166,175,240,6,23,240,0,97,28,17,224,39,233,32,80,142,8,240,78,25,56,\n9,250,136,22,39,12,156,123,144,217,240,19,245,18,6,19,154,32,79,214,124,14,\n134,140,151,227,139,237,52,11,88,37,62,33,163,37,248,226,251,77,32,213,184,\n64,89,56,39,49,224,137,61,196,5,96,38,35,251,200,15,18,61,96,17,62,40,6,\n145,1,17,31,228,64,89,45,2,39,205,0,178,122,209,63,162,2,101,64,202,113,67,\n77,247,64,92,221,197,186,196,143,4,9,19,208,1,25,187,139,112,128,178,113,\n110,177,35,193,2,68,244,0,46,110,229,30,242,71,130,4,137,232,4,35,55,113,\n110,16,22,78,81,239,36,120,32,72,158,128,64,147,138,25,249,0,52,72,242,2,\n127,2,5,74,96,140,229,203,34,103,250,154,4,17,163,151,44,137,159,234,105,4,\n33,162,93,6,73,123,13,1,165,64,202,113,251,33,6,64,14,71,78,20,101,213,207,\n4,194,207,2,12,162,0,158,176,23,218,168,23,66,64,127,239,255,255,255,255,\n255,255,19,214,33,187,85,2,232,72,0,0,0,0,0,0,0,0,57,136,15,255,0,0,0,0,0,\n0,4,122,247,73,19,69,73,180,134,149,13,68,241,1,255,192,0,0,0,0,0,0,143,90,\n67,2,104,169,54,144,210,161,168,158,32,127,248,0,0,0,0,0,0,14,73,78,20,0,0,\n0,0,0,0,0,0,8,58,189,233,24,77,217,24,93,240,1,230,238,21,23,32,247,68,13,\n155,184,75,189,205,35,102,128,47,114,64,185,187,143,137,4,137,33,205,222,\n17,6,96,48,87,130,50,37,114,1,246,147,21,143,224,54,186,213,128,114,90,112,\n164,63,252,0,0,0,0,0,0,98,117,119,128,25,55,112,96,153,57,41,197,13,53,224,\n65,147,119,38,134,19,146,156,80,211,94,5,194,94,6,37,55,113,110,16,22,78,\n12,19,39,37,56,161,166,188,14,74,110,226,220,32,44,156,154,24,78,74,113,67,\n77,120,32,97,175,4,28,61,224,133,172,186,70,22,248,1,204,73,242,104,97,47,\n128,44,196,159,11,69,175,152,32,35,100,33,142,49,39,218,76,69,237,22,190,\n96,128,141,144,136,32,196,159,24,230,204,246,66,40,179,18,125,164,196,206,\n185,179,61,144,140,28,196,159,6,9,146,200,71,20,98,79,180,152,135,208,76,\n150,66,64,99,18,124,24,49,100,36,137,49,39,218,76,67,232,49,100,37,8,49,39,\n195,186,145,149,144,150,44,196,159,105,49,31,174,164,101,100,38,10,49,39,\n198,33,180,153,37,100,38,141,49,39,218,76,76,234,27,73,146,86,66,112,163,\n18,124,145,4,230,142,86,66,120,211,18,125,164,197,46,144,78,104,229,100,40,\n15,49,39,198,33,107,68,136,39,52,114,178,20,73,24,147,237,38,38,117,11,90,\n36,65,57,163,149,144,164,68,196,159,38,134,19,46,105,56,226,150,68,157,160,\n3,200,147,228,208,194,92,32,124,137,62,49,11,90,36,65,57,163,149,178,166,\n74,68,159,105,49,51,168,90,209,34,9,205,28,173,149,65,82,36,249,34,9,205,\n28,173,175,170,54,68,159,105,49,75,164,19,154,57,91,95,88,84,137,62,49,13,\n164,201,43,111,235,141,145,39,218,76,76,234,27,73,146,86,223,216,17,34,79,\n135,117,35,43,115,236,139,145,39,218,76,71,235,169,25,91,159,104,60,137,62,\n12,19,37,178,182,42,68,159,105,49,15,160,153,45,149,193,18,36,248,199,54,\n103,182,190,232,185,18,125,164,196,206,185,179,61,181,247,133,200,147,225,\n104,181,243,4,4,109,191,190,58,68,159,105,49,23,180,90,249,130,2,54,223,\n224,67,152,147,230,8,8,217,12,16,121,18,124,193,1,27,101,131,131,56,7,38,\n193,198,72,0,0,0,0,0,0,0,0,198,231,240,134,39,63,136,151,95,63,136,49,89,\n252,66,98,243,248,133,96,132,185,5,224,32,36,201,41,248,200,213,249,0,131,\n64,7,39,192,218,148,124,137,74,216,231,198,227,141,182,124,78,40,217,231,\n197,227,4,213,227,192,159,72,10,5,21,218,138,120,74,129,124,36,98,232,228,\n74,81,62,160,20,10,107,181,21,114,32,105,137,194,70,46,142,68,165,19,235,1,\n64,170,187,81,119,34,66,146,36,104,137,194,70,46,142,68,165,19,236,1,64,\n174,187,81,95,37,134,204,23,225,35,23,71,34,82,137,246,128,160,89,93,168,\n167,147,195,201,194,70,46,142,68,165,19,238,1,64,182,187,81,71,105,20,19,\n177,139,163,145,41,68,16,7,6,15,82,70,72,115,96,32,105,221,0,0,0,0,0,91,60,\n149,195,200,194,8,134,149,216,114,1,128,83,192,144,8,194,195,16,12,168,110,\n20,120,12,141,22,16,120,12,100,22,12,120,28,78,99,192,41,224,136,115,36,14,\n100,197,213,245,193,48,189,112,40,2,237,96,175,131,117,2,178,112,145,139,\n163,145,131,114,70,46,142,218,27,182,72,197,209,219,56,26,53,161,166,28,1,\n204,178,10,14,38,78,44,141,52,207,31,0,0,21,64,129,100,180,8,148,145,92,\n203,176,160,226,100,226,200,211,76,241,240,0,1,84,2,131,137,147,142,41,100,\n73,199,192,0,5,88,6,13,10,82,70,62,0,0,42,66,88,115,18,124,67,103,177,69,\n49,130,12,73,242,136,108,246,40,165,177,6,36,248,134,207,71,90,138,99,68,\n152,147,229,16,217,232,235,81,75,130,12,73,241,13,158,158,149,20,199,9,49,\n39,202,33,179,211,210,162,151,69,24,147,225,86,224,79,79,74,138,94,20,98,\n79,133,91,129,61,109,74,41,124,60,137,62,33,179,216,166,216,193,18,36,249,\n68,54,123,20,218,216,137,18,124,67,103,163,173,77,177,162,100,73,242,136,\n108,244,117,169,181,193,18,36,248,134,207,79,74,155,99,132,200,147,229,16,\n217,233,233,83,107,162,164,73,240,171,112,39,167,165,77,175,10,145,39,194,\n173,192,158,182,165,54,191,153,51,72,71,161,196,201,45,167,146,59,68,89,24,\n70,206,1,255,128,0,0,0,0,0,1,153,51,104,71,161,196,201,45,167,146,59,68,89,\n24,70,206,1,255,128,0,0,0,0,0,1,153,51,136,71,161,196,201,45,167,146,59,68,\n89,24,70,206,1,255,128,0,0,0,0,0,1,153,51,168,71,161,196,201,45,167,146,59,\n68,89,24,70,206,2,0,0,0,0,0,0,0,1,153,51,200,71,161,196,201,45,167,146,59,\n68,89,24,70,206,2,0,0,0,0,0,0,0,1,153,51,232,71,161,196,201,45,167,146,59,\n68,89,24,70,206,2,0,128,0,0,0,0,0,1,153,52,8,71,161,196,201,45,167,146,59,\n68,89,24,70,206,2,0,128,0,0,0,0,0,1,153,52,40,71,161,196,201,45,167,146,59,\n68,89,24,70,206,2,0,128,0,0,0,0,0,1,153,52,72,71,161,196,201,45,167,146,59,\n68,89,24,70,206,2,1,0,0,0,0,0,0,1,135,52,102,32,76,72,1,246,136,235,103,\n177,69,1,17,32,7,196,54,123,20,82,88,200,144,3,237,17,214,207,71,91,171,37,\n20,65,145,32,7,218,35,173,158,142,183,66,74,41,16,92,72,1,241,13,158,142,\n183,86,74,41,48,92,72,1,241,13,158,142,183,66,74,41,80,100,72,1,246,136,\n235,103,167,165,213,146,138,40,200,144,3,237,17,214,207,79,75,161,37,20,\n138,46,36,0,248,134,207,79,75,171,37,20,154,46,36,0,248,134,207,79,75,161,\n37,20,170,46,36,0,248,85,184,19,234,201,69,24,92,72,1,240,171,112,39,208,\n146,138,70,25,18,0,124,27,168,21,147,171,37,20,113,145,32,7,193,186,129,89,\n58,18,81,72,226,162,64,15,180,71,91,62,172,148,90,0,168,144,3,237,17,214,\n207,161,37,22,144,38,36,0,248,134,207,171,37,22,160,38,36,0,248,134,207,\n161,37,22,176,42,209,68,201,218,35,173,158,197,54,4,218,40,153,56,134,207,\n98,155,75,27,104,162,100,237,17,214,207,71,91,171,37,54,65,182,138,38,78,\n209,29,108,244,117,186,18,83,104,131,45,20,76,156,67,103,163,173,213,146,\n155,76,25,104,162,100,226,27,61,29,110,132,148,218,160,219,69,19,39,104,\n142,182,122,122,93,89,41,178,141,180,81,50,118,136,235,103,167,165,208,146,\n155,69,25,104,162,100,226,27,61,61,46,172,148,218,104,203,69,19,39,16,217,\n233,233,116,36,166,213,70,90,40,153,56,85,184,19,234,201,77,152,101,162,\n137,147,133,91,129,62,132,148,218,48,219,69,19,39,6,234,5,100,234,201,77,\n156,109,162,137,147,131,117,2,178,116,36,166,209,197,218,40,153,59,68,117,\n179,234,201,78,32,11,180,81,50,118,136,235,103,208,146,156,72,21,104,162,\n100,226,27,62,172,148,226,128,171,69,19,39,16,217,244,36,167,22,53,123,102,\n53,155,80,2,21,11,94,201,128,196,133,0,185,80,32,56,156,199,130,36,160,72,\n16,78,126,54,48,5,146,208,34,82,72,1,109,20,76,155,120,28,34,1,225,32,32,2,\n223,133,69,138,43,180,132,234,219,163,161,1,0,9,174,198,238,213,84,88,31,\n86,221,40,7,252,197,200,95,223,71,61,225,122,183,27,72,144,15,253,197,81,\n217,74,224,191,131,117,110,54,142,129,32,31,237,229,189,138,147,114,135,2,\n235,209,1,0,36,135,237,81,16,180,96,63,101,8,207,71,107,74,1,255,53,4,243,\n51,249,222,104,94,202,17,158,148,3,255,106,9,230,103,243,188,210,159,129,\n228,176,192,185,127,46,155,185,41,197,13,55,38,3,127,255,20,138,160,192,25,\n106,8,8,1,58,90,130,64,128,146,27,168,37,8,9,129,186,130,96,160,152,27,165,\n171,64,32,131,25,234,10,64,65,17,11,212,19,133,18,243,167,165,163,32,24,\n157,45,65,64,6,75,191,80,80,66,149,110,116,117,5,8,41,240,247,79,72,188,8,\n134,81,122,84,1,173,198,212,20,48,139,113,180,181,5,36,42,220,109,29,13,65,\n74,6,192,95,76,188,6,196,55,78,188,6,247,91,86,136,26,32,104,220,205,72,1,\n98,234,52,122,130,136,18,72,51,117,68,3,146,27,168,40,161,37,8,207,80,81,\n129,204,13,212,20,112,179,141,26,45,65,75,112,20,43,193,25,19,66,128,153,\n78,40,105,144,92,104,152,131,124,27,253,128,0,10,116,3,68,146,163,9,128,0,\n10,102,3,138,145,137,27,60,0,0,82,129,7,2,4,16,7,2,70,143,178,203,164,237,\n35,14,25,10,134,147,143,139,158,72,207,28,54,77,47,109,13,55,113,120,96,\n196,159,29,102,241,241,115,201,25,227,131,36,133,20,62,110,143,17,16,113,\n137,62,62,46,155,167,135,147,142,47,44,151,79,221,64,98,37,194,94,100,108,\n144,21,147,140,73,168,228,19,17,124,73,82,54,124,37,230,70,201,14,108,185,\n36,155,14,243,243,83,212,69,131,132,4,12,137,114,168,37,166,145,7,10,4,28,\n200,14,12,40,56,153,56,178,52,211,60,124,0,0,85,0,160,226,100,227,138,89,\n18,113,240,0,1,86,1,131,66,148,145,143,128,0,10,144,93,134,0,0,43,80,17,42,\n4,17,136,49,73,19,49,134,16,143,67,137,146,91,79,36,118,136,178,48,141,156,\n3,255,0,0,0,0,0,0,3,49,135,16,143,67,137,146,91,79,36,118,136,178,48,141,\n156,3,255,0,0,0,0,0,0,5,20,5,173,194,227,214,4,55,0,0,21,196,7,122,192,134,\n241,197,192,0,5,121,25,140,64,132,122,28,76,146,218,121,35,180,69,145,132,\n108,224,31,248,0,0,0,0,0,0,25,140,72,132,122,28,76,146,218,121,35,180,69,\n145,132,108,224,32,0,0,0,0,0,0,0,25,140,80,132,122,28,76,146,218,121,35,\n180,69,145,132,108,224,32,0,0,0,0,0,0,0,25,140,88,132,122,28,76,146,218,\n121,35,180,69,145,132,108,224,32,8,0,0,0,0,0,0,25,140,96,132,122,28,76,146,\n218,121,35,180,69,145,132,108,224,32,8,0,0,0,0,0,0,25,140,104,132,122,28,\n76,146,218,121,35,180,69,145,132,108,224,32,8,0,0,0,0,0,0,25,140,112,132,\n122,28,76,146,218,121,35,180,69,145,132,108,224,32,16,0,0,0,0,0,0,16,113,\n225,0,48,156,209,2,122,244,5,34,92,35,68,225,161,166,218,16,33,18,224,104,\n82,146,59,50,5,7,19,39,22,70,154,103,215,32,28,78,99,193,18,80,70,131,165,\n1,205,34,8,35,68,225,161,166,239,255,4,12,70,137,195,39,248,73,7,78,3,154,\n102,16,70,137,195,67,77,223,248,1,74,9,129,125,255,130,9,65,154,232,147,\n161,115,59,255,5,64,195,32,156,50,126,197,14,2,3,107,173,213,0,\n};\n#elif defined(DUK_USE_DOUBLE_ME)\nDUK_INTERNAL const duk_uint8_t duk_builtins_data[3972] = {\n144,148,105,223,160,68,52,228,62,12,104,200,165,132,52,167,194,138,105,242,\n252,57,28,211,57,18,64,52,238,62,44,138,111,171,241,164,19,87,125,30,33,\n167,16,145,159,8,211,136,9,225,42,5,240,145,139,163,163,8,211,136,10,228,\n64,211,19,132,140,93,29,56,70,156,64,119,34,66,146,36,104,137,194,70,46,\n142,172,35,78,32,47,146,195,102,11,240,145,139,163,175,8,211,136,9,228,240,\n242,112,145,139,163,179,8,211,136,8,237,34,130,118,49,116,118,225,26,48,0,\n1,80,29,201,158,46,183,39,135,147,132,140,93,16,132,76,66,33,8,66,16,132,\n33,8,66,34,33,154,112,0,1,73,247,35,79,91,237,198,174,192,47,31,23,95,17,\n13,51,19,35,93,68,216,209,128,0,10,192,174,79,15,32,248,8,196,24,8,107,192,\n0,5,98,118,27,94,0,0,43,19,227,94,0,0,43,20,46,215,128,0,10,197,28,198,188,\n0,0,86,41,100,53,224,0,2,177,79,85,175,0,0,21,138,154,45,120,0,0,172,85,\n217,107,192,0,5,98,182,243,86,193,106,52,127,66,249,50,94,124,35,68,225,\n146,49,13,31,170,23,201,146,243,224,200,39,12,145,136,67,134,11,49,0,0,3,\n225,252,0,0,0,3,51,0,0,3,193,252,0,0,0,3,47,18,1,172,19,120,71,10,25,196,\n136,113,162,156,136,199,42,57,204,144,115,132,240,149,2,248,72,197,209,58,\n2,185,16,52,196,225,35,23,68,233,14,228,72,82,68,141,17,56,72,197,209,58,\n130,249,44,54,96,191,9,24,186,39,88,79,39,135,147,132,140,93,19,176,35,180,\n138,9,216,197,209,59,82,79,31,40,242,1,248,58,42,96,121,14,232,94,62,46,\n190,15,38,31,145,33,86,65,76,242,150,143,69,48,242,179,79,45,56,243,51,207,\n53,64,243,116,79,57,72,243,180,207,61,80,243,245,79,65,88,244,34,249,50,94,\n124,35,68,225,146,39,163,23,201,146,243,224,200,39,12,145,61,40,183,146,37,\n116,88,6,136,158,244,241,174,230,202,80,135,130,50,39,16,217,231,208,20,\n240,70,68,225,86,224,79,60,64,84,75,141,7,27,157,32,66,37,194,161,168,153,\n51,132,9,25,4,225,147,180,138,50,196,18,25,4,225,147,180,138,5,215,49,238,\n105,27,60,185,2,72,209,56,100,237,34,140,193,4,136,209,56,100,237,34,129,\n117,204,123,154,70,207,50,64,98,72,64,121,51,68,8,163,73,33,1,228,208,16,0,\n65,112,152,56,196,159,31,23,77,211,195,201,199,23,150,73,169,234,34,24,49,\n39,199,89,188,124,92,242,70,120,224,201,33,69,15,155,163,196,64,153,137,62,\n58,205,227,226,231,146,51,199,26,6,18,92,130,64,192,148,144,102,240,23,129,\n133,18,2,100,224,160,56,100,42,26,78,62,46,121,35,60,112,216,32,50,21,13,\n39,31,23,60,145,154,9,46,18,1,36,64,47,148,64,98,196,132,201,57,68,132,95,\n18,84,141,159,9,121,145,178,67,155,46,73,2,17,46,72,128,89,7,199,32,66,37,\n194,197,217,35,120,228,131,17,46,18,243,35,100,128,172,156,98,2,40,152,151,\n32,130,166,36,248,235,55,143,139,158,72,207,28,150,24,23,46,92,130,80,72,\n151,21,0,100,213,103,229,245,8,186,190,144,24,78,136,24,94,152,3,142,9,113,\n214,111,31,23,60,145,158,57,164,13,68,184,248,186,110,158,30,78,56,188,226,\n10,62,46,121,35,60,113,18,225,27,70,18,32,10,201,208,32,134,214,208,200,84,\n52,156,49,39,50,71,107,107,152,129,13,173,161,144,168,105,57,34,78,100,142,\n214,215,49,16,134,214,210,220,229,81,252,49,39,50,71,107,107,158,65,13,173,\n165,185,202,163,249,34,78,100,142,214,215,60,146,12,16,28,128,62,175,42,6,\n143,36,136,16,64,90,242,135,192,129,67,71,147,62,65,5,215,231,214,6,215,62,\n180,8,49,1,3,162,92,4,98,12,41,14,67,40,106,229,1,132,130,8,24,78,104,129,\n54,62,96,224,144,13,238,124,32,2,62,146,60,51,224,120,146,164,140,137,20,0,\n178,58,11,56,192,5,146,208,34,71,64,36,157,25,200,32,52,158,180,8,146,87,\n129,232,217,29,5,156,179,224,116,52,100,191,28,87,62,130,214,9,79,136,104,\n201,126,56,174,127,0,31,255,225,73,82,71,16,13,1,36,230,18,1,164,14,87,71,\n132,0,143,0,210,131,96,31,0,211,6,42,23,50,70,1,167,13,18,14,130,36,67,232,\n46,36,29,4,78,69,6,60,226,31,192,7,255,252,24,192,163,11,23,51,130,56,35,\n193,56,100,243,31,6,150,46,103,4,225,147,143,114,27,63,57,241,200,169,194,\n133,42,166,175,240,6,23,240,0,97,28,17,224,39,233,32,80,142,8,240,78,25,56,\n9,250,136,22,39,12,156,123,144,217,240,19,245,18,6,19,154,32,79,214,124,14,\n134,140,151,227,139,237,52,11,88,37,62,33,163,37,248,226,251,77,32,213,184,\n64,89,56,39,49,224,137,61,196,5,96,38,35,251,200,15,18,61,96,17,62,40,6,\n145,1,17,31,228,64,89,45,2,39,205,0,178,122,209,63,162,2,101,64,202,113,67,\n77,247,64,92,221,197,186,196,143,4,9,19,208,1,25,187,139,112,128,178,113,\n110,177,35,193,2,68,244,0,46,110,229,30,242,71,130,4,137,232,4,35,55,113,\n110,16,22,78,81,239,36,120,32,72,158,128,64,147,138,25,249,0,52,72,242,2,\n127,2,5,74,96,140,229,203,34,103,250,154,4,17,163,151,44,137,159,234,105,4,\n33,162,93,6,73,123,13,1,165,64,202,113,251,33,6,64,14,71,78,20,101,213,207,\n4,194,207,2,12,162,0,158,176,23,218,168,23,66,64,255,255,239,127,255,255,\n255,255,19,214,33,187,85,2,232,72,0,0,0,0,0,32,0,0,25,136,0,0,31,15,224,0,\n0,0,4,122,247,73,19,69,73,180,134,149,13,68,241,0,0,3,193,252,0,0,0,0,143,\n90,67,2,104,169,54,144,210,161,168,158,32,0,0,120,127,128,0,0,0,14,73,78,\n20,0,0,0,0,0,0,0,0,8,58,189,233,24,77,217,24,93,240,1,230,238,21,23,32,247,\n68,13,155,184,75,189,205,35,102,128,47,114,64,185,187,143,137,4,137,33,205,\n222,17,6,96,48,87,130,50,37,114,1,246,147,21,143,224,54,186,213,128,114,90,\n112,164,0,0,124,63,128,0,0,0,98,117,119,128,25,55,112,96,153,57,41,197,13,\n53,224,65,147,119,38,134,19,146,156,80,211,94,5,194,94,6,37,55,113,110,16,\n22,78,12,19,39,37,56,161,166,188,14,74,110,226,220,32,44,156,154,24,78,74,\n113,67,77,120,32,97,175,4,28,61,224,133,172,186,70,22,248,1,204,73,242,104,\n97,47,128,44,196,159,11,69,175,152,32,35,100,33,142,49,39,218,76,69,237,22,\n190,96,128,141,144,136,32,196,159,24,230,204,246,66,40,179,18,125,164,196,\n206,185,179,61,144,140,28,196,159,6,9,146,200,71,20,98,79,180,152,135,208,\n76,150,66,64,99,18,124,24,49,100,36,137,49,39,218,76,67,232,49,100,37,8,49,\n39,195,186,145,149,144,150,44,196,159,105,49,31,174,164,101,100,38,10,49,\n39,198,33,180,153,37,100,38,141,49,39,218,76,76,234,27,73,146,86,66,112,\n163,18,124,145,4,230,142,86,66,120,211,18,125,164,197,46,144,78,104,229,\n100,40,15,49,39,198,33,107,68,136,39,52,114,178,20,73,24,147,237,38,38,117,\n11,90,36,65,57,163,149,144,164,68,196,159,38,134,19,46,105,56,226,150,68,\n157,160,3,200,147,228,208,194,92,32,124,137,62,49,11,90,36,65,57,163,149,\n178,166,74,68,159,105,49,51,168,90,209,34,9,205,28,173,149,65,82,36,249,34,\n9,205,28,173,175,170,54,68,159,105,49,75,164,19,154,57,91,95,88,84,137,62,\n49,13,164,201,43,111,235,141,145,39,218,76,76,234,27,73,146,86,223,216,17,\n34,79,135,117,35,43,115,236,139,145,39,218,76,71,235,169,25,91,159,104,60,\n137,62,12,19,37,178,182,42,68,159,105,49,15,160,153,45,149,193,18,36,248,\n199,54,103,182,190,232,185,18,125,164,196,206,185,179,61,181,247,133,200,\n147,225,104,181,243,4,4,109,191,190,58,68,159,105,49,23,180,90,249,130,2,\n54,223,224,67,152,147,230,8,8,217,12,16,121,18,124,193,1,27,101,131,131,56,\n7,38,193,198,72,0,0,0,0,0,0,0,0,198,231,240,134,39,63,136,151,95,63,136,49,\n89,252,66,98,243,248,133,96,132,185,5,224,32,36,201,41,248,200,213,249,0,\n131,64,7,39,192,218,148,124,137,74,216,231,198,227,141,182,124,78,40,217,\n231,197,227,4,213,227,192,159,72,10,5,21,218,138,120,74,129,124,36,98,232,\n228,74,81,62,160,20,10,107,181,21,114,32,105,137,194,70,46,142,68,165,19,\n235,1,64,170,187,81,119,34,66,146,36,104,137,194,70,46,142,68,165,19,236,1,\n64,174,187,81,95,37,134,204,23,225,35,23,71,34,82,137,246,128,160,89,93,\n168,167,147,195,201,194,70,46,142,68,165,19,238,1,64,182,187,81,71,105,20,\n19,177,139,163,145,41,68,16,7,6,15,82,70,72,115,96,0,93,105,160,0,0,0,0,91,\n60,149,195,200,194,8,134,149,216,114,1,128,83,192,144,8,194,195,16,12,168,\n110,20,120,12,141,22,16,120,12,100,22,12,120,28,78,99,192,41,224,136,115,\n36,14,100,197,213,245,193,48,189,112,40,2,237,96,175,131,117,2,178,112,145,\n139,163,145,131,114,70,46,142,218,27,182,72,197,209,219,56,26,53,161,166,\n28,1,204,178,10,14,38,78,44,141,52,207,31,0,0,21,64,129,100,180,8,148,145,\n92,203,176,160,226,100,226,200,211,76,241,240,0,1,84,2,131,137,147,142,41,\n100,73,199,192,0,5,88,6,13,10,82,70,62,0,0,42,66,88,115,18,124,67,103,177,\n69,49,130,12,73,242,136,108,246,40,165,177,6,36,248,134,207,71,90,138,99,\n68,152,147,229,16,217,232,235,81,75,130,12,73,241,13,158,158,149,20,199,9,\n49,39,202,33,179,211,210,162,151,69,24,147,225,86,224,79,79,74,138,94,20,\n98,79,133,91,129,61,109,74,41,124,60,137,62,33,179,216,166,216,193,18,36,\n249,68,54,123,20,218,216,137,18,124,67,103,163,173,77,177,162,100,73,242,\n136,108,244,117,169,181,193,18,36,248,134,207,79,74,155,99,132,200,147,229,\n16,217,233,233,83,107,162,164,73,240,171,112,39,167,165,77,175,10,145,39,\n194,173,192,158,182,165,54,191,153,51,72,71,161,196,201,45,167,146,59,68,\n89,24,70,206,0,0,7,129,248,0,0,0,1,153,51,104,71,161,196,201,45,167,146,59,\n68,89,24,70,206,0,0,7,129,248,0,0,0,1,153,51,136,71,161,196,201,45,167,146,\n59,68,89,24,70,206,0,0,7,129,248,0,0,0,1,153,51,168,71,161,196,201,45,167,\n146,59,68,89,24,70,206,0,0,0,2,0,0,0,0,1,153,51,200,71,161,196,201,45,167,\n146,59,68,89,24,70,206,0,0,0,2,0,0,0,0,1,153,51,232,71,161,196,201,45,167,\n146,59,68,89,24,70,206,0,0,0,130,0,0,0,0,1,153,52,8,71,161,196,201,45,167,\n146,59,68,89,24,70,206,0,0,0,130,0,0,0,0,1,153,52,40,71,161,196,201,45,167,\n146,59,68,89,24,70,206,0,0,0,130,0,0,0,0,1,153,52,72,71,161,196,201,45,167,\n146,59,68,89,24,70,206,0,0,1,2,0,0,0,0,1,135,52,102,32,76,72,1,246,136,235,\n103,177,69,1,17,32,7,196,54,123,20,82,88,200,144,3,237,17,214,207,71,91,\n171,37,20,65,145,32,7,218,35,173,158,142,183,66,74,41,16,92,72,1,241,13,\n158,142,183,86,74,41,48,92,72,1,241,13,158,142,183,66,74,41,80,100,72,1,\n246,136,235,103,167,165,213,146,138,40,200,144,3,237,17,214,207,79,75,161,\n37,20,138,46,36,0,248,134,207,79,75,171,37,20,154,46,36,0,248,134,207,79,\n75,161,37,20,170,46,36,0,248,85,184,19,234,201,69,24,92,72,1,240,171,112,\n39,208,146,138,70,25,18,0,124,27,168,21,147,171,37,20,113,145,32,7,193,186,\n129,89,58,18,81,72,226,162,64,15,180,71,91,62,172,148,90,0,168,144,3,237,\n17,214,207,161,37,22,144,38,36,0,248,134,207,171,37,22,160,38,36,0,248,134,\n207,161,37,22,176,42,209,68,201,218,35,173,158,197,54,4,218,40,153,56,134,\n207,98,155,75,27,104,162,100,237,17,214,207,71,91,171,37,54,65,182,138,38,\n78,209,29,108,244,117,186,18,83,104,131,45,20,76,156,67,103,163,173,213,\n146,155,76,25,104,162,100,226,27,61,29,110,132,148,218,160,219,69,19,39,\n104,142,182,122,122,93,89,41,178,141,180,81,50,118,136,235,103,167,165,208,\n146,155,69,25,104,162,100,226,27,61,61,46,172,148,218,104,203,69,19,39,16,\n217,233,233,116,36,166,213,70,90,40,153,56,85,184,19,234,201,77,152,101,\n162,137,147,133,91,129,62,132,148,218,48,219,69,19,39,6,234,5,100,234,201,\n77,156,109,162,137,147,131,117,2,178,116,36,166,209,197,218,40,153,59,68,\n117,179,234,201,78,32,11,180,81,50,118,136,235,103,208,146,156,72,21,104,\n162,100,226,27,62,172,148,226,128,171,69,19,39,16,217,244,36,167,22,53,123,\n102,53,155,80,2,21,11,94,201,128,196,133,0,185,80,32,56,156,199,130,36,160,\n72,16,78,126,54,48,5,146,208,34,82,72,1,109,20,76,155,120,28,34,1,225,32,5,\n95,130,160,52,171,138,69,132,234,219,163,161,2,197,172,9,0,89,86,214,236,\n31,86,221,40,8,69,220,199,253,231,63,95,193,122,183,27,72,144,17,197,125,\n207,255,160,138,217,67,117,110,54,142,129,32,61,229,237,159,135,114,147,10,\n130,235,209,3,236,132,37,0,96,181,17,80,63,101,8,207,71,107,74,4,245,7,49,\n254,105,219,251,48,94,202,17,158,148,9,234,15,99,252,211,183,246,98,159,\n129,228,176,192,185,127,46,155,185,41,197,13,55,38,3,127,255,20,138,160,\n192,25,106,8,8,1,58,90,130,64,128,146,27,168,37,8,9,129,186,130,96,160,152,\n27,165,171,64,32,131,25,234,10,64,65,17,11,212,19,133,18,243,167,165,163,\n32,24,157,45,65,64,6,75,191,80,80,66,149,110,116,117,5,8,41,240,247,79,72,\n188,8,134,81,122,84,1,173,198,212,20,48,139,113,180,181,5,36,42,220,109,29,\n13,65,74,6,192,95,76,188,6,196,55,78,188,6,247,91,86,136,26,32,104,220,205,\n72,1,98,234,52,122,130,136,18,72,51,117,68,3,146,27,168,40,161,37,8,207,80,\n81,129,204,13,212,20,112,179,141,26,45,65,75,112,20,43,193,25,19,66,128,\n153,78,40,105,144,92,104,152,131,124,27,253,128,0,10,116,3,68,146,163,9,\n128,0,10,102,3,138,145,137,27,60,0,0,82,129,7,2,4,16,7,2,70,143,178,203,\n164,237,35,14,25,10,134,147,143,139,158,72,207,28,54,77,47,109,13,55,113,\n120,96,196,159,29,102,241,241,115,201,25,227,131,36,133,20,62,110,143,17,\n16,113,137,62,62,46,155,167,135,147,142,47,44,151,79,221,64,98,37,194,94,\n100,108,144,21,147,140,73,168,228,19,17,124,73,82,54,124,37,230,70,201,14,\n108,185,36,155,14,243,243,83,212,69,131,132,4,12,137,114,168,37,166,145,7,\n10,4,28,200,14,12,40,56,153,56,178,52,211,60,124,0,0,85,0,160,226,100,227,\n138,89,18,113,240,0,1,86,1,131,66,148,145,143,128,0,10,144,93,134,0,0,43,\n80,17,42,4,17,136,49,73,19,49,134,16,143,67,137,146,91,79,36,118,136,178,\n48,141,156,0,0,15,3,240,0,0,0,3,49,135,16,143,67,137,146,91,79,36,118,136,\n178,48,141,156,0,0,15,3,240,0,0,0,5,20,5,173,194,227,214,4,55,0,0,21,196,7,\n122,192,134,241,197,192,0,5,121,25,140,64,132,122,28,76,146,218,121,35,180,\n69,145,132,108,224,0,0,120,31,128,0,0,0,25,140,72,132,122,28,76,146,218,\n121,35,180,69,145,132,108,224,0,0,0,32,0,0,0,0,25,140,80,132,122,28,76,146,\n218,121,35,180,69,145,132,108,224,0,0,0,32,0,0,0,0,25,140,88,132,122,28,76,\n146,218,121,35,180,69,145,132,108,224,0,0,8,32,0,0,0,0,25,140,96,132,122,\n28,76,146,218,121,35,180,69,145,132,108,224,0,0,8,32,0,0,0,0,25,140,104,\n132,122,28,76,146,218,121,35,180,69,145,132,108,224,0,0,8,32,0,0,0,0,25,\n140,112,132,122,28,76,146,218,121,35,180,69,145,132,108,224,0,0,16,32,0,0,\n0,0,16,113,225,0,48,156,209,2,122,244,5,34,92,35,68,225,161,166,218,16,33,\n18,224,104,82,146,59,50,5,7,19,39,22,70,154,103,215,32,28,78,99,193,18,80,\n70,131,165,1,205,34,8,35,68,225,161,166,239,255,4,12,70,137,195,39,248,73,\n7,78,3,154,102,16,70,137,195,67,77,223,248,1,74,9,129,125,255,130,9,65,154,\n232,147,161,115,59,255,5,64,195,32,156,50,126,197,14,2,3,107,173,213,0,\n};\n#else\n#error invalid endianness defines\n#endif\n#endif  /* DUK_USE_ROM_OBJECTS */\n\n/* automatic undefs */\n#undef DUK__REFCINIT\n#line 1 \"duk_error_macros.c\"\n/*\n *  Error and fatal handling.\n */\n\n/* #include duk_internal.h -> already included */\n\n#define DUK__ERRFMT_BUFSIZE  256  /* size for formatting buffers */\n\n#if defined(DUK_USE_VERBOSE_ERRORS)\n\nDUK_INTERNAL DUK_COLD void duk_err_handle_error_fmt(duk_hthread *thr, const char *filename, duk_uint_t line_and_code, const char *fmt, ...) {\n\tva_list ap;\n\tchar msg[DUK__ERRFMT_BUFSIZE];\n\tva_start(ap, fmt);\n\t(void) DUK_VSNPRINTF(msg, sizeof(msg), fmt, ap);\n\tmsg[sizeof(msg) - 1] = (char) 0;\n\tduk_err_create_and_throw(thr, (duk_errcode_t) (line_and_code >> 24), msg, filename, (duk_int_t) (line_and_code & 0x00ffffffL));\n\tva_end(ap);  /* dead code, but ensures portability (see Linux man page notes) */\n}\n\nDUK_INTERNAL DUK_COLD void duk_err_handle_error(duk_hthread *thr, const char *filename, duk_uint_t line_and_code, const char *msg) {\n\tduk_err_create_and_throw(thr, (duk_errcode_t) (line_and_code >> 24), msg, filename, (duk_int_t) (line_and_code & 0x00ffffffL));\n}\n\n#else  /* DUK_USE_VERBOSE_ERRORS */\n\nDUK_INTERNAL DUK_COLD void duk_err_handle_error(duk_hthread *thr, duk_errcode_t code) {\n\tduk_err_create_and_throw(thr, code);\n}\n\n#endif  /* DUK_USE_VERBOSE_ERRORS */\n\n/*\n *  Error throwing helpers\n */\n\n#if defined(DUK_USE_VERBOSE_ERRORS)\n#if defined(DUK_USE_PARANOID_ERRORS)\nDUK_INTERNAL DUK_COLD void duk_err_require_type_index(duk_hthread *thr, const char *filename, duk_int_t linenumber, duk_idx_t idx, const char *expect_name) {\n\tDUK_ERROR_RAW_FMT3(thr, filename, linenumber, DUK_ERR_TYPE_ERROR, \"%s required, found %s (stack index %ld)\",\n\t                   expect_name, duk_get_type_name(thr, idx), (long) idx);\n}\n#else\nDUK_INTERNAL DUK_COLD void duk_err_require_type_index(duk_hthread *thr, const char *filename, duk_int_t linenumber, duk_idx_t idx, const char *expect_name) {\n\tDUK_ERROR_RAW_FMT3(thr, filename, linenumber, DUK_ERR_TYPE_ERROR, \"%s required, found %s (stack index %ld)\",\n\t                   expect_name, duk_push_string_readable(thr, idx), (long) idx);\n}\n#endif\nDUK_INTERNAL DUK_COLD void duk_err_error_internal(duk_hthread *thr, const char *filename, duk_int_t linenumber) {\n\tDUK_ERROR_RAW(thr, filename, linenumber, DUK_ERR_ERROR, DUK_STR_INTERNAL_ERROR);\n}\nDUK_INTERNAL DUK_COLD void duk_err_error_alloc_failed(duk_hthread *thr, const char *filename, duk_int_t linenumber) {\n\tDUK_ERROR_RAW(thr, filename, linenumber, DUK_ERR_ERROR, DUK_STR_ALLOC_FAILED);\n}\nDUK_INTERNAL DUK_COLD void duk_err_error(duk_hthread *thr, const char *filename, duk_int_t linenumber, const char *message) {\n\tDUK_ERROR_RAW(thr, filename, linenumber, DUK_ERR_ERROR, message);\n}\nDUK_INTERNAL DUK_COLD void duk_err_range(duk_hthread *thr, const char *filename, duk_int_t linenumber, const char *message) {\n\tDUK_ERROR_RAW(thr, filename, linenumber, DUK_ERR_RANGE_ERROR, message);\n}\nDUK_INTERNAL DUK_COLD void duk_err_range_index(duk_hthread *thr, const char *filename, duk_int_t linenumber, duk_idx_t idx) {\n\tDUK_ERROR_RAW_FMT1(thr, filename, linenumber, DUK_ERR_RANGE_ERROR, \"invalid stack index %ld\", (long) (idx));\n}\nDUK_INTERNAL DUK_COLD void duk_err_range_push_beyond(duk_hthread *thr, const char *filename, duk_int_t linenumber) {\n\tDUK_ERROR_RAW(thr, filename, linenumber, DUK_ERR_RANGE_ERROR, DUK_STR_PUSH_BEYOND_ALLOC_STACK);\n}\nDUK_INTERNAL DUK_COLD void duk_err_type_invalid_args(duk_hthread *thr, const char *filename, duk_int_t linenumber) {\n\tDUK_ERROR_RAW(thr, filename, linenumber, DUK_ERR_TYPE_ERROR, DUK_STR_INVALID_ARGS);\n}\nDUK_INTERNAL DUK_COLD void duk_err_type_invalid_state(duk_hthread *thr, const char *filename, duk_int_t linenumber) {\n\tDUK_ERROR_RAW(thr, filename, linenumber, DUK_ERR_TYPE_ERROR, DUK_STR_INVALID_STATE);\n}\nDUK_INTERNAL DUK_COLD void duk_err_type_invalid_trap_result(duk_hthread *thr, const char *filename, duk_int_t linenumber) {\n\tDUK_ERROR_RAW(thr, filename, linenumber, DUK_ERR_TYPE_ERROR, DUK_STR_INVALID_TRAP_RESULT);\n}\n#else\n/* The file/line arguments are NULL and 0, they're ignored by DUK_ERROR_RAW()\n * when non-verbose errors are used.\n */\n\nDUK_NORETURN(DUK_LOCAL_DECL void duk__err_shared(duk_hthread *thr, duk_errcode_t code));\nDUK_LOCAL void duk__err_shared(duk_hthread *thr, duk_errcode_t code) {\n\tDUK_ERROR_RAW(thr, NULL, 0, code, NULL);\n}\nDUK_INTERNAL DUK_COLD void duk_err_error(duk_hthread *thr) {\n\tduk__err_shared(thr, DUK_ERR_ERROR);\n}\nDUK_INTERNAL DUK_COLD void duk_err_range(duk_hthread *thr) {\n\tduk__err_shared(thr, DUK_ERR_RANGE_ERROR);\n}\nDUK_INTERNAL DUK_COLD void duk_err_eval(duk_hthread *thr) {\n\tduk__err_shared(thr, DUK_ERR_EVAL_ERROR);\n}\nDUK_INTERNAL DUK_COLD void duk_err_reference(duk_hthread *thr) {\n\tduk__err_shared(thr, DUK_ERR_REFERENCE_ERROR);\n}\nDUK_INTERNAL DUK_COLD void duk_err_syntax(duk_hthread *thr) {\n\tduk__err_shared(thr, DUK_ERR_SYNTAX_ERROR);\n}\nDUK_INTERNAL DUK_COLD void duk_err_type(duk_hthread *thr) {\n\tduk__err_shared(thr, DUK_ERR_TYPE_ERROR);\n}\nDUK_INTERNAL DUK_COLD void duk_err_uri(duk_hthread *thr) {\n\tduk__err_shared(thr, DUK_ERR_URI_ERROR);\n}\n#endif\n\n/*\n *  Default fatal error handler\n */\n\nDUK_INTERNAL DUK_COLD void duk_default_fatal_handler(void *udata, const char *msg) {\n\tDUK_UNREF(udata);\n\tDUK_UNREF(msg);\n\n#if defined(DUK_USE_FATAL_HANDLER)\n\t/* duk_config.h provided a custom default fatal handler. */\n\tDUK_D(DUK_DPRINT(\"custom default fatal error handler called: %s\", msg ? msg : \"NULL\"));\n\tDUK_USE_FATAL_HANDLER(udata, msg);\n#else\n\t/* Default behavior is to abort() on error.  There's no printout\n\t * which makes this awkward, so it's always recommended to use an\n\t * explicit fatal error handler.\n\t *\n\t * ====================================================================\n\t * NOTE: If you are seeing this, you are most likely dealing with an\n\t * uncaught error.  You should provide a fatal error handler in Duktape\n\t * heap creation, and should consider using a protected call as your\n\t * first call into an empty Duktape context to properly handle errors.\n\t * See:\n\t *   - http://duktape.org/guide.html#error-handling\n\t *   - http://wiki.duktape.org/HowtoFatalErrors.html\n\t *   - http://duktape.org/api.html#taglist-protected\n\t * ====================================================================\n\t */\n\tDUK_D(DUK_DPRINT(\"built-in default fatal error handler called: %s\", msg ? msg : \"NULL\"));\n\tDUK_ABORT();\n#endif\n\n\tDUK_D(DUK_DPRINT(\"fatal error handler returned, enter forever loop\"));\n\tfor (;;) {\n\t\t/* Loop forever to ensure we don't return. */\n\t}\n}\n\n/* automatic undefs */\n#undef DUK__ERRFMT_BUFSIZE\n#line 1 \"duk_unicode_support.c\"\n/*\n *  Various Unicode help functions for character classification predicates,\n *  case conversion, decoding, etc.\n */\n\n/* #include duk_internal.h -> already included */\n\n/*\n *  Fast path tables\n */\n\n#if defined(DUK_USE_IDCHAR_FASTPATH)\nDUK_INTERNAL const duk_int8_t duk_is_idchar_tab[128] = {\n\t/* 0: not IdentifierStart or IdentifierPart\n\t * 1: IdentifierStart and IdentifierPart\n\t * -1: IdentifierPart only\n\t */\n\t0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,   /* 0x00...0x0f */\n\t0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,   /* 0x10...0x1f */\n\t0,  0,  0,  0,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,   /* 0x20...0x2f */\n\t-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0,  0,  0,  0,  0,  0,   /* 0x30...0x3f */\n\t0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,   /* 0x40...0x4f */\n\t1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  1,   /* 0x50...0x5f */\n\t0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,   /* 0x60...0x6f */\n\t1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0    /* 0x70...0x7f */\n};\n#endif\n\n/*\n *  XUTF-8 and CESU-8 encoding/decoding\n */\n\nDUK_INTERNAL duk_small_int_t duk_unicode_get_xutf8_length(duk_ucodepoint_t cp) {\n\tduk_uint_fast32_t x = (duk_uint_fast32_t) cp;\n\tif (x < 0x80UL) {\n\t\t/* 7 bits */\n\t\treturn 1;\n\t} else if (x < 0x800UL) {\n\t\t/* 11 bits */\n\t\treturn 2;\n\t} else if (x < 0x10000UL) {\n\t\t/* 16 bits */\n\t\treturn 3;\n\t} else if (x < 0x200000UL) {\n\t\t/* 21 bits */\n\t\treturn 4;\n\t} else if (x < 0x4000000UL) {\n\t\t/* 26 bits */\n\t\treturn 5;\n\t} else if (x < (duk_ucodepoint_t) 0x80000000UL) {\n\t\t/* 31 bits */\n\t\treturn 6;\n\t} else {\n\t\t/* 36 bits */\n\t\treturn 7;\n\t}\n}\n\n#if defined(DUK_USE_ASSERTIONS)\nDUK_INTERNAL duk_small_int_t duk_unicode_get_cesu8_length(duk_ucodepoint_t cp) {\n\tduk_uint_fast32_t x = (duk_uint_fast32_t) cp;\n\tif (x < 0x80UL) {\n\t\t/* 7 bits */\n\t\treturn 1;\n\t} else if (x < 0x800UL) {\n\t\t/* 11 bits */\n\t\treturn 2;\n\t} else if (x < 0x10000UL) {\n\t\t/* 16 bits */\n\t\treturn 3;\n\t} else {\n\t\t/* Encoded as surrogate pair, each encoding to 3 bytes for\n\t\t * 6 bytes total.  Codepoints above U+10FFFF encode as 6 bytes\n\t\t * too, see duk_unicode_encode_cesu8().\n\t\t  */\n\t\treturn 3 + 3;\n\t}\n}\n#endif  /* DUK_USE_ASSERTIONS */\n\nDUK_INTERNAL const duk_uint8_t duk_unicode_xutf8_markers[7] = {\n\t0x00, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe\n};\n\n/* Encode to extended UTF-8; 'out' must have space for at least\n * DUK_UNICODE_MAX_XUTF8_LENGTH bytes.  Allows encoding of any\n * 32-bit (unsigned) codepoint.\n */\nDUK_INTERNAL duk_small_int_t duk_unicode_encode_xutf8(duk_ucodepoint_t cp, duk_uint8_t *out) {\n\tduk_uint_fast32_t x = (duk_uint_fast32_t) cp;\n\tduk_small_int_t len;\n\tduk_uint8_t marker;\n\tduk_small_int_t i;\n\n\tlen = duk_unicode_get_xutf8_length(cp);\n\tDUK_ASSERT(len > 0);\n\n\tmarker = duk_unicode_xutf8_markers[len - 1];  /* 64-bit OK because always >= 0 */\n\n\ti = len;\n\tDUK_ASSERT(i > 0);\n\tdo {\n\t\ti--;\n\t\tif (i > 0) {\n\t\t\tout[i] = (duk_uint8_t) (0x80 + (x & 0x3f));\n\t\t\tx >>= 6;\n\t\t} else {\n\t\t\t/* Note: masking of 'x' is not necessary because of\n\t\t\t * range check and shifting -> no bits overlapping\n\t\t\t * the marker should be set.\n\t\t\t */\n\t\t\tout[0] = (duk_uint8_t) (marker + x);\n\t\t}\n\t} while (i > 0);\n\n\treturn len;\n}\n\n/* Encode to CESU-8; 'out' must have space for at least\n * DUK_UNICODE_MAX_CESU8_LENGTH bytes; codepoints above U+10FFFF\n * will encode to garbage but won't overwrite the output buffer.\n */\nDUK_INTERNAL duk_small_int_t duk_unicode_encode_cesu8(duk_ucodepoint_t cp, duk_uint8_t *out) {\n\tduk_uint_fast32_t x = (duk_uint_fast32_t) cp;\n\tduk_small_int_t len;\n\n\tif (x < 0x80UL) {\n\t\tout[0] = (duk_uint8_t) x;\n\t\tlen = 1;\n\t} else if (x < 0x800UL) {\n\t\tout[0] = (duk_uint8_t) (0xc0 + ((x >> 6) & 0x1f));\n\t\tout[1] = (duk_uint8_t) (0x80 + (x & 0x3f));\n\t\tlen = 2;\n\t} else if (x < 0x10000UL) {\n\t\t/* surrogate pairs get encoded here */\n\t\tout[0] = (duk_uint8_t) (0xe0 + ((x >> 12) & 0x0f));\n\t\tout[1] = (duk_uint8_t) (0x80 + ((x >> 6) & 0x3f));\n\t\tout[2] = (duk_uint8_t) (0x80 + (x & 0x3f));\n\t\tlen = 3;\n\t} else {\n\t\t/*\n\t\t *  Unicode codepoints above U+FFFF are encoded as surrogate\n\t\t *  pairs here.  This ensures that all CESU-8 codepoints are\n\t\t *  16-bit values as expected in Ecmascript.  The surrogate\n\t\t *  pairs always get a 3-byte encoding (each) in CESU-8.\n\t\t *  See: http://en.wikipedia.org/wiki/Surrogate_pair\n\t\t *\n\t\t *  20-bit codepoint, 10 bits (A and B) per surrogate pair:\n\t\t *\n\t\t *    x = 0b00000000 0000AAAA AAAAAABB BBBBBBBB\n\t\t *  sp1 = 0b110110AA AAAAAAAA  (0xd800 + ((x >> 10) & 0x3ff))\n\t\t *  sp2 = 0b110111BB BBBBBBBB  (0xdc00 + (x & 0x3ff))\n\t\t *\n\t\t *  Encoded into CESU-8:\n\t\t *\n\t\t *  sp1 -> 0b11101101  (0xe0 + ((sp1 >> 12) & 0x0f))\n\t\t *      -> 0b1010AAAA  (0x80 + ((sp1 >> 6) & 0x3f))\n\t\t *      -> 0b10AAAAAA  (0x80 + (sp1 & 0x3f))\n\t\t *  sp2 -> 0b11101101  (0xe0 + ((sp2 >> 12) & 0x0f))\n\t\t *      -> 0b1011BBBB  (0x80 + ((sp2 >> 6) & 0x3f))\n\t\t *      -> 0b10BBBBBB  (0x80 + (sp2 & 0x3f))\n\t\t *\n\t\t *  Note that 0x10000 must be subtracted first.  The code below\n\t\t *  avoids the sp1, sp2 temporaries which saves around 20 bytes\n\t\t *  of code.\n\t\t */\n\n\t\tx -= 0x10000UL;\n\n\t\tout[0] = (duk_uint8_t) (0xed);\n\t\tout[1] = (duk_uint8_t) (0xa0 + ((x >> 16) & 0x0f));\n\t\tout[2] = (duk_uint8_t) (0x80 + ((x >> 10) & 0x3f));\n\t\tout[3] = (duk_uint8_t) (0xed);\n\t\tout[4] = (duk_uint8_t) (0xb0 + ((x >> 6) & 0x0f));\n\t\tout[5] = (duk_uint8_t) (0x80 + (x & 0x3f));\n\t\tlen = 6;\n\t}\n\n\treturn len;\n}\n\n/* Decode helper.  Return zero on error. */\nDUK_INTERNAL duk_small_int_t duk_unicode_decode_xutf8(duk_hthread *thr, const duk_uint8_t **ptr, const duk_uint8_t *ptr_start, const duk_uint8_t *ptr_end, duk_ucodepoint_t *out_cp) {\n\tconst duk_uint8_t *p;\n\tduk_uint32_t res;\n\tduk_uint_fast8_t ch;\n\tduk_small_int_t n;\n\n\tDUK_UNREF(thr);\n\n\tp = *ptr;\n\tif (p < ptr_start || p >= ptr_end) {\n\t\tgoto fail;\n\t}\n\n\t/*\n\t *  UTF-8 decoder which accepts longer than standard byte sequences.\n\t *  This allows full 32-bit code points to be used.\n\t */\n\n\tch = (duk_uint_fast8_t) (*p++);\n\tif (ch < 0x80) {\n\t\t/* 0xxx xxxx   [7 bits] */\n\t\tres = (duk_uint32_t) (ch & 0x7f);\n\t\tn = 0;\n\t} else if (ch < 0xc0) {\n\t\t/* 10xx xxxx -> invalid */\n\t\tgoto fail;\n\t} else if (ch < 0xe0) {\n\t\t/* 110x xxxx   10xx xxxx   [11 bits] */\n\t\tres = (duk_uint32_t) (ch & 0x1f);\n\t\tn = 1;\n\t} else if (ch < 0xf0) {\n\t\t/* 1110 xxxx   10xx xxxx   10xx xxxx   [16 bits] */\n\t\tres = (duk_uint32_t) (ch & 0x0f);\n\t\tn = 2;\n\t} else if (ch < 0xf8) {\n\t\t/* 1111 0xxx   10xx xxxx   10xx xxxx   10xx xxxx   [21 bits] */\n\t\tres = (duk_uint32_t) (ch & 0x07);\n\t\tn = 3;\n\t} else if (ch < 0xfc) {\n\t\t/* 1111 10xx   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   [26 bits] */\n\t\tres = (duk_uint32_t) (ch & 0x03);\n\t\tn = 4;\n\t} else if (ch < 0xfe) {\n\t\t/* 1111 110x   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   [31 bits] */\n\t\tres = (duk_uint32_t) (ch & 0x01);\n\t\tn = 5;\n\t} else if (ch < 0xff) {\n\t\t/* 1111 1110   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   [36 bits] */\n\t\tres = (duk_uint32_t) (0);\n\t\tn = 6;\n\t} else {\n\t\t/* 8-byte format could be:\n\t\t * 1111 1111   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   [41 bits]\n\t\t *\n\t\t * However, this format would not have a zero bit following the\n\t\t * leading one bits and would not allow 0xFF to be used as an\n\t\t * \"invalid xutf-8\" marker for internal keys.  Further, 8-byte\n\t\t * encodings (up to 41 bit code points) are not currently needed.\n\t\t */\n\t\tgoto fail;\n\t}\n\n\tDUK_ASSERT(p >= ptr_start);  /* verified at beginning */\n\tif (p + n > ptr_end) {\n\t\t/* check pointer at end */\n\t\tgoto fail;\n\t}\n\n\twhile (n > 0) {\n\t\tDUK_ASSERT(p >= ptr_start && p < ptr_end);\n\t\tch = (duk_uint_fast8_t) (*p++);\n#if 0\n\t\tif (ch & 0xc0 != 0x80) {\n\t\t\t/* not a continuation byte */\n\t\t\tp--;\n\t\t\t*ptr = p;\n\t\t\t*out_cp = DUK_UNICODE_CP_REPLACEMENT_CHARACTER;\n\t\t\treturn 1;\n\t\t}\n#endif\n\t\tres = (res << 6) + (duk_uint32_t) (ch & 0x3f);\n\t\tn--;\n\t}\n\n\t*ptr = p;\n\t*out_cp = res;\n\treturn 1;\n\n fail:\n\treturn 0;\n}\n\n/* used by e.g. duk_regexp_executor.c, string built-ins */\nDUK_INTERNAL duk_ucodepoint_t duk_unicode_decode_xutf8_checked(duk_hthread *thr, const duk_uint8_t **ptr, const duk_uint8_t *ptr_start, const duk_uint8_t *ptr_end) {\n\tduk_ucodepoint_t cp;\n\n\tif (duk_unicode_decode_xutf8(thr, ptr, ptr_start, ptr_end, &cp)) {\n\t\treturn cp;\n\t}\n\tDUK_ERROR_INTERNAL(thr);\n\tDUK_UNREACHABLE();\n\treturn 0;\n}\n\n/* Compute (extended) utf-8 length without codepoint encoding validation,\n * used for string interning.\n *\n * NOTE: This algorithm is performance critical, more so than string hashing\n * in some cases.  It is needed when interning a string and needs to scan\n * every byte of the string with no skipping.  Having an ASCII fast path\n * is useful if possible in the algorithm.  The current algorithms were\n * chosen from several variants, based on x64 gcc -O2 testing.  See:\n * https://github.com/svaarala/duktape/pull/422\n *\n * NOTE: must match tools/dukutil.py:duk_unicode_unvalidated_utf8_length().\n */\n\n#if defined(DUK_USE_PREFER_SIZE)\n/* Small variant; roughly 150 bytes smaller than the fast variant. */\nDUK_INTERNAL duk_size_t duk_unicode_unvalidated_utf8_length(const duk_uint8_t *data, duk_size_t blen) {\n\tconst duk_uint8_t *p;\n\tconst duk_uint8_t *p_end;\n\tduk_size_t ncont;\n\tduk_size_t clen;\n\n\tp = data;\n\tp_end = data + blen;\n\tncont = 0;\n\twhile (p != p_end) {\n\t\tduk_uint8_t x;\n\t\tx = *p++;\n\t\tif (DUK_UNLIKELY(x >= 0x80 && x <= 0xbf)) {\n\t\t\tncont++;\n\t\t}\n\t}\n\n\tDUK_ASSERT(ncont <= blen);\n\tclen = blen - ncont;\n\tDUK_ASSERT(clen <= blen);\n\treturn clen;\n}\n#else  /* DUK_USE_PREFER_SIZE */\n/* This seems like a good overall approach.  Fast path for ASCII in 4 byte\n * blocks.\n */\nDUK_INTERNAL duk_size_t duk_unicode_unvalidated_utf8_length(const duk_uint8_t *data, duk_size_t blen) {\n\tconst duk_uint8_t *p;\n\tconst duk_uint8_t *p_end;\n\tconst duk_uint32_t *p32_end;\n\tconst duk_uint32_t *p32;\n\tduk_size_t ncont;\n\tduk_size_t clen;\n\n\tncont = 0;  /* number of continuation (non-initial) bytes in [0x80,0xbf] */\n\tp = data;\n\tp_end = data + blen;\n\tif (blen < 16) {\n\t\tgoto skip_fastpath;\n\t}\n\n\t/* Align 'p' to 4; the input data may have arbitrary alignment.\n\t * End of string check not needed because blen >= 16.\n\t */\n\twhile (((duk_size_t) (const void *) p) & 0x03U) {\n\t\tduk_uint8_t x;\n\t\tx = *p++;\n\t\tif (DUK_UNLIKELY(x >= 0x80 && x <= 0xbf)) {\n\t\t\tncont++;\n\t\t}\n\t}\n\n\t/* Full, aligned 4-byte reads. */\n\tp32_end = (const duk_uint32_t *) (const void *) (p + ((duk_size_t) (p_end - p) & (duk_size_t) (~0x03)));\n\tp32 = (const duk_uint32_t *) (const void *) p;\n\twhile (p32 != (const duk_uint32_t *) p32_end) {\n\t\tduk_uint32_t x;\n\t\tx = *p32++;\n\t\tif (DUK_LIKELY((x & 0x80808080UL) == 0)) {\n\t\t\t;  /* ASCII fast path */\n\t\t} else {\n\t\t\t/* Flip highest bit of each byte which changes\n\t\t\t * the bit pattern 10xxxxxx into 00xxxxxx which\n\t\t\t * allows an easy bit mask test.\n\t\t\t */\n\t\t\tx ^= 0x80808080UL;\n\t\t\tif (DUK_UNLIKELY(!(x & 0xc0000000UL))) {\n\t\t\t\tncont++;\n\t\t\t}\n\t\t\tif (DUK_UNLIKELY(!(x & 0x00c00000UL))) {\n\t\t\t\tncont++;\n\t\t\t}\n\t\t\tif (DUK_UNLIKELY(!(x & 0x0000c000UL))) {\n\t\t\t\tncont++;\n\t\t\t}\n\t\t\tif (DUK_UNLIKELY(!(x & 0x000000c0UL))) {\n\t\t\t\tncont++;\n\t\t\t}\n\t\t}\n\t}\n\tp = (const duk_uint8_t *) p32;\n\t/* Fall through to handle the rest. */\n\n skip_fastpath:\n\twhile (p != p_end) {\n\t\tduk_uint8_t x;\n\t\tx = *p++;\n\t\tif (DUK_UNLIKELY(x >= 0x80 && x <= 0xbf)) {\n\t\t\tncont++;\n\t\t}\n\t}\n\n\tDUK_ASSERT(ncont <= blen);\n\tclen = blen - ncont;\n\tDUK_ASSERT(clen <= blen);\n\treturn clen;\n}\n#endif  /* DUK_USE_PREFER_SIZE */\n\n/*\n *  Unicode range matcher\n *\n *  Matches a codepoint against a packed bitstream of character ranges.\n *  Used for slow path Unicode matching.\n */\n\n/* Must match tools/extract_chars.py, generate_match_table3(). */\nDUK_LOCAL duk_uint32_t duk__uni_decode_value(duk_bitdecoder_ctx *bd_ctx) {\n\tduk_uint32_t t;\n\n\tt = (duk_uint32_t) duk_bd_decode(bd_ctx, 4);\n\tif (t <= 0x0eU) {\n\t\treturn t;\n\t}\n\tt = (duk_uint32_t) duk_bd_decode(bd_ctx, 8);\n\tif (t <= 0xfdU) {\n\t\treturn t + 0x0f;\n\t}\n\tif (t == 0xfeU) {\n\t\tt = (duk_uint32_t) duk_bd_decode(bd_ctx, 12);\n\t\treturn t + 0x0fU + 0xfeU;\n\t} else {\n\t\tt = (duk_uint32_t) duk_bd_decode(bd_ctx, 24);\n\t\treturn t + 0x0fU + 0xfeU + 0x1000UL;\n\t}\n}\n\nDUK_LOCAL duk_small_int_t duk__uni_range_match(const duk_uint8_t *unitab, duk_size_t unilen, duk_codepoint_t cp) {\n\tduk_bitdecoder_ctx bd_ctx;\n\tduk_codepoint_t prev_re;\n\n\tDUK_MEMZERO(&bd_ctx, sizeof(bd_ctx));\n\tbd_ctx.data = (const duk_uint8_t *) unitab;\n\tbd_ctx.length = (duk_size_t) unilen;\n\n\tprev_re = 0;\n\tfor (;;) {\n\t\tduk_codepoint_t r1, r2;\n\t\tr1 = (duk_codepoint_t) duk__uni_decode_value(&bd_ctx);\n\t\tif (r1 == 0) {\n\t\t\tbreak;\n\t\t}\n\t\tr2 = (duk_codepoint_t) duk__uni_decode_value(&bd_ctx);\n\n\t\tr1 = prev_re + r1;\n\t\tr2 = r1 + r2;\n\t\tprev_re = r2;\n\n\t\t/* [r1,r2] is the range */\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"duk__uni_range_match: cp=%06lx range=[0x%06lx,0x%06lx]\",\n\t\t                     (unsigned long) cp, (unsigned long) r1, (unsigned long) r2));\n\t\tif (cp >= r1 && cp <= r2) {\n\t\t\treturn 1;\n\t\t}\n\t}\n\n\treturn 0;\n}\n\n/*\n *  \"WhiteSpace\" production check.\n */\n\nDUK_INTERNAL duk_small_int_t duk_unicode_is_whitespace(duk_codepoint_t cp) {\n\t/*\n\t *  E5 Section 7.2 specifies six characters specifically as\n\t *  white space:\n\t *\n\t *    0009;<control>;Cc;0;S;;;;;N;CHARACTER TABULATION;;;;\n\t *    000B;<control>;Cc;0;S;;;;;N;LINE TABULATION;;;;\n\t *    000C;<control>;Cc;0;WS;;;;;N;FORM FEED (FF);;;;\n\t *    0020;SPACE;Zs;0;WS;;;;;N;;;;;\n\t *    00A0;NO-BREAK SPACE;Zs;0;CS;<noBreak> 0020;;;;N;NON-BREAKING SPACE;;;;\n\t *    FEFF;ZERO WIDTH NO-BREAK SPACE;Cf;0;BN;;;;;N;BYTE ORDER MARK;;;;\n\t *\n\t *  It also specifies any Unicode category 'Zs' characters as white\n\t *  space.  These can be extracted with the \"tools/extract_chars.py\" script.\n\t *  Current result:\n\t *\n\t *    RAW OUTPUT:\n\t *    ===========\n\t *    0020;SPACE;Zs;0;WS;;;;;N;;;;;\n\t *    00A0;NO-BREAK SPACE;Zs;0;CS;<noBreak> 0020;;;;N;NON-BREAKING SPACE;;;;\n\t *    1680;OGHAM SPACE MARK;Zs;0;WS;;;;;N;;;;;\n\t *    180E;MONGOLIAN VOWEL SEPARATOR;Zs;0;WS;;;;;N;;;;;\n\t *    2000;EN QUAD;Zs;0;WS;2002;;;;N;;;;;\n\t *    2001;EM QUAD;Zs;0;WS;2003;;;;N;;;;;\n\t *    2002;EN SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;\n\t *    2003;EM SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;\n\t *    2004;THREE-PER-EM SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;\n\t *    2005;FOUR-PER-EM SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;\n\t *    2006;SIX-PER-EM SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;\n\t *    2007;FIGURE SPACE;Zs;0;WS;<noBreak> 0020;;;;N;;;;;\n\t *    2008;PUNCTUATION SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;\n\t *    2009;THIN SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;\n\t *    200A;HAIR SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;\n\t *    202F;NARROW NO-BREAK SPACE;Zs;0;CS;<noBreak> 0020;;;;N;;;;;\n\t *    205F;MEDIUM MATHEMATICAL SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;\n\t *    3000;IDEOGRAPHIC SPACE;Zs;0;WS;<wide> 0020;;;;N;;;;;\n\t *\n\t *    RANGES:\n\t *    =======\n\t *    0x0020\n\t *    0x00a0\n\t *    0x1680\n\t *    0x180e\n\t *    0x2000 ... 0x200a\n\t *    0x202f\n\t *    0x205f\n\t *    0x3000\n\t *\n\t *  A manual decoder (below) is probably most compact for this.\n\t */\n\n\tduk_uint_fast8_t lo;\n\tduk_uint_fast32_t hi;\n\n\t/* cp == -1 (EOF) never matches and causes return value 0 */\n\n\tlo = (duk_uint_fast8_t) (cp & 0xff);\n\thi = (duk_uint_fast32_t) (cp >> 8);  /* does not fit into an uchar */\n\n\tif (hi == 0x0000UL) {\n\t\tif (lo == 0x09U || lo == 0x0bU || lo == 0x0cU ||\n\t\t    lo == 0x20U || lo == 0xa0U) {\n\t\t\treturn 1;\n\t\t}\n\t} else if (hi == 0x0020UL) {\n\t\tif (lo <= 0x0aU || lo == 0x2fU || lo == 0x5fU) {\n\t\t\treturn 1;\n\t\t}\n\t} else if (cp == 0x1680L || cp == 0x180eL || cp == 0x3000L ||\n\t           cp == 0xfeffL) {\n\t\treturn 1;\n\t}\n\n\treturn 0;\n}\n\n/*\n *  \"LineTerminator\" production check.\n */\n\nDUK_INTERNAL duk_small_int_t duk_unicode_is_line_terminator(duk_codepoint_t cp) {\n\t/*\n\t *  E5 Section 7.3\n\t *\n\t *  A LineTerminatorSequence essentially merges <CR> <LF> sequences\n\t *  into a single line terminator.  This must be handled by the caller.\n\t */\n\n\tif (cp == 0x000aL || cp == 0x000dL || cp == 0x2028L ||\n\t    cp == 0x2029L) {\n\t\treturn 1;\n\t}\n\n\treturn 0;\n}\n\n/*\n *  \"IdentifierStart\" production check.\n */\n\nDUK_INTERNAL duk_small_int_t duk_unicode_is_identifier_start(duk_codepoint_t cp) {\n\t/*\n\t *  E5 Section 7.6:\n\t *\n\t *    IdentifierStart:\n\t *      UnicodeLetter\n\t *      $\n\t *      _\n\t *      \\ UnicodeEscapeSequence\n\t *\n\t *  IdentifierStart production has one multi-character production:\n\t *\n\t *    \\ UnicodeEscapeSequence\n\t *\n\t *  The '\\' character is -not- matched by this function.  Rather, the caller\n\t *  should decode the escape and then call this function to check whether the\n\t *  decoded character is acceptable (see discussion in E5 Section 7.6).\n\t *\n\t *  The \"UnicodeLetter\" alternative of the production allows letters\n\t *  from various Unicode categories.  These can be extracted with the\n\t *  \"tools/extract_chars.py\" script.\n\t *\n\t *  Because the result has hundreds of Unicode codepoint ranges, matching\n\t *  for any values >= 0x80 are done using a very slow range-by-range scan\n\t *  and a packed range format.\n\t *\n\t *  The ASCII portion (codepoints 0x00 ... 0x7f) is fast-pathed below because\n\t *  it matters the most.  The ASCII related ranges of IdentifierStart are:\n\t *\n\t *    0x0041 ... 0x005a     ['A' ... 'Z']\n\t *    0x0061 ... 0x007a     ['a' ... 'z']\n\t *    0x0024                ['$']\n\t *    0x005f                ['_']\n\t */\n\n\t/* ASCII (and EOF) fast path -- quick accept and reject */\n\tif (cp <= 0x7fL) {\n#if defined(DUK_USE_IDCHAR_FASTPATH)\n\t\treturn (cp >= 0) && (duk_is_idchar_tab[cp] > 0);\n#else\n\t\tif ((cp >= 'a' && cp <= 'z') ||\n\t\t    (cp >= 'A' && cp <= 'Z') ||\n\t\t    cp == '_' || cp == '$') {\n\t\t\treturn 1;\n\t\t}\n\t\treturn 0;\n#endif\n\t}\n\n\t/* Non-ASCII slow path (range-by-range linear comparison), very slow */\n\n#if defined(DUK_USE_SOURCE_NONBMP)\n\tif (duk__uni_range_match(duk_unicode_ids_noa,\n\t                         (duk_size_t) sizeof(duk_unicode_ids_noa),\n\t                         (duk_codepoint_t) cp)) {\n\t\treturn 1;\n\t}\n\treturn 0;\n#else\n\tif (cp < 0x10000L) {\n\t\tif (duk__uni_range_match(duk_unicode_ids_noabmp,\n\t\t                         sizeof(duk_unicode_ids_noabmp),\n\t\t                         (duk_codepoint_t) cp)) {\n\t\t\treturn 1;\n\t\t}\n\t\treturn 0;\n\t} else {\n\t\t/* without explicit non-BMP support, assume non-BMP characters\n\t\t * are always accepted as identifier characters.\n\t\t */\n\t\treturn 1;\n\t}\n#endif\n}\n\n/*\n *  \"IdentifierPart\" production check.\n */\n\nDUK_INTERNAL duk_small_int_t duk_unicode_is_identifier_part(duk_codepoint_t cp) {\n\t/*\n\t *  E5 Section 7.6:\n\t *\n\t *    IdentifierPart:\n\t *      IdentifierStart\n\t *      UnicodeCombiningMark\n\t *      UnicodeDigit\n\t *      UnicodeConnectorPunctuation\n\t *      <ZWNJ>  [U+200C]\n\t *      <ZWJ>   [U+200D]\n\t *\n\t *  IdentifierPart production has one multi-character production\n\t *  as part of its IdentifierStart alternative.  The '\\' character\n\t *  of an escape sequence is not matched here, see discussion in\n\t *  duk_unicode_is_identifier_start().\n\t *\n\t *  To match non-ASCII characters (codepoints >= 0x80), a very slow\n\t *  linear range-by-range scan is used.  The codepoint is first compared\n\t *  to the IdentifierStart ranges, and if it doesn't match, then to a\n\t *  set consisting of code points in IdentifierPart but not in\n\t *  IdentifierStart.  This is done to keep the unicode range data small,\n\t *  at the expense of speed.\n\t *\n\t *  The ASCII fast path consists of:\n\t *\n\t *    0x0030 ... 0x0039     ['0' ... '9', UnicodeDigit]\n\t *    0x0041 ... 0x005a     ['A' ... 'Z', IdentifierStart]\n\t *    0x0061 ... 0x007a     ['a' ... 'z', IdentifierStart]\n\t *    0x0024                ['$', IdentifierStart]\n\t *    0x005f                ['_', IdentifierStart and\n\t *                                UnicodeConnectorPunctuation]\n\t *\n\t *  UnicodeCombiningMark has no code points <= 0x7f.\n\t *\n\t *  The matching code reuses the \"identifier start\" tables, and then\n\t *  consults a separate range set for characters in \"identifier part\"\n\t *  but not in \"identifier start\".  These can be extracted with the\n\t *  \"tools/extract_chars.py\" script.\n\t *\n\t *  UnicodeCombiningMark -> categories Mn, Mc\n\t *  UnicodeDigit -> categories Nd\n\t *  UnicodeConnectorPunctuation -> categories Pc\n\t */\n\n\t/* ASCII (and EOF) fast path -- quick accept and reject */\n\tif (cp <= 0x7fL) {\n#if defined(DUK_USE_IDCHAR_FASTPATH)\n\t\treturn (cp >= 0) && (duk_is_idchar_tab[cp] != 0);\n#else\n\t\tif ((cp >= 'a' && cp <= 'z') ||\n\t\t    (cp >= 'A' && cp <= 'Z') ||\n\t\t    (cp >= '0' && cp <= '9') ||\n\t\t    cp == '_' || cp == '$') {\n\t\t\treturn 1;\n\t\t}\n\t\treturn 0;\n#endif\n\t}\n\n\t/* Non-ASCII slow path (range-by-range linear comparison), very slow */\n\n#if defined(DUK_USE_SOURCE_NONBMP)\n\tif (duk__uni_range_match(duk_unicode_ids_noa,\n\t                         sizeof(duk_unicode_ids_noa),\n\t                         (duk_codepoint_t) cp) ||\n\t    duk__uni_range_match(duk_unicode_idp_m_ids_noa,\n\t                         sizeof(duk_unicode_idp_m_ids_noa),\n\t                         (duk_codepoint_t) cp)) {\n\t\treturn 1;\n\t}\n\treturn 0;\n#else\n\tif (cp < 0x10000L) {\n\t\tif (duk__uni_range_match(duk_unicode_ids_noabmp,\n\t\t                         sizeof(duk_unicode_ids_noabmp),\n\t\t                         (duk_codepoint_t) cp) ||\n\t\t    duk__uni_range_match(duk_unicode_idp_m_ids_noabmp,\n\t\t                         sizeof(duk_unicode_idp_m_ids_noabmp),\n\t\t                         (duk_codepoint_t) cp)) {\n\t\t\treturn 1;\n\t\t}\n\t\treturn 0;\n\t} else {\n\t\t/* without explicit non-BMP support, assume non-BMP characters\n\t\t * are always accepted as identifier characters.\n\t\t */\n\t\treturn 1;\n\t}\n#endif\n}\n\n/*\n *  Unicode letter check.\n */\n\nDUK_INTERNAL duk_small_int_t duk_unicode_is_letter(duk_codepoint_t cp) {\n\t/*\n\t *  Unicode letter is now taken to be the categories:\n\t *\n\t *    Lu, Ll, Lt, Lm, Lo\n\t *\n\t *  (Not sure if this is exactly correct.)\n\t *\n\t *  The ASCII fast path consists of:\n\t *\n\t *    0x0041 ... 0x005a     ['A' ... 'Z']\n\t *    0x0061 ... 0x007a     ['a' ... 'z']\n\t */\n\n\t/* ASCII (and EOF) fast path -- quick accept and reject */\n\tif (cp <= 0x7fL) {\n\t\tif ((cp >= 'a' && cp <= 'z') ||\n\t\t    (cp >= 'A' && cp <= 'Z')) {\n\t\t\treturn 1;\n\t\t}\n\t\treturn 0;\n\t}\n\n\t/* Non-ASCII slow path (range-by-range linear comparison), very slow */\n\n#if defined(DUK_USE_SOURCE_NONBMP)\n\tif (duk__uni_range_match(duk_unicode_ids_noa,\n\t                         sizeof(duk_unicode_ids_noa),\n\t                         (duk_codepoint_t) cp) &&\n\t    !duk__uni_range_match(duk_unicode_ids_m_let_noa,\n\t                          sizeof(duk_unicode_ids_m_let_noa),\n\t                          (duk_codepoint_t) cp)) {\n\t\treturn 1;\n\t}\n\treturn 0;\n#else\n\tif (cp < 0x10000L) {\n\t\tif (duk__uni_range_match(duk_unicode_ids_noabmp,\n\t\t                         sizeof(duk_unicode_ids_noabmp),\n\t\t                         (duk_codepoint_t) cp) &&\n\t\t    !duk__uni_range_match(duk_unicode_ids_m_let_noabmp,\n\t\t                          sizeof(duk_unicode_ids_m_let_noabmp),\n\t\t                          (duk_codepoint_t) cp)) {\n\t\t\treturn 1;\n\t\t}\n\t\treturn 0;\n\t} else {\n\t\t/* without explicit non-BMP support, assume non-BMP characters\n\t\t * are always accepted as letters.\n\t\t */\n\t\treturn 1;\n\t}\n#endif\n}\n\n/*\n *  Complex case conversion helper which decodes a bit-packed conversion\n *  control stream generated by tools/extract_caseconv.py.  The conversion\n *  is very slow because it runs through the conversion data in a linear\n *  fashion to save space (which is why ASCII characters have a special\n *  fast path before arriving here).\n *\n *  The particular bit counts etc have been determined experimentally to\n *  be small but still sufficient, and must match the Python script\n *  (tools/extract_caseconv.py).\n *\n *  The return value is the case converted codepoint or -1 if the conversion\n *  results in multiple characters (this is useful for regexp Canonicalization\n *  operation).  If 'buf' is not NULL, the result codepoint(s) are also\n *  appended to the hbuffer.\n *\n *  Context and locale specific rules must be checked before consulting\n *  this function.\n */\n\nDUK_LOCAL\nduk_codepoint_t duk__slow_case_conversion(duk_hthread *thr,\n                                          duk_bufwriter_ctx *bw,\n                                          duk_codepoint_t cp,\n                                          duk_bitdecoder_ctx *bd_ctx) {\n\tduk_small_int_t skip = 0;\n\tduk_small_int_t n;\n\tduk_small_int_t t;\n\tduk_small_int_t count;\n\tduk_codepoint_t tmp_cp;\n\tduk_codepoint_t start_i;\n\tduk_codepoint_t start_o;\n\n\tDUK_ASSERT(bd_ctx != NULL);\n\tDUK_UNREF(thr);\n\n\tDUK_DDD(DUK_DDDPRINT(\"slow case conversion for codepoint: %ld\", (long) cp));\n\n\t/* range conversion with a \"skip\" */\n\tDUK_DDD(DUK_DDDPRINT(\"checking ranges\"));\n\tfor (;;) {\n\t\tskip++;\n\t\tn = (duk_small_int_t) duk_bd_decode(bd_ctx, 6);\n\t\tif (n == 0x3f) {\n\t\t\t/* end marker */\n\t\t\tbreak;\n\t\t}\n\t\tDUK_DDD(DUK_DDDPRINT(\"skip=%ld, n=%ld\", (long) skip, (long) n));\n\n\t\twhile (n--) {\n\t\t\tstart_i = (duk_codepoint_t) duk_bd_decode(bd_ctx, 16);\n\t\t\tstart_o = (duk_codepoint_t) duk_bd_decode(bd_ctx, 16);\n\t\t\tcount = (duk_small_int_t) duk_bd_decode(bd_ctx, 7);\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"range: start_i=%ld, start_o=%ld, count=%ld, skip=%ld\",\n\t\t\t                     (long) start_i, (long) start_o, (long) count, (long) skip));\n\n\t\t\tif (cp >= start_i) {\n\t\t\t\ttmp_cp = cp - start_i;  /* always >= 0 */\n\t\t\t\tif (tmp_cp < (duk_codepoint_t) count * (duk_codepoint_t) skip &&\n\t\t\t\t    (tmp_cp % (duk_codepoint_t) skip) == 0) {\n\t\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"range matches input codepoint\"));\n\t\t\t\t\tcp = start_o + tmp_cp;\n\t\t\t\t\tgoto single;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/* 1:1 conversion */\n\tn = (duk_small_int_t) duk_bd_decode(bd_ctx, 7);\n\tDUK_DDD(DUK_DDDPRINT(\"checking 1:1 conversions (count %ld)\", (long) n));\n\twhile (n--) {\n\t\tstart_i = (duk_codepoint_t) duk_bd_decode(bd_ctx, 16);\n\t\tstart_o = (duk_codepoint_t) duk_bd_decode(bd_ctx, 16);\n\t\tDUK_DDD(DUK_DDDPRINT(\"1:1 conversion %ld -> %ld\", (long) start_i, (long) start_o));\n\t\tif (cp == start_i) {\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"1:1 matches input codepoint\"));\n\t\t\tcp = start_o;\n\t\t\tgoto single;\n\t\t}\n\t}\n\n\t/* complex, multicharacter conversion */\n\tn = (duk_small_int_t) duk_bd_decode(bd_ctx, 7);\n\tDUK_DDD(DUK_DDDPRINT(\"checking 1:n conversions (count %ld)\", (long) n));\n\twhile (n--) {\n\t\tstart_i = (duk_codepoint_t) duk_bd_decode(bd_ctx, 16);\n\t\tt = (duk_small_int_t) duk_bd_decode(bd_ctx, 2);\n\t\tDUK_DDD(DUK_DDDPRINT(\"1:n conversion %ld -> %ld chars\", (long) start_i, (long) t));\n\t\tif (cp == start_i) {\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"1:n matches input codepoint\"));\n\t\t\tif (bw != NULL) {\n\t\t\t\twhile (t--) {\n\t\t\t\t\ttmp_cp = (duk_codepoint_t) duk_bd_decode(bd_ctx, 16);\n\t\t\t\t\tDUK_BW_WRITE_RAW_XUTF8(thr, bw, (duk_ucodepoint_t) tmp_cp);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn -1;\n\t\t} else {\n\t\t\twhile (t--) {\n\t\t\t\t(void) duk_bd_decode(bd_ctx, 16);\n\t\t\t}\n\t\t}\n\t}\n\n\t/* default: no change */\n\tDUK_DDD(DUK_DDDPRINT(\"no rule matches, output is same as input\"));\n\t/* fall through */\n\n single:\n\tif (bw != NULL) {\n\t\tDUK_BW_WRITE_RAW_XUTF8(thr, bw, (duk_ucodepoint_t) cp);\n\t}\n\treturn cp;\n}\n\n/*\n *  Case conversion helper, with context/local sensitivity.\n *  For proper case conversion, one needs to know the character\n *  and the preceding and following characters, as well as\n *  locale/language.\n */\n\n/* XXX: add 'language' argument when locale/language sensitive rule\n * support added.\n */\nDUK_LOCAL\nduk_codepoint_t duk__case_transform_helper(duk_hthread *thr,\n                                           duk_bufwriter_ctx *bw,\n                                           duk_codepoint_t cp,\n                                           duk_codepoint_t prev,\n                                           duk_codepoint_t next,\n                                           duk_bool_t uppercase) {\n\tduk_bitdecoder_ctx bd_ctx;\n\n\t/* fast path for ASCII */\n\tif (cp < 0x80L) {\n\t\t/* XXX: there are language sensitive rules for the ASCII range.\n\t\t * If/when language/locale support is implemented, they need to\n\t\t * be implemented here for the fast path.  There are no context\n\t\t * sensitive rules for ASCII range.\n\t\t */\n\n\t\tif (uppercase) {\n\t\t\tif (cp >= 'a' && cp <= 'z') {\n\t\t\t\tcp = cp - 'a' + 'A';\n\t\t\t}\n\t\t} else {\n\t\t\tif (cp >= 'A' && cp <= 'Z') {\n\t\t\t\tcp = cp - 'A' + 'a';\n\t\t\t}\n\t\t}\n\n\t\tif (bw != NULL) {\n\t\t\tDUK_BW_WRITE_RAW_U8(thr, bw, (duk_uint8_t) cp);\n\t\t}\n\t\treturn cp;\n\t}\n\n\t/* context and locale specific rules which cannot currently be represented\n\t * in the caseconv bitstream: hardcoded rules in C\n\t */\n\tif (uppercase) {\n\t\t/* XXX: turkish / azeri */\n\t} else {\n\t\t/*\n\t\t *  Final sigma context specific rule.  This is a rather tricky\n\t\t *  rule and this handling is probably not 100% correct now.\n\t\t *  The rule is not locale/language specific so it is supported.\n\t\t */\n\n\t\tif (cp == 0x03a3L &&    /* U+03A3 = GREEK CAPITAL LETTER SIGMA */\n\t\t    duk_unicode_is_letter(prev) &&        /* prev exists and is not a letter */\n\t\t    !duk_unicode_is_letter(next)) {       /* next does not exist or next is not a letter */\n\t\t\t/* Capital sigma occurred at \"end of word\", lowercase to\n\t\t\t * U+03C2 = GREEK SMALL LETTER FINAL SIGMA.  Otherwise\n\t\t\t * fall through and let the normal rules lowercase it to\n\t\t\t * U+03C3 = GREEK SMALL LETTER SIGMA.\n\t\t\t */\n\t\t\tcp = 0x03c2L;\n\t\t\tgoto singlechar;\n\t\t}\n\n\t\t/* XXX: lithuanian not implemented */\n\t\t/* XXX: lithuanian, explicit dot rules */\n\t\t/* XXX: turkish / azeri, lowercase rules */\n\t}\n\n\t/* 1:1 or special conversions, but not locale/context specific: script generated rules */\n\tDUK_MEMZERO(&bd_ctx, sizeof(bd_ctx));\n\tif (uppercase) {\n\t\tbd_ctx.data = (const duk_uint8_t *) duk_unicode_caseconv_uc;\n\t\tbd_ctx.length = (duk_size_t) sizeof(duk_unicode_caseconv_uc);\n\t} else {\n\t\tbd_ctx.data = (const duk_uint8_t *) duk_unicode_caseconv_lc;\n\t\tbd_ctx.length = (duk_size_t) sizeof(duk_unicode_caseconv_lc);\n\t}\n\treturn duk__slow_case_conversion(thr, bw, cp, &bd_ctx);\n\n singlechar:\n\tif (bw != NULL) {\n\t\tDUK_BW_WRITE_RAW_XUTF8(thr, bw, (duk_ucodepoint_t) cp);\n\t}\n\treturn cp;\n\n /* unused now, not needed until Turkish/Azeri */\n#if 0\n nochar:\n\treturn -1;\n#endif\n}\n\n/*\n *  Replace valstack top with case converted version.\n */\n\nDUK_INTERNAL void duk_unicode_case_convert_string(duk_hthread *thr, duk_bool_t uppercase) {\n\tduk_hstring *h_input;\n\tduk_bufwriter_ctx bw_alloc;\n\tduk_bufwriter_ctx *bw;\n\tconst duk_uint8_t *p, *p_start, *p_end;\n\tduk_codepoint_t prev, curr, next;\n\n\th_input = duk_require_hstring(thr, -1);  /* Accept symbols. */\n\tDUK_ASSERT(h_input != NULL);\n\n\tbw = &bw_alloc;\n\tDUK_BW_INIT_PUSHBUF(thr, bw, DUK_HSTRING_GET_BYTELEN(h_input));\n\n\t/* [ ... input buffer ] */\n\n\tp_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input);\n\tp_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input);\n\tp = p_start;\n\n\tprev = -1; DUK_UNREF(prev);\n\tcurr = -1;\n\tnext = -1;\n\tfor (;;) {\n\t\tprev = curr;\n\t\tcurr = next;\n\t\tnext = -1;\n\t\tif (p < p_end) {\n\t\t\tnext = (duk_codepoint_t) duk_unicode_decode_xutf8_checked(thr, &p, p_start, p_end);\n\t\t} else {\n\t\t\t/* end of input and last char has been processed */\n\t\t\tif (curr < 0) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t/* on first round, skip */\n\t\tif (curr >= 0) {\n\t\t\t/* XXX: could add a fast path to process chunks of input codepoints,\n\t\t\t * but relative benefit would be quite small.\n\t\t\t */\n\n\t\t\t/* Ensure space for maximum multi-character result; estimate is overkill. */\n\t\t\tDUK_BW_ENSURE(thr, bw, 8 * DUK_UNICODE_MAX_XUTF8_LENGTH);\n\n\t\t\tduk__case_transform_helper(thr,\n\t\t\t                           bw,\n\t\t\t                           (duk_codepoint_t) curr,\n\t\t\t                           prev,\n\t\t\t                           next,\n\t\t\t                           uppercase);\n\t\t}\n\t}\n\n\tDUK_BW_COMPACT(thr, bw);\n\t(void) duk_buffer_to_string(thr, -1);  /* Safe, output is encoded. */\n\t/* invalidates h_buf pointer */\n\tduk_remove_m2(thr);\n}\n\n#if defined(DUK_USE_REGEXP_SUPPORT)\n\n/*\n *  Canonicalize() abstract operation needed for canonicalization of individual\n *  codepoints during regexp compilation and execution, see E5 Section 15.10.2.8.\n *  Note that codepoints are canonicalized one character at a time, so no context\n *  specific rules can apply.  Locale specific rules can apply, though.\n */\n\nDUK_INTERNAL duk_codepoint_t duk_unicode_re_canonicalize_char(duk_hthread *thr, duk_codepoint_t cp) {\n#if defined(DUK_USE_REGEXP_CANON_WORKAROUND)\n\t/* Fast canonicalization lookup at the cost of 128kB footprint. */\n\tDUK_ASSERT(cp >= 0);\n\tDUK_UNREF(thr);\n\tif (DUK_LIKELY(cp < 0x10000L)) {\n\t\treturn (duk_codepoint_t) duk_unicode_re_canon_lookup[cp];\n\t}\n\treturn cp;\n#else  /* DUK_USE_REGEXP_CANON_WORKAROUND */\n\tduk_codepoint_t y;\n\n\ty = duk__case_transform_helper(thr,\n\t                               NULL,    /* NULL is allowed, no output */\n\t                               cp,      /* curr char */\n\t                               -1,      /* prev char */\n\t                               -1,      /* next char */\n\t                               1);      /* uppercase */\n\n\tif ((y < 0) || (cp >= 0x80 && y < 0x80)) {\n\t\t/* multiple codepoint conversion or non-ASCII mapped to ASCII\n\t\t * --> leave as is.\n\t\t */\n\t\treturn cp;\n\t}\n\n\treturn y;\n#endif  /* DUK_USE_REGEXP_CANON_WORKAROUND */\n}\n\n/*\n *  E5 Section 15.10.2.6 \"IsWordChar\" abstract operation.  Assume\n *  x < 0 for characters read outside the string.\n */\n\nDUK_INTERNAL duk_small_int_t duk_unicode_re_is_wordchar(duk_codepoint_t x) {\n\t/*\n\t *  Note: the description in E5 Section 15.10.2.6 has a typo, it\n\t *  contains 'A' twice and lacks 'a'; the intent is [0-9a-zA-Z_].\n\t */\n\tif ((x >= '0' && x <= '9') ||\n\t    (x >= 'a' && x <= 'z') ||\n\t    (x >= 'A' && x <= 'Z') ||\n\t    (x == '_')) {\n\t\treturn 1;\n\t}\n\treturn 0;\n}\n\n/*\n *  Regexp range tables\n */\n\n/* exposed because lexer needs these too */\nDUK_INTERNAL const duk_uint16_t duk_unicode_re_ranges_digit[2] = {\n\t(duk_uint16_t) 0x0030UL, (duk_uint16_t) 0x0039UL,\n};\nDUK_INTERNAL const duk_uint16_t duk_unicode_re_ranges_white[22] = {\n\t(duk_uint16_t) 0x0009UL, (duk_uint16_t) 0x000DUL,\n\t(duk_uint16_t) 0x0020UL, (duk_uint16_t) 0x0020UL,\n\t(duk_uint16_t) 0x00A0UL, (duk_uint16_t) 0x00A0UL,\n\t(duk_uint16_t) 0x1680UL, (duk_uint16_t) 0x1680UL,\n\t(duk_uint16_t) 0x180EUL, (duk_uint16_t) 0x180EUL,\n\t(duk_uint16_t) 0x2000UL, (duk_uint16_t) 0x200AUL,\n\t(duk_uint16_t) 0x2028UL, (duk_uint16_t) 0x2029UL,\n\t(duk_uint16_t) 0x202FUL, (duk_uint16_t) 0x202FUL,\n\t(duk_uint16_t) 0x205FUL, (duk_uint16_t) 0x205FUL,\n\t(duk_uint16_t) 0x3000UL, (duk_uint16_t) 0x3000UL,\n\t(duk_uint16_t) 0xFEFFUL, (duk_uint16_t) 0xFEFFUL,\n};\nDUK_INTERNAL const duk_uint16_t duk_unicode_re_ranges_wordchar[8] = {\n\t(duk_uint16_t) 0x0030UL, (duk_uint16_t) 0x0039UL,\n\t(duk_uint16_t) 0x0041UL, (duk_uint16_t) 0x005AUL,\n\t(duk_uint16_t) 0x005FUL, (duk_uint16_t) 0x005FUL,\n\t(duk_uint16_t) 0x0061UL, (duk_uint16_t) 0x007AUL,\n};\nDUK_INTERNAL const duk_uint16_t duk_unicode_re_ranges_not_digit[4] = {\n\t(duk_uint16_t) 0x0000UL, (duk_uint16_t) 0x002FUL,\n\t(duk_uint16_t) 0x003AUL, (duk_uint16_t) 0xFFFFUL,\n};\nDUK_INTERNAL const duk_uint16_t duk_unicode_re_ranges_not_white[24] = {\n\t(duk_uint16_t) 0x0000UL, (duk_uint16_t) 0x0008UL,\n\t(duk_uint16_t) 0x000EUL, (duk_uint16_t) 0x001FUL,\n\t(duk_uint16_t) 0x0021UL, (duk_uint16_t) 0x009FUL,\n\t(duk_uint16_t) 0x00A1UL, (duk_uint16_t) 0x167FUL,\n\t(duk_uint16_t) 0x1681UL, (duk_uint16_t) 0x180DUL,\n\t(duk_uint16_t) 0x180FUL, (duk_uint16_t) 0x1FFFUL,\n\t(duk_uint16_t) 0x200BUL, (duk_uint16_t) 0x2027UL,\n\t(duk_uint16_t) 0x202AUL, (duk_uint16_t) 0x202EUL,\n\t(duk_uint16_t) 0x2030UL, (duk_uint16_t) 0x205EUL,\n\t(duk_uint16_t) 0x2060UL, (duk_uint16_t) 0x2FFFUL,\n\t(duk_uint16_t) 0x3001UL, (duk_uint16_t) 0xFEFEUL,\n\t(duk_uint16_t) 0xFF00UL, (duk_uint16_t) 0xFFFFUL,\n};\nDUK_INTERNAL const duk_uint16_t duk_unicode_re_ranges_not_wordchar[10] = {\n\t(duk_uint16_t) 0x0000UL, (duk_uint16_t) 0x002FUL,\n\t(duk_uint16_t) 0x003AUL, (duk_uint16_t) 0x0040UL,\n\t(duk_uint16_t) 0x005BUL, (duk_uint16_t) 0x005EUL,\n\t(duk_uint16_t) 0x0060UL, (duk_uint16_t) 0x0060UL,\n\t(duk_uint16_t) 0x007BUL, (duk_uint16_t) 0xFFFFUL,\n};\n\n#endif  /* DUK_USE_REGEXP_SUPPORT */\n#line 1 \"duk_util_misc.c\"\n/*\n *  Misc util stuff\n */\n\n/* #include duk_internal.h -> already included */\n\n/*\n *  Lowercase digits for radix values 2 to 36.  Also doubles as lowercase\n *  hex nybble table.\n */\n\nDUK_INTERNAL const duk_uint8_t duk_lc_digits[36] = {\n\tDUK_ASC_0, DUK_ASC_1, DUK_ASC_2, DUK_ASC_3,\n\tDUK_ASC_4, DUK_ASC_5, DUK_ASC_6, DUK_ASC_7,\n\tDUK_ASC_8, DUK_ASC_9, DUK_ASC_LC_A, DUK_ASC_LC_B,\n\tDUK_ASC_LC_C, DUK_ASC_LC_D, DUK_ASC_LC_E, DUK_ASC_LC_F,\n\tDUK_ASC_LC_G, DUK_ASC_LC_H, DUK_ASC_LC_I, DUK_ASC_LC_J,\n\tDUK_ASC_LC_K, DUK_ASC_LC_L, DUK_ASC_LC_M, DUK_ASC_LC_N,\n\tDUK_ASC_LC_O, DUK_ASC_LC_P, DUK_ASC_LC_Q, DUK_ASC_LC_R,\n\tDUK_ASC_LC_S, DUK_ASC_LC_T, DUK_ASC_LC_U, DUK_ASC_LC_V,\n\tDUK_ASC_LC_W, DUK_ASC_LC_X, DUK_ASC_LC_Y, DUK_ASC_LC_Z\n};\n\nDUK_INTERNAL const duk_uint8_t duk_uc_nybbles[16] = {\n\tDUK_ASC_0, DUK_ASC_1, DUK_ASC_2, DUK_ASC_3,\n\tDUK_ASC_4, DUK_ASC_5, DUK_ASC_6, DUK_ASC_7,\n\tDUK_ASC_8, DUK_ASC_9, DUK_ASC_UC_A, DUK_ASC_UC_B,\n\tDUK_ASC_UC_C, DUK_ASC_UC_D, DUK_ASC_UC_E, DUK_ASC_UC_F\n};\n\n/*\n *  Table for hex decoding ASCII hex digits\n */\n\nDUK_INTERNAL const duk_int8_t duk_hex_dectab[256] = {\n\t/* -1 if invalid */\n\t-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x00-0x0f */\n\t-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x10-0x1f */\n\t-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x20-0x2f */\n\t 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, -1, -1, -1, -1, -1, -1,  /* 0x30-0x3f */\n\t-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x40-0x4f */\n\t-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x50-0x5f */\n\t-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x60-0x6f */\n\t-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x70-0x7f */\n\t-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x80-0x8f */\n\t-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x90-0x9f */\n\t-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0xa0-0xaf */\n\t-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0xb0-0xbf */\n\t-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0xc0-0xcf */\n\t-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0xd0-0xdf */\n\t-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0xe0-0xef */\n\t-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1   /* 0xf0-0xff */\n};\n\n#if defined(DUK_USE_HEX_FASTPATH)\n/* Preshifted << 4.  Must use 16-bit entry to allow negative value signaling. */\nDUK_INTERNAL const duk_int16_t duk_hex_dectab_shift4[256] = {\n\t  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0x00-0x0f */\n\t  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0x10-0x1f */\n\t  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0x20-0x2f */\n\t0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, 0x90,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0x30-0x3f */\n\t  -1, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0x40-0x4f */\n\t  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0x50-0x5f */\n\t  -1, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0x60-0x6f */\n\t  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0x70-0x7f */\n\t  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0x80-0x8f */\n\t  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0x90-0x9f */\n\t  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0xa0-0xaf */\n\t  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0xb0-0xbf */\n\t  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0xc0-0xcf */\n\t  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0xd0-0xdf */\n\t  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0xe0-0xef */\n\t  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1   /* 0xf0-0xff */\n};\n#endif\n\n/*\n *  Table for hex encoding bytes\n */\n\n#if defined(DUK_USE_HEX_FASTPATH)\n/* Lookup to encode one byte directly into 2 characters:\n *\n *   def genhextab(bswap):\n *       for i in xrange(256):\n *           t = chr(i).encode('hex')\n *           if bswap:\n *               t = t[1] + t[0]\n *           print('0x' + t.encode('hex') + 'U')\n *   print('big endian'); genhextab(False)\n *   print('little endian'); genhextab(True)\n*/\nDUK_INTERNAL const duk_uint16_t duk_hex_enctab[256] = {\n#if defined(DUK_USE_INTEGER_BE)\n\t0x3030U, 0x3031U, 0x3032U, 0x3033U, 0x3034U, 0x3035U, 0x3036U, 0x3037U,\n\t0x3038U, 0x3039U, 0x3061U, 0x3062U, 0x3063U, 0x3064U, 0x3065U, 0x3066U,\n\t0x3130U, 0x3131U, 0x3132U, 0x3133U, 0x3134U, 0x3135U, 0x3136U, 0x3137U,\n\t0x3138U, 0x3139U, 0x3161U, 0x3162U, 0x3163U, 0x3164U, 0x3165U, 0x3166U,\n\t0x3230U, 0x3231U, 0x3232U, 0x3233U, 0x3234U, 0x3235U, 0x3236U, 0x3237U,\n\t0x3238U, 0x3239U, 0x3261U, 0x3262U, 0x3263U, 0x3264U, 0x3265U, 0x3266U,\n\t0x3330U, 0x3331U, 0x3332U, 0x3333U, 0x3334U, 0x3335U, 0x3336U, 0x3337U,\n\t0x3338U, 0x3339U, 0x3361U, 0x3362U, 0x3363U, 0x3364U, 0x3365U, 0x3366U,\n\t0x3430U, 0x3431U, 0x3432U, 0x3433U, 0x3434U, 0x3435U, 0x3436U, 0x3437U,\n\t0x3438U, 0x3439U, 0x3461U, 0x3462U, 0x3463U, 0x3464U, 0x3465U, 0x3466U,\n\t0x3530U, 0x3531U, 0x3532U, 0x3533U, 0x3534U, 0x3535U, 0x3536U, 0x3537U,\n\t0x3538U, 0x3539U, 0x3561U, 0x3562U, 0x3563U, 0x3564U, 0x3565U, 0x3566U,\n\t0x3630U, 0x3631U, 0x3632U, 0x3633U, 0x3634U, 0x3635U, 0x3636U, 0x3637U,\n\t0x3638U, 0x3639U, 0x3661U, 0x3662U, 0x3663U, 0x3664U, 0x3665U, 0x3666U,\n\t0x3730U, 0x3731U, 0x3732U, 0x3733U, 0x3734U, 0x3735U, 0x3736U, 0x3737U,\n\t0x3738U, 0x3739U, 0x3761U, 0x3762U, 0x3763U, 0x3764U, 0x3765U, 0x3766U,\n\t0x3830U, 0x3831U, 0x3832U, 0x3833U, 0x3834U, 0x3835U, 0x3836U, 0x3837U,\n\t0x3838U, 0x3839U, 0x3861U, 0x3862U, 0x3863U, 0x3864U, 0x3865U, 0x3866U,\n\t0x3930U, 0x3931U, 0x3932U, 0x3933U, 0x3934U, 0x3935U, 0x3936U, 0x3937U,\n\t0x3938U, 0x3939U, 0x3961U, 0x3962U, 0x3963U, 0x3964U, 0x3965U, 0x3966U,\n\t0x6130U, 0x6131U, 0x6132U, 0x6133U, 0x6134U, 0x6135U, 0x6136U, 0x6137U,\n\t0x6138U, 0x6139U, 0x6161U, 0x6162U, 0x6163U, 0x6164U, 0x6165U, 0x6166U,\n\t0x6230U, 0x6231U, 0x6232U, 0x6233U, 0x6234U, 0x6235U, 0x6236U, 0x6237U,\n\t0x6238U, 0x6239U, 0x6261U, 0x6262U, 0x6263U, 0x6264U, 0x6265U, 0x6266U,\n\t0x6330U, 0x6331U, 0x6332U, 0x6333U, 0x6334U, 0x6335U, 0x6336U, 0x6337U,\n\t0x6338U, 0x6339U, 0x6361U, 0x6362U, 0x6363U, 0x6364U, 0x6365U, 0x6366U,\n\t0x6430U, 0x6431U, 0x6432U, 0x6433U, 0x6434U, 0x6435U, 0x6436U, 0x6437U,\n\t0x6438U, 0x6439U, 0x6461U, 0x6462U, 0x6463U, 0x6464U, 0x6465U, 0x6466U,\n\t0x6530U, 0x6531U, 0x6532U, 0x6533U, 0x6534U, 0x6535U, 0x6536U, 0x6537U,\n\t0x6538U, 0x6539U, 0x6561U, 0x6562U, 0x6563U, 0x6564U, 0x6565U, 0x6566U,\n\t0x6630U, 0x6631U, 0x6632U, 0x6633U, 0x6634U, 0x6635U, 0x6636U, 0x6637U,\n\t0x6638U, 0x6639U, 0x6661U, 0x6662U, 0x6663U, 0x6664U, 0x6665U, 0x6666U\n#else  /* DUK_USE_INTEGER_BE */\n\t0x3030U, 0x3130U, 0x3230U, 0x3330U, 0x3430U, 0x3530U, 0x3630U, 0x3730U,\n\t0x3830U, 0x3930U, 0x6130U, 0x6230U, 0x6330U, 0x6430U, 0x6530U, 0x6630U,\n\t0x3031U, 0x3131U, 0x3231U, 0x3331U, 0x3431U, 0x3531U, 0x3631U, 0x3731U,\n\t0x3831U, 0x3931U, 0x6131U, 0x6231U, 0x6331U, 0x6431U, 0x6531U, 0x6631U,\n\t0x3032U, 0x3132U, 0x3232U, 0x3332U, 0x3432U, 0x3532U, 0x3632U, 0x3732U,\n\t0x3832U, 0x3932U, 0x6132U, 0x6232U, 0x6332U, 0x6432U, 0x6532U, 0x6632U,\n\t0x3033U, 0x3133U, 0x3233U, 0x3333U, 0x3433U, 0x3533U, 0x3633U, 0x3733U,\n\t0x3833U, 0x3933U, 0x6133U, 0x6233U, 0x6333U, 0x6433U, 0x6533U, 0x6633U,\n\t0x3034U, 0x3134U, 0x3234U, 0x3334U, 0x3434U, 0x3534U, 0x3634U, 0x3734U,\n\t0x3834U, 0x3934U, 0x6134U, 0x6234U, 0x6334U, 0x6434U, 0x6534U, 0x6634U,\n\t0x3035U, 0x3135U, 0x3235U, 0x3335U, 0x3435U, 0x3535U, 0x3635U, 0x3735U,\n\t0x3835U, 0x3935U, 0x6135U, 0x6235U, 0x6335U, 0x6435U, 0x6535U, 0x6635U,\n\t0x3036U, 0x3136U, 0x3236U, 0x3336U, 0x3436U, 0x3536U, 0x3636U, 0x3736U,\n\t0x3836U, 0x3936U, 0x6136U, 0x6236U, 0x6336U, 0x6436U, 0x6536U, 0x6636U,\n\t0x3037U, 0x3137U, 0x3237U, 0x3337U, 0x3437U, 0x3537U, 0x3637U, 0x3737U,\n\t0x3837U, 0x3937U, 0x6137U, 0x6237U, 0x6337U, 0x6437U, 0x6537U, 0x6637U,\n\t0x3038U, 0x3138U, 0x3238U, 0x3338U, 0x3438U, 0x3538U, 0x3638U, 0x3738U,\n\t0x3838U, 0x3938U, 0x6138U, 0x6238U, 0x6338U, 0x6438U, 0x6538U, 0x6638U,\n\t0x3039U, 0x3139U, 0x3239U, 0x3339U, 0x3439U, 0x3539U, 0x3639U, 0x3739U,\n\t0x3839U, 0x3939U, 0x6139U, 0x6239U, 0x6339U, 0x6439U, 0x6539U, 0x6639U,\n\t0x3061U, 0x3161U, 0x3261U, 0x3361U, 0x3461U, 0x3561U, 0x3661U, 0x3761U,\n\t0x3861U, 0x3961U, 0x6161U, 0x6261U, 0x6361U, 0x6461U, 0x6561U, 0x6661U,\n\t0x3062U, 0x3162U, 0x3262U, 0x3362U, 0x3462U, 0x3562U, 0x3662U, 0x3762U,\n\t0x3862U, 0x3962U, 0x6162U, 0x6262U, 0x6362U, 0x6462U, 0x6562U, 0x6662U,\n\t0x3063U, 0x3163U, 0x3263U, 0x3363U, 0x3463U, 0x3563U, 0x3663U, 0x3763U,\n\t0x3863U, 0x3963U, 0x6163U, 0x6263U, 0x6363U, 0x6463U, 0x6563U, 0x6663U,\n\t0x3064U, 0x3164U, 0x3264U, 0x3364U, 0x3464U, 0x3564U, 0x3664U, 0x3764U,\n\t0x3864U, 0x3964U, 0x6164U, 0x6264U, 0x6364U, 0x6464U, 0x6564U, 0x6664U,\n\t0x3065U, 0x3165U, 0x3265U, 0x3365U, 0x3465U, 0x3565U, 0x3665U, 0x3765U,\n\t0x3865U, 0x3965U, 0x6165U, 0x6265U, 0x6365U, 0x6465U, 0x6565U, 0x6665U,\n\t0x3066U, 0x3166U, 0x3266U, 0x3366U, 0x3466U, 0x3566U, 0x3666U, 0x3766U,\n\t0x3866U, 0x3966U, 0x6166U, 0x6266U, 0x6366U, 0x6466U, 0x6566U, 0x6666U\n#endif  /* DUK_USE_INTEGER_BE */\n};\n#endif  /* DUK_USE_HEX_FASTPATH */\n\n/*\n *  Table for base-64 encoding\n */\n\n#if defined(DUK_USE_BASE64_FASTPATH)\nDUK_INTERNAL const duk_uint8_t duk_base64_enctab[64] = {\n\t0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50,  /* A...P */\n\t0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66,  /* Q...f */\n\t0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76,  /* g...v */\n\t0x77, 0x78, 0x79, 0x7a, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x2b, 0x2f   /* w.../ */\n};\n#endif  /* DUK_USE_BASE64_FASTPATH */\n\n/*\n *  Table for base-64 decoding\n */\n\n#if defined(DUK_USE_BASE64_FASTPATH)\nDUK_INTERNAL const duk_int8_t duk_base64_dectab[256] = {\n\t/* -1 = error, -2 = allowed whitespace, -3 = padding ('='), 0...63 decoded bytes */\n\t-1, -1, -1, -1, -1, -1, -1, -1, -1, -2, -2, -1, -1, -2, -1, -1,  /* 0x00...0x0f */\n\t-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x10...0x1f */\n\t-2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,  /* 0x20...0x2f */\n\t52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -3, -1, -1,  /* 0x30...0x3f */\n\t-1,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,  /* 0x40...0x4f */\n\t15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,  /* 0x50...0x5f */\n\t-1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,  /* 0x60...0x6f */\n\t41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1,  /* 0x70...0x7f */\n\t-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x80...0x8f */\n\t-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x90...0x9f */\n\t-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0xa0...0xaf */\n\t-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0xb0...0xbf */\n\t-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0xc0...0xcf */\n\t-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0xd0...0xdf */\n\t-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0xe0...0xef */\n\t-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1   /* 0xf0...0xff */\n};\n#endif  /* DUK_USE_BASE64_FASTPATH */\n\n/*\n *  Arbitrary byteswap for potentially unaligned values\n *\n *  Used to byteswap pointers e.g. in debugger code.\n */\n\n#if defined(DUK_USE_DEBUGGER_SUPPORT)  /* For now only needed by the debugger. */\nDUK_INTERNAL void duk_byteswap_bytes(duk_uint8_t *p, duk_small_uint_t len) {\n\tduk_uint8_t tmp;\n\tduk_uint8_t *q = p + len - 1;\n\n\twhile (p - q < 0) {\n\t\ttmp = *p;\n\t\t*p = *q;\n\t\t*q = tmp;\n\t\tp++;\n\t\tq--;\n\t}\n}\n#endif\n\n/*\n *  Miscellaneous coercion / clamping helpers.\n */\n\n/* Check whether a duk_double_t is a whole number in the 32-bit range (reject\n * negative zero), and if so, return a duk_int32_t.\n * For compiler use: don't allow negative zero as it will cause trouble with\n * LDINT+LDINTX, positive zero is OK.\n */\nDUK_INTERNAL duk_bool_t duk_is_whole_get_int32_nonegzero(duk_double_t x, duk_int32_t *ival) {\n\tduk_int32_t t;\n\n\tt = (duk_int32_t) x;\n\tif (!((duk_double_t) t == x)) {\n\t\treturn 0;\n\t}\n\tif (t == 0) {\n\t\tduk_double_union du;\n\t\tdu.d = x;\n\t\tif (DUK_DBLUNION_HAS_SIGNBIT(&du)) {\n\t\t\treturn 0;\n\t\t}\n\t}\n\t*ival = t;\n\treturn 1;\n}\n\n/* Check whether a duk_double_t is a whole number in the 32-bit range, and if\n * so, return a duk_int32_t.\n */\nDUK_INTERNAL duk_bool_t duk_is_whole_get_int32(duk_double_t x, duk_int32_t *ival) {\n\tduk_int32_t t;\n\n\tt = (duk_int32_t) x;\n\tif (!((duk_double_t) t == x)) {\n\t\treturn 0;\n\t}\n\t*ival = t;\n\treturn 1;\n}\n\n/*\n *  IEEE double checks\n */\n\nDUK_INTERNAL duk_bool_t duk_double_is_anyinf(duk_double_t x) {\n\tduk_double_union du;\n\tdu.d = x;\n\treturn DUK_DBLUNION_IS_ANYINF(&du);\n}\n\nDUK_INTERNAL duk_bool_t duk_double_is_posinf(duk_double_t x) {\n\tduk_double_union du;\n\tdu.d = x;\n\treturn DUK_DBLUNION_IS_POSINF(&du);\n}\n\nDUK_INTERNAL duk_bool_t duk_double_is_neginf(duk_double_t x) {\n\tduk_double_union du;\n\tdu.d = x;\n\treturn DUK_DBLUNION_IS_NEGINF(&du);\n}\n\nDUK_INTERNAL duk_bool_t duk_double_is_nan(duk_double_t x) {\n\tduk_double_union du;\n\tdu.d = x;\n\t/* Assumes we're dealing with a Duktape internal NaN which is\n\t * NaN normalized if duk_tval requires it.\n\t */\n\tDUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&du));\n\treturn DUK_DBLUNION_IS_NAN(&du);\n}\n\nDUK_INTERNAL duk_bool_t duk_double_is_nan_or_zero(duk_double_t x) {\n\tduk_double_union du;\n\tdu.d = x;\n\t/* Assumes we're dealing with a Duktape internal NaN which is\n\t * NaN normalized if duk_tval requires it.\n\t */\n\tDUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&du));\n\treturn DUK_DBLUNION_IS_NAN(&du) || DUK_DBLUNION_IS_ANYZERO(&du);\n}\n\nDUK_INTERNAL duk_bool_t duk_double_is_nan_or_inf(duk_double_t x) {\n\tduk_double_union du;\n\tdu.d = x;\n\t/* If exponent is 0x7FF the argument is either a NaN or an\n\t * infinity.  We don't need to check any other fields.\n\t */\n#if defined(DUK_USE_64BIT_OPS)\n#if defined(DUK_USE_DOUBLE_ME)\n\treturn (du.ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x000000007ff00000)) == DUK_U64_CONSTANT(0x000000007ff00000);\n#else\n\treturn (du.ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x7ff0000000000000)) == DUK_U64_CONSTANT(0x7ff0000000000000);\n#endif\n#else\n\treturn (du.ui[DUK_DBL_IDX_UI0] & 0x7ff00000UL) == 0x7ff00000UL;\n#endif\n}\n\nDUK_INTERNAL duk_bool_t duk_double_is_nan_zero_inf(duk_double_t x) {\n\tduk_double_union du;\n#if defined(DUK_USE_64BIT_OPS)\n\tduk_uint64_t t;\n#else\n\tduk_uint32_t t;\n#endif\n\tdu.d = x;\n#if defined(DUK_USE_64BIT_OPS)\n#if defined(DUK_USE_DOUBLE_ME)\n\tt = du.ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x000000007ff00000);\n\tif (t == DUK_U64_CONSTANT(0x0000000000000000)) {\n\t\tt = du.ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x0000000080000000);\n\t\treturn t == 0;\n\t}\n\tif (t == DUK_U64_CONSTANT(0x000000007ff00000)) {\n\t\treturn 1;\n\t}\n#else\n\tt = du.ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x7ff0000000000000);\n\tif (t == DUK_U64_CONSTANT(0x0000000000000000)) {\n\t\tt = du.ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x8000000000000000);\n\t\treturn t == 0;\n\t}\n\tif (t == DUK_U64_CONSTANT(0x7ff0000000000000)) {\n\t\treturn 1;\n\t}\n#endif\n#else\n\tt = du.ui[DUK_DBL_IDX_UI0] & 0x7ff00000UL;\n\tif (t == 0x00000000UL) {\n\t\treturn DUK_DBLUNION_IS_ANYZERO(&du);\n\t}\n\tif (t == 0x7ff00000UL) {\n\t\treturn 1;\n\t}\n#endif\n\treturn 0;\n}\n\nDUK_INTERNAL duk_small_uint_t duk_double_signbit(duk_double_t x) {\n\tduk_double_union du;\n\tdu.d = x;\n\treturn (duk_small_uint_t) DUK_DBLUNION_GET_SIGNBIT(&du);\n}\n\nDUK_INTERNAL duk_double_t duk_double_trunc_towards_zero(duk_double_t x) {\n\t/* XXX: optimize */\n\tduk_small_uint_t s = duk_double_signbit(x);\n\tx = DUK_FLOOR(DUK_FABS(x));  /* truncate towards zero */\n\tif (s) {\n\t\tx = -x;\n\t}\n\treturn x;\n}\n\nDUK_INTERNAL duk_bool_t duk_double_same_sign(duk_double_t x, duk_double_t y) {\n\tduk_double_union du1;\n\tduk_double_union du2;\n\tdu1.d = x;\n\tdu2.d = y;\n\n\treturn (((du1.ui[DUK_DBL_IDX_UI0] ^ du2.ui[DUK_DBL_IDX_UI0]) & 0x80000000UL) == 0);\n}\n\nDUK_INTERNAL duk_double_t duk_double_fmin(duk_double_t x, duk_double_t y) {\n\t/* Doesn't replicate fmin() behavior exactly: for fmin() if one\n\t * argument is a NaN, the other argument should be returned.\n\t * Duktape doesn't rely on this behavior so the replacement can\n\t * be simplified.\n\t */\n\treturn (x < y ? x : y);\n}\n\nDUK_INTERNAL duk_double_t duk_double_fmax(duk_double_t x, duk_double_t y) {\n\t/* Doesn't replicate fmax() behavior exactly: for fmax() if one\n\t * argument is a NaN, the other argument should be returned.\n\t * Duktape doesn't rely on this behavior so the replacement can\n\t * be simplified.\n\t */\n\treturn (x > y ? x : y);\n}\n#line 1 \"duk_hobject_class.c\"\n/*\n *  Hobject Ecmascript [[Class]].\n */\n\n/* #include duk_internal.h -> already included */\n\n#if (DUK_STRIDX_UC_ARGUMENTS > 255)\n#error constant too large\n#endif\n#if (DUK_STRIDX_ARRAY > 255)\n#error constant too large\n#endif\n#if (DUK_STRIDX_UC_BOOLEAN > 255)\n#error constant too large\n#endif\n#if (DUK_STRIDX_DATE > 255)\n#error constant too large\n#endif\n#if (DUK_STRIDX_UC_ERROR > 255)\n#error constant too large\n#endif\n#if (DUK_STRIDX_UC_FUNCTION > 255)\n#error constant too large\n#endif\n#if (DUK_STRIDX_JSON > 255)\n#error constant too large\n#endif\n#if (DUK_STRIDX_MATH > 255)\n#error constant too large\n#endif\n#if (DUK_STRIDX_UC_NUMBER > 255)\n#error constant too large\n#endif\n#if (DUK_STRIDX_UC_OBJECT > 255)\n#error constant too large\n#endif\n#if (DUK_STRIDX_REG_EXP > 255)\n#error constant too large\n#endif\n#if (DUK_STRIDX_UC_STRING > 255)\n#error constant too large\n#endif\n#if (DUK_STRIDX_GLOBAL > 255)\n#error constant too large\n#endif\n#if (DUK_STRIDX_OBJ_ENV > 255)\n#error constant too large\n#endif\n#if (DUK_STRIDX_DEC_ENV > 255)\n#error constant too large\n#endif\n#if (DUK_STRIDX_UC_POINTER > 255)\n#error constant too large\n#endif\n#if (DUK_STRIDX_UC_THREAD > 255)\n#error constant too large\n#endif\n#if (DUK_STRIDX_ARRAY_BUFFER > 255)\n#error constant too large\n#endif\n#if (DUK_STRIDX_DATA_VIEW > 255)\n#error constant too large\n#endif\n#if (DUK_STRIDX_INT8_ARRAY > 255)\n#error constant too large\n#endif\n#if (DUK_STRIDX_UINT8_ARRAY > 255)\n#error constant too large\n#endif\n#if (DUK_STRIDX_UINT8_CLAMPED_ARRAY > 255)\n#error constant too large\n#endif\n#if (DUK_STRIDX_INT16_ARRAY > 255)\n#error constant too large\n#endif\n#if (DUK_STRIDX_UINT16_ARRAY > 255)\n#error constant too large\n#endif\n#if (DUK_STRIDX_INT32_ARRAY > 255)\n#error constant too large\n#endif\n#if (DUK_STRIDX_UINT32_ARRAY > 255)\n#error constant too large\n#endif\n#if (DUK_STRIDX_FLOAT32_ARRAY > 255)\n#error constant too large\n#endif\n#if (DUK_STRIDX_FLOAT64_ARRAY > 255)\n#error constant too large\n#endif\n#if (DUK_STRIDX_EMPTY_STRING > 255)\n#error constant too large\n#endif\n\n/* Note: assumes that these string indexes are 8-bit, genstrings.py must ensure that */\nDUK_INTERNAL duk_uint8_t duk_class_number_to_stridx[32] = {\n\tDUK_STRIDX_EMPTY_STRING,  /* NONE, intentionally empty */\n\tDUK_STRIDX_UC_OBJECT,\n\tDUK_STRIDX_ARRAY,\n\tDUK_STRIDX_UC_FUNCTION,\n\tDUK_STRIDX_UC_ARGUMENTS,\n\tDUK_STRIDX_UC_BOOLEAN,\n\tDUK_STRIDX_DATE,\n\tDUK_STRIDX_UC_ERROR,\n\tDUK_STRIDX_JSON,\n\tDUK_STRIDX_MATH,\n\tDUK_STRIDX_UC_NUMBER,\n\tDUK_STRIDX_REG_EXP,\n\tDUK_STRIDX_UC_STRING,\n\tDUK_STRIDX_GLOBAL,\n\tDUK_STRIDX_UC_SYMBOL,\n\tDUK_STRIDX_OBJ_ENV,\n\tDUK_STRIDX_DEC_ENV,\n\tDUK_STRIDX_UC_POINTER,\n\tDUK_STRIDX_UC_THREAD,\n\tDUK_STRIDX_ARRAY_BUFFER,\n\tDUK_STRIDX_DATA_VIEW,\n\tDUK_STRIDX_INT8_ARRAY,\n\tDUK_STRIDX_UINT8_ARRAY,\n\tDUK_STRIDX_UINT8_CLAMPED_ARRAY,\n\tDUK_STRIDX_INT16_ARRAY,\n\tDUK_STRIDX_UINT16_ARRAY,\n\tDUK_STRIDX_INT32_ARRAY,\n\tDUK_STRIDX_UINT32_ARRAY,\n\tDUK_STRIDX_FLOAT32_ARRAY,\n\tDUK_STRIDX_FLOAT64_ARRAY,\n\tDUK_STRIDX_EMPTY_STRING,  /* UNUSED, intentionally empty */\n\tDUK_STRIDX_EMPTY_STRING,  /* UNUSED, intentionally empty */\n};\n#line 1 \"duk_alloc_default.c\"\n/*\n *  Default allocation functions.\n *\n *  Assumes behavior such as malloc allowing zero size, yielding\n *  a NULL or a unique pointer which is a no-op for free.\n */\n\n/* #include duk_internal.h -> already included */\n\n#if defined(DUK_USE_PROVIDE_DEFAULT_ALLOC_FUNCTIONS)\nDUK_INTERNAL void *duk_default_alloc_function(void *udata, duk_size_t size) {\n\tvoid *res;\n\tDUK_UNREF(udata);\n\tres = DUK_ANSI_MALLOC(size);\n\tDUK_DDD(DUK_DDDPRINT(\"default alloc function: %lu -> %p\",\n\t                     (unsigned long) size, (void *) res));\n\treturn res;\n}\n\nDUK_INTERNAL void *duk_default_realloc_function(void *udata, void *ptr, duk_size_t newsize) {\n\tvoid *res;\n\tDUK_UNREF(udata);\n\tres = DUK_ANSI_REALLOC(ptr, newsize);\n\tDUK_DDD(DUK_DDDPRINT(\"default realloc function: %p %lu -> %p\",\n\t                     (void *) ptr, (unsigned long) newsize, (void *) res));\n\treturn res;\n}\n\nDUK_INTERNAL void duk_default_free_function(void *udata, void *ptr) {\n\tDUK_DDD(DUK_DDDPRINT(\"default free function: %p\", (void *) ptr));\n\tDUK_UNREF(udata);\n\tDUK_ANSI_FREE(ptr);\n}\n#endif  /* DUK_USE_PROVIDE_DEFAULT_ALLOC_FUNCTIONS */\n#line 1 \"duk_api_buffer.c\"\n/*\n *  Buffer\n */\n\n/* #include duk_internal.h -> already included */\n\nDUK_EXTERNAL void *duk_resize_buffer(duk_hthread *thr, duk_idx_t idx, duk_size_t new_size) {\n\tduk_hbuffer_dynamic *h;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\th = (duk_hbuffer_dynamic *) duk_require_hbuffer(thr, idx);\n\tDUK_ASSERT(h != NULL);\n\n\tif (!(DUK_HBUFFER_HAS_DYNAMIC(h) && !DUK_HBUFFER_HAS_EXTERNAL(h))) {\n\t\tDUK_ERROR_TYPE(thr, DUK_STR_WRONG_BUFFER_TYPE);\n\t}\n\n\t/* maximum size check is handled by callee */\n\tduk_hbuffer_resize(thr, h, new_size);\n\n\treturn DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, h);\n}\n\nDUK_EXTERNAL void *duk_steal_buffer(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_size) {\n\tduk_hbuffer_dynamic *h;\n\tvoid *ptr;\n\tduk_size_t sz;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\th = (duk_hbuffer_dynamic *) duk_require_hbuffer(thr, idx);\n\tDUK_ASSERT(h != NULL);\n\n\tif (!(DUK_HBUFFER_HAS_DYNAMIC(h) && !DUK_HBUFFER_HAS_EXTERNAL(h))) {\n\t\tDUK_ERROR_TYPE(thr, DUK_STR_WRONG_BUFFER_TYPE);\n\t}\n\n\t/* Forget the previous allocation, setting size to 0 and alloc to\n\t * NULL.  Caller is responsible for freeing the previous allocation.\n\t * Getting the allocation and clearing it is done in the same API\n\t * call to avoid any chance of a realloc.\n\t */\n\tptr = DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, h);\n\tsz = DUK_HBUFFER_DYNAMIC_GET_SIZE(h);\n\tif (out_size) {\n\t\t*out_size = sz;\n\t}\n\tDUK_HBUFFER_DYNAMIC_SET_DATA_PTR_NULL(thr->heap, h);\n\tDUK_HBUFFER_DYNAMIC_SET_SIZE(h, 0);\n\n\treturn ptr;\n}\n\nDUK_EXTERNAL void duk_config_buffer(duk_hthread *thr, duk_idx_t idx, void *ptr, duk_size_t len) {\n\tduk_hbuffer_external *h;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\th = (duk_hbuffer_external *) duk_require_hbuffer(thr, idx);\n\tDUK_ASSERT(h != NULL);\n\n\tif (!DUK_HBUFFER_HAS_EXTERNAL(h)) {\n\t\tDUK_ERROR_TYPE(thr, DUK_STR_WRONG_BUFFER_TYPE);\n\t}\n\tDUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(h));\n\n\tDUK_HBUFFER_EXTERNAL_SET_DATA_PTR(thr->heap, h, ptr);\n\tDUK_HBUFFER_EXTERNAL_SET_SIZE(h, len);\n}\n#line 1 \"duk_api_bytecode.c\"\n/*\n *  Bytecode dump/load\n *\n *  The bytecode load primitive is more important performance-wise than the\n *  dump primitive.\n *\n *  Unlike most Duktape API calls, bytecode dump/load is not guaranteed to be\n *  memory safe for invalid arguments - caller beware!  There's little point\n *  in trying to achieve memory safety unless bytecode instructions are also\n *  validated which is not easy to do with indirect register references etc.\n */\n\n/* #include duk_internal.h -> already included */\n\n#if defined(DUK_USE_BYTECODE_DUMP_SUPPORT)\n\n#define DUK__SER_MARKER  0xbf\n#define DUK__SER_STRING  0x00\n#define DUK__SER_NUMBER  0x01\n#define DUK__BYTECODE_INITIAL_ALLOC 256\n#define DUK__NO_FORMALS  0xffffffffUL\n\n/*\n *  Dump/load helpers, xxx_raw() helpers do no buffer checks\n */\n\nDUK_LOCAL duk_uint8_t *duk__load_string_raw(duk_hthread *thr, duk_uint8_t *p) {\n\tduk_uint32_t len;\n\n\tlen = DUK_RAW_READ_U32_BE(p);\n\tduk_push_lstring(thr, (const char *) p, len);\n\tp += len;\n\treturn p;\n}\n\nDUK_LOCAL duk_uint8_t *duk__load_buffer_raw(duk_hthread *thr, duk_uint8_t *p) {\n\tduk_uint32_t len;\n\tduk_uint8_t *buf;\n\n\tlen = DUK_RAW_READ_U32_BE(p);\n\tbuf = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, (duk_size_t) len);\n\tDUK_ASSERT(buf != NULL);\n\tDUK_MEMCPY((void *) buf, (const void *) p, (size_t) len);\n\tp += len;\n\treturn p;\n}\n\nDUK_LOCAL duk_uint8_t *duk__dump_hstring_raw(duk_uint8_t *p, duk_hstring *h) {\n\tduk_size_t len;\n\tduk_uint32_t tmp32;\n\n\tDUK_ASSERT(h != NULL);\n\n\tlen = DUK_HSTRING_GET_BYTELEN(h);\n\tDUK_ASSERT(len <= 0xffffffffUL);  /* string limits */\n\ttmp32 = (duk_uint32_t) len;\n\tDUK_RAW_WRITE_U32_BE(p, tmp32);\n\tDUK_MEMCPY((void *) p,\n\t           (const void *) DUK_HSTRING_GET_DATA(h),\n\t           len);\n\tp += len;\n\treturn p;\n}\n\nDUK_LOCAL duk_uint8_t *duk__dump_hbuffer_raw(duk_hthread *thr, duk_uint8_t *p, duk_hbuffer *h) {\n\tduk_size_t len;\n\tduk_uint32_t tmp32;\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(h != NULL);\n\tDUK_UNREF(thr);\n\n\tlen = DUK_HBUFFER_GET_SIZE(h);\n\tDUK_ASSERT(len <= 0xffffffffUL);  /* buffer limits */\n\ttmp32 = (duk_uint32_t) len;\n\tDUK_RAW_WRITE_U32_BE(p, tmp32);\n\tDUK_MEMCPY((void *) p,\n\t           (const void *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h),\n\t           len);\n\tp += len;\n\treturn p;\n}\n\nDUK_LOCAL duk_uint8_t *duk__dump_string_prop(duk_hthread *thr, duk_uint8_t *p, duk_bufwriter_ctx *bw_ctx, duk_hobject *func, duk_small_uint_t stridx) {\n\tduk_hstring *h_str;\n\tduk_tval *tv;\n\n\ttv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, (duk_hobject *) func, DUK_HTHREAD_GET_STRING(thr, stridx));\n\tif (tv != NULL && DUK_TVAL_IS_STRING(tv)) {\n\t\th_str = DUK_TVAL_GET_STRING(tv);\n\t\tDUK_ASSERT(h_str != NULL);\n\t} else {\n\t\th_str = DUK_HTHREAD_STRING_EMPTY_STRING(thr);\n\t\tDUK_ASSERT(h_str != NULL);\n\t}\n\tDUK_ASSERT(DUK_HSTRING_MAX_BYTELEN <= 0x7fffffffUL);  /* ensures no overflow */\n\tp = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4U + DUK_HSTRING_GET_BYTELEN(h_str), p);\n\tp = duk__dump_hstring_raw(p, h_str);\n\treturn p;\n}\n\nDUK_LOCAL duk_uint8_t *duk__dump_buffer_prop(duk_hthread *thr, duk_uint8_t *p, duk_bufwriter_ctx *bw_ctx, duk_hobject *func, duk_small_uint_t stridx) {\n\tduk_tval *tv;\n\n\ttv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, (duk_hobject *) func, DUK_HTHREAD_GET_STRING(thr, stridx));\n\tif (tv != NULL && DUK_TVAL_IS_BUFFER(tv)) {\n\t\tduk_hbuffer *h_buf;\n\t\th_buf = DUK_TVAL_GET_BUFFER(tv);\n\t\tDUK_ASSERT(h_buf != NULL);\n\t\tDUK_ASSERT(DUK_HBUFFER_MAX_BYTELEN <= 0x7fffffffUL);  /* ensures no overflow */\n\t\tp = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4U + DUK_HBUFFER_GET_SIZE(h_buf), p);\n\t\tp = duk__dump_hbuffer_raw(thr, p, h_buf);\n\t} else {\n\t\tp = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4U, p);\n\t\tDUK_RAW_WRITE_U32_BE(p, 0);\n\t}\n\treturn p;\n}\n\nDUK_LOCAL duk_uint8_t *duk__dump_uint32_prop(duk_hthread *thr, duk_uint8_t *p, duk_bufwriter_ctx *bw_ctx, duk_hobject *func, duk_small_uint_t stridx, duk_uint32_t def_value) {\n\tduk_tval *tv;\n\tduk_uint32_t val;\n\n\ttv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, (duk_hobject *) func, DUK_HTHREAD_GET_STRING(thr, stridx));\n\tif (tv != NULL && DUK_TVAL_IS_NUMBER(tv)) {\n\t\tval = (duk_uint32_t) DUK_TVAL_GET_NUMBER(tv);\n\t} else {\n\t\tval = def_value;\n\t}\n\tp = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4U, p);\n\tDUK_RAW_WRITE_U32_BE(p, val);\n\treturn p;\n}\n\nDUK_LOCAL duk_uint8_t *duk__dump_varmap(duk_hthread *thr, duk_uint8_t *p, duk_bufwriter_ctx *bw_ctx, duk_hobject *func) {\n\tduk_tval *tv;\n\n\ttv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, (duk_hobject *) func, DUK_HTHREAD_STRING_INT_VARMAP(thr));\n\tif (tv != NULL && DUK_TVAL_IS_OBJECT(tv)) {\n\t\tduk_hobject *h;\n\t\tduk_uint_fast32_t i;\n\n\t\th = DUK_TVAL_GET_OBJECT(tv);\n\t\tDUK_ASSERT(h != NULL);\n\n\t\t/* We know _Varmap only has own properties so walk property\n\t\t * table directly.  We also know _Varmap is dense and all\n\t\t * values are numbers; assert for these.  GC and finalizers\n\t\t * shouldn't affect _Varmap so side effects should be fine.\n\t\t */\n\t\tfor (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(h); i++) {\n\t\t\tduk_hstring *key;\n\t\t\tduk_tval *tv_val;\n\t\t\tduk_uint32_t val;\n\n\t\t\tkey = DUK_HOBJECT_E_GET_KEY(thr->heap, h, i);\n\t\t\tDUK_ASSERT(key != NULL);  /* _Varmap is dense */\n\t\t\tDUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, h, i));\n\t\t\ttv_val = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, h, i);\n\t\t\tDUK_ASSERT(tv_val != NULL);\n\t\t\tDUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_val));  /* known to be number; in fact an integer */\n#if defined(DUK_USE_FASTINT)\n\t\t\tDUK_ASSERT(DUK_TVAL_IS_FASTINT(tv_val));\n\t\t\tDUK_ASSERT(DUK_TVAL_GET_FASTINT(tv_val) == (duk_int64_t) DUK_TVAL_GET_FASTINT_U32(tv_val));  /* known to be 32-bit */\n\t\t\tval = DUK_TVAL_GET_FASTINT_U32(tv_val);\n#else\n\t\t\tval = (duk_uint32_t) DUK_TVAL_GET_NUMBER(tv_val);\n#endif\n\n\t\t\tDUK_ASSERT(DUK_HSTRING_MAX_BYTELEN <= 0x7fffffffUL);  /* ensures no overflow */\n\t\t\tp = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4U + DUK_HSTRING_GET_BYTELEN(key) + 4U, p);\n\t\t\tp = duk__dump_hstring_raw(p, key);\n\t\t\tDUK_RAW_WRITE_U32_BE(p, val);\n\t\t}\n\t}\n\tp = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4U, p);\n\tDUK_RAW_WRITE_U32_BE(p, 0);  /* end of _Varmap */\n\treturn p;\n}\n\nDUK_LOCAL duk_uint8_t *duk__dump_formals(duk_hthread *thr, duk_uint8_t *p, duk_bufwriter_ctx *bw_ctx, duk_hobject *func) {\n\tduk_tval *tv;\n\n\ttv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, (duk_hobject *) func, DUK_HTHREAD_STRING_INT_FORMALS(thr));\n\tif (tv != NULL && DUK_TVAL_IS_OBJECT(tv)) {\n\t\tduk_harray *h;\n\t\tduk_uint32_t i;\n\n\t\t/* Here we rely on _Formals being a dense array containing\n\t\t * strings.  This should be the case unless _Formals has been\n\t\t * tweaked by the application (which we don't support right\n\t\t * now).\n\t\t */\n\t\th = (duk_harray *) DUK_TVAL_GET_OBJECT(tv);\n\t\tDUK_ASSERT(h != NULL);\n\t\tDUK_ASSERT(DUK_HOBJECT_IS_ARRAY((duk_hobject *) h));\n\t\tDUK_ASSERT(h->length <= DUK_HOBJECT_GET_ASIZE((duk_hobject *) h));\n\n\t\tp = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4U, p);\n\t\tDUK_ASSERT(h->length != DUK__NO_FORMALS);  /* limits */\n\t\tDUK_RAW_WRITE_U32_BE(p, h->length);\n\n\t\tfor (i = 0; i < h->length; i++) {\n\t\t\tduk_tval *tv_val;\n\t\t\tduk_hstring *varname;\n\n\t\t\ttv_val = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, (duk_hobject *) h, i);\n\t\t\tDUK_ASSERT(tv_val != NULL);\n\t\t\tDUK_ASSERT(DUK_TVAL_IS_STRING(tv_val));\n\n\t\t\tvarname = DUK_TVAL_GET_STRING(tv_val);\n\t\t\tDUK_ASSERT(varname != NULL);\n\t\t\tDUK_ASSERT(DUK_HSTRING_GET_BYTELEN(varname) >= 1);\n\n\t\t\tDUK_ASSERT(DUK_HSTRING_MAX_BYTELEN <= 0x7fffffffUL);  /* ensures no overflow */\n\t\t\tp = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4U + DUK_HSTRING_GET_BYTELEN(varname), p);\n\t\t\tp = duk__dump_hstring_raw(p, varname);\n\t\t}\n\t} else {\n\t\tDUK_DD(DUK_DDPRINT(\"dumping function without _Formals, emit marker to indicate missing _Formals\"));\n\t\tp = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4U, p);\n\t\tDUK_RAW_WRITE_U32_BE(p, DUK__NO_FORMALS);  /* marker: no formals */\n\t}\n\treturn p;\n}\n\nstatic duk_uint8_t *duk__dump_func(duk_hthread *thr, duk_hcompfunc *func, duk_bufwriter_ctx *bw_ctx, duk_uint8_t *p) {\n\tduk_tval *tv, *tv_end;\n\tduk_instr_t *ins, *ins_end;\n\tduk_hobject **fn, **fn_end;\n\tduk_hstring *h_str;\n\tduk_uint32_t count_instr;\n\tduk_uint32_t tmp32;\n\tduk_uint16_t tmp16;\n\tduk_double_t d;\n\n\tDUK_DD(DUK_DDPRINT(\"dumping function %p to %p: \"\n\t                   \"consts=[%p,%p[ (%ld bytes, %ld items), \"\n\t                   \"funcs=[%p,%p[ (%ld bytes, %ld items), \"\n\t                   \"code=[%p,%p[ (%ld bytes, %ld items)\",\n\t                   (void *) func,\n\t                   (void *) p,\n\t                   (void *) DUK_HCOMPFUNC_GET_CONSTS_BASE(thr->heap, func),\n\t                   (void *) DUK_HCOMPFUNC_GET_CONSTS_END(thr->heap, func),\n\t                   (long) DUK_HCOMPFUNC_GET_CONSTS_SIZE(thr->heap, func),\n\t                   (long) DUK_HCOMPFUNC_GET_CONSTS_COUNT(thr->heap, func),\n\t                   (void *) DUK_HCOMPFUNC_GET_FUNCS_BASE(thr->heap, func),\n\t                   (void *) DUK_HCOMPFUNC_GET_FUNCS_END(thr->heap, func),\n\t                   (long) DUK_HCOMPFUNC_GET_FUNCS_SIZE(thr->heap, func),\n\t                   (long) DUK_HCOMPFUNC_GET_FUNCS_COUNT(thr->heap, func),\n\t                   (void *) DUK_HCOMPFUNC_GET_CODE_BASE(thr->heap, func),\n\t                   (void *) DUK_HCOMPFUNC_GET_CODE_END(thr->heap, func),\n\t                   (long) DUK_HCOMPFUNC_GET_CODE_SIZE(thr->heap, func),\n\t                   (long) DUK_HCOMPFUNC_GET_CODE_COUNT(thr->heap, func)));\n\n\tDUK_ASSERT(DUK_USE_ESBC_MAX_BYTES <= 0x7fffffffUL);  /* ensures no overflow */\n\tcount_instr = (duk_uint32_t) DUK_HCOMPFUNC_GET_CODE_COUNT(thr->heap, func);\n\tp = DUK_BW_ENSURE_RAW(thr, bw_ctx, 3U * 4U + 2U * 2U + 3U * 4U + count_instr * 4U, p);\n\n\t/* Fixed header info. */\n\ttmp32 = count_instr;\n\tDUK_RAW_WRITE_U32_BE(p, tmp32);\n\ttmp32 = (duk_uint32_t) DUK_HCOMPFUNC_GET_CONSTS_COUNT(thr->heap, func);\n\tDUK_RAW_WRITE_U32_BE(p, tmp32);\n\ttmp32 = (duk_uint32_t) DUK_HCOMPFUNC_GET_FUNCS_COUNT(thr->heap, func);\n\tDUK_RAW_WRITE_U32_BE(p, tmp32);\n\ttmp16 = func->nregs;\n\tDUK_RAW_WRITE_U16_BE(p, tmp16);\n\ttmp16 = func->nargs;\n\tDUK_RAW_WRITE_U16_BE(p, tmp16);\n#if defined(DUK_USE_DEBUGGER_SUPPORT)\n\ttmp32 = func->start_line;\n\tDUK_RAW_WRITE_U32_BE(p, tmp32);\n\ttmp32 = func->end_line;\n\tDUK_RAW_WRITE_U32_BE(p, tmp32);\n#else\n\tDUK_RAW_WRITE_U32_BE(p, 0);\n\tDUK_RAW_WRITE_U32_BE(p, 0);\n#endif\n\ttmp32 = DUK_HEAPHDR_GET_FLAGS((duk_heaphdr *) func);  /* masks flags, only duk_hobject flags */\n\ttmp32 &= ~(DUK_HOBJECT_FLAG_HAVE_FINALIZER);  /* finalizer flag is lost */\n\tDUK_RAW_WRITE_U32_BE(p, tmp32);\n\n\t/* Bytecode instructions: endian conversion needed unless\n\t * platform is big endian.\n\t */\n\tins = DUK_HCOMPFUNC_GET_CODE_BASE(thr->heap, func);\n\tins_end = DUK_HCOMPFUNC_GET_CODE_END(thr->heap, func);\n\tDUK_ASSERT((duk_size_t) (ins_end - ins) == (duk_size_t) count_instr);\n#if defined(DUK_USE_INTEGER_BE)\n\tDUK_MEMCPY((void *) p, (const void *) ins, (size_t) (ins_end - ins));\n\tp += (size_t) (ins_end - ins);\n#else\n\twhile (ins != ins_end) {\n\t\ttmp32 = (duk_uint32_t) (*ins);\n\t\tDUK_RAW_WRITE_U32_BE(p, tmp32);\n\t\tins++;\n\t}\n#endif\n\n\t/* Constants: variable size encoding. */\n\ttv = DUK_HCOMPFUNC_GET_CONSTS_BASE(thr->heap, func);\n\ttv_end = DUK_HCOMPFUNC_GET_CONSTS_END(thr->heap, func);\n\twhile (tv != tv_end) {\n\t\t/* constants are strings or numbers now */\n\t\tDUK_ASSERT(DUK_TVAL_IS_STRING(tv) ||\n\t\t           DUK_TVAL_IS_NUMBER(tv));\n\n\t\tif (DUK_TVAL_IS_STRING(tv)) {\n\t\t\th_str = DUK_TVAL_GET_STRING(tv);\n\t\t\tDUK_ASSERT(h_str != NULL);\n\t\t\tDUK_ASSERT(DUK_HSTRING_MAX_BYTELEN <= 0x7fffffffUL);  /* ensures no overflow */\n\t\t\tp = DUK_BW_ENSURE_RAW(thr, bw_ctx, 1U + 4U + DUK_HSTRING_GET_BYTELEN(h_str), p),\n\t\t\t*p++ = DUK__SER_STRING;\n\t\t\tp = duk__dump_hstring_raw(p, h_str);\n\t\t} else {\n\t\t\tDUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));\n\t\t\tp = DUK_BW_ENSURE_RAW(thr, bw_ctx, 1U + 8U, p);\n\t\t\t*p++ = DUK__SER_NUMBER;\n\t\t\td = DUK_TVAL_GET_NUMBER(tv);\n\t\t\tDUK_RAW_WRITE_DOUBLE_BE(p, d);\n\t\t}\n\t\ttv++;\n\t}\n\n\t/* Inner functions recursively. */\n\tfn = (duk_hobject **) DUK_HCOMPFUNC_GET_FUNCS_BASE(thr->heap, func);\n\tfn_end = (duk_hobject **) DUK_HCOMPFUNC_GET_FUNCS_END(thr->heap, func);\n\twhile (fn != fn_end) {\n\t\t/* XXX: This causes recursion up to inner function depth\n\t\t * which is normally not an issue, e.g. mark-and-sweep uses\n\t\t * a recursion limiter to avoid C stack issues.  Avoiding\n\t\t * this would mean some sort of a work list or just refusing\n\t\t * to serialize deep functions.\n\t\t */\n\t\tDUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(*fn));\n\t\tp = duk__dump_func(thr, (duk_hcompfunc *) *fn, bw_ctx, p);\n\t\tfn++;\n\t}\n\n\t/* Lexenv and varenv are not dumped. */\n\n\t/* Object extra properties.\n\t *\n\t * There are some difference between function templates and functions.\n\t * For example, function templates don't have .length and nargs is\n\t * normally used to instantiate the functions.\n\t */\n\n\tp = duk__dump_uint32_prop(thr, p, bw_ctx, (duk_hobject *) func, DUK_STRIDX_LENGTH, (duk_uint32_t) func->nargs);\n#if defined(DUK_USE_FUNC_NAME_PROPERTY)\n\tp = duk__dump_string_prop(thr, p, bw_ctx, (duk_hobject *) func, DUK_STRIDX_NAME);\n#endif\n#if defined(DUK_USE_FUNC_FILENAME_PROPERTY)\n\tp = duk__dump_string_prop(thr, p, bw_ctx, (duk_hobject *) func, DUK_STRIDX_FILE_NAME);\n#endif\n#if defined(DUK_USE_PC2LINE)\n\tp = duk__dump_buffer_prop(thr, p, bw_ctx, (duk_hobject *) func, DUK_STRIDX_INT_PC2LINE);\n#endif\n\tp = duk__dump_varmap(thr, p, bw_ctx, (duk_hobject *) func);\n\tp = duk__dump_formals(thr, p, bw_ctx, (duk_hobject *) func);\n\n\tDUK_DD(DUK_DDPRINT(\"serialized function %p -> final pointer %p\", (void *) func, (void *) p));\n\n\treturn p;\n}\n\n/* Load a function from bytecode.  The function object returned here must\n * match what is created by duk_js_push_closure() with respect to its flags,\n * properties, etc.\n *\n * NOTE: there are intentionally no input buffer length / bound checks.\n * Adding them would be easy but wouldn't ensure memory safety as untrusted\n * or broken bytecode is unsafe during execution unless the opcodes themselves\n * are validated (which is quite complex, especially for indirect opcodes).\n */\n\n#define DUK__ASSERT_LEFT(n) do { \\\n\t\tDUK_ASSERT((duk_size_t) (p_end - p) >= (duk_size_t) (n)); \\\n\t} while (0)\n\nstatic duk_uint8_t *duk__load_func(duk_hthread *thr, duk_uint8_t *p, duk_uint8_t *p_end) {\n\tduk_hcompfunc *h_fun;\n\tduk_hbuffer *h_data;\n\tduk_size_t data_size;\n\tduk_uint32_t count_instr, count_const, count_funcs;\n\tduk_uint32_t n;\n\tduk_uint32_t tmp32;\n\tduk_small_uint_t const_type;\n\tduk_uint8_t *fun_data;\n\tduk_uint8_t *q;\n\tduk_idx_t idx_base;\n\tduk_tval *tv1;\n\tduk_uarridx_t arr_idx;\n\tduk_uarridx_t arr_limit;\n\tduk_hobject *func_env;\n\tduk_bool_t need_pop;\n\n\t/* XXX: There's some overlap with duk_js_closure() here, but\n\t * seems difficult to share code.  Ensure that the final function\n\t * looks the same as created by duk_js_closure().\n\t */\n\n\tDUK_ASSERT(thr != NULL);\n\n\tDUK_DD(DUK_DDPRINT(\"loading function, p=%p, p_end=%p\", (void *) p, (void *) p_end));\n\n\tDUK__ASSERT_LEFT(3 * 4);\n\tcount_instr = DUK_RAW_READ_U32_BE(p);\n\tcount_const = DUK_RAW_READ_U32_BE(p);\n\tcount_funcs = DUK_RAW_READ_U32_BE(p);\n\n\tdata_size = sizeof(duk_tval) * count_const +\n\t            sizeof(duk_hobject *) * count_funcs +\n\t            sizeof(duk_instr_t) * count_instr;\n\n\tDUK_DD(DUK_DDPRINT(\"instr=%ld, const=%ld, funcs=%ld, data_size=%ld\",\n\t                   (long) count_instr, (long) count_const,\n\t                   (long) count_const, (long) data_size));\n\n\t/* Value stack is used to ensure reachability of constants and\n\t * inner functions being loaded.  Require enough space to handle\n\t * large functions correctly.\n\t */\n\tduk_require_stack(thr, (duk_idx_t) (2 + count_const + count_funcs));\n\tidx_base = duk_get_top(thr);\n\n\t/* Push function object, init flags etc.  This must match\n\t * duk_js_push_closure() quite carefully.\n\t */\n\th_fun = duk_push_hcompfunc(thr);\n\tDUK_ASSERT(h_fun != NULL);\n\tDUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC((duk_hobject *) h_fun));\n\tDUK_ASSERT(DUK_HCOMPFUNC_GET_DATA(thr->heap, h_fun) == NULL);\n\tDUK_ASSERT(DUK_HCOMPFUNC_GET_FUNCS(thr->heap, h_fun) == NULL);\n\tDUK_ASSERT(DUK_HCOMPFUNC_GET_BYTECODE(thr->heap, h_fun) == NULL);\n\tDUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) h_fun) == thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]);\n\n\th_fun->nregs = DUK_RAW_READ_U16_BE(p);\n\th_fun->nargs = DUK_RAW_READ_U16_BE(p);\n#if defined(DUK_USE_DEBUGGER_SUPPORT)\n\th_fun->start_line = DUK_RAW_READ_U32_BE(p);\n\th_fun->end_line = DUK_RAW_READ_U32_BE(p);\n#else\n\tp += 8;  /* skip line info */\n#endif\n\n\t/* duk_hcompfunc flags; quite version specific */\n\ttmp32 = DUK_RAW_READ_U32_BE(p);\n\tDUK_HEAPHDR_SET_FLAGS((duk_heaphdr *) h_fun, tmp32);  /* masks flags to only change duk_hobject flags */\n\n\t/* standard prototype (no need to set here, already set) */\n\tDUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) h_fun) == thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]);\n#if 0\n\tDUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, &h_fun->obj, thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]);\n#endif\n\n\t/* assert just a few critical flags */\n\tDUK_ASSERT(DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) h_fun) == DUK_HTYPE_OBJECT);\n\tDUK_ASSERT(!DUK_HOBJECT_HAS_BOUNDFUNC(&h_fun->obj));\n\tDUK_ASSERT(DUK_HOBJECT_HAS_COMPFUNC(&h_fun->obj));\n\tDUK_ASSERT(!DUK_HOBJECT_HAS_NATFUNC(&h_fun->obj));\n\tDUK_ASSERT(!DUK_HOBJECT_IS_THREAD(&h_fun->obj));\n\tDUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARRAY(&h_fun->obj));\n\tDUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(&h_fun->obj));\n\tDUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(&h_fun->obj));\n\n\t/* Create function 'data' buffer but don't attach it yet. */\n\tfun_data = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, data_size);\n\tDUK_ASSERT(fun_data != NULL);\n\n\t/* Load bytecode instructions. */\n\tDUK_ASSERT(sizeof(duk_instr_t) == 4);\n\tDUK__ASSERT_LEFT(count_instr * sizeof(duk_instr_t));\n#if defined(DUK_USE_INTEGER_BE)\n\tq = fun_data + sizeof(duk_tval) * count_const + sizeof(duk_hobject *) * count_funcs;\n\tDUK_MEMCPY((void *) q,\n\t           (const void *) p,\n\t           sizeof(duk_instr_t) * count_instr);\n\tp += sizeof(duk_instr_t) * count_instr;\n#else\n\tq = fun_data + sizeof(duk_tval) * count_const + sizeof(duk_hobject *) * count_funcs;\n\tfor (n = count_instr; n > 0; n--) {\n\t\t*((duk_instr_t *) (void *) q) = DUK_RAW_READ_U32_BE(p);\n\t\tq += sizeof(duk_instr_t);\n\t}\n#endif\n\n\t/* Load constants onto value stack but don't yet copy to buffer. */\n\tfor (n = count_const; n > 0; n--) {\n\t\tDUK__ASSERT_LEFT(1);\n\t\tconst_type = DUK_RAW_READ_U8(p);\n\t\tswitch (const_type) {\n\t\tcase DUK__SER_STRING: {\n\t\t\tp = duk__load_string_raw(thr, p);\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK__SER_NUMBER: {\n\t\t\t/* Important to do a fastint check so that constants are\n\t\t\t * properly read back as fastints.\n\t\t\t */\n\t\t\tduk_tval tv_tmp;\n\t\t\tduk_double_t val;\n\t\t\tDUK__ASSERT_LEFT(8);\n\t\t\tval = DUK_RAW_READ_DOUBLE_BE(p);\n\t\t\tDUK_TVAL_SET_NUMBER_CHKFAST_SLOW(&tv_tmp, val);\n\t\t\tduk_push_tval(thr, &tv_tmp);\n\t\t\tbreak;\n\t\t}\n\t\tdefault: {\n\t\t\tgoto format_error;\n\t\t}\n\t\t}\n\t}\n\n\t/* Load inner functions to value stack, but don't yet copy to buffer. */\n\tfor (n = count_funcs; n > 0; n--) {\n\t\tp = duk__load_func(thr, p, p_end);\n\t\tif (p == NULL) {\n\t\t\tgoto format_error;\n\t\t}\n\t}\n\n\t/* With constants and inner functions on value stack, we can now\n\t * atomically finish the function 'data' buffer, bump refcounts,\n\t * etc.\n\t *\n\t * Here we take advantage of the value stack being just a duk_tval\n\t * array: we can just memcpy() the constants as long as we incref\n\t * them afterwards.\n\t */\n\n\th_data = (duk_hbuffer *) duk_known_hbuffer(thr, idx_base + 1);\n\tDUK_ASSERT(!DUK_HBUFFER_HAS_DYNAMIC(h_data));\n\tDUK_HCOMPFUNC_SET_DATA(thr->heap, h_fun, h_data);\n\tDUK_HBUFFER_INCREF(thr, h_data);\n\n\ttv1 = duk_get_tval(thr, idx_base + 2);  /* may be NULL if no constants or inner funcs */\n\tDUK_ASSERT((count_const == 0 && count_funcs == 0) || tv1 != NULL);\n\n\tq = fun_data;\n\tif (count_const > 0) {\n\t\t/* Explicit zero size check to avoid NULL 'tv1'. */\n\t\tDUK_MEMCPY((void *) q, (const void *) tv1, sizeof(duk_tval) * count_const);\n\t\tfor (n = count_const; n > 0; n--) {\n\t\t\tDUK_TVAL_INCREF_FAST(thr, (duk_tval *) (void *) q);  /* no side effects */\n\t\t\tq += sizeof(duk_tval);\n\t\t}\n\t\ttv1 += count_const;\n\t}\n\n\tDUK_HCOMPFUNC_SET_FUNCS(thr->heap, h_fun, (duk_hobject **) (void *) q);\n\tfor (n = count_funcs; n > 0; n--) {\n\t\tduk_hobject *h_obj;\n\n\t\tDUK_ASSERT(DUK_TVAL_IS_OBJECT(tv1));\n\t\th_obj = DUK_TVAL_GET_OBJECT(tv1);\n\t\tDUK_ASSERT(h_obj != NULL);\n\t\ttv1++;\n\t\tDUK_HOBJECT_INCREF(thr, h_obj);\n\n\t\t*((duk_hobject **) (void *) q) = h_obj;\n\t\tq += sizeof(duk_hobject *);\n\t}\n\n\tDUK_HCOMPFUNC_SET_BYTECODE(thr->heap, h_fun, (duk_instr_t *) (void *) q);\n\n\t/* The function object is now reachable and refcounts are fine,\n\t * so we can pop off all the temporaries.\n\t */\n\tDUK_DDD(DUK_DDDPRINT(\"function is reachable, reset top; func: %!iT\", duk_get_tval(thr, idx_base)));\n\tduk_set_top(thr, idx_base + 1);\n\n\t/* Setup function properties. */\n\ttmp32 = DUK_RAW_READ_U32_BE(p);\n\tduk_push_u32(thr, tmp32);\n\tduk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_C);\n\n#if defined(DUK_USE_FUNC_NAME_PROPERTY)\n\tp = duk__load_string_raw(thr, p);  /* -> [ func funcname ] */\n\tfunc_env = thr->builtins[DUK_BIDX_GLOBAL_ENV];\n\tDUK_ASSERT(func_env != NULL);\n\tneed_pop = 0;\n\tif (DUK_HOBJECT_HAS_NAMEBINDING((duk_hobject *) h_fun)) {\n\t\t/* Original function instance/template had NAMEBINDING.\n\t\t * Must create a lexical environment on loading to allow\n\t\t * recursive functions like 'function foo() { foo(); }'.\n\t\t */\n\t\tduk_hdecenv *new_env;\n\n\t\tnew_env = duk_hdecenv_alloc(thr,\n\t\t                            DUK_HOBJECT_FLAG_EXTENSIBLE |\n\t\t                            DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_DECENV));\n\t\tDUK_ASSERT(new_env != NULL);\n\t\tDUK_ASSERT(new_env->thread == NULL);  /* Closed. */\n\t\tDUK_ASSERT(new_env->varmap == NULL);\n\t\tDUK_ASSERT(new_env->regbase_byteoff == 0);\n\t\tDUK_ASSERT_HDECENV_VALID(new_env);\n\t\tDUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) new_env) == NULL);\n\t\tDUK_HOBJECT_SET_PROTOTYPE(thr->heap, (duk_hobject *) new_env, func_env);\n\t\tDUK_HOBJECT_INCREF(thr, func_env);\n\n\t\tfunc_env = (duk_hobject *) new_env;\n\n\t\tduk_push_hobject(thr, (duk_hobject *) new_env);\n\n\t\tduk_dup_m2(thr);                                  /* -> [ func funcname env funcname ] */\n\t\tduk_dup(thr, idx_base);                           /* -> [ func funcname env funcname func ] */\n\t\tduk_xdef_prop(thr, -3, DUK_PROPDESC_FLAGS_NONE);  /* -> [ func funcname env ] */\n\n\t\tneed_pop = 1;  /* Need to pop env, but -after- updating h_fun and increfs. */\n\t}\n\tDUK_ASSERT(func_env != NULL);\n\tDUK_HCOMPFUNC_SET_LEXENV(thr->heap, h_fun, func_env);\n\tDUK_HCOMPFUNC_SET_VARENV(thr->heap, h_fun, func_env);\n\tDUK_HOBJECT_INCREF(thr, func_env);\n\tDUK_HOBJECT_INCREF(thr, func_env);\n\tif (need_pop) {\n\t\tduk_pop(thr);\n\t}\n\tduk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_NAME, DUK_PROPDESC_FLAGS_C);\n#endif  /* DUK_USE_FUNC_NAME_PROPERTY */\n\n#if defined(DUK_USE_FUNC_FILENAME_PROPERTY)\n\tp = duk__load_string_raw(thr, p);\n\tduk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_FILE_NAME, DUK_PROPDESC_FLAGS_C);\n#endif  /* DUK_USE_FUNC_FILENAME_PROPERTY */\n\n\tif (DUK_HOBJECT_HAS_CONSTRUCTABLE((duk_hobject *) h_fun)) {\n\t\t/* Restore empty external .prototype only for constructable\n\t\t * functions.\n\t\t */\n\t\tduk_push_object(thr);\n\t\tduk_dup_m2(thr);\n\t\tduk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_CONSTRUCTOR, DUK_PROPDESC_FLAGS_WC);  /* func.prototype.constructor = func */\n\t\tduk_compact_m1(thr);\n\t\tduk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_PROTOTYPE, DUK_PROPDESC_FLAGS_W);\n\t}\n\n#if defined(DUK_USE_PC2LINE)\n\tp = duk__load_buffer_raw(thr, p);\n\tduk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_PC2LINE, DUK_PROPDESC_FLAGS_WC);\n#endif  /* DUK_USE_PC2LINE */\n\n\tduk_push_object(thr);  /* _Varmap */\n\tfor (;;) {\n\t\t/* XXX: awkward */\n\t\tp = duk__load_string_raw(thr, p);\n\t\tif (duk_get_length(thr, -1) == 0) {\n\t\t\tduk_pop(thr);\n\t\t\tbreak;\n\t\t}\n\t\ttmp32 = DUK_RAW_READ_U32_BE(p);\n\t\tduk_push_u32(thr, tmp32);\n\t\tduk_put_prop(thr, -3);\n\t}\n\tduk_compact_m1(thr);\n\tduk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_VARMAP, DUK_PROPDESC_FLAGS_NONE);\n\n\t/* _Formals may have been missing in the original function, which is\n\t * handled using a marker length.\n\t */\n\tarr_limit = DUK_RAW_READ_U32_BE(p);\n\tif (arr_limit != DUK__NO_FORMALS) {\n\t\tduk_push_array(thr);  /* _Formals */\n\t\tfor (arr_idx = 0; arr_idx < arr_limit; arr_idx++) {\n\t\t\tp = duk__load_string_raw(thr, p);\n\t\t\tduk_put_prop_index(thr, -2, arr_idx);\n\t\t}\n\t\tduk_compact_m1(thr);\n\t\tduk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_FORMALS, DUK_PROPDESC_FLAGS_NONE);\n\t} else {\n\t\tDUK_DD(DUK_DDPRINT(\"no _Formals in dumped function\"));\n\t}\n\n\t/* Return with final function pushed on stack top. */\n\tDUK_DD(DUK_DDPRINT(\"final loaded function: %!iT\", duk_get_tval(thr, -1)));\n\tDUK_ASSERT_TOP(thr, idx_base + 1);\n\treturn p;\n\n format_error:\n\treturn NULL;\n}\n\nDUK_EXTERNAL void duk_dump_function(duk_hthread *thr) {\n\tduk_hcompfunc *func;\n\tduk_bufwriter_ctx bw_ctx_alloc;\n\tduk_bufwriter_ctx *bw_ctx = &bw_ctx_alloc;\n\tduk_uint8_t *p;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\t/* Bound functions don't have all properties so we'd either need to\n\t * lookup the non-bound target function or reject bound functions.\n\t * For now, bound functions are rejected with TypeError.\n\t */\n\tfunc = duk_require_hcompfunc(thr, -1);\n\tDUK_ASSERT(func != NULL);\n\tDUK_ASSERT(!DUK_HOBJECT_HAS_BOUNDFUNC(&func->obj));\n\n\t/* Estimating the result size beforehand would be costly, so\n\t * start with a reasonable size and extend as needed.\n\t */\n\tDUK_BW_INIT_PUSHBUF(thr, bw_ctx, DUK__BYTECODE_INITIAL_ALLOC);\n\tp = DUK_BW_GET_PTR(thr, bw_ctx);\n\t*p++ = DUK__SER_MARKER;\n\tp = duk__dump_func(thr, func, bw_ctx, p);\n\tDUK_BW_SET_PTR(thr, bw_ctx, p);\n\tDUK_BW_COMPACT(thr, bw_ctx);\n\n\tDUK_DD(DUK_DDPRINT(\"serialized result: %!T\", duk_get_tval(thr, -1)));\n\n\tduk_remove_m2(thr);  /* [ ... func buf ] -> [ ... buf ] */\n}\n\nDUK_EXTERNAL void duk_load_function(duk_hthread *thr) {\n\tduk_uint8_t *p_buf, *p, *p_end;\n\tduk_size_t sz;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tp_buf = (duk_uint8_t *) duk_require_buffer(thr, -1, &sz);\n\tDUK_ASSERT(p_buf != NULL);\n\n\t/* The caller is responsible for being sure that bytecode being loaded\n\t * is valid and trusted.  Invalid bytecode can cause memory unsafe\n\t * behavior directly during loading or later during bytecode execution\n\t * (instruction validation would be quite complex to implement).\n\t *\n\t * This signature check is the only sanity check for detecting\n\t * accidental invalid inputs.  The initial byte ensures no ordinary\n\t * string or Symbol will be accepted by accident.\n\t */\n\tp = p_buf;\n\tp_end = p_buf + sz;\n\tif (sz < 1 || p[0] != DUK__SER_MARKER) {\n\t\tgoto format_error;\n\t}\n\tp++;\n\n\tp = duk__load_func(thr, p, p_end);\n\tif (p == NULL) {\n\t\tgoto format_error;\n\t}\n\n\tduk_remove_m2(thr);  /* [ ... buf func ] -> [ ... func ] */\n\treturn;\n\n format_error:\n\tDUK_ERROR_TYPE(thr, DUK_STR_INVALID_BYTECODE);\n}\n\n#else  /* DUK_USE_BYTECODE_DUMP_SUPPORT */\n\nDUK_EXTERNAL void duk_dump_function(duk_hthread *thr) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK_ERROR_UNSUPPORTED(thr);\n}\n\nDUK_EXTERNAL void duk_load_function(duk_hthread *thr) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK_ERROR_UNSUPPORTED(thr);\n}\n\n#endif  /* DUK_USE_BYTECODE_DUMP_SUPPORT */\n\n/* automatic undefs */\n#undef DUK__ASSERT_LEFT\n#undef DUK__BYTECODE_INITIAL_ALLOC\n#undef DUK__NO_FORMALS\n#undef DUK__SER_MARKER\n#undef DUK__SER_NUMBER\n#undef DUK__SER_STRING\n#line 1 \"duk_api_call.c\"\n/*\n *  Calls.\n *\n *  Protected variants should avoid ever throwing an error.  Must be careful\n *  to catch errors related to value stack manipulation and property lookup,\n *  not just the call itself.\n *\n *  The only exception is when arguments are insane, e.g. nargs/nrets are out\n *  of bounds; in such cases an error is thrown for two reasons.  First, we\n *  can't always respect the value stack input/output guarantees in such cases\n *  so the caller would end up with the value stack in an unexpected state.\n *  Second, an attempt to create an error might itself fail (although this\n *  could be avoided by pushing a preallocated object/string or a primitive\n *  value).\n */\n\n/* #include duk_internal.h -> already included */\n\n/*\n *  Helpers\n */\n\nstruct duk__pcall_prop_args {\n\tduk_idx_t obj_idx;\n\tduk_idx_t nargs;\n\tduk_small_uint_t call_flags;\n};\ntypedef struct duk__pcall_prop_args duk__pcall_prop_args;\n\nstruct duk__pcall_method_args {\n\tduk_idx_t nargs;\n\tduk_small_uint_t call_flags;\n};\ntypedef struct duk__pcall_method_args duk__pcall_method_args;\n\nstruct duk__pcall_args {\n\tduk_idx_t nargs;\n\tduk_small_uint_t call_flags;\n};\ntypedef struct duk__pcall_args duk__pcall_args;\n\n/* Compute and validate idx_func for a certain 'nargs' and 'other'\n * parameter count (1 or 2, depending on whether 'this' binding is\n * present).\n */\nDUK_LOCAL duk_idx_t duk__call_get_idx_func(duk_hthread *thr, duk_idx_t nargs, duk_idx_t other) {\n\tduk_idx_t idx_func;\n\n\t/* XXX: byte arithmetic? */\n\n\tDUK_ASSERT(other >= 0);\n\n\tidx_func = duk_get_top(thr) - nargs - other;\n\tif (DUK_UNLIKELY((idx_func | nargs) < 0)) {  /* idx_func < 0 || nargs < 0; OR sign bits */\n\t\tDUK_ERROR_TYPE_INVALID_ARGS(thr);\n\t\t/* unreachable */\n\t}\n\tDUK_ASSERT(duk_is_valid_index(thr, idx_func));\n\treturn idx_func;\n}\n\n/* Compute idx_func, assume index will be valid.  This is a valid assumption\n * for protected calls: nargs < 0 is checked explicitly and duk_safe_call()\n * validates the argument count.\n */\nDUK_LOCAL duk_idx_t duk__call_get_idx_func_unvalidated(duk_hthread *thr, duk_idx_t nargs, duk_idx_t other) {\n\tduk_idx_t idx_func;\n\n\t/* XXX: byte arithmetic? */\n\n\tDUK_ASSERT(nargs >= 0);\n\tDUK_ASSERT(other >= 0);\n\n\tidx_func = duk_get_top(thr) - nargs - other;\n\tDUK_ASSERT(idx_func >= 0);\n\tDUK_ASSERT(duk_is_valid_index(thr, idx_func));\n\treturn idx_func;\n}\n\n/* Prepare value stack for a method call through an object property.\n * May currently throw an error e.g. when getting the property.\n */\nDUK_LOCAL void duk__call_prop_prep_stack(duk_hthread *thr, duk_idx_t normalized_obj_idx, duk_idx_t nargs) {\n\tDUK_ASSERT_CTX_VALID(thr);\n\tDUK_ASSERT(nargs >= 0);\n\n\tDUK_DDD(DUK_DDDPRINT(\"duk__call_prop_prep_stack, normalized_obj_idx=%ld, nargs=%ld, stacktop=%ld\",\n\t                     (long) normalized_obj_idx, (long) nargs, (long) duk_get_top(thr)));\n\n\t/* [... key arg1 ... argN] */\n\n\t/* duplicate key */\n\tduk_dup(thr, -nargs - 1);  /* Note: -nargs alone would fail for nargs == 0, this is OK */\n\t(void) duk_get_prop(thr, normalized_obj_idx);\n\n\tDUK_DDD(DUK_DDDPRINT(\"func: %!T\", (duk_tval *) duk_get_tval(thr, -1)));\n\n#if defined(DUK_USE_VERBOSE_ERRORS)\n\tif (DUK_UNLIKELY(!duk_is_callable(thr, -1))) {\n\t\tduk_tval *tv_targ;\n\t\tduk_tval *tv_base;\n\t\tduk_tval *tv_key;\n\n\t\ttv_targ = DUK_GET_TVAL_NEGIDX(thr, -1);\n\t\ttv_base = DUK_GET_TVAL_POSIDX(thr, normalized_obj_idx);\n\t\ttv_key = DUK_GET_TVAL_NEGIDX(thr, -nargs - 2);\n\t\tDUK_ASSERT(tv_targ >= thr->valstack_bottom && tv_targ < thr->valstack_top);\n\t\tDUK_ASSERT(tv_base >= thr->valstack_bottom && tv_base < thr->valstack_top);\n\t\tDUK_ASSERT(tv_key >= thr->valstack_bottom && tv_key < thr->valstack_top);\n\n\t\tduk_call_setup_propcall_error(thr, tv_targ, tv_base, tv_key);\n\t}\n#endif\n\n\t/* [... key arg1 ... argN func] */\n\n\tduk_replace(thr, -nargs - 2);\n\n\t/* [... func arg1 ... argN] */\n\n\tduk_dup(thr, normalized_obj_idx);\n\tduk_insert(thr, -nargs - 1);\n\n\t/* [... func this arg1 ... argN] */\n}\n\nDUK_EXTERNAL void duk_call(duk_hthread *thr, duk_idx_t nargs) {\n\tduk_small_uint_t call_flags;\n\tduk_idx_t idx_func;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tidx_func = duk__call_get_idx_func(thr, nargs, 1);\n\tDUK_ASSERT(duk_is_valid_index(thr, idx_func));\n\n\tduk_insert_undefined(thr, idx_func + 1);\n\n\tcall_flags = 0;  /* not protected, respect reclimit, not constructor */\n\tduk_handle_call_unprotected(thr, idx_func, call_flags);\n}\n\nDUK_EXTERNAL void duk_call_method(duk_hthread *thr, duk_idx_t nargs) {\n\tduk_small_uint_t call_flags;\n\tduk_idx_t idx_func;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tidx_func = duk__call_get_idx_func(thr, nargs, 2);\n\tDUK_ASSERT(duk_is_valid_index(thr, idx_func));\n\n\tcall_flags = 0;  /* not protected, respect reclimit, not constructor */\n\tduk_handle_call_unprotected(thr, idx_func, call_flags);\n}\n\nDUK_EXTERNAL void duk_call_prop(duk_hthread *thr, duk_idx_t obj_idx, duk_idx_t nargs) {\n\t/*\n\t *  XXX: if duk_handle_call() took values through indices, this could be\n\t *  made much more sensible.  However, duk_handle_call() needs to fudge\n\t *  the 'this' and 'func' values to handle bound functions, which is now\n\t *  done \"in-place\", so this is not a trivial change.\n\t */\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tobj_idx = duk_require_normalize_index(thr, obj_idx);  /* make absolute */\n\tif (DUK_UNLIKELY(nargs < 0)) {\n\t\tDUK_ERROR_TYPE_INVALID_ARGS(thr);\n\t}\n\n\tduk__call_prop_prep_stack(thr, obj_idx, nargs);\n\n\tduk_call_method(thr, nargs);\n}\n\nDUK_LOCAL duk_ret_t duk__pcall_raw(duk_hthread *thr, void *udata) {\n\tduk__pcall_args *args;\n\tduk_idx_t idx_func;\n\tduk_int_t ret;\n\n\tDUK_ASSERT_CTX_VALID(thr);\n\tDUK_ASSERT(udata != NULL);\n\n\targs = (duk__pcall_args *) udata;\n\tidx_func = duk__call_get_idx_func_unvalidated(thr, args->nargs, 1);\n\tDUK_ASSERT(duk_is_valid_index(thr, idx_func));\n\n\tduk_insert_undefined(thr, idx_func + 1);\n\n\tret = duk_handle_call_unprotected(thr, idx_func, args->call_flags);\n\tDUK_ASSERT(ret == 0);\n\tDUK_UNREF(ret);\n\n\treturn 1;\n}\n\nDUK_EXTERNAL duk_int_t duk_pcall(duk_hthread *thr, duk_idx_t nargs) {\n\tduk__pcall_args args;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\targs.nargs = nargs;\n\tif (DUK_UNLIKELY(nargs < 0)) {\n\t\tDUK_ERROR_TYPE_INVALID_ARGS(thr);\n\t\treturn DUK_EXEC_ERROR;  /* unreachable */\n\t}\n\targs.call_flags = 0;\n\n\treturn duk_safe_call(thr, duk__pcall_raw, (void *) &args /*udata*/, nargs + 1 /*nargs*/, 1 /*nrets*/);\n}\n\nDUK_LOCAL duk_ret_t duk__pcall_method_raw(duk_hthread *thr, void *udata) {\n\tduk__pcall_method_args *args;\n\tduk_idx_t idx_func;\n\tduk_int_t ret;\n\n\tDUK_ASSERT_CTX_VALID(thr);\n\tDUK_ASSERT(udata != NULL);\n\n\targs = (duk__pcall_method_args *) udata;\n\n\tidx_func = duk__call_get_idx_func_unvalidated(thr, args->nargs, 2);\n\tDUK_ASSERT(duk_is_valid_index(thr, idx_func));\n\n\tret = duk_handle_call_unprotected(thr, idx_func, args->call_flags);\n\tDUK_ASSERT(ret == 0);\n\tDUK_UNREF(ret);\n\n\treturn 1;\n}\n\nDUK_INTERNAL duk_int_t duk_pcall_method_flags(duk_hthread *thr, duk_idx_t nargs, duk_small_uint_t call_flags) {\n\tduk__pcall_method_args args;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\targs.nargs = nargs;\n\tif (DUK_UNLIKELY(nargs < 0)) {\n\t\tDUK_ERROR_TYPE_INVALID_ARGS(thr);\n\t\treturn DUK_EXEC_ERROR;  /* unreachable */\n\t}\n\targs.call_flags = call_flags;\n\n\treturn duk_safe_call(thr, duk__pcall_method_raw, (void *) &args /*udata*/, nargs + 2 /*nargs*/, 1 /*nrets*/);\n}\n\nDUK_EXTERNAL duk_int_t duk_pcall_method(duk_hthread *thr, duk_idx_t nargs) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\treturn duk_pcall_method_flags(thr, nargs, 0);\n}\n\nDUK_LOCAL duk_ret_t duk__pcall_prop_raw(duk_hthread *thr, void *udata) {\n\tduk__pcall_prop_args *args;\n\tduk_idx_t obj_idx;\n\tduk_int_t ret;\n\n\tDUK_ASSERT_CTX_VALID(thr);\n\tDUK_ASSERT(udata != NULL);\n\n\targs = (duk__pcall_prop_args *) udata;\n\n\tobj_idx = duk_require_normalize_index(thr, args->obj_idx);  /* make absolute */\n\tduk__call_prop_prep_stack(thr, obj_idx, args->nargs);\n\n\tret = duk_handle_call_unprotected_nargs(thr, args->nargs, args->call_flags);\n\tDUK_ASSERT(ret == 0);\n\tDUK_UNREF(ret);\n\treturn 1;\n}\n\nDUK_EXTERNAL duk_int_t duk_pcall_prop(duk_hthread *thr, duk_idx_t obj_idx, duk_idx_t nargs) {\n\tduk__pcall_prop_args args;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\targs.obj_idx = obj_idx;\n\targs.nargs = nargs;\n\tif (DUK_UNLIKELY(nargs < 0)) {\n\t\tDUK_ERROR_TYPE_INVALID_ARGS(thr);\n\t\treturn DUK_EXEC_ERROR;  /* unreachable */\n\t}\n\targs.call_flags = 0;\n\n\treturn duk_safe_call(thr, duk__pcall_prop_raw, (void *) &args /*udata*/, nargs + 1 /*nargs*/, 1 /*nrets*/);\n}\n\nDUK_EXTERNAL duk_int_t duk_safe_call(duk_hthread *thr, duk_safe_call_function func, void *udata, duk_idx_t nargs, duk_idx_t nrets) {\n\tduk_int_t rc;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\t/* nargs condition; fail if: top - bottom < nargs\n\t *                      <=>  top < bottom + nargs\n\t * nrets condition; fail if: end - (top - nargs) < nrets\n\t *                      <=>  end - top + nargs < nrets\n\t *                      <=>  end + nargs < top + nrets\n\t */\n\t/* XXX: check for any reserve? */\n\n\tif (DUK_UNLIKELY((nargs | nrets) < 0 ||  /* nargs < 0 || nrets < 0; OR sign bits */\n\t                 thr->valstack_top < thr->valstack_bottom + nargs ||        /* nargs too large compared to top */\n\t                 thr->valstack_end + nargs < thr->valstack_top + nrets)) {  /* nrets too large compared to reserve */\n\t\tDUK_D(DUK_DPRINT(\"not enough stack reserve for safe call or invalid arguments: \"\n\t\t                 \"nargs=%ld < 0 (?), nrets=%ld < 0 (?), top=%ld < bottom=%ld + nargs=%ld (?), \"\n\t\t                 \"end=%ld + nargs=%ld < top=%ld + nrets=%ld (?)\",\n\t\t                  (long) nargs,\n\t\t                  (long) nrets,\n\t\t                  (long) (thr->valstack_top - thr->valstack),\n\t\t                  (long) (thr->valstack_bottom - thr->valstack),\n\t\t                  (long) nargs,\n\t\t                  (long) (thr->valstack_end - thr->valstack),\n\t\t                  (long) nargs,\n\t\t                  (long) (thr->valstack_top - thr->valstack),\n\t\t                  (long) nrets));\n\t\tDUK_ERROR_TYPE_INVALID_ARGS(thr);\n\t\treturn DUK_EXEC_ERROR;  /* unreachable */\n\t}\n\n\trc = duk_handle_safe_call(thr,           /* thread */\n\t                          func,          /* func */\n\t                          udata,         /* udata */\n\t                          nargs,         /* num_stack_args */\n\t                          nrets);        /* num_stack_res */\n\n\treturn rc;\n}\n\nDUK_EXTERNAL void duk_new(duk_hthread *thr, duk_idx_t nargs) {\n\tduk_idx_t idx_func;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tidx_func = duk__call_get_idx_func(thr, nargs, 1);\n\tDUK_ASSERT(duk_is_valid_index(thr, idx_func));\n\n\tduk_push_object(thr);  /* default instance; internal proto updated by call handling */\n\tduk_insert(thr, idx_func + 1);\n\n\tduk_handle_call_unprotected(thr, idx_func, DUK_CALL_FLAG_CONSTRUCT);\n}\n\nDUK_LOCAL duk_ret_t duk__pnew_helper(duk_hthread *thr, void *udata) {\n\tduk_idx_t nargs;\n\n\tDUK_ASSERT(udata != NULL);\n\tnargs = *((duk_idx_t *) udata);\n\n\tduk_new(thr, nargs);\n\treturn 1;\n}\n\nDUK_EXTERNAL duk_int_t duk_pnew(duk_hthread *thr, duk_idx_t nargs) {\n\tduk_int_t rc;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\t/* For now, just use duk_safe_call() to wrap duk_new().  We can't\n\t * simply use a protected duk_handle_call() because pushing the\n\t * default instance might throw.\n\t */\n\n\tif (DUK_UNLIKELY(nargs < 0)) {\n\t\tDUK_ERROR_TYPE_INVALID_ARGS(thr);\n\t\treturn DUK_EXEC_ERROR;  /* unreachable */\n\t}\n\n\trc = duk_safe_call(thr, duk__pnew_helper, (void *) &nargs /*udata*/, nargs + 1 /*nargs*/, 1 /*nrets*/);\n\treturn rc;\n}\n\nDUK_EXTERNAL duk_bool_t duk_is_constructor_call(duk_hthread *thr) {\n\tduk_activation *act;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tact = thr->callstack_curr;\n\tif (act != NULL) {\n\t\treturn ((act->flags & DUK_ACT_FLAG_CONSTRUCT) != 0 ? 1 : 0);\n\t}\n\treturn 0;\n}\n\n/* XXX: Make this obsolete by adding a function flag for rejecting a\n * non-constructor call automatically?\n */\nDUK_INTERNAL void duk_require_constructor_call(duk_hthread *thr) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tif (!duk_is_constructor_call(thr)) {\n\t\tDUK_ERROR_TYPE(thr, DUK_STR_CONSTRUCT_ONLY);\n\t}\n}\n\nDUK_EXTERNAL duk_bool_t duk_is_strict_call(duk_hthread *thr) {\n\tduk_activation *act;\n\n\t/* For user code this could just return 1 (strict) always\n\t * because all Duktape/C functions are considered strict,\n\t * and strict is also the default when nothing is running.\n\t * However, Duktape may call this function internally when\n\t * the current activation is an Ecmascript function, so\n\t * this cannot be replaced by a 'return 1' without fixing\n\t * the internal call sites.\n\t */\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tact = thr->callstack_curr;\n\tif (act != NULL) {\n\t\treturn ((act->flags & DUK_ACT_FLAG_STRICT) != 0 ? 1 : 0);\n\t} else {\n\t\t/* Strict by default. */\n\t\treturn 1;\n\t}\n}\n\n/*\n *  Duktape/C function magic\n */\n\nDUK_EXTERNAL duk_int_t duk_get_current_magic(duk_hthread *thr) {\n\tduk_activation *act;\n\tduk_hobject *func;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tact = thr->callstack_curr;\n\tif (act) {\n\t\tfunc = DUK_ACT_GET_FUNC(act);\n\t\tif (!func) {\n\t\t\tduk_tval *tv = &act->tv_func;\n\t\t\tduk_small_uint_t lf_flags;\n\t\t\tlf_flags = DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv);\n\t\t\treturn (duk_int_t) DUK_LFUNC_FLAGS_GET_MAGIC(lf_flags);\n\t\t}\n\t\tDUK_ASSERT(func != NULL);\n\n\t\tif (DUK_HOBJECT_IS_NATFUNC(func)) {\n\t\t\tduk_hnatfunc *nf = (duk_hnatfunc *) func;\n\t\t\treturn (duk_int_t) nf->magic;\n\t\t}\n\t}\n\treturn 0;\n}\n\nDUK_EXTERNAL duk_int_t duk_get_magic(duk_hthread *thr, duk_idx_t idx) {\n\tduk_tval *tv;\n\tduk_hobject *h;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\ttv = duk_require_tval(thr, idx);\n\tif (DUK_TVAL_IS_OBJECT(tv)) {\n\t\th = DUK_TVAL_GET_OBJECT(tv);\n\t\tDUK_ASSERT(h != NULL);\n\t\tif (!DUK_HOBJECT_HAS_NATFUNC(h)) {\n\t\t\tgoto type_error;\n\t\t}\n\t\treturn (duk_int_t) ((duk_hnatfunc *) h)->magic;\n\t} else if (DUK_TVAL_IS_LIGHTFUNC(tv)) {\n\t\tduk_small_uint_t lf_flags = DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv);\n\t\treturn (duk_int_t) DUK_LFUNC_FLAGS_GET_MAGIC(lf_flags);\n\t}\n\n\t/* fall through */\n type_error:\n\tDUK_ERROR_TYPE(thr, DUK_STR_UNEXPECTED_TYPE);\n\treturn 0;\n}\n\nDUK_EXTERNAL void duk_set_magic(duk_hthread *thr, duk_idx_t idx, duk_int_t magic) {\n\tduk_hnatfunc *nf;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tnf = duk_require_hnatfunc(thr, idx);\n\tDUK_ASSERT(nf != NULL);\n\tnf->magic = (duk_int16_t) magic;\n}\n\n/*\n *  Misc helpers\n */\n\n/* Resolve a bound function on value stack top to a non-bound target\n * (leave other values as is).\n */\nDUK_INTERNAL void duk_resolve_nonbound_function(duk_hthread *thr) {\n\tduk_tval *tv;\n\n\tDUK_ASSERT_HTHREAD_VALID(thr);\n\n\ttv = DUK_GET_TVAL_NEGIDX(thr, -1);\n\tif (DUK_TVAL_IS_OBJECT(tv)) {\n\t\tduk_hobject *h;\n\n\t\th = DUK_TVAL_GET_OBJECT(tv);\n\t\tDUK_ASSERT(h != NULL);\n\t\tif (DUK_HOBJECT_HAS_BOUNDFUNC(h)) {\n\t\t\tduk_push_tval(thr, &((duk_hboundfunc *) h)->target);\n\t\t\tduk_replace(thr, -2);\n#if 0\n\t\t\tDUK_TVAL_SET_TVAL(tv, &((duk_hboundfunc *) h)->target);\n\t\t\tDUK_TVAL_INCREF(thr, tv);\n\t\t\tDUK_HOBJECT_DECREF_NORZ(thr, h);\n#endif\n\t\t\t/* Rely on Function.prototype.bind() on never creating a bound\n\t\t\t * function whose target is not proper.  This is now safe\n\t\t\t * because the target is not even an internal property but a\n\t\t\t * struct member.\n\t\t\t */\n\t\t\tDUK_ASSERT(duk_is_lightfunc(thr, -1) || duk_is_callable(thr, -1));\n\t\t}\n\t}\n\n\t/* Lightfuncs cannot be bound but are always callable and\n\t * constructable.\n\t */\n}\n#line 1 \"duk_api_codec.c\"\n/*\n *  Encoding and decoding basic formats: hex, base64.\n *\n *  These are in-place operations which may allow an optimized implementation.\n *\n *  Base-64: https://tools.ietf.org/html/rfc4648#section-4\n */\n\n/* #include duk_internal.h -> already included */\n\n/* Shared handling for encode/decode argument.  Fast path handling for\n * buffer and string values because they're the most common.  In particular,\n * avoid creating a temporary string or buffer when possible.\n */\nDUK_LOCAL const duk_uint8_t *duk__prep_codec_arg(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_len) {\n\tvoid *ptr;\n\tduk_bool_t isbuffer;\n\n\tDUK_ASSERT(duk_is_valid_index(thr, idx));  /* checked by caller */\n\n\t/* XXX: with def_ptr set to a stack related pointer, isbuffer could\n\t * be removed from the helper?\n\t */\n\tptr = duk_get_buffer_data_raw(thr, idx, out_len, NULL /*def_ptr*/, 0 /*def_size*/, 0 /*throw_flag*/, &isbuffer);\n\tif (isbuffer) {\n\t\tDUK_ASSERT(*out_len == 0 || ptr != NULL);\n\t\treturn (const duk_uint8_t *) ptr;\n\t}\n\treturn (const duk_uint8_t *) duk_to_lstring(thr, idx, out_len);\n}\n\n#if defined(DUK_USE_BASE64_FASTPATH)\nDUK_LOCAL void duk__base64_encode_helper(const duk_uint8_t *src, duk_size_t srclen, duk_uint8_t *dst) {\n\tduk_uint_t t;\n\tduk_size_t n_full, n_full3, n_final;\n\tconst duk_uint8_t *src_end_fast;\n\n\tn_full = srclen / 3;  /* full 3-byte -> 4-char conversions */\n\tn_full3 = n_full * 3;\n\tn_final = srclen - n_full3;\n\tDUK_ASSERT_DISABLE(n_final >= 0);\n\tDUK_ASSERT(n_final <= 2);\n\n\tsrc_end_fast = src + n_full3;\n\twhile (DUK_UNLIKELY(src != src_end_fast)) {\n\t\tt = (duk_uint_t) (*src++);\n\t\tt = (t << 8) + (duk_uint_t) (*src++);\n\t\tt = (t << 8) + (duk_uint_t) (*src++);\n\n\t\t*dst++ = duk_base64_enctab[t >> 18];\n\t\t*dst++ = duk_base64_enctab[(t >> 12) & 0x3f];\n\t\t*dst++ = duk_base64_enctab[(t >> 6) & 0x3f];\n\t\t*dst++ = duk_base64_enctab[t & 0x3f];\n\n#if 0  /* Tested: not faster on x64 */\n\t\t/* aaaaaabb bbbbcccc ccdddddd */\n\t\tdst[0] = duk_base64_enctab[(src[0] >> 2) & 0x3f];\n\t\tdst[1] = duk_base64_enctab[((src[0] << 4) & 0x30) | ((src[1] >> 4) & 0x0f)];\n\t\tdst[2] = duk_base64_enctab[((src[1] << 2) & 0x3f) | ((src[2] >> 6) & 0x03)];\n\t\tdst[3] = duk_base64_enctab[src[2] & 0x3f];\n\t\tsrc += 3; dst += 4;\n#endif\n\t}\n\n\tswitch (n_final) {\n\t/* case 0: nop */\n\tcase 1: {\n\t\t/* XX== */\n\t\tt = (duk_uint_t) (*src++);\n\t\t*dst++ = duk_base64_enctab[t >> 2];           /* XXXXXX-- */\n\t\t*dst++ = duk_base64_enctab[(t << 4) & 0x3f];  /* ------XX */\n\t\t*dst++ = DUK_ASC_EQUALS;\n\t\t*dst++ = DUK_ASC_EQUALS;\n\t\tbreak;\n\t}\n\tcase 2: {\n\t\t/* XXX= */\n\t\tt = (duk_uint_t) (*src++);\n\t\tt = (t << 8) + (duk_uint_t) (*src++);\n\t\t*dst++ = duk_base64_enctab[t >> 10];          /* XXXXXX-- -------- */\n\t\t*dst++ = duk_base64_enctab[(t >> 4) & 0x3f];  /* ------XX XXXX---- */\n\t\t*dst++ = duk_base64_enctab[(t << 2) & 0x3f];  /* -------- ----XXXX */\n\t\t*dst++ = DUK_ASC_EQUALS;\n\t\tbreak;\n\t}\n\t}\n}\n#else  /* DUK_USE_BASE64_FASTPATH */\nDUK_LOCAL void duk__base64_encode_helper(const duk_uint8_t *src, duk_size_t srclen, duk_uint8_t *dst) {\n\tduk_small_uint_t i, snip;\n\tduk_uint_t t;\n\tduk_uint_fast8_t x, y;\n\tconst duk_uint8_t *src_end;\n\n\tsrc_end = src + srclen;\n\n\twhile (src < src_end) {\n\t\t/* read 3 bytes into 't', padded by zero */\n\t\tsnip = 4;\n\t\tt = 0;\n\t\tfor (i = 0; i < 3; i++) {\n\t\t\tt = t << 8;\n\t\t\tif (src >= src_end) {\n\t\t\t\tsnip--;\n\t\t\t} else {\n\t\t\t\tt += (duk_uint_t) (*src++);\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t *  Missing bytes    snip     base64 example\n\t\t *    0               4         XXXX\n\t\t *    1               3         XXX=\n\t\t *    2               2         XX==\n\t\t */\n\n\t\tDUK_ASSERT(snip >= 2 && snip <= 4);\n\n\t\tfor (i = 0; i < 4; i++) {\n\t\t\tx = (duk_uint_fast8_t) ((t >> 18) & 0x3f);\n\t\t\tt = t << 6;\n\n\t\t\t/* A straightforward 64-byte lookup would be faster\n\t\t\t * and cleaner, but this is shorter.\n\t\t\t */\n\t\t\tif (i >= snip) {\n\t\t\t\ty = '=';\n\t\t\t} else if (x <= 25) {\n\t\t\t\ty = x + 'A';\n\t\t\t} else if (x <= 51) {\n\t\t\t\ty = x - 26 + 'a';\n\t\t\t} else if (x <= 61) {\n\t\t\t\ty = x - 52 + '0';\n\t\t\t} else if (x == 62) {\n\t\t\t\ty = '+';\n\t\t\t} else {\n\t\t\t\ty = '/';\n\t\t\t}\n\n\t\t\t*dst++ = (duk_uint8_t) y;\n\t\t}\n\t}\n}\n#endif  /* DUK_USE_BASE64_FASTPATH */\n\n#if defined(DUK_USE_BASE64_FASTPATH)\nDUK_LOCAL duk_bool_t duk__base64_decode_helper(const duk_uint8_t *src, duk_size_t srclen, duk_uint8_t *dst, duk_uint8_t **out_dst_final) {\n\tduk_int_t x;\n\tduk_int_t t;\n\tduk_small_uint_t n_equal;\n\tduk_small_uint_t n_chars;\n\tconst duk_uint8_t *src_end;\n\tconst duk_uint8_t *src_end_safe;\n\n\tsrc_end = src + srclen;\n\tsrc_end_safe = src_end - 4;  /* if 'src < src_end_safe', safe to read 4 bytes */\n\n\t/* Innermost fast path processes 4 valid base-64 characters at a time\n\t * but bails out on whitespace, padding chars ('=') and invalid chars.\n\t * Once the slow path segment has been processed, we return to the\n\t * inner fast path again.  This handles e.g. base64 with newlines\n\t * reasonably well because the majority of a line is in the fast path.\n\t */\n\tfor (;;) {\n\t\t/* Fast path, handle units with just actual encoding characters. */\n\n\t\twhile (src <= src_end_safe) {\n\t\t\t/* The lookup byte is intentionally sign extended to (at least)\n\t\t\t * 32 bits and then ORed.  This ensures that is at least 1 byte\n\t\t\t * is negative, the highest bit of 't' will be set at the end\n\t\t\t * and we don't need to check every byte.\n\t\t\t */\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"fast loop: src=%p, src_end_safe=%p, src_end=%p\",\n\t\t\t                     (const void *) src, (const void *) src_end_safe, (const void *) src_end));\n\n\t\t\tt = (duk_int_t) duk_base64_dectab[*src++];\n\t\t\tt = (t << 6) | (duk_int_t) duk_base64_dectab[*src++];\n\t\t\tt = (t << 6) | (duk_int_t) duk_base64_dectab[*src++];\n\t\t\tt = (t << 6) | (duk_int_t) duk_base64_dectab[*src++];\n\n\t\t\tif (DUK_UNLIKELY(t < 0)) {\n\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"fast loop unit was not clean, process one slow path unit\"));\n\t\t\t\tsrc -= 4;\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tDUK_ASSERT(t <= 0xffffffL);\n\t\t\tDUK_ASSERT((t >> 24) == 0);\n\t\t\t*dst++ = (duk_uint8_t) (t >> 16);\n\t\t\t*dst++ = (duk_uint8_t) ((t >> 8) & 0xff);\n\t\t\t*dst++ = (duk_uint8_t) (t & 0xff);\n\t\t}\n\n\t\t/* Handle one slow path unit (or finish if we're done). */\n\n\t\tn_equal = 0;\n\t\tn_chars = 0;\n\t\tt = 0;\n\t\tfor (;;) {\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"slow loop: src=%p, src_end=%p, n_chars=%ld, n_equal=%ld, t=%ld\",\n\t\t\t                     (const void *) src, (const void *) src_end, (long) n_chars, (long) n_equal, (long) t));\n\n\t\t\tif (DUK_UNLIKELY(src >= src_end)) {\n\t\t\t\tgoto done;  /* two level break */\n\t\t\t}\n\n\t\t\tx = duk_base64_dectab[*src++];\n\t\t\tif (DUK_UNLIKELY(x < 0)) {\n\t\t\t\tif (x == -2) {\n\t\t\t\t\tcontinue;  /* allowed ascii whitespace */\n\t\t\t\t} else if (x == -3) {\n\t\t\t\t\tn_equal++;\n\t\t\t\t\tt <<= 6;\n\t\t\t\t} else {\n\t\t\t\t\tDUK_ASSERT(x == -1);\n\t\t\t\t\tgoto decode_error;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tDUK_ASSERT(x >= 0 && x <= 63);\n\t\t\t\tif (n_equal > 0) {\n\t\t\t\t\t/* Don't allow actual chars after equal sign. */\n\t\t\t\t\tgoto decode_error;\n\t\t\t\t}\n\t\t\t\tt = (t << 6) + x;\n\t\t\t}\n\n\t\t\tif (DUK_UNLIKELY(n_chars == 3)) {\n\t\t\t\t/* Emit 3 bytes and backtrack if there was padding.  There's\n\t\t\t\t * always space for the whole 3 bytes so no check needed.\n\t\t\t\t */\n\t\t\t\tDUK_ASSERT(t <= 0xffffffL);\n\t\t\t\tDUK_ASSERT((t >> 24) == 0);\n\t\t\t\t*dst++ = (duk_uint8_t) (t >> 16);\n\t\t\t\t*dst++ = (duk_uint8_t) ((t >> 8) & 0xff);\n\t\t\t\t*dst++ = (duk_uint8_t) (t & 0xff);\n\n\t\t\t\tif (DUK_UNLIKELY(n_equal > 0)) {\n\t\t\t\t\tDUK_ASSERT(n_equal <= 4);\n\n\t\t\t\t\t/* There may be whitespace between the equal signs. */\n\t\t\t\t\tif (n_equal == 1) {\n\t\t\t\t\t\t/* XXX= */\n\t\t\t\t\t\tdst -= 1;\n\t\t\t\t\t} else if (n_equal == 2) {\n\t\t\t\t\t\t/* XX== */\n\t\t\t\t\t\tdst -= 2;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tgoto decode_error;  /* invalid padding */\n\t\t\t\t\t}\n\n\t\t\t\t\t/* Continue parsing after padding, allows concatenated,\n\t\t\t\t\t * padded base64.\n\t\t\t\t\t */\n\t\t\t\t}\n\t\t\t\tbreak;  /* back to fast loop */\n\t\t\t} else {\n\t\t\t\tn_chars++;\n\t\t\t}\n\t\t}\n\t}\n done:\n\tDUK_DDD(DUK_DDDPRINT(\"done; src=%p, src_end=%p, n_chars=%ld\",\n\t                     (const void *) src, (const void *) src_end, (long) n_chars));\n\n\tDUK_ASSERT(src == src_end);\n\n\tif (n_chars != 0) {\n\t\t/* Here we'd have the option of decoding unpadded base64\n\t\t * (e.g. \"xxxxyy\" instead of \"xxxxyy==\".  Currently not\n\t\t * accepted.\n\t\t */\n\t\tgoto decode_error;\n\t}\n\n\t*out_dst_final = dst;\n\treturn 1;\n\n decode_error:\n\treturn 0;\n}\n#else  /* DUK_USE_BASE64_FASTPATH */\nDUK_LOCAL duk_bool_t duk__base64_decode_helper(const duk_uint8_t *src, duk_size_t srclen, duk_uint8_t *dst, duk_uint8_t **out_dst_final) {\n\tduk_uint_t t;\n\tduk_uint_fast8_t x, y;\n\tduk_small_uint_t group_idx;\n\tduk_small_uint_t n_equal;\n\tconst duk_uint8_t *src_end;\n\n\tsrc_end = src + srclen;\n\tt = 0;\n\tgroup_idx = 0;\n\tn_equal = 0;\n\n\twhile (src < src_end) {\n\t\tx = *src++;\n\n\t\tif (x >= 'A' && x <= 'Z') {\n\t\t\ty = x - 'A' + 0;\n\t\t} else if (x >= 'a' && x <= 'z') {\n\t\t\ty = x - 'a' + 26;\n\t\t} else if (x >= '0' && x <= '9') {\n\t\t\ty = x - '0' + 52;\n\t\t} else if (x == '+') {\n\t\t\ty = 62;\n\t\t} else if (x == '/') {\n\t\t\ty = 63;\n\t\t} else if (x == '=') {\n\t\t\t/* We don't check the zero padding bytes here right now\n\t\t\t * (that they're actually zero).  This seems to be common\n\t\t\t * behavior for base-64 decoders.\n\t\t\t */\n\n\t\t\tn_equal++;\n\t\t\tt <<= 6;  /* shift in zeroes */\n\t\t\tgoto skip_add;\n\t\t} else if (x == 0x09 || x == 0x0a || x == 0x0d || x == 0x20) {\n\t\t\t/* allow basic ASCII whitespace */\n\t\t\tcontinue;\n\t\t} else {\n\t\t\tgoto decode_error;\n\t\t}\n\n\t\tif (n_equal > 0) {\n\t\t\t/* Don't allow mixed padding and actual chars. */\n\t\t\tgoto decode_error;\n\t\t}\n\t\tt = (t << 6) + y;\n\t skip_add:\n\n\t\tif (group_idx == 3) {\n\t\t\t/* output 3 bytes from 't' */\n\t\t\t*dst++ = (duk_uint8_t) ((t >> 16) & 0xff);\n\t\t\t*dst++ = (duk_uint8_t) ((t >> 8) & 0xff);\n\t\t\t*dst++ = (duk_uint8_t) (t & 0xff);\n\n\t\t\tif (DUK_UNLIKELY(n_equal > 0)) {\n\t\t\t\t/* Backtrack. */\n\t\t\t\tDUK_ASSERT(n_equal <= 4);\n\t\t\t\tif (n_equal == 1) {\n\t\t\t\t\tdst -= 1;\n\t\t\t\t} else if (n_equal == 2) {\n\t\t\t\t\tdst -= 2;\n\t\t\t\t} else {\n\t\t\t\t\tgoto decode_error;  /* invalid padding */\n\t\t\t\t}\n\n\t\t\t\t/* Here we can choose either to end parsing and ignore\n\t\t\t\t * whatever follows, or to continue parsing in case\n\t\t\t\t * multiple (possibly padded) base64 strings have been\n\t\t\t\t * concatenated.  Currently, keep on parsing.\n\t\t\t\t */\n\t\t\t\tn_equal = 0;\n\t\t\t}\n\n\t\t\tt = 0;\n\t\t\tgroup_idx = 0;\n\t\t} else {\n\t\t\tgroup_idx++;\n\t\t}\n\t}\n\n\tif (group_idx != 0) {\n\t\t/* Here we'd have the option of decoding unpadded base64\n\t\t * (e.g. \"xxxxyy\" instead of \"xxxxyy==\".  Currently not\n\t\t * accepted.\n\t\t */\n\t\tgoto decode_error;\n\t}\n\n\t*out_dst_final = dst;\n\treturn 1;\n\n decode_error:\n\treturn 0;\n}\n#endif  /* DUK_USE_BASE64_FASTPATH */\n\nDUK_EXTERNAL const char *duk_base64_encode(duk_hthread *thr, duk_idx_t idx) {\n\tconst duk_uint8_t *src;\n\tduk_size_t srclen;\n\tduk_size_t dstlen;\n\tduk_uint8_t *dst;\n\tconst char *ret;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\t/* XXX: optimize for string inputs: no need to coerce to a buffer\n\t * which makes a copy of the input.\n\t */\n\n\tidx = duk_require_normalize_index(thr, idx);\n\tsrc = duk__prep_codec_arg(thr, idx, &srclen);\n\t/* Note: for srclen=0, src may be NULL */\n\n\t/* Computation must not wrap; this limit works for 32-bit size_t:\n\t * >>> srclen = 3221225469\n\t * >>> '%x' % ((srclen + 2) / 3 * 4)\n\t * 'fffffffc'\n\t */\n\tif (srclen > 3221225469UL) {\n\t\tgoto type_error;\n\t}\n\tdstlen = (srclen + 2) / 3 * 4;\n\tdst = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, dstlen);\n\n\tduk__base64_encode_helper((const duk_uint8_t *) src, srclen, dst);\n\n\tret = duk_buffer_to_string(thr, -1);  /* Safe, result is ASCII. */\n\tduk_replace(thr, idx);\n\treturn ret;\n\n type_error:\n\tDUK_ERROR_TYPE(thr, DUK_STR_BASE64_ENCODE_FAILED);\n\treturn NULL;  /* never here */\n}\n\nDUK_EXTERNAL void duk_base64_decode(duk_hthread *thr, duk_idx_t idx) {\n\tconst duk_uint8_t *src;\n\tduk_size_t srclen;\n\tduk_size_t dstlen;\n\tduk_uint8_t *dst;\n\tduk_uint8_t *dst_final;\n\tduk_bool_t retval;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\t/* XXX: optimize for buffer inputs: no need to coerce to a string\n\t * which causes an unnecessary interning.\n\t */\n\n\tidx = duk_require_normalize_index(thr, idx);\n\tsrc = duk__prep_codec_arg(thr, idx, &srclen);\n\n\t/* Computation must not wrap, only srclen + 3 is at risk of\n\t * wrapping because after that the number gets smaller.\n\t * This limit works for 32-bit size_t:\n\t * 0x100000000 - 3 - 1 = 4294967292\n\t */\n\tif (srclen > 4294967292UL) {\n\t\tgoto type_error;\n\t}\n\tdstlen = (srclen + 3) / 4 * 3;  /* upper limit, assuming no whitespace etc */\n\tdst = (duk_uint8_t *) duk_push_dynamic_buffer(thr, dstlen);\n\t/* Note: for dstlen=0, dst may be NULL */\n\n\tretval = duk__base64_decode_helper((const duk_uint8_t *) src, srclen, dst, &dst_final);\n\tif (!retval) {\n\t\tgoto type_error;\n\t}\n\n\t/* XXX: convert to fixed buffer? */\n\t(void) duk_resize_buffer(thr, -1, (duk_size_t) (dst_final - dst));\n\tduk_replace(thr, idx);\n\treturn;\n\n type_error:\n\tDUK_ERROR_TYPE(thr, DUK_STR_BASE64_DECODE_FAILED);\n}\n\nDUK_EXTERNAL const char *duk_hex_encode(duk_hthread *thr, duk_idx_t idx) {\n\tconst duk_uint8_t *inp;\n\tduk_size_t len;\n\tduk_size_t i;\n\tduk_uint8_t *buf;\n\tconst char *ret;\n#if defined(DUK_USE_HEX_FASTPATH)\n\tduk_size_t len_safe;\n\tduk_uint16_t *p16;\n#endif\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tidx = duk_require_normalize_index(thr, idx);\n\tinp = duk__prep_codec_arg(thr, idx, &len);\n\tDUK_ASSERT(inp != NULL || len == 0);\n\n\t/* Fixed buffer, no zeroing because we'll fill all the data. */\n\tbuf = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, len * 2);\n\tDUK_ASSERT(buf != NULL);\n\n#if defined(DUK_USE_HEX_FASTPATH)\n\tDUK_ASSERT((((duk_size_t) buf) & 0x01U) == 0);   /* pointer is aligned, guaranteed for fixed buffer */\n\tp16 = (duk_uint16_t *) (void *) buf;\n\tlen_safe = len & ~0x03U;\n\tfor (i = 0; i < len_safe; i += 4) {\n\t\tp16[0] = duk_hex_enctab[inp[i]];\n\t\tp16[1] = duk_hex_enctab[inp[i + 1]];\n\t\tp16[2] = duk_hex_enctab[inp[i + 2]];\n\t\tp16[3] = duk_hex_enctab[inp[i + 3]];\n\t\tp16 += 4;\n\t}\n\tfor (; i < len; i++) {\n\t\t*p16++ = duk_hex_enctab[inp[i]];\n\t}\n#else  /* DUK_USE_HEX_FASTPATH */\n\tfor (i = 0; i < len; i++) {\n\t\tduk_small_uint_t t;\n\t\tt = (duk_small_uint_t) inp[i];\n\t\tbuf[i*2 + 0] = duk_lc_digits[t >> 4];\n\t\tbuf[i*2 + 1] = duk_lc_digits[t & 0x0f];\n\t}\n#endif  /* DUK_USE_HEX_FASTPATH */\n\n\t/* XXX: Using a string return value forces a string intern which is\n\t * not always necessary.  As a rough performance measure, hex encode\n\t * time for tests/perf/test-hex-encode.js dropped from ~35s to ~15s\n\t * without string coercion.  Change to returning a buffer and let the\n\t * caller coerce to string if necessary?\n\t */\n\n\tret = duk_buffer_to_string(thr, -1);  /* Safe, result is ASCII. */\n\tduk_replace(thr, idx);\n\treturn ret;\n}\n\nDUK_EXTERNAL void duk_hex_decode(duk_hthread *thr, duk_idx_t idx) {\n\tconst duk_uint8_t *inp;\n\tduk_size_t len;\n\tduk_size_t i;\n\tduk_int_t t;\n\tduk_uint8_t *buf;\n#if defined(DUK_USE_HEX_FASTPATH)\n\tduk_int_t chk;\n\tduk_uint8_t *p;\n\tduk_size_t len_safe;\n#endif\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tidx = duk_require_normalize_index(thr, idx);\n\tinp = duk__prep_codec_arg(thr, idx, &len);\n\tDUK_ASSERT(inp != NULL || len == 0);\n\n\tif (len & 0x01) {\n\t\tgoto type_error;\n\t}\n\n\t/* Fixed buffer, no zeroing because we'll fill all the data. */\n\tbuf = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, len / 2);\n\tDUK_ASSERT(buf != NULL);\n\n#if defined(DUK_USE_HEX_FASTPATH)\n\tp = buf;\n\tlen_safe = len & ~0x07U;\n\tfor (i = 0; i < len_safe; i += 8) {\n\t\tt = ((duk_int_t) duk_hex_dectab_shift4[inp[i]]) |\n\t\t    ((duk_int_t) duk_hex_dectab[inp[i + 1]]);\n\t\tchk = t;\n\t\tp[0] = (duk_uint8_t) t;\n\t\tt = ((duk_int_t) duk_hex_dectab_shift4[inp[i + 2]]) |\n\t\t    ((duk_int_t) duk_hex_dectab[inp[i + 3]]);\n\t\tchk |= t;\n\t\tp[1] = (duk_uint8_t) t;\n\t\tt = ((duk_int_t) duk_hex_dectab_shift4[inp[i + 4]]) |\n\t\t    ((duk_int_t) duk_hex_dectab[inp[i + 5]]);\n\t\tchk |= t;\n\t\tp[2] = (duk_uint8_t) t;\n\t\tt = ((duk_int_t) duk_hex_dectab_shift4[inp[i + 6]]) |\n\t\t    ((duk_int_t) duk_hex_dectab[inp[i + 7]]);\n\t\tchk |= t;\n\t\tp[3] = (duk_uint8_t) t;\n\t\tp += 4;\n\n\t\t/* Check if any lookup above had a negative result. */\n\t\tif (DUK_UNLIKELY(chk < 0)) {\n\t\t\tgoto type_error;\n\t\t}\n\t}\n\tfor (; i < len; i += 2) {\n\t\tt = (((duk_int_t) duk_hex_dectab[inp[i]]) << 4) |\n\t\t    ((duk_int_t) duk_hex_dectab[inp[i + 1]]);\n\t\tif (DUK_UNLIKELY(t < 0)) {\n\t\t\tgoto type_error;\n\t\t}\n\t\t*p++ = (duk_uint8_t) t;\n\t}\n#else  /* DUK_USE_HEX_FASTPATH */\n\tfor (i = 0; i < len; i += 2) {\n\t\t/* For invalid characters the value -1 gets extended to\n\t\t * at least 16 bits.  If either nybble is invalid, the\n\t\t * resulting 't' will be < 0.\n\t\t */\n\t\tt = (((duk_int_t) duk_hex_dectab[inp[i]]) << 4) |\n\t\t    ((duk_int_t) duk_hex_dectab[inp[i + 1]]);\n\t\tif (DUK_UNLIKELY(t < 0)) {\n\t\t\tgoto type_error;\n\t\t}\n\t\tbuf[i >> 1] = (duk_uint8_t) t;\n\t}\n#endif  /* DUK_USE_HEX_FASTPATH */\n\n\tduk_replace(thr, idx);\n\treturn;\n\n type_error:\n\tDUK_ERROR_TYPE(thr, DUK_STR_HEX_DECODE_FAILED);\n}\n\n#if defined(DUK_USE_JSON_SUPPORT)\nDUK_EXTERNAL const char *duk_json_encode(duk_hthread *thr, duk_idx_t idx) {\n#if defined(DUK_USE_ASSERTIONS)\n\tduk_idx_t top_at_entry;\n#endif\n\tconst char *ret;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n#if defined(DUK_USE_ASSERTIONS)\n\ttop_at_entry = duk_get_top(thr);\n#endif\n\n\tidx = duk_require_normalize_index(thr, idx);\n\tduk_bi_json_stringify_helper(thr,\n\t                             idx /*idx_value*/,\n\t                             DUK_INVALID_INDEX /*idx_replacer*/,\n\t                             DUK_INVALID_INDEX /*idx_space*/,\n\t                             0 /*flags*/);\n\tDUK_ASSERT(duk_is_string(thr, -1));\n\tduk_replace(thr, idx);\n\tret = duk_get_string(thr, idx);\n\n\tDUK_ASSERT(duk_get_top(thr) == top_at_entry);\n\n\treturn ret;\n}\n\nDUK_EXTERNAL void duk_json_decode(duk_hthread *thr, duk_idx_t idx) {\n#if defined(DUK_USE_ASSERTIONS)\n\tduk_idx_t top_at_entry;\n#endif\n\n\tDUK_ASSERT_API_ENTRY(thr);\n#if defined(DUK_USE_ASSERTIONS)\n\ttop_at_entry = duk_get_top(thr);\n#endif\n\n\tidx = duk_require_normalize_index(thr, idx);\n\tduk_bi_json_parse_helper(thr,\n\t                         idx /*idx_value*/,\n\t                         DUK_INVALID_INDEX /*idx_reviver*/,\n\t                         0 /*flags*/);\n\tduk_replace(thr, idx);\n\n\tDUK_ASSERT(duk_get_top(thr) == top_at_entry);\n}\n#else  /* DUK_USE_JSON_SUPPORT */\nDUK_EXTERNAL const char *duk_json_encode(duk_hthread *thr, duk_idx_t idx) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK_UNREF(idx);\n\tDUK_ERROR_UNSUPPORTED(thr);\n}\n\nDUK_EXTERNAL void duk_json_decode(duk_hthread *thr, duk_idx_t idx) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK_UNREF(idx);\n\tDUK_ERROR_UNSUPPORTED(thr);\n}\n#endif  /* DUK_USE_JSON_SUPPORT */\n#line 1 \"duk_api_compile.c\"\n/*\n *  Compilation and evaluation\n */\n\n/* #include duk_internal.h -> already included */\n\ntypedef struct duk__compile_raw_args duk__compile_raw_args;\nstruct duk__compile_raw_args {\n\tduk_size_t src_length;  /* should be first on 64-bit platforms */\n\tconst duk_uint8_t *src_buffer;\n\tduk_uint_t flags;\n};\n\n/* Eval is just a wrapper now. */\nDUK_EXTERNAL duk_int_t duk_eval_raw(duk_hthread *thr, const char *src_buffer, duk_size_t src_length, duk_uint_t flags) {\n\tduk_int_t rc;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\t/* Note: strictness is *not* inherited from the current Duktape/C.\n\t * This would be confusing because the current strictness state\n\t * depends on whether we're running inside a Duktape/C activation\n\t * (= strict mode) or outside of any activation (= non-strict mode).\n\t * See tests/api/test-eval-strictness.c for more discussion.\n\t */\n\n\t/* [ ... source? filename? ] (depends on flags) */\n\n\trc = duk_compile_raw(thr, src_buffer, src_length, flags | DUK_COMPILE_EVAL);  /* may be safe, or non-safe depending on flags */\n\n\t/* [ ... closure/error ] */\n\n\tif (rc != DUK_EXEC_SUCCESS) {\n\t\trc = DUK_EXEC_ERROR;\n\t\tgoto got_rc;\n\t}\n\n\tduk_push_global_object(thr);  /* explicit 'this' binding, see GH-164 */\n\n\tif (flags & DUK_COMPILE_SAFE) {\n\t\trc = duk_pcall_method(thr, 0);\n\t} else {\n\t\tduk_call_method(thr, 0);\n\t\trc = DUK_EXEC_SUCCESS;\n\t}\n\n\t/* [ ... result/error ] */\n\n got_rc:\n\tif (flags & DUK_COMPILE_NORESULT) {\n\t\tduk_pop(thr);\n\t}\n\n\treturn rc;\n}\n\n/* Helper which can be called both directly and with duk_safe_call(). */\nDUK_LOCAL duk_ret_t duk__do_compile(duk_hthread *thr, void *udata) {\n\tduk__compile_raw_args *comp_args;\n\tduk_uint_t flags;\n\tduk_hcompfunc *h_templ;\n\n\tDUK_ASSERT_CTX_VALID(thr);\n\tDUK_ASSERT(udata != NULL);\n\n\t/* Note: strictness is not inherited from the current Duktape/C\n\t * context.  Otherwise it would not be possible to compile\n\t * non-strict code inside a Duktape/C activation (which is\n\t * always strict now).  See tests/api/test-eval-strictness.c\n\t * for discussion.\n\t */\n\n\t/* [ ... source? filename? ] (depends on flags) */\n\n\tcomp_args = (duk__compile_raw_args *) udata;\n\tflags = comp_args->flags;\n\n\tif (flags & DUK_COMPILE_NOFILENAME) {\n\t\t/* Automatic filename: 'eval' or 'input'. */\n\t\tduk_push_hstring_stridx(thr, (flags & DUK_COMPILE_EVAL) ? DUK_STRIDX_EVAL : DUK_STRIDX_INPUT);\n\t}\n\n\t/* [ ... source? filename ] */\n\n\tif (!comp_args->src_buffer) {\n\t\tduk_hstring *h_sourcecode;\n\n\t\th_sourcecode = duk_get_hstring(thr, -2);\n\t\tif ((flags & DUK_COMPILE_NOSOURCE) ||  /* args incorrect */\n\t\t    (h_sourcecode == NULL)) {          /* e.g. duk_push_string_file_raw() pushed undefined */\n\t\t\tDUK_ERROR_TYPE(thr, DUK_STR_NO_SOURCECODE);\n\t\t}\n\t\tDUK_ASSERT(h_sourcecode != NULL);\n\t\tcomp_args->src_buffer = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_sourcecode);\n\t\tcomp_args->src_length = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h_sourcecode);\n\t}\n\tDUK_ASSERT(comp_args->src_buffer != NULL);\n\n\tif (flags & DUK_COMPILE_FUNCTION) {\n\t\tflags |= DUK_COMPILE_EVAL | DUK_COMPILE_FUNCEXPR;\n\t}\n\n\t/* [ ... source? filename ] */\n\n\tduk_js_compile(thr, comp_args->src_buffer, comp_args->src_length, flags);\n\n\t/* [ ... source? func_template ] */\n\n\tif (flags & DUK_COMPILE_NOSOURCE) {\n\t\t;\n\t} else {\n\t\tduk_remove_m2(thr);\n\t}\n\n\t/* [ ... func_template ] */\n\n\th_templ = (duk_hcompfunc *) duk_known_hobject(thr, -1);\n\tduk_js_push_closure(thr,\n\t                   h_templ,\n\t                   thr->builtins[DUK_BIDX_GLOBAL_ENV],\n\t                   thr->builtins[DUK_BIDX_GLOBAL_ENV],\n\t                   1 /*add_auto_proto*/);\n\tduk_remove_m2(thr);   /* -> [ ... closure ] */\n\n\t/* [ ... closure ] */\n\n\treturn 1;\n}\n\nDUK_EXTERNAL duk_int_t duk_compile_raw(duk_hthread *thr, const char *src_buffer, duk_size_t src_length, duk_uint_t flags) {\n\tduk__compile_raw_args comp_args_alloc;\n\tduk__compile_raw_args *comp_args = &comp_args_alloc;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tif ((flags & DUK_COMPILE_STRLEN) && (src_buffer != NULL)) {\n\t\t/* String length is computed here to avoid multiple evaluation\n\t\t * of a macro argument in the calling side.\n\t\t */\n\t\tsrc_length = DUK_STRLEN(src_buffer);\n\t}\n\n\tcomp_args->src_buffer = (const duk_uint8_t *) src_buffer;\n\tcomp_args->src_length = src_length;\n\tcomp_args->flags = flags;\n\n\t/* [ ... source? filename? ] (depends on flags) */\n\n\tif (flags & DUK_COMPILE_SAFE) {\n\t\tduk_int_t rc;\n\t\tduk_int_t nargs;\n\t\tduk_int_t nrets = 1;\n\n\t\t/* Arguments can be: [ source? filename? &comp_args] so that\n\t\t * nargs is 1 to 3.  Call site encodes the correct nargs count\n\t\t * directly into flags.\n\t\t */\n\t\tnargs = flags & 0x07;\n\t\tDUK_ASSERT(nargs == ((flags & DUK_COMPILE_NOSOURCE) ? 0 : 1) +\n\t\t                    ((flags & DUK_COMPILE_NOFILENAME) ? 0 : 1));\n\t\trc = duk_safe_call(thr, duk__do_compile, (void *) comp_args, nargs, nrets);\n\n\t\t/* [ ... closure ] */\n\t\treturn rc;\n\t}\n\n\t(void) duk__do_compile(thr, (void *) comp_args);\n\n\t/* [ ... closure ] */\n\treturn DUK_EXEC_SUCCESS;\n}\n#line 1 \"duk_api_debug.c\"\n/*\n *  Debugging related API calls\n */\n\n/* #include duk_internal.h -> already included */\n\n#if defined(DUK_USE_JSON_SUPPORT)\nDUK_EXTERNAL void duk_push_context_dump(duk_hthread *thr) {\n\tduk_idx_t idx;\n\tduk_idx_t top;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\t/* We don't duk_require_stack() here now, but rely on the caller having\n\t * enough space.\n\t */\n\n\ttop = duk_get_top(thr);\n\tduk_push_array(thr);\n\tfor (idx = 0; idx < top; idx++) {\n\t\tduk_dup(thr, idx);\n\t\tduk_put_prop_index(thr, -2, (duk_uarridx_t) idx);\n\t}\n\n\t/* XXX: conversion errors should not propagate outwards.\n\t * Perhaps values need to be coerced individually?\n\t */\n\tduk_bi_json_stringify_helper(thr,\n\t                             duk_get_top_index(thr),  /*idx_value*/\n\t                             DUK_INVALID_INDEX,  /*idx_replacer*/\n\t                             DUK_INVALID_INDEX,  /*idx_space*/\n\t                             DUK_JSON_FLAG_EXT_CUSTOM |\n\t                             DUK_JSON_FLAG_ASCII_ONLY |\n\t                             DUK_JSON_FLAG_AVOID_KEY_QUOTES /*flags*/);\n\n\tduk_push_sprintf(thr, \"ctx: top=%ld, stack=%s\", (long) top, (const char *) duk_safe_to_string(thr, -1));\n\tduk_replace(thr, -3);  /* [ ... arr jsonx(arr) res ] -> [ ... res jsonx(arr) ] */\n\tduk_pop(thr);\n\tDUK_ASSERT(duk_is_string(thr, -1));\n}\n#else  /* DUK_USE_JSON_SUPPORT */\nDUK_EXTERNAL void duk_push_context_dump(duk_hthread *thr) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK_ERROR_UNSUPPORTED(thr);\n}\n#endif  /* DUK_USE_JSON_SUPPORT */\n\n#if defined(DUK_USE_DEBUGGER_SUPPORT)\n\nDUK_EXTERNAL void duk_debugger_attach(duk_hthread *thr,\n                                      duk_debug_read_function read_cb,\n                                      duk_debug_write_function write_cb,\n                                      duk_debug_peek_function peek_cb,\n                                      duk_debug_read_flush_function read_flush_cb,\n                                      duk_debug_write_flush_function write_flush_cb,\n                                      duk_debug_request_function request_cb,\n                                      duk_debug_detached_function detached_cb,\n                                      void *udata) {\n\tduk_heap *heap;\n\tconst char *str;\n\tduk_size_t len;\n\n\t/* XXX: should there be an error or an automatic detach if\n\t * already attached?\n\t */\n\n\tDUK_D(DUK_DPRINT(\"application called duk_debugger_attach()\"));\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK_ASSERT(read_cb != NULL);\n\tDUK_ASSERT(write_cb != NULL);\n\t/* Other callbacks are optional. */\n\n\theap = thr->heap;\n\theap->dbg_read_cb = read_cb;\n\theap->dbg_write_cb = write_cb;\n\theap->dbg_peek_cb = peek_cb;\n\theap->dbg_read_flush_cb = read_flush_cb;\n\theap->dbg_write_flush_cb = write_flush_cb;\n\theap->dbg_request_cb = request_cb;\n\theap->dbg_detached_cb = detached_cb;\n\theap->dbg_udata = udata;\n\theap->dbg_have_next_byte = 0;\n\n\t/* Start in paused state. */\n\theap->dbg_processing = 0;\n\theap->dbg_state_dirty = 0;\n\theap->dbg_force_restart = 0;\n\theap->dbg_pause_flags = 0;\n\theap->dbg_pause_act = NULL;\n\theap->dbg_pause_startline = 0;\n\theap->dbg_exec_counter = 0;\n\theap->dbg_last_counter = 0;\n\theap->dbg_last_time = 0.0;\n\tduk_debug_set_paused(heap);  /* XXX: overlap with fields above */\n\n\t/* Send version identification and flush right afterwards.  Note that\n\t * we must write raw, unframed bytes here.\n\t */\n\tduk_push_sprintf(thr, \"%ld %ld %s %s\\n\",\n\t                 (long) DUK_DEBUG_PROTOCOL_VERSION,\n\t                 (long) DUK_VERSION,\n\t                 (const char *) DUK_GIT_DESCRIBE,\n\t                 (const char *) DUK_USE_TARGET_INFO);\n\tstr = duk_get_lstring(thr, -1, &len);\n\tDUK_ASSERT(str != NULL);\n\tduk_debug_write_bytes(thr, (const duk_uint8_t *) str, len);\n\tduk_debug_write_flush(thr);\n\tduk_pop(thr);\n}\n\nDUK_EXTERNAL void duk_debugger_detach(duk_hthread *thr) {\n\tDUK_D(DUK_DPRINT(\"application called duk_debugger_detach()\"));\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK_ASSERT(thr->heap != NULL);\n\n\t/* Can be called multiple times with no harm. */\n\tduk_debug_do_detach(thr->heap);\n}\n\nDUK_EXTERNAL void duk_debugger_cooperate(duk_hthread *thr) {\n\tduk_bool_t processed_messages;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK_ASSERT(thr->heap != NULL);\n\n\tif (!duk_debug_is_attached(thr->heap)) {\n\t\treturn;\n\t}\n\tif (thr->callstack_curr != NULL || thr->heap->dbg_processing) {\n\t\t/* Calling duk_debugger_cooperate() while Duktape is being\n\t\t * called into is not supported.  This is not a 100% check\n\t\t * but prevents any damage in most cases.\n\t\t */\n\t\treturn;\n\t}\n\n\tprocessed_messages = duk_debug_process_messages(thr, 1 /*no_block*/);\n\tDUK_UNREF(processed_messages);\n}\n\nDUK_EXTERNAL duk_bool_t duk_debugger_notify(duk_hthread *thr, duk_idx_t nvalues) {\n\tduk_idx_t top;\n\tduk_idx_t idx;\n\tduk_bool_t ret = 0;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK_ASSERT(thr->heap != NULL);\n\n\tDUK_D(DUK_DPRINT(\"application called duk_debugger_notify() with nvalues=%ld\", (long) nvalues));\n\n\ttop = duk_get_top(thr);\n\tif (top < nvalues) {\n\t\tDUK_ERROR_RANGE(thr, \"not enough stack values for notify\");\n\t\treturn ret;  /* unreachable */\n\t}\n\tif (duk_debug_is_attached(thr->heap)) {\n\t\tduk_debug_write_notify(thr, DUK_DBG_CMD_APPNOTIFY);\n\t\tfor (idx = top - nvalues; idx < top; idx++) {\n\t\t\tduk_tval *tv = DUK_GET_TVAL_POSIDX(thr, idx);\n\t\t\tduk_debug_write_tval(thr, tv);\n\t\t}\n\t\tduk_debug_write_eom(thr);\n\n\t\t/* Return non-zero (true) if we have a good reason to believe\n\t\t * the notify was delivered; if we're still attached at least\n\t\t * a transport error was not indicated by the transport write\n\t\t * callback.  This is not a 100% guarantee of course.\n\t\t */\n\t\tif (duk_debug_is_attached(thr->heap)) {\n\t\t\tret = 1;\n\t\t}\n\t}\n\tduk_pop_n(thr, nvalues);\n\treturn ret;\n}\n\nDUK_EXTERNAL void duk_debugger_pause(duk_hthread *thr) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK_ASSERT(thr->heap != NULL);\n\n\tDUK_D(DUK_DPRINT(\"application called duk_debugger_pause()\"));\n\n\t/* Treat like a debugger statement: ignore when not attached. */\n\tif (duk_debug_is_attached(thr->heap)) {\n\t\tif (duk_debug_is_paused(thr->heap)) {\n\t\t\tDUK_D(DUK_DPRINT(\"duk_debugger_pause() called when already paused; ignoring\"));\n\t\t} else {\n\t\t\tduk_debug_set_paused(thr->heap);\n\n\t\t\t/* Pause on the next opcode executed.  This is always safe to do even\n\t\t\t * inside the debugger message loop: the interrupt counter will be reset\n\t\t\t * to its proper value when the message loop exits.\n\t\t\t */\n\t\t\tthr->interrupt_init = 1;\n\t\t\tthr->interrupt_counter = 0;\n\t\t}\n\t}\n}\n\n#else  /* DUK_USE_DEBUGGER_SUPPORT */\n\nDUK_EXTERNAL void duk_debugger_attach(duk_hthread *thr,\n                                      duk_debug_read_function read_cb,\n                                      duk_debug_write_function write_cb,\n                                      duk_debug_peek_function peek_cb,\n                                      duk_debug_read_flush_function read_flush_cb,\n                                      duk_debug_write_flush_function write_flush_cb,\n                                      duk_debug_request_function request_cb,\n                                      duk_debug_detached_function detached_cb,\n                                      void *udata) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK_UNREF(read_cb);\n\tDUK_UNREF(write_cb);\n\tDUK_UNREF(peek_cb);\n\tDUK_UNREF(read_flush_cb);\n\tDUK_UNREF(write_flush_cb);\n\tDUK_UNREF(request_cb);\n\tDUK_UNREF(detached_cb);\n\tDUK_UNREF(udata);\n\tDUK_ERROR_TYPE(thr, \"no debugger support\");\n}\n\nDUK_EXTERNAL void duk_debugger_detach(duk_hthread *thr) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK_ERROR_TYPE(thr, \"no debugger support\");\n}\n\nDUK_EXTERNAL void duk_debugger_cooperate(duk_hthread *thr) {\n\t/* nop */\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK_UNREF(thr);\n}\n\nDUK_EXTERNAL duk_bool_t duk_debugger_notify(duk_hthread *thr, duk_idx_t nvalues) {\n\tduk_idx_t top;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\ttop = duk_get_top(thr);\n\tif (top < nvalues) {\n\t\tDUK_ERROR_RANGE_INVALID_COUNT(thr);\n\t\treturn 0;  /* unreachable */\n\t}\n\n\t/* No debugger support, just pop values. */\n\tduk_pop_n(thr, nvalues);\n\treturn 0;\n}\n\nDUK_EXTERNAL void duk_debugger_pause(duk_hthread *thr) {\n\t/* Treat like debugger statement: nop */\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK_UNREF(thr);\n}\n\n#endif  /* DUK_USE_DEBUGGER_SUPPORT */\n#line 1 \"duk_api_heap.c\"\n/*\n *  Heap creation and destruction\n */\n\n/* #include duk_internal.h -> already included */\n\ntypedef struct duk_internal_thread_state duk_internal_thread_state;\n\nstruct duk_internal_thread_state {\n\tduk_ljstate lj;\n\tduk_bool_t creating_error;\n\tduk_hthread *curr_thread;\n\tduk_int_t call_recursion_depth;\n};\n\nDUK_EXTERNAL duk_hthread *duk_create_heap(duk_alloc_function alloc_func,\n                                          duk_realloc_function realloc_func,\n                                          duk_free_function free_func,\n                                          void *heap_udata,\n                                          duk_fatal_function fatal_handler) {\n\tduk_heap *heap = NULL;\n\tduk_hthread *thr;\n\n\t/* Assume that either all memory funcs are NULL or non-NULL, mixed\n\t * cases will now be unsafe.\n\t */\n\n\t/* XXX: just assert non-NULL values here and make caller arguments\n\t * do the defaulting to the default implementations (smaller code)?\n\t */\n\n\tif (!alloc_func) {\n\t\tDUK_ASSERT(realloc_func == NULL);\n\t\tDUK_ASSERT(free_func == NULL);\n#if defined(DUK_USE_PROVIDE_DEFAULT_ALLOC_FUNCTIONS)\n\t\talloc_func = duk_default_alloc_function;\n\t\trealloc_func = duk_default_realloc_function;\n\t\tfree_func = duk_default_free_function;\n#else\n\t\tDUK_D(DUK_DPRINT(\"no allocation functions given and no default providers\"));\n\t\treturn NULL;\n#endif\n\t} else {\n\t\tDUK_ASSERT(realloc_func != NULL);\n\t\tDUK_ASSERT(free_func != NULL);\n\t}\n\n\tif (!fatal_handler) {\n\t\tfatal_handler = duk_default_fatal_handler;\n\t}\n\n\tDUK_ASSERT(alloc_func != NULL);\n\tDUK_ASSERT(realloc_func != NULL);\n\tDUK_ASSERT(free_func != NULL);\n\tDUK_ASSERT(fatal_handler != NULL);\n\n\theap = duk_heap_alloc(alloc_func, realloc_func, free_func, heap_udata, fatal_handler);\n\tif (!heap) {\n\t\treturn NULL;\n\t}\n\tthr = heap->heap_thread;\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(thr->heap != NULL);\n\treturn thr;\n}\n\nDUK_EXTERNAL void duk_destroy_heap(duk_hthread *thr) {\n\tduk_heap *heap;\n\n\tif (!thr) {\n\t\treturn;\n\t}\n\tDUK_ASSERT_API_ENTRY(thr);\n\theap = thr->heap;\n\tDUK_ASSERT(heap != NULL);\n\n\tduk_heap_free(heap);\n}\n\nDUK_EXTERNAL void duk_suspend(duk_hthread *thr, duk_thread_state *state) {\n\tduk_internal_thread_state *snapshot = (duk_internal_thread_state *) (void *) state;\n\tduk_heap *heap;\n\tduk_ljstate *lj;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK_ASSERT(thr->heap != NULL);\n\tDUK_ASSERT(state != NULL);  /* unvalidated */\n\n\t/* Currently not supported when called from within a finalizer.\n\t * If that is done, the finalizer will remain running indefinitely,\n\t * preventing other finalizers from executing.  The assert is a bit\n\t * wider, checking that it would be OK to run pending finalizers.\n\t */\n\tDUK_ASSERT(thr->heap->pf_prevent_count == 0);\n\n\t/* Currently not supported to duk_suspend() from an errCreate()\n\t * call.\n\t */\n\tDUK_ASSERT(thr->heap->creating_error == 0);\n\n\theap = thr->heap;\n\tlj = &heap->lj;\n\n\tduk_push_tval(thr, &lj->value1);\n\tduk_push_tval(thr, &lj->value2);\n\n\t/* XXX: creating_error == 0 is asserted above, so no need to store. */\n\tDUK_MEMCPY((void *) &snapshot->lj, (const void *) lj, sizeof(duk_ljstate));\n\tsnapshot->creating_error = heap->creating_error;\n\tsnapshot->curr_thread = heap->curr_thread;\n\tsnapshot->call_recursion_depth = heap->call_recursion_depth;\n\n\tlj->jmpbuf_ptr = NULL;\n\tlj->type = DUK_LJ_TYPE_UNKNOWN;\n\tDUK_TVAL_SET_UNDEFINED(&lj->value1);\n\tDUK_TVAL_SET_UNDEFINED(&lj->value2);\n\theap->creating_error = 0;\n\theap->curr_thread = NULL;\n\theap->call_recursion_depth = 0;\n}\n\nDUK_EXTERNAL void duk_resume(duk_hthread *thr, const duk_thread_state *state) {\n\tconst duk_internal_thread_state *snapshot = (const duk_internal_thread_state *) (const void *) state;\n\tduk_heap *heap;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK_ASSERT(thr->heap != NULL);\n\tDUK_ASSERT(state != NULL);  /* unvalidated */\n\n\t/* Shouldn't be necessary if duk_suspend() is called before\n\t * duk_resume(), but assert in case API sequence is incorrect.\n\t */\n\tDUK_ASSERT(thr->heap->pf_prevent_count == 0);\n\tDUK_ASSERT(thr->heap->creating_error == 0);\n\n\theap = thr->heap;\n\n\tDUK_MEMCPY((void *) &heap->lj, (const void *) &snapshot->lj, sizeof(duk_ljstate));\n\theap->creating_error = snapshot->creating_error;\n\theap->curr_thread = snapshot->curr_thread;\n\theap->call_recursion_depth = snapshot->call_recursion_depth;\n\n\tduk_pop_2(thr);\n}\n\n/* XXX: better place for this */\nDUK_EXTERNAL void duk_set_global_object(duk_hthread *thr) {\n\tduk_hobject *h_glob;\n\tduk_hobject *h_prev_glob;\n\tduk_hobjenv *h_env;\n\tduk_hobject *h_prev_env;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tDUK_D(DUK_DPRINT(\"replace global object with: %!T\", duk_get_tval(thr, -1)));\n\n\th_glob = duk_require_hobject(thr, -1);\n\tDUK_ASSERT(h_glob != NULL);\n\n\t/*\n\t *  Replace global object.\n\t */\n\n\th_prev_glob = thr->builtins[DUK_BIDX_GLOBAL];\n\tDUK_UNREF(h_prev_glob);\n\tthr->builtins[DUK_BIDX_GLOBAL] = h_glob;\n\tDUK_HOBJECT_INCREF(thr, h_glob);\n\tDUK_HOBJECT_DECREF_ALLOWNULL(thr, h_prev_glob);  /* side effects, in theory (referenced by global env) */\n\n\t/*\n\t *  Replace lexical environment for global scope\n\t *\n\t *  Create a new object environment for the global lexical scope.\n\t *  We can't just reset the _Target property of the current one,\n\t *  because the lexical scope is shared by other threads with the\n\t *  same (initial) built-ins.\n\t */\n\n\th_env = duk_hobjenv_alloc(thr,\n\t                          DUK_HOBJECT_FLAG_EXTENSIBLE |\n\t                          DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJENV));\n\tDUK_ASSERT(h_env != NULL);\n\tDUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) h_env) == NULL);\n\n\tDUK_ASSERT(h_env->target == NULL);\n\tDUK_ASSERT(h_glob != NULL);\n\th_env->target = h_glob;\n\tDUK_HOBJECT_INCREF(thr, h_glob);\n\tDUK_ASSERT(h_env->has_this == 0);\n\n\t/* [ ... new_glob ] */\n\n\th_prev_env = thr->builtins[DUK_BIDX_GLOBAL_ENV];\n\tthr->builtins[DUK_BIDX_GLOBAL_ENV] = (duk_hobject *) h_env;\n\tDUK_HOBJECT_INCREF(thr, (duk_hobject *) h_env);\n\tDUK_HOBJECT_DECREF_ALLOWNULL(thr, h_prev_env);  /* side effects */\n\tDUK_UNREF(h_env);  /* without refcounts */\n\tDUK_UNREF(h_prev_env);\n\n\t/* [ ... new_glob ] */\n\n\tduk_pop(thr);\n\n\t/* [ ... ] */\n}\n#line 1 \"duk_api_inspect.c\"\n/*\n *  Inspection\n */\n\n/* #include duk_internal.h -> already included */\n\n/* For footprint efficient multiple value setting: arrays are much better than\n * varargs, format string with parsing is often better than string pointer arrays.\n */\nDUK_LOCAL void duk__inspect_multiple_uint(duk_hthread *thr, const char *fmt, duk_int_t *vals) {\n\tduk_int_t val;\n\tconst char *p;\n\tconst char *p_curr;\n\tduk_size_t len;\n\n\tfor (p = fmt;;) {\n\t\tlen = DUK_STRLEN(p);\n\t\tp_curr = p;\n\t\tp += len + 1;\n\t\tif (len == 0) {\n\t\t\t/* Double NUL (= empty key) terminates. */\n\t\t\tbreak;\n\t\t}\n\t\tval = *vals++;\n\t\tif (val >= 0) {\n\t\t\t/* Negative values are markers to skip key. */\n\t\t\tduk_push_string(thr, p_curr);\n\t\t\tduk_push_int(thr, val);\n\t\t\tduk_put_prop(thr, -3);\n\t\t}\n\t}\n}\n\n/* Raw helper to extract internal information / statistics about a value.\n * The return value is an object with properties that are version specific.\n * The properties must not expose anything that would lead to security\n * issues (e.g. exposing compiled function 'data' buffer might be an issue).\n * Currently only counts and sizes and such are given so there shouldn't\n * be security implications.\n */\n\n#define DUK__IDX_TYPE     0\n#define DUK__IDX_ITAG     1\n#define DUK__IDX_REFC     2\n#define DUK__IDX_HBYTES   3\n#define DUK__IDX_CLASS    4\n#define DUK__IDX_PBYTES   5\n#define DUK__IDX_ESIZE    6\n#define DUK__IDX_ENEXT    7\n#define DUK__IDX_ASIZE    8\n#define DUK__IDX_HSIZE    9\n#define DUK__IDX_BCBYTES  10\n#define DUK__IDX_DBYTES   11\n#define DUK__IDX_TSTATE   12\n#define DUK__IDX_VARIANT  13\n\nDUK_EXTERNAL void duk_inspect_value(duk_hthread *thr, duk_idx_t idx) {\n\tduk_tval *tv;\n\tduk_heaphdr *h;\n\t/* The temporary values should be in an array rather than individual\n\t * variables which (in practice) ensures that the compiler won't map\n\t * them to registers and emit a lot of unnecessary shuffling code.\n\t */\n\tduk_int_t vals[14];\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\t/* Assume two's complement and set everything to -1. */\n\tDUK_MEMSET((void *) &vals, (int) 0xff, sizeof(vals));\n\tDUK_ASSERT(vals[DUK__IDX_TYPE] == -1);  /* spot check one */\n\n\ttv = duk_get_tval_or_unused(thr, idx);\n\th = (DUK_TVAL_IS_HEAP_ALLOCATED(tv) ? DUK_TVAL_GET_HEAPHDR(tv) : NULL);\n\n\tvals[DUK__IDX_TYPE] = duk_get_type_tval(tv);\n\tvals[DUK__IDX_ITAG] = (duk_int_t) DUK_TVAL_GET_TAG(tv);\n\n\tduk_push_bare_object(thr);  /* Invalidates 'tv'. */\n\ttv = NULL;\n\n\tif (h == NULL) {\n\t\tgoto finish;\n\t}\n\tduk_push_pointer(thr, (void *) h);\n\tduk_put_prop_string(thr, -2, \"hptr\");\n\n#if 0\n\t/* Covers a lot of information, e.g. buffer and string variants. */\n\tduk_push_uint(thr, (duk_uint_t) DUK_HEAPHDR_GET_FLAGS(h));\n\tduk_put_prop_string(thr, -2, \"hflags\");\n#endif\n\n#if defined(DUK_USE_REFERENCE_COUNTING)\n\tvals[DUK__IDX_REFC] = (duk_int_t) DUK_HEAPHDR_GET_REFCOUNT(h);\n#endif\n\tvals[DUK__IDX_VARIANT] = 0;\n\n\t/* Heaphdr size and additional allocation size, followed by\n\t * type specific stuff (with varying value count).\n\t */\n\tswitch ((duk_small_int_t) DUK_HEAPHDR_GET_TYPE(h)) {\n\tcase DUK_HTYPE_STRING: {\n\t\tduk_hstring *h_str = (duk_hstring *) h;\n\t\tvals[DUK__IDX_HBYTES] = (duk_int_t) (sizeof(duk_hstring) + DUK_HSTRING_GET_BYTELEN(h_str) + 1);\n#if defined(DUK_USE_HSTRING_EXTDATA)\n\t\tif (DUK_HSTRING_HAS_EXTDATA(h_str)) {\n\t\t\tvals[DUK__IDX_VARIANT] = 1;\n\t\t}\n#endif\n\t\tbreak;\n\t}\n\tcase DUK_HTYPE_OBJECT: {\n\t\tduk_hobject *h_obj = (duk_hobject *) h;\n\n\t\t/* XXX: variants here are maybe pointless; class is enough? */\n\t\tif (DUK_HOBJECT_IS_ARRAY(h_obj)) {\n\t\t\tvals[DUK__IDX_HBYTES] = sizeof(duk_harray);\n\t\t} else if (DUK_HOBJECT_IS_COMPFUNC(h_obj)) {\n\t\t\tvals[DUK__IDX_HBYTES] = sizeof(duk_hcompfunc);\n\t\t} else if (DUK_HOBJECT_IS_NATFUNC(h_obj)) {\n\t\t\tvals[DUK__IDX_HBYTES] = sizeof(duk_hnatfunc);\n\t\t} else if (DUK_HOBJECT_IS_THREAD(h_obj)) {\n\t\t\tvals[DUK__IDX_HBYTES] = sizeof(duk_hthread);\n\t\t\tvals[DUK__IDX_TSTATE] = ((duk_hthread *) h_obj)->state;\n#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)\n\t\t} else if (DUK_HOBJECT_IS_BUFOBJ(h_obj)) {\n\t\t\tvals[DUK__IDX_HBYTES] = sizeof(duk_hbufobj);\n\t\t\t/* XXX: some size information */\n#endif\n\t\t} else {\n\t\t\tvals[DUK__IDX_HBYTES] = (duk_small_uint_t) sizeof(duk_hobject);\n\t\t}\n\n\t\tvals[DUK__IDX_CLASS] = (duk_int_t) DUK_HOBJECT_GET_CLASS_NUMBER(h_obj);\n\t\tvals[DUK__IDX_PBYTES] = (duk_int_t) DUK_HOBJECT_P_ALLOC_SIZE(h_obj),\n\t\tvals[DUK__IDX_ESIZE] = (duk_int_t) DUK_HOBJECT_GET_ESIZE(h_obj);\n\t\tvals[DUK__IDX_ENEXT] = (duk_int_t) DUK_HOBJECT_GET_ENEXT(h_obj);\n\t\tvals[DUK__IDX_ASIZE] = (duk_int_t) DUK_HOBJECT_GET_ASIZE(h_obj);\n\t\tvals[DUK__IDX_HSIZE] = (duk_int_t) DUK_HOBJECT_GET_HSIZE(h_obj);\n\n\t\t/* Note: e_next indicates the number of gc-reachable entries\n\t\t * in the entry part, and also indicates the index where the\n\t\t * next new property would be inserted.  It does *not* indicate\n\t\t * the number of non-NULL keys present in the object.  That\n\t\t * value could be counted separately but requires a pass through\n\t\t * the key list.\n\t\t */\n\n\t\tif (DUK_HOBJECT_IS_COMPFUNC(h_obj)) {\n\t\t\tduk_hbuffer *h_data = (duk_hbuffer *) DUK_HCOMPFUNC_GET_DATA(thr->heap, (duk_hcompfunc *) h_obj);\n\t\t\tvals[DUK__IDX_BCBYTES] = (duk_int_t) (h_data ? DUK_HBUFFER_GET_SIZE(h_data) : 0);\n\t\t}\n\t\tbreak;\n\t}\n\tcase DUK_HTYPE_BUFFER: {\n\t\tduk_hbuffer *h_buf = (duk_hbuffer *) h;\n\n\t\tif (DUK_HBUFFER_HAS_DYNAMIC(h_buf)) {\n\t\t\tif (DUK_HBUFFER_HAS_EXTERNAL(h_buf)) {\n\t\t\t\tvals[DUK__IDX_VARIANT] = 2;  /* buffer variant 2: external */\n\t\t\t\tvals[DUK__IDX_HBYTES] = (duk_uint_t) (sizeof(duk_hbuffer_external));\n\t\t\t} else {\n\t\t\t\t/* When alloc_size == 0 the second allocation may not\n\t\t\t\t * actually exist.\n\t\t\t\t */\n\t\t\t\tvals[DUK__IDX_VARIANT] = 1;  /* buffer variant 1: dynamic */\n\t\t\t\tvals[DUK__IDX_HBYTES] = (duk_uint_t) (sizeof(duk_hbuffer_dynamic));\n\t\t\t}\n\t\t\tvals[DUK__IDX_DBYTES] = (duk_int_t) (DUK_HBUFFER_GET_SIZE(h_buf));\n\t\t} else {\n\t\t\tDUK_ASSERT(vals[DUK__IDX_VARIANT] == 0);  /* buffer variant 0: fixed */\n\t\t\tvals[DUK__IDX_HBYTES] = (duk_int_t) (sizeof(duk_hbuffer_fixed) + DUK_HBUFFER_GET_SIZE(h_buf));\n\t\t}\n\t\tbreak;\n\t}\n\t}\n\n finish:\n\tduk__inspect_multiple_uint(thr,\n\t    \"type\" \"\\x00\" \"itag\" \"\\x00\" \"refc\" \"\\x00\" \"hbytes\" \"\\x00\" \"class\" \"\\x00\"\n\t    \"pbytes\" \"\\x00\" \"esize\" \"\\x00\" \"enext\" \"\\x00\" \"asize\" \"\\x00\" \"hsize\" \"\\x00\"\n\t    \"bcbytes\" \"\\x00\" \"dbytes\" \"\\x00\" \"tstate\" \"\\x00\" \"variant\" \"\\x00\" \"\\x00\",\n\t    (duk_int_t *) &vals);\n}\n\nDUK_EXTERNAL void duk_inspect_callstack_entry(duk_hthread *thr, duk_int_t level) {\n\tduk_activation *act;\n\tduk_uint_fast32_t pc;\n\tduk_uint_fast32_t line;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\t/* -1   = top callstack entry\n\t * -2   = caller of level -1\n\t * etc\n\t */\n\tact = duk_hthread_get_activation_for_level(thr, level);\n\tif (act == NULL) {\n\t\tduk_push_undefined(thr);\n\t\treturn;\n\t}\n\tduk_push_bare_object(thr);\n\n\t/* Relevant PC is just before current one because PC is\n\t * post-incremented.  This should match what error augment\n\t * code does.\n\t */\n\tpc = duk_hthread_get_act_prev_pc(thr, act);\n\n\tduk_push_tval(thr, &act->tv_func);\n\n\tduk_push_uint(thr, (duk_uint_t) pc);\n\tduk_put_prop_stridx_short(thr, -3, DUK_STRIDX_PC);\n\n#if defined(DUK_USE_PC2LINE)\n\tline = duk_hobject_pc2line_query(thr, -1, pc);\n#else\n\tline = 0;\n#endif\n\tduk_push_uint(thr, (duk_uint_t) line);\n\tduk_put_prop_stridx_short(thr, -3, DUK_STRIDX_LINE_NUMBER);\n\n\tduk_put_prop_stridx_short(thr, -2, DUK_STRIDX_LC_FUNCTION);\n\t/* Providing access to e.g. act->lex_env would be dangerous: these\n\t * internal structures must never be accessible to the application.\n\t * Duktape relies on them having consistent data, and this consistency\n\t * is only asserted for, not checked for.\n\t */\n}\n\n/* automatic undefs */\n#undef DUK__IDX_ASIZE\n#undef DUK__IDX_BCBYTES\n#undef DUK__IDX_CLASS\n#undef DUK__IDX_DBYTES\n#undef DUK__IDX_ENEXT\n#undef DUK__IDX_ESIZE\n#undef DUK__IDX_HBYTES\n#undef DUK__IDX_HSIZE\n#undef DUK__IDX_ITAG\n#undef DUK__IDX_PBYTES\n#undef DUK__IDX_REFC\n#undef DUK__IDX_TSTATE\n#undef DUK__IDX_TYPE\n#undef DUK__IDX_VARIANT\n#line 1 \"duk_api_memory.c\"\n/*\n *  Memory calls.\n */\n\n/* #include duk_internal.h -> already included */\n\nDUK_EXTERNAL void *duk_alloc_raw(duk_hthread *thr, duk_size_t size) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\treturn DUK_ALLOC_RAW(thr->heap, size);\n}\n\nDUK_EXTERNAL void duk_free_raw(duk_hthread *thr, void *ptr) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tDUK_FREE_RAW(thr->heap, ptr);\n}\n\nDUK_EXTERNAL void *duk_realloc_raw(duk_hthread *thr, void *ptr, duk_size_t size) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\treturn DUK_REALLOC_RAW(thr->heap, ptr, size);\n}\n\nDUK_EXTERNAL void *duk_alloc(duk_hthread *thr, duk_size_t size) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\treturn DUK_ALLOC(thr->heap, size);\n}\n\nDUK_EXTERNAL void duk_free(duk_hthread *thr, void *ptr) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tDUK_FREE_CHECKED(thr, ptr);\n}\n\nDUK_EXTERNAL void *duk_realloc(duk_hthread *thr, void *ptr, duk_size_t size) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\t/*\n\t *  Note: since this is an exposed API call, there should be\n\t *  no way a mark-and-sweep could have a side effect on the\n\t *  memory allocation behind 'ptr'; the pointer should never\n\t *  be something that Duktape wants to change.\n\t *\n\t *  Thus, no need to use DUK_REALLOC_INDIRECT (and we don't\n\t *  have the storage location here anyway).\n\t */\n\n\treturn DUK_REALLOC(thr->heap, ptr, size);\n}\n\nDUK_EXTERNAL void duk_get_memory_functions(duk_hthread *thr, duk_memory_functions *out_funcs) {\n\tduk_heap *heap;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK_ASSERT(out_funcs != NULL);\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(thr->heap != NULL);\n\n\theap = thr->heap;\n\tout_funcs->alloc_func = heap->alloc_func;\n\tout_funcs->realloc_func = heap->realloc_func;\n\tout_funcs->free_func = heap->free_func;\n\tout_funcs->udata = heap->heap_udata;\n}\n\nDUK_EXTERNAL void duk_gc(duk_hthread *thr, duk_uint_t flags) {\n\tduk_heap *heap;\n\tduk_small_uint_t ms_flags;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\theap = thr->heap;\n\tDUK_ASSERT(heap != NULL);\n\n\tDUK_D(DUK_DPRINT(\"mark-and-sweep requested by application\"));\n\tDUK_ASSERT(DUK_GC_COMPACT == DUK_MS_FLAG_EMERGENCY);  /* Compact flag is 1:1 with emergency flag which forces compaction. */\n\tms_flags = (duk_small_uint_t) flags;\n\tduk_heap_mark_and_sweep(heap, ms_flags);\n}\n#line 1 \"duk_api_object.c\"\n/*\n *  Object handling: property access and other support functions.\n */\n\n/* #include duk_internal.h -> already included */\n\n/*\n *  Property handling\n *\n *  The API exposes only the most common property handling functions.\n *  The caller can invoke Ecmascript built-ins for full control (e.g.\n *  defineProperty, getOwnPropertyDescriptor).\n */\n\nDUK_EXTERNAL duk_bool_t duk_get_prop(duk_hthread *thr, duk_idx_t obj_idx) {\n\tduk_tval *tv_obj;\n\tduk_tval *tv_key;\n\tduk_bool_t rc;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\t/* Note: copying tv_obj and tv_key to locals to shield against a valstack\n\t * resize is not necessary for a property get right now.\n\t */\n\n\ttv_obj = duk_require_tval(thr, obj_idx);\n\ttv_key = duk_require_tval(thr, -1);\n\n\trc = duk_hobject_getprop(thr, tv_obj, tv_key);\n\tDUK_ASSERT(rc == 0 || rc == 1);\n\t/* a value is left on stack regardless of rc */\n\n\tduk_remove_m2(thr);  /* remove key */\n\tDUK_ASSERT(duk_is_undefined(thr, -1) || rc == 1);\n\treturn rc;  /* 1 if property found, 0 otherwise */\n}\n\nDUK_EXTERNAL duk_bool_t duk_get_prop_string(duk_hthread *thr, duk_idx_t obj_idx, const char *key) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK_ASSERT(key != NULL);\n\n\tobj_idx = duk_require_normalize_index(thr, obj_idx);\n\tduk_push_string(thr, key);\n\treturn duk_get_prop(thr, obj_idx);\n}\n\nDUK_EXTERNAL duk_bool_t duk_get_prop_lstring(duk_hthread *thr, duk_idx_t obj_idx, const char *key, duk_size_t key_len) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK_ASSERT(key != NULL);\n\n\tobj_idx = duk_require_normalize_index(thr, obj_idx);\n\tduk_push_lstring(thr, key, key_len);\n\treturn duk_get_prop(thr, obj_idx);\n}\n\nDUK_EXTERNAL duk_bool_t duk_get_prop_index(duk_hthread *thr, duk_idx_t obj_idx, duk_uarridx_t arr_idx) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tobj_idx = duk_require_normalize_index(thr, obj_idx);\n\tduk_push_uarridx(thr, arr_idx);\n\treturn duk_get_prop(thr, obj_idx);\n}\n\nDUK_EXTERNAL duk_bool_t duk_get_prop_heapptr(duk_hthread *thr, duk_idx_t obj_idx, void *ptr) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tobj_idx = duk_require_normalize_index(thr, obj_idx);\n\tduk_push_heapptr(thr, ptr);  /* NULL -> 'undefined' */\n\treturn duk_get_prop(thr, obj_idx);\n}\n\nDUK_INTERNAL duk_bool_t duk_get_prop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK_ASSERT_STRIDX_VALID(stridx);\n\n\tobj_idx = duk_require_normalize_index(thr, obj_idx);\n\tduk_push_hstring(thr, DUK_HTHREAD_GET_STRING(thr, stridx));\n\treturn duk_get_prop(thr, obj_idx);\n}\n\nDUK_INTERNAL duk_bool_t duk_get_prop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args) {\n\treturn duk_get_prop_stridx(thr, (duk_idx_t) (duk_int16_t) (packed_args >> 16),\n\t                                (duk_small_uint_t) (packed_args & 0xffffUL));\n}\n\nDUK_INTERNAL duk_bool_t duk_get_prop_stridx_boolean(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx, duk_bool_t *out_has_prop) {\n\tduk_bool_t rc;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK_ASSERT_STRIDX_VALID(stridx);\n\n\trc = duk_get_prop_stridx(thr, obj_idx, stridx);\n\tif (out_has_prop) {\n\t\t*out_has_prop = rc;\n\t}\n\trc = duk_to_boolean(thr, -1);\n\tDUK_ASSERT(rc == 0 || rc == 1);\n\tduk_pop(thr);\n\treturn rc;\n}\n\nDUK_LOCAL duk_bool_t duk__put_prop_shared(duk_hthread *thr, duk_idx_t obj_idx, duk_idx_t idx_key) {\n\tduk_tval *tv_obj;\n\tduk_tval *tv_key;\n\tduk_tval *tv_val;\n\tduk_bool_t throw_flag;\n\tduk_bool_t rc;\n\n\t/* Note: copying tv_obj and tv_key to locals to shield against a valstack\n\t * resize is not necessary for a property put right now (putprop protects\n\t * against it internally).\n\t */\n\n\t/* Key and value indices are either (-2, -1) or (-1, -2).  Given idx_key,\n\t * idx_val is always (idx_key ^ 0x01).\n\t */\n\tDUK_ASSERT((idx_key == -2 && (idx_key ^ 1) == -1) ||\n\t           (idx_key == -1 && (idx_key ^ 1) == -2));\n\t/* XXX: Direct access; faster validation. */\n\ttv_obj = duk_require_tval(thr, obj_idx);\n\ttv_key = duk_require_tval(thr, idx_key);\n\ttv_val = duk_require_tval(thr, idx_key ^ 1);\n\tthrow_flag = duk_is_strict_call(thr);\n\n\trc = duk_hobject_putprop(thr, tv_obj, tv_key, tv_val, throw_flag);\n\tDUK_ASSERT(rc == 0 || rc == 1);\n\n\tduk_pop_2(thr);  /* remove key and value */\n\treturn rc;  /* 1 if property found, 0 otherwise */\n}\n\nDUK_EXTERNAL duk_bool_t duk_put_prop(duk_hthread *thr, duk_idx_t obj_idx) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\treturn duk__put_prop_shared(thr, obj_idx, -2);\n}\n\nDUK_EXTERNAL duk_bool_t duk_put_prop_string(duk_hthread *thr, duk_idx_t obj_idx, const char *key) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK_ASSERT(key != NULL);\n\n\t/* Careful here and with other duk_put_prop_xxx() helpers: the\n\t * target object and the property value may be in the same value\n\t * stack slot (unusual, but still conceptually clear).\n\t */\n\tobj_idx = duk_normalize_index(thr, obj_idx);\n\t(void) duk_push_string(thr, key);\n\treturn duk__put_prop_shared(thr, obj_idx, -1);\n}\n\nDUK_EXTERNAL duk_bool_t duk_put_prop_lstring(duk_hthread *thr, duk_idx_t obj_idx, const char *key, duk_size_t key_len) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK_ASSERT(key != NULL);\n\n\tobj_idx = duk_normalize_index(thr, obj_idx);\n\t(void) duk_push_lstring(thr, key, key_len);\n\treturn duk__put_prop_shared(thr, obj_idx, -1);\n}\n\nDUK_EXTERNAL duk_bool_t duk_put_prop_index(duk_hthread *thr, duk_idx_t obj_idx, duk_uarridx_t arr_idx) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tobj_idx = duk_require_normalize_index(thr, obj_idx);\n\tduk_push_uarridx(thr, arr_idx);\n\treturn duk__put_prop_shared(thr, obj_idx, -1);\n}\n\nDUK_EXTERNAL duk_bool_t duk_put_prop_heapptr(duk_hthread *thr, duk_idx_t obj_idx, void *ptr) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tobj_idx = duk_require_normalize_index(thr, obj_idx);\n\tduk_push_heapptr(thr, ptr);  /* NULL -> 'undefined' */\n\treturn duk__put_prop_shared(thr, obj_idx, -1);\n}\n\n\nDUK_INTERNAL duk_bool_t duk_put_prop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK_ASSERT_STRIDX_VALID(stridx);\n\n\tobj_idx = duk_require_normalize_index(thr, obj_idx);\n\tduk_push_hstring(thr, DUK_HTHREAD_GET_STRING(thr, stridx));\n\treturn duk__put_prop_shared(thr, obj_idx, -1);\n}\n\nDUK_INTERNAL duk_bool_t duk_put_prop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args) {\n\treturn duk_put_prop_stridx(thr, (duk_idx_t) (duk_int16_t) (packed_args >> 16),\n\t                                (duk_small_uint_t) (packed_args & 0xffffUL));\n}\n\nDUK_EXTERNAL duk_bool_t duk_del_prop(duk_hthread *thr, duk_idx_t obj_idx) {\n\tduk_tval *tv_obj;\n\tduk_tval *tv_key;\n\tduk_bool_t throw_flag;\n\tduk_bool_t rc;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\t/* Note: copying tv_obj and tv_key to locals to shield against a valstack\n\t * resize is not necessary for a property delete right now.\n\t */\n\n\ttv_obj = duk_require_tval(thr, obj_idx);\n\ttv_key = duk_require_tval(thr, -1);\n\tthrow_flag = duk_is_strict_call(thr);\n\n\trc = duk_hobject_delprop(thr, tv_obj, tv_key, throw_flag);\n\tDUK_ASSERT(rc == 0 || rc == 1);\n\n\tduk_pop(thr);  /* remove key */\n\treturn rc;\n}\n\nDUK_EXTERNAL duk_bool_t duk_del_prop_string(duk_hthread *thr, duk_idx_t obj_idx, const char *key) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK_ASSERT(key != NULL);\n\n\tobj_idx = duk_require_normalize_index(thr, obj_idx);\n\tduk_push_string(thr, key);\n\treturn duk_del_prop(thr, obj_idx);\n}\n\nDUK_EXTERNAL duk_bool_t duk_del_prop_lstring(duk_hthread *thr, duk_idx_t obj_idx, const char *key, duk_size_t key_len) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK_ASSERT(key != NULL);\n\n\tobj_idx = duk_require_normalize_index(thr, obj_idx);\n\tduk_push_lstring(thr, key, key_len);\n\treturn duk_del_prop(thr, obj_idx);\n}\n\nDUK_EXTERNAL duk_bool_t duk_del_prop_index(duk_hthread *thr, duk_idx_t obj_idx, duk_uarridx_t arr_idx) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tobj_idx = duk_require_normalize_index(thr, obj_idx);\n\tduk_push_uarridx(thr, arr_idx);\n\treturn duk_del_prop(thr, obj_idx);\n}\n\nDUK_EXTERNAL duk_bool_t duk_del_prop_heapptr(duk_hthread *thr, duk_idx_t obj_idx, void *ptr) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tobj_idx = duk_require_normalize_index(thr, obj_idx);\n\tduk_push_heapptr(thr, ptr);  /* NULL -> 'undefined' */\n\treturn duk_del_prop(thr, obj_idx);\n}\n\nDUK_INTERNAL duk_bool_t duk_del_prop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK_ASSERT_STRIDX_VALID(stridx);\n\n\tobj_idx = duk_require_normalize_index(thr, obj_idx);\n\tduk_push_hstring(thr, DUK_HTHREAD_GET_STRING(thr, stridx));\n\treturn duk_del_prop(thr, obj_idx);\n}\n\n#if 0\nDUK_INTERNAL duk_bool_t duk_del_prop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args) {\n\treturn duk_del_prop_stridx(thr, (duk_idx_t) (duk_int16_t) (packed_args >> 16),\n\t                                (duk_small_uint_t) (packed_args & 0xffffUL));\n}\n#endif\n\nDUK_EXTERNAL duk_bool_t duk_has_prop(duk_hthread *thr, duk_idx_t obj_idx) {\n\tduk_tval *tv_obj;\n\tduk_tval *tv_key;\n\tduk_bool_t rc;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\t/* Note: copying tv_obj and tv_key to locals to shield against a valstack\n\t * resize is not necessary for a property existence check right now.\n\t */\n\n\ttv_obj = duk_require_tval(thr, obj_idx);\n\ttv_key = duk_require_tval(thr, -1);\n\n\trc = duk_hobject_hasprop(thr, tv_obj, tv_key);\n\tDUK_ASSERT(rc == 0 || rc == 1);\n\n\tduk_pop(thr);  /* remove key */\n\treturn rc;  /* 1 if property found, 0 otherwise */\n}\n\nDUK_EXTERNAL duk_bool_t duk_has_prop_string(duk_hthread *thr, duk_idx_t obj_idx, const char *key) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK_ASSERT(key != NULL);\n\n\tobj_idx = duk_require_normalize_index(thr, obj_idx);\n\tduk_push_string(thr, key);\n\treturn duk_has_prop(thr, obj_idx);\n}\n\nDUK_EXTERNAL duk_bool_t duk_has_prop_lstring(duk_hthread *thr, duk_idx_t obj_idx, const char *key, duk_size_t key_len) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK_ASSERT(key != NULL);\n\n\tobj_idx = duk_require_normalize_index(thr, obj_idx);\n\tduk_push_lstring(thr, key, key_len);\n\treturn duk_has_prop(thr, obj_idx);\n}\n\nDUK_EXTERNAL duk_bool_t duk_has_prop_index(duk_hthread *thr, duk_idx_t obj_idx, duk_uarridx_t arr_idx) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tobj_idx = duk_require_normalize_index(thr, obj_idx);\n\tduk_push_uarridx(thr, arr_idx);\n\treturn duk_has_prop(thr, obj_idx);\n}\n\nDUK_EXTERNAL duk_bool_t duk_has_prop_heapptr(duk_hthread *thr, duk_idx_t obj_idx, void *ptr) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tobj_idx = duk_require_normalize_index(thr, obj_idx);\n\tduk_push_heapptr(thr, ptr);  /* NULL -> 'undefined' */\n\treturn duk_has_prop(thr, obj_idx);\n}\n\nDUK_INTERNAL duk_bool_t duk_has_prop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK_ASSERT_STRIDX_VALID(stridx);\n\n\tobj_idx = duk_require_normalize_index(thr, obj_idx);\n\tduk_push_hstring(thr, DUK_HTHREAD_GET_STRING(thr, stridx));\n\treturn duk_has_prop(thr, obj_idx);\n}\n\n#if 0\nDUK_INTERNAL duk_bool_t duk_has_prop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args) {\n\treturn duk_has_prop_stridx(thr, (duk_idx_t) (duk_int16_t) (packed_args >> 16),\n\t                                (duk_small_uint_t) (packed_args & 0xffffUL));\n}\n#endif\n\n/* Define own property without inheritance lookups and such.  This differs from\n * [[DefineOwnProperty]] because special behaviors (like Array 'length') are\n * not invoked by this method.  The caller must be careful to invoke any such\n * behaviors if necessary.\n */\nDUK_INTERNAL void duk_xdef_prop(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t desc_flags) {\n\tduk_hobject *obj;\n\tduk_hstring *key;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tobj = duk_require_hobject(thr, obj_idx);\n\tDUK_ASSERT(obj != NULL);\n\tkey = duk_to_property_key_hstring(thr, -2);\n\tDUK_ASSERT(key != NULL);\n\tDUK_ASSERT(duk_require_tval(thr, -1) != NULL);\n\n\tduk_hobject_define_property_internal(thr, obj, key, desc_flags);\n\n\tduk_pop(thr);  /* pop key */\n}\n\nDUK_INTERNAL void duk_xdef_prop_index(duk_hthread *thr, duk_idx_t obj_idx, duk_uarridx_t arr_idx, duk_small_uint_t desc_flags) {\n\tduk_hobject *obj;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tobj = duk_require_hobject(thr, obj_idx);\n\tDUK_ASSERT(obj != NULL);\n\n\tduk_hobject_define_property_internal_arridx(thr, obj, arr_idx, desc_flags);\n\t/* value popped by call */\n}\n\nDUK_INTERNAL void duk_xdef_prop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx, duk_small_uint_t desc_flags) {\n\tduk_hobject *obj;\n\tduk_hstring *key;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK_ASSERT_STRIDX_VALID(stridx);\n\n\tobj = duk_require_hobject(thr, obj_idx);\n\tDUK_ASSERT(obj != NULL);\n\tkey = DUK_HTHREAD_GET_STRING(thr, stridx);\n\tDUK_ASSERT(key != NULL);\n\tDUK_ASSERT(duk_require_tval(thr, -1) != NULL);\n\n\tduk_hobject_define_property_internal(thr, obj, key, desc_flags);\n\t/* value popped by call */\n}\n\nDUK_INTERNAL void duk_xdef_prop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args) {\n\tduk_xdef_prop_stridx(thr, (duk_idx_t) (duk_int8_t) (packed_args >> 24),\n\t                          (duk_small_uint_t) (packed_args >> 8) & 0xffffUL,\n\t                          (duk_small_uint_t) (packed_args & 0xffL));\n}\n\n#if 0  /*unused*/\nDUK_INTERNAL void duk_xdef_prop_stridx_builtin(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx, duk_small_int_t builtin_idx, duk_small_uint_t desc_flags) {\n\tduk_hobject *obj;\n\tduk_hstring *key;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK_ASSERT_STRIDX_VALID(stridx);\n\tDUK_ASSERT_BIDX_VALID(builtin_idx);\n\n\tobj = duk_require_hobject(thr, obj_idx);\n\tDUK_ASSERT(obj != NULL);\n\tkey = DUK_HTHREAD_GET_STRING(thr, stridx);\n\tDUK_ASSERT(key != NULL);\n\n\tduk_push_hobject(thr, thr->builtins[builtin_idx]);\n\tduk_hobject_define_property_internal(thr, obj, key, desc_flags);\n\t/* value popped by call */\n}\n#endif\n\n/* This is a rare property helper; it sets the global thrower (E5 Section 13.2.3)\n * setter/getter into an object property.  This is needed by the 'arguments'\n * object creation code, function instance creation code, and Function.prototype.bind().\n */\n\nDUK_INTERNAL void duk_xdef_prop_stridx_thrower(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tobj_idx = duk_require_normalize_index(thr, obj_idx);\n\tduk_push_hstring_stridx(thr, stridx);\n\tduk_push_hobject_bidx(thr, DUK_BIDX_TYPE_ERROR_THROWER);\n\tduk_dup_top(thr);\n\tduk_def_prop(thr, obj_idx, DUK_DEFPROP_HAVE_SETTER | DUK_DEFPROP_HAVE_GETTER | DUK_DEFPROP_FORCE);  /* attributes always 0 */\n}\n\n/* Object.getOwnPropertyDescriptor() equivalent C binding. */\nDUK_EXTERNAL void duk_get_prop_desc(duk_hthread *thr, duk_idx_t obj_idx, duk_uint_t flags) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK_UNREF(flags);  /* no flags defined yet */\n\n\tduk_hobject_object_get_own_property_descriptor(thr, obj_idx);  /* [ ... key ] -> [ ... desc ] */\n}\n\n/* Object.defineProperty() equivalent C binding. */\nDUK_EXTERNAL void duk_def_prop(duk_hthread *thr, duk_idx_t obj_idx, duk_uint_t flags) {\n\tduk_idx_t idx_base;\n\tduk_hobject *obj;\n\tduk_hstring *key;\n\tduk_idx_t idx_value;\n\tduk_hobject *get;\n\tduk_hobject *set;\n\tduk_uint_t is_data_desc;\n\tduk_uint_t is_acc_desc;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tobj = duk_require_hobject(thr, obj_idx);\n\n\tis_data_desc = flags & (DUK_DEFPROP_HAVE_VALUE | DUK_DEFPROP_HAVE_WRITABLE);\n\tis_acc_desc = flags & (DUK_DEFPROP_HAVE_GETTER | DUK_DEFPROP_HAVE_SETTER);\n\tif (is_data_desc && is_acc_desc) {\n\t\t/* \"Have\" flags must not be conflicting so that they would\n\t\t * apply to both a plain property and an accessor at the same\n\t\t * time.\n\t\t */\n\t\tgoto fail_invalid_desc;\n\t}\n\n\tidx_base = duk_get_top_index(thr);\n\tif (flags & DUK_DEFPROP_HAVE_SETTER) {\n\t\tduk_require_type_mask(thr, idx_base, DUK_TYPE_MASK_UNDEFINED |\n\t\t                                     DUK_TYPE_MASK_OBJECT |\n\t\t                                     DUK_TYPE_MASK_LIGHTFUNC);\n\t\tset = duk_get_hobject_promote_lfunc(thr, idx_base);\n\t\tif (set != NULL && !DUK_HOBJECT_IS_CALLABLE(set)) {\n\t\t\tgoto fail_not_callable;\n\t\t}\n\t\tidx_base--;\n\t} else {\n\t\tset = NULL;\n\t}\n\tif (flags & DUK_DEFPROP_HAVE_GETTER) {\n\t\tduk_require_type_mask(thr, idx_base, DUK_TYPE_MASK_UNDEFINED |\n\t\t                                     DUK_TYPE_MASK_OBJECT |\n\t\t                                     DUK_TYPE_MASK_LIGHTFUNC);\n\t\tget = duk_get_hobject_promote_lfunc(thr, idx_base);\n\t\tif (get != NULL && !DUK_HOBJECT_IS_CALLABLE(get)) {\n\t\t\tgoto fail_not_callable;\n\t\t}\n\t\tidx_base--;\n\t} else {\n\t\tget = NULL;\n\t}\n\tif (flags & DUK_DEFPROP_HAVE_VALUE) {\n\t\tidx_value = idx_base;\n\t\tidx_base--;\n\t} else {\n\t\tidx_value = (duk_idx_t) -1;\n\t}\n\tkey = duk_to_property_key_hstring(thr, idx_base);\n\tDUK_ASSERT(key != NULL);\n\n\tduk_require_valid_index(thr, idx_base);\n\n\tduk_hobject_define_property_helper(thr,\n\t                                   flags /*defprop_flags*/,\n\t                                   obj,\n\t                                   key,\n\t                                   idx_value,\n\t                                   get,\n\t                                   set,\n\t                                   1 /*throw_flag*/);\n\n\t/* Clean up stack */\n\n\tduk_set_top(thr, idx_base);\n\n\t/* [ ... obj ... ] */\n\n\treturn;\n\n fail_invalid_desc:\n\tDUK_ERROR_TYPE(thr, DUK_STR_INVALID_DESCRIPTOR);\n\treturn;\n\n fail_not_callable:\n\tDUK_ERROR_TYPE(thr, DUK_STR_NOT_CALLABLE);\n\treturn;\n}\n\n/*\n *  Object related\n *\n *  Note: seal() and freeze() are accessible through Ecmascript bindings,\n *  and are not exposed through the API.\n */\n\nDUK_EXTERNAL void duk_compact(duk_hthread *thr, duk_idx_t obj_idx) {\n\tduk_hobject *obj;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tobj = duk_get_hobject(thr, obj_idx);\n\tif (obj) {\n\t\t/* Note: this may fail, caller should protect the call if necessary */\n\t\tduk_hobject_compact_props(thr, obj);\n\t}\n}\n\nDUK_INTERNAL void duk_compact_m1(duk_hthread *thr) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tduk_compact(thr, -1);\n}\n\n/* XXX: the duk_hobject_enum.c stack APIs should be reworked */\n\nDUK_EXTERNAL void duk_enum(duk_hthread *thr, duk_idx_t obj_idx, duk_uint_t enum_flags) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tduk_dup(thr, obj_idx);\n\tduk_require_hobject_promote_mask(thr, -1, DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER);\n\tduk_hobject_enumerator_create(thr, enum_flags);   /* [target] -> [enum] */\n}\n\nDUK_EXTERNAL duk_bool_t duk_next(duk_hthread *thr, duk_idx_t enum_index, duk_bool_t get_value) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tduk_require_hobject(thr, enum_index);\n\tduk_dup(thr, enum_index);\n\treturn duk_hobject_enumerator_next(thr, get_value);\n}\n\nDUK_INTERNAL void duk_seal_freeze_raw(duk_hthread *thr, duk_idx_t obj_idx, duk_bool_t is_freeze) {\n\tduk_tval *tv;\n\tduk_hobject *h;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\ttv = duk_require_tval(thr, obj_idx);\n\tDUK_ASSERT(tv != NULL);\n\n\t/* Seal/freeze are quite rare in practice so it'd be nice to get the\n\t * correct behavior simply via automatic promotion (at the cost of some\n\t * memory churn).  However, the promoted objects don't behave the same,\n\t * e.g. promoted lightfuncs are extensible.\n\t */\n\n\tswitch (DUK_TVAL_GET_TAG(tv)) {\n\tcase DUK_TAG_BUFFER:\n\t\t/* Plain buffer: already sealed, but not frozen (and can't be frozen\n\t\t * because index properties can't be made non-writable.\n\t\t */\n\t\tif (is_freeze) {\n\t\t\tgoto fail_cannot_freeze;\n\t\t}\n\t\tbreak;\n\tcase DUK_TAG_LIGHTFUNC:\n\t\t/* Lightfunc: already sealed and frozen, success. */\n\t\tbreak;\n\tcase DUK_TAG_OBJECT:\n\t\th = DUK_TVAL_GET_OBJECT(tv);\n\t\tDUK_ASSERT(h != NULL);\n\t\tif (is_freeze && DUK_HOBJECT_IS_BUFOBJ(h)) {\n\t\t\t/* Buffer objects cannot be frozen because there's no internal\n\t\t\t * support for making virtual array indices non-writable.\n\t\t\t */\n\t\t\tDUK_DD(DUK_DDPRINT(\"cannot freeze a buffer object\"));\n\t\t\tgoto fail_cannot_freeze;\n\t\t}\n\t\tduk_hobject_object_seal_freeze_helper(thr, h, is_freeze);\n\n\t\t/* Sealed and frozen objects cannot gain any more properties,\n\t\t * so this is a good time to compact them.\n\t\t */\n\t\tduk_hobject_compact_props(thr, h);\n\t\tbreak;\n\tdefault:\n\t\t/* ES2015 Sections 19.1.2.5, 19.1.2.17 */\n\t\tbreak;\n\t}\n\treturn;\n\n fail_cannot_freeze:\n\tDUK_ERROR_TYPE_INVALID_ARGS(thr);  /* XXX: proper error message */\n}\n\nDUK_EXTERNAL void duk_seal(duk_hthread *thr, duk_idx_t obj_idx) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tduk_seal_freeze_raw(thr, obj_idx, 0 /*is_freeze*/);\n}\n\nDUK_EXTERNAL void duk_freeze(duk_hthread *thr, duk_idx_t obj_idx) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tduk_seal_freeze_raw(thr, obj_idx, 1 /*is_freeze*/);\n}\n\n/*\n *  Helpers for writing multiple properties\n */\n\nDUK_EXTERNAL void duk_put_function_list(duk_hthread *thr, duk_idx_t obj_idx, const duk_function_list_entry *funcs) {\n\tconst duk_function_list_entry *ent = funcs;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tobj_idx = duk_require_normalize_index(thr, obj_idx);\n\tif (ent != NULL) {\n\t\twhile (ent->key != NULL) {\n\t\t\tduk_push_c_function(thr, ent->value, ent->nargs);\n\t\t\tduk_put_prop_string(thr, obj_idx, ent->key);\n\t\t\tent++;\n\t\t}\n\t}\n}\n\nDUK_EXTERNAL void duk_put_number_list(duk_hthread *thr, duk_idx_t obj_idx, const duk_number_list_entry *numbers) {\n\tconst duk_number_list_entry *ent = numbers;\n\tduk_tval *tv;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tobj_idx = duk_require_normalize_index(thr, obj_idx);\n\tif (ent != NULL) {\n\t\twhile (ent->key != NULL) {\n\t\t\ttv = thr->valstack_top++;\n\t\t\tDUK_ASSERT(DUK_TVAL_IS_UNDEFINED(tv));  /* value stack init policy */\n\t\t\tDUK_TVAL_SET_NUMBER_CHKFAST_SLOW(tv, ent->value);  /* no need for decref/incref */\n\t\t\tduk_put_prop_string(thr, obj_idx, ent->key);\n\t\t\tent++;\n\t\t}\n\t}\n}\n\n/*\n *  Shortcut for accessing global object properties\n */\n\nDUK_EXTERNAL duk_bool_t duk_get_global_string(duk_hthread *thr, const char *key) {\n\tduk_bool_t ret;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL);\n\n\t/* XXX: direct implementation */\n\n\tduk_push_hobject(thr, thr->builtins[DUK_BIDX_GLOBAL]);\n\tret = duk_get_prop_string(thr, -1, key);\n\tduk_remove_m2(thr);\n\treturn ret;\n}\n\nDUK_EXTERNAL duk_bool_t duk_get_global_lstring(duk_hthread *thr, const char *key, duk_size_t key_len) {\n\tduk_bool_t ret;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL);\n\n\t/* XXX: direct implementation */\n\n\tduk_push_hobject(thr, thr->builtins[DUK_BIDX_GLOBAL]);\n\tret = duk_get_prop_lstring(thr, -1, key, key_len);\n\tduk_remove_m2(thr);\n\treturn ret;\n}\n\nDUK_EXTERNAL duk_bool_t duk_put_global_string(duk_hthread *thr, const char *key) {\n\tduk_bool_t ret;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL);\n\n\t/* XXX: direct implementation */\n\n\tduk_push_hobject(thr, thr->builtins[DUK_BIDX_GLOBAL]);\n\tduk_insert(thr, -2);\n\tret = duk_put_prop_string(thr, -2, key);  /* [ ... global val ] -> [ ... global ] */\n\tduk_pop(thr);\n\treturn ret;\n}\n\nDUK_EXTERNAL duk_bool_t duk_put_global_lstring(duk_hthread *thr, const char *key, duk_size_t key_len) {\n\tduk_bool_t ret;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL);\n\n\t/* XXX: direct implementation */\n\n\tduk_push_hobject(thr, thr->builtins[DUK_BIDX_GLOBAL]);\n\tduk_insert(thr, -2);\n\tret = duk_put_prop_lstring(thr, -2, key, key_len);  /* [ ... global val ] -> [ ... global ] */\n\tduk_pop(thr);\n\treturn ret;\n}\n\n/*\n *  Object prototype\n */\n\nDUK_EXTERNAL void duk_get_prototype(duk_hthread *thr, duk_idx_t idx) {\n\tduk_hobject *obj;\n\tduk_hobject *proto;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tobj = duk_require_hobject(thr, idx);\n\tDUK_ASSERT(obj != NULL);\n\n\t/* XXX: shared helper for duk_push_hobject_or_undefined()? */\n\tproto = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, obj);\n\tif (proto) {\n\t\tduk_push_hobject(thr, proto);\n\t} else {\n\t\tduk_push_undefined(thr);\n\t}\n}\n\nDUK_EXTERNAL void duk_set_prototype(duk_hthread *thr, duk_idx_t idx) {\n\tduk_hobject *obj;\n\tduk_hobject *proto;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tobj = duk_require_hobject(thr, idx);\n\tDUK_ASSERT(obj != NULL);\n\tduk_require_type_mask(thr, -1, DUK_TYPE_MASK_UNDEFINED |\n\t                               DUK_TYPE_MASK_OBJECT);\n\tproto = duk_get_hobject(thr, -1);\n\t/* proto can also be NULL here (allowed explicitly) */\n\n#if defined(DUK_USE_ROM_OBJECTS)\n\tif (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj)) {\n\t\tDUK_ERROR_TYPE(thr, DUK_STR_NOT_CONFIGURABLE);  /* XXX: \"read only object\"? */\n\t\treturn;\n\t}\n#endif\n\n\tDUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, obj, proto);\n\n\tduk_pop(thr);\n}\n\n/*\n *  Object finalizer\n */\n\n#if defined(DUK_USE_FINALIZER_SUPPORT)\n/* XXX: these could be implemented as macros calling an internal function\n * directly.\n * XXX: same issue as with Duktape.fin: there's no way to delete the property\n * now (just set it to undefined).\n */\nDUK_EXTERNAL void duk_get_finalizer(duk_hthread *thr, duk_idx_t idx) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tduk_get_prop_stridx(thr, idx, DUK_STRIDX_INT_FINALIZER);\n}\n\nDUK_EXTERNAL void duk_set_finalizer(duk_hthread *thr, duk_idx_t idx) {\n\tduk_hobject *h;\n\tduk_bool_t callable;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\th = duk_require_hobject(thr, idx);  /* Get before 'put' so that 'idx' is correct. */\n\tcallable = duk_is_callable(thr, -1);\n\tduk_put_prop_stridx(thr, idx, DUK_STRIDX_INT_FINALIZER);\n\n\t/* In addition to setting the finalizer property, keep a \"have\n\t * finalizer\" flag in duk_hobject in sync so that refzero can do\n\t * a very quick finalizer check by walking the prototype chain\n\t * and checking the flag alone.  (Note that this means that just\n\t * setting _Finalizer on an object won't affect finalizer checks.)\n\t *\n\t * NOTE: if the argument is a Proxy object, this flag will be set\n\t * on the Proxy, not the target.  As a result, the target won't get\n\t * a finalizer flag and the Proxy also won't be finalized as there's\n\t * an explicit Proxy check in finalization now.\n\t */\n\tif (callable) {\n\t\tDUK_HOBJECT_SET_HAVE_FINALIZER(h);\n\t} else {\n\t\tDUK_HOBJECT_CLEAR_HAVE_FINALIZER(h);\n\t}\n}\n#else  /* DUK_USE_FINALIZER_SUPPORT */\nDUK_EXTERNAL void duk_get_finalizer(duk_hthread *thr, duk_idx_t idx) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK_UNREF(idx);\n\tDUK_ERROR_UNSUPPORTED(thr);\n}\n\nDUK_EXTERNAL void duk_set_finalizer(duk_hthread *thr, duk_idx_t idx) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK_UNREF(idx);\n\tDUK_ERROR_UNSUPPORTED(thr);\n}\n#endif  /* DUK_USE_FINALIZER_SUPPORT */\n#line 1 \"duk_api_stack.c\"\n/*\n *  API calls related to general value stack manipulation: resizing the value\n *  stack, pushing and popping values, type checking and reading values,\n *  coercing values, etc.\n *\n *  Also contains internal functions (such as duk_get_tval()), defined\n *  in duk_api_internal.h, with semantics similar to the public API.\n */\n\n/* XXX: repetition of stack pre-checks -> helper or macro or inline */\n/* XXX: shared api error strings, and perhaps even throw code for rare cases? */\n\n/* #include duk_internal.h -> already included */\n\n/*\n *  Forward declarations\n */\n\nDUK_LOCAL_DECL duk_idx_t duk__push_c_function_raw(duk_hthread *thr, duk_c_function func, duk_idx_t nargs, duk_uint_t flags, duk_small_uint_t proto_bidx);\n\n/*\n *  Global state for working around missing variadic macros\n */\n\n#if !defined(DUK_USE_VARIADIC_MACROS)\nDUK_EXTERNAL const char *duk_api_global_filename = NULL;\nDUK_EXTERNAL duk_int_t duk_api_global_line = 0;\n#endif\n\n/*\n *  Misc helpers\n */\n\nDUK_LOCAL const char * const duk__symbol_type_strings[4] = {\n\t\"hidden\", \"global\", \"local\", \"wellknown\"\n};\n\n#if !defined(DUK_USE_PACKED_TVAL)\nDUK_LOCAL const duk_uint_t duk__type_from_tag[] = {\n\tDUK_TYPE_NUMBER,\n\tDUK_TYPE_NUMBER,  /* fastint */\n\tDUK_TYPE_UNDEFINED,\n\tDUK_TYPE_NULL,\n\tDUK_TYPE_BOOLEAN,\n\tDUK_TYPE_POINTER,\n\tDUK_TYPE_LIGHTFUNC,\n\tDUK_TYPE_NONE,\n\tDUK_TYPE_STRING,\n\tDUK_TYPE_OBJECT,\n\tDUK_TYPE_BUFFER,\n};\nDUK_LOCAL const duk_uint_t duk__type_mask_from_tag[] = {\n\tDUK_TYPE_MASK_NUMBER,\n\tDUK_TYPE_MASK_NUMBER,  /* fastint */\n\tDUK_TYPE_MASK_UNDEFINED,\n\tDUK_TYPE_MASK_NULL,\n\tDUK_TYPE_MASK_BOOLEAN,\n\tDUK_TYPE_MASK_POINTER,\n\tDUK_TYPE_MASK_LIGHTFUNC,\n\tDUK_TYPE_MASK_NONE,\n\tDUK_TYPE_MASK_STRING,\n\tDUK_TYPE_MASK_OBJECT,\n\tDUK_TYPE_MASK_BUFFER,\n};\n#endif  /* !DUK_USE_PACKED_TVAL */\n\n/* Assert that there's room for one value. */\n#define DUK__ASSERT_SPACE() do { \\\n\t\tDUK_ASSERT(!(thr->valstack_top >= thr->valstack_end)); \\\n\t} while (0)\n\n/* Check that there's room to push one value. */\n#if defined(DUK_USE_VALSTACK_UNSAFE)\n/* Faster but value stack overruns are memory unsafe. */\n#define DUK__CHECK_SPACE() DUK__ASSERT_SPACE()\n#else\n#define DUK__CHECK_SPACE() do { \\\n\t\tif (DUK_UNLIKELY(thr->valstack_top >= thr->valstack_end)) { \\\n\t\t\tDUK_ERROR_RANGE_PUSH_BEYOND(thr); \\\n\t\t} \\\n\t} while (0)\n#endif\n\nDUK_LOCAL duk_small_uint_t duk__get_symbol_type(duk_hstring *h) {\n\tconst duk_uint8_t *data;\n\tduk_size_t len;\n\n\tDUK_ASSERT(h != NULL);\n\tDUK_ASSERT(DUK_HSTRING_HAS_SYMBOL(h));\n\tDUK_ASSERT(DUK_HSTRING_GET_BYTELEN(h) >= 1);  /* always true, symbol prefix */\n\n\tdata = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h);\n\tlen = DUK_HSTRING_GET_BYTELEN(h);\n\tDUK_ASSERT(len >= 1);\n\n\t/* XXX: differentiate between 0x82 and 0xff (hidden vs. internal?)? */\n\n\tif (data[0] == 0xffU) {\n\t\treturn DUK_SYMBOL_TYPE_HIDDEN;\n\t} else if (data[0] == 0x82U) {\n\t\treturn DUK_SYMBOL_TYPE_HIDDEN;\n\t} else if (data[0] == 0x80U) {\n\t\treturn DUK_SYMBOL_TYPE_GLOBAL;\n\t} else if (data[len - 1] != 0xffU) {\n\t\treturn DUK_SYMBOL_TYPE_LOCAL;\n\t} else {\n\t\treturn DUK_SYMBOL_TYPE_WELLKNOWN;\n\t}\n}\n\nDUK_LOCAL const char *duk__get_symbol_type_string(duk_hstring *h) {\n\tduk_small_uint_t idx;\n\tidx = duk__get_symbol_type(h);\n\tDUK_ASSERT(idx < sizeof(duk__symbol_type_strings));\n\treturn duk__symbol_type_strings[idx];\n}\n\nDUK_LOCAL_DECL duk_heaphdr *duk__get_tagged_heaphdr_raw(duk_hthread *thr, duk_idx_t idx, duk_uint_t tag);\n\nDUK_LOCAL duk_int_t duk__api_coerce_d2i(duk_hthread *thr, duk_idx_t idx, duk_int_t def_value, duk_bool_t require) {\n\tduk_tval *tv;\n\tduk_small_int_t c;\n\tduk_double_t d;\n\n\ttv = duk_get_tval_or_unused(thr, idx);\n\tDUK_ASSERT(tv != NULL);\n\n\t/*\n\t *  Special cases like NaN and +/- Infinity are handled explicitly\n\t *  because a plain C coercion from double to int handles these cases\n\t *  in undesirable ways.  For instance, NaN may coerce to INT_MIN\n\t *  (not zero), and INT_MAX + 1 may coerce to INT_MIN (not INT_MAX).\n\t *\n\t *  This double-to-int coercion differs from ToInteger() because it\n\t *  has a finite range (ToInteger() allows e.g. +/- Infinity).  It\n\t *  also differs from ToInt32() because the INT_MIN/INT_MAX clamping\n\t *  depends on the size of the int type on the platform.  In particular,\n\t *  on platforms with a 64-bit int type, the full range is allowed.\n\t */\n\n#if defined(DUK_USE_FASTINT)\n\tif (DUK_TVAL_IS_FASTINT(tv)) {\n\t\tduk_int64_t t = DUK_TVAL_GET_FASTINT(tv);\n#if (DUK_INT_MAX <= 0x7fffffffL)\n\t\t/* Clamping only necessary for 32-bit ints. */\n\t\tif (t < DUK_INT_MIN) {\n\t\t\tt = DUK_INT_MIN;\n\t\t} else if (t > DUK_INT_MAX) {\n\t\t\tt = DUK_INT_MAX;\n\t\t}\n#endif\n\t\treturn (duk_int_t) t;\n\t}\n#endif\n\n\tif (DUK_TVAL_IS_NUMBER(tv)) {\n\t\td = DUK_TVAL_GET_NUMBER(tv);\n\t\tc = (duk_small_int_t) DUK_FPCLASSIFY(d);\n\t\tif (c == DUK_FP_NAN) {\n\t\t\treturn 0;\n\t\t} else if (d < (duk_double_t) DUK_INT_MIN) {\n\t\t\t/* covers -Infinity */\n\t\t\treturn DUK_INT_MIN;\n\t\t} else if (d > (duk_double_t) DUK_INT_MAX) {\n\t\t\t/* covers +Infinity */\n\t\t\treturn DUK_INT_MAX;\n\t\t} else {\n\t\t\t/* coerce towards zero */\n\t\t\treturn (duk_int_t) d;\n\t\t}\n\t}\n\n\tif (require) {\n\t\tDUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, \"number\", DUK_STR_NOT_NUMBER);\n\t\t/* not reachable */\n\t}\n\n\treturn def_value;\n}\n\nDUK_LOCAL duk_uint_t duk__api_coerce_d2ui(duk_hthread *thr, duk_idx_t idx, duk_uint_t def_value, duk_bool_t require) {\n\tduk_tval *tv;\n\tduk_small_int_t c;\n\tduk_double_t d;\n\n\t/* Same as above but for unsigned int range. */\n\n\ttv = duk_get_tval_or_unused(thr, idx);\n\tDUK_ASSERT(tv != NULL);\n\n#if defined(DUK_USE_FASTINT)\n\tif (DUK_TVAL_IS_FASTINT(tv)) {\n\t\tduk_int64_t t = DUK_TVAL_GET_FASTINT(tv);\n\t\tif (t < 0) {\n\t\t\tt = 0;\n\t\t}\n#if (DUK_UINT_MAX <= 0xffffffffUL)\n\t\t/* Clamping only necessary for 32-bit ints. */\n\t\telse if (t > DUK_UINT_MAX) {\n\t\t\tt = DUK_UINT_MAX;\n\t\t}\n#endif\n\t\treturn (duk_uint_t) t;\n\t}\n#endif\n\n\tif (DUK_TVAL_IS_NUMBER(tv)) {\n\t\td = DUK_TVAL_GET_NUMBER(tv);\n\t\tc = (duk_small_int_t) DUK_FPCLASSIFY(d);\n\t\tif (c == DUK_FP_NAN) {\n\t\t\treturn 0;\n\t\t} else if (d < 0.0) {\n\t\t\t/* covers -Infinity */\n\t\t\treturn (duk_uint_t) 0;\n\t\t} else if (d > (duk_double_t) DUK_UINT_MAX) {\n\t\t\t/* covers +Infinity */\n\t\t\treturn (duk_uint_t) DUK_UINT_MAX;\n\t\t} else {\n\t\t\t/* coerce towards zero */\n\t\t\treturn (duk_uint_t) d;\n\t\t}\n\t}\n\n\tif (require) {\n\t\tDUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, \"number\", DUK_STR_NOT_NUMBER);\n\t\t/* not reachable */\n\t}\n\n\treturn def_value;\n}\n\n/*\n *  Stack index validation/normalization and getting a stack duk_tval ptr.\n *\n *  These are called by many API entrypoints so the implementations must be\n *  fast and \"inlined\".\n *\n *  There's some repetition because of this; keep the functions in sync.\n */\n\nDUK_EXTERNAL duk_idx_t duk_normalize_index(duk_hthread *thr, duk_idx_t idx) {\n\tduk_uidx_t vs_size;\n\tduk_uidx_t uidx;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK_ASSERT(DUK_INVALID_INDEX < 0);\n\n\t/* Care must be taken to avoid pointer wrapping in the index\n\t * validation.  For instance, on a 32-bit platform with 8-byte\n\t * duk_tval the index 0x20000000UL would wrap the memory space\n\t * once.\n\t */\n\n\t/* Assume value stack sizes (in elements) fits into duk_idx_t. */\n\tDUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);\n\tvs_size = (duk_uidx_t) (thr->valstack_top - thr->valstack_bottom);\n\tDUK_ASSERT_DISABLE(vs_size >= 0);  /* unsigned */\n\n\tif (idx < 0) {\n\t\tuidx = vs_size + (duk_uidx_t) idx;\n\t} else {\n\t\t/* since index non-negative */\n\t\tDUK_ASSERT(idx != DUK_INVALID_INDEX);\n\t\tuidx = (duk_uidx_t) idx;\n\t}\n\n\t/* DUK_INVALID_INDEX won't be accepted as a valid index. */\n\tDUK_ASSERT(vs_size + (duk_uidx_t) DUK_INVALID_INDEX >= vs_size);\n\n\tif (DUK_LIKELY(uidx < vs_size)) {\n\t\treturn (duk_idx_t) uidx;\n\t}\n\treturn DUK_INVALID_INDEX;\n}\n\nDUK_EXTERNAL duk_idx_t duk_require_normalize_index(duk_hthread *thr, duk_idx_t idx) {\n\tduk_uidx_t vs_size;\n\tduk_uidx_t uidx;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK_ASSERT(DUK_INVALID_INDEX < 0);\n\n\tDUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);\n\tvs_size = (duk_uidx_t) (thr->valstack_top - thr->valstack_bottom);\n\tDUK_ASSERT_DISABLE(vs_size >= 0);  /* unsigned */\n\n\tif (idx < 0) {\n\t\tuidx = vs_size + (duk_uidx_t) idx;\n\t} else {\n\t\tDUK_ASSERT(idx != DUK_INVALID_INDEX);\n\t\tuidx = (duk_uidx_t) idx;\n\t}\n\n\t/* DUK_INVALID_INDEX won't be accepted as a valid index. */\n\tDUK_ASSERT(vs_size + (duk_uidx_t) DUK_INVALID_INDEX >= vs_size);\n\n\tif (DUK_LIKELY(uidx < vs_size)) {\n\t\treturn (duk_idx_t) uidx;\n\t}\n\tDUK_ERROR_RANGE_INDEX(thr, idx);\n\treturn 0;  /* unreachable */\n}\n\nDUK_INTERNAL duk_tval *duk_get_tval(duk_hthread *thr, duk_idx_t idx) {\n\tduk_uidx_t vs_size;\n\tduk_uidx_t uidx;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK_ASSERT(DUK_INVALID_INDEX < 0);\n\n\tDUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);\n\tvs_size = (duk_uidx_t) (thr->valstack_top - thr->valstack_bottom);\n\tDUK_ASSERT_DISABLE(vs_size >= 0);  /* unsigned */\n\n\tif (idx < 0) {\n\t\tuidx = vs_size + (duk_uidx_t) idx;\n\t} else {\n\t\tDUK_ASSERT(idx != DUK_INVALID_INDEX);\n\t\tuidx = (duk_uidx_t) idx;\n\t}\n\n\t/* DUK_INVALID_INDEX won't be accepted as a valid index. */\n\tDUK_ASSERT(vs_size + (duk_uidx_t) DUK_INVALID_INDEX >= vs_size);\n\n\tif (DUK_LIKELY(uidx < vs_size)) {\n\t\treturn thr->valstack_bottom + uidx;\n\t}\n\treturn NULL;\n}\n\n/* Variant of duk_get_tval() which is guaranteed to return a valid duk_tval\n * pointer.  When duk_get_tval() would return NULL, this variant returns a\n * pointer to a duk_tval with tag DUK_TAG_UNUSED.  This allows the call site\n * to avoid an unnecessary NULL check which sometimes leads to better code.\n * The return duk_tval is read only (at least for the UNUSED value).\n */\nDUK_LOCAL const duk_tval_unused duk__const_tval_unused = DUK_TVAL_UNUSED_INITIALIZER();\n\nDUK_INTERNAL duk_tval *duk_get_tval_or_unused(duk_hthread *thr, duk_idx_t idx) {\n\tduk_tval *tv;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\ttv = duk_get_tval(thr, idx);\n\tif (tv != NULL) {\n\t\treturn tv;\n\t}\n\treturn (duk_tval *) DUK_LOSE_CONST(&duk__const_tval_unused);\n}\n\nDUK_INTERNAL duk_tval *duk_require_tval(duk_hthread *thr, duk_idx_t idx) {\n\tduk_uidx_t vs_size;\n\tduk_uidx_t uidx;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK_ASSERT(DUK_INVALID_INDEX < 0);\n\n\tDUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);\n\tvs_size = (duk_uidx_t) (thr->valstack_top - thr->valstack_bottom);\n\tDUK_ASSERT_DISABLE(vs_size >= 0);  /* unsigned */\n\n\t/* Use unsigned arithmetic to optimize comparison. */\n\tif (idx < 0) {\n\t\tuidx = vs_size + (duk_uidx_t) idx;\n\t} else {\n\t\tDUK_ASSERT(idx != DUK_INVALID_INDEX);\n\t\tuidx = (duk_uidx_t) idx;\n\t}\n\n\t/* DUK_INVALID_INDEX won't be accepted as a valid index. */\n\tDUK_ASSERT(vs_size + (duk_uidx_t) DUK_INVALID_INDEX >= vs_size);\n\n\tif (DUK_LIKELY(uidx < vs_size)) {\n\t\treturn thr->valstack_bottom + uidx;\n\t}\n\tDUK_ERROR_RANGE_INDEX(thr, idx);\n\treturn NULL;\n}\n\n/* Non-critical. */\nDUK_EXTERNAL duk_bool_t duk_is_valid_index(duk_hthread *thr, duk_idx_t idx) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK_ASSERT(DUK_INVALID_INDEX < 0);\n\n\treturn (duk_normalize_index(thr, idx) >= 0);\n}\n\n/* Non-critical. */\nDUK_EXTERNAL void duk_require_valid_index(duk_hthread *thr, duk_idx_t idx) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK_ASSERT(DUK_INVALID_INDEX < 0);\n\n\tif (DUK_UNLIKELY(duk_normalize_index(thr, idx) < 0)) {\n\t\tDUK_ERROR_RANGE_INDEX(thr, idx);\n\t\treturn;  /* unreachable */\n\t}\n}\n\n/*\n *  Value stack top handling\n */\n\nDUK_EXTERNAL duk_idx_t duk_get_top(duk_hthread *thr) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\treturn (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);\n}\n\n/* Internal helper to get current top but to require a minimum top value\n * (TypeError if not met).\n */\nDUK_INTERNAL duk_idx_t duk_get_top_require_min(duk_hthread *thr, duk_idx_t min_top) {\n\tduk_idx_t ret;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);\n\tif (DUK_UNLIKELY(ret < min_top)) {\n\t\tDUK_ERROR_TYPE_INVALID_ARGS(thr);\n\t}\n\treturn ret;\n}\n\n/* Set stack top within currently allocated range, but don't reallocate.\n * This is performance critical especially for call handling, so whenever\n * changing, profile and look at generated code.\n */\nDUK_EXTERNAL void duk_set_top(duk_hthread *thr, duk_idx_t idx) {\n\tduk_uidx_t vs_size;\n\tduk_uidx_t vs_limit;\n\tduk_uidx_t uidx;\n\tduk_tval *tv;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK_ASSERT(DUK_INVALID_INDEX < 0);\n\n\tDUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);\n\tDUK_ASSERT(thr->valstack_end >= thr->valstack_bottom);\n\tvs_size = (duk_uidx_t) (thr->valstack_top - thr->valstack_bottom);\n\tvs_limit = (duk_uidx_t) (thr->valstack_end - thr->valstack_bottom);\n\n\tif (idx < 0) {\n\t\t/* Negative indices are always within allocated stack but\n\t\t * must not go below zero index.\n\t\t */\n\t\tuidx = vs_size + (duk_uidx_t) idx;\n\t} else {\n\t\t/* Positive index can be higher than valstack top but must\n\t\t * not go above allocated stack (equality is OK).\n\t\t */\n\t\tuidx = (duk_uidx_t) idx;\n\t}\n\n\t/* DUK_INVALID_INDEX won't be accepted as a valid index. */\n\tDUK_ASSERT(vs_size + (duk_uidx_t) DUK_INVALID_INDEX >= vs_size);\n\tDUK_ASSERT(vs_size + (duk_uidx_t) DUK_INVALID_INDEX >= vs_limit);\n\n#if defined(DUK_USE_VALSTACK_UNSAFE)\n\tDUK_ASSERT(uidx <= vs_limit);\n\tDUK_UNREF(vs_limit);\n#else\n\tif (DUK_UNLIKELY(uidx > vs_limit)) {\n\t\tDUK_ERROR_RANGE_INDEX(thr, idx);\n\t\treturn;  /* unreachable */\n\t}\n#endif\n\tDUK_ASSERT(uidx <= vs_limit);\n\n\t/* Handle change in value stack top.  Respect value stack\n\t * initialization policy: 'undefined' above top.  Note that\n\t * DECREF may cause a side effect that reallocates valstack,\n\t * so must relookup after DECREF.\n\t */\n\n\tif (uidx >= vs_size) {\n\t\t/* Stack size increases or stays the same. */\n#if defined(DUK_USE_ASSERTIONS)\n\t\tduk_uidx_t count;\n\n\t\tcount = uidx - vs_size;\n\t\twhile (count != 0) {\n\t\t\tcount--;\n\t\t\ttv = thr->valstack_top + count;\n\t\t\tDUK_ASSERT(DUK_TVAL_IS_UNDEFINED(tv));\n\t\t}\n#endif\n\t\tthr->valstack_top = thr->valstack_bottom + uidx;\n\t} else {\n\t\t/* Stack size decreases. */\n#if defined(DUK_USE_REFERENCE_COUNTING)\n\t\tduk_uidx_t count;\n\t\tduk_tval *tv_end;\n\n\t\tcount = vs_size - uidx;\n\t\tDUK_ASSERT(count > 0);\n\t\ttv = thr->valstack_top;\n\t\ttv_end = tv - count;\n\t\tDUK_ASSERT(tv > tv_end);  /* Because count > 0. */\n\t\tdo {\n\t\t\ttv--;\n\t\t\tDUK_ASSERT(tv >= thr->valstack_bottom);\n\t\t\tDUK_TVAL_SET_UNDEFINED_UPDREF_NORZ(thr, tv);\n\t\t} while (tv != tv_end);\n\t\tthr->valstack_top = tv_end;\n\t\tDUK_REFZERO_CHECK_FAST(thr);\n#else  /* DUK_USE_REFERENCE_COUNTING */\n\t\tduk_uidx_t count;\n\t\tduk_tval *tv_end;\n\n\t\tcount = vs_size - uidx;\n\t\ttv = thr->valstack_top;\n\t\ttv_end = tv - count;\n\t\tDUK_ASSERT(tv > tv_end);\n\t\tdo {\n\t\t\ttv--;\n\t\t\tDUK_TVAL_SET_UNDEFINED(tv);\n\t\t} while (tv != tv_end);\n\t\tthr->valstack_top = tv_end;\n#endif  /* DUK_USE_REFERENCE_COUNTING */\n\t}\n}\n\n/* Internal variant with a non-negative index and no runtime size checks. */\n#if defined(DUK_USE_PREFER_SIZE)\nDUK_INTERNAL void duk_set_top_unsafe(duk_hthread *thr, duk_idx_t idx) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tduk_set_top(thr, idx);\n}\n#else  /* DUK_USE_PREFER_SIZE */\nDUK_INTERNAL void duk_set_top_unsafe(duk_hthread *thr, duk_idx_t idx) {\n\tduk_uidx_t uidx;\n\tduk_uidx_t vs_size;\n\tduk_tval *tv;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);\n\tDUK_ASSERT(thr->valstack_end >= thr->valstack_bottom);\n\tDUK_ASSERT(idx >= 0);\n\tDUK_ASSERT(idx <= (duk_idx_t) (thr->valstack_end - thr->valstack_bottom));\n\n\t/* XXX: byte arithmetic */\n\tuidx = (duk_uidx_t) idx;\n\tvs_size = (duk_uidx_t) (thr->valstack_top - thr->valstack_bottom);\n\n\tif (uidx >= vs_size) {\n\t\t/* Stack size increases or stays the same. */\n#if defined(DUK_USE_ASSERTIONS)\n\t\tduk_uidx_t count;\n\n\t\tcount = uidx - vs_size;\n\t\twhile (count != 0) {\n\t\t\tcount--;\n\t\t\ttv = thr->valstack_top + count;\n\t\t\tDUK_ASSERT(DUK_TVAL_IS_UNDEFINED(tv));\n\t\t}\n#endif\n\t\tthr->valstack_top = thr->valstack_bottom + uidx;\n\t} else {\n\t\t/* Stack size decreases. */\n#if defined(DUK_USE_REFERENCE_COUNTING)\n\t\tduk_uidx_t count;\n\t\tduk_tval *tv_end;\n\n\t\tcount = vs_size - uidx;\n\t\tDUK_ASSERT(count > 0);\n\t\ttv = thr->valstack_top;\n\t\ttv_end = tv - count;\n\t\tDUK_ASSERT(tv > tv_end);  /* Because count > 0. */\n\t\tdo {\n\t\t\ttv--;\n\t\t\tDUK_ASSERT(tv >= thr->valstack_bottom);\n\t\t\tDUK_TVAL_SET_UNDEFINED_UPDREF_NORZ(thr, tv);\n\t\t} while (tv != tv_end);\n\t\tthr->valstack_top = tv_end;\n\t\tDUK_REFZERO_CHECK_FAST(thr);\n#else  /* DUK_USE_REFERENCE_COUNTING */\n\t\tduk_uidx_t count;\n\t\tduk_tval *tv_end;\n\n\t\tcount = vs_size - uidx;\n\t\ttv = thr->valstack_top;\n\t\ttv_end = tv - count;\n\t\tDUK_ASSERT(tv > tv_end);\n\t\tdo {\n\t\t\ttv--;\n\t\t\tDUK_TVAL_SET_UNDEFINED(tv);\n\t\t} while (tv != tv_end);\n\t\tthr->valstack_top = tv_end;\n#endif  /* DUK_USE_REFERENCE_COUNTING */\n\t}\n}\n#endif  /* DUK_USE_PREFER_SIZE */\n\n/* Internal helper: set top to 'top', and set [idx_wipe_start,top[ to\n * 'undefined' (doing nothing if idx_wipe_start == top).  Indices are\n * positive and within value stack reserve.  This is used by call handling.\n */\nDUK_INTERNAL void duk_set_top_and_wipe(duk_hthread *thr, duk_idx_t top, duk_idx_t idx_wipe_start) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK_ASSERT(top >= 0);\n\tDUK_ASSERT(idx_wipe_start >= 0);\n\tDUK_ASSERT(idx_wipe_start <= top);\n\tDUK_ASSERT(thr->valstack_bottom + top <= thr->valstack_end);\n\tDUK_ASSERT(thr->valstack_bottom + idx_wipe_start <= thr->valstack_end);\n\n\tduk_set_top_unsafe(thr, idx_wipe_start);\n\tduk_set_top_unsafe(thr, top);\n}\n\nDUK_EXTERNAL duk_idx_t duk_get_top_index(duk_hthread *thr) {\n\tduk_idx_t ret;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom) - 1;\n\tif (DUK_UNLIKELY(ret < 0)) {\n\t\t/* Return invalid index; if caller uses this without checking\n\t\t * in another API call, the index won't map to a valid stack\n\t\t * entry.\n\t\t */\n\t\treturn DUK_INVALID_INDEX;\n\t}\n\treturn ret;\n}\n\n/* Internal variant: call assumes there is at least one element on the value\n * stack frame; this is only asserted for.\n */\nDUK_INTERNAL duk_idx_t duk_get_top_index_unsafe(duk_hthread *thr) {\n\tduk_idx_t ret;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom) - 1;\n\treturn ret;\n}\n\nDUK_EXTERNAL duk_idx_t duk_require_top_index(duk_hthread *thr) {\n\tduk_idx_t ret;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom) - 1;\n\tif (DUK_UNLIKELY(ret < 0)) {\n\t\tDUK_ERROR_RANGE_INDEX(thr, -1);\n\t\treturn 0;  /* unreachable */\n\t}\n\treturn ret;\n}\n\n/*\n *  Value stack resizing.\n *\n *  This resizing happens above the current \"top\": the value stack can be\n *  grown or shrunk, but the \"top\" is not affected.  The value stack cannot\n *  be resized to a size below the current reserve.\n *\n *  The low level reallocation primitive must carefully recompute all value\n *  stack pointers, and must also work if ALL pointers are NULL.  The resize\n *  is quite tricky because the valstack realloc may cause a mark-and-sweep,\n *  which may run finalizers.  Running finalizers may resize the valstack\n *  recursively (the same value stack we're working on).  So, after realloc\n *  returns, we know that the valstack bottom, top, and reserve should still\n *  be the same (there should not be live values above the \"top\"), but its\n *  underlying size, alloc_end, and base pointer may have changed.\n *\n *  'new_size' is known to be <= DUK_USE_VALSTACK_LIMIT, which ensures that\n *  size_t and pointer arithmetic won't wrap in duk__resize_valstack().\n */\n\n/* Low level valstack resize primitive, used for both grow and shrink.  All\n * adjustments for slack etc have already been done.  Doesn't throw but does\n * have allocation side effects.\n */\nDUK_LOCAL DUK_COLD DUK_NOINLINE duk_bool_t duk__resize_valstack(duk_hthread *thr, duk_size_t new_size) {\n\tduk_tval *pre_valstack;\n\tduk_tval *pre_bottom;\n\tduk_tval *pre_top;\n\tduk_tval *pre_end;\n\tduk_tval *pre_alloc_end;\n\tduk_ptrdiff_t ptr_diff;\n\tduk_tval *new_valstack;\n\tduk_size_t new_alloc_size;\n\tduk_tval *tv_prev_alloc_end;\n\tduk_tval *p;\n\n\tDUK_ASSERT_HTHREAD_VALID(thr);\n\tDUK_ASSERT(thr->valstack_bottom >= thr->valstack);\n\tDUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);\n\tDUK_ASSERT(thr->valstack_end >= thr->valstack_top);\n\tDUK_ASSERT(thr->valstack_alloc_end >= thr->valstack_end);\n\tDUK_ASSERT((duk_size_t) (thr->valstack_top - thr->valstack) <= new_size);  /* can't resize below 'top' */\n\tDUK_ASSERT(new_size <= DUK_USE_VALSTACK_LIMIT);  /* valstack limit caller has check, prevents wrapping */\n\tDUK_ASSERT(new_size <= DUK_SIZE_MAX / sizeof(duk_tval));  /* specific assert for wrapping */\n\n\t/* Pre-realloc pointer copies for asserts and debug logs. */\n\tpre_valstack = thr->valstack;\n\tpre_bottom = thr->valstack_bottom;\n\tpre_top = thr->valstack_top;\n\tpre_end = thr->valstack_end;\n\tpre_alloc_end = thr->valstack_alloc_end;\n\n\tDUK_UNREF(pre_valstack);\n\tDUK_UNREF(pre_bottom);\n\tDUK_UNREF(pre_top);\n\tDUK_UNREF(pre_end);\n\tDUK_UNREF(pre_alloc_end);\n\n\t/* If finalizer torture enabled, force base pointer change every time\n\t * when it would be allowed.\n\t */\n#if defined(DUK_USE_FINALIZER_TORTURE)\n\tif (thr->heap->pf_prevent_count == 0) {\n\t\tduk_hthread_valstack_torture_realloc(thr);\n\t}\n#endif\n\n\t/* Allocate a new valstack using DUK_REALLOC_DIRECT() to deal with\n\t * a side effect changing the base pointer.\n\t */\n\tnew_alloc_size = sizeof(duk_tval) * new_size;\n\tnew_valstack = (duk_tval *) DUK_REALLOC_INDIRECT(thr->heap, duk_hthread_get_valstack_ptr, (void *) thr, new_alloc_size);\n\tif (DUK_UNLIKELY(new_valstack == NULL)) {\n\t\t/* Because new_size != 0, if condition doesn't need to be\n\t\t * (new_valstack != NULL || new_size == 0).\n\t\t */\n\t\tDUK_ASSERT(new_size != 0);\n\t\tDUK_D(DUK_DPRINT(\"failed to resize valstack to %lu entries (%lu bytes)\",\n\t\t                 (unsigned long) new_size, (unsigned long) new_alloc_size));\n\t\treturn 0;\n\t}\n\n\t/* Debug log any changes in pointer(s) by side effects.  These don't\n\t * necessarily imply any incorrect behavior, but should be rare in\n\t * practice.\n\t */\n#if defined(DUK_USE_DEBUG)\n\tif (thr->valstack != pre_valstack) {\n\t\tDUK_D(DUK_DPRINT(\"valstack base pointer changed during valstack resize: %p -> %p\",\n\t\t                 (void *) pre_valstack, (void *) thr->valstack));\n\t}\n\tif (thr->valstack_bottom != pre_bottom) {\n\t\tDUK_D(DUK_DPRINT(\"valstack bottom pointer changed during valstack resize: %p -> %p\",\n\t\t                 (void *) pre_bottom, (void *) thr->valstack_bottom));\n\t}\n\tif (thr->valstack_top != pre_top) {\n\t\tDUK_D(DUK_DPRINT(\"valstack top pointer changed during valstack resize: %p -> %p\",\n\t\t                 (void *) pre_top, (void *) thr->valstack_top));\n\t}\n\tif (thr->valstack_end != pre_end) {\n\t\tDUK_D(DUK_DPRINT(\"valstack end pointer changed during valstack resize: %p -> %p\",\n\t\t                 (void *) pre_end, (void *) thr->valstack_end));\n\t}\n\tif (thr->valstack_alloc_end != pre_alloc_end) {\n\t\tDUK_D(DUK_DPRINT(\"valstack alloc_end pointer changed during valstack resize: %p -> %p\",\n\t\t                 (void *) pre_alloc_end, (void *) thr->valstack_alloc_end));\n\t}\n#endif\n\n\t/* Assertions: offsets for bottom, top, and end (reserve) must not\n\t * have changed even with side effects because they are always\n\t * restored in unwind.  For alloc_end there's no guarantee: it may\n\t * have grown or shrunk (but remain above 'end').\n\t */\n\tDUK_ASSERT(thr->valstack_bottom - thr->valstack == pre_bottom - pre_valstack);\n\tDUK_ASSERT(thr->valstack_top - thr->valstack == pre_top - pre_valstack);\n\tDUK_ASSERT(thr->valstack_end - thr->valstack == pre_end - pre_valstack);\n\tDUK_ASSERT(thr->valstack_alloc_end >= thr->valstack_end);\n\n\t/* Write new pointers.  Most pointers can be handled as a pointer\n\t * difference.\n\t */\n\tptr_diff = (duk_ptrdiff_t) ((duk_uint8_t *) new_valstack - (duk_uint8_t *) thr->valstack);\n\ttv_prev_alloc_end = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack_alloc_end + ptr_diff);\n\tthr->valstack = new_valstack;\n\tthr->valstack_bottom = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack_bottom + ptr_diff);\n\tthr->valstack_top = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack_top + ptr_diff);\n\tthr->valstack_end = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack_end + ptr_diff);\n\tthr->valstack_alloc_end = (duk_tval *) (void *) ((duk_uint8_t *) new_valstack + new_alloc_size);\n\n\t/* Assertions: pointer sanity after pointer updates. */\n\tDUK_ASSERT(thr->valstack_bottom >= thr->valstack);\n\tDUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);\n\tDUK_ASSERT(thr->valstack_end >= thr->valstack_top);\n\tDUK_ASSERT(thr->valstack_alloc_end >= thr->valstack_end);\n\n\tDUK_D(DUK_DPRINT(\"resized valstack %lu -> %lu elements (%lu -> %lu bytes): \"\n\t                 \"base=%p -> %p, bottom=%p -> %p (%ld), top=%p -> %p (%ld), \"\n\t                 \"end=%p -> %p (%ld), alloc_end=%p -> %p (%ld);\"\n\t                 \" tv_prev_alloc_end=%p (-> %ld inits; <0 means shrink)\",\n\t                 (unsigned long) (pre_alloc_end - pre_valstack),\n\t                 (unsigned long) new_size,\n\t                 (unsigned long) ((duk_uint8_t *) pre_alloc_end - (duk_uint8_t *) pre_valstack),\n\t                 (unsigned long) new_alloc_size,\n\t                 (void *) pre_valstack, (void *) thr->valstack,\n\t                 (void *) pre_bottom, (void *) thr->valstack_bottom, (long) (thr->valstack_bottom - thr->valstack),\n\t                 (void *) pre_top, (void *) thr->valstack_top, (long) (thr->valstack_top - thr->valstack),\n\t                 (void *) pre_end, (void *) thr->valstack_end, (long) (thr->valstack_end - thr->valstack),\n\t                 (void *) pre_alloc_end, (void *) thr->valstack_alloc_end, (long) (thr->valstack_alloc_end - thr->valstack),\n\t                 (void *) tv_prev_alloc_end, (long) (thr->valstack_alloc_end - tv_prev_alloc_end)));\n\n\t/* If allocation grew, init any new slots to 'undefined'. */\n\tp = tv_prev_alloc_end;\n\twhile (p < thr->valstack_alloc_end) {\n\t\t/* Never executed if new size is smaller. */\n\t\tDUK_TVAL_SET_UNDEFINED(p);\n\t\tp++;\n\t}\n\n\t/* Assert for value stack initialization policy. */\n#if defined(DUK_USE_ASSERTIONS)\n\tp = thr->valstack_top;\n\twhile (p < thr->valstack_alloc_end) {\n\t\tDUK_ASSERT(DUK_TVAL_IS_UNDEFINED(p));\n\t\tp++;\n\t}\n#endif\n\n\treturn 1;\n}\n\nDUK_LOCAL DUK_COLD DUK_NOINLINE duk_bool_t duk__valstack_grow(duk_hthread *thr, duk_size_t min_bytes, duk_bool_t throw_on_error) {\n\tduk_size_t min_size;\n\tduk_size_t new_size;\n\n\tDUK_ASSERT(min_bytes / sizeof(duk_tval) * sizeof(duk_tval) == min_bytes);\n\tmin_size = min_bytes / sizeof(duk_tval);  /* from bytes to slots */\n\n#if defined(DUK_USE_VALSTACK_GROW_SHIFT)\n\t/* New size is minimum size plus a proportional slack, e.g. shift of\n\t * 2 means a 25% slack.\n\t */\n\tnew_size = min_size + (min_size >> DUK_USE_VALSTACK_GROW_SHIFT);\n#else\n\t/* New size is tight with no slack.  This is sometimes preferred in\n\t * low memory environments.\n\t */\n\tnew_size = min_size;\n#endif\n\n\tif (DUK_UNLIKELY(new_size > DUK_USE_VALSTACK_LIMIT || new_size < min_size /*wrap*/)) {\n\t\t/* Note: may be triggered even if minimal new_size would not reach the limit,\n\t\t * plan limit accordingly.\n\t\t */\n\t\tif (throw_on_error) {\n\t\t\tDUK_ERROR_RANGE(thr, DUK_STR_VALSTACK_LIMIT);\n\t\t}\n\t\treturn 0;\n\t}\n\n\tif (duk__resize_valstack(thr, new_size) == 0) {\n\t\tif (throw_on_error) {\n\t\t\tDUK_ERROR_ALLOC_FAILED(thr);\n\t\t}\n\t\treturn 0;\n\t}\n\n\tthr->valstack_end = thr->valstack + min_size;\n\tDUK_ASSERT(thr->valstack_alloc_end >= thr->valstack_end);\n\n\treturn 1;\n}\n\n/* Hot, inlined value stack grow check.  Because value stack almost never\n * grows, the actual resize call is in a NOINLINE helper.\n */\nDUK_INTERNAL DUK_INLINE void duk_valstack_grow_check_throw(duk_hthread *thr, duk_size_t min_bytes) {\n\tduk_tval *tv;\n\n\ttv = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + min_bytes);\n\tif (DUK_LIKELY(thr->valstack_end >= tv)) {\n\t\treturn;\n\t}\n\tif (DUK_LIKELY(thr->valstack_alloc_end >= tv)) {\n\t\t/* Values in [valstack_top,valstack_alloc_end[ are initialized\n\t\t * to 'undefined' so we can just move the end pointer.\n\t\t */\n\t\tthr->valstack_end = tv;\n\t\treturn;\n\t}\n\t(void) duk__valstack_grow(thr, min_bytes, 1 /*throw_on_error*/);\n}\n\n/* Hot, inlined value stack grow check which doesn't throw. */\nDUK_INTERNAL DUK_INLINE duk_bool_t duk_valstack_grow_check_nothrow(duk_hthread *thr, duk_size_t min_bytes) {\n\tduk_tval *tv;\n\n\ttv = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + min_bytes);\n\tif (DUK_LIKELY(thr->valstack_end >= tv)) {\n\t\treturn 1;\n\t}\n\tif (DUK_LIKELY(thr->valstack_alloc_end >= tv)) {\n\t\tthr->valstack_end = tv;\n\t\treturn 1;\n\t}\n\treturn duk__valstack_grow(thr, min_bytes, 0 /*throw_on_error*/);\n}\n\n/* Value stack shrink check, called from mark-and-sweep. */\nDUK_INTERNAL void duk_valstack_shrink_check_nothrow(duk_hthread *thr, duk_bool_t snug) {\n\tduk_size_t alloc_bytes;\n\tduk_size_t reserve_bytes;\n\tduk_size_t shrink_bytes;\n\n\talloc_bytes = (duk_size_t) ((duk_uint8_t *) thr->valstack_alloc_end - (duk_uint8_t *) thr->valstack);\n\treserve_bytes = (duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack);\n\tDUK_ASSERT(alloc_bytes >= reserve_bytes);\n\n\t/* We're free to shrink the value stack allocation down to\n\t * reserve_bytes but not more.  If 'snug' (emergency GC)\n\t * shrink whatever we can.  Otherwise only shrink if the new\n\t * size would be considerably smaller.\n\t */\n\n#if defined(DUK_USE_VALSTACK_SHRINK_CHECK_SHIFT)\n\tif (snug) {\n\t\tshrink_bytes = reserve_bytes;\n\t} else {\n\t\tduk_size_t proportion, slack;\n\n\t\t/* Require that value stack shrinks by at least X% of its\n\t\t * current size.  For example, shift of 2 means at least\n\t\t * 25%.  The proportion is computed as bytes and may not\n\t\t * be a multiple of sizeof(duk_tval); that's OK here.\n\t\t */\n\t\tproportion = alloc_bytes >> DUK_USE_VALSTACK_SHRINK_CHECK_SHIFT;\n\t\tif (alloc_bytes - reserve_bytes < proportion) {\n\t\t\t/* Too little would be freed, do nothing. */\n\t\t\treturn;\n\t\t}\n\n\t\t/* Keep a slack after shrinking.  The slack is again a\n\t\t * proportion of the current size (the proportion should\n\t\t * of course be smaller than the check proportion above).\n\t\t */\n#if defined(DUK_USE_VALSTACK_SHRINK_SLACK_SHIFT)\n\t\tDUK_ASSERT(DUK_USE_VALSTACK_SHRINK_SLACK_SHIFT > DUK_USE_VALSTACK_SHRINK_CHECK_SHIFT);\n\t\tslack = alloc_bytes >> DUK_USE_VALSTACK_SHRINK_SLACK_SHIFT;\n#else\n\t\tslack = 0;\n#endif\n\t\tshrink_bytes = reserve_bytes +\n\t\t               slack / sizeof(duk_tval) * sizeof(duk_tval);  /* multiple of duk_tval */\n\t}\n#else  /* DUK_USE_VALSTACK_SHRINK_CHECK_SHIFT */\n\t/* Always snug, useful in some low memory environments. */\n\tDUK_UNREF(snug);\n\tshrink_bytes = reserve_bytes;\n#endif  /* DUK_USE_VALSTACK_SHRINK_CHECK_SHIFT */\n\n\tDUK_D(DUK_DPRINT(\"valstack shrink check: alloc_bytes=%ld, reserve_bytes=%ld, shrink_bytes=%ld (unvalidated)\",\n\t                 (long) alloc_bytes, (long) reserve_bytes, (long) shrink_bytes));\n\tDUK_ASSERT(shrink_bytes >= reserve_bytes);\n\tif (shrink_bytes >= alloc_bytes) {\n\t\t/* Skip if shrink target is same as current one (or higher,\n\t\t * though that shouldn't happen in practice).\n\t\t */\n\t\treturn;\n\t}\n\tDUK_ASSERT(shrink_bytes / sizeof(duk_tval) * sizeof(duk_tval) == shrink_bytes);\n\n\tDUK_D(DUK_DPRINT(\"valstack shrink check: decided to shrink, snug: %ld\", (long) snug));\n\n\tduk__resize_valstack(thr, shrink_bytes / sizeof(duk_tval));\n}\n\nDUK_EXTERNAL duk_bool_t duk_check_stack(duk_hthread *thr, duk_idx_t extra) {\n\tduk_size_t min_new_bytes;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK_ASSERT(thr != NULL);\n\n\tif (DUK_UNLIKELY(extra < 0 || extra > DUK_USE_VALSTACK_LIMIT)) {\n\t\tif (extra < 0) {\n\t\t\t/* Clamping to zero makes the API more robust to calling code\n\t\t\t * calculation errors.\n\t\t\t */\n\t\t\textra = 0;\n\t\t} else {\n\t\t\t/* Cause grow check to fail without wrapping arithmetic. */\n\t\t\textra = DUK_USE_VALSTACK_LIMIT;\n\t\t}\n\t}\n\n\tmin_new_bytes = (duk_size_t) ((duk_uint8_t *) thr->valstack_top - (duk_uint8_t *) thr->valstack) +\n\t                sizeof(duk_tval) * ((duk_size_t) extra + DUK_VALSTACK_INTERNAL_EXTRA);\n\treturn duk_valstack_grow_check_nothrow(thr, min_new_bytes);\n}\n\nDUK_EXTERNAL void duk_require_stack(duk_hthread *thr, duk_idx_t extra) {\n\tduk_size_t min_new_bytes;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK_ASSERT(thr != NULL);\n\n\tif (DUK_UNLIKELY(extra < 0 || extra > DUK_USE_VALSTACK_LIMIT)) {\n\t\tif (extra < 0) {\n\t\t\t/* Clamping to zero makes the API more robust to calling code\n\t\t\t * calculation errors.\n\t\t\t */\n\t\t\textra = 0;\n\t\t} else {\n\t\t\t/* Cause grow check to fail without wrapping arithmetic. */\n\t\t\textra = DUK_USE_VALSTACK_LIMIT;\n\t\t}\n\t}\n\n\tmin_new_bytes = (duk_size_t) ((duk_uint8_t *) thr->valstack_top - (duk_uint8_t *) thr->valstack) +\n\t                sizeof(duk_tval) * ((duk_size_t) extra + DUK_VALSTACK_INTERNAL_EXTRA);\n\tduk_valstack_grow_check_throw(thr, min_new_bytes);\n}\n\nDUK_EXTERNAL duk_bool_t duk_check_stack_top(duk_hthread *thr, duk_idx_t top) {\n\tduk_size_t min_new_bytes;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tif (DUK_UNLIKELY(top < 0 || top > DUK_USE_VALSTACK_LIMIT)) {\n\t\tif (top < 0) {\n\t\t\t/* Clamping to zero makes the API more robust to calling code\n\t\t\t * calculation errors.\n\t\t\t */\n\t\t\ttop = 0;\n\t\t} else {\n\t\t\t/* Cause grow check to fail without wrapping arithmetic. */\n\t\t\ttop = DUK_USE_VALSTACK_LIMIT;\n\t\t}\n\t}\n\n\tDUK_ASSERT(top >= 0);\n\tmin_new_bytes = (duk_size_t) ((duk_uint8_t *) thr->valstack_bottom - (duk_uint8_t *) thr->valstack) +\n\t                sizeof(duk_tval) * ((duk_size_t) top + DUK_VALSTACK_INTERNAL_EXTRA);\n\treturn duk_valstack_grow_check_nothrow(thr, min_new_bytes);\n}\n\nDUK_EXTERNAL void duk_require_stack_top(duk_hthread *thr, duk_idx_t top) {\n\tduk_size_t min_new_bytes;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tif (DUK_UNLIKELY(top < 0 || top > DUK_USE_VALSTACK_LIMIT)) {\n\t\tif (top < 0) {\n\t\t\t/* Clamping to zero makes the API more robust to calling code\n\t\t\t * calculation errors.\n\t\t\t */\n\t\t\ttop = 0;\n\t\t} else {\n\t\t\t/* Cause grow check to fail without wrapping arithmetic. */\n\t\t\ttop = DUK_USE_VALSTACK_LIMIT;\n\t\t}\n\t}\n\n\tDUK_ASSERT(top >= 0);\n\tmin_new_bytes = (duk_size_t) ((duk_uint8_t *) thr->valstack_bottom - (duk_uint8_t *) thr->valstack) +\n\t                sizeof(duk_tval) * ((duk_size_t) top + DUK_VALSTACK_INTERNAL_EXTRA);\n\tduk_valstack_grow_check_throw(thr, min_new_bytes);\n}\n\n/*\n *  Basic stack manipulation: swap, dup, insert, replace, etc\n */\n\nDUK_EXTERNAL void duk_swap(duk_hthread *thr, duk_idx_t idx1, duk_idx_t idx2) {\n\tduk_tval *tv1;\n\tduk_tval *tv2;\n\tduk_tval tv_tmp;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\ttv1 = duk_require_tval(thr, idx1);\n\tDUK_ASSERT(tv1 != NULL);\n\ttv2 = duk_require_tval(thr, idx2);\n\tDUK_ASSERT(tv2 != NULL);\n\n\t/* If tv1==tv2 this is a NOP, no check is needed */\n\tDUK_TVAL_SET_TVAL(&tv_tmp, tv1);\n\tDUK_TVAL_SET_TVAL(tv1, tv2);\n\tDUK_TVAL_SET_TVAL(tv2, &tv_tmp);\n}\n\nDUK_EXTERNAL void duk_swap_top(duk_hthread *thr, duk_idx_t idx) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tduk_swap(thr, idx, -1);\n}\n\nDUK_EXTERNAL void duk_dup(duk_hthread *thr, duk_idx_t from_idx) {\n\tduk_tval *tv_from;\n\tduk_tval *tv_to;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK__CHECK_SPACE();\n\n\ttv_from = duk_require_tval(thr, from_idx);\n\ttv_to = thr->valstack_top++;\n\tDUK_ASSERT(tv_from != NULL);\n\tDUK_ASSERT(tv_to != NULL);\n\tDUK_TVAL_SET_TVAL(tv_to, tv_from);\n\tDUK_TVAL_INCREF(thr, tv_to);  /* no side effects */\n}\n\nDUK_EXTERNAL void duk_dup_top(duk_hthread *thr) {\n#if defined(DUK_USE_PREFER_SIZE)\n\tduk_dup(thr, -1);\n#else\n\tduk_tval *tv_from;\n\tduk_tval *tv_to;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK__CHECK_SPACE();\n\n\tif (DUK_UNLIKELY(thr->valstack_top - thr->valstack_bottom <= 0)) {\n\t\tDUK_ERROR_RANGE_INDEX(thr, -1);\n\t\treturn;  /* unreachable */\n\t}\n\ttv_from = thr->valstack_top - 1;\n\ttv_to = thr->valstack_top++;\n\tDUK_ASSERT(tv_from != NULL);\n\tDUK_ASSERT(tv_to != NULL);\n\tDUK_TVAL_SET_TVAL(tv_to, tv_from);\n\tDUK_TVAL_INCREF(thr, tv_to);  /* no side effects */\n#endif\n}\n\nDUK_INTERNAL void duk_dup_0(duk_hthread *thr) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\tduk_dup(thr, 0);\n}\nDUK_INTERNAL void duk_dup_1(duk_hthread *thr) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\tduk_dup(thr, 1);\n}\nDUK_INTERNAL void duk_dup_2(duk_hthread *thr) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\tduk_dup(thr, 2);\n}\nDUK_INTERNAL void duk_dup_m2(duk_hthread *thr) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\tduk_dup(thr, -2);\n}\nDUK_INTERNAL void duk_dup_m3(duk_hthread *thr) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\tduk_dup(thr, -3);\n}\nDUK_INTERNAL void duk_dup_m4(duk_hthread *thr) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\tduk_dup(thr, -4);\n}\n\nDUK_EXTERNAL void duk_insert(duk_hthread *thr, duk_idx_t to_idx) {\n\tduk_tval *p;\n\tduk_tval *q;\n\tduk_tval tv_tmp;\n\tduk_size_t nbytes;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tp = duk_require_tval(thr, to_idx);\n\tDUK_ASSERT(p != NULL);\n\tq = duk_require_tval(thr, -1);\n\tDUK_ASSERT(q != NULL);\n\n\tDUK_ASSERT(q >= p);\n\n\t/*              nbytes\n\t *           <--------->\n\t *    [ ... | p | x | x | q ]\n\t * => [ ... | q | p | x | x ]\n\t */\n\n\tnbytes = (duk_size_t) (((duk_uint8_t *) q) - ((duk_uint8_t *) p));  /* Note: 'q' is top-1 */\n\n\tDUK_DDD(DUK_DDDPRINT(\"duk_insert: to_idx=%ld, p=%p, q=%p, nbytes=%lu\",\n\t                     (long) to_idx, (void *) p, (void *) q, (unsigned long) nbytes));\n\n\t/* No net refcount changes. */\n\n\tif (nbytes > 0) {\n\t\tDUK_TVAL_SET_TVAL(&tv_tmp, q);\n\t\tDUK_ASSERT(nbytes > 0);\n\t\tDUK_MEMMOVE((void *) (p + 1), (const void *) p, (size_t) nbytes);\n\t\tDUK_TVAL_SET_TVAL(p, &tv_tmp);\n\t} else {\n\t\t/* nop: insert top to top */\n\t\tDUK_ASSERT(nbytes == 0);\n\t\tDUK_ASSERT(p == q);\n\t}\n}\n\nDUK_INTERNAL void duk_insert_undefined(duk_hthread *thr, duk_idx_t idx) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK_ASSERT(idx >= 0);  /* Doesn't support negative indices. */\n\n\tduk_push_undefined(thr);\n\tduk_insert(thr, idx);\n}\n\nDUK_INTERNAL void duk_insert_undefined_n(duk_hthread *thr, duk_idx_t idx, duk_idx_t count) {\n\tduk_tval *tv, *tv_end;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK_ASSERT(idx >= 0);  /* Doesn't support negative indices or count. */\n\tDUK_ASSERT(count >= 0);\n\n\ttv = duk_reserve_gap(thr, idx, count);\n\ttv_end = tv + count;\n\twhile (tv != tv_end) {\n\t\tDUK_TVAL_SET_UNDEFINED(tv);\n\t\ttv++;\n\t}\n}\n\nDUK_EXTERNAL void duk_replace(duk_hthread *thr, duk_idx_t to_idx) {\n\tduk_tval *tv1;\n\tduk_tval *tv2;\n\tduk_tval tv_tmp;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\ttv1 = duk_require_tval(thr, -1);\n\tDUK_ASSERT(tv1 != NULL);\n\ttv2 = duk_require_tval(thr, to_idx);\n\tDUK_ASSERT(tv2 != NULL);\n\n\t/* For tv1 == tv2, both pointing to stack top, the end result\n\t * is same as duk_pop(thr).\n\t */\n\tDUK_TVAL_SET_TVAL(&tv_tmp, tv2);\n\tDUK_TVAL_SET_TVAL(tv2, tv1);\n\tDUK_TVAL_SET_UNDEFINED(tv1);\n\tthr->valstack_top--;\n\tDUK_TVAL_DECREF(thr, &tv_tmp);  /* side effects */\n}\n\nDUK_EXTERNAL void duk_copy(duk_hthread *thr, duk_idx_t from_idx, duk_idx_t to_idx) {\n\tduk_tval *tv1;\n\tduk_tval *tv2;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\ttv1 = duk_require_tval(thr, from_idx);\n\tDUK_ASSERT(tv1 != NULL);\n\ttv2 = duk_require_tval(thr, to_idx);\n\tDUK_ASSERT(tv2 != NULL);\n\n\t/* For tv1 == tv2, this is a no-op (no explicit check needed). */\n\tDUK_TVAL_SET_TVAL_UPDREF(thr, tv2, tv1);  /* side effects */\n}\n\nDUK_EXTERNAL void duk_remove(duk_hthread *thr, duk_idx_t idx) {\n\tduk_tval *p;\n\tduk_tval *q;\n#if defined(DUK_USE_REFERENCE_COUNTING)\n\tduk_tval tv_tmp;\n#endif\n\tduk_size_t nbytes;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tp = duk_require_tval(thr, idx);\n\tDUK_ASSERT(p != NULL);\n\tq = duk_require_tval(thr, -1);\n\tDUK_ASSERT(q != NULL);\n\n\tDUK_ASSERT(q >= p);\n\n\t/*              nbytes            zero size case\n\t *           <--------->\n\t *    [ ... | p | x | x | q ]     [ ... | p==q ]\n\t * => [ ... | x | x | q ]         [ ... ]\n\t */\n\n#if defined(DUK_USE_REFERENCE_COUNTING)\n\t/* use a temp: decref only when valstack reachable values are correct */\n\tDUK_TVAL_SET_TVAL(&tv_tmp, p);\n#endif\n\n\tnbytes = (duk_size_t) (((duk_uint8_t *) q) - ((duk_uint8_t *) p));  /* Note: 'q' is top-1 */\n\tDUK_MEMMOVE((void *) p, (const void *) (p + 1), (size_t) nbytes);  /* zero size not an issue: pointers are valid */\n\n\tDUK_TVAL_SET_UNDEFINED(q);\n\tthr->valstack_top--;\n\n#if defined(DUK_USE_REFERENCE_COUNTING)\n\tDUK_TVAL_DECREF(thr, &tv_tmp);  /* side effects */\n#endif\n}\n\nDUK_INTERNAL void duk_remove_unsafe(duk_hthread *thr, duk_idx_t idx) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tduk_remove(thr, idx);  /* XXX: no optimization for now */\n}\n\nDUK_INTERNAL void duk_remove_m2(duk_hthread *thr) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tduk_remove(thr, -2);\n}\n\nDUK_INTERNAL void duk_remove_n(duk_hthread *thr, duk_idx_t idx, duk_idx_t count) {\n#if defined(DUK_USE_PREFER_SIZE)\n\t/* XXX: maybe too slow even when preferring size? */\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK_ASSERT(count >= 0);\n\tDUK_ASSERT(idx >= 0);\n\n\twhile (count-- > 0) {\n\t\tduk_remove(thr, idx);\n\t}\n#else  /* DUK_USE_PREFER_SIZE */\n\tduk_tval *tv_src;\n\tduk_tval *tv_dst;\n\tduk_tval *tv_newtop;\n\tduk_tval *tv;\n\tduk_size_t bytes;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK_ASSERT(count >= 0);\n\tDUK_ASSERT(idx >= 0);\n\n\ttv_dst = thr->valstack_bottom + idx;\n\tDUK_ASSERT(tv_dst <= thr->valstack_top);\n\ttv_src = tv_dst + count;\n\tDUK_ASSERT(tv_src <= thr->valstack_top);\n\tbytes = (duk_size_t) ((duk_uint8_t *) thr->valstack_top - (duk_uint8_t *) tv_src);\n\n\tfor (tv = tv_dst; tv < tv_src; tv++) {\n\t\tDUK_TVAL_DECREF_NORZ(thr, tv);\n\t}\n\n\tDUK_MEMMOVE((void *) tv_dst, (const void *) tv_src, bytes);\n\n\ttv_newtop = thr->valstack_top - count;\n\tfor (tv = tv_newtop; tv < thr->valstack_top; tv++) {\n\t\tDUK_TVAL_SET_UNDEFINED(tv);\n\t}\n\tthr->valstack_top = tv_newtop;\n\n\t/* When not preferring size, only NORZ macros are used; caller\n\t * is expected to DUK_REFZERO_CHECK().\n\t */\n#endif  /* DUK_USE_PREFER_SIZE */\n}\n\nDUK_INTERNAL void duk_remove_n_unsafe(duk_hthread *thr, duk_idx_t idx, duk_idx_t count) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tduk_remove_n(thr, idx, count);  /* XXX: no optimization for now */\n}\n\n/*\n *  Stack slice primitives\n */\n\nDUK_EXTERNAL void duk_xcopymove_raw(duk_hthread *to_thr, duk_hthread *from_thr, duk_idx_t count, duk_bool_t is_copy) {\n\tvoid *src;\n\tduk_size_t nbytes;\n\tduk_tval *p;\n\tduk_tval *q;\n\n\t/* XXX: several pointer comparison issues here */\n\n\tDUK_ASSERT_API_ENTRY(to_thr);\n\tDUK_ASSERT_CTX_VALID(to_thr);\n\tDUK_ASSERT_CTX_VALID(from_thr);\n\tDUK_ASSERT(to_thr->heap == from_thr->heap);\n\n\tif (DUK_UNLIKELY(to_thr == from_thr)) {\n\t\tDUK_ERROR_TYPE(to_thr, DUK_STR_INVALID_CONTEXT);\n\t\treturn;\n\t}\n\tif (DUK_UNLIKELY((duk_uidx_t) count > (duk_uidx_t) DUK_USE_VALSTACK_LIMIT)) {\n\t\t/* Maximum value check ensures 'nbytes' won't wrap below.\n\t\t * Also handles negative count.\n\t\t */\n\t\tDUK_ERROR_RANGE_INVALID_COUNT(to_thr);\n\t\treturn;\n\t}\n\tDUK_ASSERT(count >= 0);\n\n\tnbytes = sizeof(duk_tval) * (duk_size_t) count;\n\tif (DUK_UNLIKELY(nbytes == 0)) {\n\t\treturn;\n\t}\n\tDUK_ASSERT(to_thr->valstack_top <= to_thr->valstack_end);\n\tif (DUK_UNLIKELY((duk_size_t) ((duk_uint8_t *) to_thr->valstack_end - (duk_uint8_t *) to_thr->valstack_top) < nbytes)) {\n\t\tDUK_ERROR_RANGE_PUSH_BEYOND(to_thr);\n\t}\n\tsrc = (void *) ((duk_uint8_t *) from_thr->valstack_top - nbytes);\n\tif (DUK_UNLIKELY(src < (void *) from_thr->valstack_bottom)) {\n\t\tDUK_ERROR_RANGE_INVALID_COUNT(to_thr);\n\t}\n\n\t/* copy values (no overlap even if to_thr == from_thr; that's not\n\t * allowed now anyway)\n\t */\n\tDUK_ASSERT(nbytes > 0);\n\tDUK_MEMCPY((void *) to_thr->valstack_top, (const void *) src, (size_t) nbytes);\n\n\tp = to_thr->valstack_top;\n\tto_thr->valstack_top = (duk_tval *) (void *) (((duk_uint8_t *) p) + nbytes);\n\n\tif (is_copy) {\n\t\t/* Incref copies, keep originals. */\n\t\tq = to_thr->valstack_top;\n\t\twhile (p < q) {\n\t\t\tDUK_TVAL_INCREF(to_thr, p);  /* no side effects */\n\t\t\tp++;\n\t\t}\n\t} else {\n\t\t/* No net refcount change. */\n\t\tp = from_thr->valstack_top;\n\t\tq = (duk_tval *) (void *) (((duk_uint8_t *) p) - nbytes);\n\t\tfrom_thr->valstack_top = q;\n\n\t\twhile (p > q) {\n\t\t\tp--;\n\t\t\tDUK_TVAL_SET_UNDEFINED(p);\n\t\t\t/* XXX: fast primitive to set a bunch of values to UNDEFINED */\n\t\t}\n\t}\n}\n\n/* Internal helper: reserve a gap of 'count' elements at 'idx_base' and return a\n * pointer to the gap.  Values in the gap are garbage and MUST be initialized by\n * the caller before any side effects may occur.  The caller must ensure there's\n * enough stack reserve for 'count' values.\n */\nDUK_INTERNAL duk_tval *duk_reserve_gap(duk_hthread *thr, duk_idx_t idx_base, duk_idx_t count) {\n\tduk_tval *tv_src;\n\tduk_tval *tv_dst;\n\tduk_size_t gap_bytes;\n\tduk_size_t copy_bytes;\n\n\t/* Caller is responsible for ensuring there's enough preallocated\n\t * value stack.\n\t */\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK_ASSERT(count >= 0);\n\tDUK_ASSERT((duk_size_t) (thr->valstack_end - thr->valstack_top) >= (duk_size_t) count);\n\n\ttv_src = thr->valstack_bottom + idx_base;\n\tgap_bytes = (duk_size_t) count * sizeof(duk_tval);\n\ttv_dst = (duk_tval *) (void *) ((duk_uint8_t *) tv_src + gap_bytes);\n\tcopy_bytes = (duk_size_t) ((duk_uint8_t *) thr->valstack_top - (duk_uint8_t *) tv_src);\n\tthr->valstack_top = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack_top + gap_bytes);\n\tDUK_MEMMOVE((void *) tv_dst, (const void *) tv_src, copy_bytes);\n\n\t/* Values in the gap are left as garbage: caller must fill them in\n\t * and INCREF them before any side effects.\n\t */\n\treturn tv_src;\n}\n\n/*\n *  Get/opt/require\n */\n\nDUK_EXTERNAL void duk_require_undefined(duk_hthread *thr, duk_idx_t idx) {\n\tduk_tval *tv;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\ttv = duk_get_tval_or_unused(thr, idx);\n\tDUK_ASSERT(tv != NULL);\n\tif (DUK_UNLIKELY(!DUK_TVAL_IS_UNDEFINED(tv))) {\n\t\tDUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, \"undefined\", DUK_STR_NOT_UNDEFINED);\n\t}\n}\n\nDUK_EXTERNAL void duk_require_null(duk_hthread *thr, duk_idx_t idx) {\n\tduk_tval *tv;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\ttv = duk_get_tval_or_unused(thr, idx);\n\tDUK_ASSERT(tv != NULL);\n\tif (DUK_UNLIKELY(!DUK_TVAL_IS_NULL(tv))) {\n\t\tDUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, \"null\", DUK_STR_NOT_NULL);\n\t}\n}\n\nDUK_LOCAL DUK_ALWAYS_INLINE duk_bool_t duk__get_boolean_raw(duk_hthread *thr, duk_idx_t idx, duk_bool_t def_value) {\n\tduk_bool_t ret;\n\tduk_tval *tv;\n\n\tDUK_ASSERT_CTX_VALID(thr);\n\n\ttv = duk_get_tval_or_unused(thr, idx);\n\tDUK_ASSERT(tv != NULL);\n\tif (DUK_TVAL_IS_BOOLEAN(tv)) {\n\t\tret = DUK_TVAL_GET_BOOLEAN(tv);\n\t\tDUK_ASSERT(ret == 0 || ret == 1);\n\t} else {\n\t\tret = def_value;\n\t\t/* Not guaranteed to be 0 or 1. */\n\t}\n\n\treturn ret;\n}\n\nDUK_EXTERNAL duk_bool_t duk_get_boolean(duk_hthread *thr, duk_idx_t idx) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\treturn duk__get_boolean_raw(thr, idx, 0);  /* default: false */\n}\n\nDUK_EXTERNAL duk_bool_t duk_get_boolean_default(duk_hthread *thr, duk_idx_t idx, duk_bool_t def_value) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\treturn duk__get_boolean_raw(thr, idx, def_value);\n}\n\nDUK_EXTERNAL duk_bool_t duk_require_boolean(duk_hthread *thr, duk_idx_t idx) {\n\tduk_tval *tv;\n\tduk_bool_t ret;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\ttv = duk_get_tval_or_unused(thr, idx);\n\tDUK_ASSERT(tv != NULL);\n\tif (DUK_LIKELY(DUK_TVAL_IS_BOOLEAN(tv))) {\n\t\tret = DUK_TVAL_GET_BOOLEAN(tv);\n\t\tDUK_ASSERT(ret == 0 || ret == 1);\n\t\treturn ret;\n\t} else {\n\t\tDUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, \"boolean\", DUK_STR_NOT_BOOLEAN);\n\t}\n}\n\nDUK_EXTERNAL duk_bool_t duk_opt_boolean(duk_hthread *thr, duk_idx_t idx, duk_bool_t def_value) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tif (duk_check_type_mask(thr, idx, DUK_TYPE_MASK_NONE | DUK_TYPE_MASK_UNDEFINED)) {\n\t\treturn def_value;\n\t}\n\treturn duk_require_boolean(thr, idx);\n}\n\nDUK_LOCAL DUK_ALWAYS_INLINE duk_double_t duk__get_number_raw(duk_hthread *thr, duk_idx_t idx, duk_double_t def_value) {\n\tduk_double_union ret;\n\tduk_tval *tv;\n\n\tDUK_ASSERT_CTX_VALID(thr);\n\n\ttv = duk_get_tval_or_unused(thr, idx);\n\tDUK_ASSERT(tv != NULL);\n#if defined(DUK_USE_FASTINT)\n\tif (DUK_TVAL_IS_FASTINT(tv)) {\n\t\tret.d = (duk_double_t) DUK_TVAL_GET_FASTINT(tv);  /* XXX: cast trick */\n\t}\n\telse\n#endif\n\tif (DUK_TVAL_IS_DOUBLE(tv)) {\n\t\t/* When using packed duk_tval, number must be in NaN-normalized form\n\t\t * for it to be a duk_tval, so no need to normalize.  NOP for unpacked\n\t\t * duk_tval.\n\t\t */\n\t\tret.d = DUK_TVAL_GET_DOUBLE(tv);\n\t\tDUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&ret));\n\t} else {\n\t\tret.d = def_value;\n\t\t/* Default value (including NaN) may not be normalized. */\n\t}\n\n\treturn ret.d;\n}\n\nDUK_EXTERNAL duk_double_t duk_get_number(duk_hthread *thr, duk_idx_t idx) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\treturn duk__get_number_raw(thr, idx, DUK_DOUBLE_NAN);  /* default: NaN */\n}\n\nDUK_EXTERNAL duk_double_t duk_get_number_default(duk_hthread *thr, duk_idx_t idx, duk_double_t def_value) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\treturn duk__get_number_raw(thr, idx, def_value);\n}\n\nDUK_EXTERNAL duk_double_t duk_require_number(duk_hthread *thr, duk_idx_t idx) {\n\tduk_tval *tv;\n\tduk_double_union ret;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\ttv = duk_get_tval_or_unused(thr, idx);\n\tDUK_ASSERT(tv != NULL);\n\tif (DUK_UNLIKELY(!DUK_TVAL_IS_NUMBER(tv))) {\n\t\tDUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, \"number\", DUK_STR_NOT_NUMBER);\n\t}\n\n\tret.d = DUK_TVAL_GET_NUMBER(tv);\n\n\t/* When using packed duk_tval, number must be in NaN-normalized form\n\t * for it to be a duk_tval, so no need to normalize.  NOP for unpacked\n\t * duk_tval.\n\t */\n\tDUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&ret));\n\treturn ret.d;\n}\n\nDUK_EXTERNAL duk_double_t duk_opt_number(duk_hthread *thr, duk_idx_t idx, duk_double_t def_value) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tif (duk_check_type_mask(thr, idx, DUK_TYPE_MASK_NONE | DUK_TYPE_MASK_UNDEFINED)) {\n\t\t/* User provided default is not NaN normalized. */\n\t\treturn def_value;\n\t}\n\treturn duk_require_number(thr, idx);\n}\n\nDUK_EXTERNAL duk_int_t duk_get_int(duk_hthread *thr, duk_idx_t idx) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\treturn (duk_int_t) duk__api_coerce_d2i(thr, idx, 0 /*def_value*/, 0 /*require*/);\n}\n\nDUK_EXTERNAL duk_uint_t duk_get_uint(duk_hthread *thr, duk_idx_t idx) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\treturn (duk_uint_t) duk__api_coerce_d2ui(thr, idx, 0 /*def_value*/, 0 /*require*/);\n}\n\nDUK_EXTERNAL duk_int_t duk_get_int_default(duk_hthread *thr, duk_idx_t idx, duk_int_t def_value) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\treturn (duk_int_t) duk__api_coerce_d2i(thr, idx, def_value, 0 /*require*/);\n}\n\nDUK_EXTERNAL duk_uint_t duk_get_uint_default(duk_hthread *thr, duk_idx_t idx, duk_uint_t def_value) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\treturn (duk_uint_t) duk__api_coerce_d2ui(thr, idx, def_value, 0 /*require*/);\n}\n\nDUK_EXTERNAL duk_int_t duk_require_int(duk_hthread *thr, duk_idx_t idx) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\treturn (duk_int_t) duk__api_coerce_d2i(thr, idx, 0 /*def_value*/, 1 /*require*/);\n}\n\nDUK_EXTERNAL duk_uint_t duk_require_uint(duk_hthread *thr, duk_idx_t idx) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\treturn (duk_uint_t) duk__api_coerce_d2ui(thr, idx, 0 /*def_value*/, 1 /*require*/);\n}\n\nDUK_EXTERNAL duk_int_t duk_opt_int(duk_hthread *thr, duk_idx_t idx, duk_int_t def_value) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tif (duk_check_type_mask(thr, idx, DUK_TYPE_MASK_NONE | DUK_TYPE_MASK_UNDEFINED)) {\n\t\treturn def_value;\n\t}\n\treturn duk_require_int(thr, idx);\n}\n\nDUK_EXTERNAL duk_uint_t duk_opt_uint(duk_hthread *thr, duk_idx_t idx, duk_uint_t def_value) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tif (duk_check_type_mask(thr, idx, DUK_TYPE_MASK_NONE | DUK_TYPE_MASK_UNDEFINED)) {\n\t\treturn def_value;\n\t}\n\treturn duk_require_uint(thr, idx);\n}\n\nDUK_EXTERNAL const char *duk_get_lstring(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_len) {\n\tduk_hstring *h;\n\tconst char *ret;\n\tduk_size_t len;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\th = duk_get_hstring(thr, idx);\n\tif (h != NULL) {\n\t\tlen = DUK_HSTRING_GET_BYTELEN(h);\n\t\tret = (const char *) DUK_HSTRING_GET_DATA(h);\n\t} else {\n\t\tlen = 0;\n\t\tret = NULL;\n\t}\n\n\tif (out_len != NULL) {\n\t\t*out_len = len;\n\t}\n\treturn ret;\n}\n\nDUK_EXTERNAL const char *duk_require_lstring(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_len) {\n\tduk_hstring *h;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\th = duk_require_hstring(thr, idx);\n\tDUK_ASSERT(h != NULL);\n\tif (out_len) {\n\t\t*out_len = DUK_HSTRING_GET_BYTELEN(h);\n\t}\n\treturn (const char *) DUK_HSTRING_GET_DATA(h);\n}\n\nDUK_INTERNAL const char *duk_require_lstring_notsymbol(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_len) {\n\tduk_hstring *h;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\th = duk_require_hstring_notsymbol(thr, idx);\n\tDUK_ASSERT(h != NULL);\n\tif (out_len) {\n\t\t*out_len = DUK_HSTRING_GET_BYTELEN(h);\n\t}\n\treturn (const char *) DUK_HSTRING_GET_DATA(h);\n}\n\nDUK_EXTERNAL const char *duk_get_string(duk_hthread *thr, duk_idx_t idx) {\n\tduk_hstring *h;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\th = duk_get_hstring(thr, idx);\n\tif (h != NULL) {\n\t\treturn (const char *) DUK_HSTRING_GET_DATA(h);\n\t} else {\n\t\treturn NULL;\n\t}\n}\n\nDUK_EXTERNAL const char *duk_opt_lstring(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_len, const char *def_ptr, duk_size_t def_len) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tif (duk_check_type_mask(thr, idx, DUK_TYPE_MASK_NONE | DUK_TYPE_MASK_UNDEFINED)) {\n\t\tif (out_len != NULL) {\n\t\t\t*out_len = def_len;\n\t\t}\n\t\treturn def_ptr;\n\t}\n\treturn duk_require_lstring(thr, idx, out_len);\n}\n\nDUK_EXTERNAL const char *duk_opt_string(duk_hthread *thr, duk_idx_t idx, const char *def_ptr) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tif (duk_check_type_mask(thr, idx, DUK_TYPE_MASK_NONE | DUK_TYPE_MASK_UNDEFINED)) {\n\t\treturn def_ptr;\n\t}\n\treturn duk_require_string(thr, idx);\n}\n\nDUK_EXTERNAL const char *duk_get_lstring_default(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_len, const char *def_ptr, duk_size_t def_len) {\n\tduk_hstring *h;\n\tconst char *ret;\n\tduk_size_t len;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\th = duk_get_hstring(thr, idx);\n\tif (h != NULL) {\n\t\tlen = DUK_HSTRING_GET_BYTELEN(h);\n\t\tret = (const char *) DUK_HSTRING_GET_DATA(h);\n\t} else {\n\t\tlen = def_len;\n\t\tret = def_ptr;\n\t}\n\n\tif (out_len != NULL) {\n\t\t*out_len = len;\n\t}\n\treturn ret;\n}\n\nDUK_EXTERNAL const char *duk_get_string_default(duk_hthread *thr, duk_idx_t idx, const char *def_value) {\n\tduk_hstring *h;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\th = duk_get_hstring(thr, idx);\n\tif (h != NULL) {\n\t\treturn (const char *) DUK_HSTRING_GET_DATA(h);\n\t} else {\n\t\treturn def_value;\n\t}\n}\n\nDUK_INTERNAL const char *duk_get_string_notsymbol(duk_hthread *thr, duk_idx_t idx) {\n\tduk_hstring *h;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\th = duk_get_hstring_notsymbol(thr, idx);\n\tif (h) {\n\t\treturn (const char *) DUK_HSTRING_GET_DATA(h);\n\t} else {\n\t\treturn NULL;\n\t}\n}\n\nDUK_EXTERNAL const char *duk_require_string(duk_hthread *thr, duk_idx_t idx) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\treturn duk_require_lstring(thr, idx, NULL);\n}\n\nDUK_INTERNAL const char *duk_require_string_notsymbol(duk_hthread *thr, duk_idx_t idx) {\n\tduk_hstring *h;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\th = duk_require_hstring_notsymbol(thr, idx);\n\tDUK_ASSERT(h != NULL);\n\treturn (const char *) DUK_HSTRING_GET_DATA(h);\n}\n\nDUK_EXTERNAL void duk_require_object(duk_hthread *thr, duk_idx_t idx) {\n\tduk_tval *tv;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\ttv = duk_get_tval_or_unused(thr, idx);\n\tDUK_ASSERT(tv != NULL);\n\tif (DUK_UNLIKELY(!DUK_TVAL_IS_OBJECT(tv))) {\n\t\tDUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, \"object\", DUK_STR_NOT_OBJECT);\n\t}\n}\n\nDUK_LOCAL void *duk__get_pointer_raw(duk_hthread *thr, duk_idx_t idx, void *def_value) {\n\tduk_tval *tv;\n\tvoid *p;\n\n\tDUK_ASSERT_CTX_VALID(thr);\n\n\ttv = duk_get_tval_or_unused(thr, idx);\n\tDUK_ASSERT(tv != NULL);\n\tif (!DUK_TVAL_IS_POINTER(tv)) {\n\t\treturn def_value;\n\t}\n\n\tp = DUK_TVAL_GET_POINTER(tv);  /* may be NULL */\n\treturn p;\n}\n\nDUK_EXTERNAL void *duk_get_pointer(duk_hthread *thr, duk_idx_t idx) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\treturn duk__get_pointer_raw(thr, idx, NULL /*def_value*/);\n}\n\nDUK_EXTERNAL void *duk_opt_pointer(duk_hthread *thr, duk_idx_t idx, void *def_value) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tif (duk_check_type_mask(thr, idx, DUK_TYPE_MASK_NONE | DUK_TYPE_MASK_UNDEFINED)) {\n\t\treturn def_value;\n\t}\n\treturn duk_require_pointer(thr, idx);\n}\n\nDUK_EXTERNAL void *duk_get_pointer_default(duk_hthread *thr, duk_idx_t idx, void *def_value) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\treturn duk__get_pointer_raw(thr, idx, def_value);\n}\n\nDUK_EXTERNAL void *duk_require_pointer(duk_hthread *thr, duk_idx_t idx) {\n\tduk_tval *tv;\n\tvoid *p;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\t/* Note: here we must be wary of the fact that a pointer may be\n\t * valid and be a NULL.\n\t */\n\ttv = duk_get_tval_or_unused(thr, idx);\n\tDUK_ASSERT(tv != NULL);\n\tif (DUK_UNLIKELY(!DUK_TVAL_IS_POINTER(tv))) {\n\t\tDUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, \"pointer\", DUK_STR_NOT_POINTER);\n\t}\n\tp = DUK_TVAL_GET_POINTER(tv);  /* may be NULL */\n\treturn p;\n}\n\n#if 0  /*unused*/\nDUK_INTERNAL void *duk_get_voidptr(duk_hthread *thr, duk_idx_t idx) {\n\tduk_tval *tv;\n\tduk_heaphdr *h;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\ttv = duk_get_tval_or_unused(thr, idx);\n\tDUK_ASSERT(tv != NULL);\n\tif (!DUK_TVAL_IS_HEAP_ALLOCATED(tv)) {\n\t\treturn NULL;\n\t}\n\n\th = DUK_TVAL_GET_HEAPHDR(tv);\n\tDUK_ASSERT(h != NULL);\n\treturn (void *) h;\n}\n#endif\n\nDUK_LOCAL void *duk__get_buffer_helper(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_size, void *def_ptr, duk_size_t def_size, duk_bool_t throw_flag) {\n\tduk_hbuffer *h;\n\tvoid *ret;\n\tduk_size_t len;\n\tduk_tval *tv;\n\n\tDUK_ASSERT_CTX_VALID(thr);\n\n\tif (out_size != NULL) {\n\t\t*out_size = 0;\n\t}\n\n\ttv = duk_get_tval_or_unused(thr, idx);\n\tDUK_ASSERT(tv != NULL);\n\tif (DUK_LIKELY(DUK_TVAL_IS_BUFFER(tv))) {\n\t\th = DUK_TVAL_GET_BUFFER(tv);\n\t\tDUK_ASSERT(h != NULL);\n\n\t\tlen = DUK_HBUFFER_GET_SIZE(h);\n\t\tret = DUK_HBUFFER_GET_DATA_PTR(thr->heap, h);\n\t} else {\n\t\tif (throw_flag) {\n\t\t\tDUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, \"buffer\", DUK_STR_NOT_BUFFER);\n\t\t}\n\t\tlen = def_size;\n\t\tret = def_ptr;\n\t}\n\n\tif (out_size != NULL) {\n\t\t*out_size = len;\n\t}\n\treturn ret;\n}\n\nDUK_EXTERNAL void *duk_get_buffer(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_size) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\treturn duk__get_buffer_helper(thr, idx, out_size, NULL /*def_ptr*/, 0 /*def_size*/, 0 /*throw_flag*/);\n}\n\nDUK_EXTERNAL void *duk_opt_buffer(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_size, void *def_ptr, duk_size_t def_size) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tif (duk_check_type_mask(thr, idx, DUK_TYPE_MASK_NONE | DUK_TYPE_MASK_UNDEFINED)) {\n\t\tif (out_size != NULL) {\n\t\t\t*out_size = def_size;\n\t\t}\n\t\treturn def_ptr;\n\t}\n\treturn duk_require_buffer(thr, idx, out_size);\n}\n\nDUK_EXTERNAL void *duk_get_buffer_default(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_size, void *def_ptr, duk_size_t def_len) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\treturn duk__get_buffer_helper(thr, idx, out_size, def_ptr, def_len, 0 /*throw_flag*/);\n}\n\nDUK_EXTERNAL void *duk_require_buffer(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_size) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\treturn duk__get_buffer_helper(thr, idx, out_size, NULL /*def_ptr*/, 0 /*def_size*/, 1 /*throw_flag*/);\n}\n\n/* Get the active buffer data area for a plain buffer or a buffer object.\n * Return NULL if the the value is not a buffer.  Note that a buffer may\n * have a NULL data pointer when its size is zero, the optional 'out_isbuffer'\n * argument allows caller to detect this reliably.\n */\nDUK_INTERNAL void *duk_get_buffer_data_raw(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_size, void *def_ptr, duk_size_t def_size, duk_bool_t throw_flag, duk_bool_t *out_isbuffer) {\n\tduk_tval *tv;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tif (out_isbuffer != NULL) {\n\t\t*out_isbuffer = 0;\n\t}\n\tif (out_size != NULL) {\n\t\t*out_size = def_size;\n\t}\n\n\ttv = duk_get_tval_or_unused(thr, idx);\n\tDUK_ASSERT(tv != NULL);\n\n\tif (DUK_TVAL_IS_BUFFER(tv)) {\n\t\tduk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv);\n\t\tDUK_ASSERT(h != NULL);\n\t\tif (out_size != NULL) {\n\t\t\t*out_size = DUK_HBUFFER_GET_SIZE(h);\n\t\t}\n\t\tif (out_isbuffer != NULL) {\n\t\t\t*out_isbuffer = 1;\n\t\t}\n\t\treturn (void *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h);  /* may be NULL (but only if size is 0) */\n\t}\n#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)\n\telse if (DUK_TVAL_IS_OBJECT(tv)) {\n\t\tduk_hobject *h = DUK_TVAL_GET_OBJECT(tv);\n\t\tDUK_ASSERT(h != NULL);\n\t\tif (DUK_HOBJECT_IS_BUFOBJ(h)) {\n\t\t\t/* XXX: this is probably a useful shared helper: for a\n\t\t\t * duk_hbufobj, get a validated buffer pointer/length.\n\t\t\t */\n\t\t\tduk_hbufobj *h_bufobj = (duk_hbufobj *) h;\n\t\t\tDUK_ASSERT_HBUFOBJ_VALID(h_bufobj);\n\n\t\t\tif (h_bufobj->buf != NULL &&\n\t\t\t    DUK_HBUFOBJ_VALID_SLICE(h_bufobj)) {\n\t\t\t\tduk_uint8_t *p;\n\n\t\t\t\tp = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufobj->buf);\n\t\t\t\tif (out_size != NULL) {\n\t\t\t\t\t*out_size = (duk_size_t) h_bufobj->length;\n\t\t\t\t}\n\t\t\t\tif (out_isbuffer != NULL) {\n\t\t\t\t\t*out_isbuffer = 1;\n\t\t\t\t}\n\t\t\t\treturn (void *) (p + h_bufobj->offset);\n\t\t\t}\n\t\t\t/* if slice not fully valid, treat as error */\n\t\t}\n\t}\n#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */\n\n\tif (throw_flag) {\n\t\tDUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, \"buffer\", DUK_STR_NOT_BUFFER);\n\t}\n\treturn def_ptr;\n}\n\nDUK_EXTERNAL void *duk_get_buffer_data(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_size) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\treturn duk_get_buffer_data_raw(thr, idx, out_size, NULL /*def_ptr*/, 0 /*def_size*/, 0 /*throw_flag*/, NULL);\n}\n\nDUK_EXTERNAL void *duk_get_buffer_data_default(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_size, void *def_ptr, duk_size_t def_size) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\treturn duk_get_buffer_data_raw(thr, idx, out_size, def_ptr, def_size, 0 /*throw_flag*/, NULL);\n}\n\nDUK_EXTERNAL void *duk_opt_buffer_data(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_size, void *def_ptr, duk_size_t def_size) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tif (duk_check_type_mask(thr, idx, DUK_TYPE_MASK_NONE | DUK_TYPE_MASK_UNDEFINED)) {\n\t\tif (out_size != NULL) {\n\t\t\t*out_size = def_size;\n\t\t}\n\t\treturn def_ptr;\n\t}\n\treturn duk_require_buffer_data(thr, idx, out_size);\n}\n\nDUK_EXTERNAL void *duk_require_buffer_data(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_size) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\treturn duk_get_buffer_data_raw(thr, idx, out_size, NULL /*def_ptr*/, 0 /*def_size*/, 1 /*throw_flag*/, NULL);\n}\n\n/* Raw helper for getting a value from the stack, checking its tag.\n * The tag cannot be a number because numbers don't have an internal\n * tag in the packed representation.\n */\n\nDUK_LOCAL duk_heaphdr *duk__get_tagged_heaphdr_raw(duk_hthread *thr, duk_idx_t idx, duk_uint_t tag) {\n\tduk_tval *tv;\n\tduk_heaphdr *ret;\n\n\tDUK_ASSERT_CTX_VALID(thr);\n\n\ttv = duk_get_tval_or_unused(thr, idx);\n\tDUK_ASSERT(tv != NULL);\n\tif (DUK_TVAL_GET_TAG(tv) != tag) {\n\t\treturn (duk_heaphdr *) NULL;\n\t}\n\n\tret = DUK_TVAL_GET_HEAPHDR(tv);\n\tDUK_ASSERT(ret != NULL);  /* tagged null pointers should never occur */\n\treturn ret;\n\n}\n\nDUK_INTERNAL duk_hstring *duk_get_hstring(duk_hthread *thr, duk_idx_t idx) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\treturn (duk_hstring *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_STRING);\n}\n\nDUK_INTERNAL duk_hstring *duk_get_hstring_notsymbol(duk_hthread *thr, duk_idx_t idx) {\n\tduk_hstring *h;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\th = (duk_hstring *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_STRING);\n\tif (DUK_UNLIKELY(h && DUK_HSTRING_HAS_SYMBOL(h))) {\n\t\treturn NULL;\n\t}\n\treturn h;\n}\n\nDUK_INTERNAL duk_hstring *duk_require_hstring(duk_hthread *thr, duk_idx_t idx) {\n\tduk_hstring *h;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\th = (duk_hstring *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_STRING);\n\tif (DUK_UNLIKELY(h == NULL)) {\n\t\tDUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, \"string\", DUK_STR_NOT_STRING);\n\t}\n\treturn h;\n}\n\nDUK_INTERNAL duk_hstring *duk_require_hstring_notsymbol(duk_hthread *thr, duk_idx_t idx) {\n\tduk_hstring *h;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\th = (duk_hstring *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_STRING);\n\tif (DUK_UNLIKELY(h == NULL || DUK_HSTRING_HAS_SYMBOL(h))) {\n\t\tDUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, \"string\", DUK_STR_NOT_STRING);\n\t}\n\treturn h;\n}\n\nDUK_INTERNAL duk_hobject *duk_get_hobject(duk_hthread *thr, duk_idx_t idx) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\treturn (duk_hobject *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_OBJECT);\n}\n\nDUK_INTERNAL duk_hobject *duk_require_hobject(duk_hthread *thr, duk_idx_t idx) {\n\tduk_hobject *h;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\th = (duk_hobject *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_OBJECT);\n\tif (DUK_UNLIKELY(h == NULL)) {\n\t\tDUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, \"object\", DUK_STR_NOT_OBJECT);\n\t}\n\treturn h;\n}\n\nDUK_INTERNAL duk_hbuffer *duk_get_hbuffer(duk_hthread *thr, duk_idx_t idx) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\treturn (duk_hbuffer *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_BUFFER);\n}\n\nDUK_INTERNAL duk_hbuffer *duk_require_hbuffer(duk_hthread *thr, duk_idx_t idx) {\n\tduk_hbuffer *h;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\th = (duk_hbuffer *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_BUFFER);\n\tif (DUK_UNLIKELY(h == NULL)) {\n\t\tDUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, \"buffer\", DUK_STR_NOT_BUFFER);\n\t}\n\treturn h;\n}\n\nDUK_INTERNAL duk_hthread *duk_get_hthread(duk_hthread *thr, duk_idx_t idx) {\n\tduk_hobject *h;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\th = (duk_hobject *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_OBJECT);\n\tif (DUK_UNLIKELY(h != NULL && !DUK_HOBJECT_IS_THREAD(h))) {\n\t\th = NULL;\n\t}\n\treturn (duk_hthread *) h;\n}\n\nDUK_INTERNAL duk_hthread *duk_require_hthread(duk_hthread *thr, duk_idx_t idx) {\n\tduk_hobject *h;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\th = (duk_hobject *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_OBJECT);\n\tif (DUK_UNLIKELY(!(h != NULL && DUK_HOBJECT_IS_THREAD(h)))) {\n\t\tDUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, \"thread\", DUK_STR_NOT_THREAD);\n\t}\n\treturn (duk_hthread *) h;\n}\n\nDUK_INTERNAL duk_hcompfunc *duk_get_hcompfunc(duk_hthread *thr, duk_idx_t idx) {\n\tduk_hobject *h;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\th = (duk_hobject *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_OBJECT);\n\tif (DUK_UNLIKELY(h != NULL && !DUK_HOBJECT_IS_COMPFUNC(h))) {\n\t\th = NULL;\n\t}\n\treturn (duk_hcompfunc *) h;\n}\n\nDUK_INTERNAL duk_hcompfunc *duk_require_hcompfunc(duk_hthread *thr, duk_idx_t idx) {\n\tduk_hobject *h;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\th = (duk_hobject *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_OBJECT);\n\tif (DUK_UNLIKELY(!(h != NULL && DUK_HOBJECT_IS_COMPFUNC(h)))) {\n\t\tDUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, \"compiledfunction\", DUK_STR_NOT_COMPFUNC);\n\t}\n\treturn (duk_hcompfunc *) h;\n}\n\nDUK_INTERNAL duk_hnatfunc *duk_get_hnatfunc(duk_hthread *thr, duk_idx_t idx) {\n\tduk_hobject *h;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\th = (duk_hobject *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_OBJECT);\n\tif (DUK_UNLIKELY(h != NULL && !DUK_HOBJECT_IS_NATFUNC(h))) {\n\t\th = NULL;\n\t}\n\treturn (duk_hnatfunc *) h;\n}\n\nDUK_INTERNAL duk_hnatfunc *duk_require_hnatfunc(duk_hthread *thr, duk_idx_t idx) {\n\tduk_hobject *h;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\th = (duk_hobject *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_OBJECT);\n\tif (DUK_UNLIKELY(!(h != NULL && DUK_HOBJECT_IS_NATFUNC(h)))) {\n\t\tDUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, \"nativefunction\", DUK_STR_NOT_NATFUNC);\n\t}\n\treturn (duk_hnatfunc *) h;\n}\n\nDUK_EXTERNAL duk_c_function duk_get_c_function(duk_hthread *thr, duk_idx_t idx) {\n\tduk_tval *tv;\n\tduk_hobject *h;\n\tduk_hnatfunc *f;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\ttv = duk_get_tval_or_unused(thr, idx);\n\tDUK_ASSERT(tv != NULL);\n\tif (DUK_UNLIKELY(!DUK_TVAL_IS_OBJECT(tv))) {\n\t\treturn NULL;\n\t}\n\th = DUK_TVAL_GET_OBJECT(tv);\n\tDUK_ASSERT(h != NULL);\n\n\tif (DUK_UNLIKELY(!DUK_HOBJECT_IS_NATFUNC(h))) {\n\t\treturn NULL;\n\t}\n\tDUK_ASSERT(DUK_HOBJECT_HAS_NATFUNC(h));\n\tf = (duk_hnatfunc *) h;\n\n\treturn f->func;\n}\n\nDUK_EXTERNAL duk_c_function duk_opt_c_function(duk_hthread *thr, duk_idx_t idx, duk_c_function def_value) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tif (duk_check_type_mask(thr, idx, DUK_TYPE_MASK_NONE | DUK_TYPE_MASK_UNDEFINED)) {\n\t\treturn def_value;\n\t}\n\treturn duk_require_c_function(thr, idx);\n}\n\nDUK_EXTERNAL duk_c_function duk_get_c_function_default(duk_hthread *thr, duk_idx_t idx, duk_c_function def_value) {\n\tduk_c_function ret;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tret = duk_get_c_function(thr, idx);\n\tif (ret != NULL) {\n\t\treturn ret;\n\t}\n\n\treturn def_value;\n}\n\nDUK_EXTERNAL duk_c_function duk_require_c_function(duk_hthread *thr, duk_idx_t idx) {\n\tduk_c_function ret;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tret = duk_get_c_function(thr, idx);\n\tif (DUK_UNLIKELY(!ret)) {\n\t\tDUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, \"nativefunction\", DUK_STR_NOT_NATFUNC);\n\t}\n\treturn ret;\n}\n\nDUK_EXTERNAL void duk_require_function(duk_hthread *thr, duk_idx_t idx) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\tif (DUK_UNLIKELY(!duk_is_function(thr, idx))) {\n\t\tDUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, \"function\", DUK_STR_NOT_FUNCTION);\n\t}\n}\n\nDUK_INTERNAL void duk_require_constructable(duk_hthread *thr, duk_idx_t idx) {\n\tduk_hobject *h;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\th = duk_require_hobject_accept_mask(thr, idx, DUK_TYPE_MASK_LIGHTFUNC);\n\tif (DUK_UNLIKELY(h != NULL && !DUK_HOBJECT_HAS_CONSTRUCTABLE(h))) {\n\t\tDUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, \"constructable\", DUK_STR_NOT_CONSTRUCTABLE);\n\t}\n\t/* Lightfuncs (h == NULL) are constructable. */\n}\n\nDUK_EXTERNAL duk_hthread *duk_get_context(duk_hthread *thr, duk_idx_t idx) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\treturn duk_get_hthread(thr, idx);\n}\n\nDUK_EXTERNAL duk_hthread *duk_require_context(duk_hthread *thr, duk_idx_t idx) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\treturn duk_require_hthread(thr, idx);\n}\n\nDUK_EXTERNAL duk_hthread *duk_opt_context(duk_hthread *thr, duk_idx_t idx, duk_hthread *def_value) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tif (duk_check_type_mask(thr, idx, DUK_TYPE_MASK_NONE | DUK_TYPE_MASK_UNDEFINED)) {\n\t\treturn def_value;\n\t}\n\treturn duk_require_context(thr, idx);\n}\n\nDUK_EXTERNAL duk_hthread *duk_get_context_default(duk_hthread *thr, duk_idx_t idx, duk_hthread *def_value) {\n\tduk_hthread *ret;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tret = duk_get_context(thr, idx);\n\tif (ret != NULL) {\n\t\treturn ret;\n\t}\n\n\treturn def_value;\n}\n\nDUK_EXTERNAL void *duk_get_heapptr(duk_hthread *thr, duk_idx_t idx) {\n\tduk_tval *tv;\n\tvoid *ret;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\ttv = duk_get_tval_or_unused(thr, idx);\n\tDUK_ASSERT(tv != NULL);\n\tif (DUK_UNLIKELY(!DUK_TVAL_IS_HEAP_ALLOCATED(tv))) {\n\t\treturn (void *) NULL;\n\t}\n\n\tret = (void *) DUK_TVAL_GET_HEAPHDR(tv);\n\tDUK_ASSERT(ret != NULL);\n\treturn ret;\n}\n\nDUK_EXTERNAL void *duk_opt_heapptr(duk_hthread *thr, duk_idx_t idx, void *def_value) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tif (duk_check_type_mask(thr, idx, DUK_TYPE_MASK_NONE | DUK_TYPE_MASK_UNDEFINED)) {\n\t\treturn def_value;\n\t}\n\treturn duk_require_heapptr(thr, idx);\n}\n\nDUK_EXTERNAL void *duk_get_heapptr_default(duk_hthread *thr, duk_idx_t idx, void *def_value) {\n\tvoid *ret;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tret = duk_get_heapptr(thr, idx);\n\tif (ret != NULL) {\n\t\treturn ret;\n\t}\n\n\treturn def_value;\n}\n\nDUK_EXTERNAL void *duk_require_heapptr(duk_hthread *thr, duk_idx_t idx) {\n\tduk_tval *tv;\n\tvoid *ret;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\ttv = duk_get_tval_or_unused(thr, idx);\n\tDUK_ASSERT(tv != NULL);\n\tif (DUK_UNLIKELY(!DUK_TVAL_IS_HEAP_ALLOCATED(tv))) {\n\t\tDUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, \"heapobject\", DUK_STR_UNEXPECTED_TYPE);\n\t}\n\n\tret = (void *) DUK_TVAL_GET_HEAPHDR(tv);\n\tDUK_ASSERT(ret != NULL);\n\treturn ret;\n}\n\n/* Internal helper for getting/requiring a duk_hobject with possible promotion. */\nDUK_LOCAL duk_hobject *duk__get_hobject_promote_mask_raw(duk_hthread *thr, duk_idx_t idx, duk_uint_t type_mask) {\n\tduk_uint_t val_mask;\n\tduk_hobject *res;\n\n\tDUK_ASSERT_CTX_VALID(thr);\n\n\tres = duk_get_hobject(thr, idx);  /* common case, not promoted */\n\tif (DUK_LIKELY(res != NULL)) {\n\t\tDUK_ASSERT(res != NULL);\n\t\treturn res;\n\t}\n\n\tval_mask = duk_get_type_mask(thr, idx);\n\tif (val_mask & type_mask) {\n\t\tif (type_mask & DUK_TYPE_MASK_PROMOTE) {\n\t\t\tres = duk_to_hobject(thr, idx);\n\t\t\tDUK_ASSERT(res != NULL);\n\t\t\treturn res;\n\t\t} else {\n\t\t\treturn NULL;  /* accept without promoting */\n\t\t}\n\t}\n\n\tif (type_mask & DUK_TYPE_MASK_THROW) {\n\t\tDUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, \"object\", DUK_STR_NOT_OBJECT);\n\t}\n\treturn NULL;\n}\n\n/* Get a duk_hobject * at 'idx'; if the value is not an object but matches the\n * supplied 'type_mask', promote it to an object and return the duk_hobject *.\n * This is useful for call sites which want an object but also accept a plain\n * buffer and/or a lightfunc which gets automatically promoted to an object.\n * Return value is NULL if value is neither an object nor a plain type allowed\n * by the mask.\n */\nDUK_INTERNAL duk_hobject *duk_get_hobject_promote_mask(duk_hthread *thr, duk_idx_t idx, duk_uint_t type_mask) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\treturn duk__get_hobject_promote_mask_raw(thr, idx, type_mask | DUK_TYPE_MASK_PROMOTE);\n}\n\n/* Like duk_get_hobject_promote_mask() but throw a TypeError instead of\n * returning a NULL.\n */\nDUK_INTERNAL duk_hobject *duk_require_hobject_promote_mask(duk_hthread *thr, duk_idx_t idx, duk_uint_t type_mask) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\treturn duk__get_hobject_promote_mask_raw(thr, idx, type_mask | DUK_TYPE_MASK_THROW | DUK_TYPE_MASK_PROMOTE);\n}\n\n/* Require a duk_hobject * at 'idx'; if the value is not an object but matches the\n * supplied 'type_mask', return a NULL instead.  Otherwise throw a TypeError.\n */\nDUK_INTERNAL duk_hobject *duk_require_hobject_accept_mask(duk_hthread *thr, duk_idx_t idx, duk_uint_t type_mask) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\treturn duk__get_hobject_promote_mask_raw(thr, idx, type_mask | DUK_TYPE_MASK_THROW);\n}\n\nDUK_INTERNAL duk_hobject *duk_get_hobject_with_class(duk_hthread *thr, duk_idx_t idx, duk_small_uint_t classnum) {\n\tduk_hobject *h;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK_ASSERT_DISABLE(classnum >= 0);  /* unsigned */\n\tDUK_ASSERT(classnum <= DUK_HOBJECT_CLASS_MAX);\n\n\th = (duk_hobject *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_OBJECT);\n\tif (DUK_UNLIKELY(h != NULL && DUK_HOBJECT_GET_CLASS_NUMBER(h) != classnum)) {\n\t\th = NULL;\n\t}\n\treturn h;\n}\n\nDUK_INTERNAL duk_hobject *duk_require_hobject_with_class(duk_hthread *thr, duk_idx_t idx, duk_small_uint_t classnum) {\n\tduk_hobject *h;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK_ASSERT_DISABLE(classnum >= 0);  /* unsigned */\n\tDUK_ASSERT(classnum <= DUK_HOBJECT_CLASS_MAX);\n\n\th = (duk_hobject *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_OBJECT);\n\tif (DUK_UNLIKELY(!(h != NULL && DUK_HOBJECT_GET_CLASS_NUMBER(h) == classnum))) {\n\t\tduk_hstring *h_class;\n\t\th_class = DUK_HTHREAD_GET_STRING(thr, DUK_HOBJECT_CLASS_NUMBER_TO_STRIDX(classnum));\n\t\tDUK_UNREF(h_class);\n\n\t\tDUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, (const char *) DUK_HSTRING_GET_DATA(h_class), DUK_STR_UNEXPECTED_TYPE);\n\t}\n\treturn h;\n}\n\nDUK_EXTERNAL duk_size_t duk_get_length(duk_hthread *thr, duk_idx_t idx) {\n\tduk_tval *tv;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\ttv = duk_get_tval_or_unused(thr, idx);\n\tDUK_ASSERT(tv != NULL);\n\n\tswitch (DUK_TVAL_GET_TAG(tv)) {\n\tcase DUK_TAG_UNDEFINED:\n\tcase DUK_TAG_NULL:\n\tcase DUK_TAG_BOOLEAN:\n\tcase DUK_TAG_POINTER:\n\t\treturn 0;\n#if defined(DUK_USE_PREFER_SIZE)\n\t/* String and buffer have a virtual non-configurable .length property\n\t * which is within size_t range so it can be looked up without specific\n\t * type checks.  Lightfuncs inherit from %NativeFunctionPrototype%\n\t * which provides an inherited .length accessor; it could be overwritten\n\t * to produce unexpected types or values, but just number convert and\n\t * duk_size_t cast for now.\n\t */\n\tcase DUK_TAG_STRING:\n\tcase DUK_TAG_BUFFER:\n\tcase DUK_TAG_LIGHTFUNC: {\n\t\tduk_size_t ret;\n\t\tduk_get_prop_stridx(thr, idx, DUK_STRIDX_LENGTH);\n\t\tret = (duk_size_t) duk_to_number_m1(thr);\n\t\tduk_pop_unsafe(thr);\n\t\treturn ret;\n\t}\n#else  /* DUK_USE_PREFER_SIZE */\n\tcase DUK_TAG_STRING: {\n\t\tduk_hstring *h = DUK_TVAL_GET_STRING(tv);\n\t\tDUK_ASSERT(h != NULL);\n\t\tif (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(h))) {\n\t\t\treturn 0;\n\t\t}\n\t\treturn (duk_size_t) DUK_HSTRING_GET_CHARLEN(h);\n\t}\n\tcase DUK_TAG_BUFFER: {\n\t\tduk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv);\n\t\tDUK_ASSERT(h != NULL);\n\t\treturn (duk_size_t) DUK_HBUFFER_GET_SIZE(h);\n\t}\n\tcase DUK_TAG_LIGHTFUNC: {\n\t\t/* We could look up the length from the lightfunc duk_tval,\n\t\t * but since Duktape 2.2 lightfunc .length comes from\n\t\t * %NativeFunctionPrototype% which can be overridden, so\n\t\t * look up the property explicitly.\n\t\t */\n\t\tduk_size_t ret;\n\t\tduk_get_prop_stridx(thr, idx, DUK_STRIDX_LENGTH);\n\t\tret = (duk_size_t) duk_to_number_m1(thr);\n\t\tduk_pop_unsafe(thr);\n\t\treturn ret;\n\t}\n#endif  /* DUK_USE_PREFER_SIZE */\n\tcase DUK_TAG_OBJECT: {\n\t\tduk_hobject *h = DUK_TVAL_GET_OBJECT(tv);\n\t\tDUK_ASSERT(h != NULL);\n\t\treturn (duk_size_t) duk_hobject_get_length(thr, h);\n\t}\n#if defined(DUK_USE_FASTINT)\n\tcase DUK_TAG_FASTINT:\n#endif\n\tdefault:\n\t\t/* number or 'unused' */\n\t\tDUK_ASSERT(DUK_TVAL_IS_NUMBER(tv) || DUK_TVAL_IS_UNUSED(tv));\n\t\treturn 0;\n\t}\n\n\tDUK_UNREACHABLE();\n}\n\n/*\n *  duk_known_xxx() helpers\n *\n *  Used internally when we're 100% sure that a certain index is valid and\n *  contains an object of a certain type.  For example, if we duk_push_object()\n *  we can then safely duk_known_hobject(thr, -1).  These helpers just assert\n *  for the index and type, and if the assumptions are not valid, memory unsafe\n *  behavior happens.\n */\n\nDUK_LOCAL duk_heaphdr *duk__known_heaphdr(duk_hthread *thr, duk_idx_t idx) {\n\tduk_tval *tv;\n\tduk_heaphdr *h;\n\n\tDUK_ASSERT_CTX_VALID(thr);\n\tif (idx < 0) {\n\t\ttv = thr->valstack_top + idx;\n\t} else {\n\t\ttv = thr->valstack_bottom + idx;\n\t}\n\tDUK_ASSERT(tv >= thr->valstack_bottom);\n\tDUK_ASSERT(tv < thr->valstack_top);\n\th = DUK_TVAL_GET_HEAPHDR(tv);\n\tDUK_ASSERT(h != NULL);\n\treturn h;\n}\n\nDUK_INTERNAL duk_hstring *duk_known_hstring(duk_hthread *thr, duk_idx_t idx) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK_ASSERT(duk_get_hstring(thr, idx) != NULL);\n\treturn (duk_hstring *) duk__known_heaphdr(thr, idx);\n}\n\nDUK_INTERNAL duk_hobject *duk_known_hobject(duk_hthread *thr, duk_idx_t idx) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK_ASSERT(duk_get_hobject(thr, idx) != NULL);\n\treturn (duk_hobject *) duk__known_heaphdr(thr, idx);\n}\n\nDUK_INTERNAL duk_hbuffer *duk_known_hbuffer(duk_hthread *thr, duk_idx_t idx) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK_ASSERT(duk_get_hbuffer(thr, idx) != NULL);\n\treturn (duk_hbuffer *) duk__known_heaphdr(thr, idx);\n}\n\nDUK_INTERNAL duk_hcompfunc *duk_known_hcompfunc(duk_hthread *thr, duk_idx_t idx) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK_ASSERT(duk_get_hcompfunc(thr, idx) != NULL);\n\treturn (duk_hcompfunc *) duk__known_heaphdr(thr, idx);\n}\n\nDUK_INTERNAL duk_hnatfunc *duk_known_hnatfunc(duk_hthread *thr, duk_idx_t idx) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK_ASSERT(duk_get_hnatfunc(thr, idx) != NULL);\n\treturn (duk_hnatfunc *) duk__known_heaphdr(thr, idx);\n}\n\nDUK_EXTERNAL void duk_set_length(duk_hthread *thr, duk_idx_t idx, duk_size_t len) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tidx = duk_normalize_index(thr, idx);\n\tduk_push_uint(thr, (duk_uint_t) len);\n\tduk_put_prop_stridx(thr, idx, DUK_STRIDX_LENGTH);\n}\n\n/*\n *  Conversions and coercions\n *\n *  The conversion/coercions are in-place operations on the value stack.\n *  Some operations are implemented here directly, while others call a\n *  helper in duk_js_ops.c after validating arguments.\n */\n\n/* E5 Section 8.12.8 */\n\nDUK_LOCAL duk_bool_t duk__defaultvalue_coerce_attempt(duk_hthread *thr, duk_idx_t idx, duk_small_uint_t func_stridx) {\n\tif (duk_get_prop_stridx(thr, idx, func_stridx)) {\n\t\t/* [ ... func ] */\n\t\tif (duk_is_callable(thr, -1)) {\n\t\t\tduk_dup(thr, idx);         /* -> [ ... func this ] */\n\t\t\tduk_call_method(thr, 0);     /* -> [ ... retval ] */\n\t\t\tif (duk_is_primitive(thr, -1)) {\n\t\t\t\tduk_replace(thr, idx);\n\t\t\t\treturn 1;\n\t\t\t}\n\t\t\t/* [ ... retval ]; popped below */\n\t\t}\n\t}\n\tduk_pop_unsafe(thr);  /* [ ... func/retval ] -> [ ... ] */\n\treturn 0;\n}\n\nDUK_EXTERNAL void duk_to_undefined(duk_hthread *thr, duk_idx_t idx) {\n\tduk_tval *tv;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\ttv = duk_require_tval(thr, idx);\n\tDUK_ASSERT(tv != NULL);\n\tDUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv);  /* side effects */\n}\n\nDUK_EXTERNAL void duk_to_null(duk_hthread *thr, duk_idx_t idx) {\n\tduk_tval *tv;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\ttv = duk_require_tval(thr, idx);\n\tDUK_ASSERT(tv != NULL);\n\tDUK_TVAL_SET_NULL_UPDREF(thr, tv);  /* side effects */\n}\n\n/* E5 Section 9.1 */\nDUK_EXTERNAL void duk_to_primitive(duk_hthread *thr, duk_idx_t idx, duk_int_t hint) {\n\t/* inline initializer for coercers[] is not allowed by old compilers like BCC */\n\tduk_small_uint_t coercers[2];\n\tduk_small_uint_t class_number;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK_ASSERT(hint == DUK_HINT_NONE || hint == DUK_HINT_NUMBER || hint == DUK_HINT_STRING);\n\n\tidx = duk_require_normalize_index(thr, idx);\n\n\tif (!duk_check_type_mask(thr, idx, DUK_TYPE_MASK_OBJECT |\n\t                                   DUK_TYPE_MASK_LIGHTFUNC |\n\t                                   DUK_TYPE_MASK_BUFFER)) {\n\t\t/* Any other values stay as is. */\n\t\tDUK_ASSERT(!duk_is_buffer(thr, idx));  /* duk_to_string() relies on this behavior */\n\t\treturn;\n\t}\n\n\tclass_number = duk_get_class_number(thr, idx);\n\n\t/* XXX: Symbol objects normally coerce via the ES2015-revised ToPrimitive()\n\t * algorithm which consults value[@@toPrimitive] and avoids calling\n\t * .valueOf() and .toString().  Before that is implemented, special\n\t * case Symbol objects to behave as if they had the default @@toPrimitive\n\t * algorithm of E6 Section 19.4.3.4, i.e. return the plain symbol value\n\t * with no further side effects.\n\t */\n\n\tif (class_number == DUK_HOBJECT_CLASS_SYMBOL) {\n\t\tduk_hobject *h_obj;\n\t\tduk_hstring *h_str;\n\n\t\t/* XXX: pretty awkward, index based API for internal value access? */\n\t\th_obj = duk_known_hobject(thr, idx);\n\t\th_str = duk_hobject_get_internal_value_string(thr->heap, h_obj);\n\t\tif (h_str) {\n\t\t\tduk_push_hstring(thr, h_str);\n\t\t\tduk_replace(thr, idx);\n\t\t\treturn;\n\t\t}\n\t}\n\n\n\t/* Objects are coerced based on E5 specification.\n\t * Lightfuncs are coerced because they behave like\n\t * objects even if they're internally a primitive\n\t * type.  Same applies to plain buffers, which behave\n\t * like ArrayBuffer objects since Duktape 2.x.\n\t */\n\n\tcoercers[0] = DUK_STRIDX_VALUE_OF;\n\tcoercers[1] = DUK_STRIDX_TO_STRING;\n\n\tif (hint == DUK_HINT_NONE) {\n\t\tif (class_number == DUK_HOBJECT_CLASS_DATE) {\n\t\t\thint = DUK_HINT_STRING;\n\t\t} else {\n\t\t\thint = DUK_HINT_NUMBER;\n\t\t}\n\t}\n\n\tif (hint == DUK_HINT_STRING) {\n\t\tcoercers[0] = DUK_STRIDX_TO_STRING;\n\t\tcoercers[1] = DUK_STRIDX_VALUE_OF;\n\t}\n\n\tif (duk__defaultvalue_coerce_attempt(thr, idx, coercers[0])) {\n\t\tDUK_ASSERT(!duk_is_buffer(thr, idx));  /* duk_to_string() relies on this behavior */\n\t\treturn;\n\t}\n\n\tif (duk__defaultvalue_coerce_attempt(thr, idx, coercers[1])) {\n\t\tDUK_ASSERT(!duk_is_buffer(thr, idx));  /* duk_to_string() relies on this behavior */\n\t\treturn;\n\t}\n\n\tDUK_ERROR_TYPE(thr, DUK_STR_TOPRIMITIVE_FAILED);\n}\n\n/* E5 Section 9.2 */\nDUK_EXTERNAL duk_bool_t duk_to_boolean(duk_hthread *thr, duk_idx_t idx) {\n\tduk_tval *tv;\n\tduk_bool_t val;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tidx = duk_require_normalize_index(thr, idx);\n\ttv = DUK_GET_TVAL_POSIDX(thr, idx);\n\tDUK_ASSERT(tv != NULL);\n\n\tval = duk_js_toboolean(tv);\n\tDUK_ASSERT(val == 0 || val == 1);\n\n\t/* Note: no need to re-lookup tv, conversion is side effect free. */\n\tDUK_ASSERT(tv != NULL);\n\tDUK_TVAL_SET_BOOLEAN_UPDREF(thr, tv, val);  /* side effects */\n\treturn val;\n}\n\nDUK_EXTERNAL duk_double_t duk_to_number(duk_hthread *thr, duk_idx_t idx) {\n\tduk_tval *tv;\n\tduk_double_t d;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\t/* XXX: No need to normalize; the whole operation could be inlined here to\n\t * avoid 'tv' re-lookup.\n\t */\n\tidx = duk_require_normalize_index(thr, idx);\n\ttv = DUK_GET_TVAL_POSIDX(thr, idx);\n\tDUK_ASSERT(tv != NULL);\n\td = duk_js_tonumber(thr, tv);  /* XXX: fastint coercion? now result will always be a non-fastint */\n\n\t/* ToNumber() may have side effects so must relookup 'tv'. */\n\ttv = DUK_GET_TVAL_POSIDX(thr, idx);\n\tDUK_TVAL_SET_NUMBER_UPDREF(thr, tv, d);  /* side effects */\n\treturn d;\n}\n\nDUK_INTERNAL duk_double_t duk_to_number_m1(duk_hthread *thr) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\treturn duk_to_number(thr, -1);\n}\nDUK_INTERNAL duk_double_t duk_to_number_m2(duk_hthread *thr) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\treturn duk_to_number(thr, -2);\n}\n\nDUK_INTERNAL duk_double_t duk_to_number_tval(duk_hthread *thr, duk_tval *tv) {\n#if defined(DUK_USE_PREFER_SIZE)\n\tduk_double_t res;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tduk_push_tval(thr, tv);\n\tres = duk_to_number_m1(thr);\n\tduk_pop_unsafe(thr);\n\treturn res;\n#else\n\tduk_double_t res;\n\tduk_tval *tv_dst;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK__ASSERT_SPACE();\n\n\ttv_dst = thr->valstack_top++;\n\tDUK_TVAL_SET_TVAL(tv_dst, tv);\n\tDUK_TVAL_INCREF(thr, tv_dst);  /* decref not necessary */\n\tres = duk_to_number_m1(thr);  /* invalidates tv_dst */\n\n\ttv_dst = --thr->valstack_top;\n\tDUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_dst));\n\tDUK_ASSERT(!DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv_dst));  /* plain number */\n\tDUK_TVAL_SET_UNDEFINED(tv_dst);  /* valstack init policy */\n\n\treturn res;\n#endif\n}\n\n/* XXX: combine all the integer conversions: they share everything\n * but the helper function for coercion.\n */\n\ntypedef duk_double_t (*duk__toint_coercer)(duk_hthread *thr, duk_tval *tv);\n\nDUK_LOCAL duk_double_t duk__to_int_uint_helper(duk_hthread *thr, duk_idx_t idx, duk__toint_coercer coerce_func) {\n\tduk_tval *tv;\n\tduk_double_t d;\n\n\tDUK_ASSERT_CTX_VALID(thr);\n\n\ttv = duk_require_tval(thr, idx);\n\tDUK_ASSERT(tv != NULL);\n\n#if defined(DUK_USE_FASTINT)\n\t/* If argument is a fastint, guarantee that it remains one.\n\t * There's no downgrade check for other cases.\n\t */\n\tif (DUK_TVAL_IS_FASTINT(tv)) {\n\t\t/* XXX: Unnecessary conversion back and forth. */\n\t\treturn (duk_double_t) DUK_TVAL_GET_FASTINT(tv);\n\t}\n#endif\n\td = coerce_func(thr, tv);\n\n\t/* XXX: fastint? */\n\n\t/* Relookup in case coerce_func() has side effects, e.g. ends up coercing an object */\n\ttv = duk_require_tval(thr, idx);\n\tDUK_TVAL_SET_NUMBER_UPDREF(thr, tv, d);  /* side effects */\n\treturn d;\n}\n\nDUK_EXTERNAL duk_int_t duk_to_int(duk_hthread *thr, duk_idx_t idx) {\n\t/* Value coercion (in stack): ToInteger(), E5 Section 9.4,\n\t * API return value coercion: custom.\n\t */\n\tDUK_ASSERT_API_ENTRY(thr);\n\t(void) duk__to_int_uint_helper(thr, idx, duk_js_tointeger);\n\treturn (duk_int_t) duk__api_coerce_d2i(thr, idx, 0 /*def_value*/, 0 /*require*/);\n}\n\nDUK_EXTERNAL duk_uint_t duk_to_uint(duk_hthread *thr, duk_idx_t idx) {\n\t/* Value coercion (in stack): ToInteger(), E5 Section 9.4,\n\t * API return value coercion: custom.\n\t */\n\tDUK_ASSERT_API_ENTRY(thr);\n\t(void) duk__to_int_uint_helper(thr, idx, duk_js_tointeger);\n\treturn (duk_uint_t) duk__api_coerce_d2ui(thr, idx, 0 /*def_value*/, 0 /*require*/);\n}\n\nDUK_EXTERNAL duk_int32_t duk_to_int32(duk_hthread *thr, duk_idx_t idx) {\n\tduk_tval *tv;\n\tduk_int32_t ret;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\ttv = duk_require_tval(thr, idx);\n\tDUK_ASSERT(tv != NULL);\n\tret = duk_js_toint32(thr, tv);\n\n\t/* Relookup in case coerce_func() has side effects, e.g. ends up coercing an object */\n\ttv = duk_require_tval(thr, idx);\n\tDUK_TVAL_SET_I32_UPDREF(thr, tv, ret);  /* side effects */\n\treturn ret;\n}\n\nDUK_EXTERNAL duk_uint32_t duk_to_uint32(duk_hthread *thr, duk_idx_t idx) {\n\tduk_tval *tv;\n\tduk_uint32_t ret;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\ttv = duk_require_tval(thr, idx);\n\tDUK_ASSERT(tv != NULL);\n\tret = duk_js_touint32(thr, tv);\n\n\t/* Relookup in case coerce_func() has side effects, e.g. ends up coercing an object */\n\ttv = duk_require_tval(thr, idx);\n\tDUK_TVAL_SET_U32_UPDREF(thr, tv, ret);  /* side effects */\n\treturn ret;\n}\n\nDUK_EXTERNAL duk_uint16_t duk_to_uint16(duk_hthread *thr, duk_idx_t idx) {\n\tduk_tval *tv;\n\tduk_uint16_t ret;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\ttv = duk_require_tval(thr, idx);\n\tDUK_ASSERT(tv != NULL);\n\tret = duk_js_touint16(thr, tv);\n\n\t/* Relookup in case coerce_func() has side effects, e.g. ends up coercing an object */\n\ttv = duk_require_tval(thr, idx);\n\tDUK_TVAL_SET_U32_UPDREF(thr, tv, ret);  /* side effects */\n\treturn ret;\n}\n\n#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)\n/* Special coercion for Uint8ClampedArray. */\nDUK_INTERNAL duk_uint8_t duk_to_uint8clamped(duk_hthread *thr, duk_idx_t idx) {\n\tduk_double_t d;\n\tduk_double_t t;\n\tduk_uint8_t ret;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\t/* XXX: Simplify this algorithm, should be possible to come up with\n\t * a shorter and faster algorithm by inspecting IEEE representation\n\t * directly.\n\t */\n\n\td = duk_to_number(thr, idx);\n\tif (d <= 0.0) {\n\t\treturn 0;\n\t} else if (d >= 255) {\n\t\treturn 255;\n\t} else if (DUK_ISNAN(d)) {\n\t\t/* Avoid NaN-to-integer coercion as it is compiler specific. */\n\t\treturn 0;\n\t}\n\n\tt = d - DUK_FLOOR(d);\n\tif (t == 0.5) {\n\t\t/* Exact halfway, round to even. */\n\t\tret = (duk_uint8_t) d;\n\t\tret = (ret + 1) & 0xfe;  /* Example: d=3.5, t=0.5 -> ret = (3 + 1) & 0xfe = 4 & 0xfe = 4\n\t\t                          * Example: d=4.5, t=0.5 -> ret = (4 + 1) & 0xfe = 5 & 0xfe = 4\n\t\t                          */\n\t} else {\n\t\t/* Not halfway, round to nearest. */\n\t\tret = (duk_uint8_t) (d + 0.5);\n\t}\n\treturn ret;\n}\n#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */\n\nDUK_EXTERNAL const char *duk_to_lstring(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_len) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\t(void) duk_to_string(thr, idx);\n\tDUK_ASSERT(duk_is_string(thr, idx));\n\treturn duk_require_lstring(thr, idx, out_len);\n}\n\nDUK_LOCAL duk_ret_t duk__safe_to_string_raw(duk_hthread *thr, void *udata) {\n\tDUK_ASSERT_CTX_VALID(thr);\n\tDUK_UNREF(udata);\n\n\tduk_to_string(thr, -1);\n\treturn 1;\n}\n\nDUK_EXTERNAL const char *duk_safe_to_lstring(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_len) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tidx = duk_require_normalize_index(thr, idx);\n\n\t/* We intentionally ignore the duk_safe_call() return value and only\n\t * check the output type.  This way we don't also need to check that\n\t * the returned value is indeed a string in the success case.\n\t */\n\n\tduk_dup(thr, idx);\n\t(void) duk_safe_call(thr, duk__safe_to_string_raw, NULL /*udata*/, 1 /*nargs*/, 1 /*nrets*/);\n\tif (!duk_is_string(thr, -1)) {\n\t\t/* Error: try coercing error to string once. */\n\t\t(void) duk_safe_call(thr, duk__safe_to_string_raw, NULL /*udata*/, 1 /*nargs*/, 1 /*nrets*/);\n\t\tif (!duk_is_string(thr, -1)) {\n\t\t\t/* Double error */\n\t\t\tduk_pop_unsafe(thr);\n\t\t\tduk_push_hstring_stridx(thr, DUK_STRIDX_UC_ERROR);\n\t\t} else {\n\t\t\t;\n\t\t}\n\t} else {\n\t\t/* String; may be a symbol, accepted. */\n\t\t;\n\t}\n\tDUK_ASSERT(duk_is_string(thr, -1));\n\n\tduk_replace(thr, idx);\n\tDUK_ASSERT(duk_get_string(thr, idx) != NULL);\n\treturn duk_get_lstring(thr, idx, out_len);\n}\n\nDUK_INTERNAL duk_hstring *duk_to_property_key_hstring(duk_hthread *thr, duk_idx_t idx) {\n\tduk_hstring *h;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tduk_to_primitive(thr, idx, DUK_HINT_STRING);  /* needed for e.g. Symbol objects */\n\th = duk_get_hstring(thr, idx);\n\tif (h == NULL) {\n\t\t/* The \"is string?\" check may seem unnecessary, but as things\n\t\t * are duk_to_hstring() invokes ToString() which fails for\n\t\t * symbols.  But since symbols are already strings for Duktape\n\t\t * C API, we check for that before doing the coercion.\n\t\t */\n\t\th = duk_to_hstring(thr, idx);\n\t}\n\tDUK_ASSERT(h != NULL);\n\treturn h;\n}\n\n#if defined(DUK_USE_DEBUGGER_SUPPORT)  /* only needed by debugger for now */\nDUK_INTERNAL duk_hstring *duk_safe_to_hstring(duk_hthread *thr, duk_idx_t idx) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\t(void) duk_safe_to_string(thr, idx);\n\tDUK_ASSERT(duk_is_string(thr, idx));\n\tDUK_ASSERT(duk_get_hstring(thr, idx) != NULL);\n\treturn duk_known_hstring(thr, idx);\n}\n#endif\n\n/* Push Object.prototype.toString() output for 'tv'. */\nDUK_INTERNAL void duk_push_class_string_tval(duk_hthread *thr, duk_tval *tv) {\n\tduk_small_uint_t stridx;\n\tduk_hstring *h_strclass;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tswitch (DUK_TVAL_GET_TAG(tv)) {\n\tcase DUK_TAG_UNUSED:  /* Treat like 'undefined', shouldn't happen. */\n\tcase DUK_TAG_UNDEFINED: {\n\t\tstridx = DUK_STRIDX_UC_UNDEFINED;\n\t\tbreak;\n\t}\n\tcase DUK_TAG_NULL: {\n\t\tstridx = DUK_STRIDX_UC_NULL;\n\t\tbreak;\n\t}\n\tcase DUK_TAG_BOOLEAN: {\n\t\tstridx = DUK_STRIDX_UC_BOOLEAN;\n\t\tbreak;\n\t}\n\tcase DUK_TAG_POINTER: {\n\t\tstridx = DUK_STRIDX_UC_POINTER;\n\t\tbreak;\n\t}\n\tcase DUK_TAG_LIGHTFUNC: {\n\t\tstridx = DUK_STRIDX_UC_FUNCTION;\n\t\tbreak;\n\t}\n\tcase DUK_TAG_STRING: {\n\t\tduk_hstring *h;\n\t\th = DUK_TVAL_GET_STRING(tv);\n\t\tDUK_ASSERT(h != NULL);\n\t\tif (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(h))) {\n\t\t\tstridx = DUK_STRIDX_UC_SYMBOL;\n\t\t} else {\n\t\t\tstridx = DUK_STRIDX_UC_STRING;\n\t\t}\n\t\tbreak;\n\t}\n\tcase DUK_TAG_OBJECT: {\n\t\tduk_hobject *h;\n\t\tduk_small_uint_t classnum;\n\n\t\th = DUK_TVAL_GET_OBJECT(tv);\n\t\tDUK_ASSERT(h != NULL);\n\t\tclassnum = DUK_HOBJECT_GET_CLASS_NUMBER(h);\n\t\tstridx = DUK_HOBJECT_CLASS_NUMBER_TO_STRIDX(classnum);\n\n\t\t/* XXX: This is not entirely correct anymore; in ES2015 the\n\t\t * default lookup should use @@toStringTag to come up with\n\t\t * e.g. [object Symbol], [object Uint8Array], etc.  See\n\t\t * ES2015 Section 19.1.3.6.  The downside of implementing that\n\t\t * directly is that the @@toStringTag lookup may have side\n\t\t * effects, so all call sites must be checked for that.\n\t\t * Some may need a side-effect free lookup, e.g. avoiding\n\t\t * getters which are not typical.\n\t\t */\n\t\tbreak;\n\t}\n\tcase DUK_TAG_BUFFER: {\n\t\tstridx = DUK_STRIDX_UINT8_ARRAY;\n\t\tbreak;\n\t}\n#if defined(DUK_USE_FASTINT)\n\tcase DUK_TAG_FASTINT:\n\t\t/* Fall through to generic number case. */\n#endif\n\tdefault: {\n\t\tDUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));  /* number (maybe fastint) */\n\t\tstridx = DUK_STRIDX_UC_NUMBER;\n\t\tbreak;\n\t}\n\t}\n\th_strclass = DUK_HTHREAD_GET_STRING(thr, stridx);\n\tDUK_ASSERT(h_strclass != NULL);\n\n\tduk_push_sprintf(thr, \"[object %s]\", (const char *) DUK_HSTRING_GET_DATA(h_strclass));\n}\n\n/* XXX: other variants like uint, u32 etc */\nDUK_INTERNAL duk_int_t duk_to_int_clamped_raw(duk_hthread *thr, duk_idx_t idx, duk_int_t minval, duk_int_t maxval, duk_bool_t *out_clamped) {\n\tduk_tval *tv;\n\tduk_tval tv_tmp;\n\tduk_double_t d, dmin, dmax;\n\tduk_int_t res;\n\tduk_bool_t clamped = 0;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\ttv = duk_require_tval(thr, idx);\n\tDUK_ASSERT(tv != NULL);\n\td = duk_js_tointeger(thr, tv);  /* E5 Section 9.4, ToInteger() */\n\n\tdmin = (duk_double_t) minval;\n\tdmax = (duk_double_t) maxval;\n\n\tif (d < dmin) {\n\t\tclamped = 1;\n\t\tres = minval;\n\t\td = dmin;\n\t} else if (d > dmax) {\n\t\tclamped = 1;\n\t\tres = maxval;\n\t\td = dmax;\n\t} else {\n\t\tres = (duk_int_t) d;\n\t}\n\tDUK_UNREF(d);  /* SCANBUILD: with suitable dmin/dmax limits 'd' is unused */\n\t/* 'd' and 'res' agree here */\n\n\t/* Relookup in case duk_js_tointeger() ends up e.g. coercing an object. */\n\ttv = duk_get_tval(thr, idx);\n\tDUK_ASSERT(tv != NULL);  /* not popped by side effect */\n\tDUK_TVAL_SET_TVAL(&tv_tmp, tv);\n#if defined(DUK_USE_FASTINT)\n#if (DUK_INT_MAX <= 0x7fffffffL)\n\tDUK_TVAL_SET_I32(tv, res);\n#else\n\t/* Clamping needed if duk_int_t is 64 bits. */\n\tif (res >= DUK_FASTINT_MIN && res <= DUK_FASTINT_MAX) {\n\t\tDUK_TVAL_SET_FASTINT(tv, res);\n\t} else {\n\t\tDUK_TVAL_SET_NUMBER(tv, d);\n\t}\n#endif\n#else\n\tDUK_TVAL_SET_NUMBER(tv, d);  /* no need to incref */\n#endif\n\tDUK_TVAL_DECREF(thr, &tv_tmp);  /* side effects */\n\n\tif (out_clamped) {\n\t\t*out_clamped = clamped;\n\t} else {\n\t\t/* coerced value is updated to value stack even when RangeError thrown */\n\t\tif (clamped) {\n\t\t\tDUK_ERROR_RANGE(thr, DUK_STR_NUMBER_OUTSIDE_RANGE);\n\t\t}\n\t}\n\n\treturn res;\n}\n\nDUK_INTERNAL duk_int_t duk_to_int_clamped(duk_hthread *thr, duk_idx_t idx, duk_idx_t minval, duk_idx_t maxval) {\n\tduk_bool_t dummy;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\treturn duk_to_int_clamped_raw(thr, idx, minval, maxval, &dummy);\n}\n\nDUK_INTERNAL duk_int_t duk_to_int_check_range(duk_hthread *thr, duk_idx_t idx, duk_int_t minval, duk_int_t maxval) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\treturn duk_to_int_clamped_raw(thr, idx, minval, maxval, NULL);  /* out_clamped==NULL -> RangeError if outside range */\n}\n\nDUK_EXTERNAL const char *duk_to_string(duk_hthread *thr, duk_idx_t idx) {\n\tduk_tval *tv;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tidx = duk_require_normalize_index(thr, idx);\n\ttv = DUK_GET_TVAL_POSIDX(thr, idx);\n\tDUK_ASSERT(tv != NULL);\n\n\tswitch (DUK_TVAL_GET_TAG(tv)) {\n\tcase DUK_TAG_UNDEFINED: {\n\t\tduk_push_hstring_stridx(thr, DUK_STRIDX_LC_UNDEFINED);\n\t\tbreak;\n\t}\n\tcase DUK_TAG_NULL: {\n\t\tduk_push_hstring_stridx(thr, DUK_STRIDX_LC_NULL);\n\t\tbreak;\n\t}\n\tcase DUK_TAG_BOOLEAN: {\n\t\tif (DUK_TVAL_GET_BOOLEAN(tv)) {\n\t\t\tduk_push_hstring_stridx(thr, DUK_STRIDX_TRUE);\n\t\t} else {\n\t\t\tduk_push_hstring_stridx(thr, DUK_STRIDX_FALSE);\n\t\t}\n\t\tbreak;\n\t}\n\tcase DUK_TAG_STRING: {\n\t\t/* Nop for actual strings, TypeError for Symbols.\n\t\t * Because various internals rely on ToString() coercion of\n\t\t * internal strings, -allow- (NOP) string coercion for hidden\n\t\t * symbols.\n\t\t */\n#if 1\n\t\tduk_hstring *h;\n\t\th = DUK_TVAL_GET_STRING(tv);\n\t\tDUK_ASSERT(h != NULL);\n\t\tif (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(h))) {\n\t\t\tDUK_ERROR_TYPE(thr, DUK_STR_CANNOT_STRING_COERCE_SYMBOL);\n\t\t} else {\n\t\t\tgoto skip_replace;\n\t\t}\n#else\n\t\tgoto skip_replace;\n#endif\n\t}\n\tcase DUK_TAG_BUFFER: /* Go through Uint8Array.prototype.toString() for coercion. */\n\tcase DUK_TAG_OBJECT: {\n\t\t/* Plain buffers: go through ArrayBuffer.prototype.toString()\n\t\t * for coercion.\n\t\t *\n\t\t * Symbol objects: duk_to_primitive() results in a plain symbol\n\t\t * value, and duk_to_string() then causes a TypeError.\n\t\t */\n\t\tduk_to_primitive(thr, idx, DUK_HINT_STRING);\n\t\tDUK_ASSERT(!duk_is_buffer(thr, idx));  /* ToPrimitive() must guarantee */\n\t\tDUK_ASSERT(!duk_is_object(thr, idx));\n\t\treturn duk_to_string(thr, idx);  /* Note: recursive call */\n\t}\n\tcase DUK_TAG_POINTER: {\n\t\tvoid *ptr = DUK_TVAL_GET_POINTER(tv);\n\t\tif (ptr != NULL) {\n\t\t\tduk_push_sprintf(thr, DUK_STR_FMT_PTR, (void *) ptr);\n\t\t} else {\n\t\t\t/* Represent a null pointer as 'null' to be consistent with\n\t\t\t * the JX format variant.  Native '%p' format for a NULL\n\t\t\t * pointer may be e.g. '(nil)'.\n\t\t\t */\n\t\t\tduk_push_hstring_stridx(thr, DUK_STRIDX_LC_NULL);\n\t\t}\n\t\tbreak;\n\t}\n\tcase DUK_TAG_LIGHTFUNC: {\n\t\t/* Should match Function.prototype.toString() */\n\t\tduk_push_lightfunc_tostring(thr, tv);\n\t\tbreak;\n\t}\n#if defined(DUK_USE_FASTINT)\n\tcase DUK_TAG_FASTINT:\n#endif\n\tdefault: {\n\t\t/* number */\n\t\tDUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));\n\t\tDUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));\n\t\tduk_push_tval(thr, tv);\n\t\tduk_numconv_stringify(thr,\n\t\t                      10 /*radix*/,\n\t\t                      0 /*precision:shortest*/,\n\t\t                      0 /*force_exponential*/);\n\t\tbreak;\n\t}\n\t}\n\n\tduk_replace(thr, idx);\n\n skip_replace:\n\tDUK_ASSERT(duk_is_string(thr, idx));\n\treturn duk_require_string(thr, idx);\n}\n\nDUK_INTERNAL duk_hstring *duk_to_hstring(duk_hthread *thr, duk_idx_t idx) {\n\tduk_hstring *ret;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tduk_to_string(thr, idx);\n\tret = duk_get_hstring(thr, idx);\n\tDUK_ASSERT(ret != NULL);\n\treturn ret;\n}\n\nDUK_INTERNAL duk_hstring *duk_to_hstring_m1(duk_hthread *thr) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\treturn duk_to_hstring(thr, -1);\n}\n\nDUK_INTERNAL duk_hstring *duk_to_hstring_acceptsymbol(duk_hthread *thr, duk_idx_t idx) {\n\tduk_hstring *ret;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tret = duk_get_hstring(thr, idx);\n\tif (DUK_UNLIKELY(ret && DUK_HSTRING_HAS_SYMBOL(ret))) {\n\t\treturn ret;\n\t}\n\treturn duk_to_hstring(thr, idx);\n}\n\n/* Convert a plain buffer or any buffer object into a string, using the buffer\n * bytes 1:1 in the internal string representation.  For views the active byte\n * slice (not element slice interpreted as an initializer) is used.  This is\n * necessary in Duktape 2.x because ToString(plainBuffer) no longer creates a\n * string with the same bytes as in the buffer but rather (usually)\n * '[object ArrayBuffer]'.\n */\nDUK_EXTERNAL const char *duk_buffer_to_string(duk_hthread *thr, duk_idx_t idx) {\n\tvoid *ptr_src;\n\tduk_size_t len;\n\tconst char *res;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tidx = duk_require_normalize_index(thr, idx);\n\n\tptr_src = duk_require_buffer_data(thr, idx, &len);\n\tDUK_ASSERT(ptr_src != NULL || len == 0);\n\n\tres = duk_push_lstring(thr, (const char *) ptr_src, len);\n\tduk_replace(thr, idx);\n\treturn res;\n}\n\nDUK_EXTERNAL void *duk_to_buffer_raw(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_size, duk_uint_t mode) {\n\tduk_hbuffer *h_buf;\n\tconst duk_uint8_t *src_data;\n\tduk_size_t src_size;\n\tduk_uint8_t *dst_data;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tidx = duk_require_normalize_index(thr, idx);\n\n\th_buf = duk_get_hbuffer(thr, idx);\n\tif (h_buf != NULL) {\n\t\t/* Buffer is kept as is, with the fixed/dynamic nature of the\n\t\t * buffer only changed if requested.  An external buffer\n\t\t * is converted into a non-external dynamic buffer in a\n\t\t * duk_to_dynamic_buffer() call.\n\t\t */\n\t\tduk_uint_t tmp;\n\t\tduk_uint8_t *tmp_ptr;\n\n\t\ttmp_ptr = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_buf);\n\t\tsrc_data = (const duk_uint8_t *) tmp_ptr;\n\t\tsrc_size = DUK_HBUFFER_GET_SIZE(h_buf);\n\n\t\ttmp = (DUK_HBUFFER_HAS_DYNAMIC(h_buf) ? DUK_BUF_MODE_DYNAMIC : DUK_BUF_MODE_FIXED);\n\t\tif ((tmp == mode && !DUK_HBUFFER_HAS_EXTERNAL(h_buf)) ||\n\t\t    mode == DUK_BUF_MODE_DONTCARE) {\n\t\t\t/* Note: src_data may be NULL if input is a zero-size\n\t\t\t * dynamic buffer.\n\t\t\t */\n\t\t\tdst_data = tmp_ptr;\n\t\t\tgoto skip_copy;\n\t\t}\n\t} else {\n\t\t/* Non-buffer value is first ToString() coerced, then converted\n\t\t * to a buffer (fixed buffer is used unless a dynamic buffer is\n\t\t * explicitly requested).  Symbols are rejected with a TypeError.\n\t\t * XXX: C API could maybe allow symbol-to-buffer coercion?\n\t\t */\n\t\tsrc_data = (const duk_uint8_t *) duk_to_lstring(thr, idx, &src_size);\n\t}\n\n\tdst_data = (duk_uint8_t *) duk_push_buffer(thr, src_size, (mode == DUK_BUF_MODE_DYNAMIC) /*dynamic*/);\n\tif (DUK_LIKELY(src_size > 0)) {\n\t\t/* When src_size == 0, src_data may be NULL (if source\n\t\t * buffer is dynamic), and dst_data may be NULL (if\n\t\t * target buffer is dynamic).  Avoid zero-size memcpy()\n\t\t * with an invalid pointer.\n\t\t */\n\t\tDUK_MEMCPY((void *) dst_data, (const void *) src_data, (size_t) src_size);\n\t}\n\tduk_replace(thr, idx);\n skip_copy:\n\n\tif (out_size) {\n\t\t*out_size = src_size;\n\t}\n\treturn dst_data;\n}\n\nDUK_EXTERNAL void *duk_to_pointer(duk_hthread *thr, duk_idx_t idx) {\n\tduk_tval *tv;\n\tvoid *res;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tidx = duk_require_normalize_index(thr, idx);\n\ttv = DUK_GET_TVAL_POSIDX(thr, idx);\n\tDUK_ASSERT(tv != NULL);\n\n\tswitch (DUK_TVAL_GET_TAG(tv)) {\n\tcase DUK_TAG_UNDEFINED:\n\tcase DUK_TAG_NULL:\n\tcase DUK_TAG_BOOLEAN:\n\t\tres = NULL;\n\t\tbreak;\n\tcase DUK_TAG_POINTER:\n\t\tres = DUK_TVAL_GET_POINTER(tv);\n\t\tbreak;\n\tcase DUK_TAG_STRING:\n\tcase DUK_TAG_OBJECT:\n\tcase DUK_TAG_BUFFER:\n\t\t/* Heap allocated: return heap pointer which is NOT useful\n\t\t * for the caller, except for debugging.\n\t\t */\n\t\tres = (void *) DUK_TVAL_GET_HEAPHDR(tv);\n\t\tbreak;\n\tcase DUK_TAG_LIGHTFUNC:\n\t\t/* Function pointers do not always cast correctly to void *\n\t\t * (depends on memory and segmentation model for instance),\n\t\t * so they coerce to NULL.\n\t\t */\n\t\tres = NULL;\n\t\tbreak;\n#if defined(DUK_USE_FASTINT)\n\tcase DUK_TAG_FASTINT:\n#endif\n\tdefault:\n\t\t/* number */\n\t\tDUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));\n\t\tDUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));\n\t\tres = NULL;\n\t\tbreak;\n\t}\n\n\tduk_push_pointer(thr, res);\n\tduk_replace(thr, idx);\n\treturn res;\n}\n\nDUK_LOCAL void duk__push_func_from_lightfunc(duk_hthread *thr, duk_c_function func, duk_small_uint_t lf_flags) {\n\tduk_idx_t nargs;\n\tduk_uint_t flags = 0;   /* shared flags for a subset of types */\n\tduk_small_uint_t lf_len;\n\tduk_hnatfunc *nf;\n\n\tnargs = (duk_idx_t) DUK_LFUNC_FLAGS_GET_NARGS(lf_flags);\n\tif (nargs == DUK_LFUNC_NARGS_VARARGS) {\n\t\tnargs = (duk_idx_t) DUK_VARARGS;\n\t}\n\n\tflags = DUK_HOBJECT_FLAG_EXTENSIBLE |\n\t        DUK_HOBJECT_FLAG_CONSTRUCTABLE |\n\t        DUK_HOBJECT_FLAG_CALLABLE |\n\t        DUK_HOBJECT_FLAG_FASTREFS |\n\t        DUK_HOBJECT_FLAG_NATFUNC |\n\t        DUK_HOBJECT_FLAG_NEWENV |\n\t        DUK_HOBJECT_FLAG_STRICT |\n\t        DUK_HOBJECT_FLAG_NOTAIL |\n\t        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_FUNCTION);\n\t(void) duk__push_c_function_raw(thr, func, nargs, flags, DUK_BIDX_NATIVE_FUNCTION_PROTOTYPE);\n\n\tlf_len = DUK_LFUNC_FLAGS_GET_LENGTH(lf_flags);\n\tif ((duk_idx_t) lf_len != nargs) {\n\t\t/* Explicit length is only needed if it differs from 'nargs'. */\n\t\tduk_push_int(thr, (duk_int_t) lf_len);\n\t\tduk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_NONE);\n\t}\n\n#if defined(DUK_USE_FUNC_NAME_PROPERTY)\n\tduk_push_lightfunc_name_raw(thr, func, lf_flags);\n\tduk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_NAME, DUK_PROPDESC_FLAGS_C);\n#endif\n\n\tnf = duk_known_hnatfunc(thr, -1);\n\tnf->magic = (duk_int16_t) DUK_LFUNC_FLAGS_GET_MAGIC(lf_flags);\n}\n\nDUK_EXTERNAL void duk_to_object(duk_hthread *thr, duk_idx_t idx) {\n\tduk_tval *tv;\n\tduk_uint_t flags = 0;   /* shared flags for a subset of types */\n\tduk_small_int_t proto = 0;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tidx = duk_require_normalize_index(thr, idx);\n\ttv = DUK_GET_TVAL_POSIDX(thr, idx);\n\tDUK_ASSERT(tv != NULL);\n\n\tswitch (DUK_TVAL_GET_TAG(tv)) {\n#if !defined(DUK_USE_BUFFEROBJECT_SUPPORT)\n\tcase DUK_TAG_BUFFER:  /* With no bufferobject support, don't object coerce. */\n#endif\n\tcase DUK_TAG_UNDEFINED:\n\tcase DUK_TAG_NULL: {\n\t\tDUK_ERROR_TYPE(thr, DUK_STR_NOT_OBJECT_COERCIBLE);\n\t\tbreak;\n\t}\n\tcase DUK_TAG_BOOLEAN: {\n\t\tflags = DUK_HOBJECT_FLAG_EXTENSIBLE |\n\t\t        DUK_HOBJECT_FLAG_FASTREFS |\n\t\t        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_BOOLEAN);\n\t\tproto = DUK_BIDX_BOOLEAN_PROTOTYPE;\n\t\tgoto create_object;\n\t}\n\tcase DUK_TAG_STRING: {\n\t\tduk_hstring *h;\n\t\th = DUK_TVAL_GET_STRING(tv);\n\t\tDUK_ASSERT(h != NULL);\n\t\tif (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(h))) {\n\t\t\tflags = DUK_HOBJECT_FLAG_EXTENSIBLE |\n\t\t\t        DUK_HOBJECT_FLAG_FASTREFS |\n\t\t\t        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_SYMBOL);\n\t\t\tproto = DUK_BIDX_SYMBOL_PROTOTYPE;\n\t\t} else {\n\t\t\tflags = DUK_HOBJECT_FLAG_EXTENSIBLE |\n\t\t\t        DUK_HOBJECT_FLAG_FASTREFS |\n\t\t\t        DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ |\n\t\t\t        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_STRING);\n\t\t\tproto = DUK_BIDX_STRING_PROTOTYPE;\n\t\t}\n\t\tgoto create_object;\n\t}\n\tcase DUK_TAG_OBJECT: {\n\t\t/* nop */\n\t\tbreak;\n\t}\n#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)\n\tcase DUK_TAG_BUFFER: {\n\t\t/* A plain buffer object coerces to a full ArrayBuffer which\n\t\t * is not fully transparent behavior (ToObject() should be a\n\t\t * nop for an object).  This behavior matches lightfuncs which\n\t\t * also coerce to an equivalent Function object.  There are\n\t\t * also downsides to defining ToObject(plainBuffer) as a no-op;\n\t\t * for example duk_to_hobject() could result in a NULL pointer.\n\t\t */\n\t\tduk_hbuffer *h_buf;\n\n\t\th_buf = DUK_TVAL_GET_BUFFER(tv);\n\t\tDUK_ASSERT(h_buf != NULL);\n\t\tduk_hbufobj_push_uint8array_from_plain(thr, h_buf);\n\t\tgoto replace_value;\n\t}\n#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */\n\tcase DUK_TAG_POINTER: {\n\t\tflags = DUK_HOBJECT_FLAG_EXTENSIBLE |\n\t\t        DUK_HOBJECT_FLAG_FASTREFS |\n\t\t        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_POINTER);\n\t\tproto = DUK_BIDX_POINTER_PROTOTYPE;\n\t\tgoto create_object;\n\t}\n\tcase DUK_TAG_LIGHTFUNC: {\n\t\t/* Lightfunc coerces to a Function instance with concrete\n\t\t * properties.  Since 'length' is virtual for Duktape/C\n\t\t * functions, don't need to define that.  The result is made\n\t\t * extensible to mimic what happens to strings in object\n\t\t * coercion:\n\t\t *\n\t\t *   > Object.isExtensible(Object('foo'))\n\t\t *   true\n\t\t */\n\t\tduk_small_uint_t lf_flags;\n\t\tduk_c_function func;\n\n\t\tDUK_TVAL_GET_LIGHTFUNC(tv, func, lf_flags);\n\t\tduk__push_func_from_lightfunc(thr, func, lf_flags);\n\t\tgoto replace_value;\n\t}\n#if defined(DUK_USE_FASTINT)\n\tcase DUK_TAG_FASTINT:\n#endif\n\tdefault: {\n\t\tDUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));\n\t\tDUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));\n\t\tflags = DUK_HOBJECT_FLAG_EXTENSIBLE |\n\t\t        DUK_HOBJECT_FLAG_FASTREFS |\n\t\t        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_NUMBER);\n\t\tproto = DUK_BIDX_NUMBER_PROTOTYPE;\n\t\tgoto create_object;\n\t}\n\t}\n\tDUK_ASSERT(duk_is_object(thr, idx));\n\treturn;\n\n create_object:\n\t(void) duk_push_object_helper(thr, flags, proto);\n\n\t/* Note: Boolean prototype's internal value property is not writable,\n\t * but duk_xdef_prop_stridx() disregards the write protection.  Boolean\n\t * instances are immutable.\n\t *\n\t * String and buffer special behaviors are already enabled which is not\n\t * ideal, but a write to the internal value is not affected by them.\n\t */\n\tduk_dup(thr, idx);\n\tduk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_NONE);\n\n replace_value:\n\tduk_replace(thr, idx);\n\tDUK_ASSERT(duk_is_object(thr, idx));\n}\n\nDUK_INTERNAL duk_hobject *duk_to_hobject(duk_hthread *thr, duk_idx_t idx) {\n\tduk_hobject *ret;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tduk_to_object(thr, idx);\n\tret = duk_known_hobject(thr, idx);\n\treturn ret;\n}\n\n/*\n *  Type checking\n */\n\nDUK_LOCAL duk_bool_t duk__tag_check(duk_hthread *thr, duk_idx_t idx, duk_small_uint_t tag) {\n\tduk_tval *tv;\n\n\ttv = duk_get_tval_or_unused(thr, idx);\n\tDUK_ASSERT(tv != NULL);\n\treturn (DUK_TVAL_GET_TAG(tv) == tag);\n}\n\nDUK_LOCAL duk_bool_t duk__obj_flag_any_default_false(duk_hthread *thr, duk_idx_t idx, duk_uint_t flag_mask) {\n\tduk_hobject *obj;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tobj = duk_get_hobject(thr, idx);\n\tif (obj) {\n\t\treturn (DUK_HEAPHDR_CHECK_FLAG_BITS((duk_heaphdr *) obj, flag_mask) ? 1 : 0);\n\t}\n\treturn 0;\n}\n\nDUK_INTERNAL duk_int_t duk_get_type_tval(duk_tval *tv) {\n\tDUK_ASSERT(tv != NULL);\n\n#if defined(DUK_USE_PACKED_TVAL)\n\tswitch (DUK_TVAL_GET_TAG(tv)) {\n\tcase DUK_TAG_UNUSED:\n\t\treturn DUK_TYPE_NONE;\n\tcase DUK_TAG_UNDEFINED:\n\t\treturn DUK_TYPE_UNDEFINED;\n\tcase DUK_TAG_NULL:\n\t\treturn DUK_TYPE_NULL;\n\tcase DUK_TAG_BOOLEAN:\n\t\treturn DUK_TYPE_BOOLEAN;\n\tcase DUK_TAG_STRING:\n\t\treturn DUK_TYPE_STRING;\n\tcase DUK_TAG_OBJECT:\n\t\treturn DUK_TYPE_OBJECT;\n\tcase DUK_TAG_BUFFER:\n\t\treturn DUK_TYPE_BUFFER;\n\tcase DUK_TAG_POINTER:\n\t\treturn DUK_TYPE_POINTER;\n\tcase DUK_TAG_LIGHTFUNC:\n\t\treturn DUK_TYPE_LIGHTFUNC;\n#if defined(DUK_USE_FASTINT)\n\tcase DUK_TAG_FASTINT:\n#endif\n\tdefault:\n\t\t/* Note: number has no explicit tag (in 8-byte representation) */\n\t\tDUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));\n\t\tDUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));\n\t\treturn DUK_TYPE_NUMBER;\n\t}\n#else  /* DUK_USE_PACKED_TVAL */\n\tDUK_ASSERT(DUK_TVAL_IS_VALID_TAG(tv));\n\tDUK_ASSERT(sizeof(duk__type_from_tag) / sizeof(duk_uint_t) == DUK_TAG_MAX - DUK_TAG_MIN + 1);\n\treturn (duk_int_t) duk__type_from_tag[DUK_TVAL_GET_TAG(tv) - DUK_TAG_MIN];\n#endif  /* DUK_USE_PACKED_TVAL */\n}\n\nDUK_EXTERNAL duk_int_t duk_get_type(duk_hthread *thr, duk_idx_t idx) {\n\tduk_tval *tv;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\ttv = duk_get_tval_or_unused(thr, idx);\n\tDUK_ASSERT(tv != NULL);\n\n\treturn duk_get_type_tval(tv);\n}\n\n#if defined(DUK_USE_VERBOSE_ERRORS) && defined(DUK_USE_PARANOID_ERRORS)\nDUK_LOCAL const char * const duk__type_names[] = {\n\t\"none\",\n\t\"undefined\",\n\t\"null\",\n\t\"boolean\",\n\t\"number\",\n\t\"string\",\n\t\"object\",\n\t\"buffer\",\n\t\"pointer\",\n\t\"lightfunc\"\n};\n\nDUK_INTERNAL const char *duk_get_type_name(duk_hthread *thr, duk_idx_t idx) {\n\tduk_int_t type_tag;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\ttype_tag = duk_get_type(thr, idx);\n\tDUK_ASSERT(type_tag >= DUK_TYPE_MIN && type_tag <= DUK_TYPE_MAX);\n\tDUK_ASSERT(DUK_TYPE_MIN == 0 && sizeof(duk__type_names) / sizeof(const char *) == DUK_TYPE_MAX + 1);\n\n\treturn duk__type_names[type_tag];\n}\n#endif  /* DUK_USE_VERBOSE_ERRORS && DUK_USE_PARANOID_ERRORS */\n\nDUK_INTERNAL duk_small_uint_t duk_get_class_number(duk_hthread *thr, duk_idx_t idx) {\n\tduk_tval *tv;\n\tduk_hobject *obj;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\ttv = duk_get_tval_or_unused(thr, idx);\n\tDUK_ASSERT(tv != NULL);\n\n\tswitch (DUK_TVAL_GET_TAG(tv)) {\n\tcase DUK_TAG_OBJECT:\n\t\tobj = DUK_TVAL_GET_OBJECT(tv);\n\t\tDUK_ASSERT(obj != NULL);\n\t\treturn DUK_HOBJECT_GET_CLASS_NUMBER(obj);\n\tcase DUK_TAG_BUFFER:\n\t\t/* Buffers behave like Uint8Array objects. */\n\t\treturn DUK_HOBJECT_CLASS_UINT8ARRAY;\n\tcase DUK_TAG_LIGHTFUNC:\n\t\t/* Lightfuncs behave like Function objects. */\n\t\treturn DUK_HOBJECT_CLASS_FUNCTION;\n\tdefault:\n\t\t/* Primitive or UNUSED, no class number. */\n\t\treturn DUK_HOBJECT_CLASS_NONE;\n\t}\n}\n\nDUK_EXTERNAL duk_bool_t duk_check_type(duk_hthread *thr, duk_idx_t idx, duk_int_t type) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\treturn (duk_get_type(thr, idx) == type) ? 1 : 0;\n}\n\nDUK_INTERNAL duk_uint_t duk_get_type_mask_tval(duk_tval *tv) {\n\tDUK_ASSERT(tv != NULL);\n\n#if defined(DUK_USE_PACKED_TVAL)\n\tswitch (DUK_TVAL_GET_TAG(tv)) {\n\tcase DUK_TAG_UNUSED:\n\t\treturn DUK_TYPE_MASK_NONE;\n\tcase DUK_TAG_UNDEFINED:\n\t\treturn DUK_TYPE_MASK_UNDEFINED;\n\tcase DUK_TAG_NULL:\n\t\treturn DUK_TYPE_MASK_NULL;\n\tcase DUK_TAG_BOOLEAN:\n\t\treturn DUK_TYPE_MASK_BOOLEAN;\n\tcase DUK_TAG_STRING:\n\t\treturn DUK_TYPE_MASK_STRING;\n\tcase DUK_TAG_OBJECT:\n\t\treturn DUK_TYPE_MASK_OBJECT;\n\tcase DUK_TAG_BUFFER:\n\t\treturn DUK_TYPE_MASK_BUFFER;\n\tcase DUK_TAG_POINTER:\n\t\treturn DUK_TYPE_MASK_POINTER;\n\tcase DUK_TAG_LIGHTFUNC:\n\t\treturn DUK_TYPE_MASK_LIGHTFUNC;\n#if defined(DUK_USE_FASTINT)\n\tcase DUK_TAG_FASTINT:\n#endif\n\tdefault:\n\t\t/* Note: number has no explicit tag (in 8-byte representation) */\n\t\tDUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));\n\t\tDUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));\n\t\treturn DUK_TYPE_MASK_NUMBER;\n\t}\n#else  /* DUK_USE_PACKED_TVAL */\n\tDUK_ASSERT(DUK_TVAL_IS_VALID_TAG(tv));\n\tDUK_ASSERT(sizeof(duk__type_mask_from_tag) / sizeof(duk_uint_t) == DUK_TAG_MAX - DUK_TAG_MIN + 1);\n\treturn duk__type_mask_from_tag[DUK_TVAL_GET_TAG(tv) - DUK_TAG_MIN];\n#endif  /* DUK_USE_PACKED_TVAL */\n}\n\nDUK_EXTERNAL duk_uint_t duk_get_type_mask(duk_hthread *thr, duk_idx_t idx) {\n\tduk_tval *tv;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\ttv = duk_get_tval_or_unused(thr, idx);\n\tDUK_ASSERT(tv != NULL);\n\n\treturn duk_get_type_mask_tval(tv);\n}\n\nDUK_EXTERNAL duk_bool_t duk_check_type_mask(duk_hthread *thr, duk_idx_t idx, duk_uint_t mask) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tif (DUK_LIKELY((duk_get_type_mask(thr, idx) & mask) != 0U)) {\n\t\treturn 1;\n\t}\n\tif (mask & DUK_TYPE_MASK_THROW) {\n\t\tDUK_ERROR_TYPE(thr, DUK_STR_UNEXPECTED_TYPE);\n\t\tDUK_UNREACHABLE();\n\t}\n\treturn 0;\n}\n\nDUK_EXTERNAL duk_bool_t duk_is_undefined(duk_hthread *thr, duk_idx_t idx) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\treturn duk__tag_check(thr, idx, DUK_TAG_UNDEFINED);\n}\n\nDUK_EXTERNAL duk_bool_t duk_is_null(duk_hthread *thr, duk_idx_t idx) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\treturn duk__tag_check(thr, idx, DUK_TAG_NULL);\n}\n\nDUK_EXTERNAL duk_bool_t duk_is_boolean(duk_hthread *thr, duk_idx_t idx) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\treturn duk__tag_check(thr, idx, DUK_TAG_BOOLEAN);\n}\n\nDUK_EXTERNAL duk_bool_t duk_is_number(duk_hthread *thr, duk_idx_t idx) {\n\tduk_tval *tv;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\t/*\n\t *  Number is special because it doesn't have a specific\n\t *  tag in the 8-byte representation.\n\t */\n\n\t/* XXX: shorter version for unpacked representation? */\n\n\ttv = duk_get_tval_or_unused(thr, idx);\n\tDUK_ASSERT(tv != NULL);\n\treturn DUK_TVAL_IS_NUMBER(tv);\n}\n\nDUK_EXTERNAL duk_bool_t duk_is_nan(duk_hthread *thr, duk_idx_t idx) {\n\t/* XXX: This will now return false for non-numbers, even though they would\n\t * coerce to NaN (as a general rule).  In particular, duk_get_number()\n\t * returns a NaN for non-numbers, so should this function also return\n\t * true for non-numbers?\n\t */\n\n\tduk_tval *tv;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\ttv = duk_get_tval_or_unused(thr, idx);\n\tDUK_ASSERT(tv != NULL);\n\n\t/* XXX: for packed duk_tval an explicit \"is number\" check is unnecessary */\n\tif (!DUK_TVAL_IS_NUMBER(tv)) {\n\t\treturn 0;\n\t}\n\treturn (duk_bool_t) DUK_ISNAN(DUK_TVAL_GET_NUMBER(tv));\n}\n\nDUK_EXTERNAL duk_bool_t duk_is_string(duk_hthread *thr, duk_idx_t idx) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\treturn duk__tag_check(thr, idx, DUK_TAG_STRING);\n}\n\nDUK_INTERNAL duk_bool_t duk_is_string_notsymbol(duk_hthread *thr, duk_idx_t idx) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\treturn duk_get_hstring_notsymbol(thr, idx) != NULL;\n}\n\nDUK_EXTERNAL duk_bool_t duk_is_object(duk_hthread *thr, duk_idx_t idx) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\treturn duk__tag_check(thr, idx, DUK_TAG_OBJECT);\n}\n\nDUK_EXTERNAL duk_bool_t duk_is_buffer(duk_hthread *thr, duk_idx_t idx) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\treturn duk__tag_check(thr, idx, DUK_TAG_BUFFER);\n}\n\n#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)\nDUK_EXTERNAL duk_bool_t duk_is_buffer_data(duk_hthread *thr, duk_idx_t idx) {\n\tduk_tval *tv;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\ttv = duk_get_tval_or_unused(thr, idx);\n\tDUK_ASSERT(tv != NULL);\n\tif (DUK_TVAL_IS_BUFFER(tv)) {\n\t\treturn 1;\n\t} else if (DUK_TVAL_IS_OBJECT(tv)) {\n\t\tduk_hobject *h = DUK_TVAL_GET_OBJECT(tv);\n\t\tDUK_ASSERT(h != NULL);\n\t\tif (DUK_HOBJECT_IS_BUFOBJ(h)) {\n\t\t\treturn 1;\n\t\t}\n\t}\n\treturn 0;\n}\n#else  /* DUK_USE_BUFFEROBJECT_SUPPORT */\nDUK_EXTERNAL duk_bool_t duk_is_buffer_data(duk_hthread *thr, duk_idx_t idx) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\treturn duk_is_buffer(thr, idx);\n}\n\n#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */\n\nDUK_EXTERNAL duk_bool_t duk_is_pointer(duk_hthread *thr, duk_idx_t idx) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\treturn duk__tag_check(thr, idx, DUK_TAG_POINTER);\n}\n\nDUK_EXTERNAL duk_bool_t duk_is_lightfunc(duk_hthread *thr, duk_idx_t idx) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\treturn duk__tag_check(thr, idx, DUK_TAG_LIGHTFUNC);\n}\n\nDUK_EXTERNAL duk_bool_t duk_is_symbol(duk_hthread *thr, duk_idx_t idx) {\n\tduk_hstring *h;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\th = duk_get_hstring(thr, idx);\n\t/* Use DUK_LIKELY() here because caller may be more likely to type\n\t * check an expected symbol than not.\n\t */\n\tif (DUK_LIKELY(h != NULL && DUK_HSTRING_HAS_SYMBOL(h))) {\n\t\treturn 1;\n\t}\n\treturn 0;\n}\n\nDUK_EXTERNAL duk_bool_t duk_is_array(duk_hthread *thr, duk_idx_t idx) {\n\tduk_hobject *obj;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tobj = duk_get_hobject(thr, idx);\n\tif (obj) {\n\t\treturn (DUK_HOBJECT_GET_CLASS_NUMBER(obj) == DUK_HOBJECT_CLASS_ARRAY ? 1 : 0);\n\t}\n\treturn 0;\n}\n\nDUK_EXTERNAL duk_bool_t duk_is_function(duk_hthread *thr, duk_idx_t idx) {\n\tduk_tval *tv;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\ttv = duk_get_tval_or_unused(thr, idx);\n\tif (DUK_TVAL_IS_OBJECT(tv)) {\n\t\tduk_hobject *h;\n\t\th = DUK_TVAL_GET_OBJECT(tv);\n\t\tDUK_ASSERT(h != NULL);\n\t\treturn DUK_HOBJECT_HAS_CALLABLE(h) ? 1 : 0;\n\t}\n\tif (DUK_TVAL_IS_LIGHTFUNC(tv)) {\n\t\treturn 1;\n\t}\n\treturn 0;\n}\n\nDUK_INTERNAL duk_bool_t duk_is_callable_tval(duk_hthread *thr, duk_tval *tv) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tDUK_UNREF(thr);\n\n\tif (DUK_TVAL_IS_OBJECT(tv)) {\n\t\tduk_hobject *h;\n\t\th = DUK_TVAL_GET_OBJECT(tv);\n\t\tDUK_ASSERT(h != NULL);\n\t\treturn DUK_HOBJECT_HAS_CALLABLE(h) ? 1 : 0;\n\t}\n\tif (DUK_TVAL_IS_LIGHTFUNC(tv)) {\n\t\treturn 1;\n\t}\n\treturn 0;\n}\n\nDUK_EXTERNAL duk_bool_t duk_is_constructable(duk_hthread *thr, duk_idx_t idx) {\n\tduk_tval *tv;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\ttv = duk_get_tval_or_unused(thr, idx);\n\tif (DUK_TVAL_IS_OBJECT(tv)) {\n\t\tduk_hobject *h;\n\t\th = DUK_TVAL_GET_OBJECT(tv);\n\t\tDUK_ASSERT(h != NULL);\n\t\treturn DUK_HOBJECT_HAS_CONSTRUCTABLE(h) ? 1 : 0;\n\t}\n\tif (DUK_TVAL_IS_LIGHTFUNC(tv)) {\n\t\treturn 1;\n\t}\n\treturn 0;\n}\n\nDUK_EXTERNAL duk_bool_t duk_is_c_function(duk_hthread *thr, duk_idx_t idx) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\treturn duk__obj_flag_any_default_false(thr,\n\t                                       idx,\n\t                                       DUK_HOBJECT_FLAG_NATFUNC);\n}\n\nDUK_EXTERNAL duk_bool_t duk_is_ecmascript_function(duk_hthread *thr, duk_idx_t idx) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\treturn duk__obj_flag_any_default_false(thr,\n\t                                       idx,\n\t                                       DUK_HOBJECT_FLAG_COMPFUNC);\n}\n\nDUK_EXTERNAL duk_bool_t duk_is_bound_function(duk_hthread *thr, duk_idx_t idx) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\treturn duk__obj_flag_any_default_false(thr,\n\t                                       idx,\n\t                                       DUK_HOBJECT_FLAG_BOUNDFUNC);\n}\n\nDUK_EXTERNAL duk_bool_t duk_is_thread(duk_hthread *thr, duk_idx_t idx) {\n\tduk_hobject *obj;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tobj = duk_get_hobject(thr, idx);\n\tif (obj) {\n\t\treturn (DUK_HOBJECT_GET_CLASS_NUMBER(obj) == DUK_HOBJECT_CLASS_THREAD ? 1 : 0);\n\t}\n\treturn 0;\n}\n\nDUK_EXTERNAL duk_bool_t duk_is_fixed_buffer(duk_hthread *thr, duk_idx_t idx) {\n\tduk_tval *tv;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\ttv = duk_get_tval_or_unused(thr, idx);\n\tDUK_ASSERT(tv != NULL);\n\tif (DUK_TVAL_IS_BUFFER(tv)) {\n\t\tduk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv);\n\t\tDUK_ASSERT(h != NULL);\n\t\treturn (DUK_HBUFFER_HAS_DYNAMIC(h) ? 0 : 1);\n\t}\n\treturn 0;\n}\n\nDUK_EXTERNAL duk_bool_t duk_is_dynamic_buffer(duk_hthread *thr, duk_idx_t idx) {\n\tduk_tval *tv;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\ttv = duk_get_tval_or_unused(thr, idx);\n\tDUK_ASSERT(tv != NULL);\n\tif (DUK_TVAL_IS_BUFFER(tv)) {\n\t\tduk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv);\n\t\tDUK_ASSERT(h != NULL);\n\t\treturn (DUK_HBUFFER_HAS_DYNAMIC(h) && !DUK_HBUFFER_HAS_EXTERNAL(h) ? 1 : 0);\n\t}\n\treturn 0;\n}\n\nDUK_EXTERNAL duk_bool_t duk_is_external_buffer(duk_hthread *thr, duk_idx_t idx) {\n\tduk_tval *tv;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\ttv = duk_get_tval_or_unused(thr, idx);\n\tDUK_ASSERT(tv != NULL);\n\tif (DUK_TVAL_IS_BUFFER(tv)) {\n\t\tduk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv);\n\t\tDUK_ASSERT(h != NULL);\n\t\treturn (DUK_HBUFFER_HAS_DYNAMIC(h) && DUK_HBUFFER_HAS_EXTERNAL(h) ? 1 : 0);\n\t}\n\treturn 0;\n}\n\nDUK_EXTERNAL duk_errcode_t duk_get_error_code(duk_hthread *thr, duk_idx_t idx) {\n\tduk_hobject *h;\n\tduk_uint_t sanity;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\th = duk_get_hobject(thr, idx);\n\n\tsanity = DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY;\n\tdo {\n\t\tif (!h) {\n\t\t\treturn DUK_ERR_NONE;\n\t\t}\n\n\t\t/* XXX: something more convenient? */\n\n\t\tif (h == thr->builtins[DUK_BIDX_EVAL_ERROR_PROTOTYPE]) {\n\t\t\treturn DUK_ERR_EVAL_ERROR;\n\t\t}\n\t\tif (h == thr->builtins[DUK_BIDX_RANGE_ERROR_PROTOTYPE]) {\n\t\t\treturn DUK_ERR_RANGE_ERROR;\n\t\t}\n\t\tif (h == thr->builtins[DUK_BIDX_REFERENCE_ERROR_PROTOTYPE]) {\n\t\t\treturn DUK_ERR_REFERENCE_ERROR;\n\t\t}\n\t\tif (h == thr->builtins[DUK_BIDX_SYNTAX_ERROR_PROTOTYPE]) {\n\t\t\treturn DUK_ERR_SYNTAX_ERROR;\n\t\t}\n\t\tif (h == thr->builtins[DUK_BIDX_TYPE_ERROR_PROTOTYPE]) {\n\t\t\treturn DUK_ERR_TYPE_ERROR;\n\t\t}\n\t\tif (h == thr->builtins[DUK_BIDX_URI_ERROR_PROTOTYPE]) {\n\t\t\treturn DUK_ERR_URI_ERROR;\n\t\t}\n\t\tif (h == thr->builtins[DUK_BIDX_ERROR_PROTOTYPE]) {\n\t\t\treturn DUK_ERR_ERROR;\n\t\t}\n\n\t\th = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h);\n\t} while (--sanity > 0);\n\n\treturn DUK_ERR_NONE;\n}\n\n/*\n *  Pushers\n */\n\nDUK_INTERNAL void duk_push_tval(duk_hthread *thr, duk_tval *tv) {\n\tduk_tval *tv_slot;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK_ASSERT(tv != NULL);\n\n\tDUK__CHECK_SPACE();\n\ttv_slot = thr->valstack_top++;\n\tDUK_TVAL_SET_TVAL(tv_slot, tv);\n\tDUK_TVAL_INCREF(thr, tv);  /* no side effects */\n}\n\nDUK_EXTERNAL void duk_push_undefined(duk_hthread *thr) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tDUK__CHECK_SPACE();\n\n\t/* Because value stack init policy is 'undefined above top',\n\t * we don't need to write, just assert.\n\t */\n\tthr->valstack_top++;\n\tDUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top - 1));\n}\n\nDUK_EXTERNAL void duk_push_null(duk_hthread *thr) {\n\tduk_tval *tv_slot;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK__CHECK_SPACE();\n\ttv_slot = thr->valstack_top++;\n\tDUK_TVAL_SET_NULL(tv_slot);\n}\n\nDUK_EXTERNAL void duk_push_boolean(duk_hthread *thr, duk_bool_t val) {\n\tduk_tval *tv_slot;\n\tduk_small_int_t b;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK__CHECK_SPACE();\n\tb = (val ? 1 : 0);  /* ensure value is 1 or 0 (not other non-zero) */\n\ttv_slot = thr->valstack_top++;\n\tDUK_TVAL_SET_BOOLEAN(tv_slot, b);\n}\n\nDUK_EXTERNAL void duk_push_true(duk_hthread *thr) {\n\tduk_tval *tv_slot;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK__CHECK_SPACE();\n\ttv_slot = thr->valstack_top++;\n\tDUK_TVAL_SET_BOOLEAN_TRUE(tv_slot);\n}\n\nDUK_EXTERNAL void duk_push_false(duk_hthread *thr) {\n\tduk_tval *tv_slot;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK__CHECK_SPACE();\n\ttv_slot = thr->valstack_top++;\n\tDUK_TVAL_SET_BOOLEAN_FALSE(tv_slot);\n}\n\n/* normalize NaN which may not match our canonical internal NaN */\nDUK_EXTERNAL void duk_push_number(duk_hthread *thr, duk_double_t val) {\n\tduk_tval *tv_slot;\n\tduk_double_union du;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK__CHECK_SPACE();\n\tdu.d = val;\n\tDUK_DBLUNION_NORMALIZE_NAN_CHECK(&du);\n\ttv_slot = thr->valstack_top++;\n\tDUK_TVAL_SET_NUMBER(tv_slot, du.d);\n}\n\nDUK_EXTERNAL void duk_push_int(duk_hthread *thr, duk_int_t val) {\n#if defined(DUK_USE_FASTINT)\n\tduk_tval *tv_slot;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK__CHECK_SPACE();\n\ttv_slot = thr->valstack_top++;\n#if DUK_INT_MAX <= 0x7fffffffL\n\tDUK_TVAL_SET_I32(tv_slot, (duk_int32_t) val);\n#else\n\tif (val >= DUK_FASTINT_MIN && val <= DUK_FASTINT_MAX) {\n\t\tDUK_TVAL_SET_FASTINT(tv_slot, (duk_int64_t) val);\n\t} else {\n\t\tduk_double_t = (duk_double_t) val;\n\t\tDUK_TVAL_SET_NUMBER(tv_slot, d);\n\t}\n#endif\n#else  /* DUK_USE_FASTINT */\n\tduk_tval *tv_slot;\n\tduk_double_t d;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK__CHECK_SPACE();\n\td = (duk_double_t) val;\n\ttv_slot = thr->valstack_top++;\n\tDUK_TVAL_SET_NUMBER(tv_slot, d);\n#endif  /* DUK_USE_FASTINT */\n}\n\nDUK_EXTERNAL void duk_push_uint(duk_hthread *thr, duk_uint_t val) {\n#if defined(DUK_USE_FASTINT)\n\tduk_tval *tv_slot;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK__CHECK_SPACE();\n\ttv_slot = thr->valstack_top++;\n#if DUK_UINT_MAX <= 0xffffffffUL\n\tDUK_TVAL_SET_U32(tv_slot, (duk_uint32_t) val);\n#else\n\tif (val <= DUK_FASTINT_MAX) {  /* val is unsigned so >= 0 */\n\t\t/* XXX: take advantage of val being unsigned, no need to mask */\n\t\tDUK_TVAL_SET_FASTINT(tv_slot, (duk_int64_t) val);\n\t} else {\n\t\tduk_double_t = (duk_double_t) val;\n\t\tDUK_TVAL_SET_NUMBER(tv_slot, d);\n\t}\n#endif\n#else  /* DUK_USE_FASTINT */\n\tduk_tval *tv_slot;\n\tduk_double_t d;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK__CHECK_SPACE();\n\td = (duk_double_t) val;\n\ttv_slot = thr->valstack_top++;\n\tDUK_TVAL_SET_NUMBER(tv_slot, d);\n#endif  /* DUK_USE_FASTINT */\n}\n\nDUK_EXTERNAL void duk_push_nan(duk_hthread *thr) {\n\tduk_tval *tv_slot;\n\tduk_double_union du;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK__CHECK_SPACE();\n\tDUK_DBLUNION_SET_NAN(&du);\n\tDUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&du));\n\ttv_slot = thr->valstack_top++;\n\tDUK_TVAL_SET_NUMBER(tv_slot, du.d);\n}\n\nDUK_EXTERNAL const char *duk_push_lstring(duk_hthread *thr, const char *str, duk_size_t len) {\n\tduk_hstring *h;\n\tduk_tval *tv_slot;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\t/* check stack before interning (avoid hanging temp) */\n\tDUK__CHECK_SPACE();\n\n\t/* NULL with zero length represents an empty string; NULL with higher\n\t * length is also now trated like an empty string although it is\n\t * a bit dubious.  This is unlike duk_push_string() which pushes a\n\t * 'null' if the input string is a NULL.\n\t */\n\tif (!str) {\n\t\tlen = 0;\n\t}\n\n\t/* Check for maximum string length */\n\tif (DUK_UNLIKELY(len > DUK_HSTRING_MAX_BYTELEN)) {\n\t\tDUK_ERROR_RANGE(thr, DUK_STR_STRING_TOO_LONG);\n\t}\n\n\th = duk_heap_strtable_intern_checked(thr, (const duk_uint8_t *) str, (duk_uint32_t) len);\n\tDUK_ASSERT(h != NULL);\n\n\ttv_slot = thr->valstack_top++;\n\tDUK_TVAL_SET_STRING(tv_slot, h);\n\tDUK_HSTRING_INCREF(thr, h);  /* no side effects */\n\n\treturn (const char *) DUK_HSTRING_GET_DATA(h);\n}\n\nDUK_EXTERNAL const char *duk_push_string(duk_hthread *thr, const char *str) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tif (str) {\n\t\treturn duk_push_lstring(thr, str, DUK_STRLEN(str));\n\t} else {\n\t\tduk_push_null(thr);\n\t\treturn NULL;\n\t}\n}\n\nDUK_EXTERNAL void duk_push_pointer(duk_hthread *thr, void *val) {\n\tduk_tval *tv_slot;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK__CHECK_SPACE();\n\ttv_slot = thr->valstack_top++;\n\tDUK_TVAL_SET_POINTER(tv_slot, val);\n}\n\nDUK_INTERNAL duk_hstring *duk_push_uint_to_hstring(duk_hthread *thr, duk_uint_t i) {\n\tduk_hstring *h_tmp;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\t/* XXX: this could be a direct DUK_SPRINTF to a buffer followed by duk_push_string() */\n\tduk_push_uint(thr, (duk_uint_t) i);\n\th_tmp = duk_to_hstring_m1(thr);\n\tDUK_ASSERT(h_tmp != NULL);\n\treturn h_tmp;\n}\n\nDUK_LOCAL void duk__push_this_helper(duk_hthread *thr, duk_small_uint_t check_object_coercible) {\n\tduk_tval *tv_slot;\n\n\tDUK__CHECK_SPACE();\n\n\tDUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top));  /* because of valstack init policy */\n\ttv_slot = thr->valstack_top++;\n\n\tif (DUK_UNLIKELY(thr->callstack_curr == NULL)) {\n\t\tif (check_object_coercible) {\n\t\t\tgoto type_error;\n\t\t}\n\t\t/* 'undefined' already on stack top */\n\t} else {\n\t\tduk_tval *tv;\n\n\t\t/* 'this' binding is just before current activation's bottom */\n\t\tDUK_ASSERT(thr->valstack_bottom > thr->valstack);\n\t\ttv = thr->valstack_bottom - 1;\n\t\tif (check_object_coercible &&\n\t\t    (DUK_TVAL_IS_UNDEFINED(tv) || DUK_TVAL_IS_NULL(tv))) {\n\t\t\t/* XXX: better macro for DUK_TVAL_IS_UNDEFINED_OR_NULL(tv) */\n\t\t\tgoto type_error;\n\t\t}\n\n\t\tDUK_TVAL_SET_TVAL(tv_slot, tv);\n\t\tDUK_TVAL_INCREF(thr, tv);\n\t}\n\treturn;\n\n type_error:\n\tDUK_ERROR_TYPE(thr, DUK_STR_NOT_OBJECT_COERCIBLE);\n}\n\nDUK_EXTERNAL void duk_push_this(duk_hthread *thr) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tduk__push_this_helper(thr, 0 /*check_object_coercible*/);\n}\n\nDUK_INTERNAL void duk_push_this_check_object_coercible(duk_hthread *thr) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tduk__push_this_helper(thr, 1 /*check_object_coercible*/);\n}\n\nDUK_INTERNAL duk_hobject *duk_push_this_coercible_to_object(duk_hthread *thr) {\n\tduk_hobject *h;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tduk__push_this_helper(thr, 1 /*check_object_coercible*/);\n\th = duk_to_hobject(thr, -1);\n\tDUK_ASSERT(h != NULL);\n\treturn h;\n}\n\nDUK_INTERNAL duk_hstring *duk_push_this_coercible_to_string(duk_hthread *thr) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tduk__push_this_helper(thr, 1 /*check_object_coercible*/);\n\treturn duk_to_hstring_m1(thr);  /* This will reject all Symbol values; accepts Symbol objects. */\n}\n\nDUK_INTERNAL duk_tval *duk_get_borrowed_this_tval(duk_hthread *thr) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tDUK_ASSERT(thr->callstack_top > 0);  /* caller required to know */\n\tDUK_ASSERT(thr->callstack_curr != NULL);  /* caller required to know */\n\tDUK_ASSERT(thr->valstack_bottom > thr->valstack);  /* consequence of above */\n\tDUK_ASSERT(thr->valstack_bottom - 1 >= thr->valstack);  /* 'this' binding exists */\n\n\treturn thr->valstack_bottom - 1;\n}\n\nDUK_EXTERNAL void duk_push_current_function(duk_hthread *thr) {\n\tduk_activation *act;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tact = thr->callstack_curr;\n\tif (act != NULL) {\n\t\tduk_push_tval(thr, &act->tv_func);\n\t} else {\n\t\tduk_push_undefined(thr);\n\t}\n}\n\nDUK_EXTERNAL void duk_push_current_thread(duk_hthread *thr) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tif (thr->heap->curr_thread) {\n\t\tduk_push_hobject(thr, (duk_hobject *) thr->heap->curr_thread);\n\t} else {\n\t\tduk_push_undefined(thr);\n\t}\n}\n\nDUK_EXTERNAL void duk_push_global_object(duk_hthread *thr) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tduk_push_hobject_bidx(thr, DUK_BIDX_GLOBAL);\n}\n\n/* XXX: size optimize */\nDUK_LOCAL void duk__push_stash(duk_hthread *thr) {\n\tif (!duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INT_VALUE)) {\n\t\tDUK_DDD(DUK_DDDPRINT(\"creating heap/global/thread stash on first use\"));\n\t\tduk_pop_unsafe(thr);\n\t\tduk_push_bare_object(thr);\n\t\tduk_dup_top(thr);\n\t\tduk_xdef_prop_stridx_short(thr, -3, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_C);  /* [ ... parent stash stash ] -> [ ... parent stash ] */\n\t}\n\tduk_remove_m2(thr);\n}\n\nDUK_EXTERNAL void duk_push_heap_stash(duk_hthread *thr) {\n\tduk_heap *heap;\n\tDUK_ASSERT_API_ENTRY(thr);\n\theap = thr->heap;\n\tDUK_ASSERT(heap->heap_object != NULL);\n\tduk_push_hobject(thr, heap->heap_object);\n\tduk__push_stash(thr);\n}\n\nDUK_EXTERNAL void duk_push_global_stash(duk_hthread *thr) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\tduk_push_global_object(thr);\n\tduk__push_stash(thr);\n}\n\nDUK_EXTERNAL void duk_push_thread_stash(duk_hthread *thr, duk_hthread *target_thr) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\tif (DUK_UNLIKELY(target_thr == NULL)) {\n\t\tDUK_ERROR_TYPE_INVALID_ARGS(thr);\n\t\treturn;  /* not reached */\n\t}\n\tduk_push_hobject(thr, (duk_hobject *) target_thr);\n\tduk__push_stash(thr);\n}\n\n/* XXX: duk_ssize_t would be useful here */\nDUK_LOCAL duk_int_t duk__try_push_vsprintf(duk_hthread *thr, void *buf, duk_size_t sz, const char *fmt, va_list ap) {\n\tduk_int_t len;\n\n\tDUK_ASSERT_CTX_VALID(thr);\n\tDUK_UNREF(thr);\n\n\t/* NUL terminator handling doesn't matter here */\n\tlen = DUK_VSNPRINTF((char *) buf, sz, fmt, ap);\n\tif (len < (duk_int_t) sz) {\n\t\t/* Return value of 'sz' or more indicates output was (potentially)\n\t\t * truncated.\n\t\t */\n\t\treturn (duk_int_t) len;\n\t}\n\treturn -1;\n}\n\nDUK_EXTERNAL const char *duk_push_vsprintf(duk_hthread *thr, const char *fmt, va_list ap) {\n\tduk_uint8_t stack_buf[DUK_PUSH_SPRINTF_INITIAL_SIZE];\n\tduk_size_t sz = DUK_PUSH_SPRINTF_INITIAL_SIZE;\n\tduk_bool_t pushed_buf = 0;\n\tvoid *buf;\n\tduk_int_t len;  /* XXX: duk_ssize_t */\n\tconst char *res;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\t/* special handling of fmt==NULL */\n\tif (!fmt) {\n\t\tduk_hstring *h_str;\n\t\tduk_push_hstring_empty(thr);\n\t\th_str = duk_known_hstring(thr, -1);\n\t\treturn (const char *) DUK_HSTRING_GET_DATA(h_str);\n\t}\n\n\t/* initial estimate based on format string */\n\tsz = DUK_STRLEN(fmt) + 16;  /* format plus something to avoid just missing */\n\tif (sz < DUK_PUSH_SPRINTF_INITIAL_SIZE) {\n\t\tsz = DUK_PUSH_SPRINTF_INITIAL_SIZE;\n\t}\n\tDUK_ASSERT(sz > 0);\n\n\t/* Try to make do with a stack buffer to avoid allocating a temporary buffer.\n\t * This works 99% of the time which is quite nice.\n\t */\n\tfor (;;) {\n\t\tva_list ap_copy;  /* copied so that 'ap' can be reused */\n\n\t\tif (sz <= sizeof(stack_buf)) {\n\t\t\tbuf = stack_buf;\n\t\t} else if (!pushed_buf) {\n\t\t\tpushed_buf = 1;\n\t\t\tbuf = duk_push_dynamic_buffer(thr, sz);\n\t\t} else {\n\t\t\tbuf = duk_resize_buffer(thr, -1, sz);\n\t\t}\n\t\tDUK_ASSERT(buf != NULL);\n\n\t\tDUK_VA_COPY(ap_copy, ap);\n\t\tlen = duk__try_push_vsprintf(thr, buf, sz, fmt, ap_copy);\n\t\tva_end(ap_copy);\n\t\tif (len >= 0) {\n\t\t\tbreak;\n\t\t}\n\n\t\t/* failed, resize and try again */\n\t\tsz = sz * 2;\n\t\tif (DUK_UNLIKELY(sz >= DUK_PUSH_SPRINTF_SANITY_LIMIT)) {\n\t\t\tDUK_ERROR_RANGE(thr, DUK_STR_RESULT_TOO_LONG);\n\t\t}\n\t}\n\n\t/* Cannot use duk_buffer_to_string() on the buffer because it is\n\t * usually larger than 'len'; 'buf' is also usually a stack buffer.\n\t */\n\tres = duk_push_lstring(thr, (const char *) buf, (duk_size_t) len);  /* [ buf? res ] */\n\tif (pushed_buf) {\n\t\tduk_remove_m2(thr);\n\t}\n\treturn res;\n}\n\nDUK_EXTERNAL const char *duk_push_sprintf(duk_hthread *thr, const char *fmt, ...) {\n\tva_list ap;\n\tconst char *ret;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\t/* allow fmt==NULL */\n\tva_start(ap, fmt);\n\tret = duk_push_vsprintf(thr, fmt, ap);\n\tva_end(ap);\n\n\treturn ret;\n}\n\nDUK_INTERNAL duk_hobject *duk_push_object_helper(duk_hthread *thr, duk_uint_t hobject_flags_and_class, duk_small_int_t prototype_bidx) {\n\tduk_tval *tv_slot;\n\tduk_hobject *h;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK_ASSERT(prototype_bidx == -1 ||\n\t           (prototype_bidx >= 0 && prototype_bidx < DUK_NUM_BUILTINS));\n\n\tDUK__CHECK_SPACE();\n\n\th = duk_hobject_alloc(thr, hobject_flags_and_class);\n\tDUK_ASSERT(h != NULL);\n\n\tDUK_DDD(DUK_DDDPRINT(\"created object with flags: 0x%08lx\", (unsigned long) h->hdr.h_flags));\n\n\ttv_slot = thr->valstack_top;\n\tDUK_TVAL_SET_OBJECT(tv_slot, h);\n\tDUK_HOBJECT_INCREF(thr, h);  /* no side effects */\n\tthr->valstack_top++;\n\n\t/* object is now reachable */\n\n\tif (prototype_bidx >= 0) {\n\t\tDUK_HOBJECT_SET_PROTOTYPE_INIT_INCREF(thr, h, thr->builtins[prototype_bidx]);\n\t} else {\n\t\tDUK_ASSERT(prototype_bidx == -1);\n\t\tDUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h) == NULL);\n\t}\n\n\treturn h;\n}\n\nDUK_INTERNAL duk_hobject *duk_push_object_helper_proto(duk_hthread *thr, duk_uint_t hobject_flags_and_class, duk_hobject *proto) {\n\tduk_hobject *h;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\th = duk_push_object_helper(thr, hobject_flags_and_class, -1);\n\tDUK_ASSERT(h != NULL);\n\tDUK_HOBJECT_SET_PROTOTYPE_INIT_INCREF(thr, h, proto);\n\treturn h;\n}\n\nDUK_EXTERNAL duk_idx_t duk_push_object(duk_hthread *thr) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\t(void) duk_push_object_helper(thr,\n\t                              DUK_HOBJECT_FLAG_EXTENSIBLE |\n\t                              DUK_HOBJECT_FLAG_FASTREFS |\n\t                              DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT),\n\t                              DUK_BIDX_OBJECT_PROTOTYPE);\n\treturn duk_get_top_index_unsafe(thr);\n}\n\nDUK_EXTERNAL duk_idx_t duk_push_array(duk_hthread *thr) {\n\tduk_uint_t flags;\n\tduk_harray *obj;\n\tduk_idx_t ret;\n\tduk_tval *tv_slot;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tflags = DUK_HOBJECT_FLAG_EXTENSIBLE |\n\t        DUK_HOBJECT_FLAG_FASTREFS |\n\t        DUK_HOBJECT_FLAG_ARRAY_PART |\n\t        DUK_HOBJECT_FLAG_EXOTIC_ARRAY |\n\t        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ARRAY);\n\n\tobj = duk_harray_alloc(thr, flags);\n\tDUK_ASSERT(obj != NULL);\n\n\tDUK_HOBJECT_SET_PROTOTYPE_INIT_INCREF(thr, (duk_hobject *) obj, thr->builtins[DUK_BIDX_ARRAY_PROTOTYPE]);\n\n\ttv_slot = thr->valstack_top;\n\tDUK_TVAL_SET_OBJECT(tv_slot, (duk_hobject *) obj);\n\tDUK_HOBJECT_INCREF(thr, obj);  /* XXX: could preallocate with refcount = 1 */\n\tret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);\n\tthr->valstack_top++;\n\n\tDUK_ASSERT(obj->length == 0);  /* Array .length starts at zero. */\n\treturn ret;\n}\n\nDUK_INTERNAL duk_harray *duk_push_harray(duk_hthread *thr) {\n\t/* XXX: API call could do this directly, cast to void in API macro. */\n\tduk_harray *a;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\t(void) duk_push_array(thr);\n\tDUK_ASSERT(DUK_TVAL_IS_OBJECT(thr->valstack_top - 1));\n\ta = (duk_harray *) DUK_TVAL_GET_OBJECT(thr->valstack_top - 1);\n\tDUK_ASSERT(a != NULL);\n\treturn a;\n}\n\n/* Push a duk_harray with preallocated size (.length also set to match size).\n * Caller may then populate array part of the duk_harray directly.\n */\nDUK_INTERNAL duk_harray *duk_push_harray_with_size(duk_hthread *thr, duk_uint32_t size) {\n\tduk_harray *a;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\ta = duk_push_harray(thr);\n\n\tduk_hobject_realloc_props(thr,\n\t                          (duk_hobject *) a,\n\t                          0,\n\t                          size,\n\t                          0,\n\t                          0);\n\ta->length = size;\n\treturn a;\n}\n\nDUK_INTERNAL duk_tval *duk_push_harray_with_size_outptr(duk_hthread *thr, duk_uint32_t size) {\n\tduk_harray *a;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\ta = duk_push_harray_with_size(thr, size);\n\tDUK_ASSERT(a != NULL);\n\treturn DUK_HOBJECT_A_GET_BASE(thr->heap, (duk_hobject *) a);\n}\n\nDUK_EXTERNAL duk_idx_t duk_push_thread_raw(duk_hthread *thr, duk_uint_t flags) {\n\tduk_hthread *obj;\n\tduk_idx_t ret;\n\tduk_tval *tv_slot;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tDUK__CHECK_SPACE();\n\n\tobj = duk_hthread_alloc(thr,\n\t                        DUK_HOBJECT_FLAG_EXTENSIBLE |\n\t                        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_THREAD));\n\tDUK_ASSERT(obj != NULL);\n\tobj->state = DUK_HTHREAD_STATE_INACTIVE;\n#if defined(DUK_USE_ROM_STRINGS)\n\t/* Nothing to initialize, strs[] is in ROM. */\n#else\n#if defined(DUK_USE_HEAPPTR16)\n\tobj->strs16 = thr->strs16;\n#else\n\tobj->strs = thr->strs;\n#endif\n#endif\n\tDUK_DDD(DUK_DDDPRINT(\"created thread object with flags: 0x%08lx\", (unsigned long) obj->obj.hdr.h_flags));\n\n\t/* make the new thread reachable */\n\ttv_slot = thr->valstack_top;\n\tDUK_TVAL_SET_OBJECT(tv_slot, (duk_hobject *) obj);\n\tDUK_HTHREAD_INCREF(thr, obj);\n\tret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);\n\tthr->valstack_top++;\n\n\t/* important to do this *after* pushing, to make the thread reachable for gc */\n\tif (DUK_UNLIKELY(!duk_hthread_init_stacks(thr->heap, obj))) {\n\t\tDUK_ERROR_ALLOC_FAILED(thr);\n\t}\n\n\t/* initialize built-ins - either by copying or creating new ones */\n\tif (flags & DUK_THREAD_NEW_GLOBAL_ENV) {\n\t\tduk_hthread_create_builtin_objects(obj);\n\t} else {\n\t\tduk_hthread_copy_builtin_objects(thr, obj);\n\t}\n\n\t/* default prototype */\n\tDUK_HOBJECT_SET_PROTOTYPE_INIT_INCREF(thr, (duk_hobject *) obj, obj->builtins[DUK_BIDX_THREAD_PROTOTYPE]);\n\n\t/* Initial stack size satisfies the stack slack constraints so there\n\t * is no need to require stack here.\n\t */\n\tDUK_ASSERT(DUK_VALSTACK_INITIAL_SIZE >=\n\t           DUK_VALSTACK_API_ENTRY_MINIMUM + DUK_VALSTACK_INTERNAL_EXTRA);\n\n\treturn ret;\n}\n\nDUK_INTERNAL duk_hcompfunc *duk_push_hcompfunc(duk_hthread *thr) {\n\tduk_hcompfunc *obj;\n\tduk_tval *tv_slot;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tDUK__CHECK_SPACE();\n\n\t/* Template functions are not strictly constructable (they don't\n\t * have a \"prototype\" property for instance), so leave the\n\t * DUK_HOBJECT_FLAG_CONSRUCTABLE flag cleared here.\n\t */\n\n\tobj = duk_hcompfunc_alloc(thr,\n\t                          DUK_HOBJECT_FLAG_EXTENSIBLE |\n\t                          DUK_HOBJECT_FLAG_CALLABLE |\n\t                          DUK_HOBJECT_FLAG_COMPFUNC |\n\t                          DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_FUNCTION));\n\tif (DUK_UNLIKELY(obj == NULL)) {\n\t\tDUK_ERROR_ALLOC_FAILED(thr);\n\t}\n\n\tDUK_DDD(DUK_DDDPRINT(\"created compiled function object with flags: 0x%08lx\", (unsigned long) obj->obj.hdr.h_flags));\n\n\ttv_slot = thr->valstack_top;\n\tDUK_TVAL_SET_OBJECT(tv_slot, (duk_hobject *) obj);\n\tDUK_HOBJECT_INCREF(thr, obj);\n\tthr->valstack_top++;\n\n\t/* default prototype */\n\tDUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) obj) == NULL);\n\tDUK_HOBJECT_SET_PROTOTYPE_INIT_INCREF(thr, (duk_hobject *) obj, thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]);\n\n\treturn obj;\n}\n\nDUK_INTERNAL duk_hboundfunc *duk_push_hboundfunc(duk_hthread *thr) {\n\tduk_hboundfunc *obj;\n\tduk_tval *tv_slot;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tDUK__CHECK_SPACE();\n\tobj = duk_hboundfunc_alloc(thr->heap,\n\t                           DUK_HOBJECT_FLAG_EXTENSIBLE |\n\t                           DUK_HOBJECT_FLAG_BOUNDFUNC |\n\t                           DUK_HOBJECT_FLAG_CONSTRUCTABLE |\n\t                           DUK_HOBJECT_FLAG_CALLABLE |\n\t                           DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_FUNCTION));\n\tif (!obj) {\n\t\tDUK_ERROR_ALLOC_FAILED(thr);\n\t}\n\n\ttv_slot = thr->valstack_top++;\n\tDUK_TVAL_SET_OBJECT(tv_slot, (duk_hobject *) obj);\n\tDUK_HOBJECT_INCREF(thr, obj);\n\n\t/* Prototype is left as NULL because the caller always sets it (and\n\t * it depends on the target function).\n\t */\n\tDUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) obj) == NULL);\n\n\treturn obj;\n}\n\nDUK_LOCAL duk_idx_t duk__push_c_function_raw(duk_hthread *thr, duk_c_function func, duk_idx_t nargs, duk_uint_t flags, duk_small_uint_t proto_bidx) {\n\tduk_hnatfunc *obj;\n\tduk_idx_t ret;\n\tduk_tval *tv_slot;\n\tduk_int16_t func_nargs;\n\n\tDUK_ASSERT_CTX_VALID(thr);\n\n\tDUK__CHECK_SPACE();\n\n\tif (DUK_UNLIKELY(func == NULL)) {\n\t\tgoto api_error;\n\t}\n\tif (nargs >= 0 && nargs < DUK_HNATFUNC_NARGS_MAX) {\n\t\tfunc_nargs = (duk_int16_t) nargs;\n\t} else if (nargs == DUK_VARARGS) {\n\t\tfunc_nargs = DUK_HNATFUNC_NARGS_VARARGS;\n\t} else {\n\t\tgoto api_error;\n\t}\n\n\tobj = duk_hnatfunc_alloc(thr, flags);\n\tDUK_ASSERT(obj != NULL);\n\n\tobj->func = func;\n\tobj->nargs = func_nargs;\n\n\tDUK_DDD(DUK_DDDPRINT(\"created native function object with flags: 0x%08lx, nargs=%ld\",\n\t                     (unsigned long) obj->obj.hdr.h_flags, (long) obj->nargs));\n\n\ttv_slot = thr->valstack_top;\n\tDUK_TVAL_SET_OBJECT(tv_slot, (duk_hobject *) obj);\n\tDUK_HOBJECT_INCREF(thr, obj);\n\tret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);\n\tthr->valstack_top++;\n\n\tDUK_ASSERT_BIDX_VALID(proto_bidx);\n\tDUK_HOBJECT_SET_PROTOTYPE_INIT_INCREF(thr, (duk_hobject *) obj, thr->builtins[proto_bidx]);\n\treturn ret;\n\n api_error:\n\tDUK_ERROR_TYPE_INVALID_ARGS(thr);\n\treturn 0;  /* not reached */\n}\n\nDUK_EXTERNAL duk_idx_t duk_push_c_function(duk_hthread *thr, duk_c_function func, duk_int_t nargs) {\n\tduk_uint_t flags;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tflags = DUK_HOBJECT_FLAG_EXTENSIBLE |\n\t        DUK_HOBJECT_FLAG_CONSTRUCTABLE |\n\t        DUK_HOBJECT_FLAG_CALLABLE |\n\t        DUK_HOBJECT_FLAG_FASTREFS |\n\t        DUK_HOBJECT_FLAG_NATFUNC |\n\t        DUK_HOBJECT_FLAG_NEWENV |\n\t        DUK_HOBJECT_FLAG_STRICT |\n\t        DUK_HOBJECT_FLAG_NOTAIL |\n\t        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_FUNCTION);\n\n\t/* Default prototype is a Duktape specific %NativeFunctionPrototype%\n\t * which provides .length and .name getters.\n\t */\n\treturn duk__push_c_function_raw(thr, func, nargs, flags, DUK_BIDX_NATIVE_FUNCTION_PROTOTYPE);\n}\n\nDUK_INTERNAL void duk_push_c_function_builtin(duk_hthread *thr, duk_c_function func, duk_int_t nargs) {\n\tduk_uint_t flags;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tflags = DUK_HOBJECT_FLAG_EXTENSIBLE |\n\t        DUK_HOBJECT_FLAG_CONSTRUCTABLE |\n\t        DUK_HOBJECT_FLAG_CALLABLE |\n\t        DUK_HOBJECT_FLAG_FASTREFS |\n\t        DUK_HOBJECT_FLAG_NATFUNC |\n\t        DUK_HOBJECT_FLAG_NEWENV |\n\t        DUK_HOBJECT_FLAG_STRICT |\n\t        DUK_HOBJECT_FLAG_NOTAIL |\n\t        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_FUNCTION);\n\n\t/* Must use Function.prototype for standard built-in functions. */\n\t(void) duk__push_c_function_raw(thr, func, nargs, flags, DUK_BIDX_FUNCTION_PROTOTYPE);\n}\n\nDUK_INTERNAL void duk_push_c_function_builtin_noconstruct(duk_hthread *thr, duk_c_function func, duk_int_t nargs) {\n\tduk_uint_t flags;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tflags = DUK_HOBJECT_FLAG_EXTENSIBLE |\n\t        DUK_HOBJECT_FLAG_CALLABLE |\n\t        DUK_HOBJECT_FLAG_FASTREFS |\n\t        DUK_HOBJECT_FLAG_NATFUNC |\n\t        DUK_HOBJECT_FLAG_NEWENV |\n\t        DUK_HOBJECT_FLAG_STRICT |\n\t        DUK_HOBJECT_FLAG_NOTAIL |\n\t        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_FUNCTION);\n\n\t/* Must use Function.prototype for standard built-in functions. */\n\t(void) duk__push_c_function_raw(thr, func, nargs, flags, DUK_BIDX_FUNCTION_PROTOTYPE);\n}\n\nDUK_EXTERNAL duk_idx_t duk_push_c_lightfunc(duk_hthread *thr, duk_c_function func, duk_idx_t nargs, duk_idx_t length, duk_int_t magic) {\n\tduk_small_uint_t lf_flags;\n\tduk_tval *tv_slot;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tDUK__CHECK_SPACE();\n\n\tif (nargs >= DUK_LFUNC_NARGS_MIN && nargs <= DUK_LFUNC_NARGS_MAX) {\n\t\t/* as is */\n\t} else if (nargs == DUK_VARARGS) {\n\t\tnargs = DUK_LFUNC_NARGS_VARARGS;\n\t} else {\n\t\tgoto api_error;\n\t}\n\tif (DUK_UNLIKELY(!(length >= DUK_LFUNC_LENGTH_MIN && length <= DUK_LFUNC_LENGTH_MAX))) {\n\t\tgoto api_error;\n\t}\n\tif (DUK_UNLIKELY(!(magic >= DUK_LFUNC_MAGIC_MIN && magic <= DUK_LFUNC_MAGIC_MAX))) {\n\t\tgoto api_error;\n\t}\n\n\tlf_flags = DUK_LFUNC_FLAGS_PACK((duk_small_int_t) magic, (duk_small_uint_t) length, (duk_small_uint_t) nargs);\n\ttv_slot = thr->valstack_top++;\n\tDUK_ASSERT(DUK_TVAL_IS_UNDEFINED(tv_slot));\n\tDUK_TVAL_SET_LIGHTFUNC(tv_slot, func, lf_flags);\n\tDUK_ASSERT(tv_slot >= thr->valstack_bottom);\n\treturn (duk_idx_t) (tv_slot - thr->valstack_bottom);\n\n api_error:\n\tDUK_ERROR_TYPE_INVALID_ARGS(thr);\n\treturn 0;  /* not reached */\n}\n\n#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)\nDUK_INTERNAL duk_hbufobj *duk_push_bufobj_raw(duk_hthread *thr, duk_uint_t hobject_flags_and_class, duk_small_int_t prototype_bidx) {\n\tduk_hbufobj *obj;\n\tduk_tval *tv_slot;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK_ASSERT(prototype_bidx >= 0);\n\n\tDUK__CHECK_SPACE();\n\n\tobj = duk_hbufobj_alloc(thr, hobject_flags_and_class);\n\tDUK_ASSERT(obj != NULL);\n\n\tDUK_HOBJECT_SET_PROTOTYPE_INIT_INCREF(thr, (duk_hobject *) obj, thr->builtins[prototype_bidx]);\n\tDUK_ASSERT_HBUFOBJ_VALID(obj);\n\n\ttv_slot = thr->valstack_top;\n\tDUK_TVAL_SET_OBJECT(tv_slot, (duk_hobject *) obj);\n\tDUK_HOBJECT_INCREF(thr, obj);\n\tthr->valstack_top++;\n\n\treturn obj;\n}\n#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */\n\n/* XXX: There's quite a bit of overlap with buffer creation handling in\n * duk_bi_buffer.c.  Look for overlap and refactor.\n */\n#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)\n#define DUK__PACK_ARGS(classnum,protobidx,elemtype,elemshift,istypedarray) \\\n\t(((classnum) << 24) | ((protobidx) << 16) | ((elemtype) << 8) | ((elemshift) << 4) | (istypedarray))\n\nstatic const duk_uint32_t duk__bufobj_flags_lookup[] = {\n\t/* Node.js Buffers are Uint8Array instances which inherit from Buffer.prototype. */\n\tDUK__PACK_ARGS(DUK_HOBJECT_CLASS_ARRAYBUFFER,       DUK_BIDX_ARRAYBUFFER_PROTOTYPE,       DUK_HBUFOBJ_ELEM_UINT8,        0, 0),  /* DUK_BUFOBJ_ARRAYBUFFER */\n\tDUK__PACK_ARGS(DUK_HOBJECT_CLASS_UINT8ARRAY,        DUK_BIDX_NODEJS_BUFFER_PROTOTYPE,     DUK_HBUFOBJ_ELEM_UINT8,        0, 1),  /* DUK_BUFOBJ_NODEJS_BUFFER */\n\tDUK__PACK_ARGS(DUK_HOBJECT_CLASS_DATAVIEW,          DUK_BIDX_DATAVIEW_PROTOTYPE,          DUK_HBUFOBJ_ELEM_UINT8,        0, 0),  /* DUK_BUFOBJ_DATAVIEW */\n\tDUK__PACK_ARGS(DUK_HOBJECT_CLASS_INT8ARRAY,         DUK_BIDX_INT8ARRAY_PROTOTYPE,         DUK_HBUFOBJ_ELEM_INT8,         0, 1),  /* DUK_BUFOBJ_INT8ARRAY */\n\tDUK__PACK_ARGS(DUK_HOBJECT_CLASS_UINT8ARRAY,        DUK_BIDX_UINT8ARRAY_PROTOTYPE,        DUK_HBUFOBJ_ELEM_UINT8,        0, 1),  /* DUK_BUFOBJ_UINT8ARRAY */\n\tDUK__PACK_ARGS(DUK_HOBJECT_CLASS_UINT8CLAMPEDARRAY, DUK_BIDX_UINT8CLAMPEDARRAY_PROTOTYPE, DUK_HBUFOBJ_ELEM_UINT8CLAMPED, 0, 1),  /* DUK_BUFOBJ_UINT8CLAMPEDARRAY */\n\tDUK__PACK_ARGS(DUK_HOBJECT_CLASS_INT16ARRAY,        DUK_BIDX_INT16ARRAY_PROTOTYPE,        DUK_HBUFOBJ_ELEM_INT16,        1, 1),  /* DUK_BUFOBJ_INT16ARRAY */\n\tDUK__PACK_ARGS(DUK_HOBJECT_CLASS_UINT16ARRAY,       DUK_BIDX_UINT16ARRAY_PROTOTYPE,       DUK_HBUFOBJ_ELEM_UINT16,       1, 1),  /* DUK_BUFOBJ_UINT16ARRAY */\n\tDUK__PACK_ARGS(DUK_HOBJECT_CLASS_INT32ARRAY,        DUK_BIDX_INT32ARRAY_PROTOTYPE,        DUK_HBUFOBJ_ELEM_INT32,        2, 1),  /* DUK_BUFOBJ_INT32ARRAY */\n\tDUK__PACK_ARGS(DUK_HOBJECT_CLASS_UINT32ARRAY,       DUK_BIDX_UINT32ARRAY_PROTOTYPE,       DUK_HBUFOBJ_ELEM_UINT32,       2, 1),  /* DUK_BUFOBJ_UINT32ARRAY */\n\tDUK__PACK_ARGS(DUK_HOBJECT_CLASS_FLOAT32ARRAY,      DUK_BIDX_FLOAT32ARRAY_PROTOTYPE,      DUK_HBUFOBJ_ELEM_FLOAT32,      2, 1),  /* DUK_BUFOBJ_FLOAT32ARRAY */\n\tDUK__PACK_ARGS(DUK_HOBJECT_CLASS_FLOAT64ARRAY,      DUK_BIDX_FLOAT64ARRAY_PROTOTYPE,      DUK_HBUFOBJ_ELEM_FLOAT64,      3, 1)   /* DUK_BUFOBJ_FLOAT64ARRAY */\n};\n#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */\n\n#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)\nDUK_EXTERNAL void duk_push_buffer_object(duk_hthread *thr, duk_idx_t idx_buffer, duk_size_t byte_offset, duk_size_t byte_length, duk_uint_t flags) {\n\tduk_hbufobj *h_bufobj;\n\tduk_hbuffer *h_val;\n\tduk_hobject *h_arraybuf;\n\tduk_uint32_t tmp;\n\tduk_uint_t classnum;\n\tduk_uint_t protobidx;\n\tduk_uint_t lookupidx;\n\tduk_uint_t uint_offset, uint_length, uint_added;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\t/* The underlying types for offset/length in duk_hbufobj is\n\t * duk_uint_t; make sure argument values fit.\n\t */\n\tuint_offset = (duk_uint_t) byte_offset;\n\tuint_length = (duk_uint_t) byte_length;\n\tif (sizeof(duk_size_t) != sizeof(duk_uint_t)) {\n\t\tif (DUK_UNLIKELY((duk_size_t) uint_offset != byte_offset || (duk_size_t) uint_length != byte_length)) {\n\t\t\tgoto range_error;\n\t\t}\n\t}\n\n\tDUK_ASSERT_DISABLE(flags >= 0);  /* flags is unsigned */\n\tlookupidx = flags;\n\tif (DUK_UNLIKELY(lookupidx >= sizeof(duk__bufobj_flags_lookup) / sizeof(duk_uint32_t))) {\n\t\tgoto arg_error;\n\t}\n\ttmp = duk__bufobj_flags_lookup[lookupidx];\n\tclassnum = tmp >> 24;\n\tprotobidx = (tmp >> 16) & 0xff;\n\n\th_arraybuf = duk_get_hobject(thr, idx_buffer);\n\tif (h_arraybuf != NULL &&  /* argument is an object */\n\t    flags != DUK_BUFOBJ_ARRAYBUFFER &&  /* creating a view */\n\t    DUK_HOBJECT_GET_CLASS_NUMBER(h_arraybuf) == DUK_HOBJECT_CLASS_ARRAYBUFFER  /* argument is ArrayBuffer */) {\n\t\tduk_uint_t tmp_offset;\n\n\t\tDUK_ASSERT_HBUFOBJ_VALID((duk_hbufobj *) h_arraybuf);\n\t\th_val = ((duk_hbufobj *) h_arraybuf)->buf;\n\t\tif (DUK_UNLIKELY(h_val == NULL)) {\n\t\t\tgoto arg_error;\n\t\t}\n\n\t\ttmp_offset = uint_offset + ((duk_hbufobj *) h_arraybuf)->offset;\n\t\tif (DUK_UNLIKELY(tmp_offset < uint_offset)) {\n\t\t\tgoto range_error;\n\t\t}\n\t\tuint_offset = tmp_offset;\n\n\t\t/* Note intentional difference to new TypedArray(): we allow\n\t\t * caller to create an uncovered typed array (which is memory\n\t\t * safe); new TypedArray() rejects it.\n\t\t */\n\t} else {\n\t\t/* Handle unexpected object arguments here too, for nice error\n\t\t * messages.\n\t\t */\n\t\th_arraybuf = NULL;\n\t\th_val = duk_require_hbuffer(thr, idx_buffer);\n\t}\n\n\t/* Wrap check for offset+length. */\n\tuint_added = uint_offset + uint_length;\n\tif (DUK_UNLIKELY(uint_added < uint_offset)) {\n\t\tgoto range_error;\n\t}\n\tDUK_ASSERT(uint_added >= uint_offset && uint_added >= uint_length);\n\n\tDUK_ASSERT(h_val != NULL);\n\n\th_bufobj = duk_push_bufobj_raw(thr,\n\t                               DUK_HOBJECT_FLAG_EXTENSIBLE |\n\t                               DUK_HOBJECT_FLAG_BUFOBJ |\n\t                               DUK_HOBJECT_CLASS_AS_FLAGS(classnum),\n\t                               (duk_small_int_t) protobidx);\n\tDUK_ASSERT(h_bufobj != NULL);\n\n\th_bufobj->buf = h_val;\n\tDUK_HBUFFER_INCREF(thr, h_val);\n\th_bufobj->buf_prop = h_arraybuf;\n\tDUK_HOBJECT_INCREF_ALLOWNULL(thr, h_arraybuf);\n\th_bufobj->offset = uint_offset;\n\th_bufobj->length = uint_length;\n\th_bufobj->shift = (tmp >> 4) & 0x0f;\n\th_bufobj->elem_type = (tmp >> 8) & 0xff;\n\th_bufobj->is_typedarray = tmp & 0x0f;\n\tDUK_ASSERT_HBUFOBJ_VALID(h_bufobj);\n\n\t/* TypedArray views need an automatic ArrayBuffer which must be\n\t * provided as .buffer property of the view.  The ArrayBuffer is\n\t * referenced via duk_hbufobj->buf_prop and an inherited .buffer\n\t * accessor returns it.  The ArrayBuffer is created lazily on first\n\t * access if necessary so we don't need to do anything more here.\n\t */\n\treturn;\n\n range_error:\n\tDUK_ERROR_RANGE(thr, DUK_STR_INVALID_ARGS);\n\treturn;  /* not reached */\n\n arg_error:\n\tDUK_ERROR_TYPE(thr, DUK_STR_INVALID_ARGS);\n\treturn;  /* not reached */\n}\n#else  /* DUK_USE_BUFFEROBJECT_SUPPORT */\nDUK_EXTERNAL void duk_push_buffer_object(duk_hthread *thr, duk_idx_t idx_buffer, duk_size_t byte_offset, duk_size_t byte_length, duk_uint_t flags) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK_UNREF(idx_buffer);\n\tDUK_UNREF(byte_offset);\n\tDUK_UNREF(byte_length);\n\tDUK_UNREF(flags);\n\tDUK_ERROR_UNSUPPORTED(thr);\n}\n#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */\n\nDUK_EXTERNAL duk_idx_t duk_push_error_object_va_raw(duk_hthread *thr, duk_errcode_t err_code, const char *filename, duk_int_t line, const char *fmt, va_list ap) {\n\tduk_hobject *proto;\n#if defined(DUK_USE_AUGMENT_ERROR_CREATE)\n\tduk_small_uint_t augment_flags;\n#endif\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK_ASSERT(thr != NULL);\n\tDUK_UNREF(filename);\n\tDUK_UNREF(line);\n\n\t/* Error code also packs a tracedata related flag. */\n#if defined(DUK_USE_AUGMENT_ERROR_CREATE)\n\taugment_flags = 0;\n\tif (err_code & DUK_ERRCODE_FLAG_NOBLAME_FILELINE) {\n\t\taugment_flags = DUK_AUGMENT_FLAG_NOBLAME_FILELINE;\n\t}\n#endif\n\terr_code = err_code & (~DUK_ERRCODE_FLAG_NOBLAME_FILELINE);\n\n\t/* error gets its 'name' from the prototype */\n\tproto = duk_error_prototype_from_code(thr, err_code);\n\t(void) duk_push_object_helper_proto(thr,\n\t                                    DUK_HOBJECT_FLAG_EXTENSIBLE |\n\t                                    DUK_HOBJECT_FLAG_FASTREFS |\n\t                                    DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ERROR),\n\t                                    proto);\n\n\t/* ... and its 'message' from an instance property */\n\tif (fmt) {\n\t\tduk_push_vsprintf(thr, fmt, ap);\n\t\tduk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_MESSAGE, DUK_PROPDESC_FLAGS_WC);\n\t} else {\n\t\t/* If no explicit message given, put error code into message field\n\t\t * (as a number).  This is not fully in keeping with the Ecmascript\n\t\t * error model because messages are supposed to be strings (Error\n\t\t * constructors use ToString() on their argument).  However, it's\n\t\t * probably more useful than having a separate 'code' property.\n\t\t */\n\t\tduk_push_int(thr, err_code);\n\t\tduk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_MESSAGE, DUK_PROPDESC_FLAGS_WC);\n\t}\n\n\t/* XXX: .code = err_code disabled, not sure if useful */\n\n\t/* Creation time error augmentation */\n#if defined(DUK_USE_AUGMENT_ERROR_CREATE)\n\t/* filename may be NULL in which case file/line is not recorded */\n\tduk_err_augment_error_create(thr, thr, filename, line, augment_flags);  /* may throw an error */\n#endif\n\n\treturn duk_get_top_index_unsafe(thr);\n}\n\nDUK_EXTERNAL duk_idx_t duk_push_error_object_raw(duk_hthread *thr, duk_errcode_t err_code, const char *filename, duk_int_t line, const char *fmt, ...) {\n\tva_list ap;\n\tduk_idx_t ret;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tva_start(ap, fmt);\n\tret = duk_push_error_object_va_raw(thr, err_code, filename, line, fmt, ap);\n\tva_end(ap);\n\treturn ret;\n}\n\n#if !defined(DUK_USE_VARIADIC_MACROS)\nDUK_EXTERNAL duk_idx_t duk_push_error_object_stash(duk_hthread *thr, duk_errcode_t err_code, const char *fmt, ...) {\n\tconst char *filename = duk_api_global_filename;\n\tduk_int_t line = duk_api_global_line;\n\tva_list ap;\n\tduk_idx_t ret;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tduk_api_global_filename = NULL;\n\tduk_api_global_line = 0;\n\tva_start(ap, fmt);\n\tret = duk_push_error_object_va_raw(thr, err_code, filename, line, fmt, ap);\n\tva_end(ap);\n\treturn ret;\n}\n#endif  /* DUK_USE_VARIADIC_MACROS */\n\nDUK_EXTERNAL void *duk_push_buffer_raw(duk_hthread *thr, duk_size_t size, duk_small_uint_t flags) {\n\tduk_tval *tv_slot;\n\tduk_hbuffer *h;\n\tvoid *buf_data;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tDUK__CHECK_SPACE();\n\n\t/* Check for maximum buffer length. */\n\tif (DUK_UNLIKELY(size > DUK_HBUFFER_MAX_BYTELEN)) {\n\t\tDUK_ERROR_RANGE(thr, DUK_STR_BUFFER_TOO_LONG);\n\t}\n\n\th = duk_hbuffer_alloc(thr->heap, size, flags, &buf_data);\n\tif (DUK_UNLIKELY(h == NULL)) {\n\t\tDUK_ERROR_ALLOC_FAILED(thr);\n\t}\n\n\ttv_slot = thr->valstack_top;\n\tDUK_TVAL_SET_BUFFER(tv_slot, h);\n\tDUK_HBUFFER_INCREF(thr, h);\n\tthr->valstack_top++;\n\n\treturn (void *) buf_data;\n}\n\nDUK_INTERNAL void *duk_push_fixed_buffer_nozero(duk_hthread *thr, duk_size_t len) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\treturn duk_push_buffer_raw(thr, len, DUK_BUF_FLAG_NOZERO);\n}\n\nDUK_INTERNAL void *duk_push_fixed_buffer_zero(duk_hthread *thr, duk_size_t len) {\n\tvoid *ptr;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tptr = duk_push_buffer_raw(thr, len, 0);\n#if !defined(DUK_USE_ZERO_BUFFER_DATA)\n\t/* ES2015 requires zeroing even when DUK_USE_ZERO_BUFFER_DATA\n\t * is not set.\n\t */\n\tDUK_MEMZERO((void *) ptr, (size_t) len);\n#endif\n\treturn ptr;\n}\n\n#if defined(DUK_USE_ES6_PROXY)\nDUK_EXTERNAL duk_idx_t duk_push_proxy(duk_hthread *thr, duk_uint_t proxy_flags) {\n\tduk_hobject *h_target;\n\tduk_hobject *h_handler;\n\tduk_hproxy *h_proxy;\n\tduk_tval *tv_slot;\n\tduk_uint_t flags;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK_UNREF(proxy_flags);\n\n\t/* DUK__CHECK_SPACE() unnecessary because the Proxy is written to\n\t * value stack in-place.\n\t */\n#if 0\n\tDUK__CHECK_SPACE();\n#endif\n\n\t/* Reject a proxy object as the target because it would need\n\t * special handling in property lookups.  (ES2015 has no such\n\t * restriction.)\n\t */\n\th_target = duk_require_hobject_promote_mask(thr, -2, DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER);\n\tDUK_ASSERT(h_target != NULL);\n\tif (DUK_HOBJECT_IS_PROXY(h_target)) {\n\t\tgoto fail_args;\n\t}\n\n\t/* Reject a proxy object as the handler because it would cause\n\t * potentially unbounded recursion.  (ES2015 has no such\n\t * restriction.)\n\t *\n\t * There's little practical reason to use a lightfunc or a plain\n\t * buffer as the handler table: one could only provide traps via\n\t * their prototype objects (Function.prototype and ArrayBuffer.prototype).\n\t * Even so, as lightfuncs and plain buffers mimic their object\n\t * counterparts, they're promoted and accepted here.\n\t */\n\th_handler = duk_require_hobject_promote_mask(thr, -1, DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER);\n\tDUK_ASSERT(h_handler != NULL);\n\tif (DUK_HOBJECT_IS_PROXY(h_handler)) {\n\t\tgoto fail_args;\n\t}\n\n\t/* XXX: Proxy object currently has no prototype, so ToPrimitive()\n\t * coercion fails which is a bit confusing.\n\t */\n\n\t/* CALLABLE and CONSTRUCTABLE flags are copied from the (initial)\n\t * target, see ES2015 Sections 9.5.15 and 9.5.13.\n\t */\n\tflags = DUK_HEAPHDR_GET_FLAGS((duk_heaphdr *) h_target) &\n\t        (DUK_HOBJECT_FLAG_CALLABLE | DUK_HOBJECT_FLAG_CONSTRUCTABLE);\n\tflags |= DUK_HOBJECT_FLAG_EXTENSIBLE |\n\t         DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ;\n\tif (flags & DUK_HOBJECT_FLAG_CALLABLE) {\n\t\tflags |= DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_FUNCTION) |\n\t\t         DUK_HOBJECT_FLAG_SPECIAL_CALL;\n\t} else {\n\t\tflags |= DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT);\n\t}\n\n\th_proxy = duk_hproxy_alloc(thr, flags);\n\tDUK_ASSERT(h_proxy != NULL);\n\tDUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) h_proxy) == NULL);\n\n\t/* Initialize Proxy target and handler references; avoid INCREF\n\t * by stealing the value stack refcounts via direct value stack\n\t * manipulation.  INCREF is needed for the Proxy itself however.\n\t */\n\tDUK_ASSERT(h_target != NULL);\n\th_proxy->target = h_target;\n\tDUK_ASSERT(h_handler != NULL);\n\th_proxy->handler = h_handler;\n\tDUK_ASSERT_HPROXY_VALID(h_proxy);\n\n\tDUK_ASSERT(duk_get_hobject(thr, -2) == h_target);\n\tDUK_ASSERT(duk_get_hobject(thr, -1) == h_handler);\n\ttv_slot = thr->valstack_top - 2;\n\tDUK_ASSERT(tv_slot >= thr->valstack_bottom);\n\tDUK_TVAL_SET_OBJECT(tv_slot, (duk_hobject *) h_proxy);\n\tDUK_HOBJECT_INCREF(thr, (duk_hobject *) h_proxy);\n\ttv_slot++;\n\tDUK_TVAL_SET_UNDEFINED(tv_slot);  /* [ ... target handler ] -> [ ... proxy undefined ] */\n\tthr->valstack_top = tv_slot;      /* -> [ ... proxy ] */\n\n\tDUK_DD(DUK_DDPRINT(\"created Proxy: %!iT\", duk_get_tval(thr, -1)));\n\n\treturn (duk_idx_t) (thr->valstack_top - thr->valstack_bottom - 1);\n\n fail_args:\n\tDUK_ERROR_TYPE_INVALID_ARGS(thr);\n}\n#else  /* DUK_USE_ES6_PROXY */\nDUK_EXTERNAL duk_idx_t duk_push_proxy(duk_hthread *thr, duk_uint_t proxy_flags) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK_UNREF(proxy_flags);\n\tDUK_ERROR_UNSUPPORTED(thr);\n}\n#endif  /* DUK_USE_ES6_PROXY */\n\n#if defined(DUK_USE_ASSERTIONS)\nDUK_LOCAL void duk__validate_push_heapptr(duk_hthread *thr, void *ptr) {\n\tduk_heaphdr *h;\n\tduk_heaphdr *curr;\n\tduk_bool_t found = 0;\n\n\th = (duk_heaphdr *) ptr;\n\tif (h == NULL) {\n\t\t/* Allowed. */\n\t\treturn;\n\t}\n\tDUK_ASSERT(h != NULL);\n\tDUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(h));\n\n\t/* One particular problem case is where an object has been\n\t * queued for finalization but the finalizer hasn't yet been\n\t * executed.\n\t *\n\t * Corner case: we're running in a finalizer for object X, and\n\t * user code calls duk_push_heapptr() for X itself.  In this\n\t * case X will be in finalize_list, and we can detect the case\n\t * by seeing that X's FINALIZED flag is set (which is done before\n\t * the finalizer starts executing).\n\t */\n#if defined(DUK_USE_FINALIZER_SUPPORT)\n\tfor (curr = thr->heap->finalize_list;\n\t     curr != NULL;\n\t     curr = DUK_HEAPHDR_GET_NEXT(thr->heap, curr)) {\n\t\t/* FINALIZABLE is set for all objects on finalize_list\n\t\t * except for an object being finalized right now.  So\n\t\t * can't assert here.\n\t\t */\n#if 0\n\t\tDUK_ASSERT(DUK_HEAPHDR_HAS_FINALIZABLE(curr));\n#endif\n\n\t\tif (curr == h) {\n\t\t\tif (DUK_HEAPHDR_HAS_FINALIZED((duk_heaphdr *) h)) {\n\t\t\t\t/* Object is currently being finalized. */\n\t\t\t\tDUK_ASSERT(found == 0);  /* Would indicate corrupted lists. */\n\t\t\t\tfound = 1;\n\t\t\t} else {\n\t\t\t\t/* Not being finalized but on finalize_list,\n\t\t\t\t * allowed since Duktape 2.1.\n\t\t\t\t */\n\t\t\t\tDUK_ASSERT(found == 0);  /* Would indicate corrupted lists. */\n\t\t\t\tfound = 1;\n\t\t\t}\n\t\t}\n\t}\n#endif  /* DUK_USE_FINALIZER_SUPPORT */\n\n#if defined(DUK_USE_REFERENCE_COUNTING)\n\t/* Because refzero_list is now processed to completion inline with\n\t * no side effects, it's always empty here.\n\t */\n\tDUK_ASSERT(thr->heap->refzero_list == NULL);\n#endif\n\n\t/* If not present in finalize_list (or refzero_list), it\n\t * must be either in heap_allocated or the string table.\n\t */\n\tif (DUK_HEAPHDR_IS_STRING(h)) {\n\t\tduk_uint32_t i;\n\t\tduk_hstring *str;\n\t\tduk_heap *heap = thr->heap;\n\n\t\tDUK_ASSERT(found == 0);\n\t\tfor (i = 0; i < heap->st_size; i++) {\n#if defined(DUK_USE_STRTAB_PTRCOMP)\n\t\t\tstr = DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, heap->strtable16[i]);\n#else\n\t\t\tstr = heap->strtable[i];\n#endif\n\t\t\twhile (str != NULL) {\n\t\t\t\tif (str == (duk_hstring *) h) {\n\t\t\t\t\tDUK_ASSERT(found == 0);  /* Would indicate corrupted lists. */\n\t\t\t\t\tfound = 1;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tstr = str->hdr.h_next;\n\t\t\t}\n\t\t}\n\t\tDUK_ASSERT(found != 0);\n\t} else {\n\t\tfor (curr = thr->heap->heap_allocated;\n\t\t     curr != NULL;\n\t\t     curr = DUK_HEAPHDR_GET_NEXT(thr->heap, curr)) {\n\t\t\tif (curr == h) {\n\t\t\t\tDUK_ASSERT(found == 0);  /* Would indicate corrupted lists. */\n\t\t\t\tfound = 1;\n\t\t\t}\n\t\t}\n\t\tDUK_ASSERT(found != 0);\n\t}\n}\n#endif  /* DUK_USE_ASSERTIONS */\n\nDUK_EXTERNAL duk_idx_t duk_push_heapptr(duk_hthread *thr, void *ptr) {\n\tduk_idx_t ret;\n\tduk_tval *tv;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\t/* Reviving an object using a heap pointer is a dangerous API\n\t * operation: if the application doesn't guarantee that the\n\t * pointer target is always reachable, difficult-to-diagnose\n\t * problems may ensue.  Try to validate the 'ptr' argument to\n\t * the extent possible.\n\t */\n\n#if defined(DUK_USE_ASSERTIONS)\n\tduk__validate_push_heapptr(thr, ptr);\n#endif\n\n\tDUK__CHECK_SPACE();\n\n\tret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);\n\ttv = thr->valstack_top++;\n\n\tif (ptr == NULL) {\n\t\tDUK_ASSERT(DUK_TVAL_IS_UNDEFINED(tv));\n\t\treturn ret;\n\t}\n\n\tDUK_ASSERT_HEAPHDR_VALID((duk_heaphdr *) ptr);\n\n\t/* If the argument is on finalize_list it has technically been\n\t * unreachable before duk_push_heapptr() but it's still safe to\n\t * push it.  Starting from Duktape 2.1 allow application code to\n\t * do so.  There are two main cases:\n\t *\n\t *   (1) The object is on the finalize_list and we're called by\n\t *       the finalizer for the object being finalized.  In this\n\t *       case do nothing: finalize_list handling will deal with\n\t *       the object queueing.  This is detected by the object not\n\t *       having a FINALIZABLE flag despite being on the finalize_list;\n\t *       the flag is cleared for the object being finalized only.\n\t *\n\t *   (2) The object is on the finalize_list but is not currently\n\t *       being processed.  In this case the object can be queued\n\t *       back to heap_allocated with a few flags cleared, in effect\n\t *       cancelling the finalizer.\n\t */\n\tif (DUK_UNLIKELY(DUK_HEAPHDR_HAS_FINALIZABLE((duk_heaphdr *) ptr))) {\n\t\tduk_heaphdr *curr;\n\n\t\tDUK_D(DUK_DPRINT(\"duk_push_heapptr() with a pointer on finalize_list, autorescue\"));\n\n\t\tcurr = (duk_heaphdr *) ptr;\n\t\tDUK_HEAPHDR_CLEAR_FINALIZABLE(curr);\n\n\t\t/* Because FINALIZED is set prior to finalizer call, it will\n\t\t * be set for the object being currently finalized, but not\n\t\t * for other objects on finalize_list.\n\t\t */\n\t\tDUK_HEAPHDR_CLEAR_FINALIZED(curr);\n\n\t\t/* Dequeue object from finalize_list and queue it back to\n\t\t * heap_allocated.\n\t\t */\n#if defined(DUK_USE_REFERENCE_COUNTING)\n\t\tDUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(curr) >= 1);  /* Preincremented on finalize_list insert. */\n\t\tDUK_HEAPHDR_PREDEC_REFCOUNT(curr);\n#endif\n\t\tDUK_HEAP_REMOVE_FROM_FINALIZE_LIST(thr->heap, curr);\n\t\tDUK_HEAP_INSERT_INTO_HEAP_ALLOCATED(thr->heap, curr);\n\n\t\t/* Continue with the rest. */\n\t}\n\n\tswitch (DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) ptr)) {\n\tcase DUK_HTYPE_STRING:\n\t\tDUK_TVAL_SET_STRING(tv, (duk_hstring *) ptr);\n\t\tbreak;\n\tcase DUK_HTYPE_OBJECT:\n\t\tDUK_TVAL_SET_OBJECT(tv, (duk_hobject *) ptr);\n\t\tbreak;\n\tdefault:\n\t\tDUK_ASSERT(DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) ptr) == DUK_HTYPE_BUFFER);\n\t\tDUK_TVAL_SET_BUFFER(tv, (duk_hbuffer *) ptr);\n\t\tbreak;\n\t}\n\n\tDUK_HEAPHDR_INCREF(thr, (duk_heaphdr *) ptr);\n\n\treturn ret;\n}\n\n/* Push object with no prototype, i.e. a \"bare\" object. */\nDUK_EXTERNAL duk_idx_t duk_push_bare_object(duk_hthread *thr) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\t(void) duk_push_object_helper(thr,\n\t                              DUK_HOBJECT_FLAG_EXTENSIBLE |\n\t                              DUK_HOBJECT_FLAG_FASTREFS |\n\t                              DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT),\n\t                              -1);  /* no prototype */\n\treturn duk_get_top_index_unsafe(thr);\n}\n\nDUK_INTERNAL void duk_push_hstring(duk_hthread *thr, duk_hstring *h) {\n\tduk_tval tv;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK_ASSERT(h != NULL);\n\n\tDUK_TVAL_SET_STRING(&tv, h);\n\tduk_push_tval(thr, &tv);\n}\n\nDUK_INTERNAL void duk_push_hstring_stridx(duk_hthread *thr, duk_small_uint_t stridx) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK_ASSERT_STRIDX_VALID(stridx);\n\tduk_push_hstring(thr, DUK_HTHREAD_GET_STRING(thr, stridx));\n}\n\nDUK_INTERNAL void duk_push_hstring_empty(duk_hthread *thr) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\tduk_push_hstring(thr, DUK_HTHREAD_GET_STRING(thr, DUK_STRIDX_EMPTY_STRING));\n}\n\nDUK_INTERNAL void duk_push_hobject(duk_hthread *thr, duk_hobject *h) {\n\tduk_tval tv;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK_ASSERT(h != NULL);\n\n\tDUK_TVAL_SET_OBJECT(&tv, h);\n\tduk_push_tval(thr, &tv);\n}\n\nDUK_INTERNAL void duk_push_hbuffer(duk_hthread *thr, duk_hbuffer *h) {\n\tduk_tval tv;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK_ASSERT(h != NULL);\n\n\tDUK_TVAL_SET_BUFFER(&tv, h);\n\tduk_push_tval(thr, &tv);\n}\n\nDUK_INTERNAL void duk_push_hobject_bidx(duk_hthread *thr, duk_small_int_t builtin_idx) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK_ASSERT(builtin_idx >= 0 && builtin_idx < DUK_NUM_BUILTINS);\n\tDUK_ASSERT(thr->builtins[builtin_idx] != NULL);\n\n\tduk_push_hobject(thr, thr->builtins[builtin_idx]);\n}\n\n/*\n *  Poppers\n */\n\nDUK_LOCAL DUK_ALWAYS_INLINE void duk__pop_n_unsafe_raw(duk_hthread *thr, duk_idx_t count) {\n\tduk_tval *tv;\n#if defined(DUK_USE_REFERENCE_COUNTING)\n\tduk_tval *tv_end;\n#endif\n\n\tDUK_ASSERT_CTX_VALID(thr);\n\tDUK_ASSERT(count >= 0);\n\tDUK_ASSERT((duk_size_t) (thr->valstack_top - thr->valstack_bottom) >= (duk_size_t) count);\n\n#if defined(DUK_USE_REFERENCE_COUNTING)\n\ttv = thr->valstack_top;\n\ttv_end = tv - count;\n\twhile (tv != tv_end) {\n\t\ttv--;\n\t\tDUK_ASSERT(tv >= thr->valstack_bottom);\n\t\tDUK_TVAL_SET_UNDEFINED_UPDREF_NORZ(thr, tv);\n\t}\n\tthr->valstack_top = tv;\n\tDUK_REFZERO_CHECK_FAST(thr);\n#else\n\ttv = thr->valstack_top;\n\twhile (count > 0) {\n\t\tcount--;\n\t\ttv--;\n\t\tDUK_ASSERT(tv >= thr->valstack_bottom);\n\t\tDUK_TVAL_SET_UNDEFINED(tv);\n\t}\n\tthr->valstack_top = tv;\n#endif\n\n\tDUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);\n}\n\nDUK_EXTERNAL void duk_pop_n(duk_hthread *thr, duk_idx_t count) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);\n\n\tif (DUK_UNLIKELY((duk_uidx_t) (thr->valstack_top - thr->valstack_bottom) < (duk_uidx_t) count)) {\n\t\tDUK_ERROR_RANGE_INVALID_COUNT(thr);\n\t\treturn;\n\t}\n\tDUK_ASSERT(count >= 0);\n\n\tduk__pop_n_unsafe_raw(thr, count);\n}\n\n#if defined(DUK_USE_PREFER_SIZE)\nDUK_INTERNAL void duk_pop_n_unsafe(duk_hthread *thr, duk_idx_t count) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\tduk_pop_n(thr, count);\n}\n#else  /* DUK_USE_PREFER_SIZE */\nDUK_INTERNAL void duk_pop_n_unsafe(duk_hthread *thr, duk_idx_t count) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\tduk__pop_n_unsafe_raw(thr, count);\n}\n#endif  /* DUK_USE_PREFER_SIZE */\n\n/* Pop N elements without DECREF (in effect \"stealing\" any actual refcounts). */\n#if defined(DUK_USE_REFERENCE_COUNTING)\nDUK_INTERNAL void duk_pop_n_nodecref_unsafe(duk_hthread *thr, duk_idx_t count) {\n\tduk_tval *tv;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK_ASSERT(count >= 0);\n\tDUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);\n\tDUK_ASSERT((duk_size_t) (thr->valstack_top - thr->valstack_bottom) >= (duk_size_t) count);\n\n\ttv = thr->valstack_top;\n\twhile (count > 0) {\n\t\tcount--;\n\t\ttv--;\n\t\tDUK_ASSERT(tv >= thr->valstack_bottom);\n\t\tDUK_TVAL_SET_UNDEFINED(tv);\n\t}\n\tthr->valstack_top = tv;\n\n\tDUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);\n}\n#else  /* DUK_USE_REFERENCE_COUNTING */\nDUK_INTERNAL void duk_pop_n_nodecref_unsafe(duk_hthread *thr, duk_idx_t count) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\tduk_pop_n_unsafe(thr, count);\n}\n#endif  /* DUK_USE_REFERENCE_COUNTING */\n\n/* Popping one element is called so often that when footprint is not an issue,\n * compile a specialized function for it.\n */\n#if defined(DUK_USE_PREFER_SIZE)\nDUK_EXTERNAL void duk_pop(duk_hthread *thr) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\tduk_pop_n(thr, 1);\n}\nDUK_INTERNAL void duk_pop_unsafe(duk_hthread *thr) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\tduk_pop_n_unsafe(thr, 1);\n}\nDUK_INTERNAL void duk_pop_nodecref_unsafe(duk_hthread *thr) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\tduk_pop_n_nodecref_unsafe(thr, 1);\n}\n#else  /* DUK_USE_PREFER_SIZE */\nDUK_LOCAL DUK_ALWAYS_INLINE void duk__pop_unsafe_raw(duk_hthread *thr) {\n\tduk_tval *tv;\n\n\tDUK_ASSERT_CTX_VALID(thr);\n\tDUK_ASSERT(thr->valstack_top != thr->valstack_bottom);\n\tDUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);\n\tDUK_ASSERT((duk_size_t) (thr->valstack_top - thr->valstack_bottom) >= (duk_size_t) 1);\n\n\ttv = --thr->valstack_top;\n\tDUK_ASSERT(tv >= thr->valstack_bottom);\n#if defined(DUK_USE_REFERENCE_COUNTING)\n\tDUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv);  /* side effects */\n#else\n\tDUK_TVAL_SET_UNDEFINED(tv);\n#endif\n\n\tDUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);\n}\nDUK_EXTERNAL void duk_pop(duk_hthread *thr) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tDUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);\n\tif (DUK_UNLIKELY(thr->valstack_top == thr->valstack_bottom)) {\n\t\tDUK_ERROR_RANGE_INVALID_COUNT(thr);\n\t}\n\n\tduk__pop_unsafe_raw(thr);\n}\nDUK_INTERNAL void duk_pop_unsafe(duk_hthread *thr) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\tduk__pop_unsafe_raw(thr);\n}\nDUK_INTERNAL void duk_pop_nodecref_unsafe(duk_hthread *thr) {\n\tduk_tval *tv;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK_ASSERT(thr->valstack_top != thr->valstack_bottom);\n\tDUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);\n\tDUK_ASSERT((duk_size_t) (thr->valstack_top - thr->valstack_bottom) >= (duk_size_t) 1);\n\n\ttv = --thr->valstack_top;\n\tDUK_ASSERT(tv >= thr->valstack_bottom);\n\tDUK_TVAL_SET_UNDEFINED(tv);\n\n\tDUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);\n}\n#endif  /* !DUK_USE_PREFER_SIZE */\n\n#if defined(DUK_USE_PREFER_SIZE)\nDUK_INTERNAL void duk_pop_undefined(duk_hthread *thr) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\tduk_pop_nodecref_unsafe(thr);\n}\n#else  /* DUK_USE_PREFER_SIZE */\nDUK_INTERNAL void duk_pop_undefined(duk_hthread *thr) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK_ASSERT(thr->valstack_top != thr->valstack_bottom);\n\tDUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);\n\tDUK_ASSERT((duk_size_t) (thr->valstack_top - thr->valstack_bottom) >= (duk_size_t) 1);\n\n\tDUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top - 1));\n\tthr->valstack_top--;\n\n\tDUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);\n}\n#endif  /* !DUK_USE_PREFER_SIZE */\n\n#if defined(DUK_USE_PREFER_SIZE)\nDUK_EXTERNAL void duk_pop_2(duk_hthread *thr) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\tduk_pop_n(thr, 2);\n}\nDUK_INTERNAL void duk_pop_2_unsafe(duk_hthread *thr) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\tduk_pop_n_unsafe(thr, 2);\n}\nDUK_INTERNAL void duk_pop_2_nodecref_unsafe(duk_hthread *thr) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\tduk_pop_n_nodecref_unsafe(thr, 2);\n}\n#else\nDUK_LOCAL DUK_ALWAYS_INLINE void duk__pop_2_unsafe_raw(duk_hthread *thr) {\n\tduk_tval *tv;\n\n\tDUK_ASSERT_CTX_VALID(thr);\n\tDUK_ASSERT(thr->valstack_top != thr->valstack_bottom);\n\tDUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);\n\tDUK_ASSERT((duk_size_t) (thr->valstack_top - thr->valstack_bottom) >= (duk_size_t) 2);\n\n\ttv = --thr->valstack_top;\n\tDUK_ASSERT(tv >= thr->valstack_bottom);\n#if defined(DUK_USE_REFERENCE_COUNTING)\n\tDUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv);  /* side effects */\n#else\n\tDUK_TVAL_SET_UNDEFINED(tv);\n#endif\n\ttv = --thr->valstack_top;\n\tDUK_ASSERT(tv >= thr->valstack_bottom);\n#if defined(DUK_USE_REFERENCE_COUNTING)\n\tDUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv);  /* side effects */\n#else\n\tDUK_TVAL_SET_UNDEFINED(tv);\n#endif\n\n\tDUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);\n}\nDUK_EXTERNAL void duk_pop_2(duk_hthread *thr) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tDUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);\n\tif (DUK_UNLIKELY(thr->valstack_top - 2 < thr->valstack_bottom)) {\n\t\tDUK_ERROR_RANGE_INVALID_COUNT(thr);\n\t}\n\n\tduk__pop_2_unsafe_raw(thr);\n}\nDUK_INTERNAL void duk_pop_2_unsafe(duk_hthread *thr) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\tduk__pop_2_unsafe_raw(thr);\n}\nDUK_INTERNAL void duk_pop_2_nodecref_unsafe(duk_hthread *thr) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK_ASSERT(thr->valstack_top != thr->valstack_bottom);\n\tDUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);\n\tDUK_ASSERT((duk_size_t) (thr->valstack_top - thr->valstack_bottom) >= (duk_size_t) 2);\n\n\tDUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top - 1));\n\tDUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top - 2));\n\tthr->valstack_top -= 2;\n\n\tDUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);\n}\n#endif  /* !DUK_USE_PREFER_SIZE */\n\nDUK_EXTERNAL void duk_pop_3(duk_hthread *thr) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\tduk_pop_n(thr, 3);\n}\n\nDUK_INTERNAL void duk_pop_3_unsafe(duk_hthread *thr) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\tduk_pop_n_unsafe(thr, 3);\n}\n\nDUK_INTERNAL void duk_pop_3_nodecref_unsafe(duk_hthread *thr) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\tduk_pop_n_nodecref_unsafe(thr, 3);\n}\n\n/*\n *  Pack and unpack (pack value stack entries into an array and vice versa)\n */\n\n/* XXX: pack index range? array index offset? */\nDUK_INTERNAL void duk_pack(duk_hthread *thr, duk_idx_t count) {\n\tduk_tval *tv_src;\n\tduk_tval *tv_dst;\n\tduk_tval *tv_curr;\n\tduk_tval *tv_limit;\n\tduk_idx_t top;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tDUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);\n\ttop = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);\n\tDUK_ASSERT(top >= 0);\n\tif (DUK_UNLIKELY((duk_uidx_t) count > (duk_uidx_t) top)) {\n\t\t/* Also handles negative count. */\n\t\tDUK_ERROR_RANGE_INVALID_COUNT(thr);\n\t\treturn;\n\t}\n\tDUK_ASSERT(count >= 0);\n\n\t/* Wrapping is controlled by the check above: value stack top can be\n\t * at most DUK_USE_VALSTACK_LIMIT which is low enough so that\n\t * multiplying with sizeof(duk_tval) won't wrap.\n\t */\n\tDUK_ASSERT(count >= 0 && count <= (duk_idx_t) DUK_USE_VALSTACK_LIMIT);\n\tDUK_ASSERT((duk_size_t) count <= DUK_SIZE_MAX / sizeof(duk_tval));  /* no wrapping */\n\n\ttv_dst = duk_push_harray_with_size_outptr(thr, (duk_uint32_t) count);  /* XXX: uninitialized would be OK */\n\tDUK_ASSERT(count == 0 || tv_dst != NULL);\n\n\t/* Copy value stack values directly to the array part without\n\t * any refcount updates: net refcount changes are zero.\n\t */\n\n\ttv_src = thr->valstack_top - count - 1;\n\tDUK_MEMCPY((void *) tv_dst, (const void *) tv_src, (size_t) count * sizeof(duk_tval));\n\n\t/* Overwrite result array to final value stack location and wipe\n\t * the rest; no refcount operations needed.\n\t */\n\n\ttv_dst = tv_src;  /* when count == 0, same as tv_src (OK) */\n\ttv_src = thr->valstack_top - 1;\n\tDUK_TVAL_SET_TVAL(tv_dst, tv_src);\n\n\t/* XXX: internal helper to wipe a value stack segment? */\n\ttv_curr = tv_dst + 1;\n\ttv_limit = thr->valstack_top;\n\twhile (tv_curr != tv_limit) {\n\t\t/* Wipe policy: keep as 'undefined'. */\n\t\tDUK_TVAL_SET_UNDEFINED(tv_curr);\n\t\ttv_curr++;\n\t}\n\tthr->valstack_top = tv_dst + 1;\n}\n\nDUK_INTERNAL duk_idx_t duk_unpack_array_like(duk_hthread *thr, duk_idx_t idx) {\n\tduk_tval *tv;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\ttv = duk_require_tval(thr, idx);\n\tif (DUK_LIKELY(DUK_TVAL_IS_OBJECT(tv))) {\n\t\tduk_hobject *h;\n\t\tduk_uint32_t len;\n\t\tduk_uint32_t i;\n\n\t\th = DUK_TVAL_GET_OBJECT(tv);\n\t\tDUK_ASSERT(h != NULL);\n\t\tDUK_UNREF(h);\n\n#if defined(DUK_USE_ARRAY_FASTPATH)  /* close enough */\n\t\tif (DUK_LIKELY(DUK_HOBJECT_IS_ARRAY(h) &&\n\t\t               ((duk_harray *) h)->length <= DUK_HOBJECT_GET_ASIZE(h))) {\n\t\t\tduk_harray *h_arr;\n\t\t\tduk_tval *tv_src;\n\t\t\tduk_tval *tv_dst;\n\n\t\t\th_arr = (duk_harray *) h;\n\t\t\tlen = h_arr->length;\n\t\t\tif (DUK_UNLIKELY(len >= 0x80000000UL)) {\n\t\t\t\tgoto fail_over_2g;\n\t\t\t}\n\t\t\tduk_require_stack(thr, (duk_idx_t) len);\n\n\t\t\t/* The potential allocation in duk_require_stack() may\n\t\t\t * run a finalizer which modifies the argArray so that\n\t\t\t * e.g. becomes sparse.  So, we need to recheck that the\n\t\t\t * array didn't change size and that there's still a\n\t\t\t * valid backing array part.\n\t\t\t *\n\t\t\t * XXX: alternatively, could prevent finalizers for the\n\t\t\t * duration.\n\t\t\t */\n\t\t\tif (DUK_UNLIKELY(len != h_arr->length ||\n\t\t\t                 h_arr->length > DUK_HOBJECT_GET_ASIZE((duk_hobject *) h_arr))) {\n\t\t\t\tgoto skip_fast;\n\t\t\t}\n\n\t\t\t/* Main fast path: arguments array is almost always\n\t\t\t * an actual array (though it might also be an arguments\n\t\t\t * object).\n\t\t\t */\n\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"fast path for %ld elements\", (long) h_arr->length));\n\t\t\ttv_src = DUK_HOBJECT_A_GET_BASE(thr->heap, h);\n\t\t\ttv_dst = thr->valstack_top;\n\t\t\twhile (len-- > 0) {\n\t\t\t\tDUK_ASSERT(tv_dst < thr->valstack_end);\n\t\t\t\tif (DUK_UNLIKELY(DUK_TVAL_IS_UNUSED(tv_src))) {\n\t\t\t\t\t/* Gaps are very unlikely.  Skip over them,\n\t\t\t\t\t * without an ancestor lookup (technically\n\t\t\t\t\t * not compliant).\n\t\t\t\t\t */\n\t\t\t\t\tDUK_ASSERT(DUK_TVAL_IS_UNDEFINED(tv_dst));  /* valstack policy */\n\t\t\t\t} else {\n\t\t\t\t\tDUK_TVAL_SET_TVAL(tv_dst, tv_src);\n\t\t\t\t\tDUK_TVAL_INCREF(thr, tv_dst);\n\t\t\t\t}\n\t\t\t\ttv_src++;\n\t\t\t\ttv_dst++;\n\t\t\t}\n\t\t\tDUK_ASSERT(tv_dst <= thr->valstack_end);\n\t\t\tthr->valstack_top = tv_dst;\n\t\t\treturn (duk_idx_t) h_arr->length;\n\t\t}\n\t skip_fast:\n#endif  /* DUK_USE_ARRAY_FASTPATH */\n\n\t\t/* Slow path: actual lookups.  The initial 'length' lookup\n\t\t * decides the output length, regardless of side effects that\n\t\t * may resize or change the argArray while we read the\n\t\t * indices.\n\t\t */\n\t\tidx = duk_normalize_index(thr, idx);\n\t\tduk_get_prop_stridx(thr, idx, DUK_STRIDX_LENGTH);\n\t\tlen = duk_to_uint32(thr, -1);  /* ToUint32() coercion required */\n\t\tif (DUK_UNLIKELY(len >= 0x80000000UL)) {\n\t\t\tgoto fail_over_2g;\n\t\t}\n\t\tduk_pop_unsafe(thr);\n\t\tDUK_DDD(DUK_DDDPRINT(\"slow path for %ld elements\", (long) len));\n\n\t\tduk_require_stack(thr, (duk_idx_t) len);\n\t\tfor (i = 0; i < len; i++) {\n\t\t\tduk_get_prop_index(thr, idx, (duk_uarridx_t) i);\n\t\t}\n\t\treturn (duk_idx_t) len;\n\t} else if (DUK_TVAL_IS_UNDEFINED(tv) || DUK_TVAL_IS_NULL(tv)) {\n\t\treturn 0;\n\t}\n\n\tDUK_ERROR_TYPE_INVALID_ARGS(thr);\n\treturn 0;\n\n fail_over_2g:\n\tDUK_ERROR_RANGE_INVALID_LENGTH(thr);\n\treturn 0;\n}\n\n/*\n *  Error throwing\n */\n\nDUK_EXTERNAL void duk_throw_raw(duk_hthread *thr) {\n\tduk_tval *tv_val;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK_ASSERT(thr->valstack_bottom >= thr->valstack);\n\tDUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);\n\tDUK_ASSERT(thr->valstack_end >= thr->valstack_top);\n\n\tif (DUK_UNLIKELY(thr->valstack_top == thr->valstack_bottom)) {\n\t\tDUK_ERROR_TYPE_INVALID_ARGS(thr);\n\t}\n\n\t/* Errors are augmented when they are created, not when they are\n\t * thrown or re-thrown.  The current error handler, however, runs\n\t * just before an error is thrown.\n\t */\n\n\t/* Sync so that augmentation sees up-to-date activations, NULL\n\t * thr->ptr_curr_pc so that it's not used if side effects occur\n\t * in augmentation or longjmp handling.\n\t */\n\tduk_hthread_sync_and_null_currpc(thr);\n\n#if defined(DUK_USE_AUGMENT_ERROR_THROW)\n\tDUK_DDD(DUK_DDDPRINT(\"THROW ERROR (API): %!dT (before throw augment)\", (duk_tval *) duk_get_tval(thr, -1)));\n\tduk_err_augment_error_throw(thr);\n#endif\n\tDUK_DDD(DUK_DDDPRINT(\"THROW ERROR (API): %!dT (after throw augment)\", (duk_tval *) duk_get_tval(thr, -1)));\n\n\ttv_val = DUK_GET_TVAL_NEGIDX(thr, -1);\n\tduk_err_setup_ljstate1(thr, DUK_LJ_TYPE_THROW, tv_val);\n#if defined(DUK_USE_DEBUGGER_SUPPORT)\n\tduk_err_check_debugger_integration(thr);\n#endif\n\n\t/* thr->heap->lj.jmpbuf_ptr is checked by duk_err_longjmp() so we don't\n\t * need to check that here.  If the value is NULL, a fatal error occurs\n\t * because we can't return.\n\t */\n\n\tduk_err_longjmp(thr);\n\tDUK_UNREACHABLE();\n}\n\nDUK_EXTERNAL void duk_fatal_raw(duk_hthread *thr, const char *err_msg) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(thr->heap != NULL);\n\tDUK_ASSERT(thr->heap->fatal_func != NULL);\n\n\tDUK_D(DUK_DPRINT(\"fatal error occurred: %s\", err_msg ? err_msg : \"NULL\"));\n\n\t/* fatal_func should be noreturn, but noreturn declarations on function\n\t * pointers has a very spotty support apparently so it's not currently\n\t * done.\n\t */\n\tthr->heap->fatal_func(thr->heap->heap_udata, err_msg);\n\n\t/* If the fatal handler returns, all bets are off.  It'd be nice to\n\t * print something here but since we don't want to depend on stdio,\n\t * there's no way to do so portably.\n\t */\n\tDUK_D(DUK_DPRINT(\"fatal error handler returned, all bets are off!\"));\n\tfor (;;) {\n\t\t/* loop forever, don't return (function marked noreturn) */\n\t}\n}\n\nDUK_EXTERNAL void duk_error_va_raw(duk_hthread *thr, duk_errcode_t err_code, const char *filename, duk_int_t line, const char *fmt, va_list ap) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tduk_push_error_object_va_raw(thr, err_code, filename, line, fmt, ap);\n\t(void) duk_throw(thr);\n}\n\nDUK_EXTERNAL void duk_error_raw(duk_hthread *thr, duk_errcode_t err_code, const char *filename, duk_int_t line, const char *fmt, ...) {\n\tva_list ap;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tva_start(ap, fmt);\n\tduk_push_error_object_va_raw(thr, err_code, filename, line, fmt, ap);\n\tva_end(ap);\n\t(void) duk_throw(thr);\n}\n\n#if !defined(DUK_USE_VARIADIC_MACROS)\nDUK_NORETURN(DUK_LOCAL_DECL void duk__throw_error_from_stash(duk_hthread *thr, duk_errcode_t err_code, const char *fmt, va_list ap));\n\nDUK_LOCAL void duk__throw_error_from_stash(duk_hthread *thr, duk_errcode_t err_code, const char *fmt, va_list ap) {\n\tconst char *filename;\n\tduk_int_t line;\n\n\tDUK_ASSERT_CTX_VALID(thr);\n\n\tfilename = duk_api_global_filename;\n\tline = duk_api_global_line;\n\tduk_api_global_filename = NULL;\n\tduk_api_global_line = 0;\n\n\tduk_push_error_object_va_raw(thr, err_code, filename, line, fmt, ap);\n\t(void) duk_throw(thr);\n}\n\n#define DUK__ERROR_STASH_SHARED(code) do { \\\n\t\tva_list ap; \\\n\t\tva_start(ap, fmt); \\\n\t\tduk__throw_error_from_stash(thr, (code), fmt, ap); \\\n\t\tva_end(ap); \\\n\t\t/* Never reached; if return 0 here, gcc/clang will complain. */ \\\n\t} while (0)\n\nDUK_EXTERNAL duk_ret_t duk_error_stash(duk_hthread *thr, duk_errcode_t err_code, const char *fmt, ...) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK__ERROR_STASH_SHARED(err_code);\n}\nDUK_EXTERNAL duk_ret_t duk_generic_error_stash(duk_hthread *thr, const char *fmt, ...) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK__ERROR_STASH_SHARED(DUK_ERR_ERROR);\n}\nDUK_EXTERNAL duk_ret_t duk_eval_error_stash(duk_hthread *thr, const char *fmt, ...) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK__ERROR_STASH_SHARED(DUK_ERR_EVAL_ERROR);\n}\nDUK_EXTERNAL duk_ret_t duk_range_error_stash(duk_hthread *thr, const char *fmt, ...) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK__ERROR_STASH_SHARED(DUK_ERR_RANGE_ERROR);\n}\nDUK_EXTERNAL duk_ret_t duk_reference_error_stash(duk_hthread *thr, const char *fmt, ...) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK__ERROR_STASH_SHARED(DUK_ERR_REFERENCE_ERROR);\n}\nDUK_EXTERNAL duk_ret_t duk_syntax_error_stash(duk_hthread *thr, const char *fmt, ...) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK__ERROR_STASH_SHARED(DUK_ERR_SYNTAX_ERROR);\n}\nDUK_EXTERNAL duk_ret_t duk_type_error_stash(duk_hthread *thr, const char *fmt, ...) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK__ERROR_STASH_SHARED(DUK_ERR_TYPE_ERROR);\n}\nDUK_EXTERNAL duk_ret_t duk_uri_error_stash(duk_hthread *thr, const char *fmt, ...) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK__ERROR_STASH_SHARED(DUK_ERR_URI_ERROR);\n}\n#endif  /* DUK_USE_VARIADIC_MACROS */\n\n/*\n *  Comparison\n */\n\nDUK_EXTERNAL duk_bool_t duk_equals(duk_hthread *thr, duk_idx_t idx1, duk_idx_t idx2) {\n\tduk_tval *tv1, *tv2;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\ttv1 = duk_get_tval(thr, idx1);\n\ttv2 = duk_get_tval(thr, idx2);\n\tif ((tv1 == NULL) || (tv2 == NULL)) {\n\t\treturn 0;\n\t}\n\n\t/* Coercion may be needed, the helper handles that by pushing the\n\t * tagged values to the stack.\n\t */\n\treturn duk_js_equals(thr, tv1, tv2);\n}\n\nDUK_EXTERNAL duk_bool_t duk_strict_equals(duk_hthread *thr, duk_idx_t idx1, duk_idx_t idx2) {\n\tduk_tval *tv1, *tv2;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\ttv1 = duk_get_tval(thr, idx1);\n\ttv2 = duk_get_tval(thr, idx2);\n\tif ((tv1 == NULL) || (tv2 == NULL)) {\n\t\treturn 0;\n\t}\n\n\t/* No coercions or other side effects, so safe */\n\treturn duk_js_strict_equals(tv1, tv2);\n}\n\nDUK_EXTERNAL duk_bool_t duk_samevalue(duk_hthread *thr, duk_idx_t idx1, duk_idx_t idx2) {\n\tduk_tval *tv1, *tv2;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\ttv1 = duk_get_tval(thr, idx1);\n\ttv2 = duk_get_tval(thr, idx2);\n\tif ((tv1 == NULL) || (tv2 == NULL)) {\n\t\treturn 0;\n\t}\n\n\t/* No coercions or other side effects, so safe */\n\treturn duk_js_samevalue(tv1, tv2);\n}\n\n/*\n *  instanceof\n */\n\nDUK_EXTERNAL duk_bool_t duk_instanceof(duk_hthread *thr, duk_idx_t idx1, duk_idx_t idx2) {\n\tduk_tval *tv1, *tv2;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\t/* Index validation is strict, which differs from duk_equals().\n\t * The strict behavior mimics how instanceof itself works, e.g.\n\t * it is a TypeError if rval is not a -callable- object.  It would\n\t * be somewhat inconsistent if rval would be allowed to be\n\t * non-existent without a TypeError.\n\t */\n\ttv1 = duk_require_tval(thr, idx1);\n\tDUK_ASSERT(tv1 != NULL);\n\ttv2 = duk_require_tval(thr, idx2);\n\tDUK_ASSERT(tv2 != NULL);\n\n\treturn duk_js_instanceof(thr, tv1, tv2);\n}\n\n/*\n *  Lightfunc\n */\n\nDUK_INTERNAL void duk_push_lightfunc_name_raw(duk_hthread *thr, duk_c_function func, duk_small_uint_t lf_flags) {\n\t/* Lightfunc name, includes Duktape/C native function pointer, which\n\t * can often be used to locate the function from a symbol table.\n\t * The name also includes the 16-bit duk_tval flags field because it\n\t * includes the magic value.  Because a single native function often\n\t * provides different functionality depending on the magic value, it\n\t * seems reasonably to include it in the name.\n\t *\n\t * On the other hand, a complicated name increases string table\n\t * pressure in low memory environments (but only when function name\n\t * is accessed).\n\t */\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tduk_push_sprintf(thr, \"light_\");\n\tduk_push_string_funcptr(thr, (duk_uint8_t *) &func, sizeof(func));\n\tduk_push_sprintf(thr, \"_%04x\", (unsigned int) lf_flags);\n\tduk_concat(thr, 3);\n}\n\nDUK_INTERNAL void duk_push_lightfunc_name(duk_hthread *thr, duk_tval *tv) {\n\tduk_c_function func;\n\tduk_small_uint_t lf_flags;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK_ASSERT(DUK_TVAL_IS_LIGHTFUNC(tv));\n\n\tDUK_TVAL_GET_LIGHTFUNC(tv, func, lf_flags);\n\tduk_push_lightfunc_name_raw(thr, func, lf_flags);\n}\n\nDUK_INTERNAL void duk_push_lightfunc_tostring(duk_hthread *thr, duk_tval *tv) {\n\tduk_c_function func;\n\tduk_small_uint_t lf_flags;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK_ASSERT(DUK_TVAL_IS_LIGHTFUNC(tv));\n\n\tDUK_TVAL_GET_LIGHTFUNC(tv, func, lf_flags);  /* read before 'tv' potentially invalidated */\n\tduk_push_string(thr, \"function \");\n\tduk_push_lightfunc_name_raw(thr, func, lf_flags);\n\tduk_push_string(thr, \"() { [lightfunc code] }\");\n\tduk_concat(thr, 3);\n}\n\n/*\n *  Function pointers\n *\n *  Printing function pointers is non-portable, so we do that by hex printing\n *  bytes from memory.\n */\n\nDUK_INTERNAL void duk_push_string_funcptr(duk_hthread *thr, duk_uint8_t *ptr, duk_size_t sz) {\n\tduk_uint8_t buf[32 * 2];\n\tduk_uint8_t *p, *q;\n\tduk_small_uint_t i;\n\tduk_small_uint_t t;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK_ASSERT(sz <= 32);  /* sanity limit for function pointer size */\n\n\tp = buf;\n#if defined(DUK_USE_INTEGER_LE)\n\tq = ptr + sz;\n#else\n\tq = ptr;\n#endif\n\tfor (i = 0; i < sz; i++) {\n#if defined(DUK_USE_INTEGER_LE)\n\t\tt = *(--q);\n#else\n\t\tt = *(q++);\n#endif\n\t\t*p++ = duk_lc_digits[t >> 4];\n\t\t*p++ = duk_lc_digits[t & 0x0f];\n\t}\n\n\tduk_push_lstring(thr, (const char *) buf, sz * 2);\n}\n\n/*\n *  Push readable string summarizing duk_tval.  The operation is side effect\n *  free and will only throw from internal errors (e.g. out of memory).\n *  This is used by e.g. property access code to summarize a key/base safely,\n *  and is not intended to be fast (but small and safe).\n */\n\n/* String limits for summary strings. */\n#define DUK__READABLE_SUMMARY_MAXCHARS 96  /* maximum supported by helper */\n#define DUK__READABLE_STRING_MAXCHARS  32  /* for strings/symbols */\n#define DUK__READABLE_ERRMSG_MAXCHARS  96  /* for error messages */\n\n/* String sanitizer which escapes ASCII control characters and a few other\n * ASCII characters, passes Unicode as is, and replaces invalid UTF-8 with\n * question marks.  No errors are thrown for any input string, except in out\n * of memory situations.\n */\nDUK_LOCAL void duk__push_hstring_readable_unicode(duk_hthread *thr, duk_hstring *h_input, duk_small_uint_t maxchars) {\n\tconst duk_uint8_t *p, *p_start, *p_end;\n\tduk_uint8_t buf[DUK_UNICODE_MAX_XUTF8_LENGTH * DUK__READABLE_SUMMARY_MAXCHARS +\n\t                2 /*quotes*/ + 3 /*periods*/];\n\tduk_uint8_t *q;\n\tduk_ucodepoint_t cp;\n\tduk_small_uint_t nchars;\n\n\tDUK_ASSERT_CTX_VALID(thr);\n\tDUK_ASSERT(h_input != NULL);\n\tDUK_ASSERT(maxchars <= DUK__READABLE_SUMMARY_MAXCHARS);\n\n\tp_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input);\n\tp_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input);\n\tp = p_start;\n\tq = buf;\n\n\tnchars = 0;\n\t*q++ = (duk_uint8_t) DUK_ASC_SINGLEQUOTE;\n\tfor (;;) {\n\t\tif (p >= p_end) {\n\t\t\tbreak;\n\t\t}\n\t\tif (nchars == maxchars) {\n\t\t\t*q++ = (duk_uint8_t) DUK_ASC_PERIOD;\n\t\t\t*q++ = (duk_uint8_t) DUK_ASC_PERIOD;\n\t\t\t*q++ = (duk_uint8_t) DUK_ASC_PERIOD;\n\t\t\tbreak;\n\t\t}\n\t\tif (duk_unicode_decode_xutf8(thr, &p, p_start, p_end, &cp)) {\n\t\t\tif (cp < 0x20 || cp == 0x7f || cp == DUK_ASC_SINGLEQUOTE || cp == DUK_ASC_BACKSLASH) {\n\t\t\t\tDUK_ASSERT(DUK_UNICODE_MAX_XUTF8_LENGTH >= 4);  /* estimate is valid */\n\t\t\t\tDUK_ASSERT((cp >> 4) <= 0x0f);\n\t\t\t\t*q++ = (duk_uint8_t) DUK_ASC_BACKSLASH;\n\t\t\t\t*q++ = (duk_uint8_t) DUK_ASC_LC_X;\n\t\t\t\t*q++ = (duk_uint8_t) duk_lc_digits[cp >> 4];\n\t\t\t\t*q++ = (duk_uint8_t) duk_lc_digits[cp & 0x0f];\n\t\t\t} else {\n\t\t\t\tq += duk_unicode_encode_xutf8(cp, q);\n\t\t\t}\n\t\t} else {\n\t\t\tp++;  /* advance manually */\n\t\t\t*q++ = (duk_uint8_t) DUK_ASC_QUESTION;\n\t\t}\n\t\tnchars++;\n\t}\n\t*q++ = (duk_uint8_t) DUK_ASC_SINGLEQUOTE;\n\n\tduk_push_lstring(thr, (const char *) buf, (duk_size_t) (q - buf));\n}\n\nDUK_LOCAL const char *duk__push_string_tval_readable(duk_hthread *thr, duk_tval *tv, duk_bool_t error_aware) {\n\tDUK_ASSERT_CTX_VALID(thr);\n\t/* 'tv' may be NULL */\n\n\tif (tv == NULL) {\n\t\tduk_push_string(thr, \"none\");\n\t} else {\n\t\tswitch (DUK_TVAL_GET_TAG(tv)) {\n\t\tcase DUK_TAG_STRING: {\n\t\t\tduk_hstring *h = DUK_TVAL_GET_STRING(tv);\n\t\t\tif (DUK_HSTRING_HAS_SYMBOL(h)) {\n\t\t\t\t/* XXX: string summary produces question marks\n\t\t\t\t * so this is not very ideal.\n\t\t\t\t */\n\t\t\t\tduk_push_string(thr, \"[Symbol \");\n\t\t\t\tduk_push_string(thr, duk__get_symbol_type_string(h));\n\t\t\t\tduk_push_string(thr, \" \");\n\t\t\t\tduk__push_hstring_readable_unicode(thr, h, DUK__READABLE_STRING_MAXCHARS);\n\t\t\t\tduk_push_string(thr, \"]\");\n\t\t\t\tduk_concat(thr, 5);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tduk__push_hstring_readable_unicode(thr, h, DUK__READABLE_STRING_MAXCHARS);\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_TAG_OBJECT: {\n\t\t\tduk_hobject *h = DUK_TVAL_GET_OBJECT(tv);\n\t\t\tDUK_ASSERT(h != NULL);\n\n\t\t\tif (error_aware &&\n\t\t\t    duk_hobject_prototype_chain_contains(thr, h, thr->builtins[DUK_BIDX_ERROR_PROTOTYPE], 1 /*ignore_loop*/)) {\n\t\t\t\t/* Get error message in a side effect free way if\n\t\t\t\t * possible; if not, summarize as a generic object.\n\t\t\t\t * Error message currently gets quoted.\n\t\t\t\t */\n\t\t\t\t/* XXX: better internal getprop call; get without side effects\n\t\t\t\t * but traverse inheritance chain.\n\t\t\t\t */\n\t\t\t\tduk_tval *tv_msg;\n\t\t\t\ttv_msg = duk_hobject_find_existing_entry_tval_ptr(thr->heap, h, DUK_HTHREAD_STRING_MESSAGE(thr));\n\t\t\t\tif (tv_msg != NULL && DUK_TVAL_IS_STRING(tv_msg)) {\n\t\t\t\t\t/* It's critical to avoid recursion so\n\t\t\t\t\t * only summarize a string .message.\n\t\t\t\t\t */\n\t\t\t\t\tduk__push_hstring_readable_unicode(thr, DUK_TVAL_GET_STRING(tv_msg), DUK__READABLE_ERRMSG_MAXCHARS);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tduk_push_class_string_tval(thr, tv);\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_TAG_BUFFER: {\n\t\t\t/* While plain buffers mimic Uint8Arrays, they summarize differently.\n\t\t\t * This is useful so that the summarized string accurately reflects the\n\t\t\t * internal type which may matter for figuring out bugs etc.\n\t\t\t */\n\t\t\t/* XXX: Hex encoded, length limited buffer summary here? */\n\t\t\tduk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv);\n\t\t\tDUK_ASSERT(h != NULL);\n\t\t\tduk_push_sprintf(thr, \"[buffer:%ld]\", (long) DUK_HBUFFER_GET_SIZE(h));\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_TAG_POINTER: {\n\t\t\t/* Surround with parentheses like in JX, ensures NULL pointer\n\t\t\t * is distinguishable from null value (\"(null)\" vs \"null\").\n\t\t\t */\n\t\t\tduk_push_tval(thr, tv);\n\t\t\tduk_push_sprintf(thr, \"(%s)\", duk_to_string(thr, -1));\n\t\t\tduk_remove_m2(thr);\n\t\t\tbreak;\n\t\t}\n\t\tdefault: {\n\t\t\tduk_push_tval(thr, tv);\n\t\t\tbreak;\n\t\t}\n\t\t}\n\t}\n\n\treturn duk_to_string(thr, -1);\n}\nDUK_INTERNAL const char *duk_push_string_tval_readable(duk_hthread *thr, duk_tval *tv) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\treturn duk__push_string_tval_readable(thr, tv, 0 /*error_aware*/);\n}\n\nDUK_INTERNAL const char *duk_push_string_readable(duk_hthread *thr, duk_idx_t idx) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\treturn duk_push_string_tval_readable(thr, duk_get_tval(thr, idx));\n}\n\nDUK_INTERNAL const char *duk_push_string_tval_readable_error(duk_hthread *thr, duk_tval *tv) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\treturn duk__push_string_tval_readable(thr, tv, 1 /*error_aware*/);\n}\n\nDUK_INTERNAL void duk_push_symbol_descriptive_string(duk_hthread *thr, duk_hstring *h) {\n\tconst duk_uint8_t *p;\n\tconst duk_uint8_t *p_end;\n\tconst duk_uint8_t *q;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\t/* .toString() */\n\tduk_push_string(thr, \"Symbol(\");\n\tp = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h);\n\tp_end = p + DUK_HSTRING_GET_BYTELEN(h);\n\tDUK_ASSERT(p[0] == 0xff || (p[0] & 0xc0) == 0x80);\n\tp++;\n\tfor (q = p; q < p_end; q++) {\n\t\tif (*q == 0xffU) {\n\t\t\t/* Terminate either at end-of-string (but NUL MUST\n\t\t\t * be accepted without terminating description) or\n\t\t\t * 0xFF, which is used to mark start of unique trailer\n\t\t\t * (and cannot occur in CESU-8 / extended UTF-8).\n\t\t\t */\n\t\t\tbreak;\n\t\t}\n\t}\n\tduk_push_lstring(thr, (const char *) p, (duk_size_t) (q - p));\n\tduk_push_string(thr, \")\");\n\tduk_concat(thr, 3);\n}\n\n/*\n *  Functions\n */\n\n#if 0  /* not used yet */\nDUK_INTERNAL void duk_push_hnatfunc_name(duk_hthread *thr, duk_hnatfunc *h) {\n\tduk_c_function func;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK_ASSERT(h != NULL);\n\tDUK_ASSERT(DUK_HOBJECT_IS_NATFUNC((duk_hobject *) h));\n\n\tduk_push_sprintf(thr, \"native_\");\n\tfunc = h->func;\n\tduk_push_string_funcptr(thr, (duk_uint8_t *) &func, sizeof(func));\n\tduk_push_sprintf(thr, \"_%04x_%04x\",\n\t                 (unsigned int) (duk_uint16_t) h->nargs,\n\t                 (unsigned int) (duk_uint16_t) h->magic);\n\tduk_concat(thr, 3);\n}\n#endif\n\n/*\n *  duk_tval slice copy\n */\n\nDUK_INTERNAL void duk_copy_tvals_incref(duk_hthread *thr, duk_tval *tv_dst, duk_tval *tv_src, duk_size_t count) {\n\tduk_tval *tv;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK_UNREF(thr);\n\tDUK_ASSERT(count * sizeof(duk_tval) >= count);  /* no wrap */\n\tDUK_MEMCPY((void *) tv_dst, (const void *) tv_src, count * sizeof(duk_tval));\n\n\ttv = tv_dst;\n\twhile (count-- > 0) {\n\t\tDUK_TVAL_INCREF(thr, tv);\n\t\ttv++;\n\t}\n}\n\n/* automatic undefs */\n#undef DUK__ASSERT_SPACE\n#undef DUK__CHECK_SPACE\n#undef DUK__ERROR_STASH_SHARED\n#undef DUK__PACK_ARGS\n#undef DUK__READABLE_ERRMSG_MAXCHARS\n#undef DUK__READABLE_STRING_MAXCHARS\n#undef DUK__READABLE_SUMMARY_MAXCHARS\n#line 1 \"duk_api_string.c\"\n/*\n *  String manipulation\n */\n\n/* #include duk_internal.h -> already included */\n\nDUK_LOCAL void duk__concat_and_join_helper(duk_hthread *thr, duk_idx_t count_in, duk_bool_t is_join) {\n\tduk_uint_t count;\n\tduk_uint_t i;\n\tduk_size_t idx;\n\tduk_size_t len;\n\tduk_hstring *h;\n\tduk_uint8_t *buf;\n\n\tDUK_ASSERT_CTX_VALID(thr);\n\n\tif (DUK_UNLIKELY(count_in <= 0)) {\n\t\tif (count_in < 0) {\n\t\t\tDUK_ERROR_RANGE_INVALID_COUNT(thr);\n\t\t\treturn;\n\t\t}\n\t\tDUK_ASSERT(count_in == 0);\n\t\tduk_push_hstring_empty(thr);\n\t\treturn;\n\t}\n\tcount = (duk_uint_t) count_in;\n\n\tif (is_join) {\n\t\tduk_size_t t1, t2, limit;\n\t\th = duk_to_hstring(thr, -((duk_idx_t) count) - 1);\n\t\tDUK_ASSERT(h != NULL);\n\n\t\t/* A bit tricky overflow test, see doc/code-issues.rst. */\n\t\tt1 = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h);\n\t\tt2 = (duk_size_t) (count - 1);\n\t\tlimit = (duk_size_t) DUK_HSTRING_MAX_BYTELEN;\n\t\tif (DUK_UNLIKELY(t2 != 0 && t1 > limit / t2)) {\n\t\t\t/* Combined size of separators already overflows. */\n\t\t\tgoto error_overflow;\n\t\t}\n\t\tlen = (duk_size_t) (t1 * t2);\n\t} else {\n\t\tlen = (duk_size_t) 0;\n\t}\n\n\tfor (i = count; i >= 1; i--) {\n\t\tduk_size_t new_len;\n\t\th = duk_to_hstring(thr, -((duk_idx_t) i));\n\t\tnew_len = len + (duk_size_t) DUK_HSTRING_GET_BYTELEN(h);\n\n\t\t/* Impose a string maximum length, need to handle overflow\n\t\t * correctly.\n\t\t */\n\t\tif (new_len < len ||  /* wrapped */\n\t\t    new_len > (duk_size_t) DUK_HSTRING_MAX_BYTELEN) {\n\t\t\tgoto error_overflow;\n\t\t}\n\t\tlen = new_len;\n\t}\n\n\tDUK_DDD(DUK_DDDPRINT(\"join/concat %lu strings, total length %lu bytes\",\n\t                     (unsigned long) count, (unsigned long) len));\n\n\t/* Use stack allocated buffer to ensure reachability in errors\n\t * (e.g. intern error).\n\t */\n\tbuf = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, len);\n\tDUK_ASSERT(buf != NULL);\n\n\t/* [ ... (sep) str1 str2 ... strN buf ] */\n\n\tidx = 0;\n\tfor (i = count; i >= 1; i--) {\n\t\tif (is_join && i != count) {\n\t\t\th = duk_require_hstring(thr, -((duk_idx_t) count) - 2);  /* extra -1 for buffer */\n\t\t\tDUK_MEMCPY(buf + idx, DUK_HSTRING_GET_DATA(h), DUK_HSTRING_GET_BYTELEN(h));\n\t\t\tidx += DUK_HSTRING_GET_BYTELEN(h);\n\t\t}\n\t\th = duk_require_hstring(thr, -((duk_idx_t) i) - 1);  /* extra -1 for buffer */\n\t\tDUK_MEMCPY(buf + idx, DUK_HSTRING_GET_DATA(h), DUK_HSTRING_GET_BYTELEN(h));\n\t\tidx += DUK_HSTRING_GET_BYTELEN(h);\n\t}\n\n\tDUK_ASSERT(idx == len);\n\n\t/* [ ... (sep) str1 str2 ... strN buf ] */\n\n\t/* Get rid of the strings early to minimize memory use before intern. */\n\n\tif (is_join) {\n\t\tduk_replace(thr, -((duk_idx_t) count) - 2);  /* overwrite sep */\n\t\tduk_pop_n(thr, (duk_idx_t) count);\n\t} else {\n\t\tduk_replace(thr, -((duk_idx_t) count) - 1);  /* overwrite str1 */\n\t\tduk_pop_n(thr, (duk_idx_t) (count - 1));\n\t}\n\n\t/* [ ... buf ] */\n\n\t(void) duk_buffer_to_string(thr, -1);  /* Safe if inputs are safe. */\n\n\t/* [ ... res ] */\n\treturn;\n\n error_overflow:\n\tDUK_ERROR_RANGE(thr, DUK_STR_RESULT_TOO_LONG);\n}\n\nDUK_EXTERNAL void duk_concat(duk_hthread *thr, duk_idx_t count) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tduk__concat_and_join_helper(thr, count, 0 /*is_join*/);\n}\n\n#if defined(DUK_USE_PREFER_SIZE)\nDUK_INTERNAL void duk_concat_2(duk_hthread *thr) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\tduk_concat(thr, 2);\n}\n#else  /* DUK_USE_PREFER_SIZE */\nDUK_INTERNAL void duk_concat_2(duk_hthread *thr) {\n\tduk_hstring *h1;\n\tduk_hstring *h2;\n\tduk_uint8_t *buf;\n\tduk_size_t len1;\n\tduk_size_t len2;\n\tduk_size_t len;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK_ASSERT(duk_get_top(thr) >= 2);  /* Trusted caller. */\n\n\th1 = duk_to_hstring(thr, -2);\n\th2 = duk_to_hstring(thr, -1);\n\tlen1 = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h1);\n\tlen2 = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h2);\n\tlen = len1 + len2;\n\tif (DUK_UNLIKELY(len < len1 ||  /* wrapped */\n\t                 len > (duk_size_t) DUK_HSTRING_MAX_BYTELEN)) {\n\t\tgoto error_overflow;\n\t}\n\tbuf = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, len);\n\tDUK_ASSERT(buf != NULL);\n\n\tDUK_MEMCPY((void *) buf, (const void *) DUK_HSTRING_GET_DATA(h1), (size_t) len1);\n\tDUK_MEMCPY((void *) (buf + len1), (const void *) DUK_HSTRING_GET_DATA(h2), (size_t) len2);\n\t(void) duk_buffer_to_string(thr, -1);  /* Safe if inputs are safe. */\n\n\t/* [ ... str1 str2 buf ] */\n\n\tduk_replace(thr, -3);\n\tduk_pop_unsafe(thr);\n\treturn;\n\n error_overflow:\n\tDUK_ERROR_RANGE(thr, DUK_STR_RESULT_TOO_LONG);\n}\n#endif  /* DUK_USE_PREFER_SIZE */\n\nDUK_EXTERNAL void duk_join(duk_hthread *thr, duk_idx_t count) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tduk__concat_and_join_helper(thr, count, 1 /*is_join*/);\n}\n\n/* XXX: could map/decode be unified with duk_unicode_support.c code?\n * Case conversion needs also the character surroundings though.\n */\n\nDUK_EXTERNAL void duk_decode_string(duk_hthread *thr, duk_idx_t idx, duk_decode_char_function callback, void *udata) {\n\tduk_hstring *h_input;\n\tconst duk_uint8_t *p, *p_start, *p_end;\n\tduk_codepoint_t cp;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\th_input = duk_require_hstring(thr, idx);  /* Accept symbols. */\n\tDUK_ASSERT(h_input != NULL);\n\n\tp_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input);\n\tp_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input);\n\tp = p_start;\n\n\tfor (;;) {\n\t\tif (p >= p_end) {\n\t\t\tbreak;\n\t\t}\n\t\tcp = (duk_codepoint_t) duk_unicode_decode_xutf8_checked(thr, &p, p_start, p_end);\n\t\tcallback(udata, cp);\n\t}\n}\n\nDUK_EXTERNAL void duk_map_string(duk_hthread *thr, duk_idx_t idx, duk_map_char_function callback, void *udata) {\n\tduk_hstring *h_input;\n\tduk_bufwriter_ctx bw_alloc;\n\tduk_bufwriter_ctx *bw;\n\tconst duk_uint8_t *p, *p_start, *p_end;\n\tduk_codepoint_t cp;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tidx = duk_normalize_index(thr, idx);\n\n\th_input = duk_require_hstring(thr, idx);  /* Accept symbols. */\n\tDUK_ASSERT(h_input != NULL);\n\n\tbw = &bw_alloc;\n\tDUK_BW_INIT_PUSHBUF(thr, bw, DUK_HSTRING_GET_BYTELEN(h_input));  /* Reasonable output estimate. */\n\n\tp_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input);\n\tp_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input);\n\tp = p_start;\n\n\tfor (;;) {\n\t\t/* XXX: could write output in chunks with fewer ensure calls,\n\t\t * but relative benefit would be small here.\n\t\t */\n\n\t\tif (p >= p_end) {\n\t\t\tbreak;\n\t\t}\n\t\tcp = (duk_codepoint_t) duk_unicode_decode_xutf8_checked(thr, &p, p_start, p_end);\n\t\tcp = callback(udata, cp);\n\n\t\tDUK_BW_WRITE_ENSURE_XUTF8(thr, bw, cp);\n\t}\n\n\tDUK_BW_COMPACT(thr, bw);\n\t(void) duk_buffer_to_string(thr, -1);  /* Safe, extended UTF-8 encoded. */\n\tduk_replace(thr, idx);\n}\n\nDUK_EXTERNAL void duk_substring(duk_hthread *thr, duk_idx_t idx, duk_size_t start_offset, duk_size_t end_offset) {\n\tduk_hstring *h;\n\tduk_hstring *res;\n\tduk_size_t start_byte_offset;\n\tduk_size_t end_byte_offset;\n\tduk_size_t charlen;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tidx = duk_require_normalize_index(thr, idx);  /* Accept symbols. */\n\th = duk_require_hstring(thr, idx);\n\tDUK_ASSERT(h != NULL);\n\n\tcharlen = DUK_HSTRING_GET_CHARLEN(h);\n\tif (end_offset >= charlen) {\n\t\tend_offset = charlen;\n\t}\n\tif (start_offset > end_offset) {\n\t\tstart_offset = end_offset;\n\t}\n\n\tDUK_ASSERT_DISABLE(start_offset >= 0);\n\tDUK_ASSERT(start_offset <= end_offset && start_offset <= DUK_HSTRING_GET_CHARLEN(h));\n\tDUK_ASSERT_DISABLE(end_offset >= 0);\n\tDUK_ASSERT(end_offset >= start_offset && end_offset <= DUK_HSTRING_GET_CHARLEN(h));\n\n\t/* Guaranteed by string limits. */\n\tDUK_ASSERT(start_offset <= DUK_UINT32_MAX);\n\tDUK_ASSERT(end_offset <= DUK_UINT32_MAX);\n\n\tstart_byte_offset = (duk_size_t) duk_heap_strcache_offset_char2byte(thr, h, (duk_uint_fast32_t) start_offset);\n\tend_byte_offset = (duk_size_t) duk_heap_strcache_offset_char2byte(thr, h, (duk_uint_fast32_t) end_offset);\n\n\tDUK_ASSERT(end_byte_offset >= start_byte_offset);\n\tDUK_ASSERT(end_byte_offset - start_byte_offset <= DUK_UINT32_MAX);  /* Guaranteed by string limits. */\n\n\t/* No size check is necessary. */\n\tres = duk_heap_strtable_intern_checked(thr,\n\t                                       DUK_HSTRING_GET_DATA(h) + start_byte_offset,\n\t                                       (duk_uint32_t) (end_byte_offset - start_byte_offset));\n\n\tduk_push_hstring(thr, res);\n\tduk_replace(thr, idx);\n}\n\n/* XXX: this is quite clunky.  Add Unicode helpers to scan backwards and\n * forwards with a callback to process codepoints?\n */\nDUK_EXTERNAL void duk_trim(duk_hthread *thr, duk_idx_t idx) {\n\tduk_hstring *h;\n\tconst duk_uint8_t *p, *p_start, *p_end, *p_tmp1, *p_tmp2;  /* pointers for scanning */\n\tconst duk_uint8_t *q_start, *q_end;  /* start (incl) and end (excl) of trimmed part */\n\tduk_codepoint_t cp;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\tidx = duk_require_normalize_index(thr, idx);  /* Accept symbols. */\n\th = duk_require_hstring(thr, idx);\n\tDUK_ASSERT(h != NULL);\n\n\tp_start = DUK_HSTRING_GET_DATA(h);\n\tp_end = p_start + DUK_HSTRING_GET_BYTELEN(h);\n\n\tp = p_start;\n\twhile (p < p_end) {\n\t\tp_tmp1 = p;\n\t\tcp = (duk_codepoint_t) duk_unicode_decode_xutf8_checked(thr, &p_tmp1, p_start, p_end);\n\t\tif (!(duk_unicode_is_whitespace(cp) || duk_unicode_is_line_terminator(cp))) {\n\t\t\tbreak;\n\t\t}\n\t\tp = p_tmp1;\n\t}\n\tq_start = p;\n\tif (p == p_end) {\n\t\t/* Entire string is whitespace. */\n\t\tq_end = p;\n\t\tgoto scan_done;\n\t}\n\n\tp = p_end;\n\twhile (p > p_start) {\n\t\tp_tmp1 = p;\n\t\twhile (p > p_start) {\n\t\t\tp--;\n\t\t\tif (((*p) & 0xc0) != 0x80) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tp_tmp2 = p;\n\n\t\tcp = (duk_codepoint_t) duk_unicode_decode_xutf8_checked(thr, &p_tmp2, p_start, p_end);\n\t\tif (!(duk_unicode_is_whitespace(cp) || duk_unicode_is_line_terminator(cp))) {\n\t\t\tp = p_tmp1;\n\t\t\tbreak;\n\t\t}\n\t}\n\tq_end = p;\n\n scan_done:\n\t/* This may happen when forward and backward scanning disagree\n\t * (possible for non-extended-UTF-8 strings).\n\t */\n\tif (q_end < q_start) {\n\t\tq_end = q_start;\n\t}\n\n\tDUK_ASSERT(q_start >= p_start && q_start <= p_end);\n\tDUK_ASSERT(q_end >= p_start && q_end <= p_end);\n\tDUK_ASSERT(q_end >= q_start);\n\n\tDUK_DDD(DUK_DDDPRINT(\"trim: p_start=%p, p_end=%p, q_start=%p, q_end=%p\",\n\t                     (const void *) p_start, (const void *) p_end,\n\t                     (const void *) q_start, (const void *) q_end));\n\n\tif (q_start == p_start && q_end == p_end) {\n\t\tDUK_DDD(DUK_DDDPRINT(\"nothing was trimmed: avoid interning (hashing etc)\"));\n\t\treturn;\n\t}\n\n\tduk_push_lstring(thr, (const char *) q_start, (duk_size_t) (q_end - q_start));\n\tduk_replace(thr, idx);\n}\n\nDUK_EXTERNAL duk_codepoint_t duk_char_code_at(duk_hthread *thr, duk_idx_t idx, duk_size_t char_offset) {\n\tduk_hstring *h;\n\tduk_ucodepoint_t cp;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\n\t/* XXX: Share code with String.prototype.charCodeAt?  Main difference\n\t * is handling of clamped offsets.\n\t */\n\n\th = duk_require_hstring(thr, idx);  /* Accept symbols. */\n\tDUK_ASSERT(h != NULL);\n\n\tDUK_ASSERT_DISABLE(char_offset >= 0);  /* Always true, arg is unsigned. */\n\tif (char_offset >= DUK_HSTRING_GET_CHARLEN(h)) {\n\t\treturn 0;\n\t}\n\n\tDUK_ASSERT(char_offset <= DUK_UINT_MAX);  /* Guaranteed by string limits. */\n\tcp = duk_hstring_char_code_at_raw(thr, h, (duk_uint_t) char_offset, 0 /*surrogate_aware*/);\n\treturn (duk_codepoint_t) cp;\n}\n#line 1 \"duk_api_time.c\"\n/*\n *  Date/time.\n */\n\n/* #include duk_internal.h -> already included */\n\nDUK_INTERNAL duk_double_t duk_time_get_ecmascript_time(duk_hthread *thr) {\n\t/* Ecmascript time, with millisecond fractions.  Exposed via\n\t * duk_get_now() for example.\n\t */\n\tDUK_UNREF(thr);\n\treturn (duk_double_t) DUK_USE_DATE_GET_NOW(thr);\n}\n\nDUK_INTERNAL duk_double_t duk_time_get_ecmascript_time_nofrac(duk_hthread *thr) {\n\t/* Ecmascript time without millisecond fractions.  Exposed via\n\t * the Date built-in which doesn't allow fractions.\n\t */\n\tDUK_UNREF(thr);\n\treturn (duk_double_t) DUK_FLOOR(DUK_USE_DATE_GET_NOW(thr));\n}\n\nDUK_INTERNAL duk_double_t duk_time_get_monotonic_time(duk_hthread *thr) {\n\tDUK_UNREF(thr);\n#if defined(DUK_USE_GET_MONOTONIC_TIME)\n\treturn (duk_double_t) DUK_USE_GET_MONOTONIC_TIME(thr);\n#else\n\treturn (duk_double_t) DUK_USE_DATE_GET_NOW(thr);\n#endif\n}\n\nDUK_EXTERNAL duk_double_t duk_get_now(duk_hthread *thr) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK_UNREF(thr);\n\n\t/* This API intentionally allows millisecond fractions. */\n\treturn duk_time_get_ecmascript_time(thr);\n}\n\n#if 0  /* XXX: worth exposing? */\nDUK_EXTERNAL duk_double_t duk_get_monotonic_time(duk_hthread *thr) {\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK_UNREF(thr);\n\n\treturn duk_time_get_monotonic_time(thr);\n}\n#endif\n\nDUK_EXTERNAL void duk_time_to_components(duk_hthread *thr, duk_double_t timeval, duk_time_components *comp) {\n\tduk_int_t parts[DUK_DATE_IDX_NUM_PARTS];\n\tduk_double_t dparts[DUK_DATE_IDX_NUM_PARTS];\n\tduk_uint_t flags;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK_ASSERT(comp != NULL);  /* XXX: or check? */\n\tDUK_UNREF(thr);\n\n\t/* Convert as one-based, but change month to zero-based to match the\n\t * Ecmascript Date built-in behavior 1:1.\n\t */\n\tflags = DUK_DATE_FLAG_ONEBASED | DUK_DATE_FLAG_NAN_TO_ZERO;\n\n\tduk_bi_date_timeval_to_parts(timeval, parts, dparts, flags);\n\n\t/* XXX: sub-millisecond accuracy for the API */\n\n\tDUK_ASSERT(dparts[DUK_DATE_IDX_MONTH] >= 1.0 && dparts[DUK_DATE_IDX_MONTH] <= 12.0);\n\tcomp->year = dparts[DUK_DATE_IDX_YEAR];\n\tcomp->month = dparts[DUK_DATE_IDX_MONTH] - 1.0;\n\tcomp->day = dparts[DUK_DATE_IDX_DAY];\n\tcomp->hours = dparts[DUK_DATE_IDX_HOUR];\n\tcomp->minutes = dparts[DUK_DATE_IDX_MINUTE];\n\tcomp->seconds = dparts[DUK_DATE_IDX_SECOND];\n\tcomp->milliseconds = dparts[DUK_DATE_IDX_MILLISECOND];\n\tcomp->weekday = dparts[DUK_DATE_IDX_WEEKDAY];\n}\n\nDUK_EXTERNAL duk_double_t duk_components_to_time(duk_hthread *thr, duk_time_components *comp) {\n\tduk_double_t d;\n\tduk_double_t dparts[DUK_DATE_IDX_NUM_PARTS];\n\tduk_uint_t flags;\n\n\tDUK_ASSERT_API_ENTRY(thr);\n\tDUK_ASSERT(comp != NULL);  /* XXX: or check? */\n\tDUK_UNREF(thr);\n\n\t/* Match Date constructor behavior (with UTC time).  Month is given\n\t * as zero-based.  Day-of-month is given as one-based so normalize\n\t * it to zero-based as the internal conversion helpers expects all\n\t * components to be zero-based.\n\t */\n\tflags = 0;\n\n\t/* XXX: expensive conversion; use array format in API instead, or unify\n\t * time provider and time API to use same struct?\n\t */\n\n\tdparts[DUK_DATE_IDX_YEAR] = comp->year;\n\tdparts[DUK_DATE_IDX_MONTH] = comp->month;\n\tdparts[DUK_DATE_IDX_DAY] = comp->day - 1.0;\n\tdparts[DUK_DATE_IDX_HOUR] = comp->hours;\n\tdparts[DUK_DATE_IDX_MINUTE] = comp->minutes;\n\tdparts[DUK_DATE_IDX_SECOND] = comp->seconds;\n\tdparts[DUK_DATE_IDX_MILLISECOND] = comp->milliseconds;\n\tdparts[DUK_DATE_IDX_WEEKDAY] = 0;  /* ignored */\n\n\td = duk_bi_date_get_timeval_from_dparts(dparts, flags);\n\n\treturn d;\n}\n#line 1 \"duk_bi_array.c\"\n/*\n *  Array built-ins\n *\n *  Most Array built-ins are intentionally generic in Ecmascript, and are\n *  intended to work even when the 'this' binding is not an Array instance.\n *  This Ecmascript feature is also used by much real world code.  For this\n *  reason the implementations here don't assume exotic Array behavior or\n *  e.g. presence of a .length property.  However, some algorithms have a\n *  fast path for duk_harray backed actual Array instances, enabled when\n *  footprint is not a concern.\n *\n *  XXX: the \"Throw\" flag should be set for (almost?) all [[Put]] and\n *  [[Delete]] operations, but it's currently false throughout.  Go through\n *  all put/delete cases and check throw flag use.  Need a new API primitive\n *  which allows throws flag to be specified.\n *\n *  XXX: array lengths above 2G won't work reliably.  There are many places\n *  where one needs a full signed 32-bit range ([-0xffffffff, 0xffffffff],\n *  i.e. -33- bits).  Although array 'length' cannot be written to be outside\n *  the unsigned 32-bit range (E5.1 Section 15.4.5.1 throws a RangeError if so)\n *  some intermediate values may be above 0xffffffff and this may not be always\n *  correctly handled now (duk_uint32_t is not enough for all algorithms).\n *  For instance, push() can legitimately write entries beyond length 0xffffffff\n *  and cause a RangeError only at the end.  To do this properly, the current\n *  push() implementation tracks the array index using a 'double' instead of a\n *  duk_uint32_t (which is somewhat awkward).  See test-bi-array-push-maxlen.js.\n *\n *  On using \"put\" vs. \"def\" prop\n *  =============================\n *\n *  Code below must be careful to use the appropriate primitive as it matters\n *  for compliance.  When using \"put\" there may be inherited properties in\n *  Array.prototype which cause side effects when values are written.  When\n *  using \"define\" there are no such side effects, and many test262 test cases\n *  check for this (for real world code, such side effects are very rare).\n *  Both \"put\" and \"define\" are used in the E5.1 specification; as a rule,\n *  \"put\" is used when modifying an existing array (or a non-array 'this'\n *  binding) and \"define\" for setting values into a fresh result array.\n */\n\n/* #include duk_internal.h -> already included */\n\n/* Perform an intermediate join when this many elements have been pushed\n * on the value stack.\n */\n#define  DUK__ARRAY_MID_JOIN_LIMIT  4096\n\n#if defined(DUK_USE_ARRAY_BUILTIN)\n\n/*\n *  Shared helpers.\n */\n\n/* Shared entry code for many Array built-ins: the 'this' binding is pushed\n * on the value stack and object coerced, and the current .length is returned.\n * Note that length is left on stack (it could be popped, but that's not\n * usually necessary because call handling will clean it up automatically).\n */\nDUK_LOCAL duk_uint32_t duk__push_this_obj_len_u32(duk_hthread *thr) {\n\tduk_uint32_t len;\n\n\t/* XXX: push more directly? */\n\t(void) duk_push_this_coercible_to_object(thr);\n\tDUK_ASSERT_HOBJECT_VALID(duk_get_hobject(thr, -1));\n\tduk_get_prop_stridx_short(thr, -1, DUK_STRIDX_LENGTH);\n\tlen = duk_to_uint32(thr, -1);\n\n\t/* -> [ ... ToObject(this) ToUint32(length) ] */\n\treturn len;\n}\n\nDUK_LOCAL duk_uint32_t duk__push_this_obj_len_u32_limited(duk_hthread *thr) {\n\t/* Range limited to [0, 0x7fffffff] range, i.e. range that can be\n\t * represented with duk_int32_t.  Use this when the method doesn't\n\t * handle the full 32-bit unsigned range correctly.\n\t */\n\tduk_uint32_t ret = duk__push_this_obj_len_u32(thr);\n\tif (DUK_UNLIKELY(ret >= 0x80000000UL)) {\n\t\tDUK_ERROR_RANGE_INVALID_LENGTH(thr);\n\t}\n\treturn ret;\n}\n\n#if defined(DUK_USE_ARRAY_FASTPATH)\n/* Check if 'this' binding is an Array instance (duk_harray) which satisfies\n * a few other guarantees for fast path operation.  The fast path doesn't\n * need to handle all operations, even for duk_harrays, but must handle a\n * significant fraction to improve performance.  Return a non-NULL duk_harray\n * pointer when all fast path criteria are met, NULL otherwise.\n */\nDUK_LOCAL duk_harray *duk__arraypart_fastpath_this(duk_hthread *thr) {\n\tduk_tval *tv;\n\tduk_hobject *h;\n\tduk_uint_t flags_mask, flags_bits, flags_value;\n\n\tDUK_ASSERT(thr->valstack_bottom > thr->valstack);  /* because call in progress */\n\ttv = DUK_GET_THIS_TVAL_PTR(thr);\n\n\t/* Fast path requires that 'this' is a duk_harray.  Read only arrays\n\t * (ROM backed) are also rejected for simplicity.\n\t */\n\tif (!DUK_TVAL_IS_OBJECT(tv)) {\n\t\tDUK_DD(DUK_DDPRINT(\"reject array fast path: not an object\"));\n\t\treturn NULL;\n\t}\n\th = DUK_TVAL_GET_OBJECT(tv);\n\tDUK_ASSERT(h != NULL);\n\tflags_mask = DUK_HOBJECT_FLAG_ARRAY_PART | \\\n\t             DUK_HOBJECT_FLAG_EXOTIC_ARRAY | \\\n\t             DUK_HEAPHDR_FLAG_READONLY;\n\tflags_bits = DUK_HOBJECT_FLAG_ARRAY_PART | \\\n\t             DUK_HOBJECT_FLAG_EXOTIC_ARRAY;\n\tflags_value = DUK_HEAPHDR_GET_FLAGS_RAW((duk_heaphdr *) h);\n\tif ((flags_value & flags_mask) != flags_bits) {\n\t\tDUK_DD(DUK_DDPRINT(\"reject array fast path: object flag check failed\"));\n\t\treturn NULL;\n\t}\n\n\t/* In some cases a duk_harray's 'length' may be larger than the\n\t * current array part allocation.  Avoid the fast path in these\n\t * cases, so that all fast path code can safely assume that all\n\t * items in the range [0,length[ are backed by the current array\n\t * part allocation.\n\t */\n\tif (((duk_harray *) h)->length > DUK_HOBJECT_GET_ASIZE(h)) {\n\t\tDUK_DD(DUK_DDPRINT(\"reject array fast path: length > array part size\"));\n\t\treturn NULL;\n\t}\n\n\t/* Guarantees for fast path. */\n\tDUK_ASSERT(h != NULL);\n\tDUK_ASSERT(DUK_HOBJECT_GET_ASIZE(h) == 0 || DUK_HOBJECT_A_GET_BASE(thr->heap, h) != NULL);\n\tDUK_ASSERT(((duk_harray *) h)->length <= DUK_HOBJECT_GET_ASIZE(h));\n\n\tDUK_DD(DUK_DDPRINT(\"array fast path allowed for: %!O\", (duk_heaphdr *) h));\n\treturn (duk_harray *) h;\n}\n#endif  /* DUK_USE_ARRAY_FASTPATH */\n\n/*\n *  Constructor\n */\n\nDUK_INTERNAL duk_ret_t duk_bi_array_constructor(duk_hthread *thr) {\n\tduk_idx_t nargs;\n\tduk_harray *a;\n\tduk_double_t d;\n\tduk_uint32_t len;\n\tduk_uint32_t len_prealloc;\n\n\tnargs = duk_get_top(thr);\n\n\tif (nargs == 1 && duk_is_number(thr, 0)) {\n\t\t/* XXX: expensive check (also shared elsewhere - so add a shared internal API call?) */\n\t\td = duk_get_number(thr, 0);\n\t\tlen = duk_to_uint32(thr, 0);\n\t\tif (((duk_double_t) len) != d) {\n\t\t\tDUK_DCERROR_RANGE_INVALID_LENGTH(thr);\n\t\t}\n\n\t\t/* For small lengths create a dense preallocated array.\n\t\t * For large arrays preallocate an initial part.\n\t\t */\n\t\tlen_prealloc = len < 64 ? len : 64;\n\t\ta = duk_push_harray_with_size(thr, len_prealloc);\n\t\tDUK_ASSERT(a != NULL);\n\t\ta->length = len;\n\t\treturn 1;\n\t}\n\n\tduk_pack(thr, nargs);\n\treturn 1;\n}\n\n/*\n *  isArray()\n */\n\nDUK_INTERNAL duk_ret_t duk_bi_array_constructor_is_array(duk_hthread *thr) {\n\tduk_hobject *h;\n\n\th = duk_get_hobject_with_class(thr, 0, DUK_HOBJECT_CLASS_ARRAY);\n\tduk_push_boolean(thr, (h != NULL));\n\treturn 1;\n}\n\n/*\n *  toString()\n */\n\nDUK_INTERNAL duk_ret_t duk_bi_array_prototype_to_string(duk_hthread *thr) {\n\t(void) duk_push_this_coercible_to_object(thr);\n\tduk_get_prop_stridx_short(thr, -1, DUK_STRIDX_JOIN);\n\n\t/* [ ... this func ] */\n\tif (!duk_is_callable(thr, -1)) {\n\t\t/* Fall back to the initial (original) Object.toString().  We don't\n\t\t * currently have pointers to the built-in functions, only the top\n\t\t * level global objects (like \"Array\") so this is now done in a bit\n\t\t * of a hacky manner.  It would be cleaner to push the (original)\n\t\t * function and use duk_call_method().\n\t\t */\n\n\t\t/* XXX: 'this' will be ToObject() coerced twice, which is incorrect\n\t\t * but should have no visible side effects.\n\t\t */\n\t\tDUK_DDD(DUK_DDDPRINT(\"this.join is not callable, fall back to (original) Object.toString\"));\n\t\tduk_set_top(thr, 0);\n\t\treturn duk_bi_object_prototype_to_string(thr);  /* has access to 'this' binding */\n\t}\n\n\t/* [ ... this func ] */\n\n\tduk_insert(thr, -2);\n\n\t/* [ ... func this ] */\n\n\tDUK_DDD(DUK_DDDPRINT(\"calling: func=%!iT, this=%!iT\",\n\t                     (duk_tval *) duk_get_tval(thr, -2),\n\t                     (duk_tval *) duk_get_tval(thr, -1)));\n\tduk_call_method(thr, 0);\n\n\treturn 1;\n}\n\n/*\n *  concat()\n */\n\nDUK_INTERNAL duk_ret_t duk_bi_array_prototype_concat(duk_hthread *thr) {\n\tduk_idx_t i, n;\n\tduk_uarridx_t idx, idx_last;\n\tduk_uarridx_t j, len;\n\tduk_hobject *h;\n\n\t/* XXX: the insert here is a bit expensive if there are a lot of items.\n\t * It could also be special cased in the outermost for loop quite easily\n\t * (as the element is dup()'d anyway).\n\t */\n\n\t(void) duk_push_this_coercible_to_object(thr);\n\tduk_insert(thr, 0);\n\tn = duk_get_top(thr);\n\tduk_push_array(thr);  /* -> [ ToObject(this) item1 ... itemN arr ] */\n\n\t/* NOTE: The Array special behaviors are NOT invoked by duk_xdef_prop_index()\n\t * (which differs from the official algorithm).  If no error is thrown, this\n\t * doesn't matter as the length is updated at the end.  However, if an error\n\t * is thrown, the length will be unset.  That shouldn't matter because the\n\t * caller won't get a reference to the intermediate value.\n\t */\n\n\tidx = 0;\n\tidx_last = 0;\n\tfor (i = 0; i < n; i++) {\n\t\tDUK_ASSERT_TOP(thr, n + 1);\n\n\t\t/* [ ToObject(this) item1 ... itemN arr ] */\n\n\t\tduk_dup(thr, i);\n\t\th = duk_get_hobject_with_class(thr, -1, DUK_HOBJECT_CLASS_ARRAY);\n\t\tif (!h) {\n\t\t\tduk_xdef_prop_index_wec(thr, -2, idx++);\n\t\t\tidx_last = idx;\n\t\t\tcontinue;\n\t\t}\n\n\t\t/* [ ToObject(this) item1 ... itemN arr item(i) ] */\n\n\t\t/* XXX: an array can have length higher than 32 bits; this is not handled\n\t\t * correctly now.\n\t\t */\n\t\tlen = (duk_uarridx_t) duk_get_length(thr, -1);\n\t\tfor (j = 0; j < len; j++) {\n\t\t\tif (duk_get_prop_index(thr, -1, j)) {\n\t\t\t\t/* [ ToObject(this) item1 ... itemN arr item(i) item(i)[j] ] */\n\t\t\t\tduk_xdef_prop_index_wec(thr, -3, idx++);\n\t\t\t\tidx_last = idx;\n\t\t\t} else {\n\t\t\t\tidx++;\n\t\t\t\tduk_pop_undefined(thr);\n#if defined(DUK_USE_NONSTD_ARRAY_CONCAT_TRAILER)\n\t\t\t\t/* According to E5.1 Section 15.4.4.4 nonexistent trailing\n\t\t\t\t * elements do not affect 'length' of the result.  Test262\n\t\t\t\t * and other engines disagree, so update idx_last here too.\n\t\t\t\t */\n\t\t\t\tidx_last = idx;\n#else\n\t\t\t\t/* Strict standard behavior, ignore trailing elements for\n\t\t\t\t * result 'length'.\n\t\t\t\t */\n#endif\n\t\t\t}\n\t\t}\n\t\tduk_pop_unsafe(thr);\n\t}\n\n\t/* The E5.1 Section 15.4.4.4 algorithm doesn't set the length explicitly\n\t * in the end, but because we're operating with an internal value which\n\t * is known to be an array, this should be equivalent.\n\t */\n\tduk_push_uarridx(thr, idx_last);\n\tduk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_W);\n\n\tDUK_ASSERT_TOP(thr, n + 1);\n\treturn 1;\n}\n\n/*\n *  join(), toLocaleString()\n *\n *  Note: checking valstack is necessary, but only in the per-element loop.\n *\n *  Note: the trivial approach of pushing all the elements on the value stack\n *  and then calling duk_join() fails when the array contains a large number\n *  of elements.  This problem can't be offloaded to duk_join() because the\n *  elements to join must be handled here and have special handling.  Current\n *  approach is to do intermediate joins with very large number of elements.\n *  There is no fancy handling; the prefix gets re-joined multiple times.\n */\n\nDUK_INTERNAL duk_ret_t duk_bi_array_prototype_join_shared(duk_hthread *thr) {\n\tduk_uint32_t len, count;\n\tduk_uint32_t idx;\n\tduk_small_int_t to_locale_string = duk_get_current_magic(thr);\n\tduk_idx_t valstack_required;\n\n\t/* For join(), nargs is 1.  For toLocaleString(), nargs is 0 and\n\t * setting the top essentially pushes an undefined to the stack,\n\t * thus defaulting to a comma separator.\n\t */\n\tduk_set_top(thr, 1);\n\tif (duk_is_undefined(thr, 0)) {\n\t\tduk_pop_undefined(thr);\n\t\tduk_push_hstring_stridx(thr, DUK_STRIDX_COMMA);\n\t} else {\n\t\tduk_to_string(thr, 0);\n\t}\n\n\tlen = duk__push_this_obj_len_u32(thr);\n\n\t/* [ sep ToObject(this) len ] */\n\n\tDUK_DDD(DUK_DDDPRINT(\"sep=%!T, this=%!T, len=%lu\",\n\t                     (duk_tval *) duk_get_tval(thr, 0),\n\t                     (duk_tval *) duk_get_tval(thr, 1),\n\t                     (unsigned long) len));\n\n\t/* The extra (+4) is tight. */\n\tvalstack_required = (duk_idx_t) ((len >= DUK__ARRAY_MID_JOIN_LIMIT ?\n\t                                  DUK__ARRAY_MID_JOIN_LIMIT : len) + 4);\n\tduk_require_stack(thr, valstack_required);\n\n\tduk_dup_0(thr);\n\n\t/* [ sep ToObject(this) len sep ] */\n\n\tcount = 0;\n\tidx = 0;\n\tfor (;;) {\n\t\tDUK_DDD(DUK_DDDPRINT(\"join idx=%ld\", (long) idx));\n\t\tif (count >= DUK__ARRAY_MID_JOIN_LIMIT ||   /* intermediate join to avoid valstack overflow */\n\t\t    idx >= len) { /* end of loop (careful with len==0) */\n\t\t\t/* [ sep ToObject(this) len sep str0 ... str(count-1) ] */\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"mid/final join, count=%ld, idx=%ld, len=%ld\",\n\t\t\t                     (long) count, (long) idx, (long) len));\n\t\t\tduk_join(thr, (duk_idx_t) count);  /* -> [ sep ToObject(this) len str ] */\n\t\t\tduk_dup_0(thr);                    /* -> [ sep ToObject(this) len str sep ] */\n\t\t\tduk_insert(thr, -2);               /* -> [ sep ToObject(this) len sep str ] */\n\t\t\tcount = 1;\n\t\t}\n\t\tif (idx >= len) {\n\t\t\t/* if true, the stack already contains the final result */\n\t\t\tbreak;\n\t\t}\n\n\t\tduk_get_prop_index(thr, 1, (duk_uarridx_t) idx);\n\t\tif (duk_is_null_or_undefined(thr, -1)) {\n\t\t\tduk_pop_nodecref_unsafe(thr);\n\t\t\tduk_push_hstring_empty(thr);\n\t\t} else {\n\t\t\tif (to_locale_string) {\n\t\t\t\tduk_to_object(thr, -1);\n\t\t\t\tduk_get_prop_stridx_short(thr, -1, DUK_STRIDX_TO_LOCALE_STRING);\n\t\t\t\tduk_insert(thr, -2);  /* -> [ ... toLocaleString ToObject(val) ] */\n\t\t\t\tduk_call_method(thr, 0);\n\t\t\t}\n\t\t\tduk_to_string(thr, -1);\n\t\t}\n\n\t\tcount++;\n\t\tidx++;\n\t}\n\n\t/* [ sep ToObject(this) len sep result ] */\n\n\treturn 1;\n}\n\n/*\n *  pop(), push()\n */\n\n#if defined(DUK_USE_ARRAY_FASTPATH)\nDUK_LOCAL duk_ret_t duk__array_pop_fastpath(duk_hthread *thr, duk_harray *h_arr) {\n\tduk_tval *tv_arraypart;\n\tduk_tval *tv_val;\n\tduk_uint32_t len;\n\n\ttv_arraypart = DUK_HOBJECT_A_GET_BASE(thr->heap, (duk_hobject *) h_arr);\n\tlen = h_arr->length;\n\tif (len <= 0) {\n\t\t/* nop, return undefined */\n\t\treturn 0;\n\t}\n\n\tlen--;\n\th_arr->length = len;\n\n\t/* Fast path doesn't check for an index property inherited from\n\t * Array.prototype.  This is quite often acceptable; if not,\n\t * disable fast path.\n\t */\n\tDUK_ASSERT_VS_SPACE(thr);\n\ttv_val = tv_arraypart + len;\n\tif (DUK_TVAL_IS_UNUSED(tv_val)) {\n\t\t/* No net refcount change.  Value stack already has\n\t\t * 'undefined' based on value stack init policy.\n\t\t */\n\t\tDUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top));\n\t\tDUK_ASSERT(DUK_TVAL_IS_UNUSED(tv_val));\n\t} else {\n\t\t/* No net refcount change. */\n\t\tDUK_TVAL_SET_TVAL(thr->valstack_top, tv_val);\n\t\tDUK_TVAL_SET_UNUSED(tv_val);\n\t}\n\tthr->valstack_top++;\n\n\t/* XXX: there's no shrink check in the fast path now */\n\n\treturn 1;\n}\n#endif  /* DUK_USE_ARRAY_FASTPATH */\n\nDUK_INTERNAL duk_ret_t duk_bi_array_prototype_pop(duk_hthread *thr) {\n\tduk_uint32_t len;\n\tduk_uint32_t idx;\n#if defined(DUK_USE_ARRAY_FASTPATH)\n\tduk_harray *h_arr;\n#endif\n\n\tDUK_ASSERT_TOP(thr, 0);\n\n#if defined(DUK_USE_ARRAY_FASTPATH)\n\th_arr = duk__arraypart_fastpath_this(thr);\n\tif (h_arr) {\n\t\treturn duk__array_pop_fastpath(thr, h_arr);\n\t}\n#endif\n\n\t/* XXX: Merge fastpath check into a related call (push this, coerce length, etc)? */\n\n\tlen = duk__push_this_obj_len_u32(thr);\n\tif (len == 0) {\n\t\tduk_push_int(thr, 0);\n\t\tduk_put_prop_stridx_short(thr, 0, DUK_STRIDX_LENGTH);\n\t\treturn 0;\n\t}\n\tidx = len - 1;\n\n\tduk_get_prop_index(thr, 0, (duk_uarridx_t) idx);\n\tduk_del_prop_index(thr, 0, (duk_uarridx_t) idx);\n\tduk_push_u32(thr, idx);\n\tduk_put_prop_stridx_short(thr, 0, DUK_STRIDX_LENGTH);\n\treturn 1;\n}\n\n#if defined(DUK_USE_ARRAY_FASTPATH)\nDUK_LOCAL duk_ret_t duk__array_push_fastpath(duk_hthread *thr, duk_harray *h_arr) {\n\tduk_tval *tv_arraypart;\n\tduk_tval *tv_src;\n\tduk_tval *tv_dst;\n\tduk_uint32_t len;\n\tduk_idx_t i, n;\n\n\tlen = h_arr->length;\n\ttv_arraypart = DUK_HOBJECT_A_GET_BASE(thr->heap, (duk_hobject *) h_arr);\n\n\tn = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);\n\tDUK_ASSERT(n >= 0);\n\tDUK_ASSERT((duk_uint32_t) n <= DUK_UINT32_MAX);\n\tif (DUK_UNLIKELY(len + (duk_uint32_t) n < len)) {\n\t\tDUK_D(DUK_DPRINT(\"Array.prototype.push() would go beyond 32-bit length, throw\"));\n\t\tDUK_DCERROR_RANGE_INVALID_LENGTH(thr);  /* != 0 return value returned as is by caller */\n\t}\n\tif (len + (duk_uint32_t) n > DUK_HOBJECT_GET_ASIZE((duk_hobject *) h_arr)) {\n\t\t/* Array part would need to be extended.  Rely on slow path\n\t\t * for now.\n\t\t *\n\t\t * XXX: Rework hobject code a bit and add extend support.\n\t\t */\n\t\treturn 0;\n\t}\n\n\ttv_src = thr->valstack_bottom;\n\ttv_dst = tv_arraypart + len;\n\tfor (i = 0; i < n; i++) {\n\t\t/* No net refcount change; reset value stack values to\n\t\t * undefined to satisfy value stack init policy.\n\t\t */\n\t\tDUK_TVAL_SET_TVAL(tv_dst, tv_src);\n\t\tDUK_TVAL_SET_UNDEFINED(tv_src);\n\t\ttv_src++;\n\t\ttv_dst++;\n\t}\n\tthr->valstack_top = thr->valstack_bottom;\n\tlen += (duk_uint32_t) n;\n\th_arr->length = len;\n\n\tDUK_ASSERT((duk_uint_t) len == len);\n\tduk_push_uint(thr, (duk_uint_t) len);\n\treturn 1;\n}\n#endif  /* DUK_USE_ARRAY_FASTPATH */\n\nDUK_INTERNAL duk_ret_t duk_bi_array_prototype_push(duk_hthread *thr) {\n\t/* Note: 'this' is not necessarily an Array object.  The push()\n\t * algorithm is supposed to work for other kinds of objects too,\n\t * so the algorithm has e.g. an explicit update for the 'length'\n\t * property which is normally \"magical\" in arrays.\n\t */\n\n\tduk_uint32_t len;\n\tduk_idx_t i, n;\n#if defined(DUK_USE_ARRAY_FASTPATH)\n\tduk_harray *h_arr;\n#endif\n\n#if defined(DUK_USE_ARRAY_FASTPATH)\n\th_arr = duk__arraypart_fastpath_this(thr);\n\tif (h_arr) {\n\t\tduk_ret_t rc;\n\t\trc = duk__array_push_fastpath(thr, h_arr);\n\t\tif (rc != 0) {\n\t\t\treturn rc;\n\t\t}\n\t\tDUK_DD(DUK_DDPRINT(\"array push() fast path exited, resize case\"));\n\t}\n#endif\n\n\tn = duk_get_top(thr);\n\tlen = duk__push_this_obj_len_u32(thr);\n\n\t/* [ arg1 ... argN obj length ] */\n\n\t/* Technically Array.prototype.push() can create an Array with length\n\t * longer than 2^32-1, i.e. outside the 32-bit range.  The final length\n\t * is *not* wrapped to 32 bits in the specification.\n\t *\n\t * This implementation tracks length with a uint32 because it's much\n\t * more practical.\n\t *\n\t * See: test-bi-array-push-maxlen.js.\n\t */\n\n\tif (len + (duk_uint32_t) n < len) {\n\t\tDUK_D(DUK_DPRINT(\"Array.prototype.push() would go beyond 32-bit length, throw\"));\n\t\tDUK_DCERROR_RANGE_INVALID_LENGTH(thr);\n\t}\n\n\tfor (i = 0; i < n; i++) {\n\t\tduk_dup(thr, i);\n\t\tduk_put_prop_index(thr, -3, (duk_uarridx_t) (len + (duk_uint32_t) i));\n\t}\n\tlen += (duk_uint32_t) n;\n\n\tduk_push_u32(thr, len);\n\tduk_dup_top(thr);\n\tduk_put_prop_stridx_short(thr, -4, DUK_STRIDX_LENGTH);\n\n\t/* [ arg1 ... argN obj length new_length ] */\n\treturn 1;\n}\n\n/*\n *  sort()\n *\n *  Currently qsort with random pivot.  This is now really, really slow,\n *  because there is no fast path for array parts.\n *\n *  Signed indices are used because qsort() leaves and degenerate cases\n *  may use a negative offset.\n */\n\nDUK_LOCAL duk_small_int_t duk__array_sort_compare(duk_hthread *thr, duk_int_t idx1, duk_int_t idx2) {\n\tduk_bool_t have1, have2;\n\tduk_bool_t undef1, undef2;\n\tduk_small_int_t ret;\n\tduk_idx_t idx_obj = 1;  /* fixed offsets in valstack */\n\tduk_idx_t idx_fn = 0;\n\tduk_hstring *h1, *h2;\n\n\t/* Fast exit if indices are identical.  This is valid for a non-existent property,\n\t * for an undefined value, and almost always for ToString() coerced comparison of\n\t * arbitrary values (corner cases where this is not the case include e.g. a an\n\t * object with varying ToString() coercion).\n\t *\n\t * The specification does not prohibit \"caching\" of values read from the array, so\n\t * assuming equality for comparing an index with itself falls into the category of\n\t * \"caching\".\n\t *\n\t * Also, compareFn may be inconsistent, so skipping a call to compareFn here may\n\t * have an effect on the final result.  The specification does not require any\n\t * specific behavior for inconsistent compare functions, so again, this fast path\n\t * is OK.\n\t */\n\n\tif (idx1 == idx2) {\n\t\tDUK_DDD(DUK_DDDPRINT(\"duk__array_sort_compare: idx1=%ld, idx2=%ld -> indices identical, quick exit\",\n\t\t                     (long) idx1, (long) idx2));\n\t\treturn 0;\n\t}\n\n\thave1 = duk_get_prop_index(thr, idx_obj, (duk_uarridx_t) idx1);\n\thave2 = duk_get_prop_index(thr, idx_obj, (duk_uarridx_t) idx2);\n\n\tDUK_DDD(DUK_DDDPRINT(\"duk__array_sort_compare: idx1=%ld, idx2=%ld, have1=%ld, have2=%ld, val1=%!T, val2=%!T\",\n\t                     (long) idx1, (long) idx2, (long) have1, (long) have2,\n\t                     (duk_tval *) duk_get_tval(thr, -2), (duk_tval *) duk_get_tval(thr, -1)));\n\n\tif (have1) {\n\t\tif (have2) {\n\t\t\t;\n\t\t} else {\n\t\t\tret = -1;\n\t\t\tgoto pop_ret;\n\t\t}\n\t} else {\n\t\tif (have2) {\n\t\t\tret = 1;\n\t\t\tgoto pop_ret;\n\t\t} else {\n\t\t\tret = 0;\n\t\t\tgoto pop_ret;\n\t\t}\n\t}\n\n\tundef1 = duk_is_undefined(thr, -2);\n\tundef2 = duk_is_undefined(thr, -1);\n\tif (undef1) {\n\t\tif (undef2) {\n\t\t\tret = 0;\n\t\t\tgoto pop_ret;\n\t\t} else {\n\t\t\tret = 1;\n\t\t\tgoto pop_ret;\n\t\t}\n\t} else {\n\t\tif (undef2) {\n\t\t\tret = -1;\n\t\t\tgoto pop_ret;\n\t\t} else {\n\t\t\t;\n\t\t}\n\t}\n\n\tif (!duk_is_undefined(thr, idx_fn)) {\n\t\tduk_double_t d;\n\n\t\t/* No need to check callable; duk_call() will do that. */\n\t\tduk_dup(thr, idx_fn);    /* -> [ ... x y fn ] */\n\t\tduk_insert(thr, -3);     /* -> [ ... fn x y ] */\n\t\tduk_call(thr, 2);        /* -> [ ... res ] */\n\n\t\t/* ES5 is a bit vague about what to do if the return value is\n\t\t * not a number.  ES2015 provides a concrete description:\n\t\t * http://www.ecma-international.org/ecma-262/6.0/#sec-sortcompare.\n\t\t */\n\n\t\td = duk_to_number_m1(thr);\n\t\tif (d < 0.0) {\n\t\t\tret = -1;\n\t\t} else if (d > 0.0) {\n\t\t\tret = 1;\n\t\t} else {\n\t\t\t/* Because NaN compares to false, NaN is handled here\n\t\t\t * without an explicit check above.\n\t\t\t */\n\t\t\tret = 0;\n\t\t}\n\n\t\tduk_pop_nodecref_unsafe(thr);\n\t\tDUK_DDD(DUK_DDDPRINT(\"-> result %ld (from comparefn, after coercion)\", (long) ret));\n\t\treturn ret;\n\t}\n\n\t/* string compare is the default (a bit oddly) */\n\n\t/* XXX: any special handling for plain array; causes repeated coercion now? */\n\th1 = duk_to_hstring(thr, -2);\n\th2 = duk_to_hstring_m1(thr);\n\tDUK_ASSERT(h1 != NULL);\n\tDUK_ASSERT(h2 != NULL);\n\n\tret = duk_js_string_compare(h1, h2);  /* retval is directly usable */\n\tgoto pop_ret;\n\n pop_ret:\n\tduk_pop_2_unsafe(thr);\n\tDUK_DDD(DUK_DDDPRINT(\"-> result %ld\", (long) ret));\n\treturn ret;\n}\n\nDUK_LOCAL void duk__array_sort_swap(duk_hthread *thr, duk_int_t l, duk_int_t r) {\n\tduk_bool_t have_l, have_r;\n\tduk_idx_t idx_obj = 1;  /* fixed offset in valstack */\n\n\tif (l == r) {\n\t\treturn;\n\t}\n\n\t/* swap elements; deal with non-existent elements correctly */\n\thave_l = duk_get_prop_index(thr, idx_obj, (duk_uarridx_t) l);\n\thave_r = duk_get_prop_index(thr, idx_obj, (duk_uarridx_t) r);\n\n\tif (have_r) {\n\t\t/* right exists, [[Put]] regardless whether or not left exists */\n\t\tduk_put_prop_index(thr, idx_obj, (duk_uarridx_t) l);\n\t} else {\n\t\tduk_del_prop_index(thr, idx_obj, (duk_uarridx_t) l);\n\t\tduk_pop_undefined(thr);\n\t}\n\n\tif (have_l) {\n\t\tduk_put_prop_index(thr, idx_obj, (duk_uarridx_t) r);\n\t} else {\n\t\tduk_del_prop_index(thr, idx_obj, (duk_uarridx_t) r);\n\t\tduk_pop_undefined(thr);\n\t}\n}\n\n#if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)\n/* Debug print which visualizes the qsort partitioning process. */\nDUK_LOCAL void duk__debuglog_qsort_state(duk_hthread *thr, duk_int_t lo, duk_int_t hi, duk_int_t pivot) {\n\tchar buf[4096];\n\tchar *ptr = buf;\n\tduk_int_t i, n;\n\tn = (duk_int_t) duk_get_length(thr, 1);\n\tif (n > 4000) {\n\t\tn = 4000;\n\t}\n\t*ptr++ = '[';\n\tfor (i = 0; i < n; i++) {\n\t\tif (i == pivot) {\n\t\t\t*ptr++ = '|';\n\t\t} else if (i == lo) {\n\t\t\t*ptr++ = '<';\n\t\t} else if (i == hi) {\n\t\t\t*ptr++ = '>';\n\t\t} else if (i >= lo && i <= hi) {\n\t\t\t*ptr++ = '-';\n\t\t} else {\n\t\t\t*ptr++ = ' ';\n\t\t}\n\t}\n\t*ptr++ = ']';\n\t*ptr++ = '\\0';\n\n\tDUK_DDD(DUK_DDDPRINT(\"%s   (lo=%ld, hi=%ld, pivot=%ld)\",\n\t                     (const char *) buf, (long) lo, (long) hi, (long) pivot));\n}\n#endif\n\nDUK_LOCAL void duk__array_qsort(duk_hthread *thr, duk_int_t lo, duk_int_t hi) {\n\tduk_int_t p, l, r;\n\n\t/* The lo/hi indices may be crossed and hi < 0 is possible at entry. */\n\n\tDUK_DDD(DUK_DDDPRINT(\"duk__array_qsort: lo=%ld, hi=%ld, obj=%!T\",\n\t                     (long) lo, (long) hi, (duk_tval *) duk_get_tval(thr, 1)));\n\n\tDUK_ASSERT_TOP(thr, 3);\n\n\t/* In some cases it may be that lo > hi, or hi < 0; these\n\t * degenerate cases happen e.g. for empty arrays, and in\n\t * recursion leaves.\n\t */\n\n\t/* trivial cases */\n\tif (hi - lo < 1) {\n\t\tDUK_DDD(DUK_DDDPRINT(\"degenerate case, return immediately\"));\n\t\treturn;\n\t}\n\tDUK_ASSERT(hi > lo);\n\tDUK_ASSERT(hi - lo + 1 >= 2);\n\n\t/* randomized pivot selection */\n\tp = lo + (duk_int_t) (DUK_UTIL_GET_RANDOM_DOUBLE(thr) * (duk_double_t) (hi - lo + 1));\n\tDUK_ASSERT(p >= lo && p <= hi);\n\tDUK_DDD(DUK_DDDPRINT(\"lo=%ld, hi=%ld, chose pivot p=%ld\", (long) lo, (long) hi, (long) p));\n\n\t/* move pivot out of the way */\n\tduk__array_sort_swap(thr, p, lo);\n\tp = lo;\n\tDUK_DDD(DUK_DDDPRINT(\"pivot moved out of the way: %!T\", (duk_tval *) duk_get_tval(thr, 1)));\n\n\tl = lo + 1;\n\tr = hi;\n\tfor (;;) {\n\t\t/* find elements to swap */\n\t\tfor (;;) {\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"left scan: l=%ld, r=%ld, p=%ld\",\n\t\t\t                     (long) l, (long) r, (long) p));\n\t\t\tif (l >= hi) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (duk__array_sort_compare(thr, l, p) >= 0) {  /* !(l < p) */\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tl++;\n\t\t}\n\t\tfor (;;) {\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"right scan: l=%ld, r=%ld, p=%ld\",\n\t\t\t                     (long) l, (long) r, (long) p));\n\t\t\tif (r <= lo) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (duk__array_sort_compare(thr, p, r) >= 0) {  /* !(p < r) */\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tr--;\n\t\t}\n\t\tif (l >= r) {\n\t\t\tgoto done;\n\t\t}\n\t\tDUK_ASSERT(l < r);\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"swap %ld and %ld\", (long) l, (long) r));\n\n\t\tduk__array_sort_swap(thr, l, r);\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"after swap: %!T\", (duk_tval *) duk_get_tval(thr, 1)));\n\t\tl++;\n\t\tr--;\n\t}\n done:\n\t/* Note that 'l' and 'r' may cross, i.e. r < l */\n\tDUK_ASSERT(l >= lo && l <= hi);\n\tDUK_ASSERT(r >= lo && r <= hi);\n\n\t/* XXX: there's no explicit recursion bound here now.  For the average\n\t * qsort recursion depth O(log n) that's not really necessary: e.g. for\n\t * 2**32 recursion depth would be about 32 which is OK.  However, qsort\n\t * worst case recursion depth is O(n) which may be a problem.\n\t */\n\n\t/* move pivot to its final place */\n\tDUK_DDD(DUK_DDDPRINT(\"before final pivot swap: %!T\", (duk_tval *) duk_get_tval(thr, 1)));\n\tduk__array_sort_swap(thr, lo, r);\n\n#if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)\n\tduk__debuglog_qsort_state(thr, lo, hi, r);\n#endif\n\n\tDUK_DDD(DUK_DDDPRINT(\"recurse: pivot=%ld, obj=%!T\", (long) r, (duk_tval *) duk_get_tval(thr, 1)));\n\tduk__array_qsort(thr, lo, r - 1);\n\tduk__array_qsort(thr, r + 1, hi);\n}\n\nDUK_INTERNAL duk_ret_t duk_bi_array_prototype_sort(duk_hthread *thr) {\n\tduk_uint32_t len;\n\n\t/* XXX: len >= 0x80000000 won't work below because a signed type\n\t * is needed by qsort.\n\t */\n\tlen = duk__push_this_obj_len_u32_limited(thr);\n\n\t/* stack[0] = compareFn\n\t * stack[1] = ToObject(this)\n\t * stack[2] = ToUint32(length)\n\t */\n\n\tif (len > 0) {\n\t\t/* avoid degenerate cases, so that (len - 1) won't underflow */\n\t\tduk__array_qsort(thr, (duk_int_t) 0, (duk_int_t) (len - 1));\n\t}\n\n\tDUK_ASSERT_TOP(thr, 3);\n\tduk_pop_nodecref_unsafe(thr);\n\treturn 1;  /* return ToObject(this) */\n}\n\n/*\n *  splice()\n */\n\n/* XXX: this compiles to over 500 bytes now, even without special handling\n * for an array part.  Uses signed ints so does not handle full array range correctly.\n */\n\n/* XXX: can shift() / unshift() use the same helper?\n *   shift() is (close to?) <--> splice(0, 1)\n *   unshift is (close to?) <--> splice(0, 0, [items])?\n */\n\nDUK_INTERNAL duk_ret_t duk_bi_array_prototype_splice(duk_hthread *thr) {\n\tduk_idx_t nargs;\n\tduk_uint32_t len_u32;\n\tduk_int_t len;\n\tduk_bool_t have_delcount;\n\tduk_int_t item_count;\n\tduk_int_t act_start;\n\tduk_int_t del_count;\n\tduk_int_t i, n;\n\n\tDUK_UNREF(have_delcount);\n\n\tnargs = duk_get_top(thr);\n\tif (nargs < 2) {\n\t\tduk_set_top(thr, 2);\n\t\tnargs = 2;\n\t\thave_delcount = 0;\n\t} else {\n\t\thave_delcount = 1;\n\t}\n\n\t/* XXX: len >= 0x80000000 won't work below because we need to be\n\t * able to represent -len.\n\t */\n\tlen_u32 = duk__push_this_obj_len_u32_limited(thr);\n\tlen = (duk_int_t) len_u32;\n\tDUK_ASSERT(len >= 0);\n\n\tact_start = duk_to_int_clamped(thr, 0, -len, len);\n\tif (act_start < 0) {\n\t\tact_start = len + act_start;\n\t}\n\tDUK_ASSERT(act_start >= 0 && act_start <= len);\n\n#if defined(DUK_USE_NONSTD_ARRAY_SPLICE_DELCOUNT)\n\tif (have_delcount) {\n#endif\n\t\tdel_count = duk_to_int_clamped(thr, 1, 0, len - act_start);\n#if defined(DUK_USE_NONSTD_ARRAY_SPLICE_DELCOUNT)\n\t} else {\n\t\t/* E5.1 standard behavior when deleteCount is not given would be\n\t\t * to treat it just like if 'undefined' was given, which coerces\n\t\t * ultimately to 0.  Real world behavior is to splice to the end\n\t\t * of array, see test-bi-array-proto-splice-no-delcount.js.\n\t\t */\n\t\tdel_count = len - act_start;\n\t}\n#endif\n\n\tDUK_ASSERT(nargs >= 2);\n\titem_count = (duk_int_t) (nargs - 2);\n\n\tDUK_ASSERT(del_count >= 0 && del_count <= len - act_start);\n\tDUK_ASSERT(del_count + act_start <= len);\n\n\t/* For now, restrict result array into 32-bit length range. */\n\tif (((duk_double_t) len) - ((duk_double_t) del_count) + ((duk_double_t) item_count) > (duk_double_t) DUK_UINT32_MAX) {\n\t\tDUK_D(DUK_DPRINT(\"Array.prototype.splice() would go beyond 32-bit length, throw\"));\n\t\tDUK_DCERROR_RANGE_INVALID_LENGTH(thr);\n\t}\n\n\tduk_push_array(thr);\n\n\t/* stack[0] = start\n\t * stack[1] = deleteCount\n\t * stack[2...nargs-1] = items\n\t * stack[nargs] = ToObject(this)               -3\n\t * stack[nargs+1] = ToUint32(length)           -2\n\t * stack[nargs+2] = result array               -1\n\t */\n\n\tDUK_ASSERT_TOP(thr, nargs + 3);\n\n\t/* Step 9: copy elements-to-be-deleted into the result array */\n\n\tfor (i = 0; i < del_count; i++) {\n\t\tif (duk_get_prop_index(thr, -3, (duk_uarridx_t) (act_start + i))) {\n\t\t\tduk_xdef_prop_index_wec(thr, -2, (duk_uarridx_t) i);  /* throw flag irrelevant (false in std alg) */\n\t\t} else {\n\t\t\tduk_pop_undefined(thr);\n\t\t}\n\t}\n\tduk_push_u32(thr, (duk_uint32_t) del_count);\n\tduk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_W);\n\n\t/* Steps 12 and 13: reorganize elements to make room for itemCount elements */\n\n\tif (item_count < del_count) {\n\t\t/*    [ A B C D E F G H ]    rel_index = 2, del_count 3, item count 1\n\t\t * -> [ A B F G H ]          (conceptual intermediate step)\n\t\t * -> [ A B . F G H ]        (placeholder marked)\n\t\t *    [ A B C F G H ]        (actual result at this point, C will be replaced)\n\t\t */\n\n\t\tDUK_ASSERT_TOP(thr, nargs + 3);\n\n\t\tn = len - del_count;\n\t\tfor (i = act_start; i < n; i++) {\n\t\t\tif (duk_get_prop_index(thr, -3, (duk_uarridx_t) (i + del_count))) {\n\t\t\t\tduk_put_prop_index(thr, -4, (duk_uarridx_t) (i + item_count));\n\t\t\t} else {\n\t\t\t\tduk_pop_undefined(thr);\n\t\t\t\tduk_del_prop_index(thr, -3, (duk_uarridx_t) (i + item_count));\n\t\t\t}\n\t\t}\n\n\t\tDUK_ASSERT_TOP(thr, nargs + 3);\n\n\t\t/* loop iterator init and limit changed from standard algorithm */\n\t\tn = len - del_count + item_count;\n\t\tfor (i = len - 1; i >= n; i--) {\n\t\t\tduk_del_prop_index(thr, -3, (duk_uarridx_t) i);\n\t\t}\n\n\t\tDUK_ASSERT_TOP(thr, nargs + 3);\n\t} else if (item_count > del_count) {\n\t\t/*    [ A B C D E F G H ]    rel_index = 2, del_count 3, item count 4\n\t\t * -> [ A B F G H ]          (conceptual intermediate step)\n\t\t * -> [ A B . . . . F G H ]  (placeholder marked)\n\t\t *    [ A B C D E F F G H ]  (actual result at this point)\n\t\t */\n\n\t\tDUK_ASSERT_TOP(thr, nargs + 3);\n\n\t\t/* loop iterator init and limit changed from standard algorithm */\n\t\tfor (i = len - del_count - 1; i >= act_start; i--) {\n\t\t\tif (duk_get_prop_index(thr, -3, (duk_uarridx_t) (i + del_count))) {\n\t\t\t\tduk_put_prop_index(thr, -4, (duk_uarridx_t) (i + item_count));\n\t\t\t} else {\n\t\t\t\tduk_pop_undefined(thr);\n\t\t\t\tduk_del_prop_index(thr, -3, (duk_uarridx_t) (i + item_count));\n\t\t\t}\n\t\t}\n\n\t\tDUK_ASSERT_TOP(thr, nargs + 3);\n\t} else {\n\t\t/*    [ A B C D E F G H ]    rel_index = 2, del_count 3, item count 3\n\t\t * -> [ A B F G H ]          (conceptual intermediate step)\n\t\t * -> [ A B . . . F G H ]    (placeholder marked)\n\t\t *    [ A B C D E F G H ]    (actual result at this point)\n\t\t */\n\t}\n\tDUK_ASSERT_TOP(thr, nargs + 3);\n\n\t/* Step 15: insert itemCount elements into the hole made above */\n\n\tfor (i = 0; i < item_count; i++) {\n\t\tduk_dup(thr, i + 2);  /* args start at index 2 */\n\t\tduk_put_prop_index(thr, -4, (duk_uarridx_t) (act_start + i));\n\t}\n\n\t/* Step 16: update length; note that the final length may be above 32 bit range\n\t * (but we checked above that this isn't the case here)\n\t */\n\n\tduk_push_u32(thr, (duk_uint32_t) (len - del_count + item_count));\n\tduk_put_prop_stridx_short(thr, -4, DUK_STRIDX_LENGTH);\n\n\t/* result array is already at the top of stack */\n\tDUK_ASSERT_TOP(thr, nargs + 3);\n\treturn 1;\n}\n\n/*\n *  reverse()\n */\n\nDUK_INTERNAL duk_ret_t duk_bi_array_prototype_reverse(duk_hthread *thr) {\n\tduk_uint32_t len;\n\tduk_uint32_t middle;\n\tduk_uint32_t lower, upper;\n\tduk_bool_t have_lower, have_upper;\n\n\tlen = duk__push_this_obj_len_u32(thr);\n\tmiddle = len / 2;\n\n\t/* If len <= 1, middle will be 0 and for-loop bails out\n\t * immediately (0 < 0 -> false).\n\t */\n\n\tfor (lower = 0; lower < middle; lower++) {\n\t\tDUK_ASSERT(len >= 2);\n\t\tDUK_ASSERT_TOP(thr, 2);\n\n\t\tDUK_ASSERT(len >= lower + 1);\n\t\tupper = len - lower - 1;\n\n\t\thave_lower = duk_get_prop_index(thr, -2, (duk_uarridx_t) lower);\n\t\thave_upper = duk_get_prop_index(thr, -3, (duk_uarridx_t) upper);\n\n\t\t/* [ ToObject(this) ToUint32(length) lowerValue upperValue ] */\n\n\t\tif (have_upper) {\n\t\t\tduk_put_prop_index(thr, -4, (duk_uarridx_t) lower);\n\t\t} else {\n\t\t\tduk_del_prop_index(thr, -4, (duk_uarridx_t) lower);\n\t\t\tduk_pop_undefined(thr);\n\t\t}\n\n\t\tif (have_lower) {\n\t\t\tduk_put_prop_index(thr, -3, (duk_uarridx_t) upper);\n\t\t} else {\n\t\t\tduk_del_prop_index(thr, -3, (duk_uarridx_t) upper);\n\t\t\tduk_pop_undefined(thr);\n\t\t}\n\n\t\tDUK_ASSERT_TOP(thr, 2);\n\t}\n\n\tDUK_ASSERT_TOP(thr, 2);\n\tduk_pop_unsafe(thr);  /* -> [ ToObject(this) ] */\n\treturn 1;\n}\n\n/*\n *  slice()\n */\n\nDUK_INTERNAL duk_ret_t duk_bi_array_prototype_slice(duk_hthread *thr) {\n\tduk_uint32_t len_u32;\n\tduk_int_t len;\n\tduk_int_t start, end;\n\tduk_int_t i;\n\tduk_uarridx_t idx;\n\tduk_uint32_t res_length = 0;\n\n\t/* XXX: len >= 0x80000000 won't work below because we need to be\n\t * able to represent -len.\n\t */\n\tlen_u32 = duk__push_this_obj_len_u32_limited(thr);\n\tlen = (duk_int_t) len_u32;\n\tDUK_ASSERT(len >= 0);\n\n\tduk_push_array(thr);\n\n\t/* stack[0] = start\n\t * stack[1] = end\n\t * stack[2] = ToObject(this)\n\t * stack[3] = ToUint32(length)\n\t * stack[4] = result array\n\t */\n\n\tstart = duk_to_int_clamped(thr, 0, -len, len);\n\tif (start < 0) {\n\t\tstart = len + start;\n\t}\n\t/* XXX: could duk_is_undefined() provide defaulting undefined to 'len'\n\t * (the upper limit)?\n\t */\n\tif (duk_is_undefined(thr, 1)) {\n\t\tend = len;\n\t} else {\n\t\tend = duk_to_int_clamped(thr, 1, -len, len);\n\t\tif (end < 0) {\n\t\t\tend = len + end;\n\t\t}\n\t}\n\tDUK_ASSERT(start >= 0 && start <= len);\n\tDUK_ASSERT(end >= 0 && end <= len);\n\n\tidx = 0;\n\tfor (i = start; i < end; i++) {\n\t\tDUK_ASSERT_TOP(thr, 5);\n\t\tif (duk_get_prop_index(thr, 2, (duk_uarridx_t) i)) {\n\t\t\tduk_xdef_prop_index_wec(thr, 4, idx);\n\t\t\tres_length = idx + 1;\n\t\t} else {\n\t\t\tduk_pop_undefined(thr);\n\t\t}\n\t\tidx++;\n\t\tDUK_ASSERT_TOP(thr, 5);\n\t}\n\n\tduk_push_u32(thr, res_length);\n\tduk_xdef_prop_stridx_short(thr, 4, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_W);\n\n\tDUK_ASSERT_TOP(thr, 5);\n\treturn 1;\n}\n\n/*\n *  shift()\n */\n\nDUK_INTERNAL duk_ret_t duk_bi_array_prototype_shift(duk_hthread *thr) {\n\tduk_uint32_t len;\n\tduk_uint32_t i;\n\n\tlen = duk__push_this_obj_len_u32(thr);\n\tif (len == 0) {\n\t\tduk_push_int(thr, 0);\n\t\tduk_put_prop_stridx_short(thr, 0, DUK_STRIDX_LENGTH);\n\t\treturn 0;\n\t}\n\n\tduk_get_prop_index(thr, 0, 0);\n\n\t/* stack[0] = object (this)\n\t * stack[1] = ToUint32(length)\n\t * stack[2] = elem at index 0 (retval)\n\t */\n\n\tfor (i = 1; i < len; i++) {\n\t\tDUK_ASSERT_TOP(thr, 3);\n\t\tif (duk_get_prop_index(thr, 0, (duk_uarridx_t) i)) {\n\t\t\t/* fromPresent = true */\n\t\t\tduk_put_prop_index(thr, 0, (duk_uarridx_t) (i - 1));\n\t\t} else {\n\t\t\t/* fromPresent = false */\n\t\t\tduk_del_prop_index(thr, 0, (duk_uarridx_t) (i - 1));\n\t\t\tduk_pop_undefined(thr);\n\t\t}\n\t}\n\tduk_del_prop_index(thr, 0, (duk_uarridx_t) (len - 1));\n\n\tduk_push_u32(thr, (duk_uint32_t) (len - 1));\n\tduk_put_prop_stridx_short(thr, 0, DUK_STRIDX_LENGTH);\n\n\tDUK_ASSERT_TOP(thr, 3);\n\treturn 1;\n}\n\n/*\n *  unshift()\n */\n\nDUK_INTERNAL duk_ret_t duk_bi_array_prototype_unshift(duk_hthread *thr) {\n\tduk_idx_t nargs;\n\tduk_uint32_t len;\n\tduk_uint32_t i;\n\n\tnargs = duk_get_top(thr);\n\tlen = duk__push_this_obj_len_u32(thr);\n\n\t/* stack[0...nargs-1] = unshift args (vararg)\n\t * stack[nargs] = ToObject(this)\n\t * stack[nargs+1] = ToUint32(length)\n\t */\n\n\tDUK_ASSERT_TOP(thr, nargs + 2);\n\n\t/* Note: unshift() may operate on indices above unsigned 32-bit range\n\t * and the final length may be >= 2**32.  However, we restrict the\n\t * final result to 32-bit range for practicality.\n\t */\n\n\tif (len + (duk_uint32_t) nargs < len) {\n\t\tDUK_D(DUK_DPRINT(\"Array.prototype.unshift() would go beyond 32-bit length, throw\"));\n\t\tDUK_DCERROR_RANGE_INVALID_LENGTH(thr);\n\t}\n\n\ti = len;\n\twhile (i > 0) {\n\t\tDUK_ASSERT_TOP(thr, nargs + 2);\n\t\ti--;\n\t\t/* k+argCount-1; note that may be above 32-bit range */\n\n\t\tif (duk_get_prop_index(thr, -2, (duk_uarridx_t) i)) {\n\t\t\t/* fromPresent = true */\n\t\t\t/* [ ... ToObject(this) ToUint32(length) val ] */\n\t\t\tduk_put_prop_index(thr, -3, (duk_uarridx_t) (i + (duk_uint32_t) nargs));  /* -> [ ... ToObject(this) ToUint32(length) ] */\n\t\t} else {\n\t\t\t/* fromPresent = false */\n\t\t\t/* [ ... ToObject(this) ToUint32(length) val ] */\n\t\t\tduk_pop_undefined(thr);\n\t\t\tduk_del_prop_index(thr, -2, (duk_uarridx_t) (i + (duk_uint32_t) nargs));  /* -> [ ... ToObject(this) ToUint32(length) ] */\n\t\t}\n\t\tDUK_ASSERT_TOP(thr, nargs + 2);\n\t}\n\n\tfor (i = 0; i < (duk_uint32_t) nargs; i++) {\n\t\tDUK_ASSERT_TOP(thr, nargs + 2);\n\t\tduk_dup(thr, (duk_idx_t) i);  /* -> [ ... ToObject(this) ToUint32(length) arg[i] ] */\n\t\tduk_put_prop_index(thr, -3, (duk_uarridx_t) i);\n\t\tDUK_ASSERT_TOP(thr, nargs + 2);\n\t}\n\n\tDUK_ASSERT_TOP(thr, nargs + 2);\n\tduk_push_u32(thr, len + (duk_uint32_t) nargs);\n\tduk_dup_top(thr);  /* -> [ ... ToObject(this) ToUint32(length) final_len final_len ] */\n\tduk_put_prop_stridx_short(thr, -4, DUK_STRIDX_LENGTH);\n\treturn 1;\n}\n\n/*\n *  indexOf(), lastIndexOf()\n */\n\nDUK_INTERNAL duk_ret_t duk_bi_array_prototype_indexof_shared(duk_hthread *thr) {\n\tduk_idx_t nargs;\n\tduk_int_t i, len;\n\tduk_int_t from_idx;\n\tduk_small_int_t idx_step = duk_get_current_magic(thr);  /* idx_step is +1 for indexOf, -1 for lastIndexOf */\n\n\t/* lastIndexOf() needs to be a vararg function because we must distinguish\n\t * between an undefined fromIndex and a \"not given\" fromIndex; indexOf() is\n\t * made vararg for symmetry although it doesn't strictly need to be.\n\t */\n\n\tnargs = duk_get_top(thr);\n\tduk_set_top(thr, 2);\n\n\t/* XXX: must be able to represent -len */\n\tlen = (duk_int_t) duk__push_this_obj_len_u32_limited(thr);\n\tif (len == 0) {\n\t\tgoto not_found;\n\t}\n\n\t/* Index clamping is a bit tricky, we must ensure that we'll only iterate\n\t * through elements that exist and that the specific requirements from E5.1\n\t * Sections 15.4.4.14 and 15.4.4.15 are fulfilled; especially:\n\t *\n\t *   - indexOf: clamp to [-len,len], negative handling -> [0,len],\n\t *     if clamped result is len, for-loop bails out immediately\n\t *\n\t *   - lastIndexOf: clamp to [-len-1, len-1], negative handling -> [-1, len-1],\n\t *     if clamped result is -1, for-loop bails out immediately\n\t *\n\t * If fromIndex is not given, ToInteger(undefined) = 0, which is correct\n\t * for indexOf() but incorrect for lastIndexOf().  Hence special handling,\n\t * and why lastIndexOf() needs to be a vararg function.\n\t */\n\n\tif (nargs >= 2) {\n\t\t/* indexOf: clamp fromIndex to [-len, len]\n\t\t * (if fromIndex == len, for-loop terminates directly)\n\t\t *\n\t\t * lastIndexOf: clamp fromIndex to [-len - 1, len - 1]\n\t\t * (if clamped to -len-1 -> fromIndex becomes -1, terminates for-loop directly)\n\t\t */\n\t\tfrom_idx = duk_to_int_clamped(thr,\n\t\t                              1,\n\t\t                              (idx_step > 0 ? -len : -len - 1),\n\t\t                              (idx_step > 0 ? len : len - 1));\n\t\tif (from_idx < 0) {\n\t\t\t/* for lastIndexOf, result may be -1 (mark immediate termination) */\n\t\t\tfrom_idx = len + from_idx;\n\t\t}\n\t} else {\n\t\t/* for indexOf, ToInteger(undefined) would be 0, i.e. correct, but\n\t\t * handle both indexOf and lastIndexOf specially here.\n\t\t */\n\t\tif (idx_step > 0) {\n\t\t\tfrom_idx = 0;\n\t\t} else {\n\t\t\tfrom_idx = len - 1;\n\t\t}\n\t}\n\n\t/* stack[0] = searchElement\n\t * stack[1] = fromIndex\n\t * stack[2] = object\n\t * stack[3] = length (not needed, but not popped above)\n\t */\n\n\tfor (i = from_idx; i >= 0 && i < len; i += idx_step) {\n\t\tDUK_ASSERT_TOP(thr, 4);\n\n\t\tif (duk_get_prop_index(thr, 2, (duk_uarridx_t) i)) {\n\t\t\tDUK_ASSERT_TOP(thr, 5);\n\t\t\tif (duk_strict_equals(thr, 0, 4)) {\n\t\t\t\tduk_push_int(thr, i);\n\t\t\t\treturn 1;\n\t\t\t}\n\t\t}\n\n\t\tduk_pop_unsafe(thr);\n\t}\n\n not_found:\n\tduk_push_int(thr, -1);\n\treturn 1;\n}\n\n/*\n *  every(), some(), forEach(), map(), filter()\n */\n\n#define DUK__ITER_EVERY    0\n#define DUK__ITER_SOME     1\n#define DUK__ITER_FOREACH  2\n#define DUK__ITER_MAP      3\n#define DUK__ITER_FILTER   4\n\n/* XXX: This helper is a bit awkward because the handling for the different iteration\n * callers is quite different.  This now compiles to a bit less than 500 bytes, so with\n * 5 callers the net result is about 100 bytes / caller.\n */\n\nDUK_INTERNAL duk_ret_t duk_bi_array_prototype_iter_shared(duk_hthread *thr) {\n\tduk_uint32_t len;\n\tduk_uint32_t i;\n\tduk_uarridx_t k;\n\tduk_bool_t bval;\n\tduk_small_int_t iter_type = duk_get_current_magic(thr);\n\tduk_uint32_t res_length = 0;\n\n\t/* each call this helper serves has nargs==2 */\n\tDUK_ASSERT_TOP(thr, 2);\n\n\tlen = duk__push_this_obj_len_u32(thr);\n\tduk_require_callable(thr, 0);\n\t/* if thisArg not supplied, behave as if undefined was supplied */\n\n\tif (iter_type == DUK__ITER_MAP || iter_type == DUK__ITER_FILTER) {\n\t\tduk_push_array(thr);\n\t} else {\n\t\tduk_push_undefined(thr);\n\t}\n\n\t/* stack[0] = callback\n\t * stack[1] = thisArg\n\t * stack[2] = object\n\t * stack[3] = ToUint32(length)  (unused, but avoid unnecessary pop)\n\t * stack[4] = result array (or undefined)\n\t */\n\n\tk = 0;  /* result index for filter() */\n\tfor (i = 0; i < len; i++) {\n\t\tDUK_ASSERT_TOP(thr, 5);\n\n\t\tif (!duk_get_prop_index(thr, 2, (duk_uarridx_t) i)) {\n#if defined(DUK_USE_NONSTD_ARRAY_MAP_TRAILER)\n\t\t\t/* Real world behavior for map(): trailing non-existent\n\t\t\t * elements don't invoke the user callback, but are still\n\t\t\t * counted towards result 'length'.\n\t\t\t */\n\t\t\tif (iter_type == DUK__ITER_MAP) {\n\t\t\t\tres_length = i + 1;\n\t\t\t}\n#else\n\t\t\t/* Standard behavior for map(): trailing non-existent\n\t\t\t * elements don't invoke the user callback and are not\n\t\t\t * counted towards result 'length'.\n\t\t\t */\n#endif\n\t\t\tduk_pop_undefined(thr);\n\t\t\tcontinue;\n\t\t}\n\n\t\t/* The original value needs to be preserved for filter(), hence\n\t\t * this funny order.  We can't re-get the value because of side\n\t\t * effects.\n\t\t */\n\n\t\tduk_dup_0(thr);\n\t\tduk_dup_1(thr);\n\t\tduk_dup_m3(thr);\n\t\tduk_push_u32(thr, i);\n\t\tduk_dup_2(thr);  /* [ ... val callback thisArg val i obj ] */\n\t\tduk_call_method(thr, 3); /* -> [ ... val retval ] */\n\n\t\tswitch (iter_type) {\n\t\tcase DUK__ITER_EVERY:\n\t\t\tbval = duk_to_boolean(thr, -1);\n\t\t\tif (!bval) {\n\t\t\t\t/* stack top contains 'false' */\n\t\t\t\treturn 1;\n\t\t\t}\n\t\t\tbreak;\n\t\tcase DUK__ITER_SOME:\n\t\t\tbval = duk_to_boolean(thr, -1);\n\t\t\tif (bval) {\n\t\t\t\t/* stack top contains 'true' */\n\t\t\t\treturn 1;\n\t\t\t}\n\t\t\tbreak;\n\t\tcase DUK__ITER_FOREACH:\n\t\t\t/* nop */\n\t\t\tbreak;\n\t\tcase DUK__ITER_MAP:\n\t\t\tduk_dup_top(thr);\n\t\t\tduk_xdef_prop_index_wec(thr, 4, (duk_uarridx_t) i);  /* retval to result[i] */\n\t\t\tres_length = i + 1;\n\t\t\tbreak;\n\t\tcase DUK__ITER_FILTER:\n\t\t\tbval = duk_to_boolean(thr, -1);\n\t\t\tif (bval) {\n\t\t\t\tduk_dup_m2(thr);  /* orig value */\n\t\t\t\tduk_xdef_prop_index_wec(thr, 4, (duk_uarridx_t) k);\n\t\t\t\tk++;\n\t\t\t\tres_length = k;\n\t\t\t}\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tDUK_UNREACHABLE();\n\t\t\tbreak;\n\t\t}\n\t\tduk_pop_2_unsafe(thr);\n\n\t\tDUK_ASSERT_TOP(thr, 5);\n\t}\n\n\tswitch (iter_type) {\n\tcase DUK__ITER_EVERY:\n\t\tduk_push_true(thr);\n\t\tbreak;\n\tcase DUK__ITER_SOME:\n\t\tduk_push_false(thr);\n\t\tbreak;\n\tcase DUK__ITER_FOREACH:\n\t\tduk_push_undefined(thr);\n\t\tbreak;\n\tcase DUK__ITER_MAP:\n\tcase DUK__ITER_FILTER:\n\t\tDUK_ASSERT_TOP(thr, 5);\n\t\tDUK_ASSERT(duk_is_array(thr, -1));  /* topmost element is the result array already */\n\t\tduk_push_u32(thr, res_length);\n\t\tduk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_W);\n\t\tbreak;\n\tdefault:\n\t\tDUK_UNREACHABLE();\n\t\tbreak;\n\t}\n\n\treturn 1;\n}\n\n/*\n *  reduce(), reduceRight()\n */\n\nDUK_INTERNAL duk_ret_t duk_bi_array_prototype_reduce_shared(duk_hthread *thr) {\n\tduk_idx_t nargs;\n\tduk_bool_t have_acc;\n\tduk_uint32_t i, len;\n\tduk_small_int_t idx_step = duk_get_current_magic(thr);  /* idx_step is +1 for reduce, -1 for reduceRight */\n\n\t/* We're a varargs function because we need to detect whether\n\t * initialValue was given or not.\n\t */\n\tnargs = duk_get_top(thr);\n\tDUK_DDD(DUK_DDDPRINT(\"nargs=%ld\", (long) nargs));\n\n\tduk_set_top(thr, 2);\n\tlen = duk__push_this_obj_len_u32(thr);\n\tduk_require_callable(thr, 0);\n\n\t/* stack[0] = callback fn\n\t * stack[1] = initialValue\n\t * stack[2] = object (coerced this)\n\t * stack[3] = length (not needed, but not popped above)\n\t * stack[4] = accumulator\n\t */\n\n\thave_acc = 0;\n\tif (nargs >= 2) {\n\t\tduk_dup_1(thr);\n\t\thave_acc = 1;\n\t}\n\tDUK_DDD(DUK_DDDPRINT(\"have_acc=%ld, acc=%!T\",\n\t                     (long) have_acc, (duk_tval *) duk_get_tval(thr, 3)));\n\n\t/* For len == 0, i is initialized to len - 1 which underflows.\n\t * The condition (i < len) will then exit the for-loop on the\n\t * first round which is correct.  Similarly, loop termination\n\t * happens by i underflowing.\n\t */\n\n\tfor (i = (idx_step >= 0 ? 0 : len - 1);\n\t     i < len;  /* i >= 0 would always be true */\n\t     i += (duk_uint32_t) idx_step) {\n\t\tDUK_DDD(DUK_DDDPRINT(\"i=%ld, len=%ld, have_acc=%ld, top=%ld, acc=%!T\",\n\t\t                     (long) i, (long) len, (long) have_acc,\n\t\t                     (long) duk_get_top(thr),\n\t\t                     (duk_tval *) duk_get_tval(thr, 4)));\n\n\t\tDUK_ASSERT((have_acc && duk_get_top(thr) == 5) ||\n\t\t           (!have_acc && duk_get_top(thr) == 4));\n\n\t\tif (!duk_has_prop_index(thr, 2, (duk_uarridx_t) i)) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (!have_acc) {\n\t\t\tDUK_ASSERT_TOP(thr, 4);\n\t\t\tduk_get_prop_index(thr, 2, (duk_uarridx_t) i);\n\t\t\thave_acc = 1;\n\t\t\tDUK_ASSERT_TOP(thr, 5);\n\t\t} else {\n\t\t\tDUK_ASSERT_TOP(thr, 5);\n\t\t\tduk_dup_0(thr);\n\t\t\tduk_dup(thr, 4);\n\t\t\tduk_get_prop_index(thr, 2, (duk_uarridx_t) i);\n\t\t\tduk_push_u32(thr, i);\n\t\t\tduk_dup_2(thr);\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"calling reduce function: func=%!T, prev=%!T, curr=%!T, idx=%!T, obj=%!T\",\n\t\t\t                     (duk_tval *) duk_get_tval(thr, -5), (duk_tval *) duk_get_tval(thr, -4),\n\t\t\t                     (duk_tval *) duk_get_tval(thr, -3), (duk_tval *) duk_get_tval(thr, -2),\n\t\t\t                     (duk_tval *) duk_get_tval(thr, -1)));\n\t\t\tduk_call(thr, 4);\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"-> result: %!T\", (duk_tval *) duk_get_tval(thr, -1)));\n\t\t\tduk_replace(thr, 4);\n\t\t\tDUK_ASSERT_TOP(thr, 5);\n\t\t}\n\t}\n\n\tif (!have_acc) {\n\t\tDUK_DCERROR_TYPE_INVALID_ARGS(thr);\n\t}\n\n\tDUK_ASSERT_TOP(thr, 5);\n\treturn 1;\n}\n\n#endif  /* DUK_USE_ARRAY_BUILTIN */\n\n/* automatic undefs */\n#undef DUK__ARRAY_MID_JOIN_LIMIT\n#undef DUK__ITER_EVERY\n#undef DUK__ITER_FILTER\n#undef DUK__ITER_FOREACH\n#undef DUK__ITER_MAP\n#undef DUK__ITER_SOME\n#line 1 \"duk_bi_boolean.c\"\n/*\n *  Boolean built-ins\n */\n\n/* #include duk_internal.h -> already included */\n\n#if defined(DUK_USE_BOOLEAN_BUILTIN)\n\n/* Shared helper to provide toString() and valueOf().  Checks 'this', gets\n * the primitive value to stack top, and optionally coerces with ToString().\n */\nDUK_INTERNAL duk_ret_t duk_bi_boolean_prototype_tostring_shared(duk_hthread *thr) {\n\tduk_tval *tv;\n\tduk_hobject *h;\n\tduk_small_int_t coerce_tostring = duk_get_current_magic(thr);\n\n\t/* XXX: there is room to use a shared helper here, many built-ins\n\t * check the 'this' type, and if it's an object, check its class,\n\t * then get its internal value, etc.\n\t */\n\n\tduk_push_this(thr);\n\ttv = duk_get_tval(thr, -1);\n\tDUK_ASSERT(tv != NULL);\n\n\tif (DUK_TVAL_IS_BOOLEAN(tv)) {\n\t\tgoto type_ok;\n\t} else if (DUK_TVAL_IS_OBJECT(tv)) {\n\t\th = DUK_TVAL_GET_OBJECT(tv);\n\t\tDUK_ASSERT(h != NULL);\n\n\t\tif (DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_BOOLEAN) {\n\t\t\tduk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INT_VALUE);\n\t\t\tDUK_ASSERT(duk_is_boolean(thr, -1));\n\t\t\tgoto type_ok;\n\t\t}\n\t}\n\n\tDUK_DCERROR_TYPE_INVALID_ARGS(thr);\n\t/* never here */\n\n type_ok:\n\tif (coerce_tostring) {\n\t\tduk_to_string(thr, -1);\n\t}\n\treturn 1;\n}\n\nDUK_INTERNAL duk_ret_t duk_bi_boolean_constructor(duk_hthread *thr) {\n\tduk_hobject *h_this;\n\n\tduk_to_boolean(thr, 0);\n\n\tif (duk_is_constructor_call(thr)) {\n\t\t/* XXX: helper; rely on Boolean.prototype as being non-writable, non-configurable */\n\t\tduk_push_this(thr);\n\t\th_this = duk_known_hobject(thr, -1);\n\t\tDUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h_this) == thr->builtins[DUK_BIDX_BOOLEAN_PROTOTYPE]);\n\n\t\tDUK_HOBJECT_SET_CLASS_NUMBER(h_this, DUK_HOBJECT_CLASS_BOOLEAN);\n\n\t\tduk_dup_0(thr);  /* -> [ val obj val ] */\n\t\tduk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_NONE);  /* XXX: proper flags? */\n\t}  /* unbalanced stack */\n\n\treturn 1;\n}\n\n#endif  /* DUK_USE_BOOLEAN_BUILTIN */\n#line 1 \"duk_bi_buffer.c\"\n/*\n *  ES2015 TypedArray and Node.js Buffer built-ins\n */\n\n/* #include duk_internal.h -> already included */\n\n/*\n *  Helpers for buffer handling, enabled with DUK_USE_BUFFEROBJECT_SUPPORT.\n */\n\n#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)\n/* Map class number (minus DUK_HOBJECT_CLASS_BUFOBJ_MIN) to a bidx for the\n * default internal prototype.\n */\nstatic const duk_uint8_t duk__buffer_proto_from_classnum[] = {\n\tDUK_BIDX_ARRAYBUFFER_PROTOTYPE,\n\tDUK_BIDX_DATAVIEW_PROTOTYPE,\n\tDUK_BIDX_INT8ARRAY_PROTOTYPE,\n\tDUK_BIDX_UINT8ARRAY_PROTOTYPE,\n\tDUK_BIDX_UINT8CLAMPEDARRAY_PROTOTYPE,\n\tDUK_BIDX_INT16ARRAY_PROTOTYPE,\n\tDUK_BIDX_UINT16ARRAY_PROTOTYPE,\n\tDUK_BIDX_INT32ARRAY_PROTOTYPE,\n\tDUK_BIDX_UINT32ARRAY_PROTOTYPE,\n\tDUK_BIDX_FLOAT32ARRAY_PROTOTYPE,\n\tDUK_BIDX_FLOAT64ARRAY_PROTOTYPE\n};\n\n/* Map DUK_HBUFOBJ_ELEM_xxx to duk_hobject class number.\n * Sync with duk_hbufobj.h and duk_hobject.h.\n */\nstatic const duk_uint8_t duk__buffer_class_from_elemtype[9] = {\n\tDUK_HOBJECT_CLASS_UINT8ARRAY,\n\tDUK_HOBJECT_CLASS_UINT8CLAMPEDARRAY,\n\tDUK_HOBJECT_CLASS_INT8ARRAY,\n\tDUK_HOBJECT_CLASS_UINT16ARRAY,\n\tDUK_HOBJECT_CLASS_INT16ARRAY,\n\tDUK_HOBJECT_CLASS_UINT32ARRAY,\n\tDUK_HOBJECT_CLASS_INT32ARRAY,\n\tDUK_HOBJECT_CLASS_FLOAT32ARRAY,\n\tDUK_HOBJECT_CLASS_FLOAT64ARRAY\n};\n\n/* Map DUK_HBUFOBJ_ELEM_xxx to prototype object built-in index.\n * Sync with duk_hbufobj.h.\n */\nstatic const duk_uint8_t duk__buffer_proto_from_elemtype[9] = {\n\tDUK_BIDX_UINT8ARRAY_PROTOTYPE,\n\tDUK_BIDX_UINT8CLAMPEDARRAY_PROTOTYPE,\n\tDUK_BIDX_INT8ARRAY_PROTOTYPE,\n\tDUK_BIDX_UINT16ARRAY_PROTOTYPE,\n\tDUK_BIDX_INT16ARRAY_PROTOTYPE,\n\tDUK_BIDX_UINT32ARRAY_PROTOTYPE,\n\tDUK_BIDX_INT32ARRAY_PROTOTYPE,\n\tDUK_BIDX_FLOAT32ARRAY_PROTOTYPE,\n\tDUK_BIDX_FLOAT64ARRAY_PROTOTYPE\n};\n\n/* Map DUK__FLD_xxx to byte size. */\nstatic const duk_uint8_t duk__buffer_nbytes_from_fldtype[6] = {\n\t1,  /* DUK__FLD_8BIT */\n\t2,  /* DUK__FLD_16BIT */\n\t4,  /* DUK__FLD_32BIT */\n\t4,  /* DUK__FLD_FLOAT */\n\t8,  /* DUK__FLD_DOUBLE */\n\t0   /* DUK__FLD_VARINT; not relevant here */\n};\n\n/* Bitfield for each DUK_HBUFOBJ_ELEM_xxx indicating which element types\n * are compatible with a blind byte copy for the TypedArray set() method (also\n * used for TypedArray constructor).  Array index is target buffer elem type,\n * bitfield indicates compatible source types.  The types must have same byte\n * size and they must be coercion compatible.\n */\n#if !defined(DUK_USE_PREFER_SIZE)\nstatic duk_uint16_t duk__buffer_elemtype_copy_compatible[9] = {\n\t/* xxx -> DUK_HBUFOBJ_ELEM_UINT8 */\n\t(1U << DUK_HBUFOBJ_ELEM_UINT8) |\n\t\t(1U << DUK_HBUFOBJ_ELEM_UINT8CLAMPED) |\n\t\t(1U << DUK_HBUFOBJ_ELEM_INT8),\n\n\t/* xxx -> DUK_HBUFOBJ_ELEM_UINT8CLAMPED\n\t * Note: INT8 is -not- copy compatible, e.g. -1 would coerce to 0x00.\n\t */\n\t(1U << DUK_HBUFOBJ_ELEM_UINT8) |\n\t\t(1U << DUK_HBUFOBJ_ELEM_UINT8CLAMPED),\n\n\t/* xxx -> DUK_HBUFOBJ_ELEM_INT8 */\n\t(1U << DUK_HBUFOBJ_ELEM_UINT8) |\n\t\t(1U << DUK_HBUFOBJ_ELEM_UINT8CLAMPED) |\n\t\t(1U << DUK_HBUFOBJ_ELEM_INT8),\n\n\t/* xxx -> DUK_HBUFOBJ_ELEM_UINT16 */\n\t(1U << DUK_HBUFOBJ_ELEM_UINT16) |\n\t\t(1U << DUK_HBUFOBJ_ELEM_INT16),\n\n\t/* xxx -> DUK_HBUFOBJ_ELEM_INT16 */\n\t(1U << DUK_HBUFOBJ_ELEM_UINT16) |\n\t\t(1U << DUK_HBUFOBJ_ELEM_INT16),\n\n\t/* xxx -> DUK_HBUFOBJ_ELEM_UINT32 */\n\t(1U << DUK_HBUFOBJ_ELEM_UINT32) |\n\t\t(1U << DUK_HBUFOBJ_ELEM_INT32),\n\n\t/* xxx -> DUK_HBUFOBJ_ELEM_INT32 */\n\t(1U << DUK_HBUFOBJ_ELEM_UINT32) |\n\t\t(1U << DUK_HBUFOBJ_ELEM_INT32),\n\n\t/* xxx -> DUK_HBUFOBJ_ELEM_FLOAT32 */\n\t(1U << DUK_HBUFOBJ_ELEM_FLOAT32),\n\n\t/* xxx -> DUK_HBUFOBJ_ELEM_FLOAT64 */\n\t(1U << DUK_HBUFOBJ_ELEM_FLOAT64)\n};\n#endif  /* !DUK_USE_PREFER_SIZE */\n\nDUK_LOCAL duk_hbufobj *duk__hbufobj_promote_this(duk_hthread *thr) {\n\tduk_tval *tv_dst;\n\tduk_hbufobj *res;\n\n\tduk_push_this(thr);\n\tDUK_ASSERT(duk_is_buffer(thr, -1));\n\tres = (duk_hbufobj *) duk_to_hobject(thr, -1);\n\tDUK_ASSERT_HBUFOBJ_VALID(res);\n\tDUK_DD(DUK_DDPRINT(\"promoted 'this' automatically to an ArrayBuffer: %!iT\", duk_get_tval(thr, -1)));\n\n\ttv_dst = duk_get_borrowed_this_tval(thr);\n\tDUK_TVAL_SET_OBJECT_UPDREF(thr, tv_dst, (duk_hobject *) res);\n\tduk_pop(thr);\n\n\treturn res;\n}\n\n#define DUK__BUFOBJ_FLAG_THROW    (1 << 0)\n#define DUK__BUFOBJ_FLAG_PROMOTE  (1 << 1)\n\n/* Shared helper.  When DUK__BUFOBJ_FLAG_PROMOTE is given, the return value is\n * always a duk_hbufobj *.  Without the flag the return value can also be a\n * plain buffer, and the caller must check for it using DUK_HEAPHDR_IS_BUFFER().\n */\nDUK_LOCAL duk_heaphdr *duk__getrequire_bufobj_this(duk_hthread *thr, duk_small_uint_t flags) {\n\tduk_tval *tv;\n\tduk_hbufobj *h_this;\n\n\tDUK_ASSERT(thr != NULL);\n\n\ttv = duk_get_borrowed_this_tval(thr);\n\tDUK_ASSERT(tv != NULL);\n\n\tif (DUK_TVAL_IS_OBJECT(tv)) {\n\t\th_this = (duk_hbufobj *) DUK_TVAL_GET_OBJECT(tv);\n\t\tDUK_ASSERT(h_this != NULL);\n\t\tif (DUK_HOBJECT_IS_BUFOBJ((duk_hobject *) h_this)) {\n\t\t\tDUK_ASSERT_HBUFOBJ_VALID(h_this);\n\t\t\treturn (duk_heaphdr *) h_this;\n\t\t}\n\t} else if (DUK_TVAL_IS_BUFFER(tv)) {\n\t\tif (flags & DUK__BUFOBJ_FLAG_PROMOTE) {\n\t\t\t/* Promote a plain buffer to a Uint8Array.  This is very\n\t\t\t * inefficient but allows plain buffer to be used wherever an\n\t\t\t * Uint8Array is used with very small cost; hot path functions\n\t\t\t * like index read/write calls should provide direct buffer\n\t\t\t * support to avoid promotion.\n\t\t\t */\n\t\t\t/* XXX: make this conditional to a flag if call sites need it? */\n\t\t\th_this = duk__hbufobj_promote_this(thr);\n\t\t\tDUK_ASSERT(h_this != NULL);\n\t\t\tDUK_ASSERT_HBUFOBJ_VALID(h_this);\n\t\t\treturn (duk_heaphdr *) h_this;\n\t\t} else {\n\t\t\t/* XXX: ugly, share return pointer for duk_hbuffer. */\n\t\t\treturn (duk_heaphdr *) DUK_TVAL_GET_BUFFER(tv);\n\t\t}\n\t}\n\n\tif (flags & DUK__BUFOBJ_FLAG_THROW) {\n\t\tDUK_ERROR_TYPE(thr, DUK_STR_NOT_BUFFER);\n\t}\n\treturn NULL;\n}\n\n/* Check that 'this' is a duk_hbufobj and return a pointer to it. */\nDUK_LOCAL duk_hbufobj *duk__get_bufobj_this(duk_hthread *thr) {\n\treturn (duk_hbufobj *) duk__getrequire_bufobj_this(thr, DUK__BUFOBJ_FLAG_PROMOTE);\n}\n\n/* Check that 'this' is a duk_hbufobj and return a pointer to it\n * (NULL if not).\n */\nDUK_LOCAL duk_hbufobj *duk__require_bufobj_this(duk_hthread *thr) {\n\treturn (duk_hbufobj *) duk__getrequire_bufobj_this(thr, DUK__BUFOBJ_FLAG_THROW | DUK__BUFOBJ_FLAG_PROMOTE);\n}\n\n/* Check that value is a duk_hbufobj and return a pointer to it. */\nDUK_LOCAL duk_hbufobj *duk__require_bufobj_value(duk_hthread *thr, duk_idx_t idx) {\n\tduk_tval *tv;\n\tduk_hbufobj *h_obj;\n\n\t/* Don't accept relative indices now. */\n\tDUK_ASSERT(idx >= 0);\n\n\ttv = duk_require_tval(thr, idx);\n\tDUK_ASSERT(tv != NULL);\n\tif (DUK_TVAL_IS_OBJECT(tv)) {\n\t\th_obj = (duk_hbufobj *) DUK_TVAL_GET_OBJECT(tv);\n\t\tDUK_ASSERT(h_obj != NULL);\n\t\tif (DUK_HOBJECT_IS_BUFOBJ((duk_hobject *) h_obj)) {\n\t\t\tDUK_ASSERT_HBUFOBJ_VALID(h_obj);\n\t\t\treturn h_obj;\n\t\t}\n\t} else if (DUK_TVAL_IS_BUFFER(tv)) {\n\t\th_obj = (duk_hbufobj *) duk_to_hobject(thr, idx);\n\t\tDUK_ASSERT(h_obj != NULL);\n\t\tDUK_ASSERT_HBUFOBJ_VALID(h_obj);\n\t\treturn h_obj;\n\t}\n\n\tDUK_ERROR_TYPE(thr, DUK_STR_NOT_BUFFER);\n\treturn NULL;  /* not reachable */\n}\n\nDUK_LOCAL void duk__set_bufobj_buffer(duk_hthread *thr, duk_hbufobj *h_bufobj, duk_hbuffer *h_val) {\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(h_bufobj != NULL);\n\tDUK_ASSERT(h_bufobj->buf == NULL);  /* no need to decref */\n\tDUK_ASSERT(h_val != NULL);\n\tDUK_ASSERT_HBUFOBJ_VALID(h_bufobj);\n\tDUK_UNREF(thr);\n\n\th_bufobj->buf = h_val;\n\tDUK_HBUFFER_INCREF(thr, h_val);\n\th_bufobj->length = (duk_uint_t) DUK_HBUFFER_GET_SIZE(h_val);\n\tDUK_ASSERT(h_bufobj->shift == 0);\n\tDUK_ASSERT(h_bufobj->elem_type == DUK_HBUFOBJ_ELEM_UINT8);\n\tDUK_ASSERT(h_bufobj->is_typedarray == 0);\n\n\tDUK_ASSERT_HBUFOBJ_VALID(h_bufobj);\n}\n\n/* Shared offset/length coercion helper. */\nDUK_LOCAL void duk__resolve_offset_opt_length(duk_hthread *thr,\n                                              duk_hbufobj *h_bufarg,\n                                              duk_idx_t idx_offset,\n                                              duk_idx_t idx_length,\n                                              duk_uint_t *out_offset,\n                                              duk_uint_t *out_length,\n                                              duk_bool_t throw_flag) {\n\tduk_int_t offset_signed;\n\tduk_int_t length_signed;\n\tduk_uint_t offset;\n\tduk_uint_t length;\n\n\toffset_signed = duk_to_int(thr, idx_offset);\n\tif (offset_signed < 0) {\n\t\tgoto fail_range;\n\t}\n\toffset = (duk_uint_t) offset_signed;\n\tif (offset > h_bufarg->length) {\n\t\tgoto fail_range;\n\t}\n\tDUK_ASSERT_DISABLE(offset >= 0);  /* unsigned */\n\tDUK_ASSERT(offset <= h_bufarg->length);\n\n\tif (duk_is_undefined(thr, idx_length)) {\n\t\tDUK_ASSERT(h_bufarg->length >= offset);\n\t\tlength = h_bufarg->length - offset;  /* >= 0 */\n\t} else {\n\t\tlength_signed = duk_to_int(thr, idx_length);\n\t\tif (length_signed < 0) {\n\t\t\tgoto fail_range;\n\t\t}\n\t\tlength = (duk_uint_t) length_signed;\n\t\tDUK_ASSERT(h_bufarg->length >= offset);\n\t\tif (length > h_bufarg->length - offset) {\n\t\t\t/* Unlike for negative arguments, some call sites\n\t\t\t * want length to be clamped if it's positive.\n\t\t\t */\n\t\t\tif (throw_flag) {\n\t\t\t\tgoto fail_range;\n\t\t\t} else {\n\t\t\t\tlength = h_bufarg->length - offset;\n\t\t\t}\n\t\t}\n\t}\n\tDUK_ASSERT_DISABLE(length >= 0);  /* unsigned */\n\tDUK_ASSERT(offset + length <= h_bufarg->length);\n\n\t*out_offset = offset;\n\t*out_length = length;\n\treturn;\n\n fail_range:\n\tDUK_ERROR_RANGE(thr, DUK_STR_INVALID_ARGS);\n}\n\n/* Shared lenient buffer length clamping helper.  No negative indices, no\n * element/byte shifting.\n */\nDUK_LOCAL void duk__clamp_startend_nonegidx_noshift(duk_hthread *thr,\n                                                    duk_int_t buffer_length,\n                                                    duk_idx_t idx_start,\n                                                    duk_idx_t idx_end,\n                                                    duk_int_t *out_start_offset,\n                                                    duk_int_t *out_end_offset) {\n\tduk_int_t start_offset;\n\tduk_int_t end_offset;\n\n\tDUK_ASSERT(out_start_offset != NULL);\n\tDUK_ASSERT(out_end_offset != NULL);\n\n\t/* undefined coerces to zero which is correct */\n\tstart_offset = duk_to_int_clamped(thr, idx_start, 0, buffer_length);\n\tif (duk_is_undefined(thr, idx_end)) {\n\t\tend_offset = buffer_length;\n\t} else {\n\t\tend_offset = duk_to_int_clamped(thr, idx_end, start_offset, buffer_length);\n\t}\n\n\tDUK_ASSERT(start_offset >= 0);\n\tDUK_ASSERT(start_offset <= buffer_length);\n\tDUK_ASSERT(end_offset >= 0);\n\tDUK_ASSERT(end_offset <= buffer_length);\n\tDUK_ASSERT(start_offset <= end_offset);\n\n\t*out_start_offset = start_offset;\n\t*out_end_offset = end_offset;\n}\n\n/* Shared lenient buffer length clamping helper.  Indices are treated as\n * element indices (though output values are byte offsets) which only\n * really matters for TypedArray views as other buffer object have a zero\n * shift.  Negative indices are counted from end of input slice; crossed\n * indices are clamped to zero length; and final indices are clamped\n * against input slice.  Used for e.g. ArrayBuffer slice().\n */\nDUK_LOCAL void duk__clamp_startend_negidx_shifted(duk_hthread *thr,\n                                                  duk_int_t buffer_length,\n                                                  duk_uint8_t buffer_shift,\n                                                  duk_idx_t idx_start,\n                                                  duk_idx_t idx_end,\n                                                  duk_int_t *out_start_offset,\n                                                  duk_int_t *out_end_offset) {\n\tduk_int_t start_offset;\n\tduk_int_t end_offset;\n\n\tDUK_ASSERT(out_start_offset != NULL);\n\tDUK_ASSERT(out_end_offset != NULL);\n\n\tbuffer_length >>= buffer_shift;  /* as (full) elements */\n\n\t/* Resolve start/end offset as element indices first; arguments\n\t * at idx_start/idx_end are element offsets.  Working with element\n\t * indices first also avoids potential for wrapping.\n\t */\n\n\tstart_offset = duk_to_int(thr, idx_start);\n\tif (start_offset < 0) {\n\t\tstart_offset = buffer_length + start_offset;\n\t}\n\tif (duk_is_undefined(thr, idx_end)) {\n\t\tend_offset = buffer_length;\n\t} else {\n\t\tend_offset = duk_to_int(thr, idx_end);\n\t\tif (end_offset < 0) {\n\t\t\tend_offset = buffer_length + end_offset;\n\t\t}\n\t}\n\t/* Note: start_offset/end_offset can still be < 0 here. */\n\n\tif (start_offset < 0) {\n\t\tstart_offset = 0;\n\t} else if (start_offset > buffer_length) {\n\t\tstart_offset = buffer_length;\n\t}\n\tif (end_offset < start_offset) {\n\t\tend_offset = start_offset;\n\t} else if (end_offset > buffer_length) {\n\t\tend_offset = buffer_length;\n\t}\n\tDUK_ASSERT(start_offset >= 0);\n\tDUK_ASSERT(start_offset <= buffer_length);\n\tDUK_ASSERT(end_offset >= 0);\n\tDUK_ASSERT(end_offset <= buffer_length);\n\tDUK_ASSERT(start_offset <= end_offset);\n\n\t/* Convert indices to byte offsets. */\n\tstart_offset <<= buffer_shift;\n\tend_offset <<= buffer_shift;\n\n\t*out_start_offset = start_offset;\n\t*out_end_offset = end_offset;\n}\n\nDUK_INTERNAL void duk_hbufobj_promote_plain(duk_hthread *thr, duk_idx_t idx) {\n\tif (duk_is_buffer(thr, idx)) {\n\t\tduk_to_object(thr, idx);\n\t}\n}\n\nDUK_INTERNAL void duk_hbufobj_push_uint8array_from_plain(duk_hthread *thr, duk_hbuffer *h_buf) {\n\t/* Push Uint8Array which will share the same underlying buffer as\n\t * the plain buffer argument.  Also create an ArrayBuffer with the\n\t * same backing for the result .buffer property.\n\t */\n\n\tduk_push_hbuffer(thr, h_buf);\n\tduk_push_buffer_object(thr, -1, 0, (duk_size_t) DUK_HBUFFER_GET_SIZE(h_buf), DUK_BUFOBJ_UINT8ARRAY);\n\tduk_remove_m2(thr);\n\n#if 0\n\t/* More verbose equivalent; maybe useful if e.g. .buffer is omitted. */\n\th_bufobj = duk_push_bufobj_raw(thr,\n\t                               DUK_HOBJECT_FLAG_EXTENSIBLE |\n\t                               DUK_HOBJECT_FLAG_BUFOBJ |\n\t                               DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_UINT8ARRAY),\n\t                               DUK_BIDX_UINT8ARRAY_PROTOTYPE);\n\tDUK_ASSERT(h_bufobj != NULL);\n\tduk__set_bufobj_buffer(thr, h_bufobj, h_buf);\n\th_bufobj->is_typedarray = 1;\n\tDUK_ASSERT_HBUFOBJ_VALID(h_bufobj);\n\n\th_arrbuf = duk_push_bufobj_raw(thr,\n\t                               DUK_HOBJECT_FLAG_EXTENSIBLE |\n\t                               DUK_HOBJECT_FLAG_BUFOBJ |\n\t                               DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ARRAYBUFFER),\n\t                               DUK_BIDX_ARRAYBUFFER_PROTOTYPE);\n\tDUK_ASSERT(h_arrbuf != NULL);\n\tduk__set_bufobj_buffer(thr, h_arrbuf, h_buf);\n\tDUK_ASSERT(h_arrbuf->is_typedarray == 0);\n\tDUK_ASSERT_HBUFOBJ_VALID(h_arrbuf);\n\n\tDUK_ASSERT(h_bufobj->buf_prop == NULL);\n\th_bufobj->buf_prop = (duk_hobject *) h_arrbuf;\n\tDUK_ASSERT(h_arrbuf != NULL);\n\tDUK_HBUFOBJ_INCREF(thr, h_arrbuf);\n\tduk_pop(thr);\n#endif\n}\n\n/* Indexed read helper for buffer objects, also called from outside this file. */\nDUK_INTERNAL void duk_hbufobj_push_validated_read(duk_hthread *thr, duk_hbufobj *h_bufobj, duk_uint8_t *p, duk_small_uint_t elem_size) {\n\tduk_double_union du;\n\n\tDUK_MEMCPY((void *) du.uc, (const void *) p, (size_t) elem_size);\n\n\tswitch (h_bufobj->elem_type) {\n\tcase DUK_HBUFOBJ_ELEM_UINT8:\n\tcase DUK_HBUFOBJ_ELEM_UINT8CLAMPED:\n\t\tduk_push_uint(thr, (duk_uint_t) du.uc[0]);\n\t\tbreak;\n\tcase DUK_HBUFOBJ_ELEM_INT8:\n\t\tduk_push_int(thr, (duk_int_t) (duk_int8_t) du.uc[0]);\n\t\tbreak;\n\tcase DUK_HBUFOBJ_ELEM_UINT16:\n\t\tduk_push_uint(thr, (duk_uint_t) du.us[0]);\n\t\tbreak;\n\tcase DUK_HBUFOBJ_ELEM_INT16:\n\t\tduk_push_int(thr, (duk_int_t) (duk_int16_t) du.us[0]);\n\t\tbreak;\n\tcase DUK_HBUFOBJ_ELEM_UINT32:\n\t\tduk_push_uint(thr, (duk_uint_t) du.ui[0]);\n\t\tbreak;\n\tcase DUK_HBUFOBJ_ELEM_INT32:\n\t\tduk_push_int(thr, (duk_int_t) (duk_int32_t) du.ui[0]);\n\t\tbreak;\n\tcase DUK_HBUFOBJ_ELEM_FLOAT32:\n\t\tduk_push_number(thr, (duk_double_t) du.f[0]);\n\t\tbreak;\n\tcase DUK_HBUFOBJ_ELEM_FLOAT64:\n\t\tduk_push_number(thr, (duk_double_t) du.d);\n\t\tbreak;\n\tdefault:\n\t\tDUK_UNREACHABLE();\n\t}\n}\n\n/* Indexed write helper for buffer objects, also called from outside this file. */\nDUK_INTERNAL void duk_hbufobj_validated_write(duk_hthread *thr, duk_hbufobj *h_bufobj, duk_uint8_t *p, duk_small_uint_t elem_size) {\n\tduk_double_union du;\n\n\t/* NOTE! Caller must ensure that any side effects from the\n\t * coercions below are safe.  If that cannot be guaranteed\n\t * (which is normally the case), caller must coerce the\n\t * argument using duk_to_number() before any pointer\n\t * validations; the result of duk_to_number() always coerces\n\t * without side effects here.\n\t */\n\n\tswitch (h_bufobj->elem_type) {\n\tcase DUK_HBUFOBJ_ELEM_UINT8:\n\t\tdu.uc[0] = (duk_uint8_t) duk_to_uint32(thr, -1);\n\t\tbreak;\n\tcase DUK_HBUFOBJ_ELEM_UINT8CLAMPED:\n\t\tdu.uc[0] = (duk_uint8_t) duk_to_uint8clamped(thr, -1);\n\t\tbreak;\n\tcase DUK_HBUFOBJ_ELEM_INT8:\n\t\tdu.uc[0] = (duk_uint8_t) duk_to_int32(thr, -1);\n\t\tbreak;\n\tcase DUK_HBUFOBJ_ELEM_UINT16:\n\t\tdu.us[0] = (duk_uint16_t) duk_to_uint32(thr, -1);\n\t\tbreak;\n\tcase DUK_HBUFOBJ_ELEM_INT16:\n\t\tdu.us[0] = (duk_uint16_t) duk_to_int32(thr, -1);\n\t\tbreak;\n\tcase DUK_HBUFOBJ_ELEM_UINT32:\n\t\tdu.ui[0] = (duk_uint32_t) duk_to_uint32(thr, -1);\n\t\tbreak;\n\tcase DUK_HBUFOBJ_ELEM_INT32:\n\t\tdu.ui[0] = (duk_uint32_t) duk_to_int32(thr, -1);\n\t\tbreak;\n\tcase DUK_HBUFOBJ_ELEM_FLOAT32:\n\t\tdu.f[0] = (duk_float_t) duk_to_number_m1(thr);\n\t\tbreak;\n\tcase DUK_HBUFOBJ_ELEM_FLOAT64:\n\t\tdu.d = (duk_double_t) duk_to_number_m1(thr);\n\t\tbreak;\n\tdefault:\n\t\tDUK_UNREACHABLE();\n\t}\n\n\tDUK_MEMCPY((void *) p, (const void *) du.uc, (size_t) elem_size);\n}\n\n/* Helper to create a fixed buffer from argument value at index 0.\n * Node.js and allocPlain() compatible.\n */\nDUK_LOCAL duk_hbuffer *duk__hbufobj_fixed_from_argvalue(duk_hthread *thr) {\n\tduk_int_t len;\n\tduk_int_t i;\n\tduk_size_t buf_size;\n\tduk_uint8_t *buf;\n\n\tswitch (duk_get_type(thr, 0)) {\n\tcase DUK_TYPE_NUMBER: {\n\t\tlen = duk_to_int_clamped(thr, 0, 0, DUK_INT_MAX);\n\t\t(void) duk_push_fixed_buffer_zero(thr, (duk_size_t) len);\n\t\tbreak;\n\t}\n\tcase DUK_TYPE_BUFFER: { /* Treat like Uint8Array. */\n\t\tgoto slow_copy;\n\t}\n\tcase DUK_TYPE_OBJECT: {\n\t\tduk_hobject *h;\n\t\tduk_hbufobj *h_bufobj;\n\n\t\t/* For Node.js Buffers \"Passing an ArrayBuffer returns a Buffer\n\t\t * that shares allocated memory with the given ArrayBuffer.\"\n\t\t * https://nodejs.org/api/buffer.html#buffer_buffer_from_buffer_alloc_and_buffer_allocunsafe\n\t\t */\n\n\t\th = duk_known_hobject(thr, 0);\n\t\tif (DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_ARRAYBUFFER) {\n\t\t\tDUK_ASSERT(DUK_HOBJECT_IS_BUFOBJ(h));\n\t\t\th_bufobj = (duk_hbufobj *) h;\n\t\t\tif (DUK_UNLIKELY(h_bufobj->buf == NULL)) {\n\t\t\t\tDUK_ERROR_TYPE_INVALID_ARGS(thr);\n\t\t\t}\n\t\t\tif (DUK_UNLIKELY(h_bufobj->offset != 0 || h_bufobj->length != DUK_HBUFFER_GET_SIZE(h_bufobj->buf))) {\n\t\t\t\t/* No support for ArrayBuffers with slice\n\t\t\t\t * offset/length.\n\t\t\t\t */\n\t\t\t\tDUK_ERROR_TYPE_INVALID_ARGS(thr);\n\t\t\t}\n\t\t\tduk_push_hbuffer(thr, h_bufobj->buf);\n\t\t\treturn h_bufobj->buf;\n\t\t}\n\t\tgoto slow_copy;\n\t}\n\tcase DUK_TYPE_STRING: {\n\t\t/* ignore encoding for now */\n\t\tduk_require_hstring_notsymbol(thr, 0);\n\t\tduk_dup_0(thr);\n\t\t(void) duk_to_buffer(thr, -1, &buf_size);\n\t\tbreak;\n\t}\n\tdefault:\n\t\tDUK_ERROR_TYPE_INVALID_ARGS(thr);\n\t}\n\n done:\n\tDUK_ASSERT(duk_is_buffer(thr, -1));\n\treturn duk_known_hbuffer(thr, -1);\n\n slow_copy:\n\t/* XXX: fast path for typed arrays and other buffer objects? */\n\n\t(void) duk_get_prop_stridx_short(thr, 0, DUK_STRIDX_LENGTH);\n\tlen = duk_to_int_clamped(thr, -1, 0, DUK_INT_MAX);\n\tduk_pop(thr);\n\tbuf = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, (duk_size_t) len);  /* no zeroing, all indices get initialized */\n\tfor (i = 0; i < len; i++) {\n\t\t/* XXX: fast path for array or buffer arguments? */\n\t\tduk_get_prop_index(thr, 0, (duk_uarridx_t) i);\n\t\tbuf[i] = (duk_uint8_t) (duk_to_uint32(thr, -1) & 0xffU);\n\t\tduk_pop(thr);\n\t}\n\tgoto done;\n}\n#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */\n\n/*\n *  Node.js Buffer constructor\n *\n *  Node.js Buffers are just Uint8Arrays with internal prototype set to\n *  Buffer.prototype so they're handled otherwise the same as Uint8Array.\n *  However, the constructor arguments are very different so a separate\n *  constructor entry point is used.\n */\n#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)\nDUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_constructor(duk_hthread *thr) {\n\tduk_hbuffer *h_buf;\n\n\th_buf = duk__hbufobj_fixed_from_argvalue(thr);\n\tDUK_ASSERT(h_buf != NULL);\n\n\tduk_push_buffer_object(thr,\n\t                       -1,\n\t                       0,\n\t                       DUK_HBUFFER_FIXED_GET_SIZE((duk_hbuffer_fixed *) h_buf),\n\t                       DUK_BUFOBJ_UINT8ARRAY);\n\tduk_push_hobject_bidx(thr, DUK_BIDX_NODEJS_BUFFER_PROTOTYPE);\n\tduk_set_prototype(thr, -2);\n\n\t/* XXX: a more direct implementation */\n\n\treturn 1;\n}\n#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */\n\n/*\n *  ArrayBuffer, DataView, and TypedArray constructors\n */\n\n#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)\nDUK_INTERNAL duk_ret_t duk_bi_arraybuffer_constructor(duk_hthread *thr) {\n\tduk_hbufobj *h_bufobj;\n\tduk_hbuffer *h_val;\n\tduk_int_t len;\n\n\tDUK_ASSERT_CTX_VALID(thr);\n\n\tduk_require_constructor_call(thr);\n\n\tlen = duk_to_int(thr, 0);\n\tif (len < 0) {\n\t\tgoto fail_length;\n\t}\n\t(void) duk_push_fixed_buffer_zero(thr, (duk_size_t) len);\n\th_val = (duk_hbuffer *) duk_known_hbuffer(thr, -1);\n\n\th_bufobj = duk_push_bufobj_raw(thr,\n\t                               DUK_HOBJECT_FLAG_EXTENSIBLE |\n\t                               DUK_HOBJECT_FLAG_BUFOBJ |\n\t                               DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ARRAYBUFFER),\n\t                               DUK_BIDX_ARRAYBUFFER_PROTOTYPE);\n\tDUK_ASSERT(h_bufobj != NULL);\n\n\tduk__set_bufobj_buffer(thr, h_bufobj, h_val);\n\tDUK_ASSERT_HBUFOBJ_VALID(h_bufobj);\n\n\treturn 1;\n\n fail_length:\n\tDUK_DCERROR_RANGE_INVALID_LENGTH(thr);\n}\n#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */\n\n\n/* Format of magic, bits:\n *   0...1: elem size shift (0-3)\n *   2...5: elem type (DUK_HBUFOBJ_ELEM_xxx)\n *\n * XXX: add prototype bidx explicitly to magic instead of using a mapping?\n */\n\n#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)\nDUK_INTERNAL duk_ret_t duk_bi_typedarray_constructor(duk_hthread *thr) {\n\tduk_tval *tv;\n\tduk_hobject *h_obj;\n\tduk_hbufobj *h_bufobj = NULL;\n\tduk_hbufobj *h_bufarg = NULL;\n\tduk_hbuffer *h_val;\n\tduk_small_uint_t magic;\n\tduk_small_uint_t shift;\n\tduk_small_uint_t elem_type;\n\tduk_small_uint_t elem_size;\n\tduk_small_uint_t class_num;\n\tduk_small_uint_t proto_bidx;\n\tduk_uint_t align_mask;\n\tduk_uint_t elem_length;\n\tduk_int_t elem_length_signed;\n\tduk_uint_t byte_length;\n\tduk_small_uint_t copy_mode;\n\n\t/* XXX: The same copy helpers could be shared with at least some\n\t * buffer functions.\n\t */\n\n\tduk_require_constructor_call(thr);\n\n\t/* We could fit built-in index into magic but that'd make the magic\n\t * number dependent on built-in numbering (genbuiltins.py doesn't\n\t * handle that yet).  So map both class and prototype from the\n\t * element type.\n\t */\n\tmagic = (duk_small_uint_t) duk_get_current_magic(thr);\n\tshift = magic & 0x03U;               /* bits 0...1: shift */\n\telem_type = (magic >> 2) & 0x0fU;    /* bits 2...5: type */\n\telem_size = 1U << shift;\n\talign_mask = elem_size - 1;\n\tDUK_ASSERT(elem_type < sizeof(duk__buffer_proto_from_elemtype) / sizeof(duk_uint8_t));\n\tproto_bidx = duk__buffer_proto_from_elemtype[elem_type];\n\tDUK_ASSERT(proto_bidx < DUK_NUM_BUILTINS);\n\tDUK_ASSERT(elem_type < sizeof(duk__buffer_class_from_elemtype) / sizeof(duk_uint8_t));\n\tclass_num = duk__buffer_class_from_elemtype[elem_type];\n\n\tDUK_DD(DUK_DDPRINT(\"typedarray constructor, magic=%d, shift=%d, elem_type=%d, \"\n\t                   \"elem_size=%d, proto_bidx=%d, class_num=%d\",\n\t                   (int) magic, (int) shift, (int) elem_type, (int) elem_size,\n\t                   (int) proto_bidx, (int) class_num));\n\n\t/* Argument variants.  When the argument is an ArrayBuffer a view to\n\t * the same buffer is created; otherwise a new ArrayBuffer is always\n\t * created.\n\t */\n\n\t/* XXX: initial iteration to treat a plain buffer like an ArrayBuffer:\n\t * coerce to an ArrayBuffer object and use that as .buffer.  The underlying\n\t * buffer will be the same but result .buffer !== inputPlainBuffer.\n\t */\n\tduk_hbufobj_promote_plain(thr, 0);\n\n\ttv = duk_get_tval(thr, 0);\n\tDUK_ASSERT(tv != NULL);  /* arg count */\n\tif (DUK_TVAL_IS_OBJECT(tv)) {\n\t\th_obj = DUK_TVAL_GET_OBJECT(tv);\n\t\tDUK_ASSERT(h_obj != NULL);\n\n\t\tif (DUK_HOBJECT_GET_CLASS_NUMBER(h_obj) == DUK_HOBJECT_CLASS_ARRAYBUFFER) {\n\t\t\t/* ArrayBuffer: unlike any other argument variant, create\n\t\t\t * a view into the existing buffer.\n\t\t\t */\n\n\t\t\tduk_int_t byte_offset_signed;\n\t\t\tduk_uint_t byte_offset;\n\n\t\t\th_bufarg = (duk_hbufobj *) h_obj;\n\n\t\t\tbyte_offset_signed = duk_to_int(thr, 1);\n\t\t\tif (byte_offset_signed < 0) {\n\t\t\t\tgoto fail_arguments;\n\t\t\t}\n\t\t\tbyte_offset = (duk_uint_t) byte_offset_signed;\n\t\t\tif (byte_offset > h_bufarg->length ||\n\t\t\t    (byte_offset & align_mask) != 0) {\n\t\t\t\t/* Must be >= 0 and multiple of element size. */\n\t\t\t\tgoto fail_arguments;\n\t\t\t}\n\t\t\tif (duk_is_undefined(thr, 2)) {\n\t\t\t\tDUK_ASSERT(h_bufarg->length >= byte_offset);\n\t\t\t\tbyte_length = h_bufarg->length - byte_offset;\n\t\t\t\tif ((byte_length & align_mask) != 0) {\n\t\t\t\t\t/* Must be element size multiple from\n\t\t\t\t\t * start offset to end of buffer.\n\t\t\t\t\t */\n\t\t\t\t\tgoto fail_arguments;\n\t\t\t\t}\n\t\t\t\telem_length = (byte_length >> shift);\n\t\t\t} else {\n\t\t\t\telem_length_signed = duk_to_int(thr, 2);\n\t\t\t\tif (elem_length_signed < 0) {\n\t\t\t\t\tgoto fail_arguments;\n\t\t\t\t}\n\t\t\t\telem_length = (duk_uint_t) elem_length_signed;\n\t\t\t\tbyte_length = elem_length << shift;\n\t\t\t\tif ((byte_length >> shift) != elem_length) {\n\t\t\t\t\t/* Byte length would overflow. */\n\t\t\t\t\t/* XXX: easier check with less code? */\n\t\t\t\t\tgoto fail_arguments;\n\t\t\t\t}\n\t\t\t\tDUK_ASSERT(h_bufarg->length >= byte_offset);\n\t\t\t\tif (byte_length > h_bufarg->length - byte_offset) {\n\t\t\t\t\t/* Not enough data. */\n\t\t\t\t\tgoto fail_arguments;\n\t\t\t\t}\n\t\t\t}\n\t\t\tDUK_UNREF(elem_length);\n\t\t\tDUK_ASSERT_DISABLE(byte_offset >= 0);\n\t\t\tDUK_ASSERT(byte_offset <= h_bufarg->length);\n\t\t\tDUK_ASSERT_DISABLE(byte_length >= 0);\n\t\t\tDUK_ASSERT(byte_offset + byte_length <= h_bufarg->length);\n\t\t\tDUK_ASSERT((elem_length << shift) == byte_length);\n\n\t\t\th_bufobj = duk_push_bufobj_raw(thr,\n\t\t\t                               DUK_HOBJECT_FLAG_EXTENSIBLE |\n\t\t\t                               DUK_HOBJECT_FLAG_BUFOBJ |\n\t\t\t                               DUK_HOBJECT_CLASS_AS_FLAGS(class_num),\n\t\t\t                               (duk_small_int_t) proto_bidx);\n\t\t\th_val = h_bufarg->buf;\n\t\t\tif (h_val == NULL) {\n\t\t\t\tDUK_DCERROR_TYPE_INVALID_ARGS(thr);\n\t\t\t}\n\t\t\th_bufobj->buf = h_val;\n\t\t\tDUK_HBUFFER_INCREF(thr, h_val);\n\t\t\th_bufobj->offset = h_bufarg->offset + byte_offset;\n\t\t\th_bufobj->length = byte_length;\n\t\t\th_bufobj->shift = (duk_uint8_t) shift;\n\t\t\th_bufobj->elem_type = (duk_uint8_t) elem_type;\n\t\t\th_bufobj->is_typedarray = 1;\n\t\t\tDUK_ASSERT_HBUFOBJ_VALID(h_bufobj);\n\n\t\t\t/* Set .buffer to the argument ArrayBuffer. */\n\t\t\tDUK_ASSERT(h_bufobj->buf_prop == NULL);\n\t\t\th_bufobj->buf_prop = (duk_hobject *) h_bufarg;\n\t\t\tDUK_ASSERT(h_bufarg != NULL);\n\t\t\tDUK_HBUFOBJ_INCREF(thr, h_bufarg);\n\t\t\treturn 1;\n\t\t} else if (DUK_HOBJECT_IS_BUFOBJ(h_obj)) {\n\t\t\t/* TypedArray (or other non-ArrayBuffer duk_hbufobj).\n\t\t\t * Conceptually same behavior as for an Array-like argument,\n\t\t\t * with a few fast paths.\n\t\t\t */\n\n\t\t\th_bufarg = (duk_hbufobj *) h_obj;\n\t\t\tDUK_ASSERT_HBUFOBJ_VALID(h_bufarg);\n\t\t\telem_length_signed = (duk_int_t) (h_bufarg->length >> h_bufarg->shift);\n\t\t\tif (h_bufarg->buf == NULL) {\n\t\t\t\tDUK_DCERROR_TYPE_INVALID_ARGS(thr);\n\t\t\t}\n\n\t\t\t/* Select copy mode.  Must take into account element\n\t\t\t * compatibility and validity of the underlying source\n\t\t\t * buffer.\n\t\t\t */\n\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"selecting copy mode for bufobj arg, \"\n\t\t\t                     \"src byte_length=%ld, src shift=%d, \"\n\t\t\t                     \"src/dst elem_length=%ld; \"\n\t\t\t                     \"dst shift=%d -> dst byte_length=%ld\",\n\t\t\t                     (long) h_bufarg->length, (int) h_bufarg->shift,\n\t\t\t                     (long) elem_length_signed, (int) shift,\n\t\t\t                     (long) (elem_length_signed << shift)));\n\n\t\t\tcopy_mode = 2;  /* default is explicit index read/write copy */\n#if !defined(DUK_USE_PREFER_SIZE)\n\t\t\t/* With a size optimized build copy_mode 2 is enough.\n\t\t\t * Modes 0 and 1 are faster but conceptually the same.\n\t\t\t */\n\t\t\tDUK_ASSERT(elem_type < sizeof(duk__buffer_elemtype_copy_compatible) / sizeof(duk_uint16_t));\n\t\t\tif (DUK_HBUFOBJ_VALID_SLICE(h_bufarg)) {\n\t\t\t\tif ((duk__buffer_elemtype_copy_compatible[elem_type] & (1 << h_bufarg->elem_type)) != 0) {\n\t\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"source/target are copy compatible, memcpy\"));\n\t\t\t\t\tDUK_ASSERT(shift == h_bufarg->shift);  /* byte sizes will match */\n\t\t\t\t\tcopy_mode = 0;\n\t\t\t\t} else {\n\t\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"source/target not copy compatible but valid, fast copy\"));\n\t\t\t\t\tcopy_mode = 1;\n\t\t\t\t}\n\t\t\t}\n#endif  /* !DUK_USE_PREFER_SIZE */\n\t\t} else {\n\t\t\t/* Array or Array-like */\n\t\t\telem_length_signed = (duk_int_t) duk_get_length(thr, 0);\n\t\t\tcopy_mode = 2;\n\t\t}\n\t} else {\n\t\t/* Non-object argument is simply int coerced, matches\n\t\t * V8 behavior (except for \"null\", which we coerce to\n\t\t * 0 but V8 TypeErrors).\n\t\t */\n\t\telem_length_signed = duk_to_int(thr, 0);\n\t\tcopy_mode = 3;\n\t}\n\tif (elem_length_signed < 0) {\n\t\tgoto fail_arguments;\n\t}\n\telem_length = (duk_uint_t) elem_length_signed;\n\tbyte_length = (duk_uint_t) (elem_length << shift);\n\tif ((byte_length >> shift) != elem_length) {\n\t\t/* Byte length would overflow. */\n\t\t/* XXX: easier check with less code? */\n\t\tgoto fail_arguments;\n\t}\n\n\tDUK_DDD(DUK_DDDPRINT(\"elem_length=%ld, byte_length=%ld\",\n\t                     (long) elem_length, (long) byte_length));\n\n\t/* ArrayBuffer argument is handled specially above; the rest of the\n\t * argument variants are handled by shared code below.\n\t *\n\t * ArrayBuffer in h_bufobj->buf_prop is intentionally left unset.\n\t * It will be automatically created by the .buffer accessor on\n\t * first access.\n\t */\n\n\t/* Push the resulting view object on top of a plain fixed buffer. */\n\t(void) duk_push_fixed_buffer(thr, byte_length);\n\th_val = duk_known_hbuffer(thr, -1);\n\tDUK_ASSERT(h_val != NULL);\n\n\th_bufobj = duk_push_bufobj_raw(thr,\n\t                               DUK_HOBJECT_FLAG_EXTENSIBLE |\n\t                               DUK_HOBJECT_FLAG_BUFOBJ |\n\t                               DUK_HOBJECT_CLASS_AS_FLAGS(class_num),\n\t                               (duk_small_int_t) proto_bidx);\n\n\th_bufobj->buf = h_val;\n\tDUK_HBUFFER_INCREF(thr, h_val);\n\tDUK_ASSERT(h_bufobj->offset == 0);\n\th_bufobj->length = byte_length;\n\th_bufobj->shift = (duk_uint8_t) shift;\n\th_bufobj->elem_type = (duk_uint8_t) elem_type;\n\th_bufobj->is_typedarray = 1;\n\tDUK_ASSERT_HBUFOBJ_VALID(h_bufobj);\n\n\t/* Copy values, the copy method depends on the arguments.\n\t *\n\t * Copy mode decision may depend on the validity of the underlying\n\t * buffer of the source argument; there must be no harmful side effects\n\t * from there to here for copy_mode to still be valid.\n\t */\n\tDUK_DDD(DUK_DDDPRINT(\"copy mode: %d\", (int) copy_mode));\n\tswitch (copy_mode) {\n\t\t/* Copy modes 0 and 1 can be omitted in size optimized build,\n\t\t * copy mode 2 handles them (but more slowly).\n\t\t */\n#if !defined(DUK_USE_PREFER_SIZE)\n\tcase 0: {\n\t\t/* Use byte copy. */\n\n\t\tduk_uint8_t *p_src;\n\t\tduk_uint8_t *p_dst;\n\n\t\tDUK_ASSERT(h_bufobj != NULL);\n\t\tDUK_ASSERT(h_bufobj->buf != NULL);\n\t\tDUK_ASSERT(DUK_HBUFOBJ_VALID_SLICE(h_bufobj));\n\t\tDUK_ASSERT(h_bufarg != NULL);\n\t\tDUK_ASSERT(h_bufarg->buf != NULL);\n\t\tDUK_ASSERT(DUK_HBUFOBJ_VALID_SLICE(h_bufarg));\n\n\t\tp_dst = DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_bufobj);\n\t\tp_src = DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_bufarg);\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"using memcpy: p_src=%p, p_dst=%p, byte_length=%ld\",\n\t\t                     (void *) p_src, (void *) p_dst, (long) byte_length));\n\n\t\tDUK_MEMCPY((void *) p_dst, (const void *) p_src, (size_t) byte_length);\n\t\tbreak;\n\t}\n\tcase 1: {\n\t\t/* Copy values through direct validated reads and writes. */\n\n\t\tduk_small_uint_t src_elem_size;\n\t\tduk_small_uint_t dst_elem_size;\n\t\tduk_uint8_t *p_src;\n\t\tduk_uint8_t *p_src_end;\n\t\tduk_uint8_t *p_dst;\n\n\t\tDUK_ASSERT(h_bufobj != NULL);\n\t\tDUK_ASSERT(h_bufobj->buf != NULL);\n\t\tDUK_ASSERT(DUK_HBUFOBJ_VALID_SLICE(h_bufobj));\n\t\tDUK_ASSERT(h_bufarg != NULL);\n\t\tDUK_ASSERT(h_bufarg->buf != NULL);\n\t\tDUK_ASSERT(DUK_HBUFOBJ_VALID_SLICE(h_bufarg));\n\n\t\tsrc_elem_size = (duk_small_uint_t) (1U << h_bufarg->shift);\n\t\tdst_elem_size = elem_size;\n\n\t\tp_src = DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_bufarg);\n\t\tp_dst = DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_bufobj);\n\t\tp_src_end = p_src + h_bufarg->length;\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"using fast copy: p_src=%p, p_src_end=%p, p_dst=%p, \"\n\t\t                     \"src_elem_size=%d, dst_elem_size=%d\",\n\t\t                     (void *) p_src, (void *) p_src_end, (void *) p_dst,\n\t\t                     (int) src_elem_size, (int) dst_elem_size));\n\n\t\twhile (p_src != p_src_end) {\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"fast path per element copy loop: \"\n\t\t\t                     \"p_src=%p, p_src_end=%p, p_dst=%p\",\n\t\t\t                     (void *) p_src, (void *) p_src_end, (void *) p_dst));\n\t\t\t/* A validated read() is always a number, so it's write coercion\n\t\t\t * is always side effect free an won't invalidate pointers etc.\n\t\t\t */\n\t\t\tduk_hbufobj_push_validated_read(thr, h_bufarg, p_src, src_elem_size);\n\t\t\tduk_hbufobj_validated_write(thr, h_bufobj, p_dst, dst_elem_size);\n\t\t\tduk_pop(thr);\n\t\t\tp_src += src_elem_size;\n\t\t\tp_dst += dst_elem_size;\n\t\t}\n\t\tbreak;\n\t}\n#endif  /* !DUK_USE_PREFER_SIZE */\n\tcase 2: {\n\t\t/* Copy values by index reads and writes.  Let virtual\n\t\t * property handling take care of coercion.\n\t\t */\n\t\tduk_uint_t i;\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"using slow copy\"));\n\n\t\tfor (i = 0; i < elem_length; i++) {\n\t\t\tduk_get_prop_index(thr, 0, (duk_uarridx_t) i);\n\t\t\tduk_put_prop_index(thr, -2, (duk_uarridx_t) i);\n\t\t}\n\t\tbreak;\n\t}\n\tdefault:\n\tcase 3: {\n\t\t/* No copy, leave zero bytes in the buffer.  There's no\n\t\t * ambiguity with Float32/Float64 because zero bytes also\n\t\t * represent 0.0.\n\t\t */\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"using no copy\"));\n\t\tbreak;\n\t}\n\t}\n\n\treturn 1;\n\n fail_arguments:\n\tDUK_DCERROR_RANGE_INVALID_ARGS(thr);\n}\n#else  /* DUK_USE_BUFFEROBJECT_SUPPORT */\n/* When bufferobject support is disabled, new Uint8Array() could still be\n * supported to create a plain fixed buffer.  Disabled for now.\n */\n#if 0\nDUK_INTERNAL duk_ret_t duk_bi_typedarray_constructor(duk_hthread *thr) {\n\tduk_int_t elem_length_signed;\n\tduk_uint_t byte_length;\n\n\t/* XXX: The same copy helpers could be shared with at least some\n\t * buffer functions.\n\t */\n\n\tduk_require_constructor_call(thr);\n\n\telem_length_signed = duk_require_int(thr, 0);\n\tif (elem_length_signed < 0) {\n\t\tgoto fail_arguments;\n\t}\n\tbyte_length = (duk_uint_t) elem_length_signed;\n\n\t(void) duk_push_fixed_buffer_zero(thr, (duk_size_t) byte_length);\n\treturn 1;\n\n fail_arguments:\n\tDUK_DCERROR_RANGE_INVALID_ARGS(thr);\n}\n#endif  /* 0 */\n#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */\n\n#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)\nDUK_INTERNAL duk_ret_t duk_bi_dataview_constructor(duk_hthread *thr) {\n\tduk_hbufobj *h_bufarg;\n\tduk_hbufobj *h_bufobj;\n\tduk_hbuffer *h_val;\n\tduk_uint_t offset;\n\tduk_uint_t length;\n\n\tduk_require_constructor_call(thr);\n\n\th_bufarg = duk__require_bufobj_value(thr, 0);\n\tDUK_ASSERT(h_bufarg != NULL);\n\tif (DUK_HOBJECT_GET_CLASS_NUMBER((duk_hobject *) h_bufarg) != DUK_HOBJECT_CLASS_ARRAYBUFFER) {\n\t\tDUK_DCERROR_TYPE_INVALID_ARGS(thr);\n\t}\n\n\tduk__resolve_offset_opt_length(thr, h_bufarg, 1, 2, &offset, &length, 1 /*throw_flag*/);\n\tDUK_ASSERT(offset <= h_bufarg->length);\n\tDUK_ASSERT(offset + length <= h_bufarg->length);\n\n\th_bufobj = duk_push_bufobj_raw(thr,\n\t                               DUK_HOBJECT_FLAG_EXTENSIBLE |\n\t                               DUK_HOBJECT_FLAG_BUFOBJ |\n\t                               DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_DATAVIEW),\n\t                               DUK_BIDX_DATAVIEW_PROTOTYPE);\n\n\th_val = h_bufarg->buf;\n\tif (h_val == NULL) {\n\t\tDUK_DCERROR_TYPE_INVALID_ARGS(thr);\n\t}\n\th_bufobj->buf = h_val;\n\tDUK_HBUFFER_INCREF(thr, h_val);\n\th_bufobj->offset = h_bufarg->offset + offset;\n\th_bufobj->length = length;\n\tDUK_ASSERT(h_bufobj->shift == 0);\n\tDUK_ASSERT(h_bufobj->elem_type == DUK_HBUFOBJ_ELEM_UINT8);\n\tDUK_ASSERT(h_bufobj->is_typedarray == 0);\n\n\tDUK_ASSERT(h_bufobj->buf_prop == NULL);\n\th_bufobj->buf_prop = (duk_hobject *) h_bufarg;\n\tDUK_ASSERT(h_bufarg != NULL);\n\tDUK_HBUFOBJ_INCREF(thr, h_bufarg);\n\n\tDUK_ASSERT_HBUFOBJ_VALID(h_bufobj);\n\treturn 1;\n}\n#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */\n\n/*\n *  ArrayBuffer.isView()\n */\n\n#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)\nDUK_INTERNAL duk_ret_t duk_bi_arraybuffer_isview(duk_hthread *thr) {\n\tduk_hobject *h_obj;\n\tduk_bool_t ret = 0;\n\n\tif (duk_is_buffer(thr, 0)) {\n\t\tret = 1;\n\t} else {\n\t\th_obj = duk_get_hobject(thr, 0);\n\t\tif (h_obj != NULL && DUK_HOBJECT_IS_BUFOBJ(h_obj)) {\n\t\t\t/* DataView needs special casing: ArrayBuffer.isView() is\n\t\t\t * true, but ->is_typedarray is 0.\n\t\t\t */\n\t\t\tret = ((duk_hbufobj *) h_obj)->is_typedarray ||\n\t\t\t      (DUK_HOBJECT_GET_CLASS_NUMBER(h_obj) == DUK_HOBJECT_CLASS_DATAVIEW);\n\t\t}\n\t}\n\tduk_push_boolean(thr, ret);\n\treturn 1;\n}\n#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */\n\n/*\n *  Uint8Array.allocPlain()\n */\n\n#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)\nDUK_INTERNAL duk_ret_t duk_bi_uint8array_allocplain(duk_hthread *thr) {\n\tduk__hbufobj_fixed_from_argvalue(thr);\n\treturn 1;\n}\n#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */\n\n/*\n *  Uint8Array.plainOf()\n */\n\n#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)\nDUK_INTERNAL duk_ret_t duk_bi_uint8array_plainof(duk_hthread *thr) {\n\tduk_hbufobj *h_bufobj;\n\n#if !defined(DUK_USE_PREFER_SIZE)\n\t/* Avoid churn if argument is already a plain buffer. */\n\tif (duk_is_buffer(thr, 0)) {\n\t\treturn 1;\n\t}\n#endif\n\n\t/* Promotes plain buffers to ArrayBuffers, so for a plain buffer\n\t * argument we'll create a pointless temporary (but still work\n\t * correctly).\n\t */\n\th_bufobj = duk__require_bufobj_value(thr, 0);\n\tif (h_bufobj->buf == NULL) {\n\t\tduk_push_undefined(thr);\n\t} else {\n\t\tduk_push_hbuffer(thr, h_bufobj->buf);\n\t}\n\treturn 1;\n}\n#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */\n\n/*\n *  Node.js Buffer: toString([encoding], [start], [end])\n */\n\n#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)\nDUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_tostring(duk_hthread *thr) {\n\tduk_hbufobj *h_this;\n\tduk_int_t start_offset, end_offset;\n\tduk_uint8_t *buf_slice;\n\tduk_size_t slice_length;\n\n\th_this = duk__get_bufobj_this(thr);\n\tif (h_this == NULL) {\n\t\t/* XXX: happens e.g. when evaluating: String(Buffer.prototype). */\n\t\tduk_push_string(thr, \"[object Object]\");\n\t\treturn 1;\n\t}\n\tDUK_ASSERT_HBUFOBJ_VALID(h_this);\n\n\t/* Ignore encoding for now. */\n\n\tduk__clamp_startend_nonegidx_noshift(thr,\n\t                                     (duk_int_t) h_this->length,\n\t                                     1 /*idx_start*/,\n\t                                     2 /*idx_end*/,\n\t                                     &start_offset,\n\t                                     &end_offset);\n\n\tslice_length = (duk_size_t) (end_offset - start_offset);\n\tbuf_slice = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, slice_length);  /* all bytes initialized below */\n\tDUK_ASSERT(buf_slice != NULL);\n\n\t/* Neutered or uncovered, TypeError. */\n\tif (h_this->buf == NULL ||\n\t    !DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h_this, (duk_size_t) start_offset + slice_length)) {\n\t\tDUK_DCERROR_TYPE_INVALID_ARGS(thr);\n\t}\n\n\t/* XXX: ideally we wouldn't make a copy but a view into the buffer for the\n\t * decoding process.  Or the decoding helper could be changed to accept\n\t * the slice info (a buffer pointer is NOT a good approach because guaranteeing\n\t * its stability is difficult).\n\t */\n\n\tDUK_ASSERT(DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h_this, (duk_size_t) start_offset + slice_length));\n\tDUK_MEMCPY((void *) buf_slice,\n\t           (const void *) (DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this) + start_offset),\n\t           (size_t) slice_length);\n\n\t/* Use the equivalent of: new TextEncoder().encode(this) to convert the\n\t * string.  Result will be valid UTF-8; non-CESU-8 inputs are currently\n\t * interpreted loosely.  Value stack convention is a bit odd for now.\n\t */\n\tduk_replace(thr, 0);\n\tduk_set_top(thr, 1);\n\treturn duk_textdecoder_decode_utf8_nodejs(thr);\n}\n#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */\n\n/*\n *  Node.js Buffer.prototype: toJSON()\n */\n\n#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)\nDUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_tojson(duk_hthread *thr) {\n\tduk_hbufobj *h_this;\n\tduk_uint8_t *buf;\n\tduk_uint_t i, n;\n\tduk_tval *tv;\n\n\th_this = duk__require_bufobj_this(thr);\n\tDUK_ASSERT(h_this != NULL);\n\n\tif (h_this->buf == NULL || !DUK_HBUFOBJ_VALID_SLICE(h_this)) {\n\t\t/* Serialize uncovered backing buffer as a null; doesn't\n\t\t * really matter as long we're memory safe.\n\t\t */\n\t\tduk_push_null(thr);\n\t\treturn 1;\n\t}\n\n\tduk_push_object(thr);\n\tduk_push_hstring_stridx(thr, DUK_STRIDX_UC_BUFFER);\n\tduk_put_prop_stridx_short(thr, -2, DUK_STRIDX_TYPE);\n\n\t/* XXX: uninitialized would be OK */\n\tDUK_ASSERT_DISABLE((duk_size_t) h_this->length <= (duk_size_t) DUK_UINT32_MAX);\n\ttv = duk_push_harray_with_size_outptr(thr, (duk_uint32_t) h_this->length);  /* XXX: needs revision with >4G buffers */\n\n\tDUK_ASSERT(h_this->buf != NULL);\n\tbuf = DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this);\n\tfor (i = 0, n = h_this->length; i < n; i++) {\n\t\tDUK_TVAL_SET_U32(tv + i, (duk_uint32_t) buf[i]);  /* no need for decref or incref */\n\t}\n\tduk_put_prop_stridx_short(thr, -2, DUK_STRIDX_DATA);\n\n\treturn 1;\n}\n#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */\n\n/*\n *  Node.js Buffer.prototype.equals()\n *  Node.js Buffer.prototype.compare()\n *  Node.js Buffer.compare()\n */\n\n#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)\nDUK_INTERNAL duk_ret_t duk_bi_buffer_compare_shared(duk_hthread *thr) {\n\tduk_small_uint_t magic;\n\tduk_hbufobj *h_bufarg1;\n\tduk_hbufobj *h_bufarg2;\n\tduk_small_int_t comp_res;\n\n\t/* XXX: keep support for plain buffers and non-Node.js buffers? */\n\n\tmagic = (duk_small_uint_t) duk_get_current_magic(thr);\n\tif (magic & 0x02U) {\n\t\t/* Static call style. */\n\t\th_bufarg1 = duk__require_bufobj_value(thr, 0);\n\t\th_bufarg2 = duk__require_bufobj_value(thr, 1);\n\t} else {\n\t\th_bufarg1 = duk__require_bufobj_this(thr);\n\t\th_bufarg2 = duk__require_bufobj_value(thr, 0);\n\t}\n\tDUK_ASSERT(h_bufarg1 != NULL);\n\tDUK_ASSERT(h_bufarg2 != NULL);\n\n\t/* We want to compare the slice/view areas of the arguments.\n\t * If either slice/view is invalid (underlying buffer is shorter)\n\t * ensure equals() is false, but otherwise the only thing that\n\t * matters is to be memory safe.\n\t */\n\n\tif (DUK_HBUFOBJ_VALID_SLICE(h_bufarg1) &&\n\t    DUK_HBUFOBJ_VALID_SLICE(h_bufarg2)) {\n\t\tcomp_res = duk_js_data_compare((const duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufarg1->buf) + h_bufarg1->offset,\n\t\t                               (const duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufarg2->buf) + h_bufarg2->offset,\n\t\t                               (duk_size_t) h_bufarg1->length,\n\t\t                               (duk_size_t) h_bufarg2->length);\n\t} else {\n\t\tcomp_res = -1;  /* either nonzero value is ok */\n\t}\n\n\tif (magic & 0x01U) {\n\t\t/* compare: similar to string comparison but for buffer data. */\n\t\tduk_push_int(thr, comp_res);\n\t} else {\n\t\t/* equals */\n\t\tduk_push_boolean(thr, (comp_res == 0));\n\t}\n\n\treturn 1;\n}\n#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */\n\n/*\n *  Node.js Buffer.prototype.fill()\n */\n\n#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)\nDUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_fill(duk_hthread *thr) {\n\tduk_hbufobj *h_this;\n\tconst duk_uint8_t *fill_str_ptr;\n\tduk_size_t fill_str_len;\n\tduk_uint8_t fill_value;\n\tduk_int_t fill_offset;\n\tduk_int_t fill_end;\n\tduk_size_t fill_length;\n\tduk_uint8_t *p;\n\n\th_this = duk__require_bufobj_this(thr);\n\tDUK_ASSERT(h_this != NULL);\n\tif (h_this->buf == NULL) {\n\t\tDUK_DCERROR_TYPE_INVALID_ARGS(thr);\n\t}\n\n\t/* [ value offset end ] */\n\n\tif (duk_is_string_notsymbol(thr, 0)) {\n\t\tfill_str_ptr = (const duk_uint8_t *) duk_get_lstring(thr, 0, &fill_str_len);\n\t\tDUK_ASSERT(fill_str_ptr != NULL);\n\t} else {\n\t\t/* Symbols get ToNumber() coerced and cause TypeError. */\n\t\tfill_value = (duk_uint8_t) duk_to_uint32(thr, 0);\n\t\tfill_str_ptr = (const duk_uint8_t *) &fill_value;\n\t\tfill_str_len = 1;\n\t}\n\n\t/* Fill offset handling is more lenient than in Node.js. */\n\n\tduk__clamp_startend_nonegidx_noshift(thr,\n\t                                     (duk_int_t) h_this->length,\n\t                                     1 /*idx_start*/,\n\t                                     2 /*idx_end*/,\n\t                                     &fill_offset,\n\t                                     &fill_end);\n\n\tDUK_DDD(DUK_DDDPRINT(\"fill: fill_value=%02x, fill_offset=%ld, fill_end=%ld, view length=%ld\",\n\t                     (unsigned int) fill_value, (long) fill_offset, (long) fill_end, (long) h_this->length));\n\n\tDUK_ASSERT(fill_end - fill_offset >= 0);\n\tDUK_ASSERT(h_this->buf != NULL);\n\n\tp = (DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this) + fill_offset);\n\tfill_length = (duk_size_t) (fill_end - fill_offset);\n\tif (fill_str_len == 1) {\n\t\t/* Handle single character fills as memset() even when\n\t\t * the fill data comes from a one-char argument.\n\t\t */\n\t\tDUK_MEMSET((void *) p, (int) fill_str_ptr[0], (size_t) fill_length);\n\t} else if (fill_str_len > 1) {\n\t\tduk_size_t i, n, t;\n\n\t\tfor (i = 0, n = (duk_size_t) (fill_end - fill_offset), t = 0; i < n; i++) {\n\t\t\tp[i] = fill_str_ptr[t++];\n\t\t\tif (t >= fill_str_len) {\n\t\t\t\tt = 0;\n\t\t\t}\n\t\t}\n\t} else {\n\t\tDUK_DDD(DUK_DDDPRINT(\"zero size fill pattern, ignore silently\"));\n\t}\n\n\t/* Return the Buffer to allow chaining: b.fill(0x11).fill(0x22, 3, 5).toString() */\n\tduk_push_this(thr);\n\treturn 1;\n}\n#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */\n\n/*\n *  Node.js Buffer.prototype.write(string, [offset], [length], [encoding])\n */\n\n#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)\nDUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_write(duk_hthread *thr) {\n\tduk_hbufobj *h_this;\n\tduk_uint_t offset;\n\tduk_uint_t length;\n\tconst duk_uint8_t *str_data;\n\tduk_size_t str_len;\n\n\t/* XXX: very inefficient support for plain buffers */\n\th_this = duk__require_bufobj_this(thr);\n\tDUK_ASSERT(h_this != NULL);\n\n\t/* Argument must be a string, e.g. a buffer is not allowed. */\n\tstr_data = (const duk_uint8_t *) duk_require_lstring_notsymbol(thr, 0, &str_len);\n\n\tduk__resolve_offset_opt_length(thr, h_this, 1, 2, &offset, &length, 0 /*throw_flag*/);\n\tDUK_ASSERT(offset <= h_this->length);\n\tDUK_ASSERT(offset + length <= h_this->length);\n\n\t/* XXX: encoding is ignored now. */\n\n\tif (length > str_len) {\n\t\tlength = (duk_uint_t) str_len;\n\t}\n\n\tif (DUK_HBUFOBJ_VALID_SLICE(h_this)) {\n\t\t/* Cannot overlap. */\n\t\tDUK_MEMCPY((void *) (DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this) + offset),\n\t\t           (const void *) str_data,\n\t\t           (size_t) length);\n\t} else {\n\t\tDUK_DDD(DUK_DDDPRINT(\"write() target buffer is not covered, silent ignore\"));\n\t}\n\n\tduk_push_uint(thr, length);\n\treturn 1;\n}\n#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */\n\n/*\n *  Node.js Buffer.prototype.copy()\n */\n\n#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)\nDUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_copy(duk_hthread *thr) {\n\tduk_hbufobj *h_this;\n\tduk_hbufobj *h_bufarg;\n\tduk_int_t source_length;\n\tduk_int_t target_length;\n\tduk_int_t target_start, source_start, source_end;\n\tduk_uint_t target_ustart, source_ustart, source_uend;\n\tduk_uint_t copy_size = 0;\n\n\t/* [ targetBuffer targetStart sourceStart sourceEnd ] */\n\n\th_this = duk__require_bufobj_this(thr);\n\th_bufarg = duk__require_bufobj_value(thr, 0);\n\tDUK_ASSERT(h_this != NULL);\n\tDUK_ASSERT(h_bufarg != NULL);\n\tsource_length = (duk_int_t) h_this->length;\n\ttarget_length = (duk_int_t) h_bufarg->length;\n\n\ttarget_start = duk_to_int(thr, 1);\n\tsource_start = duk_to_int(thr, 2);\n\tif (duk_is_undefined(thr, 3)) {\n\t\tsource_end = source_length;\n\t} else {\n\t\tsource_end = duk_to_int(thr, 3);\n\t}\n\n\tDUK_DDD(DUK_DDDPRINT(\"checking copy args: target_start=%ld, target_length=%ld, \"\n\t                     \"source_start=%ld, source_end=%ld, source_length=%ld\",\n\t                     (long) target_start, (long) h_bufarg->length,\n\t                     (long) source_start, (long) source_end, (long) source_length));\n\n\t/* This behavior mostly mimics Node.js now. */\n\n\tif (source_start < 0 || source_end < 0 || target_start < 0) {\n\t\t/* Negative offsets cause a RangeError. */\n\t\tgoto fail_bounds;\n\t}\n\tsource_ustart = (duk_uint_t) source_start;\n\tsource_uend = (duk_uint_t) source_end;\n\ttarget_ustart = (duk_uint_t) target_start;\n\tif (source_ustart >= source_uend ||  /* crossed offsets or zero size */\n\t    source_ustart >= (duk_uint_t) source_length ||  /* source out-of-bounds (but positive) */\n\t    target_ustart >= (duk_uint_t) target_length) {  /* target out-of-bounds (but positive) */\n\t\tgoto silent_ignore;\n\t}\n\tif (source_uend >= (duk_uint_t) source_length) {\n\t\t/* Source end clamped silently to available length. */\n\t\tsource_uend = (duk_uint_t) source_length;\n\t}\n\tcopy_size = source_uend - source_ustart;\n\tif (target_ustart + copy_size > (duk_uint_t) target_length) {\n\t\t/* Clamp to target's end if too long.\n\t\t *\n\t\t * NOTE: there's no overflow possibility in the comparison;\n\t\t * both target_ustart and copy_size are >= 0 and based on\n\t\t * values in duk_int_t range.  Adding them as duk_uint_t\n\t\t * values is then guaranteed not to overflow.\n\t\t */\n\t\tDUK_ASSERT(target_ustart + copy_size >= target_ustart);  /* no overflow */\n\t\tDUK_ASSERT(target_ustart + copy_size >= copy_size);  /* no overflow */\n\t\tcopy_size = (duk_uint_t) target_length - target_ustart;\n\t}\n\n\tDUK_DDD(DUK_DDDPRINT(\"making copy: target_ustart=%lu source_ustart=%lu copy_size=%lu\",\n\t                     (unsigned long) target_ustart, (unsigned long) source_ustart,\n\t                     (unsigned long) copy_size));\n\n\tDUK_ASSERT(copy_size >= 1);\n\tDUK_ASSERT(source_ustart <= (duk_uint_t) source_length);\n\tDUK_ASSERT(source_ustart + copy_size <= (duk_uint_t) source_length);\n\tDUK_ASSERT(target_ustart <= (duk_uint_t) target_length);\n\tDUK_ASSERT(target_ustart + copy_size <= (duk_uint_t) target_length);\n\n\t/* Ensure copy is covered by underlying buffers. */\n\tDUK_ASSERT(h_bufarg->buf != NULL);  /* length check */\n\tDUK_ASSERT(h_this->buf != NULL);    /* length check */\n\tif (DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h_bufarg, target_ustart + copy_size) &&\n\t    DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h_this, source_ustart + copy_size)) {\n\t\t/* Must use memmove() because copy area may overlap (source and target\n\t\t * buffer may be the same, or from different slices.\n\t\t */\n\t\tDUK_MEMMOVE((void *) (DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_bufarg) + target_ustart),\n\t\t            (const void *) (DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this) + source_ustart),\n\t\t            (size_t) copy_size);\n\t} else {\n\t\tDUK_DDD(DUK_DDDPRINT(\"buffer copy not covered by underlying buffer(s), ignoring\"));\n\t}\n\n silent_ignore:\n\t/* Return value is like write(), number of bytes written.\n\t * The return value matters because of code like:\n\t * \"off += buf.copy(...)\".\n         */\n\tduk_push_uint(thr, copy_size);\n\treturn 1;\n\n fail_bounds:\n\tDUK_DCERROR_RANGE_INVALID_ARGS(thr);\n}\n#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */\n\n/*\n *  TypedArray.prototype.set()\n *\n *  TypedArray set() is pretty interesting to implement because:\n *\n *    - The source argument may be a plain array or a typedarray.  If the\n *      source is a TypedArray, values are decoded and re-encoded into the\n *      target (not as a plain byte copy).  This may happen even when the\n *      element byte size is the same, e.g. integer values may be re-encoded\n *      into floats.\n *\n *    - Source and target may refer to the same underlying buffer, so that\n *      the set() operation may overlap.  The specification requires that this\n *      must work as if a copy was made before the operation.  Note that this\n *      is NOT a simple memmove() situation because the source and target\n *      byte sizes may be different -- e.g. a 4-byte source (Int8Array) may\n *      expand to a 16-byte target (Uint32Array) so that the target overlaps\n *      the source both from beginning and the end (unlike in typical memmove).\n *\n *    - Even if 'buf' pointers of the source and target differ, there's no\n *      guarantee that their memory areas don't overlap.  This may be the\n *      case with external buffers.\n *\n *  Even so, it is nice to optimize for the common case:\n *\n *    - Source and target separate buffers or non-overlapping.\n *\n *    - Source and target have a compatible type so that a plain byte copy\n *      is possible.  Note that while e.g. uint8 and int8 are compatible\n *      (coercion one way or another doesn't change the byte representation),\n *      e.g. int8 and uint8clamped are NOT compatible when writing int8\n *      values into uint8clamped typedarray (-1 would clamp to 0 for instance).\n *\n *  See test-bi-typedarray-proto-set.js.\n */\n\n#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)\nDUK_INTERNAL duk_ret_t duk_bi_typedarray_set(duk_hthread *thr) {\n\tduk_hbufobj *h_this;\n\tduk_hobject *h_obj;\n\tduk_uarridx_t i, n;\n\tduk_int_t offset_signed;\n\tduk_uint_t offset_elems;\n\tduk_uint_t offset_bytes;\n\n\th_this = duk__require_bufobj_this(thr);\n\tDUK_ASSERT(h_this != NULL);\n\tDUK_ASSERT_HBUFOBJ_VALID(h_this);\n\n\tif (h_this->buf == NULL) {\n\t\tDUK_DDD(DUK_DDDPRINT(\"source neutered, skip copy\"));\n\t\treturn 0;\n\t}\n\n\tduk_hbufobj_promote_plain(thr, 0);\n\th_obj = duk_require_hobject(thr, 0);\n\n\t/* XXX: V8 throws a TypeError for negative values.  Would it\n\t * be more useful to interpret negative offsets here from the\n\t * end of the buffer too?\n\t */\n\toffset_signed = duk_to_int(thr, 1);\n\tif (offset_signed < 0) {\n\t\t/* For some reason this is a TypeError (at least in V8). */\n\t\tDUK_DCERROR_TYPE_INVALID_ARGS(thr);\n\t}\n\toffset_elems = (duk_uint_t) offset_signed;\n\toffset_bytes = offset_elems << h_this->shift;\n\tif ((offset_bytes >> h_this->shift) != offset_elems) {\n\t\t/* Byte length would overflow. */\n\t\t/* XXX: easier check with less code? */\n\t\tgoto fail_args;\n\t}\n\tif (offset_bytes > h_this->length) {\n\t\t/* Equality may be OK but >length not.  Checking\n\t\t * this explicitly avoids some overflow cases\n\t\t * below.\n\t\t */\n\t\tgoto fail_args;\n\t}\n\tDUK_ASSERT(offset_bytes <= h_this->length);\n\n\t/* Fast path: source is a TypedArray (or any bufobj). */\n\n\tif (DUK_HOBJECT_IS_BUFOBJ(h_obj)) {\n\t\tduk_hbufobj *h_bufarg;\n#if !defined(DUK_USE_PREFER_SIZE)\n\t\tduk_uint16_t comp_mask;\n#endif\n\t\tduk_small_int_t no_overlap = 0;\n\t\tduk_uint_t src_length;\n\t\tduk_uint_t dst_length;\n\t\tduk_uint_t dst_length_elems;\n\t\tduk_uint8_t *p_src_base;\n\t\tduk_uint8_t *p_src_end;\n\t\tduk_uint8_t *p_src;\n\t\tduk_uint8_t *p_dst_base;\n\t\tduk_uint8_t *p_dst;\n\t\tduk_small_uint_t src_elem_size;\n\t\tduk_small_uint_t dst_elem_size;\n\n\t\th_bufarg = (duk_hbufobj *) h_obj;\n\t\tDUK_ASSERT_HBUFOBJ_VALID(h_bufarg);\n\n\t\tif (h_bufarg->buf == NULL) {\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"target neutered, skip copy\"));\n\t\t\treturn 0;\n\t\t}\n\n\t\t/* Nominal size check. */\n\t\tsrc_length = h_bufarg->length;  /* bytes in source */\n\t\tdst_length_elems = (src_length >> h_bufarg->shift);  /* elems in source and dest */\n\t\tdst_length = dst_length_elems << h_this->shift;  /* bytes in dest */\n\t\tif ((dst_length >> h_this->shift) != dst_length_elems) {\n\t\t\t/* Byte length would overflow. */\n\t\t\t/* XXX: easier check with less code? */\n\t\t\tgoto fail_args;\n\t\t}\n\t\tDUK_DDD(DUK_DDDPRINT(\"nominal size check: src_length=%ld, dst_length=%ld\",\n\t\t                     (long) src_length, (long) dst_length));\n\t\tDUK_ASSERT(offset_bytes <= h_this->length);\n\t\tif (dst_length > h_this->length - offset_bytes) {\n\t\t\t/* Overflow not an issue because subtraction is used on the right\n\t\t\t * side and guaranteed to be >= 0.\n\t\t\t */\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"copy exceeds target buffer nominal length\"));\n\t\t\tgoto fail_args;\n\t\t}\n\t\tif (!DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h_this, offset_bytes + dst_length)) {\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"copy not covered by underlying target buffer, ignore\"));\n\t\t\treturn 0;\n\t\t}\n\n\t\tp_src_base = DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_bufarg);\n\t\tp_dst_base = DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this) + offset_bytes;\n\n\t\t/* Check actual underlying buffers for validity and that they\n\t\t * cover the copy.  No side effects are allowed after the check\n\t\t * so that the validity status doesn't change.\n\t\t */\n\t\tif (!DUK_HBUFOBJ_VALID_SLICE(h_this) ||\n\t\t    !DUK_HBUFOBJ_VALID_SLICE(h_bufarg)) {\n\t\t\t/* The condition could be more narrow and check for the\n\t\t\t * copy area only, but there's no need for fine grained\n\t\t\t * behavior when the underlying buffer is misconfigured.\n\t\t\t */\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"source and/or target not covered by underlying buffer, skip copy\"));\n\t\t\treturn 0;\n\t\t}\n\n\t\t/* We want to do a straight memory copy if possible: this is\n\t\t * an important operation because .set() is the TypedArray\n\t\t * way to copy chunks of memory.  However, because set()\n\t\t * conceptually works in terms of elements, not all views are\n\t\t * compatible with direct byte copying.\n\t\t *\n\t\t * If we do manage a direct copy, the \"overlap issue\" handled\n\t\t * below can just be solved using memmove() because the source\n\t\t * and destination element sizes are necessarily equal.\n\t\t */\n\n#if !defined(DUK_USE_PREFER_SIZE)\n\t\tDUK_ASSERT(h_this->elem_type < sizeof(duk__buffer_elemtype_copy_compatible) / sizeof(duk_uint16_t));\n\t\tcomp_mask = duk__buffer_elemtype_copy_compatible[h_this->elem_type];\n\t\tif (comp_mask & (1 << h_bufarg->elem_type)) {\n\t\t\tDUK_ASSERT(src_length == dst_length);\n\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"fast path: able to use memmove() because views are compatible\"));\n\t\t\tDUK_MEMMOVE((void *) p_dst_base, (const void *) p_src_base, (size_t) dst_length);\n\t\t\treturn 0;\n\t\t}\n\t\tDUK_DDD(DUK_DDDPRINT(\"fast path: views are not compatible with a byte copy, copy by item\"));\n#endif  /* !DUK_USE_PREFER_SIZE */\n\n\t\t/* We want to avoid making a copy to process set() but that's\n\t\t * not always possible: the source and the target may overlap\n\t\t * and because element sizes are different, the overlap cannot\n\t\t * always be handled with a memmove() or choosing the copy\n\t\t * direction in a certain way.  For example, if source type is\n\t\t * uint8 and target type is uint32, the target area may exceed\n\t\t * the source area from both ends!\n\t\t *\n\t\t * Note that because external buffers may point to the same\n\t\t * memory areas, we must ultimately make this check using\n\t\t * pointers.\n\t\t *\n\t\t * NOTE: careful with side effects: any side effect may cause\n\t\t * a buffer resize (or external buffer pointer/length update)!\n\t\t */\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"overlap check: p_src_base=%p, src_length=%ld, \"\n\t\t                     \"p_dst_base=%p, dst_length=%ld\",\n\t\t                     (void *) p_src_base, (long) src_length,\n\t\t                     (void *) p_dst_base, (long) dst_length));\n\n\t\tif (p_src_base >= p_dst_base + dst_length ||  /* source starts after dest ends */\n\t\t    p_src_base + src_length <= p_dst_base) {   /* source ends before dest starts */\n\t\t\tno_overlap = 1;\n\t\t}\n\n\t\tif (!no_overlap) {\n\t\t\t/* There's overlap: the desired end result is that\n\t\t\t * conceptually a copy is made to avoid \"trampling\"\n\t\t\t * of source data by destination writes.  We make\n\t\t\t * an actual temporary copy to handle this case.\n\t\t\t */\n\t\t\tduk_uint8_t *p_src_copy;\n\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"there is overlap, make a copy of the source\"));\n\t\t\tp_src_copy = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, src_length);\n\t\t\tDUK_ASSERT(p_src_copy != NULL);\n\t\t\tDUK_MEMCPY((void *) p_src_copy, (const void *) p_src_base, (size_t) src_length);\n\n\t\t\tp_src_base = p_src_copy;  /* use p_src_base from now on */\n\t\t}\n\t\t/* Value stack intentionally mixed size here. */\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"after overlap check: p_src_base=%p, src_length=%ld, \"\n\t\t                     \"p_dst_base=%p, dst_length=%ld, valstack top=%ld\",\n\t\t                     (void *) p_src_base, (long) src_length,\n\t\t                     (void *) p_dst_base, (long) dst_length,\n\t\t                     (long) duk_get_top(thr)));\n\n\t\t/* Ready to make the copy.  We must proceed element by element\n\t\t * and must avoid any side effects that might cause the buffer\n\t\t * validity check above to become invalid.\n\t\t *\n\t\t * Although we work through the value stack here, only plain\n\t\t * numbers are handled which should be side effect safe.\n\t\t */\n\n\t\tsrc_elem_size = (duk_small_uint_t) (1U << h_bufarg->shift);\n\t\tdst_elem_size = (duk_small_uint_t) (1U << h_this->shift);\n\t\tp_src = p_src_base;\n\t\tp_dst = p_dst_base;\n\t\tp_src_end = p_src_base + src_length;\n\n\t\twhile (p_src != p_src_end) {\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"fast path per element copy loop: \"\n\t\t\t                     \"p_src=%p, p_src_end=%p, p_dst=%p\",\n\t\t\t                     (void *) p_src, (void *) p_src_end, (void *) p_dst));\n\t\t\t/* A validated read() is always a number, so it's write coercion\n\t\t\t * is always side effect free an won't invalidate pointers etc.\n\t\t\t */\n\t\t\tduk_hbufobj_push_validated_read(thr, h_bufarg, p_src, src_elem_size);\n\t\t\tduk_hbufobj_validated_write(thr, h_this, p_dst, dst_elem_size);\n\t\t\tduk_pop(thr);\n\t\t\tp_src += src_elem_size;\n\t\t\tp_dst += dst_elem_size;\n\t\t}\n\n\t\treturn 0;\n\t} else {\n\t\t/* Slow path: quite slow, but we save space by using the property code\n\t\t * to write coerce target values.  We don't need to worry about overlap\n\t\t * here because the source is not a TypedArray.\n\t\t *\n\t\t * We could use the bufobj write coercion helper but since the\n\t\t * property read may have arbitrary side effects, full validity checks\n\t\t * would be needed for every element anyway.\n\t\t */\n\n\t\tn = (duk_uarridx_t) duk_get_length(thr, 0);\n\t\tDUK_ASSERT(offset_bytes <= h_this->length);\n\t\tif ((n << h_this->shift) > h_this->length - offset_bytes) {\n\t\t\t/* Overflow not an issue because subtraction is used on the right\n\t\t\t * side and guaranteed to be >= 0.\n\t\t\t */\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"copy exceeds target buffer nominal length\"));\n\t\t\tgoto fail_args;\n\t\t}\n\n\t\t/* There's no need to check for buffer validity status for the\n\t\t * target here: the property access code will do that for each\n\t\t * element.  Moreover, if we did check the validity here, side\n\t\t * effects from reading the source argument might invalidate\n\t\t * the results anyway.\n\t\t */\n\n\t\tDUK_ASSERT_TOP(thr, 2);\n\t\tduk_push_this(thr);\n\n\t\tfor (i = 0; i < n; i++) {\n\t\t\tduk_get_prop_index(thr, 0, i);\n\t\t\tduk_put_prop_index(thr, 2, offset_elems + i);\n\t\t}\n\t}\n\n\treturn 0;\n\n fail_args:\n\tDUK_DCERROR_RANGE_INVALID_ARGS(thr);\n}\n#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */\n\n/*\n *  Node.js Buffer.prototype.slice([start], [end])\n *  ArrayBuffer.prototype.slice(begin, [end])\n *  TypedArray.prototype.subarray(begin, [end])\n *\n *  The API calls are almost identical; negative indices are counted from end\n *  of buffer, and final indices are clamped (allowing crossed indices).  Main\n *  differences:\n *\n *    - Copy/view behavior; Node.js .slice() and TypedArray .subarray() create\n *      views, ArrayBuffer .slice() creates a copy\n *\n *    - Resulting object has a different class and prototype depending on the\n *      call (or 'this' argument)\n *\n *    - TypedArray .subarray() arguments are element indices, not byte offsets\n *\n *    - Plain buffer argument creates a plain buffer slice\n */\n\n#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)\nDUK_LOCAL void duk__arraybuffer_plain_slice(duk_hthread *thr, duk_hbuffer *h_val) {\n\tduk_int_t start_offset, end_offset;\n\tduk_uint_t slice_length;\n\tduk_uint8_t *p_copy;\n\tduk_size_t copy_length;\n\n\tduk__clamp_startend_negidx_shifted(thr,\n\t                                   (duk_int_t) DUK_HBUFFER_GET_SIZE(h_val),\n\t                                   0 /*buffer_shift*/,\n\t                                   0 /*idx_start*/,\n\t                                   1 /*idx_end*/,\n\t                                   &start_offset,\n\t                                   &end_offset);\n\tDUK_ASSERT(end_offset <= (duk_int_t) DUK_HBUFFER_GET_SIZE(h_val));\n\tDUK_ASSERT(start_offset >= 0);\n\tDUK_ASSERT(end_offset >= start_offset);\n\tslice_length = (duk_uint_t) (end_offset - start_offset);\n\n\tp_copy = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, (duk_size_t) slice_length);\n\tDUK_ASSERT(p_copy != NULL);\n\tcopy_length = slice_length;\n\n\tDUK_MEMCPY((void *) p_copy,\n\t           (const void *) ((duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_val) + start_offset),\n\t           copy_length);\n}\n#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */\n\n#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)\n/* Shared helper for slice/subarray operation.\n * Magic: 0x01=isView, 0x02=copy, 0x04=Node.js Buffer special handling.\n */\nDUK_INTERNAL duk_ret_t duk_bi_buffer_slice_shared(duk_hthread *thr) {\n\tduk_small_int_t magic;\n\tduk_small_uint_t res_class_num;\n\tduk_small_int_t res_proto_bidx;\n\tduk_hbufobj *h_this;\n\tduk_hbufobj *h_bufobj;\n\tduk_hbuffer *h_val;\n\tduk_int_t start_offset, end_offset;\n\tduk_uint_t slice_length;\n\tduk_tval *tv;\n\n\t/* [ start end ] */\n\n\tmagic = duk_get_current_magic(thr);\n\n\ttv = duk_get_borrowed_this_tval(thr);\n\tDUK_ASSERT(tv != NULL);\n\n\tif (DUK_TVAL_IS_BUFFER(tv)) {\n\t\t/* For plain buffers return a plain buffer slice. */\n\t\th_val = DUK_TVAL_GET_BUFFER(tv);\n\t\tDUK_ASSERT(h_val != NULL);\n\n\t\tif (magic & 0x02) {\n\t\t\t/* Make copy: ArrayBuffer.prototype.slice() uses this. */\n\t\t\tduk__arraybuffer_plain_slice(thr, h_val);\n\t\t\treturn 1;\n\t\t} else {\n\t\t\t/* View into existing buffer: cannot be done if the\n\t\t\t * result is a plain buffer because there's no slice\n\t\t\t * info.  So return an ArrayBuffer instance; coerce\n\t\t\t * the 'this' binding into an object and behave as if\n\t\t\t * the original call was for an Object-coerced plain\n\t\t\t * buffer (handled automatically by duk__require_bufobj_this()).\n\t\t\t */\n\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"slice() doesn't handle view into plain buffer, coerce 'this' to ArrayBuffer object\"));\n\t\t\t/* fall through */\n\t\t}\n\t}\n\ttv = NULL;  /* No longer valid nor needed. */\n\n\th_this = duk__require_bufobj_this(thr);\n\n\t/* Slice offsets are element (not byte) offsets, which only matters\n\t * for TypedArray views, Node.js Buffer and ArrayBuffer have shift\n\t * zero so byte and element offsets are the same.  Negative indices\n\t * are counted from end of slice, crossed indices are allowed (and\n\t * result in zero length result), and final values are clamped\n\t * against the current slice.  There's intentionally no check\n\t * against the underlying buffer here.\n\t */\n\n\tduk__clamp_startend_negidx_shifted(thr,\n\t                                   (duk_int_t) h_this->length,\n\t                                   (duk_uint8_t) h_this->shift,\n\t                                   0 /*idx_start*/,\n\t                                   1 /*idx_end*/,\n\t                                   &start_offset,\n\t                                   &end_offset);\n\tDUK_ASSERT(end_offset >= start_offset);\n\tDUK_ASSERT(start_offset >= 0);\n\tDUK_ASSERT(end_offset >= 0);\n\tslice_length = (duk_uint_t) (end_offset - start_offset);\n\n\t/* The resulting buffer object gets the same class and prototype as\n\t * the buffer in 'this', e.g. if the input is a Uint8Array the\n\t * result is a Uint8Array; if the input is a Float32Array, the\n\t * result is a Float32Array.  The result internal prototype should\n\t * be the default prototype for the class (e.g. initial value of\n\t * Uint8Array.prototype), not copied from the argument (Duktape 1.x\n\t * did that).\n\t *\n\t * Node.js Buffers have special handling: they're Uint8Arrays as far\n\t * as the internal class is concerned, so the new Buffer should also\n\t * be an Uint8Array but inherit from Buffer.prototype.\n\t */\n\tres_class_num = DUK_HOBJECT_GET_CLASS_NUMBER((duk_hobject *) h_this);\n\tDUK_ASSERT(res_class_num >= DUK_HOBJECT_CLASS_BUFOBJ_MIN);  /* type check guarantees */\n\tDUK_ASSERT(res_class_num <= DUK_HOBJECT_CLASS_BUFOBJ_MAX);\n\tres_proto_bidx = duk__buffer_proto_from_classnum[res_class_num - DUK_HOBJECT_CLASS_BUFOBJ_MIN];\n\tif (magic & 0x04) {\n\t\tres_proto_bidx = DUK_BIDX_NODEJS_BUFFER_PROTOTYPE;\n\t}\n\th_bufobj = duk_push_bufobj_raw(thr,\n\t                               DUK_HOBJECT_FLAG_EXTENSIBLE |\n\t                               DUK_HOBJECT_FLAG_BUFOBJ |\n\t                               DUK_HOBJECT_CLASS_AS_FLAGS(res_class_num),\n\t                               res_proto_bidx);\n\tDUK_ASSERT(h_bufobj != NULL);\n\n\tDUK_ASSERT(h_bufobj->length == 0);\n\th_bufobj->shift = h_this->shift;  /* inherit */\n\th_bufobj->elem_type = h_this->elem_type;  /* inherit */\n\th_bufobj->is_typedarray = magic & 0x01;\n\tDUK_ASSERT(h_bufobj->is_typedarray == 0 || h_bufobj->is_typedarray == 1);\n\n\th_val = h_this->buf;\n\tif (h_val == NULL) {\n\t\tDUK_DCERROR_TYPE_INVALID_ARGS(thr);\n\t}\n\n\tif (magic & 0x02) {\n\t\t/* non-zero: make copy */\n\t\tduk_uint8_t *p_copy;\n\t\tduk_size_t copy_length;\n\n\t\tp_copy = (duk_uint8_t *) duk_push_fixed_buffer_zero(thr, (duk_size_t) slice_length);  /* must be zeroed, not all bytes always copied */\n\t\tDUK_ASSERT(p_copy != NULL);\n\n\t\t/* Copy slice, respecting underlying buffer limits; remainder\n\t\t * is left as zero.\n\t\t */\n\t\tcopy_length = DUK_HBUFOBJ_CLAMP_BYTELENGTH(h_this, slice_length);\n\t\tDUK_MEMCPY((void *) p_copy,\n\t\t           (const void *) (DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this) + start_offset),\n\t\t           copy_length);\n\n\t\th_val = duk_known_hbuffer(thr, -1);\n\n\t\th_bufobj->buf = h_val;\n\t\tDUK_HBUFFER_INCREF(thr, h_val);\n\t\th_bufobj->length = slice_length;\n\t\tDUK_ASSERT(h_bufobj->offset == 0);\n\n\t\tduk_pop(thr);  /* reachable so pop OK */\n\t} else {\n\t\th_bufobj->buf = h_val;\n\t\tDUK_HBUFFER_INCREF(thr, h_val);\n\t\th_bufobj->length = slice_length;\n\t\th_bufobj->offset = h_this->offset + (duk_uint_t) start_offset;\n\n\t\t/* Copy the .buffer property, needed for TypedArray.prototype.subarray().\n\t\t *\n\t\t * XXX: limit copy only for TypedArray classes specifically?\n\t\t */\n\n\t\tDUK_ASSERT(h_bufobj->buf_prop == NULL);\n\t\th_bufobj->buf_prop = h_this->buf_prop;  /* may be NULL */\n\t\tDUK_HOBJECT_INCREF_ALLOWNULL(thr, (duk_hobject *) h_bufobj->buf_prop);\n\t}\n\t/* unbalanced stack on purpose */\n\n\tDUK_ASSERT_HBUFOBJ_VALID(h_bufobj);\n\treturn 1;\n}\n#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */\n\n/*\n *  Node.js Buffer.isEncoding()\n */\n\n#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)\nDUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_is_encoding(duk_hthread *thr) {\n\tconst char *encoding;\n\n\t/* only accept lowercase 'utf8' now. */\n\n\tencoding = duk_to_string(thr, 0);\n\tDUK_ASSERT(duk_is_string(thr, 0));  /* guaranteed by duk_to_string() */\n\tduk_push_boolean(thr, DUK_STRCMP(encoding, \"utf8\") == 0);\n\treturn 1;\n}\n#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */\n\n/*\n *  Node.js Buffer.isBuffer()\n */\n\n#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)\nDUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_is_buffer(duk_hthread *thr) {\n\tduk_hobject *h;\n\tduk_hobject *h_proto;\n\tduk_bool_t ret = 0;\n\n\tDUK_ASSERT(duk_get_top(thr) >= 1);  /* nargs */\n\th = duk_get_hobject(thr, 0);\n\tif (h != NULL) {\n\t\th_proto = thr->builtins[DUK_BIDX_NODEJS_BUFFER_PROTOTYPE];\n\t\tDUK_ASSERT(h_proto != NULL);\n\n\t\th = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h);\n\t\tif (h != NULL) {\n\t\t\tret = duk_hobject_prototype_chain_contains(thr, h, h_proto, 0 /*ignore_loop*/);\n\t\t}\n\t}\n\n\tduk_push_boolean(thr, ret);\n\treturn 1;\n}\n#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */\n\n/*\n *  Node.js Buffer.byteLength()\n */\n\n#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)\nDUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_byte_length(duk_hthread *thr) {\n\tconst char *str;\n\tduk_size_t len;\n\n\t/* At the moment Buffer(<str>) will just use the string bytes as\n\t * is (ignoring encoding), so we return the string length here\n\t * unconditionally.\n\t */\n\n\t/* XXX: to be revised; Old Node.js behavior just coerces any buffer\n\t * values to string:\n\t * $ node\n\t * > Buffer.byteLength(new Uint32Array(10))\n\t * 20\n\t * > Buffer.byteLength(new Uint32Array(100))\n\t * 20\n\t * (The 20 comes from '[object Uint32Array]'.length\n\t */\n\n\tstr = duk_to_lstring(thr, 0, &len);\n\tDUK_UNREF(str);\n\tduk_push_size_t(thr, len);\n\treturn 1;\n}\n#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */\n\n/*\n *  Node.js Buffer.concat()\n */\n\n#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)\nDUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_concat(duk_hthread *thr) {\n\tduk_hobject *h_arg;\n\tduk_uint_t total_length;\n\tduk_hbufobj *h_bufobj;\n\tduk_hbufobj *h_bufres;\n\tduk_hbuffer *h_val;\n\tduk_uint_t i, n;\n\tduk_uint8_t *p;\n\tduk_size_t space_left;\n\tduk_size_t copy_size;\n\n\t/* Node.js accepts only actual Arrays. */\n\th_arg = duk_require_hobject(thr, 0);\n\tif (DUK_HOBJECT_GET_CLASS_NUMBER(h_arg) != DUK_HOBJECT_CLASS_ARRAY) {\n\t\tDUK_DCERROR_TYPE_INVALID_ARGS(thr);\n\t}\n\n\t/* Compute result length and validate argument buffers. */\n\tn = (duk_uint_t) duk_get_length(thr, 0);\n\ttotal_length = 0;\n\tfor (i = 0; i < n; i++) {\n\t\t/* Neutered checks not necessary here: neutered buffers have\n\t\t * zero 'length' so we'll effectively skip them.\n\t\t */\n\t\tDUK_ASSERT_TOP(thr, 2);  /* [ array totalLength ] */\n\t\tduk_get_prop_index(thr, 0, (duk_uarridx_t) i);  /* -> [ array totalLength buf ] */\n\t\th_bufobj = duk__require_bufobj_value(thr, 2);\n\t\tDUK_ASSERT(h_bufobj != NULL);\n\t\ttotal_length += h_bufobj->length;\n\t\tif (DUK_UNLIKELY(total_length < h_bufobj->length)) {\n\t\t\tDUK_DCERROR_RANGE_INVALID_ARGS(thr);  /* Wrapped. */\n\t\t}\n\t\tduk_pop(thr);\n\t}\n\t/* In Node.js v0.12.1 a 1-element array is special and won't create a\n\t * copy, this was fixed later so an explicit check no longer needed.\n\t */\n\n\t/* User totalLength overrides a computed length, but we'll check\n\t * every copy in the copy loop.  Note that duk_to_int() can\n\t * technically have arbitrary side effects so we need to recheck\n\t * the buffers in the copy loop.\n\t */\n\tif (!duk_is_undefined(thr, 1) && n > 0) {\n\t\t/* For n == 0, Node.js ignores totalLength argument and\n\t\t * returns a zero length buffer.\n\t\t */\n\t\tduk_int_t total_length_signed;\n\t\ttotal_length_signed = duk_to_int(thr, 1);\n\t\tif (total_length_signed < 0) {\n\t\t\tDUK_DCERROR_RANGE_INVALID_ARGS(thr);\n\t\t}\n\t\ttotal_length = (duk_uint_t) total_length_signed;\n\t}\n\n\th_bufres = duk_push_bufobj_raw(thr,\n\t                               DUK_HOBJECT_FLAG_EXTENSIBLE |\n\t                               DUK_HOBJECT_FLAG_BUFOBJ |\n\t                               DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_UINT8ARRAY),\n\t                               DUK_BIDX_NODEJS_BUFFER_PROTOTYPE);\n\tDUK_ASSERT(h_bufres != NULL);\n\n\tp = (duk_uint8_t *) duk_push_fixed_buffer_zero(thr, total_length);  /* must be zeroed, all bytes not necessarily written over */\n\tDUK_ASSERT(p != NULL);\n\tspace_left = (duk_size_t) total_length;\n\n\tfor (i = 0; i < n; i++) {\n\t\tDUK_ASSERT_TOP(thr, 4);  /* [ array totalLength bufres buf ] */\n\n\t\tduk_get_prop_index(thr, 0, (duk_uarridx_t) i);\n\t\th_bufobj = duk__require_bufobj_value(thr, 4);\n\t\tDUK_ASSERT(h_bufobj != NULL);\n\n\t\tcopy_size = h_bufobj->length;\n\t\tif (copy_size > space_left) {\n\t\t\tcopy_size = space_left;\n\t\t}\n\n\t\tif (h_bufobj->buf != NULL &&\n\t\t    DUK_HBUFOBJ_VALID_SLICE(h_bufobj)) {\n\t\t\tDUK_MEMCPY((void *) p,\n\t\t\t           (const void *) DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_bufobj),\n\t\t\t           copy_size);\n\t\t} else {\n\t\t\t/* Just skip, leaving zeroes in the result. */\n\t\t\t;\n\t\t}\n\t\tp += copy_size;\n\t\tspace_left -= copy_size;\n\n\t\tduk_pop(thr);\n\t}\n\n\th_val = duk_known_hbuffer(thr, -1);\n\n\tduk__set_bufobj_buffer(thr, h_bufres, h_val);\n\th_bufres->is_typedarray = 1;\n\tDUK_ASSERT_HBUFOBJ_VALID(h_bufres);\n\n\tduk_pop(thr);  /* pop plain buffer, now reachable through h_bufres */\n\n\treturn 1;  /* return h_bufres */\n}\n#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */\n\n/*\n *  Shared readfield and writefield methods\n *\n *  The readfield/writefield methods need support for endianness and field\n *  types.  All offsets are byte based so no offset shifting is needed.\n */\n\n#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)\n/* Format of magic, bits:\n *   0...1: field type; 0=uint8, 1=uint16, 2=uint32, 3=float, 4=double, 5=unused, 6=unused, 7=unused\n *       3: endianness: 0=little, 1=big\n *       4: signed: 1=yes, 0=no\n *       5: typedarray: 1=yes, 0=no\n */\n#define  DUK__FLD_8BIT         0\n#define  DUK__FLD_16BIT        1\n#define  DUK__FLD_32BIT        2\n#define  DUK__FLD_FLOAT        3\n#define  DUK__FLD_DOUBLE       4\n#define  DUK__FLD_VARINT       5\n#define  DUK__FLD_BIGENDIAN    (1 << 3)\n#define  DUK__FLD_SIGNED       (1 << 4)\n#define  DUK__FLD_TYPEDARRAY   (1 << 5)\n\n/* XXX: split into separate functions for each field type? */\nDUK_INTERNAL duk_ret_t duk_bi_buffer_readfield(duk_hthread *thr) {\n\tduk_small_int_t magic = (duk_small_int_t) duk_get_current_magic(thr);\n\tduk_small_int_t magic_ftype;\n\tduk_small_int_t magic_bigendian;\n\tduk_small_int_t magic_signed;\n\tduk_small_int_t magic_typedarray;\n\tduk_small_int_t endswap;\n\tduk_hbufobj *h_this;\n\tduk_bool_t no_assert;\n\tduk_int_t offset_signed;\n\tduk_uint_t offset;\n\tduk_uint_t buffer_length;\n\tduk_uint_t check_length;\n\tduk_uint8_t *buf;\n\tduk_double_union du;\n\n\tmagic_ftype = magic & 0x0007;\n\tmagic_bigendian = magic & 0x0008;\n\tmagic_signed = magic & 0x0010;\n\tmagic_typedarray = magic & 0x0020;\n\n\th_this = duk__require_bufobj_this(thr);  /* XXX: very inefficient for plain buffers */\n\tDUK_ASSERT(h_this != NULL);\n\tbuffer_length = h_this->length;\n\n\t/* [ offset noAssert                 ], when ftype != DUK__FLD_VARINT */\n\t/* [ offset fieldByteLength noAssert ], when ftype == DUK__FLD_VARINT */\n\t/* [ offset littleEndian             ], when DUK__FLD_TYPEDARRAY (regardless of ftype) */\n\n\t/* Handle TypedArray vs. Node.js Buffer arg differences */\n\tif (magic_typedarray) {\n\t\tno_assert = 0;\n#if defined(DUK_USE_INTEGER_LE)\n\t\tendswap = !duk_to_boolean(thr, 1);  /* 1=little endian */\n#else\n\t\tendswap = duk_to_boolean(thr, 1);  /* 1=little endian */\n#endif\n\t} else {\n\t\tno_assert = duk_to_boolean(thr, (magic_ftype == DUK__FLD_VARINT) ? 2 : 1);\n#if defined(DUK_USE_INTEGER_LE)\n\t\tendswap = magic_bigendian;\n#else\n\t\tendswap = !magic_bigendian;\n#endif\n\t}\n\n\t/* Offset is coerced first to signed integer range and then to unsigned.\n\t * This ensures we can add a small byte length (1-8) to the offset in\n\t * bound checks and not wrap.\n\t */\n\toffset_signed = duk_to_int(thr, 0);\n\toffset = (duk_uint_t) offset_signed;\n\tif (offset_signed < 0) {\n\t\tgoto fail_bounds;\n\t}\n\n\tDUK_DDD(DUK_DDDPRINT(\"readfield, buffer_length=%ld, offset=%ld, no_assert=%d, \"\n\t                     \"magic=%04x, magic_fieldtype=%d, magic_bigendian=%d, magic_signed=%d, \"\n\t                     \"endswap=%d\",\n\t                     (long) buffer_length, (long) offset, (int) no_assert,\n\t                     (unsigned int) magic, (int) magic_ftype, (int) (magic_bigendian >> 3),\n\t                     (int) (magic_signed >> 4), (int) endswap));\n\n\t/* Update 'buffer_length' to be the effective, safe limit which\n\t * takes into account the underlying buffer.  This value will be\n\t * potentially invalidated by any side effect.\n\t */\n\tcheck_length = DUK_HBUFOBJ_CLAMP_BYTELENGTH(h_this, buffer_length);\n\tDUK_DDD(DUK_DDDPRINT(\"buffer_length=%ld, check_length=%ld\",\n\t                     (long) buffer_length, (long) check_length));\n\n\tif (h_this->buf) {\n\t\tbuf = DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this);\n\t} else {\n\t\t/* Neutered.  We could go into the switch-case safely with\n\t\t * buf == NULL because check_length == 0.  To avoid scanbuild\n\t\t * warnings, fail directly instead.\n\t\t */\n\t\tDUK_ASSERT(check_length == 0);\n\t\tgoto fail_neutered;\n\t}\n\tDUK_ASSERT(buf != NULL);\n\n\tswitch (magic_ftype) {\n\tcase DUK__FLD_8BIT: {\n\t\tduk_uint8_t tmp;\n\t\tif (offset + 1U > check_length) {\n\t\t\tgoto fail_bounds;\n\t\t}\n\t\ttmp = buf[offset];\n\t\tif (magic_signed) {\n\t\t\tduk_push_int(thr, (duk_int_t) ((duk_int8_t) tmp));\n\t\t} else {\n\t\t\tduk_push_uint(thr, (duk_uint_t) tmp);\n\t\t}\n\t\tbreak;\n\t}\n\tcase DUK__FLD_16BIT: {\n\t\tduk_uint16_t tmp;\n\t\tif (offset + 2U > check_length) {\n\t\t\tgoto fail_bounds;\n\t\t}\n\t\tDUK_MEMCPY((void *) du.uc, (const void *) (buf + offset), 2);\n\t\ttmp = du.us[0];\n\t\tif (endswap) {\n\t\t\ttmp = DUK_BSWAP16(tmp);\n\t\t}\n\t\tif (magic_signed) {\n\t\t\tduk_push_int(thr, (duk_int_t) ((duk_int16_t) tmp));\n\t\t} else {\n\t\t\tduk_push_uint(thr, (duk_uint_t) tmp);\n\t\t}\n\t\tbreak;\n\t}\n\tcase DUK__FLD_32BIT: {\n\t\tduk_uint32_t tmp;\n\t\tif (offset + 4U > check_length) {\n\t\t\tgoto fail_bounds;\n\t\t}\n\t\tDUK_MEMCPY((void *) du.uc, (const void *) (buf + offset), 4);\n\t\ttmp = du.ui[0];\n\t\tif (endswap) {\n\t\t\ttmp = DUK_BSWAP32(tmp);\n\t\t}\n\t\tif (magic_signed) {\n\t\t\tduk_push_int(thr, (duk_int_t) ((duk_int32_t) tmp));\n\t\t} else {\n\t\t\tduk_push_uint(thr, (duk_uint_t) tmp);\n\t\t}\n\t\tbreak;\n\t}\n\tcase DUK__FLD_FLOAT: {\n\t\tduk_uint32_t tmp;\n\t\tif (offset + 4U > check_length) {\n\t\t\tgoto fail_bounds;\n\t\t}\n\t\tDUK_MEMCPY((void *) du.uc, (const void *) (buf + offset), 4);\n\t\tif (endswap) {\n\t\t\ttmp = du.ui[0];\n\t\t\ttmp = DUK_BSWAP32(tmp);\n\t\t\tdu.ui[0] = tmp;\n\t\t}\n\t\tduk_push_number(thr, (duk_double_t) du.f[0]);\n\t\tbreak;\n\t}\n\tcase DUK__FLD_DOUBLE: {\n\t\tif (offset + 8U > check_length) {\n\t\t\tgoto fail_bounds;\n\t\t}\n\t\tDUK_MEMCPY((void *) du.uc, (const void *) (buf + offset), 8);\n\t\tif (endswap) {\n\t\t\tDUK_DBLUNION_BSWAP64(&du);\n\t\t}\n\t\tduk_push_number(thr, (duk_double_t) du.d);\n\t\tbreak;\n\t}\n\tcase DUK__FLD_VARINT: {\n\t\t/* Node.js Buffer variable width integer field.  We don't really\n\t\t * care about speed here, so aim for shortest algorithm.\n\t\t */\n\t\tduk_int_t field_bytelen;\n\t\tduk_int_t i, i_step, i_end;\n#if defined(DUK_USE_64BIT_OPS)\n\t\tduk_int64_t tmp;\n\t\tduk_small_uint_t shift_tmp;\n#else\n\t\tduk_double_t tmp;\n\t\tduk_small_int_t highbyte;\n#endif\n\t\tconst duk_uint8_t *p;\n\n\t\tfield_bytelen = duk_get_int(thr, 1);  /* avoid side effects! */\n\t\tif (field_bytelen < 1 || field_bytelen > 6) {\n\t\t\tgoto fail_field_length;\n\t\t}\n\t\tif (offset + (duk_uint_t) field_bytelen > check_length) {\n\t\t\tgoto fail_bounds;\n\t\t}\n\t\tp = (const duk_uint8_t *) (buf + offset);\n\n\t\t/* Slow gathering of value using either 64-bit arithmetic\n\t\t * or IEEE doubles if 64-bit types not available.  Handling\n\t\t * of negative numbers is a bit non-obvious in both cases.\n\t\t */\n\n\t\tif (magic_bigendian) {\n\t\t\t/* Gather in big endian */\n\t\t\ti = 0;\n\t\t\ti_step = 1;\n\t\t\ti_end = field_bytelen;  /* one i_step over */\n\t\t} else {\n\t\t\t/* Gather in little endian */\n\t\t\ti = field_bytelen - 1;\n\t\t\ti_step = -1;\n\t\t\ti_end = -1;  /* one i_step over */\n\t\t}\n\n#if defined(DUK_USE_64BIT_OPS)\n\t\ttmp = 0;\n\t\tdo {\n\t\t\tDUK_ASSERT(i >= 0 && i < field_bytelen);\n\t\t\ttmp = (tmp << 8) + (duk_int64_t) p[i];\n\t\t\ti += i_step;\n\t\t} while (i != i_end);\n\n\t\tif (magic_signed) {\n\t\t\t/* Shift to sign extend. */\n\t\t\tshift_tmp = (duk_small_uint_t) (64U - (duk_small_uint_t) field_bytelen * 8U);\n\t\t\ttmp = (tmp << shift_tmp) >> shift_tmp;\n\t\t}\n\n\t\tduk_push_i64(thr, tmp);\n#else\n\t\thighbyte = p[i];\n\t\tif (magic_signed && (highbyte & 0x80) != 0) {\n\t\t\t/* 0xff => 255 - 256 = -1; 0x80 => 128 - 256 = -128 */\n\t\t\ttmp = (duk_double_t) (highbyte - 256);\n\t\t} else {\n\t\t\ttmp = (duk_double_t) highbyte;\n\t\t}\n\t\tfor (;;) {\n\t\t\ti += i_step;\n\t\t\tif (i == i_end) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tDUK_ASSERT(i >= 0 && i < field_bytelen);\n\t\t\ttmp = (tmp * 256.0) + (duk_double_t) p[i];\n\t\t}\n\n\t\tduk_push_number(thr, tmp);\n#endif\n\t\tbreak;\n\t}\n\tdefault: {  /* should never happen but default here */\n\t\tgoto fail_bounds;\n\t}\n\t}\n\n\treturn 1;\n\n fail_neutered:\n fail_field_length:\n fail_bounds:\n\tif (no_assert) {\n\t\t/* Node.js return value for noAssert out-of-bounds reads is\n\t\t * usually (but not always) NaN.  Return NaN consistently.\n\t\t */\n\t\tduk_push_nan(thr);\n\t\treturn 1;\n\t}\n\tDUK_DCERROR_RANGE_INVALID_ARGS(thr);\n}\n#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */\n\n#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)\n/* XXX: split into separate functions for each field type? */\nDUK_INTERNAL duk_ret_t duk_bi_buffer_writefield(duk_hthread *thr) {\n\tduk_small_int_t magic = (duk_small_int_t) duk_get_current_magic(thr);\n\tduk_small_int_t magic_ftype;\n\tduk_small_int_t magic_bigendian;\n\tduk_small_int_t magic_signed;\n\tduk_small_int_t magic_typedarray;\n\tduk_small_int_t endswap;\n\tduk_hbufobj *h_this;\n\tduk_bool_t no_assert;\n\tduk_int_t offset_signed;\n\tduk_uint_t offset;\n\tduk_uint_t buffer_length;\n\tduk_uint_t check_length;\n\tduk_uint8_t *buf;\n\tduk_double_union du;\n\tduk_int_t nbytes = 0;\n\n\tmagic_ftype = magic & 0x0007;\n\tmagic_bigendian = magic & 0x0008;\n\tmagic_signed = magic & 0x0010;\n\tmagic_typedarray = magic & 0x0020;\n\tDUK_UNREF(magic_signed);\n\n\th_this = duk__require_bufobj_this(thr);  /* XXX: very inefficient for plain buffers */\n\tDUK_ASSERT(h_this != NULL);\n\tbuffer_length = h_this->length;\n\n\t/* [ value  offset noAssert                 ], when ftype != DUK__FLD_VARINT */\n\t/* [ value  offset fieldByteLength noAssert ], when ftype == DUK__FLD_VARINT */\n\t/* [ offset value  littleEndian             ], when DUK__FLD_TYPEDARRAY (regardless of ftype) */\n\n\t/* Handle TypedArray vs. Node.js Buffer arg differences */\n\tif (magic_typedarray) {\n\t\tno_assert = 0;\n#if defined(DUK_USE_INTEGER_LE)\n\t\tendswap = !duk_to_boolean(thr, 2);  /* 1=little endian */\n#else\n\t\tendswap = duk_to_boolean(thr, 2);  /* 1=little endian */\n#endif\n\t\tduk_swap(thr, 0, 1);  /* offset/value order different from Node.js */\n\t} else {\n\t\tno_assert = duk_to_boolean(thr, (magic_ftype == DUK__FLD_VARINT) ? 3 : 2);\n#if defined(DUK_USE_INTEGER_LE)\n\t\tendswap = magic_bigendian;\n#else\n\t\tendswap = !magic_bigendian;\n#endif\n\t}\n\n\t/* Offset is coerced first to signed integer range and then to unsigned.\n\t * This ensures we can add a small byte length (1-8) to the offset in\n\t * bound checks and not wrap.\n\t */\n\toffset_signed = duk_to_int(thr, 1);\n\toffset = (duk_uint_t) offset_signed;\n\n\t/* We need 'nbytes' even for a failed offset; return value must be\n\t * (offset + nbytes) even when write fails due to invalid offset.\n\t */\n\tif (magic_ftype != DUK__FLD_VARINT) {\n\t\tDUK_ASSERT(magic_ftype >= 0 && magic_ftype < (duk_small_int_t) (sizeof(duk__buffer_nbytes_from_fldtype) / sizeof(duk_uint8_t)));\n\t\tnbytes = duk__buffer_nbytes_from_fldtype[magic_ftype];\n\t} else {\n\t\tnbytes = duk_get_int(thr, 2);\n\t\tif (nbytes < 1 || nbytes > 6) {\n\t\t\tgoto fail_field_length;\n\t\t}\n\t}\n\tDUK_ASSERT(nbytes >= 1 && nbytes <= 8);\n\n\t/* Now we can check offset validity. */\n\tif (offset_signed < 0) {\n\t\tgoto fail_bounds;\n\t}\n\n\tDUK_DDD(DUK_DDDPRINT(\"writefield, value=%!T, buffer_length=%ld, offset=%ld, no_assert=%d, \"\n\t                     \"magic=%04x, magic_fieldtype=%d, magic_bigendian=%d, magic_signed=%d, \"\n\t                     \"endswap=%d\",\n\t                     duk_get_tval(thr, 0), (long) buffer_length, (long) offset, (int) no_assert,\n\t                     (unsigned int) magic, (int) magic_ftype, (int) (magic_bigendian >> 3),\n\t                     (int) (magic_signed >> 4), (int) endswap));\n\n\t/* Coerce value to a number before computing check_length, so that\n\t * the field type specific coercion below can't have side effects\n\t * that would invalidate check_length.\n\t */\n\tduk_to_number(thr, 0);\n\n\t/* Update 'buffer_length' to be the effective, safe limit which\n\t * takes into account the underlying buffer.  This value will be\n\t * potentially invalidated by any side effect.\n\t */\n\tcheck_length = DUK_HBUFOBJ_CLAMP_BYTELENGTH(h_this, buffer_length);\n\tDUK_DDD(DUK_DDDPRINT(\"buffer_length=%ld, check_length=%ld\",\n\t                     (long) buffer_length, (long) check_length));\n\n\tif (h_this->buf) {\n\t\tbuf = DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this);\n\t} else {\n\t\t/* Neutered.  We could go into the switch-case safely with\n\t\t * buf == NULL because check_length == 0.  To avoid scanbuild\n\t\t * warnings, fail directly instead.\n\t\t */\n\t\tDUK_ASSERT(check_length == 0);\n\t\tgoto fail_neutered;\n\t}\n\tDUK_ASSERT(buf != NULL);\n\n\tswitch (magic_ftype) {\n\tcase DUK__FLD_8BIT: {\n\t\tif (offset + 1U > check_length) {\n\t\t\tgoto fail_bounds;\n\t\t}\n\t\t/* sign doesn't matter when writing */\n\t\tbuf[offset] = (duk_uint8_t) duk_to_uint32(thr, 0);\n\t\tbreak;\n\t}\n\tcase DUK__FLD_16BIT: {\n\t\tduk_uint16_t tmp;\n\t\tif (offset + 2U > check_length) {\n\t\t\tgoto fail_bounds;\n\t\t}\n\t\ttmp = (duk_uint16_t) duk_to_uint32(thr, 0);\n\t\tif (endswap) {\n\t\t\ttmp = DUK_BSWAP16(tmp);\n\t\t}\n\t\tdu.us[0] = tmp;\n\t\t/* sign doesn't matter when writing */\n\t\tDUK_MEMCPY((void *) (buf + offset), (const void *) du.uc, 2);\n\t\tbreak;\n\t}\n\tcase DUK__FLD_32BIT: {\n\t\tduk_uint32_t tmp;\n\t\tif (offset + 4U > check_length) {\n\t\t\tgoto fail_bounds;\n\t\t}\n\t\ttmp = (duk_uint32_t) duk_to_uint32(thr, 0);\n\t\tif (endswap) {\n\t\t\ttmp = DUK_BSWAP32(tmp);\n\t\t}\n\t\tdu.ui[0] = tmp;\n\t\t/* sign doesn't matter when writing */\n\t\tDUK_MEMCPY((void *) (buf + offset), (const void *) du.uc, 4);\n\t\tbreak;\n\t}\n\tcase DUK__FLD_FLOAT: {\n\t\tduk_uint32_t tmp;\n\t\tif (offset + 4U > check_length) {\n\t\t\tgoto fail_bounds;\n\t\t}\n\t\tdu.f[0] = (duk_float_t) duk_to_number(thr, 0);\n\t\tif (endswap) {\n\t\t\ttmp = du.ui[0];\n\t\t\ttmp = DUK_BSWAP32(tmp);\n\t\t\tdu.ui[0] = tmp;\n\t\t}\n\t\t/* sign doesn't matter when writing */\n\t\tDUK_MEMCPY((void *) (buf + offset), (const void *) du.uc, 4);\n\t\tbreak;\n\t}\n\tcase DUK__FLD_DOUBLE: {\n\t\tif (offset + 8U > check_length) {\n\t\t\tgoto fail_bounds;\n\t\t}\n\t\tdu.d = (duk_double_t) duk_to_number(thr, 0);\n\t\tif (endswap) {\n\t\t\tDUK_DBLUNION_BSWAP64(&du);\n\t\t}\n\t\t/* sign doesn't matter when writing */\n\t\tDUK_MEMCPY((void *) (buf + offset), (const void *) du.uc, 8);\n\t\tbreak;\n\t}\n\tcase DUK__FLD_VARINT: {\n\t\t/* Node.js Buffer variable width integer field.  We don't really\n\t\t * care about speed here, so aim for shortest algorithm.\n\t\t */\n\t\tduk_int_t field_bytelen;\n\t\tduk_int_t i, i_step, i_end;\n#if defined(DUK_USE_64BIT_OPS)\n\t\tduk_int64_t tmp;\n#else\n\t\tduk_double_t tmp;\n#endif\n\t\tduk_uint8_t *p;\n\n\t\tfield_bytelen = (duk_int_t) nbytes;\n\t\tif (offset + (duk_uint_t) field_bytelen > check_length) {\n\t\t\tgoto fail_bounds;\n\t\t}\n\n\t\t/* Slow writing of value using either 64-bit arithmetic\n\t\t * or IEEE doubles if 64-bit types not available.  There's\n\t\t * no special sign handling when writing varints.\n\t\t */\n\n\t\tif (magic_bigendian) {\n\t\t\t/* Write in big endian */\n\t\t\ti = field_bytelen;  /* one i_step added at top of loop */\n\t\t\ti_step = -1;\n\t\t\ti_end = 0;\n\t\t} else {\n\t\t\t/* Write in little endian */\n\t\t\ti = -1;  /* one i_step added at top of loop */\n\t\t\ti_step = 1;\n\t\t\ti_end = field_bytelen - 1;\n\t\t}\n\n\t\t/* XXX: The duk_to_number() cast followed by integer coercion\n\t\t * is platform specific so NaN, +/- Infinity, and out-of-bounds\n\t\t * values result in platform specific output now.\n\t\t * See: test-bi-nodejs-buffer-proto-varint-special.js\n\t\t */\n\n#if defined(DUK_USE_64BIT_OPS)\n\t\ttmp = (duk_int64_t) duk_to_number(thr, 0);\n\t\tp = (duk_uint8_t *) (buf + offset);\n\t\tdo {\n\t\t\ti += i_step;\n\t\t\tDUK_ASSERT(i >= 0 && i < field_bytelen);\n\t\t\tp[i] = (duk_uint8_t) (tmp & 0xff);\n\t\t\ttmp = tmp >> 8;  /* unnecessary shift for last byte */\n\t\t} while (i != i_end);\n#else\n\t\ttmp = duk_to_number(thr, 0);\n\t\tp = (duk_uint8_t *) (buf + offset);\n\t\tdo {\n\t\t\ti += i_step;\n\t\t\ttmp = DUK_FLOOR(tmp);\n\t\t\tDUK_ASSERT(i >= 0 && i < field_bytelen);\n\t\t\tp[i] = (duk_uint8_t) (DUK_FMOD(tmp, 256.0));\n\t\t\ttmp = tmp / 256.0;  /* unnecessary div for last byte */\n\t\t} while (i != i_end);\n#endif\n\t\tbreak;\n\t}\n\tdefault: {  /* should never happen but default here */\n\t\tgoto fail_bounds;\n\t}\n\t}\n\n\t/* Node.js Buffer: return offset + #bytes written (i.e. next\n\t * write offset).\n\t */\n\tif (magic_typedarray) {\n\t\t/* For TypedArrays 'undefined' return value is specified\n\t\t * by ES2015 (matches V8).\n\t\t */\n\t\treturn 0;\n\t}\n\tduk_push_uint(thr, offset + (duk_uint_t) nbytes);\n\treturn 1;\n\n fail_neutered:\n fail_field_length:\n fail_bounds:\n\tif (no_assert) {\n\t\t/* Node.js return value for failed writes is offset + #bytes\n\t\t * that would have been written.\n\t\t */\n\t\t/* XXX: for negative input offsets, 'offset' will be a large\n\t\t * positive value so the result here is confusing.\n\t\t */\n\t\tif (magic_typedarray) {\n\t\t\treturn 0;\n\t\t}\n\t\tduk_push_uint(thr, offset + (duk_uint_t) nbytes);\n\t\treturn 1;\n\t}\n\tDUK_DCERROR_RANGE_INVALID_ARGS(thr);\n}\n#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */\n\n/*\n *  Accessors for .buffer, .byteLength, .byteOffset\n */\n\n#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)\nDUK_LOCAL duk_hbufobj *duk__autospawn_arraybuffer(duk_hthread *thr, duk_hbuffer *h_buf) {\n\tduk_hbufobj *h_res;\n\n\th_res = duk_push_bufobj_raw(thr,\n\t                            DUK_HOBJECT_FLAG_EXTENSIBLE |\n\t                            DUK_HOBJECT_FLAG_BUFOBJ |\n\t                            DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ARRAYBUFFER),\n\t                            DUK_BIDX_ARRAYBUFFER_PROTOTYPE);\n\tDUK_ASSERT(h_res != NULL);\n\tDUK_UNREF(h_res);\n\n\tduk__set_bufobj_buffer(thr, h_res, h_buf);\n\tDUK_ASSERT_HBUFOBJ_VALID(h_res);\n\tDUK_ASSERT(h_res->buf_prop == NULL);\n\treturn h_res;\n}\n\nDUK_INTERNAL duk_ret_t duk_bi_typedarray_buffer_getter(duk_hthread *thr) {\n\tduk_hbufobj *h_bufobj;\n\n\th_bufobj = (duk_hbufobj *) duk__getrequire_bufobj_this(thr, DUK__BUFOBJ_FLAG_THROW /*flags*/);\n\tDUK_ASSERT(h_bufobj != NULL);\n\tif (DUK_HEAPHDR_IS_BUFFER((duk_heaphdr *) h_bufobj)) {\n\t\tDUK_DD(DUK_DDPRINT(\"autospawn ArrayBuffer for plain buffer\"));\n\t\t(void) duk__autospawn_arraybuffer(thr, (duk_hbuffer *) h_bufobj);\n\t\treturn 1;\n\t} else {\n\t\tif (h_bufobj->buf_prop == NULL &&\n\t\t    DUK_HOBJECT_GET_CLASS_NUMBER((duk_hobject *) h_bufobj) != DUK_HOBJECT_CLASS_ARRAYBUFFER &&\n\t\t    h_bufobj->buf != NULL) {\n\t\t\tduk_hbufobj *h_arrbuf;\n\n\t\t\tDUK_DD(DUK_DDPRINT(\"autospawn ArrayBuffer for typed array or DataView\"));\n\t\t\th_arrbuf = duk__autospawn_arraybuffer(thr, h_bufobj->buf);\n\n\t\t\tif (h_bufobj->buf_prop == NULL) {\n\t\t\t\t/* Must recheck buf_prop, in case ArrayBuffer\n\t\t\t\t * alloc had a side effect which already filled\n\t\t\t\t * it!\n\t\t\t\t */\n\n\t\t\t\t/* Set ArrayBuffer's .byteOffset and .byteLength based\n\t\t\t\t * on the view so that Arraybuffer[view.byteOffset]\n\t\t\t\t * matches view[0].\n\t\t\t\t */\n\t\t\t\th_arrbuf->offset = 0;\n\t\t\t\tDUK_ASSERT(h_bufobj->offset + h_bufobj->length >= h_bufobj->offset);  /* Wrap check on creation. */\n\t\t\t\th_arrbuf->length = h_bufobj->offset + h_bufobj->length;\n\t\t\t\tDUK_ASSERT(h_arrbuf->buf_prop == NULL);\n\n\t\t\t\tDUK_ASSERT(h_bufobj->buf_prop == NULL);\n\t\t\t\th_bufobj->buf_prop = (duk_hobject *) h_arrbuf;\n\t\t\t\tDUK_HBUFOBJ_INCREF(thr, h_arrbuf);  /* Now reachable and accounted for. */\n\t\t\t}\n\n\t\t\t/* Left on stack; pushed for the second time below (OK). */\n\t\t}\n\t\tif (h_bufobj->buf_prop) {\n\t\t\tduk_push_hobject(thr, h_bufobj->buf_prop);\n\t\t\treturn 1;\n\t\t}\n\t}\n\treturn 0;\n}\n\nDUK_INTERNAL duk_ret_t duk_bi_typedarray_byteoffset_getter(duk_hthread *thr) {\n\tduk_hbufobj *h_bufobj;\n\n\th_bufobj = (duk_hbufobj *) duk__getrequire_bufobj_this(thr, DUK__BUFOBJ_FLAG_THROW /*flags*/);\n\tDUK_ASSERT(h_bufobj != NULL);\n\tif (DUK_HEAPHDR_IS_BUFFER((duk_heaphdr *) h_bufobj)) {\n\t\tduk_push_uint(thr, 0);\n\t} else {\n\t\t/* If neutered must return 0; offset is zeroed during\n\t\t * neutering.\n\t\t */\n\t\tduk_push_uint(thr, h_bufobj->offset);\n\t}\n\treturn 1;\n}\n\nDUK_INTERNAL duk_ret_t duk_bi_typedarray_bytelength_getter(duk_hthread *thr) {\n\tduk_hbufobj *h_bufobj;\n\n\th_bufobj = (duk_hbufobj *) duk__getrequire_bufobj_this(thr, DUK__BUFOBJ_FLAG_THROW /*flags*/);\n\tDUK_ASSERT(h_bufobj != NULL);\n\tif (DUK_HEAPHDR_IS_BUFFER((duk_heaphdr *) h_bufobj)) {\n\t\tduk_hbuffer *h_buf;\n\n\t\th_buf = (duk_hbuffer *) h_bufobj;\n\t\tDUK_ASSERT(DUK_HBUFFER_GET_SIZE(h_buf) <= DUK_UINT_MAX);  /* Buffer limits. */\n\t\tduk_push_uint(thr, (duk_uint_t) DUK_HBUFFER_GET_SIZE(h_buf));\n\t} else {\n\t\t/* If neutered must return 0; length is zeroed during\n\t\t * neutering.\n\t\t */\n\t\tduk_push_uint(thr, h_bufobj->length);\n\t}\n\treturn 1;\n}\n#else  /* DUK_USE_BUFFEROBJECT_SUPPORT */\n/* No .buffer getter without ArrayBuffer support. */\n#if 0\nDUK_INTERNAL duk_ret_t duk_bi_typedarray_buffer_getter(duk_hthread *thr) {\n\treturn 0;\n}\n#endif\n\nDUK_INTERNAL duk_ret_t duk_bi_typedarray_byteoffset_getter(duk_hthread *thr) {\n\tduk_push_uint(thr, 0);\n\treturn 1;\n}\n\nDUK_INTERNAL duk_ret_t duk_bi_typedarray_bytelength_getter(duk_hthread *thr) {\n\tduk_hbuffer *h_buf;\n\n\t/* XXX: helper? */\n\tduk_push_this(thr);\n\th_buf = duk_require_hbuffer(thr, -1);\n\tduk_push_uint(thr, DUK_HBUFFER_GET_SIZE(h_buf));\n\treturn 1;\n}\n#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */\n\n/* automatic undefs */\n#undef DUK__BUFOBJ_FLAG_PROMOTE\n#undef DUK__BUFOBJ_FLAG_THROW\n#undef DUK__FLD_16BIT\n#undef DUK__FLD_32BIT\n#undef DUK__FLD_8BIT\n#undef DUK__FLD_BIGENDIAN\n#undef DUK__FLD_DOUBLE\n#undef DUK__FLD_FLOAT\n#undef DUK__FLD_SIGNED\n#undef DUK__FLD_TYPEDARRAY\n#undef DUK__FLD_VARINT\n#line 1 \"duk_bi_date.c\"\n/*\n *  Date built-ins\n *\n *  Unlike most built-ins, Date has some platform dependencies for getting\n *  UTC time, converting between UTC and local time, and parsing and\n *  formatting time values.  These are all abstracted behind DUK_USE_xxx\n *  config options.  There are built-in platform specific providers for\n *  POSIX and Windows, but external providers can also be used.\n *\n *  See doc/datetime.rst.\n *\n */\n\n/* #include duk_internal.h -> already included */\n\n/* XXX: currently defines unnecessary symbols when DUK_USE_DATE_BUILTIN is disabled. */\n\n/*\n *  Forward declarations\n */\n\nDUK_LOCAL_DECL duk_double_t duk__push_this_get_timeval_tzoffset(duk_hthread *thr, duk_small_uint_t flags, duk_int_t *out_tzoffset);\nDUK_LOCAL_DECL duk_double_t duk__push_this_get_timeval(duk_hthread *thr, duk_small_uint_t flags);\nDUK_LOCAL_DECL void duk__twodigit_year_fixup(duk_hthread *thr, duk_idx_t idx_val);\nDUK_LOCAL_DECL duk_ret_t duk__set_this_timeval_from_dparts(duk_hthread *thr, duk_double_t *dparts, duk_small_uint_t flags);\n\n/*\n *  Other file level defines\n */\n\n/* Debug macro to print all parts and dparts (used manually because of debug level). */\n#define  DUK__DPRINT_PARTS_AND_DPARTS(parts,dparts)  do { \\\n\t\tDUK_D(DUK_DPRINT(\"parts: %ld %ld %ld %ld %ld %ld %ld %ld, dparts: %lf %lf %lf %lf %lf %lf %lf %lf\", \\\n\t\t                 (long) (parts)[0], (long) (parts)[1], \\\n\t\t                 (long) (parts)[2], (long) (parts)[3], \\\n\t\t                 (long) (parts)[4], (long) (parts)[5], \\\n\t\t                 (long) (parts)[6], (long) (parts)[7], \\\n\t\t                 (double) (dparts)[0], (double) (dparts)[1], \\\n\t\t                 (double) (dparts)[2], (double) (dparts)[3], \\\n\t\t                 (double) (dparts)[4], (double) (dparts)[5], \\\n\t\t                 (double) (dparts)[6], (double) (dparts)[7])); \\\n\t} while (0)\n#define  DUK__DPRINT_PARTS(parts)  do { \\\n\t\tDUK_D(DUK_DPRINT(\"parts: %ld %ld %ld %ld %ld %ld %ld %ld\", \\\n\t\t                 (long) (parts)[0], (long) (parts)[1], \\\n\t\t                 (long) (parts)[2], (long) (parts)[3], \\\n\t\t                 (long) (parts)[4], (long) (parts)[5], \\\n\t\t                 (long) (parts)[6], (long) (parts)[7])); \\\n\t} while (0)\n#define  DUK__DPRINT_DPARTS(dparts)  do { \\\n\t\tDUK_D(DUK_DPRINT(\"dparts: %lf %lf %lf %lf %lf %lf %lf %lf\", \\\n\t\t                 (double) (dparts)[0], (double) (dparts)[1], \\\n\t\t                 (double) (dparts)[2], (double) (dparts)[3], \\\n\t\t                 (double) (dparts)[4], (double) (dparts)[5], \\\n\t\t                 (double) (dparts)[6], (double) (dparts)[7])); \\\n\t} while (0)\n\n/* Equivalent year for DST calculations outside [1970,2038[ range, see\n * E5 Section 15.9.1.8.  Equivalent year has the same leap-year-ness and\n * starts with the same weekday on Jan 1.\n * https://bugzilla.mozilla.org/show_bug.cgi?id=351066\n */\n#define DUK__YEAR(x) ((duk_uint8_t) ((x) - 1970))\nDUK_LOCAL duk_uint8_t duk__date_equivyear[14] = {\n#if 1\n\t/* This is based on V8 EquivalentYear() algorithm (see util/genequivyear.py):\n\t * http://code.google.com/p/v8/source/browse/trunk/src/date.h#146\n\t */\n\n\t/* non-leap year: sunday, monday, ... */\n\tDUK__YEAR(2023), DUK__YEAR(2035), DUK__YEAR(2019), DUK__YEAR(2031),\n\tDUK__YEAR(2015), DUK__YEAR(2027), DUK__YEAR(2011),\n\n\t/* leap year: sunday, monday, ... */\n\tDUK__YEAR(2012), DUK__YEAR(2024), DUK__YEAR(2008), DUK__YEAR(2020),\n\tDUK__YEAR(2032), DUK__YEAR(2016), DUK__YEAR(2028)\n#endif\n\n#if 0\n\t/* This is based on Rhino EquivalentYear() algorithm:\n\t * https://github.com/mozilla/rhino/blob/f99cc11d616f0cdda2c42bde72b3484df6182947/src/org/mozilla/javascript/NativeDate.java\n\t */\n\n\t/* non-leap year: sunday, monday, ... */\n\tDUK__YEAR(1978), DUK__YEAR(1973), DUK__YEAR(1985), DUK__YEAR(1986),\n\tDUK__YEAR(1981), DUK__YEAR(1971), DUK__YEAR(1977),\n\n\t/* leap year: sunday, monday, ... */\n\tDUK__YEAR(1984), DUK__YEAR(1996), DUK__YEAR(1980), DUK__YEAR(1992),\n\tDUK__YEAR(1976), DUK__YEAR(1988), DUK__YEAR(1972)\n#endif\n};\n\n/*\n *  ISO 8601 subset parser.\n */\n\n/* Parser part count. */\n#define DUK__NUM_ISO8601_PARSER_PARTS  9\n\n/* Parser part indices. */\n#define DUK__PI_YEAR         0\n#define DUK__PI_MONTH        1\n#define DUK__PI_DAY          2\n#define DUK__PI_HOUR         3\n#define DUK__PI_MINUTE       4\n#define DUK__PI_SECOND       5\n#define DUK__PI_MILLISECOND  6\n#define DUK__PI_TZHOUR       7\n#define DUK__PI_TZMINUTE     8\n\n/* Parser part masks. */\n#define DUK__PM_YEAR         (1 << DUK__PI_YEAR)\n#define DUK__PM_MONTH        (1 << DUK__PI_MONTH)\n#define DUK__PM_DAY          (1 << DUK__PI_DAY)\n#define DUK__PM_HOUR         (1 << DUK__PI_HOUR)\n#define DUK__PM_MINUTE       (1 << DUK__PI_MINUTE)\n#define DUK__PM_SECOND       (1 << DUK__PI_SECOND)\n#define DUK__PM_MILLISECOND  (1 << DUK__PI_MILLISECOND)\n#define DUK__PM_TZHOUR       (1 << DUK__PI_TZHOUR)\n#define DUK__PM_TZMINUTE     (1 << DUK__PI_TZMINUTE)\n\n/* Parser separator indices. */\n#define DUK__SI_PLUS         0\n#define DUK__SI_MINUS        1\n#define DUK__SI_T            2\n#define DUK__SI_SPACE        3\n#define DUK__SI_COLON        4\n#define DUK__SI_PERIOD       5\n#define DUK__SI_Z            6\n#define DUK__SI_NUL          7\n\n/* Parser separator masks. */\n#define DUK__SM_PLUS         (1 << DUK__SI_PLUS)\n#define DUK__SM_MINUS        (1 << DUK__SI_MINUS)\n#define DUK__SM_T            (1 << DUK__SI_T)\n#define DUK__SM_SPACE        (1 << DUK__SI_SPACE)\n#define DUK__SM_COLON        (1 << DUK__SI_COLON)\n#define DUK__SM_PERIOD       (1 << DUK__SI_PERIOD)\n#define DUK__SM_Z            (1 << DUK__SI_Z)\n#define DUK__SM_NUL          (1 << DUK__SI_NUL)\n\n/* Rule control flags. */\n#define DUK__CF_NEG          (1 << 0)  /* continue matching, set neg_tzoffset flag */\n#define DUK__CF_ACCEPT       (1 << 1)  /* accept string */\n#define DUK__CF_ACCEPT_NUL   (1 << 2)  /* accept string if next char is NUL (otherwise reject) */\n\n#define DUK__PACK_RULE(partmask,sepmask,nextpart,flags)  \\\n\t((duk_uint32_t) (partmask) + \\\n\t (((duk_uint32_t) (sepmask)) << 9) + \\\n\t (((duk_uint32_t) (nextpart)) << 17) + \\\n\t (((duk_uint32_t) (flags)) << 21))\n\n#define DUK__UNPACK_RULE(rule,var_nextidx,var_flags)  do { \\\n\t\t(var_nextidx) = (duk_small_uint_t) (((rule) >> 17) & 0x0f); \\\n\t\t(var_flags) = (duk_small_uint_t) ((rule) >> 21); \\\n\t} while (0)\n\n#define DUK__RULE_MASK_PART_SEP  0x1ffffUL\n\n/* Matching separator index is used in the control table */\nDUK_LOCAL const duk_uint8_t duk__parse_iso8601_seps[] = {\n\tDUK_ASC_PLUS /*0*/, DUK_ASC_MINUS /*1*/, DUK_ASC_UC_T /*2*/, DUK_ASC_SPACE /*3*/,\n\tDUK_ASC_COLON /*4*/, DUK_ASC_PERIOD /*5*/, DUK_ASC_UC_Z /*6*/, DUK_ASC_NUL /*7*/\n};\n\n/* Rule table: first matching rule is used to determine what to do next. */\nDUK_LOCAL const duk_uint32_t duk__parse_iso8601_control[] = {\n\tDUK__PACK_RULE(DUK__PM_YEAR, DUK__SM_MINUS, DUK__PI_MONTH, 0),\n\tDUK__PACK_RULE(DUK__PM_MONTH, DUK__SM_MINUS, DUK__PI_DAY, 0),\n\tDUK__PACK_RULE(DUK__PM_YEAR | DUK__PM_MONTH | DUK__PM_DAY, DUK__SM_T | DUK__SM_SPACE, DUK__PI_HOUR, 0),\n\tDUK__PACK_RULE(DUK__PM_HOUR, DUK__SM_COLON, DUK__PI_MINUTE, 0),\n\tDUK__PACK_RULE(DUK__PM_MINUTE, DUK__SM_COLON, DUK__PI_SECOND, 0),\n\tDUK__PACK_RULE(DUK__PM_SECOND, DUK__SM_PERIOD, DUK__PI_MILLISECOND, 0),\n\tDUK__PACK_RULE(DUK__PM_TZHOUR, DUK__SM_COLON, DUK__PI_TZMINUTE, 0),\n\tDUK__PACK_RULE(DUK__PM_YEAR | DUK__PM_MONTH | DUK__PM_DAY | DUK__PM_HOUR /*Note1*/ | DUK__PM_MINUTE | DUK__PM_SECOND | DUK__PM_MILLISECOND, DUK__SM_PLUS, DUK__PI_TZHOUR, 0),\n\tDUK__PACK_RULE(DUK__PM_YEAR | DUK__PM_MONTH | DUK__PM_DAY | DUK__PM_HOUR /*Note1*/ | DUK__PM_MINUTE | DUK__PM_SECOND | DUK__PM_MILLISECOND, DUK__SM_MINUS, DUK__PI_TZHOUR, DUK__CF_NEG),\n\tDUK__PACK_RULE(DUK__PM_YEAR | DUK__PM_MONTH | DUK__PM_DAY | DUK__PM_HOUR /*Note1*/ | DUK__PM_MINUTE | DUK__PM_SECOND | DUK__PM_MILLISECOND, DUK__SM_Z, 0, DUK__CF_ACCEPT_NUL),\n\tDUK__PACK_RULE(DUK__PM_YEAR | DUK__PM_MONTH | DUK__PM_DAY | DUK__PM_HOUR /*Note1*/ | DUK__PM_MINUTE | DUK__PM_SECOND | DUK__PM_MILLISECOND | DUK__PM_TZHOUR /*Note2*/ | DUK__PM_TZMINUTE, DUK__SM_NUL, 0, DUK__CF_ACCEPT)\n\n\t/* Note1: the specification doesn't require matching a time form with\n\t *        just hours (\"HH\"), but we accept it here, e.g. \"2012-01-02T12Z\".\n\t *\n\t * Note2: the specification doesn't require matching a timezone offset\n\t *        with just hours (\"HH\"), but accept it here, e.g. \"2012-01-02T03:04:05+02\"\n\t */\n};\n\nDUK_LOCAL duk_bool_t duk__parse_string_iso8601_subset(duk_hthread *thr, const char *str) {\n\tduk_int_t parts[DUK__NUM_ISO8601_PARSER_PARTS];\n\tduk_double_t dparts[DUK_DATE_IDX_NUM_PARTS];\n\tduk_double_t d;\n\tconst duk_uint8_t *p;\n\tduk_small_uint_t part_idx = 0;\n\tduk_int_t accum = 0;\n\tduk_small_uint_t ndigits = 0;\n\tduk_bool_t neg_year = 0;\n\tduk_bool_t neg_tzoffset = 0;\n\tduk_uint_fast8_t ch;\n\tduk_small_uint_t i;\n\n\t/* During parsing, month and day are one-based; set defaults here. */\n\tDUK_MEMZERO(parts, sizeof(parts));\n\tDUK_ASSERT(parts[DUK_DATE_IDX_YEAR] == 0);  /* don't care value, year is mandatory */\n\tparts[DUK_DATE_IDX_MONTH] = 1;\n\tparts[DUK_DATE_IDX_DAY] = 1;\n\n\t/* Special handling for year sign. */\n\tp = (const duk_uint8_t *) str;\n\tch = p[0];\n\tif (ch == DUK_ASC_PLUS) {\n\t\tp++;\n\t} else if (ch == DUK_ASC_MINUS) {\n\t\tneg_year = 1;\n\t\tp++;\n\t}\n\n\tfor (;;) {\n\t\tch = *p++;\n\t\tDUK_DDD(DUK_DDDPRINT(\"parsing, part_idx=%ld, char=%ld ('%c')\",\n\t\t                     (long) part_idx, (long) ch,\n\t\t                     (int) ((ch >= 0x20 && ch <= 0x7e) ? ch : DUK_ASC_QUESTION)));\n\n\t\tif (ch >= DUK_ASC_0 && ch <= DUK_ASC_9) {\n\t\t\tif (ndigits >= 9) {\n\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"too many digits -> reject\"));\n\t\t\t\tgoto reject;\n\t\t\t}\n\t\t\tif (part_idx == DUK__PI_MILLISECOND && ndigits >= 3) {\n\t\t\t\t/* ignore millisecond fractions after 3 */\n\t\t\t} else {\n\t\t\t\taccum = accum * 10 + ((duk_int_t) ch) - ((duk_int_t) DUK_ASC_0) + 0x00;\n\t\t\t\tndigits++;\n\t\t\t}\n\t\t} else {\n\t\t\tduk_uint_fast32_t match_val;\n\t\t\tduk_small_uint_t sep_idx;\n\n\t\t\tif (ndigits <= 0) {\n\t\t\t\tgoto reject;\n\t\t\t}\n\t\t\tif (part_idx == DUK__PI_MILLISECOND) {\n\t\t\t\t/* complete the millisecond field */\n\t\t\t\twhile (ndigits < 3) {\n\t\t\t\t\taccum *= 10;\n\t\t\t\t\tndigits++;\n\t\t\t\t}\n\t\t\t}\n\t\t\tparts[part_idx] = accum;\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"wrote part %ld -> value %ld\", (long) part_idx, (long) accum));\n\n\t\t\taccum = 0;\n\t\t\tndigits = 0;\n\n\t\t\tfor (i = 0; i < (duk_small_uint_t) (sizeof(duk__parse_iso8601_seps) / sizeof(duk_uint8_t)); i++) {\n\t\t\t\tif (duk__parse_iso8601_seps[i] == ch) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (i == (duk_small_uint_t) (sizeof(duk__parse_iso8601_seps) / sizeof(duk_uint8_t))) {\n\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"separator character doesn't match -> reject\"));\n\t\t\t\tgoto reject;\n\t\t\t}\n\n\t\t\tsep_idx = i;\n\t\t\tmatch_val = (1UL << part_idx) + (1UL << (sep_idx + 9));  /* match against rule part/sep bits */\n\n\t\t\tfor (i = 0; i < (duk_small_uint_t) (sizeof(duk__parse_iso8601_control) / sizeof(duk_uint32_t)); i++) {\n\t\t\t\tduk_uint_fast32_t rule = duk__parse_iso8601_control[i];\n\t\t\t\tduk_small_uint_t nextpart;\n\t\t\t\tduk_small_uint_t cflags;\n\n\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"part_idx=%ld, sep_idx=%ld, match_val=0x%08lx, considering rule=0x%08lx\",\n\t\t\t\t                     (long) part_idx, (long) sep_idx,\n\t\t\t\t                     (unsigned long) match_val, (unsigned long) rule));\n\n\t\t\t\tif ((rule & match_val) != match_val) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tDUK__UNPACK_RULE(rule, nextpart, cflags);\n\n\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"rule match -> part_idx=%ld, sep_idx=%ld, match_val=0x%08lx, \"\n\t\t\t\t                     \"rule=0x%08lx -> nextpart=%ld, cflags=0x%02lx\",\n\t\t\t\t                     (long) part_idx, (long) sep_idx,\n\t\t\t\t                     (unsigned long) match_val, (unsigned long) rule,\n\t\t\t\t                     (long) nextpart, (unsigned long) cflags));\n\n\t\t\t\tif (cflags & DUK__CF_NEG) {\n\t\t\t\t\tneg_tzoffset = 1;\n\t\t\t\t}\n\n\t\t\t\tif (cflags & DUK__CF_ACCEPT) {\n\t\t\t\t\tgoto accept;\n\t\t\t\t}\n\n\t\t\t\tif (cflags & DUK__CF_ACCEPT_NUL) {\n\t\t\t\t\tDUK_ASSERT(*(p - 1) != (char) 0);\n\t\t\t\t\tif (*p == DUK_ASC_NUL) {\n\t\t\t\t\t\tgoto accept;\n\t\t\t\t\t}\n\t\t\t\t\tgoto reject;\n\t\t\t\t}\n\n\t\t\t\tpart_idx = nextpart;\n\t\t\t\tbreak;\n\t\t\t}  /* rule match */\n\n\t\t\tif (i == (duk_small_uint_t) (sizeof(duk__parse_iso8601_control) / sizeof(duk_uint32_t))) {\n\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"no rule matches -> reject\"));\n\t\t\t\tgoto reject;\n\t\t\t}\n\n\t\t\tif (ch == 0) {\n\t\t\t\t/* This shouldn't be necessary, but check just in case\n\t\t\t\t * to avoid any chance of overruns.\n\t\t\t\t */\n\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"NUL after rule matching (should not happen) -> reject\"));\n\t\t\t\tgoto reject;\n\t\t\t}\n\t\t}  /* if-digit-else-ctrl */\n\t}  /* char loop */\n\n\t/* We should never exit the loop above. */\n\tDUK_UNREACHABLE();\n\n reject:\n\tDUK_DDD(DUK_DDDPRINT(\"reject\"));\n\treturn 0;\n\n accept:\n\tDUK_DDD(DUK_DDDPRINT(\"accept\"));\n\n\t/* Apply timezone offset to get the main parts in UTC */\n\tif (neg_year) {\n\t\tparts[DUK__PI_YEAR] = -parts[DUK__PI_YEAR];\n\t}\n\tif (neg_tzoffset) {\n\t\tparts[DUK__PI_HOUR] += parts[DUK__PI_TZHOUR];\n\t\tparts[DUK__PI_MINUTE] += parts[DUK__PI_TZMINUTE];\n\t} else {\n\t\tparts[DUK__PI_HOUR] -= parts[DUK__PI_TZHOUR];\n\t\tparts[DUK__PI_MINUTE] -= parts[DUK__PI_TZMINUTE];\n\t}\n\tparts[DUK__PI_MONTH] -= 1;  /* zero-based month */\n\tparts[DUK__PI_DAY] -= 1;  /* zero-based day */\n\n\t/* Use double parts, they tolerate unnormalized time.\n\t *\n\t * Note: DUK_DATE_IDX_WEEKDAY is initialized with a bogus value (DUK__PI_TZHOUR)\n\t * on purpose.  It won't be actually used by duk_bi_date_get_timeval_from_dparts(),\n\t * but will make the value initialized just in case, and avoid any\n\t * potential for Valgrind issues.\n\t */\n\tfor (i = 0; i < DUK_DATE_IDX_NUM_PARTS; i++) {\n\t\tDUK_DDD(DUK_DDDPRINT(\"part[%ld] = %ld\", (long) i, (long) parts[i]));\n\t\tdparts[i] = parts[i];\n\t}\n\n\td = duk_bi_date_get_timeval_from_dparts(dparts, 0 /*flags*/);\n\tduk_push_number(thr, d);\n\treturn 1;\n}\n\n/*\n *  Date/time parsing helper.\n *\n *  Parse a datetime string into a time value.  We must first try to parse\n *  the input according to the standard format in E5.1 Section 15.9.1.15.\n *  If that fails, we can try to parse using custom parsing, which can\n *  either be platform neutral (custom code) or platform specific (using\n *  existing platform API calls).\n *\n *  Note in particular that we must parse whatever toString(), toUTCString(),\n *  and toISOString() can produce; see E5.1 Section 15.9.4.2.\n *\n *  Returns 1 to allow tail calling.\n *\n *  There is much room for improvement here with respect to supporting\n *  alternative datetime formats.  For instance, V8 parses '2012-01-01' as\n *  UTC and '2012/01/01' as local time.\n */\n\nDUK_LOCAL duk_ret_t duk__parse_string(duk_hthread *thr, const char *str) {\n\t/* XXX: there is a small risk here: because the ISO 8601 parser is\n\t * very loose, it may end up parsing some datetime values which\n\t * would be better parsed with a platform specific parser.\n\t */\n\n\tDUK_ASSERT(str != NULL);\n\tDUK_DDD(DUK_DDDPRINT(\"parse datetime from string '%s'\", (const char *) str));\n\n\tif (duk__parse_string_iso8601_subset(thr, str) != 0) {\n\t\treturn 1;\n\t}\n\n#if defined(DUK_USE_DATE_PARSE_STRING)\n\t/* Contract, either:\n\t * - Push value on stack and return 1\n\t * - Don't push anything on stack and return 0\n\t */\n\n\tif (DUK_USE_DATE_PARSE_STRING(thr, str) != 0) {\n\t\treturn 1;\n\t}\n#else\n\t/* No platform-specific parsing, this is not an error. */\n#endif\n\n\tduk_push_nan(thr);\n\treturn 1;\n}\n\n/*\n *  Calendar helpers\n *\n *  Some helpers are used for getters and can operate on normalized values\n *  which can be represented with 32-bit signed integers.  Other helpers are\n *  needed by setters and operate on un-normalized double values, must watch\n *  out for non-finite numbers etc.\n */\n\nDUK_LOCAL duk_uint8_t duk__days_in_month[12] = {\n\t(duk_uint8_t) 31, (duk_uint8_t) 28, (duk_uint8_t) 31, (duk_uint8_t) 30,\n\t(duk_uint8_t) 31, (duk_uint8_t) 30, (duk_uint8_t) 31, (duk_uint8_t) 31,\n\t(duk_uint8_t) 30, (duk_uint8_t) 31, (duk_uint8_t) 30, (duk_uint8_t) 31\n};\n\n/* Maximum iteration count for computing UTC-to-local time offset when\n * creating an Ecmascript time value from local parts.\n */\n#define DUK__LOCAL_TZOFFSET_MAXITER   4\n\n/* Because 'day since epoch' can be negative and is used to compute weekday\n * using a modulo operation, add this multiple of 7 to avoid negative values\n * when year is below 1970 epoch.  Ecmascript time values are restricted to\n * +/- 100 million days from epoch, so this adder fits nicely into 32 bits.\n * Round to a multiple of 7 (= floor(100000000 / 7) * 7) and add margin.\n */\n#define DUK__WEEKDAY_MOD_ADDER  (20000000 * 7)  /* 0x08583b00 */\n\nDUK_INTERNAL duk_bool_t duk_bi_date_is_leap_year(duk_int_t year) {\n\tif ((year % 4) != 0) {\n\t\treturn 0;\n\t}\n\tif ((year % 100) != 0) {\n\t\treturn 1;\n\t}\n\tif ((year % 400) != 0) {\n\t\treturn 0;\n\t}\n\treturn 1;\n}\n\nDUK_INTERNAL duk_bool_t duk_bi_date_timeval_in_valid_range(duk_double_t x) {\n\treturn (x >= -DUK_DATE_MSEC_100M_DAYS && x <= DUK_DATE_MSEC_100M_DAYS);\n}\n\nDUK_INTERNAL duk_bool_t duk_bi_date_timeval_in_leeway_range(duk_double_t x) {\n\treturn (x >= -DUK_DATE_MSEC_100M_DAYS_LEEWAY && x <= DUK_DATE_MSEC_100M_DAYS_LEEWAY);\n}\n\nDUK_INTERNAL duk_bool_t duk_bi_date_year_in_valid_range(duk_double_t x) {\n\treturn (x >= DUK_DATE_MIN_ECMA_YEAR && x <= DUK_DATE_MAX_ECMA_YEAR);\n}\n\nDUK_LOCAL duk_double_t duk__timeclip(duk_double_t x) {\n\tif (!DUK_ISFINITE(x)) {\n\t\treturn DUK_DOUBLE_NAN;\n\t}\n\n\tif (!duk_bi_date_timeval_in_valid_range(x)) {\n\t\treturn DUK_DOUBLE_NAN;\n\t}\n\n\tx = duk_js_tointeger_number(x);\n\n\t/* Here we'd have the option to normalize -0 to +0. */\n\treturn x;\n}\n\n/* Integer division which floors also negative values correctly. */\nDUK_LOCAL duk_int_t duk__div_floor(duk_int_t a, duk_int_t b) {\n\tDUK_ASSERT(b > 0);\n\tif (a >= 0) {\n\t\treturn a / b;\n\t} else {\n\t\t/* e.g. a = -4, b = 5  -->  -4 - 5 + 1 / 5  -->  -8 / 5  -->  -1\n\t\t *      a = -5, b = 5  -->  -5 - 5 + 1 / 5  -->  -9 / 5  -->  -1\n\t\t *      a = -6, b = 5  -->  -6 - 5 + 1 / 5  -->  -10 / 5  -->  -2\n\t\t */\n\t\treturn (a - b + 1) / b;\n\t}\n}\n\n/* Compute day number of the first day of a given year. */\nDUK_LOCAL duk_int_t duk__day_from_year(duk_int_t year) {\n\t/* Note: in integer arithmetic, (x / 4) is same as floor(x / 4) for non-negative\n\t * values, but is incorrect for negative ones.\n\t */\n\treturn 365 * (year - 1970)\n\t       + duk__div_floor(year - 1969, 4)\n\t       - duk__div_floor(year - 1901, 100)\n\t       + duk__div_floor(year - 1601, 400);\n}\n\n/* Given a day number, determine year and day-within-year. */\nDUK_LOCAL duk_int_t duk__year_from_day(duk_int_t day, duk_small_int_t *out_day_within_year) {\n\tduk_int_t year;\n\tduk_int_t diff_days;\n\n\t/* estimate year upwards (towards positive infinity), then back down;\n\t * two iterations should be enough\n\t */\n\n\tif (day >= 0) {\n\t\tyear = 1970 + day / 365;\n\t} else {\n\t\tyear = 1970 + day / 366;\n\t}\n\n\tfor (;;) {\n\t\tdiff_days = duk__day_from_year(year) - day;\n\t\tDUK_DDD(DUK_DDDPRINT(\"year=%ld day=%ld, diff_days=%ld\", (long) year, (long) day, (long) diff_days));\n\t\tif (diff_days <= 0) {\n\t\t\tDUK_ASSERT(-diff_days < 366);  /* fits into duk_small_int_t */\n\t\t\t*out_day_within_year = -diff_days;\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"--> year=%ld, day-within-year=%ld\",\n\t\t\t                     (long) year, (long) *out_day_within_year));\n\t\t\tDUK_ASSERT(*out_day_within_year >= 0);\n\t\t\tDUK_ASSERT(*out_day_within_year < (duk_bi_date_is_leap_year(year) ? 366 : 365));\n\t\t\treturn year;\n\t\t}\n\n\t\t/* Note: this is very tricky; we must never 'overshoot' the\n\t\t * correction downwards.\n\t\t */\n\t\tyear -= 1 + (diff_days - 1) / 366;  /* conservative */\n\t}\n}\n\n/* Given a (year, month, day-within-month) triple, compute day number.\n * The input triple is un-normalized and may contain non-finite values.\n */\nDUK_LOCAL duk_double_t duk__make_day(duk_double_t year, duk_double_t month, duk_double_t day) {\n\tduk_int_t day_num;\n\tduk_bool_t is_leap;\n\tduk_small_int_t i, n;\n\n\t/* Assume that year, month, day are all coerced to whole numbers.\n\t * They may also be NaN or infinity, in which case this function\n\t * must return NaN or infinity to ensure time value becomes NaN.\n\t * If 'day' is NaN, the final return will end up returning a NaN,\n\t * so it doesn't need to be checked here.\n\t */\n\n\tif (!DUK_ISFINITE(year) || !DUK_ISFINITE(month)) {\n\t\treturn DUK_DOUBLE_NAN;\n\t}\n\n\tyear += DUK_FLOOR(month / 12.0);\n\n\tmonth = DUK_FMOD(month, 12.0);\n\tif (month < 0.0) {\n\t\t/* handle negative values */\n\t\tmonth += 12.0;\n\t}\n\n\t/* The algorithm in E5.1 Section 15.9.1.12 normalizes month, but\n\t * does not normalize the day-of-month (nor check whether or not\n\t * it is finite) because it's not necessary for finding the day\n\t * number which matches the (year,month) pair.\n\t *\n\t * We assume that duk__day_from_year() is exact here.\n\t *\n\t * Without an explicit infinity / NaN check in the beginning,\n\t * day_num would be a bogus integer here.\n\t *\n\t * It's possible for 'year' to be out of integer range here.\n\t * If so, we need to return NaN without integer overflow.\n\t * This fixes test-bug-setyear-overflow.js.\n\t */\n\n\tif (!duk_bi_date_year_in_valid_range(year)) {\n\t\tDUK_DD(DUK_DDPRINT(\"year not in ecmascript valid range, avoid integer overflow: %lf\", (double) year));\n\t\treturn DUK_DOUBLE_NAN;\n\t}\n\tday_num = duk__day_from_year((duk_int_t) year);\n\tis_leap = duk_bi_date_is_leap_year((duk_int_t) year);\n\n\tn = (duk_small_int_t) month;\n\tfor (i = 0; i < n; i++) {\n\t\tday_num += duk__days_in_month[i];\n\t\tif (i == 1 && is_leap) {\n\t\t\tday_num++;\n\t\t}\n\t}\n\n\t/* If 'day' is NaN, returns NaN. */\n\treturn (duk_double_t) day_num + day;\n}\n\n/* Split time value into parts.  The time value may contain fractions (it may\n * come from duk_time_to_components() API call) which are truncated.  Possible\n * local time adjustment has already been applied when reading the time value.\n */\nDUK_INTERNAL void duk_bi_date_timeval_to_parts(duk_double_t d, duk_int_t *parts, duk_double_t *dparts, duk_small_uint_t flags) {\n\tduk_double_t d1, d2;\n\tduk_int_t t1, t2;\n\tduk_int_t day_since_epoch;\n\tduk_int_t year;  /* does not fit into 16 bits */\n\tduk_small_int_t day_in_year;\n\tduk_small_int_t month;\n\tduk_small_int_t day;\n\tduk_small_int_t dim;\n\tduk_int_t jan1_since_epoch;\n\tduk_small_int_t jan1_weekday;\n\tduk_int_t equiv_year;\n\tduk_small_uint_t i;\n\tduk_bool_t is_leap;\n\tduk_small_int_t arridx;\n\n\tDUK_ASSERT(DUK_ISFINITE(d));    /* caller checks */\n\td = DUK_FLOOR(d);  /* remove fractions if present */\n\tDUK_ASSERT(DUK_FLOOR(d) == d);\n\n\t/* The timevalue must be in valid Ecmascript range, but since a local\n\t * time offset can be applied, we need to allow a +/- 24h leeway to\n\t * the value.  In other words, although the UTC time is within the\n\t * Ecmascript range, the local part values can be just outside of it.\n\t */\n\tDUK_UNREF(duk_bi_date_timeval_in_leeway_range);\n\tDUK_ASSERT(duk_bi_date_timeval_in_leeway_range(d));\n\n\t/* These computations are guaranteed to be exact for the valid\n\t * E5 time value range, assuming milliseconds without fractions.\n\t */\n\td1 = (duk_double_t) DUK_FMOD(d, (double) DUK_DATE_MSEC_DAY);\n\tif (d1 < 0.0) {\n\t\t/* deal with negative values */\n\t\td1 += (duk_double_t) DUK_DATE_MSEC_DAY;\n\t}\n\td2 = DUK_FLOOR((double) (d / (duk_double_t) DUK_DATE_MSEC_DAY));\n\tDUK_ASSERT(d2 * ((duk_double_t) DUK_DATE_MSEC_DAY) + d1 == d);\n\t/* now expected to fit into a 32-bit integer */\n\tt1 = (duk_int_t) d1;\n\tt2 = (duk_int_t) d2;\n\tday_since_epoch = t2;\n\tDUK_ASSERT((duk_double_t) t1 == d1);\n\tDUK_ASSERT((duk_double_t) t2 == d2);\n\n\t/* t1 = milliseconds within day (fits 32 bit)\n\t * t2 = day number from epoch (fits 32 bit, may be negative)\n\t */\n\n\tparts[DUK_DATE_IDX_MILLISECOND] = t1 % 1000; t1 /= 1000;\n\tparts[DUK_DATE_IDX_SECOND] = t1 % 60; t1 /= 60;\n\tparts[DUK_DATE_IDX_MINUTE] = t1 % 60; t1 /= 60;\n\tparts[DUK_DATE_IDX_HOUR] = t1;\n\tDUK_ASSERT(parts[DUK_DATE_IDX_MILLISECOND] >= 0 && parts[DUK_DATE_IDX_MILLISECOND] <= 999);\n\tDUK_ASSERT(parts[DUK_DATE_IDX_SECOND] >= 0 && parts[DUK_DATE_IDX_SECOND] <= 59);\n\tDUK_ASSERT(parts[DUK_DATE_IDX_MINUTE] >= 0 && parts[DUK_DATE_IDX_MINUTE] <= 59);\n\tDUK_ASSERT(parts[DUK_DATE_IDX_HOUR] >= 0 && parts[DUK_DATE_IDX_HOUR] <= 23);\n\n\tDUK_DDD(DUK_DDDPRINT(\"d=%lf, d1=%lf, d2=%lf, t1=%ld, t2=%ld, parts: hour=%ld min=%ld sec=%ld msec=%ld\",\n\t                     (double) d, (double) d1, (double) d2, (long) t1, (long) t2,\n\t                     (long) parts[DUK_DATE_IDX_HOUR],\n\t                     (long) parts[DUK_DATE_IDX_MINUTE],\n\t                     (long) parts[DUK_DATE_IDX_SECOND],\n\t                     (long) parts[DUK_DATE_IDX_MILLISECOND]));\n\n\t/* This assert depends on the input parts representing time inside\n\t * the Ecmascript range.\n\t */\n\tDUK_ASSERT(t2 + DUK__WEEKDAY_MOD_ADDER >= 0);\n\tparts[DUK_DATE_IDX_WEEKDAY] = (t2 + 4 + DUK__WEEKDAY_MOD_ADDER) % 7;  /* E5.1 Section 15.9.1.6 */\n\tDUK_ASSERT(parts[DUK_DATE_IDX_WEEKDAY] >= 0 && parts[DUK_DATE_IDX_WEEKDAY] <= 6);\n\n\tyear = duk__year_from_day(t2, &day_in_year);\n\tday = day_in_year;\n\tis_leap = duk_bi_date_is_leap_year(year);\n\tfor (month = 0; month < 12; month++) {\n\t\tdim = duk__days_in_month[month];\n\t\tif (month == 1 && is_leap) {\n\t\t\tdim++;\n\t\t}\n\t\tDUK_DDD(DUK_DDDPRINT(\"month=%ld, dim=%ld, day=%ld\",\n\t\t                     (long) month, (long) dim, (long) day));\n\t\tif (day < dim) {\n\t\t\tbreak;\n\t\t}\n\t\tday -= dim;\n\t}\n\tDUK_DDD(DUK_DDDPRINT(\"final month=%ld\", (long) month));\n\tDUK_ASSERT(month >= 0 && month <= 11);\n\tDUK_ASSERT(day >= 0 && day <= 31);\n\n\t/* Equivalent year mapping, used to avoid DST trouble when platform\n\t * may fail to provide reasonable DST answers for dates outside the\n\t * ordinary range (e.g. 1970-2038).  An equivalent year has the same\n\t * leap-year-ness as the original year and begins on the same weekday\n\t * (Jan 1).\n\t *\n\t * The year 2038 is avoided because there seem to be problems with it\n\t * on some platforms.  The year 1970 is also avoided as there were\n\t * practical problems with it; an equivalent year is used for it too,\n\t * which breaks some DST computations for 1970 right now, see e.g.\n\t * test-bi-date-tzoffset-brute-fi.js.\n\t */\n\tif ((flags & DUK_DATE_FLAG_EQUIVYEAR) && (year < 1971 || year > 2037)) {\n\t\tDUK_ASSERT(is_leap == 0 || is_leap == 1);\n\n\t\tjan1_since_epoch = day_since_epoch - day_in_year;  /* day number for Jan 1 since epoch */\n\t\tDUK_ASSERT(jan1_since_epoch + DUK__WEEKDAY_MOD_ADDER >= 0);\n\t\tjan1_weekday = (jan1_since_epoch + 4 + DUK__WEEKDAY_MOD_ADDER) % 7;  /* E5.1 Section 15.9.1.6 */\n\t\tDUK_ASSERT(jan1_weekday >= 0 && jan1_weekday <= 6);\n\t\tarridx = jan1_weekday;\n\t\tif (is_leap) {\n\t\t\tarridx += 7;\n\t\t}\n\t\tDUK_ASSERT(arridx >= 0 && arridx < (duk_small_int_t) (sizeof(duk__date_equivyear) / sizeof(duk_uint8_t)));\n\n\t\tequiv_year = (duk_int_t) duk__date_equivyear[arridx] + 1970;\n\t\tyear = equiv_year;\n\t\tDUK_DDD(DUK_DDDPRINT(\"equiv year mapping, year=%ld, day_in_year=%ld, day_since_epoch=%ld, \"\n\t\t                     \"jan1_since_epoch=%ld, jan1_weekday=%ld -> equiv year %ld\",\n\t\t                     (long) year, (long) day_in_year, (long) day_since_epoch,\n\t\t                     (long) jan1_since_epoch, (long) jan1_weekday, (long) equiv_year));\n\t}\n\n\tparts[DUK_DATE_IDX_YEAR] = year;\n\tparts[DUK_DATE_IDX_MONTH] = month;\n\tparts[DUK_DATE_IDX_DAY] = day;\n\n\tif (flags & DUK_DATE_FLAG_ONEBASED) {\n\t\tparts[DUK_DATE_IDX_MONTH]++;  /* zero-based -> one-based */\n\t\tparts[DUK_DATE_IDX_DAY]++;    /* -\"\"- */\n\t}\n\n\tif (dparts != NULL) {\n\t\tfor (i = 0; i < DUK_DATE_IDX_NUM_PARTS; i++) {\n\t\t\tdparts[i] = (duk_double_t) parts[i];\n\t\t}\n\t}\n}\n\n/* Compute time value from (double) parts.  The parts can be either UTC\n * or local time; if local, they need to be (conceptually) converted into\n * UTC time.  The parts may represent valid or invalid time, and may be\n * wildly out of range (but may cancel each other and still come out in\n * the valid Date range).\n */\nDUK_INTERNAL duk_double_t duk_bi_date_get_timeval_from_dparts(duk_double_t *dparts, duk_small_uint_t flags) {\n#if defined(DUK_USE_PARANOID_DATE_COMPUTATION)\n\t/* See comments below on MakeTime why these are volatile. */\n\tvolatile duk_double_t tmp_time;\n\tvolatile duk_double_t tmp_day;\n\tvolatile duk_double_t d;\n#else\n\tduk_double_t tmp_time;\n\tduk_double_t tmp_day;\n\tduk_double_t d;\n#endif\n\tduk_small_uint_t i;\n\tduk_int_t tzoff, tzoffprev1, tzoffprev2;\n\n\t/* Expects 'this' at top of stack on entry. */\n\n\t/* Coerce all finite parts with ToInteger().  ToInteger() must not\n\t * be called for NaN/Infinity because it will convert e.g. NaN to\n\t * zero.  If ToInteger() has already been called, this has no side\n\t * effects and is idempotent.\n\t *\n\t * Don't read dparts[DUK_DATE_IDX_WEEKDAY]; it will cause Valgrind\n\t * issues if the value is uninitialized.\n\t */\n\tfor (i = 0; i <= DUK_DATE_IDX_MILLISECOND; i++) {\n\t\t/* SCANBUILD: scan-build complains here about assigned value\n\t\t * being garbage or undefined.  This is correct but operating\n\t\t * on undefined values has no ill effect and is ignored by the\n\t\t * caller in the case where this happens.\n\t\t */\n\t\td = dparts[i];\n\t\tif (DUK_ISFINITE(d)) {\n\t\t\tdparts[i] = duk_js_tointeger_number(d);\n\t\t}\n\t}\n\n\t/* Use explicit steps in computation to try to ensure that\n\t * computation happens with intermediate results coerced to\n\t * double values (instead of using something more accurate).\n\t * E.g. E5.1 Section 15.9.1.11 requires use of IEEE 754\n\t * rules (= Ecmascript '+' and '*' operators).\n\t *\n\t * Without 'volatile' even this approach fails on some platform\n\t * and compiler combinations.  For instance, gcc 4.8.1 on Ubuntu\n\t * 64-bit, with -m32 and without -std=c99, test-bi-date-canceling.js\n\t * would fail because of some optimizations when computing tmp_time\n\t * (MakeTime below).  Adding 'volatile' to tmp_time solved this\n\t * particular problem (annoyingly, also adding debug prints or\n\t * running the executable under valgrind hides it).\n\t */\n\n\t/* MakeTime */\n\ttmp_time = 0.0;\n\ttmp_time += dparts[DUK_DATE_IDX_HOUR] * ((duk_double_t) DUK_DATE_MSEC_HOUR);\n\ttmp_time += dparts[DUK_DATE_IDX_MINUTE] * ((duk_double_t) DUK_DATE_MSEC_MINUTE);\n\ttmp_time += dparts[DUK_DATE_IDX_SECOND] * ((duk_double_t) DUK_DATE_MSEC_SECOND);\n\ttmp_time += dparts[DUK_DATE_IDX_MILLISECOND];\n\n\t/* MakeDay */\n\ttmp_day = duk__make_day(dparts[DUK_DATE_IDX_YEAR], dparts[DUK_DATE_IDX_MONTH], dparts[DUK_DATE_IDX_DAY]);\n\n\t/* MakeDate */\n\td = tmp_day * ((duk_double_t) DUK_DATE_MSEC_DAY) + tmp_time;\n\n\tDUK_DDD(DUK_DDDPRINT(\"time=%lf day=%lf --> timeval=%lf\",\n\t                     (double) tmp_time, (double) tmp_day, (double) d));\n\n\t/* Optional UTC conversion. */\n\tif (flags & DUK_DATE_FLAG_LOCALTIME) {\n\t\t/* DUK_USE_DATE_GET_LOCAL_TZOFFSET() needs to be called with a\n\t\t * time value computed from UTC parts.  At this point we only\n\t\t * have 'd' which is a time value computed from local parts, so\n\t\t * it is off by the UTC-to-local time offset which we don't know\n\t\t * yet.  The current solution for computing the UTC-to-local\n\t\t * time offset is to iterate a few times and detect a fixed\n\t\t * point or a two-cycle loop (or a sanity iteration limit),\n\t\t * see test-bi-date-local-parts.js and test-bi-date-tzoffset-basic-fi.js.\n\t\t *\n\t\t * E5.1 Section 15.9.1.9:\n\t\t * UTC(t) = t - LocalTZA - DaylightSavingTA(t - LocalTZA)\n\t\t *\n\t\t * For NaN/inf, DUK_USE_DATE_GET_LOCAL_TZOFFSET() returns 0.\n\t\t */\n\n#if 0\n\t\t/* Old solution: don't iterate, incorrect */\n\t\ttzoff = DUK_USE_DATE_GET_LOCAL_TZOFFSET(d);\n\t\tDUK_DDD(DUK_DDDPRINT(\"tzoffset w/o iteration, tzoff=%ld\", (long) tzoff));\n\t\td -= tzoff * 1000L;\n\t\tDUK_UNREF(tzoffprev1);\n\t\tDUK_UNREF(tzoffprev2);\n#endif\n\n\t\t/* Iteration solution */\n\t\ttzoff = 0;\n\t\ttzoffprev1 = 999999999L;  /* invalid value which never matches */\n\t\tfor (i = 0; i < DUK__LOCAL_TZOFFSET_MAXITER; i++) {\n\t\t\ttzoffprev2 = tzoffprev1;\n\t\t\ttzoffprev1 = tzoff;\n\t\t\ttzoff = DUK_USE_DATE_GET_LOCAL_TZOFFSET(d - tzoff * 1000L);\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"tzoffset iteration, i=%d, tzoff=%ld, tzoffprev1=%ld tzoffprev2=%ld\",\n\t\t\t                     (int) i, (long) tzoff, (long) tzoffprev1, (long) tzoffprev2));\n\t\t\tif (tzoff == tzoffprev1) {\n\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"tzoffset iteration finished, i=%d, tzoff=%ld, tzoffprev1=%ld, tzoffprev2=%ld\",\n\t\t\t\t                     (int) i, (long) tzoff, (long) tzoffprev1, (long) tzoffprev2));\n\t\t\t\tbreak;\n\t\t\t} else if (tzoff == tzoffprev2) {\n\t\t\t\t/* Two value cycle, see e.g. test-bi-date-tzoffset-basic-fi.js.\n\t\t\t\t * In these cases, favor a higher tzoffset to get a consistent\n\t\t\t\t * result which is independent of iteration count.  Not sure if\n\t\t\t\t * this is a generically correct solution.\n\t\t\t\t */\n\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"tzoffset iteration two-value cycle, i=%d, tzoff=%ld, tzoffprev1=%ld, tzoffprev2=%ld\",\n\t\t\t\t                     (int) i, (long) tzoff, (long) tzoffprev1, (long) tzoffprev2));\n\t\t\t\tif (tzoffprev1 > tzoff) {\n\t\t\t\t\ttzoff = tzoffprev1;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tDUK_DDD(DUK_DDDPRINT(\"tzoffset iteration, tzoff=%ld\", (long) tzoff));\n\t\td -= tzoff * 1000L;\n\t}\n\n\t/* TimeClip(), which also handles Infinity -> NaN conversion */\n\td = duk__timeclip(d);\n\n\treturn d;\n}\n\n/*\n *  API oriented helpers\n */\n\n/* Push 'this' binding, check that it is a Date object; then push the\n * internal time value.  At the end, stack is: [ ... this timeval ].\n * Returns the time value.  Local time adjustment is done if requested.\n */\nDUK_LOCAL duk_double_t duk__push_this_get_timeval_tzoffset(duk_hthread *thr, duk_small_uint_t flags, duk_int_t *out_tzoffset) {\n\tduk_hobject *h;\n\tduk_double_t d;\n\tduk_int_t tzoffset = 0;\n\n\tduk_push_this(thr);\n\th = duk_get_hobject(thr, -1);  /* XXX: getter with class check, useful in built-ins */\n\tif (h == NULL || DUK_HOBJECT_GET_CLASS_NUMBER(h) != DUK_HOBJECT_CLASS_DATE) {\n\t\tDUK_ERROR_TYPE(thr, \"expected Date\");\n\t}\n\n\tduk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INT_VALUE);\n\td = duk_to_number_m1(thr);\n\tduk_pop(thr);\n\n\tif (DUK_ISNAN(d)) {\n\t\tif (flags & DUK_DATE_FLAG_NAN_TO_ZERO) {\n\t\t\td = 0.0;\n\t\t}\n\t\tif (flags & DUK_DATE_FLAG_NAN_TO_RANGE_ERROR) {\n\t\t\tDUK_ERROR_RANGE(thr, \"Invalid Date\");\n\t\t}\n\t}\n\t/* if no NaN handling flag, may still be NaN here, but not Inf */\n\tDUK_ASSERT(!DUK_ISINF(d));\n\n\tif (flags & DUK_DATE_FLAG_LOCALTIME) {\n\t\t/* Note: DST adjustment is determined using UTC time.\n\t\t * If 'd' is NaN, tzoffset will be 0.\n\t\t */\n\t\ttzoffset = DUK_USE_DATE_GET_LOCAL_TZOFFSET(d);  /* seconds */\n\t\td += tzoffset * 1000L;\n\t}\n\tif (out_tzoffset) {\n\t\t*out_tzoffset = tzoffset;\n\t}\n\n\t/* [ ... this ] */\n\treturn d;\n}\n\nDUK_LOCAL duk_double_t duk__push_this_get_timeval(duk_hthread *thr, duk_small_uint_t flags) {\n\treturn duk__push_this_get_timeval_tzoffset(thr, flags, NULL);\n}\n\n/* Set timeval to 'this' from dparts, push the new time value onto the\n * value stack and return 1 (caller can then tail call us).  Expects\n * the value stack to contain 'this' on the stack top.\n */\nDUK_LOCAL duk_ret_t duk__set_this_timeval_from_dparts(duk_hthread *thr, duk_double_t *dparts, duk_small_uint_t flags) {\n\tduk_double_t d;\n\n\t/* [ ... this ] */\n\n\td = duk_bi_date_get_timeval_from_dparts(dparts, flags);\n\tduk_push_number(thr, d);  /* -> [ ... this timeval_new ] */\n\tduk_dup_top(thr);         /* -> [ ... this timeval_new timeval_new ] */\n\tduk_put_prop_stridx_short(thr, -3, DUK_STRIDX_INT_VALUE);\n\n\t/* stack top: new time value, return 1 to allow tail calls */\n\treturn 1;\n}\n\n/* 'out_buf' must be at least DUK_BI_DATE_ISO8601_BUFSIZE long. */\nDUK_LOCAL void duk__format_parts_iso8601(duk_int_t *parts, duk_int_t tzoffset, duk_small_uint_t flags, duk_uint8_t *out_buf) {\n\tchar yearstr[8];   /* \"-123456\\0\" */\n\tchar tzstr[8];     /* \"+11:22\\0\" */\n\tchar sep = (flags & DUK_DATE_FLAG_SEP_T) ? DUK_ASC_UC_T : DUK_ASC_SPACE;\n\n\tDUK_ASSERT(parts[DUK_DATE_IDX_MONTH] >= 1 && parts[DUK_DATE_IDX_MONTH] <= 12);\n\tDUK_ASSERT(parts[DUK_DATE_IDX_DAY] >= 1 && parts[DUK_DATE_IDX_DAY] <= 31);\n\tDUK_ASSERT(parts[DUK_DATE_IDX_YEAR] >= -999999 && parts[DUK_DATE_IDX_YEAR] <= 999999);\n\n\t/* Note: %06d for positive value, %07d for negative value to include\n\t * sign and 6 digits.\n\t */\n\tDUK_SNPRINTF(yearstr,\n\t             sizeof(yearstr),\n\t             (parts[DUK_DATE_IDX_YEAR] >= 0 && parts[DUK_DATE_IDX_YEAR] <= 9999) ? \"%04ld\" :\n\t                    ((parts[DUK_DATE_IDX_YEAR] >= 0) ? \"+%06ld\" : \"%07ld\"),\n\t             (long) parts[DUK_DATE_IDX_YEAR]);\n\tyearstr[sizeof(yearstr) - 1] = (char) 0;\n\n\tif (flags & DUK_DATE_FLAG_LOCALTIME) {\n\t\t/* tzoffset seconds are dropped; 16 bits suffice for\n\t\t * time offset in minutes\n\t\t */\n\t\tconst char *fmt;\n\t\tduk_small_int_t tmp, arg_hours, arg_minutes;\n\n\t\tif (tzoffset >= 0) {\n\t\t\ttmp = tzoffset;\n\t\t\tfmt = \"+%02d:%02d\";\n\t\t} else {\n\t\t\ttmp = -tzoffset;\n\t\t\tfmt = \"-%02d:%02d\";\n\t\t}\n\t\ttmp = tmp / 60;\n\t\targ_hours = tmp / 60;\n\t\targ_minutes = tmp % 60;\n\t\tDUK_ASSERT(arg_hours <= 24);  /* Even less is actually guaranteed for a valid tzoffset. */\n\t\targ_hours = arg_hours & 0x3f;  /* For [0,24] this is a no-op, but fixes GCC 7 warning, see https://github.com/svaarala/duktape/issues/1602. */\n\n\t\tDUK_SNPRINTF(tzstr, sizeof(tzstr), fmt, (int) arg_hours, (int) arg_minutes);\n\t\ttzstr[sizeof(tzstr) - 1] = (char) 0;\n\t} else {\n\t\ttzstr[0] = DUK_ASC_UC_Z;\n\t\ttzstr[1] = (char) 0;\n\t}\n\n\t/* Unlike year, the other parts fit into 16 bits so %d format\n\t * is portable.\n\t */\n\tif ((flags & DUK_DATE_FLAG_TOSTRING_DATE) && (flags & DUK_DATE_FLAG_TOSTRING_TIME)) {\n\t\tDUK_SPRINTF((char *) out_buf, \"%s-%02d-%02d%c%02d:%02d:%02d.%03d%s\",\n\t\t            (const char *) yearstr, (int) parts[DUK_DATE_IDX_MONTH], (int) parts[DUK_DATE_IDX_DAY], (int) sep,\n\t\t            (int) parts[DUK_DATE_IDX_HOUR], (int) parts[DUK_DATE_IDX_MINUTE],\n\t\t            (int) parts[DUK_DATE_IDX_SECOND], (int) parts[DUK_DATE_IDX_MILLISECOND], (const char *) tzstr);\n\t} else if (flags & DUK_DATE_FLAG_TOSTRING_DATE) {\n\t\tDUK_SPRINTF((char *) out_buf, \"%s-%02d-%02d\",\n\t\t            (const char *) yearstr, (int) parts[DUK_DATE_IDX_MONTH], (int) parts[DUK_DATE_IDX_DAY]);\n\t} else {\n\t\tDUK_ASSERT(flags & DUK_DATE_FLAG_TOSTRING_TIME);\n\t\tDUK_SPRINTF((char *) out_buf, \"%02d:%02d:%02d.%03d%s\",\n\t\t            (int) parts[DUK_DATE_IDX_HOUR], (int) parts[DUK_DATE_IDX_MINUTE],\n\t\t            (int) parts[DUK_DATE_IDX_SECOND], (int) parts[DUK_DATE_IDX_MILLISECOND],\n\t\t            (const char *) tzstr);\n\t}\n}\n\n/* Helper for string conversion calls: check 'this' binding, get the\n * internal time value, and format date and/or time in a few formats.\n * Return value allows tail calls.\n */\nDUK_LOCAL duk_ret_t duk__to_string_helper(duk_hthread *thr, duk_small_uint_t flags) {\n\tduk_double_t d;\n\tduk_int_t parts[DUK_DATE_IDX_NUM_PARTS];\n\tduk_int_t tzoffset;  /* seconds, doesn't fit into 16 bits */\n\tduk_bool_t rc;\n\tduk_uint8_t buf[DUK_BI_DATE_ISO8601_BUFSIZE];\n\n\tDUK_UNREF(rc);  /* unreferenced with some options */\n\n\td = duk__push_this_get_timeval_tzoffset(thr, flags, &tzoffset);\n\tif (DUK_ISNAN(d)) {\n\t\tduk_push_hstring_stridx(thr, DUK_STRIDX_INVALID_DATE);\n\t\treturn 1;\n\t}\n\tDUK_ASSERT(DUK_ISFINITE(d));\n\n\t/* formatters always get one-based month/day-of-month */\n\tduk_bi_date_timeval_to_parts(d, parts, NULL, DUK_DATE_FLAG_ONEBASED);\n\tDUK_ASSERT(parts[DUK_DATE_IDX_MONTH] >= 1 && parts[DUK_DATE_IDX_MONTH] <= 12);\n\tDUK_ASSERT(parts[DUK_DATE_IDX_DAY] >= 1 && parts[DUK_DATE_IDX_DAY] <= 31);\n\n\tif (flags & DUK_DATE_FLAG_TOSTRING_LOCALE) {\n\t\t/* try locale specific formatter; if it refuses to format the\n\t\t * string, fall back to an ISO 8601 formatted value in local\n\t\t * time.\n\t\t */\n#if defined(DUK_USE_DATE_FORMAT_STRING)\n\t\t/* Contract, either:\n\t\t * - Push string to value stack and return 1\n\t\t * - Don't push anything and return 0\n\t\t */\n\n\t\trc = DUK_USE_DATE_FORMAT_STRING(thr, parts, tzoffset, flags);\n\t\tif (rc != 0) {\n\t\t\treturn 1;\n\t\t}\n#else\n\t\t/* No locale specific formatter; this is OK, we fall back\n\t\t * to ISO 8601.\n\t\t */\n#endif\n\t}\n\n\t/* Different calling convention than above used because the helper\n\t * is shared.\n\t */\n\tduk__format_parts_iso8601(parts, tzoffset, flags, buf);\n\tduk_push_string(thr, (const char *) buf);\n\treturn 1;\n}\n\n/* Helper for component getter calls: check 'this' binding, get the\n * internal time value, split it into parts (either as UTC time or\n * local time), push a specified component as a return value to the\n * value stack and return 1 (caller can then tail call us).\n */\nDUK_LOCAL duk_ret_t duk__get_part_helper(duk_hthread *thr, duk_small_uint_t flags_and_idx) {\n\tduk_double_t d;\n\tduk_int_t parts[DUK_DATE_IDX_NUM_PARTS];\n\tduk_small_uint_t idx_part = (duk_small_uint_t) (flags_and_idx >> DUK_DATE_FLAG_VALUE_SHIFT);  /* unpack args */\n\n\tDUK_ASSERT_DISABLE(idx_part >= 0);  /* unsigned */\n\tDUK_ASSERT(idx_part < DUK_DATE_IDX_NUM_PARTS);\n\n\td = duk__push_this_get_timeval(thr, flags_and_idx);\n\tif (DUK_ISNAN(d)) {\n\t\tduk_push_nan(thr);\n\t\treturn 1;\n\t}\n\tDUK_ASSERT(DUK_ISFINITE(d));\n\n\tduk_bi_date_timeval_to_parts(d, parts, NULL, flags_and_idx);  /* no need to mask idx portion */\n\n\t/* Setter APIs detect special year numbers (0...99) and apply a +1900\n\t * only in certain cases.  The legacy getYear() getter applies -1900\n\t * unconditionally.\n\t */\n\tduk_push_int(thr, (flags_and_idx & DUK_DATE_FLAG_SUB1900) ? parts[idx_part] - 1900 : parts[idx_part]);\n\treturn 1;\n}\n\n/* Helper for component setter calls: check 'this' binding, get the\n * internal time value, split it into parts (either as UTC time or\n * local time), modify one or more components as specified, recompute\n * the time value, set it as the internal value.  Finally, push the\n * new time value as a return value to the value stack and return 1\n * (caller can then tail call us).\n */\nDUK_LOCAL duk_ret_t duk__set_part_helper(duk_hthread *thr, duk_small_uint_t flags_and_maxnargs) {\n\tduk_double_t d;\n\tduk_int_t parts[DUK_DATE_IDX_NUM_PARTS];\n\tduk_double_t dparts[DUK_DATE_IDX_NUM_PARTS];\n\tduk_idx_t nargs;\n\tduk_small_uint_t maxnargs = (duk_small_uint_t) (flags_and_maxnargs >> DUK_DATE_FLAG_VALUE_SHIFT);  /* unpack args */\n\tduk_small_uint_t idx_first, idx;\n\tduk_small_uint_t i;\n\n\tnargs = duk_get_top(thr);\n\td = duk__push_this_get_timeval(thr, flags_and_maxnargs);\n\tDUK_ASSERT(DUK_ISFINITE(d) || DUK_ISNAN(d));\n\n\tif (DUK_ISFINITE(d)) {\n\t\tduk_bi_date_timeval_to_parts(d, parts, dparts, flags_and_maxnargs);\n\t} else {\n\t\t/* NaN timevalue: we need to coerce the arguments, but\n\t\t * the resulting internal timestamp needs to remain NaN.\n\t\t * This works but is not pretty: parts and dparts will\n\t\t * be partially uninitialized, but we only write to them.\n\t\t */\n\t}\n\n\t/*\n\t *  Determining which datetime components to overwrite based on\n\t *  stack arguments is a bit complicated, but important to factor\n\t *  out from setters themselves for compactness.\n\t *\n\t *  If DUK_DATE_FLAG_TIMESETTER, maxnargs indicates setter type:\n\t *\n\t *   1 -> millisecond\n\t *   2 -> second, [millisecond]\n\t *   3 -> minute, [second], [millisecond]\n\t *   4 -> hour, [minute], [second], [millisecond]\n\t *\n\t *  Else:\n\t *\n\t *   1 -> date\n\t *   2 -> month, [date]\n\t *   3 -> year, [month], [date]\n\t *\n\t *  By comparing nargs and maxnargs (and flags) we know which\n\t *  components to override.  We rely on part index ordering.\n\t */\n\n\tif (flags_and_maxnargs & DUK_DATE_FLAG_TIMESETTER) {\n\t\tDUK_ASSERT(maxnargs >= 1 && maxnargs <= 4);\n\t\tidx_first = DUK_DATE_IDX_MILLISECOND - (maxnargs - 1);\n\t} else {\n\t\tDUK_ASSERT(maxnargs >= 1 && maxnargs <= 3);\n\t\tidx_first = DUK_DATE_IDX_DAY - (maxnargs - 1);\n\t}\n\tDUK_ASSERT_DISABLE(idx_first >= 0);  /* unsigned */\n\tDUK_ASSERT(idx_first < DUK_DATE_IDX_NUM_PARTS);\n\n\tfor (i = 0; i < maxnargs; i++) {\n\t\tif ((duk_idx_t) i >= nargs) {\n\t\t\t/* no argument given -> leave components untouched */\n\t\t\tbreak;\n\t\t}\n\t\tidx = idx_first + i;\n\t\tDUK_ASSERT_DISABLE(idx >= 0);  /* unsigned */\n\t\tDUK_ASSERT(idx < DUK_DATE_IDX_NUM_PARTS);\n\n\t\tif (idx == DUK_DATE_IDX_YEAR && (flags_and_maxnargs & DUK_DATE_FLAG_YEAR_FIXUP)) {\n\t\t\tduk__twodigit_year_fixup(thr, (duk_idx_t) i);\n\t\t}\n\n\t\tdparts[idx] = duk_to_number(thr, (duk_idx_t) i);\n\n\t\tif (idx == DUK_DATE_IDX_DAY) {\n\t\t\t/* Day-of-month is one-based in the API, but zero-based\n\t\t\t * internally, so fix here.  Note that month is zero-based\n\t\t\t * both in the API and internally.\n\t\t\t */\n\t\t\t/* SCANBUILD: complains about use of uninitialized values.\n\t\t\t * The complaint is correct, but operating in undefined\n\t\t\t * values here is intentional in some cases and the caller\n\t\t\t * ignores the results.\n\t\t\t */\n\t\t\tdparts[idx] -= 1.0;\n\t\t}\n\t}\n\n\t/* Leaves new timevalue on stack top and returns 1, which is correct\n\t * for part setters.\n\t */\n\tif (DUK_ISFINITE(d)) {\n\t\treturn duk__set_this_timeval_from_dparts(thr, dparts, flags_and_maxnargs);\n\t} else {\n\t\t/* Internal timevalue is already NaN, so don't touch it. */\n\t\tduk_push_nan(thr);\n\t\treturn 1;\n\t}\n}\n\n/* Apply ToNumber() to specified index; if ToInteger(val) in [0,99], add\n * 1900 and replace value at idx_val.\n */\nDUK_LOCAL void duk__twodigit_year_fixup(duk_hthread *thr, duk_idx_t idx_val) {\n\tduk_double_t d;\n\n\t/* XXX: idx_val would fit into 16 bits, but using duk_small_uint_t\n\t * might not generate better code due to casting.\n\t */\n\n\t/* E5 Sections 15.9.3.1, B.2.4, B.2.5 */\n\tduk_to_number(thr, idx_val);\n\tif (duk_is_nan(thr, idx_val)) {\n\t\treturn;\n\t}\n\tduk_dup(thr, idx_val);\n\tduk_to_int(thr, -1);\n\td = duk_get_number(thr, -1);  /* get as double to handle huge numbers correctly */\n\tif (d >= 0.0 && d <= 99.0) {\n\t\td += 1900.0;\n\t\tduk_push_number(thr, d);\n\t\tduk_replace(thr, idx_val);\n\t}\n\tduk_pop(thr);\n}\n\n/* Set datetime parts from stack arguments, defaulting any missing values.\n * Day-of-week is not set; it is not required when setting the time value.\n */\nDUK_LOCAL void duk__set_parts_from_args(duk_hthread *thr, duk_double_t *dparts, duk_idx_t nargs) {\n\tduk_double_t d;\n\tduk_small_uint_t i;\n\tduk_small_uint_t idx;\n\n\t/* Causes a ToNumber() coercion, but doesn't break coercion order since\n\t * year is coerced first anyway.\n\t */\n\tduk__twodigit_year_fixup(thr, 0);\n\n\t/* There are at most 7 args, but we use 8 here so that also\n\t * DUK_DATE_IDX_WEEKDAY gets initialized (to zero) to avoid the potential\n\t * for any Valgrind gripes later.\n\t */\n\tfor (i = 0; i < 8; i++) {\n\t\t/* Note: rely on index ordering */\n\t\tidx = DUK_DATE_IDX_YEAR + i;\n\t\tif ((duk_idx_t) i < nargs) {\n\t\t\td = duk_to_number(thr, (duk_idx_t) i);\n\t\t\tif (idx == DUK_DATE_IDX_DAY) {\n\t\t\t\t/* Convert day from one-based to zero-based (internal).  This may\n\t\t\t\t * cause the day part to be negative, which is OK.\n\t\t\t\t */\n\t\t\t\td -= 1.0;\n\t\t\t}\n\t\t} else {\n\t\t\t/* All components default to 0 except day-of-month which defaults\n\t\t\t * to 1.  However, because our internal day-of-month is zero-based,\n\t\t\t * it also defaults to zero here.\n\t\t\t */\n\t\t\td = 0.0;\n\t\t}\n\t\tdparts[idx] = d;\n\t}\n\n\tDUK_DDD(DUK_DDDPRINT(\"parts from args -> %lf %lf %lf %lf %lf %lf %lf %lf\",\n\t                     (double) dparts[0], (double) dparts[1],\n\t                     (double) dparts[2], (double) dparts[3],\n\t                     (double) dparts[4], (double) dparts[5],\n\t                     (double) dparts[6], (double) dparts[7]));\n}\n\n/*\n *  Indirect magic value lookup for Date methods.\n *\n *  Date methods don't put their control flags into the function magic value\n *  because they wouldn't fit into a LIGHTFUNC's magic field.  Instead, the\n *  magic value is set to an index pointing to the array of control flags\n *  below.\n *\n *  This must be kept in strict sync with genbuiltins.py!\n */\n\nstatic duk_uint16_t duk__date_magics[] = {\n\t/* 0: toString */\n\tDUK_DATE_FLAG_TOSTRING_DATE + DUK_DATE_FLAG_TOSTRING_TIME + DUK_DATE_FLAG_LOCALTIME,\n\n\t/* 1: toDateString */\n\tDUK_DATE_FLAG_TOSTRING_DATE + DUK_DATE_FLAG_LOCALTIME,\n\n\t/* 2: toTimeString */\n\tDUK_DATE_FLAG_TOSTRING_TIME + DUK_DATE_FLAG_LOCALTIME,\n\n\t/* 3: toLocaleString */\n\tDUK_DATE_FLAG_TOSTRING_DATE + DUK_DATE_FLAG_TOSTRING_TIME + DUK_DATE_FLAG_TOSTRING_LOCALE + DUK_DATE_FLAG_LOCALTIME,\n\n\t/* 4: toLocaleDateString */\n\tDUK_DATE_FLAG_TOSTRING_DATE + DUK_DATE_FLAG_TOSTRING_LOCALE + DUK_DATE_FLAG_LOCALTIME,\n\n\t/* 5: toLocaleTimeString */\n\tDUK_DATE_FLAG_TOSTRING_TIME + DUK_DATE_FLAG_TOSTRING_LOCALE + DUK_DATE_FLAG_LOCALTIME,\n\n\t/* 6: toUTCString */\n\tDUK_DATE_FLAG_TOSTRING_DATE + DUK_DATE_FLAG_TOSTRING_TIME,\n\n\t/* 7: toISOString */\n\tDUK_DATE_FLAG_TOSTRING_DATE + DUK_DATE_FLAG_TOSTRING_TIME + DUK_DATE_FLAG_NAN_TO_RANGE_ERROR + DUK_DATE_FLAG_SEP_T,\n\n\t/* 8: getFullYear */\n\tDUK_DATE_FLAG_LOCALTIME + (DUK_DATE_IDX_YEAR << DUK_DATE_FLAG_VALUE_SHIFT),\n\n\t/* 9: getUTCFullYear */\n\t0 + (DUK_DATE_IDX_YEAR << DUK_DATE_FLAG_VALUE_SHIFT),\n\n\t/* 10: getMonth */\n\tDUK_DATE_FLAG_LOCALTIME + (DUK_DATE_IDX_MONTH << DUK_DATE_FLAG_VALUE_SHIFT),\n\n\t/* 11: getUTCMonth */\n\t0 + (DUK_DATE_IDX_MONTH << DUK_DATE_FLAG_VALUE_SHIFT),\n\n\t/* 12: getDate */\n\tDUK_DATE_FLAG_ONEBASED + DUK_DATE_FLAG_LOCALTIME + (DUK_DATE_IDX_DAY << DUK_DATE_FLAG_VALUE_SHIFT),\n\n\t/* 13: getUTCDate */\n\tDUK_DATE_FLAG_ONEBASED + (DUK_DATE_IDX_DAY << DUK_DATE_FLAG_VALUE_SHIFT),\n\n\t/* 14: getDay */\n\tDUK_DATE_FLAG_LOCALTIME + (DUK_DATE_IDX_WEEKDAY << DUK_DATE_FLAG_VALUE_SHIFT),\n\n\t/* 15: getUTCDay */\n\t0 + (DUK_DATE_IDX_WEEKDAY << DUK_DATE_FLAG_VALUE_SHIFT),\n\n\t/* 16: getHours */\n\tDUK_DATE_FLAG_LOCALTIME + (DUK_DATE_IDX_HOUR << DUK_DATE_FLAG_VALUE_SHIFT),\n\n\t/* 17: getUTCHours */\n\t0 + (DUK_DATE_IDX_HOUR << DUK_DATE_FLAG_VALUE_SHIFT),\n\n\t/* 18: getMinutes */\n\tDUK_DATE_FLAG_LOCALTIME + (DUK_DATE_IDX_MINUTE << DUK_DATE_FLAG_VALUE_SHIFT),\n\n\t/* 19: getUTCMinutes */\n\t0 + (DUK_DATE_IDX_MINUTE << DUK_DATE_FLAG_VALUE_SHIFT),\n\n\t/* 20: getSeconds */\n\tDUK_DATE_FLAG_LOCALTIME + (DUK_DATE_IDX_SECOND << DUK_DATE_FLAG_VALUE_SHIFT),\n\n\t/* 21: getUTCSeconds */\n\t0 + (DUK_DATE_IDX_SECOND << DUK_DATE_FLAG_VALUE_SHIFT),\n\n\t/* 22: getMilliseconds */\n\tDUK_DATE_FLAG_LOCALTIME + (DUK_DATE_IDX_MILLISECOND << DUK_DATE_FLAG_VALUE_SHIFT),\n\n\t/* 23: getUTCMilliseconds */\n\t0 + (DUK_DATE_IDX_MILLISECOND << DUK_DATE_FLAG_VALUE_SHIFT),\n\n\t/* 24: setMilliseconds */\n\tDUK_DATE_FLAG_TIMESETTER + DUK_DATE_FLAG_LOCALTIME + (1 << DUK_DATE_FLAG_VALUE_SHIFT),\n\n\t/* 25: setUTCMilliseconds */\n\tDUK_DATE_FLAG_TIMESETTER + (1 << DUK_DATE_FLAG_VALUE_SHIFT),\n\n\t/* 26: setSeconds */\n\tDUK_DATE_FLAG_TIMESETTER + DUK_DATE_FLAG_LOCALTIME + (2 << DUK_DATE_FLAG_VALUE_SHIFT),\n\n\t/* 27: setUTCSeconds */\n\tDUK_DATE_FLAG_TIMESETTER + (2 << DUK_DATE_FLAG_VALUE_SHIFT),\n\n\t/* 28: setMinutes */\n\tDUK_DATE_FLAG_TIMESETTER + DUK_DATE_FLAG_LOCALTIME + (3 << DUK_DATE_FLAG_VALUE_SHIFT),\n\n\t/* 29: setUTCMinutes */\n\tDUK_DATE_FLAG_TIMESETTER + (3 << DUK_DATE_FLAG_VALUE_SHIFT),\n\n\t/* 30: setHours */\n\tDUK_DATE_FLAG_TIMESETTER + DUK_DATE_FLAG_LOCALTIME + (4 << DUK_DATE_FLAG_VALUE_SHIFT),\n\n\t/* 31: setUTCHours */\n\tDUK_DATE_FLAG_TIMESETTER + (4 << DUK_DATE_FLAG_VALUE_SHIFT),\n\n\t/* 32: setDate */\n\tDUK_DATE_FLAG_LOCALTIME + (1 << DUK_DATE_FLAG_VALUE_SHIFT),\n\n\t/* 33: setUTCDate */\n\t0 + (1 << DUK_DATE_FLAG_VALUE_SHIFT),\n\n\t/* 34: setMonth */\n\tDUK_DATE_FLAG_LOCALTIME + (2 << DUK_DATE_FLAG_VALUE_SHIFT),\n\n\t/* 35: setUTCMonth */\n\t0 + (2 << DUK_DATE_FLAG_VALUE_SHIFT),\n\n\t/* 36: setFullYear */\n\tDUK_DATE_FLAG_NAN_TO_ZERO + DUK_DATE_FLAG_LOCALTIME + (3 << DUK_DATE_FLAG_VALUE_SHIFT),\n\n\t/* 37: setUTCFullYear */\n\tDUK_DATE_FLAG_NAN_TO_ZERO + (3 << DUK_DATE_FLAG_VALUE_SHIFT),\n\n\t/* 38: getYear */\n\tDUK_DATE_FLAG_LOCALTIME + DUK_DATE_FLAG_SUB1900 + (DUK_DATE_IDX_YEAR << DUK_DATE_FLAG_VALUE_SHIFT),\n\n\t/* 39: setYear */\n\tDUK_DATE_FLAG_NAN_TO_ZERO + DUK_DATE_FLAG_YEAR_FIXUP + (3 << DUK_DATE_FLAG_VALUE_SHIFT),\n};\n\nDUK_LOCAL duk_small_uint_t duk__date_get_indirect_magic(duk_hthread *thr) {\n\tduk_small_uint_t magicidx = (duk_small_uint_t) duk_get_current_magic(thr);\n\tDUK_ASSERT(magicidx < (duk_small_int_t) (sizeof(duk__date_magics) / sizeof(duk_uint16_t)));\n\treturn (duk_small_uint_t) duk__date_magics[magicidx];\n}\n\n#if defined(DUK_USE_DATE_BUILTIN)\n/*\n *  Constructor calls\n */\n\nDUK_INTERNAL duk_ret_t duk_bi_date_constructor(duk_hthread *thr) {\n\tduk_idx_t nargs = duk_get_top(thr);\n\tduk_bool_t is_cons = duk_is_constructor_call(thr);\n\tduk_double_t dparts[DUK_DATE_IDX_NUM_PARTS];\n\tduk_double_t d;\n\n\tDUK_DDD(DUK_DDDPRINT(\"Date constructor, nargs=%ld, is_cons=%ld\", (long) nargs, (long) is_cons));\n\n\t(void) duk_push_object_helper(thr,\n\t                              DUK_HOBJECT_FLAG_EXTENSIBLE |\n\t                              DUK_HOBJECT_FLAG_FASTREFS |\n\t                              DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_DATE),\n\t                              DUK_BIDX_DATE_PROTOTYPE);\n\n\t/* Unlike most built-ins, the internal [[PrimitiveValue]] of a Date\n\t * is mutable.\n\t */\n\n\tif (nargs == 0 || !is_cons) {\n\t\td = duk__timeclip(duk_time_get_ecmascript_time_nofrac(thr));\n\t\tduk_push_number(thr, d);\n\t\tduk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_W);\n\t\tif (!is_cons) {\n\t\t\t/* called as a normal function: return new Date().toString() */\n\t\t\tduk_to_string(thr, -1);\n\t\t}\n\t\treturn 1;\n\t} else if (nargs == 1) {\n\t\tconst char *str;\n\t\tduk_to_primitive(thr, 0, DUK_HINT_NONE);\n\t\tstr = duk_get_string_notsymbol(thr, 0);\n\t\tif (str) {\n\t\t\tduk__parse_string(thr, str);\n\t\t\tduk_replace(thr, 0);  /* may be NaN */\n\t\t}\n\t\td = duk__timeclip(duk_to_number(thr, 0));  /* symbols fail here */\n\t\tduk_push_number(thr, d);\n\t\tduk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_W);\n\t\treturn 1;\n\t}\n\n\tduk__set_parts_from_args(thr, dparts, nargs);\n\n\t/* Parts are in local time, convert when setting. */\n\n\t(void) duk__set_this_timeval_from_dparts(thr, dparts, DUK_DATE_FLAG_LOCALTIME /*flags*/);  /* -> [ ... this timeval ] */\n\tduk_pop(thr);  /* -> [ ... this ] */\n\treturn 1;\n}\n\nDUK_INTERNAL duk_ret_t duk_bi_date_constructor_parse(duk_hthread *thr) {\n\treturn duk__parse_string(thr, duk_to_string(thr, 0));\n}\n\nDUK_INTERNAL duk_ret_t duk_bi_date_constructor_utc(duk_hthread *thr) {\n\tduk_idx_t nargs = duk_get_top(thr);\n\tduk_double_t dparts[DUK_DATE_IDX_NUM_PARTS];\n\tduk_double_t d;\n\n\t/* Behavior for nargs < 2 is implementation dependent: currently we'll\n\t * set a NaN time value (matching V8 behavior) in this case.\n\t */\n\n\tif (nargs < 2) {\n\t\tduk_push_nan(thr);\n\t} else {\n\t\tduk__set_parts_from_args(thr, dparts, nargs);\n\t\td = duk_bi_date_get_timeval_from_dparts(dparts, 0 /*flags*/);\n\t\tduk_push_number(thr, d);\n\t}\n\treturn 1;\n}\n\nDUK_INTERNAL duk_ret_t duk_bi_date_constructor_now(duk_hthread *thr) {\n\tduk_double_t d;\n\n\td = duk_time_get_ecmascript_time_nofrac(thr);\n\tDUK_ASSERT(duk__timeclip(d) == d);  /* TimeClip() should never be necessary */\n\tduk_push_number(thr, d);\n\treturn 1;\n}\n\n/*\n *  String/JSON conversions\n *\n *  Human readable conversions are now basically ISO 8601 with a space\n *  (instead of 'T') as the date/time separator.  This is a good baseline\n *  and is platform independent.\n *\n *  A shared native helper to provide many conversions.  Magic value contains\n *  a set of flags.  The helper provides:\n *\n *    toString()\n *    toDateString()\n *    toTimeString()\n *    toLocaleString()\n *    toLocaleDateString()\n *    toLocaleTimeString()\n *    toUTCString()\n *    toISOString()\n *\n *  Notes:\n *\n *    - Date.prototype.toGMTString() and Date.prototype.toUTCString() are\n *      required to be the same Ecmascript function object (!), so it is\n *      omitted from here.\n *\n *    - Date.prototype.toUTCString(): E5.1 specification does not require a\n *      specific format, but result should be human readable.  The\n *      specification suggests using ISO 8601 format with a space (instead\n *      of 'T') separator if a more human readable format is not available.\n *\n *    - Date.prototype.toISOString(): unlike other conversion functions,\n *      toISOString() requires a RangeError for invalid date values.\n */\n\nDUK_INTERNAL duk_ret_t duk_bi_date_prototype_tostring_shared(duk_hthread *thr) {\n\tduk_small_uint_t flags = duk__date_get_indirect_magic(thr);\n\treturn duk__to_string_helper(thr, flags);\n}\n\nDUK_INTERNAL duk_ret_t duk_bi_date_prototype_value_of(duk_hthread *thr) {\n\t/* This native function is also used for Date.prototype.getTime()\n\t * as their behavior is identical.\n\t */\n\n\tduk_double_t d = duk__push_this_get_timeval(thr, 0 /*flags*/);  /* -> [ this ] */\n\tDUK_ASSERT(DUK_ISFINITE(d) || DUK_ISNAN(d));\n\tduk_push_number(thr, d);\n\treturn 1;\n}\n\nDUK_INTERNAL duk_ret_t duk_bi_date_prototype_to_json(duk_hthread *thr) {\n\t/* Note: toJSON() is a generic function which works even if 'this'\n\t * is not a Date.  The sole argument is ignored.\n\t */\n\n\tduk_push_this(thr);\n\tduk_to_object(thr, -1);\n\n\tduk_dup_top(thr);\n\tduk_to_primitive(thr, -1, DUK_HINT_NUMBER);\n\tif (duk_is_number(thr, -1)) {\n\t\tduk_double_t d = duk_get_number(thr, -1);\n\t\tif (!DUK_ISFINITE(d)) {\n\t\t\tduk_push_null(thr);\n\t\t\treturn 1;\n\t\t}\n\t}\n\tduk_pop(thr);\n\n\tduk_get_prop_stridx_short(thr, -1, DUK_STRIDX_TO_ISO_STRING);\n\tduk_dup_m2(thr);  /* -> [ O toIsoString O ] */\n\tduk_call_method(thr, 0);\n\treturn 1;\n}\n\n/*\n *  Getters.\n *\n *  Implementing getters is quite easy.  The internal time value is either\n *  NaN, or represents milliseconds (without fractions) from Jan 1, 1970.\n *  The internal time value can be converted to integer parts, and each\n *  part will be normalized and will fit into a 32-bit signed integer.\n *\n *  A shared native helper to provide all getters.  Magic value contains\n *  a set of flags and also packs the date component index argument.  The\n *  helper provides:\n *\n *    getFullYear()\n *    getUTCFullYear()\n *    getMonth()\n *    getUTCMonth()\n *    getDate()\n *    getUTCDate()\n *    getDay()\n *    getUTCDay()\n *    getHours()\n *    getUTCHours()\n *    getMinutes()\n *    getUTCMinutes()\n *    getSeconds()\n *    getUTCSeconds()\n *    getMilliseconds()\n *    getUTCMilliseconds()\n *    getYear()\n *\n *  Notes:\n *\n *    - Date.prototype.getDate(): 'date' means day-of-month, and is\n *      zero-based in internal calculations but public API expects it to\n *      be one-based.\n *\n *    - Date.prototype.getTime() and Date.prototype.valueOf() have identical\n *      behavior.  They have separate function objects, but share the same C\n *      function (duk_bi_date_prototype_value_of).\n */\n\nDUK_INTERNAL duk_ret_t duk_bi_date_prototype_get_shared(duk_hthread *thr) {\n\tduk_small_uint_t flags_and_idx = duk__date_get_indirect_magic(thr);\n\treturn duk__get_part_helper(thr, flags_and_idx);\n}\n\nDUK_INTERNAL duk_ret_t duk_bi_date_prototype_get_timezone_offset(duk_hthread *thr) {\n\t/*\n\t *  Return (t - LocalTime(t)) in minutes:\n\t *\n\t *    t - LocalTime(t) = t - (t + LocalTZA + DaylightSavingTA(t))\n\t *                     = -(LocalTZA + DaylightSavingTA(t))\n\t *\n\t *  where DaylightSavingTA() is checked for time 't'.\n\t *\n\t *  Note that the sign of the result is opposite to common usage,\n\t *  e.g. for EE(S)T which normally is +2h or +3h from UTC, this\n\t *  function returns -120 or -180.\n\t *\n\t */\n\n\tduk_double_t d;\n\tduk_int_t tzoffset;\n\n\t/* Note: DST adjustment is determined using UTC time. */\n\td = duk__push_this_get_timeval(thr, 0 /*flags*/);\n\tDUK_ASSERT(DUK_ISFINITE(d) || DUK_ISNAN(d));\n\tif (DUK_ISNAN(d)) {\n\t\tduk_push_nan(thr);\n\t} else {\n\t\tDUK_ASSERT(DUK_ISFINITE(d));\n\t\ttzoffset = DUK_USE_DATE_GET_LOCAL_TZOFFSET(d);\n\t\tduk_push_int(thr, -tzoffset / 60);\n\t}\n\treturn 1;\n}\n\n/*\n *  Setters.\n *\n *  Setters are a bit more complicated than getters.  Component setters\n *  break down the current time value into its (normalized) component\n *  parts, replace one or more components with -unnormalized- new values,\n *  and the components are then converted back into a time value.  As an\n *  example of using unnormalized values:\n *\n *    var d = new Date(1234567890);\n *\n *  is equivalent to:\n *\n *    var d = new Date(0);\n *    d.setUTCMilliseconds(1234567890);\n *\n *  A shared native helper to provide almost all setters.  Magic value\n *  contains a set of flags and also packs the \"maxnargs\" argument.  The\n *  helper provides:\n *\n *    setMilliseconds()\n *    setUTCMilliseconds()\n *    setSeconds()\n *    setUTCSeconds()\n *    setMinutes()\n *    setUTCMinutes()\n *    setHours()\n *    setUTCHours()\n *    setDate()\n *    setUTCDate()\n *    setMonth()\n *    setUTCMonth()\n *    setFullYear()\n *    setUTCFullYear()\n *    setYear()\n *\n *  Notes:\n *\n *    - Date.prototype.setYear() (Section B addition): special year check\n *      is omitted.  NaN / Infinity will just flow through and ultimately\n *      result in a NaN internal time value.\n *\n *    - Date.prototype.setYear() does not have optional arguments for\n *      setting month and day-in-month (like setFullYear()), but we indicate\n *      'maxnargs' to be 3 to get the year written to the correct component\n *      index in duk__set_part_helper().  The function has nargs == 1, so only\n *      the year will be set regardless of actual argument count.\n */\n\nDUK_INTERNAL duk_ret_t duk_bi_date_prototype_set_shared(duk_hthread *thr) {\n\tduk_small_uint_t flags_and_maxnargs = duk__date_get_indirect_magic(thr);\n\treturn duk__set_part_helper(thr, flags_and_maxnargs);\n}\n\nDUK_INTERNAL duk_ret_t duk_bi_date_prototype_set_time(duk_hthread *thr) {\n\tduk_double_t d;\n\n\t(void) duk__push_this_get_timeval(thr, 0 /*flags*/); /* -> [ timeval this ] */\n\td = duk__timeclip(duk_to_number(thr, 0));\n\tduk_push_number(thr, d);\n\tduk_dup_top(thr);\n\tduk_put_prop_stridx_short(thr, -3, DUK_STRIDX_INT_VALUE); /* -> [ timeval this timeval ] */\n\n\treturn 1;\n}\n\n#endif  /* DUK_USE_DATE_BUILTIN */\n\n/* automatic undefs */\n#undef DUK__CF_ACCEPT\n#undef DUK__CF_ACCEPT_NUL\n#undef DUK__CF_NEG\n#undef DUK__DPRINT_DPARTS\n#undef DUK__DPRINT_PARTS\n#undef DUK__DPRINT_PARTS_AND_DPARTS\n#undef DUK__LOCAL_TZOFFSET_MAXITER\n#undef DUK__NUM_ISO8601_PARSER_PARTS\n#undef DUK__PACK_RULE\n#undef DUK__PI_DAY\n#undef DUK__PI_HOUR\n#undef DUK__PI_MILLISECOND\n#undef DUK__PI_MINUTE\n#undef DUK__PI_MONTH\n#undef DUK__PI_SECOND\n#undef DUK__PI_TZHOUR\n#undef DUK__PI_TZMINUTE\n#undef DUK__PI_YEAR\n#undef DUK__PM_DAY\n#undef DUK__PM_HOUR\n#undef DUK__PM_MILLISECOND\n#undef DUK__PM_MINUTE\n#undef DUK__PM_MONTH\n#undef DUK__PM_SECOND\n#undef DUK__PM_TZHOUR\n#undef DUK__PM_TZMINUTE\n#undef DUK__PM_YEAR\n#undef DUK__RULE_MASK_PART_SEP\n#undef DUK__SI_COLON\n#undef DUK__SI_MINUS\n#undef DUK__SI_NUL\n#undef DUK__SI_PERIOD\n#undef DUK__SI_PLUS\n#undef DUK__SI_SPACE\n#undef DUK__SI_T\n#undef DUK__SI_Z\n#undef DUK__SM_COLON\n#undef DUK__SM_MINUS\n#undef DUK__SM_NUL\n#undef DUK__SM_PERIOD\n#undef DUK__SM_PLUS\n#undef DUK__SM_SPACE\n#undef DUK__SM_T\n#undef DUK__SM_Z\n#undef DUK__UNPACK_RULE\n#undef DUK__WEEKDAY_MOD_ADDER\n#undef DUK__YEAR\n#line 1 \"duk_bi_date_unix.c\"\n/*\n *  Unix-like Date providers\n *\n *  Generally useful Unix / POSIX / ANSI Date providers.\n */\n\n/* #include duk_internal.h -> already included */\n\n/* The necessary #includes are in place in duk_config.h. */\n\n/* Buffer sizes for some UNIX calls.  Larger than strictly necessary\n * to avoid Valgrind errors.\n */\n#define DUK__STRPTIME_BUF_SIZE  64\n#define DUK__STRFTIME_BUF_SIZE  64\n\n#if defined(DUK_USE_DATE_NOW_GETTIMEOFDAY)\n/* Get current Ecmascript time (= UNIX/Posix time, but in milliseconds). */\nDUK_INTERNAL duk_double_t duk_bi_date_get_now_gettimeofday(void) {\n\tstruct timeval tv;\n\tduk_double_t d;\n\n\tif (gettimeofday(&tv, NULL) != 0) {\n\t\tDUK_D(DUK_DPRINT(\"gettimeofday() failed\"));\n\t\treturn 0.0;\n\t}\n\n\t/* As of Duktape 2.2.0 allow fractions. */\n\td = ((duk_double_t) tv.tv_sec) * 1000.0 +\n\t    ((duk_double_t) tv.tv_usec) / 1000.0;\n\n\treturn d;\n}\n#endif  /* DUK_USE_DATE_NOW_GETTIMEOFDAY */\n\n#if defined(DUK_USE_DATE_NOW_TIME)\n/* Not a very good provider: only full seconds are available. */\nDUK_INTERNAL duk_double_t duk_bi_date_get_now_time(void) {\n\ttime_t t;\n\n\tt = time(NULL);\n\tif (t == (time_t) -1) {\n\t\tDUK_D(DUK_DPRINT(\"time() failed\"));\n\t\treturn 0.0;\n\t}\n\treturn ((duk_double_t) t) * 1000.0;\n}\n#endif  /* DUK_USE_DATE_NOW_TIME */\n\n#if defined(DUK_USE_DATE_TZO_GMTIME) || defined(DUK_USE_DATE_TZO_GMTIME_R) || defined(DUK_USE_DATE_TZO_GMTIME_S)\n/* Get local time offset (in seconds) for a certain (UTC) instant 'd'. */\nDUK_INTERNAL duk_int_t duk_bi_date_get_local_tzoffset_gmtime(duk_double_t d) {\n\ttime_t t, t1, t2;\n\tduk_int_t parts[DUK_DATE_IDX_NUM_PARTS];\n\tduk_double_t dparts[DUK_DATE_IDX_NUM_PARTS];\n\tstruct tm tms[2];\n#if defined(DUK_USE_DATE_TZO_GMTIME)\n\tstruct tm *tm_ptr;\n#endif\n\n\t/* For NaN/inf, the return value doesn't matter. */\n\tif (!DUK_ISFINITE(d)) {\n\t\treturn 0;\n\t}\n\n\t/* If not within Ecmascript range, some integer time calculations\n\t * won't work correctly (and some asserts will fail), so bail out\n\t * if so.  This fixes test-bug-date-insane-setyear.js.  There is\n\t * a +/- 24h leeway in this range check to avoid a test262 corner\n\t * case documented in test-bug-date-timeval-edges.js.\n\t */\n\tif (!duk_bi_date_timeval_in_leeway_range(d)) {\n\t\tDUK_DD(DUK_DDPRINT(\"timeval not within valid range, skip tzoffset computation to avoid integer overflows\"));\n\t\treturn 0;\n\t}\n\n\t/*\n\t *  This is a bit tricky to implement portably.  The result depends\n\t *  on the timestamp (specifically, DST depends on the timestamp).\n\t *  If e.g. UNIX APIs are used, they'll have portability issues with\n\t *  very small and very large years.\n\t *\n\t *  Current approach:\n\t *\n\t *  - Stay within portable UNIX limits by using equivalent year mapping.\n\t *    Avoid year 1970 and 2038 as some conversions start to fail, at\n\t *    least on some platforms.  Avoiding 1970 means that there are\n\t *    currently DST discrepancies for 1970.\n\t *\n\t *  - Create a UTC and local time breakdowns from 't'.  Then create\n\t *    a time_t using gmtime() and localtime() and compute the time\n\t *    difference between the two.\n\t *\n\t *  Equivalent year mapping (E5 Section 15.9.1.8):\n\t *\n\t *    If the host environment provides functionality for determining\n\t *    daylight saving time, the implementation of ECMAScript is free\n\t *    to map the year in question to an equivalent year (same\n\t *    leap-year-ness and same starting week day for the year) for which\n\t *    the host environment provides daylight saving time information.\n\t *    The only restriction is that all equivalent years should produce\n\t *    the same result.\n\t *\n\t *  This approach is quite reasonable but not entirely correct, e.g.\n\t *  the specification also states (E5 Section 15.9.1.8):\n\t *\n\t *    The implementation of ECMAScript should not try to determine\n\t *    whether the exact time was subject to daylight saving time, but\n\t *    just whether daylight saving time would have been in effect if\n\t *    the _current daylight saving time algorithm_ had been used at the\n\t *    time.  This avoids complications such as taking into account the\n\t *    years that the locale observed daylight saving time year round.\n\t *\n\t *  Since we rely on the platform APIs for conversions between local\n\t *  time and UTC, we can't guarantee the above.  Rather, if the platform\n\t *  has historical DST rules they will be applied.  This seems to be the\n\t *  general preferred direction in Ecmascript standardization (or at least\n\t *  implementations) anyway, and even the equivalent year mapping should\n\t *  be disabled if the platform is known to handle DST properly for the\n\t *  full Ecmascript range.\n\t *\n\t *  The following has useful discussion and links:\n\t *\n\t *    https://bugzilla.mozilla.org/show_bug.cgi?id=351066\n\t */\n\n\tduk_bi_date_timeval_to_parts(d, parts, dparts, DUK_DATE_FLAG_EQUIVYEAR /*flags*/);\n\tDUK_ASSERT(parts[DUK_DATE_IDX_YEAR] >= 1970 && parts[DUK_DATE_IDX_YEAR] <= 2038);\n\n\td = duk_bi_date_get_timeval_from_dparts(dparts, 0 /*flags*/);\n\tDUK_ASSERT(d >= 0 && d < 2147483648.0 * 1000.0);  /* unsigned 31-bit range */\n\tt = (time_t) (d / 1000.0);\n\tDUK_DDD(DUK_DDDPRINT(\"timeval: %lf -> time_t %ld\", (double) d, (long) t));\n\n\tDUK_MEMZERO((void *) tms, sizeof(struct tm) * 2);\n\n#if defined(DUK_USE_DATE_TZO_GMTIME_R)\n\t(void) gmtime_r(&t, &tms[0]);\n\t(void) localtime_r(&t, &tms[1]);\n#elif defined(DUK_USE_DATE_TZO_GMTIME_S)\n\t(void) gmtime_s(&t, &tms[0]);\n\t(void) localtime_s(&t, &tms[1]);\n#elif defined(DUK_USE_DATE_TZO_GMTIME)\n\ttm_ptr = gmtime(&t);\n\tDUK_MEMCPY((void *) &tms[0], tm_ptr, sizeof(struct tm));\n\ttm_ptr = localtime(&t);\n\tDUK_MEMCPY((void *) &tms[1], tm_ptr, sizeof(struct tm));\n#else\n#error internal error\n#endif\n\tDUK_DDD(DUK_DDDPRINT(\"gmtime result: tm={sec:%ld,min:%ld,hour:%ld,mday:%ld,mon:%ld,year:%ld,\"\n\t                     \"wday:%ld,yday:%ld,isdst:%ld}\",\n\t                     (long) tms[0].tm_sec, (long) tms[0].tm_min, (long) tms[0].tm_hour,\n\t                     (long) tms[0].tm_mday, (long) tms[0].tm_mon, (long) tms[0].tm_year,\n\t                     (long) tms[0].tm_wday, (long) tms[0].tm_yday, (long) tms[0].tm_isdst));\n\tDUK_DDD(DUK_DDDPRINT(\"localtime result: tm={sec:%ld,min:%ld,hour:%ld,mday:%ld,mon:%ld,year:%ld,\"\n\t                     \"wday:%ld,yday:%ld,isdst:%ld}\",\n\t                     (long) tms[1].tm_sec, (long) tms[1].tm_min, (long) tms[1].tm_hour,\n\t                     (long) tms[1].tm_mday, (long) tms[1].tm_mon, (long) tms[1].tm_year,\n\t                     (long) tms[1].tm_wday, (long) tms[1].tm_yday, (long) tms[1].tm_isdst));\n\n\t/* tm_isdst is both an input and an output to mktime(), use 0 to\n\t * avoid DST handling in mktime():\n\t * - https://github.com/svaarala/duktape/issues/406\n\t * - http://stackoverflow.com/questions/8558919/mktime-and-tm-isdst\n\t */\n\ttms[0].tm_isdst = 0;\n\ttms[1].tm_isdst = 0;\n\tt1 = mktime(&tms[0]);  /* UTC */\n\tt2 = mktime(&tms[1]);  /* local */\n\tif (t1 == (time_t) -1 || t2 == (time_t) -1) {\n\t\t/* This check used to be for (t < 0) but on some platforms\n\t\t * time_t is unsigned and apparently the proper way to detect\n\t\t * an mktime() error return is the cast above.  See e.g.:\n\t\t * http://pubs.opengroup.org/onlinepubs/009695299/functions/mktime.html\n\t\t */\n\t\tgoto mktime_error;\n\t}\n\tDUK_DDD(DUK_DDDPRINT(\"t1=%ld (utc), t2=%ld (local)\", (long) t1, (long) t2));\n\n\t/* Compute final offset in seconds, positive if local time ahead of\n\t * UTC (returned value is UTC-to-local offset).\n\t *\n\t * difftime() returns a double, so coercion to int generates quite\n\t * a lot of code.  Direct subtraction is not portable, however.\n\t * XXX: allow direct subtraction on known platforms.\n\t */\n#if 0\n\treturn (duk_int_t) (t2 - t1);\n#endif\n\treturn (duk_int_t) difftime(t2, t1);\n\n mktime_error:\n\t/* XXX: return something more useful, so that caller can throw? */\n\tDUK_D(DUK_DPRINT(\"mktime() failed, d=%lf\", (double) d));\n\treturn 0;\n}\n#endif  /* DUK_USE_DATE_TZO_GMTIME */\n\n#if defined(DUK_USE_DATE_PRS_STRPTIME)\nDUK_INTERNAL duk_bool_t duk_bi_date_parse_string_strptime(duk_hthread *thr, const char *str) {\n\tstruct tm tm;\n\ttime_t t;\n\tchar buf[DUK__STRPTIME_BUF_SIZE];\n\n\t/* Copy to buffer with slack to avoid Valgrind gripes from strptime. */\n\tDUK_ASSERT(str != NULL);\n\tDUK_MEMZERO(buf, sizeof(buf));  /* valgrind whine without this */\n\tDUK_SNPRINTF(buf, sizeof(buf), \"%s\", (const char *) str);\n\tbuf[sizeof(buf) - 1] = (char) 0;\n\n\tDUK_DDD(DUK_DDDPRINT(\"parsing: '%s'\", (const char *) buf));\n\n\tDUK_MEMZERO(&tm, sizeof(tm));\n\tif (strptime((const char *) buf, \"%c\", &tm) != NULL) {\n\t\tDUK_DDD(DUK_DDDPRINT(\"before mktime: tm={sec:%ld,min:%ld,hour:%ld,mday:%ld,mon:%ld,year:%ld,\"\n\t\t                     \"wday:%ld,yday:%ld,isdst:%ld}\",\n\t\t                     (long) tm.tm_sec, (long) tm.tm_min, (long) tm.tm_hour,\n\t\t                     (long) tm.tm_mday, (long) tm.tm_mon, (long) tm.tm_year,\n\t\t                     (long) tm.tm_wday, (long) tm.tm_yday, (long) tm.tm_isdst));\n\t\ttm.tm_isdst = -1;  /* negative: dst info not available */\n\n\t\tt = mktime(&tm);\n\t\tDUK_DDD(DUK_DDDPRINT(\"mktime() -> %ld\", (long) t));\n\t\tif (t >= 0) {\n\t\t\tduk_push_number(thr, ((duk_double_t) t) * 1000.0);\n\t\t\treturn 1;\n\t\t}\n\t}\n\n\treturn 0;\n}\n#endif  /* DUK_USE_DATE_PRS_STRPTIME */\n\n#if defined(DUK_USE_DATE_PRS_GETDATE)\nDUK_INTERNAL duk_bool_t duk_bi_date_parse_string_getdate(duk_hthread *thr, const char *str) {\n\tstruct tm tm;\n\tduk_small_int_t rc;\n\ttime_t t;\n\n\t/* For this to work, DATEMSK must be set, so this is not very\n\t * convenient for an embeddable interpreter.\n\t */\n\n\tDUK_MEMZERO(&tm, sizeof(struct tm));\n\trc = (duk_small_int_t) getdate_r(str, &tm);\n\tDUK_DDD(DUK_DDDPRINT(\"getdate_r() -> %ld\", (long) rc));\n\n\tif (rc == 0) {\n\t\tt = mktime(&tm);\n\t\tDUK_DDD(DUK_DDDPRINT(\"mktime() -> %ld\", (long) t));\n\t\tif (t >= 0) {\n\t\t\tduk_push_number(thr, (duk_double_t) t);\n\t\t\treturn 1;\n\t\t}\n\t}\n\n\treturn 0;\n}\n#endif  /* DUK_USE_DATE_PRS_GETDATE */\n\n#if defined(DUK_USE_DATE_FMT_STRFTIME)\nDUK_INTERNAL duk_bool_t duk_bi_date_format_parts_strftime(duk_hthread *thr, duk_int_t *parts, duk_int_t tzoffset, duk_small_uint_t flags) {\n\tchar buf[DUK__STRFTIME_BUF_SIZE];\n\tstruct tm tm;\n\tconst char *fmt;\n\n\tDUK_UNREF(tzoffset);\n\n\t/* If the platform doesn't support the entire Ecmascript range, we need\n\t * to return 0 so that the caller can fall back to the default formatter.\n\t *\n\t * For now, assume that if time_t is 8 bytes or more, the whole Ecmascript\n\t * range is supported.  For smaller time_t values (4 bytes in practice),\n\t * assumes that the signed 32-bit range is supported.\n\t *\n\t * XXX: detect this more correctly per platform.  The size of time_t is\n\t * probably not an accurate guarantee of strftime() supporting or not\n\t * supporting a large time range (the full Ecmascript range).\n\t */\n\tif (sizeof(time_t) < 8 &&\n\t    (parts[DUK_DATE_IDX_YEAR] < 1970 || parts[DUK_DATE_IDX_YEAR] > 2037)) {\n\t\t/* be paranoid for 32-bit time values (even avoiding negative ones) */\n\t\treturn 0;\n\t}\n\n\tDUK_MEMZERO(&tm, sizeof(tm));\n\ttm.tm_sec = parts[DUK_DATE_IDX_SECOND];\n\ttm.tm_min = parts[DUK_DATE_IDX_MINUTE];\n\ttm.tm_hour = parts[DUK_DATE_IDX_HOUR];\n\ttm.tm_mday = parts[DUK_DATE_IDX_DAY];       /* already one-based */\n\ttm.tm_mon = parts[DUK_DATE_IDX_MONTH] - 1;  /* one-based -> zero-based */\n\ttm.tm_year = parts[DUK_DATE_IDX_YEAR] - 1900;\n\ttm.tm_wday = parts[DUK_DATE_IDX_WEEKDAY];\n\ttm.tm_isdst = 0;\n\n\tDUK_MEMZERO(buf, sizeof(buf));\n\tif ((flags & DUK_DATE_FLAG_TOSTRING_DATE) && (flags & DUK_DATE_FLAG_TOSTRING_TIME)) {\n\t\tfmt = \"%c\";\n\t} else if (flags & DUK_DATE_FLAG_TOSTRING_DATE) {\n\t\tfmt = \"%x\";\n\t} else {\n\t\tDUK_ASSERT(flags & DUK_DATE_FLAG_TOSTRING_TIME);\n\t\tfmt = \"%X\";\n\t}\n\t(void) strftime(buf, sizeof(buf) - 1, fmt, &tm);\n\tDUK_ASSERT(buf[sizeof(buf) - 1] == 0);\n\n\tduk_push_string(thr, buf);\n\treturn 1;\n}\n#endif  /* DUK_USE_DATE_FMT_STRFTIME */\n\n#if defined(DUK_USE_GET_MONOTONIC_TIME_CLOCK_GETTIME)\nDUK_INTERNAL duk_double_t duk_bi_date_get_monotonic_time_clock_gettime(void) {\n\tstruct timespec ts;\n\n\tif (clock_gettime(CLOCK_MONOTONIC, &ts) == 0) {\n\t\treturn (duk_double_t) ts.tv_sec * 1000.0 + (duk_double_t) ts.tv_nsec / 1000000.0;\n\t} else {\n\t\tDUK_D(DUK_DPRINT(\"clock_gettime(CLOCK_MONOTONIC) failed\"));\n\t\treturn 0.0;\n\t}\n}\n#endif\n\n/* automatic undefs */\n#undef DUK__STRFTIME_BUF_SIZE\n#undef DUK__STRPTIME_BUF_SIZE\n#line 1 \"duk_bi_date_windows.c\"\n/*\n *  Windows Date providers\n *\n *  Platform specific links:\n *\n *    - http://msdn.microsoft.com/en-us/library/windows/desktop/ms725473(v=vs.85).aspx\n */\n\n/* #include duk_internal.h -> already included */\n\n/* The necessary #includes are in place in duk_config.h. */\n\n#if defined(DUK_USE_DATE_NOW_WINDOWS) || defined(DUK_USE_DATE_TZO_WINDOWS)\n/* Shared Windows helpers. */\nDUK_LOCAL void duk__convert_systime_to_ularge(const SYSTEMTIME *st, ULARGE_INTEGER *res) {\n\tFILETIME ft;\n\tif (SystemTimeToFileTime(st, &ft) == 0) {\n\t\tDUK_D(DUK_DPRINT(\"SystemTimeToFileTime() failed, returning 0\"));\n\t\tres->QuadPart = 0;\n\t} else {\n\t\tres->LowPart = ft.dwLowDateTime;\n\t\tres->HighPart = ft.dwHighDateTime;\n\t}\n}\n\nDUK_LOCAL void duk__convert_filetime_to_ularge(const FILETIME *ft, ULARGE_INTEGER *res) {\n\tres->LowPart = ft->dwLowDateTime;\n\tres->HighPart = ft->dwHighDateTime;\n}\n\nDUK_LOCAL void duk__set_systime_jan1970(SYSTEMTIME *st) {\n\tDUK_MEMZERO((void *) st, sizeof(*st));\n\tst->wYear = 1970;\n\tst->wMonth = 1;\n\tst->wDayOfWeek = 4;  /* not sure whether or not needed; Thursday */\n\tst->wDay = 1;\n\tDUK_ASSERT(st->wHour == 0);\n\tDUK_ASSERT(st->wMinute == 0);\n\tDUK_ASSERT(st->wSecond == 0);\n\tDUK_ASSERT(st->wMilliseconds == 0);\n}\n#endif  /* defined(DUK_USE_DATE_NOW_WINDOWS) || defined(DUK_USE_DATE_TZO_WINDOWS) */\n\n#if defined(DUK_USE_DATE_NOW_WINDOWS)\nDUK_INTERNAL duk_double_t duk_bi_date_get_now_windows(void) {\n\t/* Suggested step-by-step method from documentation of RtlTimeToSecondsSince1970:\n\t * http://msdn.microsoft.com/en-us/library/windows/desktop/ms724928(v=vs.85).aspx\n\t */\n\tSYSTEMTIME st1, st2;\n\tULARGE_INTEGER tmp1, tmp2;\n\n\tGetSystemTime(&st1);\n\tduk__convert_systime_to_ularge((const SYSTEMTIME *) &st1, &tmp1);\n\n\tduk__set_systime_jan1970(&st2);\n\tduk__convert_systime_to_ularge((const SYSTEMTIME *) &st2, &tmp2);\n\n\t/* Difference is in 100ns units, convert to milliseconds, keeping\n\t * fractions since Duktape 2.2.0.  This is only theoretical because\n\t * SYSTEMTIME is limited to milliseconds.\n\t */\n\treturn (duk_double_t) ((LONGLONG) tmp1.QuadPart - (LONGLONG) tmp2.QuadPart) / 10000.0;\n}\n#endif  /* DUK_USE_DATE_NOW_WINDOWS */\n\n#if defined(DUK_USE_DATE_NOW_WINDOWS_SUBMS)\nDUK_INTERNAL duk_double_t duk_bi_date_get_now_windows_subms(void) {\n\t/* Variant of the basic algorithm using GetSystemTimePreciseAsFileTime()\n\t * for more accuracy.\n\t */\n\tFILETIME ft1;\n\tSYSTEMTIME st2;\n\tULARGE_INTEGER tmp1, tmp2;\n\n\tGetSystemTimePreciseAsFileTime(&ft1);\n\tduk__convert_filetime_to_ularge((const FILETIME *) &ft1, &tmp1);\n\n\tduk__set_systime_jan1970(&st2);\n\tduk__convert_systime_to_ularge((const SYSTEMTIME *) &st2, &tmp2);\n\n\t/* Difference is in 100ns units, convert to milliseconds, keeping\n\t * fractions since Duktape 2.2.0.\n\t */\n\treturn (duk_double_t) ((LONGLONG) tmp1.QuadPart - (LONGLONG) tmp2.QuadPart) / 10000.0;\n}\n#endif  /* DUK_USE_DATE_NOW_WINDOWS */\n\n#if defined(DUK_USE_DATE_TZO_WINDOWS)\nDUK_INTERNAL duk_int_t duk_bi_date_get_local_tzoffset_windows(duk_double_t d) {\n\tSYSTEMTIME st1;\n\tSYSTEMTIME st2;\n\tSYSTEMTIME st3;\n\tULARGE_INTEGER tmp1;\n\tULARGE_INTEGER tmp2;\n\tULARGE_INTEGER tmp3;\n\tFILETIME ft1;\n\n\t/* XXX: handling of timestamps outside Windows supported range.\n\t * How does Windows deal with dates before 1600?  Does windows\n\t * support all Ecmascript years (like -200000 and +200000)?\n\t * Should equivalent year mapping be used here too?  If so, use\n\t * a shared helper (currently integrated into timeval-to-parts).\n\t */\n\n\t/* Use the approach described in \"Remarks\" of FileTimeToLocalFileTime:\n\t * http://msdn.microsoft.com/en-us/library/windows/desktop/ms724277(v=vs.85).aspx\n\t */\n\n\tduk__set_systime_jan1970(&st1);\n\tduk__convert_systime_to_ularge((const SYSTEMTIME *) &st1, &tmp1);\n\ttmp2.QuadPart = (ULONGLONG) (d * 10000.0);  /* millisec -> 100ns units since jan 1, 1970 */\n\ttmp2.QuadPart += tmp1.QuadPart;             /* input 'd' in Windows UTC, 100ns units */\n\n\tft1.dwLowDateTime = tmp2.LowPart;\n\tft1.dwHighDateTime = tmp2.HighPart;\n\tFileTimeToSystemTime((const FILETIME *) &ft1, &st2);\n\tif (SystemTimeToTzSpecificLocalTime((LPTIME_ZONE_INFORMATION) NULL, &st2, &st3) == 0) {\n\t\tDUK_D(DUK_DPRINT(\"SystemTimeToTzSpecificLocalTime() failed, return tzoffset 0\"));\n\t\treturn 0;\n\t}\n\tduk__convert_systime_to_ularge((const SYSTEMTIME *) &st3, &tmp3);\n\n\t/* Positive if local time ahead of UTC. */\n\treturn (duk_int_t) (((LONGLONG) tmp3.QuadPart - (LONGLONG) tmp2.QuadPart) / DUK_I64_CONSTANT(10000000));  /* seconds */\n}\n#endif  /* DUK_USE_DATE_TZO_WINDOWS */\n\n#if defined(DUK_USE_DATE_TZO_WINDOWS_NO_DST)\nDUK_INTERNAL duk_int_t duk_bi_date_get_local_tzoffset_windows_no_dst(duk_double_t d) {\n\tSYSTEMTIME st1;\n\tSYSTEMTIME st2;\n\tFILETIME ft1;\n\tFILETIME ft2;\n\tULARGE_INTEGER tmp1;\n\tULARGE_INTEGER tmp2;\n\n\t/* Do a similar computation to duk_bi_date_get_local_tzoffset_windows\n\t * but without accounting for daylight savings time.  Use this on\n\t * Windows platforms (like Durango) that don't support the\n\t * SystemTimeToTzSpecificLocalTime() call.\n\t */\n\n\t/* current time not needed for this computation */\n\tDUK_UNREF(d);\n\n\tduk__set_systime_jan1970(&st1);\n\tduk__convert_systime_to_ularge((const SYSTEMTIME *) &st1, &tmp1);\n\n\tft1.dwLowDateTime = tmp1.LowPart;\n\tft1.dwHighDateTime = tmp1.HighPart;\n\tFileTimeToLocalFileTime((const FILETIME *) &ft1, &ft2);\n\n\tFileTimeToSystemTime((const FILETIME *) &ft2, &st2);\n\tduk__convert_systime_to_ularge((const SYSTEMTIME *) &st2, &tmp2);\n\n\treturn (duk_int_t) (((LONGLONG) tmp2.QuadPart - (LONGLONG) tmp1.QuadPart) / DUK_I64_CONSTANT(10000000));  /* seconds */\n}\n#endif  /* DUK_USE_DATE_TZO_WINDOWS_NO_DST */\n\n#if defined(DUK_USE_GET_MONOTONIC_TIME_WINDOWS_QPC)\nDUK_INTERNAL duk_double_t duk_bi_date_get_monotonic_time_windows_qpc(void) {\n\tLARGE_INTEGER count, freq;\n\n\t/* There are legacy issues with QueryPerformanceCounter():\n\t * - Potential jumps: https://support.microsoft.com/en-us/help/274323/performance-counter-value-may-unexpectedly-leap-forward\n\t * - Differences between cores (XP): https://msdn.microsoft.com/en-us/library/windows/desktop/dn553408(v=vs.85).aspx#qpc_support_in_windows_versions\n\t *\n\t * We avoid these by enabling QPC by default only for Vista or later.\n\t */\n\n\tif (QueryPerformanceCounter(&count) && QueryPerformanceFrequency(&freq)) {\n\t\t/* XXX: QueryPerformanceFrequency() can be cached */\n\t\treturn (duk_double_t) count.QuadPart / (duk_double_t) freq.QuadPart * 1000.0;\n\t} else {\n\t\t/* MSDN: \"On systems that run Windows XP or later, the function\n\t\t * will always succeed and will thus never return zero.\"\n\t\t * Provide minimal error path just in case user enables this\n\t\t * feature in pre-XP Windows.\n\t\t */\n\t\treturn 0.0;\n\t}\n}\n#endif  /* DUK_USE_GET_MONOTONIC_TIME_WINDOWS_QPC */\n#line 1 \"duk_bi_duktape.c\"\n/*\n *  Duktape built-ins\n *\n *  Size optimization note: it might seem that vararg multipurpose functions\n *  like fin(), enc(), and dec() are not very size optimal, but using a single\n *  user-visible Ecmascript function saves a lot of run-time footprint; each\n *  Function instance takes >100 bytes.  Using a shared native helper and a\n *  'magic' value won't save much if there are multiple Function instances\n *  anyway.\n */\n\n/* #include duk_internal.h -> already included */\n\n#if defined(DUK_USE_DUKTAPE_BUILTIN)\n\nDUK_INTERNAL duk_ret_t duk_bi_duktape_object_info(duk_hthread *thr) {\n\tduk_inspect_value(thr, -1);\n\treturn 1;\n}\n\nDUK_INTERNAL duk_ret_t duk_bi_duktape_object_act(duk_hthread *thr) {\n\tduk_int_t level;\n\n\tlevel = duk_to_int(thr, 0);\n\tduk_inspect_callstack_entry(thr, level);\n\treturn 1;\n}\n\nDUK_INTERNAL duk_ret_t duk_bi_duktape_object_gc(duk_hthread *thr) {\n\tduk_small_uint_t flags;\n\n\tflags = (duk_small_uint_t) duk_get_uint(thr, 0);\n\tduk_heap_mark_and_sweep(thr->heap, flags);\n\n\t/* XXX: Not sure what the best return value would be in the API.\n\t * Return true for now.\n\t */\n\tduk_push_true(thr);\n\treturn 1;\n}\n\n#if defined(DUK_USE_FINALIZER_SUPPORT)\nDUK_INTERNAL duk_ret_t duk_bi_duktape_object_fin(duk_hthread *thr) {\n\t(void) duk_require_hobject(thr, 0);\n\tif (duk_get_top(thr) >= 2) {\n\t\t/* Set: currently a finalizer is disabled by setting it to\n\t\t * undefined; this does not remove the property at the moment.\n\t\t * The value could be type checked to be either a function\n\t\t * or something else; if something else, the property could\n\t\t * be deleted.  Must use duk_set_finalizer() to keep\n\t\t * DUK_HOBJECT_FLAG_HAVE_FINALIZER in sync.\n\t\t */\n\t\tduk_set_top(thr, 2);\n\t\tduk_set_finalizer(thr, 0);\n\t\treturn 0;\n\t} else {\n\t\t/* Get. */\n\t\tDUK_ASSERT(duk_get_top(thr) == 1);\n\t\tduk_get_finalizer(thr, 0);\n\t\treturn 1;\n\t}\n}\n#endif  /* DUK_USE_FINALIZER_SUPPORT */\n\nDUK_INTERNAL duk_ret_t duk_bi_duktape_object_enc(duk_hthread *thr) {\n\tduk_hstring *h_str;\n\n\t/* Vararg function: must be careful to check/require arguments.\n\t * The JSON helpers accept invalid indices and treat them like\n\t * non-existent optional parameters.\n\t */\n\n\th_str = duk_require_hstring(thr, 0);  /* Could reject symbols, but no point: won't match comparisons. */\n\tduk_require_valid_index(thr, 1);\n\n\tif (h_str == DUK_HTHREAD_STRING_HEX(thr)) {\n\t\tduk_set_top(thr, 2);\n\t\tduk_hex_encode(thr, 1);\n\t\tDUK_ASSERT_TOP(thr, 2);\n\t} else if (h_str == DUK_HTHREAD_STRING_BASE64(thr)) {\n\t\tduk_set_top(thr, 2);\n\t\tduk_base64_encode(thr, 1);\n\t\tDUK_ASSERT_TOP(thr, 2);\n#if defined(DUK_USE_JSON_SUPPORT) && defined(DUK_USE_JX)\n\t} else if (h_str == DUK_HTHREAD_STRING_JX(thr)) {\n\t\tduk_bi_json_stringify_helper(thr,\n\t\t                             1 /*idx_value*/,\n\t\t                             2 /*idx_replacer*/,\n\t\t                             3 /*idx_space*/,\n\t\t                             DUK_JSON_FLAG_EXT_CUSTOM |\n\t\t                             DUK_JSON_FLAG_ASCII_ONLY |\n\t\t                             DUK_JSON_FLAG_AVOID_KEY_QUOTES /*flags*/);\n#endif\n#if defined(DUK_USE_JSON_SUPPORT) && defined(DUK_USE_JC)\n\t} else if (h_str == DUK_HTHREAD_STRING_JC(thr)) {\n\t\tduk_bi_json_stringify_helper(thr,\n\t\t                             1 /*idx_value*/,\n\t\t                             2 /*idx_replacer*/,\n\t\t                             3 /*idx_space*/,\n\t\t                             DUK_JSON_FLAG_EXT_COMPATIBLE |\n\t\t                             DUK_JSON_FLAG_ASCII_ONLY /*flags*/);\n#endif\n\t} else {\n\t\tDUK_DCERROR_TYPE_INVALID_ARGS(thr);\n\t}\n\treturn 1;\n}\n\nDUK_INTERNAL duk_ret_t duk_bi_duktape_object_dec(duk_hthread *thr) {\n\tduk_hstring *h_str;\n\n\t/* Vararg function: must be careful to check/require arguments.\n\t * The JSON helpers accept invalid indices and treat them like\n\t * non-existent optional parameters.\n\t */\n\n\th_str = duk_require_hstring(thr, 0);  /* Could reject symbols, but no point: won't match comparisons */\n\tduk_require_valid_index(thr, 1);\n\n\tif (h_str == DUK_HTHREAD_STRING_HEX(thr)) {\n\t\tduk_set_top(thr, 2);\n\t\tduk_hex_decode(thr, 1);\n\t\tDUK_ASSERT_TOP(thr, 2);\n\t} else if (h_str == DUK_HTHREAD_STRING_BASE64(thr)) {\n\t\tduk_set_top(thr, 2);\n\t\tduk_base64_decode(thr, 1);\n\t\tDUK_ASSERT_TOP(thr, 2);\n#if defined(DUK_USE_JSON_SUPPORT) && defined(DUK_USE_JX)\n\t} else if (h_str == DUK_HTHREAD_STRING_JX(thr)) {\n\t\tduk_bi_json_parse_helper(thr,\n\t\t                         1 /*idx_value*/,\n\t\t                         2 /*idx_replacer*/,\n\t\t                         DUK_JSON_FLAG_EXT_CUSTOM /*flags*/);\n#endif\n#if defined(DUK_USE_JSON_SUPPORT) && defined(DUK_USE_JC)\n\t} else if (h_str == DUK_HTHREAD_STRING_JC(thr)) {\n\t\tduk_bi_json_parse_helper(thr,\n\t\t                         1 /*idx_value*/,\n\t\t                         2 /*idx_replacer*/,\n\t\t                         DUK_JSON_FLAG_EXT_COMPATIBLE /*flags*/);\n#endif\n\t} else {\n\t\tDUK_DCERROR_TYPE_INVALID_ARGS(thr);\n\t}\n\treturn 1;\n}\n\n/*\n *  Compact an object\n */\n\nDUK_INTERNAL duk_ret_t duk_bi_duktape_object_compact(duk_hthread *thr) {\n\tDUK_ASSERT_TOP(thr, 1);\n\tduk_compact(thr, 0);\n\treturn 1;  /* return the argument object */\n}\n\n#endif  /* DUK_USE_DUKTAPE_BUILTIN */\n#line 1 \"duk_bi_encoding.c\"\n/*\n *  WHATWG Encoding API built-ins\n *\n *  API specification: https://encoding.spec.whatwg.org/#api\n *  Web IDL: https://www.w3.org/TR/WebIDL/\n */\n\n/* #include duk_internal.h -> already included */\n\n/*\n *  Data structures for encoding/decoding\n */\n\ntypedef struct {\n\tduk_uint8_t *out;      /* where to write next byte(s) */\n\tduk_codepoint_t lead;  /* lead surrogate */\n} duk__encode_context;\n\ntypedef struct {\n\t/* UTF-8 decoding state */\n\tduk_codepoint_t codepoint;  /* built up incrementally */\n\tduk_uint8_t upper;          /* max value of next byte (decode error otherwise) */\n\tduk_uint8_t lower;          /* min value of next byte (ditto) */\n\tduk_uint8_t needed;         /* how many more bytes we need */\n\tduk_uint8_t bom_handled;    /* BOM seen or no longer expected */\n\n\t/* Decoder configuration */\n\tduk_uint8_t fatal;\n\tduk_uint8_t ignore_bom;\n} duk__decode_context;\n\n/* The signed duk_codepoint_t type is used to signal a decoded codepoint\n * (>= 0) or various other states using negative values.\n */\n#define DUK__CP_CONTINUE   (-1)  /* continue to next byte, no completed codepoint */\n#define DUK__CP_ERROR      (-2)  /* decoding error */\n#define DUK__CP_RETRY      (-3)  /* decoding error; retry last byte */\n\n/*\n *  Raw helpers for encoding/decoding\n */\n\n/* Emit UTF-8 (= CESU-8) encoded U+FFFD (replacement char), i.e. ef bf bd. */\nDUK_LOCAL duk_uint8_t *duk__utf8_emit_repl(duk_uint8_t *ptr) {\n\t*ptr++ = 0xef;\n\t*ptr++ = 0xbf;\n\t*ptr++ = 0xbd;\n\treturn ptr;\n}\n\nDUK_LOCAL void duk__utf8_decode_init(duk__decode_context *dec_ctx) {\n\t/* (Re)init the decoding state of 'dec_ctx' but leave decoder\n\t * configuration fields untouched.\n\t */\n\tdec_ctx->codepoint = 0x0000L;\n\tdec_ctx->upper = 0xbf;\n\tdec_ctx->lower = 0x80;\n\tdec_ctx->needed = 0;\n\tdec_ctx->bom_handled = 0;\n}\n\nDUK_LOCAL duk_codepoint_t duk__utf8_decode_next(duk__decode_context *dec_ctx, duk_uint8_t x) {\n\t/*\n\t *  UTF-8 algorithm based on the Encoding specification:\n\t *  https://encoding.spec.whatwg.org/#utf-8-decoder\n\t *\n\t *  Two main states: decoding initial byte vs. decoding continuation\n\t *  bytes.  Shortest length encoding is validated by restricting the\n\t *  allowed range of first continuation byte using 'lower' and 'upper'.\n\t */\n\n\tif (dec_ctx->needed == 0) {\n\t\t/* process initial byte */\n\t\tif (x <= 0x7f) {\n\t\t\t/* U+0000-U+007F, 1 byte (ASCII) */\n\t\t\treturn (duk_codepoint_t) x;\n\t\t} else if (x >= 0xc2 && x <= 0xdf) {\n\t\t\t/* U+0080-U+07FF, 2 bytes */\n\t\t\tdec_ctx->needed = 1;\n\t\t\tdec_ctx->codepoint = x & 0x1f;\n\t\t\tDUK_ASSERT(dec_ctx->lower == 0x80);\n\t\t\tDUK_ASSERT(dec_ctx->upper == 0xbf);\n\t\t\treturn DUK__CP_CONTINUE;\n\t\t} else if (x >= 0xe0 && x <= 0xef) {\n\t\t\t/* U+0800-U+FFFF, 3 bytes */\n\t\t\tif (x == 0xe0) {\n\t\t\t\tdec_ctx->lower = 0xa0;\n\t\t\t\tDUK_ASSERT(dec_ctx->upper == 0xbf);\n\t\t\t} else if (x == 0xed) {\n\t\t\t\tDUK_ASSERT(dec_ctx->lower == 0x80);\n\t\t\t\tdec_ctx->upper = 0x9f;\n\t\t\t}\n\t\t\tdec_ctx->needed = 2;\n\t\t\tdec_ctx->codepoint = x & 0x0f;\n\t\t\treturn DUK__CP_CONTINUE;\n\t\t} else if (x >= 0xf0 && x <= 0xf4) {\n\t\t\t/* U+010000-U+10FFFF, 4 bytes */\n\t\t\tif (x == 0xf0) {\n\t\t\t\tdec_ctx->lower = 0x90;\n\t\t\t\tDUK_ASSERT(dec_ctx->upper == 0xbf);\n\t\t\t} else if (x == 0xf4) {\n\t\t\t\tDUK_ASSERT(dec_ctx->lower == 0x80);\n\t\t\t\tdec_ctx->upper = 0x8f;\n\t\t\t}\n\t\t\tdec_ctx->needed = 3;\n\t\t\tdec_ctx->codepoint = x & 0x07;\n\t\t\treturn DUK__CP_CONTINUE;\n\t\t} else {\n\t\t\t/* not a legal initial byte */\n\t\t\treturn DUK__CP_ERROR;\n\t\t}\n\t} else {\n\t\t/* process continuation byte */\n\t\tif (x >= dec_ctx->lower && x <= dec_ctx->upper) {\n\t\t\tdec_ctx->lower = 0x80;\n\t\t\tdec_ctx->upper = 0xbf;\n\t\t\tdec_ctx->codepoint = (dec_ctx->codepoint << 6) | (x & 0x3f);\n\t\t\tif (--dec_ctx->needed > 0) {\n\t\t\t\t/* need more bytes */\n\t\t\t\treturn DUK__CP_CONTINUE;\n\t\t\t} else {\n\t\t\t\t/* got a codepoint */\n\t\t\t\tduk_codepoint_t ret;\n\t\t\t\tDUK_ASSERT(dec_ctx->codepoint <= 0x10ffffL);  /* Decoding rules guarantee. */\n\t\t\t\tret = dec_ctx->codepoint;\n\t\t\t\tdec_ctx->codepoint = 0x0000L;\n\t\t\t\tdec_ctx->needed = 0;\n\t\t\t\treturn ret;\n\t\t\t}\n\t\t} else {\n\t\t\t/* We just encountered an illegal UTF-8 continuation byte.  This might\n\t\t\t * be the initial byte of the next character; if we return a plain\n\t\t\t * error status and the decoder is in replacement mode, the character\n\t\t\t * will be masked.  We still need to alert the caller to the error\n\t\t\t * though.\n\t\t\t */\n\t\t\tdec_ctx->codepoint = 0x0000L;\n\t\t\tdec_ctx->needed = 0;\n\t\t\tdec_ctx->lower = 0x80;\n\t\t\tdec_ctx->upper = 0xbf;\n\t\t\treturn DUK__CP_RETRY;\n\t\t}\n\t}\n}\n\n#if defined(DUK_USE_ENCODING_BUILTINS)\nDUK_LOCAL void duk__utf8_encode_char(void *udata, duk_codepoint_t codepoint) {\n\tduk__encode_context *enc_ctx;\n\n\tDUK_ASSERT(codepoint >= 0);\n\tenc_ctx = (duk__encode_context *) udata;\n\tDUK_ASSERT(enc_ctx != NULL);\n\n#if !defined(DUK_USE_PREFER_SIZE)\n\tif (codepoint <= 0x7f && enc_ctx->lead == 0x0000L) {\n\t\t/* Fast path for ASCII. */\n\t\t*enc_ctx->out++ = (duk_uint8_t) codepoint;\n\t\treturn;\n\t}\n#endif\n\n\tif (DUK_UNLIKELY(codepoint > 0x10ffffL)) {\n\t\t/* cannot legally encode in UTF-8 */\n\t\tcodepoint = DUK_UNICODE_CP_REPLACEMENT_CHARACTER;\n\t} else if (codepoint >= 0xd800L && codepoint <= 0xdfffL) {\n\t\tif (codepoint <= 0xdbffL) {\n\t\t\t/* high surrogate */\n\t\t\tduk_codepoint_t prev_lead = enc_ctx->lead;\n\t\t\tenc_ctx->lead = codepoint;\n\t\t\tif (prev_lead == 0x0000L) {\n\t\t\t\t/* high surrogate, no output */\n\t\t\t\treturn;\n\t\t\t} else {\n\t\t\t\t/* consecutive high surrogates, consider first one unpaired */\n\t\t\t\tcodepoint = DUK_UNICODE_CP_REPLACEMENT_CHARACTER;\n\t\t\t}\n\t\t} else {\n\t\t\t/* low surrogate */\n\t\t\tif (enc_ctx->lead != 0x0000L) {\n\t\t\t\tcodepoint = (duk_codepoint_t) (0x010000L + ((enc_ctx->lead - 0xd800L) << 10) + (codepoint - 0xdc00L));\n\t\t\t\tenc_ctx->lead = 0x0000L;\n\t\t\t} else {\n\t\t\t\t/* unpaired low surrogate */\n\t\t\t\tDUK_ASSERT(enc_ctx->lead == 0x0000L);\n\t\t\t\tcodepoint = DUK_UNICODE_CP_REPLACEMENT_CHARACTER;\n\t\t\t}\n\t\t}\n\t} else {\n\t\tif (enc_ctx->lead != 0x0000L) {\n\t\t\t/* unpaired high surrogate: emit replacement character and the input codepoint */\n\t\t\tenc_ctx->lead = 0x0000L;\n\t\t\tenc_ctx->out = duk__utf8_emit_repl(enc_ctx->out);\n\t\t}\n\t}\n\n\t/* Codepoint may be original input, a decoded surrogate pair, or may\n\t * have been replaced with U+FFFD.\n\t */\n\tenc_ctx->out += duk_unicode_encode_xutf8((duk_ucodepoint_t) codepoint, enc_ctx->out);\n}\n#endif  /* DUK_USE_ENCODING_BUILTINS */\n\n/* Shared helper for buffer-to-string using a TextDecoder() compatible UTF-8\n * decoder.\n */\nDUK_LOCAL duk_ret_t duk__decode_helper(duk_hthread *thr, duk__decode_context *dec_ctx) {\n\tconst duk_uint8_t *input;\n\tduk_size_t len = 0;\n\tduk_size_t len_tmp;\n\tduk_bool_t stream = 0;\n\tduk_codepoint_t codepoint;\n\tduk_uint8_t *output;\n\tconst duk_uint8_t *in;\n\tduk_uint8_t *out;\n\n\tDUK_ASSERT(dec_ctx != NULL);\n\n\t/* Careful with input buffer pointer: any side effects involving\n\t * code execution (e.g. getters, coercion calls, and finalizers)\n\t * may cause a resize and invalidate a pointer we've read.  This\n\t * is why the pointer is actually looked up at the last minute.\n\t * Argument validation must still happen first to match WHATWG\n\t * required side effect order.\n\t */\n\n\tif (duk_is_undefined(thr, 0)) {\n\t\tduk_push_fixed_buffer_nozero(thr, 0);\n\t\tduk_replace(thr, 0);\n\t}\n\t(void) duk_require_buffer_data(thr, 0, &len);  /* Need 'len', avoid pointer. */\n\n\tif (duk_check_type_mask(thr, 1, DUK_TYPE_MASK_UNDEFINED |\n\t                                DUK_TYPE_MASK_NULL |\n\t                                DUK_TYPE_MASK_NONE)) {\n\t\t/* Use defaults, treat missing value like undefined. */\n\t} else {\n\t\tduk_require_type_mask(thr, 1, DUK_TYPE_MASK_UNDEFINED |\n\t                                      DUK_TYPE_MASK_NULL |\n\t                                      DUK_TYPE_MASK_LIGHTFUNC |\n\t                                      DUK_TYPE_MASK_BUFFER |\n\t\t                              DUK_TYPE_MASK_OBJECT);\n\t\tif (duk_get_prop_string(thr, 1, \"stream\")) {\n\t\t\tstream = duk_to_boolean(thr, -1);\n\t\t}\n\t}\n\n\t/* Allowance is 3*len in the general case because all bytes may potentially\n\t * become U+FFFD.  If the first byte completes a non-BMP codepoint it will\n\t * decode to a CESU-8 surrogate pair (6 bytes) so we allow 3 extra bytes to\n\t * compensate: (1*3)+3 = 6.  Non-BMP codepoints are safe otherwise because\n\t * the 4->6 expansion is well under the 3x allowance.\n\t *\n\t * XXX: As with TextEncoder, need a better buffer allocation strategy here.\n\t */\n\tif (len >= (DUK_HBUFFER_MAX_BYTELEN / 3) - 3) {\n\t\tDUK_ERROR_TYPE(thr, DUK_STR_RESULT_TOO_LONG);\n\t}\n\toutput = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, 3 + (3 * len));  /* used parts will be always manually written over */\n\n\tinput = (const duk_uint8_t *) duk_get_buffer_data(thr, 0, &len_tmp);\n\tDUK_ASSERT(input != NULL || len == 0);\n\tif (DUK_UNLIKELY(len != len_tmp)) {\n\t\t/* Very unlikely but possible: source buffer was resized by\n\t\t * a side effect when fixed buffer was pushed.  Output buffer\n\t\t * may not be large enough to hold output, so just fail if\n\t\t * length has changed.\n\t\t */\n\t\tDUK_D(DUK_DPRINT(\"input buffer resized by side effect, fail\"));\n\t\tgoto fail_type;\n\t}\n\n\t/* From this point onwards it's critical that no side effect occur\n\t * which may disturb 'input': finalizer execution, property accesses,\n\t * active coercions, etc.  Even an allocation related mark-and-sweep\n\t * may affect the pointer because it may trigger a pending finalizer.\n\t */\n\n\tin = input;\n\tout = output;\n\twhile (in < input + len) {\n\t\tcodepoint = duk__utf8_decode_next(dec_ctx, *in++);\n\t\tif (codepoint < 0) {\n\t\t\tif (codepoint == DUK__CP_CONTINUE) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t/* Decoding error with or without retry. */\n\t\t\tDUK_ASSERT(codepoint == DUK__CP_ERROR || codepoint == DUK__CP_RETRY);\n\t\t\tif (codepoint == DUK__CP_RETRY) {\n\t\t\t\t--in;  /* retry last byte */\n\t\t\t}\n\t\t\t/* replacement mode: replace with U+FFFD */\n\t\t\tcodepoint = DUK_UNICODE_CP_REPLACEMENT_CHARACTER;\n\t\t\tif (dec_ctx->fatal) {\n\t\t\t\t/* fatal mode: throw a TypeError */\n\t\t\t\tgoto fail_type;\n\t\t\t}\n\t\t\t/* Continue with 'codepoint', Unicode replacement. */\n\t\t}\n\t\tDUK_ASSERT(codepoint >= 0x0000L && codepoint <= 0x10ffffL);\n\n\t\tif (!dec_ctx->bom_handled) {\n\t\t\tdec_ctx->bom_handled = 1;\n\t\t\tif (codepoint == 0xfeffL && !dec_ctx->ignore_bom) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\n\t\tout += duk_unicode_encode_cesu8((duk_ucodepoint_t) codepoint, out);\n\t\tDUK_ASSERT(out <= output + (3 + (3 * len)));\n\t}\n\n\tif (!stream) {\n\t\tif (dec_ctx->needed != 0) {\n\t\t\t/* truncated sequence at end of buffer */\n\t\t\tif (dec_ctx->fatal) {\n\t\t\t\tgoto fail_type;\n\t\t\t} else {\n\t\t\t\tout += duk_unicode_encode_cesu8(DUK_UNICODE_CP_REPLACEMENT_CHARACTER, out);\n\t\t\t\tDUK_ASSERT(out <= output + (3 + (3 * len)));\n\t\t\t}\n\t\t}\n\t\tduk__utf8_decode_init(dec_ctx);  /* Initialize decoding state for potential reuse. */\n\t}\n\n\t/* Output buffer is fixed and thus stable even if there had been\n\t * side effects (which there shouldn't be).\n\t */\n\tduk_push_lstring(thr, (const char *) output, (duk_size_t) (out - output));\n\treturn 1;\n\n fail_type:\n\tDUK_ERROR_TYPE(thr, DUK_STR_UTF8_DECODE_FAILED);\n\tDUK_UNREACHABLE();\n}\n\n/*\n *  Built-in bindings\n */\n\n#if defined(DUK_USE_ENCODING_BUILTINS)\nDUK_INTERNAL duk_ret_t duk_bi_textencoder_constructor(duk_hthread *thr) {\n\t/* TextEncoder currently requires no persistent state, so the constructor\n\t * does nothing on purpose.\n\t */\n\n\tduk_require_constructor_call(thr);\n\treturn 0;\n}\n\nDUK_INTERNAL duk_ret_t duk_bi_textencoder_prototype_encoding_getter(duk_hthread *thr) {\n\tduk_push_string(thr, \"utf-8\");\n\treturn 1;\n}\n\nDUK_INTERNAL duk_ret_t duk_bi_textencoder_prototype_encode(duk_hthread *thr) {\n\tduk__encode_context enc_ctx;\n\tduk_size_t len;\n\tduk_size_t final_len;\n\tduk_uint8_t *output;\n\n\tDUK_ASSERT_TOP(thr, 1);\n\tif (duk_is_undefined(thr, 0)) {\n\t\tlen = 0;\n\t} else {\n\t\tduk_hstring *h_input;\n\n\t\th_input = duk_to_hstring(thr, 0);\n\t\tDUK_ASSERT(h_input != NULL);\n\n\t\tlen = (duk_size_t) DUK_HSTRING_GET_CHARLEN(h_input);\n\t\tif (len >= DUK_HBUFFER_MAX_BYTELEN / 3) {\n\t\t\tDUK_ERROR_TYPE(thr, DUK_STR_RESULT_TOO_LONG);\n\t\t}\n\t}\n\n\t/* Allowance is 3*len because all bytes can potentially be replaced with\n\t * U+FFFD -- which rather inconveniently encodes to 3 bytes in UTF-8.\n\t * Rely on dynamic buffer data pointer stability: no other code has\n\t * access to the data pointer.\n\t *\n\t * XXX: The buffer allocation strategy used here is rather inefficient.\n\t * Maybe switch to a chunk-based strategy, or preprocess the string to\n\t * figure out the space needed ahead of time?\n\t */\n\tDUK_ASSERT(3 * len >= len);\n\toutput = (duk_uint8_t *) duk_push_dynamic_buffer(thr, 3 * len);\n\n\tif (len > 0) {\n\t\tDUK_ASSERT(duk_is_string(thr, 0));  /* True if len > 0. */\n\n\t\t/* XXX: duk_decode_string() is used to process the input\n\t\t * string.  For standard Ecmascript strings, represented\n\t\t * internally as CESU-8, this is fine.  However, behavior\n\t\t * beyond CESU-8 is not very strict: codepoints using an\n\t\t * extended form of UTF-8 are also accepted, and invalid\n\t\t * codepoint sequences (which are allowed in Duktape strings)\n\t\t * are not handled as well as they could (e.g. invalid\n\t\t * continuation bytes may mask following codepoints).\n\t\t * This is how Ecmascript code would also see such strings.\n\t\t * Maybe replace duk_decode_string() with an explicit strict\n\t\t * CESU-8 decoder here?\n\t\t */\n\t\tenc_ctx.lead = 0x0000L;\n\t\tenc_ctx.out = output;\n\t\tduk_decode_string(thr, 0, duk__utf8_encode_char, (void *) &enc_ctx);\n\t\tif (enc_ctx.lead != 0x0000L) {\n\t\t\t/* unpaired high surrogate at end of string */\n\t\t\tenc_ctx.out = duk__utf8_emit_repl(enc_ctx.out);\n\t\t\tDUK_ASSERT(enc_ctx.out <= output + (3 * len));\n\t\t}\n\n\t\t/* The output buffer is usually very much oversized, so shrink it to\n\t\t * actually needed size.  Pointer stability assumed up to this point.\n\t\t */\n\t\tDUK_ASSERT_TOP(thr, 2);\n\t\tDUK_ASSERT(output == (duk_uint8_t *) duk_get_buffer_data(thr, -1, NULL));\n\n\t\tfinal_len = (duk_size_t) (enc_ctx.out - output);\n\t\tduk_resize_buffer(thr, -1, final_len);\n\t\t/* 'output' and 'enc_ctx.out' are potentially invalidated by the resize. */\n\t} else {\n\t\tfinal_len = 0;\n\t}\n\n\t/* Standard WHATWG output is a Uint8Array.  Here the Uint8Array will\n\t * be backed by a dynamic buffer which differs from e.g. Uint8Arrays\n\t * created as 'new Uint8Array(N)'.  Ecmascript code won't see the\n\t * difference but C code will.  When bufferobjects are not supported,\n\t * returns a plain dynamic buffer.\n\t */\n#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)\n\tduk_push_buffer_object(thr, -1, 0, final_len, DUK_BUFOBJ_UINT8ARRAY);\n#endif\n\treturn 1;\n}\n\nDUK_INTERNAL duk_ret_t duk_bi_textdecoder_constructor(duk_hthread *thr) {\n\tduk__decode_context *dec_ctx;\n\tduk_bool_t fatal = 0;\n\tduk_bool_t ignore_bom = 0;\n\n\tDUK_ASSERT_TOP(thr, 2);\n\tduk_require_constructor_call(thr);\n\tif (!duk_is_undefined(thr, 0)) {\n\t\t/* XXX: For now ignore 'label' (encoding identifier). */\n\t\tduk_to_string(thr, 0);\n\t}\n\tif (!duk_is_null_or_undefined(thr, 1)) {\n\t\tif (duk_get_prop_string(thr, 1, \"fatal\")) {\n\t\t\tfatal = duk_to_boolean(thr, -1);\n\t\t}\n\t\tif (duk_get_prop_string(thr, 1, \"ignoreBOM\")) {\n\t\t\tignore_bom = duk_to_boolean(thr, -1);\n\t\t}\n\t}\n\n\tduk_push_this(thr);\n\n\t/* The decode context is not assumed to be zeroed; all fields are\n\t * initialized explicitly.\n\t */\n\tdec_ctx = (duk__decode_context *) duk_push_fixed_buffer(thr, sizeof(duk__decode_context));\n\tdec_ctx->fatal = (duk_uint8_t) fatal;\n\tdec_ctx->ignore_bom = (duk_uint8_t) ignore_bom;\n\tduk__utf8_decode_init(dec_ctx);  /* Initializes remaining fields. */\n\n\tduk_put_prop_string(thr, -2, DUK_INTERNAL_SYMBOL(\"Context\"));\n\treturn 0;\n}\n\n/* Get TextDecoder context from 'this'; leaves garbage on stack. */\nDUK_LOCAL duk__decode_context *duk__get_textdecoder_context(duk_hthread *thr) {\n\tduk__decode_context *dec_ctx;\n\tduk_push_this(thr);\n\tduk_get_prop_string(thr, -1, DUK_INTERNAL_SYMBOL(\"Context\"));\n\tdec_ctx = (duk__decode_context *) duk_require_buffer(thr, -1, NULL);\n\tDUK_ASSERT(dec_ctx != NULL);\n\treturn dec_ctx;\n}\n\nDUK_INTERNAL duk_ret_t duk_bi_textdecoder_prototype_shared_getter(duk_hthread *thr) {\n\tduk__decode_context *dec_ctx;\n\tduk_int_t magic;\n\n\tdec_ctx = duk__get_textdecoder_context(thr);\n\tmagic = duk_get_current_magic(thr);\n\tswitch (magic) {\n\tcase 0:\n\t\t/* Encoding is now fixed, so _Context lookup is only needed to\n\t\t * validate the 'this' binding (TypeError if not TextDecoder-like).\n\t\t */\n\t\tduk_push_string(thr, \"utf-8\");\n\t\tbreak;\n\tcase 1:\n\t\tduk_push_boolean(thr, dec_ctx->fatal);\n\t\tbreak;\n\tdefault:\n\t\tduk_push_boolean(thr, dec_ctx->ignore_bom);\n\t\tbreak;\n\t}\n\n\treturn 1;\n}\n\nDUK_INTERNAL duk_ret_t duk_bi_textdecoder_prototype_decode(duk_hthread *thr) {\n\tduk__decode_context *dec_ctx;\n\n\tdec_ctx = duk__get_textdecoder_context(thr);\n\treturn duk__decode_helper(thr, dec_ctx);\n}\n#endif  /* DUK_USE_ENCODING_BUILTINS */\n\n/*\n *  Internal helper for Node.js Buffer\n */\n\n/* Internal helper used for Node.js Buffer .toString().  Value stack convention\n * is currently odd: it mimics TextDecoder .decode() so that argument must be at\n * index 0, and decode options (not present for Buffer) at index 1.  Return value\n * is a Duktape/C function return value.\n */\nDUK_INTERNAL duk_ret_t duk_textdecoder_decode_utf8_nodejs(duk_hthread *thr) {\n\tduk__decode_context dec_ctx;\n\n\tdec_ctx.fatal = 0;  /* use replacement chars */\n\tdec_ctx.ignore_bom = 1;  /* ignore BOMs (matches Node.js Buffer .toString()) */\n\tduk__utf8_decode_init(&dec_ctx);\n\n\treturn duk__decode_helper(thr, &dec_ctx);\n}\n\n/* automatic undefs */\n#undef DUK__CP_CONTINUE\n#undef DUK__CP_ERROR\n#undef DUK__CP_RETRY\n#line 1 \"duk_bi_error.c\"\n/*\n *  Error built-ins\n */\n\n/* #include duk_internal.h -> already included */\n\nDUK_INTERNAL duk_ret_t duk_bi_error_constructor_shared(duk_hthread *thr) {\n\t/* Behavior for constructor and non-constructor call is\n\t * the same except for augmenting the created error.  When\n\t * called as a constructor, the caller (duk_new()) will handle\n\t * augmentation; when called as normal function, we need to do\n\t * it here.\n\t */\n\n\tduk_small_int_t bidx_prototype = duk_get_current_magic(thr);\n\n\t/* same for both error and each subclass like TypeError */\n\tduk_uint_t flags_and_class = DUK_HOBJECT_FLAG_EXTENSIBLE |\n\t                             DUK_HOBJECT_FLAG_FASTREFS |\n\t                             DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ERROR);\n\n\t(void) duk_push_object_helper(thr, flags_and_class, bidx_prototype);\n\n\t/* If message is undefined, the own property 'message' is not set at\n\t * all to save property space.  An empty message is inherited anyway.\n\t */\n\tif (!duk_is_undefined(thr, 0)) {\n\t\tduk_to_string(thr, 0);\n\t\tduk_dup_0(thr);  /* [ message error message ] */\n\t\tduk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_MESSAGE, DUK_PROPDESC_FLAGS_WC);\n\t}\n\n\t/* Augment the error if called as a normal function.  __FILE__ and __LINE__\n\t * are not desirable in this case.\n\t */\n\n#if defined(DUK_USE_AUGMENT_ERROR_CREATE)\n\tif (!duk_is_constructor_call(thr)) {\n\t\tduk_err_augment_error_create(thr, thr, NULL, 0, DUK_AUGMENT_FLAG_NOBLAME_FILELINE);\n\t}\n#endif\n\n\treturn 1;\n}\n\nDUK_INTERNAL duk_ret_t duk_bi_error_prototype_to_string(duk_hthread *thr) {\n\t/* XXX: optimize with more direct internal access */\n\n\tduk_push_this(thr);\n\t(void) duk_require_hobject_promote_mask(thr, -1, DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER);\n\n\t/* [ ... this ] */\n\n\tduk_get_prop_stridx_short(thr, -1, DUK_STRIDX_NAME);\n\tif (duk_is_undefined(thr, -1)) {\n\t\tduk_pop(thr);\n\t\tduk_push_string(thr, \"Error\");\n\t} else {\n\t\tduk_to_string(thr, -1);\n\t}\n\n\t/* [ ... this name ] */\n\n\t/* XXX: Are steps 6 and 7 in E5 Section 15.11.4.4 duplicated by\n\t * accident or are they actually needed?  The first ToString()\n\t * could conceivably return 'undefined'.\n\t */\n\tduk_get_prop_stridx_short(thr, -2, DUK_STRIDX_MESSAGE);\n\tif (duk_is_undefined(thr, -1)) {\n\t\tduk_pop(thr);\n\t\tduk_push_hstring_empty(thr);\n\t} else {\n\t\tduk_to_string(thr, -1);\n\t}\n\n\t/* [ ... this name message ] */\n\n\tif (duk_get_length(thr, -2) == 0) {\n\t\t/* name is empty -> return message */\n\t\treturn 1;\n\t}\n\tif (duk_get_length(thr, -1) == 0) {\n\t\t/* message is empty -> return name */\n\t\tduk_pop(thr);\n\t\treturn 1;\n\t}\n\tduk_push_string(thr, \": \");\n\tduk_insert(thr, -2);  /* ... name ': ' message */\n\tduk_concat(thr, 3);\n\n\treturn 1;\n}\n\n#if defined(DUK_USE_TRACEBACKS)\n\n/*\n *  Traceback handling\n *\n *  The unified helper decodes the traceback and produces various requested\n *  outputs.  It should be optimized for size, and may leave garbage on stack,\n *  only the topmost return value matters.  For instance, traceback separator\n *  and decoded strings are pushed even when looking for filename only.\n *\n *  NOTE: although _Tracedata is an internal property, user code can currently\n *  write to the array (or replace it with something other than an array).\n *  The code below must tolerate arbitrary _Tracedata.  It can throw errors\n *  etc, but cannot cause a segfault or memory unsafe behavior.\n */\n\n/* constants arbitrary, chosen for small loads */\n#define DUK__OUTPUT_TYPE_TRACEBACK   (-1)\n#define DUK__OUTPUT_TYPE_FILENAME    0\n#define DUK__OUTPUT_TYPE_LINENUMBER  1\n\nDUK_LOCAL duk_ret_t duk__error_getter_helper(duk_hthread *thr, duk_small_int_t output_type) {\n\tduk_idx_t idx_td;\n\tduk_small_int_t i;  /* traceback depth fits into 16 bits */\n\tduk_small_int_t t;  /* stack type fits into 16 bits */\n\tduk_small_int_t count_func = 0;  /* traceback depth ensures fits into 16 bits */\n\tconst char *str_tailcall = \" tailcall\";\n\tconst char *str_strict = \" strict\";\n\tconst char *str_construct = \" construct\";\n\tconst char *str_prevyield = \" preventsyield\";\n\tconst char *str_directeval = \" directeval\";\n\tconst char *str_empty = \"\";\n\n\tDUK_ASSERT_TOP(thr, 0);  /* fixed arg count */\n\n\tduk_push_this(thr);\n\tduk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INT_TRACEDATA);\n\tidx_td = duk_get_top_index(thr);\n\n\tduk_push_hstring_stridx(thr, DUK_STRIDX_NEWLINE_4SPACE);\n\tduk_push_this(thr);\n\n\t/* [ ... this tracedata sep this ] */\n\n\t/* XXX: skip null filename? */\n\n\tif (duk_check_type(thr, idx_td, DUK_TYPE_OBJECT)) {\n\t\t/* Current tracedata contains 2 entries per callstack entry. */\n\t\tfor (i = 0; ; i += 2) {\n\t\t\tduk_int_t pc;\n\t\t\tduk_uint_t line;\n\t\t\tduk_uint_t flags;\n\t\t\tduk_double_t d;\n\t\t\tconst char *funcname;\n\t\t\tconst char *filename;\n\t\t\tduk_hobject *h_func;\n\t\t\tduk_hstring *h_name;\n\n\t\t\tduk_require_stack(thr, 5);\n\t\t\tduk_get_prop_index(thr, idx_td, (duk_uarridx_t) i);\n\t\t\tduk_get_prop_index(thr, idx_td, (duk_uarridx_t) (i + 1));\n\t\t\td = duk_to_number_m1(thr);\n\t\t\tpc = (duk_int_t) DUK_FMOD(d, DUK_DOUBLE_2TO32);\n\t\t\tflags = (duk_uint_t) DUK_FLOOR(d / DUK_DOUBLE_2TO32);\n\t\t\tt = (duk_small_int_t) duk_get_type(thr, -2);\n\n\t\t\tif (t == DUK_TYPE_OBJECT || t == DUK_TYPE_LIGHTFUNC) {\n\t\t\t\t/*\n\t\t\t\t *  Ecmascript/native function call or lightfunc call\n\t\t\t\t */\n\n\t\t\t\tcount_func++;\n\n\t\t\t\t/* [ ... v1(func) v2(pc+flags) ] */\n\n\t\t\t\t/* These may be systematically omitted by Duktape\n\t\t\t\t * with certain config options, but allow user to\n\t\t\t\t * set them on a case-by-case basis.\n\t\t\t\t */\n\t\t\t\tduk_get_prop_stridx_short(thr, -2, DUK_STRIDX_NAME);\n\t\t\t\tduk_get_prop_stridx_short(thr, -3, DUK_STRIDX_FILE_NAME);\n\n#if defined(DUK_USE_PC2LINE)\n\t\t\t\tline = (duk_uint_t) duk_hobject_pc2line_query(thr, -4, (duk_uint_fast32_t) pc);\n#else\n\t\t\t\tline = 0;\n#endif\n\n\t\t\t\t/* [ ... v1 v2 name filename ] */\n\n\t\t\t\t/* When looking for .fileName/.lineNumber, blame first\n\t\t\t\t * function which has a .fileName.\n\t\t\t\t */\n\t\t\t\tif (duk_is_string_notsymbol(thr, -1)) {\n\t\t\t\t\tif (output_type == DUK__OUTPUT_TYPE_FILENAME) {\n\t\t\t\t\t\treturn 1;\n\t\t\t\t\t} else if (output_type == DUK__OUTPUT_TYPE_LINENUMBER) {\n\t\t\t\t\t\tduk_push_uint(thr, line);\n\t\t\t\t\t\treturn 1;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t/* XXX: Change 'anon' handling here too, to use empty string for anonymous functions? */\n\t\t\t\t/* XXX: Could be improved by coercing to a readable duk_tval (especially string escaping) */\n\t\t\t\th_name = duk_get_hstring_notsymbol(thr, -2);  /* may be NULL */\n\t\t\t\tfuncname = (h_name == NULL || h_name == DUK_HTHREAD_STRING_EMPTY_STRING(thr)) ?\n\t\t\t\t           \"[anon]\" : (const char *) DUK_HSTRING_GET_DATA(h_name);\n\t\t\t\tfilename = duk_get_string_notsymbol(thr, -1);\n\t\t\t\tfilename = filename ? filename : \"\";\n\t\t\t\tDUK_ASSERT(funcname != NULL);\n\t\t\t\tDUK_ASSERT(filename != NULL);\n\n\t\t\t\th_func = duk_get_hobject(thr, -4);  /* NULL for lightfunc */\n\n\t\t\t\tif (h_func == NULL) {\n\t\t\t\t\tduk_push_sprintf(thr, \"at %s light%s%s%s%s%s\",\n\t\t\t\t\t                 (const char *) funcname,\n\t\t\t\t\t                 (const char *) ((flags & DUK_ACT_FLAG_STRICT) ? str_strict : str_empty),\n\t\t\t\t\t                 (const char *) ((flags & DUK_ACT_FLAG_TAILCALLED) ? str_tailcall : str_empty),\n\t\t\t\t\t                 (const char *) ((flags & DUK_ACT_FLAG_CONSTRUCT) ? str_construct : str_empty),\n\t\t\t\t\t                 (const char *) ((flags & DUK_ACT_FLAG_DIRECT_EVAL) ? str_directeval : str_empty),\n\t\t\t\t\t                 (const char *) ((flags & DUK_ACT_FLAG_PREVENT_YIELD) ? str_prevyield : str_empty));\n\t\t\t\t} else if (DUK_HOBJECT_HAS_NATFUNC(h_func)) {\n\t\t\t\t\tduk_push_sprintf(thr, \"at %s (%s) native%s%s%s%s%s\",\n\t\t\t\t\t                 (const char *) funcname,\n\t\t\t\t\t                 (const char *) filename,\n\t\t\t\t\t                 (const char *) ((flags & DUK_ACT_FLAG_STRICT) ? str_strict : str_empty),\n\t\t\t\t\t                 (const char *) ((flags & DUK_ACT_FLAG_TAILCALLED) ? str_tailcall : str_empty),\n\t\t\t\t\t                 (const char *) ((flags & DUK_ACT_FLAG_CONSTRUCT) ? str_construct : str_empty),\n\t\t\t\t\t                 (const char *) ((flags & DUK_ACT_FLAG_DIRECT_EVAL) ? str_directeval : str_empty),\n\t\t\t\t\t                 (const char *) ((flags & DUK_ACT_FLAG_PREVENT_YIELD) ? str_prevyield : str_empty));\n\t\t\t\t} else {\n\t\t\t\t\tduk_push_sprintf(thr, \"at %s (%s:%lu)%s%s%s%s%s\",\n\t\t\t\t\t                 (const char *) funcname,\n\t\t\t\t\t                 (const char *) filename,\n\t\t\t\t\t                 (unsigned long) line,\n\t\t\t\t\t                 (const char *) ((flags & DUK_ACT_FLAG_STRICT) ? str_strict : str_empty),\n\t\t\t\t\t                 (const char *) ((flags & DUK_ACT_FLAG_TAILCALLED) ? str_tailcall : str_empty),\n\t\t\t\t\t                 (const char *) ((flags & DUK_ACT_FLAG_CONSTRUCT) ? str_construct : str_empty),\n\t\t\t\t\t                 (const char *) ((flags & DUK_ACT_FLAG_DIRECT_EVAL) ? str_directeval : str_empty),\n\t\t\t\t\t                 (const char *) ((flags & DUK_ACT_FLAG_PREVENT_YIELD) ? str_prevyield : str_empty));\n\t\t\t\t}\n\t\t\t\tduk_replace(thr, -5);   /* [ ... v1 v2 name filename str ] -> [ ... str v2 name filename ] */\n\t\t\t\tduk_pop_3(thr);         /* -> [ ... str ] */\n\t\t\t} else if (t == DUK_TYPE_STRING) {\n\t\t\t\tconst char *str_file;\n\n\t\t\t\t/*\n\t\t\t\t *  __FILE__ / __LINE__ entry, here 'pc' is line number directly.\n\t\t\t\t *  Sometimes __FILE__ / __LINE__ is reported as the source for\n\t\t\t\t *  the error (fileName, lineNumber), sometimes not.\n\t\t\t\t */\n\n\t\t\t\t/* [ ... v1(filename) v2(line+flags) ] */\n\n\t\t\t\t/* When looking for .fileName/.lineNumber, blame compilation\n\t\t\t\t * or C call site unless flagged not to do so.\n\t\t\t\t */\n\t\t\t\tif (!(flags & DUK_TB_FLAG_NOBLAME_FILELINE)) {\n\t\t\t\t\tif (output_type == DUK__OUTPUT_TYPE_FILENAME) {\n\t\t\t\t\t\tduk_pop(thr);\n\t\t\t\t\t\treturn 1;\n\t\t\t\t\t} else if (output_type == DUK__OUTPUT_TYPE_LINENUMBER) {\n\t\t\t\t\t\tduk_push_int(thr, pc);\n\t\t\t\t\t\treturn 1;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t/* Tracedata is trusted but avoid any risk of using a NULL\n\t\t\t\t * for %s format because it has undefined behavior.  Symbols\n\t\t\t\t * don't need to be explicitly rejected as they pose no memory\n\t\t\t\t * safety issues.\n\t\t\t\t */\n\t\t\t\tstr_file = (const char *) duk_get_string(thr, -2);\n\t\t\t\tduk_push_sprintf(thr, \"at [anon] (%s:%ld) internal\",\n\t\t\t\t                 (const char *) (str_file ? str_file : \"null\"), (long) pc);\n\t\t\t\tduk_replace(thr, -3);  /* [ ... v1 v2 str ] -> [ ... str v2 ] */\n\t\t\t\tduk_pop(thr);          /* -> [ ... str ] */\n\t\t\t} else {\n\t\t\t\t/* unknown, ignore */\n\t\t\t\tduk_pop_2(thr);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif (count_func >= DUK_USE_TRACEBACK_DEPTH) {\n\t\t\t/* Possibly truncated; there is no explicit truncation\n\t\t\t * marker so this is the best we can do.\n\t\t\t */\n\n\t\t\tduk_push_hstring_stridx(thr, DUK_STRIDX_BRACKETED_ELLIPSIS);\n\t\t}\n\t}\n\n\t/* [ ... this tracedata sep this str1 ... strN ] */\n\n\tif (output_type != DUK__OUTPUT_TYPE_TRACEBACK) {\n\t\treturn 0;\n\t} else {\n\t\t/* The 'this' after 'sep' will get ToString() coerced by\n\t\t * duk_join() automatically.  We don't want to do that\n\t\t * coercion when providing .fileName or .lineNumber (GH-254).\n\t\t */\n\t\tduk_join(thr, duk_get_top(thr) - (idx_td + 2) /*count, not including sep*/);\n\t\treturn 1;\n\t}\n}\n\n/* XXX: Output type could be encoded into native function 'magic' value to\n * save space.  For setters the stridx could be encoded into 'magic'.\n */\n\nDUK_INTERNAL duk_ret_t duk_bi_error_prototype_stack_getter(duk_hthread *thr) {\n\treturn duk__error_getter_helper(thr, DUK__OUTPUT_TYPE_TRACEBACK);\n}\n\nDUK_INTERNAL duk_ret_t duk_bi_error_prototype_filename_getter(duk_hthread *thr) {\n\treturn duk__error_getter_helper(thr, DUK__OUTPUT_TYPE_FILENAME);\n}\n\nDUK_INTERNAL duk_ret_t duk_bi_error_prototype_linenumber_getter(duk_hthread *thr) {\n\treturn duk__error_getter_helper(thr, DUK__OUTPUT_TYPE_LINENUMBER);\n}\n\n#else  /* DUK_USE_TRACEBACKS */\n\n/*\n *  Traceback handling when tracebacks disabled.\n *\n *  The fileName / lineNumber stubs are now necessary because built-in\n *  data will include the accessor properties in Error.prototype.  If those\n *  are removed for builds without tracebacks, these can also be removed.\n *  'stack' should still be present and produce a ToString() equivalent:\n *  this is useful for user code which prints a stacktrace and expects to\n *  see something useful.  A normal stacktrace also begins with a ToString()\n *  of the error so this makes sense.\n */\n\nDUK_INTERNAL duk_ret_t duk_bi_error_prototype_stack_getter(duk_hthread *thr) {\n\t/* XXX: remove this native function and map 'stack' accessor\n\t * to the toString() implementation directly.\n\t */\n\treturn duk_bi_error_prototype_to_string(thr);\n}\n\nDUK_INTERNAL duk_ret_t duk_bi_error_prototype_filename_getter(duk_hthread *thr) {\n\tDUK_UNREF(thr);\n\treturn 0;\n}\n\nDUK_INTERNAL duk_ret_t duk_bi_error_prototype_linenumber_getter(duk_hthread *thr) {\n\tDUK_UNREF(thr);\n\treturn 0;\n}\n\n#endif  /* DUK_USE_TRACEBACKS */\n\nDUK_LOCAL duk_ret_t duk__error_setter_helper(duk_hthread *thr, duk_small_uint_t stridx_key) {\n\t/* Attempt to write 'stack', 'fileName', 'lineNumber' works as if\n\t * user code called Object.defineProperty() to create an overriding\n\t * own property.  This allows user code to overwrite .fileName etc\n\t * intuitively as e.g. \"err.fileName = 'dummy'\" as one might expect.\n\t * See https://github.com/svaarala/duktape/issues/387.\n\t */\n\n\tDUK_ASSERT_TOP(thr, 1);  /* fixed arg count: value */\n\n\tduk_push_this(thr);\n\tduk_push_hstring_stridx(thr, stridx_key);\n\tduk_dup_0(thr);\n\n\t/* [ ... obj key value ] */\n\n\tDUK_DD(DUK_DDPRINT(\"error setter: %!T %!T %!T\",\n\t                   duk_get_tval(thr, -3), duk_get_tval(thr, -2), duk_get_tval(thr, -1)));\n\n\tduk_def_prop(thr, -3, DUK_DEFPROP_HAVE_VALUE |\n\t                      DUK_DEFPROP_HAVE_WRITABLE | DUK_DEFPROP_WRITABLE |\n\t                      DUK_DEFPROP_HAVE_ENUMERABLE | /*not enumerable*/\n\t                      DUK_DEFPROP_HAVE_CONFIGURABLE | DUK_DEFPROP_CONFIGURABLE);\n\treturn 0;\n}\n\nDUK_INTERNAL duk_ret_t duk_bi_error_prototype_stack_setter(duk_hthread *thr) {\n\treturn duk__error_setter_helper(thr, DUK_STRIDX_STACK);\n}\n\nDUK_INTERNAL duk_ret_t duk_bi_error_prototype_filename_setter(duk_hthread *thr) {\n\treturn duk__error_setter_helper(thr, DUK_STRIDX_FILE_NAME);\n}\n\nDUK_INTERNAL duk_ret_t duk_bi_error_prototype_linenumber_setter(duk_hthread *thr) {\n\treturn duk__error_setter_helper(thr, DUK_STRIDX_LINE_NUMBER);\n}\n\n/* automatic undefs */\n#undef DUK__OUTPUT_TYPE_FILENAME\n#undef DUK__OUTPUT_TYPE_LINENUMBER\n#undef DUK__OUTPUT_TYPE_TRACEBACK\n#line 1 \"duk_bi_function.c\"\n/*\n *  Function built-ins\n */\n\n/* #include duk_internal.h -> already included */\n\n/* Needed even when Function built-in is disabled. */\nDUK_INTERNAL duk_ret_t duk_bi_function_prototype(duk_hthread *thr) {\n\t/* ignore arguments, return undefined (E5 Section 15.3.4) */\n\tDUK_UNREF(thr);\n\treturn 0;\n}\n\n#if defined(DUK_USE_FUNCTION_BUILTIN)\nDUK_INTERNAL duk_ret_t duk_bi_function_constructor(duk_hthread *thr) {\n\tduk_hstring *h_sourcecode;\n\tduk_idx_t nargs;\n\tduk_idx_t i;\n\tduk_small_uint_t comp_flags;\n\tduk_hcompfunc *func;\n\tduk_hobject *outer_lex_env;\n\tduk_hobject *outer_var_env;\n\n\t/* normal and constructor calls have identical semantics */\n\n\tnargs = duk_get_top(thr);\n\tfor (i = 0; i < nargs; i++) {\n\t\tduk_to_string(thr, i);  /* Rejects Symbols during coercion. */\n\t}\n\n\tif (nargs == 0) {\n\t\tduk_push_hstring_empty(thr);\n\t\tduk_push_hstring_empty(thr);\n\t} else if (nargs == 1) {\n\t\t/* XXX: cover this with the generic >1 case? */\n\t\tduk_push_hstring_empty(thr);\n\t} else {\n\t\tduk_insert(thr, 0);   /* [ arg1 ... argN-1 body] -> [body arg1 ... argN-1] */\n\t\tduk_push_string(thr, \",\");\n\t\tduk_insert(thr, 1);\n\t\tduk_join(thr, nargs - 1);\n\t}\n\n\t/* [ body formals ], formals is comma separated list that needs to be parsed */\n\n\tDUK_ASSERT_TOP(thr, 2);\n\n\t/* XXX: this placeholder is not always correct, but use for now.\n\t * It will fail in corner cases; see test-dev-func-cons-args.js.\n\t */\n\tduk_push_string(thr, \"function(\");\n\tduk_dup_1(thr);\n\tduk_push_string(thr, \"){\");\n\tduk_dup_0(thr);\n\tduk_push_string(thr, \"}\");\n\tduk_concat(thr, 5);\n\n\t/* [ body formals source ] */\n\n\tDUK_ASSERT_TOP(thr, 3);\n\n\t/* strictness is not inherited, intentional */\n\tcomp_flags = DUK_COMPILE_FUNCEXPR;\n\n\tduk_push_hstring_stridx(thr, DUK_STRIDX_COMPILE);  /* XXX: copy from caller? */  /* XXX: ignored now */\n\th_sourcecode = duk_require_hstring(thr, -2);  /* no symbol check needed; -2 is concat'd code */\n\tduk_js_compile(thr,\n\t               (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_sourcecode),\n\t               (duk_size_t) DUK_HSTRING_GET_BYTELEN(h_sourcecode),\n\t               comp_flags);\n\n\t/* Force .name to 'anonymous' (ES2015). */\n\tduk_push_string(thr, \"anonymous\");\n\tduk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_NAME, DUK_PROPDESC_FLAGS_C);\n\n\tfunc = (duk_hcompfunc *) duk_known_hobject(thr, -1);\n\tDUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC((duk_hobject *) func));\n\tDUK_ASSERT(DUK_HOBJECT_HAS_CONSTRUCTABLE((duk_hobject *) func));\n\n\t/* [ body formals source template ] */\n\n\t/* only outer_lex_env matters, as functions always get a new\n\t * variable declaration environment.\n\t */\n\n\touter_lex_env = thr->builtins[DUK_BIDX_GLOBAL_ENV];\n\touter_var_env = thr->builtins[DUK_BIDX_GLOBAL_ENV];\n\n\tduk_js_push_closure(thr, func, outer_var_env, outer_lex_env, 1 /*add_auto_proto*/);\n\n\t/* [ body formals source template closure ] */\n\n\treturn 1;\n}\n#endif  /* DUK_USE_FUNCTION_BUILTIN */\n\n#if defined(DUK_USE_FUNCTION_BUILTIN)\nDUK_INTERNAL duk_ret_t duk_bi_function_prototype_to_string(duk_hthread *thr) {\n\tduk_tval *tv;\n\n\t/*\n\t *  E5 Section 15.3.4.2 places few requirements on the output of\n\t *  this function: the result is implementation dependent, must\n\t *  follow FunctionDeclaration syntax (in particular, must have a\n\t *  name even for anonymous functions or functions with empty name).\n\t *  The output does NOT need to compile into anything useful.\n\t *\n\t *  E6 Section 19.2.3.5 changes the requirements completely: the\n\t *  result must either eval() to a functionally equivalent object\n\t *  OR eval() to a SyntaxError.\n\t *\n\t *  We opt for the SyntaxError approach for now, with a syntax that\n\t *  mimics V8's native function syntax:\n\t *\n\t *      'function cos() { [native code] }'\n\t *\n\t *  but extended with [ecmascript code], [bound code], and\n\t *  [lightfunc code].\n\t */\n\n\tduk_push_this(thr);\n\ttv = DUK_GET_TVAL_NEGIDX(thr, -1);\n\tDUK_ASSERT(tv != NULL);\n\n\tif (DUK_TVAL_IS_OBJECT(tv)) {\n\t\tduk_hobject *obj = DUK_TVAL_GET_OBJECT(tv);\n\t\tconst char *func_name;\n\n\t\t/* Function name: missing/undefined is mapped to empty string,\n\t\t * otherwise coerce to string.  No handling for invalid identifier\n\t\t * characters or e.g. '{' in the function name.  This doesn't\n\t\t * really matter as long as a SyntaxError results.  Technically\n\t\t * if the name contained a suitable prefix followed by '//' it\n\t\t * might cause the result to parse without error.\n\t\t */\n\t\tduk_get_prop_stridx_short(thr, -1, DUK_STRIDX_NAME);\n\t\tif (duk_is_undefined(thr, -1)) {\n\t\t\tfunc_name = \"\";\n\t\t} else {\n\t\t\tfunc_name = duk_to_string(thr, -1);\n\t\t\tDUK_ASSERT(func_name != NULL);\n\t\t}\n\n\t\tif (DUK_HOBJECT_IS_COMPFUNC(obj)) {\n\t\t\tduk_push_sprintf(thr, \"function %s() { [ecmascript code] }\", (const char *) func_name);\n\t\t} else if (DUK_HOBJECT_IS_NATFUNC(obj)) {\n\t\t\tduk_push_sprintf(thr, \"function %s() { [native code] }\", (const char *) func_name);\n\t\t} else if (DUK_HOBJECT_IS_BOUNDFUNC(obj)) {\n\t\t\tduk_push_sprintf(thr, \"function %s() { [bound code] }\", (const char *) func_name);\n\t\t} else {\n\t\t\tgoto type_error;\n\t\t}\n\t} else if (DUK_TVAL_IS_LIGHTFUNC(tv)) {\n\t\tduk_push_lightfunc_tostring(thr, tv);\n\t} else {\n\t\tgoto type_error;\n\t}\n\n\treturn 1;\n\n type_error:\n\tDUK_DCERROR_TYPE_INVALID_ARGS(thr);\n}\n#endif\n\n/* Always present because the native function pointer is needed in call\n * handling.\n */\nDUK_INTERNAL duk_ret_t duk_bi_function_prototype_call(duk_hthread *thr) {\n\t/* .call() is dealt with in call handling by simulating its\n\t * effects so this function is actually never called.\n\t */\n\tDUK_UNREF(thr);\n\treturn DUK_RET_TYPE_ERROR;\n}\n\nDUK_INTERNAL duk_ret_t duk_bi_function_prototype_apply(duk_hthread *thr) {\n\t/* Like .call(), never actually called. */\n\tDUK_UNREF(thr);\n\treturn DUK_RET_TYPE_ERROR;\n}\n\nDUK_INTERNAL duk_ret_t duk_bi_reflect_apply(duk_hthread *thr) {\n\t/* Like .call(), never actually called. */\n\tDUK_UNREF(thr);\n\treturn DUK_RET_TYPE_ERROR;\n}\n\nDUK_INTERNAL duk_ret_t duk_bi_reflect_construct(duk_hthread *thr) {\n\t/* Like .call(), never actually called. */\n\tDUK_UNREF(thr);\n\treturn DUK_RET_TYPE_ERROR;\n}\n\n#if defined(DUK_USE_FUNCTION_BUILTIN)\n/* Create a bound function which points to a target function which may\n * be bound or non-bound.  If the target is bound, the argument lists\n * and 'this' binding of the functions are merged and the resulting\n * function points directly to the non-bound target.\n */\nDUK_INTERNAL duk_ret_t duk_bi_function_prototype_bind(duk_hthread *thr) {\n\tduk_hboundfunc *h_bound;\n\tduk_idx_t nargs;  /* bound args, not counting 'this' binding */\n\tduk_idx_t bound_nargs;\n\tduk_int_t bound_len;\n\tduk_tval *tv_prevbound;\n\tduk_idx_t n_prevbound;\n\tduk_tval *tv_res;\n\tduk_tval *tv_tmp;\n\n\t/* XXX: C API call, e.g. duk_push_bound_function(thr, target_idx, nargs); */\n\n\t/* Vararg function, careful arg handling, e.g. thisArg may not\n\t * be present.\n\t */\n\tnargs = duk_get_top(thr) - 1;  /* actual args, not counting 'this' binding */\n\tif (nargs < 0) {\n\t\tnargs++;\n\t\tduk_push_undefined(thr);\n\t}\n\tDUK_ASSERT(nargs >= 0);\n\n\t/* Limit 'nargs' for bound functions to guarantee arithmetic\n\t * below will never wrap.\n\t */\n\tif (nargs > (duk_idx_t) DUK_HBOUNDFUNC_MAX_ARGS) {\n\t\tDUK_DCERROR_RANGE_INVALID_COUNT(thr);\n\t}\n\n\tduk_push_this(thr);\n\tduk_require_callable(thr, -1);\n\n\t/* [ thisArg arg1 ... argN func ]  (thisArg+args == nargs+1 total) */\n\tDUK_ASSERT_TOP(thr, nargs + 2);\n\n\t/* Create bound function object. */\n\th_bound = duk_push_hboundfunc(thr);\n\tDUK_ASSERT(DUK_TVAL_IS_UNDEFINED(&h_bound->target));\n\tDUK_ASSERT(DUK_TVAL_IS_UNDEFINED(&h_bound->this_binding));\n\tDUK_ASSERT(h_bound->args == NULL);\n\tDUK_ASSERT(h_bound->nargs == 0);\n\tDUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) h_bound) == NULL);\n\n\t/* [ thisArg arg1 ... argN func boundFunc ] */\n\n\t/* If the target is a bound function, argument lists must be\n\t * merged.  The 'this' binding closest to the target function\n\t * wins because in call handling the 'this' gets replaced over\n\t * and over again until we call the non-bound function.\n\t */\n\ttv_prevbound = NULL;\n\tn_prevbound = 0;\n\ttv_tmp = DUK_GET_TVAL_POSIDX(thr, 0);\n\tDUK_TVAL_SET_TVAL(&h_bound->this_binding, tv_tmp);\n\ttv_tmp = DUK_GET_TVAL_NEGIDX(thr, -2);\n\tDUK_TVAL_SET_TVAL(&h_bound->target, tv_tmp);\n\n\tif (DUK_TVAL_IS_OBJECT(tv_tmp)) {\n\t\tduk_hobject *h_target;\n\t\tduk_hobject *bound_proto;\n\n\t\th_target = DUK_TVAL_GET_OBJECT(tv_tmp);\n\t\tDUK_ASSERT(DUK_HOBJECT_IS_CALLABLE(h_target));\n\n\t\t/* Internal prototype must be copied from the target.\n\t\t * For lightfuncs Function.prototype is used and is already\n\t\t * in place.\n\t\t */\n\t\tbound_proto = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h_target);\n\t\tDUK_HOBJECT_SET_PROTOTYPE_INIT_INCREF(thr, (duk_hobject *) h_bound, bound_proto);\n\n\t\t/* The 'strict' flag is copied to get the special [[Get]] of E5.1\n\t\t * Section 15.3.5.4 to apply when a 'caller' value is a strict bound\n\t\t * function.  Not sure if this is correct, because the specification\n\t\t * is a bit ambiguous on this point but it would make sense.\n\t\t */\n\t\t/* Strictness is inherited from target. */\n\t\tif (DUK_HOBJECT_HAS_STRICT(h_target)) {\n\t\t\tDUK_HOBJECT_SET_STRICT((duk_hobject *) h_bound);\n\t\t}\n\n\t\tif (DUK_HOBJECT_HAS_BOUNDFUNC(h_target)) {\n\t\t\tduk_hboundfunc *h_boundtarget;\n\n\t\t\th_boundtarget = (duk_hboundfunc *) h_target;\n\n\t\t\t/* The final function should always be non-bound, unless\n\t\t\t * there's a bug in the internals.  Assert for it.\n\t\t\t */\n\t\t\tDUK_ASSERT(DUK_TVAL_IS_LIGHTFUNC(&h_boundtarget->target) ||\n\t\t\t           (DUK_TVAL_IS_OBJECT(&h_boundtarget->target) &&\n\t\t\t            DUK_HOBJECT_IS_CALLABLE(DUK_TVAL_GET_OBJECT(&h_boundtarget->target)) &&\n\t\t\t            !DUK_HOBJECT_IS_BOUNDFUNC(DUK_TVAL_GET_OBJECT(&h_boundtarget->target))));\n\n\t\t\tDUK_TVAL_SET_TVAL(&h_bound->target, &h_boundtarget->target);\n\t\t\tDUK_TVAL_SET_TVAL(&h_bound->this_binding, &h_boundtarget->this_binding);\n\n\t\t\ttv_prevbound = h_boundtarget->args;\n\t\t\tn_prevbound = h_boundtarget->nargs;\n\t\t}\n\t} else {\n\t\t/* Lightfuncs are always strict. */\n\t\tduk_hobject *bound_proto;\n\n\t\tDUK_ASSERT(DUK_TVAL_IS_LIGHTFUNC(tv_tmp));\n\t\tDUK_HOBJECT_SET_STRICT((duk_hobject *) h_bound);\n\t\tbound_proto = thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE];\n\t\tDUK_HOBJECT_SET_PROTOTYPE_INIT_INCREF(thr, (duk_hobject *) h_bound, bound_proto);\n\t}\n\n\tDUK_TVAL_INCREF(thr, &h_bound->target);  /* old values undefined, no decref needed */\n\tDUK_TVAL_INCREF(thr, &h_bound->this_binding);\n\n\tbound_nargs = n_prevbound + nargs;\n\tif (bound_nargs > (duk_idx_t) DUK_HBOUNDFUNC_MAX_ARGS) {\n\t\tDUK_DCERROR_RANGE_INVALID_COUNT(thr);\n\t}\n\ttv_res = (duk_tval *) DUK_ALLOC_CHECKED(thr, ((duk_size_t) bound_nargs) * sizeof(duk_tval));\n\tDUK_ASSERT(tv_res != NULL);\n\tDUK_ASSERT(h_bound->args == NULL);\n\tDUK_ASSERT(h_bound->nargs == 0);\n\th_bound->args = tv_res;\n\th_bound->nargs = bound_nargs;\n\n\tDUK_ASSERT(n_prevbound >= 0);\n\tduk_copy_tvals_incref(thr, tv_res, tv_prevbound, (duk_size_t) n_prevbound);\n\tDUK_ASSERT(nargs >= 0);\n\tduk_copy_tvals_incref(thr, tv_res + n_prevbound, DUK_GET_TVAL_POSIDX(thr, 1), (duk_size_t) nargs);\n\n\t/* [ thisArg arg1 ... argN func boundFunc ] */\n\n\t/* Bound function 'length' property is interesting.\n\t * For lightfuncs, simply read the virtual property.\n\t */\n\tduk_get_prop_stridx_short(thr, -2, DUK_STRIDX_LENGTH);\n\tbound_len = duk_get_int(thr, -1);  /* ES2015: no coercion */\n\tif (bound_len < nargs) {\n\t\tbound_len = 0;\n\t} else {\n\t\tbound_len -= nargs;\n\t}\n\tif (sizeof(duk_int_t) > 4 && bound_len > (duk_int_t) DUK_UINT32_MAX) {\n\t\tbound_len = (duk_int_t) DUK_UINT32_MAX;\n\t}\n\tduk_pop(thr);\n\tDUK_ASSERT(bound_len >= 0);\n\ttv_tmp = thr->valstack_top++;\n\tDUK_ASSERT(DUK_TVAL_IS_UNDEFINED(tv_tmp));\n\tDUK_ASSERT(!DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv_tmp));\n\tDUK_TVAL_SET_U32(tv_tmp, (duk_uint32_t) bound_len);  /* in-place update, fastint */\n\tduk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_C);  /* attrs in E6 Section 9.2.4 */\n\n\t/* XXX: could these be virtual? */\n\t/* Caller and arguments must use the same thrower, [[ThrowTypeError]]. */\n\tduk_xdef_prop_stridx_thrower(thr, -1, DUK_STRIDX_CALLER);\n\tduk_xdef_prop_stridx_thrower(thr, -1, DUK_STRIDX_LC_ARGUMENTS);\n\n\t/* Function name and fileName (non-standard). */\n\tduk_push_string(thr, \"bound \");  /* ES2015 19.2.3.2. */\n\tduk_get_prop_stridx(thr, -3, DUK_STRIDX_NAME);\n\tif (!duk_is_string_notsymbol(thr, -1)) {\n\t\t/* ES2015 has requirement to check that .name of target is a string\n\t\t * (also must check for Symbol); if not, targetName should be the\n\t\t * empty string.  ES2015 19.2.3.2.\n\t\t */\n\t\tduk_pop(thr);\n\t\tduk_push_hstring_empty(thr);\n\t}\n\tduk_concat(thr, 2);\n\tduk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_NAME, DUK_PROPDESC_FLAGS_C);\n#if defined(DUK_USE_FUNC_FILENAME_PROPERTY)\n\tduk_get_prop_stridx_short(thr, -2, DUK_STRIDX_FILE_NAME);\n\tduk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_FILE_NAME, DUK_PROPDESC_FLAGS_C);\n#endif\n\n\tDUK_DDD(DUK_DDDPRINT(\"created bound function: %!iT\", (duk_tval *) duk_get_tval(thr, -1)));\n\n\treturn 1;\n}\n#endif  /* DUK_USE_FUNCTION_BUILTIN */\n\n/* %NativeFunctionPrototype% .length getter. */\nDUK_INTERNAL duk_ret_t duk_bi_native_function_length(duk_hthread *thr) {\n\tduk_tval *tv;\n\tduk_hnatfunc *h;\n\tduk_int16_t func_nargs;\n\n\ttv = duk_get_borrowed_this_tval(thr);\n\tDUK_ASSERT(tv != NULL);\n\n\tif (DUK_TVAL_IS_OBJECT(tv)) {\n\t\th = (duk_hnatfunc *) DUK_TVAL_GET_OBJECT(tv);\n\t\tDUK_ASSERT(h != NULL);\n\t\tif (!DUK_HOBJECT_IS_NATFUNC((duk_hobject *) h)) {\n\t\t\tgoto fail_type;\n\t\t}\n\t\tfunc_nargs = h->nargs;\n\t\tduk_push_int(thr, func_nargs == DUK_HNATFUNC_NARGS_VARARGS ? 0 : func_nargs);\n\t} else if (DUK_TVAL_IS_LIGHTFUNC(tv)) {\n\t\tduk_small_uint_t lf_flags;\n\t\tduk_small_uint_t lf_len;\n\n\t\tlf_flags = DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv);\n\t\tlf_len = DUK_LFUNC_FLAGS_GET_LENGTH(lf_flags);\n\t\tduk_push_uint(thr, lf_len);\n\t} else {\n\t\tgoto fail_type;\n\t}\n\treturn 1;\n\n fail_type:\n\tDUK_DCERROR_TYPE_INVALID_ARGS(thr);\n}\n\n/* %NativeFunctionPrototype% .name getter. */\nDUK_INTERNAL duk_ret_t duk_bi_native_function_name(duk_hthread *thr) {\n\tduk_tval *tv;\n\tduk_hnatfunc *h;\n\n\ttv = duk_get_borrowed_this_tval(thr);\n\tDUK_ASSERT(tv != NULL);\n\n\tif (DUK_TVAL_IS_OBJECT(tv)) {\n\t\th = (duk_hnatfunc *) DUK_TVAL_GET_OBJECT(tv);\n\t\tDUK_ASSERT(h != NULL);\n\t\tif (!DUK_HOBJECT_IS_NATFUNC((duk_hobject *) h)) {\n\t\t\tgoto fail_type;\n\t\t}\n#if 0\n\t\tduk_push_hnatfunc_name(thr, h);\n#endif\n\t\tduk_push_hstring_empty(thr);\n\t} else if (DUK_TVAL_IS_LIGHTFUNC(tv)) {\n\t\tduk_push_lightfunc_name(thr, tv);\n\t} else {\n\t\tgoto fail_type;\n\t}\n\treturn 1;\n\n fail_type:\n\tDUK_DCERROR_TYPE_INVALID_ARGS(thr);\n}\n#line 1 \"duk_bi_global.c\"\n/*\n *  Global object built-ins\n */\n\n/* #include duk_internal.h -> already included */\n\n/*\n *  Encoding/decoding helpers\n */\n\n/* XXX: Could add fast path (for each transform callback) with direct byte\n * lookups (no shifting) and no explicit check for x < 0x80 before table\n * lookup.\n */\n\n/* Macros for creating and checking bitmasks for character encoding.\n * Bit number is a bit counterintuitive, but minimizes code size.\n */\n#define DUK__MKBITS(a,b,c,d,e,f,g,h)  ((duk_uint8_t) ( \\\n\t((a) << 0) | ((b) << 1) | ((c) << 2) | ((d) << 3) | \\\n\t((e) << 4) | ((f) << 5) | ((g) << 6) | ((h) << 7) \\\n\t))\n#define DUK__CHECK_BITMASK(table,cp)  ((table)[(cp) >> 3] & (1 << ((cp) & 0x07)))\n\n/* E5.1 Section 15.1.3.3: uriReserved + uriUnescaped + '#' */\nDUK_LOCAL const duk_uint8_t duk__encode_uriunescaped_table[16] = {\n\tDUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x00-0x0f */\n\tDUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x10-0x1f */\n\tDUK__MKBITS(0, 1, 0, 1, 1, 0, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1),  /* 0x20-0x2f */\n\tDUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 0, 1, 0, 1),  /* 0x30-0x3f */\n\tDUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1),  /* 0x40-0x4f */\n\tDUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 0, 0, 0, 0, 1),  /* 0x50-0x5f */\n\tDUK__MKBITS(0, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1),  /* 0x60-0x6f */\n\tDUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 0, 0, 0, 1, 0),  /* 0x70-0x7f */\n};\n\n/* E5.1 Section 15.1.3.4: uriUnescaped */\nDUK_LOCAL const duk_uint8_t duk__encode_uricomponent_unescaped_table[16] = {\n\tDUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x00-0x0f */\n\tDUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x10-0x1f */\n\tDUK__MKBITS(0, 1, 0, 0, 0, 0, 0, 1), DUK__MKBITS(1, 1, 1, 0, 0, 1, 1, 0),  /* 0x20-0x2f */\n\tDUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 0, 0, 0, 0, 0, 0),  /* 0x30-0x3f */\n\tDUK__MKBITS(0, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1),  /* 0x40-0x4f */\n\tDUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 0, 0, 0, 0, 1),  /* 0x50-0x5f */\n\tDUK__MKBITS(0, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1),  /* 0x60-0x6f */\n\tDUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 0, 0, 0, 1, 0),  /* 0x70-0x7f */\n};\n\n/* E5.1 Section 15.1.3.1: uriReserved + '#' */\nDUK_LOCAL const duk_uint8_t duk__decode_uri_reserved_table[16] = {\n\tDUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x00-0x0f */\n\tDUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x10-0x1f */\n\tDUK__MKBITS(0, 0, 0, 1, 1, 0, 1, 0), DUK__MKBITS(0, 0, 0, 1, 1, 0, 0, 1),  /* 0x20-0x2f */\n\tDUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 1, 1, 0, 1, 0, 1),  /* 0x30-0x3f */\n\tDUK__MKBITS(1, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x40-0x4f */\n\tDUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x50-0x5f */\n\tDUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x60-0x6f */\n\tDUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x70-0x7f */\n};\n\n/* E5.1 Section 15.1.3.2: empty */\nDUK_LOCAL const duk_uint8_t duk__decode_uri_component_reserved_table[16] = {\n\tDUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x00-0x0f */\n\tDUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x10-0x1f */\n\tDUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x20-0x2f */\n\tDUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x30-0x3f */\n\tDUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x40-0x4f */\n\tDUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x50-0x5f */\n\tDUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x60-0x6f */\n\tDUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x70-0x7f */\n};\n\n#if defined(DUK_USE_SECTION_B)\n/* E5.1 Section B.2.2, step 7. */\nDUK_LOCAL const duk_uint8_t duk__escape_unescaped_table[16] = {\n\tDUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x00-0x0f */\n\tDUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x10-0x1f */\n\tDUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 1, 1, 0, 1, 1, 1),  /* 0x20-0x2f */\n\tDUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 0, 0, 0, 0, 0, 0),  /* 0x30-0x3f */\n\tDUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1),  /* 0x40-0x4f */\n\tDUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 0, 0, 0, 0, 1),  /* 0x50-0x5f */\n\tDUK__MKBITS(0, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1),  /* 0x60-0x6f */\n\tDUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 0, 0, 0, 0, 0)   /* 0x70-0x7f */\n};\n#endif  /* DUK_USE_SECTION_B */\n\ntypedef struct {\n\tduk_hthread *thr;\n\tduk_hstring *h_str;\n\tduk_bufwriter_ctx bw;\n\tconst duk_uint8_t *p;\n\tconst duk_uint8_t *p_start;\n\tconst duk_uint8_t *p_end;\n} duk__transform_context;\n\ntypedef void (*duk__transform_callback)(duk__transform_context *tfm_ctx, const void *udata, duk_codepoint_t cp);\n\n/* XXX: refactor and share with other code */\nDUK_LOCAL duk_small_int_t duk__decode_hex_escape(const duk_uint8_t *p, duk_small_int_t n) {\n\tduk_small_int_t ch;\n\tduk_small_int_t t = 0;\n\n\twhile (n > 0) {\n\t\tt = t * 16;\n\t\tch = (duk_small_int_t) duk_hex_dectab[*p++];\n\t\tif (DUK_LIKELY(ch >= 0)) {\n\t\t\tt += ch;\n\t\t} else {\n\t\t\treturn -1;\n\t\t}\n\t\tn--;\n\t}\n\treturn t;\n}\n\nDUK_LOCAL int duk__transform_helper(duk_hthread *thr, duk__transform_callback callback, const void *udata) {\n\tduk__transform_context tfm_ctx_alloc;\n\tduk__transform_context *tfm_ctx = &tfm_ctx_alloc;\n\tduk_codepoint_t cp;\n\n\ttfm_ctx->thr = thr;\n\n\ttfm_ctx->h_str = duk_to_hstring(thr, 0);\n\tDUK_ASSERT(tfm_ctx->h_str != NULL);\n\n\tDUK_BW_INIT_PUSHBUF(thr, &tfm_ctx->bw, DUK_HSTRING_GET_BYTELEN(tfm_ctx->h_str));  /* initial size guess */\n\n\ttfm_ctx->p_start = DUK_HSTRING_GET_DATA(tfm_ctx->h_str);\n\ttfm_ctx->p_end = tfm_ctx->p_start + DUK_HSTRING_GET_BYTELEN(tfm_ctx->h_str);\n\ttfm_ctx->p = tfm_ctx->p_start;\n\n\twhile (tfm_ctx->p < tfm_ctx->p_end) {\n\t\tcp = (duk_codepoint_t) duk_unicode_decode_xutf8_checked(thr, &tfm_ctx->p, tfm_ctx->p_start, tfm_ctx->p_end);\n\t\tcallback(tfm_ctx, udata, cp);\n\t}\n\n\tDUK_BW_COMPACT(thr, &tfm_ctx->bw);\n\n\t(void) duk_buffer_to_string(thr, -1);  /* Safe if transform is safe. */\n\treturn 1;\n}\n\nDUK_LOCAL void duk__transform_callback_encode_uri(duk__transform_context *tfm_ctx, const void *udata, duk_codepoint_t cp) {\n\tduk_uint8_t xutf8_buf[DUK_UNICODE_MAX_XUTF8_LENGTH];\n\tduk_small_int_t len;\n\tduk_codepoint_t cp1, cp2;\n\tduk_small_int_t i, t;\n\tconst duk_uint8_t *unescaped_table = (const duk_uint8_t *) udata;\n\n\t/* UTF-8 encoded bytes escaped as %xx%xx%xx... -> 3 * nbytes.\n\t * Codepoint range is restricted so this is a slightly too large\n\t * but doesn't matter.\n\t */\n\tDUK_BW_ENSURE(tfm_ctx->thr, &tfm_ctx->bw, 3 * DUK_UNICODE_MAX_XUTF8_LENGTH);\n\n\tif (cp < 0) {\n\t\tgoto uri_error;\n\t} else if ((cp < 0x80L) && DUK__CHECK_BITMASK(unescaped_table, cp)) {\n\t\tDUK_BW_WRITE_RAW_U8(tfm_ctx->thr, &tfm_ctx->bw, (duk_uint8_t) cp);\n\t\treturn;\n\t} else if (cp >= 0xdc00L && cp <= 0xdfffL) {\n\t\tgoto uri_error;\n\t} else if (cp >= 0xd800L && cp <= 0xdbffL) {\n\t\t/* Needs lookahead */\n\t\tif (duk_unicode_decode_xutf8(tfm_ctx->thr, &tfm_ctx->p, tfm_ctx->p_start, tfm_ctx->p_end, (duk_ucodepoint_t *) &cp2) == 0) {\n\t\t\tgoto uri_error;\n\t\t}\n\t\tif (!(cp2 >= 0xdc00L && cp2 <= 0xdfffL)) {\n\t\t\tgoto uri_error;\n\t\t}\n\t\tcp1 = cp;\n\t\tcp = (duk_codepoint_t) (((cp1 - 0xd800L) << 10) + (cp2 - 0xdc00L) + 0x10000L);\n\t} else if (cp > 0x10ffffL) {\n\t\t/* Although we can allow non-BMP characters (they'll decode\n\t\t * back into surrogate pairs), we don't allow extended UTF-8\n\t\t * characters; they would encode to URIs which won't decode\n\t\t * back because of strict UTF-8 checks in URI decoding.\n\t\t * (However, we could just as well allow them here.)\n\t\t */\n\t\tgoto uri_error;\n\t} else {\n\t\t/* Non-BMP characters within valid UTF-8 range: encode as is.\n\t\t * They'll decode back into surrogate pairs if the escaped\n\t\t * output is decoded.\n\t\t */\n\t\t;\n\t}\n\n\tlen = duk_unicode_encode_xutf8((duk_ucodepoint_t) cp, xutf8_buf);\n\tfor (i = 0; i < len; i++) {\n\t\tt = (duk_small_int_t) xutf8_buf[i];\n\t\tDUK_BW_WRITE_RAW_U8_3(tfm_ctx->thr,\n\t\t                      &tfm_ctx->bw,\n\t\t                      DUK_ASC_PERCENT,\n\t\t                      (duk_uint8_t) duk_uc_nybbles[t >> 4],\n                                      (duk_uint8_t) duk_uc_nybbles[t & 0x0f]);\n\t}\n\n\treturn;\n\n uri_error:\n\tDUK_ERROR_URI(tfm_ctx->thr, DUK_STR_INVALID_INPUT);\n}\n\nDUK_LOCAL void duk__transform_callback_decode_uri(duk__transform_context *tfm_ctx, const void *udata, duk_codepoint_t cp) {\n\tconst duk_uint8_t *reserved_table = (const duk_uint8_t *) udata;\n\tduk_small_uint_t utf8_blen;\n\tduk_codepoint_t min_cp;\n\tduk_small_int_t t;  /* must be signed */\n\tduk_small_uint_t i;\n\n\t/* Maximum write size: XUTF8 path writes max DUK_UNICODE_MAX_XUTF8_LENGTH,\n\t * percent escape path writes max two times CESU-8 encoded BMP length.\n\t */\n\tDUK_BW_ENSURE(tfm_ctx->thr,\n\t              &tfm_ctx->bw,\n\t              (DUK_UNICODE_MAX_XUTF8_LENGTH >= 2 * DUK_UNICODE_MAX_CESU8_BMP_LENGTH ?\n\t              DUK_UNICODE_MAX_XUTF8_LENGTH : DUK_UNICODE_MAX_CESU8_BMP_LENGTH));\n\n\tif (cp == (duk_codepoint_t) '%') {\n\t\tconst duk_uint8_t *p = tfm_ctx->p;\n\t\tduk_size_t left = (duk_size_t) (tfm_ctx->p_end - p);  /* bytes left */\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"percent encoding, left=%ld\", (long) left));\n\n\t\tif (left < 2) {\n\t\t\tgoto uri_error;\n\t\t}\n\n\t\tt = duk__decode_hex_escape(p, 2);\n\t\tDUK_DDD(DUK_DDDPRINT(\"first byte: %ld\", (long) t));\n\t\tif (t < 0) {\n\t\t\tgoto uri_error;\n\t\t}\n\n\t\tif (t < 0x80) {\n\t\t\tif (DUK__CHECK_BITMASK(reserved_table, t)) {\n\t\t\t\t/* decode '%xx' to '%xx' if decoded char in reserved set */\n\t\t\t\tDUK_ASSERT(tfm_ctx->p - 1 >= tfm_ctx->p_start);\n\t\t\t\tDUK_BW_WRITE_RAW_U8_3(tfm_ctx->thr,\n\t\t\t\t                      &tfm_ctx->bw,\n\t\t\t\t                      DUK_ASC_PERCENT,\n\t\t\t\t                      p[0],\n\t\t\t\t                      p[1]);\n\t\t\t} else {\n\t\t\t\tDUK_BW_WRITE_RAW_U8(tfm_ctx->thr, &tfm_ctx->bw, (duk_uint8_t) t);\n\t\t\t}\n\t\t\ttfm_ctx->p += 2;\n\t\t\treturn;\n\t\t}\n\n\t\t/* Decode UTF-8 codepoint from a sequence of hex escapes.  The\n\t\t * first byte of the sequence has been decoded to 't'.\n\t\t *\n\t\t * Note that UTF-8 validation must be strict according to the\n\t\t * specification: E5.1 Section 15.1.3, decode algorithm step\n\t\t * 4.d.vii.8.  URIError from non-shortest encodings is also\n\t\t * specifically noted in the spec.\n\t\t */\n\n\t\tDUK_ASSERT(t >= 0x80);\n\t\tif (t < 0xc0) {\n\t\t\t/* continuation byte */\n\t\t\tgoto uri_error;\n\t\t} else if (t < 0xe0) {\n\t\t\t/* 110x xxxx; 2 bytes */\n\t\t\tutf8_blen = 2;\n\t\t\tmin_cp = 0x80L;\n\t\t\tcp = t & 0x1f;\n\t\t} else if (t < 0xf0) {\n\t\t\t/* 1110 xxxx; 3 bytes */\n\t\t\tutf8_blen = 3;\n\t\t\tmin_cp = 0x800L;\n\t\t\tcp = t & 0x0f;\n\t\t} else if (t < 0xf8) {\n\t\t\t/* 1111 0xxx; 4 bytes */\n\t\t\tutf8_blen = 4;\n\t\t\tmin_cp = 0x10000L;\n\t\t\tcp = t & 0x07;\n\t\t} else {\n\t\t\t/* extended utf-8 not allowed for URIs */\n\t\t\tgoto uri_error;\n\t\t}\n\n\t\tif (left < utf8_blen * 3 - 1) {\n\t\t\t/* '%xx%xx...%xx', p points to char after first '%' */\n\t\t\tgoto uri_error;\n\t\t}\n\n\t\tp += 3;\n\t\tfor (i = 1; i < utf8_blen; i++) {\n\t\t\t/* p points to digit part ('%xy', p points to 'x') */\n\t\t\tt = duk__decode_hex_escape(p, 2);\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"i=%ld utf8_blen=%ld cp=%ld t=0x%02lx\",\n\t\t\t                     (long) i, (long) utf8_blen, (long) cp, (unsigned long) t));\n\t\t\tif (t < 0) {\n\t\t\t\tgoto uri_error;\n\t\t\t}\n\t\t\tif ((t & 0xc0) != 0x80) {\n\t\t\t\tgoto uri_error;\n\t\t\t}\n\t\t\tcp = (cp << 6) + (t & 0x3f);\n\t\t\tp += 3;\n\t\t}\n\t\tp--;  /* p overshoots */\n\t\ttfm_ctx->p = p;\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"final cp=%ld, min_cp=%ld\", (long) cp, (long) min_cp));\n\n\t\tif (cp < min_cp || cp > 0x10ffffL || (cp >= 0xd800L && cp <= 0xdfffL)) {\n\t\t\tgoto uri_error;\n\t\t}\n\n\t\t/* The E5.1 algorithm checks whether or not a decoded codepoint\n\t\t * is below 0x80 and perhaps may be in the \"reserved\" set.\n\t\t * This seems pointless because the single byte UTF-8 case is\n\t\t * handled separately, and non-shortest encodings are rejected.\n\t\t * So, 'cp' cannot be below 0x80 here, and thus cannot be in\n\t\t * the reserved set.\n\t\t */\n\n\t\t/* utf-8 validation ensures these */\n\t\tDUK_ASSERT(cp >= 0x80L && cp <= 0x10ffffL);\n\n\t\tif (cp >= 0x10000L) {\n\t\t\tcp -= 0x10000L;\n\t\t\tDUK_ASSERT(cp < 0x100000L);\n\n\t\t\tDUK_BW_WRITE_RAW_XUTF8(tfm_ctx->thr, &tfm_ctx->bw, ((cp >> 10) + 0xd800L));\n\t\t\tDUK_BW_WRITE_RAW_XUTF8(tfm_ctx->thr, &tfm_ctx->bw, ((cp & 0x03ffL) + 0xdc00L));\n\t\t} else {\n\t\t\tDUK_BW_WRITE_RAW_XUTF8(tfm_ctx->thr, &tfm_ctx->bw, cp);\n\t\t}\n\t} else {\n\t\tDUK_BW_WRITE_RAW_XUTF8(tfm_ctx->thr, &tfm_ctx->bw, cp);\n\t}\n\treturn;\n\n uri_error:\n\tDUK_ERROR_URI(tfm_ctx->thr, DUK_STR_INVALID_INPUT);\n}\n\n#if defined(DUK_USE_SECTION_B)\nDUK_LOCAL void duk__transform_callback_escape(duk__transform_context *tfm_ctx, const void *udata, duk_codepoint_t cp) {\n\tDUK_UNREF(udata);\n\n\tDUK_BW_ENSURE(tfm_ctx->thr, &tfm_ctx->bw, 6);\n\n\tif (cp < 0) {\n\t\tgoto esc_error;\n\t} else if ((cp < 0x80L) && DUK__CHECK_BITMASK(duk__escape_unescaped_table, cp)) {\n\t\tDUK_BW_WRITE_RAW_U8(tfm_ctx->thr, &tfm_ctx->bw, (duk_uint8_t) cp);\n\t} else if (cp < 0x100L) {\n\t\tDUK_BW_WRITE_RAW_U8_3(tfm_ctx->thr,\n\t\t                      &tfm_ctx->bw,\n\t\t                      (duk_uint8_t) DUK_ASC_PERCENT,\n\t\t                      (duk_uint8_t) duk_uc_nybbles[cp >> 4],\n\t\t                      (duk_uint8_t) duk_uc_nybbles[cp & 0x0f]);\n\t} else if (cp < 0x10000L) {\n\t\tDUK_BW_WRITE_RAW_U8_6(tfm_ctx->thr,\n\t\t                      &tfm_ctx->bw,\n\t\t                      (duk_uint8_t) DUK_ASC_PERCENT,\n\t\t                      (duk_uint8_t) DUK_ASC_LC_U,\n\t\t                      (duk_uint8_t) duk_uc_nybbles[cp >> 12],\n\t\t                      (duk_uint8_t) duk_uc_nybbles[(cp >> 8) & 0x0f],\n\t\t                      (duk_uint8_t) duk_uc_nybbles[(cp >> 4) & 0x0f],\n\t\t                      (duk_uint8_t) duk_uc_nybbles[cp & 0x0f]);\n\t} else {\n\t\t/* Characters outside BMP cannot be escape()'d.  We could\n\t\t * encode them as surrogate pairs (for codepoints inside\n\t\t * valid UTF-8 range, but not extended UTF-8).  Because\n\t\t * escape() and unescape() are legacy functions, we don't.\n\t\t */\n\t\tgoto esc_error;\n\t}\n\n\treturn;\n\n esc_error:\n\tDUK_ERROR_TYPE(tfm_ctx->thr, DUK_STR_INVALID_INPUT);\n}\n\nDUK_LOCAL void duk__transform_callback_unescape(duk__transform_context *tfm_ctx, const void *udata, duk_codepoint_t cp) {\n\tduk_small_int_t t;\n\n\tDUK_UNREF(udata);\n\n\tif (cp == (duk_codepoint_t) '%') {\n\t\tconst duk_uint8_t *p = tfm_ctx->p;\n\t\tduk_size_t left = (duk_size_t) (tfm_ctx->p_end - p);  /* bytes left */\n\n\t\tif (left >= 5 && p[0] == 'u' &&\n\t\t    ((t = duk__decode_hex_escape(p + 1, 4)) >= 0)) {\n\t\t\tcp = (duk_codepoint_t) t;\n\t\t\ttfm_ctx->p += 5;\n\t\t} else if (left >= 2 &&\n\t\t           ((t = duk__decode_hex_escape(p, 2)) >= 0)) {\n\t\t\tcp = (duk_codepoint_t) t;\n\t\t\ttfm_ctx->p += 2;\n\t\t}\n\t}\n\n\tDUK_BW_WRITE_ENSURE_XUTF8(tfm_ctx->thr, &tfm_ctx->bw, cp);\n}\n#endif  /* DUK_USE_SECTION_B */\n\n/*\n *  Eval\n *\n *  Eval needs to handle both a \"direct eval\" and an \"indirect eval\".\n *  Direct eval handling needs access to the caller's activation so that its\n *  lexical environment can be accessed.  A direct eval is only possible from\n *  Ecmascript code; an indirect eval call is possible also from C code.\n *  When an indirect eval call is made from C code, there may not be a\n *  calling activation at all which needs careful handling.\n */\n\nDUK_INTERNAL duk_ret_t duk_bi_global_object_eval(duk_hthread *thr) {\n\tduk_hstring *h;\n\tduk_activation *act_caller;\n\tduk_activation *act_eval;\n\tduk_hcompfunc *func;\n\tduk_hobject *outer_lex_env;\n\tduk_hobject *outer_var_env;\n\tduk_bool_t this_to_global = 1;\n\tduk_small_uint_t comp_flags;\n\tduk_int_t level = -2;\n\tduk_small_uint_t call_flags;\n\n\tDUK_ASSERT(duk_get_top(thr) == 1 || duk_get_top(thr) == 2);  /* 2 when called by debugger */\n\tDUK_ASSERT(thr->callstack_top >= 1);  /* at least this function exists */\n\tDUK_ASSERT(thr->callstack_curr != NULL);\n\tDUK_ASSERT((thr->callstack_curr->flags & DUK_ACT_FLAG_DIRECT_EVAL) == 0 || /* indirect eval */\n\t           (thr->callstack_top >= 2));  /* if direct eval, calling activation must exist */\n\n\t/*\n\t *  callstack_top - 1 --> this function\n\t *  callstack_top - 2 --> caller (may not exist)\n\t *\n\t *  If called directly from C, callstack_top might be 1.  If calling\n\t *  activation doesn't exist, call must be indirect.\n\t */\n\n\th = duk_get_hstring_notsymbol(thr, 0);\n\tif (!h) {\n\t\t/* Symbol must be returned as is, like any non-string values. */\n\t\treturn 1;  /* return arg as-is */\n\t}\n\n#if defined(DUK_USE_DEBUGGER_SUPPORT)\n\t/* NOTE: level is used only by the debugger and should never be present\n\t * for an Ecmascript eval().\n\t */\n\tDUK_ASSERT(level == -2);  /* by default, use caller's environment */\n\tif (duk_get_top(thr) >= 2 && duk_is_number(thr, 1)) {\n\t\tlevel = duk_get_int(thr, 1);\n\t}\n\tDUK_ASSERT(level <= -2);  /* This is guaranteed by debugger code. */\n#endif\n\n\t/* [ source ] */\n\n\tcomp_flags = DUK_COMPILE_EVAL;\n\tact_eval = thr->callstack_curr;  /* this function */\n\tDUK_ASSERT(act_eval != NULL);\n\tact_caller = duk_hthread_get_activation_for_level(thr, level);\n\tif (act_caller != NULL) {\n\t\t/* Have a calling activation, check for direct eval (otherwise\n\t\t * assume indirect eval.\n\t\t */\n\t\tif ((act_caller->flags & DUK_ACT_FLAG_STRICT) &&\n\t\t    (act_eval->flags & DUK_ACT_FLAG_DIRECT_EVAL)) {\n\t\t\t/* Only direct eval inherits strictness from calling code\n\t\t\t * (E5.1 Section 10.1.1).\n\t\t\t */\n\t\t\tcomp_flags |= DUK_COMPILE_STRICT;\n\t\t}\n\t} else {\n\t\tDUK_ASSERT((act_eval->flags & DUK_ACT_FLAG_DIRECT_EVAL) == 0);\n\t}\n\n\tduk_push_hstring_stridx(thr, DUK_STRIDX_INPUT);  /* XXX: copy from caller? */\n\tduk_js_compile(thr,\n\t               (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h),\n\t               (duk_size_t) DUK_HSTRING_GET_BYTELEN(h),\n\t               comp_flags);\n\tfunc = (duk_hcompfunc *) duk_known_hobject(thr, -1);\n\tDUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC((duk_hobject *) func));\n\n\t/* [ source template ] */\n\n\t/* E5 Section 10.4.2 */\n\n\tif (act_eval->flags & DUK_ACT_FLAG_DIRECT_EVAL) {\n\t\tDUK_ASSERT(thr->callstack_top >= 2);\n\t\tDUK_ASSERT(act_caller != NULL);\n\t\tif (act_caller->lex_env == NULL) {\n\t\t\tDUK_ASSERT(act_caller->var_env == NULL);\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"delayed environment initialization\"));\n\n\t\t\t/* this may have side effects, so re-lookup act */\n\t\t\tduk_js_init_activation_environment_records_delayed(thr, act_caller);\n\t\t}\n\t\tDUK_ASSERT(act_caller->lex_env != NULL);\n\t\tDUK_ASSERT(act_caller->var_env != NULL);\n\n\t\tthis_to_global = 0;\n\n\t\tif (DUK_HOBJECT_HAS_STRICT((duk_hobject *) func)) {\n\t\t\tduk_hdecenv *new_env;\n\t\t\tduk_hobject *act_lex_env;\n\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"direct eval call to a strict function -> \"\n\t\t\t                     \"var_env and lex_env to a fresh env, \"\n\t\t\t                     \"this_binding to caller's this_binding\"));\n\n\t\t\tact_lex_env = act_caller->lex_env;\n\n\t\t\tnew_env = duk_hdecenv_alloc(thr,\n\t\t\t                            DUK_HOBJECT_FLAG_EXTENSIBLE |\n\t\t\t                            DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_DECENV));\n\t\t\tDUK_ASSERT(new_env != NULL);\n\t\t\tduk_push_hobject(thr, (duk_hobject *) new_env);\n\n\t\t\tDUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) new_env) == NULL);\n\t\t\tDUK_HOBJECT_SET_PROTOTYPE(thr->heap, (duk_hobject *) new_env, act_lex_env);\n\t\t\tDUK_HOBJECT_INCREF_ALLOWNULL(thr, act_lex_env);\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"new_env allocated: %!iO\", (duk_heaphdr *) new_env));\n\n\t\t\touter_lex_env = (duk_hobject *) new_env;\n\t\t\touter_var_env = (duk_hobject *) new_env;\n\n\t\t\tduk_insert(thr, 0);  /* stash to bottom of value stack to keep new_env reachable for duration of eval */\n\n\t\t\t/* compiler's responsibility */\n\t\t\tDUK_ASSERT(DUK_HOBJECT_HAS_NEWENV((duk_hobject *) func));\n\t\t} else {\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"direct eval call to a non-strict function -> \"\n\t\t\t                     \"var_env and lex_env to caller's envs, \"\n\t\t\t                     \"this_binding to caller's this_binding\"));\n\n\t\t\touter_lex_env = act_caller->lex_env;\n\t\t\touter_var_env = act_caller->var_env;\n\n\t\t\t/* compiler's responsibility */\n\t\t\tDUK_ASSERT(!DUK_HOBJECT_HAS_NEWENV((duk_hobject *) func));\n\t\t}\n\t} else {\n\t\tDUK_DDD(DUK_DDDPRINT(\"indirect eval call -> var_env and lex_env to \"\n\t\t                     \"global object, this_binding to global object\"));\n\n\t\tthis_to_global = 1;\n\t\touter_lex_env = thr->builtins[DUK_BIDX_GLOBAL_ENV];\n\t\touter_var_env = thr->builtins[DUK_BIDX_GLOBAL_ENV];\n\t}\n\n\t/* Eval code doesn't need an automatic .prototype object. */\n\tduk_js_push_closure(thr, func, outer_var_env, outer_lex_env, 0 /*add_auto_proto*/);\n\n\t/* [ env? source template closure ] */\n\n\tif (this_to_global) {\n\t\tDUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL);\n\t\tduk_push_hobject_bidx(thr, DUK_BIDX_GLOBAL);\n\t} else {\n\t\tduk_tval *tv;\n\t\tDUK_ASSERT(thr->callstack_top >= 2);\n\t\tDUK_ASSERT(act_caller != NULL);\n\t\ttv = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + act_caller->bottom_byteoff - sizeof(duk_tval));  /* this is just beneath bottom */\n\t\tDUK_ASSERT(tv >= thr->valstack);\n\t\tduk_push_tval(thr, tv);\n\t}\n\n\tDUK_DDD(DUK_DDDPRINT(\"eval -> lex_env=%!iO, var_env=%!iO, this_binding=%!T\",\n\t                     (duk_heaphdr *) outer_lex_env,\n\t                     (duk_heaphdr *) outer_var_env,\n\t                     duk_get_tval(thr, -1)));\n\n\t/* [ env? source template closure this ] */\n\n\tcall_flags = 0;\n\tif (act_eval->flags & DUK_ACT_FLAG_DIRECT_EVAL) {\n\t\t/* Set DIRECT_EVAL flag for the call; it's not strictly\n\t\t * needed for the 'inner' eval call (the eval body) but\n\t\t * current new.target implementation expects to find it\n\t\t * so it can traverse direct eval chains up to the real\n\t\t * calling function.\n\t\t */\n\t\tcall_flags |= DUK_CALL_FLAG_DIRECT_EVAL;\n\t}\n\tduk_handle_call_unprotected_nargs(thr, 0, call_flags);\n\n\t/* [ env? source template result ] */\n\n\treturn 1;\n}\n\n/*\n *  Parsing of ints and floats\n */\n\n#if defined(DUK_USE_GLOBAL_BUILTIN)\nDUK_INTERNAL duk_ret_t duk_bi_global_object_parse_int(duk_hthread *thr) {\n\tduk_int32_t radix;\n\tduk_small_uint_t s2n_flags;\n\n\tDUK_ASSERT_TOP(thr, 2);\n\tduk_to_string(thr, 0);  /* Reject symbols. */\n\n\tradix = duk_to_int32(thr, 1);\n\n\t/* While parseInt() recognizes 0xdeadbeef, it doesn't recognize\n\t * ES2015 0o123 or 0b10001.\n\t */\n\ts2n_flags = DUK_S2N_FLAG_TRIM_WHITE |\n\t            DUK_S2N_FLAG_ALLOW_GARBAGE |\n\t            DUK_S2N_FLAG_ALLOW_PLUS |\n\t            DUK_S2N_FLAG_ALLOW_MINUS |\n\t            DUK_S2N_FLAG_ALLOW_LEADING_ZERO |\n\t            DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT;\n\n\t/* Specification stripPrefix maps to DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT.\n\t *\n\t * Don't autodetect octals (from leading zeroes), require user code to\n\t * provide an explicit radix 8 for parsing octal.  See write-up from Mozilla:\n\t * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/parseInt#ECMAScript_5_Removes_Octal_Interpretation\n\t */\n\n\tif (radix != 0) {\n\t\tif (radix < 2 || radix > 36) {\n\t\t\tgoto ret_nan;\n\t\t}\n\t\tif (radix != 16) {\n\t\t\ts2n_flags &= ~DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT;\n\t\t}\n\t} else {\n\t\tradix = 10;\n\t}\n\n\tduk_dup_0(thr);\n\tduk_numconv_parse(thr, (duk_small_int_t) radix, s2n_flags);\n\treturn 1;\n\n ret_nan:\n\tduk_push_nan(thr);\n\treturn 1;\n}\n#endif  /* DUK_USE_GLOBAL_BUILTIN */\n\n#if defined(DUK_USE_GLOBAL_BUILTIN)\nDUK_INTERNAL duk_ret_t duk_bi_global_object_parse_float(duk_hthread *thr) {\n\tduk_small_uint_t s2n_flags;\n\n\tDUK_ASSERT_TOP(thr, 1);\n\tduk_to_string(thr, 0);  /* Reject symbols. */\n\n\t/* XXX: check flags */\n\ts2n_flags = DUK_S2N_FLAG_TRIM_WHITE |\n\t            DUK_S2N_FLAG_ALLOW_EXP |\n\t            DUK_S2N_FLAG_ALLOW_GARBAGE |\n\t            DUK_S2N_FLAG_ALLOW_PLUS |\n\t            DUK_S2N_FLAG_ALLOW_MINUS |\n\t            DUK_S2N_FLAG_ALLOW_INF |\n\t            DUK_S2N_FLAG_ALLOW_FRAC |\n\t            DUK_S2N_FLAG_ALLOW_NAKED_FRAC |\n\t            DUK_S2N_FLAG_ALLOW_EMPTY_FRAC |\n\t            DUK_S2N_FLAG_ALLOW_LEADING_ZERO;\n\n\tduk_numconv_parse(thr, 10 /*radix*/, s2n_flags);\n\treturn 1;\n}\n#endif  /* DUK_USE_GLOBAL_BUILTIN */\n\n/*\n *  Number checkers\n */\n\n#if defined(DUK_USE_GLOBAL_BUILTIN)\nDUK_INTERNAL duk_ret_t duk_bi_global_object_is_nan(duk_hthread *thr) {\n\tduk_double_t d = duk_to_number(thr, 0);\n\tduk_push_boolean(thr, (duk_bool_t) DUK_ISNAN(d));\n\treturn 1;\n}\n#endif  /* DUK_USE_GLOBAL_BUILTIN */\n\n#if defined(DUK_USE_GLOBAL_BUILTIN)\nDUK_INTERNAL duk_ret_t duk_bi_global_object_is_finite(duk_hthread *thr) {\n\tduk_double_t d = duk_to_number(thr, 0);\n\tduk_push_boolean(thr, (duk_bool_t) DUK_ISFINITE(d));\n\treturn 1;\n}\n#endif  /* DUK_USE_GLOBAL_BUILTIN */\n\n/*\n *  URI handling\n */\n\n#if defined(DUK_USE_GLOBAL_BUILTIN)\nDUK_INTERNAL duk_ret_t duk_bi_global_object_decode_uri(duk_hthread *thr) {\n\treturn duk__transform_helper(thr, duk__transform_callback_decode_uri, (const void *) duk__decode_uri_reserved_table);\n}\n\nDUK_INTERNAL duk_ret_t duk_bi_global_object_decode_uri_component(duk_hthread *thr) {\n\treturn duk__transform_helper(thr, duk__transform_callback_decode_uri, (const void *) duk__decode_uri_component_reserved_table);\n}\n\nDUK_INTERNAL duk_ret_t duk_bi_global_object_encode_uri(duk_hthread *thr) {\n\treturn duk__transform_helper(thr, duk__transform_callback_encode_uri, (const void *) duk__encode_uriunescaped_table);\n}\n\nDUK_INTERNAL duk_ret_t duk_bi_global_object_encode_uri_component(duk_hthread *thr) {\n\treturn duk__transform_helper(thr, duk__transform_callback_encode_uri, (const void *) duk__encode_uricomponent_unescaped_table);\n}\n\n#if defined(DUK_USE_SECTION_B)\nDUK_INTERNAL duk_ret_t duk_bi_global_object_escape(duk_hthread *thr) {\n\treturn duk__transform_helper(thr, duk__transform_callback_escape, (const void *) NULL);\n}\n\nDUK_INTERNAL duk_ret_t duk_bi_global_object_unescape(duk_hthread *thr) {\n\treturn duk__transform_helper(thr, duk__transform_callback_unescape, (const void *) NULL);\n}\n#endif  /* DUK_USE_SECTION_B */\n#endif  /* DUK_USE_GLOBAL_BUILTIN */\n\n/* automatic undefs */\n#undef DUK__CHECK_BITMASK\n#undef DUK__MKBITS\n#line 1 \"duk_bi_json.c\"\n/*\n *  JSON built-ins.\n *\n *  See doc/json.rst.\n *\n *  Codepoints are handled as duk_uint_fast32_t to ensure that the full\n *  unsigned 32-bit range is supported.  This matters to e.g. JX.\n *\n *  Input parsing doesn't do an explicit end-of-input check at all.  This is\n *  safe: input string data is always NUL-terminated (0x00) and valid JSON\n *  inputs never contain plain NUL characters, so that as long as syntax checks\n *  are correct, we'll never read past the NUL.  This approach reduces code size\n *  and improves parsing performance, but it's critical that syntax checks are\n *  indeed correct!\n */\n\n/* #include duk_internal.h -> already included */\n\n#if defined(DUK_USE_JSON_SUPPORT)\n\n/*\n *  Local defines and forward declarations.\n */\n\n#define DUK__JSON_DECSTR_BUFSIZE 128\n#define DUK__JSON_DECSTR_CHUNKSIZE 64\n#define DUK__JSON_ENCSTR_CHUNKSIZE 64\n#define DUK__JSON_STRINGIFY_BUFSIZE 128\n#define DUK__JSON_MAX_ESC_LEN 10  /* '\\Udeadbeef' */\n\nDUK_LOCAL_DECL void duk__dec_syntax_error(duk_json_dec_ctx *js_ctx);\nDUK_LOCAL_DECL void duk__dec_eat_white(duk_json_dec_ctx *js_ctx);\n#if defined(DUK_USE_JX)\nDUK_LOCAL_DECL duk_uint8_t duk__dec_peek(duk_json_dec_ctx *js_ctx);\n#endif\nDUK_LOCAL_DECL duk_uint8_t duk__dec_get(duk_json_dec_ctx *js_ctx);\nDUK_LOCAL_DECL duk_uint8_t duk__dec_get_nonwhite(duk_json_dec_ctx *js_ctx);\nDUK_LOCAL_DECL duk_uint_fast32_t duk__dec_decode_hex_escape(duk_json_dec_ctx *js_ctx, duk_small_uint_t n);\nDUK_LOCAL_DECL void duk__dec_req_stridx(duk_json_dec_ctx *js_ctx, duk_small_uint_t stridx);\nDUK_LOCAL_DECL void duk__dec_string(duk_json_dec_ctx *js_ctx);\n#if defined(DUK_USE_JX)\nDUK_LOCAL_DECL void duk__dec_plain_string(duk_json_dec_ctx *js_ctx);\nDUK_LOCAL_DECL void duk__dec_pointer(duk_json_dec_ctx *js_ctx);\nDUK_LOCAL_DECL void duk__dec_buffer(duk_json_dec_ctx *js_ctx);\n#endif\nDUK_LOCAL_DECL void duk__dec_number(duk_json_dec_ctx *js_ctx);\nDUK_LOCAL_DECL void duk__dec_objarr_entry(duk_json_dec_ctx *js_ctx);\nDUK_LOCAL_DECL void duk__dec_objarr_exit(duk_json_dec_ctx *js_ctx);\nDUK_LOCAL_DECL void duk__dec_object(duk_json_dec_ctx *js_ctx);\nDUK_LOCAL_DECL void duk__dec_array(duk_json_dec_ctx *js_ctx);\nDUK_LOCAL_DECL void duk__dec_value(duk_json_dec_ctx *js_ctx);\nDUK_LOCAL_DECL void duk__dec_reviver_walk(duk_json_dec_ctx *js_ctx);\n\nDUK_LOCAL_DECL void duk__emit_1(duk_json_enc_ctx *js_ctx, duk_uint_fast8_t ch);\nDUK_LOCAL_DECL void duk__emit_2(duk_json_enc_ctx *js_ctx, duk_uint_fast8_t ch1, duk_uint_fast8_t ch2);\nDUK_LOCAL_DECL void duk__unemit_1(duk_json_enc_ctx *js_ctx);\nDUK_LOCAL_DECL void duk__emit_hstring(duk_json_enc_ctx *js_ctx, duk_hstring *h);\n#if defined(DUK_USE_FASTINT)\nDUK_LOCAL_DECL void duk__emit_cstring(duk_json_enc_ctx *js_ctx, const char *p);\n#endif\nDUK_LOCAL_DECL void duk__emit_stridx(duk_json_enc_ctx *js_ctx, duk_small_uint_t stridx);\nDUK_LOCAL_DECL duk_uint8_t *duk__emit_esc_auto_fast(duk_json_enc_ctx *js_ctx, duk_uint_fast32_t cp, duk_uint8_t *q);\nDUK_LOCAL_DECL void duk__enc_key_autoquote(duk_json_enc_ctx *js_ctx, duk_hstring *k);\nDUK_LOCAL_DECL void duk__enc_quote_string(duk_json_enc_ctx *js_ctx, duk_hstring *h_str);\nDUK_LOCAL_DECL void duk__enc_objarr_entry(duk_json_enc_ctx *js_ctx, duk_idx_t *entry_top);\nDUK_LOCAL_DECL void duk__enc_objarr_exit(duk_json_enc_ctx *js_ctx, duk_idx_t *entry_top);\nDUK_LOCAL_DECL void duk__enc_object(duk_json_enc_ctx *js_ctx);\nDUK_LOCAL_DECL void duk__enc_array(duk_json_enc_ctx *js_ctx);\nDUK_LOCAL_DECL duk_bool_t duk__enc_value(duk_json_enc_ctx *js_ctx, duk_idx_t idx_holder);\nDUK_LOCAL_DECL duk_bool_t duk__enc_allow_into_proplist(duk_tval *tv);\nDUK_LOCAL_DECL void duk__enc_double(duk_json_enc_ctx *js_ctx);\n#if defined(DUK_USE_FASTINT)\nDUK_LOCAL_DECL void duk__enc_fastint_tval(duk_json_enc_ctx *js_ctx, duk_tval *tv);\n#endif\n#if defined(DUK_USE_JX) || defined(DUK_USE_JC)\nDUK_LOCAL_DECL void duk__enc_buffer_jx_jc(duk_json_enc_ctx *js_ctx, duk_hbuffer *h);\nDUK_LOCAL_DECL void duk__enc_pointer(duk_json_enc_ctx *js_ctx, void *ptr);\n#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)\nDUK_LOCAL_DECL void duk__enc_bufobj(duk_json_enc_ctx *js_ctx, duk_hbufobj *h_bufobj);\n#endif\n#endif\n#if defined(DUK_USE_JSON_STRINGIFY_FASTPATH)\nDUK_LOCAL_DECL void duk__enc_buffer_json_fastpath(duk_json_enc_ctx *js_ctx, duk_hbuffer *h);\n#endif\nDUK_LOCAL_DECL void duk__enc_newline_indent(duk_json_enc_ctx *js_ctx, duk_uint_t depth);\n\n/*\n *  Helper tables\n */\n\n#if defined(DUK_USE_JSON_QUOTESTRING_FASTPATH)\nDUK_LOCAL const duk_uint8_t duk__json_quotestr_lookup[256] = {\n\t/* 0x00 ... 0x7f: as is\n\t * 0x80: escape generically\n\t * 0x81: slow path\n\t * 0xa0 ... 0xff: backslash + one char\n\t */\n\n\t0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xe2, 0xf4, 0xee, 0x80, 0xe6, 0xf2, 0x80, 0x80,\n\t0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,\n\t0x20, 0x21, 0xa2, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,\n\t0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,\n\t0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,\n\t0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0xdc, 0x5d, 0x5e, 0x5f,\n\t0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,\n\t0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x81,\n\t0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,\n\t0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,\n\t0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,\n\t0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,\n\t0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,\n\t0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,\n\t0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,\n\t0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81\n};\n#else  /* DUK_USE_JSON_QUOTESTRING_FASTPATH */\nDUK_LOCAL const duk_uint8_t duk__json_quotestr_esc[14] = {\n\tDUK_ASC_NUL, DUK_ASC_NUL, DUK_ASC_NUL, DUK_ASC_NUL,\n\tDUK_ASC_NUL, DUK_ASC_NUL, DUK_ASC_NUL, DUK_ASC_NUL,\n\tDUK_ASC_LC_B, DUK_ASC_LC_T, DUK_ASC_LC_N, DUK_ASC_NUL,\n\tDUK_ASC_LC_F, DUK_ASC_LC_R\n};\n#endif  /* DUK_USE_JSON_QUOTESTRING_FASTPATH */\n\n#if defined(DUK_USE_JSON_DECSTRING_FASTPATH)\nDUK_LOCAL const duk_uint8_t duk__json_decstr_lookup[256] = {\n\t/* 0x00: slow path\n\t * other: as is\n\t */\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x20, 0x21, 0x00, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,\n\t0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,\n\t0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,\n\t0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x00, 0x5d, 0x5e, 0x5f,\n\t0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,\n\t0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,\n\t0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,\n\t0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,\n\t0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,\n\t0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,\n\t0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,\n\t0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,\n\t0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,\n\t0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff\n};\n#endif  /* DUK_USE_JSON_DECSTRING_FASTPATH */\n\n#if defined(DUK_USE_JSON_EATWHITE_FASTPATH)\nDUK_LOCAL const duk_uint8_t duk__json_eatwhite_lookup[256] = {\n\t/* 0x00: finish (non-white)\n\t * 0x01: continue\n\t */\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00\n};\n#endif  /* DUK_USE_JSON_EATWHITE_FASTPATH */\n\n#if defined(DUK_USE_JSON_DECNUMBER_FASTPATH)\nDUK_LOCAL const duk_uint8_t duk__json_decnumber_lookup[256] = {\n\t/* 0x00: finish (not part of number)\n\t * 0x01: continue\n\t */\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x01, 0x00,\n\t0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00\n};\n#endif  /* DUK_USE_JSON_DECNUMBER_FASTPATH */\n\n/*\n *  Parsing implementation.\n *\n *  JSON lexer is now separate from duk_lexer.c because there are numerous\n *  small differences making it difficult to share the lexer.\n *\n *  The parser here works with raw bytes directly; this works because all\n *  JSON delimiters are ASCII characters.  Invalid xUTF-8 encoded values\n *  inside strings will be passed on without normalization; this is not a\n *  compliance concern because compliant inputs will always be valid\n *  CESU-8 encodings.\n */\n\nDUK_LOCAL void duk__dec_syntax_error(duk_json_dec_ctx *js_ctx) {\n\t/* Shared handler to minimize parser size.  Cause will be\n\t * hidden, unfortunately, but we'll have an offset which\n\t * is often quite enough.\n\t */\n\tDUK_ERROR_FMT1(js_ctx->thr, DUK_ERR_SYNTAX_ERROR, DUK_STR_FMT_INVALID_JSON,\n\t               (long) (js_ctx->p - js_ctx->p_start));\n}\n\nDUK_LOCAL void duk__dec_eat_white(duk_json_dec_ctx *js_ctx) {\n\tconst duk_uint8_t *p;\n\tduk_uint8_t t;\n\n\tp = js_ctx->p;\n\tfor (;;) {\n\t\tDUK_ASSERT(p <= js_ctx->p_end);\n\t\tt = *p;\n\n#if defined(DUK_USE_JSON_EATWHITE_FASTPATH)\n\t\t/* This fast path is pretty marginal in practice.\n\t\t * XXX: candidate for removal.\n\t\t */\n\t\tDUK_ASSERT(duk__json_eatwhite_lookup[0x00] == 0x00);  /* end-of-input breaks */\n\t\tif (duk__json_eatwhite_lookup[t] == 0) {\n\t\t\tbreak;\n\t\t}\n#else  /* DUK_USE_JSON_EATWHITE_FASTPATH */\n\t\tif (!(t == 0x20 || t == 0x0a || t == 0x0d || t == 0x09)) {\n\t\t\t/* NUL also comes here.  Comparison order matters, 0x20\n\t\t\t * is most common whitespace.\n\t\t\t */\n\t\t\tbreak;\n\t\t}\n#endif  /* DUK_USE_JSON_EATWHITE_FASTPATH */\n\t\tp++;\n\t}\n\tjs_ctx->p = p;\n}\n\n#if defined(DUK_USE_JX)\nDUK_LOCAL duk_uint8_t duk__dec_peek(duk_json_dec_ctx *js_ctx) {\n\tDUK_ASSERT(js_ctx->p <= js_ctx->p_end);\n\treturn *js_ctx->p;\n}\n#endif\n\nDUK_LOCAL duk_uint8_t duk__dec_get(duk_json_dec_ctx *js_ctx) {\n\tDUK_ASSERT(js_ctx->p <= js_ctx->p_end);\n\treturn *js_ctx->p++;\n}\n\nDUK_LOCAL duk_uint8_t duk__dec_get_nonwhite(duk_json_dec_ctx *js_ctx) {\n\tduk__dec_eat_white(js_ctx);\n\treturn duk__dec_get(js_ctx);\n}\n\n/* For JX, expressing the whole unsigned 32-bit range matters. */\nDUK_LOCAL duk_uint_fast32_t duk__dec_decode_hex_escape(duk_json_dec_ctx *js_ctx, duk_small_uint_t n) {\n\tduk_small_uint_t i;\n\tduk_uint_fast32_t res = 0;\n\tduk_uint8_t x;\n\tduk_small_int_t t;\n\n\tfor (i = 0; i < n; i++) {\n\t\t/* XXX: share helper from lexer; duk_lexer.c / hexval(). */\n\n\t\tx = duk__dec_get(js_ctx);\n\t\tDUK_DDD(DUK_DDDPRINT(\"decode_hex_escape: i=%ld, n=%ld, res=%ld, x=%ld\",\n\t\t                     (long) i, (long) n, (long) res, (long) x));\n\n\t\t/* x == 0x00 (EOF) causes syntax_error */\n\t\tDUK_ASSERT(duk_hex_dectab[0] == -1);\n\t\tt = duk_hex_dectab[x & 0xff];\n\t\tif (DUK_LIKELY(t >= 0)) {\n\t\t\tres = (res * 16) + (duk_uint_fast32_t) t;\n\t\t} else {\n\t\t\t/* catches EOF and invalid digits */\n\t\t\tgoto syntax_error;\n\t\t}\n\t}\n\n\tDUK_DDD(DUK_DDDPRINT(\"final hex decoded value: %ld\", (long) res));\n\treturn res;\n\n syntax_error:\n\tduk__dec_syntax_error(js_ctx);\n\tDUK_UNREACHABLE();\n\treturn 0;\n}\n\nDUK_LOCAL void duk__dec_req_stridx(duk_json_dec_ctx *js_ctx, duk_small_uint_t stridx) {\n\tduk_hstring *h;\n\tconst duk_uint8_t *p;\n\tduk_uint8_t x, y;\n\n\t/* First character has already been eaten and checked by the caller.\n\t * We can scan until a NUL in stridx string because no built-in strings\n\t * have internal NULs.\n\t */\n\n\tDUK_ASSERT_STRIDX_VALID(stridx);\n\th = DUK_HTHREAD_GET_STRING(js_ctx->thr, stridx);\n\tDUK_ASSERT(h != NULL);\n\n\tp = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h) + 1;\n\tDUK_ASSERT(*(js_ctx->p - 1) == *(p - 1));  /* first character has been matched */\n\n\tfor (;;) {\n\t\tx = *p;\n\t\tif (x == 0) {\n\t\t\tbreak;\n\t\t}\n\t\ty = duk__dec_get(js_ctx);\n\t\tif (x != y) {\n\t\t\t/* Catches EOF of JSON input. */\n\t\t\tgoto syntax_error;\n\t\t}\n\t\tp++;\n\t}\n\n\treturn;\n\n syntax_error:\n\tduk__dec_syntax_error(js_ctx);\n\tDUK_UNREACHABLE();\n}\n\nDUK_LOCAL duk_small_int_t duk__dec_string_escape(duk_json_dec_ctx *js_ctx, duk_uint8_t **ext_p) {\n\tduk_uint_fast32_t cp;\n\n\t/* EOF (-1) will be cast to an unsigned value first\n\t * and then re-cast for the switch.  In any case, it\n\t * will match the default case (syntax error).\n\t */\n\tcp = (duk_uint_fast32_t) duk__dec_get(js_ctx);\n\tswitch (cp) {\n\tcase DUK_ASC_BACKSLASH: break;\n\tcase DUK_ASC_DOUBLEQUOTE: break;\n\tcase DUK_ASC_SLASH: break;\n\tcase DUK_ASC_LC_T: cp = 0x09; break;\n\tcase DUK_ASC_LC_N: cp = 0x0a; break;\n\tcase DUK_ASC_LC_R: cp = 0x0d; break;\n\tcase DUK_ASC_LC_F: cp = 0x0c; break;\n\tcase DUK_ASC_LC_B: cp = 0x08; break;\n\tcase DUK_ASC_LC_U: {\n\t\tcp = duk__dec_decode_hex_escape(js_ctx, 4);\n\t\tbreak;\n\t}\n#if defined(DUK_USE_JX)\n\tcase DUK_ASC_UC_U: {\n\t\tif (js_ctx->flag_ext_custom) {\n\t\t\tcp = duk__dec_decode_hex_escape(js_ctx, 8);\n\t\t} else {\n\t\t\treturn 1;  /* syntax error */\n\t\t}\n\t\tbreak;\n\t}\n\tcase DUK_ASC_LC_X: {\n\t\tif (js_ctx->flag_ext_custom) {\n\t\t\tcp = duk__dec_decode_hex_escape(js_ctx, 2);\n\t\t} else {\n\t\t\treturn 1;  /* syntax error */\n\t\t}\n\t\tbreak;\n\t}\n#endif  /* DUK_USE_JX */\n\tdefault:\n\t\t/* catches EOF (0x00) */\n\t\treturn 1;  /* syntax error */\n\t}\n\n\tDUK_RAW_WRITE_XUTF8(*ext_p, cp);\n\n\treturn 0;\n}\n\nDUK_LOCAL void duk__dec_string(duk_json_dec_ctx *js_ctx) {\n\tduk_hthread *thr = js_ctx->thr;\n\tduk_bufwriter_ctx bw_alloc;\n\tduk_bufwriter_ctx *bw;\n\tduk_uint8_t *q;\n\n\t/* '\"' was eaten by caller */\n\n\t/* Note that we currently parse -bytes-, not codepoints.\n\t * All non-ASCII extended UTF-8 will encode to bytes >= 0x80,\n\t * so they'll simply pass through (valid UTF-8 or not).\n\t */\n\n\tbw = &bw_alloc;\n\tDUK_BW_INIT_PUSHBUF(js_ctx->thr, bw, DUK__JSON_DECSTR_BUFSIZE);\n\tq = DUK_BW_GET_PTR(js_ctx->thr, bw);\n\n#if defined(DUK_USE_JSON_DECSTRING_FASTPATH)\n\tfor (;;) {\n\t\tduk_small_uint_t safe;\n\t\tduk_uint8_t b, x;\n\t\tconst duk_uint8_t *p;\n\n\t\t/* Select a safe loop count where no output checks are\n\t\t * needed assuming we won't encounter escapes.  Input\n\t\t * bound checks are not necessary as a NUL (guaranteed)\n\t\t * will cause a SyntaxError before we read out of bounds.\n\t\t */\n\n\t\tsafe = DUK__JSON_DECSTR_CHUNKSIZE;\n\n\t\t/* Ensure space for 1:1 output plus one escape. */\n\t\tq = DUK_BW_ENSURE_RAW(js_ctx->thr, bw, safe + DUK_UNICODE_MAX_XUTF8_LENGTH, q);\n\n\t\tp = js_ctx->p;  /* temp copy, write back for next loop */\n\t\tfor (;;) {\n\t\t\tif (safe == 0) {\n\t\t\t\tjs_ctx->p = p;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tsafe--;\n\n\t\t\t/* End of input (NUL) goes through slow path and causes SyntaxError. */\n\t\t\tDUK_ASSERT(duk__json_decstr_lookup[0] == 0x00);\n\n\t\t\tb = *p++;\n\t\t\tx = (duk_small_int_t) duk__json_decstr_lookup[b];\n\t\t\tif (DUK_LIKELY(x != 0)) {\n\t\t\t\t/* Fast path, decode as is. */\n\t\t\t\t*q++ = b;\n\t\t\t} else if (b == DUK_ASC_DOUBLEQUOTE) {\n\t\t\t\tjs_ctx->p = p;\n\t\t\t\tgoto found_quote;\n\t\t\t} else if (b == DUK_ASC_BACKSLASH) {\n\t\t\t\t/* We've ensured space for one escaped input; then\n\t\t\t\t * bail out and recheck (this makes escape handling\n\t\t\t\t * quite slow but it's uncommon).\n\t\t\t\t */\n\t\t\t\tjs_ctx->p = p;\n\t\t\t\tif (duk__dec_string_escape(js_ctx, &q) != 0) {\n\t\t\t\t\tgoto syntax_error;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t} else {\n\t\t\t\tjs_ctx->p = p;\n\t\t\t\tgoto syntax_error;\n\t\t\t}\n\t\t}\n\t}\n found_quote:\n#else  /* DUK_USE_JSON_DECSTRING_FASTPATH */\n\tfor (;;) {\n\t\tduk_uint8_t x;\n\n\t\tq = DUK_BW_ENSURE_RAW(js_ctx->thr, bw, DUK_UNICODE_MAX_XUTF8_LENGTH, q);\n\n\t\tx = duk__dec_get(js_ctx);\n\n\t\tif (x == DUK_ASC_DOUBLEQUOTE) {\n\t\t\tbreak;\n\t\t} else if (x == DUK_ASC_BACKSLASH) {\n\t\t\tif (duk__dec_string_escape(js_ctx, &q) != 0) {\n\t\t\t\tgoto syntax_error;\n\t\t\t}\n\t\t} else if (x < 0x20) {\n\t\t\t/* catches EOF (NUL) */\n\t\t\tgoto syntax_error;\n\t\t} else {\n\t\t\t*q++ = (duk_uint8_t) x;\n\t\t}\n\t}\n#endif  /* DUK_USE_JSON_DECSTRING_FASTPATH */\n\n\tDUK_BW_SETPTR_AND_COMPACT(js_ctx->thr, bw, q);\n\t(void) duk_buffer_to_string(thr, -1);  /* Safe if input string is safe. */\n\n\t/* [ ... str ] */\n\n\treturn;\n\n syntax_error:\n\tduk__dec_syntax_error(js_ctx);\n\tDUK_UNREACHABLE();\n}\n\n#if defined(DUK_USE_JX)\n/* Decode a plain string consisting entirely of identifier characters.\n * Used to parse plain keys (e.g. \"foo: 123\").\n */\nDUK_LOCAL void duk__dec_plain_string(duk_json_dec_ctx *js_ctx) {\n\tduk_hthread *thr = js_ctx->thr;\n\tconst duk_uint8_t *p;\n\tduk_small_int_t x;\n\n\t/* Caller has already eaten the first char so backtrack one byte. */\n\n\tjs_ctx->p--;  /* safe */\n\tp = js_ctx->p;\n\n\t/* Here again we parse bytes, and non-ASCII UTF-8 will cause end of\n\t * parsing (which is correct except if there are non-shortest encodings).\n\t * There is also no need to check explicitly for end of input buffer as\n\t * the input is NUL padded and NUL will exit the parsing loop.\n\t *\n\t * Because no unescaping takes place, we can just scan to the end of the\n\t * plain string and intern from the input buffer.\n\t */\n\n\tfor (;;) {\n\t\tx = *p;\n\n\t\t/* There is no need to check the first character specially here\n\t\t * (i.e. reject digits): the caller only accepts valid initial\n\t\t * characters and won't call us if the first character is a digit.\n\t\t * This also ensures that the plain string won't be empty.\n\t\t */\n\n\t\tif (!duk_unicode_is_identifier_part((duk_codepoint_t) x)) {\n\t\t\tbreak;\n\t\t}\n\t\tp++;\n\t}\n\n\tduk_push_lstring(thr, (const char *) js_ctx->p, (duk_size_t) (p - js_ctx->p));\n\tjs_ctx->p = p;\n\n\t/* [ ... str ] */\n}\n#endif  /* DUK_USE_JX */\n\n#if defined(DUK_USE_JX)\nDUK_LOCAL void duk__dec_pointer(duk_json_dec_ctx *js_ctx) {\n\tduk_hthread *thr = js_ctx->thr;\n\tconst duk_uint8_t *p;\n\tduk_small_int_t x;\n\tvoid *voidptr;\n\n\t/* Caller has already eaten the first character ('(') which we don't need. */\n\n\tp = js_ctx->p;\n\n\tfor (;;) {\n\t\tx = *p;\n\n\t\t/* Assume that the native representation never contains a closing\n\t\t * parenthesis.\n\t\t */\n\n\t\tif (x == DUK_ASC_RPAREN) {\n\t\t\tbreak;\n\t\t} else if (x <= 0) {\n\t\t\t/* NUL term or -1 (EOF), NUL check would suffice */\n\t\t\tgoto syntax_error;\n\t\t}\n\t\tp++;\n\t}\n\n\t/* There is no need to NUL delimit the sscanf() call: trailing garbage is\n\t * ignored and there is always a NUL terminator which will force an error\n\t * if no error is encountered before it.  It's possible that the scan\n\t * would scan further than between [js_ctx->p,p[ though and we'd advance\n\t * by less than the scanned value.\n\t *\n\t * Because pointers are platform specific, a failure to scan a pointer\n\t * results in a null pointer which is a better placeholder than a missing\n\t * value or an error.\n\t */\n\n\tvoidptr = NULL;\n\t(void) DUK_SSCANF((const char *) js_ctx->p, DUK_STR_FMT_PTR, &voidptr);\n\tduk_push_pointer(thr, voidptr);\n\tjs_ctx->p = p + 1;  /* skip ')' */\n\n\t/* [ ... ptr ] */\n\n\treturn;\n\n syntax_error:\n\tduk__dec_syntax_error(js_ctx);\n\tDUK_UNREACHABLE();\n}\n#endif  /* DUK_USE_JX */\n\n#if defined(DUK_USE_JX)\nDUK_LOCAL void duk__dec_buffer(duk_json_dec_ctx *js_ctx) {\n\tduk_hthread *thr = js_ctx->thr;\n\tconst duk_uint8_t *p;\n\tduk_uint8_t *buf;\n\tduk_size_t src_len;\n\tduk_small_int_t x;\n\n\t/* Caller has already eaten the first character ('|') which we don't need. */\n\n\tp = js_ctx->p;\n\n\t/* XXX: Would be nice to share the fast path loop from duk_hex_decode()\n\t * and avoid creating a temporary buffer.  However, there are some\n\t * differences which prevent trivial sharing:\n\t *\n\t *   - Pipe char detection\n\t *   - EOF detection\n\t *   - Unknown length of input and output\n\t *\n\t * The best approach here would be a bufwriter and a reasonaly sized\n\t * safe inner loop (e.g. 64 output bytes at a time).\n\t */\n\n\tfor (;;) {\n\t\tx = *p;\n\n\t\t/* This loop intentionally does not ensure characters are valid\n\t\t * ([0-9a-fA-F]) because the hex decode call below will do that.\n\t\t */\n\t\tif (x == DUK_ASC_PIPE) {\n\t\t\tbreak;\n\t\t} else if (x <= 0) {\n\t\t\t/* NUL term or -1 (EOF), NUL check would suffice */\n\t\t\tgoto syntax_error;\n\t\t}\n\t\tp++;\n\t}\n\n\t/* XXX: this is not very nice; unnecessary copy is made. */\n\tsrc_len = (duk_size_t) (p - js_ctx->p);\n\tbuf = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, src_len);\n\tDUK_ASSERT(buf != NULL);\n\tDUK_MEMCPY((void *) buf, (const void *) js_ctx->p, src_len);\n\tduk_hex_decode(thr, -1);\n\n\tjs_ctx->p = p + 1;  /* skip '|' */\n\n\t/* [ ... buf ] */\n\n\treturn;\n\n syntax_error:\n\tduk__dec_syntax_error(js_ctx);\n\tDUK_UNREACHABLE();\n}\n#endif  /* DUK_USE_JX */\n\n/* Parse a number, other than NaN or +/- Infinity */\nDUK_LOCAL void duk__dec_number(duk_json_dec_ctx *js_ctx) {\n\tduk_hthread *thr = js_ctx->thr;\n\tconst duk_uint8_t *p_start;\n\tconst duk_uint8_t *p;\n\tduk_uint8_t x;\n\tduk_small_uint_t s2n_flags;\n\n\tDUK_DDD(DUK_DDDPRINT(\"parse_number\"));\n\n\tp_start = js_ctx->p;\n\n\t/* First pass parse is very lenient (e.g. allows '1.2.3') and extracts a\n\t * string for strict number parsing.\n\t */\n\n\tp = js_ctx->p;\n\tfor (;;) {\n\t\tx = *p;\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"parse_number: p_start=%p, p=%p, p_end=%p, x=%ld\",\n\t\t                     (const void *) p_start, (const void *) p,\n\t\t                     (const void *) js_ctx->p_end, (long) x));\n\n#if defined(DUK_USE_JSON_DECNUMBER_FASTPATH)\n\t\t/* This fast path is pretty marginal in practice.\n\t\t * XXX: candidate for removal.\n\t\t */\n\t\tDUK_ASSERT(duk__json_decnumber_lookup[0x00] == 0x00);  /* end-of-input breaks */\n\t\tif (duk__json_decnumber_lookup[x] == 0) {\n\t\t\tbreak;\n\t\t}\n#else  /* DUK_USE_JSON_DECNUMBER_FASTPATH */\n\t\tif (!((x >= DUK_ASC_0 && x <= DUK_ASC_9) ||\n\t\t      (x == DUK_ASC_PERIOD || x == DUK_ASC_LC_E ||\n\t\t       x == DUK_ASC_UC_E || x == DUK_ASC_MINUS || x == DUK_ASC_PLUS))) {\n\t\t\t/* Plus sign must be accepted for positive exponents\n\t\t\t * (e.g. '1.5e+2').  This clause catches NULs.\n\t\t\t */\n\t\t\tbreak;\n\t\t}\n#endif  /* DUK_USE_JSON_DECNUMBER_FASTPATH */\n\t\tp++;  /* safe, because matched (NUL causes a break) */\n\t}\n\tjs_ctx->p = p;\n\n\tDUK_ASSERT(js_ctx->p > p_start);\n\tduk_push_lstring(thr, (const char *) p_start, (duk_size_t) (p - p_start));\n\n\ts2n_flags = DUK_S2N_FLAG_ALLOW_EXP |\n\t            DUK_S2N_FLAG_ALLOW_MINUS |  /* but don't allow leading plus */\n\t            DUK_S2N_FLAG_ALLOW_FRAC;\n\n\tDUK_DDD(DUK_DDDPRINT(\"parse_number: string before parsing: %!T\",\n\t                     (duk_tval *) duk_get_tval(thr, -1)));\n\tduk_numconv_parse(thr, 10 /*radix*/, s2n_flags);\n\tif (duk_is_nan(thr, -1)) {\n\t\tduk__dec_syntax_error(js_ctx);\n\t}\n\tDUK_ASSERT(duk_is_number(thr, -1));\n\tDUK_DDD(DUK_DDDPRINT(\"parse_number: final number: %!T\",\n\t                     (duk_tval *) duk_get_tval(thr, -1)));\n\n\t/* [ ... num ] */\n}\n\nDUK_LOCAL void duk__dec_objarr_entry(duk_json_dec_ctx *js_ctx) {\n\tduk_hthread *thr = js_ctx->thr;\n\tduk_require_stack(thr, DUK_JSON_DEC_REQSTACK);\n\n\t/* c recursion check */\n\n\tDUK_ASSERT_DISABLE(js_ctx->recursion_depth >= 0);  /* unsigned */\n\tDUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);\n\tif (js_ctx->recursion_depth >= js_ctx->recursion_limit) {\n\t\tDUK_ERROR_RANGE(thr, DUK_STR_JSONDEC_RECLIMIT);\n\t}\n\tjs_ctx->recursion_depth++;\n}\n\nDUK_LOCAL void duk__dec_objarr_exit(duk_json_dec_ctx *js_ctx) {\n\t/* c recursion check */\n\n\tDUK_ASSERT(js_ctx->recursion_depth > 0);\n\tDUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);\n\tjs_ctx->recursion_depth--;\n}\n\nDUK_LOCAL void duk__dec_object(duk_json_dec_ctx *js_ctx) {\n\tduk_hthread *thr = js_ctx->thr;\n\tduk_int_t key_count;  /* XXX: a \"first\" flag would suffice */\n\tduk_uint8_t x;\n\n\tDUK_DDD(DUK_DDDPRINT(\"parse_object\"));\n\n\tduk__dec_objarr_entry(js_ctx);\n\n\tduk_push_object(thr);\n\n\t/* Initial '{' has been checked and eaten by caller. */\n\n\tkey_count = 0;\n\tfor (;;) {\n\t\tx = duk__dec_get_nonwhite(js_ctx);\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"parse_object: obj=%!T, x=%ld, key_count=%ld\",\n\t\t                     (duk_tval *) duk_get_tval(thr, -1),\n\t\t                     (long) x, (long) key_count));\n\n\t\t/* handle comma and closing brace */\n\n\t\tif (x == DUK_ASC_COMMA && key_count > 0) {\n\t\t\t/* accept comma, expect new value */\n\t\t\tx = duk__dec_get_nonwhite(js_ctx);\n\t\t} else if (x == DUK_ASC_RCURLY) {\n\t\t\t/* eat closing brace */\n\t\t\tbreak;\n\t\t} else if (key_count == 0) {\n\t\t\t/* accept anything, expect first value (EOF will be\n\t\t\t * caught by key parsing below.\n\t\t\t */\n\t\t\t;\n\t\t} else {\n\t\t\t/* catches EOF (NUL) and initial comma */\n\t\t\tgoto syntax_error;\n\t\t}\n\n\t\t/* parse key and value */\n\n\t\tif (x == DUK_ASC_DOUBLEQUOTE) {\n\t\t\tduk__dec_string(js_ctx);\n#if defined(DUK_USE_JX)\n\t\t} else if (js_ctx->flag_ext_custom &&\n\t\t           duk_unicode_is_identifier_start((duk_codepoint_t) x)) {\n\t\t\tduk__dec_plain_string(js_ctx);\n#endif\n\t\t} else {\n\t\t\tgoto syntax_error;\n\t\t}\n\n\t\t/* [ ... obj key ] */\n\n\t\tx = duk__dec_get_nonwhite(js_ctx);\n\t\tif (x != DUK_ASC_COLON) {\n\t\t\tgoto syntax_error;\n\t\t}\n\n\t\tduk__dec_value(js_ctx);\n\n\t\t/* [ ... obj key val ] */\n\n\t\tduk_xdef_prop_wec(thr, -3);\n\n\t\t/* [ ... obj ] */\n\n\t\tkey_count++;\n\t}\n\n\t/* [ ... obj ] */\n\n\tDUK_DDD(DUK_DDDPRINT(\"parse_object: final object is %!T\",\n\t                     (duk_tval *) duk_get_tval(thr, -1)));\n\n\tduk__dec_objarr_exit(js_ctx);\n\treturn;\n\n syntax_error:\n\tduk__dec_syntax_error(js_ctx);\n\tDUK_UNREACHABLE();\n}\n\nDUK_LOCAL void duk__dec_array(duk_json_dec_ctx *js_ctx) {\n\tduk_hthread *thr = js_ctx->thr;\n\tduk_uarridx_t arr_idx;\n\tduk_uint8_t x;\n\n\tDUK_DDD(DUK_DDDPRINT(\"parse_array\"));\n\n\tduk__dec_objarr_entry(js_ctx);\n\n\tduk_push_array(thr);\n\n\t/* Initial '[' has been checked and eaten by caller. */\n\n\tarr_idx = 0;\n\tfor (;;) {\n\t\tx = duk__dec_get_nonwhite(js_ctx);\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"parse_array: arr=%!T, x=%ld, arr_idx=%ld\",\n\t\t                     (duk_tval *) duk_get_tval(thr, -1),\n\t\t                     (long) x, (long) arr_idx));\n\n\t\t/* handle comma and closing bracket */\n\n\t\tif ((x == DUK_ASC_COMMA) && (arr_idx != 0)) {\n\t\t\t/* accept comma, expect new value */\n\t\t\t;\n\t\t} else if (x == DUK_ASC_RBRACKET) {\n\t\t\t/* eat closing bracket */\n\t\t\tbreak;\n\t\t} else if (arr_idx == 0) {\n\t\t\t/* accept anything, expect first value (EOF will be\n\t\t\t * caught by duk__dec_value() below.\n\t\t\t */\n\t\t\tjs_ctx->p--;  /* backtrack (safe) */\n\t\t} else {\n\t\t\t/* catches EOF (NUL) and initial comma */\n\t\t\tgoto syntax_error;\n\t\t}\n\n\t\t/* parse value */\n\n\t\tduk__dec_value(js_ctx);\n\n\t\t/* [ ... arr val ] */\n\n\t\tduk_xdef_prop_index_wec(thr, -2, arr_idx);\n\t\tarr_idx++;\n\t}\n\n\t/* Must set 'length' explicitly when using duk_xdef_prop_xxx() to\n\t * set the values.\n\t */\n\n\tduk_set_length(thr, -1, arr_idx);\n\n\t/* [ ... arr ] */\n\n\tDUK_DDD(DUK_DDDPRINT(\"parse_array: final array is %!T\",\n\t                     (duk_tval *) duk_get_tval(thr, -1)));\n\n\tduk__dec_objarr_exit(js_ctx);\n\treturn;\n\n syntax_error:\n\tduk__dec_syntax_error(js_ctx);\n\tDUK_UNREACHABLE();\n}\n\nDUK_LOCAL void duk__dec_value(duk_json_dec_ctx *js_ctx) {\n\tduk_hthread *thr = js_ctx->thr;\n\tduk_uint8_t x;\n\n\tx = duk__dec_get_nonwhite(js_ctx);\n\n\tDUK_DDD(DUK_DDDPRINT(\"parse_value: initial x=%ld\", (long) x));\n\n\t/* Note: duk__dec_req_stridx() backtracks one char */\n\n\tif (x == DUK_ASC_DOUBLEQUOTE) {\n\t\tduk__dec_string(js_ctx);\n\t} else if ((x >= DUK_ASC_0 && x <= DUK_ASC_9) || (x == DUK_ASC_MINUS)) {\n#if defined(DUK_USE_JX)\n\t\tif (js_ctx->flag_ext_custom && x == DUK_ASC_MINUS && duk__dec_peek(js_ctx) == DUK_ASC_UC_I) {\n\t\t\tduk__dec_req_stridx(js_ctx, DUK_STRIDX_MINUS_INFINITY);  /* \"-Infinity\", '-' has been eaten */\n\t\t\tduk_push_number(thr, -DUK_DOUBLE_INFINITY);\n\t\t} else {\n#else\n\t\t{  /* unconditional block */\n#endif\n\t\t\t/* We already ate 'x', so backup one byte. */\n\t\t\tjs_ctx->p--;  /* safe */\n\t\t\tduk__dec_number(js_ctx);\n\t\t}\n\t} else if (x == DUK_ASC_LC_T) {\n\t\tduk__dec_req_stridx(js_ctx, DUK_STRIDX_TRUE);\n\t\tduk_push_true(thr);\n\t} else if (x == DUK_ASC_LC_F) {\n\t\tduk__dec_req_stridx(js_ctx, DUK_STRIDX_FALSE);\n\t\tduk_push_false(thr);\n\t} else if (x == DUK_ASC_LC_N) {\n\t\tduk__dec_req_stridx(js_ctx, DUK_STRIDX_LC_NULL);\n\t\tduk_push_null(thr);\n#if defined(DUK_USE_JX)\n\t} else if (js_ctx->flag_ext_custom && x == DUK_ASC_LC_U) {\n\t\tduk__dec_req_stridx(js_ctx, DUK_STRIDX_LC_UNDEFINED);\n\t\tduk_push_undefined(thr);\n\t} else if (js_ctx->flag_ext_custom && x == DUK_ASC_UC_N) {\n\t\tduk__dec_req_stridx(js_ctx, DUK_STRIDX_NAN);\n\t\tduk_push_nan(thr);\n\t} else if (js_ctx->flag_ext_custom && x == DUK_ASC_UC_I) {\n\t\tduk__dec_req_stridx(js_ctx, DUK_STRIDX_INFINITY);\n\t\tduk_push_number(thr, DUK_DOUBLE_INFINITY);\n\t} else if (js_ctx->flag_ext_custom && x == DUK_ASC_LPAREN) {\n\t\tduk__dec_pointer(js_ctx);\n\t} else if (js_ctx->flag_ext_custom && x == DUK_ASC_PIPE) {\n\t\tduk__dec_buffer(js_ctx);\n#endif\n\t} else if (x == DUK_ASC_LCURLY) {\n\t\tduk__dec_object(js_ctx);\n\t} else if (x == DUK_ASC_LBRACKET) {\n\t\tduk__dec_array(js_ctx);\n\t} else {\n\t\t/* catches EOF (NUL) */\n\t\tgoto syntax_error;\n\t}\n\n\tduk__dec_eat_white(js_ctx);\n\n\t/* [ ... val ] */\n\treturn;\n\n syntax_error:\n\tduk__dec_syntax_error(js_ctx);\n\tDUK_UNREACHABLE();\n}\n\n/* Recursive value reviver, implements the Walk() algorithm.  No C recursion\n * check is done here because the initial parsing step will already ensure\n * there is a reasonable limit on C recursion depth and hence object depth.\n */\nDUK_LOCAL void duk__dec_reviver_walk(duk_json_dec_ctx *js_ctx) {\n\tduk_hthread *thr = js_ctx->thr;\n\tduk_hobject *h;\n\tduk_uarridx_t i, arr_len;\n\n\tDUK_DDD(DUK_DDDPRINT(\"walk: top=%ld, holder=%!T, name=%!T\",\n\t                     (long) duk_get_top(thr),\n\t                     (duk_tval *) duk_get_tval(thr, -2),\n\t                     (duk_tval *) duk_get_tval(thr, -1)));\n\n\tduk_dup_top(thr);\n\tduk_get_prop(thr, -3);  /* -> [ ... holder name val ] */\n\n\th = duk_get_hobject(thr, -1);\n\tif (h != NULL) {\n\t\tif (DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_ARRAY) {\n\t\t\tarr_len = (duk_uarridx_t) duk_get_length(thr, -1);\n\t\t\tfor (i = 0; i < arr_len; i++) {\n\t\t\t\t/* [ ... holder name val ] */\n\n\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"walk: array, top=%ld, i=%ld, arr_len=%ld, holder=%!T, name=%!T, val=%!T\",\n\t\t\t\t                     (long) duk_get_top(thr), (long) i, (long) arr_len,\n\t\t\t\t                     (duk_tval *) duk_get_tval(thr, -3), (duk_tval *) duk_get_tval(thr, -2),\n\t\t\t\t                     (duk_tval *) duk_get_tval(thr, -1)));\n\n\t\t\t\tduk_dup_top(thr);\n\t\t\t\t(void) duk_push_uint_to_hstring(thr, (duk_uint_t) i);  /* -> [ ... holder name val val ToString(i) ] */\n\t\t\t\tduk__dec_reviver_walk(js_ctx);  /* -> [ ... holder name val new_elem ] */\n\n\t\t\t\tif (duk_is_undefined(thr, -1)) {\n\t\t\t\t\tduk_pop(thr);\n\t\t\t\t\tduk_del_prop_index(thr, -1, i);\n\t\t\t\t} else {\n\t\t\t\t\t/* XXX: duk_xdef_prop_index_wec() would be more appropriate\n\t\t\t\t\t * here but it currently makes some assumptions that might\n\t\t\t\t\t * not hold (e.g. that previous property is not an accessor).\n\t\t\t\t\t */\n\t\t\t\t\tduk_put_prop_index(thr, -2, i);\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\t/* [ ... holder name val ] */\n\t\t\tduk_enum(thr, -1, DUK_ENUM_OWN_PROPERTIES_ONLY /*flags*/);\n\t\t\twhile (duk_next(thr, -1 /*enum_index*/, 0 /*get_value*/)) {\n\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"walk: object, top=%ld, holder=%!T, name=%!T, val=%!T, enum=%!iT, obj_key=%!T\",\n\t\t\t\t                     (long) duk_get_top(thr), (duk_tval *) duk_get_tval(thr, -5),\n\t\t\t\t                     (duk_tval *) duk_get_tval(thr, -4), (duk_tval *) duk_get_tval(thr, -3),\n\t\t\t\t                     (duk_tval *) duk_get_tval(thr, -2), (duk_tval *) duk_get_tval(thr, -1)));\n\n\t\t\t\t/* [ ... holder name val enum obj_key ] */\n\t\t\t\tduk_dup_m3(thr);\n\t\t\t\tduk_dup_m2(thr);\n\n\t\t\t\t/* [ ... holder name val enum obj_key val obj_key ] */\n\t\t\t\tduk__dec_reviver_walk(js_ctx);\n\n\t\t\t\t/* [ ... holder name val enum obj_key new_elem ] */\n\t\t\t\tif (duk_is_undefined(thr, -1)) {\n\t\t\t\t\tduk_pop(thr);\n\t\t\t\t\tduk_del_prop(thr, -3);\n\t\t\t\t} else {\n\t\t\t\t\t/* XXX: duk_xdef_prop_index_wec() would be more appropriate\n\t\t\t\t\t * here but it currently makes some assumptions that might\n\t\t\t\t\t * not hold (e.g. that previous property is not an accessor).\n\t\t\t\t\t *\n\t\t\t\t\t * Using duk_put_prop() works incorrectly with '__proto__'\n\t\t\t\t\t * if the own property with that name has been deleted.  This\n\t\t\t\t\t * does not happen normally, but a clever reviver can trigger\n\t\t\t\t\t * that, see complex reviver case in: test-bug-json-parse-__proto__.js.\n\t\t\t\t\t */\n\t\t\t\t\tduk_put_prop(thr, -4);\n\t\t\t\t}\n\t\t\t}\n\t\t\tduk_pop(thr);  /* pop enum */\n\t\t}\n\t}\n\n\t/* [ ... holder name val ] */\n\n\tduk_dup(thr, js_ctx->idx_reviver);\n\tduk_insert(thr, -4);  /* -> [ ... reviver holder name val ] */\n\tduk_call_method(thr, 2);  /* -> [ ... res ] */\n\n\tDUK_DDD(DUK_DDDPRINT(\"walk: top=%ld, result=%!T\",\n\t                     (long) duk_get_top(thr), (duk_tval *) duk_get_tval(thr, -1)));\n}\n\n/*\n *  Stringify implementation.\n */\n\n#define DUK__EMIT_1(js_ctx,ch)          duk__emit_1((js_ctx), (duk_uint_fast8_t) (ch))\n#define DUK__EMIT_2(js_ctx,ch1,ch2)     duk__emit_2((js_ctx), (duk_uint_fast8_t) (ch1), (duk_uint_fast8_t) (ch2))\n#define DUK__EMIT_HSTR(js_ctx,h)        duk__emit_hstring((js_ctx), (h))\n#if defined(DUK_USE_FASTINT) || defined(DUK_USE_JX) || defined(DUK_USE_JC)\n#define DUK__EMIT_CSTR(js_ctx,p)        duk__emit_cstring((js_ctx), (p))\n#endif\n#define DUK__EMIT_STRIDX(js_ctx,i)      duk__emit_stridx((js_ctx), (i))\n#define DUK__UNEMIT_1(js_ctx)           duk__unemit_1((js_ctx))\n\nDUK_LOCAL void duk__emit_1(duk_json_enc_ctx *js_ctx, duk_uint_fast8_t ch) {\n\tDUK_BW_WRITE_ENSURE_U8(js_ctx->thr, &js_ctx->bw, ch);\n}\n\nDUK_LOCAL void duk__emit_2(duk_json_enc_ctx *js_ctx, duk_uint_fast8_t ch1, duk_uint_fast8_t ch2) {\n\tDUK_BW_WRITE_ENSURE_U8_2(js_ctx->thr, &js_ctx->bw, ch1, ch2);\n}\n\nDUK_LOCAL void duk__emit_hstring(duk_json_enc_ctx *js_ctx, duk_hstring *h) {\n\tDUK_BW_WRITE_ENSURE_HSTRING(js_ctx->thr, &js_ctx->bw, h);\n}\n\n#if defined(DUK_USE_FASTINT) || defined(DUK_USE_JX) || defined(DUK_USE_JC)\nDUK_LOCAL void duk__emit_cstring(duk_json_enc_ctx *js_ctx, const char *str) {\n\tDUK_BW_WRITE_ENSURE_CSTRING(js_ctx->thr, &js_ctx->bw, str);\n}\n#endif\n\nDUK_LOCAL void duk__emit_stridx(duk_json_enc_ctx *js_ctx, duk_small_uint_t stridx) {\n\tduk_hstring *h;\n\n\tDUK_ASSERT_STRIDX_VALID(stridx);\n\th = DUK_HTHREAD_GET_STRING(js_ctx->thr, stridx);\n\tDUK_ASSERT(h != NULL);\n\n\tDUK_BW_WRITE_ENSURE_HSTRING(js_ctx->thr, &js_ctx->bw, h);\n}\n\nDUK_LOCAL void duk__unemit_1(duk_json_enc_ctx *js_ctx) {\n\tDUK_ASSERT(DUK_BW_GET_SIZE(js_ctx->thr, &js_ctx->bw) >= 1);\n\tDUK_BW_ADD_PTR(js_ctx->thr, &js_ctx->bw, -1);\n}\n\n#define DUK__MKESC(nybbles,esc1,esc2)  \\\n\t(((duk_uint_fast32_t) (nybbles)) << 16) | \\\n\t(((duk_uint_fast32_t) (esc1)) << 8) | \\\n\t((duk_uint_fast32_t) (esc2))\n\nDUK_LOCAL duk_uint8_t *duk__emit_esc_auto_fast(duk_json_enc_ctx *js_ctx, duk_uint_fast32_t cp, duk_uint8_t *q) {\n\tduk_uint_fast32_t tmp;\n\tduk_small_uint_t dig;\n\n\tDUK_UNREF(js_ctx);\n\n\t/* Caller ensures space for at least DUK__JSON_MAX_ESC_LEN. */\n\n\t/* Select appropriate escape format automatically, and set 'tmp' to a\n\t * value encoding both the escape format character and the nybble count:\n\t *\n\t *   (nybble_count << 16) | (escape_char1) | (escape_char2)\n\t */\n\n#if defined(DUK_USE_JX)\n\tif (DUK_LIKELY(cp < 0x100UL)) {\n\t\tif (DUK_UNLIKELY(js_ctx->flag_ext_custom != 0U)) {\n\t\t\ttmp = DUK__MKESC(2, DUK_ASC_BACKSLASH, DUK_ASC_LC_X);\n\t\t} else {\n\t\t\ttmp = DUK__MKESC(4, DUK_ASC_BACKSLASH, DUK_ASC_LC_U);\n\t\t}\n\t} else\n#endif\n\tif (DUK_LIKELY(cp < 0x10000UL)) {\n\t\ttmp = DUK__MKESC(4, DUK_ASC_BACKSLASH, DUK_ASC_LC_U);\n\t} else {\n#if defined(DUK_USE_JX)\n\t\tif (DUK_LIKELY(js_ctx->flag_ext_custom != 0U)) {\n\t\t\ttmp = DUK__MKESC(8, DUK_ASC_BACKSLASH, DUK_ASC_UC_U);\n\t\t} else\n#endif\n\t\t{\n\t\t\t/* In compatible mode and standard JSON mode, output\n\t\t\t * something useful for non-BMP characters.  This won't\n\t\t\t * roundtrip but will still be more or less readable and\n\t\t\t * more useful than an error.\n\t\t\t */\n\t\t\ttmp = DUK__MKESC(8, DUK_ASC_UC_U, DUK_ASC_PLUS);\n\t\t}\n\t}\n\n\t*q++ = (duk_uint8_t) ((tmp >> 8) & 0xff);\n\t*q++ = (duk_uint8_t) (tmp & 0xff);\n\n\ttmp = tmp >> 16;\n\twhile (tmp > 0) {\n\t\ttmp--;\n\t\tdig = (duk_small_uint_t) ((cp >> (4 * tmp)) & 0x0f);\n\t\t*q++ = duk_lc_digits[dig];\n\t}\n\n\treturn q;\n}\n\nDUK_LOCAL void duk__enc_key_autoquote(duk_json_enc_ctx *js_ctx, duk_hstring *k) {\n\tconst duk_int8_t *p, *p_start, *p_end;  /* Note: intentionally signed. */\n\tduk_size_t k_len;\n\tduk_codepoint_t cp;\n\n\tDUK_ASSERT(k != NULL);\n\n\t/* Accept ASCII strings which conform to identifier requirements\n\t * as being emitted without key quotes.  Since we only accept ASCII\n\t * there's no need for actual decoding: 'p' is intentionally signed\n\t * so that bytes >= 0x80 extend to negative values and are rejected\n\t * as invalid identifier codepoints.\n\t */\n\n\tif (js_ctx->flag_avoid_key_quotes) {\n\t\tk_len = DUK_HSTRING_GET_BYTELEN(k);\n\t\tp_start = (const duk_int8_t *) DUK_HSTRING_GET_DATA(k);\n\t\tp_end = p_start + k_len;\n\t\tp = p_start;\n\n\t\tif (p == p_end) {\n\t\t\t/* Zero length string is not accepted without quotes */\n\t\t\tgoto quote_normally;\n\t\t}\n\t\tcp = (duk_codepoint_t) (*p++);\n\t\tif (DUK_UNLIKELY(!duk_unicode_is_identifier_start(cp))) {\n\t\t\tgoto quote_normally;\n\t\t}\n\t\twhile (p < p_end) {\n\t\t\tcp = (duk_codepoint_t) (*p++);\n\t\t\tif (DUK_UNLIKELY(!duk_unicode_is_identifier_part(cp))) {\n\t\t\t\tgoto quote_normally;\n\t\t\t}\n\t\t}\n\n\t\t/* This seems faster than emitting bytes one at a time and\n\t\t * then potentially rewinding.\n\t\t */\n\t\tDUK__EMIT_HSTR(js_ctx, k);\n\t\treturn;\n\t}\n\n quote_normally:\n\tduk__enc_quote_string(js_ctx, k);\n}\n\n/* The Quote(value) operation: quote a string.\n *\n * Stack policy: [ ] -> [ ].\n */\n\nDUK_LOCAL void duk__enc_quote_string(duk_json_enc_ctx *js_ctx, duk_hstring *h_str) {\n\tduk_hthread *thr = js_ctx->thr;\n\tconst duk_uint8_t *p, *p_start, *p_end, *p_now, *p_tmp;\n\tduk_uint8_t *q;\n\tduk_ucodepoint_t cp;  /* typed for duk_unicode_decode_xutf8() */\n\n\tDUK_DDD(DUK_DDDPRINT(\"duk__enc_quote_string: h_str=%!O\", (duk_heaphdr *) h_str));\n\n\tDUK_ASSERT(h_str != NULL);\n\tp_start = DUK_HSTRING_GET_DATA(h_str);\n\tp_end = p_start + DUK_HSTRING_GET_BYTELEN(h_str);\n\tp = p_start;\n\n\tDUK__EMIT_1(js_ctx, DUK_ASC_DOUBLEQUOTE);\n\n\t/* Encode string in small chunks, estimating the maximum expansion so that\n\t * there's no need to ensure space while processing the chunk.\n\t */\n\n\twhile (p < p_end) {\n\t\tduk_size_t left, now, space;\n\n\t\tleft = (duk_size_t) (p_end - p);\n\t\tnow = (left > DUK__JSON_ENCSTR_CHUNKSIZE ?\n\t\t       DUK__JSON_ENCSTR_CHUNKSIZE : left);\n\n\t\t/* Maximum expansion per input byte is 6:\n\t\t *   - invalid UTF-8 byte causes \"\\uXXXX\" to be emitted (6/1 = 6).\n\t\t *   - 2-byte UTF-8 encodes as \"\\uXXXX\" (6/2 = 3).\n\t\t *   - 4-byte UTF-8 encodes as \"\\Uxxxxxxxx\" (10/4 = 2.5).\n\t\t */\n\t\tspace = now * 6;\n\t\tq = DUK_BW_ENSURE_GETPTR(thr, &js_ctx->bw, space);\n\n\t\tp_now = p + now;\n\n\t\twhile (p < p_now) {\n#if defined(DUK_USE_JSON_QUOTESTRING_FASTPATH)\n\t\t\tduk_uint8_t b;\n\n\t\t\tb = duk__json_quotestr_lookup[*p++];\n\t\t\tif (DUK_LIKELY(b < 0x80)) {\n\t\t\t\t/* Most input bytes go through here. */\n\t\t\t\t*q++ = b;\n\t\t\t} else if (b >= 0xa0) {\n\t\t\t\t*q++ = DUK_ASC_BACKSLASH;\n\t\t\t\t*q++ = (duk_uint8_t) (b - 0x80);\n\t\t\t} else if (b == 0x80) {\n\t\t\t\tcp = (duk_ucodepoint_t) (*(p - 1));\n\t\t\t\tq = duk__emit_esc_auto_fast(js_ctx, cp, q);\n\t\t\t} else if (b == 0x7f && js_ctx->flag_ascii_only) {\n\t\t\t\t/* 0x7F is special */\n\t\t\t\tDUK_ASSERT(b == 0x81);\n\t\t\t\tcp = (duk_ucodepoint_t) 0x7f;\n\t\t\t\tq = duk__emit_esc_auto_fast(js_ctx, cp, q);\n\t\t\t} else {\n\t\t\t\tDUK_ASSERT(b == 0x81);\n\t\t\t\tp--;\n\n\t\t\t\t/* slow path is shared */\n#else  /* DUK_USE_JSON_QUOTESTRING_FASTPATH */\n\t\t\tcp = *p;\n\n\t\t\tif (DUK_LIKELY(cp <= 0x7f)) {\n\t\t\t\t/* ascii fast path: avoid decoding utf-8 */\n\t\t\t\tp++;\n\t\t\t\tif (cp == 0x22 || cp == 0x5c) {\n\t\t\t\t\t/* double quote or backslash */\n\t\t\t\t\t*q++ = DUK_ASC_BACKSLASH;\n\t\t\t\t\t*q++ = (duk_uint8_t) cp;\n\t\t\t\t} else if (cp < 0x20) {\n\t\t\t\t\tduk_uint_fast8_t esc_char;\n\n\t\t\t\t\t/* This approach is a bit shorter than a straight\n\t\t\t\t\t * if-else-ladder and also a bit faster.\n\t\t\t\t\t */\n\t\t\t\t\tif (cp < (sizeof(duk__json_quotestr_esc) / sizeof(duk_uint8_t)) &&\n\t\t\t\t\t    (esc_char = duk__json_quotestr_esc[cp]) != 0) {\n\t\t\t\t\t\t*q++ = DUK_ASC_BACKSLASH;\n\t\t\t\t\t\t*q++ = (duk_uint8_t) esc_char;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tq = duk__emit_esc_auto_fast(js_ctx, cp, q);\n\t\t\t\t\t}\n\t\t\t\t} else if (cp == 0x7f && js_ctx->flag_ascii_only) {\n\t\t\t\t\tq = duk__emit_esc_auto_fast(js_ctx, cp, q);\n\t\t\t\t} else {\n\t\t\t\t\t/* any other printable -> as is */\n\t\t\t\t\t*q++ = (duk_uint8_t) cp;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t/* slow path is shared */\n#endif  /* DUK_USE_JSON_QUOTESTRING_FASTPATH */\n\n\t\t\t\t/* slow path decode */\n\n\t\t\t\t/* If XUTF-8 decoding fails, treat the offending byte as a codepoint directly\n\t\t\t\t * and go forward one byte.  This is of course very lossy, but allows some kind\n\t\t\t\t * of output to be produced even for internal strings which don't conform to\n\t\t\t\t * XUTF-8.  All standard Ecmascript strings are always CESU-8, so this behavior\n\t\t\t\t * does not violate the Ecmascript specification.  The behavior is applied to\n\t\t\t\t * all modes, including Ecmascript standard JSON.  Because the current XUTF-8\n\t\t\t\t * decoding is not very strict, this behavior only really affects initial bytes\n\t\t\t\t * and truncated codepoints.\n\t\t\t\t *\n\t\t\t\t * Another alternative would be to scan forwards to start of next codepoint\n\t\t\t\t * (or end of input) and emit just one replacement codepoint.\n\t\t\t\t */\n\n\t\t\t\tp_tmp = p;\n\t\t\t\tif (!duk_unicode_decode_xutf8(thr, &p, p_start, p_end, &cp)) {\n\t\t\t\t\t/* Decode failed. */\n\t\t\t\t\tcp = *p_tmp;\n\t\t\t\t\tp = p_tmp + 1;\n\t\t\t\t}\n\n#if defined(DUK_USE_NONSTD_JSON_ESC_U2028_U2029)\n\t\t\t\tif (js_ctx->flag_ascii_only || cp == 0x2028 || cp == 0x2029) {\n#else\n\t\t\t\tif (js_ctx->flag_ascii_only) {\n#endif\n\t\t\t\t\tq = duk__emit_esc_auto_fast(js_ctx, cp, q);\n\t\t\t\t} else {\n\t\t\t\t\t/* as is */\n\t\t\t\t\tDUK_RAW_WRITE_XUTF8(q, cp);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tDUK_BW_SET_PTR(thr, &js_ctx->bw, q);\n\t}\n\n\tDUK__EMIT_1(js_ctx, DUK_ASC_DOUBLEQUOTE);\n}\n\n/* Encode a double (checked by caller) from stack top.  Stack top may be\n * replaced by serialized string but is not popped (caller does that).\n */\nDUK_LOCAL void duk__enc_double(duk_json_enc_ctx *js_ctx) {\n\tduk_hthread *thr;\n\tduk_tval *tv;\n\tduk_double_t d;\n\tduk_small_int_t c;\n\tduk_small_int_t s;\n\tduk_small_uint_t stridx;\n\tduk_small_uint_t n2s_flags;\n\tduk_hstring *h_str;\n\n\tDUK_ASSERT(js_ctx != NULL);\n\tthr = js_ctx->thr;\n\tDUK_ASSERT(thr != NULL);\n\n\t/* Caller must ensure 'tv' is indeed a double and not a fastint! */\n\ttv = DUK_GET_TVAL_NEGIDX(thr, -1);\n\tDUK_ASSERT(DUK_TVAL_IS_DOUBLE(tv));\n\td = DUK_TVAL_GET_DOUBLE(tv);\n\n\tc = (duk_small_int_t) DUK_FPCLASSIFY(d);\n\ts = (duk_small_int_t) DUK_SIGNBIT(d);\n\tDUK_UNREF(s);\n\n\tif (DUK_LIKELY(!(c == DUK_FP_INFINITE || c == DUK_FP_NAN))) {\n\t\tDUK_ASSERT(DUK_ISFINITE(d));\n\n#if defined(DUK_USE_JX) || defined(DUK_USE_JC)\n\t\t/* Negative zero needs special handling in JX/JC because\n\t\t * it would otherwise serialize to '0', not '-0'.\n\t\t */\n\t\tif (DUK_UNLIKELY(c == DUK_FP_ZERO && s != 0 &&\n\t\t                 (js_ctx->flag_ext_custom_or_compatible))) {\n\t\t\tduk_push_hstring_stridx(thr, DUK_STRIDX_MINUS_ZERO);  /* '-0' */\n\t\t} else\n#endif  /* DUK_USE_JX || DUK_USE_JC */\n\t\t{\n\t\t\tn2s_flags = 0;\n\t\t\t/* [ ... number ] -> [ ... string ] */\n\t\t\tduk_numconv_stringify(thr, 10 /*radix*/, 0 /*digits*/, n2s_flags);\n\t\t}\n\t\th_str = duk_known_hstring(thr, -1);\n\t\tDUK__EMIT_HSTR(js_ctx, h_str);\n\t\treturn;\n\t}\n\n#if defined(DUK_USE_JX) || defined(DUK_USE_JC)\n\tif (!(js_ctx->flags & (DUK_JSON_FLAG_EXT_CUSTOM |\n\t                       DUK_JSON_FLAG_EXT_COMPATIBLE))) {\n\t\tstridx = DUK_STRIDX_LC_NULL;\n\t} else if (c == DUK_FP_NAN) {\n\t\tstridx = js_ctx->stridx_custom_nan;\n\t} else if (s == 0) {\n\t\tstridx = js_ctx->stridx_custom_posinf;\n\t} else {\n\t\tstridx = js_ctx->stridx_custom_neginf;\n\t}\n#else\n\tstridx = DUK_STRIDX_LC_NULL;\n#endif\n\tDUK__EMIT_STRIDX(js_ctx, stridx);\n}\n\n#if defined(DUK_USE_FASTINT)\n/* Encode a fastint from duk_tval ptr, no value stack effects. */\nDUK_LOCAL void duk__enc_fastint_tval(duk_json_enc_ctx *js_ctx, duk_tval *tv) {\n\tduk_int64_t v;\n\n\t/* Fastint range is signed 48-bit so longest value is -2^47 = -140737488355328\n\t * (16 chars long), longest signed 64-bit value is -2^63 = -9223372036854775808\n\t * (20 chars long).  Alloc space for 64-bit range to be safe.\n\t */\n\tduk_uint8_t buf[20 + 1];\n\n\t/* Caller must ensure 'tv' is indeed a fastint! */\n\tDUK_ASSERT(DUK_TVAL_IS_FASTINT(tv));\n\tv = DUK_TVAL_GET_FASTINT(tv);\n\n\t/* XXX: There are no format strings in duk_config.h yet, could add\n\t * one for formatting duk_int64_t.  For now, assumes \"%lld\" and that\n\t * \"long long\" type exists.  Could also rely on C99 directly but that\n\t * won't work for older MSVC.\n\t */\n\tDUK_SPRINTF((char *) buf, \"%lld\", (long long) v);\n\tDUK__EMIT_CSTR(js_ctx, (const char *) buf);\n}\n#endif\n\n#if defined(DUK_USE_JX) || defined(DUK_USE_JC)\n#if defined(DUK_USE_HEX_FASTPATH)\nDUK_LOCAL duk_uint8_t *duk__enc_buffer_data_hex(const duk_uint8_t *src, duk_size_t src_len, duk_uint8_t *dst) {\n\tduk_uint8_t *q;\n\tduk_uint16_t *q16;\n\tduk_small_uint_t x;\n\tduk_size_t i, len_safe;\n#if !defined(DUK_USE_UNALIGNED_ACCESSES_POSSIBLE)\n\tduk_bool_t shift_dst;\n#endif\n\n\t/* Unlike in duk_hex_encode() 'dst' is not necessarily aligned by 2.\n\t * For platforms where unaligned accesses are not allowed, shift 'dst'\n\t * ahead by 1 byte to get alignment and then DUK_MEMMOVE() the result\n\t * in place.  The faster encoding loop makes up the difference.\n\t * There's always space for one extra byte because a terminator always\n\t * follows the hex data and that's been accounted for by the caller.\n\t */\n\n#if defined(DUK_USE_UNALIGNED_ACCESSES_POSSIBLE)\n\tq16 = (duk_uint16_t *) (void *) dst;\n#else\n\tshift_dst = (duk_bool_t) (((duk_size_t) dst) & 0x01U);\n\tif (shift_dst) {\n\t\tDUK_DD(DUK_DDPRINT(\"unaligned accesses not possible, dst not aligned -> step to dst + 1\"));\n\t\tq16 = (duk_uint16_t *) (void *) (dst + 1);\n\t} else {\n\t\tDUK_DD(DUK_DDPRINT(\"unaligned accesses not possible, dst is aligned\"));\n\t\tq16 = (duk_uint16_t *) (void *) dst;\n\t}\n\tDUK_ASSERT((((duk_size_t) q16) & 0x01U) == 0);\n#endif\n\n\tlen_safe = src_len & ~0x03U;\n\tfor (i = 0; i < len_safe; i += 4) {\n\t\tq16[0] = duk_hex_enctab[src[i]];\n\t\tq16[1] = duk_hex_enctab[src[i + 1]];\n\t\tq16[2] = duk_hex_enctab[src[i + 2]];\n\t\tq16[3] = duk_hex_enctab[src[i + 3]];\n\t\tq16 += 4;\n\t}\n\tq = (duk_uint8_t *) q16;\n\n#if !defined(DUK_USE_UNALIGNED_ACCESSES_POSSIBLE)\n\tif (shift_dst) {\n\t\tq--;\n\t\tDUK_MEMMOVE((void *) dst, (const void *) (dst + 1), 2 * len_safe);\n\t\tDUK_ASSERT(dst + 2 * len_safe == q);\n\t}\n#endif\n\n\tfor (; i < src_len; i++) {\n\t\tx = src[i];\n\t\t*q++ = duk_lc_digits[x >> 4];\n\t\t*q++ = duk_lc_digits[x & 0x0f];\n\t}\n\n\treturn q;\n}\n#else  /* DUK_USE_HEX_FASTPATH */\nDUK_LOCAL duk_uint8_t *duk__enc_buffer_data_hex(const duk_uint8_t *src, duk_size_t src_len, duk_uint8_t *dst) {\n\tconst duk_uint8_t *p;\n\tconst duk_uint8_t *p_end;\n\tduk_uint8_t *q;\n\tduk_small_uint_t x;\n\n\tp = src;\n\tp_end = src + src_len;\n\tq = dst;\n\twhile (p != p_end) {\n\t\tx = *p++;\n\t\t*q++ = duk_lc_digits[x >> 4];\n\t\t*q++ = duk_lc_digits[x & 0x0f];\n\t}\n\n\treturn q;\n}\n#endif  /* DUK_USE_HEX_FASTPATH */\n\nDUK_LOCAL void duk__enc_buffer_data(duk_json_enc_ctx *js_ctx, duk_uint8_t *buf_data, duk_size_t buf_len) {\n\tduk_hthread *thr;\n\tduk_uint8_t *q;\n\tduk_size_t space;\n\n\tthr = js_ctx->thr;\n\n\tDUK_ASSERT(js_ctx->flag_ext_custom || js_ctx->flag_ext_compatible);  /* caller checks */\n\tDUK_ASSERT(js_ctx->flag_ext_custom_or_compatible);\n\n\t/* Buffer values are encoded in (lowercase) hex to make the\n\t * binary data readable.  Base64 or similar would be more\n\t * compact but less readable, and the point of JX/JC\n\t * variants is to be as useful to a programmer as possible.\n\t */\n\n\t/* The #if defined() clutter here needs to handle the three\n\t * cases: (1) JX+JC, (2) JX only, (3) JC only.\n\t */\n\n\t/* Note: space must cater for both JX and JC. */\n\tspace = 9 + buf_len * 2 + 2;\n\tDUK_ASSERT(DUK_HBUFFER_MAX_BYTELEN <= 0x7ffffffeUL);\n\tDUK_ASSERT((space - 2) / 2 >= buf_len);  /* overflow not possible, buffer limits */\n\tq = DUK_BW_ENSURE_GETPTR(thr, &js_ctx->bw, space);\n\n#if defined(DUK_USE_JX) && defined(DUK_USE_JC)\n\tif (js_ctx->flag_ext_custom)\n#endif\n#if defined(DUK_USE_JX)\n\t{\n\t\t*q++ = DUK_ASC_PIPE;\n\t\tq = duk__enc_buffer_data_hex(buf_data, buf_len, q);\n\t\t*q++ = DUK_ASC_PIPE;\n\n\t}\n#endif\n#if defined(DUK_USE_JX) && defined(DUK_USE_JC)\n\telse\n#endif\n#if defined(DUK_USE_JC)\n\t{\n\t\tDUK_ASSERT(js_ctx->flag_ext_compatible);\n\t\tDUK_MEMCPY((void *) q, (const void *) \"{\\\"_buf\\\":\\\"\", 9);  /* len: 9 */\n\t\tq += 9;\n\t\tq = duk__enc_buffer_data_hex(buf_data, buf_len, q);\n\t\t*q++ = DUK_ASC_DOUBLEQUOTE;\n\t\t*q++ = DUK_ASC_RCURLY;\n\t}\n#endif\n\n\tDUK_BW_SET_PTR(thr, &js_ctx->bw, q);\n}\n\nDUK_LOCAL void duk__enc_buffer_jx_jc(duk_json_enc_ctx *js_ctx, duk_hbuffer *h) {\n\tduk__enc_buffer_data(js_ctx,\n\t                     (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(js_ctx->thr->heap, h),\n\t                     (duk_size_t) DUK_HBUFFER_GET_SIZE(h));\n}\n#endif  /* DUK_USE_JX || DUK_USE_JC */\n\n#if defined(DUK_USE_JSON_STRINGIFY_FASTPATH)\nDUK_LOCAL void duk__enc_buffer_json_fastpath(duk_json_enc_ctx *js_ctx, duk_hbuffer *h) {\n\tduk_size_t i, n;\n\tconst duk_uint8_t *buf;\n\tduk_uint8_t *q;\n\n\tn = DUK_HBUFFER_GET_SIZE(h);\n\tif (n == 0) {\n\t\tDUK__EMIT_2(js_ctx, DUK_ASC_LCURLY, DUK_ASC_RCURLY);\n\t\treturn;\n\t}\n\n\tDUK__EMIT_1(js_ctx, DUK_ASC_LCURLY);\n\n\t/* Maximum encoded length with 32-bit index: 1 + 10 + 2 + 3 + 1 + 1 = 18,\n\t * with 64-bit index: 1 + 20 + 2 + 3 + 1 + 1 = 28.  32 has some slack.\n\t *\n\t * Note that because the output buffer is reallocated from time to time,\n\t * side effects (such as finalizers) affecting the buffer 'h' must be\n\t * disabled.  This is the case in the JSON.stringify() fast path.\n\t */\n\n\tbuf = (const duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(js_ctx->thr->heap, h);\n\tif (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {\n\t\tfor (i = 0; i < n; i++) {\n\t\t\tduk__enc_newline_indent(js_ctx, js_ctx->recursion_depth + 1);\n\t\t\tq = DUK_BW_ENSURE_GETPTR(js_ctx->thr, &js_ctx->bw, 32);\n\t\t\tq += DUK_SPRINTF((char *) q, \"\\\"%lu\\\": %u,\", (unsigned long) i, (unsigned int) buf[i]);\n\t\t\tDUK_BW_SET_PTR(js_ctx->thr, &js_ctx->bw, q);\n\t\t}\n\t} else {\n\t\tq = DUK_BW_GET_PTR(js_ctx->thr, &js_ctx->bw);\n\t\tfor (i = 0; i < n; i++) {\n\t\t\tq = DUK_BW_ENSURE_RAW(js_ctx->thr, &js_ctx->bw, 32, q);\n\t\t\tq += DUK_SPRINTF((char *) q, \"\\\"%lu\\\":%u,\", (unsigned long) i, (unsigned int) buf[i]);\n\t\t}\n\t\tDUK_BW_SET_PTR(js_ctx->thr, &js_ctx->bw, q);\n\t}\n\tDUK__UNEMIT_1(js_ctx);  /* eat trailing comma */\n\n\tif (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {\n\t\tduk__enc_newline_indent(js_ctx, js_ctx->recursion_depth);\n\t}\n\tDUK__EMIT_1(js_ctx, DUK_ASC_RCURLY);\n}\n#endif  /* DUK_USE_JSON_STRINGIFY_FASTPATH */\n\n#if defined(DUK_USE_JX) || defined(DUK_USE_JC)\nDUK_LOCAL void duk__enc_pointer(duk_json_enc_ctx *js_ctx, void *ptr) {\n\tchar buf[64];  /* XXX: how to figure correct size? */\n\tconst char *fmt;\n\n\tDUK_ASSERT(js_ctx->flag_ext_custom || js_ctx->flag_ext_compatible);  /* caller checks */\n\tDUK_ASSERT(js_ctx->flag_ext_custom_or_compatible);\n\n\tDUK_MEMZERO(buf, sizeof(buf));\n\n\t/* The #if defined() clutter here needs to handle the three\n\t * cases: (1) JX+JC, (2) JX only, (3) JC only.\n\t */\n#if defined(DUK_USE_JX) && defined(DUK_USE_JC)\n\tif (js_ctx->flag_ext_custom)\n#endif\n#if defined(DUK_USE_JX)\n\t{\n\t\tfmt = ptr ? \"(%p)\" : \"(null)\";\n\t}\n#endif\n#if defined(DUK_USE_JX) && defined(DUK_USE_JC)\n\telse\n#endif\n#if defined(DUK_USE_JC)\n\t{\n\t\tDUK_ASSERT(js_ctx->flag_ext_compatible);\n\t\tfmt = ptr ? \"{\\\"_ptr\\\":\\\"%p\\\"}\" : \"{\\\"_ptr\\\":\\\"null\\\"}\";\n\t}\n#endif\n\n\t/* When ptr == NULL, the format argument is unused. */\n\tDUK_SNPRINTF(buf, sizeof(buf) - 1, fmt, ptr);  /* must not truncate */\n\tDUK__EMIT_CSTR(js_ctx, buf);\n}\n#endif  /* DUK_USE_JX || DUK_USE_JC */\n\n#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)\n#if defined(DUK_USE_JX) || defined(DUK_USE_JC)\nDUK_LOCAL void duk__enc_bufobj(duk_json_enc_ctx *js_ctx, duk_hbufobj *h_bufobj) {\n\tDUK_ASSERT_HBUFOBJ_VALID(h_bufobj);\n\n\tif (h_bufobj->buf == NULL || !DUK_HBUFOBJ_VALID_SLICE(h_bufobj)) {\n\t\tDUK__EMIT_STRIDX(js_ctx, DUK_STRIDX_LC_NULL);\n\t} else {\n\t\t/* Handle both full and partial slice (as long as covered). */\n\t\tduk__enc_buffer_data(js_ctx,\n\t\t                     (duk_uint8_t *) DUK_HBUFOBJ_GET_SLICE_BASE(js_ctx->thr->heap, h_bufobj),\n\t\t                     (duk_size_t) h_bufobj->length);\n\t}\n}\n#endif  /* DUK_USE_JX || DUK_USE_JC */\n#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */\n\n/* Indent helper.  Calling code relies on js_ctx->recursion_depth also being\n * directly related to indent depth.\n */\n#if defined(DUK_USE_PREFER_SIZE)\nDUK_LOCAL void duk__enc_newline_indent(duk_json_enc_ctx *js_ctx, duk_uint_t depth) {\n\tDUK_ASSERT(js_ctx->h_gap != NULL);\n\tDUK_ASSERT(DUK_HSTRING_GET_BYTELEN(js_ctx->h_gap) > 0);  /* caller guarantees */\n\n\tDUK__EMIT_1(js_ctx, 0x0a);\n\twhile (depth-- > 0) {\n\t\tDUK__EMIT_HSTR(js_ctx, js_ctx->h_gap);\n\t}\n}\n#else  /* DUK_USE_PREFER_SIZE */\nDUK_LOCAL void duk__enc_newline_indent(duk_json_enc_ctx *js_ctx, duk_uint_t depth) {\n\tconst duk_uint8_t *gap_data;\n\tduk_size_t gap_len;\n\tduk_size_t avail_bytes;   /* bytes of indent available for copying */\n\tduk_size_t need_bytes;    /* bytes of indent still needed */\n\tduk_uint8_t *p_start;\n\tduk_uint8_t *p;\n\n\tDUK_ASSERT(js_ctx->h_gap != NULL);\n\tDUK_ASSERT(DUK_HSTRING_GET_BYTELEN(js_ctx->h_gap) > 0);  /* caller guarantees */\n\n\tDUK__EMIT_1(js_ctx, 0x0a);\n\tif (DUK_UNLIKELY(depth == 0)) {\n\t\treturn;\n\t}\n\n\t/* To handle deeper indents efficiently, make use of copies we've\n\t * already emitted.  In effect we can emit a sequence of 1, 2, 4,\n\t * 8, etc copies, and then finish the last run.  Byte counters\n\t * avoid multiply with gap_len on every loop.\n\t */\n\n\tgap_data = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(js_ctx->h_gap);\n\tgap_len = (duk_size_t) DUK_HSTRING_GET_BYTELEN(js_ctx->h_gap);\n\tDUK_ASSERT(gap_len > 0);\n\n\tneed_bytes = gap_len * depth;\n\tp = DUK_BW_ENSURE_GETPTR(js_ctx->thr, &js_ctx->bw, need_bytes);\n\tp_start = p;\n\n\tDUK_MEMCPY((void *) p, (const void *) gap_data, (size_t) gap_len);\n\tp += gap_len;\n\tavail_bytes = gap_len;\n\tDUK_ASSERT(need_bytes >= gap_len);\n\tneed_bytes -= gap_len;\n\n\twhile (need_bytes >= avail_bytes) {\n\t\tDUK_MEMCPY((void *) p, (const void *) p_start, (size_t) avail_bytes);\n\t\tp += avail_bytes;\n\t\tneed_bytes -= avail_bytes;\n\t\tavail_bytes <<= 1;\n\t}\n\n\tDUK_ASSERT(need_bytes < avail_bytes);  /* need_bytes may be zero */\n\tDUK_MEMCPY((void *) p, (const void *) p_start, (size_t) need_bytes);\n\tp += need_bytes;\n\t/*avail_bytes += need_bytes*/\n\n\tDUK_BW_SET_PTR(js_ctx->thr, &js_ctx->bw, p);\n}\n#endif  /* DUK_USE_PREFER_SIZE */\n\n/* Shared entry handling for object/array serialization. */\nDUK_LOCAL void duk__enc_objarr_entry(duk_json_enc_ctx *js_ctx, duk_idx_t *entry_top) {\n\tduk_hthread *thr = js_ctx->thr;\n\tduk_hobject *h_target;\n\tduk_uint_fast32_t i, n;\n\n\t*entry_top = duk_get_top(thr);\n\n\tduk_require_stack(thr, DUK_JSON_ENC_REQSTACK);\n\n\t/* Loop check using a hybrid approach: a fixed-size visited[] array\n\t * with overflow in a loop check object.\n\t */\n\n\th_target = duk_known_hobject(thr, -1);  /* object or array */\n\n\tn = js_ctx->recursion_depth;\n\tif (DUK_UNLIKELY(n > DUK_JSON_ENC_LOOPARRAY)) {\n\t\tn = DUK_JSON_ENC_LOOPARRAY;\n\t}\n\tfor (i = 0; i < n; i++) {\n\t\tif (DUK_UNLIKELY(js_ctx->visiting[i] == h_target)) {\n\t\t\tDUK_DD(DUK_DDPRINT(\"slow path loop detect\"));\n\t\t\tDUK_ERROR_TYPE(thr, DUK_STR_CYCLIC_INPUT);\n\t\t}\n\t}\n\tif (js_ctx->recursion_depth < DUK_JSON_ENC_LOOPARRAY) {\n\t\tjs_ctx->visiting[js_ctx->recursion_depth] = h_target;\n\t} else {\n\t\tduk_push_sprintf(thr, DUK_STR_FMT_PTR, (void *) h_target);\n\t\tduk_dup_top(thr);  /* -> [ ... voidp voidp ] */\n\t\tif (duk_has_prop(thr, js_ctx->idx_loop)) {\n\t\t\tDUK_ERROR_TYPE(thr, DUK_STR_CYCLIC_INPUT);\n\t\t}\n\t\tduk_push_true(thr);  /* -> [ ... voidp true ] */\n\t\tduk_put_prop(thr, js_ctx->idx_loop);  /* -> [ ... ] */\n\t}\n\n\t/* C recursion check. */\n\n\tDUK_ASSERT_DISABLE(js_ctx->recursion_depth >= 0);  /* unsigned */\n\tDUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);\n\tif (js_ctx->recursion_depth >= js_ctx->recursion_limit) {\n\t\tDUK_ERROR_RANGE(thr, DUK_STR_JSONENC_RECLIMIT);\n\t}\n\tjs_ctx->recursion_depth++;\n\n\tDUK_DDD(DUK_DDDPRINT(\"shared entry finished: top=%ld, loop=%!T\",\n\t                     (long) duk_get_top(thr), (duk_tval *) duk_get_tval(thr, js_ctx->idx_loop)));\n}\n\n/* Shared exit handling for object/array serialization. */\nDUK_LOCAL void duk__enc_objarr_exit(duk_json_enc_ctx *js_ctx, duk_idx_t *entry_top) {\n\tduk_hthread *thr = js_ctx->thr;\n\tduk_hobject *h_target;\n\n\t/* C recursion check. */\n\n\tDUK_ASSERT(js_ctx->recursion_depth > 0);\n\tDUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);\n\tjs_ctx->recursion_depth--;\n\n\t/* Loop check. */\n\n\th_target = duk_known_hobject(thr, *entry_top - 1);  /* original target at entry_top - 1 */\n\n\tif (js_ctx->recursion_depth < DUK_JSON_ENC_LOOPARRAY) {\n\t\t/* Previous entry was inside visited[], nothing to do. */\n\t} else {\n\t\tduk_push_sprintf(thr, DUK_STR_FMT_PTR, (void *) h_target);\n\t\tduk_del_prop(thr, js_ctx->idx_loop);  /* -> [ ... ] */\n\t}\n\n\t/* Restore stack top after unbalanced code paths. */\n\tduk_set_top(thr, *entry_top);\n\n\tDUK_DDD(DUK_DDDPRINT(\"shared entry finished: top=%ld, loop=%!T\",\n\t                     (long) duk_get_top(thr), (duk_tval *) duk_get_tval(thr, js_ctx->idx_loop)));\n}\n\n/* The JO(value) operation: encode object.\n *\n * Stack policy: [ object ] -> [ object ].\n */\nDUK_LOCAL void duk__enc_object(duk_json_enc_ctx *js_ctx) {\n\tduk_hthread *thr = js_ctx->thr;\n\tduk_hstring *h_key;\n\tduk_idx_t entry_top;\n\tduk_idx_t idx_obj;\n\tduk_idx_t idx_keys;\n\tduk_bool_t emitted;\n\tduk_uarridx_t arr_len, i;\n\tduk_size_t prev_size;\n\n\tDUK_DDD(DUK_DDDPRINT(\"duk__enc_object: obj=%!T\", (duk_tval *) duk_get_tval(thr, -1)));\n\n\tduk__enc_objarr_entry(js_ctx, &entry_top);\n\n\tidx_obj = entry_top - 1;\n\n\tif (js_ctx->idx_proplist >= 0) {\n\t\tidx_keys = js_ctx->idx_proplist;\n\t} else {\n\t\t/* XXX: would be nice to enumerate an object at specified index */\n\t\tduk_dup(thr, idx_obj);\n\t\t(void) duk_hobject_get_enumerated_keys(thr, DUK_ENUM_OWN_PROPERTIES_ONLY /*flags*/);  /* [ ... target ] -> [ ... target keys ] */\n\t\tidx_keys = duk_require_normalize_index(thr, -1);\n\t\t/* leave stack unbalanced on purpose */\n\t}\n\n\tDUK_DDD(DUK_DDDPRINT(\"idx_keys=%ld, h_keys=%!T\",\n\t                     (long) idx_keys, (duk_tval *) duk_get_tval(thr, idx_keys)));\n\n\t/* Steps 8-10 have been merged to avoid a \"partial\" variable. */\n\n\tDUK__EMIT_1(js_ctx, DUK_ASC_LCURLY);\n\n\t/* XXX: keys is an internal object with all keys to be processed\n\t * in its (gapless) array part.  Because nobody can touch the keys\n\t * object, we could iterate its array part directly (keeping in mind\n\t * that it can be reallocated).\n\t */\n\n\tarr_len = (duk_uarridx_t) duk_get_length(thr, idx_keys);\n\temitted = 0;\n\tfor (i = 0; i < arr_len; i++) {\n\t\tduk_get_prop_index(thr, idx_keys, i);  /* -> [ ... key ] */\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"object property loop: holder=%!T, key=%!T\",\n\t\t                     (duk_tval *) duk_get_tval(thr, idx_obj),\n\t\t                     (duk_tval *) duk_get_tval(thr, -1)));\n\n\t\th_key = duk_known_hstring(thr, -1);\n\t\tDUK_ASSERT(h_key != NULL);\n\t\tDUK_ASSERT(!DUK_HSTRING_HAS_SYMBOL(h_key));  /* proplist filtering; enum options */\n\n\t\tprev_size = DUK_BW_GET_SIZE(js_ctx->thr, &js_ctx->bw);\n\t\tif (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {\n\t\t\tduk__enc_newline_indent(js_ctx, js_ctx->recursion_depth);\n\t\t\tduk__enc_key_autoquote(js_ctx, h_key);\n\t\t\tDUK__EMIT_2(js_ctx, DUK_ASC_COLON, DUK_ASC_SPACE);\n\t\t} else {\n\t\t\tduk__enc_key_autoquote(js_ctx, h_key);\n\t\t\tDUK__EMIT_1(js_ctx, DUK_ASC_COLON);\n\t\t}\n\n\t\t/* [ ... key ] */\n\n\t\tif (DUK_UNLIKELY(duk__enc_value(js_ctx, idx_obj) == 0)) {\n\t\t\t/* Value would yield 'undefined', so skip key altogether.\n\t\t\t * Side effects have already happened.\n\t\t\t */\n\t\t\tDUK_BW_SET_SIZE(js_ctx->thr, &js_ctx->bw, prev_size);\n\t\t} else {\n\t\t\tDUK__EMIT_1(js_ctx, DUK_ASC_COMMA);\n\t\t\temitted = 1;\n\t\t}\n\n\t\t/* [ ... ] */\n\t}\n\n\tif (emitted) {\n\t\tDUK_ASSERT(*((duk_uint8_t *) DUK_BW_GET_PTR(js_ctx->thr, &js_ctx->bw) - 1) == DUK_ASC_COMMA);\n\t\tDUK__UNEMIT_1(js_ctx);  /* eat trailing comma */\n\t\tif (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {\n\t\t\tDUK_ASSERT(js_ctx->recursion_depth >= 1);\n\t\t\tduk__enc_newline_indent(js_ctx, js_ctx->recursion_depth - 1U);\n\t\t}\n\t}\n\tDUK__EMIT_1(js_ctx, DUK_ASC_RCURLY);\n\n\tduk__enc_objarr_exit(js_ctx, &entry_top);\n\n\tDUK_ASSERT_TOP(thr, entry_top);\n}\n\n/* The JA(value) operation: encode array.\n *\n * Stack policy: [ array ] -> [ array ].\n */\nDUK_LOCAL void duk__enc_array(duk_json_enc_ctx *js_ctx) {\n\tduk_hthread *thr = js_ctx->thr;\n\tduk_idx_t entry_top;\n\tduk_idx_t idx_arr;\n\tduk_bool_t emitted;\n\tduk_uarridx_t i, arr_len;\n\n\tDUK_DDD(DUK_DDDPRINT(\"duk__enc_array: array=%!T\",\n\t                     (duk_tval *) duk_get_tval(thr, -1)));\n\n\tduk__enc_objarr_entry(js_ctx, &entry_top);\n\n\tidx_arr = entry_top - 1;\n\n\t/* Steps 8-10 have been merged to avoid a \"partial\" variable. */\n\n\tDUK__EMIT_1(js_ctx, DUK_ASC_LBRACKET);\n\n\tarr_len = (duk_uarridx_t) duk_get_length(thr, idx_arr);\n\temitted = 0;\n\tfor (i = 0; i < arr_len; i++) {\n\t\tDUK_DDD(DUK_DDDPRINT(\"array entry loop: array=%!T, index=%ld, arr_len=%ld\",\n\t\t                     (duk_tval *) duk_get_tval(thr, idx_arr),\n\t\t                     (long) i, (long) arr_len));\n\n\t\tif (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {\n\t\t\tDUK_ASSERT(js_ctx->recursion_depth >= 1);\n\t\t\tduk__enc_newline_indent(js_ctx, js_ctx->recursion_depth);\n\t\t}\n\n\t\t(void) duk_push_uint_to_hstring(thr, (duk_uint_t) i);  /* -> [ ... key ] */\n\n\t\t/* [ ... key ] */\n\n\t\tif (DUK_UNLIKELY(duk__enc_value(js_ctx, idx_arr) == 0)) {\n\t\t\t/* Value would normally be omitted, replace with 'null'. */\n\t\t\tDUK__EMIT_STRIDX(js_ctx, DUK_STRIDX_LC_NULL);\n\t\t} else {\n\t\t\t;\n\t\t}\n\n\t\t/* [ ... ] */\n\n\t\tDUK__EMIT_1(js_ctx, DUK_ASC_COMMA);\n\t\temitted = 1;\n\t}\n\n\tif (emitted) {\n\t\tDUK_ASSERT(*((duk_uint8_t *) DUK_BW_GET_PTR(js_ctx->thr, &js_ctx->bw) - 1) == DUK_ASC_COMMA);\n\t\tDUK__UNEMIT_1(js_ctx);  /* eat trailing comma */\n\t\tif (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {\n\t\t\tDUK_ASSERT(js_ctx->recursion_depth >= 1);\n\t\t\tduk__enc_newline_indent(js_ctx, js_ctx->recursion_depth - 1U);\n\t\t}\n\t}\n\tDUK__EMIT_1(js_ctx, DUK_ASC_RBRACKET);\n\n\tduk__enc_objarr_exit(js_ctx, &entry_top);\n\n\tDUK_ASSERT_TOP(thr, entry_top);\n}\n\n/* The Str(key, holder) operation.\n *\n * Stack policy: [ ... key ] -> [ ... ]\n */\nDUK_LOCAL duk_bool_t duk__enc_value(duk_json_enc_ctx *js_ctx, duk_idx_t idx_holder) {\n\tduk_hthread *thr = js_ctx->thr;\n\tduk_tval *tv;\n\tduk_tval *tv_holder;\n\tduk_tval *tv_key;\n\tduk_small_int_t c;\n\n\tDUK_DDD(DUK_DDDPRINT(\"duk__enc_value: idx_holder=%ld, holder=%!T, key=%!T\",\n\t                     (long) idx_holder, (duk_tval *) duk_get_tval(thr, idx_holder),\n\t                     (duk_tval *) duk_get_tval(thr, -1)));\n\n\ttv_holder = DUK_GET_TVAL_POSIDX(thr, idx_holder);\n\tDUK_ASSERT(DUK_TVAL_IS_OBJECT(tv_holder));\n\ttv_key = DUK_GET_TVAL_NEGIDX(thr, -1);\n\tDUK_ASSERT(DUK_TVAL_IS_STRING(tv_key));\n\tDUK_ASSERT(!DUK_HSTRING_HAS_SYMBOL(DUK_TVAL_GET_STRING(tv_key)));  /* Caller responsible. */\n\t(void) duk_hobject_getprop(thr, tv_holder, tv_key);\n\n\t/* -> [ ... key val ] */\n\n\tDUK_DDD(DUK_DDDPRINT(\"value=%!T\", (duk_tval *) duk_get_tval(thr, -1)));\n\n\t/* Standard JSON checks for .toJSON() only for actual objects; for\n\t * example, setting Number.prototype.toJSON and then serializing a\n\t * number won't invoke the .toJSON() method.  However, lightfuncs and\n\t * plain buffers mimic objects so we check for their .toJSON() method.\n\t */\n\tif (duk_check_type_mask(thr, -1, DUK_TYPE_MASK_OBJECT |\n\t                                 DUK_TYPE_MASK_LIGHTFUNC |\n\t                                 DUK_TYPE_MASK_BUFFER)) {\n\t\tduk_get_prop_stridx_short(thr, -1, DUK_STRIDX_TO_JSON);\n\t\tif (duk_is_callable(thr, -1)) {  /* toJSON() can also be a lightfunc */\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"value is object, has callable toJSON() -> call it\"));\n\t\t\t/* XXX: duk_dup_unvalidated(thr, -2) etc. */\n\t\t\tduk_dup_m2(thr);          /* -> [ ... key val toJSON val ] */\n\t\t\tduk_dup_m4(thr);          /* -> [ ... key val toJSON val key ] */\n\t\t\tduk_call_method(thr, 1);  /* -> [ ... key val val' ] */\n\t\t\tduk_remove_m2(thr);       /* -> [ ... key val' ] */\n\t\t} else {\n\t\t\tduk_pop(thr);             /* -> [ ... key val ] */\n\t\t}\n\t}\n\n\t/* [ ... key val ] */\n\n\tDUK_DDD(DUK_DDDPRINT(\"value=%!T\", (duk_tval *) duk_get_tval(thr, -1)));\n\n\tif (js_ctx->h_replacer) {\n\t\t/* XXX: Here a \"slice copy\" would be useful. */\n\t\tDUK_DDD(DUK_DDDPRINT(\"replacer is set, call replacer\"));\n\t\tduk_push_hobject(thr, js_ctx->h_replacer);  /* -> [ ... key val replacer ] */\n\t\tduk_dup(thr, idx_holder);                   /* -> [ ... key val replacer holder ] */\n\t\tduk_dup_m4(thr);                            /* -> [ ... key val replacer holder key ] */\n\t\tduk_dup_m4(thr);                            /* -> [ ... key val replacer holder key val ] */\n\t\tduk_call_method(thr, 2);                    /* -> [ ... key val val' ] */\n\t\tduk_remove_m2(thr);                         /* -> [ ... key val' ] */\n\t}\n\n\t/* [ ... key val ] */\n\n\tDUK_DDD(DUK_DDDPRINT(\"value=%!T\", (duk_tval *) duk_get_tval(thr, -1)));\n\n\ttv = DUK_GET_TVAL_NEGIDX(thr, -1);\n\tif (DUK_TVAL_IS_OBJECT(tv)) {\n\t\tduk_hobject *h;\n\n\t\th = DUK_TVAL_GET_OBJECT(tv);\n\t\tDUK_ASSERT(h != NULL);\n\n#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)\n#if defined(DUK_USE_JX) || defined(DUK_USE_JC)\n\t\tif (DUK_HOBJECT_IS_BUFOBJ(h) &&\n\t\t    js_ctx->flags & (DUK_JSON_FLAG_EXT_CUSTOM | DUK_JSON_FLAG_EXT_COMPATIBLE)) {\n\t\t\t/* With JX/JC a bufferobject gets serialized specially. */\n\t\t\tduk_hbufobj *h_bufobj;\n\t\t\th_bufobj = (duk_hbufobj *) h;\n\t\t\tDUK_ASSERT_HBUFOBJ_VALID(h_bufobj);\n\t\t\tduk__enc_bufobj(js_ctx, h_bufobj);\n\t\t\tgoto pop2_emitted;\n\t\t}\n\t\t/* Otherwise bufferobjects get serialized as normal objects. */\n#endif  /* JX || JC */\n#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */\n\t\tc = (duk_small_int_t) DUK_HOBJECT_GET_CLASS_NUMBER(h);\n\t\tswitch (c) {\n\t\tcase DUK_HOBJECT_CLASS_NUMBER: {\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"value is a Number object -> coerce with ToNumber()\"));\n\t\t\tduk_to_number_m1(thr);\n\t\t\t/* The coercion potentially invokes user .valueOf() and .toString()\n\t\t\t * but can't result in a function value because ToPrimitive() would\n\t\t\t * reject such a result: test-dev-json-stringify-coercion-1.js.\n\t\t\t */\n\t\t\tDUK_ASSERT(!duk_is_callable(thr, -1));\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_HOBJECT_CLASS_STRING: {\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"value is a String object -> coerce with ToString()\"));\n\t\t\tduk_to_string(thr, -1);\n\t\t\t/* Same coercion behavior as for Number. */\n\t\t\tDUK_ASSERT(!duk_is_callable(thr, -1));\n\t\t\tbreak;\n\t\t}\n#if defined(DUK_USE_JX) || defined(DUK_USE_JC)\n\t\tcase DUK_HOBJECT_CLASS_POINTER:\n#endif\n\t\tcase DUK_HOBJECT_CLASS_BOOLEAN: {\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"value is a Boolean/Buffer/Pointer object -> get internal value\"));\n\t\t\tduk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INT_VALUE);\n\t\t\tduk_remove_m2(thr);\n\t\t\tbreak;\n\t\t}\n\t\tdefault: {\n\t\t\t/* Normal object which doesn't get automatically coerced to a\n\t\t\t * primitive value.  Functions are checked for specially.  The\n\t\t\t * primitive value coercions for Number, String, Pointer, and\n\t\t\t * Boolean can't result in functions so suffices to check here.\n\t\t\t * Symbol objects are handled like plain objects (their primitive\n\t\t\t * value is NOT looked up like for e.g. String objects).\n\t\t\t */\n\t\t\tDUK_ASSERT(h != NULL);\n\t\t\tif (DUK_HOBJECT_IS_CALLABLE(h)) {\n#if defined(DUK_USE_JX) || defined(DUK_USE_JC)\n\t\t\t\tif (js_ctx->flags & (DUK_JSON_FLAG_EXT_CUSTOM |\n\t\t\t\t                     DUK_JSON_FLAG_EXT_COMPATIBLE)) {\n\t\t\t\t\t/* We only get here when doing non-standard JSON encoding */\n\t\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"-> function allowed, serialize to custom format\"));\n\t\t\t\t\tDUK_ASSERT(js_ctx->flag_ext_custom || js_ctx->flag_ext_compatible);\n\t\t\t\t\tDUK__EMIT_STRIDX(js_ctx, js_ctx->stridx_custom_function);\n\t\t\t\t\tgoto pop2_emitted;\n\t\t\t\t} else {\n\t\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"-> will result in undefined (function)\"));\n\t\t\t\t\tgoto pop2_undef;\n\t\t\t\t}\n#else  /* DUK_USE_JX || DUK_USE_JC */\n\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"-> will result in undefined (function)\"));\n\t\t\t\tgoto pop2_undef;\n#endif  /* DUK_USE_JX || DUK_USE_JC */\n\t\t\t}\n\t\t}\n\t\t}  /* end switch */\n\t}\n\n\t/* [ ... key val ] */\n\n\tDUK_DDD(DUK_DDDPRINT(\"value=%!T\", (duk_tval *) duk_get_tval(thr, -1)));\n\n\tif (duk_check_type_mask(thr, -1, js_ctx->mask_for_undefined)) {\n\t\t/* will result in undefined */\n\t\tDUK_DDD(DUK_DDDPRINT(\"-> will result in undefined (type mask check)\"));\n\t\tgoto pop2_undef;\n\t}\n\ttv = DUK_GET_TVAL_NEGIDX(thr, -1);\n\n\tswitch (DUK_TVAL_GET_TAG(tv)) {\n#if defined(DUK_USE_JX) || defined(DUK_USE_JC)\n\t/* When JX/JC not in use, the type mask above will avoid this case if needed. */\n\tcase DUK_TAG_UNDEFINED: {\n\t\tDUK__EMIT_STRIDX(js_ctx, js_ctx->stridx_custom_undefined);\n\t\tbreak;\n\t}\n#endif\n\tcase DUK_TAG_NULL: {\n\t\tDUK__EMIT_STRIDX(js_ctx, DUK_STRIDX_LC_NULL);\n\t\tbreak;\n\t}\n\tcase DUK_TAG_BOOLEAN: {\n\t\tDUK__EMIT_STRIDX(js_ctx, DUK_TVAL_GET_BOOLEAN(tv) ?\n\t\t                 DUK_STRIDX_TRUE : DUK_STRIDX_FALSE);\n\t\tbreak;\n\t}\n#if defined(DUK_USE_JX) || defined(DUK_USE_JC)\n\t/* When JX/JC not in use, the type mask above will avoid this case if needed. */\n\tcase DUK_TAG_POINTER: {\n\t\tduk__enc_pointer(js_ctx, DUK_TVAL_GET_POINTER(tv));\n\t\tbreak;\n\t}\n#endif  /* DUK_USE_JX || DUK_USE_JC */\n\tcase DUK_TAG_STRING: {\n\t\tduk_hstring *h = DUK_TVAL_GET_STRING(tv);\n\t\tDUK_ASSERT(h != NULL);\n\t\tif (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(h))) {\n\t\t\tgoto pop2_undef;\n\t\t}\n\t\tduk__enc_quote_string(js_ctx, h);\n\t\tbreak;\n\t}\n\tcase DUK_TAG_OBJECT: {\n\t\tduk_hobject *h = DUK_TVAL_GET_OBJECT(tv);\n\t\tDUK_ASSERT(h != NULL);\n\n\t\t/* Function values are handled completely above (including\n\t\t * coercion results):\n\t\t */\n\t\tDUK_ASSERT(!DUK_HOBJECT_IS_CALLABLE(h));\n\n\t\tif (DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_ARRAY) {\n\t\t\tduk__enc_array(js_ctx);\n\t\t} else {\n\t\t\tduk__enc_object(js_ctx);\n\t\t}\n\t\tbreak;\n\t}\n\t/* Because plain buffers mimics Uint8Array, they have enumerable\n\t * index properties [0,byteLength[.  Because JSON only serializes\n\t * enumerable own properties, no properties can be serialized for\n\t * plain buffers (all virtual properties are non-enumerable).  However,\n\t * there may be a .toJSON() method which was already handled above.\n\t */\n\tcase DUK_TAG_BUFFER: {\n#if defined(DUK_USE_JX) || defined(DUK_USE_JC)\n\t\tif (js_ctx->flag_ext_custom_or_compatible) {\n\t\t\tduk__enc_buffer_jx_jc(js_ctx, DUK_TVAL_GET_BUFFER(tv));\n\t\t\tbreak;\n\t\t}\n#endif\n\n\t\t/* Could implement a fastpath, but the fast path would need\n\t\t * to handle realloc side effects correctly.\n\t\t */\n\t\tduk_to_object(thr, -1);\n\t\tduk__enc_object(js_ctx);\n\t\tbreak;\n\t}\n\tcase DUK_TAG_LIGHTFUNC: {\n#if defined(DUK_USE_JX) || defined(DUK_USE_JC)\n\t\t/* We only get here when doing non-standard JSON encoding */\n\t\tDUK_ASSERT(js_ctx->flag_ext_custom || js_ctx->flag_ext_compatible);\n\t\tDUK__EMIT_STRIDX(js_ctx, js_ctx->stridx_custom_function);\n#else\n\t\t/* Standard JSON omits functions */\n\t\tDUK_UNREACHABLE();\n#endif\n\t\tbreak;\n\t}\n#if defined(DUK_USE_FASTINT)\n\tcase DUK_TAG_FASTINT:\n\t\t/* Number serialization has a significant impact relative to\n\t\t * other fast path code, so careful fast path for fastints.\n\t\t */\n\t\tduk__enc_fastint_tval(js_ctx, tv);\n\t\tbreak;\n#endif\n\tdefault: {\n\t\t/* number */\n\t\tDUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));\n\t\tDUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));\n\t\t/* XXX: A fast path for usual integers would be useful when\n\t\t * fastint support is not enabled.\n\t\t */\n\t\tduk__enc_double(js_ctx);\n\t\tbreak;\n\t}\n\t}\n\n#if defined(DUK_USE_JX) || defined(DUK_USE_JC)\n pop2_emitted:\n#endif\n\tduk_pop_2(thr); /* [ ... key val ] -> [ ... ] */\n\treturn 1;  /* emitted */\n\n pop2_undef:\n\tduk_pop_2(thr);  /* [ ... key val ] -> [ ... ] */\n\treturn 0;  /* not emitted */\n}\n\n/* E5 Section 15.12.3, main algorithm, step 4.b.ii steps 1-4. */\nDUK_LOCAL duk_bool_t duk__enc_allow_into_proplist(duk_tval *tv) {\n\tduk_small_int_t c;\n\n\t/* XXX: some kind of external internal type checker?\n\t * - type mask; symbol flag; class mask\n\t */\n\tDUK_ASSERT(tv != NULL);\n\tif (DUK_TVAL_IS_STRING(tv)) {\n\t\tduk_hstring *h;\n\t\th = DUK_TVAL_GET_STRING(tv);\n\t\tDUK_ASSERT(h != NULL);\n\t\tif (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(h))) {\n\t\t\treturn 0;\n\t\t}\n\t\treturn 1;\n\t} else if (DUK_TVAL_IS_NUMBER(tv)) {\n\t\treturn 1;\n\t} else if (DUK_TVAL_IS_OBJECT(tv)) {\n\t\tduk_hobject *h;\n\t\th = DUK_TVAL_GET_OBJECT(tv);\n\t\tDUK_ASSERT(h != NULL);\n\t\tc = (duk_small_int_t) DUK_HOBJECT_GET_CLASS_NUMBER(h);\n\t\tif (c == DUK_HOBJECT_CLASS_STRING || c == DUK_HOBJECT_CLASS_NUMBER) {\n\t\t\treturn 1;\n\t\t}\n\t}\n\n\treturn 0;\n}\n\n/*\n *  JSON.stringify() fast path\n *\n *  Otherwise supports full JSON, JX, and JC features, but bails out on any\n *  possible side effect which might change the value being serialized.  The\n *  fast path can take advantage of the fact that the value being serialized\n *  is unchanged so that we can walk directly through property tables etc.\n */\n\n#if defined(DUK_USE_JSON_STRINGIFY_FASTPATH)\nDUK_LOCAL duk_bool_t duk__json_stringify_fast_value(duk_json_enc_ctx *js_ctx, duk_tval *tv) {\n\tduk_uint_fast32_t i, n;\n\n\tDUK_DDD(DUK_DDDPRINT(\"stringify fast: %!T\", tv));\n\n\tDUK_ASSERT(js_ctx != NULL);\n\tDUK_ASSERT(js_ctx->thr != NULL);\n\n#if 0 /* disabled for now */\n restart_match:\n#endif\n\n\tDUK_ASSERT(tv != NULL);\n\n\tswitch (DUK_TVAL_GET_TAG(tv)) {\n\tcase DUK_TAG_UNDEFINED: {\n#if defined(DUK_USE_JX) || defined(DUK_USE_JC)\n\t\tif (js_ctx->flag_ext_custom || js_ctx->flag_ext_compatible) {\n\t\t\tDUK__EMIT_STRIDX(js_ctx, js_ctx->stridx_custom_undefined);\n\t\t\tbreak;\n\t\t} else {\n\t\t\tgoto emit_undefined;\n\t\t}\n#else\n\t\tgoto emit_undefined;\n#endif\n\t}\n\tcase DUK_TAG_NULL: {\n\t\tDUK__EMIT_STRIDX(js_ctx, DUK_STRIDX_LC_NULL);\n\t\tbreak;\n\t}\n\tcase DUK_TAG_BOOLEAN: {\n\t\tDUK__EMIT_STRIDX(js_ctx, DUK_TVAL_GET_BOOLEAN(tv) ?\n\t\t                 DUK_STRIDX_TRUE : DUK_STRIDX_FALSE);\n\t\tbreak;\n\t}\n\tcase DUK_TAG_STRING: {\n\t\tduk_hstring *h;\n\t\th = DUK_TVAL_GET_STRING(tv);\n\t\tDUK_ASSERT(h != NULL);\n\t\tif (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(h))) {\n\t\t\tgoto emit_undefined;\n\t\t}\n\t\tduk__enc_quote_string(js_ctx, h);\n\t\tbreak;\n\t}\n\tcase DUK_TAG_OBJECT: {\n\t\tduk_hobject *obj;\n\t\tduk_tval *tv_val;\n\t\tduk_bool_t emitted = 0;\n\t\tduk_uint32_t c_bit, c_all, c_array, c_unbox, c_undef,\n\t\t             c_func, c_bufobj, c_object, c_abort;\n\n\t\t/* For objects JSON.stringify() only looks for own, enumerable\n\t\t * properties which is nice for the fast path here.\n\t\t *\n\t\t * For arrays JSON.stringify() uses [[Get]] so it will actually\n\t\t * inherit properties during serialization!  This fast path\n\t\t * supports gappy arrays as long as there's no actual inherited\n\t\t * property (which might be a getter etc).\n\t\t *\n\t\t * Since recursion only happens for objects, we can have both\n\t\t * recursion and loop checks here.  We use a simple, depth-limited\n\t\t * loop check in the fast path because the object-based tracking\n\t\t * is very slow (when tested, it accounted for 50% of fast path\n\t\t * execution time for input data with a lot of small objects!).\n\t\t */\n\n\t\t/* XXX: for real world code, could just ignore array inheritance\n\t\t * and only look at array own properties.\n\t\t */\n\n\t\t/* We rely on a few object flag / class number relationships here,\n\t\t * assert for them.\n\t\t */\n\n\t\tobj = DUK_TVAL_GET_OBJECT(tv);\n\t\tDUK_ASSERT(obj != NULL);\n\t\tDUK_ASSERT_HOBJECT_VALID(obj);\n\n\t\t/* Once recursion depth is increased, exit path must decrease\n\t\t * it (though it's OK to abort the fast path).\n\t\t */\n\n\t\tDUK_ASSERT_DISABLE(js_ctx->recursion_depth >= 0);  /* unsigned */\n\t\tDUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);\n\t\tif (js_ctx->recursion_depth >= js_ctx->recursion_limit) {\n\t\t\tDUK_DD(DUK_DDPRINT(\"fast path recursion limit\"));\n\t\t\tDUK_ERROR_RANGE(js_ctx->thr, DUK_STR_JSONDEC_RECLIMIT);\n\t\t}\n\n\t\tfor (i = 0, n = (duk_uint_fast32_t) js_ctx->recursion_depth; i < n; i++) {\n\t\t\tif (DUK_UNLIKELY(js_ctx->visiting[i] == obj)) {\n\t\t\t\tDUK_DD(DUK_DDPRINT(\"fast path loop detect\"));\n\t\t\t\tDUK_ERROR_TYPE(js_ctx->thr, DUK_STR_CYCLIC_INPUT);\n\t\t\t}\n\t\t}\n\n\t\t/* Guaranteed by recursion_limit setup so we don't have to\n\t\t * check twice.\n\t\t */\n\t\tDUK_ASSERT(js_ctx->recursion_depth < DUK_JSON_ENC_LOOPARRAY);\n\t\tjs_ctx->visiting[js_ctx->recursion_depth] = obj;\n\t\tjs_ctx->recursion_depth++;\n\n\t\t/* If object has a .toJSON() property, we can't be certain\n\t\t * that it wouldn't mutate any value arbitrarily, so bail\n\t\t * out of the fast path.\n\t\t *\n\t\t * If an object is a Proxy we also can't avoid side effects\n\t\t * so abandon.\n\t\t */\n\t\t/* XXX: non-callable .toJSON() doesn't need to cause an abort\n\t\t * but does at the moment, probably not worth fixing.\n\t\t */\n\t\tif (duk_hobject_hasprop_raw(js_ctx->thr, obj, DUK_HTHREAD_STRING_TO_JSON(js_ctx->thr)) ||\n\t\t    DUK_HOBJECT_IS_PROXY(obj)) {\n\t\t\tDUK_DD(DUK_DDPRINT(\"object has a .toJSON property or object is a Proxy, abort fast path\"));\n\t\t\tgoto abort_fastpath;\n\t\t}\n\n\t\t/* We could use a switch-case for the class number but it turns out\n\t\t * a small if-else ladder on class masks is better.  The if-ladder\n\t\t * should be in order of relevancy.\n\t\t */\n\n\t\t/* XXX: move masks to js_ctx? they don't change during one\n\t\t * fast path invocation.\n\t\t */\n\t\tDUK_ASSERT(DUK_HOBJECT_CLASS_MAX <= 31);\n#if defined(DUK_USE_JX) || defined(DUK_USE_JC)\n\t\tif (js_ctx->flag_ext_custom_or_compatible) {\n\t\t\tc_all = DUK_HOBJECT_CMASK_ALL;\n\t\t\tc_array = DUK_HOBJECT_CMASK_ARRAY;\n\t\t\tc_unbox = DUK_HOBJECT_CMASK_NUMBER |\n\t\t\t          DUK_HOBJECT_CMASK_STRING |\n\t\t\t          DUK_HOBJECT_CMASK_BOOLEAN |\n\t\t\t          DUK_HOBJECT_CMASK_POINTER;  /* Symbols are not unboxed. */\n\t\t\tc_func = DUK_HOBJECT_CMASK_FUNCTION;\n\t\t\tc_bufobj = DUK_HOBJECT_CMASK_ALL_BUFOBJS;\n\t\t\tc_undef = 0;\n\t\t\tc_abort = 0;\n\t\t\tc_object = c_all & ~(c_array | c_unbox | c_func | c_bufobj | c_undef | c_abort);\n\t\t}\n\t\telse\n#endif\n\t\t{\n\t\t\tc_all = DUK_HOBJECT_CMASK_ALL;\n\t\t\tc_array = DUK_HOBJECT_CMASK_ARRAY;\n\t\t\tc_unbox = DUK_HOBJECT_CMASK_NUMBER |\n\t\t\t          DUK_HOBJECT_CMASK_STRING |\n\t\t\t          DUK_HOBJECT_CMASK_BOOLEAN;  /* Symbols are not unboxed. */\n\t\t\tc_func = 0;\n\t\t\tc_bufobj = 0;\n\t\t\tc_undef = DUK_HOBJECT_CMASK_FUNCTION |\n\t\t\t          DUK_HOBJECT_CMASK_POINTER;\n\t\t\t/* As the fast path doesn't currently properly support\n\t\t\t * duk_hbufobj virtual properties, abort fast path if\n\t\t\t * we encounter them in plain JSON mode.\n\t\t\t */\n\t\t\tc_abort = DUK_HOBJECT_CMASK_ALL_BUFOBJS;\n\t\t\tc_object = c_all & ~(c_array | c_unbox | c_func | c_bufobj | c_undef | c_abort);\n\t\t}\n\n\t\tc_bit = (duk_uint32_t) DUK_HOBJECT_GET_CLASS_MASK(obj);\n\t\tif (c_bit & c_object) {\n\t\t\t/* All other object types. */\n\t\t\tDUK__EMIT_1(js_ctx, DUK_ASC_LCURLY);\n\n\t\t\t/* A non-Array object should not have an array part in practice.\n\t\t\t * But since it is supported internally (and perhaps used at some\n\t\t\t * point), check and abandon if that's the case.\n\t\t\t */\n\t\t\tif (DUK_HOBJECT_HAS_ARRAY_PART(obj)) {\n\t\t\t\tDUK_DD(DUK_DDPRINT(\"non-Array object has array part, abort fast path\"));\n\t\t\t\tgoto abort_fastpath;\n\t\t\t}\n\n\t\t\tfor (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(obj); i++) {\n\t\t\t\tduk_hstring *k;\n\t\t\t\tduk_size_t prev_size;\n\n\t\t\t\tk = DUK_HOBJECT_E_GET_KEY(js_ctx->thr->heap, obj, i);\n\t\t\t\tif (!k) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (DUK_HSTRING_HAS_ARRIDX(k)) {\n\t\t\t\t\t/* If an object has array index keys we would need\n\t\t\t\t\t * to sort them into the ES2015 enumeration order to\n\t\t\t\t\t * be consistent with the slow path.  Abort the fast\n\t\t\t\t\t * path and handle in the slow path for now.\n\t\t\t\t\t */\n\t\t\t\t\tDUK_DD(DUK_DDPRINT(\"property key is an array index, abort fast path\"));\n\t\t\t\t\tgoto abort_fastpath;\n\t\t\t\t}\n\t\t\t\tif (!DUK_HOBJECT_E_SLOT_IS_ENUMERABLE(js_ctx->thr->heap, obj, i)) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (DUK_HOBJECT_E_SLOT_IS_ACCESSOR(js_ctx->thr->heap, obj, i)) {\n\t\t\t\t\t/* Getter might have arbitrary side effects,\n\t\t\t\t\t * so bail out.\n\t\t\t\t\t */\n\t\t\t\t\tDUK_DD(DUK_DDPRINT(\"property is an accessor, abort fast path\"));\n\t\t\t\t\tgoto abort_fastpath;\n\t\t\t\t}\n\t\t\t\tif (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(k))) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\ttv_val = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(js_ctx->thr->heap, obj, i);\n\n\t\t\t\tprev_size = DUK_BW_GET_SIZE(js_ctx->thr, &js_ctx->bw);\n\t\t\t\tif (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {\n\t\t\t\t\tduk__enc_newline_indent(js_ctx, js_ctx->recursion_depth);\n\t\t\t\t\tduk__enc_key_autoquote(js_ctx, k);\n\t\t\t\t\tDUK__EMIT_2(js_ctx, DUK_ASC_COLON, DUK_ASC_SPACE);\n\t\t\t\t} else {\n\t\t\t\t\tduk__enc_key_autoquote(js_ctx, k);\n\t\t\t\t\tDUK__EMIT_1(js_ctx, DUK_ASC_COLON);\n\t\t\t\t}\n\n\t\t\t\tif (duk__json_stringify_fast_value(js_ctx, tv_val) == 0) {\n\t\t\t\t\tDUK_DD(DUK_DDPRINT(\"prop value not supported, rewind key and colon\"));\n\t\t\t\t\tDUK_BW_SET_SIZE(js_ctx->thr, &js_ctx->bw, prev_size);\n\t\t\t\t} else {\n\t\t\t\t\tDUK__EMIT_1(js_ctx, DUK_ASC_COMMA);\n\t\t\t\t\temitted = 1;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/* If any non-Array value had enumerable virtual own\n\t\t\t * properties, they should be serialized here (actually,\n\t\t\t * before the explicit properties).  Standard types don't.\n\t\t\t */\n\n\t\t\tif (emitted) {\n\t\t\t\tDUK_ASSERT(*((duk_uint8_t *) DUK_BW_GET_PTR(js_ctx->thr, &js_ctx->bw) - 1) == DUK_ASC_COMMA);\n\t\t\t\tDUK__UNEMIT_1(js_ctx);  /* eat trailing comma */\n\t\t\t\tif (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {\n\t\t\t\t\tDUK_ASSERT(js_ctx->recursion_depth >= 1);\n\t\t\t\t\tduk__enc_newline_indent(js_ctx, js_ctx->recursion_depth - 1U);\n\t\t\t\t}\n\t\t\t}\n\t\t\tDUK__EMIT_1(js_ctx, DUK_ASC_RCURLY);\n\t\t} else if (c_bit & c_array) {\n\t\t\tduk_uint_fast32_t arr_len;\n\t\t\tduk_uint_fast32_t asize;\n\n\t\t\tDUK__EMIT_1(js_ctx, DUK_ASC_LBRACKET);\n\n\t\t\t/* Assume arrays are dense in the fast path. */\n\t\t\tif (!DUK_HOBJECT_HAS_ARRAY_PART(obj)) {\n\t\t\t\tDUK_DD(DUK_DDPRINT(\"Array object is sparse, abort fast path\"));\n\t\t\t\tgoto abort_fastpath;\n\t\t\t}\n\n\t\t\tarr_len = (duk_uint_fast32_t) ((duk_harray *) obj)->length;\n\t\t\tasize = (duk_uint_fast32_t) DUK_HOBJECT_GET_ASIZE(obj);\n\t\t\t/* Array part may be larger than 'length'; if so, iterate\n\t\t\t * only up to array 'length'.  Array part may also be smaller\n\t\t\t * than 'length' in some cases.\n\t\t\t */\n\t\t\tfor (i = 0; i < arr_len; i++) {\n\t\t\t\tduk_tval *tv_arrval;\n\t\t\t\tduk_hstring *h_tmp;\n\t\t\t\tduk_bool_t has_inherited;\n\n\t\t\t\tif (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {\n\t\t\t\t\tduk__enc_newline_indent(js_ctx, js_ctx->recursion_depth);\n\t\t\t\t}\n\n\t\t\t\tif (DUK_LIKELY(i < asize)) {\n\t\t\t\t\ttv_arrval = DUK_HOBJECT_A_GET_VALUE_PTR(js_ctx->thr->heap, obj, i);\n\t\t\t\t\tif (DUK_LIKELY(!DUK_TVAL_IS_UNUSED(tv_arrval))) {\n\t\t\t\t\t\t/* Expected case: element is present. */\n\t\t\t\t\t\tif (duk__json_stringify_fast_value(js_ctx, tv_arrval) == 0) {\n\t\t\t\t\t\t\tDUK__EMIT_STRIDX(js_ctx, DUK_STRIDX_LC_NULL);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tgoto elem_done;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t/* Gap in array; check for inherited property,\n\t\t\t\t * bail out if one exists.  This should be enough\n\t\t\t\t * to support gappy arrays for all practical code.\n\t\t\t\t */\n\n\t\t\t\th_tmp = duk_push_uint_to_hstring(js_ctx->thr, (duk_uint_t) i);\n\t\t\t\thas_inherited = duk_hobject_hasprop_raw(js_ctx->thr, obj, h_tmp);\n\t\t\t\tduk_pop(js_ctx->thr);\n\t\t\t\tif (has_inherited) {\n\t\t\t\t\tDUK_D(DUK_DPRINT(\"gap in array, conflicting inherited property, abort fast path\"));\n\t\t\t\t\tgoto abort_fastpath;\n\t\t\t\t}\n\n\t\t\t\t/* Ordinary gap, undefined encodes to 'null' in\n\t\t\t\t * standard JSON, but JX/JC use their form for\n\t\t\t\t * undefined to better preserve the typing.\n\t\t\t\t */\n\t\t\t\tDUK_D(DUK_DPRINT(\"gap in array, no conflicting inherited property, remain on fast path\"));\n#if defined(DUK_USE_JX)\n\t\t\t\tDUK__EMIT_STRIDX(js_ctx, js_ctx->stridx_custom_undefined);\n#else\n\t\t\t\tDUK__EMIT_STRIDX(js_ctx, DUK_STRIDX_LC_NULL);\n#endif\n\t\t\t\t/* fall through */\n\n\t\t\t elem_done:\n\t\t\t\tDUK__EMIT_1(js_ctx, DUK_ASC_COMMA);\n\t\t\t\temitted = 1;\n\t\t\t}\n\n\t\t\tif (emitted) {\n\t\t\t\tDUK_ASSERT(*((duk_uint8_t *) DUK_BW_GET_PTR(js_ctx->thr, &js_ctx->bw) - 1) == DUK_ASC_COMMA);\n\t\t\t\tDUK__UNEMIT_1(js_ctx);  /* eat trailing comma */\n\t\t\t\tif (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {\n\t\t\t\t\tDUK_ASSERT(js_ctx->recursion_depth >= 1);\n\t\t\t\t\tduk__enc_newline_indent(js_ctx, js_ctx->recursion_depth - 1U);\n\t\t\t\t}\n\t\t\t}\n\t\t\tDUK__EMIT_1(js_ctx, DUK_ASC_RBRACKET);\n\t\t} else if (c_bit & c_unbox) {\n\t\t\t/* Certain boxed types are required to go through\n\t\t\t * automatic unboxing.  Rely on internal value being\n\t\t\t * sane (to avoid infinite recursion).\n\t\t\t */\n\t\t\tDUK_ASSERT((c_bit & DUK_HOBJECT_CMASK_SYMBOL) == 0);  /* Symbols are not unboxed. */\n\n#if 1\n\t\t\t/* The code below is incorrect if .toString() or .valueOf() have\n\t\t\t * have been overridden.  The correct approach would be to look up\n\t\t\t * the method(s) and if they resolve to the built-in function we\n\t\t\t * can safely bypass it and look up the internal value directly.\n\t\t\t * Unimplemented for now, abort fast path for boxed values.\n\t\t\t */\n\t\t\tgoto abort_fastpath;\n#else  /* disabled */\n\t\t\t/* Disabled until fixed, see above. */\n\t\t\tduk_tval *tv_internal;\n\n\t\t\tDUK_DD(DUK_DDPRINT(\"auto unboxing in fast path\"));\n\n\t\t\ttv_internal = duk_hobject_get_internal_value_tval_ptr(js_ctx->thr->heap, obj);\n\t\t\tDUK_ASSERT(tv_internal != NULL);\n\t\t\tDUK_ASSERT(DUK_TVAL_IS_STRING(tv_internal) ||\n\t\t\t           DUK_TVAL_IS_NUMBER(tv_internal) ||\n\t\t\t           DUK_TVAL_IS_BOOLEAN(tv_internal) ||\n\t\t\t           DUK_TVAL_IS_POINTER(tv_internal));\n\n\t\t\ttv = tv_internal;\n\t\t\tDUK_ASSERT(js_ctx->recursion_depth > 0);\n\t\t\tjs_ctx->recursion_depth--;  /* required to keep recursion depth correct */\n\t\t\tgoto restart_match;\n#endif  /* disabled */\n#if defined(DUK_USE_JX) || defined(DUK_USE_JC)\n\t\t} else if (c_bit & c_func) {\n\t\t\tDUK__EMIT_STRIDX(js_ctx, js_ctx->stridx_custom_function);\n#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)\n\t\t} else if (c_bit & c_bufobj) {\n\t\t\tduk__enc_bufobj(js_ctx, (duk_hbufobj *) obj);\n#endif\n#endif\n\t\t} else if (c_bit & c_abort) {\n\t\t\tDUK_DD(DUK_DDPRINT(\"abort fast path for unsupported type\"));\n\t\t\tgoto abort_fastpath;\n\t\t} else {\n\t\t\tDUK_ASSERT((c_bit & c_undef) != 0);\n\n\t\t\t/* Must decrease recursion depth before returning. */\n\t\t\tDUK_ASSERT(js_ctx->recursion_depth > 0);\n\t\t\tDUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);\n\t\t\tjs_ctx->recursion_depth--;\n\t\t\tgoto emit_undefined;\n\t\t}\n\n\t\tDUK_ASSERT(js_ctx->recursion_depth > 0);\n\t\tDUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);\n\t\tjs_ctx->recursion_depth--;\n\t\tbreak;\n\t}\n\tcase DUK_TAG_BUFFER: {\n\t\t/* Plain buffers are treated like Uint8Arrays: they have\n\t\t * enumerable indices.  Other virtual properties are not\n\t\t * enumerable, and inherited properties are not serialized.\n\t\t * However, there can be a replacer (not relevant here) or\n\t\t * a .toJSON() method (which we need to check for explicitly).\n\t\t */\n\n#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)\n\t\tif (duk_hobject_hasprop_raw(js_ctx->thr,\n\t\t                            js_ctx->thr->builtins[DUK_BIDX_UINT8ARRAY_PROTOTYPE],\n\t\t                            DUK_HTHREAD_STRING_TO_JSON(js_ctx->thr))) {\n\t\t\tDUK_DD(DUK_DDPRINT(\"value is a plain buffer and there's an inherited .toJSON, abort fast path\"));\n\t\t\tgoto abort_fastpath;\n\t\t}\n#endif\n\n#if defined(DUK_USE_JX) || defined(DUK_USE_JC)\n\t\tif (js_ctx->flag_ext_custom_or_compatible) {\n\t\t\tduk__enc_buffer_jx_jc(js_ctx, DUK_TVAL_GET_BUFFER(tv));\n\t\t\tbreak;\n\t\t}\n#endif\n\n\t\t/* Plain buffers mimic Uint8Arrays, and have enumerable index\n\t\t * properties.\n\t\t */\n\t\tduk__enc_buffer_json_fastpath(js_ctx, DUK_TVAL_GET_BUFFER(tv));\n\t\tbreak;\n\t}\n\tcase DUK_TAG_POINTER: {\n#if defined(DUK_USE_JX) || defined(DUK_USE_JC)\n\t\tif (js_ctx->flag_ext_custom_or_compatible) {\n\t\t\tduk__enc_pointer(js_ctx, DUK_TVAL_GET_POINTER(tv));\n\t\t\tbreak;\n\t\t} else {\n\t\t\tgoto emit_undefined;\n\t\t}\n#else\n\t\tgoto emit_undefined;\n#endif\n\t}\n\tcase DUK_TAG_LIGHTFUNC: {\n\t\t/* A lightfunc might also inherit a .toJSON() so just bail out. */\n\t\t/* XXX: Could just lookup .toJSON() and continue in fast path,\n\t\t * as it would almost never be defined.\n\t\t */\n\t\tDUK_DD(DUK_DDPRINT(\"value is a lightfunc, abort fast path\"));\n\t\tgoto abort_fastpath;\n\t}\n#if defined(DUK_USE_FASTINT)\n\tcase DUK_TAG_FASTINT: {\n\t\t/* Number serialization has a significant impact relative to\n\t\t * other fast path code, so careful fast path for fastints.\n\t\t */\n\t\tduk__enc_fastint_tval(js_ctx, tv);\n\t\tbreak;\n\t}\n#endif\n\tdefault: {\n\t\t/* XXX: A fast path for usual integers would be useful when\n\t\t * fastint support is not enabled.\n\t\t */\n\t\tDUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));\n\t\tDUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));\n\n\t\t/* XXX: Stack discipline is annoying, could be changed in numconv. */\n\t\tduk_push_tval(js_ctx->thr, tv);\n\t\tduk__enc_double(js_ctx);\n\t\tduk_pop(js_ctx->thr);\n\n#if 0\n\t\t/* Could also rely on native sprintf(), but it will handle\n\t\t * values like NaN, Infinity, -0, exponent notation etc in\n\t\t * a JSON-incompatible way.\n\t\t */\n\t\tduk_double_t d;\n\t\tchar buf[64];\n\n\t\tDUK_ASSERT(DUK_TVAL_IS_DOUBLE(tv));\n\t\td = DUK_TVAL_GET_DOUBLE(tv);\n\t\tDUK_SPRINTF(buf, \"%lg\", d);\n\t\tDUK__EMIT_CSTR(js_ctx, buf);\n#endif\n\t}\n\t}\n\treturn 1;  /* not undefined */\n\n emit_undefined:\n\treturn 0;  /* value was undefined/unsupported */\n\n abort_fastpath:\n\t/* Error message doesn't matter: the error is ignored anyway. */\n\tDUK_DD(DUK_DDPRINT(\"aborting fast path\"));\n\tDUK_ERROR_INTERNAL(js_ctx->thr);\n\treturn 0;  /* unreachable */\n}\n\nDUK_LOCAL duk_ret_t duk__json_stringify_fast(duk_hthread *thr, void *udata) {\n\tduk_json_enc_ctx *js_ctx;\n\tduk_tval *tv;\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(udata != NULL);\n\n\tjs_ctx = (duk_json_enc_ctx *) udata;\n\tDUK_ASSERT(js_ctx != NULL);\n\n\ttv = DUK_GET_TVAL_NEGIDX(thr, -1);\n\tif (duk__json_stringify_fast_value(js_ctx, tv) == 0) {\n\t\tDUK_DD(DUK_DDPRINT(\"top level value not supported, fail fast path\"));\n\t\tDUK_DCERROR_TYPE_INVALID_ARGS(thr);  /* Error message is ignored, so doesn't matter. */\n\t}\n\n\treturn 0;\n}\n#endif  /* DUK_USE_JSON_STRINGIFY_FASTPATH */\n\n/*\n *  Top level wrappers\n */\n\nDUK_INTERNAL\nvoid duk_bi_json_parse_helper(duk_hthread *thr,\n                              duk_idx_t idx_value,\n                              duk_idx_t idx_reviver,\n                              duk_small_uint_t flags) {\n\tduk_json_dec_ctx js_ctx_alloc;\n\tduk_json_dec_ctx *js_ctx = &js_ctx_alloc;\n\tduk_hstring *h_text;\n#if defined(DUK_USE_ASSERTIONS)\n\tduk_idx_t entry_top = duk_get_top(thr);\n#endif\n\n\t/* negative top-relative indices not allowed now */\n\tDUK_ASSERT(idx_value == DUK_INVALID_INDEX || idx_value >= 0);\n\tDUK_ASSERT(idx_reviver == DUK_INVALID_INDEX || idx_reviver >= 0);\n\n\tDUK_DDD(DUK_DDDPRINT(\"JSON parse start: text=%!T, reviver=%!T, flags=0x%08lx, stack_top=%ld\",\n\t                     (duk_tval *) duk_get_tval(thr, idx_value),\n\t                     (duk_tval *) duk_get_tval(thr, idx_reviver),\n\t                     (unsigned long) flags,\n\t                     (long) duk_get_top(thr)));\n\n\tDUK_MEMZERO(&js_ctx_alloc, sizeof(js_ctx_alloc));\n\tjs_ctx->thr = thr;\n#if defined(DUK_USE_EXPLICIT_NULL_INIT)\n\t/* nothing now */\n#endif\n\tjs_ctx->recursion_limit = DUK_USE_JSON_DEC_RECLIMIT;\n\tDUK_ASSERT(js_ctx->recursion_depth == 0);\n\n\t/* Flag handling currently assumes that flags are consistent.  This is OK\n\t * because the call sites are now strictly controlled.\n\t */\n\n\tjs_ctx->flags = flags;\n#if defined(DUK_USE_JX)\n\tjs_ctx->flag_ext_custom = flags & DUK_JSON_FLAG_EXT_CUSTOM;\n#endif\n#if defined(DUK_USE_JC)\n\tjs_ctx->flag_ext_compatible = flags & DUK_JSON_FLAG_EXT_COMPATIBLE;\n#endif\n#if defined(DUK_USE_JX) || defined(DUK_USE_JC)\n\tjs_ctx->flag_ext_custom_or_compatible = flags & (DUK_JSON_FLAG_EXT_CUSTOM | DUK_JSON_FLAG_EXT_COMPATIBLE);\n#endif\n\n\th_text = duk_to_hstring(thr, idx_value);  /* coerce in-place; rejects Symbols */\n\tDUK_ASSERT(h_text != NULL);\n\n\t/* JSON parsing code is allowed to read [p_start,p_end]: p_end is\n\t * valid and points to the string NUL terminator (which is always\n\t * guaranteed for duk_hstrings.\n\t */\n\tjs_ctx->p_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_text);\n\tjs_ctx->p = js_ctx->p_start;\n\tjs_ctx->p_end = ((const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_text)) +\n\t                DUK_HSTRING_GET_BYTELEN(h_text);\n\tDUK_ASSERT(*(js_ctx->p_end) == 0x00);\n\n\tduk__dec_value(js_ctx);  /* -> [ ... value ] */\n\n\t/* Trailing whitespace has been eaten by duk__dec_value(), so if\n\t * we're not at end of input here, it's a SyntaxError.\n\t */\n\n\tif (js_ctx->p != js_ctx->p_end) {\n\t\tduk__dec_syntax_error(js_ctx);\n\t}\n\n\tif (duk_is_callable(thr, idx_reviver)) {\n\t\tDUK_DDD(DUK_DDDPRINT(\"applying reviver: %!T\",\n\t\t                     (duk_tval *) duk_get_tval(thr, idx_reviver)));\n\n\t\tjs_ctx->idx_reviver = idx_reviver;\n\n\t\tduk_push_object(thr);\n\t\tduk_dup_m2(thr);  /* -> [ ... val root val ] */\n\t\tduk_put_prop_stridx_short(thr, -2, DUK_STRIDX_EMPTY_STRING);  /* default attrs ok */\n\t\tduk_push_hstring_stridx(thr, DUK_STRIDX_EMPTY_STRING);  /* -> [ ... val root \"\" ] */\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"start reviver walk, root=%!T, name=%!T\",\n\t\t                     (duk_tval *) duk_get_tval(thr, -2),\n\t\t                     (duk_tval *) duk_get_tval(thr, -1)));\n\n\t\tduk__dec_reviver_walk(js_ctx);  /* [ ... val root \"\" ] -> [ ... val val' ] */\n\t\tduk_remove_m2(thr);             /* -> [ ... val' ] */\n\t} else {\n\t\tDUK_DDD(DUK_DDDPRINT(\"reviver does not exist or is not callable: %!T\",\n\t\t                     (duk_tval *) duk_get_tval(thr, idx_reviver)));\n\t}\n\n\t/* Final result is at stack top. */\n\n\tDUK_DDD(DUK_DDDPRINT(\"JSON parse end: text=%!T, reviver=%!T, flags=0x%08lx, result=%!T, stack_top=%ld\",\n\t                     (duk_tval *) duk_get_tval(thr, idx_value),\n\t                     (duk_tval *) duk_get_tval(thr, idx_reviver),\n\t                     (unsigned long) flags,\n\t                     (duk_tval *) duk_get_tval(thr, -1),\n\t                     (long) duk_get_top(thr)));\n\n\tDUK_ASSERT(duk_get_top(thr) == entry_top + 1);\n}\n\nDUK_INTERNAL\nvoid duk_bi_json_stringify_helper(duk_hthread *thr,\n                                  duk_idx_t idx_value,\n                                  duk_idx_t idx_replacer,\n                                  duk_idx_t idx_space,\n                                  duk_small_uint_t flags) {\n\tduk_json_enc_ctx js_ctx_alloc;\n\tduk_json_enc_ctx *js_ctx = &js_ctx_alloc;\n\tduk_hobject *h;\n\tduk_idx_t idx_holder;\n\tduk_idx_t entry_top;\n\n\t/* negative top-relative indices not allowed now */\n\tDUK_ASSERT(idx_value == DUK_INVALID_INDEX || idx_value >= 0);\n\tDUK_ASSERT(idx_replacer == DUK_INVALID_INDEX || idx_replacer >= 0);\n\tDUK_ASSERT(idx_space == DUK_INVALID_INDEX || idx_space >= 0);\n\n\tDUK_DDD(DUK_DDDPRINT(\"JSON stringify start: value=%!T, replacer=%!T, space=%!T, flags=0x%08lx, stack_top=%ld\",\n\t                     (duk_tval *) duk_get_tval(thr, idx_value),\n\t                     (duk_tval *) duk_get_tval(thr, idx_replacer),\n\t                     (duk_tval *) duk_get_tval(thr, idx_space),\n\t                     (unsigned long) flags,\n\t                     (long) duk_get_top(thr)));\n\n\tentry_top = duk_get_top(thr);\n\n\t/*\n\t *  Context init\n\t */\n\n\tDUK_MEMZERO(&js_ctx_alloc, sizeof(js_ctx_alloc));\n\tjs_ctx->thr = thr;\n#if defined(DUK_USE_EXPLICIT_NULL_INIT)\n\tjs_ctx->h_replacer = NULL;\n\tjs_ctx->h_gap = NULL;\n#endif\n\tjs_ctx->idx_proplist = -1;\n\n\t/* Flag handling currently assumes that flags are consistent.  This is OK\n\t * because the call sites are now strictly controlled.\n\t */\n\n\tjs_ctx->flags = flags;\n\tjs_ctx->flag_ascii_only = flags & DUK_JSON_FLAG_ASCII_ONLY;\n\tjs_ctx->flag_avoid_key_quotes = flags & DUK_JSON_FLAG_AVOID_KEY_QUOTES;\n#if defined(DUK_USE_JX)\n\tjs_ctx->flag_ext_custom = flags & DUK_JSON_FLAG_EXT_CUSTOM;\n#endif\n#if defined(DUK_USE_JC)\n\tjs_ctx->flag_ext_compatible = flags & DUK_JSON_FLAG_EXT_COMPATIBLE;\n#endif\n#if defined(DUK_USE_JX) || defined(DUK_USE_JC)\n\tjs_ctx->flag_ext_custom_or_compatible = flags & (DUK_JSON_FLAG_EXT_CUSTOM | DUK_JSON_FLAG_EXT_COMPATIBLE);\n#endif\n\n\t/* The #if defined() clutter here handles the JX/JC enable/disable\n\t * combinations properly.\n\t */\n#if defined(DUK_USE_JX) || defined(DUK_USE_JC)\n\tjs_ctx->stridx_custom_undefined = DUK_STRIDX_LC_NULL;  /* standard JSON; array gaps */\n#if defined(DUK_USE_JX)\n\tif (flags & DUK_JSON_FLAG_EXT_CUSTOM) {\n\t\tjs_ctx->stridx_custom_undefined = DUK_STRIDX_LC_UNDEFINED;\n\t\tjs_ctx->stridx_custom_nan = DUK_STRIDX_NAN;\n\t\tjs_ctx->stridx_custom_neginf = DUK_STRIDX_MINUS_INFINITY;\n\t\tjs_ctx->stridx_custom_posinf = DUK_STRIDX_INFINITY;\n\t\tjs_ctx->stridx_custom_function =\n\t\t        (flags & DUK_JSON_FLAG_AVOID_KEY_QUOTES) ?\n\t\t                DUK_STRIDX_JSON_EXT_FUNCTION2 :\n\t\t                DUK_STRIDX_JSON_EXT_FUNCTION1;\n\t}\n#endif  /* DUK_USE_JX */\n#if defined(DUK_USE_JX) && defined(DUK_USE_JC)\n\telse\n#endif  /* DUK_USE_JX && DUK_USE_JC */\n#if defined(DUK_USE_JC)\n\tif (js_ctx->flags & DUK_JSON_FLAG_EXT_COMPATIBLE) {\n\t\tjs_ctx->stridx_custom_undefined = DUK_STRIDX_JSON_EXT_UNDEFINED;\n\t\tjs_ctx->stridx_custom_nan = DUK_STRIDX_JSON_EXT_NAN;\n\t\tjs_ctx->stridx_custom_neginf = DUK_STRIDX_JSON_EXT_NEGINF;\n\t\tjs_ctx->stridx_custom_posinf = DUK_STRIDX_JSON_EXT_POSINF;\n\t\tjs_ctx->stridx_custom_function = DUK_STRIDX_JSON_EXT_FUNCTION1;\n\t}\n#endif  /* DUK_USE_JC */\n#endif  /* DUK_USE_JX || DUK_USE_JC */\n\n#if defined(DUK_USE_JX) || defined(DUK_USE_JC)\n\tif (js_ctx->flags & (DUK_JSON_FLAG_EXT_CUSTOM |\n\t                     DUK_JSON_FLAG_EXT_COMPATIBLE)) {\n\t\tDUK_ASSERT(js_ctx->mask_for_undefined == 0);  /* already zero */\n\t}\n\telse\n#endif  /* DUK_USE_JX || DUK_USE_JC */\n\t{\n\t\t/* Plain buffer is treated like ArrayBuffer and serialized.\n\t\t * Lightfuncs are treated like objects, but JSON explicitly\n\t\t * skips serializing Function objects so we can just reject\n\t\t * lightfuncs here.\n\t\t */\n\t\tjs_ctx->mask_for_undefined = DUK_TYPE_MASK_UNDEFINED |\n\t\t                             DUK_TYPE_MASK_POINTER |\n\t\t                             DUK_TYPE_MASK_LIGHTFUNC;\n\t}\n\n\tDUK_BW_INIT_PUSHBUF(thr, &js_ctx->bw, DUK__JSON_STRINGIFY_BUFSIZE);\n\n\tjs_ctx->idx_loop = duk_push_bare_object(thr);\n\tDUK_ASSERT(js_ctx->idx_loop >= 0);\n\n\t/* [ ... buf loop ] */\n\n\t/*\n\t *  Process replacer/proplist (2nd argument to JSON.stringify)\n\t */\n\n\th = duk_get_hobject(thr, idx_replacer);\n\tif (h != NULL) {\n\t\tif (DUK_HOBJECT_IS_CALLABLE(h)) {\n\t\t\tjs_ctx->h_replacer = h;\n\t\t} else if (DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_ARRAY) {\n\t\t\t/* Here the specification requires correct array index enumeration\n\t\t\t * which is a bit tricky for sparse arrays (it is handled by the\n\t\t\t * enum setup code).  We now enumerate ancestors too, although the\n\t\t\t * specification is not very clear on whether that is required.\n\t\t\t */\n\n\t\t\tduk_uarridx_t plist_idx = 0;\n\t\t\tduk_small_uint_t enum_flags;\n\n\t\t\tjs_ctx->idx_proplist = duk_push_array(thr);  /* XXX: array internal? */\n\n\t\t\tenum_flags = DUK_ENUM_ARRAY_INDICES_ONLY |\n\t\t\t             DUK_ENUM_SORT_ARRAY_INDICES;  /* expensive flag */\n\t\t\tduk_enum(thr, idx_replacer, enum_flags);\n\t\t\twhile (duk_next(thr, -1 /*enum_index*/, 1 /*get_value*/)) {\n\t\t\t\t/* [ ... proplist enum_obj key val ] */\n\t\t\t\tif (duk__enc_allow_into_proplist(duk_get_tval(thr, -1))) {\n\t\t\t\t\t/* XXX: duplicates should be eliminated here */\n\t\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"proplist enum: key=%!T, val=%!T --> accept\",\n\t\t\t\t\t                     (duk_tval *) duk_get_tval(thr, -2),\n\t\t\t\t\t                     (duk_tval *) duk_get_tval(thr, -1)));\n\t\t\t\t\tduk_to_string(thr, -1);  /* extra coercion of strings is OK */\n\t\t\t\t\tduk_put_prop_index(thr, -4, plist_idx);  /* -> [ ... proplist enum_obj key ] */\n\t\t\t\t\tplist_idx++;\n\t\t\t\t\tduk_pop(thr);\n\t\t\t\t} else {\n\t\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"proplist enum: key=%!T, val=%!T --> reject\",\n\t\t\t\t\t                     (duk_tval *) duk_get_tval(thr, -2),\n\t\t\t\t\t                     (duk_tval *) duk_get_tval(thr, -1)));\n\t\t\t\t\tduk_pop_2(thr);\n\t\t\t\t}\n                        }\n                        duk_pop(thr);  /* pop enum */\n\n\t\t\t/* [ ... proplist ] */\n\t\t}\n\t}\n\n\t/* [ ... buf loop (proplist) ] */\n\n\t/*\n\t *  Process space (3rd argument to JSON.stringify)\n\t */\n\n\th = duk_get_hobject(thr, idx_space);\n\tif (h != NULL) {\n\t\tduk_small_uint_t c = DUK_HOBJECT_GET_CLASS_NUMBER(h);\n\t\tif (c == DUK_HOBJECT_CLASS_NUMBER) {\n\t\t\tduk_to_number(thr, idx_space);\n\t\t} else if (c == DUK_HOBJECT_CLASS_STRING) {\n\t\t\tduk_to_string(thr, idx_space);\n\t\t}\n\t}\n\n\tif (duk_is_number(thr, idx_space)) {\n\t\tduk_small_int_t nspace;\n\t\t/* spaces[] must be static to allow initializer with old compilers like BCC */\n\t\tstatic const char spaces[10] = {\n\t\t\tDUK_ASC_SPACE, DUK_ASC_SPACE, DUK_ASC_SPACE, DUK_ASC_SPACE,\n\t\t\tDUK_ASC_SPACE, DUK_ASC_SPACE, DUK_ASC_SPACE, DUK_ASC_SPACE,\n\t\t\tDUK_ASC_SPACE, DUK_ASC_SPACE\n\t\t};  /* XXX: helper */\n\n\t\t/* ToInteger() coercion; NaN -> 0, infinities are clamped to 0 and 10 */\n\t\tnspace = (duk_small_int_t) duk_to_int_clamped(thr, idx_space, 0 /*minval*/, 10 /*maxval*/);\n\t\tDUK_ASSERT(nspace >= 0 && nspace <= 10);\n\n\t\tduk_push_lstring(thr, spaces, (duk_size_t) nspace);\n\t\tjs_ctx->h_gap = duk_known_hstring(thr, -1);\n\t\tDUK_ASSERT(js_ctx->h_gap != NULL);\n\t} else if (duk_is_string_notsymbol(thr, idx_space)) {\n\t\tduk_dup(thr, idx_space);\n\t\tduk_substring(thr, -1, 0, 10);  /* clamp to 10 chars */\n\t\tjs_ctx->h_gap = duk_known_hstring(thr, -1);\n\t} else {\n\t\t/* nop */\n\t}\n\n\tif (js_ctx->h_gap != NULL) {\n\t\t/* If gap is empty, behave as if not given at all.  Check\n\t\t * against byte length because character length is more\n\t\t * expensive.\n\t\t */\n\t\tif (DUK_HSTRING_GET_BYTELEN(js_ctx->h_gap) == 0) {\n\t\t\tjs_ctx->h_gap = NULL;\n\t\t}\n\t}\n\n\t/* [ ... buf loop (proplist) (gap) ] */\n\n\t/*\n\t *  Fast path: assume no mutation, iterate object property tables\n\t *  directly; bail out if that assumption doesn't hold.\n\t */\n\n#if defined(DUK_USE_JSON_STRINGIFY_FASTPATH)\n\tif (js_ctx->h_replacer == NULL &&  /* replacer is a mutation risk */\n\t    js_ctx->idx_proplist == -1) {  /* proplist is very rare */\n\t\tduk_int_t pcall_rc;\n\t\tduk_small_uint_t prev_ms_base_flags;\n\n\t\tDUK_DD(DUK_DDPRINT(\"try JSON.stringify() fast path\"));\n\n\t\t/* Use recursion_limit to ensure we don't overwrite js_ctx->visiting[]\n\t\t * array so we don't need two counter checks in the fast path.  The\n\t\t * slow path has a much larger recursion limit which we'll use if\n\t\t * necessary.\n\t\t */\n\t\tDUK_ASSERT(DUK_USE_JSON_ENC_RECLIMIT >= DUK_JSON_ENC_LOOPARRAY);\n\t\tjs_ctx->recursion_limit = DUK_JSON_ENC_LOOPARRAY;\n\t\tDUK_ASSERT(js_ctx->recursion_depth == 0);\n\n\t\t/* Execute the fast path in a protected call.  If any error is thrown,\n\t\t * fall back to the slow path.  This includes e.g. recursion limit\n\t\t * because the fast path has a smaller recursion limit (and simpler,\n\t\t * limited loop detection).\n\t\t */\n\n\t\tduk_dup(thr, idx_value);\n\n\t\t/* Must prevent finalizers which may have arbitrary side effects. */\n\t\tprev_ms_base_flags = thr->heap->ms_base_flags;\n\t\tthr->heap->ms_base_flags |=\n\t\t        DUK_MS_FLAG_NO_OBJECT_COMPACTION;      /* Avoid attempt to compact any objects. */\n\t\tthr->heap->pf_prevent_count++;                 /* Prevent finalizers. */\n\t\tDUK_ASSERT(thr->heap->pf_prevent_count != 0);  /* Wrap. */\n\n\t\tpcall_rc = duk_safe_call(thr, duk__json_stringify_fast, (void *) js_ctx /*udata*/, 1 /*nargs*/, 0 /*nret*/);\n\n\t\tDUK_ASSERT(thr->heap->pf_prevent_count > 0);\n\t\tthr->heap->pf_prevent_count--;\n\t\tthr->heap->ms_base_flags = prev_ms_base_flags;\n\n\t\tif (pcall_rc == DUK_EXEC_SUCCESS) {\n\t\t\tDUK_DD(DUK_DDPRINT(\"fast path successful\"));\n\t\t\tDUK_BW_PUSH_AS_STRING(thr, &js_ctx->bw);\n\t\t\tgoto replace_finished;\n\t\t}\n\n\t\t/* We come here for actual aborts (like encountering .toJSON())\n\t\t * but also for recursion/loop errors.  Bufwriter size can be\n\t\t * kept because we'll probably need at least as much as we've\n\t\t * allocated so far.\n\t\t */\n\t\tDUK_D(DUK_DPRINT(\"fast path failed, serialize using slow path instead\"));\n\t\tDUK_BW_RESET_SIZE(thr, &js_ctx->bw);\n\t\tjs_ctx->recursion_depth = 0;\n\t}\n#endif\n\n\t/*\n\t *  Create wrapper object and serialize\n\t */\n\n\tidx_holder = duk_push_object(thr);\n\tduk_dup(thr, idx_value);\n\tduk_put_prop_stridx_short(thr, -2, DUK_STRIDX_EMPTY_STRING);\n\n\tDUK_DDD(DUK_DDDPRINT(\"before: flags=0x%08lx, loop=%!T, replacer=%!O, \"\n\t                     \"proplist=%!T, gap=%!O, holder=%!T\",\n\t                     (unsigned long) js_ctx->flags,\n\t                     (duk_tval *) duk_get_tval(thr, js_ctx->idx_loop),\n\t                     (duk_heaphdr *) js_ctx->h_replacer,\n\t                     (duk_tval *) (js_ctx->idx_proplist >= 0 ? duk_get_tval(thr, js_ctx->idx_proplist) : NULL),\n\t                     (duk_heaphdr *) js_ctx->h_gap,\n\t                     (duk_tval *) duk_get_tval(thr, -1)));\n\n\t/* serialize the wrapper with empty string key */\n\n\tduk_push_hstring_empty(thr);\n\n\t/* [ ... buf loop (proplist) (gap) holder \"\" ] */\n\n\tjs_ctx->recursion_limit = DUK_USE_JSON_ENC_RECLIMIT;\n\tDUK_ASSERT(js_ctx->recursion_depth == 0);\n\n\tif (DUK_UNLIKELY(duk__enc_value(js_ctx, idx_holder) == 0)) {  /* [ ... holder key ] -> [ ... holder ] */\n\t\t/* Result is undefined. */\n\t\tduk_push_undefined(thr);\n\t} else {\n\t\t/* Convert buffer to result string. */\n\t\tDUK_BW_PUSH_AS_STRING(thr, &js_ctx->bw);\n\t}\n\n\tDUK_DDD(DUK_DDDPRINT(\"after: flags=0x%08lx, loop=%!T, replacer=%!O, \"\n\t                     \"proplist=%!T, gap=%!O, holder=%!T\",\n\t                     (unsigned long) js_ctx->flags,\n\t                     (duk_tval *) duk_get_tval(thr, js_ctx->idx_loop),\n\t                     (duk_heaphdr *) js_ctx->h_replacer,\n\t                     (duk_tval *) (js_ctx->idx_proplist >= 0 ? duk_get_tval(thr, js_ctx->idx_proplist) : NULL),\n\t                     (duk_heaphdr *) js_ctx->h_gap,\n\t                     (duk_tval *) duk_get_tval(thr, idx_holder)));\n\n\t/* The stack has a variable shape here, so force it to the\n\t * desired one explicitly.\n\t */\n\n#if defined(DUK_USE_JSON_STRINGIFY_FASTPATH)\n replace_finished:\n#endif\n\tduk_replace(thr, entry_top);\n\tduk_set_top(thr, entry_top + 1);\n\n\tDUK_DDD(DUK_DDDPRINT(\"JSON stringify end: value=%!T, replacer=%!T, space=%!T, \"\n\t                     \"flags=0x%08lx, result=%!T, stack_top=%ld\",\n\t                     (duk_tval *) duk_get_tval(thr, idx_value),\n\t                     (duk_tval *) duk_get_tval(thr, idx_replacer),\n\t                     (duk_tval *) duk_get_tval(thr, idx_space),\n\t                     (unsigned long) flags,\n\t                     (duk_tval *) duk_get_tval(thr, -1),\n\t                     (long) duk_get_top(thr)));\n\n\tDUK_ASSERT(duk_get_top(thr) == entry_top + 1);\n}\n\n#if defined(DUK_USE_JSON_BUILTIN)\n\n/*\n *  Entry points\n */\n\nDUK_INTERNAL duk_ret_t duk_bi_json_object_parse(duk_hthread *thr) {\n\tduk_bi_json_parse_helper(thr,\n\t                         0 /*idx_value*/,\n\t                         1 /*idx_replacer*/,\n\t                         0 /*flags*/);\n\treturn 1;\n}\n\nDUK_INTERNAL duk_ret_t duk_bi_json_object_stringify(duk_hthread *thr) {\n\tduk_bi_json_stringify_helper(thr,\n\t                             0 /*idx_value*/,\n\t                             1 /*idx_replacer*/,\n\t                             2 /*idx_space*/,\n\t                             0 /*flags*/);\n\treturn 1;\n}\n\n#endif  /* DUK_USE_JSON_BUILTIN */\n\n#endif  /* DUK_USE_JSON_SUPPORT */\n\n/* automatic undefs */\n#undef DUK__EMIT_1\n#undef DUK__EMIT_2\n#undef DUK__EMIT_CSTR\n#undef DUK__EMIT_HSTR\n#undef DUK__EMIT_STRIDX\n#undef DUK__JSON_DECSTR_BUFSIZE\n#undef DUK__JSON_DECSTR_CHUNKSIZE\n#undef DUK__JSON_ENCSTR_CHUNKSIZE\n#undef DUK__JSON_MAX_ESC_LEN\n#undef DUK__JSON_STRINGIFY_BUFSIZE\n#undef DUK__MKESC\n#undef DUK__UNEMIT_1\n#line 1 \"duk_bi_math.c\"\n/*\n *  Math built-ins\n */\n\n/* #include duk_internal.h -> already included */\n\n#if defined(DUK_USE_MATH_BUILTIN)\n\n/*\n *  Use static helpers which can work with math.h functions matching\n *  the following signatures. This is not portable if any of these math\n *  functions is actually a macro.\n *\n *  Typing here is intentionally 'double' wherever values interact with\n *  the standard library APIs.\n */\n\ntypedef double (*duk__one_arg_func)(double);\ntypedef double (*duk__two_arg_func)(double, double);\n\nDUK_LOCAL duk_ret_t duk__math_minmax(duk_hthread *thr, duk_double_t initial, duk__two_arg_func min_max) {\n\tduk_idx_t n = duk_get_top(thr);\n\tduk_idx_t i;\n\tduk_double_t res = initial;\n\tduk_double_t t;\n\n\t/*\n\t *  Note: fmax() does not match the E5 semantics.  E5 requires\n\t *  that if -any- input to Math.max() is a NaN, the result is a\n\t *  NaN.  fmax() will return a NaN only if -both- inputs are NaN.\n\t *  Same applies to fmin().\n\t *\n\t *  Note: every input value must be coerced with ToNumber(), even\n\t *  if we know the result will be a NaN anyway: ToNumber() may have\n\t *  side effects for which even order of evaluation matters.\n\t */\n\n\tfor (i = 0; i < n; i++) {\n\t\tt = duk_to_number(thr, i);\n\t\tif (DUK_FPCLASSIFY(t) == DUK_FP_NAN || DUK_FPCLASSIFY(res) == DUK_FP_NAN) {\n\t\t\t/* Note: not normalized, but duk_push_number() will normalize */\n\t\t\tres = (duk_double_t) DUK_DOUBLE_NAN;\n\t\t} else {\n\t\t\tres = (duk_double_t) min_max(res, (double) t);\n\t\t}\n\t}\n\n\tduk_push_number(thr, res);\n\treturn 1;\n}\n\nDUK_LOCAL double duk__fmin_fixed(double x, double y) {\n\t/* fmin() with args -0 and +0 is not guaranteed to return\n\t * -0 as Ecmascript requires.\n\t */\n\tif (x == 0 && y == 0) {\n\t\tduk_double_union du1, du2;\n\t\tdu1.d = x;\n\t\tdu2.d = y;\n\n\t\t/* Already checked to be zero so these must hold, and allow us\n\t\t * to check for \"x is -0 or y is -0\" by ORing the high parts\n\t\t * for comparison.\n\t\t */\n\t\tDUK_ASSERT(du1.ui[DUK_DBL_IDX_UI0] == 0 || du1.ui[DUK_DBL_IDX_UI0] == 0x80000000UL);\n\t\tDUK_ASSERT(du2.ui[DUK_DBL_IDX_UI0] == 0 || du2.ui[DUK_DBL_IDX_UI0] == 0x80000000UL);\n\n\t\t/* XXX: what's the safest way of creating a negative zero? */\n\t\tif ((du1.ui[DUK_DBL_IDX_UI0] | du2.ui[DUK_DBL_IDX_UI0]) != 0) {\n\t\t\t/* Enter here if either x or y (or both) is -0. */\n\t\t\treturn -0.0;\n\t\t} else {\n\t\t\treturn +0.0;\n\t\t}\n\t}\n\treturn duk_double_fmin(x, y);\n}\n\nDUK_LOCAL double duk__fmax_fixed(double x, double y) {\n\t/* fmax() with args -0 and +0 is not guaranteed to return\n\t * +0 as Ecmascript requires.\n\t */\n\tif (x == 0 && y == 0) {\n\t\tif (DUK_SIGNBIT(x) == 0 || DUK_SIGNBIT(y) == 0) {\n\t\t\treturn +0.0;\n\t\t} else {\n\t\t\treturn -0.0;\n\t\t}\n\t}\n\treturn duk_double_fmax(x, y);\n}\n\n#if defined(DUK_USE_ES6)\nDUK_LOCAL double duk__cbrt(double x) {\n\t/* cbrt() is C99.  To avoid hassling embedders with the need to provide a\n\t * cube root function, we can get by with pow().  The result is not\n\t * identical, but that's OK: ES2015 says it's implementation-dependent.\n\t */\n\n#if defined(DUK_CBRT)\n\t/* cbrt() matches ES2015 requirements. */\n\treturn DUK_CBRT(x);\n#else\n\tduk_small_int_t c = (duk_small_int_t) DUK_FPCLASSIFY(x);\n\n\t/* pow() does not, however. */\n\tif (c == DUK_FP_NAN || c == DUK_FP_INFINITE || c == DUK_FP_ZERO) {\n\t\treturn x;\n\t}\n\tif (DUK_SIGNBIT(x)) {\n\t\treturn -DUK_POW(-x, 1.0 / 3.0);\n\t} else {\n\t\treturn DUK_POW(x, 1.0 / 3.0);\n\t}\n#endif\n}\n\nDUK_LOCAL double duk__log2(double x) {\n#if defined(DUK_LOG2)\n\treturn DUK_LOG2(x);\n#else\n\treturn DUK_LOG(x) * DUK_DOUBLE_LOG2E;\n#endif\n}\n\nDUK_LOCAL double duk__log10(double x) {\n#if defined(DUK_LOG10)\n\treturn DUK_LOG10(x);\n#else\n\treturn DUK_LOG(x) * DUK_DOUBLE_LOG10E;\n#endif\n}\n\nDUK_LOCAL double duk__trunc(double x) {\n#if defined(DUK_TRUNC)\n\treturn DUK_TRUNC(x);\n#else\n\t/* Handles -0 correctly: -0.0 matches 'x >= 0.0' but floor()\n\t * is required to return -0 when the argument is -0.\n\t */\n\treturn x >= 0.0 ? DUK_FLOOR(x) : DUK_CEIL(x);\n#endif\n}\n#endif  /* DUK_USE_ES6 */\n\nDUK_LOCAL double duk__round_fixed(double x) {\n\t/* Numbers half-way between integers must be rounded towards +Infinity,\n\t * e.g. -3.5 must be rounded to -3 (not -4).  When rounded to zero, zero\n\t * sign must be set appropriately.  E5.1 Section 15.8.2.15.\n\t *\n\t * Note that ANSI C round() is \"round to nearest integer, away from zero\",\n\t * which is incorrect for negative values.  Here we make do with floor().\n\t */\n\n\tduk_small_int_t c = (duk_small_int_t) DUK_FPCLASSIFY(x);\n\tif (c == DUK_FP_NAN || c == DUK_FP_INFINITE || c == DUK_FP_ZERO) {\n\t\treturn x;\n\t}\n\n\t/*\n\t *  x is finite and non-zero\n\t *\n\t *  -1.6 -> floor(-1.1) -> -2\n\t *  -1.5 -> floor(-1.0) -> -1  (towards +Inf)\n\t *  -1.4 -> floor(-0.9) -> -1\n\t *  -0.5 -> -0.0               (special case)\n\t *  -0.1 -> -0.0               (special case)\n\t *  +0.1 -> +0.0               (special case)\n\t *  +0.5 -> floor(+1.0) -> 1   (towards +Inf)\n\t *  +1.4 -> floor(+1.9) -> 1\n\t *  +1.5 -> floor(+2.0) -> 2   (towards +Inf)\n\t *  +1.6 -> floor(+2.1) -> 2\n\t */\n\n\tif (x >= -0.5 && x < 0.5) {\n\t\t/* +0.5 is handled by floor, this is on purpose */\n\t\tif (x < 0.0) {\n\t\t\treturn -0.0;\n\t\t} else {\n\t\t\treturn +0.0;\n\t\t}\n\t}\n\n\treturn DUK_FLOOR(x + 0.5);\n}\n\n/* Wrappers for calling standard math library methods.  These may be required\n * on platforms where one or more of the math built-ins are defined as macros\n * or inline functions and are thus not suitable to be used as function pointers.\n */\n#if defined(DUK_USE_AVOID_PLATFORM_FUNCPTRS)\nDUK_LOCAL double duk__fabs(double x) {\n\treturn DUK_FABS(x);\n}\nDUK_LOCAL double duk__acos(double x) {\n\treturn DUK_ACOS(x);\n}\nDUK_LOCAL double duk__asin(double x) {\n\treturn DUK_ASIN(x);\n}\nDUK_LOCAL double duk__atan(double x) {\n\treturn DUK_ATAN(x);\n}\nDUK_LOCAL double duk__ceil(double x) {\n\treturn DUK_CEIL(x);\n}\nDUK_LOCAL double duk__cos(double x) {\n\treturn DUK_COS(x);\n}\nDUK_LOCAL double duk__exp(double x) {\n\treturn DUK_EXP(x);\n}\nDUK_LOCAL double duk__floor(double x) {\n\treturn DUK_FLOOR(x);\n}\nDUK_LOCAL double duk__log(double x) {\n\treturn DUK_LOG(x);\n}\nDUK_LOCAL double duk__sin(double x) {\n\treturn DUK_SIN(x);\n}\nDUK_LOCAL double duk__sqrt(double x) {\n\treturn DUK_SQRT(x);\n}\nDUK_LOCAL double duk__tan(double x) {\n\treturn DUK_TAN(x);\n}\nDUK_LOCAL double duk__atan2_fixed(double x, double y) {\n#if defined(DUK_USE_ATAN2_WORKAROUNDS)\n\t/* Specific fixes to common atan2() implementation issues:\n\t * - test-bug-mingw-math-issues.js\n\t */\n\tif (DUK_ISINF(x) && DUK_ISINF(y)) {\n\t\tif (DUK_SIGNBIT(x)) {\n\t\t\tif (DUK_SIGNBIT(y)) {\n\t\t\t\treturn -2.356194490192345;\n\t\t\t} else {\n\t\t\t\treturn -0.7853981633974483;\n\t\t\t}\n\t\t} else {\n\t\t\tif (DUK_SIGNBIT(y)) {\n\t\t\t\treturn 2.356194490192345;\n\t\t\t} else {\n\t\t\t\treturn 0.7853981633974483;\n\t\t\t}\n\t\t}\n\t}\n#else\n\t/* Some ISO C assumptions. */\n\tDUK_ASSERT(DUK_ATAN2(DUK_DOUBLE_INFINITY, DUK_DOUBLE_INFINITY) == 0.7853981633974483);\n\tDUK_ASSERT(DUK_ATAN2(-DUK_DOUBLE_INFINITY, DUK_DOUBLE_INFINITY) == -0.7853981633974483);\n\tDUK_ASSERT(DUK_ATAN2(DUK_DOUBLE_INFINITY, -DUK_DOUBLE_INFINITY) == 2.356194490192345);\n\tDUK_ASSERT(DUK_ATAN2(-DUK_DOUBLE_INFINITY, -DUK_DOUBLE_INFINITY) == -2.356194490192345);\n#endif\n\n\treturn DUK_ATAN2(x, y);\n}\n#endif  /* DUK_USE_AVOID_PLATFORM_FUNCPTRS */\n\n/* order must match constants in genbuiltins.py */\nDUK_LOCAL const duk__one_arg_func duk__one_arg_funcs[] = {\n#if defined(DUK_USE_AVOID_PLATFORM_FUNCPTRS)\n\tduk__fabs,\n\tduk__acos,\n\tduk__asin,\n\tduk__atan,\n\tduk__ceil,\n\tduk__cos,\n\tduk__exp,\n\tduk__floor,\n\tduk__log,\n\tduk__round_fixed,\n\tduk__sin,\n\tduk__sqrt,\n\tduk__tan,\n#if defined(DUK_USE_ES6)\n\tduk__cbrt,\n\tduk__log2,\n\tduk__log10,\n\tduk__trunc\n#endif\n#else  /* DUK_USE_AVOID_PLATFORM_FUNCPTRS */\n\tDUK_FABS,\n\tDUK_ACOS,\n\tDUK_ASIN,\n\tDUK_ATAN,\n\tDUK_CEIL,\n\tDUK_COS,\n\tDUK_EXP,\n\tDUK_FLOOR,\n\tDUK_LOG,\n\tduk__round_fixed,\n\tDUK_SIN,\n\tDUK_SQRT,\n\tDUK_TAN,\n#if defined(DUK_USE_ES6)\n\tduk__cbrt,\n\tduk__log2,\n\tduk__log10,\n\tduk__trunc\n#endif\n#endif  /* DUK_USE_AVOID_PLATFORM_FUNCPTRS */\n};\n\n/* order must match constants in genbuiltins.py */\nDUK_LOCAL const duk__two_arg_func duk__two_arg_funcs[] = {\n#if defined(DUK_USE_AVOID_PLATFORM_FUNCPTRS)\n\tduk__atan2_fixed,\n\tduk_js_arith_pow\n#else\n\tduk__atan2_fixed,\n\tduk_js_arith_pow\n#endif\n};\n\nDUK_INTERNAL duk_ret_t duk_bi_math_object_onearg_shared(duk_hthread *thr) {\n\tduk_small_int_t fun_idx = duk_get_current_magic(thr);\n\tduk__one_arg_func fun;\n\tduk_double_t arg1;\n\n\tDUK_ASSERT(fun_idx >= 0);\n\tDUK_ASSERT(fun_idx < (duk_small_int_t) (sizeof(duk__one_arg_funcs) / sizeof(duk__one_arg_func)));\n\targ1 = duk_to_number(thr, 0);\n\tfun = duk__one_arg_funcs[fun_idx];\n\tduk_push_number(thr, (duk_double_t) fun((double) arg1));\n\treturn 1;\n}\n\nDUK_INTERNAL duk_ret_t duk_bi_math_object_twoarg_shared(duk_hthread *thr) {\n\tduk_small_int_t fun_idx = duk_get_current_magic(thr);\n\tduk__two_arg_func fun;\n\tduk_double_t arg1;\n\tduk_double_t arg2;\n\n\tDUK_ASSERT(fun_idx >= 0);\n\tDUK_ASSERT(fun_idx < (duk_small_int_t) (sizeof(duk__two_arg_funcs) / sizeof(duk__two_arg_func)));\n\targ1 = duk_to_number(thr, 0);  /* explicit ordered evaluation to match coercion semantics */\n\targ2 = duk_to_number(thr, 1);\n\tfun = duk__two_arg_funcs[fun_idx];\n\tduk_push_number(thr, (duk_double_t) fun((double) arg1, (double) arg2));\n\treturn 1;\n}\n\nDUK_INTERNAL duk_ret_t duk_bi_math_object_max(duk_hthread *thr) {\n\treturn duk__math_minmax(thr, -DUK_DOUBLE_INFINITY, duk__fmax_fixed);\n}\n\nDUK_INTERNAL duk_ret_t duk_bi_math_object_min(duk_hthread *thr) {\n\treturn duk__math_minmax(thr, DUK_DOUBLE_INFINITY, duk__fmin_fixed);\n}\n\nDUK_INTERNAL duk_ret_t duk_bi_math_object_random(duk_hthread *thr) {\n\tduk_push_number(thr, (duk_double_t) DUK_UTIL_GET_RANDOM_DOUBLE(thr));\n\treturn 1;\n}\n\n#if defined(DUK_USE_ES6)\nDUK_INTERNAL duk_ret_t duk_bi_math_object_hypot(duk_hthread *thr) {\n\t/*\n\t *  E6 Section 20.2.2.18: Math.hypot\n\t *\n\t *  - If no arguments are passed, the result is +0.\n\t *  - If any argument is +inf, the result is +inf.\n\t *  - If any argument is -inf, the result is +inf.\n\t *  - If no argument is +inf or -inf, and any argument is NaN, the result is\n\t *    NaN.\n\t *  - If all arguments are either +0 or -0, the result is +0.\n\t */\n\n\tduk_idx_t nargs;\n\tduk_idx_t i;\n\tduk_bool_t found_nan;\n\tduk_double_t max;\n\tduk_double_t sum, summand;\n\tduk_double_t comp, prelim;\n\tduk_double_t t;\n\n\tnargs = duk_get_top(thr);\n\n\t/* Find the highest value.  Also ToNumber() coerces. */\n\tmax = 0.0;\n\tfound_nan = 0;\n\tfor (i = 0; i < nargs; i++) {\n\t\tt = DUK_FABS(duk_to_number(thr, i));\n\t\tif (DUK_FPCLASSIFY(t) == DUK_FP_NAN) {\n\t\t\tfound_nan = 1;\n\t\t} else {\n\t\t\tmax = duk_double_fmax(max, t);\n\t\t}\n\t}\n\n\t/* Early return cases. */\n\tif (max == DUK_DOUBLE_INFINITY) {\n\t\tduk_push_number(thr, DUK_DOUBLE_INFINITY);\n\t\treturn 1;\n\t} else if (found_nan) {\n\t\tduk_push_number(thr, DUK_DOUBLE_NAN);\n\t\treturn 1;\n\t} else if (max == 0.0) {\n\t\tduk_push_number(thr, 0.0);\n\t\t/* Otherwise we'd divide by zero. */\n\t\treturn 1;\n\t}\n\n\t/* Use Kahan summation and normalize to the highest value to minimize\n\t * floating point rounding error and avoid overflow.\n\t *\n\t * https://en.wikipedia.org/wiki/Kahan_summation_algorithm\n\t */\n\tsum = 0.0;\n\tcomp = 0.0;\n\tfor (i = 0; i < nargs; i++) {\n\t\tt = DUK_FABS(duk_get_number(thr, i)) / max;\n\t\tsummand = (t * t) - comp;\n\t\tprelim = sum + summand;\n\t\tcomp = (prelim - sum) - summand;\n\t\tsum = prelim;\n\t}\n\n\tduk_push_number(thr, (duk_double_t) DUK_SQRT(sum) * max);\n\treturn 1;\n}\n#endif  /* DUK_USE_ES6 */\n\n#if defined(DUK_USE_ES6)\nDUK_INTERNAL duk_ret_t duk_bi_math_object_sign(duk_hthread *thr) {\n\tduk_double_t d;\n\n\td = duk_to_number(thr, 0);\n\tif (duk_double_is_nan(d)) {\n\t\tDUK_ASSERT(duk_is_nan(thr, -1));\n\t\treturn 1;  /* NaN input -> return NaN */\n\t}\n\tif (d == 0.0) {\n\t\t/* Zero sign kept, i.e. -0 -> -0, +0 -> +0. */\n\t\treturn 1;\n\t}\n\tduk_push_int(thr, (d > 0.0 ? 1 : -1));\n\treturn 1;\n}\n#endif  /* DUK_USE_ES6 */\n\n#if defined(DUK_USE_ES6)\nDUK_INTERNAL duk_ret_t duk_bi_math_object_clz32(duk_hthread *thr) {\n\tduk_uint32_t x;\n\tduk_small_uint_t i;\n\n#if defined(DUK_USE_PREFER_SIZE)\n\tduk_uint32_t mask;\n\n\tx = duk_to_uint32(thr, 0);\n\tfor (i = 0, mask = 0x80000000UL; mask != 0; mask >>= 1) {\n\t\tif (x & mask) {\n\t\t\tbreak;\n\t\t}\n\t\ti++;\n\t}\n\tDUK_ASSERT(i <= 32);\n\tduk_push_uint(thr, i);\n\treturn 1;\n#else  /* DUK_USE_PREFER_SIZE */\n\ti = 0;\n\tx = duk_to_uint32(thr, 0);\n\tif (x & 0xffff0000UL) {\n\t\tx >>= 16;\n\t} else {\n\t\ti += 16;\n\t}\n\tif (x & 0x0000ff00UL) {\n\t\tx >>= 8;\n\t} else {\n\t\ti += 8;\n\t}\n\tif (x & 0x000000f0UL) {\n\t\tx >>= 4;\n\t} else {\n\t\ti += 4;\n\t}\n\tif (x & 0x0000000cUL) {\n\t\tx >>= 2;\n\t} else {\n\t\ti += 2;\n\t}\n\tif (x & 0x00000002UL) {\n\t\tx >>= 1;\n\t} else {\n\t\ti += 1;\n\t}\n\tif (x & 0x00000001UL) {\n\t\t;\n\t} else {\n\t\ti += 1;\n\t}\n\tDUK_ASSERT(i <= 32);\n\tduk_push_uint(thr, i);\n\treturn 1;\n#endif  /* DUK_USE_PREFER_SIZE */\n}\n#endif  /* DUK_USE_ES6 */\n\n#if defined(DUK_USE_ES6)\nDUK_INTERNAL duk_ret_t duk_bi_math_object_imul(duk_hthread *thr) {\n\tduk_uint32_t x, y, z;\n\n\tx = duk_to_uint32(thr, 0);\n\ty = duk_to_uint32(thr, 1);\n\tz = x * y;\n\n\t/* While arguments are ToUint32() coerced and the multiplication\n\t * is unsigned as such, the final result is curiously interpreted\n\t * as a signed 32-bit value.\n\t */\n\tduk_push_i32(thr, (duk_int32_t) z);\n\treturn 1;\n}\n#endif  /* DUK_USE_ES6 */\n\n#endif  /* DUK_USE_MATH_BUILTIN */\n#line 1 \"duk_bi_number.c\"\n/*\n *  Number built-ins\n */\n\n/* #include duk_internal.h -> already included */\n\n#if defined(DUK_USE_NUMBER_BUILTIN)\n\nDUK_LOCAL duk_double_t duk__push_this_number_plain(duk_hthread *thr) {\n\tduk_hobject *h;\n\n\t/* Number built-in accepts a plain number or a Number object (whose\n\t * internal value is operated on).  Other types cause TypeError.\n\t */\n\n\tduk_push_this(thr);\n\tif (duk_is_number(thr, -1)) {\n\t\tDUK_DDD(DUK_DDDPRINT(\"plain number value: %!T\", (duk_tval *) duk_get_tval(thr, -1)));\n\t\tgoto done;\n\t}\n\th = duk_get_hobject(thr, -1);\n\tif (!h ||\n\t    (DUK_HOBJECT_GET_CLASS_NUMBER(h) != DUK_HOBJECT_CLASS_NUMBER)) {\n\t\tDUK_DDD(DUK_DDDPRINT(\"unacceptable this value: %!T\", (duk_tval *) duk_get_tval(thr, -1)));\n\t\tDUK_ERROR_TYPE(thr, \"number expected\");\n\t}\n\tduk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INT_VALUE);\n\tDUK_ASSERT(duk_is_number(thr, -1));\n\tDUK_DDD(DUK_DDDPRINT(\"number object: %!T, internal value: %!T\",\n\t                     (duk_tval *) duk_get_tval(thr, -2), (duk_tval *) duk_get_tval(thr, -1)));\n\tduk_remove_m2(thr);\n\n done:\n\treturn duk_get_number(thr, -1);\n}\n\nDUK_INTERNAL duk_ret_t duk_bi_number_constructor(duk_hthread *thr) {\n\tduk_idx_t nargs;\n\tduk_hobject *h_this;\n\n\t/*\n\t *  The Number constructor uses ToNumber(arg) for number coercion\n\t *  (coercing an undefined argument to NaN).  However, if the\n\t *  argument is not given at all, +0 must be used instead.  To do\n\t *  this, a vararg function is used.\n\t */\n\n\tnargs = duk_get_top(thr);\n\tif (nargs == 0) {\n\t\tduk_push_int(thr, 0);\n\t}\n\tduk_to_number(thr, 0);\n\tduk_set_top(thr, 1);\n\tDUK_ASSERT_TOP(thr, 1);\n\n\tif (!duk_is_constructor_call(thr)) {\n\t\treturn 1;\n\t}\n\n\t/*\n\t *  E5 Section 15.7.2.1 requires that the constructed object\n\t *  must have the original Number.prototype as its internal\n\t *  prototype.  However, since Number.prototype is non-writable\n\t *  and non-configurable, this doesn't have to be enforced here:\n\t *  The default object (bound to 'this') is OK, though we have\n\t *  to change its class.\n\t *\n\t *  Internal value set to ToNumber(arg) or +0; if no arg given,\n\t *  ToNumber(undefined) = NaN, so special treatment is needed\n\t *  (above).  String internal value is immutable.\n\t */\n\n\t/* XXX: helper */\n\tduk_push_this(thr);\n\th_this = duk_known_hobject(thr, -1);\n\tDUK_HOBJECT_SET_CLASS_NUMBER(h_this, DUK_HOBJECT_CLASS_NUMBER);\n\n\tDUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h_this) == thr->builtins[DUK_BIDX_NUMBER_PROTOTYPE]);\n\tDUK_ASSERT(DUK_HOBJECT_GET_CLASS_NUMBER(h_this) == DUK_HOBJECT_CLASS_NUMBER);\n\tDUK_ASSERT(DUK_HOBJECT_HAS_EXTENSIBLE(h_this));\n\n\tduk_dup_0(thr);  /* -> [ val obj val ] */\n\tduk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_NONE);\n\treturn 0;  /* no return value -> don't replace created value */\n}\n\nDUK_INTERNAL duk_ret_t duk_bi_number_prototype_value_of(duk_hthread *thr) {\n\t(void) duk__push_this_number_plain(thr);\n\treturn 1;\n}\n\nDUK_INTERNAL duk_ret_t duk_bi_number_prototype_to_string(duk_hthread *thr) {\n\tduk_small_int_t radix;\n\tduk_small_uint_t n2s_flags;\n\n\t(void) duk__push_this_number_plain(thr);\n\tif (duk_is_undefined(thr, 0)) {\n\t\tradix = 10;\n\t} else {\n\t\tradix = (duk_small_int_t) duk_to_int_check_range(thr, 0, 2, 36);\n\t}\n\tDUK_DDD(DUK_DDDPRINT(\"radix=%ld\", (long) radix));\n\n\tn2s_flags = 0;\n\n\tduk_numconv_stringify(thr,\n\t                      radix /*radix*/,\n\t                      0 /*digits*/,\n\t                      n2s_flags /*flags*/);\n\treturn 1;\n}\n\nDUK_INTERNAL duk_ret_t duk_bi_number_prototype_to_locale_string(duk_hthread *thr) {\n\t/* XXX: just use toString() for now; permitted although not recommended.\n\t * nargs==1, so radix is passed to toString().\n\t */\n\treturn duk_bi_number_prototype_to_string(thr);\n}\n\n/*\n *  toFixed(), toExponential(), toPrecision()\n */\n\n/* XXX: shared helper for toFixed(), toExponential(), toPrecision()? */\n\nDUK_INTERNAL duk_ret_t duk_bi_number_prototype_to_fixed(duk_hthread *thr) {\n\tduk_small_int_t frac_digits;\n\tduk_double_t d;\n\tduk_small_int_t c;\n\tduk_small_uint_t n2s_flags;\n\n\tfrac_digits = (duk_small_int_t) duk_to_int_check_range(thr, 0, 0, 20);\n\td = duk__push_this_number_plain(thr);\n\n\tc = (duk_small_int_t) DUK_FPCLASSIFY(d);\n\tif (c == DUK_FP_NAN || c == DUK_FP_INFINITE) {\n\t\tgoto use_to_string;\n\t}\n\n\tif (d >= 1.0e21 || d <= -1.0e21) {\n\t\tgoto use_to_string;\n\t}\n\n\tn2s_flags = DUK_N2S_FLAG_FIXED_FORMAT |\n\t            DUK_N2S_FLAG_FRACTION_DIGITS;\n\n\tduk_numconv_stringify(thr,\n\t                      10 /*radix*/,\n\t                      frac_digits /*digits*/,\n\t                      n2s_flags /*flags*/);\n\treturn 1;\n\n use_to_string:\n\tDUK_ASSERT_TOP(thr, 2);\n\tduk_to_string(thr, -1);\n\treturn 1;\n}\n\nDUK_INTERNAL duk_ret_t duk_bi_number_prototype_to_exponential(duk_hthread *thr) {\n\tduk_bool_t frac_undefined;\n\tduk_small_int_t frac_digits;\n\tduk_double_t d;\n\tduk_small_int_t c;\n\tduk_small_uint_t n2s_flags;\n\n\td = duk__push_this_number_plain(thr);\n\n\tfrac_undefined = duk_is_undefined(thr, 0);\n\tduk_to_int(thr, 0);  /* for side effects */\n\n\tc = (duk_small_int_t) DUK_FPCLASSIFY(d);\n\tif (c == DUK_FP_NAN || c == DUK_FP_INFINITE) {\n\t\tgoto use_to_string;\n\t}\n\n\tfrac_digits = (duk_small_int_t) duk_to_int_check_range(thr, 0, 0, 20);\n\n\tn2s_flags = DUK_N2S_FLAG_FORCE_EXP |\n\t           (frac_undefined ? 0 : DUK_N2S_FLAG_FIXED_FORMAT);\n\n\tduk_numconv_stringify(thr,\n\t                      10 /*radix*/,\n\t                      frac_digits + 1 /*leading digit + fractions*/,\n\t                      n2s_flags /*flags*/);\n\treturn 1;\n\n use_to_string:\n\tDUK_ASSERT_TOP(thr, 2);\n\tduk_to_string(thr, -1);\n\treturn 1;\n}\n\nDUK_INTERNAL duk_ret_t duk_bi_number_prototype_to_precision(duk_hthread *thr) {\n\t/* The specification has quite awkward order of coercion and\n\t * checks for toPrecision().  The operations below are a bit\n\t * reordered, within constraints of observable side effects.\n\t */\n\n\tduk_double_t d;\n\tduk_small_int_t prec;\n\tduk_small_int_t c;\n\tduk_small_uint_t n2s_flags;\n\n\tDUK_ASSERT_TOP(thr, 1);\n\n\td = duk__push_this_number_plain(thr);\n\tif (duk_is_undefined(thr, 0)) {\n\t\tgoto use_to_string;\n\t}\n\tDUK_ASSERT_TOP(thr, 2);\n\n\tduk_to_int(thr, 0);  /* for side effects */\n\n\tc = (duk_small_int_t) DUK_FPCLASSIFY(d);\n\tif (c == DUK_FP_NAN || c == DUK_FP_INFINITE) {\n\t\tgoto use_to_string;\n\t}\n\n\tprec = (duk_small_int_t) duk_to_int_check_range(thr, 0, 1, 21);\n\n\tn2s_flags = DUK_N2S_FLAG_FIXED_FORMAT |\n\t            DUK_N2S_FLAG_NO_ZERO_PAD;\n\n\tduk_numconv_stringify(thr,\n\t                      10 /*radix*/,\n\t                      prec /*digits*/,\n\t                      n2s_flags /*flags*/);\n\treturn 1;\n\n use_to_string:\n\t/* Used when precision is undefined; also used for NaN (-> \"NaN\"),\n\t * and +/- infinity (-> \"Infinity\", \"-Infinity\").\n\t */\n\n\tDUK_ASSERT_TOP(thr, 2);\n\tduk_to_string(thr, -1);\n\treturn 1;\n}\n\n#endif  /* DUK_USE_NUMBER_BUILTIN */\n#line 1 \"duk_bi_object.c\"\n/*\n *  Object built-ins\n */\n\n/* #include duk_internal.h -> already included */\n\n/* Needed even when Object built-in disabled. */\nDUK_INTERNAL duk_ret_t duk_bi_object_prototype_to_string(duk_hthread *thr) {\n\tduk_tval *tv;\n\ttv = DUK_HTHREAD_THIS_PTR(thr);\n\t/* XXX: This is not entirely correct anymore; in ES2015 the\n\t * default lookup should use @@toStringTag to come up with\n\t * e.g. [object Symbol].\n\t */\n\tduk_push_class_string_tval(thr, tv);\n\treturn 1;\n}\n\n#if defined(DUK_USE_OBJECT_BUILTIN)\nDUK_INTERNAL duk_ret_t duk_bi_object_constructor(duk_hthread *thr) {\n\tduk_uint_t arg_mask;\n\n\targ_mask = duk_get_type_mask(thr, 0);\n\n\tif (!duk_is_constructor_call(thr) &&  /* not a constructor call */\n\t    ((arg_mask & (DUK_TYPE_MASK_NULL | DUK_TYPE_MASK_UNDEFINED)) == 0)) {  /* and argument not null or undefined */\n\t\tduk_to_object(thr, 0);\n\t\treturn 1;\n\t}\n\n\t/* Pointer and buffer primitive values are treated like other\n\t * primitives values which have a fully fledged object counterpart:\n\t * promote to an object value.  Lightfuncs and plain buffers are\n\t * coerced with ToObject() even they could also be returned as is.\n\t */\n\tif (arg_mask & (DUK_TYPE_MASK_OBJECT |\n\t                DUK_TYPE_MASK_STRING |\n\t                DUK_TYPE_MASK_BOOLEAN |\n\t                DUK_TYPE_MASK_NUMBER |\n\t                DUK_TYPE_MASK_POINTER |\n\t                DUK_TYPE_MASK_BUFFER |\n\t                DUK_TYPE_MASK_LIGHTFUNC)) {\n\t\t/* For DUK_TYPE_OBJECT the coercion is a no-op and could\n\t\t * be checked for explicitly, but Object(obj) calls are\n\t\t * not very common so opt for minimal footprint.\n\t\t */\n\t\tduk_to_object(thr, 0);\n\t\treturn 1;\n\t}\n\n\t(void) duk_push_object_helper(thr,\n\t                              DUK_HOBJECT_FLAG_EXTENSIBLE |\n\t                              DUK_HOBJECT_FLAG_FASTREFS |\n\t                              DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT),\n\t                              DUK_BIDX_OBJECT_PROTOTYPE);\n\treturn 1;\n}\n#endif  /* DUK_USE_OBJECT_BUILTIN */\n\n#if defined(DUK_USE_OBJECT_BUILTIN) && defined(DUK_USE_ES6)\nDUK_INTERNAL duk_ret_t duk_bi_object_constructor_assign(duk_hthread *thr) {\n\tduk_idx_t nargs;\n\tduk_int_t idx;\n\n\tnargs = duk_get_top_require_min(thr, 1 /*min_top*/);\n\n\tduk_to_object(thr, 0);\n\tfor (idx = 1; idx < nargs; idx++) {\n\t\t/* E7 19.1.2.1 (step 4a) */\n\t\tif (duk_is_null_or_undefined(thr, idx)) {\n\t\t\tcontinue;\n\t\t}\n\n\t\t/* duk_enum() respects ES2015+ [[OwnPropertyKeys]] ordering, which is\n\t\t * convenient here.\n\t\t */\n\t\tduk_to_object(thr, idx);\n\t\tduk_enum(thr, idx, DUK_ENUM_OWN_PROPERTIES_ONLY);\n\t\twhile (duk_next(thr, -1, 1 /*get_value*/)) {\n\t\t\t/* [ target ... enum key value ] */\n\t\t\tduk_put_prop(thr, 0);\n\t\t\t/* [ target ... enum ] */\n\t\t}\n\t\t/* Could pop enumerator, but unnecessary because of duk_set_top()\n\t\t * below.\n\t\t */\n\t}\n\n\tduk_set_top(thr, 1);\n\treturn 1;\n}\n#endif\n\n#if defined(DUK_USE_OBJECT_BUILTIN) && defined(DUK_USE_ES6)\nDUK_INTERNAL duk_ret_t duk_bi_object_constructor_is(duk_hthread *thr) {\n\tDUK_ASSERT_TOP(thr, 2);\n\tduk_push_boolean(thr, duk_samevalue(thr, 0, 1));\n\treturn 1;\n}\n#endif\n\n#if defined(DUK_USE_OBJECT_BUILTIN)\nDUK_INTERNAL duk_ret_t duk_bi_object_constructor_create(duk_hthread *thr) {\n\tduk_hobject *proto;\n\n\tDUK_ASSERT_TOP(thr, 2);\n\n#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)\n\tduk_hbufobj_promote_plain(thr, 0);\n#endif\n\tproto = duk_require_hobject_accept_mask(thr, 0, DUK_TYPE_MASK_NULL);\n\tDUK_ASSERT(proto != NULL || duk_is_null(thr, 0));\n\n\t(void) duk_push_object_helper_proto(thr,\n\t                                    DUK_HOBJECT_FLAG_EXTENSIBLE |\n\t                                    DUK_HOBJECT_FLAG_FASTREFS |\n\t                                    DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT),\n\t                                    proto);\n\n\tif (!duk_is_undefined(thr, 1)) {\n\t\t/* [ O Properties obj ] */\n\n\t\tduk_replace(thr, 0);\n\n\t\t/* [ obj Properties ] */\n\n\t\t/* Just call the \"original\" Object.defineProperties() to\n\t\t * finish up.\n\t\t */\n\n\t\treturn duk_bi_object_constructor_define_properties(thr);\n\t}\n\n\t/* [ O Properties obj ] */\n\n\treturn 1;\n}\n#endif  /* DUK_USE_OBJECT_BUILTIN */\n\n#if defined(DUK_USE_OBJECT_BUILTIN)\nDUK_INTERNAL duk_ret_t duk_bi_object_constructor_define_properties(duk_hthread *thr) {\n\tduk_small_uint_t pass;\n\tduk_uint_t defprop_flags;\n\tduk_hobject *obj;\n\tduk_idx_t idx_value;\n\tduk_hobject *get;\n\tduk_hobject *set;\n\n\t/* Lightfunc and plain buffer handling by ToObject() coercion. */\n\tobj = duk_require_hobject_promote_mask(thr, 0, DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER);\n\tDUK_ASSERT(obj != NULL);\n\n\tduk_to_object(thr, 1);        /* properties object */\n\n\tDUK_DDD(DUK_DDDPRINT(\"target=%!iT, properties=%!iT\",\n\t                     (duk_tval *) duk_get_tval(thr, 0),\n\t                     (duk_tval *) duk_get_tval(thr, 1)));\n\n\t/*\n\t *  Two pass approach to processing the property descriptors.\n\t *  On first pass validate and normalize all descriptors before\n\t *  any changes are made to the target object.  On second pass\n\t *  make the actual modifications to the target object.\n\t *\n\t *  Right now we'll just use the same normalize/validate helper\n\t *  on both passes, ignoring its outputs on the first pass.\n\t */\n\n\tfor (pass = 0; pass < 2; pass++) {\n\t\tduk_set_top(thr, 2);  /* -> [ hobject props ] */\n\t\tduk_enum(thr, 1, DUK_ENUM_OWN_PROPERTIES_ONLY | DUK_ENUM_INCLUDE_SYMBOLS /*enum_flags*/);\n\n\t\tfor (;;) {\n\t\t\tduk_hstring *key;\n\n\t\t\t/* [ hobject props enum(props) ] */\n\n\t\t\tduk_set_top(thr, 3);\n\n\t\t\tif (!duk_next(thr, 2, 1 /*get_value*/)) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"-> key=%!iT, desc=%!iT\",\n\t\t\t                     (duk_tval *) duk_get_tval(thr, -2),\n\t\t\t                     (duk_tval *) duk_get_tval(thr, -1)));\n\n\t\t\t/* [ hobject props enum(props) key desc ] */\n\n\t\t\tduk_hobject_prepare_property_descriptor(thr,\n\t\t\t                                        4 /*idx_desc*/,\n\t\t\t                                        &defprop_flags,\n\t\t\t                                        &idx_value,\n\t\t\t                                        &get,\n\t\t\t                                        &set);\n\n\t\t\t/* [ hobject props enum(props) key desc [multiple values] ] */\n\n\t\t\tif (pass == 0) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t/* This allows symbols on purpose. */\n\t\t\tkey = duk_known_hstring(thr, 3);\n\t\t\tDUK_ASSERT(key != NULL);\n\n\t\t\tduk_hobject_define_property_helper(thr,\n\t\t\t                                   defprop_flags,\n\t\t\t                                   obj,\n\t\t\t                                   key,\n\t\t\t                                   idx_value,\n\t\t\t                                   get,\n\t\t\t                                   set,\n\t\t\t                                   1 /*throw_flag*/);\n\t\t}\n\t}\n\n\t/*\n\t *  Return target object\n\t */\n\n\tduk_dup_0(thr);\n\treturn 1;\n}\n#endif  /* DUK_USE_OBJECT_BUILTIN */\n\n#if defined(DUK_USE_OBJECT_BUILTIN)\nDUK_INTERNAL duk_ret_t duk_bi_object_constructor_seal_freeze_shared(duk_hthread *thr) {\n\tDUK_ASSERT_TOP(thr, 1);\n\n\tduk_seal_freeze_raw(thr, 0, (duk_bool_t) duk_get_current_magic(thr) /*is_freeze*/);\n\treturn 1;\n}\n#endif  /* DUK_USE_OBJECT_BUILTIN */\n\n#if defined(DUK_USE_OBJECT_BUILTIN)\nDUK_INTERNAL duk_ret_t duk_bi_object_constructor_is_sealed_frozen_shared(duk_hthread *thr) {\n\tduk_hobject *h;\n\tduk_bool_t is_frozen;\n\tduk_uint_t mask;\n\n\tis_frozen = (duk_bool_t) duk_get_current_magic(thr);\n\tmask = duk_get_type_mask(thr, 0);\n\tif (mask & (DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER)) {\n\t\tDUK_ASSERT(is_frozen == 0 || is_frozen == 1);\n\t\tduk_push_boolean(thr, (mask & DUK_TYPE_MASK_LIGHTFUNC) ?\n\t\t                          1 :               /* lightfunc always frozen and sealed */\n\t\t                          (is_frozen ^ 1)); /* buffer sealed but not frozen (index props writable) */\n\t} else {\n\t\t/* ES2015 Sections 19.1.2.12, 19.1.2.13: anything other than an object\n\t\t * is considered to be already sealed and frozen.\n\t\t */\n\t\th = duk_get_hobject(thr, 0);\n\t\tduk_push_boolean(thr, (h == NULL) ||\n\t\t                      duk_hobject_object_is_sealed_frozen_helper(thr, h, is_frozen /*is_frozen*/));\n\t}\n\treturn 1;\n}\n#endif  /* DUK_USE_OBJECT_BUILTIN */\n\n#if defined(DUK_USE_OBJECT_BUILTIN)\nDUK_INTERNAL duk_ret_t duk_bi_object_prototype_to_locale_string(duk_hthread *thr) {\n\tDUK_ASSERT_TOP(thr, 0);\n\t(void) duk_push_this_coercible_to_object(thr);\n\tduk_get_prop_stridx_short(thr, 0, DUK_STRIDX_TO_STRING);\n#if 0  /* This is mentioned explicitly in the E5.1 spec, but duk_call_method() checks for it in practice. */\n\tduk_require_callable(thr, 1);\n#endif\n\tduk_dup_0(thr);  /* -> [ O toString O ] */\n\tduk_call_method(thr, 0);  /* XXX: call method tail call? */\n\treturn 1;\n}\n#endif  /* DUK_USE_OBJECT_BUILTIN */\n\n#if defined(DUK_USE_OBJECT_BUILTIN)\nDUK_INTERNAL duk_ret_t duk_bi_object_prototype_value_of(duk_hthread *thr) {\n\t/* For lightfuncs and plain buffers, returns Object() coerced. */\n\t(void) duk_push_this_coercible_to_object(thr);\n\treturn 1;\n}\n#endif  /* DUK_USE_OBJECT_BUILTIN */\n\n#if defined(DUK_USE_OBJECT_BUILTIN)\nDUK_INTERNAL duk_ret_t duk_bi_object_prototype_is_prototype_of(duk_hthread *thr) {\n\tduk_hobject *h_v;\n\tduk_hobject *h_obj;\n\n\tDUK_ASSERT_TOP(thr, 1);\n\n\th_v = duk_get_hobject(thr, 0);\n\tif (!h_v) {\n\t\tduk_push_false(thr);  /* XXX: tail call: return duk_push_false(thr) */\n\t\treturn 1;\n\t}\n\n\th_obj = duk_push_this_coercible_to_object(thr);\n\tDUK_ASSERT(h_obj != NULL);\n\n\t/* E5.1 Section 15.2.4.6, step 3.a, lookup proto once before compare.\n\t * Prototype loops should cause an error to be thrown.\n\t */\n\tduk_push_boolean(thr, duk_hobject_prototype_chain_contains(thr, DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h_v), h_obj, 0 /*ignore_loop*/));\n\treturn 1;\n}\n#endif  /* DUK_USE_OBJECT_BUILTIN */\n\n#if defined(DUK_USE_OBJECT_BUILTIN)\nDUK_INTERNAL duk_ret_t duk_bi_object_prototype_has_own_property(duk_hthread *thr) {\n\treturn (duk_ret_t) duk_hobject_object_ownprop_helper(thr, 0 /*required_desc_flags*/);\n}\n#endif  /* DUK_USE_OBJECT_BUILTIN */\n\n#if defined(DUK_USE_OBJECT_BUILTIN)\nDUK_INTERNAL duk_ret_t duk_bi_object_prototype_property_is_enumerable(duk_hthread *thr) {\n\treturn (duk_ret_t) duk_hobject_object_ownprop_helper(thr, DUK_PROPDESC_FLAG_ENUMERABLE /*required_desc_flags*/);\n}\n#endif  /* DUK_USE_OBJECT_BUILTIN */\n\n#if defined(DUK_USE_OBJECT_BUILTIN) || defined(DUK_USE_REFLECT_BUILTIN)\n/* Shared helper to implement Object.getPrototypeOf,\n * Object.prototype.__proto__ getter, and Reflect.getPrototypeOf.\n *\n * http://www.ecma-international.org/ecma-262/6.0/index.html#sec-get-object.prototype.__proto__\n */\nDUK_INTERNAL duk_ret_t duk_bi_object_getprototype_shared(duk_hthread *thr) {\n\t/*\n\t *  magic = 0: __proto__ getter\n\t *  magic = 1: Object.getPrototypeOf()\n\t *  magic = 2: Reflect.getPrototypeOf()\n\t */\n\n\tduk_hobject *h;\n\tduk_hobject *proto;\n\tduk_tval *tv;\n\tduk_int_t magic;\n\n\tmagic = duk_get_current_magic(thr);\n\n\tif (magic == 0) {\n\t\tDUK_ASSERT_TOP(thr, 0);\n\t\tduk_push_this_coercible_to_object(thr);\n\t}\n\tDUK_ASSERT(duk_get_top(thr) >= 1);\n\tif (magic < 2) {\n\t\t/* ES2015 Section 19.1.2.9, step 1 */\n\t\tduk_to_object(thr, 0);\n\t}\n\ttv = DUK_GET_TVAL_POSIDX(thr, 0);\n\n\tswitch (DUK_TVAL_GET_TAG(tv)) {\n\tcase DUK_TAG_BUFFER:\n\t\tproto = thr->builtins[DUK_BIDX_UINT8ARRAY_PROTOTYPE];\n\t\tbreak;\n\tcase DUK_TAG_LIGHTFUNC:\n\t\tproto = thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE];\n\t\tbreak;\n\tcase DUK_TAG_OBJECT:\n\t\th = DUK_TVAL_GET_OBJECT(tv);\n\t\tproto = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h);\n\t\tbreak;\n\tdefault:\n\t\t/* This implicitly handles CheckObjectCoercible() caused\n\t\t * TypeError.\n\t\t */\n\t\tDUK_DCERROR_TYPE_INVALID_ARGS(thr);\n\t}\n\tif (proto != NULL) {\n\t\tduk_push_hobject(thr, proto);\n\t} else {\n\t\tduk_push_null(thr);\n\t}\n\treturn 1;\n}\n#endif  /* DUK_USE_OBJECT_BUILTIN || DUK_USE_REFLECT_BUILTIN */\n\n#if defined(DUK_USE_OBJECT_BUILTIN) || defined(DUK_USE_REFLECT_BUILTIN)\n/* Shared helper to implement ES2015 Object.setPrototypeOf,\n * Object.prototype.__proto__ setter, and Reflect.setPrototypeOf.\n *\n * http://www.ecma-international.org/ecma-262/6.0/index.html#sec-get-object.prototype.__proto__\n * http://www.ecma-international.org/ecma-262/6.0/index.html#sec-object.setprototypeof\n */\nDUK_INTERNAL duk_ret_t duk_bi_object_setprototype_shared(duk_hthread *thr) {\n\t/*\n\t *  magic = 0: __proto__ setter\n\t *  magic = 1: Object.setPrototypeOf()\n\t *  magic = 2: Reflect.setPrototypeOf()\n\t */\n\n\tduk_hobject *h_obj;\n\tduk_hobject *h_new_proto;\n\tduk_hobject *h_curr;\n\tduk_ret_t ret_success = 1;  /* retval for success path */\n\tduk_uint_t mask;\n\tduk_int_t magic;\n\n\t/* Preliminaries for __proto__ and setPrototypeOf (E6 19.1.2.18 steps 1-4). */\n\tmagic = duk_get_current_magic(thr);\n\tif (magic == 0) {\n\t\tduk_push_this_check_object_coercible(thr);\n\t\tduk_insert(thr, 0);\n\t\tif (!duk_check_type_mask(thr, 1, DUK_TYPE_MASK_NULL | DUK_TYPE_MASK_OBJECT)) {\n\t\t\treturn 0;\n\t\t}\n\n\t\t/* __proto__ setter returns 'undefined' on success unlike the\n\t\t * setPrototypeOf() call which returns the target object.\n\t\t */\n\t\tret_success = 0;\n\t} else {\n\t\tif (magic == 1) {\n\t\t\tduk_require_object_coercible(thr, 0);\n\t\t} else {\n\t\t\tduk_require_hobject_accept_mask(thr, 0,\n\t\t\t                                DUK_TYPE_MASK_LIGHTFUNC |\n\t\t\t                                DUK_TYPE_MASK_BUFFER);\n\t\t}\n\t\tduk_require_type_mask(thr, 1, DUK_TYPE_MASK_NULL | DUK_TYPE_MASK_OBJECT);\n\t}\n\n\th_new_proto = duk_get_hobject(thr, 1);\n\t/* h_new_proto may be NULL */\n\n\tmask = duk_get_type_mask(thr, 0);\n\tif (mask & (DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER)) {\n\t\tduk_hobject *curr_proto;\n\t\tcurr_proto = thr->builtins[(mask & DUK_TYPE_MASK_LIGHTFUNC) ?\n\t\t                               DUK_BIDX_FUNCTION_PROTOTYPE :\n\t\t                               DUK_BIDX_UINT8ARRAY_PROTOTYPE];\n\t\tif (h_new_proto == curr_proto) {\n\t\t\tgoto skip;\n\t\t}\n\t\tgoto fail_nonextensible;\n\t}\n\th_obj = duk_get_hobject(thr, 0);\n\tif (h_obj == NULL) {\n\t\tgoto skip;\n\t}\n\tDUK_ASSERT(h_obj != NULL);\n\n\t/* [[SetPrototypeOf]] standard behavior, E6 9.1.2. */\n\t/* TODO: implement Proxy object support here */\n\n\tif (h_new_proto == DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h_obj)) {\n\t\tgoto skip;\n\t}\n\tif (!DUK_HOBJECT_HAS_EXTENSIBLE(h_obj)) {\n\t\tgoto fail_nonextensible;\n\t}\n\tfor (h_curr = h_new_proto; h_curr != NULL; h_curr = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h_curr)) {\n\t\t/* Loop prevention. */\n\t\tif (h_curr == h_obj) {\n\t\t\tgoto fail_loop;\n\t\t}\n\t}\n\tDUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, h_obj, h_new_proto);\n\t/* fall thru */\n\n skip:\n\tduk_set_top(thr, 1);\n\tif (magic == 2) {\n\t\tduk_push_true(thr);\n\t}\n\treturn ret_success;\n\n fail_nonextensible:\n fail_loop:\n\tif (magic != 2) {\n\t\tDUK_DCERROR_TYPE_INVALID_ARGS(thr);\n\t} else {\n\t\tduk_push_false(thr);\n\t\treturn 1;\n\t}\n}\n#endif  /* DUK_USE_OBJECT_BUILTIN || DUK_USE_REFLECT_BUILTIN */\n\n#if defined(DUK_USE_OBJECT_BUILTIN) || defined(DUK_USE_REFLECT_BUILTIN)\nDUK_INTERNAL duk_ret_t duk_bi_object_constructor_define_property(duk_hthread *thr) {\n\t/*\n\t *  magic = 0: Object.defineProperty()\n\t *  magic = 1: Reflect.defineProperty()\n\t */\n\n\tduk_hobject *obj;\n\tduk_hstring *key;\n\tduk_hobject *get;\n\tduk_hobject *set;\n\tduk_idx_t idx_value;\n\tduk_uint_t defprop_flags;\n\tduk_small_uint_t magic;\n\tduk_bool_t throw_flag;\n\tduk_bool_t ret;\n\n\tDUK_ASSERT(thr != NULL);\n\n\tDUK_DDD(DUK_DDDPRINT(\"Object.defineProperty(): ctx=%p obj=%!T key=%!T desc=%!T\",\n\t                     (void *) thr,\n\t                     (duk_tval *) duk_get_tval(thr, 0),\n\t                     (duk_tval *) duk_get_tval(thr, 1),\n\t                     (duk_tval *) duk_get_tval(thr, 2)));\n\n\t/* [ obj key desc ] */\n\n\tmagic = (duk_small_uint_t) duk_get_current_magic(thr);\n\n\t/* Lightfuncs are currently supported by coercing to a temporary\n\t * Function object; changes will be allowed (the coerced value is\n\t * extensible) but will be lost.  Same for plain buffers.\n\t */\n\tobj = duk_require_hobject_promote_mask(thr, 0, DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER);\n\tDUK_ASSERT(obj != NULL);\n\tkey = duk_to_property_key_hstring(thr, 1);\n\t(void) duk_require_hobject(thr, 2);\n\n\tDUK_ASSERT(obj != NULL);\n\tDUK_ASSERT(key != NULL);\n\tDUK_ASSERT(duk_get_hobject(thr, 2) != NULL);\n\n\t/*\n\t *  Validate and convert argument property descriptor (an Ecmascript\n\t *  object) into a set of defprop_flags and possibly property value,\n\t *  getter, and/or setter values on the value stack.\n\t *\n\t *  Lightfunc set/get values are coerced to full Functions.\n\t */\n\n\tduk_hobject_prepare_property_descriptor(thr,\n\t                                        2 /*idx_desc*/,\n\t                                        &defprop_flags,\n\t                                        &idx_value,\n\t                                        &get,\n\t                                        &set);\n\n\t/*\n\t *  Use Object.defineProperty() helper for the actual operation.\n\t */\n\n\tDUK_ASSERT(magic == 0U || magic == 1U);\n\tthrow_flag = magic ^ 1U;\n\tret = duk_hobject_define_property_helper(thr,\n\t                                         defprop_flags,\n\t                                         obj,\n\t                                         key,\n\t                                         idx_value,\n\t                                         get,\n\t                                         set,\n\t                                         throw_flag);\n\n\t/* Ignore the normalize/validate helper outputs on the value stack,\n\t * they're popped automatically.\n\t */\n\n\tif (magic == 0U) {\n\t\t/* Object.defineProperty(): return target object. */\n\t\tduk_push_hobject(thr, obj);\n\t} else {\n\t\t/* Reflect.defineProperty(): return success/fail. */\n\t\tduk_push_boolean(thr, ret);\n\t}\n\treturn 1;\n}\n#endif  /* DUK_USE_OBJECT_BUILTIN || DUK_USE_REFLECT_BUILTIN */\n\n#if defined(DUK_USE_OBJECT_BUILTIN) || defined(DUK_USE_REFLECT_BUILTIN)\nDUK_INTERNAL duk_ret_t duk_bi_object_constructor_get_own_property_descriptor(duk_hthread *thr) {\n\tDUK_ASSERT_TOP(thr, 2);\n\n\t/* ES2015 Section 19.1.2.6, step 1 */\n\tif (duk_get_current_magic(thr) == 0) {\n\t\tduk_to_object(thr, 0);\n\t}\n\n\t/* [ obj key ] */\n\n\tduk_hobject_object_get_own_property_descriptor(thr, -2);\n\treturn 1;\n}\n#endif  /* DUK_USE_OBJECT_BUILTIN || DUK_USE_REFLECT_BUILTIN */\n\n#if defined(DUK_USE_OBJECT_BUILTIN) || defined(DUK_USE_REFLECT_BUILTIN)\nDUK_INTERNAL duk_ret_t duk_bi_object_constructor_is_extensible(duk_hthread *thr) {\n\t/*\n\t *  magic = 0: Object.isExtensible()\n\t *  magic = 1: Reflect.isExtensible()\n\t */\n\n\tduk_hobject *h;\n\n\tif (duk_get_current_magic(thr) == 0) {\n\t\th = duk_get_hobject(thr, 0);\n\t} else {\n\t\t/* Reflect.isExtensible(): throw if non-object, but we accept lightfuncs\n\t\t * and plain buffers here because they pretend to be objects.\n\t\t */\n\t\th = duk_require_hobject_accept_mask(thr, 0, DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER);\n\t}\n\n\tduk_push_boolean(thr, (h != NULL) && DUK_HOBJECT_HAS_EXTENSIBLE(h));\n\treturn 1;\n}\n#endif  /* DUK_USE_OBJECT_BUILTIN || DUK_USE_REFLECT_BUILTIN */\n\n#if defined(DUK_USE_OBJECT_BUILTIN) || defined(DUK_USE_REFLECT_BUILTIN)\n/* Shared helper for various key/symbol listings, magic:\n * 0=Object.keys()\n * 1=Object.getOwnPropertyNames(),\n * 2=Object.getOwnPropertySymbols(),\n * 3=Reflect.ownKeys()\n */\nDUK_LOCAL const duk_small_uint_t duk__object_keys_enum_flags[4] = {\n\t/* Object.keys() */\n\tDUK_ENUM_OWN_PROPERTIES_ONLY |\n\t    DUK_ENUM_NO_PROXY_BEHAVIOR,\n\n\t/* Object.getOwnPropertyNames() */\n\tDUK_ENUM_INCLUDE_NONENUMERABLE |\n\t    DUK_ENUM_OWN_PROPERTIES_ONLY |\n\t    DUK_ENUM_NO_PROXY_BEHAVIOR,\n\n\t/* Object.getOwnPropertySymbols() */\n\tDUK_ENUM_INCLUDE_SYMBOLS |\n\t    DUK_ENUM_OWN_PROPERTIES_ONLY |\n\t    DUK_ENUM_EXCLUDE_STRINGS |\n\t    DUK_ENUM_INCLUDE_NONENUMERABLE |\n\t    DUK_ENUM_NO_PROXY_BEHAVIOR,\n\n\t/* Reflect.ownKeys() */\n\tDUK_ENUM_INCLUDE_SYMBOLS |\n\t    DUK_ENUM_OWN_PROPERTIES_ONLY |\n\t    DUK_ENUM_INCLUDE_NONENUMERABLE |\n\t    DUK_ENUM_NO_PROXY_BEHAVIOR\n};\n\nDUK_INTERNAL duk_ret_t duk_bi_object_constructor_keys_shared(duk_hthread *thr) {\n\tduk_hobject *obj;\n#if defined(DUK_USE_ES6_PROXY)\n\tduk_hobject *h_proxy_target;\n\tduk_hobject *h_proxy_handler;\n\tduk_hobject *h_trap_result;\n#endif\n\tduk_small_uint_t enum_flags;\n\tduk_int_t magic;\n\n\tDUK_ASSERT_TOP(thr, 1);\n\n\tmagic = duk_get_current_magic(thr);\n\tif (magic == 3) {\n\t\t/* ES2015 Section 26.1.11 requires a TypeError for non-objects.  Lightfuncs\n\t\t * and plain buffers pretend to be objects, so accept those too.\n\t\t */\n\t\tobj = duk_require_hobject_promote_mask(thr, 0, DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER);\n\t} else {\n\t\t/* ES2015: ToObject coerce. */\n\t\tobj = duk_to_hobject(thr, 0);\n\t}\n\tDUK_ASSERT(obj != NULL);\n\tDUK_UNREF(obj);\n\n\t/* XXX: proxy chains */\n\n#if defined(DUK_USE_ES6_PROXY)\n\t/* XXX: better sharing of code between proxy target call sites */\n\tif (DUK_LIKELY(!duk_hobject_proxy_check(obj,\n\t                                        &h_proxy_target,\n\t                                        &h_proxy_handler))) {\n\t\tgoto skip_proxy;\n\t}\n\n\tduk_push_hobject(thr, h_proxy_handler);\n\tif (!duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_OWN_KEYS)) {\n\t\t/* Careful with reachability here: don't pop 'obj' before pushing\n\t\t * proxy target.\n\t\t */\n\t\tDUK_DDD(DUK_DDDPRINT(\"no ownKeys trap, get keys of target instead\"));\n\t\tduk_pop_2(thr);\n\t\tduk_push_hobject(thr, h_proxy_target);\n\t\tduk_replace(thr, 0);\n\t\tDUK_ASSERT_TOP(thr, 1);\n\t\tgoto skip_proxy;\n\t}\n\n\t/* [ obj handler trap ] */\n\tduk_insert(thr, -2);\n\tduk_push_hobject(thr, h_proxy_target);  /* -> [ obj trap handler target ] */\n\tduk_call_method(thr, 1 /*nargs*/);      /* -> [ obj trap_result ] */\n\th_trap_result = duk_require_hobject(thr, -1);\n\tDUK_UNREF(h_trap_result);\n\n\tmagic = duk_get_current_magic(thr);\n\tDUK_ASSERT(magic >= 0 && magic < (duk_int_t) (sizeof(duk__object_keys_enum_flags) / sizeof(duk_small_uint_t)));\n\tenum_flags = duk__object_keys_enum_flags[magic];\n\n\tduk_proxy_ownkeys_postprocess(thr, h_proxy_target, enum_flags);\n\treturn 1;\n\n skip_proxy:\n#endif  /* DUK_USE_ES6_PROXY */\n\n\tDUK_ASSERT_TOP(thr, 1);\n\tmagic = duk_get_current_magic(thr);\n\tDUK_ASSERT(magic >= 0 && magic < (duk_int_t) (sizeof(duk__object_keys_enum_flags) / sizeof(duk_small_uint_t)));\n\tenum_flags = duk__object_keys_enum_flags[magic];\n\treturn duk_hobject_get_enumerated_keys(thr, enum_flags);\n}\n#endif  /* DUK_USE_OBJECT_BUILTIN || DUK_USE_REFLECT_BUILTIN */\n\n#if defined(DUK_USE_OBJECT_BUILTIN) || defined(DUK_USE_REFLECT_BUILTIN)\nDUK_INTERNAL duk_ret_t duk_bi_object_constructor_prevent_extensions(duk_hthread *thr) {\n\t/*\n\t *  magic = 0: Object.preventExtensions()\n\t *  magic = 1: Reflect.preventExtensions()\n\t */\n\n\tduk_hobject *h;\n\tduk_uint_t mask;\n\tduk_int_t magic;\n\n\tmagic = duk_get_current_magic(thr);\n\n\t/* Silent success for lightfuncs and plain buffers always. */\n\tmask = DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER;\n\n\t/* Object.preventExtensions() silent success for non-object. */\n\tif (magic == 0) {\n\t\tmask |= DUK_TYPE_MASK_UNDEFINED |\n\t\t        DUK_TYPE_MASK_NULL |\n\t\t        DUK_TYPE_MASK_BOOLEAN |\n\t\t        DUK_TYPE_MASK_NUMBER |\n\t\t        DUK_TYPE_MASK_STRING |\n\t\t        DUK_TYPE_MASK_POINTER;\n\t}\n\n\tif (duk_check_type_mask(thr, 0, mask)) {\n\t\t/* Not an object, already non-extensible so always success. */\n\t\tgoto done;\n\t}\n\th = duk_require_hobject(thr, 0);\n\tDUK_ASSERT(h != NULL);\n\n\tDUK_HOBJECT_CLEAR_EXTENSIBLE(h);\n\n\t/* A non-extensible object cannot gain any more properties,\n\t * so this is a good time to compact.\n\t */\n\tduk_hobject_compact_props(thr, h);\n\n done:\n\tif (magic == 1) {\n\t\tduk_push_true(thr);\n\t}\n\treturn 1;\n}\n#endif  /* DUK_USE_OBJECT_BUILTIN || DUK_USE_REFLECT_BUILTIN */\n\n/*\n *  __defineGetter__, __defineSetter__, __lookupGetter__, __lookupSetter__\n */\n\n#if defined(DUK_USE_ES8)\nDUK_INTERNAL duk_ret_t duk_bi_object_prototype_defineaccessor(duk_hthread *thr) {\n\tduk_push_this(thr);\n\tduk_insert(thr, 0);\n\tduk_to_object(thr, 0);\n\tduk_require_callable(thr, 2);\n\n\t/* [ ToObject(this) key getter/setter ] */\n\n\t/* ToPropertyKey() coercion is not needed, duk_def_prop() does it. */\n\tduk_def_prop(thr, 0, DUK_DEFPROP_SET_ENUMERABLE |\n\t                     DUK_DEFPROP_SET_CONFIGURABLE |\n\t                     (duk_get_current_magic(thr) ? DUK_DEFPROP_HAVE_SETTER : DUK_DEFPROP_HAVE_GETTER));\n\treturn 0;\n}\nDUK_INTERNAL duk_ret_t duk_bi_object_prototype_lookupaccessor(duk_hthread *thr) {\n\tduk_uint_t sanity;\n\n\tduk_push_this(thr);\n\tduk_to_object(thr, -1);\n\n\t/* XXX: Prototype walk (with sanity) should be a core property\n\t * operation, could add a flag to e.g. duk_get_prop_desc().\n\t */\n\n\t/* ToPropertyKey() coercion is not needed, duk_get_prop_desc() does it. */\n\tsanity = DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY;\n\twhile (!duk_is_undefined(thr, -1)) {\n\t\t/* [ key obj ] */\n\t\tduk_dup(thr, 0);\n\t\tduk_get_prop_desc(thr, 1, 0 /*flags*/);\n\t\tif (!duk_is_undefined(thr, -1)) {\n\t\t\tduk_get_prop_stridx(thr, -1, (duk_get_current_magic(thr) != 0 ? DUK_STRIDX_SET : DUK_STRIDX_GET));\n\t\t\treturn 1;\n\t\t}\n\t\tduk_pop(thr);\n\n\t\tif (DUK_UNLIKELY(sanity-- == 0)) {\n\t\t\tDUK_ERROR_RANGE(thr, DUK_STR_PROTOTYPE_CHAIN_LIMIT);\n\t\t}\n\n\t\tduk_get_prototype(thr, -1);\n\t\tduk_remove(thr, -2);\n\t}\n\treturn 1;\n}\n#endif  /* DUK_USE_ES8 */\n#line 1 \"duk_bi_performance.c\"\n/*\n *  High resolution time API (performance.now() et al)\n *\n *  API specification: https://encoding.spec.whatwg.org/#ap://www.w3.org/TR/hr-time/\n */\n\n/* #include duk_internal.h -> already included */\n\n#if defined(DUK_USE_PERFORMANCE_BUILTIN)\nDUK_INTERNAL duk_ret_t duk_bi_performance_now(duk_hthread *thr) {\n\t/* From API spec:\n\t * The DOMHighResTimeStamp type is used to store a time value in\n\t * milliseconds, measured relative from the time origin, global\n\t * monotonic clock, or a time value that represents a duration\n\t * between two DOMHighResTimeStamp's.\n\t */\n\tduk_push_number(thr, duk_time_get_monotonic_time(thr));\n\treturn 1;\n}\n\n#if 0  /* Missing until semantics decided. */\nDUK_INTERNAL duk_ret_t duk_bi_performance_timeorigin_getter(duk_hthread *thr) {\n\t/* No decision yet how to handle timeOrigins, e.g. should one be\n\t * initialized per heap, or per global object set.  See\n\t * https://www.w3.org/TR/hr-time/#time-origin.\n\t */\n\tduk_push_uint(thr, 0);\n\treturn 1;\n}\n#endif  /* 0 */\n#endif  /* DUK_USE_PERFORMANCE_BUILTIN */\n#line 1 \"duk_bi_pointer.c\"\n/*\n *  Pointer built-ins\n */\n\n/* #include duk_internal.h -> already included */\n\n/*\n *  Constructor\n */\n\nDUK_INTERNAL duk_ret_t duk_bi_pointer_constructor(duk_hthread *thr) {\n\t/* XXX: this behavior is quite useless now; it would be nice to be able\n\t * to create pointer values from e.g. numbers or strings.  Numbers are\n\t * problematic on 64-bit platforms though.  Hex encoded strings?\n\t */\n\tif (duk_get_top(thr) == 0) {\n\t\tduk_push_pointer(thr, NULL);\n\t} else {\n\t\tduk_to_pointer(thr, 0);\n\t}\n\tDUK_ASSERT(duk_is_pointer(thr, 0));\n\tduk_set_top(thr, 1);\n\n\tif (duk_is_constructor_call(thr)) {\n\t\t(void) duk_push_object_helper(thr,\n\t\t                              DUK_HOBJECT_FLAG_EXTENSIBLE |\n\t\t                              DUK_HOBJECT_FLAG_FASTREFS |\n\t\t                              DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_POINTER),\n\t\t                              DUK_BIDX_POINTER_PROTOTYPE);\n\n\t\t/* Pointer object internal value is immutable */\n\t\tduk_dup_0(thr);\n\t\tduk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_NONE);\n\t}\n\t/* Note: unbalanced stack on purpose */\n\n\treturn 1;\n}\n\n/*\n *  toString(), valueOf()\n */\n\nDUK_INTERNAL duk_ret_t duk_bi_pointer_prototype_tostring_shared(duk_hthread *thr) {\n\tduk_tval *tv;\n\tduk_small_int_t to_string = duk_get_current_magic(thr);\n\n\tduk_push_this(thr);\n\ttv = duk_require_tval(thr, -1);\n\tDUK_ASSERT(tv != NULL);\n\n\tif (DUK_TVAL_IS_POINTER(tv)) {\n\t\t/* nop */\n\t} else if (DUK_TVAL_IS_OBJECT(tv)) {\n\t\tduk_hobject *h = DUK_TVAL_GET_OBJECT(tv);\n\t\tDUK_ASSERT(h != NULL);\n\n\t\t/* Must be a \"pointer object\", i.e. class \"Pointer\" */\n\t\tif (DUK_HOBJECT_GET_CLASS_NUMBER(h) != DUK_HOBJECT_CLASS_POINTER) {\n\t\t\tgoto type_error;\n\t\t}\n\n\t\tduk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INT_VALUE);\n\t} else {\n\t\tgoto type_error;\n\t}\n\n\tif (to_string) {\n\t\tduk_to_string(thr, -1);\n\t}\n\treturn 1;\n\n type_error:\n\tDUK_DCERROR_TYPE_INVALID_ARGS(thr);\n}\n#line 1 \"duk_bi_promise.c\"\n/*\n *  Promise built-in\n */\n\n/* #include duk_internal.h -> already included */\n\n#if defined(DUK_USE_PROMISE_BUILTIN)\n\nDUK_INTERNAL duk_ret_t duk_bi_promise_constructor(duk_hthread *thr) {\n\tDUK_ERROR_TYPE(thr, \"unimplemented\");\n\treturn 0;\n}\n\nDUK_INTERNAL duk_ret_t duk_bi_promise_all(duk_hthread *thr) {\n\tDUK_ERROR_TYPE(thr, \"unimplemented\");\n\treturn 0;\n}\n\nDUK_INTERNAL duk_ret_t duk_bi_promise_race(duk_hthread *thr) {\n\tDUK_ERROR_TYPE(thr, \"unimplemented\");\n\treturn 0;\n}\n\nDUK_INTERNAL duk_ret_t duk_bi_promise_reject(duk_hthread *thr) {\n\tDUK_ERROR_TYPE(thr, \"unimplemented\");\n\treturn 0;\n}\n\nDUK_INTERNAL duk_ret_t duk_bi_promise_resolve(duk_hthread *thr) {\n\tDUK_ERROR_TYPE(thr, \"unimplemented\");\n\treturn 0;\n}\n\nDUK_INTERNAL duk_ret_t duk_bi_promise_catch(duk_hthread *thr) {\n\tDUK_ERROR_TYPE(thr, \"unimplemented\");\n\treturn 0;\n}\n\nDUK_INTERNAL duk_ret_t duk_bi_promise_then(duk_hthread *thr) {\n\tDUK_ERROR_TYPE(thr, \"unimplemented\");\n\treturn 0;\n}\n\n#endif  /* DUK_USE_PROMISE_BUILTIN */\n#line 1 \"duk_bi_proxy.c\"\n/*\n *  Proxy built-in (ES2015)\n */\n\n/* #include duk_internal.h -> already included */\n\n#if defined(DUK_USE_ES6_PROXY)\n/* Post-process a Proxy ownKeys() result at stack top.  Push a cleaned up\n * array of valid result keys (strings or symbols).  TypeError for invalid\n * values.  Flags are shared with duk_enum().\n */\nDUK_INTERNAL void duk_proxy_ownkeys_postprocess(duk_hthread *thr, duk_hobject *h_proxy_target, duk_uint_t flags) {\n\tduk_uarridx_t i, len, idx;\n\tduk_propdesc desc;\n\n\tDUK_ASSERT_CTX_VALID(thr);\n\tDUK_ASSERT(h_proxy_target != NULL);\n\n\tlen = (duk_uarridx_t) duk_get_length(thr, -1);\n\tidx = 0;\n\tduk_push_array(thr);\n\t/* XXX: preallocated dense array, fill in directly */\n\tfor (i = 0; i < len; i++) {\n\t\tduk_hstring *h;\n\n\t\t/* [ obj trap_result res_arr ] */\n\t\t(void) duk_get_prop_index(thr, -2, i);\n\t\th = duk_get_hstring(thr, -1);\n\t\tif (h == NULL) {\n\t\t\tDUK_ERROR_TYPE_INVALID_TRAP_RESULT(thr);\n\t\t}\n\n\t\tif (!(flags & DUK_ENUM_INCLUDE_NONENUMERABLE)) {\n\t\t\t/* No support for 'getOwnPropertyDescriptor' trap yet,\n\t\t\t * so check enumerability always from target object\n\t\t\t * descriptor.\n\t\t\t */\n\t\t\tif (duk_hobject_get_own_propdesc(thr, h_proxy_target, duk_known_hstring(thr, -1), &desc, 0 /*flags*/)) {\n\t\t\t\tif ((desc.flags & DUK_PROPDESC_FLAG_ENUMERABLE) == 0) {\n\t\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"ignore non-enumerable property: %!T\", duk_get_tval(thr, -1)));\n\t\t\t\t\tgoto skip_key;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"ignore non-existent property: %!T\", duk_get_tval(thr, -1)));\n\t\t\t\tgoto skip_key;\n\t\t\t}\n\t\t}\n\t\tif (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(h))) {\n\t\t\tif (!(flags & DUK_ENUM_INCLUDE_SYMBOLS)) {\n\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"ignore symbol property: %!T\", duk_get_tval(thr, -1)));\n\t\t\t\tgoto skip_key;\n\t\t\t}\n\t\t\tif (DUK_HSTRING_HAS_HIDDEN(h) && !(flags & DUK_ENUM_INCLUDE_HIDDEN)) {\n\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"ignore hidden symbol property: %!T\", duk_get_tval(thr, -1)));\n\t\t\t\tgoto skip_key;\n\t\t\t}\n\t\t} else {\n\t\t\tif (flags & DUK_ENUM_EXCLUDE_STRINGS) {\n\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"ignore string property: %!T\", duk_get_tval(thr, -1)));\n\t\t\t\tgoto skip_key;\n\t\t\t}\n\t\t}\n\n\t\t/* [ obj trap_result res_arr propname ] */\n\t\tduk_put_prop_index(thr, -2, idx++);\n\t\tcontinue;\n\n\t skip_key:\n\t\tduk_pop(thr);\n\t\tcontinue;\n\t}\n\n\t/* XXX: Missing trap result validation for non-configurable target keys\n\t * (must be present), for non-extensible target all target keys must be\n\t * present and no extra keys can be present.\n\t * http://www.ecma-international.org/ecma-262/6.0/#sec-proxy-object-internal-methods-and-internal-slots-ownpropertykeys\n\t */\n\n\t/* XXX: The key enumerability check should trigger the \"getOwnPropertyDescriptor\"\n\t * trap which has not yet been implemented.  In the absence of such a trap,\n\t * the enumerability should be checked from the target object; this is\n\t * handled above.\n\t */\n}\n#endif  /* DUK_USE_ES6_PROXY */\n\n#if defined(DUK_USE_ES6_PROXY)\nDUK_INTERNAL duk_ret_t duk_bi_proxy_constructor(duk_hthread *thr) {\n\tDUK_ASSERT_TOP(thr, 2);  /* [ target handler ] */\n\n\tduk_require_constructor_call(thr);\n\tduk_push_proxy(thr, 0 /*flags*/);  /* [ target handler ] -> [ proxy ] */\n\treturn 1;  /* replacement */\n}\n#endif  /* DUK_USE_ES6_PROXY */\n#line 1 \"duk_bi_reflect.c\"\n/*\n *  'Reflect' built-in (ES2016 Section 26.1)\n *  http://www.ecma-international.org/ecma-262/7.0/#sec-reflect-object\n *\n *  Many Reflect built-in functions are provided by shared helpers in\n *  duk_bi_object.c or duk_bi_function.c.\n */\n\n/* #include duk_internal.h -> already included */\n\n#if defined(DUK_USE_REFLECT_BUILTIN)\nDUK_INTERNAL duk_ret_t duk_bi_reflect_object_delete_property(duk_hthread *thr) {\n\tduk_tval *tv_obj;\n\tduk_tval *tv_key;\n\tduk_bool_t ret;\n\n\tDUK_ASSERT_TOP(thr, 2);\n\t(void) duk_require_hobject(thr, 0);\n\t(void) duk_to_string(thr, 1);\n\n\t/* [ target key ] */\n\n\tDUK_ASSERT(thr != NULL);\n\ttv_obj = DUK_GET_TVAL_POSIDX(thr, 0);\n\ttv_key = DUK_GET_TVAL_POSIDX(thr, 1);\n\tret = duk_hobject_delprop(thr, tv_obj, tv_key, 0 /*throw_flag*/);\n\tduk_push_boolean(thr, ret);\n\treturn 1;\n}\n\nDUK_INTERNAL duk_ret_t duk_bi_reflect_object_get(duk_hthread *thr) {\n\tduk_tval *tv_obj;\n\tduk_tval *tv_key;\n\tduk_idx_t nargs;\n\n\tDUK_ASSERT(thr != NULL);\n\tnargs = duk_get_top_require_min(thr, 2 /*min_top*/);\n\t(void) duk_require_hobject(thr, 0);\n\t(void) duk_to_string(thr, 1);\n\tif (nargs >= 3 && !duk_strict_equals(thr, 0, 2)) {\n\t\t/* XXX: [[Get]] receiver currently unsupported */\n\t\tDUK_ERROR_UNSUPPORTED(thr);\n\t}\n\n\t/* [ target key receiver? ...? ] */\n\n\ttv_obj = DUK_GET_TVAL_POSIDX(thr, 0);\n\ttv_key = DUK_GET_TVAL_POSIDX(thr, 1);\n\t(void) duk_hobject_getprop(thr, tv_obj, tv_key);  /* This could also be a duk_get_prop(). */\n\treturn 1;\n}\n\nDUK_INTERNAL duk_ret_t duk_bi_reflect_object_has(duk_hthread *thr) {\n\tduk_tval *tv_obj;\n\tduk_tval *tv_key;\n\tduk_bool_t ret;\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT_TOP(thr, 2);\n\t(void) duk_require_hobject(thr, 0);\n\t(void) duk_to_string(thr, 1);\n\n\t/* [ target key ] */\n\n\ttv_obj = DUK_GET_TVAL_POSIDX(thr, 0);\n\ttv_key = DUK_GET_TVAL_POSIDX(thr, 1);\n\tret = duk_hobject_hasprop(thr, tv_obj, tv_key);\n\tduk_push_boolean(thr, ret);\n\treturn 1;\n}\n\nDUK_INTERNAL duk_ret_t duk_bi_reflect_object_set(duk_hthread *thr) {\n\tduk_tval *tv_obj;\n\tduk_tval *tv_key;\n\tduk_tval *tv_val;\n\tduk_idx_t nargs;\n\tduk_bool_t ret;\n\n\tDUK_ASSERT(thr != NULL);\n\tnargs = duk_get_top_require_min(thr, 3 /*min_top*/);\n\t(void) duk_require_hobject(thr, 0);\n\t(void) duk_to_string(thr, 1);\n\tif (nargs >= 4 && !duk_strict_equals(thr, 0, 3)) {\n\t\t/* XXX: [[Set]] receiver currently unsupported */\n\t\tDUK_ERROR_UNSUPPORTED(thr);\n\t}\n\n\t/* [ target key value receiver? ...? ] */\n\n\ttv_obj = DUK_GET_TVAL_POSIDX(thr, 0);\n\ttv_key = DUK_GET_TVAL_POSIDX(thr, 1);\n\ttv_val = DUK_GET_TVAL_POSIDX(thr, 2);\n\tret = duk_hobject_putprop(thr, tv_obj, tv_key, tv_val, 0 /*throw_flag*/);\n\tduk_push_boolean(thr, ret);\n\treturn 1;\n}\n#endif  /* DUK_USE_REFLECT_BUILTIN */\n#line 1 \"duk_bi_regexp.c\"\n/*\n *  RegExp built-ins\n */\n\n/* #include duk_internal.h -> already included */\n\n#if defined(DUK_USE_REGEXP_SUPPORT)\n\nDUK_LOCAL void duk__get_this_regexp(duk_hthread *thr) {\n\tduk_hobject *h;\n\n\tduk_push_this(thr);\n\th = duk_require_hobject_with_class(thr, -1, DUK_HOBJECT_CLASS_REGEXP);\n\tDUK_ASSERT(h != NULL);\n\tDUK_UNREF(h);\n\tduk_insert(thr, 0);  /* prepend regexp to valstack 0 index */\n}\n\n/* XXX: much to improve (code size) */\nDUK_INTERNAL duk_ret_t duk_bi_regexp_constructor(duk_hthread *thr) {\n\tduk_hobject *h_pattern;\n\n\tDUK_ASSERT_TOP(thr, 2);\n\th_pattern = duk_get_hobject(thr, 0);\n\n\tif (!duk_is_constructor_call(thr) &&\n\t    h_pattern != NULL &&\n\t    DUK_HOBJECT_GET_CLASS_NUMBER(h_pattern) == DUK_HOBJECT_CLASS_REGEXP &&\n\t    duk_is_undefined(thr, 1)) {\n\t\t/* Called as a function, pattern has [[Class]] \"RegExp\" and\n\t\t * flags is undefined -> return object as is.\n\t\t */\n\t\t/* XXX: ES2015 has a NewTarget SameValue() check which is not\n\t\t * yet implemented.\n\t\t */\n\t\tduk_dup_0(thr);\n\t\treturn 1;\n\t}\n\n\t/* Else functionality is identical for function call and constructor\n\t * call.\n\t */\n\n\tif (h_pattern != NULL &&\n\t    DUK_HOBJECT_GET_CLASS_NUMBER(h_pattern) == DUK_HOBJECT_CLASS_REGEXP) {\n\t\tduk_get_prop_stridx_short(thr, 0, DUK_STRIDX_SOURCE);\n\t\tif (duk_is_undefined(thr, 1)) {\n\t\t\t/* In ES5 one would need to read the flags individually;\n\t\t\t * in ES2015 just read .flags.\n\t\t\t */\n\t\t\tduk_get_prop_stridx(thr, 0, DUK_STRIDX_FLAGS);\n\t\t} else {\n\t\t\t/* In ES2015 allowed; overrides argument RegExp flags. */\n\t\t\tduk_dup_1(thr);\n\t\t}\n\t} else {\n\t\tif (duk_is_undefined(thr, 0)) {\n\t\t\tduk_push_hstring_empty(thr);\n\t\t} else {\n\t\t\tduk_dup_0(thr);\n\t\t\tduk_to_string(thr, -1);  /* Rejects Symbols. */\n\t\t}\n\t\tif (duk_is_undefined(thr, 1)) {\n\t\t\tduk_push_hstring_empty(thr);\n\t\t} else {\n\t\t\tduk_dup_1(thr);\n\t\t\tduk_to_string(thr, -1);  /* Rejects Symbols. */\n\t\t}\n\n\t\t/* [ ... pattern flags ] */\n\t}\n\n\tDUK_DDD(DUK_DDDPRINT(\"RegExp constructor/function call, pattern=%!T, flags=%!T\",\n\t                     (duk_tval *) duk_get_tval(thr, -2), (duk_tval *) duk_get_tval(thr, -1)));\n\n\t/* [ ... pattern flags ] (both uncoerced) */\n\n\tduk_to_string(thr, -2);\n\tduk_to_string(thr, -1);\n\tduk_regexp_compile(thr);\n\n\t/* [ ... bytecode escaped_source ] */\n\n\tduk_regexp_create_instance(thr);\n\n\t/* [ ... RegExp ] */\n\n\treturn 1;\n}\n\nDUK_INTERNAL duk_ret_t duk_bi_regexp_prototype_exec(duk_hthread *thr) {\n\tduk__get_this_regexp(thr);\n\n\t/* [ regexp input ] */\n\n\tduk_regexp_match(thr);\n\n\t/* [ result ] */\n\n\treturn 1;\n}\n\nDUK_INTERNAL duk_ret_t duk_bi_regexp_prototype_test(duk_hthread *thr) {\n\tduk__get_this_regexp(thr);\n\n\t/* [ regexp input ] */\n\n\t/* result object is created and discarded; wasteful but saves code space */\n\tduk_regexp_match(thr);\n\n\t/* [ result ] */\n\n\tduk_push_boolean(thr, (duk_is_null(thr, -1) ? 0 : 1));\n\n\treturn 1;\n}\n\nDUK_INTERNAL duk_ret_t duk_bi_regexp_prototype_tostring(duk_hthread *thr) {\n\t/* This must be generic in ES2015 and later. */\n\tDUK_ASSERT_TOP(thr, 0);\n\tduk_push_this(thr);\n\tduk_push_string(thr, \"/\");\n\tduk_get_prop_stridx(thr, 0, DUK_STRIDX_SOURCE);\n\tduk_dup_m2(thr);  /* another \"/\" */\n\tduk_get_prop_stridx(thr, 0, DUK_STRIDX_FLAGS);\n\tduk_concat(thr, 4);\n\treturn 1;\n}\n\nDUK_INTERNAL duk_ret_t duk_bi_regexp_prototype_flags(duk_hthread *thr) {\n\t/* .flags is ES2015 but present even when ES2015 bindings are\n\t * disabled because the constructor relies on it.\n\t */\n\tduk_uint8_t buf[8];  /* enough for all flags + NUL */\n\tduk_uint8_t *p = buf;\n\n\t/* .flags is generic and works on any object. */\n\tduk_push_this(thr);\n\t(void) duk_require_hobject(thr, -1);\n\tif (duk_get_prop_stridx_boolean(thr, 0, DUK_STRIDX_GLOBAL, NULL)) {\n\t\t*p++ = DUK_ASC_LC_G;\n\t}\n\tif (duk_get_prop_stridx_boolean(thr, 0, DUK_STRIDX_IGNORE_CASE, NULL)) {\n\t\t*p++ = DUK_ASC_LC_I;\n\t}\n\tif (duk_get_prop_stridx_boolean(thr, 0, DUK_STRIDX_MULTILINE, NULL)) {\n\t\t*p++ = DUK_ASC_LC_M;\n\t}\n\t/* .unicode: to be added */\n\t/* .sticky: to be added */\n\t*p++ = DUK_ASC_NUL;\n\tDUK_ASSERT((duk_size_t) (p - buf) <= sizeof(buf));\n\n\tduk_push_string(thr, (const char *) buf);\n\treturn 1;\n}\n\n/* Shared helper for providing .source, .global, .multiline, etc getters. */\nDUK_INTERNAL duk_ret_t duk_bi_regexp_prototype_shared_getter(duk_hthread *thr) {\n\tduk_hstring *h_bc;\n\tduk_small_uint_t re_flags;\n\tduk_hobject *h;\n\tduk_int_t magic;\n\n\tDUK_ASSERT_TOP(thr, 0);\n\n\tduk_push_this(thr);\n\th = duk_require_hobject(thr, -1);\n\tmagic = duk_get_current_magic(thr);\n\n\tif (DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_REGEXP) {\n\t\tduk_get_prop_stridx_short(thr, 0, DUK_STRIDX_INT_SOURCE);\n\t\tduk_get_prop_stridx_short(thr, 0, DUK_STRIDX_INT_BYTECODE);\n\t\th_bc = duk_require_hstring(thr, -1);\n\t\tre_flags = (duk_small_uint_t) DUK_HSTRING_GET_DATA(h_bc)[0];  /* Safe even if h_bc length is 0 (= NUL) */\n\t\tduk_pop(thr);\n\t} else if (h == thr->builtins[DUK_BIDX_REGEXP_PROTOTYPE]) {\n\t\t/* In ES2015 and ES2016 a TypeError would be thrown here.\n\t\t * However, this had real world issues so ES2017 draft\n\t\t * allows RegExp.prototype specifically, returning '(?:)'\n\t\t * for .source and undefined for all flags.\n\t\t */\n\t\tif (magic != 16 /* .source */) {\n\t\t\treturn 0;\n\t\t}\n\t\tduk_push_string(thr, \"(?:)\");  /* .source handled by switch-case */\n\t\tre_flags = 0;\n\t} else {\n\t\tDUK_DCERROR_TYPE_INVALID_ARGS(thr);\n\t}\n\n\t/* [ regexp source ] */\n\n\tswitch (magic) {\n\tcase 0: {  /* global */\n\t\tduk_push_boolean(thr, (re_flags & DUK_RE_FLAG_GLOBAL));\n\t\tbreak;\n\t}\n\tcase 1: {  /* ignoreCase */\n\t\tduk_push_boolean(thr, (re_flags & DUK_RE_FLAG_IGNORE_CASE));\n\t\tbreak;\n\t}\n\tcase 2: {  /* multiline */\n\t\tduk_push_boolean(thr, (re_flags & DUK_RE_FLAG_MULTILINE));\n\t\tbreak;\n\t}\n#if 0\n\t/* Don't provide until implemented to avoid interfering with feature\n\t * detection in user code.\n\t */\n\tcase 3:    /* sticky */\n\tcase 4: {  /* unicode */\n\t\tduk_push_false(thr);\n\t\tbreak;\n\t}\n#endif\n\tdefault: {  /* source */\n\t\t/* leave 'source' on top */\n\t\tbreak;\n\t}\n\t}\n\n\treturn 1;\n}\n\n#endif  /* DUK_USE_REGEXP_SUPPORT */\n#line 1 \"duk_bi_string.c\"\n/*\n *  String built-ins\n *\n *  Most String built-ins must only accept strings (or String objects).\n *  Symbols, represented internally as strings, must be generally rejected.\n *  The duk_push_this_coercible_to_string() helper does this automatically.\n */\n\n/* XXX: There are several limitations in the current implementation for\n * strings with >= 0x80000000UL characters.  In some cases one would need\n * to be able to represent the range [-0xffffffff,0xffffffff] and so on.\n * Generally character and byte length are assumed to fit into signed 32\n * bits (< 0x80000000UL).  Places with issues are not marked explicitly\n * below in all cases, look for signed type usage (duk_int_t etc) for\n * offsets/lengths.\n */\n\n/* #include duk_internal.h -> already included */\n\n#if defined(DUK_USE_STRING_BUILTIN)\n\n/*\n *  Helpers\n */\n\nDUK_LOCAL duk_hstring *duk__str_tostring_notregexp(duk_hthread *thr, duk_idx_t idx) {\n\tduk_hstring *h;\n\n\tif (duk_get_class_number(thr, idx) == DUK_HOBJECT_CLASS_REGEXP) {\n\t\tDUK_ERROR_TYPE_INVALID_ARGS(thr);\n\t}\n\th = duk_to_hstring(thr, idx);\n\tDUK_ASSERT(h != NULL);\n\n\treturn h;\n}\n\nDUK_LOCAL duk_int_t duk__str_search_shared(duk_hthread *thr, duk_hstring *h_this, duk_hstring *h_search, duk_int_t start_cpos, duk_bool_t backwards) {\n\tduk_int_t cpos;\n\tduk_int_t bpos;\n\tconst duk_uint8_t *p_start, *p_end, *p;\n\tconst duk_uint8_t *q_start;\n\tduk_int_t q_blen;\n\tduk_uint8_t firstbyte;\n\tduk_uint8_t t;\n\n\tcpos = start_cpos;\n\n\t/* Empty searchstring always matches; cpos must be clamped here.\n\t * (If q_blen were < 0 due to clamped coercion, it would also be\n\t * caught here.)\n\t */\n\tq_start = DUK_HSTRING_GET_DATA(h_search);\n\tq_blen = (duk_int_t) DUK_HSTRING_GET_BYTELEN(h_search);\n\tif (q_blen <= 0) {\n\t\treturn cpos;\n\t}\n\tDUK_ASSERT(q_blen > 0);\n\n\tbpos = (duk_int_t) duk_heap_strcache_offset_char2byte(thr, h_this, (duk_uint32_t) cpos);\n\n\tp_start = DUK_HSTRING_GET_DATA(h_this);\n\tp_end = p_start + DUK_HSTRING_GET_BYTELEN(h_this);\n\tp = p_start + bpos;\n\n\t/* This loop is optimized for size.  For speed, there should be\n\t * two separate loops, and we should ensure that memcmp() can be\n\t * used without an extra \"will searchstring fit\" check.  Doing\n\t * the preconditioning for 'p' and 'p_end' is easy but cpos\n\t * must be updated if 'p' is wound back (backward scanning).\n\t */\n\n\tfirstbyte = q_start[0];  /* leading byte of match string */\n\twhile (p <= p_end && p >= p_start) {\n\t\tt = *p;\n\n\t\t/* For Ecmascript strings, this check can only match for\n\t\t * initial UTF-8 bytes (not continuation bytes).  For other\n\t\t * strings all bets are off.\n\t\t */\n\n\t\tif ((t == firstbyte) && ((duk_size_t) (p_end - p) >= (duk_size_t) q_blen)) {\n\t\t\tDUK_ASSERT(q_blen > 0);  /* no issues with memcmp() zero size, even if broken */\n\t\t\tif (DUK_MEMCMP((const void *) p, (const void *) q_start, (size_t) q_blen) == 0) {\n\t\t\t\treturn cpos;\n\t\t\t}\n\t\t}\n\n\t\t/* track cpos while scanning */\n\t\tif (backwards) {\n\t\t\t/* when going backwards, we decrement cpos 'early';\n\t\t\t * 'p' may point to a continuation byte of the char\n\t\t\t * at offset 'cpos', but that's OK because we'll\n\t\t\t * backtrack all the way to the initial byte.\n\t\t\t */\n\t\t\tif ((t & 0xc0) != 0x80) {\n\t\t\t\tcpos--;\n\t\t\t}\n\t\t\tp--;\n\t\t} else {\n\t\t\tif ((t & 0xc0) != 0x80) {\n\t\t\t\tcpos++;\n\t\t\t}\n\t\t\tp++;\n\t\t}\n\t}\n\n\t/* Not found.  Empty string case is handled specially above. */\n\treturn -1;\n}\n\n/*\n *  Constructor\n */\n\nDUK_INTERNAL duk_ret_t duk_bi_string_constructor(duk_hthread *thr) {\n\tduk_hstring *h;\n\tduk_uint_t flags;\n\n\t/* String constructor needs to distinguish between an argument not given at all\n\t * vs. given as 'undefined'.  We're a vararg function to handle this properly.\n\t */\n\n\t/* XXX: copy current activation flags to thr, including current magic,\n\t * is_constructor_call etc.  This takes a few bytes in duk_hthread but\n\t * makes call sites smaller (there are >30 is_constructor_call and get\n\t * current magic call sites.\n\t */\n\n\tif (duk_get_top(thr) == 0) {\n\t\tduk_push_hstring_empty(thr);\n\t} else {\n\t\th = duk_to_hstring_acceptsymbol(thr, 0);\n\t\tif (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(h) && !duk_is_constructor_call(thr))) {\n\t\t\tduk_push_symbol_descriptive_string(thr, h);\n\t\t\tduk_replace(thr, 0);\n\t\t}\n\t}\n\tduk_to_string(thr, 0);  /* catches symbol argument for constructor call */\n\tDUK_ASSERT(duk_is_string(thr, 0));\n\tduk_set_top(thr, 1);  /* Top may be 1 or larger. */\n\n\tif (duk_is_constructor_call(thr)) {\n\t\t/* String object internal value is immutable */\n\t\tflags = DUK_HOBJECT_FLAG_EXTENSIBLE |\n\t\t        DUK_HOBJECT_FLAG_FASTREFS |\n\t\t        DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ |\n\t\t        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_STRING);\n\t\tduk_push_object_helper(thr, flags, DUK_BIDX_STRING_PROTOTYPE);\n\t\tduk_dup_0(thr);\n\t\tduk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_NONE);\n\t}\n\t/* Note: unbalanced stack on purpose */\n\n\treturn 1;\n}\n\nDUK_LOCAL duk_ret_t duk__construct_from_codepoints(duk_hthread *thr, duk_bool_t nonbmp) {\n\tduk_bufwriter_ctx bw_alloc;\n\tduk_bufwriter_ctx *bw;\n\tduk_idx_t i, n;\n\tduk_ucodepoint_t cp;\n\n\t/* XXX: It would be nice to build the string directly but ToUint16()\n\t * coercion is needed so a generic helper would not be very\n\t * helpful (perhaps coerce the value stack first here and then\n\t * build a string from a duk_tval number sequence in one go?).\n\t */\n\n\tn = duk_get_top(thr);\n\n\tbw = &bw_alloc;\n\tDUK_BW_INIT_PUSHBUF(thr, bw, (duk_size_t) n);  /* initial estimate for ASCII only codepoints */\n\n\tfor (i = 0; i < n; i++) {\n\t\t/* XXX: could improve bufwriter handling to write multiple codepoints\n\t\t * with one ensure call but the relative benefit would be quite small.\n\t\t */\n\n\t\tif (nonbmp) {\n\t\t\t/* ES2015 requires that (1) SameValue(cp, ToInteger(cp)) and\n\t\t\t * (2) cp >= 0 and cp <= 0x10ffff.  This check does not\n\t\t\t * implement the steps exactly but the outcome should be\n\t\t\t * the same.\n\t\t\t */\n\t\t\tduk_int32_t i32 = 0;\n\t\t\tif (!duk_is_whole_get_int32(duk_to_number(thr, i), &i32) ||\n\t\t\t    i32 < 0 || i32 > 0x10ffffL) {\n\t\t\t\tDUK_DCERROR_RANGE_INVALID_ARGS(thr);\n\t\t\t}\n\t\t\tDUK_ASSERT(i32 >= 0 && i32 <= 0x10ffffL);\n\t\t\tcp = (duk_ucodepoint_t) i32;\n\t\t\tDUK_BW_WRITE_ENSURE_CESU8(thr, bw, cp);\n\t\t} else {\n#if defined(DUK_USE_NONSTD_STRING_FROMCHARCODE_32BIT)\n\t\t\t/* ToUint16() coercion is mandatory in the E5.1 specification, but\n\t\t\t * this non-compliant behavior makes more sense because we support\n\t\t\t * non-BMP codepoints.  Don't use CESU-8 because that'd create\n\t\t\t * surrogate pairs.\n\t\t\t */\n\t\t\tcp = (duk_ucodepoint_t) duk_to_uint32(thr, i);\n\t\t\tDUK_BW_WRITE_ENSURE_XUTF8(thr, bw, cp);\n#else\n\t\t\tcp = (duk_ucodepoint_t) duk_to_uint16(thr, i);\n\t\t\tDUK_ASSERT(cp >= 0 && cp <= 0x10ffffL);\n\t\t\tDUK_BW_WRITE_ENSURE_CESU8(thr, bw, cp);\n#endif\n\t\t}\n\t}\n\n\tDUK_BW_COMPACT(thr, bw);\n\t(void) duk_buffer_to_string(thr, -1);  /* Safe, extended UTF-8 or CESU-8 encoded. */\n\treturn 1;\n}\n\nDUK_INTERNAL duk_ret_t duk_bi_string_constructor_from_char_code(duk_hthread *thr) {\n\treturn duk__construct_from_codepoints(thr, 0 /*nonbmp*/);\n}\n\n#if defined(DUK_USE_ES6)\nDUK_INTERNAL duk_ret_t duk_bi_string_constructor_from_code_point(duk_hthread *thr) {\n\treturn duk__construct_from_codepoints(thr, 1 /*nonbmp*/);\n}\n#endif\n\n/*\n *  toString(), valueOf()\n */\n\nDUK_INTERNAL duk_ret_t duk_bi_string_prototype_to_string(duk_hthread *thr) {\n\tduk_tval *tv;\n\n\tduk_push_this(thr);\n\ttv = duk_require_tval(thr, -1);\n\tDUK_ASSERT(tv != NULL);\n\n\tif (DUK_TVAL_IS_STRING(tv)) {\n\t\t/* return as is */\n\t} else if (DUK_TVAL_IS_OBJECT(tv)) {\n\t\tduk_hobject *h = DUK_TVAL_GET_OBJECT(tv);\n\t\tDUK_ASSERT(h != NULL);\n\n\t\t/* Must be a \"string object\", i.e. class \"String\" */\n\t\tif (DUK_HOBJECT_GET_CLASS_NUMBER(h) != DUK_HOBJECT_CLASS_STRING) {\n\t\t\tgoto type_error;\n\t\t}\n\n\t\tduk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INT_VALUE);\n\t\tDUK_ASSERT(duk_is_string(thr, -1));\n\t} else {\n\t\tgoto type_error;\n\t}\n\n\t(void) duk_require_hstring_notsymbol(thr, -1);  /* Reject symbols (and wrapped symbols). */\n\treturn 1;\n\n type_error:\n\tDUK_DCERROR_TYPE_INVALID_ARGS(thr);\n}\n\n/*\n *  Character and charcode access\n */\n\nDUK_INTERNAL duk_ret_t duk_bi_string_prototype_char_at(duk_hthread *thr) {\n\tduk_int_t pos;\n\n\t/* XXX: faster implementation */\n\n\t(void) duk_push_this_coercible_to_string(thr);\n\tpos = duk_to_int(thr, 0);\n\tduk_substring(thr, -1, (duk_size_t) pos, (duk_size_t) (pos + 1));\n\treturn 1;\n}\n\n/* Magic: 0=charCodeAt, 1=codePointAt */\nDUK_INTERNAL duk_ret_t duk_bi_string_prototype_char_code_at(duk_hthread *thr) {\n\tduk_int_t pos;\n\tduk_hstring *h;\n\tduk_bool_t clamped;\n\tduk_uint32_t cp;\n\tduk_int_t magic;\n\n\t/* XXX: faster implementation */\n\n\tDUK_DDD(DUK_DDDPRINT(\"arg=%!T\", (duk_tval *) duk_get_tval(thr, 0)));\n\n\th = duk_push_this_coercible_to_string(thr);\n\tDUK_ASSERT(h != NULL);\n\n\tpos = duk_to_int_clamped_raw(thr,\n\t                             0 /*index*/,\n\t                             0 /*min(incl)*/,\n\t                             (duk_int_t) DUK_HSTRING_GET_CHARLEN(h) - 1 /*max(incl)*/,\n\t                             &clamped /*out_clamped*/);\n#if defined(DUK_USE_ES6)\n\tmagic = duk_get_current_magic(thr);\n#else\n\tDUK_ASSERT(duk_get_current_magic(thr) == 0);\n\tmagic = 0;\n#endif\n\tif (clamped) {\n\t\t/* For out-of-bounds indices .charCodeAt() returns NaN and\n\t\t * .codePointAt() returns undefined.\n\t\t */\n\t\tif (magic != 0) {\n\t\t\treturn 0;\n\t\t}\n\t\tduk_push_nan(thr);\n\t} else {\n\t\tDUK_ASSERT(pos >= 0);\n\t\tcp = (duk_uint32_t) duk_hstring_char_code_at_raw(thr, h, (duk_uint_t) pos, (duk_bool_t) magic /*surrogate_aware*/);\n\t\tduk_push_u32(thr, cp);\n\t}\n\treturn 1;\n}\n\n/*\n *  substring(), substr(), slice()\n */\n\n/* XXX: any chance of merging these three similar but still slightly\n * different algorithms so that footprint would be reduced?\n */\n\nDUK_INTERNAL duk_ret_t duk_bi_string_prototype_substring(duk_hthread *thr) {\n\tduk_hstring *h;\n\tduk_int_t start_pos, end_pos;\n\tduk_int_t len;\n\n\th = duk_push_this_coercible_to_string(thr);\n\tDUK_ASSERT(h != NULL);\n\tlen = (duk_int_t) DUK_HSTRING_GET_CHARLEN(h);\n\n\t/* [ start end str ] */\n\n\tstart_pos = duk_to_int_clamped(thr, 0, 0, len);\n\tif (duk_is_undefined(thr, 1)) {\n\t\tend_pos = len;\n\t} else {\n\t\tend_pos = duk_to_int_clamped(thr, 1, 0, len);\n\t}\n\tDUK_ASSERT(start_pos >= 0 && start_pos <= len);\n\tDUK_ASSERT(end_pos >= 0 && end_pos <= len);\n\n\tif (start_pos > end_pos) {\n\t\tduk_int_t tmp = start_pos;\n\t\tstart_pos = end_pos;\n\t\tend_pos = tmp;\n\t}\n\n\tDUK_ASSERT(end_pos >= start_pos);\n\n\tduk_substring(thr, -1, (duk_size_t) start_pos, (duk_size_t) end_pos);\n\treturn 1;\n}\n\n#if defined(DUK_USE_SECTION_B)\nDUK_INTERNAL duk_ret_t duk_bi_string_prototype_substr(duk_hthread *thr) {\n\tduk_hstring *h;\n\tduk_int_t start_pos, end_pos;\n\tduk_int_t len;\n\n\t/* Unlike non-obsolete String calls, substr() algorithm in E5.1\n\t * specification will happily coerce undefined and null to strings\n\t * (\"undefined\" and \"null\").\n\t */\n\tduk_push_this(thr);\n\th = duk_to_hstring_m1(thr);  /* Reject Symbols. */\n\tDUK_ASSERT(h != NULL);\n\tlen = (duk_int_t) DUK_HSTRING_GET_CHARLEN(h);\n\n\t/* [ start length str ] */\n\n\t/* The implementation for computing of start_pos and end_pos differs\n\t * from the standard algorithm, but is intended to result in the exactly\n\t * same behavior.  This is not always obvious.\n\t */\n\n\t/* combines steps 2 and 5; -len ensures max() not needed for step 5 */\n\tstart_pos = duk_to_int_clamped(thr, 0, -len, len);\n\tif (start_pos < 0) {\n\t\tstart_pos = len + start_pos;\n\t}\n\tDUK_ASSERT(start_pos >= 0 && start_pos <= len);\n\n\t/* combines steps 3, 6; step 7 is not needed */\n\tif (duk_is_undefined(thr, 1)) {\n\t\tend_pos = len;\n\t} else {\n\t\tDUK_ASSERT(start_pos <= len);\n\t\tend_pos = start_pos + duk_to_int_clamped(thr, 1, 0, len - start_pos);\n\t}\n\tDUK_ASSERT(start_pos >= 0 && start_pos <= len);\n\tDUK_ASSERT(end_pos >= 0 && end_pos <= len);\n\tDUK_ASSERT(end_pos >= start_pos);\n\n\tduk_substring(thr, -1, (duk_size_t) start_pos, (duk_size_t) end_pos);\n\treturn 1;\n}\n#endif  /* DUK_USE_SECTION_B */\n\nDUK_INTERNAL duk_ret_t duk_bi_string_prototype_slice(duk_hthread *thr) {\n\tduk_hstring *h;\n\tduk_int_t start_pos, end_pos;\n\tduk_int_t len;\n\n\th = duk_push_this_coercible_to_string(thr);\n\tDUK_ASSERT(h != NULL);\n\tlen = (duk_int_t) DUK_HSTRING_GET_CHARLEN(h);\n\n\t/* [ start end str ] */\n\n\tstart_pos = duk_to_int_clamped(thr, 0, -len, len);\n\tif (start_pos < 0) {\n\t\tstart_pos = len + start_pos;\n\t}\n\tif (duk_is_undefined(thr, 1)) {\n\t\tend_pos = len;\n\t} else {\n\t\tend_pos = duk_to_int_clamped(thr, 1, -len, len);\n\t\tif (end_pos < 0) {\n\t\t\tend_pos = len + end_pos;\n\t\t}\n\t}\n\tDUK_ASSERT(start_pos >= 0 && start_pos <= len);\n\tDUK_ASSERT(end_pos >= 0 && end_pos <= len);\n\n\tif (end_pos < start_pos) {\n\t\tend_pos = start_pos;\n\t}\n\n\tDUK_ASSERT(end_pos >= start_pos);\n\n\tduk_substring(thr, -1, (duk_size_t) start_pos, (duk_size_t) end_pos);\n\treturn 1;\n}\n\n/*\n *  Case conversion\n */\n\nDUK_INTERNAL duk_ret_t duk_bi_string_prototype_caseconv_shared(duk_hthread *thr) {\n\tduk_small_int_t uppercase = duk_get_current_magic(thr);\n\n\t(void) duk_push_this_coercible_to_string(thr);\n\tduk_unicode_case_convert_string(thr, (duk_bool_t) uppercase);\n\treturn 1;\n}\n\n/*\n *  indexOf() and lastIndexOf()\n */\n\nDUK_INTERNAL duk_ret_t duk_bi_string_prototype_indexof_shared(duk_hthread *thr) {\n\tduk_hstring *h_this;\n\tduk_hstring *h_search;\n\tduk_int_t clen_this;\n\tduk_int_t cpos;\n\tduk_small_uint_t is_lastindexof = (duk_small_uint_t) duk_get_current_magic(thr);  /* 0=indexOf, 1=lastIndexOf */\n\n\th_this = duk_push_this_coercible_to_string(thr);\n\tDUK_ASSERT(h_this != NULL);\n\tclen_this = (duk_int_t) DUK_HSTRING_GET_CHARLEN(h_this);\n\n\th_search = duk_to_hstring(thr, 0);\n\tDUK_ASSERT(h_search != NULL);\n\n\tduk_to_number(thr, 1);\n\tif (duk_is_nan(thr, 1) && is_lastindexof) {\n\t\t/* indexOf: NaN should cause pos to be zero.\n\t\t * lastIndexOf: NaN should cause pos to be +Infinity\n\t\t * (and later be clamped to len).\n\t\t */\n\t\tcpos = clen_this;\n\t} else {\n\t\tcpos = duk_to_int_clamped(thr, 1, 0, clen_this);\n\t}\n\n\tcpos = duk__str_search_shared(thr, h_this, h_search, cpos, is_lastindexof /*backwards*/);\n\tduk_push_int(thr, cpos);\n\treturn 1;\n}\n\n/*\n *  replace()\n */\n\n/* XXX: the current implementation works but is quite clunky; it compiles\n * to almost 1,4kB of x86 code so it needs to be simplified (better approach,\n * shared helpers, etc).  Some ideas for refactoring:\n *\n * - a primitive to convert a string into a regexp matcher (reduces matching\n *   code at the cost of making matching much slower)\n * - use replace() as a basic helper for match() and split(), which are both\n *   much simpler\n * - API call to get_prop and to_boolean\n */\n\nDUK_INTERNAL duk_ret_t duk_bi_string_prototype_replace(duk_hthread *thr) {\n\tduk_hstring *h_input;\n\tduk_hstring *h_match;\n\tduk_hstring *h_search;\n\tduk_hobject *h_re;\n\tduk_bufwriter_ctx bw_alloc;\n\tduk_bufwriter_ctx *bw;\n#if defined(DUK_USE_REGEXP_SUPPORT)\n\tduk_bool_t is_regexp;\n\tduk_bool_t is_global;\n#endif\n\tduk_bool_t is_repl_func;\n\tduk_uint32_t match_start_coff, match_start_boff;\n#if defined(DUK_USE_REGEXP_SUPPORT)\n\tduk_int_t match_caps;\n#endif\n\tduk_uint32_t prev_match_end_boff;\n\tconst duk_uint8_t *r_start, *r_end, *r;   /* repl string scan */\n\tduk_size_t tmp_sz;\n\n\tDUK_ASSERT_TOP(thr, 2);\n\th_input = duk_push_this_coercible_to_string(thr);\n\tDUK_ASSERT(h_input != NULL);\n\n\tbw = &bw_alloc;\n\tDUK_BW_INIT_PUSHBUF(thr, bw, DUK_HSTRING_GET_BYTELEN(h_input));  /* input size is good output starting point */\n\n\tDUK_ASSERT_TOP(thr, 4);\n\n\t/* stack[0] = search value\n\t * stack[1] = replace value\n\t * stack[2] = input string\n\t * stack[3] = result buffer\n\t */\n\n\th_re = duk_get_hobject_with_class(thr, 0, DUK_HOBJECT_CLASS_REGEXP);\n\tif (h_re) {\n#if defined(DUK_USE_REGEXP_SUPPORT)\n\t\tis_regexp = 1;\n\t\tis_global = duk_get_prop_stridx_boolean(thr, 0, DUK_STRIDX_GLOBAL, NULL);\n\n\t\tif (is_global) {\n\t\t\t/* start match from beginning */\n\t\t\tduk_push_int(thr, 0);\n\t\t\tduk_put_prop_stridx_short(thr, 0, DUK_STRIDX_LAST_INDEX);\n\t\t}\n#else  /* DUK_USE_REGEXP_SUPPORT */\n\t\tDUK_DCERROR_UNSUPPORTED(thr);\n#endif  /* DUK_USE_REGEXP_SUPPORT */\n\t} else {\n\t\tduk_to_string(thr, 0);  /* rejects symbols */\n#if defined(DUK_USE_REGEXP_SUPPORT)\n\t\tis_regexp = 0;\n\t\tis_global = 0;\n#endif\n\t}\n\n\tif (duk_is_function(thr, 1)) {\n\t\tis_repl_func = 1;\n\t\tr_start = NULL;\n\t\tr_end = NULL;\n\t} else {\n\t\tduk_hstring *h_repl;\n\n\t\tis_repl_func = 0;\n\t\th_repl = duk_to_hstring(thr, 1);  /* reject symbols */\n\t\tDUK_ASSERT(h_repl != NULL);\n\t\tr_start = DUK_HSTRING_GET_DATA(h_repl);\n\t\tr_end = r_start + DUK_HSTRING_GET_BYTELEN(h_repl);\n\t}\n\n\tprev_match_end_boff = 0;\n\n\tfor (;;) {\n\t\t/*\n\t\t *  If matching with a regexp:\n\t\t *    - non-global RegExp: lastIndex not touched on a match, zeroed\n\t\t *      on a non-match\n\t\t *    - global RegExp: on match, lastIndex will be updated by regexp\n\t\t *      executor to point to next char after the matching part (so that\n\t\t *      characters in the matching part are not matched again)\n\t\t *\n\t\t *  If matching with a string:\n\t\t *    - always non-global match, find first occurrence\n\t\t *\n\t\t *  We need:\n\t\t *    - The character offset of start-of-match for the replacer function\n\t\t *    - The byte offsets for start-of-match and end-of-match to implement\n\t\t *      the replacement values $&, $`, and $', and to copy non-matching\n\t\t *      input string portions (including header and trailer) verbatim.\n\t\t *\n\t\t *  NOTE: the E5.1 specification is a bit vague how the RegExp should\n\t\t *  behave in the replacement process; e.g. is matching done first for\n\t\t *  all matches (in the global RegExp case) before any replacer calls\n\t\t *  are made?  See: test-bi-string-proto-replace.js for discussion.\n\t\t */\n\n\t\tDUK_ASSERT_TOP(thr, 4);\n\n#if defined(DUK_USE_REGEXP_SUPPORT)\n\t\tif (is_regexp) {\n\t\t\tduk_dup_0(thr);\n\t\t\tduk_dup_2(thr);\n\t\t\tduk_regexp_match(thr);  /* [ ... regexp input ] -> [ res_obj ] */\n\t\t\tif (!duk_is_object(thr, -1)) {\n\t\t\t\tduk_pop(thr);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tduk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INDEX);\n\t\t\tDUK_ASSERT(duk_is_number(thr, -1));\n\t\t\tmatch_start_coff = duk_get_uint(thr, -1);\n\t\t\tduk_pop(thr);\n\n\t\t\tduk_get_prop_index(thr, -1, 0);\n\t\t\tDUK_ASSERT(duk_is_string(thr, -1));\n\t\t\th_match = duk_known_hstring(thr, -1);\n\t\t\tduk_pop(thr);  /* h_match is borrowed, remains reachable through match_obj */\n\n\t\t\tif (DUK_HSTRING_GET_BYTELEN(h_match) == 0) {\n\t\t\t\t/* This should be equivalent to match() algorithm step 8.f.iii.2:\n\t\t\t\t * detect an empty match and allow it, but don't allow it twice.\n\t\t\t\t */\n\t\t\t\tduk_uint32_t last_index;\n\n\t\t\t\tduk_get_prop_stridx_short(thr, 0, DUK_STRIDX_LAST_INDEX);\n\t\t\t\tlast_index = (duk_uint32_t) duk_get_uint(thr, -1);\n\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"empty match, bump lastIndex: %ld -> %ld\",\n\t\t\t\t                     (long) last_index, (long) (last_index + 1)));\n\t\t\t\tduk_pop(thr);\n\t\t\t\tduk_push_uint(thr, (duk_uint_t) (last_index + 1));\n\t\t\t\tduk_put_prop_stridx_short(thr, 0, DUK_STRIDX_LAST_INDEX);\n\t\t\t}\n\n\t\t\tDUK_ASSERT(duk_get_length(thr, -1) <= DUK_INT_MAX);  /* string limits */\n\t\t\tmatch_caps = (duk_int_t) duk_get_length(thr, -1);\n\t\t} else {\n#else  /* DUK_USE_REGEXP_SUPPORT */\n\t\t{  /* unconditionally */\n#endif  /* DUK_USE_REGEXP_SUPPORT */\n\t\t\tconst duk_uint8_t *p_start, *p_end, *p;   /* input string scan */\n\t\t\tconst duk_uint8_t *q_start;               /* match string */\n\t\t\tduk_size_t q_blen;\n\n#if defined(DUK_USE_REGEXP_SUPPORT)\n\t\t\tDUK_ASSERT(!is_global);  /* single match always */\n#endif\n\n\t\t\tp_start = DUK_HSTRING_GET_DATA(h_input);\n\t\t\tp_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input);\n\t\t\tp = p_start;\n\n\t\t\th_search = duk_known_hstring(thr, 0);\n\t\t\tq_start = DUK_HSTRING_GET_DATA(h_search);\n\t\t\tq_blen = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h_search);\n\n\t\t\tp_end -= q_blen;  /* ensure full memcmp() fits in while */\n\n\t\t\tmatch_start_coff = 0;\n\n\t\t\twhile (p <= p_end) {\n\t\t\t\tDUK_ASSERT(p + q_blen <= DUK_HSTRING_GET_DATA(h_input) + DUK_HSTRING_GET_BYTELEN(h_input));\n\t\t\t\tif (DUK_MEMCMP((const void *) p, (const void *) q_start, (size_t) q_blen) == 0) {\n\t\t\t\t\tduk_dup_0(thr);\n\t\t\t\t\th_match = duk_known_hstring(thr, -1);\n#if defined(DUK_USE_REGEXP_SUPPORT)\n\t\t\t\t\tmatch_caps = 0;\n#endif\n\t\t\t\t\tgoto found;\n\t\t\t\t}\n\n\t\t\t\t/* track utf-8 non-continuation bytes */\n\t\t\t\tif ((p[0] & 0xc0) != 0x80) {\n\t\t\t\t\tmatch_start_coff++;\n\t\t\t\t}\n\t\t\t\tp++;\n\t\t\t}\n\n\t\t\t/* not found */\n\t\t\tbreak;\n\t\t}\n\t found:\n\n\t\t/* stack[0] = search value\n\t\t * stack[1] = replace value\n\t\t * stack[2] = input string\n\t\t * stack[3] = result buffer\n\t\t * stack[4] = regexp match OR match string\n\t\t */\n\n\t\tmatch_start_boff = (duk_uint32_t) duk_heap_strcache_offset_char2byte(thr, h_input, match_start_coff);\n\n\t\ttmp_sz = (duk_size_t) (match_start_boff - prev_match_end_boff);\n\t\tDUK_BW_WRITE_ENSURE_BYTES(thr, bw, DUK_HSTRING_GET_DATA(h_input) + prev_match_end_boff, tmp_sz);\n\n\t\tprev_match_end_boff = match_start_boff + DUK_HSTRING_GET_BYTELEN(h_match);\n\n\t\tif (is_repl_func) {\n\t\t\tduk_idx_t idx_args;\n\t\t\tduk_hstring *h_repl;\n\n\t\t\t/* regexp res_obj is at index 4 */\n\n\t\t\tduk_dup_1(thr);\n\t\t\tidx_args = duk_get_top(thr);\n\n#if defined(DUK_USE_REGEXP_SUPPORT)\n\t\t\tif (is_regexp) {\n\t\t\t\tduk_int_t idx;\n\t\t\t\tduk_require_stack(thr, match_caps + 2);\n\t\t\t\tfor (idx = 0; idx < match_caps; idx++) {\n\t\t\t\t\t/* match followed by capture(s) */\n\t\t\t\t\tduk_get_prop_index(thr, 4, (duk_uarridx_t) idx);\n\t\t\t\t}\n\t\t\t} else {\n#else  /* DUK_USE_REGEXP_SUPPORT */\n\t\t\t{  /* unconditionally */\n#endif  /* DUK_USE_REGEXP_SUPPORT */\n\t\t\t\t/* match == search string, by definition */\n\t\t\t\tduk_dup_0(thr);\n\t\t\t}\n\t\t\tduk_push_uint(thr, (duk_uint_t) match_start_coff);\n\t\t\tduk_dup_2(thr);\n\n\t\t\t/* [ ... replacer match [captures] match_char_offset input ] */\n\n\t\t\tduk_call(thr, duk_get_top(thr) - idx_args);\n\t\t\th_repl = duk_to_hstring_m1(thr);  /* -> [ ... repl_value ] */\n\t\t\tDUK_ASSERT(h_repl != NULL);\n\n\t\t\tDUK_BW_WRITE_ENSURE_HSTRING(thr, bw, h_repl);\n\n\t\t\tduk_pop(thr);  /* repl_value */\n\t\t} else {\n\t\t\tr = r_start;\n\n\t\t\twhile (r < r_end) {\n\t\t\t\tduk_int_t ch1;\n\t\t\t\tduk_int_t ch2;\n#if defined(DUK_USE_REGEXP_SUPPORT)\n\t\t\t\tduk_int_t ch3;\n#endif\n\t\t\t\tduk_size_t left;\n\n\t\t\t\tch1 = *r++;\n\t\t\t\tif (ch1 != DUK_ASC_DOLLAR) {\n\t\t\t\t\tgoto repl_write;\n\t\t\t\t}\n\t\t\t\tDUK_ASSERT(r <= r_end);\n\t\t\t\tleft = (duk_size_t) (r_end - r);\n\n\t\t\t\tif (left <= 0) {\n\t\t\t\t\tgoto repl_write;\n\t\t\t\t}\n\n\t\t\t\tch2 = r[0];\n\t\t\t\tswitch (ch2) {\n\t\t\t\tcase DUK_ASC_DOLLAR: {\n\t\t\t\t\tch1 = (1 << 8) + DUK_ASC_DOLLAR;\n\t\t\t\t\tgoto repl_write;\n\t\t\t\t}\n\t\t\t\tcase DUK_ASC_AMP: {\n\t\t\t\t\tDUK_BW_WRITE_ENSURE_HSTRING(thr, bw, h_match);\n\t\t\t\t\tr++;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tcase DUK_ASC_GRAVE: {\n\t\t\t\t\ttmp_sz = (duk_size_t) match_start_boff;\n\t\t\t\t\tDUK_BW_WRITE_ENSURE_BYTES(thr, bw, DUK_HSTRING_GET_DATA(h_input), tmp_sz);\n\t\t\t\t\tr++;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tcase DUK_ASC_SINGLEQUOTE: {\n\t\t\t\t\tduk_uint32_t match_end_boff;\n\n\t\t\t\t\t/* Use match charlen instead of bytelen, just in case the input and\n\t\t\t\t\t * match codepoint encodings would have different lengths.\n\t\t\t\t\t */\n\t\t\t\t\t/* XXX: charlen computed here, and also in char2byte helper. */\n\t\t\t\t\tmatch_end_boff = (duk_uint32_t) duk_heap_strcache_offset_char2byte(thr,\n\t\t\t\t\t                                                                   h_input,\n\t\t\t\t\t                                                                   match_start_coff + (duk_uint_fast32_t) DUK_HSTRING_GET_CHARLEN(h_match));\n\n\t\t\t\t\ttmp_sz = (duk_size_t) (DUK_HSTRING_GET_BYTELEN(h_input) - match_end_boff);\n\t\t\t\t\tDUK_BW_WRITE_ENSURE_BYTES(thr, bw, DUK_HSTRING_GET_DATA(h_input) + match_end_boff, tmp_sz);\n\t\t\t\t\tr++;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tdefault: {\n#if defined(DUK_USE_REGEXP_SUPPORT)\n\t\t\t\t\tduk_int_t capnum, captmp, capadv;\n\t\t\t\t\t/* XXX: optional check, match_caps is zero if no regexp,\n\t\t\t\t\t * so dollar will be interpreted literally anyway.\n\t\t\t\t\t */\n\n\t\t\t\t\tif (!is_regexp) {\n\t\t\t\t\t\tgoto repl_write;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (!(ch2 >= DUK_ASC_0 && ch2 <= DUK_ASC_9)) {\n\t\t\t\t\t\tgoto repl_write;\n\t\t\t\t\t}\n\t\t\t\t\tcapnum = ch2 - DUK_ASC_0;\n\t\t\t\t\tcapadv = 1;\n\n\t\t\t\t\tif (left >= 2) {\n\t\t\t\t\t\tch3 = r[1];\n\t\t\t\t\t\tif (ch3 >= DUK_ASC_0 && ch3 <= DUK_ASC_9) {\n\t\t\t\t\t\t\tcaptmp = capnum * 10 + (ch3 - DUK_ASC_0);\n\t\t\t\t\t\t\tif (captmp < match_caps) {\n\t\t\t\t\t\t\t\tcapnum = captmp;\n\t\t\t\t\t\t\t\tcapadv = 2;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (capnum > 0 && capnum < match_caps) {\n\t\t\t\t\t\tDUK_ASSERT(is_regexp != 0);  /* match_caps == 0 without regexps */\n\n\t\t\t\t\t\t/* regexp res_obj is at offset 4 */\n\t\t\t\t\t\tduk_get_prop_index(thr, 4, (duk_uarridx_t) capnum);\n\t\t\t\t\t\tif (duk_is_string(thr, -1)) {\n\t\t\t\t\t\t\tduk_hstring *h_tmp_str;\n\n\t\t\t\t\t\t\th_tmp_str = duk_known_hstring(thr, -1);\n\n\t\t\t\t\t\t\tDUK_BW_WRITE_ENSURE_HSTRING(thr, bw, h_tmp_str);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t/* undefined -> skip (replaced with empty) */\n\t\t\t\t\t\t}\n\t\t\t\t\t\tduk_pop(thr);\n\t\t\t\t\t\tr += capadv;\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tgoto repl_write;\n\t\t\t\t\t}\n#else  /* DUK_USE_REGEXP_SUPPORT */\n\t\t\t\t\tgoto repl_write;  /* unconditionally */\n#endif  /* DUK_USE_REGEXP_SUPPORT */\n\t\t\t\t}  /* default case */\n\t\t\t\t}  /* switch (ch2) */\n\n\t\t\t repl_write:\n\t\t\t\t/* ch1 = (r_increment << 8) + byte */\n\n\t\t\t\tDUK_BW_WRITE_ENSURE_U8(thr, bw, (duk_uint8_t) (ch1 & 0xff));\n\t\t\t\tr += ch1 >> 8;\n\t\t\t}  /* while repl */\n\t\t}  /* if (is_repl_func) */\n\n\t\tduk_pop(thr);  /* pop regexp res_obj or match string */\n\n#if defined(DUK_USE_REGEXP_SUPPORT)\n\t\tif (!is_global) {\n#else\n\t\t{  /* unconditionally; is_global==0 */\n#endif\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t/* trailer */\n\ttmp_sz = (duk_size_t) (DUK_HSTRING_GET_BYTELEN(h_input) - prev_match_end_boff);\n\tDUK_BW_WRITE_ENSURE_BYTES(thr, bw, DUK_HSTRING_GET_DATA(h_input) + prev_match_end_boff, tmp_sz);\n\n\tDUK_ASSERT_TOP(thr, 4);\n\tDUK_BW_COMPACT(thr, bw);\n\t(void) duk_buffer_to_string(thr, -1);  /* Safe if inputs are safe. */\n\treturn 1;\n}\n\n/*\n *  split()\n */\n\n/* XXX: very messy now, but works; clean up, remove unused variables (nomimally\n * used so compiler doesn't complain).\n */\n\nDUK_INTERNAL duk_ret_t duk_bi_string_prototype_split(duk_hthread *thr) {\n\tduk_hstring *h_input;\n\tduk_hstring *h_sep;\n\tduk_uint32_t limit;\n\tduk_uint32_t arr_idx;\n#if defined(DUK_USE_REGEXP_SUPPORT)\n\tduk_bool_t is_regexp;\n#endif\n\tduk_bool_t matched;  /* set to 1 if any match exists (needed for empty input special case) */\n\tduk_uint32_t prev_match_end_coff, prev_match_end_boff;\n\tduk_uint32_t match_start_boff, match_start_coff;\n\tduk_uint32_t match_end_boff, match_end_coff;\n\n\th_input = duk_push_this_coercible_to_string(thr);\n\tDUK_ASSERT(h_input != NULL);\n\n\tduk_push_array(thr);\n\n\tif (duk_is_undefined(thr, 1)) {\n\t\tlimit = 0xffffffffUL;\n\t} else {\n\t\tlimit = duk_to_uint32(thr, 1);\n\t}\n\n\tif (limit == 0) {\n\t\treturn 1;\n\t}\n\n\t/* If the separator is a RegExp, make a \"clone\" of it.  The specification\n\t * algorithm calls [[Match]] directly for specific indices; we emulate this\n\t * by tweaking lastIndex and using a \"force global\" variant of duk_regexp_match()\n\t * which will use global-style matching even when the RegExp itself is non-global.\n\t */\n\n\tif (duk_is_undefined(thr, 0)) {\n\t\t/* The spec algorithm first does \"R = ToString(separator)\" before checking\n\t\t * whether separator is undefined.  Since this is side effect free, we can\n\t\t * skip the ToString() here.\n\t\t */\n\t\tduk_dup_2(thr);\n\t\tduk_put_prop_index(thr, 3, 0);\n\t\treturn 1;\n\t} else if (duk_get_hobject_with_class(thr, 0, DUK_HOBJECT_CLASS_REGEXP) != NULL) {\n#if defined(DUK_USE_REGEXP_SUPPORT)\n\t\tduk_push_hobject_bidx(thr, DUK_BIDX_REGEXP_CONSTRUCTOR);\n\t\tduk_dup_0(thr);\n\t\tduk_new(thr, 1);  /* [ ... RegExp val ] -> [ ... res ] */\n\t\tduk_replace(thr, 0);\n\t\t/* lastIndex is initialized to zero by new RegExp() */\n\t\tis_regexp = 1;\n#else\n\t\tDUK_DCERROR_UNSUPPORTED(thr);\n#endif\n\t} else {\n\t\tduk_to_string(thr, 0);\n#if defined(DUK_USE_REGEXP_SUPPORT)\n\t\tis_regexp = 0;\n#endif\n\t}\n\n\t/* stack[0] = separator (string or regexp)\n\t * stack[1] = limit\n\t * stack[2] = input string\n\t * stack[3] = result array\n\t */\n\n\tprev_match_end_boff = 0;\n\tprev_match_end_coff = 0;\n\tarr_idx = 0;\n\tmatched = 0;\n\n\tfor (;;) {\n\t\t/*\n\t\t *  The specification uses RegExp [[Match]] to attempt match at specific\n\t\t *  offsets.  We don't have such a primitive, so we use an actual RegExp\n\t\t *  and tweak lastIndex.  Since the RegExp may be non-global, we use a\n\t\t *  special variant which forces global-like behavior for matching.\n\t\t */\n\n\t\tDUK_ASSERT_TOP(thr, 4);\n\n#if defined(DUK_USE_REGEXP_SUPPORT)\n\t\tif (is_regexp) {\n\t\t\tduk_dup_0(thr);\n\t\t\tduk_dup_2(thr);\n\t\t\tduk_regexp_match_force_global(thr);  /* [ ... regexp input ] -> [ res_obj ] */\n\t\t\tif (!duk_is_object(thr, -1)) {\n\t\t\t\tduk_pop(thr);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tmatched = 1;\n\n\t\t\tduk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INDEX);\n\t\t\tDUK_ASSERT(duk_is_number(thr, -1));\n\t\t\tmatch_start_coff = duk_get_uint(thr, -1);\n\t\t\tmatch_start_boff = (duk_uint32_t) duk_heap_strcache_offset_char2byte(thr, h_input, match_start_coff);\n\t\t\tduk_pop(thr);\n\n\t\t\tif (match_start_coff == DUK_HSTRING_GET_CHARLEN(h_input)) {\n\t\t\t\t/* don't allow an empty match at the end of the string */\n\t\t\t\tduk_pop(thr);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tduk_get_prop_stridx_short(thr, 0, DUK_STRIDX_LAST_INDEX);\n\t\t\tDUK_ASSERT(duk_is_number(thr, -1));\n\t\t\tmatch_end_coff = duk_get_uint(thr, -1);\n\t\t\tmatch_end_boff = (duk_uint32_t) duk_heap_strcache_offset_char2byte(thr, h_input, match_end_coff);\n\t\t\tduk_pop(thr);\n\n\t\t\t/* empty match -> bump and continue */\n\t\t\tif (prev_match_end_boff == match_end_boff) {\n\t\t\t\tduk_push_uint(thr, (duk_uint_t) (match_end_coff + 1));\n\t\t\t\tduk_put_prop_stridx_short(thr, 0, DUK_STRIDX_LAST_INDEX);\n\t\t\t\tduk_pop(thr);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t} else {\n#else  /* DUK_USE_REGEXP_SUPPORT */\n\t\t{  /* unconditionally */\n#endif  /* DUK_USE_REGEXP_SUPPORT */\n\t\t\tconst duk_uint8_t *p_start, *p_end, *p;   /* input string scan */\n\t\t\tconst duk_uint8_t *q_start;               /* match string */\n\t\t\tduk_size_t q_blen, q_clen;\n\n\t\t\tp_start = DUK_HSTRING_GET_DATA(h_input);\n\t\t\tp_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input);\n\t\t\tp = p_start + prev_match_end_boff;\n\n\t\t\th_sep = duk_known_hstring(thr, 0);  /* symbol already rejected above */\n\t\t\tq_start = DUK_HSTRING_GET_DATA(h_sep);\n\t\t\tq_blen = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h_sep);\n\t\t\tq_clen = (duk_size_t) DUK_HSTRING_GET_CHARLEN(h_sep);\n\n\t\t\tp_end -= q_blen;  /* ensure full memcmp() fits in while */\n\n\t\t\tmatch_start_coff = prev_match_end_coff;\n\n\t\t\tif (q_blen == 0) {\n\t\t\t\t/* Handle empty separator case: it will always match, and always\n\t\t\t\t * triggers the check in step 13.c.iii initially.  Note that we\n\t\t\t\t * must skip to either end of string or start of first codepoint,\n\t\t\t\t * skipping over any continuation bytes!\n\t\t\t\t *\n\t\t\t\t * Don't allow an empty string to match at the end of the input.\n\t\t\t\t */\n\n\t\t\t\tmatched = 1;  /* empty separator can always match */\n\n\t\t\t\tmatch_start_coff++;\n\t\t\t\tp++;\n\t\t\t\twhile (p < p_end) {\n\t\t\t\t\tif ((p[0] & 0xc0) != 0x80) {\n\t\t\t\t\t\tgoto found;\n\t\t\t\t\t}\n\t\t\t\t\tp++;\n\t\t\t\t}\n\t\t\t\tgoto not_found;\n\t\t\t}\n\n\t\t\tDUK_ASSERT(q_blen > 0 && q_clen > 0);\n\t\t\twhile (p <= p_end) {\n\t\t\t\tDUK_ASSERT(p + q_blen <= DUK_HSTRING_GET_DATA(h_input) + DUK_HSTRING_GET_BYTELEN(h_input));\n\t\t\t\tDUK_ASSERT(q_blen > 0);  /* no issues with empty memcmp() */\n\t\t\t\tif (DUK_MEMCMP((const void *) p, (const void *) q_start, (size_t) q_blen) == 0) {\n\t\t\t\t\t/* never an empty match, so step 13.c.iii can't be triggered */\n\t\t\t\t\tgoto found;\n\t\t\t\t}\n\n\t\t\t\t/* track utf-8 non-continuation bytes */\n\t\t\t\tif ((p[0] & 0xc0) != 0x80) {\n\t\t\t\t\tmatch_start_coff++;\n\t\t\t\t}\n\t\t\t\tp++;\n\t\t\t}\n\n\t\t not_found:\n\t\t\t/* not found */\n\t\t\tbreak;\n\n\t\t found:\n\t\t\tmatched = 1;\n\t\t\tmatch_start_boff = (duk_uint32_t) (p - p_start);\n\t\t\tmatch_end_coff = (duk_uint32_t) (match_start_coff + q_clen);  /* constrained by string length */\n\t\t\tmatch_end_boff = (duk_uint32_t) (match_start_boff + q_blen);  /* ditto */\n\n\t\t\t/* empty match (may happen with empty separator) -> bump and continue */\n\t\t\tif (prev_match_end_boff == match_end_boff) {\n\t\t\t\tprev_match_end_boff++;\n\t\t\t\tprev_match_end_coff++;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}  /* if (is_regexp) */\n\n\t\t/* stack[0] = separator (string or regexp)\n\t\t * stack[1] = limit\n\t\t * stack[2] = input string\n\t\t * stack[3] = result array\n\t\t * stack[4] = regexp res_obj (if is_regexp)\n\t\t */\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"split; match_start b=%ld,c=%ld, match_end b=%ld,c=%ld, prev_end b=%ld,c=%ld\",\n\t\t                     (long) match_start_boff, (long) match_start_coff,\n\t\t                     (long) match_end_boff, (long) match_end_coff,\n\t\t                     (long) prev_match_end_boff, (long) prev_match_end_coff));\n\n\t\tduk_push_lstring(thr,\n\t\t                 (const char *) (DUK_HSTRING_GET_DATA(h_input) + prev_match_end_boff),\n\t\t                 (duk_size_t) (match_start_boff - prev_match_end_boff));\n\t\tduk_put_prop_index(thr, 3, arr_idx);\n\t\tarr_idx++;\n\t\tif (arr_idx >= limit) {\n\t\t\tgoto hit_limit;\n\t\t}\n\n#if defined(DUK_USE_REGEXP_SUPPORT)\n\t\tif (is_regexp) {\n\t\t\tduk_size_t i, len;\n\n\t\t\tlen = duk_get_length(thr, 4);\n\t\t\tfor (i = 1; i < len; i++) {\n\t\t\t\tDUK_ASSERT(i <= DUK_UARRIDX_MAX);  /* cannot have >4G captures */\n\t\t\t\tduk_get_prop_index(thr, 4, (duk_uarridx_t) i);\n\t\t\t\tduk_put_prop_index(thr, 3, arr_idx);\n\t\t\t\tarr_idx++;\n\t\t\t\tif (arr_idx >= limit) {\n\t\t\t\t\tgoto hit_limit;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tduk_pop(thr);\n\t\t\t/* lastIndex already set up for next match */\n\t\t} else {\n#else  /* DUK_USE_REGEXP_SUPPORT */\n\t\t{  /* unconditionally */\n#endif  /* DUK_USE_REGEXP_SUPPORT */\n\t\t\t/* no action */\n\t\t}\n\n\t\tprev_match_end_boff = match_end_boff;\n\t\tprev_match_end_coff = match_end_coff;\n\t\tcontinue;\n\t}  /* for */\n\n\t/* Combined step 11 (empty string special case) and 14-15. */\n\n\tDUK_DDD(DUK_DDDPRINT(\"split trailer; prev_end b=%ld,c=%ld\",\n\t                     (long) prev_match_end_boff, (long) prev_match_end_coff));\n\n\tif (DUK_HSTRING_GET_BYTELEN(h_input) > 0 || !matched) {\n\t\t/* Add trailer if:\n\t\t *   a) non-empty input\n\t\t *   b) empty input and no (zero size) match found (step 11)\n\t\t */\n\n\t\tduk_push_lstring(thr,\n\t\t                 (const char *) DUK_HSTRING_GET_DATA(h_input) + prev_match_end_boff,\n\t\t                 (duk_size_t) (DUK_HSTRING_GET_BYTELEN(h_input) - prev_match_end_boff));\n\t\tduk_put_prop_index(thr, 3, arr_idx);\n\t\t/* No arr_idx update or limit check */\n\t}\n\n\treturn 1;\n\n hit_limit:\n#if defined(DUK_USE_REGEXP_SUPPORT)\n\tif (is_regexp) {\n\t\tduk_pop(thr);\n\t}\n#endif\n\n\treturn 1;\n}\n\n/*\n *  Various\n */\n\n#if defined(DUK_USE_REGEXP_SUPPORT)\nDUK_LOCAL void duk__to_regexp_helper(duk_hthread *thr, duk_idx_t idx, duk_bool_t force_new) {\n\tduk_hobject *h;\n\n\t/* Shared helper for match() steps 3-4, search() steps 3-4. */\n\n\tDUK_ASSERT(idx >= 0);\n\n\tif (force_new) {\n\t\tgoto do_new;\n\t}\n\n\th = duk_get_hobject_with_class(thr, idx, DUK_HOBJECT_CLASS_REGEXP);\n\tif (!h) {\n\t\tgoto do_new;\n\t}\n\treturn;\n\n do_new:\n\tduk_push_hobject_bidx(thr, DUK_BIDX_REGEXP_CONSTRUCTOR);\n\tduk_dup(thr, idx);\n\tduk_new(thr, 1);  /* [ ... RegExp val ] -> [ ... res ] */\n\tduk_replace(thr, idx);\n}\n#endif  /* DUK_USE_REGEXP_SUPPORT */\n\n#if defined(DUK_USE_REGEXP_SUPPORT)\nDUK_INTERNAL duk_ret_t duk_bi_string_prototype_search(duk_hthread *thr) {\n\t/* Easiest way to implement the search required by the specification\n\t * is to do a RegExp test() with lastIndex forced to zero.  To avoid\n\t * side effects on the argument, \"clone\" the RegExp if a RegExp was\n\t * given as input.\n\t *\n\t * The global flag of the RegExp should be ignored; setting lastIndex\n\t * to zero (which happens when \"cloning\" the RegExp) should have an\n\t * equivalent effect.\n\t */\n\n\tDUK_ASSERT_TOP(thr, 1);\n\t(void) duk_push_this_coercible_to_string(thr);  /* at index 1 */\n\tduk__to_regexp_helper(thr, 0 /*index*/, 1 /*force_new*/);\n\n\t/* stack[0] = regexp\n\t * stack[1] = string\n\t */\n\n\t/* Avoid using RegExp.prototype methods, as they're writable and\n\t * configurable and may have been changed.\n\t */\n\n\tduk_dup_0(thr);\n\tduk_dup_1(thr);  /* [ ... re_obj input ] */\n\tduk_regexp_match(thr);  /* -> [ ... res_obj ] */\n\n\tif (!duk_is_object(thr, -1)) {\n\t\tduk_push_int(thr, -1);\n\t\treturn 1;\n\t}\n\n\tduk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INDEX);\n\tDUK_ASSERT(duk_is_number(thr, -1));\n\treturn 1;\n}\n#endif  /* DUK_USE_REGEXP_SUPPORT */\n\n#if defined(DUK_USE_REGEXP_SUPPORT)\nDUK_INTERNAL duk_ret_t duk_bi_string_prototype_match(duk_hthread *thr) {\n\tduk_bool_t global;\n\tduk_int_t prev_last_index;\n\tduk_int_t this_index;\n\tduk_int_t arr_idx;\n\n\tDUK_ASSERT_TOP(thr, 1);\n\t(void) duk_push_this_coercible_to_string(thr);\n\tduk__to_regexp_helper(thr, 0 /*index*/, 0 /*force_new*/);\n\tglobal = duk_get_prop_stridx_boolean(thr, 0, DUK_STRIDX_GLOBAL, NULL);\n\tDUK_ASSERT_TOP(thr, 2);\n\n\t/* stack[0] = regexp\n\t * stack[1] = string\n\t */\n\n\tif (!global) {\n\t\tduk_regexp_match(thr);  /* -> [ res_obj ] */\n\t\treturn 1;  /* return 'res_obj' */\n\t}\n\n\t/* Global case is more complex. */\n\n\t/* [ regexp string ] */\n\n\tduk_push_int(thr, 0);\n\tduk_put_prop_stridx_short(thr, 0, DUK_STRIDX_LAST_INDEX);\n\tduk_push_array(thr);\n\n\t/* [ regexp string res_arr ] */\n\n\tprev_last_index = 0;\n\tarr_idx = 0;\n\n\tfor (;;) {\n\t\tDUK_ASSERT_TOP(thr, 3);\n\n\t\tduk_dup_0(thr);\n\t\tduk_dup_1(thr);\n\t\tduk_regexp_match(thr);  /* -> [ ... regexp string ] -> [ ... res_obj ] */\n\n\t\tif (!duk_is_object(thr, -1)) {\n\t\t\tduk_pop(thr);\n\t\t\tbreak;\n\t\t}\n\n\t\tduk_get_prop_stridx_short(thr, 0, DUK_STRIDX_LAST_INDEX);\n\t\tDUK_ASSERT(duk_is_number(thr, -1));\n\t\tthis_index = duk_get_int(thr, -1);\n\t\tduk_pop(thr);\n\n\t\tif (this_index == prev_last_index) {\n\t\t\tthis_index++;\n\t\t\tduk_push_int(thr, this_index);\n\t\t\tduk_put_prop_stridx_short(thr, 0, DUK_STRIDX_LAST_INDEX);\n\t\t}\n\t\tprev_last_index = this_index;\n\n\t\tduk_get_prop_index(thr, -1, 0);  /* match string */\n\t\tduk_put_prop_index(thr, 2, (duk_uarridx_t) arr_idx);\n\t\tarr_idx++;\n\t\tduk_pop(thr);  /* res_obj */\n\t}\n\n\tif (arr_idx == 0) {\n\t\tduk_push_null(thr);\n\t}\n\n\treturn 1;  /* return 'res_arr' or 'null' */\n}\n#endif  /* DUK_USE_REGEXP_SUPPORT */\n\nDUK_INTERNAL duk_ret_t duk_bi_string_prototype_concat(duk_hthread *thr) {\n\t/* duk_concat() coerces arguments with ToString() in correct order */\n\t(void) duk_push_this_coercible_to_string(thr);\n\tduk_insert(thr, 0);  /* this is relatively expensive */\n\tduk_concat(thr, duk_get_top(thr));\n\treturn 1;\n}\n\nDUK_INTERNAL duk_ret_t duk_bi_string_prototype_trim(duk_hthread *thr) {\n\tDUK_ASSERT_TOP(thr, 0);\n\t(void) duk_push_this_coercible_to_string(thr);\n\tduk_trim(thr, 0);\n\tDUK_ASSERT_TOP(thr, 1);\n\treturn 1;\n}\n\n#if defined(DUK_USE_ES6)\nDUK_INTERNAL duk_ret_t duk_bi_string_prototype_repeat(duk_hthread *thr) {\n\tduk_hstring *h_input;\n\tduk_size_t input_blen;\n\tduk_size_t result_len;\n\tduk_int_t count_signed;\n\tduk_uint_t count;\n\tconst duk_uint8_t *src;\n\tduk_uint8_t *buf;\n\tduk_uint8_t *p;\n\tduk_double_t d;\n#if !defined(DUK_USE_PREFER_SIZE)\n\tduk_size_t copy_size;\n\tduk_uint8_t *p_end;\n#endif\n\n\tDUK_ASSERT_TOP(thr, 1);\n\th_input = duk_push_this_coercible_to_string(thr);\n\tDUK_ASSERT(h_input != NULL);\n\tinput_blen = DUK_HSTRING_GET_BYTELEN(h_input);\n\n\t/* Count is ToNumber() coerced; +Infinity must be always rejected\n\t * (even if input string is zero length), as well as negative values\n\t * and -Infinity.  -Infinity doesn't require an explicit check\n\t * because duk_get_int() clamps it to DUK_INT_MIN which gets rejected\n\t * as a negative value (regardless of input string length).\n\t */\n\td = duk_to_number(thr, 0);\n\tif (duk_double_is_posinf(d)) {\n\t\tgoto fail_range;\n\t}\n\tcount_signed = duk_get_int(thr, 0);\n\tif (count_signed < 0) {\n\t\tgoto fail_range;\n\t}\n\tcount = (duk_uint_t) count_signed;\n\n\t/* Overflow check for result length. */\n\tresult_len = count * input_blen;\n\tif (count != 0 && result_len / count != input_blen) {\n\t\tgoto fail_range;\n\t}\n\n\t/* Temporary fixed buffer, later converted to string. */\n\tbuf = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, result_len);\n\tsrc = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input);\n\n#if defined(DUK_USE_PREFER_SIZE)\n\tp = buf;\n\twhile (count-- > 0) {\n\t\tDUK_MEMCPY((void *) p, (const void *) src, input_blen);  /* copy size may be zero */\n\t\tp += input_blen;\n\t}\n#else  /* DUK_USE_PREFER_SIZE */\n\t/* Take advantage of already copied pieces to speed up the process\n\t * especially for small repeated strings.\n\t */\n\tp = buf;\n\tp_end = p + result_len;\n\tcopy_size = input_blen;\n\tfor (;;) {\n\t\tduk_size_t remain = (duk_size_t) (p_end - p);\n\t\tDUK_DDD(DUK_DDDPRINT(\"remain=%ld, copy_size=%ld, input_blen=%ld, result_len=%ld\",\n\t\t                     (long) remain, (long) copy_size, (long) input_blen,\n\t\t                     (long) result_len));\n\t\tif (remain <= copy_size) {\n\t\t\t/* If result_len is zero, this case is taken and does\n\t\t\t * a zero size copy.\n\t\t\t */\n\t\t\tDUK_MEMCPY((void *) p, (const void *) src, remain);\n\t\t\tbreak;\n\t\t} else {\n\t\t\tDUK_MEMCPY((void *) p, (const void *) src, copy_size);\n\t\t\tp += copy_size;\n\t\t}\n\n\t\tsrc = (const duk_uint8_t *) buf;  /* Use buf as source for larger copies. */\n\t\tcopy_size = (duk_size_t) (p - buf);\n\t}\n#endif  /* DUK_USE_PREFER_SIZE */\n\n\t/* XXX: It would be useful to be able to create a duk_hstring with\n\t * a certain byte size whose data area wasn't initialized and which\n\t * wasn't in the string table yet.  This would allow a string to be\n\t * constructed directly without a buffer temporary and when it was\n\t * finished, it could be injected into the string table.  Currently\n\t * this isn't possible because duk_hstrings are only tracked by the\n\t * intern table (they are not in heap_allocated).\n\t */\n\n\tduk_buffer_to_string(thr, -1);  /* Safe if input is safe. */\n\treturn 1;\n\n fail_range:\n\tDUK_DCERROR_RANGE_INVALID_ARGS(thr);\n}\n#endif  /* DUK_USE_ES6 */\n\nDUK_INTERNAL duk_ret_t duk_bi_string_prototype_locale_compare(duk_hthread *thr) {\n\tduk_hstring *h1;\n\tduk_hstring *h2;\n\tduk_size_t h1_len, h2_len, prefix_len;\n\tduk_small_int_t ret = 0;\n\tduk_small_int_t rc;\n\n\t/* The current implementation of localeCompare() is simply a codepoint\n\t * by codepoint comparison, implemented with a simple string compare\n\t * because UTF-8 should preserve codepoint ordering (assuming valid\n\t * shortest UTF-8 encoding).\n\t *\n\t * The specification requires that the return value must be related\n\t * to the sort order: e.g. negative means that 'this' comes before\n\t * 'that' in sort order.  We assume an ascending sort order.\n\t */\n\n\t/* XXX: could share code with duk_js_ops.c, duk_js_compare_helper */\n\n\th1 = duk_push_this_coercible_to_string(thr);\n\tDUK_ASSERT(h1 != NULL);\n\n\th2 = duk_to_hstring(thr, 0);\n\tDUK_ASSERT(h2 != NULL);\n\n\th1_len = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h1);\n\th2_len = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h2);\n\tprefix_len = (h1_len <= h2_len ? h1_len : h2_len);\n\n\t/* Zero size compare not an issue with DUK_MEMCMP. */\n\trc = (duk_small_int_t) DUK_MEMCMP((const void *) DUK_HSTRING_GET_DATA(h1),\n\t                                  (const void *) DUK_HSTRING_GET_DATA(h2),\n\t                                  (size_t) prefix_len);\n\n\tif (rc < 0) {\n\t\tret = -1;\n\t\tgoto done;\n\t} else if (rc > 0) {\n\t\tret = 1;\n\t\tgoto done;\n\t}\n\n\t/* prefix matches, lengths matter now */\n\tif (h1_len > h2_len) {\n\t\tret = 1;\n\t\tgoto done;\n\t} else if (h1_len == h2_len) {\n\t\tDUK_ASSERT(ret == 0);\n\t\tgoto done;\n\t}\n\tret = -1;\n\tgoto done;\n\n done:\n\tduk_push_int(thr, (duk_int_t) ret);\n\treturn 1;\n}\n\n#if defined(DUK_USE_ES6)\nDUK_INTERNAL duk_ret_t duk_bi_string_prototype_startswith_endswith(duk_hthread *thr) {\n\tduk_int_t magic;\n\tduk_hstring *h;\n\tduk_hstring *h_search;\n\tduk_size_t blen_search;\n\tconst duk_uint8_t *p_cmp_start;\n\tduk_bool_t result;\n\n\th = duk_push_this_coercible_to_string(thr);\n\tDUK_ASSERT(h != NULL);\n\n\th_search = duk__str_tostring_notregexp(thr, 0);\n\tDUK_ASSERT(h_search != NULL);\n\n\tmagic = duk_get_current_magic(thr);\n\n\tp_cmp_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h);\n\tblen_search = DUK_HSTRING_GET_BYTELEN(h_search);\n\n\tif (duk_is_undefined(thr, 1)) {\n\t\tif (magic) {\n\t\t\tp_cmp_start += DUK_HSTRING_GET_BYTELEN(h) - blen_search;\n\t\t} else {\n\t\t\t/* p_cmp_start already OK */\n\t\t}\n\t} else {\n\t\tduk_int_t len;\n\t\tduk_int_t pos;\n\n\t\tDUK_ASSERT(DUK_HSTRING_MAX_BYTELEN <= DUK_INT_MAX);\n\t\tlen = (duk_int_t) DUK_HSTRING_GET_CHARLEN(h);\n\t\tpos = duk_to_int_clamped(thr, 1, 0, len);\n\t\tDUK_ASSERT(pos >= 0 && pos <= len);\n\n\t\tif (magic) {\n\t\t\tp_cmp_start -= blen_search;  /* Conceptually subtracted last, but do already here. */\n\t\t}\n\t\tDUK_ASSERT(pos >= 0 && pos <= len);\n\n\t\tp_cmp_start += duk_heap_strcache_offset_char2byte(thr, h, (duk_uint_fast32_t) pos);\n\t}\n\n\t/* The main comparison can be done using a memcmp() rather than\n\t * doing codepoint comparisons: for CESU-8 strings there is a\n\t * canonical representation for every codepoint.  But we do need\n\t * to deal with the char/byte offset translation to find the\n\t * comparison range.\n\t */\n\n\tresult = 0;\n\tif (p_cmp_start >= DUK_HSTRING_GET_DATA(h) &&\n\t    (duk_size_t) (p_cmp_start - (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h)) + blen_search <= DUK_HSTRING_GET_BYTELEN(h)) {\n\t\tif (DUK_MEMCMP((const void *) p_cmp_start,\n\t\t               (const void *) DUK_HSTRING_GET_DATA(h_search),\n\t\t               (size_t) blen_search) == 0) {\n\t\t\tresult = 1;\n\t\t}\n\t}\n\n\tduk_push_boolean(thr, result);\n\treturn 1;\n}\n#endif  /* DUK_USE_ES6 */\n\n#if defined(DUK_USE_ES6)\nDUK_INTERNAL duk_ret_t duk_bi_string_prototype_includes(duk_hthread *thr) {\n\tduk_hstring *h;\n\tduk_hstring *h_search;\n\tduk_int_t len;\n\tduk_int_t pos;\n\n\th = duk_push_this_coercible_to_string(thr);\n\tDUK_ASSERT(h != NULL);\n\n\th_search = duk__str_tostring_notregexp(thr, 0);\n\tDUK_ASSERT(h_search != NULL);\n\n\tlen = (duk_int_t) DUK_HSTRING_GET_CHARLEN(h);\n\tpos = duk_to_int_clamped(thr, 1, 0, len);\n\tDUK_ASSERT(pos >= 0 && pos <= len);\n\n\tpos = duk__str_search_shared(thr, h, h_search, pos, 0 /*backwards*/);\n\tduk_push_boolean(thr, pos >= 0);\n\treturn 1;\n}\n#endif  /* DUK_USE_ES6 */\n#endif  /* DUK_USE_STRING_BUILTIN */\n#line 1 \"duk_bi_symbol.c\"\n/*\n *  Symbol built-in\n */\n\n/* #include duk_internal.h -> already included */\n\n#if defined(DUK_USE_SYMBOL_BUILTIN)\n\n/*\n *  Constructor\n */\n\nDUK_INTERNAL duk_ret_t duk_bi_symbol_constructor_shared(duk_hthread *thr) {\n\tconst duk_uint8_t *desc;\n\tduk_size_t len;\n\tduk_uint8_t *buf;\n\tduk_uint8_t *p;\n\tduk_int_t magic;\n\n\tmagic = duk_get_current_magic(thr);\n\tif (duk_is_undefined(thr, 0) && (magic == 0)) {\n\t\t/* Symbol() accepts undefined and empty string, but they are\n\t\t * treated differently.\n\t\t */\n\t\tdesc = NULL;\n\t\tlen = 0;\n\t} else {\n\t\t/* Symbol.for() coerces undefined to 'undefined' */\n\t\tdesc = (const duk_uint8_t *) duk_to_lstring(thr, 0, &len);\n\t}\n\n\t/* Maximum symbol data length:\n\t *   +1    initial byte (0x80 or 0x81)\n\t *   +len  description\n\t *   +1    0xff after description, before unique suffix\n\t *   +17   autogenerated unique suffix: 'ffffffff-ffffffff' is longest\n\t *   +1    0xff after unique suffix for symbols with undefined description\n\t */\n\tbuf = (duk_uint8_t *) duk_push_fixed_buffer(thr, 1 + len + 1 + 17 + 1);\n\tp = buf + 1;\n\tDUK_ASSERT(desc != NULL || len == 0);  /* may be NULL if len is 0 */\n\tDUK_MEMCPY((void *) p, (const void *) desc, len);\n\tp += len;\n\tif (magic == 0) {\n\t\t/* Symbol(): create unique symbol.  Use two 32-bit values\n\t\t * to avoid dependency on 64-bit types and 64-bit integer\n\t\t * formatting (at least for now).\n\t\t */\n\t\tif (++thr->heap->sym_counter[0] == 0) {\n\t\t\tthr->heap->sym_counter[1]++;\n\t\t}\n\t\tp += DUK_SPRINTF((char *) p, \"\\xFF\" \"%lx-%lx\",\n\t\t                 (unsigned long) thr->heap->sym_counter[1],\n\t\t                 (unsigned long) thr->heap->sym_counter[0]);\n\t\tif (desc == NULL) {\n\t\t\t/* Special case for 'undefined' description, trailing\n\t\t\t * 0xff distinguishes from empty string description,\n\t\t\t * but needs minimal special case handling elsewhere.\n\t\t\t */\n\t\t\t*p++ = 0xff;\n\t\t}\n\t\tbuf[0] = 0x81;\n\t} else {\n\t\t/* Symbol.for(): create a global symbol */\n\t\tbuf[0] = 0x80;\n\t}\n\n\tduk_push_lstring(thr, (const char *) buf, (duk_size_t) (p - buf));\n\tDUK_DDD(DUK_DDDPRINT(\"created symbol: %!T\", duk_get_tval(thr, -1)));\n\treturn 1;\n}\n\nDUK_LOCAL duk_hstring *duk__auto_unbox_symbol(duk_hthread *thr, duk_tval *tv_arg) {\n\tduk_tval *tv;\n\tduk_tval tv_val;\n\tduk_hobject *h_obj;\n\tduk_hstring *h_str;\n\n\tDUK_ASSERT(tv_arg != NULL);\n\n\t/* XXX: add internal helper: duk_auto_unbox_tval(thr, tv, mask); */\n\t/* XXX: add internal helper: duk_auto_unbox(thr, tv, idx); */\n\n\ttv = tv_arg;\n\tif (DUK_TVAL_IS_OBJECT(tv)) {\n\t\th_obj = DUK_TVAL_GET_OBJECT(tv);\n\t\tDUK_ASSERT(h_obj != NULL);\n\t\tif (DUK_HOBJECT_GET_CLASS_NUMBER(h_obj) == DUK_HOBJECT_CLASS_SYMBOL) {\n\t\t\tif (!duk_hobject_get_internal_value(thr->heap, h_obj, &tv_val)) {\n\t\t\t\treturn NULL;\n\t\t\t}\n\t\t\ttv = &tv_val;\n\t\t} else {\n\t\t\treturn NULL;\n\t\t}\n\t}\n\n\tif (!DUK_TVAL_IS_STRING(tv)) {\n\t\treturn NULL;\n\t}\n\th_str = DUK_TVAL_GET_STRING(tv);\n\tDUK_ASSERT(h_str != NULL);\n\n\t/* Here symbol is more expected than not. */\n\tif (DUK_UNLIKELY(!DUK_HSTRING_HAS_SYMBOL(h_str))) {\n\t\treturn NULL;\n\t}\n\n\treturn h_str;\n}\n\nDUK_INTERNAL duk_ret_t duk_bi_symbol_tostring_shared(duk_hthread *thr) {\n\tduk_hstring *h_str;\n\n\th_str = duk__auto_unbox_symbol(thr, DUK_HTHREAD_THIS_PTR(thr));\n\tif (h_str == NULL) {\n\t\treturn DUK_RET_TYPE_ERROR;\n\t}\n\n\tif (duk_get_current_magic(thr) == 0) {\n\t\t/* .toString() */\n\t\tduk_push_symbol_descriptive_string(thr, h_str);\n\t} else {\n\t\t/* .valueOf() */\n\t\tduk_push_hstring(thr, h_str);\n\t}\n\treturn 1;\n}\n\nDUK_INTERNAL duk_ret_t duk_bi_symbol_key_for(duk_hthread *thr) {\n\tduk_hstring *h;\n\tconst duk_uint8_t *p;\n\n\t/* Argument must be a symbol but not checked here.  The initial byte\n\t * check will catch non-symbol strings.\n\t */\n\th = duk_require_hstring(thr, 0);\n\tDUK_ASSERT(h != NULL);\n\n\tp = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h);\n\tDUK_ASSERT(p != NULL);\n\n\t/* Even for zero length strings there's at least one NUL byte so\n\t * we can safely check the initial byte.\n\t */\n\tif (p[0] == 0x80) {\n\t\t/* Global symbol, return its key (bytes just after the initial byte). */\n\t\tduk_push_lstring(thr, (const char *) (p + 1), (duk_size_t) (DUK_HSTRING_GET_BYTELEN(h) - 1));\n\t\treturn 1;\n\t} else if (p[0] == 0x81 || p[0] == 0x82 || p[0] == 0xff) {\n\t\t/* Local symbol or hidden symbol, return undefined. */\n\t\treturn 0;\n\t}\n\n\t/* Covers normal strings and unknown initial bytes. */\n\treturn DUK_RET_TYPE_ERROR;\n}\n\nDUK_INTERNAL duk_ret_t duk_bi_symbol_toprimitive(duk_hthread *thr) {\n\tduk_hstring *h_str;\n\n\th_str = duk__auto_unbox_symbol(thr, DUK_HTHREAD_THIS_PTR(thr));\n\tif (h_str == NULL) {\n\t\treturn DUK_RET_TYPE_ERROR;\n\t}\n\tduk_push_hstring(thr, h_str);\n\treturn 1;\n}\n\n#endif  /* DUK_USE_SYMBOL_BUILTIN */\n#line 1 \"duk_bi_thread.c\"\n/*\n *  Thread builtins\n */\n\n/* #include duk_internal.h -> already included */\n\n/*\n *  Constructor\n */\n\n#if defined(DUK_USE_COROUTINE_SUPPORT)\nDUK_INTERNAL duk_ret_t duk_bi_thread_constructor(duk_hthread *thr) {\n\tduk_hthread *new_thr;\n\tduk_hobject *func;\n\n\t/* Check that the argument is callable; this is not 100% because we\n\t * don't allow native functions to be a thread's initial function.\n\t * Resume will reject such functions in any case.\n\t */\n\t/* XXX: need a duk_require_func_promote_lfunc() */\n\tfunc = duk_require_hobject_promote_lfunc(thr, 0);\n\tDUK_ASSERT(func != NULL);\n\tduk_require_callable(thr, 0);\n\n\tduk_push_thread(thr);\n\tnew_thr = (duk_hthread *) duk_known_hobject(thr, -1);\n\tnew_thr->state = DUK_HTHREAD_STATE_INACTIVE;\n\n\t/* push initial function call to new thread stack; this is\n\t * picked up by resume().\n\t */\n\tduk_push_hobject(new_thr, func);\n\n\treturn 1;  /* return thread */\n}\n#endif\n\n/*\n *  Resume a thread.\n *\n *  The thread must be in resumable state, either (a) new thread which hasn't\n *  yet started, or (b) a thread which has previously yielded.  This method\n *  must be called from an Ecmascript function.\n *\n *  Args:\n *    - thread\n *    - value\n *    - isError (defaults to false)\n *\n *  Note: yield and resume handling is currently asymmetric.\n */\n\n#if defined(DUK_USE_COROUTINE_SUPPORT)\nDUK_INTERNAL duk_ret_t duk_bi_thread_resume(duk_hthread *ctx) {\n\tduk_hthread *thr = (duk_hthread *) ctx;\n\tduk_hthread *thr_resume;\n\tduk_hobject *caller_func;\n\tduk_small_uint_t is_error;\n\n\tDUK_DDD(DUK_DDDPRINT(\"Duktape.Thread.resume(): thread=%!T, value=%!T, is_error=%!T\",\n\t                     (duk_tval *) duk_get_tval(thr, 0),\n\t                     (duk_tval *) duk_get_tval(thr, 1),\n\t                     (duk_tval *) duk_get_tval(thr, 2)));\n\n\tDUK_ASSERT(thr->state == DUK_HTHREAD_STATE_RUNNING);\n\tDUK_ASSERT(thr->heap->curr_thread == thr);\n\n\tthr_resume = duk_require_hthread(thr, 0);\n\tis_error = (duk_small_uint_t) duk_to_boolean(thr, 2);\n\tduk_set_top(thr, 2);\n\n\t/* [ thread value ] */\n\n\t/*\n\t *  Thread state and calling context checks\n\t */\n\n\tif (thr->callstack_top < 2) {\n\t\tDUK_DD(DUK_DDPRINT(\"resume state invalid: callstack should contain at least 2 entries (caller and Duktape.Thread.resume)\"));\n\t\tgoto state_error;\n\t}\n\tDUK_ASSERT(thr->callstack_curr != NULL);\n\tDUK_ASSERT(thr->callstack_curr->parent != NULL);\n\tDUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack_curr) != NULL);  /* us */\n\tDUK_ASSERT(DUK_HOBJECT_IS_NATFUNC(DUK_ACT_GET_FUNC(thr->callstack_curr)));\n\tDUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack_curr->parent) != NULL);  /* caller */\n\n\tcaller_func = DUK_ACT_GET_FUNC(thr->callstack_curr->parent);\n\tif (!DUK_HOBJECT_IS_COMPFUNC(caller_func)) {\n\t\tDUK_DD(DUK_DDPRINT(\"resume state invalid: caller must be Ecmascript code\"));\n\t\tgoto state_error;\n\t}\n\n\t/* Note: there is no requirement that: 'thr->callstack_preventcount == 1'\n\t * like for yield.\n\t */\n\n\tif (thr_resume->state != DUK_HTHREAD_STATE_INACTIVE &&\n\t    thr_resume->state != DUK_HTHREAD_STATE_YIELDED) {\n\t\tDUK_DD(DUK_DDPRINT(\"resume state invalid: target thread must be INACTIVE or YIELDED\"));\n\t\tgoto state_error;\n\t}\n\n\tDUK_ASSERT(thr_resume->state == DUK_HTHREAD_STATE_INACTIVE ||\n\t           thr_resume->state == DUK_HTHREAD_STATE_YIELDED);\n\n\t/* Further state-dependent pre-checks */\n\n\tif (thr_resume->state == DUK_HTHREAD_STATE_YIELDED) {\n\t\t/* no pre-checks now, assume a previous yield() has left things in\n\t\t * tip-top shape (longjmp handler will assert for these).\n\t\t */\n\t} else {\n\t\tduk_hobject *h_fun;\n\n\t\tDUK_ASSERT(thr_resume->state == DUK_HTHREAD_STATE_INACTIVE);\n\n\t\t/* The initial function must be an Ecmascript function (but\n\t\t * can be bound).  We must make sure of that before we longjmp\n\t\t * because an error in the RESUME handler call processing will\n\t\t * not be handled very cleanly.\n\t\t */\n\t\tif ((thr_resume->callstack_top != 0) ||\n\t\t    (thr_resume->valstack_top - thr_resume->valstack != 1)) {\n\t\t\tgoto state_error;\n\t\t}\n\n\t\tduk_push_tval(thr, DUK_GET_TVAL_NEGIDX(thr_resume, -1));\n\t\tduk_resolve_nonbound_function(thr);\n\t\th_fun = duk_require_hobject(thr, -1);  /* reject lightfuncs on purpose */\n\t\tif (!DUK_HOBJECT_IS_CALLABLE(h_fun) || !DUK_HOBJECT_IS_COMPFUNC(h_fun)) {\n\t\t\tgoto state_error;\n\t\t}\n\t\tduk_pop(thr);\n\t}\n\n\t/*\n\t *  The error object has been augmented with a traceback and other\n\t *  info from its creation point -- usually another thread.  The\n\t *  error handler is called here right before throwing, but it also\n\t *  runs in the resumer's thread.  It might be nice to get a traceback\n\t *  from the resumee but this is not the case now.\n\t */\n\n#if defined(DUK_USE_AUGMENT_ERROR_THROW)\n\tif (is_error) {\n\t\tDUK_ASSERT_TOP(thr, 2);  /* value (error) is at stack top */\n\t\tduk_err_augment_error_throw(thr);  /* in resumer's context */\n\t}\n#endif\n\n#if defined(DUK_USE_DEBUG)\n\tif (is_error) {\n\t\tDUK_DDD(DUK_DDDPRINT(\"RESUME ERROR: thread=%!T, value=%!T\",\n\t\t                     (duk_tval *) duk_get_tval(thr, 0),\n\t\t                     (duk_tval *) duk_get_tval(thr, 1)));\n\t} else if (thr_resume->state == DUK_HTHREAD_STATE_YIELDED) {\n\t\tDUK_DDD(DUK_DDDPRINT(\"RESUME NORMAL: thread=%!T, value=%!T\",\n\t\t                     (duk_tval *) duk_get_tval(thr, 0),\n\t\t                     (duk_tval *) duk_get_tval(thr, 1)));\n\t} else {\n\t\tDUK_DDD(DUK_DDDPRINT(\"RESUME INITIAL: thread=%!T, value=%!T\",\n\t\t                     (duk_tval *) duk_get_tval(thr, 0),\n\t\t                     (duk_tval *) duk_get_tval(thr, 1)));\n\t}\n#endif\n\n\tthr->heap->lj.type = DUK_LJ_TYPE_RESUME;\n\n\t/* lj value2: thread */\n\tDUK_ASSERT(thr->valstack_bottom < thr->valstack_top);\n\tDUK_TVAL_SET_TVAL_UPDREF(thr, &thr->heap->lj.value2, &thr->valstack_bottom[0]);  /* side effects */\n\n\t/* lj value1: value */\n\tDUK_ASSERT(thr->valstack_bottom + 1 < thr->valstack_top);\n\tDUK_TVAL_SET_TVAL_UPDREF(thr, &thr->heap->lj.value1, &thr->valstack_bottom[1]);  /* side effects */\n\tDUK_TVAL_CHKFAST_INPLACE_SLOW(&thr->heap->lj.value1);\n\n\tthr->heap->lj.iserror = is_error;\n\n\tDUK_ASSERT(thr->heap->lj.jmpbuf_ptr != NULL);  /* call is from executor, so we know we have a jmpbuf */\n\tduk_err_longjmp(thr);  /* execution resumes in bytecode executor */\n\tDUK_UNREACHABLE();\n\t/* Never here, fall through to error (from compiler point of view). */\n\n state_error:\n\tDUK_DCERROR_TYPE_INVALID_STATE(thr);\n}\n#endif\n\n/*\n *  Yield the current thread.\n *\n *  The thread must be in yieldable state: it must have a resumer, and there\n *  must not be any yield-preventing calls (native calls and constructor calls,\n *  currently) in the thread's call stack (otherwise a resume would not be\n *  possible later).  This method must be called from an Ecmascript function.\n *\n *  Args:\n *    - value\n *    - isError (defaults to false)\n *\n *  Note: yield and resume handling is currently asymmetric.\n */\n\n#if defined(DUK_USE_COROUTINE_SUPPORT)\nDUK_INTERNAL duk_ret_t duk_bi_thread_yield(duk_hthread *thr) {\n\tduk_hobject *caller_func;\n\tduk_small_uint_t is_error;\n\n\tDUK_DDD(DUK_DDDPRINT(\"Duktape.Thread.yield(): value=%!T, is_error=%!T\",\n\t                     (duk_tval *) duk_get_tval(thr, 0),\n\t                     (duk_tval *) duk_get_tval(thr, 1)));\n\n\tDUK_ASSERT(thr->state == DUK_HTHREAD_STATE_RUNNING);\n\tDUK_ASSERT(thr->heap->curr_thread == thr);\n\n\tis_error = (duk_small_uint_t) duk_to_boolean(thr, 1);\n\tduk_set_top(thr, 1);\n\n\t/* [ value ] */\n\n\t/*\n\t *  Thread state and calling context checks\n\t */\n\n\tif (!thr->resumer) {\n\t\tDUK_DD(DUK_DDPRINT(\"yield state invalid: current thread must have a resumer\"));\n\t\tgoto state_error;\n\t}\n\tDUK_ASSERT(thr->resumer->state == DUK_HTHREAD_STATE_RESUMED);\n\n\tif (thr->callstack_top < 2) {\n\t\tDUK_DD(DUK_DDPRINT(\"yield state invalid: callstack should contain at least 2 entries (caller and Duktape.Thread.yield)\"));\n\t\tgoto state_error;\n\t}\n\tDUK_ASSERT(thr->callstack_curr != NULL);\n\tDUK_ASSERT(thr->callstack_curr->parent != NULL);\n\tDUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack_curr) != NULL);  /* us */\n\tDUK_ASSERT(DUK_HOBJECT_IS_NATFUNC(DUK_ACT_GET_FUNC(thr->callstack_curr)));\n\tDUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack_curr->parent) != NULL);  /* caller */\n\n\tcaller_func = DUK_ACT_GET_FUNC(thr->callstack_curr->parent);\n\tif (!DUK_HOBJECT_IS_COMPFUNC(caller_func)) {\n\t\tDUK_DD(DUK_DDPRINT(\"yield state invalid: caller must be Ecmascript code\"));\n\t\tgoto state_error;\n\t}\n\n\tDUK_ASSERT(thr->callstack_preventcount >= 1);  /* should never be zero, because we (Duktape.Thread.yield) are on the stack */\n\tif (thr->callstack_preventcount != 1) {\n\t\t/* Note: the only yield-preventing call is Duktape.Thread.yield(), hence check for 1, not 0 */\n\t\tDUK_DD(DUK_DDPRINT(\"yield state invalid: there must be no yield-preventing calls in current thread callstack (preventcount is %ld)\",\n\t\t                   (long) thr->callstack_preventcount));\n\t\tgoto state_error;\n\t}\n\n\t/*\n\t *  The error object has been augmented with a traceback and other\n\t *  info from its creation point -- usually the current thread.\n\t *  The error handler, however, is called right before throwing\n\t *  and runs in the yielder's thread.\n\t */\n\n#if defined(DUK_USE_AUGMENT_ERROR_THROW)\n\tif (is_error) {\n\t\tDUK_ASSERT_TOP(thr, 1);  /* value (error) is at stack top */\n\t\tduk_err_augment_error_throw(thr);  /* in yielder's context */\n\t}\n#endif\n\n#if defined(DUK_USE_DEBUG)\n\tif (is_error) {\n\t\tDUK_DDD(DUK_DDDPRINT(\"YIELD ERROR: value=%!T\",\n\t\t                     (duk_tval *) duk_get_tval(thr, 0)));\n\t} else {\n\t\tDUK_DDD(DUK_DDDPRINT(\"YIELD NORMAL: value=%!T\",\n\t\t                     (duk_tval *) duk_get_tval(thr, 0)));\n\t}\n#endif\n\n\t/*\n\t *  Process yield\n\t *\n\t *  After longjmp(), processing continues in bytecode executor longjmp\n\t *  handler, which will e.g. update thr->resumer to NULL.\n\t */\n\n\tthr->heap->lj.type = DUK_LJ_TYPE_YIELD;\n\n\t/* lj value1: value */\n\tDUK_ASSERT(thr->valstack_bottom < thr->valstack_top);\n\tDUK_TVAL_SET_TVAL_UPDREF(thr, &thr->heap->lj.value1, &thr->valstack_bottom[0]);  /* side effects */\n\tDUK_TVAL_CHKFAST_INPLACE_SLOW(&thr->heap->lj.value1);\n\n\tthr->heap->lj.iserror = is_error;\n\n\tDUK_ASSERT(thr->heap->lj.jmpbuf_ptr != NULL);  /* call is from executor, so we know we have a jmpbuf */\n\tduk_err_longjmp(thr);  /* execution resumes in bytecode executor */\n\tDUK_UNREACHABLE();\n\t/* Never here, fall through to error (from compiler point of view). */\n\n state_error:\n\tDUK_DCERROR_TYPE_INVALID_STATE(thr);\n}\n#endif\n\n#if defined(DUK_USE_COROUTINE_SUPPORT)\nDUK_INTERNAL duk_ret_t duk_bi_thread_current(duk_hthread *thr) {\n\tduk_push_current_thread(thr);\n\treturn 1;\n}\n#endif\n#line 1 \"duk_bi_thrower.c\"\n/*\n *  Type error thrower, E5 Section 13.2.3.\n */\n\n/* #include duk_internal.h -> already included */\n\nDUK_INTERNAL duk_ret_t duk_bi_type_error_thrower(duk_hthread *thr) {\n\tDUK_DCERROR_TYPE_INVALID_ARGS(thr);\n}\n#line 1 \"duk_debug_fixedbuffer.c\"\n/*\n *  Fixed buffer helper useful for debugging, requires no allocation\n *  which is critical for debugging.\n */\n\n/* #include duk_internal.h -> already included */\n\n#if defined(DUK_USE_DEBUG)\n\nDUK_INTERNAL void duk_fb_put_bytes(duk_fixedbuffer *fb, const duk_uint8_t *buffer, duk_size_t length) {\n\tduk_size_t avail;\n\tduk_size_t copylen;\n\n\tavail = (fb->offset >= fb->length ? (duk_size_t) 0 : (duk_size_t) (fb->length - fb->offset));\n\tif (length > avail) {\n\t\tcopylen = avail;\n\t\tfb->truncated = 1;\n\t} else {\n\t\tcopylen = length;\n\t}\n\tDUK_MEMCPY(fb->buffer + fb->offset, buffer, copylen);\n\tfb->offset += copylen;\n}\n\nDUK_INTERNAL void duk_fb_put_byte(duk_fixedbuffer *fb, duk_uint8_t x) {\n\tduk_fb_put_bytes(fb, (const duk_uint8_t *) &x, 1);\n}\n\nDUK_INTERNAL void duk_fb_put_cstring(duk_fixedbuffer *fb, const char *x) {\n\tduk_fb_put_bytes(fb, (const duk_uint8_t *) x, (duk_size_t) DUK_STRLEN(x));\n}\n\nDUK_INTERNAL void duk_fb_sprintf(duk_fixedbuffer *fb, const char *fmt, ...) {\n\tduk_size_t avail;\n\tva_list ap;\n\n\tva_start(ap, fmt);\n\tavail = (fb->offset >= fb->length ? (duk_size_t) 0 : (duk_size_t) (fb->length - fb->offset));\n\tif (avail > 0) {\n\t\tduk_int_t res = (duk_int_t) DUK_VSNPRINTF((char *) (fb->buffer + fb->offset), avail, fmt, ap);\n\t\tif (res < 0) {\n\t\t\t/* error */\n\t\t} else if ((duk_size_t) res >= avail) {\n\t\t\t/* (maybe) truncated */\n\t\t\tfb->offset += avail;\n\t\t\tif ((duk_size_t) res > avail) {\n\t\t\t\t/* actual chars dropped (not just NUL term) */\n\t\t\t\tfb->truncated = 1;\n\t\t\t}\n\t\t} else {\n\t\t\t/* normal */\n\t\t\tfb->offset += (duk_size_t) res;\n\t\t}\n\t}\n\tva_end(ap);\n}\n\nDUK_INTERNAL void duk_fb_put_funcptr(duk_fixedbuffer *fb, duk_uint8_t *fptr, duk_size_t fptr_size) {\n\tchar buf[64+1];\n\tduk_debug_format_funcptr(buf, sizeof(buf), fptr, fptr_size);\n\tbuf[sizeof(buf) - 1] = (char) 0;\n\tduk_fb_put_cstring(fb, buf);\n}\n\nDUK_INTERNAL duk_bool_t duk_fb_is_full(duk_fixedbuffer *fb) {\n\treturn (fb->offset >= fb->length);\n}\n\n#endif  /* DUK_USE_DEBUG */\n#line 1 \"duk_debug_vsnprintf.c\"\n/*\n *  Custom formatter for debug printing, allowing Duktape specific data\n *  structures (such as tagged values and heap objects) to be printed with\n *  a nice format string.  Because debug printing should not affect execution\n *  state, formatting here must be independent of execution (see implications\n *  below) and must not allocate memory.\n *\n *  Custom format tags begin with a '%!' to safely distinguish them from\n *  standard format tags.  The following conversions are supported:\n *\n *     %!T    tagged value (duk_tval *)\n *     %!O    heap object (duk_heaphdr *)\n *     %!I    decoded bytecode instruction\n *     %!C    bytecode instruction opcode name (arg is long)\n *\n *  Everything is serialized in a JSON-like manner.  The default depth is one\n *  level, internal prototype is not followed, and internal properties are not\n *  serialized.  The following modifiers change this behavior:\n *\n *     @      print pointers\n *     #      print binary representations (where applicable)\n *     d      deep traversal of own properties (not prototype)\n *     p      follow prototype chain (useless without 'd')\n *     i      include internal properties (other than prototype)\n *     x      hexdump buffers\n *     h      heavy formatting\n *\n *  For instance, the following serializes objects recursively, but does not\n *  follow the prototype chain nor print internal properties: \"%!dO\".\n *\n *  Notes:\n *\n *    * Standard snprintf return value semantics seem to vary.  This\n *      implementation returns the number of bytes it actually wrote\n *      (excluding the null terminator).  If retval == buffer size,\n *      output was truncated (except for corner cases).\n *\n *    * Output format is intentionally different from Ecmascript\n *      formatting requirements, as formatting here serves debugging\n *      of internals.\n *\n *    * Depth checking (and updating) is done in each type printer\n *      separately, to allow them to call each other freely.\n *\n *    * Some pathological structures might take ages to print (e.g.\n *      self recursion with 100 properties pointing to the object\n *      itself).  To guard against these, each printer also checks\n *      whether the output buffer is full; if so, early exit.\n *\n *    * Reference loops are detected using a loop stack.\n */\n\n/* #include duk_internal.h -> already included */\n\n#if defined(DUK_USE_DEBUG)\n\n/* #include stdio.h -> already included */\n/* #include stdarg.h -> already included */\n#include <string.h>\n\n/* list of conversion specifiers that terminate a format tag;\n * this is unfortunately guesswork.\n */\n#define DUK__ALLOWED_STANDARD_SPECIFIERS  \"diouxXeEfFgGaAcsCSpnm\"\n\n/* maximum length of standard format tag that we support */\n#define DUK__MAX_FORMAT_TAG_LENGTH  32\n\n/* heapobj recursion depth when deep printing is selected */\n#define DUK__DEEP_DEPTH_LIMIT  8\n\n/* maximum recursion depth for loop detection stacks */\n#define DUK__LOOP_STACK_DEPTH  256\n\n/* must match bytecode defines now; build autogenerate? */\nDUK_LOCAL const char * const duk__bc_optab[256] = {\n\t\"LDREG\", \"STREG\", \"JUMP\", \"LDCONST\", \"LDINT\", \"LDINTX\", \"LDTHIS\", \"LDUNDEF\",\n\t\"LDNULL\", \"LDTRUE\", \"LDFALSE\", \"GETVAR\", \"BNOT\", \"LNOT\", \"UNM\", \"UNP\",\n\t\"EQ_RR\", \"EQ_CR\", \"EQ_RC\", \"EQ_CC\", \"NEQ_RR\", \"NEQ_CR\", \"NEQ_RC\", \"NEQ_CC\",\n\t\"SEQ_RR\", \"SEQ_CR\", \"SEQ_RC\", \"SEQ_CC\", \"SNEQ_RR\", \"SNEQ_CR\", \"SNEQ_RC\", \"SNEQ_CC\",\n\n\t\"GT_RR\", \"GT_CR\", \"GT_RC\", \"GT_CC\", \"GE_RR\", \"GE_CR\", \"GE_RC\", \"GE_CC\",\n\t\"LT_RR\", \"LT_CR\", \"LT_RC\", \"LT_CC\", \"LE_RR\", \"LE_CR\", \"LE_RC\", \"LE_CC\",\n\t\"IFTRUE_R\", \"IFTRUE_C\", \"IFFALSE_R\", \"IFFALSE_C\", \"ADD_RR\", \"ADD_CR\", \"ADD_RC\", \"ADD_CC\",\n\t\"SUB_RR\", \"SUB_CR\", \"SUB_RC\", \"SUB_CC\", \"MUL_RR\", \"MUL_CR\", \"MUL_RC\", \"MUL_CC\",\n\n\t\"DIV_RR\", \"DIV_CR\", \"DIV_RC\", \"DIV_CC\", \"MOD_RR\", \"MOD_CR\", \"MOD_RC\", \"MOD_CC\",\n\t\"EXP_RR\", \"EXP_CR\", \"EXP_RC\", \"EXP_CC\", \"BAND_RR\", \"BAND_CR\", \"BAND_RC\", \"BAND_CC\",\n\t\"BOR_RR\", \"BOR_CR\", \"BOR_RC\", \"BOR_CC\", \"BXOR_RR\", \"BXOR_CR\", \"BXOR_RC\", \"BXOR_CC\",\n\t\"BASL_RR\", \"BASL_CR\", \"BASL_RC\", \"BASL_CC\", \"BLSR_RR\", \"BLSR_CR\", \"BLSR_RC\", \"BLSR_CC\",\n\n\t\"BASR_RR\", \"BASR_CR\", \"BASR_RC\", \"BASR_CC\", \"INSTOF_RR\", \"INSTOF_CR\", \"INSTOF_RC\", \"INSTOF_CC\",\n\t\"IN_RR\", \"IN_CR\", \"IN_RC\", \"IN_CC\", \"GETPROP_RR\", \"GETPROP_CR\", \"GETPROP_RC\", \"GETPROP_CC\",\n\t\"PUTPROP_RR\", \"PUTPROP_CR\", \"PUTPROP_RC\", \"PUTPROP_CC\", \"DELPROP_RR\", \"DELPROP_CR\", \"DELPROP_RC\", \"DELPROP_CC\",\n\t\"PREINCR\", \"PREDECR\", \"POSTINCR\", \"POSTDECR\", \"PREINCV\", \"PREDECV\", \"POSTINCV\", \"POSTDECV\",\n\n\t\"PREINCP_RR\", \"PREINCP_CR\", \"PREINCP_RC\", \"PREINCP_CC\", \"PREDECP_RR\", \"PREDECP_CR\", \"PREDECP_RC\", \"PREDECP_CC\",\n\t\"POSTINCP_RR\", \"POSTINCP_CR\", \"POSTINCP_RC\", \"POSTINCP_CC\", \"POSTDECP_RR\", \"POSTDECP_CR\", \"POSTDECP_RC\", \"POSTDECP_CC\",\n\t\"DECLVAR_RR\", \"DECLVAR_CR\", \"DECLVAR_RC\", \"DECLVAR_CC\", \"REGEXP_RR\", \"REGEXP_RC\", \"REGEXP_CR\", \"REGEXP_CC\",\n\t\"CLOSURE\", \"TYPEOF\", \"TYPEOFID\", \"PUTVAR\", \"DELVAR\", \"RETREG\", \"RETUNDEF\", \"RETCONST\",\n\n\t\"RETCONSTN\", \"LABEL\", \"ENDLABEL\", \"BREAK\", \"CONTINUE\", \"TRYCATCH\", \"ENDTRY\", \"ENDCATCH\",\n\t\"ENDFIN\", \"THROW\", \"INVLHS\", \"CSREG\", \"CSVAR_RR\", \"CSVAR_CR\", \"CSVAR_RC\", \"CSVAR_CC\",\n\t\"CALL0\", \"CALL1\", \"CALL2\", \"CALL3\", \"CALL4\", \"CALL5\", \"CALL6\", \"CALL7\",\n\t\"CALL8\", \"CALL9\", \"CALL10\", \"CALL11\", \"CALL12\", \"CALL13\", \"CALL14\", \"CALL15\",\n\n\t\"NEWOBJ\", \"NEWARR\", \"MPUTOBJ\", \"MPUTOBJI\", \"INITSET\", \"INITGET\", \"MPUTARR\", \"MPUTARRI\",\n\t\"SETALEN\", \"INITENUM\", \"NEXTENUM\", \"NEWTARGET\", \"DEBUGGER\", \"NOP\", \"INVALID\", \"UNUSED207\",\n\t\"GETPROPC_RR\", \"GETPROPC_CR\", \"GETPROPC_RC\", \"GETPROPC_CC\", \"UNUSED212\", \"UNUSED213\", \"UNUSED214\", \"UNUSED215\",\n\t\"UNUSED216\", \"UNUSED217\", \"UNUSED218\", \"UNUSED219\", \"UNUSED220\", \"UNUSED221\", \"UNUSED222\", \"UNUSED223\",\n\n\t\"UNUSED224\", \"UNUSED225\", \"UNUSED226\", \"UNUSED227\", \"UNUSED228\", \"UNUSED229\", \"UNUSED230\", \"UNUSED231\",\n\t\"UNUSED232\", \"UNUSED233\", \"UNUSED234\", \"UNUSED235\", \"UNUSED236\", \"UNUSED237\", \"UNUSED238\", \"UNUSED239\",\n\t\"UNUSED240\", \"UNUSED241\", \"UNUSED242\", \"UNUSED243\", \"UNUSED244\", \"UNUSED245\", \"UNUSED246\", \"UNUSED247\",\n\t\"UNUSED248\", \"UNUSED249\", \"UNUSED250\", \"UNUSED251\", \"UNUSED252\", \"UNUSED253\", \"UNUSED254\", \"UNUSED255\"\n};\n\ntypedef struct duk__dprint_state duk__dprint_state;\nstruct duk__dprint_state {\n\tduk_fixedbuffer *fb;\n\n\t/* loop_stack_index could be perhaps be replaced by 'depth', but it's nice\n\t * to not couple these two mechanisms unnecessarily.\n\t */\n\tduk_hobject *loop_stack[DUK__LOOP_STACK_DEPTH];\n\tduk_int_t loop_stack_index;\n\tduk_int_t loop_stack_limit;\n\n\tduk_int_t depth;\n\tduk_int_t depth_limit;\n\n\tduk_bool_t pointer;\n\tduk_bool_t heavy;\n\tduk_bool_t binary;\n\tduk_bool_t follow_proto;\n\tduk_bool_t internal;\n\tduk_bool_t hexdump;\n};\n\n/* helpers */\nDUK_LOCAL_DECL void duk__print_hstring(duk__dprint_state *st, duk_hstring *k, duk_bool_t quotes);\nDUK_LOCAL_DECL void duk__print_hobject(duk__dprint_state *st, duk_hobject *h);\nDUK_LOCAL_DECL void duk__print_hbuffer(duk__dprint_state *st, duk_hbuffer *h);\nDUK_LOCAL_DECL void duk__print_tval(duk__dprint_state *st, duk_tval *tv);\nDUK_LOCAL_DECL void duk__print_instr(duk__dprint_state *st, duk_instr_t ins);\nDUK_LOCAL_DECL void duk__print_heaphdr(duk__dprint_state *st, duk_heaphdr *h);\nDUK_LOCAL_DECL void duk__print_shared_heaphdr(duk__dprint_state *st, duk_heaphdr *h);\nDUK_LOCAL_DECL void duk__print_shared_heaphdr_string(duk__dprint_state *st, duk_heaphdr_string *h);\n\nDUK_LOCAL void duk__print_shared_heaphdr(duk__dprint_state *st, duk_heaphdr *h) {\n\tduk_fixedbuffer *fb = st->fb;\n\n\tif (st->heavy) {\n\t\tduk_fb_sprintf(fb, \"(%p)\", (void *) h);\n\t}\n\n\tif (!h) {\n\t\treturn;\n\t}\n\n\tif (st->binary) {\n\t\tduk_size_t i;\n\t\tduk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_LBRACKET);\n\t\tfor (i = 0; i < (duk_size_t) sizeof(*h); i++) {\n\t\t\tduk_fb_sprintf(fb, \"%02lx\", (unsigned long) ((duk_uint8_t *)h)[i]);\n\t\t}\n\t\tduk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_RBRACKET);\n\t}\n\n#if defined(DUK_USE_REFERENCE_COUNTING)  /* currently implicitly also DUK_USE_DOUBLE_LINKED_HEAP */\n\tif (st->heavy) {\n\t\tduk_fb_sprintf(fb, \"[h_next=%p,h_prev=%p,h_refcount=%lu,h_flags=%08lx,type=%ld,\"\n\t\t               \"reachable=%ld,temproot=%ld,finalizable=%ld,finalized=%ld]\",\n\t\t               (void *) DUK_HEAPHDR_GET_NEXT(NULL, h),\n\t\t               (void *) DUK_HEAPHDR_GET_PREV(NULL, h),\n\t\t               (unsigned long) DUK_HEAPHDR_GET_REFCOUNT(h),\n\t\t               (unsigned long) DUK_HEAPHDR_GET_FLAGS(h),\n\t\t               (long) DUK_HEAPHDR_GET_TYPE(h),\n\t\t               (long) (DUK_HEAPHDR_HAS_REACHABLE(h) ? 1 : 0),\n\t\t               (long) (DUK_HEAPHDR_HAS_TEMPROOT(h) ? 1 : 0),\n\t\t               (long) (DUK_HEAPHDR_HAS_FINALIZABLE(h) ? 1 : 0),\n\t\t               (long) (DUK_HEAPHDR_HAS_FINALIZED(h) ? 1 : 0));\n\t}\n#else\n\tif (st->heavy) {\n\t\tduk_fb_sprintf(fb, \"[h_next=%p,h_flags=%08lx,type=%ld,reachable=%ld,temproot=%ld,finalizable=%ld,finalized=%ld]\",\n\t\t               (void *) DUK_HEAPHDR_GET_NEXT(NULL, h),\n\t\t               (unsigned long) DUK_HEAPHDR_GET_FLAGS(h),\n\t\t               (long) DUK_HEAPHDR_GET_TYPE(h),\n\t\t               (long) (DUK_HEAPHDR_HAS_REACHABLE(h) ? 1 : 0),\n\t\t               (long) (DUK_HEAPHDR_HAS_TEMPROOT(h) ? 1 : 0),\n\t\t               (long) (DUK_HEAPHDR_HAS_FINALIZABLE(h) ? 1 : 0),\n\t\t               (long) (DUK_HEAPHDR_HAS_FINALIZED(h) ? 1 : 0));\n\t}\n#endif\n}\n\nDUK_LOCAL void duk__print_shared_heaphdr_string(duk__dprint_state *st, duk_heaphdr_string *h) {\n\tduk_fixedbuffer *fb = st->fb;\n\n\tif (st->heavy) {\n\t\tduk_fb_sprintf(fb, \"(%p)\", (void *) h);\n\t}\n\n\tif (!h) {\n\t\treturn;\n\t}\n\n\tif (st->binary) {\n\t\tduk_size_t i;\n\t\tduk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_LBRACKET);\n\t\tfor (i = 0; i < (duk_size_t) sizeof(*h); i++) {\n\t\t\tduk_fb_sprintf(fb, \"%02lx\", (unsigned long) ((duk_uint8_t *)h)[i]);\n\t\t}\n\t\tduk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_RBRACKET);\n\t}\n\n#if defined(DUK_USE_REFERENCE_COUNTING)\n\tif (st->heavy) {\n\t\tduk_fb_sprintf(fb, \"[h_refcount=%lu,h_flags=%08lx,type=%ld,reachable=%ld,temproot=%ld,finalizable=%ld,finalized=%ld]\",\n\t\t               (unsigned long) DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) h),\n\t\t               (unsigned long) DUK_HEAPHDR_GET_FLAGS((duk_heaphdr *) h),\n\t\t               (long) DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) h),\n\t\t               (long) (DUK_HEAPHDR_HAS_REACHABLE((duk_heaphdr *) h) ? 1 : 0),\n\t\t               (long) (DUK_HEAPHDR_HAS_TEMPROOT((duk_heaphdr *) h) ? 1 : 0),\n\t\t               (long) (DUK_HEAPHDR_HAS_FINALIZABLE((duk_heaphdr *) h) ? 1 : 0),\n\t\t               (long) (DUK_HEAPHDR_HAS_FINALIZED((duk_heaphdr *) h) ? 1 : 0));\n\t}\n#else\n\tif (st->heavy) {\n\t\tduk_fb_sprintf(fb, \"[h_flags=%08lx,type=%ld,reachable=%ld,temproot=%ld,finalizable=%ld,finalized=%ld]\",\n\t\t               (unsigned long) DUK_HEAPHDR_GET_FLAGS((duk_heaphdr *) h),\n\t\t               (long) DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) h),\n\t\t               (long) (DUK_HEAPHDR_HAS_REACHABLE((duk_heaphdr *) h) ? 1 : 0),\n\t\t               (long) (DUK_HEAPHDR_HAS_TEMPROOT((duk_heaphdr *) h) ? 1 : 0),\n\t\t               (long) (DUK_HEAPHDR_HAS_FINALIZABLE((duk_heaphdr *) h) ? 1 : 0),\n\t\t               (long) (DUK_HEAPHDR_HAS_FINALIZED((duk_heaphdr *) h) ? 1 : 0));\n\t}\n#endif\n}\n\nDUK_LOCAL void duk__print_hstring(duk__dprint_state *st, duk_hstring *h, duk_bool_t quotes) {\n\tduk_fixedbuffer *fb = st->fb;\n\tconst duk_uint8_t *p;\n\tconst duk_uint8_t *p_end;\n\n\t/* terminal type: no depth check */\n\n\tif (duk_fb_is_full(fb)) {\n\t\treturn;\n\t}\n\n\tduk__print_shared_heaphdr_string(st, &h->hdr);\n\n\tif (!h) {\n\t\tduk_fb_put_cstring(fb, \"NULL\");\n\t\treturn;\n\t}\n\n\tp = DUK_HSTRING_GET_DATA(h);\n\tp_end = p + DUK_HSTRING_GET_BYTELEN(h);\n\n\tif (p_end > p && p[0] == DUK_ASC_UNDERSCORE) {\n\t\t/* If property key begins with underscore, encode it with\n\t\t * forced quotes (e.g. \"_Foo\") to distinguish it from encoded\n\t\t * internal properties (e.g. \\x82Bar -> _Bar).\n\t\t */\n\t\tquotes = 1;\n\t}\n\n\tif (quotes) {\n\t\tduk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_DOUBLEQUOTE);\n\t}\n\twhile (p < p_end) {\n\t\tduk_uint8_t ch = *p++;\n\n\t\t/* two special escapes: '\\' and '\"', other printables as is */\n\t\tif (ch == '\\\\') {\n\t\t\tduk_fb_sprintf(fb, \"\\\\\\\\\");\n\t\t} else if (ch == '\"') {\n\t\t\tduk_fb_sprintf(fb, \"\\\\\\\"\");\n\t\t} else if (ch >= 0x20 && ch <= 0x7e) {\n\t\t\tduk_fb_put_byte(fb, ch);\n\t\t} else if (ch == 0x82 && !quotes) {\n\t\t\t/* encode \\x82Bar as _Bar if no quotes are\n\t\t\t * applied, this is for readable internal keys.\n\t\t\t */\n\t\t\tduk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_UNDERSCORE);\n\t\t} else {\n\t\t\tduk_fb_sprintf(fb, \"\\\\x%02lx\", (unsigned long) ch);\n\t\t}\n\t}\n\tif (quotes) {\n\t\tduk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_DOUBLEQUOTE);\n\t}\n#if defined(DUK_USE_REFERENCE_COUNTING)\n\t/* XXX: limit to quoted strings only, to save keys from being cluttered? */\n\tduk_fb_sprintf(fb, \"/%lu\", (unsigned long) DUK_HEAPHDR_GET_REFCOUNT(&h->hdr));\n#endif\n}\n\n#define DUK__COMMA()  do { \\\n\t\tif (first) { \\\n\t\t\tfirst = 0; \\\n\t\t} else { \\\n\t\t\tduk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_COMMA); \\\n\t\t} \\\n\t} while (0)\n\nDUK_LOCAL void duk__print_hobject(duk__dprint_state *st, duk_hobject *h) {\n\tduk_fixedbuffer *fb = st->fb;\n\tduk_uint_fast32_t i;\n\tduk_tval *tv;\n\tduk_hstring *key;\n\tduk_bool_t first = 1;\n\tconst char *brace1 = \"{\";\n\tconst char *brace2 = \"}\";\n\tduk_bool_t pushed_loopstack = 0;\n\n\tif (duk_fb_is_full(fb)) {\n\t\treturn;\n\t}\n\n\tduk__print_shared_heaphdr(st, &h->hdr);\n\n\tif (h && DUK_HOBJECT_HAS_ARRAY_PART(h)) {\n\t\tbrace1 = \"[\";\n\t\tbrace2 = \"]\";\n\t}\n\n\tif (!h) {\n\t\tduk_fb_put_cstring(fb, \"NULL\");\n\t\tgoto finished;\n\t}\n\n\tif (st->depth >= st->depth_limit) {\n\t\tconst char *subtype = \"generic\";\n\n\t\tif (DUK_HOBJECT_IS_COMPFUNC(h)) {\n\t\t\tsubtype = \"compfunc\";\n\t\t} else if (DUK_HOBJECT_IS_NATFUNC(h)) {\n\t\t\tsubtype = \"natfunc\";\n\t\t} else if (DUK_HOBJECT_IS_THREAD(h)) {\n\t\t\tsubtype = \"thread\";\n\t\t} else if (DUK_HOBJECT_IS_BUFOBJ(h)) {\n\t\t\tsubtype = \"bufobj\";\n\t\t} else if (DUK_HOBJECT_IS_ARRAY(h)) {\n\t\t\tsubtype = \"array\";\n\t\t}\n\t\tduk_fb_sprintf(fb, \"%sobject/%s %p%s\", (const char *) brace1, subtype, (void *) h, (const char *) brace2);\n\t\treturn;\n\t}\n\n\tfor (i = 0; i < (duk_uint_fast32_t) st->loop_stack_index; i++) {\n\t\tif (st->loop_stack[i] == h) {\n\t\t\tduk_fb_sprintf(fb, \"%sLOOP:%p%s\", (const char *) brace1, (void *) h, (const char *) brace2);\n\t\t\treturn;\n\t\t}\n\t}\n\n\t/* after this, return paths should 'goto finished' for decrement */\n\tst->depth++;\n\n\tif (st->loop_stack_index >= st->loop_stack_limit) {\n\t\tduk_fb_sprintf(fb, \"%sOUT-OF-LOOP-STACK%s\", (const char *) brace1, (const char *) brace2);\n\t\tgoto finished;\n\t}\n\tst->loop_stack[st->loop_stack_index++] = h;\n\tpushed_loopstack = 1;\n\n\t/*\n\t *  Notation: double underscore used for internal properties which are not\n\t *  stored in the property allocation (e.g. '__valstack').\n\t */\n\n\tduk_fb_put_cstring(fb, brace1);\n\n\tif (DUK_HOBJECT_GET_PROPS(NULL, h)) {\n\t\tduk_uint32_t a_limit;\n\n\t\ta_limit = DUK_HOBJECT_GET_ASIZE(h);\n\t\tif (st->internal) {\n\t\t\t/* dump all allocated entries, unused entries print as 'unused',\n\t\t\t * note that these may extend beyond current 'length' and look\n\t\t\t * a bit funny.\n\t\t\t */\n\t\t} else {\n\t\t\t/* leave out trailing 'unused' elements */\n\t\t\twhile (a_limit > 0) {\n\t\t\t\ttv = DUK_HOBJECT_A_GET_VALUE_PTR(NULL, h, a_limit - 1);\n\t\t\t\tif (!DUK_TVAL_IS_UNUSED(tv)) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\ta_limit--;\n\t\t\t}\n\t\t}\n\n\t\tfor (i = 0; i < a_limit; i++) {\n\t\t\ttv = DUK_HOBJECT_A_GET_VALUE_PTR(NULL, h, i);\n\t\t\tDUK__COMMA();\n\t\t\tduk__print_tval(st, tv);\n\t\t}\n\t\tfor (i = 0; i < DUK_HOBJECT_GET_ENEXT(h); i++) {\n\t\t\tkey = DUK_HOBJECT_E_GET_KEY(NULL, h, i);\n\t\t\tif (!key) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (!st->internal && DUK_HSTRING_HAS_HIDDEN(key)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tDUK__COMMA();\n\t\t\tduk__print_hstring(st, key, 0);\n\t\t\tduk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_COLON);\n\t\t\tif (DUK_HOBJECT_E_SLOT_IS_ACCESSOR(NULL, h, i)) {\n\t\t\t\tduk_fb_sprintf(fb, \"[get:%p,set:%p]\",\n\t\t\t\t               (void *) DUK_HOBJECT_E_GET_VALUE(NULL, h, i).a.get,\n\t\t\t\t               (void *) DUK_HOBJECT_E_GET_VALUE(NULL, h, i).a.set);\n\t\t\t} else {\n\t\t\t\ttv = &DUK_HOBJECT_E_GET_VALUE(NULL, h, i).v;\n\t\t\t\tduk__print_tval(st, tv);\n\t\t\t}\n\t\t\tif (st->heavy) {\n\t\t\t\tduk_fb_sprintf(fb, \"<%02lx>\", (unsigned long) DUK_HOBJECT_E_GET_FLAGS(NULL, h, i));\n\t\t\t}\n\t\t}\n\t}\n\tif (st->internal) {\n\t\tif (DUK_HOBJECT_IS_ARRAY(h)) {\n\t\t\tDUK__COMMA(); duk_fb_sprintf(fb, \"__array:true\");\n\t\t}\n\t\tif (DUK_HOBJECT_HAS_EXTENSIBLE(h)) {\n\t\t\tDUK__COMMA(); duk_fb_sprintf(fb, \"__extensible:true\");\n\t\t}\n\t\tif (DUK_HOBJECT_HAS_CONSTRUCTABLE(h)) {\n\t\t\tDUK__COMMA(); duk_fb_sprintf(fb, \"__constructable:true\");\n\t\t}\n\t\tif (DUK_HOBJECT_HAS_BOUNDFUNC(h)) {\n\t\t\tDUK__COMMA(); duk_fb_sprintf(fb, \"__boundfunc:true\");\n\t\t}\n\t\tif (DUK_HOBJECT_HAS_COMPFUNC(h)) {\n\t\t\tDUK__COMMA(); duk_fb_sprintf(fb, \"__compfunc:true\");\n\t\t}\n\t\tif (DUK_HOBJECT_HAS_NATFUNC(h)) {\n\t\t\tDUK__COMMA(); duk_fb_sprintf(fb, \"__natfunc:true\");\n\t\t}\n\t\tif (DUK_HOBJECT_HAS_BUFOBJ(h)) {\n\t\t\tDUK__COMMA(); duk_fb_sprintf(fb, \"__bufobj:true\");\n\t\t}\n\t\tif (DUK_HOBJECT_IS_THREAD(h)) {\n\t\t\tDUK__COMMA(); duk_fb_sprintf(fb, \"__thread:true\");\n\t\t}\n\t\tif (DUK_HOBJECT_HAS_ARRAY_PART(h)) {\n\t\t\tDUK__COMMA(); duk_fb_sprintf(fb, \"__array_part:true\");\n\t\t}\n\t\tif (DUK_HOBJECT_HAS_STRICT(h)) {\n\t\t\tDUK__COMMA(); duk_fb_sprintf(fb, \"__strict:true\");\n\t\t}\n\t\tif (DUK_HOBJECT_HAS_NOTAIL(h)) {\n\t\t\tDUK__COMMA(); duk_fb_sprintf(fb, \"__notail:true\");\n\t\t}\n\t\tif (DUK_HOBJECT_HAS_NEWENV(h)) {\n\t\t\tDUK__COMMA(); duk_fb_sprintf(fb, \"__newenv:true\");\n\t\t}\n\t\tif (DUK_HOBJECT_HAS_NAMEBINDING(h)) {\n\t\t\tDUK__COMMA(); duk_fb_sprintf(fb, \"__namebinding:true\");\n\t\t}\n\t\tif (DUK_HOBJECT_HAS_CREATEARGS(h)) {\n\t\t\tDUK__COMMA(); duk_fb_sprintf(fb, \"__createargs:true\");\n\t\t}\n\t\tif (DUK_HOBJECT_HAS_EXOTIC_ARRAY(h)) {\n\t\t\tDUK__COMMA(); duk_fb_sprintf(fb, \"__exotic_array:true\");\n\t\t}\n\t\tif (DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(h)) {\n\t\t\tDUK__COMMA(); duk_fb_sprintf(fb, \"__exotic_stringobj:true\");\n\t\t}\n\t\tif (DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(h)) {\n\t\t\tDUK__COMMA(); duk_fb_sprintf(fb, \"__exotic_arguments:true\");\n\t\t}\n\t\tif (DUK_HOBJECT_IS_BUFOBJ(h)) {\n\t\t\tDUK__COMMA(); duk_fb_sprintf(fb, \"__exotic_bufobj:true\");\n\t\t}\n\t\tif (DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(h)) {\n\t\t\tDUK__COMMA(); duk_fb_sprintf(fb, \"__exotic_proxyobj:true\");\n\t\t}\n\t}\n\n\tif (st->internal && DUK_HOBJECT_IS_ARRAY(h)) {\n\t\tduk_harray *a = (duk_harray *) h;\n\t\tDUK__COMMA(); duk_fb_sprintf(fb, \"__length:%ld\", (long) a->length);\n\t\tDUK__COMMA(); duk_fb_sprintf(fb, \"__length_nonwritable:%ld\", (long) a->length_nonwritable);\n\t} else if (st->internal && DUK_HOBJECT_IS_COMPFUNC(h)) {\n\t\tduk_hcompfunc *f = (duk_hcompfunc *) h;\n\t\tDUK__COMMA(); duk_fb_put_cstring(fb, \"__data:\");\n\t\tduk__print_hbuffer(st, (duk_hbuffer *) DUK_HCOMPFUNC_GET_DATA(NULL, f));\n\t\tDUK__COMMA(); duk_fb_put_cstring(fb, \"__lexenv:\"); duk__print_hobject(st, DUK_HCOMPFUNC_GET_LEXENV(NULL, f));\n\t\tDUK__COMMA(); duk_fb_put_cstring(fb, \"__varenv:\"); duk__print_hobject(st, DUK_HCOMPFUNC_GET_VARENV(NULL, f));\n\t\tDUK__COMMA(); duk_fb_sprintf(fb, \"__nregs:%ld\", (long) f->nregs);\n\t\tDUK__COMMA(); duk_fb_sprintf(fb, \"__nargs:%ld\", (long) f->nargs);\n#if defined(DUK_USE_DEBUGGER_SUPPORT)\n\t\tDUK__COMMA(); duk_fb_sprintf(fb, \"__start_line:%ld\", (long) f->start_line);\n\t\tDUK__COMMA(); duk_fb_sprintf(fb, \"__end_line:%ld\", (long) f->end_line);\n#endif\n\t\tDUK__COMMA(); duk_fb_put_cstring(fb, \"__data:\");\n\t\tduk__print_hbuffer(st, (duk_hbuffer *) DUK_HCOMPFUNC_GET_DATA(NULL, f));\n\t} else if (st->internal && DUK_HOBJECT_IS_NATFUNC(h)) {\n\t\tduk_hnatfunc *f = (duk_hnatfunc *) h;\n\t\tDUK__COMMA(); duk_fb_sprintf(fb, \"__func:\");\n\t\tduk_fb_put_funcptr(fb, (duk_uint8_t *) &f->func, sizeof(f->func));\n\t\tDUK__COMMA(); duk_fb_sprintf(fb, \"__nargs:%ld\", (long) f->nargs);\n\t\tDUK__COMMA(); duk_fb_sprintf(fb, \"__magic:%ld\", (long) f->magic);\n\t} else if (st->internal && DUK_HOBJECT_IS_DECENV(h)) {\n\t\tduk_hdecenv *e = (duk_hdecenv *) h;\n\t\tDUK__COMMA(); duk_fb_sprintf(fb, \"__thread:\"); duk__print_hobject(st, (duk_hobject *) e->thread);\n\t\tDUK__COMMA(); duk_fb_sprintf(fb, \"__varmap:\"); duk__print_hobject(st, (duk_hobject *) e->varmap);\n\t\tDUK__COMMA(); duk_fb_sprintf(fb, \"__regbase_byteoff:%ld\", (long) e->regbase_byteoff);\n\t} else if (st->internal && DUK_HOBJECT_IS_OBJENV(h)) {\n\t\tduk_hobjenv *e = (duk_hobjenv *) h;\n\t\tDUK__COMMA(); duk_fb_sprintf(fb, \"__target:\"); duk__print_hobject(st, (duk_hobject *) e->target);\n\t\tDUK__COMMA(); duk_fb_sprintf(fb, \"__has_this:%ld\", (long) e->has_this);\n#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)\n\t} else if (st->internal && DUK_HOBJECT_IS_BUFOBJ(h)) {\n\t\tduk_hbufobj *b = (duk_hbufobj *) h;\n\t\tDUK__COMMA(); duk_fb_sprintf(fb, \"__buf:\");\n\t\tduk__print_hbuffer(st, (duk_hbuffer *) b->buf);\n\t\tDUK__COMMA(); duk_fb_sprintf(fb, \"__buf_prop:\");\n\t\tduk__print_hobject(st, (duk_hobject *) b->buf_prop);\n\t\tDUK__COMMA(); duk_fb_sprintf(fb, \"__offset:%ld\", (long) b->offset);\n\t\tDUK__COMMA(); duk_fb_sprintf(fb, \"__length:%ld\", (long) b->length);\n\t\tDUK__COMMA(); duk_fb_sprintf(fb, \"__shift:%ld\", (long) b->shift);\n\t\tDUK__COMMA(); duk_fb_sprintf(fb, \"__elemtype:%ld\", (long) b->elem_type);\n#endif\n\t} else if (st->internal && DUK_HOBJECT_IS_PROXY(h)) {\n\t\tduk_hproxy *p = (duk_hproxy *) h;\n\t\tDUK__COMMA(); duk_fb_sprintf(fb, \"__target:\");\n\t\tduk__print_hobject(st, p->target);\n\t\tDUK__COMMA(); duk_fb_sprintf(fb, \"__handler:\");\n\t\tduk__print_hobject(st, p->handler);\n\t} else if (st->internal && DUK_HOBJECT_IS_THREAD(h)) {\n\t\tduk_hthread *t = (duk_hthread *) h;\n\t\tDUK__COMMA(); duk_fb_sprintf(fb, \"__ptr_curr_pc:%p\", (void *) t->ptr_curr_pc);\n\t\tDUK__COMMA(); duk_fb_sprintf(fb, \"__heap:%p\", (void *) t->heap);\n\t\tDUK__COMMA(); duk_fb_sprintf(fb, \"__strict:%ld\", (long) t->strict);\n\t\tDUK__COMMA(); duk_fb_sprintf(fb, \"__state:%ld\", (long) t->state);\n\t\tDUK__COMMA(); duk_fb_sprintf(fb, \"__unused1:%ld\", (long) t->unused1);\n\t\tDUK__COMMA(); duk_fb_sprintf(fb, \"__unused2:%ld\", (long) t->unused2);\n\t\tDUK__COMMA(); duk_fb_sprintf(fb, \"__valstack:%p\", (void *) t->valstack);\n\t\tDUK__COMMA(); duk_fb_sprintf(fb, \"__valstack_end:%p/%ld\", (void *) t->valstack_end, (long) (t->valstack_end - t->valstack));\n\t\tDUK__COMMA(); duk_fb_sprintf(fb, \"__valstack_alloc_end:%p/%ld\", (void *) t->valstack_alloc_end, (long) (t->valstack_alloc_end - t->valstack));\n\t\tDUK__COMMA(); duk_fb_sprintf(fb, \"__valstack_bottom:%p/%ld\", (void *) t->valstack_bottom, (long) (t->valstack_bottom - t->valstack));\n\t\tDUK__COMMA(); duk_fb_sprintf(fb, \"__valstack_top:%p/%ld\", (void *) t->valstack_top, (long) (t->valstack_top - t->valstack));\n\t\tDUK__COMMA(); duk_fb_sprintf(fb, \"__callstack_curr:%p\", (void *) t->callstack_curr);\n\t\tDUK__COMMA(); duk_fb_sprintf(fb, \"__callstack_top:%ld\", (long) t->callstack_top);\n\t\tDUK__COMMA(); duk_fb_sprintf(fb, \"__callstack_preventcount:%ld\", (long) t->callstack_preventcount);\n\t\tDUK__COMMA(); duk_fb_sprintf(fb, \"__resumer:\"); duk__print_hobject(st, (duk_hobject *) t->resumer);\n\t\tDUK__COMMA(); duk_fb_sprintf(fb, \"__compile_ctx:%p\", (void *) t->compile_ctx);\n#if defined(DUK_USE_INTERRUPT_COUNTER)\n\t\tDUK__COMMA(); duk_fb_sprintf(fb, \"__interrupt_counter:%ld\", (long) t->interrupt_counter);\n\t\tDUK__COMMA(); duk_fb_sprintf(fb, \"__interrupt_init:%ld\", (long) t->interrupt_init);\n#endif\n\n\t\t/* XXX: print built-ins array? */\n\n\t}\n#if defined(DUK_USE_REFERENCE_COUNTING)\n\tif (st->internal) {\n\t\tDUK__COMMA(); duk_fb_sprintf(fb, \"__refcount:%lu\", (unsigned long) DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) h));\n\t}\n#endif\n\tif (st->internal) {\n\t\tDUK__COMMA(); duk_fb_sprintf(fb, \"__class:%ld\", (long) DUK_HOBJECT_GET_CLASS_NUMBER(h));\n\t}\n\n\tDUK__COMMA(); duk_fb_sprintf(fb, \"__heapptr:%p\", (void *) h);  /* own pointer */\n\n\t/* prototype should be last, for readability */\n\tif (DUK_HOBJECT_GET_PROTOTYPE(NULL, h)) {\n\t\tif (st->follow_proto) {\n\t\t\tDUK__COMMA(); duk_fb_put_cstring(fb, \"__prototype:\"); duk__print_hobject(st, DUK_HOBJECT_GET_PROTOTYPE(NULL, h));\n\t\t} else {\n\t\t\tDUK__COMMA(); duk_fb_sprintf(fb, \"__prototype:%p\", (void *) DUK_HOBJECT_GET_PROTOTYPE(NULL, h));\n\t\t}\n\t}\n\n\tduk_fb_put_cstring(fb, brace2);\n\n#if defined(DUK_USE_HOBJECT_HASH_PART)\n\tif (st->heavy && DUK_HOBJECT_GET_HSIZE(h) > 0) {\n\t\tduk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_LANGLE);\n\t\tfor (i = 0; i < DUK_HOBJECT_GET_HSIZE(h); i++) {\n\t\t\tduk_uint_t h_idx = DUK_HOBJECT_H_GET_INDEX(NULL, h, i);\n\t\t\tif (i > 0) {\n\t\t\t\tduk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_COMMA);\n\t\t\t}\n\t\t\tif (h_idx == DUK_HOBJECT_HASHIDX_UNUSED) {\n\t\t\t\tduk_fb_sprintf(fb, \"u\");\n\t\t\t} else if (h_idx == DUK_HOBJECT_HASHIDX_DELETED) {\n\t\t\t\tduk_fb_sprintf(fb, \"d\");\n\t\t\t} else {\n\t\t\t\tduk_fb_sprintf(fb, \"%ld\", (long) h_idx);\n\t\t\t}\n\t\t}\n\t\tduk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_RANGLE);\n\t}\n#endif\n\n finished:\n\tst->depth--;\n\tif (pushed_loopstack) {\n\t\tst->loop_stack_index--;\n\t\tst->loop_stack[st->loop_stack_index] = NULL;\n\t}\n}\n\nDUK_LOCAL void duk__print_hbuffer(duk__dprint_state *st, duk_hbuffer *h) {\n\tduk_fixedbuffer *fb = st->fb;\n\tduk_size_t i, n;\n\tduk_uint8_t *p;\n\n\tif (duk_fb_is_full(fb)) {\n\t\treturn;\n\t}\n\n\t/* terminal type: no depth check */\n\n\tif (!h) {\n\t\tduk_fb_put_cstring(fb, \"NULL\");\n\t\treturn;\n\t}\n\n\tif (DUK_HBUFFER_HAS_DYNAMIC(h)) {\n\t\tif (DUK_HBUFFER_HAS_EXTERNAL(h)) {\n\t\t\tduk_hbuffer_external *g = (duk_hbuffer_external *) h;\n\t\t\tduk_fb_sprintf(fb, \"buffer:external:%p:%ld\",\n\t\t\t               (void *) DUK_HBUFFER_EXTERNAL_GET_DATA_PTR(NULL, g),\n\t\t\t               (long) DUK_HBUFFER_EXTERNAL_GET_SIZE(g));\n\t\t} else {\n\t\t\tduk_hbuffer_dynamic *g = (duk_hbuffer_dynamic *) h;\n\t\t\tduk_fb_sprintf(fb, \"buffer:dynamic:%p:%ld\",\n\t\t\t               (void *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(NULL, g),\n\t\t\t               (long) DUK_HBUFFER_DYNAMIC_GET_SIZE(g));\n\t\t}\n\t} else {\n\t\tduk_fb_sprintf(fb, \"buffer:fixed:%ld\", (long) DUK_HBUFFER_GET_SIZE(h));\n\t}\n\n#if defined(DUK_USE_REFERENCE_COUNTING)\n\tduk_fb_sprintf(fb, \"/%lu\", (unsigned long) DUK_HEAPHDR_GET_REFCOUNT(&h->hdr));\n#endif\n\n\tif (st->hexdump) {\n\t\tduk_fb_sprintf(fb, \"=[\");\n\t\tn = DUK_HBUFFER_GET_SIZE(h);\n\t\tp = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(NULL, h);\n\t\tfor (i = 0; i < n; i++) {\n\t\t\tduk_fb_sprintf(fb, \"%02lx\", (unsigned long) p[i]);\n\t\t}\n\t\tduk_fb_sprintf(fb, \"]\");\n\t}\n}\n\nDUK_LOCAL void duk__print_heaphdr(duk__dprint_state *st, duk_heaphdr *h) {\n\tduk_fixedbuffer *fb = st->fb;\n\n\tif (duk_fb_is_full(fb)) {\n\t\treturn;\n\t}\n\n\tif (!h) {\n\t\tduk_fb_put_cstring(fb, \"NULL\");\n\t\treturn;\n\t}\n\n\tswitch (DUK_HEAPHDR_GET_TYPE(h)) {\n\tcase DUK_HTYPE_STRING:\n\t\tduk__print_hstring(st, (duk_hstring *) h, 1);\n\t\tbreak;\n\tcase DUK_HTYPE_OBJECT:\n\t\tduk__print_hobject(st, (duk_hobject *) h);\n\t\tbreak;\n\tcase DUK_HTYPE_BUFFER:\n\t\tduk__print_hbuffer(st, (duk_hbuffer *) h);\n\t\tbreak;\n\tdefault:\n\t\tduk_fb_sprintf(fb, \"[unknown htype %ld]\", (long) DUK_HEAPHDR_GET_TYPE(h));\n\t\tbreak;\n\t}\n}\n\nDUK_LOCAL void duk__print_tval(duk__dprint_state *st, duk_tval *tv) {\n\tduk_fixedbuffer *fb = st->fb;\n\n\tif (duk_fb_is_full(fb)) {\n\t\treturn;\n\t}\n\n\t/* depth check is done when printing an actual type */\n\n\tif (st->heavy) {\n\t\tduk_fb_sprintf(fb, \"(%p)\", (void *) tv);\n\t}\n\n\tif (!tv) {\n\t\tduk_fb_put_cstring(fb, \"NULL\");\n\t\treturn;\n\t}\n\n\tif (st->binary) {\n\t\tduk_size_t i;\n\t\tduk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_LBRACKET);\n\t\tfor (i = 0; i < (duk_size_t) sizeof(*tv); i++) {\n\t\t\tduk_fb_sprintf(fb, \"%02lx\", (unsigned long) ((duk_uint8_t *)tv)[i]);\n\t\t}\n\t\tduk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_RBRACKET);\n\t}\n\n\tif (st->heavy) {\n\t\tduk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_LANGLE);\n\t}\n\tswitch (DUK_TVAL_GET_TAG(tv)) {\n\tcase DUK_TAG_UNDEFINED: {\n\t\tduk_fb_put_cstring(fb, \"undefined\");\n\t\tbreak;\n\t}\n\tcase DUK_TAG_UNUSED: {\n\t\tduk_fb_put_cstring(fb, \"unused\");\n\t\tbreak;\n\t}\n\tcase DUK_TAG_NULL: {\n\t\tduk_fb_put_cstring(fb, \"null\");\n\t\tbreak;\n\t}\n\tcase DUK_TAG_BOOLEAN: {\n\t\tduk_fb_put_cstring(fb, DUK_TVAL_GET_BOOLEAN(tv) ? \"true\" : \"false\");\n\t\tbreak;\n\t}\n\tcase DUK_TAG_STRING: {\n\t\t/* Note: string is a terminal heap object, so no depth check here */\n\t\tduk__print_hstring(st, DUK_TVAL_GET_STRING(tv), 1);\n\t\tbreak;\n\t}\n\tcase DUK_TAG_OBJECT: {\n\t\tduk__print_hobject(st, DUK_TVAL_GET_OBJECT(tv));\n\t\tbreak;\n\t}\n\tcase DUK_TAG_BUFFER: {\n\t\tduk__print_hbuffer(st, DUK_TVAL_GET_BUFFER(tv));\n\t\tbreak;\n\t}\n\tcase DUK_TAG_POINTER: {\n\t\tduk_fb_sprintf(fb, \"pointer:%p\", (void *) DUK_TVAL_GET_POINTER(tv));\n\t\tbreak;\n\t}\n\tcase DUK_TAG_LIGHTFUNC: {\n\t\tduk_c_function func;\n\t\tduk_small_uint_t lf_flags;\n\n\t\tDUK_TVAL_GET_LIGHTFUNC(tv, func, lf_flags);\n\t\tduk_fb_sprintf(fb, \"lightfunc:\");\n\t\tduk_fb_put_funcptr(fb, (duk_uint8_t *) &func, sizeof(func));\n\t\tduk_fb_sprintf(fb, \":%04lx\", (long) lf_flags);\n\t\tbreak;\n\t}\n#if defined(DUK_USE_FASTINT)\n\tcase DUK_TAG_FASTINT:\n\t\tDUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));\n\t\tDUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));\n\t\tduk_fb_sprintf(fb, \"%.18g_F\", (double) DUK_TVAL_GET_NUMBER(tv));\n\t\tbreak;\n#endif\n\tdefault: {\n\t\t/* IEEE double is approximately 16 decimal digits; print a couple extra */\n\t\tDUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));\n\t\tDUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));\n\t\tduk_fb_sprintf(fb, \"%.18g\", (double) DUK_TVAL_GET_NUMBER(tv));\n\t\tbreak;\n\t}\n\t}\n\tif (st->heavy) {\n\t\tduk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_RANGLE);\n\t}\n}\n\nDUK_LOCAL void duk__print_instr(duk__dprint_state *st, duk_instr_t ins) {\n\tduk_fixedbuffer *fb = st->fb;\n\tduk_small_int_t op;\n\tconst char *op_name;\n\n\top = (duk_small_int_t) DUK_DEC_OP(ins);\n\top_name = duk__bc_optab[op];\n\n\t/* XXX: option to fix opcode length so it lines up nicely */\n\n\tif (op == DUK_OP_JUMP) {\n\t\tduk_int_t diff1 = (duk_int_t) (DUK_DEC_ABC(ins) - DUK_BC_JUMP_BIAS);  /* from next pc */\n\t\tduk_int_t diff2 = diff1 + 1;                                          /* from curr pc */\n\n\t\tduk_fb_sprintf(fb, \"%s %ld (to pc%c%ld)\",\n\t\t               (const char *) op_name, (long) diff1,\n\t\t               (int) (diff2 >= 0 ? '+' : '-'),  /* char format: use int */\n\t\t               (long) (diff2 >= 0 ? diff2 : -diff2));\n\t} else {\n\t\tduk_fb_sprintf(fb, \"%s %ld, %ld, %ld\",\n\t\t               (const char *) op_name, (long) DUK_DEC_A(ins),\n\t\t               (long) DUK_DEC_B(ins), (long) DUK_DEC_C(ins));\n\t}\n}\n\nDUK_LOCAL void duk__print_opcode(duk__dprint_state *st, duk_small_int_t opcode) {\n\tduk_fixedbuffer *fb = st->fb;\n\n\tif (opcode < DUK_BC_OP_MIN || opcode > DUK_BC_OP_MAX) {\n\t\tduk_fb_sprintf(fb, \"?(%ld)\", (long) opcode);\n\t} else {\n\t\tduk_fb_sprintf(fb, \"%s\", (const char *) duk__bc_optab[opcode]);\n\t}\n}\n\nDUK_INTERNAL duk_int_t duk_debug_vsnprintf(char *str, duk_size_t size, const char *format, va_list ap) {\n\tduk_fixedbuffer fb;\n\tconst char *p = format;\n\tconst char *p_end = p + DUK_STRLEN(format);\n\tduk_int_t retval;\n\n\tDUK_MEMZERO(&fb, sizeof(fb));\n\tfb.buffer = (duk_uint8_t *) str;\n\tfb.length = size;\n\tfb.offset = 0;\n\tfb.truncated = 0;\n\n\twhile (p < p_end) {\n\t\tchar ch = *p++;\n\t\tconst char *p_begfmt = NULL;\n\t\tduk_bool_t got_exclamation = 0;\n\t\tduk_bool_t got_long = 0;  /* %lf, %ld etc */\n\t\tduk__dprint_state st;\n\n\t\tif (ch != DUK_ASC_PERCENT) {\n\t\t\tduk_fb_put_byte(&fb, (duk_uint8_t) ch);\n\t\t\tcontinue;\n\t\t}\n\n\t\t/*\n\t\t *  Format tag parsing.  Since we don't understand all the\n\t\t *  possible format tags allowed, we just scan for a terminating\n\t\t *  specifier and keep track of relevant modifiers that we do\n\t\t *  understand.  See man 3 printf.\n\t\t */\n\n\t\tDUK_MEMZERO(&st, sizeof(st));\n\t\tst.fb = &fb;\n\t\tst.depth = 0;\n\t\tst.depth_limit = 1;\n\t\tst.loop_stack_index = 0;\n\t\tst.loop_stack_limit = DUK__LOOP_STACK_DEPTH;\n\n\t\tp_begfmt = p - 1;\n\t\twhile (p < p_end) {\n\t\t\tch = *p++;\n\n\t\t\tif (ch == DUK_ASC_STAR) {\n\t\t\t\t/* unsupported: would consume multiple args */\n\t\t\t\tgoto format_error;\n\t\t\t} else if (ch == DUK_ASC_PERCENT) {\n\t\t\t\tduk_fb_put_byte(&fb, (duk_uint8_t) DUK_ASC_PERCENT);\n\t\t\t\tbreak;\n\t\t\t} else if (ch == DUK_ASC_EXCLAMATION) {\n\t\t\t\tgot_exclamation = 1;\n\t\t\t} else if (!got_exclamation && ch == DUK_ASC_LC_L) {\n\t\t\t\tgot_long = 1;\n\t\t\t} else if (got_exclamation && ch == DUK_ASC_LC_D) {\n\t\t\t\tst.depth_limit = DUK__DEEP_DEPTH_LIMIT;\n\t\t\t} else if (got_exclamation && ch == DUK_ASC_LC_P) {\n\t\t\t\tst.follow_proto = 1;\n\t\t\t} else if (got_exclamation && ch == DUK_ASC_LC_I) {\n\t\t\t\tst.internal = 1;\n\t\t\t} else if (got_exclamation && ch == DUK_ASC_LC_X) {\n\t\t\t\tst.hexdump = 1;\n\t\t\t} else if (got_exclamation && ch == DUK_ASC_LC_H) {\n\t\t\t\tst.heavy = 1;\n\t\t\t} else if (got_exclamation && ch == DUK_ASC_ATSIGN) {\n\t\t\t\tst.pointer = 1;\n\t\t\t} else if (got_exclamation && ch == DUK_ASC_HASH) {\n\t\t\t\tst.binary = 1;\n\t\t\t} else if (got_exclamation && ch == DUK_ASC_UC_T) {\n\t\t\t\tduk_tval *t = va_arg(ap, duk_tval *);\n\t\t\t\tif (st.pointer && !st.heavy) {\n\t\t\t\t\tduk_fb_sprintf(&fb, \"(%p)\", (void *) t);\n\t\t\t\t}\n\t\t\t\tduk__print_tval(&st, t);\n\t\t\t\tbreak;\n\t\t\t} else if (got_exclamation && ch == DUK_ASC_UC_O) {\n\t\t\t\tduk_heaphdr *t = va_arg(ap, duk_heaphdr *);\n\t\t\t\tif (st.pointer && !st.heavy) {\n\t\t\t\t\tduk_fb_sprintf(&fb, \"(%p)\", (void *) t);\n\t\t\t\t}\n\t\t\t\tduk__print_heaphdr(&st, t);\n\t\t\t\tbreak;\n\t\t\t} else if (got_exclamation && ch == DUK_ASC_UC_I) {\n\t\t\t\tduk_instr_t t = va_arg(ap, duk_instr_t);\n\t\t\t\tduk__print_instr(&st, t);\n\t\t\t\tbreak;\n\t\t\t} else if (got_exclamation && ch == DUK_ASC_UC_C) {\n\t\t\t\tlong t = va_arg(ap, long);\n\t\t\t\tduk__print_opcode(&st, (duk_small_int_t) t);\n\t\t\t\tbreak;\n\t\t\t} else if (!got_exclamation && strchr(DUK__ALLOWED_STANDARD_SPECIFIERS, (int) ch)) {\n\t\t\t\tchar fmtbuf[DUK__MAX_FORMAT_TAG_LENGTH];\n\t\t\t\tduk_size_t fmtlen;\n\n\t\t\t\tDUK_ASSERT(p >= p_begfmt);\n\t\t\t\tfmtlen = (duk_size_t) (p - p_begfmt);\n\t\t\t\tif (fmtlen >= sizeof(fmtbuf)) {\n\t\t\t\t\t/* format is too large, abort */\n\t\t\t\t\tgoto format_error;\n\t\t\t\t}\n\t\t\t\tDUK_MEMZERO(fmtbuf, sizeof(fmtbuf));\n\t\t\t\tDUK_MEMCPY(fmtbuf, p_begfmt, fmtlen);\n\n\t\t\t\t/* assume exactly 1 arg, which is why '*' is forbidden; arg size still\n\t\t\t\t * depends on type though.\n\t\t\t\t */\n\n\t\t\t\tif (ch == DUK_ASC_LC_F || ch == DUK_ASC_LC_G || ch == DUK_ASC_LC_E) {\n\t\t\t\t\t/* %f and %lf both consume a 'long' */\n\t\t\t\t\tdouble arg = va_arg(ap, double);\n\t\t\t\t\tduk_fb_sprintf(&fb, fmtbuf, arg);\n\t\t\t\t} else if (ch == DUK_ASC_LC_D && got_long) {\n\t\t\t\t\t/* %ld */\n\t\t\t\t\tlong arg = va_arg(ap, long);\n\t\t\t\t\tduk_fb_sprintf(&fb, fmtbuf, arg);\n\t\t\t\t} else if (ch == DUK_ASC_LC_D) {\n\t\t\t\t\t/* %d; only 16 bits are guaranteed */\n\t\t\t\t\tint arg = va_arg(ap, int);\n\t\t\t\t\tduk_fb_sprintf(&fb, fmtbuf, arg);\n\t\t\t\t} else if (ch == DUK_ASC_LC_U && got_long) {\n\t\t\t\t\t/* %lu */\n\t\t\t\t\tunsigned long arg = va_arg(ap, unsigned long);\n\t\t\t\t\tduk_fb_sprintf(&fb, fmtbuf, arg);\n\t\t\t\t} else if (ch == DUK_ASC_LC_U) {\n\t\t\t\t\t/* %u; only 16 bits are guaranteed */\n\t\t\t\t\tunsigned int arg = va_arg(ap, unsigned int);\n\t\t\t\t\tduk_fb_sprintf(&fb, fmtbuf, arg);\n\t\t\t\t} else if (ch == DUK_ASC_LC_X && got_long) {\n\t\t\t\t\t/* %lx */\n\t\t\t\t\tunsigned long arg = va_arg(ap, unsigned long);\n\t\t\t\t\tduk_fb_sprintf(&fb, fmtbuf, arg);\n\t\t\t\t} else if (ch == DUK_ASC_LC_X) {\n\t\t\t\t\t/* %x; only 16 bits are guaranteed */\n\t\t\t\t\tunsigned int arg = va_arg(ap, unsigned int);\n\t\t\t\t\tduk_fb_sprintf(&fb, fmtbuf, arg);\n\t\t\t\t} else if (ch == DUK_ASC_LC_S) {\n\t\t\t\t\t/* %s */\n\t\t\t\t\tconst char *arg = va_arg(ap, const char *);\n\t\t\t\t\tif (arg == NULL) {\n\t\t\t\t\t\t/* '%s' and NULL is not portable, so special case\n\t\t\t\t\t\t * it for debug printing.\n\t\t\t\t\t\t */\n\t\t\t\t\t\tduk_fb_sprintf(&fb, \"NULL\");\n\t\t\t\t\t} else {\n\t\t\t\t\t\tduk_fb_sprintf(&fb, fmtbuf, arg);\n\t\t\t\t\t}\n\t\t\t\t} else if (ch == DUK_ASC_LC_P) {\n\t\t\t\t\t/* %p */\n\t\t\t\t\tvoid *arg = va_arg(ap, void *);\n\t\t\t\t\tif (arg == NULL) {\n\t\t\t\t\t\t/* '%p' and NULL is portable, but special case it\n\t\t\t\t\t\t * anyway to get a standard NULL marker in logs.\n\t\t\t\t\t\t */\n\t\t\t\t\t\tduk_fb_sprintf(&fb, \"NULL\");\n\t\t\t\t\t} else {\n\t\t\t\t\t\tduk_fb_sprintf(&fb, fmtbuf, arg);\n\t\t\t\t\t}\n\t\t\t\t} else if (ch == DUK_ASC_LC_C) {\n\t\t\t\t\t/* '%c', passed concretely as int */\n\t\t\t\t\tint arg = va_arg(ap, int);\n\t\t\t\t\tduk_fb_sprintf(&fb, fmtbuf, arg);\n\t\t\t\t} else {\n\t\t\t\t\t/* Should not happen. */\n\t\t\t\t\tduk_fb_sprintf(&fb, \"INVALID-FORMAT(%s)\", (const char *) fmtbuf);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t} else {\n\t\t\t\t/* ignore */\n\t\t\t}\n\t\t}\n\t}\n\tgoto done;\n\n format_error:\n\tduk_fb_put_cstring(&fb, \"FMTERR\");\n\t/* fall through */\n\n done:\n\tretval = (duk_int_t) fb.offset;\n\tduk_fb_put_byte(&fb, (duk_uint8_t) 0);\n\n\t/* return total chars written excluding terminator */\n\treturn retval;\n}\n\n#if 0  /*unused*/\nDUK_INTERNAL duk_int_t duk_debug_snprintf(char *str, duk_size_t size, const char *format, ...) {\n\tduk_int_t retval;\n\tva_list ap;\n\tva_start(ap, format);\n\tretval = duk_debug_vsnprintf(str, size, format, ap);\n\tva_end(ap);\n\treturn retval;\n}\n#endif\n\n/* Formatting function pointers is tricky: there is no standard pointer for\n * function pointers and the size of a function pointer may depend on the\n * specific pointer type.  This helper formats a function pointer based on\n * its memory layout to get something useful on most platforms.\n */\nDUK_INTERNAL void duk_debug_format_funcptr(char *buf, duk_size_t buf_size, duk_uint8_t *fptr, duk_size_t fptr_size) {\n\tduk_size_t i;\n\tduk_uint8_t *p = (duk_uint8_t *) buf;\n\tduk_uint8_t *p_end = (duk_uint8_t *) (buf + buf_size - 1);\n\n\tDUK_MEMZERO(buf, buf_size);\n\n\tfor (i = 0; i < fptr_size; i++) {\n\t\tduk_int_t left = (duk_int_t) (p_end - p);\n\t\tduk_uint8_t ch;\n\t\tif (left <= 0) {\n\t\t\tbreak;\n\t\t}\n\n\t\t/* Quite approximate but should be useful for little and big endian. */\n#if defined(DUK_USE_INTEGER_BE)\n\t\tch = fptr[i];\n#else\n\t\tch = fptr[fptr_size - 1 - i];\n#endif\n\t\tp += DUK_SNPRINTF((char *) p, (duk_size_t) left, \"%02lx\", (unsigned long) ch);\n\t}\n}\n\n#endif  /* DUK_USE_DEBUG */\n\n/* automatic undefs */\n#undef DUK__ALLOWED_STANDARD_SPECIFIERS\n#undef DUK__COMMA\n#undef DUK__DEEP_DEPTH_LIMIT\n#undef DUK__LOOP_STACK_DEPTH\n#undef DUK__MAX_FORMAT_TAG_LENGTH\n#line 1 \"duk_debugger.c\"\n/*\n *  Duktape debugger\n */\n\n/* #include duk_internal.h -> already included */\n\n#if defined(DUK_USE_DEBUGGER_SUPPORT)\n\n/*\n *  Assert helpers\n */\n\n#if defined(DUK_USE_ASSERTIONS)\n#define DUK__DBG_TPORT_ENTER() do { \\\n\t\tDUK_ASSERT(heap->dbg_calling_transport == 0); \\\n\t\theap->dbg_calling_transport = 1; \\\n\t} while (0)\n#define DUK__DBG_TPORT_EXIT() do { \\\n\t\tDUK_ASSERT(heap->dbg_calling_transport == 1); \\\n\t\theap->dbg_calling_transport = 0; \\\n\t} while (0)\n#else\n#define DUK__DBG_TPORT_ENTER() do {} while (0)\n#define DUK__DBG_TPORT_EXIT() do {} while (0)\n#endif\n\n/*\n *  Helper structs\n */\n\ntypedef union {\n\tvoid *p;\n\tduk_uint_t b[1];\n\t/* Use b[] to access the size of the union, which is strictly not\n\t * correct.  Can't use fixed size unless there's feature detection\n\t * for pointer byte size.\n\t */\n} duk__ptr_union;\n\n/*\n *  Detach handling\n */\n\n#define DUK__SET_CONN_BROKEN(thr,reason) do { \\\n\t\t/* For now shared handler is fine. */ \\\n\t\tduk__debug_do_detach1((thr)->heap, (reason)); \\\n\t} while (0)\n\nDUK_LOCAL void duk__debug_do_detach1(duk_heap *heap, duk_int_t reason) {\n\t/* Can be called multiple times with no harm.  Mark the transport\n\t * bad (dbg_read_cb == NULL) and clear state except for the detached\n\t * callback and the udata field.  The detached callback is delayed\n\t * to the message loop so that it can be called between messages;\n\t * this avoids corner cases related to immediate debugger reattach\n\t * inside the detached callback.\n\t */\n\n\tif (heap->dbg_detaching) {\n\t\tDUK_D(DUK_DPRINT(\"debugger already detaching, ignore detach1\"));\n\t\treturn;\n\t}\n\n\tDUK_D(DUK_DPRINT(\"debugger transport detaching, marking transport broken\"));\n\n\theap->dbg_detaching = 1;  /* prevent multiple in-progress detaches */\n\n\tif (heap->dbg_write_cb != NULL) {\n\t\tduk_hthread *thr;\n\n\t\tthr = heap->heap_thread;\n\t\tDUK_ASSERT(thr != NULL);\n\n\t\tduk_debug_write_notify(thr, DUK_DBG_CMD_DETACHING);\n\t\tduk_debug_write_int(thr, reason);\n\t\tduk_debug_write_eom(thr);\n\t}\n\n\theap->dbg_read_cb = NULL;\n\theap->dbg_write_cb = NULL;\n\theap->dbg_peek_cb = NULL;\n\theap->dbg_read_flush_cb = NULL;\n\theap->dbg_write_flush_cb = NULL;\n\theap->dbg_request_cb = NULL;\n\t/* heap->dbg_detached_cb: keep */\n\t/* heap->dbg_udata: keep */\n\t/* heap->dbg_processing: keep on purpose to avoid debugger re-entry in detaching state */\n\theap->dbg_state_dirty = 0;\n\theap->dbg_force_restart = 0;\n\theap->dbg_pause_flags = 0;\n\theap->dbg_pause_act = NULL;\n\theap->dbg_pause_startline = 0;\n\theap->dbg_have_next_byte = 0;\n\tduk_debug_clear_paused(heap);  /* XXX: some overlap with field inits above */\n\theap->dbg_state_dirty = 0;     /* XXX: clear_paused sets dirty; rework? */\n\n\t/* Ensure there are no stale active breakpoint pointers.\n\t * Breakpoint list is currently kept - we could empty it\n\t * here but we'd need to handle refcounts correctly, and\n\t * we'd need a 'thr' reference for that.\n\t *\n\t * XXX: clear breakpoint on either attach or detach?\n\t */\n\theap->dbg_breakpoints_active[0] = (duk_breakpoint *) NULL;\n}\n\nDUK_LOCAL void duk__debug_do_detach2(duk_heap *heap) {\n\tduk_debug_detached_function detached_cb;\n\tvoid *detached_udata;\n\tduk_hthread *thr;\n\n\tthr = heap->heap_thread;\n\tif (thr == NULL) {\n\t\tDUK_ASSERT(heap->dbg_detached_cb == NULL);\n\t\treturn;\n\t}\n\n\t/* Safe to call multiple times. */\n\n\tdetached_cb = heap->dbg_detached_cb;\n\tdetached_udata = heap->dbg_udata;\n\theap->dbg_detached_cb = NULL;\n\theap->dbg_udata = NULL;\n\n\tif (detached_cb) {\n\t\t/* Careful here: state must be wiped before the call\n\t\t * so that we can cleanly handle a re-attach from\n\t\t * inside the callback.\n\t\t */\n\t\tDUK_D(DUK_DPRINT(\"detached during message loop, delayed call to detached_cb\"));\n\t\tdetached_cb(thr, detached_udata);\n\t}\n\n\theap->dbg_detaching = 0;\n}\n\nDUK_INTERNAL void duk_debug_do_detach(duk_heap *heap) {\n\tduk__debug_do_detach1(heap, 0);\n\tduk__debug_do_detach2(heap);\n}\n\n/* Called on a read/write error: NULL all callbacks except the detached\n * callback so that we never accidentally call them after a read/write\n * error has been indicated.  This is especially important for the transport\n * I/O callbacks to fulfill guaranteed callback semantics.\n */\nDUK_LOCAL void duk__debug_null_most_callbacks(duk_hthread *thr) {\n\tduk_heap *heap;\n\n\tDUK_ASSERT(thr != NULL);\n\n\theap = thr->heap;\n\tDUK_D(DUK_DPRINT(\"transport read/write error, NULL all callbacks expected detached\"));\n\theap->dbg_read_cb = NULL;\n\theap->dbg_write_cb = NULL;  /* this is especially critical to avoid another write call in detach1() */\n\theap->dbg_peek_cb = NULL;\n\theap->dbg_read_flush_cb = NULL;\n\theap->dbg_write_flush_cb = NULL;\n\theap->dbg_request_cb = NULL;\n\t/* keep heap->dbg_detached_cb */\n}\n\n/*\n *  Pause handling\n */\n\nDUK_LOCAL void duk__debug_set_pause_state(duk_hthread *thr, duk_heap *heap, duk_small_uint_t pause_flags) {\n\tduk_uint_fast32_t line;\n\n\tline = duk_debug_curr_line(thr);\n\tif (line == 0) {\n\t\t/* No line info for current function. */\n\t\tduk_small_uint_t updated_flags;\n\n\t\tupdated_flags = pause_flags & ~(DUK_PAUSE_FLAG_LINE_CHANGE);\n\t\tDUK_D(DUK_DPRINT(\"no line info for current activation, disable line-based pause flags: 0x%08lx -> 0x%08lx\",\n\t\t                 (long) pause_flags, (long) updated_flags));\n\t\tpause_flags = updated_flags;\n\t}\n\n\theap->dbg_pause_flags = pause_flags;\n\theap->dbg_pause_act = thr->callstack_curr;\n\theap->dbg_pause_startline = (duk_uint32_t) line;\n\theap->dbg_state_dirty = 1;\n\n\tDUK_D(DUK_DPRINT(\"set state for automatic pause triggers, flags=0x%08lx, act=%p, startline=%ld\",\n\t                 (long) heap->dbg_pause_flags, (void *) heap->dbg_pause_act,\n\t                 (long) heap->dbg_pause_startline));\n}\n\n/*\n *  Debug connection peek and flush primitives\n */\n\nDUK_INTERNAL duk_bool_t duk_debug_read_peek(duk_hthread *thr) {\n\tduk_heap *heap;\n\tduk_bool_t ret;\n\n\tDUK_ASSERT(thr != NULL);\n\theap = thr->heap;\n\tDUK_ASSERT(heap != NULL);\n\n\tif (heap->dbg_read_cb == NULL) {\n\t\tDUK_D(DUK_DPRINT(\"attempt to peek in detached state, return zero (= no data)\"));\n\t\treturn 0;\n\t}\n\tif (heap->dbg_peek_cb == NULL) {\n\t\tDUK_DD(DUK_DDPRINT(\"no peek callback, return zero (= no data)\"));\n\t\treturn 0;\n\t}\n\n\tDUK__DBG_TPORT_ENTER();\n\tret = (duk_bool_t) (heap->dbg_peek_cb(heap->dbg_udata) > 0);\n\tDUK__DBG_TPORT_EXIT();\n\treturn ret;\n}\n\nDUK_INTERNAL void duk_debug_read_flush(duk_hthread *thr) {\n\tduk_heap *heap;\n\n\tDUK_ASSERT(thr != NULL);\n\theap = thr->heap;\n\tDUK_ASSERT(heap != NULL);\n\n\tif (heap->dbg_read_cb == NULL) {\n\t\tDUK_D(DUK_DPRINT(\"attempt to read flush in detached state, ignore\"));\n\t\treturn;\n\t}\n\tif (heap->dbg_read_flush_cb == NULL) {\n\t\tDUK_DD(DUK_DDPRINT(\"no read flush callback, ignore\"));\n\t\treturn;\n\t}\n\n\tDUK__DBG_TPORT_ENTER();\n\theap->dbg_read_flush_cb(heap->dbg_udata);\n\tDUK__DBG_TPORT_EXIT();\n}\n\nDUK_INTERNAL void duk_debug_write_flush(duk_hthread *thr) {\n\tduk_heap *heap;\n\n\tDUK_ASSERT(thr != NULL);\n\theap = thr->heap;\n\tDUK_ASSERT(heap != NULL);\n\n\tif (heap->dbg_read_cb == NULL) {\n\t\tDUK_D(DUK_DPRINT(\"attempt to write flush in detached state, ignore\"));\n\t\treturn;\n\t}\n\tif (heap->dbg_write_flush_cb == NULL) {\n\t\tDUK_DD(DUK_DDPRINT(\"no write flush callback, ignore\"));\n\t\treturn;\n\t}\n\n\tDUK__DBG_TPORT_ENTER();\n\theap->dbg_write_flush_cb(heap->dbg_udata);\n\tDUK__DBG_TPORT_EXIT();\n}\n\n/*\n *  Debug connection skip primitives\n */\n\n/* Skip fully. */\nDUK_INTERNAL void duk_debug_skip_bytes(duk_hthread *thr, duk_size_t length) {\n\tduk_uint8_t dummy[64];\n\tduk_size_t now;\n\n\tDUK_ASSERT(thr != NULL);\n\n\twhile (length > 0) {\n\t\tnow = (length > sizeof(dummy) ? sizeof(dummy) : length);\n\t\tduk_debug_read_bytes(thr, dummy, now);\n\t\tlength -= now;\n\t}\n}\n\nDUK_INTERNAL void duk_debug_skip_byte(duk_hthread *thr) {\n\tDUK_ASSERT(thr != NULL);\n\n\t(void) duk_debug_read_byte(thr);\n}\n\n/*\n *  Debug connection read primitives\n */\n\n/* Peek ahead in the stream one byte. */\nDUK_INTERNAL uint8_t duk_debug_peek_byte(duk_hthread *thr) {\n\t/* It is important not to call this if the last byte read was an EOM.\n\t * Reading ahead in this scenario would cause unnecessary blocking if\n\t * another message is not available.\n\t */\n\n\tduk_uint8_t x;\n\n\tx = duk_debug_read_byte(thr);\n\tthr->heap->dbg_have_next_byte = 1;\n\tthr->heap->dbg_next_byte = x;\n\treturn x;\n}\n\n/* Read fully. */\nDUK_INTERNAL void duk_debug_read_bytes(duk_hthread *thr, duk_uint8_t *data, duk_size_t length) {\n\tduk_heap *heap;\n\tduk_uint8_t *p;\n\tduk_size_t left;\n\tduk_size_t got;\n\n\tDUK_ASSERT(thr != NULL);\n\theap = thr->heap;\n\tDUK_ASSERT(heap != NULL);\n\n\tif (heap->dbg_read_cb == NULL) {\n\t\tDUK_D(DUK_DPRINT(\"attempt to read %ld bytes in detached state, return zero data\", (long) length));\n\t\tgoto fail;\n\t}\n\n\t/* NOTE: length may be zero */\n\tp = data;\n\tif (length >= 1 && heap->dbg_have_next_byte) {\n\t\theap->dbg_have_next_byte = 0;\n\t\t*p++ = heap->dbg_next_byte;\n\t}\n\tfor (;;) {\n\t\tleft = (duk_size_t) ((data + length) - p);\n\t\tif (left == 0) {\n\t\t\tbreak;\n\t\t}\n\t\tDUK_ASSERT(heap->dbg_read_cb != NULL);\n\t\tDUK_ASSERT(left >= 1);\n#if defined(DUK_USE_DEBUGGER_TRANSPORT_TORTURE)\n\t\tleft = 1;\n#endif\n\t\tDUK__DBG_TPORT_ENTER();\n\t\tgot = heap->dbg_read_cb(heap->dbg_udata, (char *) p, left);\n\t\tDUK__DBG_TPORT_EXIT();\n\n\t\tif (got == 0 || got > left) {\n\t\t\tDUK_D(DUK_DPRINT(\"connection error during read, return zero data\"));\n\t\t\tduk__debug_null_most_callbacks(thr);  /* avoid calling write callback in detach1() */\n\t\t\tDUK__SET_CONN_BROKEN(thr, 1);\n\t\t\tgoto fail;\n\t\t}\n\t\tp += got;\n\t}\n\treturn;\n\n fail:\n\tDUK_MEMZERO((void *) data, (size_t) length);\n}\n\nDUK_INTERNAL duk_uint8_t duk_debug_read_byte(duk_hthread *thr) {\n\tduk_uint8_t x;\n\n\tx = 0;  /* just in case callback is broken and won't write 'x' */\n\tduk_debug_read_bytes(thr, &x, 1);\n\treturn x;\n}\n\nDUK_LOCAL duk_uint32_t duk__debug_read_uint32_raw(duk_hthread *thr) {\n\tduk_uint8_t buf[4];\n\n\tDUK_ASSERT(thr != NULL);\n\n\tduk_debug_read_bytes(thr, buf, 4);\n\treturn ((duk_uint32_t) buf[0] << 24) |\n\t       ((duk_uint32_t) buf[1] << 16) |\n\t       ((duk_uint32_t) buf[2] << 8) |\n\t       (duk_uint32_t) buf[3];\n}\n\nDUK_LOCAL duk_int32_t duk__debug_read_int32_raw(duk_hthread *thr) {\n\treturn (duk_int32_t) duk__debug_read_uint32_raw(thr);\n}\n\nDUK_LOCAL duk_uint16_t duk__debug_read_uint16_raw(duk_hthread *thr) {\n\tduk_uint8_t buf[2];\n\n\tDUK_ASSERT(thr != NULL);\n\n\tduk_debug_read_bytes(thr, buf, 2);\n\treturn ((duk_uint16_t) buf[0] << 8) |\n\t       (duk_uint16_t) buf[1];\n}\n\nDUK_INTERNAL duk_int32_t duk_debug_read_int(duk_hthread *thr) {\n\tduk_small_uint_t x;\n\tduk_small_uint_t t;\n\n\tDUK_ASSERT(thr != NULL);\n\n\tx = duk_debug_read_byte(thr);\n\tif (x >= 0xc0) {\n\t\tt = duk_debug_read_byte(thr);\n\t\treturn (duk_int32_t) (((x - 0xc0) << 8) + t);\n\t} else if (x >= 0x80) {\n\t\treturn (duk_int32_t) (x - 0x80);\n\t} else if (x == DUK_DBG_IB_INT4) {\n\t\treturn (duk_int32_t) duk__debug_read_uint32_raw(thr);\n\t}\n\n\tDUK_D(DUK_DPRINT(\"debug connection error: failed to decode int\"));\n\tDUK__SET_CONN_BROKEN(thr, 1);\n\treturn 0;\n}\n\nDUK_LOCAL duk_hstring *duk__debug_read_hstring_raw(duk_hthread *thr, duk_uint32_t len) {\n\tduk_uint8_t buf[31];\n\tduk_uint8_t *p;\n\n\tif (len <= sizeof(buf)) {\n\t\tduk_debug_read_bytes(thr, buf, (duk_size_t) len);\n\t\tduk_push_lstring(thr, (const char *) buf, (duk_size_t) len);\n\t} else {\n\t\tp = (duk_uint8_t *) duk_push_fixed_buffer(thr, (duk_size_t) len);  /* zero for paranoia */\n\t\tDUK_ASSERT(p != NULL);\n\t\tduk_debug_read_bytes(thr, p, (duk_size_t) len);\n\t\t(void) duk_buffer_to_string(thr, -1);  /* Safety relies on debug client, which is OK. */\n\t}\n\n\treturn duk_require_hstring(thr, -1);\n}\n\nDUK_INTERNAL duk_hstring *duk_debug_read_hstring(duk_hthread *thr) {\n\tduk_small_uint_t x;\n\tduk_uint32_t len;\n\n\tDUK_ASSERT(thr != NULL);\n\n\tx = duk_debug_read_byte(thr);\n\tif (x >= 0x60 && x <= 0x7f) {\n\t\t/* For short strings, use a fixed temp buffer. */\n\t\tlen = (duk_uint32_t) (x - 0x60);\n\t} else if (x == DUK_DBG_IB_STR2) {\n\t\tlen = (duk_uint32_t) duk__debug_read_uint16_raw(thr);\n\t} else if (x == DUK_DBG_IB_STR4) {\n\t\tlen = (duk_uint32_t) duk__debug_read_uint32_raw(thr);\n\t} else {\n\t\tgoto fail;\n\t}\n\n\treturn duk__debug_read_hstring_raw(thr, len);\n\n fail:\n\tDUK_D(DUK_DPRINT(\"debug connection error: failed to decode int\"));\n\tDUK__SET_CONN_BROKEN(thr, 1);\n\tduk_push_hstring_empty(thr);  /* always push some string */\n\treturn duk_require_hstring(thr, -1);\n}\n\nDUK_LOCAL duk_hbuffer *duk__debug_read_hbuffer_raw(duk_hthread *thr, duk_uint32_t len) {\n\tduk_uint8_t *p;\n\n\tp = (duk_uint8_t *) duk_push_fixed_buffer(thr, (duk_size_t) len);  /* zero for paranoia */\n\tDUK_ASSERT(p != NULL);\n\tduk_debug_read_bytes(thr, p, (duk_size_t) len);\n\n\treturn duk_require_hbuffer(thr, -1);\n}\n\nDUK_LOCAL void *duk__debug_read_pointer_raw(duk_hthread *thr) {\n\tduk_small_uint_t x;\n\tduk__ptr_union pu;\n\n\tDUK_ASSERT(thr != NULL);\n\n\tx = duk_debug_read_byte(thr);\n\tif (x != sizeof(pu)) {\n\t\tgoto fail;\n\t}\n\tduk_debug_read_bytes(thr, (duk_uint8_t *) &pu.p, sizeof(pu));\n#if defined(DUK_USE_INTEGER_LE)\n\tduk_byteswap_bytes((duk_uint8_t *) pu.b, sizeof(pu));\n#endif\n\treturn (void *) pu.p;\n\n fail:\n\tDUK_D(DUK_DPRINT(\"debug connection error: failed to decode pointer\"));\n\tDUK__SET_CONN_BROKEN(thr, 1);\n\treturn (void *) NULL;\n}\n\nDUK_LOCAL duk_double_t duk__debug_read_double_raw(duk_hthread *thr) {\n\tduk_double_union du;\n\n\tDUK_ASSERT(sizeof(du.uc) == 8);\n\tduk_debug_read_bytes(thr, (duk_uint8_t *) du.uc, sizeof(du.uc));\n\tDUK_DBLUNION_DOUBLE_NTOH(&du);\n\treturn du.d;\n}\n\n#if 0\nDUK_INTERNAL duk_heaphdr *duk_debug_read_heapptr(duk_hthread *thr) {\n\tduk_small_uint_t x;\n\n\tDUK_ASSERT(thr != NULL);\n\n\tx = duk_debug_read_byte(thr);\n\tif (x != DUK_DBG_IB_HEAPPTR) {\n\t\tgoto fail;\n\t}\n\n\treturn (duk_heaphdr *) duk__debug_read_pointer_raw(thr);\n\n fail:\n\tDUK_D(DUK_DPRINT(\"debug connection error: failed to decode heapptr\"));\n\tDUK__SET_CONN_BROKEN(thr, 1);\n\treturn NULL;\n}\n#endif\n\nDUK_INTERNAL duk_heaphdr *duk_debug_read_any_ptr(duk_hthread *thr) {\n\tduk_small_uint_t x;\n\n\tDUK_ASSERT(thr != NULL);\n\n\tx = duk_debug_read_byte(thr);\n\tswitch (x) {\n\tcase DUK_DBG_IB_OBJECT:\n\tcase DUK_DBG_IB_POINTER:\n\tcase DUK_DBG_IB_HEAPPTR:\n\t\t/* Accept any pointer-like value; for 'object' dvalue, read\n\t\t * and ignore the class number.\n\t\t */\n\t\tif (x == DUK_DBG_IB_OBJECT) {\n\t\t\tduk_debug_skip_byte(thr);\n\t\t}\n\t\tbreak;\n\tdefault:\n\t\tgoto fail;\n\t}\n\n\treturn (duk_heaphdr *) duk__debug_read_pointer_raw(thr);\n\n fail:\n\tDUK_D(DUK_DPRINT(\"debug connection error: failed to decode any pointer (object, pointer, heapptr)\"));\n\tDUK__SET_CONN_BROKEN(thr, 1);\n\treturn NULL;\n}\n\nDUK_INTERNAL duk_tval *duk_debug_read_tval(duk_hthread *thr) {\n\tduk_uint8_t x;\n\tduk_uint_t t;\n\tduk_uint32_t len;\n\n\tDUK_ASSERT(thr != NULL);\n\n\tx = duk_debug_read_byte(thr);\n\n\tif (x >= 0xc0) {\n\t\tt = (duk_uint_t) (x - 0xc0);\n\t\tt = (t << 8) + duk_debug_read_byte(thr);\n\t\tduk_push_uint(thr, (duk_uint_t) t);\n\t\tgoto return_ptr;\n\t}\n\tif (x >= 0x80) {\n\t\tduk_push_uint(thr, (duk_uint_t) (x - 0x80));\n\t\tgoto return_ptr;\n\t}\n\tif (x >= 0x60) {\n\t\tlen = (duk_uint32_t) (x - 0x60);\n\t\tduk__debug_read_hstring_raw(thr, len);\n\t\tgoto return_ptr;\n\t}\n\n\tswitch (x) {\n\tcase DUK_DBG_IB_INT4: {\n\t\tduk_int32_t i = duk__debug_read_int32_raw(thr);\n\t\tduk_push_i32(thr, i);\n\t\tbreak;\n\t}\n\tcase DUK_DBG_IB_STR4: {\n\t\tlen = duk__debug_read_uint32_raw(thr);\n\t\tduk__debug_read_hstring_raw(thr, len);\n\t\tbreak;\n\t}\n\tcase DUK_DBG_IB_STR2: {\n\t\tlen = duk__debug_read_uint16_raw(thr);\n\t\tduk__debug_read_hstring_raw(thr, len);\n\t\tbreak;\n\t}\n\tcase DUK_DBG_IB_BUF4: {\n\t\tlen = duk__debug_read_uint32_raw(thr);\n\t\tduk__debug_read_hbuffer_raw(thr, len);\n\t\tbreak;\n\t}\n\tcase DUK_DBG_IB_BUF2: {\n\t\tlen = duk__debug_read_uint16_raw(thr);\n\t\tduk__debug_read_hbuffer_raw(thr, len);\n\t\tbreak;\n\t}\n\tcase DUK_DBG_IB_UNDEFINED: {\n\t\tduk_push_undefined(thr);\n\t\tbreak;\n\t}\n\tcase DUK_DBG_IB_NULL: {\n\t\tduk_push_null(thr);\n\t\tbreak;\n\t}\n\tcase DUK_DBG_IB_TRUE: {\n\t\tduk_push_true(thr);\n\t\tbreak;\n\t}\n\tcase DUK_DBG_IB_FALSE: {\n\t\tduk_push_false(thr);\n\t\tbreak;\n\t}\n\tcase DUK_DBG_IB_NUMBER: {\n\t\tduk_double_t d;\n\t\td = duk__debug_read_double_raw(thr);\n\t\tduk_push_number(thr, d);\n\t\tbreak;\n\t}\n\tcase DUK_DBG_IB_OBJECT: {\n\t\tduk_heaphdr *h;\n\t\tduk_debug_skip_byte(thr);\n\t\th = (duk_heaphdr *) duk__debug_read_pointer_raw(thr);\n\t\tduk_push_heapptr(thr, (void *) h);\n\t\tbreak;\n\t}\n\tcase DUK_DBG_IB_POINTER: {\n\t\tvoid *ptr;\n\t\tptr = duk__debug_read_pointer_raw(thr);\n\t\tduk_push_pointer(thr, ptr);\n\t\tbreak;\n\t}\n\tcase DUK_DBG_IB_LIGHTFUNC: {\n\t\t/* XXX: Not needed for now, so not implemented.  Note that\n\t\t * function pointers may have different size/layout than\n\t\t * a void pointer.\n\t\t */\n\t\tDUK_D(DUK_DPRINT(\"reading lightfunc values unimplemented\"));\n\t\tgoto fail;\n\t}\n\tcase DUK_DBG_IB_HEAPPTR: {\n\t\tduk_heaphdr *h;\n\t\th = (duk_heaphdr *) duk__debug_read_pointer_raw(thr);\n\t\tduk_push_heapptr(thr, (void *) h);\n\t\tbreak;\n\t}\n\tcase DUK_DBG_IB_UNUSED:  /* unused: not accepted in inbound messages */\n\tdefault:\n\t\tgoto fail;\n\t}\n\n return_ptr:\n\treturn DUK_GET_TVAL_NEGIDX(thr, -1);\n\n fail:\n\tDUK_D(DUK_DPRINT(\"debug connection error: failed to decode tval\"));\n\tDUK__SET_CONN_BROKEN(thr, 1);\n\treturn NULL;\n}\n\n/*\n *  Debug connection write primitives\n */\n\n/* Write fully. */\nDUK_INTERNAL void duk_debug_write_bytes(duk_hthread *thr, const duk_uint8_t *data, duk_size_t length) {\n\tduk_heap *heap;\n\tconst duk_uint8_t *p;\n\tduk_size_t left;\n\tduk_size_t got;\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(length == 0 || data != NULL);\n\theap = thr->heap;\n\tDUK_ASSERT(heap != NULL);\n\n\tif (heap->dbg_write_cb == NULL) {\n\t\tDUK_D(DUK_DPRINT(\"attempt to write %ld bytes in detached state, ignore\", (long) length));\n\t\treturn;\n\t}\n\tif (length == 0) {\n\t\t/* Avoid doing an actual write callback with length == 0,\n\t\t * because that's reserved for a write flush.\n\t\t */\n\t\treturn;\n\t}\n\tDUK_ASSERT(data != NULL);\n\n\tp = data;\n\tfor (;;) {\n\t\tleft = (duk_size_t) ((data + length) - p);\n\t\tif (left == 0) {\n\t\t\tbreak;\n\t\t}\n\t\tDUK_ASSERT(heap->dbg_write_cb != NULL);\n\t\tDUK_ASSERT(left >= 1);\n#if defined(DUK_USE_DEBUGGER_TRANSPORT_TORTURE)\n\t\tleft = 1;\n#endif\n\t\tDUK__DBG_TPORT_ENTER();\n\t\tgot = heap->dbg_write_cb(heap->dbg_udata, (const char *) p, left);\n\t\tDUK__DBG_TPORT_EXIT();\n\n\t\tif (got == 0 || got > left) {\n\t\t\tduk__debug_null_most_callbacks(thr);  /* avoid calling write callback in detach1() */\n\t\t\tDUK_D(DUK_DPRINT(\"connection error during write\"));\n\t\t\tDUK__SET_CONN_BROKEN(thr, 1);\n\t\t\treturn;\n\t\t}\n\t\tp += got;\n\t}\n}\n\nDUK_INTERNAL void duk_debug_write_byte(duk_hthread *thr, duk_uint8_t x) {\n\tduk_debug_write_bytes(thr, (const duk_uint8_t *) &x, 1);\n}\n\nDUK_INTERNAL void duk_debug_write_unused(duk_hthread *thr) {\n\tduk_debug_write_byte(thr, DUK_DBG_IB_UNUSED);\n}\n\nDUK_INTERNAL void duk_debug_write_undefined(duk_hthread *thr) {\n\tduk_debug_write_byte(thr, DUK_DBG_IB_UNDEFINED);\n}\n\n#if defined(DUK_USE_DEBUGGER_INSPECT)\nDUK_INTERNAL void duk_debug_write_null(duk_hthread *thr) {\n\tduk_debug_write_byte(thr, DUK_DBG_IB_NULL);\n}\n#endif\n\nDUK_INTERNAL void duk_debug_write_boolean(duk_hthread *thr, duk_uint_t val) {\n\tduk_debug_write_byte(thr, val ? DUK_DBG_IB_TRUE : DUK_DBG_IB_FALSE);\n}\n\n/* Write signed 32-bit integer. */\nDUK_INTERNAL void duk_debug_write_int(duk_hthread *thr, duk_int32_t x) {\n\tduk_uint8_t buf[5];\n\tduk_size_t len;\n\n\tDUK_ASSERT(thr != NULL);\n\n\tif (x >= 0 && x <= 0x3fL) {\n\t\tbuf[0] = (duk_uint8_t) (0x80 + x);\n\t\tlen = 1;\n\t} else if (x >= 0 && x <= 0x3fffL) {\n\t\tbuf[0] = (duk_uint8_t) (0xc0 + (x >> 8));\n\t\tbuf[1] = (duk_uint8_t) (x & 0xff);\n\t\tlen = 2;\n\t} else {\n\t\t/* Signed integers always map to 4 bytes now. */\n\t\tbuf[0] = (duk_uint8_t) DUK_DBG_IB_INT4;\n\t\tbuf[1] = (duk_uint8_t) ((x >> 24) & 0xff);\n\t\tbuf[2] = (duk_uint8_t) ((x >> 16) & 0xff);\n\t\tbuf[3] = (duk_uint8_t) ((x >> 8) & 0xff);\n\t\tbuf[4] = (duk_uint8_t) (x & 0xff);\n\t\tlen = 5;\n\t}\n\tduk_debug_write_bytes(thr, buf, len);\n}\n\n/* Write unsigned 32-bit integer. */\nDUK_INTERNAL void duk_debug_write_uint(duk_hthread *thr, duk_uint32_t x) {\n\t/* The debugger protocol doesn't support a plain integer encoding for\n\t * the full 32-bit unsigned range (only 32-bit signed).  For now,\n\t * unsigned 32-bit values simply written as signed ones.  This is not\n\t * a concrete issue except for 32-bit heaphdr fields.  Proper solutions\n\t * would be to (a) write such integers as IEEE doubles or (b) add an\n\t * unsigned 32-bit dvalue.\n\t */\n\tif (x >= 0x80000000UL) {\n\t\tDUK_D(DUK_DPRINT(\"writing unsigned integer 0x%08lx as signed integer\",\n\t\t                 (long) x));\n\t}\n\tduk_debug_write_int(thr, (duk_int32_t) x);\n}\n\nDUK_INTERNAL void duk_debug_write_strbuf(duk_hthread *thr, const char *data, duk_size_t length, duk_uint8_t marker_base) {\n\tduk_uint8_t buf[5];\n\tduk_size_t buflen;\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(length == 0 || data != NULL);\n\n\tif (length <= 0x1fUL && marker_base == DUK_DBG_IB_STR4) {\n\t\t/* For strings, special form for short lengths. */\n\t\tbuf[0] = (duk_uint8_t) (0x60 + length);\n\t\tbuflen = 1;\n\t} else if (length <= 0xffffUL) {\n\t\tbuf[0] = (duk_uint8_t) (marker_base + 1);\n\t\tbuf[1] = (duk_uint8_t) (length >> 8);\n\t\tbuf[2] = (duk_uint8_t) (length & 0xff);\n\t\tbuflen = 3;\n\t} else {\n\t\tbuf[0] = (duk_uint8_t) marker_base;\n\t\tbuf[1] = (duk_uint8_t) (length >> 24);\n\t\tbuf[2] = (duk_uint8_t) ((length >> 16) & 0xff);\n\t\tbuf[3] = (duk_uint8_t) ((length >> 8) & 0xff);\n\t\tbuf[4] = (duk_uint8_t) (length & 0xff);\n\t\tbuflen = 5;\n\t}\n\n\tduk_debug_write_bytes(thr, (const duk_uint8_t *) buf, buflen);\n\tduk_debug_write_bytes(thr, (const duk_uint8_t *) data, length);\n}\n\nDUK_INTERNAL void duk_debug_write_string(duk_hthread *thr, const char *data, duk_size_t length) {\n\tduk_debug_write_strbuf(thr, data, length, DUK_DBG_IB_STR4);\n}\n\nDUK_INTERNAL void duk_debug_write_cstring(duk_hthread *thr, const char *data) {\n\tDUK_ASSERT(thr != NULL);\n\n\tduk_debug_write_string(thr,\n\t                       data,\n\t                       data ? DUK_STRLEN(data) : 0);\n}\n\nDUK_INTERNAL void duk_debug_write_hstring(duk_hthread *thr, duk_hstring *h) {\n\tDUK_ASSERT(thr != NULL);\n\n\t/* XXX: differentiate null pointer from empty string? */\n\tduk_debug_write_string(thr,\n\t                       (h != NULL ? (const char *) DUK_HSTRING_GET_DATA(h) : NULL),\n\t                       (h != NULL ? (duk_size_t) DUK_HSTRING_GET_BYTELEN(h) : 0));\n}\n\nDUK_LOCAL void duk__debug_write_hstring_safe_top(duk_hthread *thr) {\n\tduk_debug_write_hstring(thr, duk_safe_to_hstring(thr, -1));\n}\n\nDUK_INTERNAL void duk_debug_write_buffer(duk_hthread *thr, const char *data, duk_size_t length) {\n\tduk_debug_write_strbuf(thr, data, length, DUK_DBG_IB_BUF4);\n}\n\nDUK_INTERNAL void duk_debug_write_hbuffer(duk_hthread *thr, duk_hbuffer *h) {\n\tDUK_ASSERT(thr != NULL);\n\n\tduk_debug_write_buffer(thr,\n\t                       (h != NULL ? (const char *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h) : NULL),\n\t                       (h != NULL ? (duk_size_t) DUK_HBUFFER_GET_SIZE(h) : 0));\n}\n\nDUK_LOCAL void duk__debug_write_pointer_raw(duk_hthread *thr, void *ptr, duk_uint8_t ibyte) {\n\tduk_uint8_t buf[2];\n\tduk__ptr_union pu;\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(sizeof(ptr) >= 1 && sizeof(ptr) <= 16);\n\t/* ptr may be NULL */\n\n\tbuf[0] = ibyte;\n\tbuf[1] = sizeof(pu);\n\tduk_debug_write_bytes(thr, buf, 2);\n\tpu.p = (void *) ptr;\n#if defined(DUK_USE_INTEGER_LE)\n\tduk_byteswap_bytes((duk_uint8_t *) pu.b, sizeof(pu));\n#endif\n\tduk_debug_write_bytes(thr, (const duk_uint8_t *) &pu.p, (duk_size_t) sizeof(pu));\n}\n\nDUK_INTERNAL void duk_debug_write_pointer(duk_hthread *thr, void *ptr) {\n\tduk__debug_write_pointer_raw(thr, ptr, DUK_DBG_IB_POINTER);\n}\n\n#if defined(DUK_USE_DEBUGGER_DUMPHEAP) || defined(DUK_USE_DEBUGGER_INSPECT)\nDUK_INTERNAL void duk_debug_write_heapptr(duk_hthread *thr, duk_heaphdr *h) {\n\tduk__debug_write_pointer_raw(thr, (void *) h, DUK_DBG_IB_HEAPPTR);\n}\n#endif  /* DUK_USE_DEBUGGER_DUMPHEAP || DUK_USE_DEBUGGER_INSPECT */\n\nDUK_INTERNAL void duk_debug_write_hobject(duk_hthread *thr, duk_hobject *obj) {\n\tduk_uint8_t buf[3];\n\tduk__ptr_union pu;\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(sizeof(obj) >= 1 && sizeof(obj) <= 16);\n\tDUK_ASSERT(obj != NULL);\n\n\tbuf[0] = DUK_DBG_IB_OBJECT;\n\tbuf[1] = (duk_uint8_t) DUK_HOBJECT_GET_CLASS_NUMBER(obj);\n\tbuf[2] = sizeof(pu);\n\tduk_debug_write_bytes(thr, buf, 3);\n\tpu.p = (void *) obj;\n#if defined(DUK_USE_INTEGER_LE)\n\tduk_byteswap_bytes((duk_uint8_t *) pu.b, sizeof(pu));\n#endif\n\tduk_debug_write_bytes(thr, (const duk_uint8_t *) &pu.p, (duk_size_t) sizeof(pu));\n}\n\nDUK_INTERNAL void duk_debug_write_tval(duk_hthread *thr, duk_tval *tv) {\n\tduk_c_function lf_func;\n\tduk_small_uint_t lf_flags;\n\tduk_uint8_t buf[4];\n\tduk_double_union du1;\n\tduk_double_union du2;\n\tduk_int32_t i32;\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(tv != NULL);\n\n\tswitch (DUK_TVAL_GET_TAG(tv)) {\n\tcase DUK_TAG_UNDEFINED:\n\t\tduk_debug_write_byte(thr, DUK_DBG_IB_UNDEFINED);\n\t\tbreak;\n\tcase DUK_TAG_UNUSED:\n\t\tduk_debug_write_byte(thr, DUK_DBG_IB_UNUSED);\n\t\tbreak;\n\tcase DUK_TAG_NULL:\n\t\tduk_debug_write_byte(thr, DUK_DBG_IB_NULL);\n\t\tbreak;\n\tcase DUK_TAG_BOOLEAN:\n\t\tDUK_ASSERT(DUK_TVAL_GET_BOOLEAN(tv) == 0 ||\n\t\t           DUK_TVAL_GET_BOOLEAN(tv) == 1);\n\t\tduk_debug_write_boolean(thr, DUK_TVAL_GET_BOOLEAN(tv));\n\t\tbreak;\n\tcase DUK_TAG_POINTER:\n\t\tduk_debug_write_pointer(thr, (void *) DUK_TVAL_GET_POINTER(tv));\n\t\tbreak;\n\tcase DUK_TAG_LIGHTFUNC:\n\t\tDUK_TVAL_GET_LIGHTFUNC(tv, lf_func, lf_flags);\n\t\tbuf[0] = DUK_DBG_IB_LIGHTFUNC;\n\t\tbuf[1] = (duk_uint8_t) (lf_flags >> 8);\n\t\tbuf[2] = (duk_uint8_t) (lf_flags & 0xff);\n\t\tbuf[3] = sizeof(lf_func);\n\t\tduk_debug_write_bytes(thr, buf, 4);\n\t\tduk_debug_write_bytes(thr, (const duk_uint8_t *) &lf_func, sizeof(lf_func));\n\t\tbreak;\n\tcase DUK_TAG_STRING:\n\t\tduk_debug_write_hstring(thr, DUK_TVAL_GET_STRING(tv));\n\t\tbreak;\n\tcase DUK_TAG_OBJECT:\n\t\tduk_debug_write_hobject(thr, DUK_TVAL_GET_OBJECT(tv));\n\t\tbreak;\n\tcase DUK_TAG_BUFFER:\n\t\tduk_debug_write_hbuffer(thr, DUK_TVAL_GET_BUFFER(tv));\n\t\tbreak;\n#if defined(DUK_USE_FASTINT)\n\tcase DUK_TAG_FASTINT:\n#endif\n\tdefault:\n\t\t/* Numbers are normalized to big (network) endian.  We can\n\t\t * (but are not required) to use integer dvalues when there's\n\t\t * no loss of precision.\n\t\t *\n\t\t * XXX: share check with other code; this check is slow but\n\t\t * reliable and doesn't require careful exponent/mantissa\n\t\t * mask tricks as in the fastint downgrade code.\n\t\t */\n\t\tDUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));\n\t\tDUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));\n\t\tdu1.d = DUK_TVAL_GET_NUMBER(tv);\n\t\ti32 = (duk_int32_t) du1.d;\n\t\tdu2.d = (duk_double_t) i32;\n\n\t\tDUK_DD(DUK_DDPRINT(\"i32=%ld du1=%02x%02x%02x%02x%02x%02x%02x%02x \"\n\t\t                   \"du2=%02x%02x%02x%02x%02x%02x%02x%02x\",\n\t\t                   (long) i32,\n\t\t                   (unsigned int) du1.uc[0], (unsigned int) du1.uc[1],\n\t\t                   (unsigned int) du1.uc[2], (unsigned int) du1.uc[3],\n\t\t                   (unsigned int) du1.uc[4], (unsigned int) du1.uc[5],\n\t\t                   (unsigned int) du1.uc[6], (unsigned int) du1.uc[7],\n\t\t                   (unsigned int) du2.uc[0], (unsigned int) du2.uc[1],\n\t\t                   (unsigned int) du2.uc[2], (unsigned int) du2.uc[3],\n\t\t                   (unsigned int) du2.uc[4], (unsigned int) du2.uc[5],\n\t\t                   (unsigned int) du2.uc[6], (unsigned int) du2.uc[7]));\n\n\t\tif (DUK_MEMCMP((const void *) du1.uc, (const void *) du2.uc, sizeof(du1.uc)) == 0) {\n\t\t\tduk_debug_write_int(thr, i32);\n\t\t} else {\n\t\t\tDUK_DBLUNION_DOUBLE_HTON(&du1);\n\t\t\tduk_debug_write_byte(thr, DUK_DBG_IB_NUMBER);\n\t\t\tduk_debug_write_bytes(thr, (const duk_uint8_t *) du1.uc, sizeof(du1.uc));\n\t\t}\n\t}\n}\n\n#if defined(DUK_USE_DEBUGGER_DUMPHEAP)\n/* Variant for writing duk_tvals so that any heap allocated values are\n * written out as tagged heap pointers.\n */\nDUK_LOCAL void duk__debug_write_tval_heapptr(duk_hthread *thr, duk_tval *tv) {\n\tif (DUK_TVAL_IS_HEAP_ALLOCATED(tv)) {\n\t\tduk_heaphdr *h = DUK_TVAL_GET_HEAPHDR(tv);\n\t\tduk_debug_write_heapptr(thr, h);\n\t} else {\n\t\tduk_debug_write_tval(thr, tv);\n\t}\n}\n#endif  /* DUK_USE_DEBUGGER_DUMPHEAP */\n\n/*\n *  Debug connection message write helpers\n */\n\n#if 0  /* unused */\nDUK_INTERNAL void duk_debug_write_request(duk_hthread *thr, duk_small_uint_t command) {\n\tduk_debug_write_byte(thr, DUK_DBG_IB_REQUEST);\n\tduk_debug_write_int(thr, command);\n}\n#endif\n\nDUK_INTERNAL void duk_debug_write_reply(duk_hthread *thr) {\n\tduk_debug_write_byte(thr, DUK_DBG_IB_REPLY);\n}\n\nDUK_INTERNAL void duk_debug_write_error_eom(duk_hthread *thr, duk_small_uint_t err_code, const char *msg) {\n\t/* Allow NULL 'msg' */\n\tduk_debug_write_byte(thr, DUK_DBG_IB_ERROR);\n\tduk_debug_write_int(thr, (duk_int32_t) err_code);\n\tduk_debug_write_cstring(thr, msg);\n\tduk_debug_write_eom(thr);\n}\n\nDUK_INTERNAL void duk_debug_write_notify(duk_hthread *thr, duk_small_uint_t command) {\n\tduk_debug_write_byte(thr, DUK_DBG_IB_NOTIFY);\n\tduk_debug_write_int(thr, (duk_int32_t) command);\n}\n\nDUK_INTERNAL void duk_debug_write_eom(duk_hthread *thr) {\n\tduk_debug_write_byte(thr, DUK_DBG_IB_EOM);\n\n\t/* As an initial implementation, write flush after every EOM (and the\n\t * version identifier).  A better implementation would flush only when\n\t * Duktape is finished processing messages so that a flush only happens\n\t * after all outbound messages are finished on that occasion.\n\t */\n\tduk_debug_write_flush(thr);\n}\n\n/*\n *  Status message and helpers\n */\n\nDUK_INTERNAL duk_uint_fast32_t duk_debug_curr_line(duk_hthread *thr) {\n\tduk_activation *act;\n\tduk_uint_fast32_t line;\n\tduk_uint_fast32_t pc;\n\n\tact = thr->callstack_curr;\n\tif (act == NULL) {\n\t\treturn 0;\n\t}\n\n\t/* We're conceptually between two opcodes; act->pc indicates the next\n\t * instruction to be executed.  This is usually the correct pc/line to\n\t * indicate in Status.  (For the 'debugger' statement this now reports\n\t * the pc/line after the debugger statement because the debugger opcode\n\t * has already been executed.)\n\t */\n\n\tpc = duk_hthread_get_act_curr_pc(thr, act);\n\n\t/* XXX: this should be optimized to be a raw query and avoid valstack\n\t * operations if possible.\n\t */\n\tduk_push_tval(thr, &act->tv_func);\n\tline = duk_hobject_pc2line_query(thr, -1, pc);\n\tduk_pop(thr);\n\treturn line;\n}\n\nDUK_INTERNAL void duk_debug_send_status(duk_hthread *thr) {\n\tduk_activation *act;\n\n\tduk_debug_write_notify(thr, DUK_DBG_CMD_STATUS);\n\tduk_debug_write_int(thr, (DUK_HEAP_HAS_DEBUGGER_PAUSED(thr->heap) ? 1 : 0));\n\n\tact = thr->callstack_curr;\n\tif (act == NULL) {\n\t\tduk_debug_write_undefined(thr);\n\t\tduk_debug_write_undefined(thr);\n\t\tduk_debug_write_int(thr, 0);\n\t\tduk_debug_write_int(thr, 0);\n\t} else {\n\t\tduk_push_tval(thr, &act->tv_func);\n\t\tduk_get_prop_string(thr, -1, \"fileName\");\n\t\tduk__debug_write_hstring_safe_top(thr);\n\t\tduk_get_prop_string(thr, -2, \"name\");\n\t\tduk__debug_write_hstring_safe_top(thr);\n\t\tduk_pop_3(thr);\n\t\t/* Report next pc/line to be executed. */\n\t\tduk_debug_write_uint(thr, (duk_uint32_t) duk_debug_curr_line(thr));\n\t\tduk_debug_write_uint(thr, (duk_uint32_t) duk_hthread_get_act_curr_pc(thr, act));\n\t}\n\n\tduk_debug_write_eom(thr);\n}\n\n#if defined(DUK_USE_DEBUGGER_THROW_NOTIFY)\nDUK_INTERNAL void duk_debug_send_throw(duk_hthread *thr, duk_bool_t fatal) {\n\t/*\n\t *  NFY <int: 5> <int: fatal> <str: msg> <str: filename> <int: linenumber> EOM\n\t */\n\n\tduk_activation *act;\n\tduk_uint32_t pc;\n\n\tDUK_ASSERT(thr->valstack_top > thr->valstack);  /* At least: ... [err] */\n\n\tduk_debug_write_notify(thr, DUK_DBG_CMD_THROW);\n\tduk_debug_write_int(thr, (duk_int32_t) fatal);\n\n\t/* Report thrown value to client coerced to string */\n\tduk_dup_top(thr);\n\tduk__debug_write_hstring_safe_top(thr);\n\tduk_pop(thr);\n\n\tif (duk_is_error(thr, -1)) {\n\t\t/* Error instance, use augmented error data directly */\n\t\tduk_get_prop_stridx_short(thr, -1, DUK_STRIDX_FILE_NAME);\n\t\tduk__debug_write_hstring_safe_top(thr);\n\t\tduk_get_prop_stridx_short(thr, -2, DUK_STRIDX_LINE_NUMBER);\n\t\tduk_debug_write_uint(thr, duk_get_uint(thr, -1));\n\t\tduk_pop_2(thr);\n\t} else {\n\t\t/* For anything other than an Error instance, we calculate the\n\t\t * error location directly from the current activation if one\n\t\t * exists.\n\t\t */\n\t\tact = thr->callstack_curr;\n\t\tif (act != NULL) {\n\t\t\tduk_push_tval(thr, &act->tv_func);\n\t\t\tduk_get_prop_string(thr, -1, \"fileName\");\n\t\t\tduk__debug_write_hstring_safe_top(thr);\n\t\t\tpc = (duk_uint32_t) duk_hthread_get_act_prev_pc(thr, act);\n\t\t\tduk_debug_write_uint(thr, (duk_uint32_t) duk_hobject_pc2line_query(thr, -2, pc));\n\t\t\tduk_pop_2(thr);\n\t\t} else {\n\t\t\t/* Can happen if duk_throw() is called on an empty\n\t\t\t * callstack.\n\t\t\t */\n\t\t\tduk_debug_write_cstring(thr, \"\");\n\t\t\tduk_debug_write_uint(thr, 0);\n\t\t}\n\t}\n\n\tduk_debug_write_eom(thr);\n}\n#endif  /* DUK_USE_DEBUGGER_THROW_NOTIFY */\n\n/*\n *  Debug message processing\n */\n\n/* Skip dvalue. */\nDUK_LOCAL duk_bool_t duk__debug_skip_dvalue(duk_hthread *thr) {\n\tduk_uint8_t x;\n\tduk_uint32_t len;\n\n\tx = duk_debug_read_byte(thr);\n\n\tif (x >= 0xc0) {\n\t\tduk_debug_skip_byte(thr);\n\t\treturn 0;\n\t}\n\tif (x >= 0x80) {\n\t\treturn 0;\n\t}\n\tif (x >= 0x60) {\n\t\tduk_debug_skip_bytes(thr, (duk_size_t) (x - 0x60));\n\t\treturn 0;\n\t}\n\tswitch(x) {\n\tcase DUK_DBG_IB_EOM:\n\t\treturn 1;  /* Return 1: got EOM */\n\tcase DUK_DBG_IB_REQUEST:\n\tcase DUK_DBG_IB_REPLY:\n\tcase DUK_DBG_IB_ERROR:\n\tcase DUK_DBG_IB_NOTIFY:\n\t\tbreak;\n\tcase DUK_DBG_IB_INT4:\n\t\t(void) duk__debug_read_uint32_raw(thr);\n\t\tbreak;\n\tcase DUK_DBG_IB_STR4:\n\tcase DUK_DBG_IB_BUF4:\n\t\tlen = duk__debug_read_uint32_raw(thr);\n\t\tduk_debug_skip_bytes(thr, len);\n\t\tbreak;\n\tcase DUK_DBG_IB_STR2:\n\tcase DUK_DBG_IB_BUF2:\n\t\tlen = duk__debug_read_uint16_raw(thr);\n\t\tduk_debug_skip_bytes(thr, len);\n\t\tbreak;\n\tcase DUK_DBG_IB_UNUSED:\n\tcase DUK_DBG_IB_UNDEFINED:\n\tcase DUK_DBG_IB_NULL:\n\tcase DUK_DBG_IB_TRUE:\n\tcase DUK_DBG_IB_FALSE:\n\t\tbreak;\n\tcase DUK_DBG_IB_NUMBER:\n\t\tduk_debug_skip_bytes(thr, 8);\n\t\tbreak;\n\tcase DUK_DBG_IB_OBJECT:\n\t\tduk_debug_skip_byte(thr);\n\t\tlen = duk_debug_read_byte(thr);\n\t\tduk_debug_skip_bytes(thr, len);\n\t\tbreak;\n\tcase DUK_DBG_IB_POINTER:\n\tcase DUK_DBG_IB_HEAPPTR:\n\t\tlen = duk_debug_read_byte(thr);\n\t\tduk_debug_skip_bytes(thr, len);\n\t\tbreak;\n\tcase DUK_DBG_IB_LIGHTFUNC:\n\t\tduk_debug_skip_bytes(thr, 2);\n\t\tlen = duk_debug_read_byte(thr);\n\t\tduk_debug_skip_bytes(thr, len);\n\t\tbreak;\n\tdefault:\n\t\tgoto fail;\n\t}\n\n\treturn 0;\n\n fail:\n\tDUK__SET_CONN_BROKEN(thr, 1);\n\treturn 1;  /* Pretend like we got EOM */\n}\n\n/* Skip dvalues to EOM. */\nDUK_LOCAL void duk__debug_skip_to_eom(duk_hthread *thr) {\n\tfor (;;) {\n\t\tif (duk__debug_skip_dvalue(thr)) {\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\n/* Read and validate a call stack index.  If index is invalid, write out an\n * error message and return zero.\n */\nDUK_LOCAL duk_int32_t duk__debug_read_validate_csindex(duk_hthread *thr) {\n\tduk_int32_t level;\n\tlevel = duk_debug_read_int(thr);\n\tif (level >= 0 || -level > (duk_int32_t) thr->callstack_top) {\n\t\tduk_debug_write_error_eom(thr, DUK_DBG_ERR_NOTFOUND, \"invalid callstack index\");\n\t\treturn 0;  /* zero indicates failure */\n\t}\n\treturn level;\n}\n\n/* Read a call stack index and lookup the corresponding duk_activation.\n * If index is invalid, write out an error message and return NULL.\n */\nDUK_LOCAL duk_activation *duk__debug_read_level_get_activation(duk_hthread *thr) {\n\tduk_activation *act;\n\tduk_int32_t level;\n\n\tlevel = duk_debug_read_int(thr);\n\tact = duk_hthread_get_activation_for_level(thr, level);\n\tif (act == NULL) {\n\t\tduk_debug_write_error_eom(thr, DUK_DBG_ERR_NOTFOUND, \"invalid callstack index\");\n\t}\n\treturn act;\n}\n\n/*\n *  Simple commands\n */\n\nDUK_LOCAL void duk__debug_handle_basic_info(duk_hthread *thr, duk_heap *heap) {\n\tDUK_UNREF(heap);\n\tDUK_D(DUK_DPRINT(\"debug command Version\"));\n\n\tduk_debug_write_reply(thr);\n\tduk_debug_write_int(thr, DUK_VERSION);\n\tduk_debug_write_cstring(thr, DUK_GIT_DESCRIBE);\n\tduk_debug_write_cstring(thr, DUK_USE_TARGET_INFO);\n#if defined(DUK_USE_DOUBLE_LE)\n\tduk_debug_write_int(thr, 1);\n#elif defined(DUK_USE_DOUBLE_ME)\n\tduk_debug_write_int(thr, 2);\n#elif defined(DUK_USE_DOUBLE_BE)\n\tduk_debug_write_int(thr, 3);\n#else\n\tduk_debug_write_int(thr, 0);\n#endif\n\tduk_debug_write_int(thr, (duk_int_t) sizeof(void *));\n\tduk_debug_write_eom(thr);\n}\n\nDUK_LOCAL void duk__debug_handle_trigger_status(duk_hthread *thr, duk_heap *heap) {\n\tDUK_UNREF(heap);\n\tDUK_D(DUK_DPRINT(\"debug command TriggerStatus\"));\n\n\tduk_debug_write_reply(thr);\n\tduk_debug_write_eom(thr);\n\theap->dbg_state_dirty = 1;\n}\n\nDUK_LOCAL void duk__debug_handle_pause(duk_hthread *thr, duk_heap *heap) {\n\tDUK_D(DUK_DPRINT(\"debug command Pause\"));\n\tduk_debug_set_paused(heap);\n\tduk_debug_write_reply(thr);\n\tduk_debug_write_eom(thr);\n}\n\nDUK_LOCAL void duk__debug_handle_resume(duk_hthread *thr, duk_heap *heap) {\n\tduk_small_uint_t pause_flags;\n\n\tDUK_D(DUK_DPRINT(\"debug command Resume\"));\n\n\tduk_debug_clear_paused(heap);\n\n\tpause_flags = 0;\n#if 0  /* manual testing */\n\tpause_flags |= DUK_PAUSE_FLAG_ONE_OPCODE;\n\tpause_flags |= DUK_PAUSE_FLAG_CAUGHT_ERROR;\n\tpause_flags |= DUK_PAUSE_FLAG_UNCAUGHT_ERROR;\n#endif\n#if defined(DUK_USE_DEBUGGER_PAUSE_UNCAUGHT)\n\tpause_flags |= DUK_PAUSE_FLAG_UNCAUGHT_ERROR;\n#endif\n\n\tduk__debug_set_pause_state(thr, heap, pause_flags);\n\n\tduk_debug_write_reply(thr);\n\tduk_debug_write_eom(thr);\n}\n\nDUK_LOCAL void duk__debug_handle_step(duk_hthread *thr, duk_heap *heap, duk_int32_t cmd) {\n\tduk_small_uint_t pause_flags;\n\n\tDUK_D(DUK_DPRINT(\"debug command StepInto/StepOver/StepOut: %d\", (int) cmd));\n\n\tif (cmd == DUK_DBG_CMD_STEPINTO) {\n\t\tpause_flags = DUK_PAUSE_FLAG_LINE_CHANGE |\n\t\t              DUK_PAUSE_FLAG_FUNC_ENTRY |\n\t\t              DUK_PAUSE_FLAG_FUNC_EXIT;\n\t} else if (cmd == DUK_DBG_CMD_STEPOVER) {\n\t\tpause_flags = DUK_PAUSE_FLAG_LINE_CHANGE |\n\t\t              DUK_PAUSE_FLAG_FUNC_EXIT;\n\t} else {\n\t\tDUK_ASSERT(cmd == DUK_DBG_CMD_STEPOUT);\n\t\tpause_flags = DUK_PAUSE_FLAG_FUNC_EXIT;\n\t}\n#if defined(DUK_USE_DEBUGGER_PAUSE_UNCAUGHT)\n\tpause_flags |= DUK_PAUSE_FLAG_UNCAUGHT_ERROR;\n#endif\n\n\t/* If current activation doesn't have line information, line-based\n\t * pause flags are automatically disabled.  As a result, e.g.\n\t * StepInto will then pause on (native) function entry or exit.\n\t */\n\tduk_debug_clear_paused(heap);\n\tduk__debug_set_pause_state(thr, heap, pause_flags);\n\n\tduk_debug_write_reply(thr);\n\tduk_debug_write_eom(thr);\n}\n\nDUK_LOCAL void duk__debug_handle_list_break(duk_hthread *thr, duk_heap *heap) {\n\tduk_small_int_t i;\n\n\tDUK_D(DUK_DPRINT(\"debug command ListBreak\"));\n\tduk_debug_write_reply(thr);\n\tfor (i = 0; i < (duk_small_int_t) heap->dbg_breakpoint_count; i++) {\n\t\tduk_debug_write_hstring(thr, heap->dbg_breakpoints[i].filename);\n\t\tduk_debug_write_uint(thr, (duk_uint32_t) heap->dbg_breakpoints[i].line);\n\t}\n\tduk_debug_write_eom(thr);\n}\n\nDUK_LOCAL void duk__debug_handle_add_break(duk_hthread *thr, duk_heap *heap) {\n\tduk_hstring *filename;\n\tduk_uint32_t linenumber;\n\tduk_small_int_t idx;\n\n\tDUK_UNREF(heap);\n\n\tfilename = duk_debug_read_hstring(thr);\n\tlinenumber = (duk_uint32_t) duk_debug_read_int(thr);\n\tDUK_D(DUK_DPRINT(\"debug command AddBreak: %!O:%ld\", (duk_hobject *) filename, (long) linenumber));\n\tidx = duk_debug_add_breakpoint(thr, filename, linenumber);\n\tif (idx >= 0) {\n\t\tduk_debug_write_reply(thr);\n\t\tduk_debug_write_int(thr, (duk_int32_t) idx);\n\t\tduk_debug_write_eom(thr);\n\t} else {\n\t\tduk_debug_write_error_eom(thr, DUK_DBG_ERR_TOOMANY, \"no space for breakpoint\");\n\t}\n}\n\nDUK_LOCAL void duk__debug_handle_del_break(duk_hthread *thr, duk_heap *heap) {\n\tduk_small_uint_t idx;\n\n\tDUK_UNREF(heap);\n\n\tDUK_D(DUK_DPRINT(\"debug command DelBreak\"));\n\tidx = (duk_small_uint_t) duk_debug_read_int(thr);\n\tif (duk_debug_remove_breakpoint(thr, idx)) {\n\t\tduk_debug_write_reply(thr);\n\t\tduk_debug_write_eom(thr);\n\t} else {\n\t\tduk_debug_write_error_eom(thr, DUK_DBG_ERR_NOTFOUND, \"invalid breakpoint index\");\n\t}\n}\n\nDUK_LOCAL void duk__debug_handle_get_var(duk_hthread *thr, duk_heap *heap) {\n\tduk_activation *act;\n\tduk_hstring *str;\n\tduk_bool_t rc;\n\n\tDUK_UNREF(heap);\n\tDUK_D(DUK_DPRINT(\"debug command GetVar\"));\n\n\tact = duk__debug_read_level_get_activation(thr);\n\tif (act == NULL) {\n\t\treturn;\n\t}\n\tstr = duk_debug_read_hstring(thr);  /* push to stack */\n\tDUK_ASSERT(str != NULL);\n\n\trc = duk_js_getvar_activation(thr, act, str, 0);\n\n\tduk_debug_write_reply(thr);\n\tif (rc) {\n\t\tduk_debug_write_int(thr, 1);\n\t\tDUK_ASSERT(duk_get_tval(thr, -2) != NULL);\n\t\tduk_debug_write_tval(thr, duk_get_tval(thr, -2));\n\t} else {\n\t\tduk_debug_write_int(thr, 0);\n\t\tduk_debug_write_unused(thr);\n\t}\n\tduk_debug_write_eom(thr);\n}\n\nDUK_LOCAL void duk__debug_handle_put_var(duk_hthread *thr, duk_heap *heap) {\n\tduk_activation *act;\n\tduk_hstring *str;\n\tduk_tval *tv;\n\n\tDUK_UNREF(heap);\n\tDUK_D(DUK_DPRINT(\"debug command PutVar\"));\n\n\tact = duk__debug_read_level_get_activation(thr);\n\tif (act == NULL) {\n\t\treturn;\n\t}\n\tstr = duk_debug_read_hstring(thr);  /* push to stack */\n\tDUK_ASSERT(str != NULL);\n\ttv = duk_debug_read_tval(thr);\n\tif (tv == NULL) {\n\t\t/* detached */\n\t\treturn;\n\t}\n\n\tduk_js_putvar_activation(thr, act, str, tv, 0);\n\n\t/* XXX: Current putvar implementation doesn't have a success flag,\n\t * add one and send to debug client?\n\t */\n\tduk_debug_write_reply(thr);\n\tduk_debug_write_eom(thr);\n}\n\nDUK_LOCAL void duk__debug_handle_get_call_stack(duk_hthread *thr, duk_heap *heap) {\n\tduk_hthread *curr_thr = thr;\n\tduk_activation *curr_act;\n\tduk_uint_fast32_t pc;\n\tduk_uint_fast32_t line;\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_UNREF(heap);\n\n\tduk_debug_write_reply(thr);\n\twhile (curr_thr != NULL) {\n\t\tfor (curr_act = curr_thr->callstack_curr; curr_act != NULL; curr_act = curr_act->parent) {\n\t\t\t/* PC/line semantics here are:\n\t\t\t *   - For callstack top we're conceptually between two\n\t\t\t *     opcodes and current PC indicates next line to\n\t\t\t *     execute, so report that (matches Status).\n\t\t\t *   - For other activations we're conceptually still\n\t\t\t *     executing the instruction at PC-1, so report that\n\t\t\t *     (matches error stacktrace behavior).\n\t\t\t *   - See: https://github.com/svaarala/duktape/issues/281\n\t\t\t */\n\n\t\t\t/* XXX: optimize to use direct reads, i.e. avoid\n\t\t\t * value stack operations.\n\t\t\t */\n\t\t\tduk_push_tval(thr, &curr_act->tv_func);\n\t\t\tduk_get_prop_stridx_short(thr, -1, DUK_STRIDX_FILE_NAME);\n\t\t\tduk__debug_write_hstring_safe_top(thr);\n\t\t\tduk_get_prop_stridx_short(thr, -2, DUK_STRIDX_NAME);\n\t\t\tduk__debug_write_hstring_safe_top(thr);\n\t\t\tpc = duk_hthread_get_act_curr_pc(thr, curr_act);\n\t\t\tif (curr_act != curr_thr->callstack_curr && pc > 0) {\n\t\t\t\tpc--;\n\t\t\t}\n\t\t\tline = duk_hobject_pc2line_query(thr, -3, pc);\n\t\t\tduk_debug_write_uint(thr, (duk_uint32_t) line);\n\t\t\tduk_debug_write_uint(thr, (duk_uint32_t) pc);\n\t\t\tduk_pop_3(thr);\n\t\t}\n\t\tcurr_thr = curr_thr->resumer;\n\t}\n\t/* SCANBUILD: warning about 'thr' potentially being NULL here,\n\t * warning is incorrect because thr != NULL always here.\n\t */\n\tduk_debug_write_eom(thr);\n}\n\nDUK_LOCAL void duk__debug_handle_get_locals(duk_hthread *thr, duk_heap *heap) {\n\tduk_activation *act;\n\tduk_hstring *varname;\n\n\tDUK_UNREF(heap);\n\n\tact = duk__debug_read_level_get_activation(thr);\n\tif (act == NULL) {\n\t\treturn;\n\t}\n\n\tduk_debug_write_reply(thr);\n\n\t/* XXX: several nice-to-have improvements here:\n\t *   - Use direct reads avoiding value stack operations\n\t *   - Avoid triggering getters, indicate getter values to debug client\n\t *   - If side effects are possible, add error catching\n\t */\n\n\tduk_push_tval(thr, &act->tv_func);\n\tduk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INT_VARMAP);\n\tif (duk_is_object(thr, -1)) {\n\t\tduk_enum(thr, -1, 0 /*enum_flags*/);\n\t\twhile (duk_next(thr, -1 /*enum_index*/, 0 /*get_value*/)) {\n\t\t\tvarname = duk_known_hstring(thr, -1);\n\n\t\t\tduk_js_getvar_activation(thr, act, varname, 0 /*throw_flag*/);\n\t\t\t/* [ ... func varmap enum key value this ] */\n\t\t\tduk_debug_write_hstring(thr, duk_get_hstring(thr, -3));\n\t\t\tduk_debug_write_tval(thr, duk_get_tval(thr, -2));\n\t\t\tduk_pop_3(thr);  /* -> [ ... func varmap enum ] */\n\t\t}\n\t} else {\n\t\tDUK_D(DUK_DPRINT(\"varmap is not an object in GetLocals, ignore\"));\n\t}\n\n\tduk_debug_write_eom(thr);\n}\n\nDUK_LOCAL void duk__debug_handle_eval(duk_hthread *thr, duk_heap *heap) {\n\tduk_small_uint_t call_flags;\n\tduk_int_t call_ret;\n\tduk_small_int_t eval_err;\n\tduk_bool_t direct_eval;\n\tduk_int32_t level;\n\tduk_idx_t idx_func;\n\n\tDUK_UNREF(heap);\n\n\tDUK_D(DUK_DPRINT(\"debug command Eval\"));\n\n\t/* The eval code is executed within the lexical environment of a specified\n\t * activation.  For now, use global object eval() function, with the eval\n\t * considered a 'direct call to eval'.\n\t *\n\t * Callstack index for debug commands only affects scope -- the callstack\n\t * as seen by, e.g. Duktape.act() will be the same regardless.\n\t */\n\n\t/* nargs == 2 so we can pass a callstack index to eval(). */\n\tidx_func = duk_get_top(thr);\n\tduk_push_c_function(thr, duk_bi_global_object_eval, 2 /*nargs*/);\n\tduk_push_undefined(thr);  /* 'this' binding shouldn't matter here */\n\n\t/* Read callstack index, if non-null. */\n\tif (duk_debug_peek_byte(thr) == DUK_DBG_IB_NULL) {\n\t\tdirect_eval = 0;\n\t\tlevel = -1;  /* Not needed, but silences warning. */\n\t\t(void) duk_debug_read_byte(thr);\n\t} else {\n\t\tdirect_eval = 1;\n\t\tlevel = duk__debug_read_validate_csindex(thr);\n\t\tif (level == 0) {\n\t\t\treturn;\n\t\t}\n\t}\n\n\tDUK_ASSERT(!direct_eval ||\n\t           (level < 0 && -level <= (duk_int32_t) thr->callstack_top));\n\n\t(void) duk_debug_read_hstring(thr);\n\tif (direct_eval) {\n\t\tduk_push_int(thr, level - 1);  /* compensate for eval() call */\n\t}\n\n\t/* [ ... eval \"eval\" eval_input level? ] */\n\n\tcall_flags = 0;\n\tif (direct_eval) {\n\t\tduk_activation *act;\n\t\tduk_hobject *fun;\n\n\t\tact = duk_hthread_get_activation_for_level(thr, level);\n\t\tif (act != NULL) {\n\t\t\tfun = DUK_ACT_GET_FUNC(act);\n\t\t\tif (fun != NULL && DUK_HOBJECT_IS_COMPFUNC(fun)) {\n\t\t\t\t/* Direct eval requires that there's a current\n\t\t\t\t * activation and it is an Ecmascript function.\n\t\t\t\t * When Eval is executed from e.g. cooperate API\n\t\t\t\t * call we'll need to do an indirect eval instead.\n\t\t\t\t */\n\t\t\t\tcall_flags |= DUK_CALL_FLAG_DIRECT_EVAL;\n\t\t\t}\n\t\t}\n\t}\n\n\tcall_ret = duk_pcall_method_flags(thr, duk_get_top(thr) - (idx_func + 2), call_flags);\n\n\tif (call_ret == DUK_EXEC_SUCCESS) {\n\t\teval_err = 0;\n\t\t/* Use result value as is. */\n\t} else {\n\t\t/* For errors a string coerced result is most informative\n\t\t * right now, as the debug client doesn't have the capability\n\t\t * to traverse the error object.\n\t\t */\n\t\teval_err = 1;\n\t\tduk_safe_to_string(thr, -1);\n\t}\n\n\t/* [ ... result ] */\n\n\tduk_debug_write_reply(thr);\n\tduk_debug_write_int(thr, (duk_int32_t) eval_err);\n\tDUK_ASSERT(duk_get_tval(thr, -1) != NULL);\n\tduk_debug_write_tval(thr, duk_get_tval(thr, -1));\n\tduk_debug_write_eom(thr);\n}\n\nDUK_LOCAL void duk__debug_handle_detach(duk_hthread *thr, duk_heap *heap) {\n\tDUK_UNREF(heap);\n\tDUK_D(DUK_DPRINT(\"debug command Detach\"));\n\n\tduk_debug_write_reply(thr);\n\tduk_debug_write_eom(thr);\n\n\tDUK_D(DUK_DPRINT(\"debug connection detached, mark broken\"));\n\tDUK__SET_CONN_BROKEN(thr, 0);  /* not an error */\n}\n\nDUK_LOCAL void duk__debug_handle_apprequest(duk_hthread *thr, duk_heap *heap) {\n\tduk_idx_t old_top;\n\n\tDUK_D(DUK_DPRINT(\"debug command AppRequest\"));\n\n\told_top = duk_get_top(thr);  /* save stack top */\n\n\tif (heap->dbg_request_cb != NULL) {\n\t\tduk_idx_t nrets;\n\t\tduk_idx_t nvalues = 0;\n\t\tduk_idx_t top, idx;\n\n\t\t/* Read tvals from the message and push them onto the valstack,\n\t\t * then call the request callback to process the request.\n\t\t */\n\t\twhile (duk_debug_peek_byte(thr) != DUK_DBG_IB_EOM) {\n\t\t\tduk_tval *tv;\n\t\t\tif (!duk_check_stack(thr, 1)) {\n\t\t\t\tDUK_D(DUK_DPRINT(\"failed to allocate space for request dvalue(s)\"));\n\t\t\t\tgoto fail;\n\t\t\t}\n\t\t\ttv = duk_debug_read_tval(thr);  /* push to stack */\n\t\t\tif (tv == NULL) {\n\t\t\t\t/* detached */\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tnvalues++;\n\t\t}\n\t\tDUK_ASSERT(duk_get_top(thr) == old_top + nvalues);\n\n\t\t/* Request callback should push values for reply to client onto valstack */\n\t\tDUK_D(DUK_DPRINT(\"calling into AppRequest request_cb with nvalues=%ld, old_top=%ld, top=%ld\",\n\t\t                 (long) nvalues, (long) old_top, (long) duk_get_top(thr)));\n\t\tnrets = heap->dbg_request_cb(thr, heap->dbg_udata, nvalues);\n\t\tDUK_D(DUK_DPRINT(\"returned from AppRequest request_cb; nvalues=%ld -> nrets=%ld, old_top=%ld, top=%ld\",\n\t\t                 (long) nvalues, (long) nrets, (long) old_top, (long) duk_get_top(thr)));\n\t\tif (nrets >= 0) {\n\t\t\tDUK_ASSERT(duk_get_top(thr) >= old_top + nrets);\n\t\t\tif (duk_get_top(thr) < old_top + nrets) {\n\t\t\t\tDUK_D(DUK_DPRINT(\"AppRequest callback doesn't match value stack configuration, \"\n\t\t\t\t                 \"top=%ld < old_top=%ld + nrets=%ld; \"\n\t\t\t\t                 \"this might mean it's unsafe to continue!\",\n\t\t\t\t                 (long) duk_get_top(thr), (long) old_top, (long) nrets));\n\t\t\t\tgoto fail;\n\t\t\t}\n\n\t\t\t/* Reply with tvals pushed by request callback */\n\t\t\tduk_debug_write_byte(thr, DUK_DBG_IB_REPLY);\n\t\t\ttop = duk_get_top(thr);\n\t\t\tfor (idx = top - nrets; idx < top; idx++) {\n\t\t\t\tduk_debug_write_tval(thr, DUK_GET_TVAL_POSIDX(thr, idx));\n\t\t\t}\n\t\t\tduk_debug_write_eom(thr);\n\t\t} else {\n\t\t\tDUK_ASSERT(duk_get_top(thr) >= old_top + 1);\n\t\t\tif (duk_get_top(thr) < old_top + 1) {\n\t\t\t\tDUK_D(DUK_DPRINT(\"request callback return value doesn't match value stack configuration\"));\n\t\t\t\tgoto fail;\n\t\t\t}\n\t\t\tduk_debug_write_error_eom(thr, DUK_DBG_ERR_APPLICATION, duk_get_string(thr, -1));\n\t\t}\n\n\t\tduk_set_top(thr, old_top);  /* restore stack top */\n\t} else {\n\t\tDUK_D(DUK_DPRINT(\"no request callback, treat AppRequest as unsupported\"));\n\t\tduk_debug_write_error_eom(thr, DUK_DBG_ERR_UNSUPPORTED, \"AppRequest unsupported by target\");\n\t}\n\n\treturn;\n\n fail:\n\tduk_set_top(thr, old_top);  /* restore stack top */\n\tDUK__SET_CONN_BROKEN(thr, 1);\n}\n\n/*\n *  DumpHeap command\n */\n\n#if defined(DUK_USE_DEBUGGER_DUMPHEAP)\n/* XXX: this has some overlap with object inspection; remove this and make\n * DumpHeap return lists of heapptrs instead?\n */\nDUK_LOCAL void duk__debug_dump_heaphdr(duk_hthread *thr, duk_heap *heap, duk_heaphdr *hdr) {\n\tDUK_UNREF(heap);\n\n\tduk_debug_write_heapptr(thr, hdr);\n\tduk_debug_write_uint(thr, (duk_uint32_t) DUK_HEAPHDR_GET_TYPE(hdr));\n\tduk_debug_write_uint(thr, (duk_uint32_t) DUK_HEAPHDR_GET_FLAGS_RAW(hdr));\n#if defined(DUK_USE_REFERENCE_COUNTING)\n\tduk_debug_write_uint(thr, (duk_uint32_t) DUK_HEAPHDR_GET_REFCOUNT(hdr));\n#else\n\tduk_debug_write_int(thr, (duk_int32_t) -1);\n#endif\n\n\tswitch (DUK_HEAPHDR_GET_TYPE(hdr)) {\n\tcase DUK_HTYPE_STRING: {\n\t\tduk_hstring *h = (duk_hstring *) hdr;\n\n\t\tduk_debug_write_uint(thr, (duk_uint32_t) DUK_HSTRING_GET_BYTELEN(h));\n\t\tduk_debug_write_uint(thr, (duk_uint32_t) DUK_HSTRING_GET_CHARLEN(h));\n\t\tduk_debug_write_uint(thr, (duk_uint32_t) DUK_HSTRING_GET_HASH(h));\n\t\tduk_debug_write_hstring(thr, h);\n\t\tbreak;\n\t}\n\tcase DUK_HTYPE_OBJECT: {\n\t\tduk_hobject *h = (duk_hobject *) hdr;\n\t\tduk_hstring *k;\n\t\tduk_uint_fast32_t i;\n\n\t\tduk_debug_write_uint(thr, (duk_uint32_t) DUK_HOBJECT_GET_CLASS_NUMBER(h));\n\t\tduk_debug_write_heapptr(thr, (duk_heaphdr *) DUK_HOBJECT_GET_PROTOTYPE(heap, h));\n\t\tduk_debug_write_uint(thr, (duk_uint32_t) DUK_HOBJECT_GET_ESIZE(h));\n\t\tduk_debug_write_uint(thr, (duk_uint32_t) DUK_HOBJECT_GET_ENEXT(h));\n\t\tduk_debug_write_uint(thr, (duk_uint32_t) DUK_HOBJECT_GET_ASIZE(h));\n\t\tduk_debug_write_uint(thr, (duk_uint32_t) DUK_HOBJECT_GET_HSIZE(h));\n\n\t\tfor (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(h); i++) {\n\t\t\tduk_debug_write_uint(thr, (duk_uint32_t) DUK_HOBJECT_E_GET_FLAGS(heap, h, i));\n\t\t\tk = DUK_HOBJECT_E_GET_KEY(heap, h, i);\n\t\t\tduk_debug_write_heapptr(thr, (duk_heaphdr *) k);\n\t\t\tif (k == NULL) {\n\t\t\t\tduk_debug_write_int(thr, 0);  /* isAccessor */\n\t\t\t\tduk_debug_write_unused(thr);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (DUK_HOBJECT_E_SLOT_IS_ACCESSOR(heap, h, i)) {\n\t\t\t\tduk_debug_write_int(thr, 1);  /* isAccessor */\n\t\t\t\tduk_debug_write_heapptr(thr, (duk_heaphdr *) DUK_HOBJECT_E_GET_VALUE_PTR(heap, h, i)->a.get);\n\t\t\t\tduk_debug_write_heapptr(thr, (duk_heaphdr *) DUK_HOBJECT_E_GET_VALUE_PTR(heap, h, i)->a.set);\n\t\t\t} else {\n\t\t\t\tduk_debug_write_int(thr, 0);  /* isAccessor */\n\n\t\t\t\tduk__debug_write_tval_heapptr(thr, &DUK_HOBJECT_E_GET_VALUE_PTR(heap, h, i)->v);\n\t\t\t}\n\t\t}\n\n\t\tfor (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ASIZE(h); i++) {\n\t\t\t/* Note: array dump will include elements beyond\n\t\t\t * 'length'.\n\t\t\t */\n\t\t\tduk__debug_write_tval_heapptr(thr, DUK_HOBJECT_A_GET_VALUE_PTR(heap, h, i));\n\t\t}\n\t\tbreak;\n\t}\n\tcase DUK_HTYPE_BUFFER: {\n\t\tduk_hbuffer *h = (duk_hbuffer *) hdr;\n\n\t\tduk_debug_write_uint(thr, (duk_uint32_t) DUK_HBUFFER_GET_SIZE(h));\n\t\tduk_debug_write_buffer(thr, (const char *) DUK_HBUFFER_GET_DATA_PTR(heap, h), (duk_size_t) DUK_HBUFFER_GET_SIZE(h));\n\t\tbreak;\n\t}\n\tdefault: {\n\t\tDUK_D(DUK_DPRINT(\"invalid htype: %d\", (int) DUK_HEAPHDR_GET_TYPE(hdr)));\n\t}\n\t}\n}\n\nDUK_LOCAL void duk__debug_dump_heap_allocated(duk_hthread *thr, duk_heap *heap) {\n\tduk_heaphdr *hdr;\n\n\thdr = heap->heap_allocated;\n\twhile (hdr != NULL) {\n\t\tduk__debug_dump_heaphdr(thr, heap, hdr);\n\t\thdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);\n\t}\n}\n\nDUK_LOCAL void duk__debug_dump_strtab(duk_hthread *thr, duk_heap *heap) {\n\tduk_uint32_t i;\n\tduk_hstring *h;\n\n\tfor (i = 0; i < heap->st_size; i++) {\n#if defined(DUK_USE_STRTAB_PTRCOMP)\n\t\th = DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, heap->strtable16[i]);\n#else\n\t\th = heap->strtable[i];\n#endif\n\t\twhile (h != NULL) {\n\t\t\tduk__debug_dump_heaphdr(thr, heap, (duk_heaphdr *) h);\n\t\t\th = h->hdr.h_next;\n\t\t}\n\t}\n}\n\nDUK_LOCAL void duk__debug_handle_dump_heap(duk_hthread *thr, duk_heap *heap) {\n\tDUK_D(DUK_DPRINT(\"debug command DumpHeap\"));\n\n\tduk_debug_write_reply(thr);\n\tduk__debug_dump_heap_allocated(thr, heap);\n\tduk__debug_dump_strtab(thr, heap);\n\tduk_debug_write_eom(thr);\n}\n#endif  /* DUK_USE_DEBUGGER_DUMPHEAP */\n\nDUK_LOCAL void duk__debug_handle_get_bytecode(duk_hthread *thr, duk_heap *heap) {\n\tduk_activation *act;\n\tduk_hcompfunc *fun = NULL;\n\tduk_size_t i, n;\n\tduk_tval *tv;\n\tduk_hobject **fn;\n\tduk_int32_t level = -1;\n\tduk_uint8_t ibyte;\n\n\tDUK_UNREF(heap);\n\n\tDUK_D(DUK_DPRINT(\"debug command GetBytecode\"));\n\n\tibyte = duk_debug_peek_byte(thr);\n\tif (ibyte != DUK_DBG_IB_EOM) {\n\t\ttv = duk_debug_read_tval(thr);\n\t\tif (tv == NULL) {\n\t\t\t/* detached */\n\t\t\treturn;\n\t\t}\n\t\tif (DUK_TVAL_IS_OBJECT(tv)) {\n\t\t\t/* tentative, checked later */\n\t\t\tfun = (duk_hcompfunc *) DUK_TVAL_GET_OBJECT(tv);\n\t\t\tDUK_ASSERT(fun != NULL);\n\t\t} else if (DUK_TVAL_IS_NUMBER(tv)) {\n\t\t\tlevel = (duk_int32_t) DUK_TVAL_GET_NUMBER(tv);\n\t\t} else {\n\t\t\tDUK_D(DUK_DPRINT(\"invalid argument to GetBytecode: %!T\", tv));\n\t\t\tgoto fail_args;\n\t\t}\n\t}\n\n\tif (fun == NULL) {\n\t\tact = duk_hthread_get_activation_for_level(thr, level);\n\t\tif (act == NULL) {\n\t\t\tgoto fail_index;\n\t\t}\n\t\tfun = (duk_hcompfunc *) DUK_ACT_GET_FUNC(act);\n\t}\n\n\tif (fun == NULL || !DUK_HOBJECT_IS_COMPFUNC((duk_hobject *) fun)) {\n\t\tDUK_D(DUK_DPRINT(\"invalid argument to GetBytecode: %!O\", fun));\n\t\tgoto fail_args;\n\t}\n\tDUK_ASSERT(fun != NULL && DUK_HOBJECT_IS_COMPFUNC((duk_hobject *) fun));\n\n\tduk_debug_write_reply(thr);\n\tn = DUK_HCOMPFUNC_GET_CONSTS_COUNT(heap, fun);\n\tduk_debug_write_int(thr, (duk_int32_t) n);\n\ttv = DUK_HCOMPFUNC_GET_CONSTS_BASE(heap, fun);\n\tfor (i = 0; i < n; i++) {\n\t\tduk_debug_write_tval(thr, tv);\n\t\ttv++;\n\t}\n\tn = DUK_HCOMPFUNC_GET_FUNCS_COUNT(heap, fun);\n\tduk_debug_write_int(thr, (duk_int32_t) n);\n\tfn = DUK_HCOMPFUNC_GET_FUNCS_BASE(heap, fun);\n\tfor (i = 0; i < n; i++) {\n\t\tduk_debug_write_hobject(thr, *fn);\n\t\tfn++;\n\t}\n\tduk_debug_write_string(thr,\n\t                       (const char *) DUK_HCOMPFUNC_GET_CODE_BASE(heap, fun),\n\t                       (duk_size_t) DUK_HCOMPFUNC_GET_CODE_SIZE(heap, fun));\n\tduk_debug_write_eom(thr);\n\treturn;\n\n fail_args:\n\tduk_debug_write_error_eom(thr, DUK_DBG_ERR_UNKNOWN, \"invalid argument\");\n\treturn;\n\n fail_index:\n\tduk_debug_write_error_eom(thr, DUK_DBG_ERR_NOTFOUND, \"invalid callstack index\");\n\treturn;\n}\n\n/*\n *  Object inspection commands: GetHeapObjInfo, GetObjPropDesc,\n *  GetObjPropDescRange\n */\n\n#if defined(DUK_USE_DEBUGGER_INSPECT)\n\n#if 0 /* pruned */\nDUK_LOCAL const char * const duk__debug_getinfo_heaphdr_keys[] = {\n\t\"reachable\",\n\t\"temproot\",\n\t\"finalizable\",\n\t\"finalized\",\n\t\"readonly\"\n\t/* NULL not needed here */\n};\nDUK_LOCAL duk_uint_t duk__debug_getinfo_heaphdr_masks[] = {\n\tDUK_HEAPHDR_FLAG_REACHABLE,\n\tDUK_HEAPHDR_FLAG_TEMPROOT,\n\tDUK_HEAPHDR_FLAG_FINALIZABLE,\n\tDUK_HEAPHDR_FLAG_FINALIZED,\n\tDUK_HEAPHDR_FLAG_READONLY,\n\t0  /* terminator */\n};\n#endif\nDUK_LOCAL const char * const duk__debug_getinfo_hstring_keys[] = {\n#if 0\n\t\"arridx\",\n\t\"symbol\",\n\t\"hidden\",\n\t\"reserved_word\",\n\t\"strict_reserved_word\",\n\t\"eval_or_arguments\",\n#endif\n\t\"extdata\"\n\t/* NULL not needed here */\n};\nDUK_LOCAL duk_uint_t duk__debug_getinfo_hstring_masks[] = {\n#if 0\n\tDUK_HSTRING_FLAG_ARRIDX,\n\tDUK_HSTRING_FLAG_SYMBOL,\n\tDUK_HSTRING_FLAG_HIDDEN,\n\tDUK_HSTRING_FLAG_RESERVED_WORD,\n\tDUK_HSTRING_FLAG_STRICT_RESERVED_WORD,\n\tDUK_HSTRING_FLAG_EVAL_OR_ARGUMENTS,\n#endif\n\tDUK_HSTRING_FLAG_EXTDATA,\n\t0  /* terminator */\n};\nDUK_LOCAL const char * const duk__debug_getinfo_hobject_keys[] = {\n\t\"extensible\",\n\t\"constructable\",\n\t\"callable\",\n\t\"boundfunc\",\n\t\"compfunc\",\n\t\"natfunc\",\n\t\"bufobj\",\n\t\"fastrefs\",\n\t\"array_part\",\n\t\"strict\",\n\t\"notail\",\n\t\"newenv\",\n\t\"namebinding\",\n\t\"createargs\",\n\t\"have_finalizer\",\n\t\"exotic_array\",\n\t\"exotic_stringobj\",\n\t\"exotic_arguments\",\n\t\"exotic_proxyobj\",\n\t\"special_call\"\n\t/* NULL not needed here */\n};\nDUK_LOCAL duk_uint_t duk__debug_getinfo_hobject_masks[] = {\n\tDUK_HOBJECT_FLAG_EXTENSIBLE,\n\tDUK_HOBJECT_FLAG_CONSTRUCTABLE,\n\tDUK_HOBJECT_FLAG_CALLABLE,\n\tDUK_HOBJECT_FLAG_BOUNDFUNC,\n\tDUK_HOBJECT_FLAG_COMPFUNC,\n\tDUK_HOBJECT_FLAG_NATFUNC,\n\tDUK_HOBJECT_FLAG_BUFOBJ,\n\tDUK_HOBJECT_FLAG_FASTREFS,\n\tDUK_HOBJECT_FLAG_ARRAY_PART,\n\tDUK_HOBJECT_FLAG_STRICT,\n\tDUK_HOBJECT_FLAG_NOTAIL,\n\tDUK_HOBJECT_FLAG_NEWENV,\n\tDUK_HOBJECT_FLAG_NAMEBINDING,\n\tDUK_HOBJECT_FLAG_CREATEARGS,\n\tDUK_HOBJECT_FLAG_HAVE_FINALIZER,\n\tDUK_HOBJECT_FLAG_EXOTIC_ARRAY,\n\tDUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ,\n\tDUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS,\n\tDUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ,\n\tDUK_HOBJECT_FLAG_SPECIAL_CALL,\n\t0  /* terminator */\n};\nDUK_LOCAL const char * const duk__debug_getinfo_hbuffer_keys[] = {\n\t\"dynamic\",\n\t\"external\"\n\t/* NULL not needed here */\n};\nDUK_LOCAL duk_uint_t duk__debug_getinfo_hbuffer_masks[] = {\n\tDUK_HBUFFER_FLAG_DYNAMIC,\n\tDUK_HBUFFER_FLAG_EXTERNAL,\n\t0  /* terminator */\n};\n\nDUK_LOCAL void duk__debug_getinfo_flags_key(duk_hthread *thr, const char *key) {\n\tduk_debug_write_uint(thr, 0);\n\tduk_debug_write_cstring(thr, key);\n}\n\nDUK_LOCAL void duk__debug_getinfo_prop_uint(duk_hthread *thr, const char *key, duk_uint_t val) {\n\tduk_debug_write_uint(thr, 0);\n\tduk_debug_write_cstring(thr, key);\n\tduk_debug_write_uint(thr, val);\n}\n\nDUK_LOCAL void duk__debug_getinfo_prop_int(duk_hthread *thr, const char *key, duk_int_t val) {\n\tduk_debug_write_uint(thr, 0);\n\tduk_debug_write_cstring(thr, key);\n\tduk_debug_write_int(thr, val);\n}\n\nDUK_LOCAL void duk__debug_getinfo_prop_bool(duk_hthread *thr, const char *key, duk_bool_t val) {\n\tduk_debug_write_uint(thr, 0);\n\tduk_debug_write_cstring(thr, key);\n\tduk_debug_write_boolean(thr, val);\n}\n\nDUK_LOCAL void duk__debug_getinfo_bitmask(duk_hthread *thr, const char * const * keys, duk_uint_t *masks, duk_uint_t flags) {\n\tconst char *key;\n\tduk_uint_t mask;\n\n\tfor (;;) {\n\t\tmask = *masks++;\n\t\tif (mask == 0) {\n\t\t\tbreak;\n\t\t}\n\t\tkey = *keys++;\n\t\tDUK_ASSERT(key != NULL);\n\n\t\tDUK_DD(DUK_DDPRINT(\"inspect bitmask: key=%s, mask=0x%08lx, flags=0x%08lx\", key, (unsigned long) mask, (unsigned long) flags));\n\t\tduk__debug_getinfo_prop_bool(thr, key, flags & mask);\n\t}\n}\n\n/* Inspect a property using a virtual index into a conceptual property list\n * consisting of (1) all array part items from [0,a_size[ (even when above\n * .length) and (2) all entry part items from [0,e_next[.  Unused slots are\n * indicated using dvalue 'unused'.\n */\nDUK_LOCAL duk_bool_t duk__debug_getprop_index(duk_hthread *thr, duk_heap *heap, duk_hobject *h_obj, duk_uint_t idx) {\n\tduk_uint_t a_size;\n\tduk_tval *tv;\n\tduk_hstring *h_key;\n\tduk_hobject *h_getset;\n\tduk_uint_t flags;\n\n\tDUK_UNREF(heap);\n\n\ta_size = DUK_HOBJECT_GET_ASIZE(h_obj);\n\tif (idx < a_size) {\n\t\tduk_debug_write_uint(thr, DUK_PROPDESC_FLAGS_WEC);\n\t\tduk_debug_write_uint(thr, idx);\n\t\ttv = DUK_HOBJECT_A_GET_VALUE_PTR(heap, h_obj, idx);\n\t\tduk_debug_write_tval(thr, tv);\n\t\treturn 1;\n\t}\n\n\tidx -= a_size;\n\tif (idx >= DUK_HOBJECT_GET_ENEXT(h_obj)) {\n\t\treturn 0;\n\t}\n\n\th_key = DUK_HOBJECT_E_GET_KEY(heap, h_obj, idx);\n\tif (h_key == NULL) {\n\t\tduk_debug_write_uint(thr, 0);\n\t\tduk_debug_write_null(thr);\n\t\tduk_debug_write_unused(thr);\n\t\treturn 1;\n\t}\n\n\tflags = DUK_HOBJECT_E_GET_FLAGS(heap, h_obj, idx);\n\tif (DUK_HSTRING_HAS_SYMBOL(h_key)) {\n\t\tflags |= DUK_DBG_PROPFLAG_SYMBOL;\n\t}\n\tif (DUK_HSTRING_HAS_HIDDEN(h_key)) {\n\t\tflags |= DUK_DBG_PROPFLAG_HIDDEN;\n\t}\n\tduk_debug_write_uint(thr, flags);\n\tduk_debug_write_hstring(thr, h_key);\n\tif (flags & DUK_PROPDESC_FLAG_ACCESSOR) {\n\t\th_getset = DUK_HOBJECT_E_GET_VALUE_GETTER(heap, h_obj, idx);\n\t\tif (h_getset) {\n\t\t\tduk_debug_write_hobject(thr, h_getset);\n\t\t} else {\n\t\t\tduk_debug_write_null(thr);\n\t\t}\n\t\th_getset = DUK_HOBJECT_E_GET_VALUE_SETTER(heap, h_obj, idx);\n\t\tif (h_getset) {\n\t\t\tduk_debug_write_hobject(thr, h_getset);\n\t\t} else {\n\t\t\tduk_debug_write_null(thr);\n\t\t}\n\t} else {\n\t\ttv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(heap, h_obj, idx);\n\t\tduk_debug_write_tval(thr, tv);\n\t}\n\treturn 1;\n}\n\nDUK_LOCAL void duk__debug_handle_get_heap_obj_info(duk_hthread *thr, duk_heap *heap) {\n\tduk_heaphdr *h;\n\n\tDUK_D(DUK_DPRINT(\"debug command GetHeapObjInfo\"));\n\tDUK_UNREF(heap);\n\n\tDUK_ASSERT(sizeof(duk__debug_getinfo_hstring_keys) / sizeof(const char *) == sizeof(duk__debug_getinfo_hstring_masks) / sizeof(duk_uint_t) - 1);\n\tDUK_ASSERT(sizeof(duk__debug_getinfo_hobject_keys) / sizeof(const char *) == sizeof(duk__debug_getinfo_hobject_masks) / sizeof(duk_uint_t) - 1);\n\tDUK_ASSERT(sizeof(duk__debug_getinfo_hbuffer_keys) / sizeof(const char *) == sizeof(duk__debug_getinfo_hbuffer_masks) / sizeof(duk_uint_t) - 1);\n\n\th = duk_debug_read_any_ptr(thr);\n\tif (!h) {\n\t\tduk_debug_write_error_eom(thr, DUK_DBG_ERR_UNKNOWN, \"invalid target\");\n\t\treturn;\n\t}\n\n\tduk_debug_write_reply(thr);\n\n\t/* As with all inspection code, we rely on the debug client providing\n\t * a valid, non-stale pointer: there's no portable way to safely\n\t * validate the pointer here.\n\t */\n\n\tduk__debug_getinfo_flags_key(thr, \"heapptr\");\n\tduk_debug_write_heapptr(thr, h);\n\n\t/* XXX: comes out as signed now */\n\tduk__debug_getinfo_prop_uint(thr, \"heaphdr_flags\", (duk_uint_t) DUK_HEAPHDR_GET_FLAGS(h));\n\tduk__debug_getinfo_prop_uint(thr, \"heaphdr_type\", (duk_uint_t) DUK_HEAPHDR_GET_TYPE(h));\n#if defined(DUK_USE_REFERENCE_COUNTING)\n\tduk__debug_getinfo_prop_uint(thr, \"refcount\", (duk_uint_t) DUK_HEAPHDR_GET_REFCOUNT(h));\n#endif\n#if 0 /* pruned */\n\tduk__debug_getinfo_bitmask(thr,\n\t                           duk__debug_getinfo_heaphdr_keys,\n\t                           duk__debug_getinfo_heaphdr_masks,\n\t                           DUK_HEAPHDR_GET_FLAGS_RAW(h));\n#endif\n\n\tswitch (DUK_HEAPHDR_GET_TYPE(h)) {\n\tcase DUK_HTYPE_STRING: {\n\t\tduk_hstring *h_str;\n\n\t\th_str = (duk_hstring *) h;\n\t\tduk__debug_getinfo_bitmask(thr,\n\t\t                           duk__debug_getinfo_hstring_keys,\n\t\t                           duk__debug_getinfo_hstring_masks,\n\t\t                           DUK_HEAPHDR_GET_FLAGS_RAW(h));\n\t\tduk__debug_getinfo_prop_uint(thr, \"bytelen\", (duk_uint_t) DUK_HSTRING_GET_BYTELEN(h_str));\n\t\tduk__debug_getinfo_prop_uint(thr, \"charlen\", (duk_uint_t) DUK_HSTRING_GET_CHARLEN(h_str));\n\t\tduk__debug_getinfo_prop_uint(thr, \"hash\", (duk_uint_t) DUK_HSTRING_GET_HASH(h_str));\n\t\tduk__debug_getinfo_flags_key(thr, \"data\");\n\t\tduk_debug_write_hstring(thr, h_str);\n\t\tbreak;\n\t}\n\tcase DUK_HTYPE_OBJECT: {\n\t\tduk_hobject *h_obj;\n\t\tduk_hobject *h_proto;\n\n\t\th_obj = (duk_hobject *) h;\n\t\th_proto = DUK_HOBJECT_GET_PROTOTYPE(heap, h_obj);\n\n\t\t/* duk_hobject specific fields. */\n\t\tduk__debug_getinfo_bitmask(thr,\n\t\t                           duk__debug_getinfo_hobject_keys,\n\t\t                           duk__debug_getinfo_hobject_masks,\n\t\t                           DUK_HEAPHDR_GET_FLAGS_RAW(h));\n\t\tduk__debug_getinfo_prop_uint(thr, \"class_number\", DUK_HOBJECT_GET_CLASS_NUMBER(h_obj));\n\t\tduk__debug_getinfo_flags_key(thr, \"class_name\");\n\t\tduk_debug_write_hstring(thr, DUK_HOBJECT_GET_CLASS_STRING(heap, h_obj));\n\t\tduk__debug_getinfo_flags_key(thr, \"prototype\");\n\t\tif (h_proto != NULL) {\n\t\t\tduk_debug_write_hobject(thr, h_proto);\n\t\t} else {\n\t\t\tduk_debug_write_null(thr);\n\t\t}\n\t\tduk__debug_getinfo_flags_key(thr, \"props\");\n\t\tduk_debug_write_pointer(thr, (void *) DUK_HOBJECT_GET_PROPS(heap, h_obj));\n\t\tduk__debug_getinfo_prop_uint(thr, \"e_size\", (duk_uint_t) DUK_HOBJECT_GET_ESIZE(h_obj));\n\t\tduk__debug_getinfo_prop_uint(thr, \"e_next\", (duk_uint_t) DUK_HOBJECT_GET_ENEXT(h_obj));\n\t\tduk__debug_getinfo_prop_uint(thr, \"a_size\", (duk_uint_t) DUK_HOBJECT_GET_ASIZE(h_obj));\n\t\tduk__debug_getinfo_prop_uint(thr, \"h_size\", (duk_uint_t) DUK_HOBJECT_GET_HSIZE(h_obj));\n\n\t\tif (DUK_HOBJECT_IS_ARRAY(h_obj)) {\n\t\t\tduk_harray *h_arr;\n\t\t\th_arr = (duk_harray *) h_obj;\n\n\t\t\tduk__debug_getinfo_prop_uint(thr, \"length\", (duk_uint_t) h_arr->length);\n\t\t\tduk__debug_getinfo_prop_bool(thr, \"length_nonwritable\", h_arr->length_nonwritable);\n\t\t}\n\n\t\tif (DUK_HOBJECT_IS_NATFUNC(h_obj)) {\n\t\t\tduk_hnatfunc *h_fun;\n\t\t\th_fun = (duk_hnatfunc *) h_obj;\n\n\t\t\tduk__debug_getinfo_prop_int(thr, \"nargs\", h_fun->nargs);\n\t\t\tduk__debug_getinfo_prop_int(thr, \"magic\", h_fun->magic);\n\t\t\tduk__debug_getinfo_prop_bool(thr, \"varargs\", h_fun->magic == DUK_HNATFUNC_NARGS_VARARGS);\n\t\t\t/* Native function pointer may be different from a void pointer,\n\t\t\t * and we serialize it from memory directly now (no byte swapping etc).\n\t\t\t */\n\t\t\tduk__debug_getinfo_flags_key(thr, \"funcptr\");\n\t\t\tduk_debug_write_buffer(thr, (const char *) &h_fun->func, sizeof(h_fun->func));\n\t\t}\n\n\t\tif (DUK_HOBJECT_IS_COMPFUNC(h_obj)) {\n\t\t\tduk_hcompfunc *h_fun;\n\t\t\tduk_hbuffer *h_buf;\n\t\t\tduk_hobject *h_lexenv;\n\t\t\tduk_hobject *h_varenv;\n\t\t\th_fun = (duk_hcompfunc *) h_obj;\n\n\t\t\tduk__debug_getinfo_prop_int(thr, \"nregs\", h_fun->nregs);\n\t\t\tduk__debug_getinfo_prop_int(thr, \"nargs\", h_fun->nargs);\n\n\t\t\tduk__debug_getinfo_flags_key(thr, \"lex_env\");\n\t\t\th_lexenv = DUK_HCOMPFUNC_GET_LEXENV(thr->heap, h_fun);\n\t\t\tif (h_lexenv != NULL) {\n\t\t\t\tduk_debug_write_hobject(thr, h_lexenv);\n\t\t\t} else {\n\t\t\t\tduk_debug_write_null(thr);\n\t\t\t}\n\t\t\tduk__debug_getinfo_flags_key(thr, \"var_env\");\n\t\t\th_varenv = DUK_HCOMPFUNC_GET_VARENV(thr->heap, h_fun);\n\t\t\tif (h_varenv != NULL) {\n\t\t\t\tduk_debug_write_hobject(thr, h_varenv);\n\t\t\t} else {\n\t\t\t\tduk_debug_write_null(thr);\n\t\t\t}\n\n\t\t\tduk__debug_getinfo_prop_uint(thr, \"start_line\", h_fun->start_line);\n\t\t\tduk__debug_getinfo_prop_uint(thr, \"end_line\", h_fun->end_line);\n\t\t\th_buf = (duk_hbuffer *) DUK_HCOMPFUNC_GET_DATA(thr->heap, h_fun);\n\t\t\tif (h_buf != NULL) {\n\t\t\t\tduk__debug_getinfo_flags_key(thr, \"data\");\n\t\t\t\tduk_debug_write_heapptr(thr, (duk_heaphdr *) h_buf);\n\t\t\t}\n\t\t}\n\n\t\tif (DUK_HOBJECT_IS_BOUNDFUNC(h_obj)) {\n\t\t\tduk_hboundfunc *h_bfun;\n\t\t\th_bfun = (duk_hboundfunc *) h_obj;\n\n\t\t\tduk__debug_getinfo_flags_key(thr, \"target\");\n\t\t\tduk_debug_write_tval(thr, &h_bfun->target);\n\t\t\tduk__debug_getinfo_flags_key(thr, \"this_binding\");\n\t\t\tduk_debug_write_tval(thr, &h_bfun->this_binding);\n\t\t\tduk__debug_getinfo_flags_key(thr, \"nargs\");\n\t\t\tduk_debug_write_int(thr, h_bfun->nargs);\n\t\t\t/* h_bfun->args not exposed now */\n\t\t}\n\n\t\tif (DUK_HOBJECT_IS_THREAD(h_obj)) {\n\t\t\t/* XXX: Currently no inspection of threads, e.g. value stack, call\n\t\t\t * stack, catch stack, etc.\n\t\t\t */\n\t\t\tduk_hthread *h_thr;\n\t\t\th_thr = (duk_hthread *) h_obj;\n\t\t\tDUK_UNREF(h_thr);\n\t\t}\n\n\t\tif (DUK_HOBJECT_IS_DECENV(h_obj)) {\n\t\t\tduk_hdecenv *h_env;\n\t\t\th_env = (duk_hdecenv *) h_obj;\n\n\t\t\tduk__debug_getinfo_flags_key(thr, \"thread\");\n\t\t\tduk_debug_write_heapptr(thr, (duk_heaphdr *) (h_env->thread));\n\t\t\tduk__debug_getinfo_flags_key(thr, \"varmap\");\n\t\t\tduk_debug_write_heapptr(thr, (duk_heaphdr *) (h_env->varmap));\n\t\t\tduk__debug_getinfo_prop_uint(thr, \"regbase\", (duk_uint_t) h_env->regbase_byteoff);\n\t\t}\n\n\t\tif (DUK_HOBJECT_IS_OBJENV(h_obj)) {\n\t\t\tduk_hobjenv *h_env;\n\t\t\th_env = (duk_hobjenv *) h_obj;\n\n\t\t\tduk__debug_getinfo_flags_key(thr, \"target\");\n\t\t\tduk_debug_write_heapptr(thr, (duk_heaphdr *) (h_env->target));\n\t\t\tduk__debug_getinfo_prop_bool(thr, \"has_this\", h_env->has_this);\n\t\t}\n\n#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)\n\t\tif (DUK_HOBJECT_IS_BUFOBJ(h_obj)) {\n\t\t\tduk_hbufobj *h_bufobj;\n\t\t\th_bufobj = (duk_hbufobj *) h_obj;\n\n\t\t\tduk__debug_getinfo_prop_uint(thr, \"slice_offset\", h_bufobj->offset);\n\t\t\tduk__debug_getinfo_prop_uint(thr, \"slice_length\", h_bufobj->length);\n\t\t\tduk__debug_getinfo_prop_uint(thr, \"elem_shift\", (duk_uint_t) h_bufobj->shift);\n\t\t\tduk__debug_getinfo_prop_uint(thr, \"elem_type\", (duk_uint_t) h_bufobj->elem_type);\n\t\t\tduk__debug_getinfo_prop_bool(thr, \"is_typedarray\", (duk_uint_t) h_bufobj->is_typedarray);\n\t\t\tif (h_bufobj->buf != NULL) {\n\t\t\t\tduk__debug_getinfo_flags_key(thr, \"buffer\");\n\t\t\t\tduk_debug_write_heapptr(thr, (duk_heaphdr *) h_bufobj->buf);\n\t\t\t}\n\t\t}\n#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */\n\t\tbreak;\n\t}\n\tcase DUK_HTYPE_BUFFER: {\n\t\tduk_hbuffer *h_buf;\n\n\t\th_buf = (duk_hbuffer *) h;\n\t\tduk__debug_getinfo_bitmask(thr,\n\t\t                           duk__debug_getinfo_hbuffer_keys,\n\t\t                           duk__debug_getinfo_hbuffer_masks,\n\t\t                           DUK_HEAPHDR_GET_FLAGS_RAW(h));\n\t\tduk__debug_getinfo_prop_uint(thr, \"size\", (duk_uint_t) DUK_HBUFFER_GET_SIZE(h_buf));\n\t\tduk__debug_getinfo_flags_key(thr, \"dataptr\");\n\t\tduk_debug_write_pointer(thr, (void *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_buf));\n\t\tduk__debug_getinfo_flags_key(thr, \"data\");\n\t\tduk_debug_write_hbuffer(thr, h_buf);  /* tolerates NULL h_buf */\n\t\tbreak;\n\t}\n\tdefault: {\n\t\t/* Since we already started writing the reply, just emit nothing. */\n\t\tDUK_D(DUK_DPRINT(\"inspect target pointer has invalid heaphdr type\"));\n\t}\n\t}\n\n\tduk_debug_write_eom(thr);\n}\n\nDUK_LOCAL void duk__debug_handle_get_obj_prop_desc(duk_hthread *thr, duk_heap *heap) {\n\tduk_heaphdr *h;\n\tduk_hobject *h_obj;\n\tduk_hstring *h_key;\n\tduk_propdesc desc;\n\n\tDUK_D(DUK_DPRINT(\"debug command GetObjPropDesc\"));\n\tDUK_UNREF(heap);\n\n\th = duk_debug_read_any_ptr(thr);\n\tif (!h) {\n\t\tduk_debug_write_error_eom(thr, DUK_DBG_ERR_UNKNOWN, \"invalid target\");\n\t\treturn;\n\t}\n\th_key = duk_debug_read_hstring(thr);\n\tif (h == NULL || DUK_HEAPHDR_GET_TYPE(h) != DUK_HTYPE_OBJECT || h_key == NULL) {\n\t\tgoto fail_args;\n\t}\n\th_obj = (duk_hobject *) h;\n\n\tif (duk_hobject_get_own_propdesc(thr, h_obj, h_key, &desc, 0 /*flags*/)) {\n\t\tduk_int_t virtual_idx;\n\t\tduk_bool_t rc;\n\n\t\t/* To use the shared helper need the virtual index. */\n\t\tDUK_ASSERT(desc.e_idx >= 0 || desc.a_idx >= 0);\n\t\tvirtual_idx = (desc.a_idx >= 0 ? desc.a_idx :\n\t\t               (duk_int_t) DUK_HOBJECT_GET_ASIZE(h_obj) + desc.e_idx);\n\n\t\tduk_debug_write_reply(thr);\n\t\trc = duk__debug_getprop_index(thr, heap, h_obj, (duk_uint_t) virtual_idx);\n\t\tDUK_ASSERT(rc == 1);\n\t\tDUK_UNREF(rc);\n\t\tduk_debug_write_eom(thr);\n\t} else {\n\t\tduk_debug_write_error_eom(thr, DUK_DBG_ERR_NOTFOUND, \"not found\");\n\t}\n\treturn;\n\n fail_args:\n\tduk_debug_write_error_eom(thr, DUK_DBG_ERR_UNKNOWN, \"invalid args\");\n}\n\nDUK_LOCAL void duk__debug_handle_get_obj_prop_desc_range(duk_hthread *thr, duk_heap *heap) {\n\tduk_heaphdr *h;\n\tduk_hobject *h_obj;\n\tduk_uint_t idx, idx_start, idx_end;\n\n\tDUK_D(DUK_DPRINT(\"debug command GetObjPropDescRange\"));\n\tDUK_UNREF(heap);\n\n\th = duk_debug_read_any_ptr(thr);\n\tidx_start = (duk_uint_t) duk_debug_read_int(thr);\n\tidx_end = (duk_uint_t) duk_debug_read_int(thr);\n\tif (h == NULL || DUK_HEAPHDR_GET_TYPE(h) != DUK_HTYPE_OBJECT) {\n\t\tgoto fail_args;\n\t}\n\th_obj = (duk_hobject *) h;\n\n\t/* The index range space is conceptually the array part followed by the\n\t * entry part.  Unlike normal enumeration all slots are exposed here as\n\t * is and return 'unused' if the slots are not in active use.  In particular\n\t * the array part is included for the full a_size regardless of what the\n\t * array .length is.\n\t */\n\n\tduk_debug_write_reply(thr);\n\tfor (idx = idx_start; idx < idx_end; idx++) {\n\t\tif (!duk__debug_getprop_index(thr, heap, h_obj, idx)) {\n\t\t\tbreak;\n\t\t}\n\t}\n\tduk_debug_write_eom(thr);\n\treturn;\n\n fail_args:\n\tduk_debug_write_error_eom(thr, DUK_DBG_ERR_UNKNOWN, \"invalid args\");\n}\n\n#endif  /* DUK_USE_DEBUGGER_INSPECT */\n\n/*\n *  Process incoming debug requests\n *\n *  Individual request handlers can push temporaries on the value stack and\n *  rely on duk__debug_process_message() to restore the value stack top\n *  automatically.\n */\n\n/* Process one debug message.  Automatically restore value stack top to its\n * entry value, so that individual message handlers don't need exact value\n * stack handling which is convenient.\n */\nDUK_LOCAL void duk__debug_process_message(duk_hthread *thr) {\n\tduk_heap *heap;\n\tduk_uint8_t x;\n\tduk_int32_t cmd;\n\tduk_idx_t entry_top;\n\n\tDUK_ASSERT(thr != NULL);\n\theap = thr->heap;\n\tDUK_ASSERT(heap != NULL);\n\n\tentry_top = duk_get_top(thr);\n\n\tx = duk_debug_read_byte(thr);\n\tswitch (x) {\n\tcase DUK_DBG_IB_REQUEST: {\n\t\tcmd = duk_debug_read_int(thr);\n\t\tswitch (cmd) {\n\t\tcase DUK_DBG_CMD_BASICINFO: {\n\t\t\tduk__debug_handle_basic_info(thr, heap);\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_DBG_CMD_TRIGGERSTATUS: {\n\t\t\tduk__debug_handle_trigger_status(thr, heap);\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_DBG_CMD_PAUSE: {\n\t\t\tduk__debug_handle_pause(thr, heap);\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_DBG_CMD_RESUME: {\n\t\t\tduk__debug_handle_resume(thr, heap);\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_DBG_CMD_STEPINTO:\n\t\tcase DUK_DBG_CMD_STEPOVER:\n\t\tcase DUK_DBG_CMD_STEPOUT: {\n\t\t\tduk__debug_handle_step(thr, heap, cmd);\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_DBG_CMD_LISTBREAK: {\n\t\t\tduk__debug_handle_list_break(thr, heap);\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_DBG_CMD_ADDBREAK: {\n\t\t\tduk__debug_handle_add_break(thr, heap);\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_DBG_CMD_DELBREAK: {\n\t\t\tduk__debug_handle_del_break(thr, heap);\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_DBG_CMD_GETVAR: {\n\t\t\tduk__debug_handle_get_var(thr, heap);\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_DBG_CMD_PUTVAR: {\n\t\t\tduk__debug_handle_put_var(thr, heap);\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_DBG_CMD_GETCALLSTACK: {\n\t\t\tduk__debug_handle_get_call_stack(thr, heap);\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_DBG_CMD_GETLOCALS: {\n\t\t\tduk__debug_handle_get_locals(thr, heap);\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_DBG_CMD_EVAL: {\n\t\t\tduk__debug_handle_eval(thr, heap);\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_DBG_CMD_DETACH: {\n\t\t\t/* The actual detached_cb call is postponed to message loop so\n\t\t\t * we don't need any special precautions here (just skip to EOM\n\t\t\t * on the already closed connection).\n\t\t\t */\n\t\t\tduk__debug_handle_detach(thr, heap);\n\t\t\tbreak;\n\t\t}\n#if defined(DUK_USE_DEBUGGER_DUMPHEAP)\n\t\tcase DUK_DBG_CMD_DUMPHEAP: {\n\t\t\tduk__debug_handle_dump_heap(thr, heap);\n\t\t\tbreak;\n\t\t}\n#endif  /* DUK_USE_DEBUGGER_DUMPHEAP */\n\t\tcase DUK_DBG_CMD_GETBYTECODE: {\n\t\t\tduk__debug_handle_get_bytecode(thr, heap);\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_DBG_CMD_APPREQUEST: {\n\t\t\tduk__debug_handle_apprequest(thr, heap);\n\t\t\tbreak;\n\t\t}\n#if defined(DUK_USE_DEBUGGER_INSPECT)\n\t\tcase DUK_DBG_CMD_GETHEAPOBJINFO: {\n\t\t\tduk__debug_handle_get_heap_obj_info(thr, heap);\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_DBG_CMD_GETOBJPROPDESC: {\n\t\t\tduk__debug_handle_get_obj_prop_desc(thr, heap);\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_DBG_CMD_GETOBJPROPDESCRANGE: {\n\t\t\tduk__debug_handle_get_obj_prop_desc_range(thr, heap);\n\t\t\tbreak;\n\t\t}\n#endif  /* DUK_USE_DEBUGGER_INSPECT */\n\t\tdefault: {\n\t\t\tDUK_D(DUK_DPRINT(\"debug command unsupported: %d\", (int) cmd));\n\t\t\tduk_debug_write_error_eom(thr, DUK_DBG_ERR_UNSUPPORTED, \"unsupported command\");\n\t\t}\n\t\t}  /* switch cmd */\n\t\tbreak;\n\t}\n\tcase DUK_DBG_IB_REPLY: {\n\t\tDUK_D(DUK_DPRINT(\"debug reply, skipping\"));\n\t\tbreak;\n\t}\n\tcase DUK_DBG_IB_ERROR: {\n\t\tDUK_D(DUK_DPRINT(\"debug error, skipping\"));\n\t\tbreak;\n\t}\n\tcase DUK_DBG_IB_NOTIFY: {\n\t\tDUK_D(DUK_DPRINT(\"debug notify, skipping\"));\n\t\tbreak;\n\t}\n\tdefault: {\n\t\tDUK_D(DUK_DPRINT(\"invalid initial byte, drop connection: %d\", (int) x));\n\t\tgoto fail;\n\t}\n\t}  /* switch initial byte */\n\n\tDUK_ASSERT(duk_get_top(thr) >= entry_top);\n\tduk_set_top(thr, entry_top);\n\tduk__debug_skip_to_eom(thr);\n\treturn;\n\n fail:\n\tDUK_ASSERT(duk_get_top(thr) >= entry_top);\n\tduk_set_top(thr, entry_top);\n\tDUK__SET_CONN_BROKEN(thr, 1);\n\treturn;\n}\n\nDUK_LOCAL void duk__check_resend_status(duk_hthread *thr) {\n\tif (thr->heap->dbg_read_cb != NULL && thr->heap->dbg_state_dirty) {\n\t\tduk_debug_send_status(thr);\n\t\tthr->heap->dbg_state_dirty = 0;\n\t}\n}\n\nDUK_INTERNAL duk_bool_t duk_debug_process_messages(duk_hthread *thr, duk_bool_t no_block) {\n#if defined(DUK_USE_ASSERTIONS)\n\tduk_idx_t entry_top;\n#endif\n\tduk_bool_t retval = 0;\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(thr->heap != NULL);\n#if defined(DUK_USE_ASSERTIONS)\n\tentry_top = duk_get_top(thr);\n#endif\n\n\tDUK_D(DUK_DPRINT(\"process debug messages: read_cb=%s, no_block=%ld, detaching=%ld, processing=%ld\",\n\t                 thr->heap->dbg_read_cb ? \"not NULL\" : \"NULL\", (long) no_block,\n\t                 (long) thr->heap->dbg_detaching, (long) thr->heap->dbg_processing));\n\tDUK_DD(DUK_DDPRINT(\"top at entry: %ld\", (long) duk_get_top(thr)));\n\n\t/* thr->heap->dbg_detaching may be != 0 if a debugger write outside\n\t * the message loop caused a transport error and detach1() to run.\n\t */\n\tDUK_ASSERT(thr->heap->dbg_detaching == 0 || thr->heap->dbg_detaching == 1);\n\tDUK_ASSERT(thr->heap->dbg_processing == 0);\n\tthr->heap->dbg_processing = 1;\n\n\t/* Ensure dirty state causes a Status even if never process any\n\t * messages.  This is expected by the bytecode executor when in\n\t * the running state.\n\t */\n\tduk__check_resend_status(thr);\n\n\tfor (;;) {\n\t\t/* Process messages until we're no longer paused or we peek\n\t\t * and see there's nothing to read right now.\n\t\t */\n\t\tDUK_DD(DUK_DDPRINT(\"top at loop top: %ld\", (long) duk_get_top(thr)));\n\t\tDUK_ASSERT(thr->heap->dbg_processing == 1);\n\n\t\twhile (thr->heap->dbg_read_cb == NULL && thr->heap->dbg_detaching) {\n\t\t\t/* Detach is pending; can be triggered from outside the\n\t\t\t * debugger loop (e.g. Status notify write error) or by\n\t\t\t * previous message handling.  Call detached callback\n\t\t\t * here, in a controlled state, to ensure a possible\n\t\t\t * reattach inside the detached_cb is handled correctly.\n\t\t\t *\n\t\t\t * Recheck for detach in a while loop: an immediate\n\t\t\t * reattach involves a call to duk_debugger_attach()\n\t\t\t * which writes a debugger handshake line immediately\n\t\t\t * inside the API call.  If the transport write fails\n\t\t\t * for that handshake, we can immediately end up in a\n\t\t\t * \"transport broken, detaching\" case several times here.\n\t\t\t * Loop back until we're either cleanly attached or\n\t\t\t * fully detached.\n\t\t\t *\n\t\t\t * NOTE: Reset dbg_processing = 1 forcibly, in case we\n\t\t\t * re-attached; duk_debugger_attach() sets dbg_processing\n\t\t\t * to 0 at the moment.\n\t\t\t */\n\n\t\t\tDUK_D(DUK_DPRINT(\"detach pending (dbg_read_cb == NULL, dbg_detaching != 0), call detach2\"));\n\n\t\t\tduk__debug_do_detach2(thr->heap);\n\t\t\tthr->heap->dbg_processing = 1;  /* may be set to 0 by duk_debugger_attach() inside callback */\n\n\t\t\tDUK_D(DUK_DPRINT(\"after detach2 (and possible reattach): dbg_read_cb=%s, dbg_detaching=%ld\",\n\t\t\t                 thr->heap->dbg_read_cb ? \"not NULL\" : \"NULL\", (long) thr->heap->dbg_detaching));\n\t\t}\n\t\tDUK_ASSERT(thr->heap->dbg_detaching == 0);  /* true even with reattach */\n\t\tDUK_ASSERT(thr->heap->dbg_processing == 1);  /* even after a detach and possible reattach */\n\n\t\tif (thr->heap->dbg_read_cb == NULL) {\n\t\t\tDUK_D(DUK_DPRINT(\"debug connection broken (and not detaching), stop processing messages\"));\n\t\t\tbreak;\n\t\t}\n\n\t\tif (!DUK_HEAP_HAS_DEBUGGER_PAUSED(thr->heap) || no_block) {\n\t\t\tif (!duk_debug_read_peek(thr)) {\n\t\t\t\t/* Note: peek cannot currently trigger a detach\n\t\t\t\t * so the dbg_detaching == 0 assert outside the\n\t\t\t\t * loop is correct.\n\t\t\t\t */\n\t\t\t\tDUK_D(DUK_DPRINT(\"processing debug message, peek indicated no data, stop processing messages\"));\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tDUK_D(DUK_DPRINT(\"processing debug message, peek indicated there is data, handle it\"));\n\t\t} else {\n\t\t\tDUK_D(DUK_DPRINT(\"paused, process debug message, blocking if necessary\"));\n\t\t}\n\n\t\tduk__check_resend_status(thr);\n\t\tduk__debug_process_message(thr);\n\t\tduk__check_resend_status(thr);\n\n\t\tretval = 1;  /* processed one or more messages */\n\t}\n\n\tDUK_ASSERT(thr->heap->dbg_detaching == 0);\n\tDUK_ASSERT(thr->heap->dbg_processing == 1);\n\tthr->heap->dbg_processing = 0;\n\n\t/* As an initial implementation, read flush after exiting the message\n\t * loop.  If transport is broken, this is a no-op (with debug logs).\n\t */\n\tduk_debug_read_flush(thr);  /* this cannot initiate a detach */\n\tDUK_ASSERT(thr->heap->dbg_detaching == 0);\n\n\tDUK_DD(DUK_DDPRINT(\"top at exit: %ld\", (long) duk_get_top(thr)));\n\n#if defined(DUK_USE_ASSERTIONS)\n\t/* Easy to get wrong, so assert for it. */\n\tDUK_ASSERT(entry_top == duk_get_top(thr));\n#endif\n\n\treturn retval;\n}\n\n/*\n *  Halt execution helper\n */\n\n/* Halt execution and enter a debugger message loop until execution is resumed\n * by the client.  PC for the current activation may be temporarily decremented\n * so that the \"current\" instruction will be shown by the client.  This helper\n * is callable from anywhere, also outside bytecode executor.\n */\n\nDUK_INTERNAL void duk_debug_halt_execution(duk_hthread *thr, duk_bool_t use_prev_pc) {\n\tduk_activation *act;\n\tduk_hcompfunc *fun;\n\tduk_instr_t *old_pc = NULL;\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(thr->heap != NULL);\n\tDUK_ASSERT(duk_debug_is_attached(thr->heap));\n\tDUK_ASSERT(thr->heap->dbg_processing == 0);\n\tDUK_ASSERT(!duk_debug_is_paused(thr->heap));\n\n\tduk_debug_set_paused(thr->heap);\n\n\tact = thr->callstack_curr;\n\n\t/* NOTE: act may be NULL if an error is thrown outside of any activation,\n\t * which may happen in the case of, e.g. syntax errors.\n\t */\n\n\t/* Decrement PC if that was requested, this requires a PC sync. */\n\tif (act != NULL) {\n\t\tduk_hthread_sync_currpc(thr);\n\t\told_pc = act->curr_pc;\n\t\tfun = (duk_hcompfunc *) DUK_ACT_GET_FUNC(act);\n\n\t\t/* Short circuit if is safe: if act->curr_pc != NULL, 'fun' is\n\t\t * guaranteed to be a non-NULL Ecmascript function.\n\t\t */\n\t\tDUK_ASSERT(act->curr_pc == NULL ||\n\t\t           (fun != NULL && DUK_HOBJECT_IS_COMPFUNC((duk_hobject *) fun)));\n\t\tif (use_prev_pc &&\n\t\t    act->curr_pc != NULL &&\n\t\t    act->curr_pc > DUK_HCOMPFUNC_GET_CODE_BASE(thr->heap, fun)) {\n\t\t\tact->curr_pc--;\n\t\t}\n\t}\n\n\t/* Process debug messages until we are no longer paused. */\n\n\t/* NOTE: This is a bit fragile.  It's important to ensure that\n\t * duk_debug_process_messages() never throws an error or\n\t * act->curr_pc will never be reset.\n\t */\n\n\tthr->heap->dbg_state_dirty = 1;\n\twhile (DUK_HEAP_HAS_DEBUGGER_PAUSED(thr->heap)) {\n\t\tDUK_ASSERT(duk_debug_is_attached(thr->heap));\n\t\tDUK_ASSERT(thr->heap->dbg_processing == 0);\n\t\tduk_debug_process_messages(thr, 0 /*no_block*/);\n\t}\n\n\t/* XXX: Decrementing and restoring act->curr_pc works now, but if the\n\t * debugger message loop gains the ability to adjust the current PC\n\t * (e.g. a forced jump) restoring the PC here will break.  Another\n\t * approach would be to use a state flag for the \"decrement 1 from\n\t * topmost activation's PC\" and take it into account whenever dealing\n\t * with PC values.\n\t */\n\tif (act != NULL) {\n\t\tact->curr_pc = old_pc;  /* restore PC */\n\t}\n}\n\n/*\n *  Breakpoint management\n */\n\nDUK_INTERNAL duk_small_int_t duk_debug_add_breakpoint(duk_hthread *thr, duk_hstring *filename, duk_uint32_t line) {\n\tduk_heap *heap;\n\tduk_breakpoint *b;\n\n\t/* Caller must trigger recomputation of active breakpoint list.  To\n\t * ensure stale values are not used if that doesn't happen, clear the\n\t * active breakpoint list here.\n\t */\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(filename != NULL);\n\theap = thr->heap;\n\tDUK_ASSERT(heap != NULL);\n\n\tif (heap->dbg_breakpoint_count >= DUK_HEAP_MAX_BREAKPOINTS) {\n\t\tDUK_D(DUK_DPRINT(\"failed to add breakpoint for %O:%ld, all breakpoint slots used\",\n\t\t                 (duk_heaphdr *) filename, (long) line));\n\t\treturn -1;\n\t}\n\theap->dbg_breakpoints_active[0] = (duk_breakpoint *) NULL;\n\tb = heap->dbg_breakpoints + (heap->dbg_breakpoint_count++);\n\tb->filename = filename;\n\tb->line = line;\n\tDUK_HSTRING_INCREF(thr, filename);\n\n\treturn (duk_small_int_t) (heap->dbg_breakpoint_count - 1);  /* index */\n}\n\nDUK_INTERNAL duk_bool_t duk_debug_remove_breakpoint(duk_hthread *thr, duk_small_uint_t breakpoint_index) {\n\tduk_heap *heap;\n\tduk_hstring *h;\n\tduk_breakpoint *b;\n\tduk_size_t move_size;\n\n\t/* Caller must trigger recomputation of active breakpoint list.  To\n\t * ensure stale values are not used if that doesn't happen, clear the\n\t * active breakpoint list here.\n\t */\n\n\tDUK_ASSERT(thr != NULL);\n\theap = thr->heap;\n\tDUK_ASSERT(heap != NULL);\n\tDUK_ASSERT(duk_debug_is_attached(thr->heap));\n\tDUK_ASSERT_DISABLE(breakpoint_index >= 0);  /* unsigned */\n\n\tif (breakpoint_index >= heap->dbg_breakpoint_count) {\n\t\tDUK_D(DUK_DPRINT(\"invalid breakpoint index: %ld\", (long) breakpoint_index));\n\t\treturn 0;\n\t}\n\tb = heap->dbg_breakpoints + breakpoint_index;\n\n\th = b->filename;\n\tDUK_ASSERT(h != NULL);\n\n\tmove_size = sizeof(duk_breakpoint) * (heap->dbg_breakpoint_count - breakpoint_index - 1);\n\tif (move_size > 0) {\n\t\tDUK_MEMMOVE((void *) b,\n\t\t            (const void *) (b + 1),\n\t\t            (size_t) move_size);\n\t}\n\theap->dbg_breakpoint_count--;\n\theap->dbg_breakpoints_active[0] = (duk_breakpoint *) NULL;\n\n\tDUK_HSTRING_DECREF(thr, h);  /* side effects */\n\tDUK_UNREF(h);  /* w/o refcounting */\n\n\t/* Breakpoint entries above the used area are left as garbage. */\n\n\treturn 1;\n}\n\n/*\n *  Misc state management\n */\n\nDUK_INTERNAL duk_bool_t duk_debug_is_attached(duk_heap *heap) {\n\treturn (heap->dbg_read_cb != NULL);\n}\n\nDUK_INTERNAL duk_bool_t duk_debug_is_paused(duk_heap *heap) {\n\treturn (DUK_HEAP_HAS_DEBUGGER_PAUSED(heap) != 0);\n}\n\nDUK_INTERNAL void duk_debug_set_paused(duk_heap *heap) {\n\tif (duk_debug_is_paused(heap)) {\n\t\tDUK_D(DUK_DPRINT(\"trying to set paused state when already paused, ignoring\"));\n\t} else {\n\t\tDUK_HEAP_SET_DEBUGGER_PAUSED(heap);\n\t\theap->dbg_state_dirty = 1;\n\t\tduk_debug_clear_pause_state(heap);\n\t\tDUK_ASSERT(heap->ms_running == 0);  /* debugger can't be triggered within mark-and-sweep */\n\t\theap->ms_running = 1;  /* prevent mark-and-sweep, prevent refzero queueing */\n\t\theap->ms_prevent_count++;\n\t\tDUK_ASSERT(heap->ms_prevent_count != 0);  /* Wrap. */\n\t\tDUK_ASSERT(heap->heap_thread != NULL);\n\t}\n}\n\nDUK_INTERNAL void duk_debug_clear_paused(duk_heap *heap) {\n\tif (duk_debug_is_paused(heap)) {\n\t\tDUK_HEAP_CLEAR_DEBUGGER_PAUSED(heap);\n\t\theap->dbg_state_dirty = 1;\n\t\tduk_debug_clear_pause_state(heap);\n\t\tDUK_ASSERT(heap->ms_running == 1);\n\t\tDUK_ASSERT(heap->ms_prevent_count > 0);\n\t\theap->ms_prevent_count--;\n\t\theap->ms_running = 0;\n\t\tDUK_ASSERT(heap->heap_thread != NULL);\n\t} else {\n\t\tDUK_D(DUK_DPRINT(\"trying to clear paused state when not paused, ignoring\"));\n\t}\n}\n\nDUK_INTERNAL void duk_debug_clear_pause_state(duk_heap *heap) {\n\theap->dbg_pause_flags = 0;\n\theap->dbg_pause_act = NULL;\n\theap->dbg_pause_startline = 0;\n}\n\n#else  /* DUK_USE_DEBUGGER_SUPPORT */\n\n/* No debugger support. */\n\n#endif  /* DUK_USE_DEBUGGER_SUPPORT */\n\n/* automatic undefs */\n#undef DUK__DBG_TPORT_ENTER\n#undef DUK__DBG_TPORT_EXIT\n#undef DUK__SET_CONN_BROKEN\n#line 1 \"duk_error_augment.c\"\n/*\n *  Augmenting errors at their creation site and their throw site.\n *\n *  When errors are created, traceback data is added by built-in code\n *  and a user error handler (if defined) can process or replace the\n *  error.  Similarly, when errors are thrown, a user error handler\n *  (if defined) can process or replace the error.\n *\n *  Augmentation and other processing at error creation time is nice\n *  because an error is only created once, but it may be thrown and\n *  rethrown multiple times.  User error handler registered for processing\n *  an error at its throw site must be careful to handle rethrowing in\n *  a useful manner.\n *\n *  Error augmentation may throw an internal error (e.g. alloc error).\n *\n *  Ecmascript allows throwing any values, so all values cannot be\n *  augmented.  Currently, the built-in augmentation at error creation\n *  only augments error values which are Error instances (= have the\n *  built-in Error.prototype in their prototype chain) and are also\n *  extensible.  User error handlers have no limitations in this respect.\n */\n\n/* #include duk_internal.h -> already included */\n\n/*\n *  Helper for calling a user error handler.\n *\n *  'thr' must be the currently active thread; the error handler is called\n *  in its context.  The valstack of 'thr' must have the error value on\n *  top, and will be replaced by another error value based on the return\n *  value of the error handler.\n *\n *  The helper calls duk_handle_call() recursively in protected mode.\n *  Before that call happens, no longjmps should happen; as a consequence,\n *  we must assume that the valstack contains enough temporary space for\n *  arguments and such.\n *\n *  While the error handler runs, any errors thrown will not trigger a\n *  recursive error handler call (this is implemented using a heap level\n *  flag which will \"follow\" through any coroutines resumed inside the\n *  error handler).  If the error handler is not callable or throws an\n *  error, the resulting error replaces the original error (for Duktape\n *  internal errors, duk_error_throw.c further substitutes this error with\n *  a DoubleError which is not ideal).  This would be easy to change and\n *  even signal to the caller.\n *\n *  The user error handler is stored in 'Duktape.errCreate' or\n *  'Duktape.errThrow' depending on whether we're augmenting the error at\n *  creation or throw time.  There are several alternatives to this approach,\n *  see doc/error-objects.rst for discussion.\n *\n *  Note: since further longjmp()s may occur while calling the error handler\n *  (for many reasons, e.g. a labeled 'break' inside the handler), the\n *  caller can make no assumptions on the thr->heap->lj state after the\n *  call (this affects especially duk_error_throw.c).  This is not an issue\n *  as long as the caller writes to the lj state only after the error handler\n *  finishes.\n */\n\n#if defined(DUK_USE_ERRTHROW) || defined(DUK_USE_ERRCREATE)\nDUK_LOCAL void duk__err_augment_user(duk_hthread *thr, duk_small_uint_t stridx_cb) {\n\tduk_tval *tv_hnd;\n\tduk_int_t rc;\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(thr->heap != NULL);\n\tDUK_ASSERT_STRIDX_VALID(stridx_cb);\n\n\tif (thr->heap->augmenting_error) {\n\t\tDUK_D(DUK_DPRINT(\"recursive call to error augmentation, ignore\"));\n\t\treturn;\n\t}\n\n\t/*\n\t *  Check whether or not we have an error handler.\n\t *\n\t *  We must be careful of not triggering an error when looking up the\n\t *  property.  For instance, if the property is a getter, we don't want\n\t *  to call it, only plain values are allowed.  The value, if it exists,\n\t *  is not checked.  If the value is not a function, a TypeError happens\n\t *  when it is called and that error replaces the original one.\n\t */\n\n\tDUK_ASSERT_VALSTACK_SPACE(thr, 4);  /* 3 entries actually needed below */\n\n\t/* [ ... errval ] */\n\n\tif (thr->builtins[DUK_BIDX_DUKTAPE] == NULL) {\n\t\t/* When creating built-ins, some of the built-ins may not be set\n\t\t * and we want to tolerate that when throwing errors.\n\t\t */\n\t\tDUK_DD(DUK_DDPRINT(\"error occurred when DUK_BIDX_DUKTAPE is NULL, ignoring\"));\n\t\treturn;\n\t}\n\ttv_hnd = duk_hobject_find_existing_entry_tval_ptr(thr->heap,\n\t                                                  thr->builtins[DUK_BIDX_DUKTAPE],\n\t                                                  DUK_HTHREAD_GET_STRING(thr, stridx_cb));\n\tif (tv_hnd == NULL) {\n\t\tDUK_DD(DUK_DDPRINT(\"error handler does not exist or is not a plain value: %!T\",\n\t\t                   (duk_tval *) tv_hnd));\n\t\treturn;\n\t}\n\tDUK_DDD(DUK_DDDPRINT(\"error handler dump (callability not checked): %!T\",\n\t                     (duk_tval *) tv_hnd));\n\tduk_push_tval(thr, tv_hnd);\n\n\t/* [ ... errval errhandler ] */\n\n\tduk_insert(thr, -2);  /* -> [ ... errhandler errval ] */\n\tduk_push_undefined(thr);\n\tduk_insert(thr, -2);  /* -> [ ... errhandler undefined(= this) errval ] */\n\n\t/* [ ... errhandler undefined errval ] */\n\n\t/*\n\t *  heap->augmenting_error prevents recursive re-entry and also causes\n\t *  call handling to use a larger (but not unbounded) call stack limit\n\t *  for the duration of error augmentation.\n\t *\n\t *  We ignore errors now: a success return and an error value both\n\t *  replace the original error value.  (This would be easy to change.)\n\t */\n\n\tDUK_ASSERT(thr->heap->augmenting_error == 0);\n\tthr->heap->augmenting_error = 1;\n\n\trc = duk_pcall_method(thr, 1);\n\tDUK_UNREF(rc);  /* no need to check now: both success and error are OK */\n\n\tDUK_ASSERT(thr->heap->augmenting_error == 1);\n\tthr->heap->augmenting_error = 0;\n\n\t/* [ ... errval ] */\n}\n#endif  /* DUK_USE_ERRTHROW || DUK_USE_ERRCREATE */\n\n/*\n *  Add ._Tracedata to an error on the stack top.\n */\n\n#if defined(DUK_USE_TRACEBACKS)\nDUK_LOCAL void duk__add_traceback(duk_hthread *thr, duk_hthread *thr_callstack, const char *c_filename, duk_int_t c_line, duk_small_uint_t flags) {\n\tduk_activation *act;\n\tduk_int_t depth;\n\tduk_int_t arr_size;\n\tduk_tval *tv;\n\tduk_hstring *s;\n\tduk_uint32_t u32;\n\tduk_double_t d;\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(thr_callstack != NULL);\n\n\t/* [ ... error ] */\n\n\t/*\n\t *  The traceback format is pretty arcane in an attempt to keep it compact\n\t *  and cheap to create.  It may change arbitrarily from version to version.\n\t *  It should be decoded/accessed through version specific accessors only.\n\t *\n\t *  See doc/error-objects.rst.\n\t */\n\n\tDUK_DDD(DUK_DDDPRINT(\"adding traceback to object: %!T\",\n\t                     (duk_tval *) duk_get_tval(thr, -1)));\n\n\t/* Preallocate array to correct size, so that we can just write out\n\t * the _Tracedata values into the array part.\n\t */\n\tact = thr->callstack_curr;\n\tdepth = DUK_USE_TRACEBACK_DEPTH;\n\tDUK_ASSERT(thr_callstack->callstack_top <= DUK_INT_MAX);  /* callstack limits */\n\tif (depth > (duk_int_t) thr_callstack->callstack_top) {\n\t\tdepth = (duk_int_t) thr_callstack->callstack_top;\n\t}\n\tif (depth > 0) {\n\t\tif (flags & DUK_AUGMENT_FLAG_SKIP_ONE) {\n\t\t\tDUK_ASSERT(act != NULL);\n\t\t\tact = act->parent;\n\t\t\tdepth--;\n\t\t}\n\t}\n\tarr_size = depth * 2;\n\tif (thr->compile_ctx != NULL && thr->compile_ctx->h_filename != NULL) {\n\t\tarr_size += 2;\n\t}\n\tif (c_filename) {\n\t\t/* We need the C filename to be interned before getting the\n\t\t * array part pointer to avoid any GC interference while the\n\t\t * array part is populated.\n\t\t */\n\t\tduk_push_string(thr, c_filename);\n\t\tarr_size += 2;\n\t}\n\n\t/* XXX: uninitialized would be OK */\n\tDUK_D(DUK_DPRINT(\"preallocated _Tracedata to %ld items\", (long) arr_size));\n\ttv = duk_push_harray_with_size_outptr(thr, (duk_uint32_t) arr_size);\n\tDUK_ASSERT(arr_size == 0 || tv != NULL);\n\n\t/* Compiler SyntaxErrors (and other errors) come first, and are\n\t * blamed by default (not flagged \"noblame\").\n\t */\n\tif (thr->compile_ctx != NULL && thr->compile_ctx->h_filename != NULL) {\n\t\ts = thr->compile_ctx->h_filename;\n\t\tDUK_TVAL_SET_STRING(tv, s);\n\t\tDUK_HSTRING_INCREF(thr, s);\n\t\ttv++;\n\n\t\tu32 = (duk_uint32_t) thr->compile_ctx->curr_token.start_line;  /* (flags<<32) + (line), flags = 0 */\n\t\tDUK_TVAL_SET_U32(tv, u32);\n\t\ttv++;\n\t}\n\n\t/* Filename/line from C macros (__FILE__, __LINE__) are added as an\n\t * entry with a special format: (string, number).  The number contains\n\t * the line and flags.\n\t */\n\n\t/* [ ... error c_filename? arr ] */\n\n\tif (c_filename) {\n\t\tDUK_ASSERT(DUK_TVAL_IS_STRING(thr->valstack_top - 2));\n\t\ts = DUK_TVAL_GET_STRING(thr->valstack_top - 2);  /* interned c_filename */\n\t\tDUK_ASSERT(s != NULL);\n\t\tDUK_TVAL_SET_STRING(tv, s);\n\t\tDUK_HSTRING_INCREF(thr, s);\n\t\ttv++;\n\n\t\td = ((flags & DUK_AUGMENT_FLAG_NOBLAME_FILELINE) ? ((duk_double_t) DUK_TB_FLAG_NOBLAME_FILELINE) * DUK_DOUBLE_2TO32 : 0.0) +\n\t\t    (duk_double_t) c_line;\n\t\tDUK_TVAL_SET_DOUBLE(tv, d);\n\t\ttv++;\n\t}\n\n\t/* Traceback depth doesn't take into account the filename/line\n\t * special handling above (intentional).\n\t */\n\tfor (; depth-- > 0; act = act->parent) {\n\t\tduk_uint32_t pc;\n\t\tduk_tval *tv_src;\n\n\t\t/* [... arr] */\n\n\t\tDUK_ASSERT(act != NULL);  /* depth check above, assumes book-keeping is correct */\n\t\tDUK_ASSERT_DISABLE(act->pc >= 0);  /* unsigned */\n\n\t\t/* Add function object. */\n\t\ttv_src = &act->tv_func;  /* object (function) or lightfunc */\n\t\tDUK_ASSERT(DUK_TVAL_IS_OBJECT(tv_src) || DUK_TVAL_IS_LIGHTFUNC(tv_src));\n\t\tDUK_TVAL_SET_TVAL(tv, tv_src);\n\t\tDUK_TVAL_INCREF(thr, tv);\n\t\ttv++;\n\n\t\t/* Add a number containing: pc, activation flags.\n\t\t *\n\t\t * PC points to next instruction, find offending PC.  Note that\n\t\t * PC == 0 for native code.\n\t\t */\n\t\tpc = (duk_uint32_t) duk_hthread_get_act_prev_pc(thr_callstack, act);\n\t\tDUK_ASSERT_DISABLE(pc >= 0);  /* unsigned */\n\t\tDUK_ASSERT((duk_double_t) pc < DUK_DOUBLE_2TO32);  /* assume PC is at most 32 bits and non-negative */\n\t\td = ((duk_double_t) act->flags) * DUK_DOUBLE_2TO32 + (duk_double_t) pc;\n\t\tDUK_TVAL_SET_DOUBLE(tv, d);\n\t\ttv++;\n\t}\n\n#if defined(DUK_USE_ASSERTIONS)\n\t{\n\t\tduk_harray *a;\n\t\ta = (duk_harray *) duk_known_hobject(thr, -1);\n\t\tDUK_ASSERT(a != NULL);\n\t\tDUK_ASSERT((duk_uint32_t) (tv - DUK_HOBJECT_A_GET_BASE(thr->heap, (duk_hobject *) a)) == a->length);\n\t\tDUK_ASSERT(a->length == (duk_uint32_t) arr_size);\n\t}\n#endif\n\n\t/* [ ... error c_filename? arr ] */\n\n\tif (c_filename) {\n\t\tduk_remove_m2(thr);\n\t}\n\n\t/* [ ... error arr ] */\n\n\tduk_xdef_prop_stridx_short_wec(thr, -2, DUK_STRIDX_INT_TRACEDATA);  /* -> [ ... error ] */\n}\n#endif  /* DUK_USE_TRACEBACKS */\n\n/*\n *  Add .fileName and .lineNumber to an error on the stack top.\n */\n\n#if defined(DUK_USE_AUGMENT_ERROR_CREATE) && !defined(DUK_USE_TRACEBACKS)\nDUK_LOCAL void duk__add_fileline(duk_hthread *thr, duk_hthread *thr_callstack, const char *c_filename, duk_int_t c_line, duk_small_uint_t flags) {\n#if defined(DUK_USE_ASSERTIONS)\n\tduk_int_t entry_top;\n#endif\n\n#if defined(DUK_USE_ASSERTIONS)\n\tentry_top = duk_get_top(thr);\n#endif\n\n\t/*\n\t *  If tracebacks are disabled, 'fileName' and 'lineNumber' are added\n\t *  as plain own properties.  Since Error.prototype has accessors of\n\t *  the same name, we need to define own properties directly (cannot\n\t *  just use e.g. duk_put_prop_stridx).  Existing properties are not\n\t *  overwritten in case they already exist.\n\t */\n\n\tif (thr->compile_ctx != NULL && thr->compile_ctx->h_filename != NULL) {\n\t\t/* Compiler SyntaxError (or other error) gets the primary blame.\n\t\t * Currently no flag to prevent blaming.\n\t\t */\n\t\tduk_push_uint(thr, (duk_uint_t) thr->compile_ctx->curr_token.start_line);\n\t\tduk_push_hstring(thr, thr->compile_ctx->h_filename);\n\t} else if (c_filename && (flags & DUK_AUGMENT_FLAG_NOBLAME_FILELINE) == 0) {\n\t\t/* C call site gets blamed next, unless flagged not to do so.\n\t\t * XXX: file/line is disabled in minimal builds, so disable this\n\t\t * too when appropriate.\n\t\t */\n\t\tduk_push_int(thr, c_line);\n\t\tduk_push_string(thr, c_filename);\n\t} else {\n\t\t/* Finally, blame the innermost callstack entry which has a\n\t\t * .fileName property.\n\t\t */\n\t\tduk_small_uint_t depth;\n\t\tduk_uint32_t ecma_line;\n\t\tduk_activation *act;\n\n\t\tDUK_ASSERT(thr_callstack->callstack_top <= DUK_INT_MAX);  /* callstack limits */\n\t\tdepth = DUK_USE_TRACEBACK_DEPTH;\n\t\tif (depth > thr_callstack->callstack_top) {\n\t\t\tdepth = thr_callstack->callstack_top;\n\t\t}\n\t\tfor (act = thr_callstack->callstack_curr; depth-- > 0; act = act->parent) {\n\t\t\tduk_hobject *func;\n\t\t\tduk_uint32_t pc;\n\n\t\t\tDUK_ASSERT(act != NULL);\n\t\t\tfunc = DUK_ACT_GET_FUNC(act);\n\t\t\tif (func == NULL) {\n\t\t\t\t/* Lightfunc, not blamed now. */\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t/* PC points to next instruction, find offending PC,\n\t\t\t * PC == 0 for native code.\n\t\t\t */\n\t\t\tpc = duk_hthread_get_act_prev_pc(thr, act);  /* thr argument only used for thr->heap, so specific thread doesn't matter */\n\t\t\tDUK_UNREF(pc);\n\t\t\tDUK_ASSERT_DISABLE(pc >= 0);  /* unsigned */\n\t\t\tDUK_ASSERT((duk_double_t) pc < DUK_DOUBLE_2TO32);  /* assume PC is at most 32 bits and non-negative */\n\t\t\tact = NULL;  /* invalidated by pushes, so get out of the way */\n\n\t\t\tduk_push_hobject(thr, func);\n\n\t\t\t/* [ ... error func ] */\n\n\t\t\tduk_get_prop_stridx_short(thr, -1, DUK_STRIDX_FILE_NAME);\n\t\t\tif (!duk_is_string_notsymbol(thr, -1)) {\n\t\t\t\tduk_pop_2(thr);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t/* [ ... error func fileName ] */\n\n\t\t\tecma_line = 0;\n#if defined(DUK_USE_PC2LINE)\n\t\t\tif (DUK_HOBJECT_IS_COMPFUNC(func)) {\n\t\t\t\tecma_line = duk_hobject_pc2line_query(thr, -2, (duk_uint_fast32_t) pc);\n\t\t\t} else {\n\t\t\t\t/* Native function, no relevant lineNumber. */\n\t\t\t}\n#endif  /* DUK_USE_PC2LINE */\n\t\t\tduk_push_u32(thr, ecma_line);\n\n\t\t\t/* [ ... error func fileName lineNumber ] */\n\n\t\t\tduk_replace(thr, -3);\n\n\t\t\t/* [ ... error lineNumber fileName ] */\n\t\t\tgoto define_props;\n\t\t}\n\n\t\t/* No activation matches, use undefined for both .fileName and\n\t\t * .lineNumber (matches what we do with a _Tracedata based\n\t\t * no-match lookup.\n\t\t */\n\t\tduk_push_undefined(thr);\n\t\tduk_push_undefined(thr);\n\t}\n\n define_props:\n\t/* [ ... error lineNumber fileName ] */\n#if defined(DUK_USE_ASSERTIONS)\n\tDUK_ASSERT(duk_get_top(thr) == entry_top + 2);\n#endif\n\tduk_xdef_prop_stridx_short(thr, -3, DUK_STRIDX_FILE_NAME, DUK_PROPDESC_FLAGS_C | DUK_PROPDESC_FLAG_NO_OVERWRITE);\n\tduk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_LINE_NUMBER, DUK_PROPDESC_FLAGS_C | DUK_PROPDESC_FLAG_NO_OVERWRITE);\n}\n#endif  /* DUK_USE_AUGMENT_ERROR_CREATE && !DUK_USE_TRACEBACKS */\n\n/*\n *  Add line number to a compiler error.\n */\n\n#if defined(DUK_USE_AUGMENT_ERROR_CREATE)\nDUK_LOCAL void duk__add_compiler_error_line(duk_hthread *thr) {\n\n\t/* Append a \"(line NNN)\" to the \"message\" property of any error\n\t * thrown during compilation.  Usually compilation errors are\n\t * SyntaxErrors but they can also be out-of-memory errors and\n\t * the like.\n\t */\n\n\t/* [ ... error ] */\n\n\tDUK_ASSERT(duk_is_object(thr, -1));\n\n\tif (!(thr->compile_ctx != NULL && thr->compile_ctx->h_filename != NULL)) {\n\t\treturn;\n\t}\n\n\tDUK_DDD(DUK_DDDPRINT(\"compile error, before adding line info: %!T\",\n\t                     (duk_tval *) duk_get_tval(thr, -1)));\n\n\tif (duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_MESSAGE)) {\n\t\tduk_push_sprintf(thr, \" (line %ld)\", (long) thr->compile_ctx->curr_token.start_line);\n\t\tduk_concat(thr, 2);\n\t\tduk_put_prop_stridx_short(thr, -2, DUK_STRIDX_MESSAGE);\n\t} else {\n\t\tduk_pop(thr);\n\t}\n\n\tDUK_DDD(DUK_DDDPRINT(\"compile error, after adding line info: %!T\",\n\t                     (duk_tval *) duk_get_tval(thr, -1)));\n}\n#endif  /* DUK_USE_AUGMENT_ERROR_CREATE */\n\n/*\n *  Augment an error being created using Duktape specific properties\n *  like _Tracedata or .fileName/.lineNumber.\n */\n\n#if defined(DUK_USE_AUGMENT_ERROR_CREATE)\nDUK_LOCAL void duk__err_augment_builtin_create(duk_hthread *thr, duk_hthread *thr_callstack, const char *c_filename, duk_int_t c_line, duk_hobject *obj, duk_small_uint_t flags) {\n#if defined(DUK_USE_ASSERTIONS)\n\tduk_int_t entry_top;\n#endif\n\n#if defined(DUK_USE_ASSERTIONS)\n\tentry_top = duk_get_top(thr);\n#endif\n\tDUK_ASSERT(obj != NULL);\n\n\tDUK_UNREF(obj);  /* unreferenced w/o tracebacks */\n\n\tduk__add_compiler_error_line(thr);\n\n#if defined(DUK_USE_TRACEBACKS)\n\t/* If tracebacks are enabled, the '_Tracedata' property is the only\n\t * thing we need: 'fileName' and 'lineNumber' are virtual properties\n\t * which use '_Tracedata'.\n\t */\n\tif (duk_hobject_hasprop_raw(thr, obj, DUK_HTHREAD_STRING_INT_TRACEDATA(thr))) {\n\t\tDUK_DDD(DUK_DDDPRINT(\"error value already has a '_Tracedata' property, not modifying it\"));\n\t} else {\n\t\tduk__add_traceback(thr, thr_callstack, c_filename, c_line, flags);\n\t}\n#else\n\t/* Without tracebacks the concrete .fileName and .lineNumber need\n\t * to be added directly.\n\t */\n\tduk__add_fileline(thr, thr_callstack, c_filename, c_line, flags);\n#endif\n\n#if defined(DUK_USE_ASSERTIONS)\n\tDUK_ASSERT(duk_get_top(thr) == entry_top);\n#endif\n}\n#endif  /* DUK_USE_AUGMENT_ERROR_CREATE */\n\n/*\n *  Augment an error at creation time with _Tracedata/fileName/lineNumber\n *  and allow a user error handler (if defined) to process/replace the error.\n *  The error to be augmented is at the stack top.\n *\n *  thr: thread containing the error value\n *  thr_callstack: thread which should be used for generating callstack etc.\n *  c_filename: C __FILE__ related to the error\n *  c_line: C __LINE__ related to the error\n *  flags & DUK_AUGMENT_FLAG_NOBLAME_FILELINE:\n *      if true, don't fileName/line as error source, otherwise use traceback\n *      (needed because user code filename/line are reported but internal ones\n *      are not)\n */\n\n#if defined(DUK_USE_AUGMENT_ERROR_CREATE)\nDUK_INTERNAL void duk_err_augment_error_create(duk_hthread *thr, duk_hthread *thr_callstack, const char *c_filename, duk_int_t c_line, duk_small_uint_t flags) {\n\tduk_hobject *obj;\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(thr_callstack != NULL);\n\n\t/* [ ... error ] */\n\n\t/*\n\t *  Criteria for augmenting:\n\t *\n\t *   - augmentation enabled in build (naturally)\n\t *   - error value internal prototype chain contains the built-in\n\t *     Error prototype object (i.e. 'val instanceof Error')\n\t *\n\t *  Additional criteria for built-in augmenting:\n\t *\n\t *   - error value is an extensible object\n\t */\n\n\tobj = duk_get_hobject(thr, -1);\n\tif (!obj) {\n\t\tDUK_DDD(DUK_DDDPRINT(\"value is not an object, skip both built-in and user augment\"));\n\t\treturn;\n\t}\n\tif (!duk_hobject_prototype_chain_contains(thr, obj, thr->builtins[DUK_BIDX_ERROR_PROTOTYPE], 1 /*ignore_loop*/)) {\n\t\t/* If the value has a prototype loop, it's critical not to\n\t\t * throw here.  Instead, assume the value is not to be\n\t\t * augmented.\n\t\t */\n\t\tDUK_DDD(DUK_DDDPRINT(\"value is not an error instance, skip both built-in and user augment\"));\n\t\treturn;\n\t}\n\tif (DUK_HOBJECT_HAS_EXTENSIBLE(obj)) {\n\t\tDUK_DDD(DUK_DDDPRINT(\"error meets criteria, built-in augment\"));\n\t\tduk__err_augment_builtin_create(thr, thr_callstack, c_filename, c_line, obj, flags);\n\t} else {\n\t\tDUK_DDD(DUK_DDDPRINT(\"error does not meet criteria, no built-in augment\"));\n\t}\n\n\t/* [ ... error ] */\n\n#if defined(DUK_USE_ERRCREATE)\n\tduk__err_augment_user(thr, DUK_STRIDX_ERR_CREATE);\n#endif\n}\n#endif  /* DUK_USE_AUGMENT_ERROR_CREATE */\n\n/*\n *  Augment an error at throw time; allow a user error handler (if defined)\n *  to process/replace the error.  The error to be augmented is at the\n *  stack top.\n */\n\n#if defined(DUK_USE_AUGMENT_ERROR_THROW)\nDUK_INTERNAL void duk_err_augment_error_throw(duk_hthread *thr) {\n#if defined(DUK_USE_ERRTHROW)\n\tduk__err_augment_user(thr, DUK_STRIDX_ERR_THROW);\n#endif  /* DUK_USE_ERRTHROW */\n}\n#endif  /* DUK_USE_AUGMENT_ERROR_THROW */\n#line 1 \"duk_error_longjmp.c\"\n/*\n *  Do a longjmp call, calling the fatal error handler if no\n *  catchpoint exists.\n */\n\n/* #include duk_internal.h -> already included */\n\n#if defined(DUK_USE_PREFER_SIZE)\nDUK_LOCAL void duk__uncaught_minimal(duk_hthread *thr) {\n\t(void) duk_fatal(thr, \"uncaught error\");\n}\n#endif\n\n#if 0\nDUK_LOCAL void duk__uncaught_readable(duk_hthread *thr) {\n\tconst char *summary;\n\tchar buf[DUK_USE_FATAL_MAXLEN];\n\n\tsummary = duk_push_string_tval_readable(thr, &thr->heap->lj.value1);\n\tDUK_SNPRINTF(buf, sizeof(buf), \"uncaught: %s\", summary);\n\tbuf[sizeof(buf) - 1] = (char) 0;\n\t(void) duk_fatal(thr, (const char *) buf);\n}\n#endif\n\n#if !defined(DUK_USE_PREFER_SIZE)\nDUK_LOCAL void duk__uncaught_error_aware(duk_hthread *thr) {\n\tconst char *summary;\n\tchar buf[DUK_USE_FATAL_MAXLEN];\n\n\tsummary = duk_push_string_tval_readable_error(thr, &thr->heap->lj.value1);\n\tDUK_ASSERT(summary != NULL);\n\tDUK_SNPRINTF(buf, sizeof(buf), \"uncaught: %s\", summary);\n\tbuf[sizeof(buf) - 1] = (char) 0;\n\t(void) duk_fatal(thr, (const char *) buf);\n}\n#endif\n\nDUK_INTERNAL void duk_err_longjmp(duk_hthread *thr) {\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(thr->heap != NULL);\n\n\tDUK_DD(DUK_DDPRINT(\"longjmp error: type=%d iserror=%d value1=%!T value2=%!T\",\n\t                   (int) thr->heap->lj.type, (int) thr->heap->lj.iserror,\n\t                   &thr->heap->lj.value1, &thr->heap->lj.value2));\n\n\t/* Prevent finalizer execution during error handling.  All error\n\t * handling sites will process pending finalizers once error handling\n\t * is complete and we're ready for the side effects.  Does not prevent\n\t * refzero freeing or mark-and-sweep during error handling.\n\t *\n\t * NOTE: when we come here some calling code may have used DECREF\n\t * NORZ macros without an explicit DUK_REFZERO_CHECK_xxx() call.\n\t * We don't want to do it here because it would just check for\n\t * pending finalizers and we prevent that explicitly.  Instead,\n\t * the error catcher will run the finalizers once error handling\n\t * is complete.\n\t */\n\n\tDUK_ASSERT_LJSTATE_SET(thr->heap);\n\n\tthr->heap->pf_prevent_count++;\n\tDUK_ASSERT(thr->heap->pf_prevent_count != 0);  /* Wrap. */\n\n#if defined(DUK_USE_ASSERTIONS)\n\t/* XXX: set this immediately when longjmp state is set */\n\tDUK_ASSERT(thr->heap->error_not_allowed == 0);  /* Detect error within critical section. */\n\tthr->heap->error_not_allowed = 1;\n#endif\n\n\tDUK_DD(DUK_DDPRINT(\"about to longjmp, pf_prevent_count=%ld\", (long) thr->heap->pf_prevent_count));\n\n#if !defined(DUK_USE_CPP_EXCEPTIONS)\n\t/* If we don't have a jmpbuf_ptr, there is little we can do except\n\t * cause a fatal error.  The caller's expectation is that we never\n\t * return.\n\t *\n\t * With C++ exceptions we now just propagate an uncaught error\n\t * instead of invoking the fatal error handler.  Because there's\n\t * a dummy jmpbuf for C++ exceptions now, this could be changed.\n\t */\n\tif (!thr->heap->lj.jmpbuf_ptr) {\n\t\tDUK_D(DUK_DPRINT(\"uncaught error: type=%d iserror=%d value1=%!T value2=%!T\",\n\t\t                 (int) thr->heap->lj.type, (int) thr->heap->lj.iserror,\n\t\t                 &thr->heap->lj.value1, &thr->heap->lj.value2));\n\n#if defined(DUK_USE_PREFER_SIZE)\n\t\tduk__uncaught_minimal(thr);\n#else\n\t\tduk__uncaught_error_aware(thr);\n#endif\n\t\tDUK_UNREACHABLE();\n\t}\n#endif  /* DUK_USE_CPP_EXCEPTIONS */\n\n#if defined(DUK_USE_CPP_EXCEPTIONS)\n\t{\n\t\tduk_internal_exception exc;  /* dummy */\n\t\tthrow exc;\n\t}\n#else  /* DUK_USE_CPP_EXCEPTIONS */\n\tDUK_LONGJMP(thr->heap->lj.jmpbuf_ptr->jb);\n#endif  /* DUK_USE_CPP_EXCEPTIONS */\n\n\tDUK_UNREACHABLE();\n}\n#line 1 \"duk_error_misc.c\"\n/*\n *  Error helpers\n */\n\n/* #include duk_internal.h -> already included */\n\n/*\n *  Helper to walk the thread chain and see if there is an active error\n *  catcher.  Protected calls or finally blocks aren't considered catching.\n */\n\n#if defined(DUK_USE_DEBUGGER_SUPPORT)\nDUK_LOCAL duk_bool_t duk__have_active_catcher(duk_hthread *thr) {\n\t/* As noted above, a protected API call won't be counted as a\n\t * catcher.  This is usually convenient, e.g. in the case of a top-\n\t * level duk_pcall(), but may not always be desirable.  Perhaps add\n\t * an argument to treat them as catchers?\n\t */\n\n\tduk_activation *act;\n\tduk_catcher *cat;\n\n\tDUK_ASSERT(thr != NULL);\n\n\tfor (; thr != NULL; thr = thr->resumer) {\n\t\tfor (act = thr->callstack_curr; act != NULL; act = act->parent) {\n\t\t\tfor (cat = act->cat; cat != NULL; cat = cat->parent) {\n\t\t\t\tif (DUK_CAT_HAS_CATCH_ENABLED(cat)) {\n\t\t\t\t\treturn 1;  /* all we need to know */\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn 0;\n}\n#endif  /* DUK_USE_DEBUGGER_SUPPORT */\n\n/*\n *  Get prototype object for an integer error code.\n */\n\nDUK_INTERNAL duk_hobject *duk_error_prototype_from_code(duk_hthread *thr, duk_errcode_t code) {\n\tswitch (code) {\n\tcase DUK_ERR_EVAL_ERROR:\n\t\treturn thr->builtins[DUK_BIDX_EVAL_ERROR_PROTOTYPE];\n\tcase DUK_ERR_RANGE_ERROR:\n\t\treturn thr->builtins[DUK_BIDX_RANGE_ERROR_PROTOTYPE];\n\tcase DUK_ERR_REFERENCE_ERROR:\n\t\treturn thr->builtins[DUK_BIDX_REFERENCE_ERROR_PROTOTYPE];\n\tcase DUK_ERR_SYNTAX_ERROR:\n\t\treturn thr->builtins[DUK_BIDX_SYNTAX_ERROR_PROTOTYPE];\n\tcase DUK_ERR_TYPE_ERROR:\n\t\treturn thr->builtins[DUK_BIDX_TYPE_ERROR_PROTOTYPE];\n\tcase DUK_ERR_URI_ERROR:\n\t\treturn thr->builtins[DUK_BIDX_URI_ERROR_PROTOTYPE];\n\tcase DUK_ERR_ERROR:\n\tdefault:\n\t\treturn thr->builtins[DUK_BIDX_ERROR_PROTOTYPE];\n\t}\n}\n\n/*\n *  Helper for debugger throw notify and pause-on-uncaught integration.\n */\n\n#if defined(DUK_USE_DEBUGGER_SUPPORT)\nDUK_INTERNAL void duk_err_check_debugger_integration(duk_hthread *thr) {\n\tduk_bool_t uncaught;\n\tduk_tval *tv_obj;\n\n\t/* If something is thrown with the debugger attached and nobody will\n\t * catch it, execution is paused before the longjmp, turning over\n\t * control to the debug client.  This allows local state to be examined\n\t * before the stack is unwound.  Errors are not intercepted when debug\n\t * message loop is active (e.g. for Eval).\n\t */\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(thr->heap != NULL);\n\n\t/* XXX: Allow customizing the pause and notify behavior at runtime\n\t * using debugger runtime flags.  For now the behavior is fixed using\n\t * config options.\n\t */\n\n\tif (!duk_debug_is_attached(thr->heap) ||\n\t    thr->heap->dbg_processing ||\n\t    thr->heap->lj.type != DUK_LJ_TYPE_THROW ||\n\t    thr->heap->creating_error) {\n\t\tDUK_D(DUK_DPRINT(\"skip debugger error integration; not attached, debugger processing, not THROW, or error thrown while creating error\"));\n\t\treturn;\n\t}\n\n\t/* Don't intercept a DoubleError, we may have caused the initial double\n\t * fault and attempting to intercept it will cause us to be called\n\t * recursively and exhaust the C stack.  (This should no longer happen\n\t * for the initial throw because DoubleError path doesn't do a debugger\n\t * integration check, but it might happen for rethrows.)\n\t */\n\ttv_obj = &thr->heap->lj.value1;\n\tif (DUK_TVAL_IS_OBJECT(tv_obj) && DUK_TVAL_GET_OBJECT(tv_obj) == thr->builtins[DUK_BIDX_DOUBLE_ERROR]) {\n\t\tDUK_D(DUK_DPRINT(\"built-in DoubleError instance (re)thrown, not intercepting\"));\n\t\treturn;\n\t}\n\n\tuncaught = !duk__have_active_catcher(thr);\n\n\t/* Debugger code expects the value at stack top.  This also serves\n\t * as a backup: we need to store/restore the longjmp state because\n\t * when the debugger is paused Eval commands may be executed and\n\t * they can arbitrarily clobber the longjmp state.\n\t */\n\tduk_push_tval(thr, tv_obj);\n\n\t/* Store and reset longjmp state. */\n\tDUK_ASSERT_LJSTATE_SET(thr->heap);\n\tDUK_TVAL_DECREF_NORZ(thr, tv_obj);\n\tDUK_ASSERT(DUK_TVAL_IS_UNDEFINED(&thr->heap->lj.value2));  /* Always for THROW type. */\n\tDUK_TVAL_SET_UNDEFINED(tv_obj);\n\tthr->heap->lj.type = DUK_LJ_TYPE_UNKNOWN;\n\tDUK_ASSERT_LJSTATE_UNSET(thr->heap);\n\n#if defined(DUK_USE_DEBUGGER_THROW_NOTIFY)\n\t/* Report it to the debug client */\n\tDUK_D(DUK_DPRINT(\"throw with debugger attached, report to client\"));\n\tduk_debug_send_throw(thr, uncaught);\n#endif\n\n\tif (uncaught) {\n\t\tif (thr->heap->dbg_pause_flags & DUK_PAUSE_FLAG_UNCAUGHT_ERROR) {\n\t\t\tDUK_D(DUK_DPRINT(\"PAUSE TRIGGERED by uncaught error\"));\n\t\t\tduk_debug_halt_execution(thr, 1 /*use_prev_pc*/);\n\t\t}\n\t} else {\n\t\tif (thr->heap->dbg_pause_flags & DUK_PAUSE_FLAG_CAUGHT_ERROR) {\n\t\t\tDUK_D(DUK_DPRINT(\"PAUSE TRIGGERED by caught error\"));\n\t\t\tduk_debug_halt_execution(thr, 1 /*use_prev_pc*/);\n\t\t}\n\t}\n\n\t/* Restore longjmp state. */\n\tDUK_ASSERT_LJSTATE_UNSET(thr->heap);\n\tthr->heap->lj.type = DUK_LJ_TYPE_THROW;\n\ttv_obj = DUK_GET_TVAL_NEGIDX(thr, -1);\n\tDUK_ASSERT(DUK_TVAL_IS_UNDEFINED(&thr->heap->lj.value1));\n\tDUK_ASSERT(DUK_TVAL_IS_UNDEFINED(&thr->heap->lj.value2));\n\tDUK_TVAL_SET_TVAL(&thr->heap->lj.value1, tv_obj);\n\tDUK_TVAL_INCREF(thr, tv_obj);\n\tDUK_ASSERT_LJSTATE_SET(thr->heap);\n\n\tduk_pop(thr);\n}\n#endif  /* DUK_USE_DEBUGGER_SUPPORT */\n\n/*\n *  Helpers for setting up heap longjmp state.\n */\n\nDUK_INTERNAL void duk_err_setup_ljstate1(duk_hthread *thr, duk_small_uint_t lj_type, duk_tval *tv_val) {\n\tduk_heap *heap;\n\n\tDUK_ASSERT(thr != NULL);\n\theap = thr->heap;\n\tDUK_ASSERT(heap != NULL);\n\tDUK_ASSERT(tv_val != NULL);\n\n\tDUK_ASSERT_LJSTATE_UNSET(heap);\n\n\theap->lj.type = lj_type;\n\tDUK_TVAL_SET_TVAL(&heap->lj.value1, tv_val);\n\tDUK_TVAL_INCREF(thr, tv_val);\n\n\tDUK_ASSERT_LJSTATE_SET(heap);\n}\n#line 1 \"duk_error_throw.c\"\n/*\n *  Create and throw an Ecmascript error object based on a code and a message.\n *\n *  Used when we throw errors internally.  Ecmascript generated error objects\n *  are created by Ecmascript code, and the throwing is handled by the bytecode\n *  executor.\n */\n\n/* #include duk_internal.h -> already included */\n\n/*\n *  Create and throw an error (originating from Duktape internally)\n *\n *  Push an error object on top of the stack, possibly throw augmenting\n *  the error, and finally longjmp.\n *\n *  If an error occurs while we're dealing with the current error, we might\n *  enter an infinite recursion loop.  This is prevented by detecting a\n *  \"double fault\" through the heap->creating_error flag; the recursion\n *  then stops at the second level.\n */\n\n#if defined(DUK_USE_VERBOSE_ERRORS)\nDUK_INTERNAL void duk_err_create_and_throw(duk_hthread *thr, duk_errcode_t code, const char *msg, const char *filename, duk_int_t line) {\n#else\nDUK_INTERNAL void duk_err_create_and_throw(duk_hthread *thr, duk_errcode_t code) {\n#endif\n#if defined(DUK_USE_VERBOSE_ERRORS)\n\tDUK_DD(DUK_DDPRINT(\"duk_err_create_and_throw(): code=%ld, msg=%s, filename=%s, line=%ld\",\n\t                   (long) code, (const char *) msg,\n\t                   (const char *) filename, (long) line));\n#else\n\tDUK_DD(DUK_DDPRINT(\"duk_err_create_and_throw(): code=%ld\", (long) code));\n#endif\n\n\tDUK_ASSERT(thr != NULL);\n\n\t/* Even though nested call is possible because we throw an error when\n\t * trying to create an error, the potential errors must happen before\n\t * the longjmp state is configured.\n\t */\n\tDUK_ASSERT_LJSTATE_UNSET(thr->heap);\n\n\t/* Sync so that augmentation sees up-to-date activations, NULL\n\t * thr->ptr_curr_pc so that it's not used if side effects occur\n\t * in augmentation or longjmp handling.\n\t */\n\tduk_hthread_sync_and_null_currpc(thr);\n\n\t/*\n\t *  Create and push an error object onto the top of stack.\n\t *  The error is potentially augmented before throwing.\n\t *\n\t *  If a \"double error\" occurs, use a fixed error instance\n\t *  to avoid further trouble.\n\t */\n\n\tif (thr->heap->creating_error) {\n\t\tduk_tval tv_val;\n\t\tduk_hobject *h_err;\n\n\t\tthr->heap->creating_error = 0;\n\n\t\th_err = thr->builtins[DUK_BIDX_DOUBLE_ERROR];\n\t\tif (h_err != NULL) {\n\t\t\tDUK_D(DUK_DPRINT(\"double fault detected -> use built-in fixed 'double error' instance\"));\n\t\t\tDUK_TVAL_SET_OBJECT(&tv_val, h_err);\n\t\t} else {\n\t\t\tDUK_D(DUK_DPRINT(\"double fault detected; there is no built-in fixed 'double error' instance \"\n\t\t\t                 \"-> use the error code as a number\"));\n\t\t\tDUK_TVAL_SET_I32(&tv_val, (duk_int32_t) code);\n\t\t}\n\n\t\tduk_err_setup_ljstate1(thr, DUK_LJ_TYPE_THROW, &tv_val);\n\n\t\t/* No augmentation to avoid any allocations or side effects. */\n\t} else {\n\t\t/* Prevent infinite recursion.  Extra call stack and C\n\t\t * recursion headroom (see GH-191) is added for augmentation.\n\t\t * That is now signalled by heap->augmenting error and taken\n\t\t * into account in call handling without an explicit limit bump.\n\t\t */\n\t\tthr->heap->creating_error = 1;\n\n\t\tduk_require_stack(thr, 1);\n\n\t\t/* XXX: usually unnecessary '%s' formatting here, but cannot\n\t\t * use 'msg' as a format string directly.\n\t\t */\n#if defined(DUK_USE_VERBOSE_ERRORS)\n\t\tduk_push_error_object_raw(thr,\n\t\t                          code | DUK_ERRCODE_FLAG_NOBLAME_FILELINE,\n\t\t                          filename,\n\t\t                          line,\n\t\t                          \"%s\",\n\t\t                          (const char *) msg);\n#else\n\t\tduk_push_error_object_raw(thr,\n\t\t                          code | DUK_ERRCODE_FLAG_NOBLAME_FILELINE,\n\t\t                          NULL,\n\t\t                          0,\n\t\t                          NULL);\n#endif\n\n\t\t/* Note that an alloc error may happen during error augmentation.\n\t\t * This may happen both when the original error is an alloc error\n\t\t * and when it's something else.  Because any error in augmentation\n\t\t * must be handled correctly anyway, there's no special check for\n\t\t * avoiding it for alloc errors (this differs from Duktape 1.x).\n\t\t */\n#if defined(DUK_USE_AUGMENT_ERROR_THROW)\n\t\tDUK_DDD(DUK_DDDPRINT(\"THROW ERROR (INTERNAL): %!iT (before throw augment)\",\n\t\t                     (duk_tval *) duk_get_tval(thr, -1)));\n\t\tduk_err_augment_error_throw(thr);\n#endif\n\n\t\tduk_err_setup_ljstate1(thr, DUK_LJ_TYPE_THROW, DUK_GET_TVAL_NEGIDX(thr, -1));\n\t\tthr->heap->creating_error = 0;\n\n\t\t/* Error is now created and we assume no errors can occur any\n\t\t * more.  Check for debugger Throw integration only when the\n\t\t * error is complete.  If we enter debugger message loop,\n\t\t * creating_error must be 0 so that errors can be thrown in\n\t\t * the paused state, e.g. in Eval commands.\n\t\t */\n#if defined(DUK_USE_DEBUGGER_SUPPORT)\n\t\tduk_err_check_debugger_integration(thr);\n#endif\n\t}\n\n\t/*\n\t *  Finally, longjmp\n\t */\n\n\tDUK_DDD(DUK_DDDPRINT(\"THROW ERROR (INTERNAL): %!iT, %!iT (after throw augment)\",\n\t                     (duk_tval *) &thr->heap->lj.value1, (duk_tval *) &thr->heap->lj.value2));\n\n\tduk_err_longjmp(thr);\n\tDUK_UNREACHABLE();\n}\n\n/*\n *  Helper for C function call negative return values.\n */\n\nDUK_INTERNAL void duk_error_throw_from_negative_rc(duk_hthread *thr, duk_ret_t rc) {\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(rc < 0);\n\n\t/*\n\t *  The __FILE__ and __LINE__ information is intentionally not used in the\n\t *  creation of the error object, as it isn't useful in the tracedata.  The\n\t *  tracedata still contains the function which returned the negative return\n\t *  code, and having the file/line of this function isn't very useful.\n\t *\n\t *  The error messages for DUK_RET_xxx shorthand are intentionally very\n\t *  minimal: they're only really useful for low memory targets.\n\t */\n\n\tduk_error_raw(thr, -rc, NULL, 0, \"error (rc %ld)\", (long) rc);\n\tDUK_UNREACHABLE();\n}\n#line 1 \"duk_hbuffer_alloc.c\"\n/*\n *  duk_hbuffer allocation and freeing.\n */\n\n/* #include duk_internal.h -> already included */\n\n/* Allocate a new duk_hbuffer of a certain type and return a pointer to it\n * (NULL on error).  Write buffer data pointer to 'out_bufdata' (only if\n * allocation successful).\n */\nDUK_INTERNAL duk_hbuffer *duk_hbuffer_alloc(duk_heap *heap, duk_size_t size, duk_small_uint_t flags, void **out_bufdata) {\n\tduk_hbuffer *res = NULL;\n\tduk_size_t header_size;\n\tduk_size_t alloc_size;\n\n\tDUK_ASSERT(heap != NULL);\n\tDUK_ASSERT(out_bufdata != NULL);\n\n\tDUK_DDD(DUK_DDDPRINT(\"allocate hbuffer\"));\n\n\t/* Size sanity check.  Should not be necessary because caller is\n\t * required to check this, but we don't want to cause a segfault\n\t * if the size wraps either in duk_size_t computation or when\n\t * storing the size in a 16-bit field.\n\t */\n\tif (size > DUK_HBUFFER_MAX_BYTELEN) {\n\t\tDUK_D(DUK_DPRINT(\"hbuffer alloc failed: size too large: %ld\", (long) size));\n\t\treturn NULL;  /* no need to write 'out_bufdata' */\n\t}\n\n\tif (flags & DUK_BUF_FLAG_EXTERNAL) {\n\t\theader_size = sizeof(duk_hbuffer_external);\n\t\talloc_size = sizeof(duk_hbuffer_external);\n\t} else if (flags & DUK_BUF_FLAG_DYNAMIC) {\n\t\theader_size = sizeof(duk_hbuffer_dynamic);\n\t\talloc_size = sizeof(duk_hbuffer_dynamic);\n\t} else {\n\t\theader_size = sizeof(duk_hbuffer_fixed);\n\t\talloc_size = sizeof(duk_hbuffer_fixed) + size;\n\t\tDUK_ASSERT(alloc_size >= sizeof(duk_hbuffer_fixed));  /* no wrapping */\n\t}\n\n\tres = (duk_hbuffer *) DUK_ALLOC(heap, alloc_size);\n\tif (DUK_UNLIKELY(res == NULL)) {\n\t\tgoto alloc_error;\n\t}\n\n\t/* zero everything unless requested not to do so */\n#if defined(DUK_USE_ZERO_BUFFER_DATA)\n\tDUK_MEMZERO((void *) res,\n\t            (flags & DUK_BUF_FLAG_NOZERO) ? header_size : alloc_size);\n#else\n\tDUK_MEMZERO((void *) res, header_size);\n#endif\n\n\tif (flags & DUK_BUF_FLAG_EXTERNAL) {\n\t\tduk_hbuffer_external *h;\n\t\th = (duk_hbuffer_external *) res;\n\t\tDUK_UNREF(h);\n\t\t*out_bufdata = NULL;\n#if defined(DUK_USE_EXPLICIT_NULL_INIT)\n#if defined(DUK_USE_HEAPPTR16)\n/* the compressed pointer is zeroed which maps to NULL, so nothing to do. */\n#else\n\t\tDUK_HBUFFER_EXTERNAL_SET_DATA_PTR(heap, h, NULL);\n#endif\n#endif\n\t\tDUK_ASSERT(DUK_HBUFFER_EXTERNAL_GET_DATA_PTR(heap, h) == NULL);\n\t} else if (flags & DUK_BUF_FLAG_DYNAMIC) {\n\t\tduk_hbuffer_dynamic *h = (duk_hbuffer_dynamic *) res;\n\t\tvoid *ptr;\n\n\t\tif (size > 0) {\n\t\t\tDUK_ASSERT(!(flags & DUK_BUF_FLAG_EXTERNAL));  /* alloc external with size zero */\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"dynamic buffer with nonzero size, alloc actual buffer\"));\n#if defined(DUK_USE_ZERO_BUFFER_DATA)\n\t\t\tptr = DUK_ALLOC_ZEROED(heap, size);\n#else\n\t\t\tptr = DUK_ALLOC(heap, size);\n#endif\n\t\t\tif (DUK_UNLIKELY(ptr == NULL)) {\n\t\t\t\t/* Because size > 0, NULL check is correct */\n\t\t\t\tgoto alloc_error;\n\t\t\t}\n\t\t\t*out_bufdata = ptr;\n\n\t\t\tDUK_HBUFFER_DYNAMIC_SET_DATA_PTR(heap, h, ptr);\n\t\t} else {\n\t\t\t*out_bufdata = NULL;\n#if defined(DUK_USE_EXPLICIT_NULL_INIT)\n#if defined(DUK_USE_HEAPPTR16)\n/* the compressed pointer is zeroed which maps to NULL, so nothing to do. */\n#else\n\t\t\tDUK_HBUFFER_DYNAMIC_SET_DATA_PTR(heap, h, NULL);\n#endif\n#endif\n\t\t\tDUK_ASSERT(DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(heap, h) == NULL);\n\t\t}\n\t} else {\n\t\t*out_bufdata = (void *) ((duk_hbuffer_fixed *) res + 1);\n\t}\n\n\tDUK_HBUFFER_SET_SIZE(res, size);\n\n\tDUK_HEAPHDR_SET_TYPE(&res->hdr, DUK_HTYPE_BUFFER);\n\tif (flags & DUK_BUF_FLAG_DYNAMIC) {\n\t\tDUK_HBUFFER_SET_DYNAMIC(res);\n\t\tif (flags & DUK_BUF_FLAG_EXTERNAL) {\n\t\t\tDUK_HBUFFER_SET_EXTERNAL(res);\n\t\t}\n\t} else {\n\t\tDUK_ASSERT(!(flags & DUK_BUF_FLAG_EXTERNAL));\n\t}\n        DUK_HEAP_INSERT_INTO_HEAP_ALLOCATED(heap, &res->hdr);\n\n\tDUK_DDD(DUK_DDDPRINT(\"allocated hbuffer: %p\", (void *) res));\n\treturn res;\n\n alloc_error:\n\tDUK_DD(DUK_DDPRINT(\"hbuffer allocation failed\"));\n\n\tDUK_FREE(heap, res);\n\treturn NULL;  /* no need to write 'out_bufdata' */\n}\n\n/* For indirect allocs. */\n\nDUK_INTERNAL void *duk_hbuffer_get_dynalloc_ptr(duk_heap *heap, void *ud) {\n\tduk_hbuffer_dynamic *buf = (duk_hbuffer_dynamic *) ud;\n\tDUK_UNREF(heap);\n\treturn (void *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(heap, buf);\n}\n#line 1 \"duk_hbuffer_ops.c\"\n/*\n *  duk_hbuffer operations such as resizing and inserting/appending data to\n *  a dynamic buffer.\n */\n\n/* #include duk_internal.h -> already included */\n\n/*\n *  Resizing\n */\n\nDUK_INTERNAL void duk_hbuffer_resize(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_size_t new_size) {\n\tvoid *res;\n\tduk_size_t prev_size;\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(buf != NULL);\n\tDUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(buf));\n\tDUK_ASSERT(!DUK_HBUFFER_HAS_EXTERNAL(buf));\n\n\t/*\n\t *  Maximum size check\n\t */\n\n\tif (new_size > DUK_HBUFFER_MAX_BYTELEN) {\n\t\tDUK_ERROR_RANGE(thr, \"buffer too long\");\n\t}\n\n\t/*\n\t *  Note: use indirect realloc variant just in case mark-and-sweep\n\t *  (finalizers) might resize this same buffer during garbage\n\t *  collection.\n\t */\n\n\tres = DUK_REALLOC_INDIRECT(thr->heap, duk_hbuffer_get_dynalloc_ptr, (void *) buf, new_size);\n\tif (DUK_LIKELY(res != NULL || new_size == 0)) {\n\t\t/* 'res' may be NULL if new allocation size is 0. */\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"resized dynamic buffer %p:%ld -> %p:%ld\",\n\t\t                     (void *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, buf),\n\t\t                     (long) DUK_HBUFFER_DYNAMIC_GET_SIZE(buf),\n\t\t                     (void *) res,\n\t\t                     (long) new_size));\n\n\t\t/*\n\t\t *  The entire allocated buffer area, regardless of actual used\n\t\t *  size, is kept zeroed in resizes for simplicity.  If the buffer\n\t\t *  is grown, zero the new part.\n\t\t */\n\n\t\tprev_size = DUK_HBUFFER_DYNAMIC_GET_SIZE(buf);\n\t\tif (new_size > prev_size) {\n\t\t\tDUK_ASSERT(new_size - prev_size > 0);\n#if defined(DUK_USE_ZERO_BUFFER_DATA)\n\t\t\tDUK_MEMZERO((void *) ((char *) res + prev_size),\n\t\t\t            (duk_size_t) (new_size - prev_size));\n#endif\n\t\t}\n\n\t\tDUK_HBUFFER_DYNAMIC_SET_SIZE(buf, new_size);\n\t\tDUK_HBUFFER_DYNAMIC_SET_DATA_PTR(thr->heap, buf, res);\n\t} else {\n\t\tDUK_ERROR_ALLOC_FAILED(thr);\n\t}\n\n\tDUK_ASSERT(res != NULL || new_size == 0);\n}\n\nDUK_INTERNAL void duk_hbuffer_reset(duk_hthread *thr, duk_hbuffer_dynamic *buf) {\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(buf != NULL);\n\tDUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(buf));\n\tDUK_ASSERT(!DUK_HBUFFER_HAS_EXTERNAL(buf));\n\n\tduk_hbuffer_resize(thr, buf, 0);\n}\n/* #include duk_internal.h -> already included */\n#line 2 \"duk_hbufobj_misc.c\"\n\n#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)\nDUK_INTERNAL duk_uint_t duk_hbufobj_clamp_bytelength(duk_hbufobj *h_bufobj, duk_uint_t len) {\n\tduk_uint_t buf_size;\n\tduk_uint_t buf_avail;\n\n\tDUK_ASSERT(h_bufobj != NULL);\n\tDUK_ASSERT(h_bufobj->buf != NULL);\n\n\tbuf_size = (duk_uint_t) DUK_HBUFFER_GET_SIZE(h_bufobj->buf);\n\tif (h_bufobj->offset > buf_size) {\n\t\t/* Slice starting point is beyond current length. */\n\t\treturn 0;\n\t}\n\tbuf_avail = buf_size - h_bufobj->offset;\n\n\treturn buf_avail >= len ? len : buf_avail;\n}\n#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */\n#line 1 \"duk_heap_alloc.c\"\n/*\n *  duk_heap allocation and freeing.\n */\n\n/* #include duk_internal.h -> already included */\n\n#if defined(DUK_USE_ROM_STRINGS)\n/* Fixed seed value used with ROM strings. */\n#define DUK__FIXED_HASH_SEED       0xabcd1234\n#endif\n\n/*\n *  Free a heap object.\n *\n *  Free heap object and its internal (non-heap) pointers.  Assumes that\n *  caller has removed the object from heap allocated list or the string\n *  intern table, and any weak references (which strings may have) have\n *  been already dealt with.\n */\n\nDUK_INTERNAL void duk_free_hobject(duk_heap *heap, duk_hobject *h) {\n\tDUK_ASSERT(heap != NULL);\n\tDUK_ASSERT(h != NULL);\n\n\tDUK_FREE(heap, DUK_HOBJECT_GET_PROPS(heap, h));\n\n\tif (DUK_HOBJECT_IS_COMPFUNC(h)) {\n\t\tduk_hcompfunc *f = (duk_hcompfunc *) h;\n\t\tDUK_UNREF(f);\n\t\t/* Currently nothing to free; 'data' is a heap object */\n\t} else if (DUK_HOBJECT_IS_NATFUNC(h)) {\n\t\tduk_hnatfunc *f = (duk_hnatfunc *) h;\n\t\tDUK_UNREF(f);\n\t\t/* Currently nothing to free */\n\t} else if (DUK_HOBJECT_IS_THREAD(h)) {\n\t\tduk_hthread *t = (duk_hthread *) h;\n\t\tduk_activation *act;\n\n\t\tDUK_FREE(heap, t->valstack);\n\n\t\t/* Don't free h->resumer because it exists in the heap.\n\t\t * Callstack entries also contain function pointers which\n\t\t * are not freed for the same reason.  They are decref\n\t\t * finalized and the targets are freed if necessary based\n\t\t * on their refcount (or reachability).\n\t\t */\n\t\tfor (act = t->callstack_curr; act != NULL;) {\n\t\t\tduk_activation *act_next;\n\t\t\tduk_catcher *cat;\n\n\t\t\tfor (cat = act->cat; cat != NULL;) {\n\t\t\t\tduk_catcher *cat_next;\n\n\t\t\t\tcat_next = cat->parent;\n\t\t\t\tDUK_FREE(heap, (void *) cat);\n\t\t\t\tcat = cat_next;\n\t\t\t}\n\n\t\t\tact_next = act->parent;\n\t\t\tDUK_FREE(heap, (void *) act);\n\t\t\tact = act_next;\n\t\t}\n\n\t\t/* XXX: with 'caller' property the callstack would need\n\t\t * to be unwound to update the 'caller' properties of\n\t\t * functions in the callstack.\n\t\t */\n\t} else if (DUK_HOBJECT_IS_BOUNDFUNC(h)) {\n\t\tduk_hboundfunc *f = (duk_hboundfunc *) h;\n\n\t\tDUK_FREE(heap, f->args);\n\t}\n\n\tDUK_FREE(heap, (void *) h);\n}\n\nDUK_INTERNAL void duk_free_hbuffer(duk_heap *heap, duk_hbuffer *h) {\n\tDUK_ASSERT(heap != NULL);\n\tDUK_ASSERT(h != NULL);\n\n\tif (DUK_HBUFFER_HAS_DYNAMIC(h) && !DUK_HBUFFER_HAS_EXTERNAL(h)) {\n\t\tduk_hbuffer_dynamic *g = (duk_hbuffer_dynamic *) h;\n\t\tDUK_DDD(DUK_DDDPRINT(\"free dynamic buffer %p\", (void *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(heap, g)));\n\t\tDUK_FREE(heap, DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(heap, g));\n\t}\n\tDUK_FREE(heap, (void *) h);\n}\n\nDUK_INTERNAL void duk_free_hstring(duk_heap *heap, duk_hstring *h) {\n\tDUK_ASSERT(heap != NULL);\n\tDUK_ASSERT(h != NULL);\n\n\tDUK_UNREF(heap);\n\tDUK_UNREF(h);\n\n#if defined(DUK_USE_HSTRING_EXTDATA) && defined(DUK_USE_EXTSTR_FREE)\n\tif (DUK_HSTRING_HAS_EXTDATA(h)) {\n\t\tDUK_DDD(DUK_DDDPRINT(\"free extstr: hstring %!O, extdata: %p\",\n\t\t                     h, DUK_HSTRING_GET_EXTDATA((duk_hstring_external *) h)));\n\t\tDUK_USE_EXTSTR_FREE(heap->heap_udata, (const void *) DUK_HSTRING_GET_EXTDATA((duk_hstring_external *) h));\n\t}\n#endif\n\tDUK_FREE(heap, (void *) h);\n}\n\nDUK_INTERNAL void duk_heap_free_heaphdr_raw(duk_heap *heap, duk_heaphdr *hdr) {\n\tDUK_ASSERT(heap);\n\tDUK_ASSERT(hdr);\n\n\tDUK_DDD(DUK_DDDPRINT(\"free heaphdr %p, htype %ld\", (void *) hdr, (long) DUK_HEAPHDR_GET_TYPE(hdr)));\n\n\tswitch (DUK_HEAPHDR_GET_TYPE(hdr)) {\n\tcase DUK_HTYPE_STRING:\n\t\tduk_free_hstring(heap, (duk_hstring *) hdr);\n\t\tbreak;\n\tcase DUK_HTYPE_OBJECT:\n\t\tduk_free_hobject(heap, (duk_hobject *) hdr);\n\t\tbreak;\n\tdefault:\n\t\tDUK_ASSERT(DUK_HEAPHDR_GET_TYPE(hdr) == DUK_HTYPE_BUFFER);\n\t\tduk_free_hbuffer(heap, (duk_hbuffer *) hdr);\n\t}\n\n}\n\n/*\n *  Free the heap.\n *\n *  Frees heap-related non-heap-tracked allocations such as the\n *  string intern table; then frees the heap allocated objects;\n *  and finally frees the heap structure itself.  Reference counts\n *  and GC markers are ignored (and not updated) in this process,\n *  and finalizers won't be called.\n *\n *  The heap pointer and heap object pointers must not be used\n *  after this call.\n */\n\n#if defined(DUK_USE_CACHE_ACTIVATION)\nDUK_LOCAL duk_size_t duk__heap_free_activation_freelist(duk_heap *heap) {\n\tduk_activation *act;\n\tduk_activation *act_next;\n\tduk_size_t count_act = 0;\n\n\tfor (act = heap->activation_free; act != NULL;) {\n\t\tact_next = act->parent;\n\t\tDUK_FREE(heap, (void *) act);\n\t\tact = act_next;\n#if defined(DUK_USE_DEBUG)\n\t\tcount_act++;\n#endif\n\t}\n\theap->activation_free = NULL;  /* needed when called from mark-and-sweep */\n\treturn count_act;\n}\n#endif  /* DUK_USE_CACHE_ACTIVATION */\n\n#if defined(DUK_USE_CACHE_CATCHER)\nDUK_LOCAL duk_size_t duk__heap_free_catcher_freelist(duk_heap *heap) {\n\tduk_catcher *cat;\n\tduk_catcher *cat_next;\n\tduk_size_t count_cat = 0;\n\n\tfor (cat = heap->catcher_free; cat != NULL;) {\n\t\tcat_next = cat->parent;\n\t\tDUK_FREE(heap, (void *) cat);\n\t\tcat = cat_next;\n#if defined(DUK_USE_DEBUG)\n\t\tcount_cat++;\n#endif\n\t}\n\theap->catcher_free = NULL;  /* needed when called from mark-and-sweep */\n\n\treturn count_cat;\n}\n#endif  /* DUK_USE_CACHE_CATCHER */\n\nDUK_INTERNAL void duk_heap_free_freelists(duk_heap *heap) {\n\tduk_size_t count_act = 0;\n\tduk_size_t count_cat = 0;\n\n#if defined(DUK_USE_CACHE_ACTIVATION)\n\tcount_act = duk__heap_free_activation_freelist(heap);\n#endif\n#if defined(DUK_USE_CACHE_CATCHER)\n\tcount_cat = duk__heap_free_catcher_freelist(heap);\n#endif\n\tDUK_UNREF(heap);\n\tDUK_UNREF(count_act);\n\tDUK_UNREF(count_cat);\n\n\tDUK_D(DUK_DPRINT(\"freed %ld activation freelist entries, %ld catcher freelist entries\",\n\t                 (long) count_act, (long) count_cat));\n}\n\nDUK_LOCAL void duk__free_allocated(duk_heap *heap) {\n\tduk_heaphdr *curr;\n\tduk_heaphdr *next;\n\n\tcurr = heap->heap_allocated;\n\twhile (curr) {\n\t\t/* We don't log or warn about freeing zero refcount objects\n\t\t * because they may happen with finalizer processing.\n\t\t */\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"FINALFREE (allocated): %!iO\",\n\t\t                     (duk_heaphdr *) curr));\n\t\tnext = DUK_HEAPHDR_GET_NEXT(heap, curr);\n\t\tduk_heap_free_heaphdr_raw(heap, curr);\n\t\tcurr = next;\n\t}\n}\n\n#if defined(DUK_USE_FINALIZER_SUPPORT)\nDUK_LOCAL void duk__free_finalize_list(duk_heap *heap) {\n\tduk_heaphdr *curr;\n\tduk_heaphdr *next;\n\n\tcurr = heap->finalize_list;\n\twhile (curr) {\n\t\tDUK_DDD(DUK_DDDPRINT(\"FINALFREE (finalize_list): %!iO\",\n\t\t                     (duk_heaphdr *) curr));\n\t\tnext = DUK_HEAPHDR_GET_NEXT(heap, curr);\n\t\tduk_heap_free_heaphdr_raw(heap, curr);\n\t\tcurr = next;\n\t}\n}\n#endif  /* DUK_USE_FINALIZER_SUPPORT */\n\nDUK_LOCAL void duk__free_stringtable(duk_heap *heap) {\n\t/* strings are only tracked by stringtable */\n\tduk_heap_strtable_free(heap);\n}\n\n#if defined(DUK_USE_FINALIZER_SUPPORT)\nDUK_LOCAL void duk__free_run_finalizers(duk_heap *heap) {\n\tduk_heaphdr *curr;\n\tduk_uint_t round_no;\n\tduk_size_t count_all;\n\tduk_size_t count_finalized;\n\tduk_size_t curr_limit;\n\n\tDUK_ASSERT(heap != NULL);\n\n#if defined(DUK_USE_REFERENCE_COUNTING)\n\tDUK_ASSERT(heap->refzero_list == NULL);  /* refzero not running -> must be empty */\n#endif\n\tDUK_ASSERT(heap->finalize_list == NULL);  /* mark-and-sweep last pass */\n\n\tif (heap->heap_thread == NULL) {\n\t\t/* May happen when heap allocation fails right off.  There\n\t\t * cannot be any finalizable objects in this case.\n\t\t */\n\t\tDUK_D(DUK_DPRINT(\"no heap_thread in heap destruct, assume no finalizable objects\"));\n\t\treturn;\n\t}\n\n\t/* Prevent finalize_list processing and mark-and-sweep entirely.\n\t * Setting ms_running = 1 also prevents refzero handling from moving\n\t * objects away from the heap_allocated list (the flag name is a bit\n\t * misleading here).\n\t */\n\tDUK_ASSERT(heap->pf_prevent_count == 0);\n\theap->pf_prevent_count = 1;\n\tDUK_ASSERT(heap->ms_running == 0);\n\theap->ms_running = 1;\n\tDUK_ASSERT(heap->ms_prevent_count == 0);\n\theap->ms_prevent_count = 1;  /* Bump, because mark-and-sweep assumes it's bumped when ms_running is set. */\n\n\tcurr_limit = 0;  /* suppress warning, not used */\n\tfor (round_no = 0; ; round_no++) {\n\t\tcurr = heap->heap_allocated;\n\t\tcount_all = 0;\n\t\tcount_finalized = 0;\n\t\twhile (curr) {\n\t\t\tcount_all++;\n\t\t\tif (DUK_HEAPHDR_IS_OBJECT(curr)) {\n\t\t\t\t/* Only objects in heap_allocated may have finalizers.  Check that\n\t\t\t\t * the object itself has a _Finalizer property (own or inherited)\n\t\t\t\t * so that we don't execute finalizers for e.g. Proxy objects.\n\t\t\t\t */\n\t\t\t\tDUK_ASSERT(curr != NULL);\n\n\t\t\t\tif (DUK_HOBJECT_HAS_FINALIZER_FAST(heap, (duk_hobject *) curr)) {\n\t\t\t\t\tif (!DUK_HEAPHDR_HAS_FINALIZED((duk_heaphdr *) curr)) {\n\t\t\t\t\t\tDUK_ASSERT(DUK_HEAP_HAS_FINALIZER_NORESCUE(heap));  /* maps to finalizer 2nd argument */\n\t\t\t\t\t\tduk_heap_run_finalizer(heap, (duk_hobject *) curr);\n\t\t\t\t\t\tcount_finalized++;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tcurr = DUK_HEAPHDR_GET_NEXT(heap, curr);\n\t\t}\n\n\t\t/* Each round of finalizer execution may spawn new finalizable objects\n\t\t * which is normal behavior for some applications.  Allow multiple\n\t\t * rounds of finalization, but use a shrinking limit based on the\n\t\t * first round to detect the case where a runaway finalizer creates\n\t\t * an unbounded amount of new finalizable objects.  Finalizer rescue\n\t\t * is not supported: the semantics are unclear because most of the\n\t\t * objects being finalized here are already reachable.  The finalizer\n\t\t * is given a boolean to indicate that rescue is not possible.\n\t\t *\n\t\t * See discussion in: https://github.com/svaarala/duktape/pull/473\n\t\t */\n\n\t\tif (round_no == 0) {\n\t\t\t/* Cannot wrap: each object is at least 8 bytes so count is\n\t\t\t * at most 1/8 of that.\n\t\t\t */\n\t\t\tcurr_limit = count_all * 2;\n\t\t} else {\n\t\t\tcurr_limit = (curr_limit * 3) / 4;   /* Decrease by 25% every round */\n\t\t}\n\t\tDUK_D(DUK_DPRINT(\"finalizer round %ld complete, %ld objects, tried to execute %ld finalizers, current limit is %ld\",\n\t\t                 (long) round_no, (long) count_all, (long) count_finalized, (long) curr_limit));\n\n\t\tif (count_finalized == 0) {\n\t\t\tDUK_D(DUK_DPRINT(\"no more finalizable objects, forced finalization finished\"));\n\t\t\tbreak;\n\t\t}\n\t\tif (count_finalized >= curr_limit) {\n\t\t\tDUK_D(DUK_DPRINT(\"finalizer count above limit, potentially runaway finalizer; skip remaining finalizers\"));\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tDUK_ASSERT(heap->ms_running == 1);\n\theap->ms_running = 0;\n\tDUK_ASSERT(heap->pf_prevent_count == 1);\n\theap->pf_prevent_count = 0;\n}\n#endif  /* DUK_USE_FINALIZER_SUPPORT */\n\nDUK_INTERNAL void duk_heap_free(duk_heap *heap) {\n\tDUK_D(DUK_DPRINT(\"free heap: %p\", (void *) heap));\n\n#if defined(DUK_USE_DEBUG)\n\tduk_heap_strtable_dump(heap);\n#endif\n\n#if defined(DUK_USE_DEBUGGER_SUPPORT)\n\t/* Detach a debugger if attached (can be called multiple times)\n\t * safely.\n\t */\n\t/* XXX: Add a flag to reject an attempt to re-attach?  Otherwise\n\t * the detached callback may immediately reattach.\n\t */\n\tduk_debug_do_detach(heap);\n#endif\n\n\t/* Execute finalizers before freeing the heap, even for reachable\n\t * objects.  This gives finalizers the chance to free any native\n\t * resources like file handles, allocations made outside Duktape,\n\t * etc.  This is quite tricky to get right, so that all finalizer\n\t * guarantees are honored.\n\t *\n\t * Run mark-and-sweep a few times just in case (unreachable object\n\t * finalizers run already here).  The last round must rescue objects\n\t * from the previous round without running any more finalizers.  This\n\t * ensures rescued objects get their FINALIZED flag cleared so that\n\t * their finalizer is called once more in forced finalization to\n\t * satisfy finalizer guarantees.  However, we don't want to run any\n\t * more finalizers because that'd required one more loop, and so on.\n\t *\n\t * XXX: this perhaps requires an execution time limit.\n\t */\n\tDUK_D(DUK_DPRINT(\"execute finalizers before freeing heap\"));\n\tDUK_ASSERT(heap->pf_skip_finalizers == 0);\n\tDUK_D(DUK_DPRINT(\"forced gc #1 in heap destruction\"));\n\tduk_heap_mark_and_sweep(heap, 0);\n\tDUK_D(DUK_DPRINT(\"forced gc #2 in heap destruction\"));\n\tduk_heap_mark_and_sweep(heap, 0);\n\tDUK_D(DUK_DPRINT(\"forced gc #3 in heap destruction (don't run finalizers)\"));\n\theap->pf_skip_finalizers = 1;\n\tduk_heap_mark_and_sweep(heap, 0);  /* Skip finalizers; queue finalizable objects to heap_allocated. */\n\n\t/* There are never objects in refzero_list at this point, or at any\n\t * point beyond a DECREF (even a DECREF_NORZ).  Since Duktape 2.1\n\t * refzero_list processing is side effect free, so it is always\n\t * processed to completion by a DECREF initially triggering a zero\n\t * refcount.\n\t */\n#if defined(DUK_USE_REFERENCE_COUNTING)\n\tDUK_ASSERT(heap->refzero_list == NULL);  /* Always processed to completion inline. */\n#endif\n#if defined(DUK_USE_FINALIZER_SUPPORT)\n\tDUK_ASSERT(heap->finalize_list == NULL);  /* Last mark-and-sweep with skip_finalizers. */\n#endif\n\n#if defined(DUK_USE_FINALIZER_SUPPORT)\n\tDUK_D(DUK_DPRINT(\"run finalizers for remaining finalizable objects\"));\n\tDUK_HEAP_SET_FINALIZER_NORESCUE(heap);  /* Rescue no longer supported. */\n\tduk__free_run_finalizers(heap);\n#endif  /* DUK_USE_FINALIZER_SUPPORT */\n\n\t/* Note: heap->heap_thread, heap->curr_thread, and heap->heap_object\n\t * are on the heap allocated list.\n\t */\n\n\tDUK_D(DUK_DPRINT(\"freeing temporary freelists\"));\n\tduk_heap_free_freelists(heap);\n\n\tDUK_D(DUK_DPRINT(\"freeing heap_allocated of heap: %p\", (void *) heap));\n\tduk__free_allocated(heap);\n\n#if defined(DUK_USE_REFERENCE_COUNTING)\n\tDUK_ASSERT(heap->refzero_list == NULL);  /* Always processed to completion inline. */\n#endif\n\n#if defined(DUK_USE_FINALIZER_SUPPORT)\n\tDUK_D(DUK_DPRINT(\"freeing finalize_list of heap: %p\", (void *) heap));\n\tduk__free_finalize_list(heap);\n#endif\n\n\tDUK_D(DUK_DPRINT(\"freeing string table of heap: %p\", (void *) heap));\n\tduk__free_stringtable(heap);\n\n\tDUK_D(DUK_DPRINT(\"freeing heap structure: %p\", (void *) heap));\n\theap->free_func(heap->heap_udata, heap);\n}\n\n/*\n *  Allocate a heap.\n *\n *  String table is initialized with built-in strings from genbuiltins.py,\n *  either by dynamically creating the strings or by referring to ROM strings.\n */\n\n#if defined(DUK_USE_ROM_STRINGS)\nDUK_LOCAL duk_bool_t duk__init_heap_strings(duk_heap *heap) {\n#if defined(DUK_USE_ASSERTIONS)\n\tduk_small_uint_t i;\n#endif\n\n\tDUK_UNREF(heap);\n\n\t/* With ROM-based strings, heap->strs[] and thr->strs[] are omitted\n\t * so nothing to initialize for strs[].\n\t */\n\n#if defined(DUK_USE_ASSERTIONS)\n\tfor (i = 0; i < sizeof(duk_rom_strings_lookup) / sizeof(const duk_hstring *); i++) {\n\t\tconst duk_hstring *h;\n\t\tduk_uint32_t hash;\n\n\t\th = duk_rom_strings_lookup[i];\n\t\twhile (h != NULL) {\n\t\t\thash = duk_heap_hashstring(heap, (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h), DUK_HSTRING_GET_BYTELEN(h));\n\t\t\tDUK_DD(DUK_DDPRINT(\"duk_rom_strings_lookup[%d] -> hash 0x%08lx, computed 0x%08lx\",\n\t\t\t                   (int) i, (unsigned long) DUK_HSTRING_GET_HASH(h), (unsigned long) hash));\n\t\t\tDUK_ASSERT(hash == (duk_uint32_t) DUK_HSTRING_GET_HASH(h));\n\n\t\t\th = (const duk_hstring *) h->hdr.h_next;\n\t\t}\n\t}\n#endif\n\treturn 1;\n}\n#else  /* DUK_USE_ROM_STRINGS */\n\nDUK_LOCAL duk_bool_t duk__init_heap_strings(duk_heap *heap) {\n\tduk_bitdecoder_ctx bd_ctx;\n\tduk_bitdecoder_ctx *bd = &bd_ctx;  /* convenience */\n\tduk_small_uint_t i;\n\n\tDUK_MEMZERO(&bd_ctx, sizeof(bd_ctx));\n\tbd->data = (const duk_uint8_t *) duk_strings_data;\n\tbd->length = (duk_size_t) DUK_STRDATA_DATA_LENGTH;\n\n\tfor (i = 0; i < DUK_HEAP_NUM_STRINGS; i++) {\n\t\tduk_uint8_t tmp[DUK_STRDATA_MAX_STRLEN];\n\t\tduk_small_uint_t len;\n\t\tduk_hstring *h;\n\n\t\tlen = duk_bd_decode_bitpacked_string(bd, tmp);\n\n\t\t/* No need to length check string: it will never exceed even\n\t\t * the 16-bit length maximum.\n\t\t */\n\t\tDUK_ASSERT(len <= 0xffffUL);\n\t\tDUK_DDD(DUK_DDDPRINT(\"intern built-in string %ld\", (long) i));\n\t\th = duk_heap_strtable_intern(heap, tmp, len);\n\t\tif (!h) {\n\t\t\tgoto failed;\n\t\t}\n\t\tDUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) h));\n\n\t\t/* Special flags checks.  Since these strings are always\n\t\t * reachable and a string cannot appear twice in the string\n\t\t * table, there's no need to check/set these flags elsewhere.\n\t\t * The 'internal' flag is set by string intern code.\n\t\t */\n\t\tif (i == DUK_STRIDX_EVAL || i == DUK_STRIDX_LC_ARGUMENTS) {\n\t\t\tDUK_HSTRING_SET_EVAL_OR_ARGUMENTS(h);\n\t\t}\n\t\tif (i >= DUK_STRIDX_START_RESERVED && i < DUK_STRIDX_END_RESERVED) {\n\t\t\tDUK_HSTRING_SET_RESERVED_WORD(h);\n\t\t\tif (i >= DUK_STRIDX_START_STRICT_RESERVED) {\n\t\t\t\tDUK_HSTRING_SET_STRICT_RESERVED_WORD(h);\n\t\t\t}\n\t\t}\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"interned: %!O\", (duk_heaphdr *) h));\n\n\t\t/* XXX: The incref macro takes a thread pointer but doesn't\n\t\t * use it right now.\n\t\t */\n\t\tDUK_HSTRING_INCREF(_never_referenced_, h);\n\n#if defined(DUK_USE_HEAPPTR16)\n\t\theap->strs16[i] = DUK_USE_HEAPPTR_ENC16(heap->heap_udata, (void *) h);\n#else\n\t\theap->strs[i] = h;\n#endif\n\t}\n\n\treturn 1;\n\n failed:\n\treturn 0;\n}\n#endif  /* DUK_USE_ROM_STRINGS */\n\nDUK_LOCAL duk_bool_t duk__init_heap_thread(duk_heap *heap) {\n\tduk_hthread *thr;\n\n\tDUK_D(DUK_DPRINT(\"heap init: alloc heap thread\"));\n\tthr = duk_hthread_alloc_unchecked(heap,\n\t                                  DUK_HOBJECT_FLAG_EXTENSIBLE |\n\t                                  DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_THREAD));\n\tif (thr == NULL) {\n\t\tDUK_D(DUK_DPRINT(\"failed to alloc heap_thread\"));\n\t\treturn 0;\n\t}\n\tthr->state = DUK_HTHREAD_STATE_INACTIVE;\n#if defined(DUK_USE_ROM_STRINGS)\n\t/* No strs[] pointer. */\n#else  /* DUK_USE_ROM_STRINGS */\n#if defined(DUK_USE_HEAPPTR16)\n\tthr->strs16 = heap->strs16;\n#else\n\tthr->strs = heap->strs;\n#endif\n#endif  /* DUK_USE_ROM_STRINGS */\n\n\theap->heap_thread = thr;\n\tDUK_HTHREAD_INCREF(thr, thr);  /* Note: first argument not really used */\n\n\t/* 'thr' is now reachable */\n\n\tDUK_D(DUK_DPRINT(\"heap init: init heap thread stacks\"));\n\tif (!duk_hthread_init_stacks(heap, thr)) {\n\t\treturn 0;\n\t}\n\n\t/* XXX: this may now fail, and is not handled correctly */\n\tduk_hthread_create_builtin_objects(thr);\n\n\t/* default prototype */\n\tDUK_HOBJECT_SET_PROTOTYPE_INIT_INCREF(thr, (duk_hobject *) thr, thr->builtins[DUK_BIDX_THREAD_PROTOTYPE]);\n\n\treturn 1;\n}\n\n#if defined(DUK_USE_DEBUG)\n#define DUK__DUMPSZ(t)  do { \\\n\t\tDUK_D(DUK_DPRINT(\"\" #t \"=%ld\", (long) sizeof(t))); \\\n\t} while (0)\n\n/* These is not 100% because format would need to be non-portable \"long long\".\n * Also print out as doubles to catch cases where the \"long\" type is not wide\n * enough; the limits will then not be printed accurately but the magnitude\n * will be correct.\n */\n#define DUK__DUMPLM_SIGNED_RAW(t,a,b)  do { \\\n\t\tDUK_D(DUK_DPRINT(t \"=[%ld,%ld]=[%lf,%lf]\", \\\n\t\t                 (long) (a), (long) (b), \\\n\t\t                 (double) (a), (double) (b))); \\\n\t} while (0)\n#define DUK__DUMPLM_UNSIGNED_RAW(t,a,b)  do { \\\n\t\tDUK_D(DUK_DPRINT(t \"=[%lu,%lu]=[%lf,%lf]\", \\\n\t\t                 (unsigned long) (a), (unsigned long) (b), \\\n\t\t                 (double) (a), (double) (b))); \\\n\t} while (0)\n#define DUK__DUMPLM_SIGNED(t)  do { \\\n\t\tDUK__DUMPLM_SIGNED_RAW(\"DUK_\" #t \"_{MIN,MAX}\", DUK_##t##_MIN, DUK_##t##_MAX); \\\n\t} while (0)\n#define DUK__DUMPLM_UNSIGNED(t)  do { \\\n\t\tDUK__DUMPLM_UNSIGNED_RAW(\"DUK_\" #t \"_{MIN,MAX}\", DUK_##t##_MIN, DUK_##t##_MAX); \\\n\t} while (0)\n\nDUK_LOCAL void duk__dump_type_sizes(void) {\n\tDUK_D(DUK_DPRINT(\"sizeof()\"));\n\n\t/* basic platform types */\n\tDUK__DUMPSZ(char);\n\tDUK__DUMPSZ(short);\n\tDUK__DUMPSZ(int);\n\tDUK__DUMPSZ(long);\n\tDUK__DUMPSZ(double);\n\tDUK__DUMPSZ(void *);\n\tDUK__DUMPSZ(size_t);\n\n\t/* basic types from duk_features.h */\n\tDUK__DUMPSZ(duk_uint8_t);\n\tDUK__DUMPSZ(duk_int8_t);\n\tDUK__DUMPSZ(duk_uint16_t);\n\tDUK__DUMPSZ(duk_int16_t);\n\tDUK__DUMPSZ(duk_uint32_t);\n\tDUK__DUMPSZ(duk_int32_t);\n\tDUK__DUMPSZ(duk_uint64_t);\n\tDUK__DUMPSZ(duk_int64_t);\n\tDUK__DUMPSZ(duk_uint_least8_t);\n\tDUK__DUMPSZ(duk_int_least8_t);\n\tDUK__DUMPSZ(duk_uint_least16_t);\n\tDUK__DUMPSZ(duk_int_least16_t);\n\tDUK__DUMPSZ(duk_uint_least32_t);\n\tDUK__DUMPSZ(duk_int_least32_t);\n#if defined(DUK_USE_64BIT_OPS)\n\tDUK__DUMPSZ(duk_uint_least64_t);\n\tDUK__DUMPSZ(duk_int_least64_t);\n#endif\n\tDUK__DUMPSZ(duk_uint_fast8_t);\n\tDUK__DUMPSZ(duk_int_fast8_t);\n\tDUK__DUMPSZ(duk_uint_fast16_t);\n\tDUK__DUMPSZ(duk_int_fast16_t);\n\tDUK__DUMPSZ(duk_uint_fast32_t);\n\tDUK__DUMPSZ(duk_int_fast32_t);\n#if defined(DUK_USE_64BIT_OPS)\n\tDUK__DUMPSZ(duk_uint_fast64_t);\n\tDUK__DUMPSZ(duk_int_fast64_t);\n#endif\n\tDUK__DUMPSZ(duk_uintptr_t);\n\tDUK__DUMPSZ(duk_intptr_t);\n\tDUK__DUMPSZ(duk_uintmax_t);\n\tDUK__DUMPSZ(duk_intmax_t);\n\tDUK__DUMPSZ(duk_double_t);\n\n\t/* important chosen base types */\n\tDUK__DUMPSZ(duk_int_t);\n\tDUK__DUMPSZ(duk_uint_t);\n\tDUK__DUMPSZ(duk_int_fast_t);\n\tDUK__DUMPSZ(duk_uint_fast_t);\n\tDUK__DUMPSZ(duk_small_int_t);\n\tDUK__DUMPSZ(duk_small_uint_t);\n\tDUK__DUMPSZ(duk_small_int_fast_t);\n\tDUK__DUMPSZ(duk_small_uint_fast_t);\n\n\t/* some derived types */\n\tDUK__DUMPSZ(duk_codepoint_t);\n\tDUK__DUMPSZ(duk_ucodepoint_t);\n\tDUK__DUMPSZ(duk_idx_t);\n\tDUK__DUMPSZ(duk_errcode_t);\n\tDUK__DUMPSZ(duk_uarridx_t);\n\n\t/* tval */\n\tDUK__DUMPSZ(duk_double_union);\n\tDUK__DUMPSZ(duk_tval);\n\n\t/* structs from duk_forwdecl.h */\n\tDUK__DUMPSZ(duk_jmpbuf);  /* just one 'int' for C++ exceptions */\n\tDUK__DUMPSZ(duk_heaphdr);\n\tDUK__DUMPSZ(duk_heaphdr_string);\n\tDUK__DUMPSZ(duk_hstring);\n\tDUK__DUMPSZ(duk_hstring_external);\n\tDUK__DUMPSZ(duk_hobject);\n\tDUK__DUMPSZ(duk_harray);\n\tDUK__DUMPSZ(duk_hcompfunc);\n\tDUK__DUMPSZ(duk_hnatfunc);\n\tDUK__DUMPSZ(duk_hdecenv);\n\tDUK__DUMPSZ(duk_hobjenv);\n\tDUK__DUMPSZ(duk_hthread);\n#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)\n\tDUK__DUMPSZ(duk_hbufobj);\n#endif\n\tDUK__DUMPSZ(duk_hproxy);\n\tDUK__DUMPSZ(duk_hbuffer);\n\tDUK__DUMPSZ(duk_hbuffer_fixed);\n\tDUK__DUMPSZ(duk_hbuffer_dynamic);\n\tDUK__DUMPSZ(duk_hbuffer_external);\n\tDUK__DUMPSZ(duk_propaccessor);\n\tDUK__DUMPSZ(duk_propvalue);\n\tDUK__DUMPSZ(duk_propdesc);\n\tDUK__DUMPSZ(duk_heap);\n\tDUK__DUMPSZ(duk_activation);\n\tDUK__DUMPSZ(duk_catcher);\n\tDUK__DUMPSZ(duk_strcache);\n\tDUK__DUMPSZ(duk_ljstate);\n\tDUK__DUMPSZ(duk_fixedbuffer);\n\tDUK__DUMPSZ(duk_bitdecoder_ctx);\n\tDUK__DUMPSZ(duk_bitencoder_ctx);\n\tDUK__DUMPSZ(duk_token);\n\tDUK__DUMPSZ(duk_re_token);\n\tDUK__DUMPSZ(duk_lexer_point);\n\tDUK__DUMPSZ(duk_lexer_ctx);\n\tDUK__DUMPSZ(duk_compiler_instr);\n\tDUK__DUMPSZ(duk_compiler_func);\n\tDUK__DUMPSZ(duk_compiler_ctx);\n\tDUK__DUMPSZ(duk_re_matcher_ctx);\n\tDUK__DUMPSZ(duk_re_compiler_ctx);\n}\nDUK_LOCAL void duk__dump_type_limits(void) {\n\tDUK_D(DUK_DPRINT(\"limits\"));\n\n\t/* basic types */\n\tDUK__DUMPLM_SIGNED(INT8);\n\tDUK__DUMPLM_UNSIGNED(UINT8);\n\tDUK__DUMPLM_SIGNED(INT_FAST8);\n\tDUK__DUMPLM_UNSIGNED(UINT_FAST8);\n\tDUK__DUMPLM_SIGNED(INT_LEAST8);\n\tDUK__DUMPLM_UNSIGNED(UINT_LEAST8);\n\tDUK__DUMPLM_SIGNED(INT16);\n\tDUK__DUMPLM_UNSIGNED(UINT16);\n\tDUK__DUMPLM_SIGNED(INT_FAST16);\n\tDUK__DUMPLM_UNSIGNED(UINT_FAST16);\n\tDUK__DUMPLM_SIGNED(INT_LEAST16);\n\tDUK__DUMPLM_UNSIGNED(UINT_LEAST16);\n\tDUK__DUMPLM_SIGNED(INT32);\n\tDUK__DUMPLM_UNSIGNED(UINT32);\n\tDUK__DUMPLM_SIGNED(INT_FAST32);\n\tDUK__DUMPLM_UNSIGNED(UINT_FAST32);\n\tDUK__DUMPLM_SIGNED(INT_LEAST32);\n\tDUK__DUMPLM_UNSIGNED(UINT_LEAST32);\n#if defined(DUK_USE_64BIT_OPS)\n\tDUK__DUMPLM_SIGNED(INT64);\n\tDUK__DUMPLM_UNSIGNED(UINT64);\n\tDUK__DUMPLM_SIGNED(INT_FAST64);\n\tDUK__DUMPLM_UNSIGNED(UINT_FAST64);\n\tDUK__DUMPLM_SIGNED(INT_LEAST64);\n\tDUK__DUMPLM_UNSIGNED(UINT_LEAST64);\n#endif\n\tDUK__DUMPLM_SIGNED(INTPTR);\n\tDUK__DUMPLM_UNSIGNED(UINTPTR);\n\tDUK__DUMPLM_SIGNED(INTMAX);\n\tDUK__DUMPLM_UNSIGNED(UINTMAX);\n\n\t/* derived types */\n\tDUK__DUMPLM_SIGNED(INT);\n\tDUK__DUMPLM_UNSIGNED(UINT);\n\tDUK__DUMPLM_SIGNED(INT_FAST);\n\tDUK__DUMPLM_UNSIGNED(UINT_FAST);\n\tDUK__DUMPLM_SIGNED(SMALL_INT);\n\tDUK__DUMPLM_UNSIGNED(SMALL_UINT);\n\tDUK__DUMPLM_SIGNED(SMALL_INT_FAST);\n\tDUK__DUMPLM_UNSIGNED(SMALL_UINT_FAST);\n}\n\nDUK_LOCAL void duk__dump_misc_options(void) {\n\tDUK_D(DUK_DPRINT(\"DUK_VERSION: %ld\", (long) DUK_VERSION));\n\tDUK_D(DUK_DPRINT(\"DUK_GIT_DESCRIBE: %s\", DUK_GIT_DESCRIBE));\n\tDUK_D(DUK_DPRINT(\"OS string: %s\", DUK_USE_OS_STRING));\n\tDUK_D(DUK_DPRINT(\"architecture string: %s\", DUK_USE_ARCH_STRING));\n\tDUK_D(DUK_DPRINT(\"compiler string: %s\", DUK_USE_COMPILER_STRING));\n\tDUK_D(DUK_DPRINT(\"debug level: %ld\", (long) DUK_USE_DEBUG_LEVEL));\n#if defined(DUK_USE_PACKED_TVAL)\n\tDUK_D(DUK_DPRINT(\"DUK_USE_PACKED_TVAL: yes\"));\n#else\n\tDUK_D(DUK_DPRINT(\"DUK_USE_PACKED_TVAL: no\"));\n#endif\n#if defined(DUK_USE_VARIADIC_MACROS)\n\tDUK_D(DUK_DPRINT(\"DUK_USE_VARIADIC_MACROS: yes\"));\n#else\n\tDUK_D(DUK_DPRINT(\"DUK_USE_VARIADIC_MACROS: no\"));\n#endif\n#if defined(DUK_USE_INTEGER_LE)\n\tDUK_D(DUK_DPRINT(\"integer endianness: little\"));\n#elif defined(DUK_USE_INTEGER_ME)\n\tDUK_D(DUK_DPRINT(\"integer endianness: mixed\"));\n#elif defined(DUK_USE_INTEGER_BE)\n\tDUK_D(DUK_DPRINT(\"integer endianness: big\"));\n#else\n\tDUK_D(DUK_DPRINT(\"integer endianness: ???\"));\n#endif\n#if defined(DUK_USE_DOUBLE_LE)\n\tDUK_D(DUK_DPRINT(\"IEEE double endianness: little\"));\n#elif defined(DUK_USE_DOUBLE_ME)\n\tDUK_D(DUK_DPRINT(\"IEEE double endianness: mixed\"));\n#elif defined(DUK_USE_DOUBLE_BE)\n\tDUK_D(DUK_DPRINT(\"IEEE double endianness: big\"));\n#else\n\tDUK_D(DUK_DPRINT(\"IEEE double endianness: ???\"));\n#endif\n}\n#endif  /* DUK_USE_DEBUG */\n\nDUK_INTERNAL\nduk_heap *duk_heap_alloc(duk_alloc_function alloc_func,\n                         duk_realloc_function realloc_func,\n                         duk_free_function free_func,\n                         void *heap_udata,\n                         duk_fatal_function fatal_func) {\n\tduk_heap *res = NULL;\n\tduk_uint32_t st_initsize;\n\n\tDUK_D(DUK_DPRINT(\"allocate heap\"));\n\n\t/*\n\t *  Random config sanity asserts\n\t */\n\n\tDUK_ASSERT(DUK_USE_STRTAB_MINSIZE >= 64);\n\n\tDUK_ASSERT((DUK_HTYPE_STRING & 0x01U) == 0);\n\tDUK_ASSERT((DUK_HTYPE_BUFFER & 0x01U) == 0);\n\tDUK_ASSERT((DUK_HTYPE_OBJECT & 0x01U) == 1);  /* DUK_HEAPHDR_IS_OBJECT() relies ont his. */\n\n\t/*\n\t *  Debug dump type sizes\n\t */\n\n#if defined(DUK_USE_DEBUG)\n\tduk__dump_misc_options();\n\tduk__dump_type_sizes();\n\tduk__dump_type_limits();\n#endif\n\n\t/*\n\t *  If selftests enabled, run them as early as possible.\n\t */\n\n#if defined(DUK_USE_SELF_TESTS)\n\tDUK_D(DUK_DPRINT(\"run self tests\"));\n\tif (duk_selftest_run_tests(alloc_func, realloc_func, free_func, heap_udata) > 0) {\n\t\tfatal_func(heap_udata, \"self test(s) failed\");\n\t}\n\tDUK_D(DUK_DPRINT(\"self tests passed\"));\n#endif\n\n\t/*\n\t *  Important assert-like checks that should be enabled even\n\t *  when assertions are otherwise not enabled.\n\t */\n\n#if defined(DUK_USE_EXEC_REGCONST_OPTIMIZE)\n\t/* Can't check sizeof() using preprocessor so explicit check.\n\t * This will be optimized away in practice; unfortunately a\n\t * warning is generated on some compilers as a result.\n\t */\n#if defined(DUK_USE_PACKED_TVAL)\n\tif (sizeof(duk_tval) != 8) {\n#else\n\tif (sizeof(duk_tval) != 16) {\n#endif\n\t\tfatal_func(heap_udata, \"sizeof(duk_tval) not 8 or 16, cannot use DUK_USE_EXEC_REGCONST_OPTIMIZE option\");\n\t}\n#endif  /* DUK_USE_EXEC_REGCONST_OPTIMIZE */\n\n\t/*\n\t *  Computed values (e.g. INFINITY)\n\t */\n\n#if defined(DUK_USE_COMPUTED_NAN)\n\tdo {\n\t\t/* Workaround for some exotic platforms where NAN is missing\n\t\t * and the expression (0.0 / 0.0) does NOT result in a NaN.\n\t\t * Such platforms use the global 'duk_computed_nan' which must\n\t\t * be initialized at runtime.  Use 'volatile' to ensure that\n\t\t * the compiler will actually do the computation and not try\n\t\t * to do constant folding which might result in the original\n\t\t * problem.\n\t\t */\n\t\tvolatile double dbl1 = 0.0;\n\t\tvolatile double dbl2 = 0.0;\n\t\tduk_computed_nan = dbl1 / dbl2;\n\t} while (0);\n#endif\n\n#if defined(DUK_USE_COMPUTED_INFINITY)\n\tdo {\n\t\t/* Similar workaround for INFINITY. */\n\t\tvolatile double dbl1 = 1.0;\n\t\tvolatile double dbl2 = 0.0;\n\t\tduk_computed_infinity = dbl1 / dbl2;\n\t} while (0);\n#endif\n\n\t/*\n\t *  Allocate heap struct\n\t *\n\t *  Use a raw call, all macros expect the heap to be initialized\n\t */\n\n#if defined(DUK_USE_INJECT_HEAP_ALLOC_ERROR) && (DUK_USE_INJECT_HEAP_ALLOC_ERROR == 1)\n\tgoto failed;\n#endif\n\tDUK_D(DUK_DPRINT(\"alloc duk_heap object\"));\n\tres = (duk_heap *) alloc_func(heap_udata, sizeof(duk_heap));\n\tif (!res) {\n\t\tgoto failed;\n\t}\n\n\t/*\n\t *  Zero the struct, and start initializing roughly in order\n\t */\n\n\tDUK_MEMZERO(res, sizeof(*res));\n#if defined(DUK_USE_ASSERTIONS)\n\tres->heap_initializing = 1;\n#endif\n\n\t/* explicit NULL inits */\n#if defined(DUK_USE_EXPLICIT_NULL_INIT)\n\tres->heap_udata = NULL;\n\tres->heap_allocated = NULL;\n#if defined(DUK_USE_REFERENCE_COUNTING)\n\tres->refzero_list = NULL;\n#endif\n#if defined(DUK_USE_FINALIZER_SUPPORT)\n\tres->finalize_list = NULL;\n#if defined(DUK_USE_ASSERTIONS)\n\tres->currently_finalizing = NULL;\n#endif\n#endif\n#if defined(DUK_USE_CACHE_ACTIVATION)\n\tres->activation_free = NULL;\n#endif\n#if defined(DUK_USE_CACHE_CATCHER)\n\tres->catcher_free = NULL;\n#endif\n\tres->heap_thread = NULL;\n\tres->curr_thread = NULL;\n\tres->heap_object = NULL;\n#if defined(DUK_USE_STRTAB_PTRCOMP)\n\tres->strtable16 = NULL;\n#else\n\tres->strtable = NULL;\n#endif\n#if defined(DUK_USE_ROM_STRINGS)\n\t/* no res->strs[] */\n#else  /* DUK_USE_ROM_STRINGS */\n#if defined(DUK_USE_HEAPPTR16)\n\t/* res->strs16[] is zeroed and zero decodes to NULL, so no NULL inits. */\n#else\n\t{\n\t\tduk_small_uint_t i;\n\t        for (i = 0; i < DUK_HEAP_NUM_STRINGS; i++) {\n\t\t\tres->strs[i] = NULL;\n\t        }\n\t}\n#endif\n#endif  /* DUK_USE_ROM_STRINGS */\n#if defined(DUK_USE_DEBUGGER_SUPPORT)\n\tres->dbg_read_cb = NULL;\n\tres->dbg_write_cb = NULL;\n\tres->dbg_peek_cb = NULL;\n\tres->dbg_read_flush_cb = NULL;\n\tres->dbg_write_flush_cb = NULL;\n\tres->dbg_request_cb = NULL;\n\tres->dbg_udata = NULL;\n\tres->dbg_pause_act = NULL;\n#endif\n#endif  /* DUK_USE_EXPLICIT_NULL_INIT */\n\n\tres->alloc_func = alloc_func;\n\tres->realloc_func = realloc_func;\n\tres->free_func = free_func;\n\tres->heap_udata = heap_udata;\n\tres->fatal_func = fatal_func;\n\n\t/* XXX: for now there's a pointer packing zero assumption, i.e.\n\t * NULL <=> compressed pointer 0.  If this is removed, may need\n\t * to precompute e.g. null16 here.\n\t */\n\n\t/* res->ms_trigger_counter == 0 -> now causes immediate GC; which is OK */\n\n\t/* Prevent mark-and-sweep and finalizer execution until heap is completely\n\t * initialized.\n\t */\n\tDUK_ASSERT(res->ms_prevent_count == 0);\n\tDUK_ASSERT(res->pf_prevent_count == 0);\n\tres->ms_prevent_count = 1;\n\tres->pf_prevent_count = 1;\n\tDUK_ASSERT(res->ms_running == 0);\n\n\tres->call_recursion_depth = 0;\n\tres->call_recursion_limit = DUK_USE_NATIVE_CALL_RECLIMIT;\n\n\t/* XXX: use the pointer as a seed for now: mix in time at least */\n\n\t/* The casts through duk_intptr_t is to avoid the following GCC warning:\n\t *\n\t *   warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]\n\t *\n\t * This still generates a /Wp64 warning on VS2010 when compiling for x86.\n\t */\n#if defined(DUK_USE_ROM_STRINGS)\n\t/* XXX: make a common DUK_USE_ option, and allow custom fixed seed? */\n\tDUK_D(DUK_DPRINT(\"using rom strings, force heap hash_seed to fixed value 0x%08lx\", (long) DUK__FIXED_HASH_SEED));\n\tres->hash_seed = (duk_uint32_t) DUK__FIXED_HASH_SEED;\n#else  /* DUK_USE_ROM_STRINGS */\n\tres->hash_seed = (duk_uint32_t) (duk_intptr_t) res;\n#if !defined(DUK_USE_STRHASH_DENSE)\n\tres->hash_seed ^= 5381;  /* Bernstein hash init value is normally 5381; XOR it in in case pointer low bits are 0 */\n#endif\n#endif  /* DUK_USE_ROM_STRINGS */\n\n#if defined(DUK_USE_EXPLICIT_NULL_INIT)\n\tres->lj.jmpbuf_ptr = NULL;\n#endif\n\tDUK_ASSERT(res->lj.type == DUK_LJ_TYPE_UNKNOWN);  /* zero */\n\tDUK_ASSERT(res->lj.iserror == 0);\n\tDUK_TVAL_SET_UNDEFINED(&res->lj.value1);\n\tDUK_TVAL_SET_UNDEFINED(&res->lj.value2);\n\n\tDUK_ASSERT_LJSTATE_UNSET(res);\n\n\t/*\n\t *  Init stringtable: fixed variant\n\t */\n\n\tst_initsize = DUK_USE_STRTAB_MINSIZE;\n#if defined(DUK_USE_STRTAB_PTRCOMP)\n\tres->strtable16 = (duk_uint16_t *) alloc_func(heap_udata, sizeof(duk_uint16_t) * st_initsize);\n\tif (res->strtable16 == NULL) {\n\t\tgoto failed;\n\t}\n#else\n\tres->strtable = (duk_hstring **) alloc_func(heap_udata, sizeof(duk_hstring *) * st_initsize);\n\tif (res->strtable == NULL) {\n\t\tgoto failed;\n\t}\n#endif\n\tres->st_size = st_initsize;\n\tres->st_mask = st_initsize - 1;\n#if (DUK_USE_STRTAB_MINSIZE != DUK_USE_STRTAB_MAXSIZE)\n\tDUK_ASSERT(res->st_count == 0);\n#endif\n\n#if defined(DUK_USE_STRTAB_PTRCOMP)\n\t/* zero assumption */\n\tDUK_MEMZERO(res->strtable16, sizeof(duk_uint16_t) * st_initsize);\n#else\n#if defined(DUK_USE_EXPLICIT_NULL_INIT)\n\t{\n\t\tduk_small_uint_t i;\n\t        for (i = 0; i < st_initsize; i++) {\n\t\t\tres->strtable[i] = NULL;\n\t        }\n\t}\n#else\n\tDUK_MEMZERO(res->strtable, sizeof(duk_hstring *) * st_initsize);\n#endif  /* DUK_USE_EXPLICIT_NULL_INIT */\n#endif  /* DUK_USE_STRTAB_PTRCOMP */\n\n\t/*\n\t *  Init stringcache\n\t */\n\n#if defined(DUK_USE_EXPLICIT_NULL_INIT)\n\t{\n\t\tduk_small_uint_t i;\n\t\tfor (i = 0; i < DUK_HEAP_STRCACHE_SIZE; i++) {\n\t\t\tres->strcache[i].h = NULL;\n\t\t}\n\t}\n#endif\n\n\t/* XXX: error handling is incomplete.  It would be cleanest if\n\t * there was a setjmp catchpoint, so that all init code could\n\t * freely throw errors.  If that were the case, the return code\n\t * passing here could be removed.\n\t */\n\n\t/*\n\t *  Init built-in strings\n\t */\n\n#if defined(DUK_USE_INJECT_HEAP_ALLOC_ERROR) && (DUK_USE_INJECT_HEAP_ALLOC_ERROR == 2)\n\tgoto failed;\n#endif\n\tDUK_D(DUK_DPRINT(\"heap init: initialize heap strings\"));\n\tif (!duk__init_heap_strings(res)) {\n\t\tgoto failed;\n\t}\n\n\t/*\n\t *  Init the heap thread\n\t */\n\n#if defined(DUK_USE_INJECT_HEAP_ALLOC_ERROR) && (DUK_USE_INJECT_HEAP_ALLOC_ERROR == 3)\n\tgoto failed;\n#endif\n\tDUK_D(DUK_DPRINT(\"heap init: initialize heap thread\"));\n\tif (!duk__init_heap_thread(res)) {\n\t\tgoto failed;\n\t}\n\n\t/*\n\t *  Init the heap object\n\t */\n\n#if defined(DUK_USE_INJECT_HEAP_ALLOC_ERROR) && (DUK_USE_INJECT_HEAP_ALLOC_ERROR == 4)\n\tgoto failed;\n#endif\n\tDUK_D(DUK_DPRINT(\"heap init: initialize heap object\"));\n\tDUK_ASSERT(res->heap_thread != NULL);\n\tres->heap_object = duk_hobject_alloc_unchecked(res, DUK_HOBJECT_FLAG_EXTENSIBLE |\n\t                                                    DUK_HOBJECT_FLAG_FASTREFS |\n\t                                                    DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT));\n\tif (res->heap_object == NULL) {\n\t\tgoto failed;\n\t}\n\tDUK_HOBJECT_INCREF(res->heap_thread, res->heap_object);\n\n\t/*\n\t *  Odds and ends depending on the heap thread\n\t */\n\n#if !defined(DUK_USE_GET_RANDOM_DOUBLE)\n#if defined(DUK_USE_PREFER_SIZE) || !defined(DUK_USE_64BIT_OPS)\n\tres->rnd_state = (duk_uint32_t) duk_time_get_ecmascript_time(res->heap_thread);\n\tduk_util_tinyrandom_prepare_seed(res->heap_thread);\n#else\n\tres->rnd_state[0] = (duk_uint64_t) duk_time_get_ecmascript_time(res->heap_thread);\n\tDUK_ASSERT(res->rnd_state[1] == 0);  /* Not filled here, filled in by seed preparation. */\n#if 0  /* Manual test values matching misc/xoroshiro128plus_test.c. */\n\tres->rnd_state[0] = DUK_U64_CONSTANT(0xdeadbeef12345678);\n\tres->rnd_state[1] = DUK_U64_CONSTANT(0xcafed00d12345678);\n#endif\n\tduk_util_tinyrandom_prepare_seed(res->heap_thread);\n\t/* Mix in heap pointer: this ensures that if two Duktape heaps are\n\t * created on the same millisecond, they get a different PRNG\n\t * sequence (unless e.g. virtual memory addresses cause also the\n\t * heap object pointer to be the same).\n\t */\n\t{\n\t\tduk_uint64_t tmp_u64;\n\t\ttmp_u64 = 0;\n\t\tDUK_MEMCPY((void *) &tmp_u64,\n\t\t           (const void *) &res,\n\t\t           (size_t) (sizeof(void *) >= sizeof(duk_uint64_t) ? sizeof(duk_uint64_t) : sizeof(void *)));\n\t\tres->rnd_state[1] ^= tmp_u64;\n\t}\n\tdo {\n\t\tduk_small_uint_t i;\n\t\tfor (i = 0; i < 10; i++) {\n\t\t\t/* Throw away a few initial random numbers just in\n\t\t\t * case.  Probably unnecessary due to SplitMix64\n\t\t\t * preparation.\n\t\t\t */\n\t\t\t(void) duk_util_tinyrandom_get_double(res->heap_thread);\n\t\t}\n\t} while (0);\n#endif\n#endif\n\n\t/*\n\t *  Allow finalizer and mark-and-sweep processing.\n\t */\n\n\tDUK_D(DUK_DPRINT(\"heap init: allow finalizer/mark-and-sweep processing\"));\n\tDUK_ASSERT(res->ms_prevent_count == 1);\n\tDUK_ASSERT(res->pf_prevent_count == 1);\n\tres->ms_prevent_count = 0;\n\tres->pf_prevent_count = 0;\n\tDUK_ASSERT(res->ms_running == 0);\n#if defined(DUK_USE_ASSERTIONS)\n\tres->heap_initializing = 0;\n#endif\n\n\t/*\n\t *  All done.\n\t */\n\n\tDUK_D(DUK_DPRINT(\"allocated heap: %p\", (void *) res));\n\treturn res;\n\n failed:\n\tDUK_D(DUK_DPRINT(\"heap allocation failed\"));\n\n\tif (res != NULL) {\n\t\t/* Assumes that allocated pointers and alloc funcs are valid\n\t\t * if res exists.\n\t\t */\n\t\tDUK_ASSERT(res->ms_prevent_count == 1);\n\t\tDUK_ASSERT(res->pf_prevent_count == 1);\n\t\tDUK_ASSERT(res->ms_running == 0);\n\t\tif (res->heap_thread != NULL) {\n\t\t\tres->ms_prevent_count = 0;\n\t\t\tres->pf_prevent_count = 0;\n\t\t}\n#if defined(DUK_USE_ASSERTIONS)\n\t\tres->heap_initializing = 0;\n#endif\n\n\t\tDUK_ASSERT(res->alloc_func != NULL);\n\t\tDUK_ASSERT(res->realloc_func != NULL);\n\t\tDUK_ASSERT(res->free_func != NULL);\n\t\tduk_heap_free(res);\n\t}\n\n\treturn NULL;\n}\n\n/* automatic undefs */\n#undef DUK__DUMPLM_SIGNED\n#undef DUK__DUMPLM_SIGNED_RAW\n#undef DUK__DUMPLM_UNSIGNED\n#undef DUK__DUMPLM_UNSIGNED_RAW\n#undef DUK__DUMPSZ\n#undef DUK__FIXED_HASH_SEED\n#line 1 \"duk_heap_finalize.c\"\n/*\n *  Finalizer handling.\n */\n\n/* #include duk_internal.h -> already included */\n\n#if defined(DUK_USE_FINALIZER_SUPPORT)\n\n/*\n *  Fake torture finalizer.\n */\n\n#if defined(DUK_USE_FINALIZER_TORTURE)\nDUK_LOCAL duk_ret_t duk__fake_global_finalizer(duk_hthread *thr) {\n\tDUK_DD(DUK_DDPRINT(\"fake global torture finalizer executed\"));\n\n\t/* Require a lot of stack to force a value stack grow/shrink. */\n\tduk_require_stack(thr, 100000);\n\n\t/* Force a reallocation with pointer change for value stack\n\t * to maximize side effects.\n\t */\n\tduk_hthread_valstack_torture_realloc(thr);\n\n\t/* Inner function call, error throw. */\n\tduk_eval_string_noresult(thr,\n\t\t\"(function dummy() {\\n\"\n\t\t\"    dummy.prototype = null;  /* break reference loop */\\n\"\n\t\t\"    try {\\n\"\n\t\t\"        throw 'fake-finalizer-dummy-error';\\n\"\n\t\t\"    } catch (e) {\\n\"\n\t\t\"        void e;\\n\"\n\t\t\"    }\\n\"\n\t\t\"})()\");\n\n\t/* The above creates garbage (e.g. a function instance).  Because\n\t * the function/prototype reference loop is broken, it gets collected\n\t * immediately by DECREF.  If Function.prototype has a _Finalizer\n\t * property (happens in some test cases), the garbage gets queued to\n\t * finalize_list.  This still won't cause an infinite loop because\n\t * the torture finalizer is called once per finalize_list run and\n\t * the garbage gets handled in the same run.  (If the garbage needs\n\t * mark-and-sweep collection, an infinite loop might ensue.)\n\t */\n\treturn 0;\n}\n\nDUK_LOCAL void duk__run_global_torture_finalizer(duk_hthread *thr) {\n\tDUK_ASSERT(thr != NULL);\n\n\t/* Avoid fake finalization when callstack limit is near.  Otherwise\n\t * a callstack limit error will be created, then refzero'ed.  The\n\t * +5 headroom is conservative.\n\t */\n\tif (thr->heap->call_recursion_depth + 5 >= thr->heap->call_recursion_limit ||\n\t    thr->callstack_top + 5 >= DUK_USE_CALLSTACK_LIMIT) {\n\t\tDUK_D(DUK_DPRINT(\"skip global torture finalizer, too little headroom for call recursion or call stack size\"));\n\t\treturn;\n\t}\n\n\t/* Run fake finalizer.  Avoid creating unnecessary garbage. */\n\tduk_push_c_function(thr, duk__fake_global_finalizer, 0 /*nargs*/);\n\t(void) duk_pcall(thr, 0 /*nargs*/);\n\tduk_pop(thr);\n}\n#endif  /* DUK_USE_FINALIZER_TORTURE */\n\n/*\n *  Process the finalize_list to completion.\n *\n *  An object may be placed on finalize_list by either refcounting or\n *  mark-and-sweep.  The refcount of objects placed by refcounting will be\n *  zero; the refcount of objects placed by mark-and-sweep is > 0.  In both\n *  cases the refcount is bumped by 1 artificially so that a REFZERO event\n *  can never happen while an object is waiting for finalization.  Without\n *  this bump a REFZERO could now happen because user code may call\n *  duk_push_heapptr() and then pop a value even when it's on finalize_list.\n *\n *  List processing assumes refcounts are kept up-to-date at all times, so\n *  that once the finalizer returns, a zero refcount is a reliable reason to\n *  free the object immediately rather than place it back to the heap.  This\n *  is the case because we run outside of refzero_list processing so that\n *  DECREF cascades are handled fully inline.\n *\n *  For mark-and-sweep queued objects (had_zero_refcount false) the object\n *  may be freed immediately if its refcount is zero after the finalizer call\n *  (i.e. finalizer removed the reference loop for the object).  If not, the\n *  next mark-and-sweep will collect the object unless it has become reachable\n *  (i.e. rescued) by that time and its refcount hasn't fallen to zero before\n *  that.  Mark-and-sweep detects these objects because their FINALIZED flag\n *  is set.\n *\n *  There's an inherent limitation for mark-and-sweep finalizer rescuing: an\n *  object won't get refinalized if (1) it's rescued, but (2) becomes\n *  unreachable before mark-and-sweep has had time to notice it.  The next\n *  mark-and-sweep round simply doesn't have any information of whether the\n *  object has been unreachable the whole time or not (the only way to get\n *  that information would be a mark-and-sweep pass for *every finalized\n *  object*).  This is awkward for the application because the mark-and-sweep\n *  round is not generally visible or under full application control.\n *\n *  For refcount queued objects (had_zero_refcount true) the object is either\n *  immediately freed or rescued, and waiting for a mark-and-sweep round is not\n *  necessary (or desirable); FINALIZED is cleared when a rescued object is\n *  queued back to heap_allocated.  The object is eligible for finalization\n *  again (either via refcounting or mark-and-sweep) immediately after being\n *  rescued.  If a refcount finalized object is placed into an unreachable\n *  reference loop by its finalizer, it will get collected by mark-and-sweep\n *  and currently the finalizer will execute again.\n *\n *  There's a special case where:\n *\n *    - Mark-and-sweep queues an object to finalize_list for finalization.\n *    - The finalizer is executed, FINALIZED is set, and object is queued\n *      back to heap_allocated, waiting for a new mark-and-sweep round.\n *    - The object's refcount drops to zero before mark-and-sweep has a\n *      chance to run another round and make a rescue/free decision.\n *\n *  This is now handled by refzero code: if an object has a finalizer but\n *  FINALIZED is already set, the object is freed without finalizer processing.\n *  The outcome is the same as if mark-and-sweep was executed at that point;\n *  mark-and-sweep would also free the object without another finalizer run.\n *  This could also be changed so that the refzero-triggered finalizer *IS*\n *  executed: being refzero collected implies someone has operated on the\n *  object so it hasn't been totally unreachable the whole time.  This would\n *  risk a finalizer loop however.\n */\n\nDUK_INTERNAL void duk_heap_process_finalize_list(duk_heap *heap) {\n\tduk_heaphdr *curr;\n#if defined(DUK_USE_DEBUG)\n\tduk_size_t count = 0;\n#endif\n\n\tDUK_DDD(DUK_DDDPRINT(\"duk_heap_process_finalize_list: %p\", (void *) heap));\n\n\tif (heap->pf_prevent_count != 0) {\n\t\tDUK_DDD(DUK_DDDPRINT(\"skip finalize_list processing: pf_prevent_count != 0\"));\n\t\treturn;\n\t}\n\n\t/* Heap alloc prevents mark-and-sweep before heap_thread is ready. */\n\tDUK_ASSERT(heap != NULL);\n\tDUK_ASSERT(heap->heap_thread != NULL);\n\tDUK_ASSERT(heap->heap_thread->valstack != NULL);\n#if defined(DUK_USE_REFERENCE_COUNTING)\n\tDUK_ASSERT(heap->refzero_list == NULL);\n#endif\n\n\tDUK_ASSERT(heap->pf_prevent_count == 0);\n\theap->pf_prevent_count = 1;\n\n\t/* Mark-and-sweep no longer needs to be prevented when running\n\t * finalizers: mark-and-sweep skips any rescue decisions if there\n\t * are any objects in finalize_list when mark-and-sweep is entered.\n\t * This protects finalized objects from incorrect rescue decisions\n\t * caused by finalize_list being a reachability root and only\n\t * partially processed.  Freeing decisions are not postponed.\n\t */\n\n\t/* When finalizer torture is enabled, make a fake finalizer call with\n\t * maximum side effects regardless of whether finalize_list is empty.\n\t */\n#if defined(DUK_USE_FINALIZER_TORTURE)\n\tduk__run_global_torture_finalizer(heap->heap_thread);\n#endif\n\n\t/* Process finalize_list until it becomes empty.  There's currently no\n\t * protection against a finalizer always creating more garbage.\n\t */\n\twhile ((curr = heap->finalize_list) != NULL) {\n#if defined(DUK_USE_REFERENCE_COUNTING)\n\t\tduk_bool_t queue_back;\n#endif\n\n\t\tDUK_DD(DUK_DDPRINT(\"processing finalize_list entry: %p -> %!iO\", (void *) curr, curr));\n\n\t\tDUK_ASSERT(DUK_HEAPHDR_GET_TYPE(curr) == DUK_HTYPE_OBJECT);  /* Only objects have finalizers. */\n\t\tDUK_ASSERT(!DUK_HEAPHDR_HAS_REACHABLE(curr));\n\t\tDUK_ASSERT(!DUK_HEAPHDR_HAS_TEMPROOT(curr));\n\t\tDUK_ASSERT(DUK_HEAPHDR_HAS_FINALIZABLE(curr));  /* All objects on finalize_list will have this flag (except object being finalized right now). */\n\t\tDUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZED(curr));   /* Queueing code ensures. */\n\t\tDUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY(curr));  /* ROM objects never get freed (or finalized). */\n\n#if defined(DUK_USE_ASSERTIONS)\n\t\tDUK_ASSERT(heap->currently_finalizing == NULL);\n\t\theap->currently_finalizing = curr;\n#endif\n\n\t\t/* Clear FINALIZABLE for object being finalized, so that\n\t\t * duk_push_heapptr() can properly ignore the object.\n\t\t */\n\t\tDUK_HEAPHDR_CLEAR_FINALIZABLE(curr);\n\n\t\tif (DUK_LIKELY(!heap->pf_skip_finalizers)) {\n\t\t\t/* Run the finalizer, duk_heap_run_finalizer() sets\n\t\t\t * and checks for FINALIZED to prevent the finalizer\n\t\t\t * from executing multiple times per finalization cycle.\n\t\t\t * (This safeguard shouldn't be actually needed anymore).\n\t\t\t */\n\n#if defined(DUK_USE_REFERENCE_COUNTING)\n\t\t\tduk_bool_t had_zero_refcount;\n#endif\n\n\t\t\t/* The object's refcount is >0 throughout so it won't be\n\t\t\t * refzero processed prematurely.\n\t\t\t */\n#if defined(DUK_USE_REFERENCE_COUNTING)\n\t\t\tDUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(curr) >= 1);\n\t\t\thad_zero_refcount = (DUK_HEAPHDR_GET_REFCOUNT(curr) == 1);  /* Preincremented on finalize_list insert. */\n#endif\n\n\t\t\tDUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZED(curr));\n\t\t\tduk_heap_run_finalizer(heap, (duk_hobject *) curr);  /* must never longjmp */\n\t\t\tDUK_ASSERT(DUK_HEAPHDR_HAS_FINALIZED(curr));\n\t\t\t/* XXX: assert that object is still in finalize_list\n\t\t\t * when duk_push_heapptr() allows automatic rescue.\n\t\t\t */\n\n#if defined(DUK_USE_REFERENCE_COUNTING)\n\t\t\tDUK_DD(DUK_DDPRINT(\"refcount after finalizer (includes bump): %ld\", (long) DUK_HEAPHDR_GET_REFCOUNT(curr)));\n\t\t\tif (DUK_HEAPHDR_GET_REFCOUNT(curr) == 1) {  /* Only artificial bump in refcount? */\n#if defined(DUK_USE_DEBUG)\n\t\t\t\tif (had_zero_refcount) {\n\t\t\t\t\tDUK_DD(DUK_DDPRINT(\"finalized object's refcount is zero -> free immediately (refcount queued)\"));\n\t\t\t\t} else {\n\t\t\t\t\tDUK_DD(DUK_DDPRINT(\"finalized object's refcount is zero -> free immediately (mark-and-sweep queued)\"));\n\t\t\t\t}\n#endif\n\t\t\t\tqueue_back = 0;\n\t\t\t} else\n#endif\n\t\t\t{\n#if defined(DUK_USE_REFERENCE_COUNTING)\n\t\t\t\tqueue_back = 1;\n\t\t\t\tif (had_zero_refcount) {\n\t\t\t\t\t/* When finalization is triggered\n\t\t\t\t\t * by refzero and we queue the object\n\t\t\t\t\t * back, clear FINALIZED right away\n\t\t\t\t\t * so that the object can be refinalized\n\t\t\t\t\t * immediately if necessary.\n\t\t\t\t\t */\n\t\t\t\t\tDUK_HEAPHDR_CLEAR_FINALIZED(curr);\n\t\t\t\t}\n#endif\n\t\t\t}\n\t\t} else {\n\t\t\t/* Used during heap destruction: don't actually run finalizers\n\t\t\t * because we're heading into forced finalization.  Instead,\n\t\t\t * queue finalizable objects back to the heap_allocated list.\n\t\t\t */\n\t\t\tDUK_D(DUK_DPRINT(\"skip finalizers flag set, queue object to heap_allocated without finalizing\"));\n\t\t\tDUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZED(curr));\n#if defined(DUK_USE_REFERENCE_COUNTING)\n\t\t\tqueue_back = 1;\n#endif\n\t\t}\n\n\t\t/* Dequeue object from finalize_list.  Note that 'curr' may no\n\t\t * longer be finalize_list head because new objects may have\n\t\t * been queued to the list.  As a result we can't optimize for\n\t\t * the single-linked heap case and must scan the list for\n\t\t * removal, typically the scan is very short however.\n\t\t */\n\t\tDUK_HEAP_REMOVE_FROM_FINALIZE_LIST(heap, curr);\n\n\t\t/* Queue back to heap_allocated or free immediately. */\n#if defined(DUK_USE_REFERENCE_COUNTING)\n\t\tif (queue_back) {\n\t\t\t/* FINALIZED is only cleared if object originally\n\t\t\t * queued for finalization by refcounting.  For\n\t\t\t * mark-and-sweep FINALIZED is left set, so that\n\t\t\t * next mark-and-sweep round can make a rescue/free\n\t\t\t * decision.\n\t\t\t */\n\t\t\tDUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(curr) >= 1);\n\t\t\tDUK_HEAPHDR_PREDEC_REFCOUNT(curr);  /* Remove artificial refcount bump. */\n\t\t\tDUK_HEAPHDR_CLEAR_FINALIZABLE(curr);\n\t\t\tDUK_HEAP_INSERT_INTO_HEAP_ALLOCATED(heap, curr);\n\t\t} else {\n\t\t\t/* No need to remove the refcount bump here. */\n\t\t\tDUK_ASSERT(DUK_HEAPHDR_GET_TYPE(curr) == DUK_HTYPE_OBJECT);  /* currently, always the case */\n\t\t\tDUK_DD(DUK_DDPRINT(\"refcount finalize after finalizer call: %!O\", curr));\n\t\t\tduk_hobject_refcount_finalize_norz(heap, (duk_hobject *) curr);\n\t\t\tduk_free_hobject(heap, (duk_hobject *) curr);\n\t\t\tDUK_DD(DUK_DDPRINT(\"freed hobject after finalization: %p\", (void *) curr));\n\t\t}\n#else  /* DUK_USE_REFERENCE_COUNTING */\n\t\tDUK_HEAPHDR_CLEAR_FINALIZABLE(curr);\n\t\tDUK_HEAP_INSERT_INTO_HEAP_ALLOCATED(heap, curr);\n#endif  /* DUK_USE_REFERENCE_COUNTING */\n\n#if defined(DUK_USE_DEBUG)\n\t\tcount++;\n#endif\n\n#if defined(DUK_USE_ASSERTIONS)\n\t\tDUK_ASSERT(heap->currently_finalizing != NULL);\n\t\theap->currently_finalizing = NULL;\n#endif\n\t}\n\n\t/* finalize_list will always be processed completely. */\n\tDUK_ASSERT(heap->finalize_list == NULL);\n\n#if 0\n\t/* While NORZ macros are used above, this is unnecessary because the\n\t * only pending side effects are now finalizers, and finalize_list is\n\t * empty.\n\t */\n\tDUK_REFZERO_CHECK_SLOW(heap->heap_thread);\n#endif\n\n\t/* Prevent count may be bumped while finalizers run, but should always\n\t * be reliably unbumped by the time we get here.\n\t */\n\tDUK_ASSERT(heap->pf_prevent_count == 1);\n\theap->pf_prevent_count = 0;\n\n#if defined(DUK_USE_DEBUG)\n\tDUK_DD(DUK_DDPRINT(\"duk_heap_process_finalize_list: %ld finalizers called\", (long) count));\n#endif\n}\n\n/*\n *  Run an duk_hobject finalizer.  Must never throw an uncaught error\n *  (but may throw caught errors).\n *\n *  There is no return value.  Any return value or error thrown by\n *  the finalizer is ignored (although errors are debug logged).\n *\n *  Notes:\n *\n *    - The finalizer thread 'top' assertions are there because it is\n *      critical that strict stack policy is observed (i.e. no cruft\n *      left on the finalizer stack).\n */\n\nDUK_LOCAL duk_ret_t duk__finalize_helper(duk_hthread *thr, void *udata) {\n\tDUK_ASSERT(thr != NULL);\n\tDUK_UNREF(udata);\n\n\tDUK_DDD(DUK_DDDPRINT(\"protected finalization helper running\"));\n\n\t/* [... obj] */\n\n\t/* _Finalizer property is read without checking if the value is\n\t * callable or even exists.  This is intentional, and handled\n\t * by throwing an error which is caught by the safe call wrapper.\n\t *\n\t * XXX: Finalizer lookup should traverse the prototype chain (to allow\n\t * inherited finalizers) but should not invoke accessors or proxy object\n\t * behavior.  At the moment this lookup will invoke proxy behavior, so\n\t * caller must ensure that this function is not called if the target is\n\t * a Proxy.\n\t */\n\tduk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INT_FINALIZER);  /* -> [... obj finalizer] */\n\tduk_dup_m2(thr);\n\tduk_push_boolean(thr, DUK_HEAP_HAS_FINALIZER_NORESCUE(thr->heap));\n\tDUK_DDD(DUK_DDDPRINT(\"calling finalizer\"));\n\tduk_call(thr, 2);  /* [ ... obj finalizer obj heapDestruct ]  -> [ ... obj retval ] */\n\tDUK_DDD(DUK_DDDPRINT(\"finalizer returned successfully\"));\n\treturn 0;\n\n\t/* Note: we rely on duk_safe_call() to fix up the stack for the caller,\n\t * so we don't need to pop stuff here.  There is no return value;\n\t * caller determines rescued status based on object refcount.\n\t */\n}\n\nDUK_INTERNAL void duk_heap_run_finalizer(duk_heap *heap, duk_hobject *obj) {\n\tduk_hthread *thr;\n\tduk_ret_t rc;\n#if defined(DUK_USE_ASSERTIONS)\n\tduk_idx_t entry_top;\n#endif\n\n\tDUK_DD(DUK_DDPRINT(\"running duk_hobject finalizer for object: %p\", (void *) obj));\n\n\tDUK_ASSERT(heap != NULL);\n\tDUK_ASSERT(heap->heap_thread != NULL);\n\tthr = heap->heap_thread;\n\tDUK_ASSERT(obj != NULL);\n\tDUK_ASSERT_VALSTACK_SPACE(heap->heap_thread, 1);\n\n#if defined(DUK_USE_ASSERTIONS)\n\tentry_top = duk_get_top(thr);\n#endif\n\t/*\n\t *  Get and call the finalizer.  All of this must be wrapped\n\t *  in a protected call, because even getting the finalizer\n\t *  may trigger an error (getter may throw one, for instance).\n\t */\n\n\t/* ROM objects could inherit a finalizer, but they are never deemed\n\t * unreachable by mark-and-sweep, and their refcount never falls to 0.\n\t */\n\tDUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj));\n\n\t/* Duktape 2.1: finalize_list never contains objects with FINALIZED\n\t * set, so no need to check here.\n\t */\n\tDUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZED((duk_heaphdr *) obj));\n#if 0\n\tif (DUK_HEAPHDR_HAS_FINALIZED((duk_heaphdr *) obj)) {\n\t\tDUK_D(DUK_DPRINT(\"object already finalized, avoid running finalizer twice: %!O\", obj));\n\t\treturn;\n\t}\n#endif\n\tDUK_HEAPHDR_SET_FINALIZED((duk_heaphdr *) obj);  /* ensure never re-entered until rescue cycle complete */\n\n#if defined(DUK_USE_ES6_PROXY)\n\tif (DUK_HOBJECT_IS_PROXY(obj)) {\n\t\t/* This may happen if duk_set_finalizer() or Duktape.fin() is\n\t\t * called for a Proxy object.  In such cases the fast finalizer\n\t\t * flag will be set on the Proxy, not the target, and neither\n\t\t * will be finalized.\n\t\t */\n\t\tDUK_D(DUK_DPRINT(\"object is a Proxy, skip finalizer call\"));\n\t\treturn;\n\t}\n#endif  /* DUK_USE_ES6_PROXY */\n\n\tduk_push_hobject(thr, obj);  /* this also increases refcount by one */\n\trc = duk_safe_call(thr, duk__finalize_helper, NULL /*udata*/, 0 /*nargs*/, 1 /*nrets*/);  /* -> [... obj retval/error] */\n\tDUK_ASSERT_TOP(thr, entry_top + 2);  /* duk_safe_call discipline */\n\n\tif (rc != DUK_EXEC_SUCCESS) {\n\t\t/* Note: we ask for one return value from duk_safe_call to get this\n\t\t * error debugging here.\n\t\t */\n\t\tDUK_D(DUK_DPRINT(\"wrapped finalizer call failed for object %p (ignored); error: %!T\",\n\t\t                 (void *) obj, (duk_tval *) duk_get_tval(thr, -1)));\n\t}\n\tduk_pop_2(thr);  /* -> [...] */\n\n\tDUK_ASSERT_TOP(thr, entry_top);\n}\n\n#else  /* DUK_USE_FINALIZER_SUPPORT */\n\n/* nothing */\n\n#endif  /* DUK_USE_FINALIZER_SUPPORT */\n#line 1 \"duk_heap_hashstring.c\"\n/*\n *  String hash computation (interning).\n *\n *  String hashing is performance critical because a string hash is computed\n *  for all new strings which are candidates to be added to the string table.\n *  However, strings actually added to the string table go through a codepoint\n *  length calculation which dominates performance because it goes through\n *  every byte of the input string (but only for strings added).\n *\n *  The string hash algorithm should be fast, but on the other hand provide\n *  good enough hashes to ensure both string table and object property table\n *  hash tables work reasonably well (i.e., there aren't too many collisions\n *  with real world inputs).  Unless the hash is cryptographic, it's always\n *  possible to craft inputs with maximal hash collisions.\n *\n *  NOTE: The hash algorithms must match tools/dukutil.py:duk_heap_hashstring()\n *  for ROM string support!\n */\n\n/* #include duk_internal.h -> already included */\n\n#if defined(DUK_USE_STRHASH_DENSE)\n/* Constants for duk_hashstring(). */\n#define DUK__STRHASH_SHORTSTRING   4096L\n#define DUK__STRHASH_MEDIUMSTRING  (256L * 1024L)\n#define DUK__STRHASH_BLOCKSIZE     256L\n\nDUK_INTERNAL duk_uint32_t duk_heap_hashstring(duk_heap *heap, const duk_uint8_t *str, duk_size_t len) {\n\tduk_uint32_t hash;\n\n\t/* Use Murmurhash2 directly for short strings, and use \"block skipping\"\n\t * for long strings: hash an initial part and then sample the rest of\n\t * the string with reasonably sized chunks.  An initial offset for the\n\t * sampling is computed based on a hash of the initial part of the string;\n\t * this is done to (usually) avoid the case where all long strings have\n\t * certain offset ranges which are never sampled.\n\t *\n\t * Skip should depend on length and bound the total time to roughly\n\t * logarithmic.  With current values:\n\t *\n\t *   1M string => 256 * 241 = 61696 bytes (0.06M) of hashing\n\t *   1G string => 256 * 16321 = 4178176 bytes (3.98M) of hashing\n\t *\n\t * XXX: It would be better to compute the skip offset more \"smoothly\"\n\t * instead of having a few boundary values.\n\t */\n\n\t/* note: mixing len into seed improves hashing when skipping */\n\tduk_uint32_t str_seed = heap->hash_seed ^ ((duk_uint32_t) len);\n\n\tif (len <= DUK__STRHASH_SHORTSTRING) {\n\t\thash = duk_util_hashbytes(str, len, str_seed);\n\t} else {\n\t\tduk_size_t off;\n\t\tduk_size_t skip;\n\n\t\tif (len <= DUK__STRHASH_MEDIUMSTRING) {\n\t\t\tskip = (duk_size_t) (16 * DUK__STRHASH_BLOCKSIZE + DUK__STRHASH_BLOCKSIZE);\n\t\t} else {\n\t\t\tskip = (duk_size_t) (256 * DUK__STRHASH_BLOCKSIZE + DUK__STRHASH_BLOCKSIZE);\n\t\t}\n\n\t\thash = duk_util_hashbytes(str, (duk_size_t) DUK__STRHASH_SHORTSTRING, str_seed);\n\t\toff = DUK__STRHASH_SHORTSTRING + (skip * (hash % 256)) / 256;\n\n\t\t/* XXX: inefficient loop */\n\t\twhile (off < len) {\n\t\t\tduk_size_t left = len - off;\n\t\t\tduk_size_t now = (duk_size_t) (left > DUK__STRHASH_BLOCKSIZE ? DUK__STRHASH_BLOCKSIZE : left);\n\t\t\thash ^= duk_util_hashbytes(str + off, now, str_seed);\n\t\t\toff += skip;\n\t\t}\n\t}\n\n#if defined(DUK_USE_STRHASH16)\n\t/* Truncate to 16 bits here, so that a computed hash can be compared\n\t * against a hash stored in a 16-bit field.\n\t */\n\thash &= 0x0000ffffUL;\n#endif\n\treturn hash;\n}\n#else  /* DUK_USE_STRHASH_DENSE */\nDUK_INTERNAL duk_uint32_t duk_heap_hashstring(duk_heap *heap, const duk_uint8_t *str, duk_size_t len) {\n\tduk_uint32_t hash;\n\tduk_size_t step;\n\tduk_size_t off;\n\n\t/* Slightly modified \"Bernstein hash\" from:\n\t *\n\t *     http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx\n\t *\n\t * Modifications: string skipping and reverse direction similar to\n\t * Lua 5.1.5, and different hash initializer.\n\t *\n\t * The reverse direction ensures last byte it always included in the\n\t * hash which is a good default as changing parts of the string are\n\t * more often in the suffix than in the prefix.\n\t */\n\n\thash = heap->hash_seed ^ ((duk_uint32_t) len);  /* Bernstein hash init value is normally 5381 */\n\tstep = (len >> DUK_USE_STRHASH_SKIP_SHIFT) + 1;\n\tfor (off = len; off >= step; off -= step) {\n\t\tDUK_ASSERT(off >= 1);  /* off >= step, and step >= 1 */\n\t\thash = (hash * 33) + str[off - 1];\n\t}\n\n#if defined(DUK_USE_STRHASH16)\n\t/* Truncate to 16 bits here, so that a computed hash can be compared\n\t * against a hash stored in a 16-bit field.\n\t */\n\thash &= 0x0000ffffUL;\n#endif\n\treturn hash;\n}\n#endif  /* DUK_USE_STRHASH_DENSE */\n\n/* automatic undefs */\n#undef DUK__STRHASH_BLOCKSIZE\n#undef DUK__STRHASH_MEDIUMSTRING\n#undef DUK__STRHASH_SHORTSTRING\n#line 1 \"duk_heap_markandsweep.c\"\n/*\n *  Mark-and-sweep garbage collection.\n */\n\n/* #include duk_internal.h -> already included */\n\nDUK_LOCAL_DECL void duk__mark_heaphdr(duk_heap *heap, duk_heaphdr *h);\nDUK_LOCAL_DECL void duk__mark_heaphdr_nonnull(duk_heap *heap, duk_heaphdr *h);\nDUK_LOCAL_DECL void duk__mark_tval(duk_heap *heap, duk_tval *tv);\nDUK_LOCAL_DECL void duk__mark_tvals(duk_heap *heap, duk_tval *tv, duk_idx_t count);\n\n/*\n *  Marking functions for heap types: mark children recursively.\n */\n\nDUK_LOCAL void duk__mark_hstring(duk_heap *heap, duk_hstring *h) {\n\tDUK_UNREF(heap);\n\tDUK_UNREF(h);\n\n\tDUK_DDD(DUK_DDDPRINT(\"duk__mark_hstring: %p\", (void *) h));\n\tDUK_ASSERT(h);\n\n\t/* nothing to process */\n}\n\nDUK_LOCAL void duk__mark_hobject(duk_heap *heap, duk_hobject *h) {\n\tduk_uint_fast32_t i;\n\n\tDUK_DDD(DUK_DDDPRINT(\"duk__mark_hobject: %p\", (void *) h));\n\n\tDUK_ASSERT(h);\n\n\t/* XXX: use advancing pointers instead of index macros -> faster and smaller? */\n\n\tfor (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(h); i++) {\n\t\tduk_hstring *key = DUK_HOBJECT_E_GET_KEY(heap, h, i);\n\t\tif (key == NULL) {\n\t\t\tcontinue;\n\t\t}\n\t\tduk__mark_heaphdr_nonnull(heap, (duk_heaphdr *) key);\n\t\tif (DUK_HOBJECT_E_SLOT_IS_ACCESSOR(heap, h, i)) {\n\t\t\tduk__mark_heaphdr(heap, (duk_heaphdr *) DUK_HOBJECT_E_GET_VALUE_PTR(heap, h, i)->a.get);\n\t\t\tduk__mark_heaphdr(heap, (duk_heaphdr *) DUK_HOBJECT_E_GET_VALUE_PTR(heap, h, i)->a.set);\n\t\t} else {\n\t\t\tduk__mark_tval(heap, &DUK_HOBJECT_E_GET_VALUE_PTR(heap, h, i)->v);\n\t\t}\n\t}\n\n\tfor (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ASIZE(h); i++) {\n\t\tduk__mark_tval(heap, DUK_HOBJECT_A_GET_VALUE_PTR(heap, h, i));\n\t}\n\n\t/* Hash part is a 'weak reference' and does not contribute. */\n\n\tduk__mark_heaphdr(heap, (duk_heaphdr *) DUK_HOBJECT_GET_PROTOTYPE(heap, h));\n\n\t/* Fast path for objects which don't have a subclass struct, or have a\n\t * subclass struct but nothing that needs marking in the subclass struct.\n\t */\n\tif (DUK_HOBJECT_HAS_FASTREFS(h)) {\n\t\tDUK_ASSERT(DUK_HOBJECT_ALLOWS_FASTREFS(h));\n\t\treturn;\n\t}\n\tDUK_ASSERT(DUK_HOBJECT_PROHIBITS_FASTREFS(h));\n\n\t/* XXX: reorg, more common first */\n\tif (DUK_HOBJECT_IS_COMPFUNC(h)) {\n\t\tduk_hcompfunc *f = (duk_hcompfunc *) h;\n\t\tduk_tval *tv, *tv_end;\n\t\tduk_hobject **fn, **fn_end;\n\n\t\tDUK_ASSERT_HCOMPFUNC_VALID(f);\n\n\t\t/* 'data' is reachable through every compiled function which\n\t\t * contains a reference.\n\t\t */\n\n\t\tduk__mark_heaphdr(heap, (duk_heaphdr *) DUK_HCOMPFUNC_GET_DATA(heap, f));\n\t\tduk__mark_heaphdr(heap, (duk_heaphdr *) DUK_HCOMPFUNC_GET_LEXENV(heap, f));\n\t\tduk__mark_heaphdr(heap, (duk_heaphdr *) DUK_HCOMPFUNC_GET_VARENV(heap, f));\n\n\t\tif (DUK_HCOMPFUNC_GET_DATA(heap, f) != NULL) {\n\t\t\ttv = DUK_HCOMPFUNC_GET_CONSTS_BASE(heap, f);\n\t\t\ttv_end = DUK_HCOMPFUNC_GET_CONSTS_END(heap, f);\n\t\t\twhile (tv < tv_end) {\n\t\t\t\tduk__mark_tval(heap, tv);\n\t\t\t\ttv++;\n\t\t\t}\n\n\t\t\tfn = DUK_HCOMPFUNC_GET_FUNCS_BASE(heap, f);\n\t\t\tfn_end = DUK_HCOMPFUNC_GET_FUNCS_END(heap, f);\n\t\t\twhile (fn < fn_end) {\n\t\t\t\tduk__mark_heaphdr_nonnull(heap, (duk_heaphdr *) *fn);\n\t\t\t\tfn++;\n\t\t\t}\n\t\t} else {\n\t\t\t/* May happen in some out-of-memory corner cases. */\n\t\t\tDUK_D(DUK_DPRINT(\"duk_hcompfunc 'data' is NULL, skipping marking\"));\n\t\t}\n\t} else if (DUK_HOBJECT_IS_DECENV(h)) {\n\t\tduk_hdecenv *e = (duk_hdecenv *) h;\n\t\tDUK_ASSERT_HDECENV_VALID(e);\n\t\tduk__mark_heaphdr(heap, (duk_heaphdr *) e->thread);\n\t\tduk__mark_heaphdr(heap, (duk_heaphdr *) e->varmap);\n\t} else if (DUK_HOBJECT_IS_OBJENV(h)) {\n\t\tduk_hobjenv *e = (duk_hobjenv *) h;\n\t\tDUK_ASSERT_HOBJENV_VALID(e);\n\t\tduk__mark_heaphdr_nonnull(heap, (duk_heaphdr *) e->target);\n#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)\n\t} else if (DUK_HOBJECT_IS_BUFOBJ(h)) {\n\t\tduk_hbufobj *b = (duk_hbufobj *) h;\n\t\tDUK_ASSERT_HBUFOBJ_VALID(b);\n\t\tduk__mark_heaphdr(heap, (duk_heaphdr *) b->buf);\n\t\tduk__mark_heaphdr(heap, (duk_heaphdr *) b->buf_prop);\n#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */\n\t} else if (DUK_HOBJECT_IS_BOUNDFUNC(h)) {\n\t\tduk_hboundfunc *f = (duk_hboundfunc *) h;\n\t\tDUK_ASSERT_HBOUNDFUNC_VALID(f);\n\t\tduk__mark_tval(heap, &f->target);\n\t\tduk__mark_tval(heap, &f->this_binding);\n\t\tduk__mark_tvals(heap, f->args, f->nargs);\n#if defined(DUK_USE_ES6_PROXY)\n\t} else if (DUK_HOBJECT_IS_PROXY(h)) {\n\t\tduk_hproxy *p = (duk_hproxy *) h;\n\t\tDUK_ASSERT_HPROXY_VALID(p);\n\t\tduk__mark_heaphdr_nonnull(heap, (duk_heaphdr *) p->target);\n\t\tduk__mark_heaphdr_nonnull(heap, (duk_heaphdr *) p->handler);\n#endif  /* DUK_USE_ES6_PROXY */\n\t} else if (DUK_HOBJECT_IS_THREAD(h)) {\n\t\tduk_hthread *t = (duk_hthread *) h;\n\t\tduk_activation *act;\n\t\tduk_tval *tv;\n\n\t\tDUK_ASSERT_HTHREAD_VALID(t);\n\n\t\ttv = t->valstack;\n\t\twhile (tv < t->valstack_top) {\n\t\t\tduk__mark_tval(heap, tv);\n\t\t\ttv++;\n\t\t}\n\n\t\tfor (act = t->callstack_curr; act != NULL; act = act->parent) {\n\t\t\tduk__mark_heaphdr(heap, (duk_heaphdr *) DUK_ACT_GET_FUNC(act));\n\t\t\tduk__mark_heaphdr(heap, (duk_heaphdr *) act->var_env);\n\t\t\tduk__mark_heaphdr(heap, (duk_heaphdr *) act->lex_env);\n#if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)\n\t\t\tduk__mark_heaphdr(heap, (duk_heaphdr *) act->prev_caller);\n#endif\n#if 0  /* nothing now */\n\t\t\tfor (cat = act->cat; cat != NULL; cat = cat->parent) {\n\t\t\t}\n#endif\n\t\t}\n\n\t\tduk__mark_heaphdr(heap, (duk_heaphdr *) t->resumer);\n\n\t\tfor (i = 0; i < DUK_NUM_BUILTINS; i++) {\n\t\t\tduk__mark_heaphdr(heap, (duk_heaphdr *) t->builtins[i]);\n\t\t}\n\t} else {\n\t\t/* We may come here if the object should have a FASTREFS flag\n\t\t * but it's missing for some reason.  Assert for never getting\n\t\t * here; however, other than performance, this is harmless.\n\t\t */\n\t\tDUK_D(DUK_DPRINT(\"missing FASTREFS flag for: %!iO\", h));\n\t\tDUK_ASSERT(0);\n\t}\n}\n\n/* Mark any duk_heaphdr type.  Recursion tracking happens only here. */\nDUK_LOCAL void duk__mark_heaphdr(duk_heap *heap, duk_heaphdr *h) {\n\tDUK_DDD(DUK_DDDPRINT(\"duk__mark_heaphdr %p, type %ld\",\n\t                     (void *) h,\n\t                     (h != NULL ? (long) DUK_HEAPHDR_GET_TYPE(h) : (long) -1)));\n\n\t/* XXX: add non-null variant? */\n\tif (h == NULL) {\n\t\treturn;\n\t}\n\n\tDUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY(h) || DUK_HEAPHDR_HAS_REACHABLE(h));\n\n#if defined(DUK_USE_ASSERTIONS) && defined(DUK_USE_REFERENCE_COUNTING)\n\tif (!DUK_HEAPHDR_HAS_READONLY(h)) {\n\t\th->h_assert_refcount++;  /* Comparison refcount: bump even if already reachable. */\n\t}\n#endif\n\tif (DUK_HEAPHDR_HAS_REACHABLE(h)) {\n\t\tDUK_DDD(DUK_DDDPRINT(\"already marked reachable, skip\"));\n\t\treturn;\n\t}\n#if defined(DUK_USE_ROM_OBJECTS)\n\t/* READONLY objects always have REACHABLE set, so the check above\n\t * will prevent READONLY objects from being marked here.\n\t */\n\tDUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY(h));\n#endif\n\n\tDUK_HEAPHDR_SET_REACHABLE(h);\n\n\tif (heap->ms_recursion_depth >= DUK_USE_MARK_AND_SWEEP_RECLIMIT) {\n\t\tDUK_D(DUK_DPRINT(\"mark-and-sweep recursion limit reached, marking as temproot: %p\", (void *) h));\n\t\tDUK_HEAP_SET_MARKANDSWEEP_RECLIMIT_REACHED(heap);\n\t\tDUK_HEAPHDR_SET_TEMPROOT(h);\n\t\treturn;\n\t}\n\n\theap->ms_recursion_depth++;\n\tDUK_ASSERT(heap->ms_recursion_depth != 0);  /* Wrap. */\n\n\tswitch (DUK_HEAPHDR_GET_TYPE(h)) {\n\tcase DUK_HTYPE_STRING:\n\t\tduk__mark_hstring(heap, (duk_hstring *) h);\n\t\tbreak;\n\tcase DUK_HTYPE_OBJECT:\n\t\tduk__mark_hobject(heap, (duk_hobject *) h);\n\t\tbreak;\n\tcase DUK_HTYPE_BUFFER:\n\t\t/* nothing to mark */\n\t\tbreak;\n\tdefault:\n\t\tDUK_D(DUK_DPRINT(\"attempt to mark heaphdr %p with invalid htype %ld\", (void *) h, (long) DUK_HEAPHDR_GET_TYPE(h)));\n\t\tDUK_UNREACHABLE();\n\t}\n\n\tDUK_ASSERT(heap->ms_recursion_depth > 0);\n\theap->ms_recursion_depth--;\n}\n\nDUK_LOCAL void duk__mark_tval(duk_heap *heap, duk_tval *tv) {\n\tDUK_DDD(DUK_DDDPRINT(\"duk__mark_tval %p\", (void *) tv));\n\tif (tv == NULL) {\n\t\treturn;\n\t}\n\tif (DUK_TVAL_IS_HEAP_ALLOCATED(tv)) {\n\t\tduk_heaphdr *h;\n\t\th = DUK_TVAL_GET_HEAPHDR(tv);\n\t\tDUK_ASSERT(h != NULL);\n\t\tduk__mark_heaphdr_nonnull(heap, h);\n\t}\n}\n\nDUK_LOCAL void duk__mark_tvals(duk_heap *heap, duk_tval *tv, duk_idx_t count) {\n\tDUK_ASSERT(count == 0 || tv != NULL);\n\n\twhile (count-- > 0) {\n\t\tif (DUK_TVAL_IS_HEAP_ALLOCATED(tv)) {\n\t\t\tduk_heaphdr *h;\n\t\t\th = DUK_TVAL_GET_HEAPHDR(tv);\n\t\t\tDUK_ASSERT(h != NULL);\n\t\t\tduk__mark_heaphdr_nonnull(heap, h);\n\t\t}\n\t\ttv++;\n\t}\n}\n\n/* Mark any duk_heaphdr type, caller guarantees a non-NULL pointer. */\nDUK_LOCAL void duk__mark_heaphdr_nonnull(duk_heap *heap, duk_heaphdr *h) {\n\t/* For now, just call the generic handler.  Change when call sites\n\t * are changed too.\n\t */\n\tduk__mark_heaphdr(heap, h);\n}\n\n/*\n *  Mark the heap.\n */\n\nDUK_LOCAL void duk__mark_roots_heap(duk_heap *heap) {\n\tduk_small_uint_t i;\n\n\tDUK_DD(DUK_DDPRINT(\"duk__mark_roots_heap: %p\", (void *) heap));\n\n\tduk__mark_heaphdr(heap, (duk_heaphdr *) heap->heap_thread);\n\tduk__mark_heaphdr(heap, (duk_heaphdr *) heap->heap_object);\n\n\tfor (i = 0; i < DUK_HEAP_NUM_STRINGS; i++) {\n\t\tduk_hstring *h = DUK_HEAP_GET_STRING(heap, i);\n\t\tduk__mark_heaphdr(heap, (duk_heaphdr *) h);\n\t}\n\n\tduk__mark_tval(heap, &heap->lj.value1);\n\tduk__mark_tval(heap, &heap->lj.value2);\n\n#if defined(DUK_USE_DEBUGGER_SUPPORT)\n\tfor (i = 0; i < heap->dbg_breakpoint_count; i++) {\n\t\tduk__mark_heaphdr(heap, (duk_heaphdr *) heap->dbg_breakpoints[i].filename);\n\t}\n#endif\n}\n\n/*\n *  Mark unreachable, finalizable objects.\n *\n *  Such objects will be moved aside and their finalizers run later.  They\n *  have to be treated as reachability roots for their properties etc to\n *  remain allocated.  This marking is only done for unreachable values which\n *  would be swept later.\n *\n *  Objects are first marked FINALIZABLE and only then marked as reachability\n *  roots; otherwise circular references might be handled inconsistently.\n */\n\n#if defined(DUK_USE_FINALIZER_SUPPORT)\nDUK_LOCAL void duk__mark_finalizable(duk_heap *heap) {\n\tduk_heaphdr *hdr;\n\tduk_size_t count_finalizable = 0;\n\n\tDUK_DD(DUK_DDPRINT(\"duk__mark_finalizable: %p\", (void *) heap));\n\n\tDUK_ASSERT(heap->heap_thread != NULL);\n\n\thdr = heap->heap_allocated;\n\twhile (hdr != NULL) {\n\t\t/* A finalizer is looked up from the object and up its\n\t\t * prototype chain (which allows inherited finalizers).\n\t\t * The finalizer is checked for using a duk_hobject flag\n\t\t * which is kept in sync with the presence and callability\n\t\t * of a _Finalizer hidden symbol.\n\t\t */\n\n\t\tif (!DUK_HEAPHDR_HAS_REACHABLE(hdr) &&\n\t\t    DUK_HEAPHDR_IS_OBJECT(hdr) &&\n\t\t    !DUK_HEAPHDR_HAS_FINALIZED(hdr) &&\n\t\t    DUK_HOBJECT_HAS_FINALIZER_FAST(heap, (duk_hobject *) hdr)) {\n\t\t\t/* heaphdr:\n\t\t\t *  - is not reachable\n\t\t\t *  - is an object\n\t\t\t *  - is not a finalized object waiting for rescue/keep decision\n\t\t\t *  - has a finalizer\n\t\t\t */\n\n\t\t\tDUK_DD(DUK_DDPRINT(\"unreachable heap object will be \"\n\t\t\t                   \"finalized -> mark as finalizable \"\n\t\t\t                   \"and treat as a reachability root: %p\",\n\t\t\t                   (void *) hdr));\n\t\t\tDUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY(hdr));\n\t\t\tDUK_HEAPHDR_SET_FINALIZABLE(hdr);\n\t\t\tcount_finalizable++;\n\t\t}\n\n\t\thdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);\n\t}\n\n\tif (count_finalizable == 0) {\n\t\treturn;\n\t}\n\n\tDUK_DD(DUK_DDPRINT(\"marked %ld heap objects as finalizable, now mark them reachable\",\n\t                   (long) count_finalizable));\n\n\thdr = heap->heap_allocated;\n\twhile (hdr != NULL) {\n\t\tif (DUK_HEAPHDR_HAS_FINALIZABLE(hdr)) {\n\t\t\tduk__mark_heaphdr_nonnull(heap, hdr);\n\t\t}\n\n\t\thdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);\n\t}\n\n\t/* Caller will finish the marking process if we hit a recursion limit. */\n}\n#endif  /* DUK_USE_FINALIZER_SUPPORT */\n\n/*\n *  Mark objects on finalize_list.\n */\n\n#if defined(DUK_USE_FINALIZER_SUPPORT)\nDUK_LOCAL void duk__mark_finalize_list(duk_heap *heap) {\n\tduk_heaphdr *hdr;\n#if defined(DUK_USE_DEBUG)\n\tduk_size_t count_finalize_list = 0;\n#endif\n\n\tDUK_DD(DUK_DDPRINT(\"duk__mark_finalize_list: %p\", (void *) heap));\n\n\thdr = heap->finalize_list;\n\twhile (hdr != NULL) {\n\t\tduk__mark_heaphdr_nonnull(heap, hdr);\n\t\thdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);\n#if defined(DUK_USE_DEBUG)\n\t\tcount_finalize_list++;\n#endif\n\t}\n\n#if defined(DUK_USE_DEBUG)\n\tif (count_finalize_list > 0) {\n\t\tDUK_D(DUK_DPRINT(\"marked %ld objects on the finalize_list as reachable (previous finalizer run skipped)\",\n\t\t                 (long) count_finalize_list));\n\t}\n#endif\n}\n#endif  /* DUK_USE_FINALIZER_SUPPORT */\n\n/*\n *  Fallback marking handler if recursion limit is reached.\n *\n *  Iterates 'temproots' until recursion limit is no longer hit.  Temproots\n *  can be in heap_allocated or finalize_list; refzero_list is now always\n *  empty for mark-and-sweep.  A temproot may occur in finalize_list now if\n *  there are objects on the finalize_list and user code creates a reference\n *  from an object in heap_allocated to the object in finalize_list (which is\n *  now allowed), and it happened to coincide with the recursion depth limit.\n *\n *  This is a slow scan, but guarantees that we finish with a bounded C stack.\n *\n *  Note that nodes may have been marked as temproots before this scan begun,\n *  OR they may have been marked during the scan (as we process nodes\n *  recursively also during the scan).  This is intended behavior.\n */\n\n#if defined(DUK_USE_DEBUG)\nDUK_LOCAL void duk__handle_temproot(duk_heap *heap, duk_heaphdr *hdr, duk_size_t *count) {\n#else\nDUK_LOCAL void duk__handle_temproot(duk_heap *heap, duk_heaphdr *hdr) {\n#endif\n\tDUK_ASSERT(hdr != NULL);\n\n\tif (!DUK_HEAPHDR_HAS_TEMPROOT(hdr)) {\n\t\tDUK_DDD(DUK_DDDPRINT(\"not a temp root: %p\", (void *) hdr));\n\t\treturn;\n\t}\n\n\tDUK_DDD(DUK_DDDPRINT(\"found a temp root: %p\", (void *) hdr));\n\tDUK_HEAPHDR_CLEAR_TEMPROOT(hdr);\n\tDUK_HEAPHDR_CLEAR_REACHABLE(hdr);  /* Done so that duk__mark_heaphdr() works correctly. */\n#if defined(DUK_USE_ASSERTIONS) && defined(DUK_USE_REFERENCE_COUNTING)\n\thdr->h_assert_refcount--;  /* Same node visited twice. */\n#endif\n\tduk__mark_heaphdr_nonnull(heap, hdr);\n\n#if defined(DUK_USE_DEBUG)\n\t(*count)++;\n#endif\n}\n\nDUK_LOCAL void duk__mark_temproots_by_heap_scan(duk_heap *heap) {\n\tduk_heaphdr *hdr;\n#if defined(DUK_USE_DEBUG)\n\tduk_size_t count;\n#endif\n\n\tDUK_DD(DUK_DDPRINT(\"duk__mark_temproots_by_heap_scan: %p\", (void *) heap));\n\n\twhile (DUK_HEAP_HAS_MARKANDSWEEP_RECLIMIT_REACHED(heap)) {\n\t\tDUK_DD(DUK_DDPRINT(\"recursion limit reached, doing heap scan to continue from temproots\"));\n\n#if defined(DUK_USE_DEBUG)\n\t\tcount = 0;\n#endif\n\t\tDUK_HEAP_CLEAR_MARKANDSWEEP_RECLIMIT_REACHED(heap);\n\n\t\thdr = heap->heap_allocated;\n\t\twhile (hdr) {\n#if defined(DUK_USE_DEBUG)\n\t\t\tduk__handle_temproot(heap, hdr, &count);\n#else\n\t\t\tduk__handle_temproot(heap, hdr);\n#endif\n\t\t\thdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);\n\t\t}\n\n#if defined(DUK_USE_FINALIZER_SUPPORT)\n\t\thdr = heap->finalize_list;\n\t\twhile (hdr) {\n#if defined(DUK_USE_DEBUG)\n\t\t\tduk__handle_temproot(heap, hdr, &count);\n#else\n\t\t\tduk__handle_temproot(heap, hdr);\n#endif\n\t\t\thdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);\n\t\t}\n#endif\n\n#if defined(DUK_USE_DEBUG)\n\t\tDUK_DD(DUK_DDPRINT(\"temproot mark heap scan processed %ld temp roots\", (long) count));\n#endif\n\t}\n}\n\n/*\n *  Finalize refcounts for heap elements just about to be freed.\n *  This must be done for all objects before freeing to avoid any\n *  stale pointer dereferences.\n *\n *  Note that this must deduce the set of objects to be freed\n *  identically to duk__sweep_heap().\n */\n\n#if defined(DUK_USE_REFERENCE_COUNTING)\nDUK_LOCAL void duk__finalize_refcounts(duk_heap *heap) {\n\tduk_heaphdr *hdr;\n\n\tDUK_ASSERT(heap->heap_thread != NULL);\n\n\tDUK_DD(DUK_DDPRINT(\"duk__finalize_refcounts: heap=%p\", (void *) heap));\n\n\thdr = heap->heap_allocated;\n\twhile (hdr) {\n\t\tif (!DUK_HEAPHDR_HAS_REACHABLE(hdr)) {\n\t\t\t/*\n\t\t\t *  Unreachable object about to be swept.  Finalize target refcounts\n\t\t\t *  (objects which the unreachable object points to) without doing\n\t\t\t *  refzero processing.  Recursive decrefs are also prevented when\n\t\t\t *  refzero processing is disabled.\n\t\t\t *\n\t\t\t *  Value cannot be a finalizable object, as they have been made\n\t\t\t *  temporarily reachable for this round.\n\t\t\t */\n\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"unreachable object, refcount finalize before sweeping: %p\", (void *) hdr));\n\n\t\t\t/* Finalize using heap->heap_thread; DECREF has a\n\t\t\t * suppress check for mark-and-sweep which is based\n\t\t\t * on heap->ms_running.\n\t\t\t */\n\t\t\tduk_heaphdr_refcount_finalize_norz(heap, hdr);\n\t\t}\n\n\t\thdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);\n\t}\n}\n#endif  /* DUK_USE_REFERENCE_COUNTING */\n\n/*\n *  Clear (reachable) flags of finalize_list.\n *\n *  We could mostly do in the sweep phase when we move objects from the\n *  heap into the finalize_list.  However, if a finalizer run is skipped\n *  during a mark-and-sweep, the objects on the finalize_list will be marked\n *  reachable during the next mark-and-sweep.  Since they're already on the\n *  finalize_list, no-one will be clearing their REACHABLE flag so we do it\n *  here.  (This now overlaps with the sweep handling in a harmless way.)\n */\n\n#if defined(DUK_USE_FINALIZER_SUPPORT)\nDUK_LOCAL void duk__clear_finalize_list_flags(duk_heap *heap) {\n\tduk_heaphdr *hdr;\n\n\tDUK_DD(DUK_DDPRINT(\"duk__clear_finalize_list_flags: %p\", (void *) heap));\n\n\thdr = heap->finalize_list;\n\twhile (hdr) {\n\t\tDUK_HEAPHDR_CLEAR_REACHABLE(hdr);\n#if defined(DUK_USE_ASSERTIONS)\n\t\tDUK_ASSERT(DUK_HEAPHDR_HAS_FINALIZABLE(hdr) || \\\n\t\t           (heap->currently_finalizing == hdr));\n#endif\n\t\t/* DUK_HEAPHDR_FLAG_FINALIZED may be set. */\n\t\tDUK_ASSERT(!DUK_HEAPHDR_HAS_TEMPROOT(hdr));\n\t\thdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);\n\t}\n}\n#endif  /* DUK_USE_FINALIZER_SUPPORT */\n\n/*\n *  Sweep stringtable.\n */\n\nDUK_LOCAL void duk__sweep_stringtable(duk_heap *heap, duk_size_t *out_count_keep) {\n\tduk_hstring *h;\n\tduk_hstring *prev;\n\tduk_uint32_t i;\n#if defined(DUK_USE_DEBUG)\n\tduk_size_t count_free = 0;\n#endif\n\tduk_size_t count_keep = 0;\n\n\tDUK_DD(DUK_DDPRINT(\"duk__sweep_stringtable: %p\", (void *) heap));\n\n#if defined(DUK_USE_STRTAB_PTRCOMP)\n\tif (heap->strtable16 == NULL) {\n#else\n\tif (heap->strtable == NULL) {\n#endif\n\t\tgoto done;\n\t}\n\n\tfor (i = 0; i < heap->st_size; i++) {\n#if defined(DUK_USE_STRTAB_PTRCOMP)\n\t\th = DUK_USE_HEAPPTR_DEC16(heap->heap_udata, heap->strtable16[i]);\n#else\n\t\th = heap->strtable[i];\n#endif\n\t\tprev = NULL;\n\t\twhile (h != NULL) {\n\t\t\tduk_hstring *next;\n\t\t\tnext = h->hdr.h_next;\n\n\t\t\tif (DUK_HEAPHDR_HAS_REACHABLE((duk_heaphdr *) h)) {\n\t\t\t\tDUK_HEAPHDR_CLEAR_REACHABLE((duk_heaphdr *) h);\n\t\t\t\tcount_keep++;\n\t\t\t\tprev = h;\n\t\t\t} else {\n#if defined(DUK_USE_DEBUG)\n\t\t\t\tcount_free++;\n#endif\n\n#if defined(DUK_USE_REFERENCE_COUNTING)\n\t\t\t\t/* Non-zero refcounts should not happen for unreachable strings,\n\t\t\t\t * because we refcount finalize all unreachable objects which\n\t\t\t\t * should have decreased unreachable string refcounts to zero\n\t\t\t\t * (even for cycles).\n\t\t\t\t */\n\t\t\t\tDUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) h) == 0);\n#endif\n\n\t\t\t\t/* Deal with weak references first. */\n\t\t\t\tduk_heap_strcache_string_remove(heap, (duk_hstring *) h);\n\n\t\t\t\t/* Remove the string from the string table. */\n\t\t\t\tduk_heap_strtable_unlink_prev(heap, (duk_hstring *) h, (duk_hstring *) prev);\n\n\t\t\t\t/* Free inner references (these exist e.g. when external\n\t\t\t\t * strings are enabled) and the struct itself.\n\t\t\t\t */\n\t\t\t\tduk_free_hstring(heap, (duk_hstring *) h);\n\n\t\t\t\t/* Don't update 'prev'; it should be last string kept. */\n\t\t\t}\n\n\t\t\th = next;\n\t\t}\n\t}\n\n done:\n#if defined(DUK_USE_DEBUG)\n\tDUK_D(DUK_DPRINT(\"mark-and-sweep sweep stringtable: %ld freed, %ld kept\",\n\t                 (long) count_free, (long) count_keep));\n#endif\n\t*out_count_keep = count_keep;\n}\n\n/*\n *  Sweep heap.\n */\n\nDUK_LOCAL void duk__sweep_heap(duk_heap *heap, duk_small_uint_t flags, duk_size_t *out_count_keep) {\n\tduk_heaphdr *prev;  /* last element that was left in the heap */\n\tduk_heaphdr *curr;\n\tduk_heaphdr *next;\n#if defined(DUK_USE_DEBUG)\n\tduk_size_t count_free = 0;\n\tduk_size_t count_finalize = 0;\n\tduk_size_t count_rescue = 0;\n#endif\n\tduk_size_t count_keep = 0;\n\n\tDUK_DD(DUK_DDPRINT(\"duk__sweep_heap: %p\", (void *) heap));\n\n\tprev = NULL;\n\tcurr = heap->heap_allocated;\n\theap->heap_allocated = NULL;\n\twhile (curr) {\n\t\t/* Strings and ROM objects are never placed on the heap allocated list. */\n\t\tDUK_ASSERT(DUK_HEAPHDR_GET_TYPE(curr) != DUK_HTYPE_STRING);\n\t\tDUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY(curr));\n\n\t\tnext = DUK_HEAPHDR_GET_NEXT(heap, curr);\n\n\t\tif (DUK_HEAPHDR_HAS_REACHABLE(curr)) {\n\t\t\t/*\n\t\t\t *  Reachable object:\n\t\t\t *    - If FINALIZABLE -> actually unreachable (but marked\n\t\t\t *      artificially reachable), queue to finalize_list.\n\t\t\t *    - If !FINALIZABLE but FINALIZED -> rescued after\n\t\t\t *      finalizer execution.\n\t\t\t *    - Otherwise just a normal, reachable object.\n\t\t\t *\n\t\t\t *  Objects which are kept are queued to heap_allocated\n\t\t\t *  tail (we're essentially filtering heap_allocated in\n\t\t\t *  practice).\n\t\t\t */\n\n#if defined(DUK_USE_FINALIZER_SUPPORT)\n\t\t\tif (DUK_UNLIKELY(DUK_HEAPHDR_HAS_FINALIZABLE(curr))) {\n\t\t\t\tDUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZED(curr));\n\t\t\t\tDUK_ASSERT(DUK_HEAPHDR_GET_TYPE(curr) == DUK_HTYPE_OBJECT);\n\t\t\t\tDUK_DD(DUK_DDPRINT(\"sweep; reachable, finalizable --> move to finalize_list: %p\", (void *) curr));\n\n#if defined(DUK_USE_REFERENCE_COUNTING)\n\t\t\t\tDUK_HEAPHDR_PREINC_REFCOUNT(curr);  /* Bump refcount so that refzero never occurs when pending a finalizer call. */\n#endif\n\t\t\t\tDUK_HEAP_INSERT_INTO_FINALIZE_LIST(heap, curr);\n#if defined(DUK_USE_DEBUG)\n\t\t\t\tcount_finalize++;\n#endif\n\t\t\t}\n\t\t\telse\n#endif  /* DUK_USE_FINALIZER_SUPPORT */\n\t\t\t{\n\t\t\t\tif (DUK_UNLIKELY(DUK_HEAPHDR_HAS_FINALIZED(curr))) {\n\t\t\t\t\tDUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZABLE(curr));\n\t\t\t\t\tDUK_ASSERT(DUK_HEAPHDR_GET_TYPE(curr) == DUK_HTYPE_OBJECT);\n\n\t\t\t\t\tif (flags & DUK_MS_FLAG_POSTPONE_RESCUE) {\n\t\t\t\t\t\tDUK_DD(DUK_DDPRINT(\"sweep; reachable, finalized, but postponing rescue decisions --> keep object (with FINALIZED set): %!iO\", curr));\n\t\t\t\t\t\tcount_keep++;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tDUK_DD(DUK_DDPRINT(\"sweep; reachable, finalized --> rescued after finalization: %p\", (void *) curr));\n#if defined(DUK_USE_FINALIZER_SUPPORT)\n\t\t\t\t\t\tDUK_HEAPHDR_CLEAR_FINALIZED(curr);\n#endif\n#if defined(DUK_USE_DEBUG)\n\t\t\t\t\t\tcount_rescue++;\n#endif\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tDUK_DD(DUK_DDPRINT(\"sweep; reachable --> keep: %!iO\", curr));\n\t\t\t\t\tcount_keep++;\n\t\t\t\t}\n\n\t\t\t\tif (prev != NULL) {\n\t\t\t\t\tDUK_ASSERT(heap->heap_allocated != NULL);\n\t\t\t\t\tDUK_HEAPHDR_SET_NEXT(heap, prev, curr);\n\t\t\t\t} else {\n\t\t\t\t\tDUK_ASSERT(heap->heap_allocated == NULL);\n\t\t\t\t\theap->heap_allocated = curr;\n\t\t\t\t}\n#if defined(DUK_USE_DOUBLE_LINKED_HEAP)\n\t\t\t\tDUK_HEAPHDR_SET_PREV(heap, curr, prev);\n#endif\n\t\t\t\tDUK_ASSERT_HEAPHDR_LINKS(heap, prev);\n\t\t\t\tDUK_ASSERT_HEAPHDR_LINKS(heap, curr);\n\t\t\t\tprev = curr;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t *  Shrink check for value stacks here.  We're inside\n\t\t\t *  ms_prevent_count protection which prevents recursive\n\t\t\t *  mark-and-sweep and refzero finalizers, so there are\n\t\t\t *  no side effects that would affect the heap lists.\n\t\t\t */\n\t\t\tif (DUK_HEAPHDR_IS_OBJECT(curr) && DUK_HOBJECT_IS_THREAD((duk_hobject *) curr)) {\n\t\t\t\tduk_hthread *thr_curr = (duk_hthread *) curr;\n\t\t\t\tDUK_DD(DUK_DDPRINT(\"value stack shrink check for thread: %!O\", curr));\n\t\t\t\tduk_valstack_shrink_check_nothrow(thr_curr, flags & DUK_MS_FLAG_EMERGENCY /*snug*/);\n\t\t\t}\n\n\t\t\tDUK_HEAPHDR_CLEAR_REACHABLE(curr);\n\t\t\t/* Keep FINALIZED if set, used if rescue decisions are postponed. */\n\t\t\t/* Keep FINALIZABLE for objects on finalize_list. */\n\t\t\tDUK_ASSERT(!DUK_HEAPHDR_HAS_REACHABLE(curr));\n\t\t} else {\n\t\t\t/*\n\t\t\t *  Unreachable object:\n\t\t\t *    - If FINALIZED, object was finalized but not\n\t\t\t *      rescued.  This doesn't affect freeing.\n\t\t\t *    - Otherwise normal unreachable object.\n\t\t\t *\n\t\t\t *  There's no guard preventing a FINALIZED object\n\t\t\t *  from being freed while finalizers execute: the\n\t\t\t *  artificial finalize_list reachability roots can't\n\t\t\t *  cause an incorrect free decision (but can cause\n\t\t\t *  an incorrect rescue decision).\n\t\t\t */\n\n#if defined(DUK_USE_REFERENCE_COUNTING)\n\t\t\t/* Non-zero refcounts should not happen because we refcount\n\t\t\t * finalize all unreachable objects which should cancel out\n\t\t\t * refcounts (even for cycles).\n\t\t\t */\n\t\t\tDUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(curr) == 0);\n#endif\n\t\t\tDUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZABLE(curr));\n\n#if defined(DUK_USE_DEBUG)\n\t\t\tif (DUK_HEAPHDR_HAS_FINALIZED(curr)) {\n\t\t\t\tDUK_DD(DUK_DDPRINT(\"sweep; unreachable, finalized --> finalized object not rescued: %p\", (void *) curr));\n\t\t\t} else {\n\t\t\t\tDUK_DD(DUK_DDPRINT(\"sweep; not reachable --> free: %p\", (void *) curr));\n\t\t\t}\n\n#endif\n\n\t\t\t/* Note: object cannot be a finalizable unreachable object, as\n\t\t\t * they have been marked temporarily reachable for this round,\n\t\t\t * and are handled above.\n\t\t\t */\n\n#if defined(DUK_USE_DEBUG)\n\t\t\tcount_free++;\n#endif\n\n\t\t\t/* Weak refs should be handled here, but no weak refs for\n\t\t\t * any non-string objects exist right now.\n\t\t\t */\n\n\t\t\t/* Free object and all auxiliary (non-heap) allocs. */\n\t\t\tduk_heap_free_heaphdr_raw(heap, curr);\n\t\t}\n\n\t\tcurr = next;\n\t}\n\n\tif (prev != NULL) {\n\t\tDUK_HEAPHDR_SET_NEXT(heap, prev, NULL);\n\t}\n\tDUK_ASSERT_HEAPHDR_LINKS(heap, prev);\n\n#if defined(DUK_USE_DEBUG)\n\tDUK_D(DUK_DPRINT(\"mark-and-sweep sweep objects (non-string): %ld freed, %ld kept, %ld rescued, %ld queued for finalization\",\n\t                 (long) count_free, (long) count_keep, (long) count_rescue, (long) count_finalize));\n#endif\n\t*out_count_keep = count_keep;\n}\n\n/*\n *  Object compaction.\n *\n *  Compaction is assumed to never throw an error.\n */\n\nDUK_LOCAL int duk__protected_compact_object(duk_hthread *thr, void *udata) {\n\tduk_hobject *obj;\n\t/* XXX: for threads, compact stacks? */\n\n\tDUK_UNREF(udata);\n\tobj = duk_known_hobject(thr, -1);\n\tduk_hobject_compact_props(thr, obj);\n\treturn 0;\n}\n\n#if defined(DUK_USE_DEBUG)\nDUK_LOCAL void duk__compact_object_list(duk_heap *heap, duk_hthread *thr, duk_heaphdr *start, duk_size_t *p_count_check, duk_size_t *p_count_compact, duk_size_t *p_count_bytes_saved) {\n#else\nDUK_LOCAL void duk__compact_object_list(duk_heap *heap, duk_hthread *thr, duk_heaphdr *start) {\n#endif\n\tduk_heaphdr *curr;\n#if defined(DUK_USE_DEBUG)\n\tduk_size_t old_size, new_size;\n#endif\n\tduk_hobject *obj;\n\n\tDUK_UNREF(heap);\n\n\tcurr = start;\n\twhile (curr) {\n\t\tDUK_DDD(DUK_DDDPRINT(\"mark-and-sweep compact: %p\", (void *) curr));\n\n\t\tif (DUK_HEAPHDR_GET_TYPE(curr) != DUK_HTYPE_OBJECT) {\n\t\t\tgoto next;\n\t\t}\n\t\tobj = (duk_hobject *) curr;\n\n#if defined(DUK_USE_DEBUG)\n\t\told_size = DUK_HOBJECT_P_COMPUTE_SIZE(DUK_HOBJECT_GET_ESIZE(obj),\n\t\t                                      DUK_HOBJECT_GET_ASIZE(obj),\n\t\t                                      DUK_HOBJECT_GET_HSIZE(obj));\n#endif\n\n\t\tDUK_DD(DUK_DDPRINT(\"compact object: %p\", (void *) obj));\n\t\tduk_push_hobject(thr, obj);\n\t\t/* XXX: disable error handlers for duration of compaction? */\n\t\tduk_safe_call(thr, duk__protected_compact_object, NULL, 1, 0);\n\n#if defined(DUK_USE_DEBUG)\n\t\tnew_size = DUK_HOBJECT_P_COMPUTE_SIZE(DUK_HOBJECT_GET_ESIZE(obj),\n\t\t                                      DUK_HOBJECT_GET_ASIZE(obj),\n\t\t                                      DUK_HOBJECT_GET_HSIZE(obj));\n#endif\n\n#if defined(DUK_USE_DEBUG)\n\t\t(*p_count_compact)++;\n\t\t(*p_count_bytes_saved) += (duk_size_t) (old_size - new_size);\n#endif\n\n\t next:\n\t\tcurr = DUK_HEAPHDR_GET_NEXT(heap, curr);\n#if defined(DUK_USE_DEBUG)\n\t\t(*p_count_check)++;\n#endif\n\t}\n}\n\nDUK_LOCAL void duk__compact_objects(duk_heap *heap) {\n\t/* XXX: which lists should participate?  to be finalized? */\n#if defined(DUK_USE_DEBUG)\n\tduk_size_t count_check = 0;\n\tduk_size_t count_compact = 0;\n\tduk_size_t count_bytes_saved = 0;\n#endif\n\n\tDUK_DD(DUK_DDPRINT(\"duk__compact_objects: %p\", (void *) heap));\n\n\tDUK_ASSERT(heap->heap_thread != NULL);\n\n#if defined(DUK_USE_DEBUG)\n\tduk__compact_object_list(heap, heap->heap_thread, heap->heap_allocated, &count_check, &count_compact, &count_bytes_saved);\n#if defined(DUK_USE_FINALIZER_SUPPORT)\n\tduk__compact_object_list(heap, heap->heap_thread, heap->finalize_list, &count_check, &count_compact, &count_bytes_saved);\n#endif\n#else\n\tduk__compact_object_list(heap, heap->heap_thread, heap->heap_allocated);\n#if defined(DUK_USE_FINALIZER_SUPPORT)\n\tduk__compact_object_list(heap, heap->heap_thread, heap->finalize_list);\n#endif\n#endif\n#if defined(DUK_USE_REFERENCE_COUNTING)\n\tDUK_ASSERT(heap->refzero_list == NULL);  /* Always handled to completion inline in DECREF. */\n#endif\n\n#if defined(DUK_USE_DEBUG)\n\tDUK_D(DUK_DPRINT(\"mark-and-sweep compact objects: %ld checked, %ld compaction attempts, %ld bytes saved by compaction\",\n\t                 (long) count_check, (long) count_compact, (long) count_bytes_saved));\n#endif\n}\n\n/*\n *  Assertion helpers.\n */\n\n#if defined(DUK_USE_ASSERTIONS)\nDUK_LOCAL void duk__assert_heaphdr_flags(duk_heap *heap) {\n\tduk_heaphdr *hdr;\n\n\thdr = heap->heap_allocated;\n\twhile (hdr) {\n\t\tDUK_ASSERT(!DUK_HEAPHDR_HAS_REACHABLE(hdr));\n\t\tDUK_ASSERT(!DUK_HEAPHDR_HAS_TEMPROOT(hdr));\n\t\tDUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZABLE(hdr));\n\t\t/* may have FINALIZED */\n\t\thdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);\n\t}\n\n#if defined(DUK_USE_REFERENCE_COUNTING)\n\tDUK_ASSERT(heap->refzero_list == NULL);  /* Always handled to completion inline in DECREF. */\n#endif\n}\n\n#if defined(DUK_USE_REFERENCE_COUNTING)\nDUK_LOCAL void duk__assert_valid_refcounts(duk_heap *heap) {\n\tduk_heaphdr *hdr = heap->heap_allocated;\n\twhile (hdr) {\n\t\t/* Cannot really assert much w.r.t. refcounts now. */\n\n\t\tif (DUK_HEAPHDR_GET_REFCOUNT(hdr) == 0 &&\n\t\t    DUK_HEAPHDR_HAS_FINALIZED(hdr)) {\n\t\t\t/* An object may be in heap_allocated list with a zero\n\t\t\t * refcount if it has just been finalized and is waiting\n\t\t\t * to be collected by the next cycle.\n\t\t\t * (This doesn't currently happen however.)\n\t\t\t */\n\t\t} else if (DUK_HEAPHDR_GET_REFCOUNT(hdr) == 0) {\n\t\t\t/* An object may be in heap_allocated list with a zero\n\t\t\t * refcount also if it is a temporary object created\n\t\t\t * during debugger paused state.  It will get collected\n\t\t\t * by mark-and-sweep based on its reachability status\n\t\t\t * (presumably not reachable because refcount is 0).\n\t\t\t */\n\t\t}\n\t\tDUK_ASSERT_DISABLE(DUK_HEAPHDR_GET_REFCOUNT(hdr) >= 0);  /* Unsigned. */\n\t\thdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);\n\t}\n}\n\nDUK_LOCAL void duk__clear_assert_refcounts(duk_heap *heap) {\n\tduk_heaphdr *curr;\n\tduk_uint32_t i;\n\n\tfor (curr = heap->heap_allocated; curr != NULL; curr = DUK_HEAPHDR_GET_NEXT(heap, curr)) {\n\t\tcurr->h_assert_refcount = 0;\n\t}\n#if defined(DUK_USE_FINALIZER_SUPPORT)\n\tfor (curr = heap->finalize_list; curr != NULL; curr = DUK_HEAPHDR_GET_NEXT(heap, curr)) {\n\t\tcurr->h_assert_refcount = 0;\n\t}\n#endif\n#if defined(DUK_USE_REFERENCE_COUNTING)\n\tfor (curr = heap->refzero_list; curr != NULL; curr = DUK_HEAPHDR_GET_NEXT(heap, curr)) {\n\t\tcurr->h_assert_refcount = 0;\n\t}\n#endif\n\n\tfor (i = 0; i < heap->st_size; i++) {\n\t\tduk_hstring *h;\n\n#if defined(DUK_USE_STRTAB_PTRCOMP)\n\t\th = DUK_USE_HEAPPTR_DEC16(heap->heap_udata, heap->strtable16[i]);\n#else\n\t\th = heap->strtable[i];\n#endif\n\t\twhile (h != NULL) {\n\t\t\t((duk_heaphdr *) h)->h_assert_refcount = 0;\n\t\t\th = h->hdr.h_next;\n\t\t}\n\t}\n}\n\nDUK_LOCAL void duk__check_refcount_heaphdr(duk_heaphdr *hdr) {\n\tduk_bool_t count_ok;\n\n\t/* The refcount check only makes sense for reachable objects on\n\t * heap_allocated or string table, after the sweep phase.  Prior to\n\t * sweep phase refcounts will include references that are not visible\n\t * via reachability roots.\n\t *\n\t * Because we're called after the sweep phase, all heap objects on\n\t * heap_allocated are reachable.  REACHABLE flags have already been\n\t * cleared so we can't check them.\n\t */\n\n\t/* ROM objects have intentionally incorrect refcount (1), but we won't\n\t * check them.\n\t */\n\tDUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY(hdr));\n\n\tcount_ok = ((duk_size_t) DUK_HEAPHDR_GET_REFCOUNT(hdr) == hdr->h_assert_refcount);\n\tif (!count_ok) {\n\t\tDUK_D(DUK_DPRINT(\"refcount mismatch for: %p: header=%ld counted=%ld --> %!iO\",\n\t\t                 (void *) hdr, (long) DUK_HEAPHDR_GET_REFCOUNT(hdr),\n\t\t                 (long) hdr->h_assert_refcount, hdr));\n\t\tDUK_ASSERT(0);\n\t}\n}\n\nDUK_LOCAL void duk__check_assert_refcounts(duk_heap *heap) {\n\tduk_heaphdr *curr;\n\tduk_uint32_t i;\n\n\tfor (curr = heap->heap_allocated; curr != NULL; curr = DUK_HEAPHDR_GET_NEXT(heap, curr)) {\n\t\tduk__check_refcount_heaphdr(curr);\n\t}\n#if defined(DUK_USE_FINALIZER_SUPPORT)\n\tfor (curr = heap->finalize_list; curr != NULL; curr = DUK_HEAPHDR_GET_NEXT(heap, curr)) {\n\t\tduk__check_refcount_heaphdr(curr);\n\t}\n#endif\n\n\tfor (i = 0; i < heap->st_size; i++) {\n\t\tduk_hstring *h;\n\n#if defined(DUK_USE_STRTAB_PTRCOMP)\n\t\th = DUK_USE_HEAPPTR_DEC16(heap->heap_udata, heap->strtable16[i]);\n#else\n\t\th = heap->strtable[i];\n#endif\n\t\twhile (h != NULL) {\n\t\t\tduk__check_refcount_heaphdr((duk_heaphdr *) h);\n\t\t\th = h->hdr.h_next;\n\t\t}\n\t}\n}\n#endif  /* DUK_USE_REFERENCE_COUNTING */\n#endif  /* DUK_USE_ASSERTIONS */\n\n/*\n *  Stats dump.\n */\n\n#if defined(DUK_USE_DEBUG)\nDUK_LOCAL void duk__dump_stats(duk_heap *heap) {\n\tDUK_D(DUK_DPRINT(\"stats executor: opcodes=%ld, interrupt=%ld, throw=%ld\",\n\t                 (long) heap->stats_exec_opcodes, (long) heap->stats_exec_interrupt,\n\t                 (long) heap->stats_exec_throw));\n\tDUK_D(DUK_DPRINT(\"stats call: all=%ld, tailcall=%ld, ecmatoecma=%ld\",\n\t                 (long) heap->stats_call_all, (long) heap->stats_call_tailcall,\n\t                 (long) heap->stats_call_ecmatoecma));\n\tDUK_D(DUK_DPRINT(\"stats safecall: all=%ld, nothrow=%ld, throw=%ld\",\n\t                 (long) heap->stats_safecall_all, (long) heap->stats_safecall_nothrow,\n\t                 (long) heap->stats_safecall_throw));\n\tDUK_D(DUK_DPRINT(\"stats mark-and-sweep: try_count=%ld, skip_count=%ld, emergency_count=%ld\",\n\t                 (long) heap->stats_ms_try_count, (long) heap->stats_ms_skip_count,\n\t                 (long) heap->stats_ms_emergency_count));\n\tDUK_D(DUK_DPRINT(\"stats stringtable: intern_hit=%ld, intern_miss=%ld, resize_check=%ld, resize_grow=%ld, resize_shrink=%ld\",\n\t                 (long) heap->stats_strtab_intern_hit, (long) heap->stats_strtab_intern_miss,\n\t                 (long) heap->stats_strtab_resize_check, (long) heap->stats_strtab_resize_grow,\n\t                 (long) heap->stats_strtab_resize_shrink));\n\tDUK_D(DUK_DPRINT(\"stats object: realloc_props=%ld, abandon_array=%ld\",\n\t                 (long) heap->stats_object_realloc_props, (long) heap->stats_object_abandon_array));\n\tDUK_D(DUK_DPRINT(\"stats getownpropdesc: count=%ld, hit=%ld, miss=%ld\",\n\t                 (long) heap->stats_getownpropdesc_count, (long) heap->stats_getownpropdesc_hit,\n\t                 (long) heap->stats_getownpropdesc_miss));\n\tDUK_D(DUK_DPRINT(\"stats getpropdesc: count=%ld, hit=%ld, miss=%ld\",\n\t                 (long) heap->stats_getpropdesc_count, (long) heap->stats_getpropdesc_hit,\n\t                 (long) heap->stats_getpropdesc_miss));\n\tDUK_D(DUK_DPRINT(\"stats getprop: all=%ld, arrayidx=%ld, bufobjidx=%ld, \"\n\t                 \"bufferidx=%ld, bufferlen=%ld, stringidx=%ld, stringlen=%ld, \"\n\t                 \"proxy=%ld, arguments=%ld\",\n\t                 (long) heap->stats_getprop_all, (long) heap->stats_getprop_arrayidx,\n\t                 (long) heap->stats_getprop_bufobjidx, (long) heap->stats_getprop_bufferidx,\n\t                 (long) heap->stats_getprop_bufferlen, (long) heap->stats_getprop_stringidx,\n\t                 (long) heap->stats_getprop_stringlen, (long) heap->stats_getprop_proxy,\n\t                 (long) heap->stats_getprop_arguments));\n\tDUK_D(DUK_DPRINT(\"stats putprop: all=%ld, arrayidx=%ld, bufobjidx=%ld, \"\n\t                 \"bufferidx=%ld, proxy=%ld\",\n\t                 (long) heap->stats_putprop_all, (long) heap->stats_putprop_arrayidx,\n\t                 (long) heap->stats_putprop_bufobjidx, (long) heap->stats_putprop_bufferidx,\n\t                 (long) heap->stats_putprop_proxy));\n\tDUK_D(DUK_DPRINT(\"stats getvar: all=%ld\",\n\t                 (long) heap->stats_getvar_all));\n\tDUK_D(DUK_DPRINT(\"stats putvar: all=%ld\",\n\t                 (long) heap->stats_putvar_all));\n}\n#endif  /* DUK_USE_DEBUG */\n\n/*\n *  Main mark-and-sweep function.\n *\n *  'flags' represents the features requested by the caller.  The current\n *  heap->ms_base_flags is ORed automatically into the flags; the base flags\n *  mask typically prevents certain mark-and-sweep operation to avoid trouble.\n */\n\nDUK_INTERNAL void duk_heap_mark_and_sweep(duk_heap *heap, duk_small_uint_t flags) {\n\tduk_size_t count_keep_obj;\n\tduk_size_t count_keep_str;\n#if defined(DUK_USE_VOLUNTARY_GC)\n\tduk_size_t tmp;\n#endif\n\n\tDUK_STATS_INC(heap, stats_ms_try_count);\n#if defined(DUK_USE_DEBUG)\n\tif (flags & DUK_MS_FLAG_EMERGENCY) {\n\t\tDUK_STATS_INC(heap, stats_ms_emergency_count);\n\t}\n#endif\n\n\t/* If debugger is paused, garbage collection is disabled by default.\n\t * This is achieved by bumping ms_prevent_count when becoming paused.\n\t */\n\tDUK_ASSERT(!DUK_HEAP_HAS_DEBUGGER_PAUSED(heap) || heap->ms_prevent_count > 0);\n\n\t/* Prevention/recursion check as soon as possible because we may\n\t * be called a number of times when voluntary mark-and-sweep is\n\t * pending.\n\t */\n\tif (heap->ms_prevent_count != 0) {\n\t\tDUK_DD(DUK_DDPRINT(\"reject recursive mark-and-sweep\"));\n\t\tDUK_STATS_INC(heap, stats_ms_skip_count);\n\t\treturn;\n\t}\n\tDUK_ASSERT(heap->ms_running == 0);  /* ms_prevent_count is bumped when ms_running is set */\n\n\t/* Heap_thread is used during mark-and-sweep for refcount finalization\n\t * (it's also used for finalizer execution once mark-and-sweep is\n\t * complete).  Heap allocation code ensures heap_thread is set and\n\t * properly initialized before setting ms_prevent_count to 0.\n\t */\n\tDUK_ASSERT(heap->heap_thread != NULL);\n\tDUK_ASSERT(heap->heap_thread->valstack != NULL);\n\n\tDUK_D(DUK_DPRINT(\"garbage collect (mark-and-sweep) starting, requested flags: 0x%08lx, effective flags: 0x%08lx\",\n\t                 (unsigned long) flags, (unsigned long) (flags | heap->ms_base_flags)));\n\n\tflags |= heap->ms_base_flags;\n#if defined(DUK_USE_FINALIZER_SUPPORT)\n\tif (heap->finalize_list != NULL) {\n\t\tflags |= DUK_MS_FLAG_POSTPONE_RESCUE;\n\t}\n#endif\n\n\t/*\n\t *  Assertions before\n\t */\n\n#if defined(DUK_USE_ASSERTIONS)\n\tDUK_ASSERT(heap->ms_prevent_count == 0);\n\tDUK_ASSERT(heap->ms_running == 0);\n\tDUK_ASSERT(!DUK_HEAP_HAS_DEBUGGER_PAUSED(heap));\n\tDUK_ASSERT(!DUK_HEAP_HAS_MARKANDSWEEP_RECLIMIT_REACHED(heap));\n\tDUK_ASSERT(heap->ms_recursion_depth == 0);\n\tduk__assert_heaphdr_flags(heap);\n#if defined(DUK_USE_REFERENCE_COUNTING)\n\t/* Note: heap->refzero_free_running may be true; a refcount\n\t * finalizer may trigger a mark-and-sweep.\n\t */\n\tduk__assert_valid_refcounts(heap);\n#endif  /* DUK_USE_REFERENCE_COUNTING */\n#endif  /* DUK_USE_ASSERTIONS */\n\n\t/*\n\t *  Begin\n\t */\n\n\tDUK_ASSERT(heap->ms_prevent_count == 0);\n\tDUK_ASSERT(heap->ms_running == 0);\n\theap->ms_prevent_count = 1;\n\theap->ms_running = 1;\n\n\t/*\n\t *  Free activation/catcher freelists on every mark-and-sweep for now.\n\t *  This is an initial rough draft; ideally we'd keep count of the\n\t *  freelist size and free only excess entries.\n\t */\n\n\tDUK_D(DUK_DPRINT(\"freeing temporary freelists\"));\n\tduk_heap_free_freelists(heap);\n\n\t/*\n\t *  Mark roots, hoping that recursion limit is not normally hit.\n\t *  If recursion limit is hit, run additional reachability rounds\n\t *  starting from \"temproots\" until marking is complete.\n\t *\n\t *  Marking happens in two phases: first we mark actual reachability\n\t *  roots (and run \"temproots\" to complete the process).  Then we\n\t *  check which objects are unreachable and are finalizable; such\n\t *  objects are marked as FINALIZABLE and marked as reachability\n\t *  (and \"temproots\" is run again to complete the process).\n\t *\n\t *  The heap finalize_list must also be marked as a reachability root.\n\t *  There may be objects on the list from a previous round if the\n\t *  previous run had finalizer skip flag.\n\t */\n\n#if defined(DUK_USE_ASSERTIONS) && defined(DUK_USE_REFERENCE_COUNTING)\n\tduk__clear_assert_refcounts(heap);\n#endif\n\tduk__mark_roots_heap(heap);               /* Mark main reachability roots. */\n#if defined(DUK_USE_REFERENCE_COUNTING)\n\tDUK_ASSERT(heap->refzero_list == NULL);   /* Always handled to completion inline in DECREF. */\n#endif\n\tduk__mark_temproots_by_heap_scan(heap);   /* Temproots. */\n\n#if defined(DUK_USE_FINALIZER_SUPPORT)\n\tduk__mark_finalizable(heap);              /* Mark finalizable as reachability roots. */\n\tduk__mark_finalize_list(heap);            /* Mark finalizer work list as reachability roots. */\n#endif\n\tduk__mark_temproots_by_heap_scan(heap);   /* Temproots. */\n\n\t/*\n\t *  Sweep garbage and remove marking flags, and move objects with\n\t *  finalizers to the finalizer work list.\n\t *\n\t *  Objects to be swept need to get their refcounts finalized before\n\t *  they are swept.  In other words, their target object refcounts\n\t *  need to be decreased.  This has to be done before freeing any\n\t *  objects to avoid decref'ing dangling pointers (which may happen\n\t *  even without bugs, e.g. with reference loops)\n\t *\n\t *  Because strings don't point to other heap objects, similar\n\t *  finalization is not necessary for strings.\n\t */\n\n\t/* XXX: more emergency behavior, e.g. find smaller hash sizes etc */\n\n#if defined(DUK_USE_REFERENCE_COUNTING)\n\tduk__finalize_refcounts(heap);\n#endif\n\tduk__sweep_heap(heap, flags, &count_keep_obj);\n\tduk__sweep_stringtable(heap, &count_keep_str);\n#if defined(DUK_USE_ASSERTIONS) && defined(DUK_USE_REFERENCE_COUNTING)\n\tduk__check_assert_refcounts(heap);\n#endif\n#if defined(DUK_USE_REFERENCE_COUNTING)\n\tDUK_ASSERT(heap->refzero_list == NULL);   /* Always handled to completion inline in DECREF. */\n#endif\n#if defined(DUK_USE_FINALIZER_SUPPORT)\n\tduk__clear_finalize_list_flags(heap);\n#endif\n\n\t/*\n\t *  Object compaction (emergency only).\n\t *\n\t *  Object compaction is a separate step after sweeping, as there is\n\t *  more free memory for it to work with.  Also, currently compaction\n\t *  may insert new objects into the heap allocated list and the string\n\t *  table which we don't want to do during a sweep (the reachability\n\t *  flags of such objects would be incorrect).  The objects inserted\n\t *  are currently:\n\t *\n\t *    - a temporary duk_hbuffer for a new properties allocation\n\t *    - if array part is abandoned, string keys are interned\n\t *\n\t *  The object insertions go to the front of the list, so they do not\n\t *  cause an infinite loop (they are not compacted).\n\t */\n\n\tif ((flags & DUK_MS_FLAG_EMERGENCY) &&\n\t    !(flags & DUK_MS_FLAG_NO_OBJECT_COMPACTION)) {\n\t\tduk__compact_objects(heap);\n\t}\n\n\t/*\n\t *  String table resize check.\n\t *\n\t *  This is mainly useful in emergency GC: if the string table load\n\t *  factor is really low for some reason, we can shrink the string\n\t *  table to a smaller size and free some memory in the process.\n\t *  Only execute in emergency GC.  String table has internal flags\n\t *  to protect against recursive resizing if this mark-and-sweep pass\n\t *  was triggered by a string table resize.\n\t */\n\n\tif (flags & DUK_MS_FLAG_EMERGENCY) {\n\t\tDUK_D(DUK_DPRINT(\"stringtable resize check in emergency gc\"));\n\t\tduk_heap_strtable_force_resize(heap);\n\t}\n\n\t/*\n\t *  Finish\n\t */\n\n\tDUK_ASSERT(heap->ms_prevent_count == 1);\n\theap->ms_prevent_count = 0;\n\tDUK_ASSERT(heap->ms_running == 1);\n\theap->ms_running = 0;\n\n\t/*\n\t *  Assertions after\n\t */\n\n#if defined(DUK_USE_ASSERTIONS)\n\tDUK_ASSERT(heap->ms_prevent_count == 0);\n\tDUK_ASSERT(!DUK_HEAP_HAS_MARKANDSWEEP_RECLIMIT_REACHED(heap));\n\tDUK_ASSERT(heap->ms_recursion_depth == 0);\n\tduk__assert_heaphdr_flags(heap);\n#if defined(DUK_USE_REFERENCE_COUNTING)\n\t/* Note: heap->refzero_free_running may be true; a refcount\n\t * finalizer may trigger a mark-and-sweep.\n\t */\n\tduk__assert_valid_refcounts(heap);\n#endif  /* DUK_USE_REFERENCE_COUNTING */\n#endif  /* DUK_USE_ASSERTIONS */\n\n\t/*\n\t *  Reset trigger counter\n\t */\n\n#if defined(DUK_USE_VOLUNTARY_GC)\n\ttmp = (count_keep_obj + count_keep_str) / 256;\n\theap->ms_trigger_counter = (duk_int_t) (\n\t    (tmp * DUK_HEAP_MARK_AND_SWEEP_TRIGGER_MULT) +\n\t    DUK_HEAP_MARK_AND_SWEEP_TRIGGER_ADD);\n\tDUK_D(DUK_DPRINT(\"garbage collect (mark-and-sweep) finished: %ld objects kept, %ld strings kept, trigger reset to %ld\",\n\t                 (long) count_keep_obj, (long) count_keep_str, (long) heap->ms_trigger_counter));\n#else\n\tDUK_D(DUK_DPRINT(\"garbage collect (mark-and-sweep) finished: %ld objects kept, %ld strings kept, no voluntary trigger\",\n\t                 (long) count_keep_obj, (long) count_keep_str));\n#endif\n\n\t/*\n\t *  Stats dump\n\t */\n\n#if defined(DUK_USE_DEBUG)\n\tduk__dump_stats(heap);\n#endif\n\n\t/*\n\t *  Finalize objects in the finalization work list.  Finalized\n\t *  objects are queued back to heap_allocated with FINALIZED set.\n\t *\n\t *  Since finalizers may cause arbitrary side effects, they are\n\t *  prevented e.g. during string table and object property allocation\n\t *  resizing using heap->pf_prevent_count.  In this case the objects\n\t *  remain in the finalization work list after mark-and-sweep exits\n\t *  and they may be finalized on the next pass or any DECREF checking\n\t *  for finalize_list.\n\t *\n\t *  As of Duktape 2.1 finalization happens outside mark-and-sweep\n\t *  protection.  Mark-and-sweep is allowed while the finalize_list\n\t *  is being processed, but no rescue decisions are done while the\n\t *  process is on-going.  This avoids incorrect rescue decisions\n\t *  if an object is considered reachable (and thus rescued) because\n\t *  of a reference via finalize_list (which is considered a reachability\n\t *  root).  When finalize_list is being processed, reachable objects\n\t *  with FINALIZED set will just keep their FINALIZED flag for later\n\t *  mark-and-sweep processing.\n\t *\n\t *  This could also be handled (a bit better) by having a more refined\n\t *  notion of reachability for rescue/free decisions.\n\t *\n\t *  XXX: avoid finalizer execution when doing emergency GC?\n\t */\n\n#if defined(DUK_USE_FINALIZER_SUPPORT)\n\t/* Attempt to process finalize_list, pf_prevent_count check\n\t * is inside the target.\n\t */\n\tduk_heap_process_finalize_list(heap);\n#endif  /* DUK_USE_FINALIZER_SUPPORT */\n}\n#line 1 \"duk_heap_memory.c\"\n/*\n *  Memory allocation handling.\n */\n\n/* #include duk_internal.h -> already included */\n\n/*\n *  Voluntary GC check\n */\n\n#if defined(DUK_USE_VOLUNTARY_GC)\nDUK_LOCAL DUK_INLINE void duk__check_voluntary_gc(duk_heap *heap) {\n\tif (DUK_UNLIKELY(--(heap)->ms_trigger_counter < 0)) {\n#if defined(DUK_USE_DEBUG)\n\t\tif (heap->ms_prevent_count == 0) {\n\t\t\tDUK_D(DUK_DPRINT(\"triggering voluntary mark-and-sweep\"));\n\t\t} else {\n\t\t\tDUK_DD(DUK_DDPRINT(\"gc blocked -> skip voluntary mark-and-sweep now\"));\n\t\t}\n#endif\n\n\t\t/* Prevention checks in the call target handle cases where\n\t\t * voluntary GC is not allowed.  The voluntary GC trigger\n\t\t * counter is only rewritten if mark-and-sweep actually runs.\n\t\t */\n\t\tduk_heap_mark_and_sweep(heap, DUK_MS_FLAG_VOLUNTARY /*flags*/);\n\t}\n}\n#define DUK__VOLUNTARY_PERIODIC_GC(heap)  do { duk__check_voluntary_gc((heap)); } while (0)\n#else\n#define DUK__VOLUNTARY_PERIODIC_GC(heap)  /* no voluntary gc */\n#endif  /* DUK_USE_VOLUNTARY_GC */\n\n/*\n *  Allocate memory with garbage collection\n */\n\nDUK_INTERNAL void *duk_heap_mem_alloc(duk_heap *heap, duk_size_t size) {\n\tvoid *res;\n\tduk_small_int_t i;\n\n\tDUK_ASSERT(heap != NULL);\n\tDUK_ASSERT_DISABLE(size >= 0);\n\n\t/*\n\t *  Voluntary periodic GC (if enabled)\n\t */\n\n\tDUK__VOLUNTARY_PERIODIC_GC(heap);\n\n\t/*\n\t *  First attempt\n\t */\n\n#if defined(DUK_USE_GC_TORTURE)\n\t/* Simulate alloc failure on every alloc, except when mark-and-sweep\n\t * is running.\n\t */\n\tif (heap->ms_prevent_count == 0) {\n\t\tDUK_DDD(DUK_DDDPRINT(\"gc torture enabled, pretend that first alloc attempt fails\"));\n\t\tres = NULL;\n\t\tDUK_UNREF(res);\n\t\tgoto skip_attempt;\n\t}\n#endif\n\tres = heap->alloc_func(heap->heap_udata, size);\n\tif (DUK_LIKELY(res || size == 0)) {\n\t\t/* For zero size allocations NULL is allowed. */\n\t\treturn res;\n\t}\n#if defined(DUK_USE_GC_TORTURE)\n skip_attempt:\n#endif\n\n\tDUK_D(DUK_DPRINT(\"first alloc attempt failed, attempt to gc and retry\"));\n\n#if 0\n\t/*\n\t *  Avoid a GC if GC is already running.  This can happen at a late\n\t *  stage in a GC when we try to e.g. resize the stringtable\n\t *  or compact objects.\n\t *\n\t *  NOTE: explicit handling isn't actually be needed: if the GC is\n\t *  not allowed, duk_heap_mark_and_sweep() will reject it for every\n\t *  attempt in the loop below, resulting in a NULL same as here.\n\t */\n\n\tif (heap->ms_prevent_count != 0) {\n\t\tDUK_D(DUK_DPRINT(\"duk_heap_mem_alloc() failed, gc in progress (gc skipped), alloc size %ld\", (long) size));\n\t\treturn NULL;\n\t}\n#endif\n\n\t/*\n\t *  Retry with several GC attempts.  Initial attempts are made without\n\t *  emergency mode; later attempts use emergency mode which minimizes\n\t *  memory allocations forcibly.\n\t */\n\n\tfor (i = 0; i < DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_LIMIT; i++) {\n\t\tduk_small_uint_t flags;\n\n\t\tflags = 0;\n\t\tif (i >= DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_EMERGENCY_LIMIT - 1) {\n\t\t\tflags |= DUK_MS_FLAG_EMERGENCY;\n\t\t}\n\n\t\tduk_heap_mark_and_sweep(heap, flags);\n\n\t\tres = heap->alloc_func(heap->heap_udata, size);\n\t\tif (res) {\n\t\t\tDUK_D(DUK_DPRINT(\"duk_heap_mem_alloc() succeeded after gc (pass %ld), alloc size %ld\",\n\t\t\t                 (long) (i + 1), (long) size));\n\t\t\treturn res;\n\t\t}\n\t}\n\n\tDUK_D(DUK_DPRINT(\"duk_heap_mem_alloc() failed even after gc, alloc size %ld\", (long) size));\n\treturn NULL;\n}\n\nDUK_INTERNAL void *duk_heap_mem_alloc_zeroed(duk_heap *heap, duk_size_t size) {\n\tvoid *res;\n\n\tDUK_ASSERT(heap != NULL);\n\tDUK_ASSERT_DISABLE(size >= 0);\n\n\tres = DUK_ALLOC(heap, size);\n\tif (DUK_LIKELY(res != NULL)) {\n\t\t/* assume memset with zero size is OK */\n\t\tDUK_MEMZERO(res, size);\n\t}\n\treturn res;\n}\n\nDUK_INTERNAL void *duk_heap_mem_alloc_checked(duk_hthread *thr, duk_size_t size) {\n\tvoid *res;\n\n\tDUK_ASSERT(thr != NULL);\n\tres = duk_heap_mem_alloc(thr->heap, size);\n\tif (DUK_LIKELY(res != NULL || size == 0)) {\n\t\treturn res;\n\t}\n\tDUK_ERROR_ALLOC_FAILED(thr);\n\treturn NULL;\n}\n\nDUK_INTERNAL void *duk_heap_mem_alloc_checked_zeroed(duk_hthread *thr, duk_size_t size) {\n\tvoid *res;\n\n\tDUK_ASSERT(thr != NULL);\n\tres = duk_heap_mem_alloc_zeroed(thr->heap, size);\n\tif (DUK_LIKELY(res != NULL || size == 0)) {\n\t\treturn res;\n\t}\n\tDUK_ERROR_ALLOC_FAILED(thr);\n\treturn NULL;\n}\n\n/*\n *  Reallocate memory with garbage collection\n */\n\nDUK_INTERNAL void *duk_heap_mem_realloc(duk_heap *heap, void *ptr, duk_size_t newsize) {\n\tvoid *res;\n\tduk_small_int_t i;\n\n\tDUK_ASSERT(heap != NULL);\n\t/* ptr may be NULL */\n\tDUK_ASSERT_DISABLE(newsize >= 0);\n\n\t/*\n\t *  Voluntary periodic GC (if enabled)\n\t */\n\n\tDUK__VOLUNTARY_PERIODIC_GC(heap);\n\n\t/*\n\t *  First attempt\n\t */\n\n#if defined(DUK_USE_GC_TORTURE)\n\t/* Simulate alloc failure on every realloc, except when mark-and-sweep\n\t * is running.\n\t */\n\tif (heap->ms_prevent_count == 0) {\n\t\tDUK_DDD(DUK_DDDPRINT(\"gc torture enabled, pretend that first realloc attempt fails\"));\n\t\tres = NULL;\n\t\tDUK_UNREF(res);\n\t\tgoto skip_attempt;\n\t}\n#endif\n\tres = heap->realloc_func(heap->heap_udata, ptr, newsize);\n\tif (DUK_LIKELY(res || newsize == 0)) {\n\t\t/* For zero size allocations NULL is allowed. */\n\t\treturn res;\n\t}\n#if defined(DUK_USE_GC_TORTURE)\n skip_attempt:\n#endif\n\n\tDUK_D(DUK_DPRINT(\"first realloc attempt failed, attempt to gc and retry\"));\n\n#if 0\n\t/*\n\t *  Avoid a GC if GC is already running.  See duk_heap_mem_alloc().\n\t */\n\n\tif (heap->ms_prevent_count != 0) {\n\t\tDUK_D(DUK_DPRINT(\"duk_heap_mem_realloc() failed, gc in progress (gc skipped), alloc size %ld\", (long) newsize));\n\t\treturn NULL;\n\t}\n#endif\n\n\t/*\n\t *  Retry with several GC attempts.  Initial attempts are made without\n\t *  emergency mode; later attempts use emergency mode which minimizes\n\t *  memory allocations forcibly.\n\t */\n\n\tfor (i = 0; i < DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_LIMIT; i++) {\n\t\tduk_small_uint_t flags;\n\n\t\tflags = 0;\n\t\tif (i >= DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_EMERGENCY_LIMIT - 1) {\n\t\t\tflags |= DUK_MS_FLAG_EMERGENCY;\n\t\t}\n\n\t\tduk_heap_mark_and_sweep(heap, flags);\n\n\t\tres = heap->realloc_func(heap->heap_udata, ptr, newsize);\n\t\tif (res || newsize == 0) {\n\t\t\tDUK_D(DUK_DPRINT(\"duk_heap_mem_realloc() succeeded after gc (pass %ld), alloc size %ld\",\n\t\t\t                 (long) (i + 1), (long) newsize));\n\t\t\treturn res;\n\t\t}\n\t}\n\n\tDUK_D(DUK_DPRINT(\"duk_heap_mem_realloc() failed even after gc, alloc size %ld\", (long) newsize));\n\treturn NULL;\n}\n\n/*\n *  Reallocate memory with garbage collection, using a callback to provide\n *  the current allocated pointer.  This variant is used when a mark-and-sweep\n *  (e.g. finalizers) might change the original pointer.\n */\n\nDUK_INTERNAL void *duk_heap_mem_realloc_indirect(duk_heap *heap, duk_mem_getptr cb, void *ud, duk_size_t newsize) {\n\tvoid *res;\n\tduk_small_int_t i;\n\n\tDUK_ASSERT(heap != NULL);\n\tDUK_ASSERT_DISABLE(newsize >= 0);\n\n\t/*\n\t *  Voluntary periodic GC (if enabled)\n\t */\n\n\tDUK__VOLUNTARY_PERIODIC_GC(heap);\n\n\t/*\n\t *  First attempt\n\t */\n\n#if defined(DUK_USE_GC_TORTURE)\n\t/* Simulate alloc failure on every realloc, except when mark-and-sweep\n\t * is running.\n\t */\n\tif (heap->ms_prevent_count == 0) {\n\t\tDUK_DDD(DUK_DDDPRINT(\"gc torture enabled, pretend that first indirect realloc attempt fails\"));\n\t\tres = NULL;\n\t\tDUK_UNREF(res);\n\t\tgoto skip_attempt;\n\t}\n#endif\n\tres = heap->realloc_func(heap->heap_udata, cb(heap, ud), newsize);\n\tif (DUK_LIKELY(res || newsize == 0)) {\n\t\t/* For zero size allocations NULL is allowed. */\n\t\treturn res;\n\t}\n#if defined(DUK_USE_GC_TORTURE)\n skip_attempt:\n#endif\n\n\tDUK_D(DUK_DPRINT(\"first indirect realloc attempt failed, attempt to gc and retry\"));\n\n#if 0\n\t/*\n\t *  Avoid a GC if GC is already running.  See duk_heap_mem_alloc().\n\t */\n\n\tif (heap->ms_prevent_count != 0) {\n\t\tDUK_D(DUK_DPRINT(\"duk_heap_mem_realloc_indirect() failed, gc in progress (gc skipped), alloc size %ld\", (long) newsize));\n\t\treturn NULL;\n\t}\n#endif\n\n\t/*\n\t *  Retry with several GC attempts.  Initial attempts are made without\n\t *  emergency mode; later attempts use emergency mode which minimizes\n\t *  memory allocations forcibly.\n\t */\n\n\tfor (i = 0; i < DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_LIMIT; i++) {\n\t\tduk_small_uint_t flags;\n\n#if defined(DUK_USE_DEBUG)\n\t\tvoid *ptr_pre;\n\t\tvoid *ptr_post;\n#endif\n\n#if defined(DUK_USE_DEBUG)\n\t\tptr_pre = cb(heap, ud);\n#endif\n\t\tflags = 0;\n\t\tif (i >= DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_EMERGENCY_LIMIT - 1) {\n\t\t\tflags |= DUK_MS_FLAG_EMERGENCY;\n\t\t}\n\n\t\tduk_heap_mark_and_sweep(heap, flags);\n#if defined(DUK_USE_DEBUG)\n\t\tptr_post = cb(heap, ud);\n\t\tif (ptr_pre != ptr_post) {\n\t\t\tDUK_DD(DUK_DDPRINT(\"realloc base pointer changed by mark-and-sweep: %p -> %p\",\n\t\t\t                   (void *) ptr_pre, (void *) ptr_post));\n\t\t}\n#endif\n\n\t\t/* Note: key issue here is to re-lookup the base pointer on every attempt.\n\t\t * The pointer being reallocated may change after every mark-and-sweep.\n\t\t */\n\n\t\tres = heap->realloc_func(heap->heap_udata, cb(heap, ud), newsize);\n\t\tif (res || newsize == 0) {\n\t\t\tDUK_D(DUK_DPRINT(\"duk_heap_mem_realloc_indirect() succeeded after gc (pass %ld), alloc size %ld\",\n\t\t\t                 (long) (i + 1), (long) newsize));\n\t\t\treturn res;\n\t\t}\n\t}\n\n\tDUK_D(DUK_DPRINT(\"duk_heap_mem_realloc_indirect() failed even after gc, alloc size %ld\", (long) newsize));\n\treturn NULL;\n}\n\n/*\n *  Free memory\n */\n\nDUK_INTERNAL void duk_heap_mem_free(duk_heap *heap, void *ptr) {\n\tDUK_ASSERT(heap != NULL);\n\t/* ptr may be NULL */\n\n\t/* Must behave like a no-op with NULL and any pointer returned from\n\t * malloc/realloc with zero size.\n\t */\n\theap->free_func(heap->heap_udata, ptr);\n\n\t/* Never perform a GC (even voluntary) in a memory free, otherwise\n\t * all call sites doing frees would need to deal with the side effects.\n\t * No need to update voluntary GC counter either.\n\t */\n}\n\n/* automatic undefs */\n#undef DUK__VOLUNTARY_PERIODIC_GC\n#line 1 \"duk_heap_misc.c\"\n/*\n *  Support functions for duk_heap.\n */\n\n/* #include duk_internal.h -> already included */\n\nDUK_INTERNAL void duk_heap_insert_into_heap_allocated(duk_heap *heap, duk_heaphdr *hdr) {\n\tduk_heaphdr *root;\n\n\tDUK_ASSERT(DUK_HEAPHDR_GET_TYPE(hdr) != DUK_HTYPE_STRING);\n\n\troot = heap->heap_allocated;\n#if defined(DUK_USE_DOUBLE_LINKED_HEAP)\n\tif (root != NULL) {\n\t\tDUK_ASSERT(DUK_HEAPHDR_GET_PREV(heap, root) == NULL);\n\t\tDUK_HEAPHDR_SET_PREV(heap, root, hdr);\n\t}\n\tDUK_HEAPHDR_SET_PREV(heap, hdr, NULL);\n#endif\n\tDUK_HEAPHDR_SET_NEXT(heap, hdr, root);\n\tDUK_ASSERT_HEAPHDR_LINKS(heap, hdr);\n\tDUK_ASSERT_HEAPHDR_LINKS(heap, root);\n\theap->heap_allocated = hdr;\n}\n\n#if defined(DUK_USE_REFERENCE_COUNTING)\nDUK_INTERNAL void duk_heap_remove_from_heap_allocated(duk_heap *heap, duk_heaphdr *hdr) {\n\tduk_heaphdr *prev;\n\tduk_heaphdr *next;\n\n\t/* Strings are in string table. */\n\tDUK_ASSERT(hdr != NULL);\n\tDUK_ASSERT(DUK_HEAPHDR_GET_TYPE(hdr) != DUK_HTYPE_STRING);\n\n\t/* Target 'hdr' must be in heap_allocated (not e.g. finalize_list).\n\t * If not, heap lists will become corrupted so assert early for it.\n\t */\n#if defined(DUK_USE_ASSERTIONS)\n\t{\n\t\tduk_heaphdr *tmp;\n\t\tfor (tmp = heap->heap_allocated; tmp != NULL; tmp = DUK_HEAPHDR_GET_NEXT(heap, tmp)) {\n\t\t\tif (tmp == hdr) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tDUK_ASSERT(tmp == hdr);\n\t}\n#endif\n\n\t/* Read/write only once to minimize pointer compression calls. */\n\tprev = DUK_HEAPHDR_GET_PREV(heap, hdr);\n\tnext = DUK_HEAPHDR_GET_NEXT(heap, hdr);\n\n\tif (prev != NULL) {\n\t\tDUK_ASSERT(heap->heap_allocated != hdr);\n\t\tDUK_HEAPHDR_SET_NEXT(heap, prev, next);\n\t} else {\n\t\tDUK_ASSERT(heap->heap_allocated == hdr);\n\t\theap->heap_allocated = next;\n\t}\n\tif (next != NULL) {\n\t\tDUK_HEAPHDR_SET_PREV(heap, next, prev);\n\t} else {\n\t\t;\n\t}\n}\n#endif  /* DUK_USE_REFERENCE_COUNTING */\n\n#if defined(DUK_USE_FINALIZER_SUPPORT)\nDUK_INTERNAL void duk_heap_insert_into_finalize_list(duk_heap *heap, duk_heaphdr *hdr) {\n\tduk_heaphdr *root;\n\n\troot = heap->finalize_list;\n#if defined(DUK_USE_DOUBLE_LINKED_HEAP)\n\tDUK_HEAPHDR_SET_PREV(heap, hdr, NULL);\n\tif (root != NULL) {\n\t\tDUK_ASSERT(DUK_HEAPHDR_GET_PREV(heap, root) == NULL);\n\t\tDUK_HEAPHDR_SET_PREV(heap, root, hdr);\n\t}\n#endif\n\tDUK_HEAPHDR_SET_NEXT(heap, hdr, root);\n\tDUK_ASSERT_HEAPHDR_LINKS(heap, hdr);\n\tDUK_ASSERT_HEAPHDR_LINKS(heap, root);\n\theap->finalize_list = hdr;\n}\n#endif  /* DUK_USE_FINALIZER_SUPPORT */\n\n#if defined(DUK_USE_FINALIZER_SUPPORT)\nDUK_INTERNAL void duk_heap_remove_from_finalize_list(duk_heap *heap, duk_heaphdr *hdr) {\n#if defined(DUK_USE_DOUBLE_LINKED_HEAP)\n\tduk_heaphdr *next;\n\tduk_heaphdr *prev;\n\n\tnext = DUK_HEAPHDR_GET_NEXT(heap, hdr);\n\tprev = DUK_HEAPHDR_GET_PREV(heap, hdr);\n\tif (next != NULL) {\n\t\tDUK_ASSERT(DUK_HEAPHDR_GET_PREV(heap, next) == hdr);\n\t\tDUK_HEAPHDR_SET_PREV(heap, next, prev);\n\t}\n\tif (prev == NULL) {\n\t\tDUK_ASSERT(hdr == heap->finalize_list);\n\t\theap->finalize_list = next;\n\t} else {\n\t\tDUK_ASSERT(hdr != heap->finalize_list);\n\t\tDUK_HEAPHDR_SET_NEXT(heap, prev, next);\n\t}\n#else\n\tduk_heaphdr *next;\n\tduk_heaphdr *curr;\n\n\t/* Random removal is expensive: we need to locate the previous element\n\t * because we don't have a 'prev' pointer.\n\t */\n\tcurr = heap->finalize_list;\n\tif (curr == hdr) {\n\t\theap->finalize_list = DUK_HEAPHDR_GET_NEXT(heap, curr);\n\t} else {\n\t\tDUK_ASSERT(hdr != heap->finalize_list);\n\t\tfor (;;) {\n\t\t\tDUK_ASSERT(curr != NULL);  /* Caller responsibility. */\n\n\t\t\tnext = DUK_HEAPHDR_GET_NEXT(heap, curr);\n\t\t\tif (next == hdr) {\n\t\t\t\tnext = DUK_HEAPHDR_GET_NEXT(heap, hdr);\n\t\t\t\tDUK_HEAPHDR_SET_NEXT(heap, curr, next);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n#endif\n}\n#endif  /* DUK_USE_FINALIZER_SUPPORT */\n\n#if defined(DUK_USE_ASSERTIONS)\nDUK_INTERNAL duk_bool_t duk_heap_in_heap_allocated(duk_heap *heap, duk_heaphdr *ptr) {\n\tduk_heaphdr *curr;\n\tDUK_ASSERT(heap != NULL);\n\n\tfor (curr = heap->heap_allocated; curr != NULL; curr = DUK_HEAPHDR_GET_NEXT(heap, curr)) {\n\t\tif (curr == ptr) {\n\t\t\treturn 1;\n\t\t}\n\t}\n\treturn 0;\n}\n#endif  /* DUK_USE_ASSERTIONS */\n\n#if defined(DUK_USE_INTERRUPT_COUNTER)\nDUK_INTERNAL void duk_heap_switch_thread(duk_heap *heap, duk_hthread *new_thr) {\n\tduk_hthread *curr_thr;\n\n\tDUK_ASSERT(heap != NULL);\n\n\tif (new_thr != NULL) {\n\t\tcurr_thr = heap->curr_thread;\n\t\tif (curr_thr == NULL) {\n\t\t\t/* For initial entry use default value; zero forces an\n\t\t\t * interrupt before executing the first insturction.\n\t\t\t */\n\t\t\tDUK_DD(DUK_DDPRINT(\"switch thread, initial entry, init default interrupt counter\"));\n\t\t\tnew_thr->interrupt_counter = 0;\n\t\t\tnew_thr->interrupt_init = 0;\n\t\t} else {\n\t\t\t/* Copy interrupt counter/init value state to new thread (if any).\n\t\t\t * It's OK for new_thr to be the same as curr_thr.\n\t\t\t */\n#if defined(DUK_USE_DEBUG)\n\t\t\tif (new_thr != curr_thr) {\n\t\t\t\tDUK_DD(DUK_DDPRINT(\"switch thread, not initial entry, copy interrupt counter\"));\n\t\t\t}\n#endif\n\t\t\tnew_thr->interrupt_counter = curr_thr->interrupt_counter;\n\t\t\tnew_thr->interrupt_init = curr_thr->interrupt_init;\n\t\t}\n\t} else {\n\t\tDUK_DD(DUK_DDPRINT(\"switch thread, new thread is NULL, no interrupt counter changes\"));\n\t}\n\n\theap->curr_thread = new_thr;  /* may be NULL */\n}\n#endif  /* DUK_USE_INTERRUPT_COUNTER */\n#line 1 \"duk_heap_refcount.c\"\n/*\n *  Reference counting implementation.\n *\n *  INCREF/DECREF, finalization and freeing of objects whose refcount reaches\n *  zero (refzero).  These operations are very performance sensitive, so\n *  various small tricks are used in an attempt to maximize speed.\n */\n\n/* #include duk_internal.h -> already included */\n\n#if defined(DUK_USE_REFERENCE_COUNTING)\n\n#if !defined(DUK_USE_DOUBLE_LINKED_HEAP)\n#error internal error, reference counting requires a double linked heap\n#endif\n\n/*\n *  Heap object refcount finalization.\n *\n *  When an object is about to be freed, all other objects it refers to must\n *  be decref'd.  Refcount finalization does NOT free the object or its inner\n *  allocations (mark-and-sweep shares these helpers), it just manipulates\n *  the refcounts.\n *\n *  Note that any of the DECREFs may cause a refcount to drop to zero.  If so,\n *  the object won't be refzero processed inline, but will just be queued to\n *  refzero_list and processed by an earlier caller working on refzero_list,\n *  eliminating C recursion from even long refzero cascades.  If refzero\n *  finalization is triggered by mark-and-sweep, refzero conditions are ignored\n *  (objects are not even queued to refzero_list) because mark-and-sweep deals\n *  with them; refcounts are still updated so that they remain in sync with\n *  actual references.\n */\n\nDUK_LOCAL void duk__decref_tvals_norz(duk_hthread *thr, duk_tval *tv, duk_idx_t count) {\n\tDUK_ASSERT(count == 0 || tv != NULL);\n\n\twhile (count-- > 0) {\n\t\tDUK_TVAL_DECREF_NORZ(thr, tv);\n\t\ttv++;\n\t}\n}\n\nDUK_INTERNAL void duk_hobject_refcount_finalize_norz(duk_heap *heap, duk_hobject *h) {\n\tduk_hthread *thr;\n\tduk_uint_fast32_t i;\n\tduk_uint_fast32_t n;\n\tduk_propvalue *p_val;\n\tduk_tval *p_tv;\n\tduk_hstring **p_key;\n\tduk_uint8_t *p_flag;\n\tduk_hobject *h_proto;\n\n\tDUK_ASSERT(heap != NULL);\n\tDUK_ASSERT(heap->heap_thread != NULL);\n\tDUK_ASSERT(h);\n\tDUK_ASSERT(DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) h) == DUK_HTYPE_OBJECT);\n\n\tthr = heap->heap_thread;\n\tDUK_ASSERT(thr != NULL);\n\n\tp_key = DUK_HOBJECT_E_GET_KEY_BASE(heap, h);\n\tp_val = DUK_HOBJECT_E_GET_VALUE_BASE(heap, h);\n\tp_flag = DUK_HOBJECT_E_GET_FLAGS_BASE(heap, h);\n\tn = DUK_HOBJECT_GET_ENEXT(h);\n\twhile (n-- > 0) {\n\t\tduk_hstring *key;\n\n\t\tkey = p_key[n];\n\t\tif (DUK_UNLIKELY(key == NULL)) {\n\t\t\tcontinue;\n\t\t}\n\t\tDUK_HSTRING_DECREF_NORZ(thr, key);\n\t\tif (DUK_UNLIKELY(p_flag[n] & DUK_PROPDESC_FLAG_ACCESSOR)) {\n\t\t\tduk_hobject *h_getset;\n\t\t\th_getset = p_val[n].a.get;\n\t\t\tDUK_ASSERT(h_getset == NULL || DUK_HEAPHDR_IS_OBJECT((duk_heaphdr *) h_getset));\n\t\t\tDUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, h_getset);\n\t\t\th_getset = p_val[n].a.set;\n\t\t\tDUK_ASSERT(h_getset == NULL || DUK_HEAPHDR_IS_OBJECT((duk_heaphdr *) h_getset));\n\t\t\tDUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, h_getset);\n\t\t} else {\n\t\t\tduk_tval *tv_val;\n\t\t\ttv_val = &p_val[n].v;\n\t\t\tDUK_TVAL_DECREF_NORZ(thr, tv_val);\n\t\t}\n\t}\n\n\tp_tv = DUK_HOBJECT_A_GET_BASE(heap, h);\n\tn = DUK_HOBJECT_GET_ASIZE(h);\n\twhile (n-- > 0) {\n\t\tduk_tval *tv_val;\n\t\ttv_val = p_tv + n;\n\t\tDUK_TVAL_DECREF_NORZ(thr, tv_val);\n\t}\n\n\t/* Hash part is a 'weak reference' and doesn't contribute to refcounts. */\n\n\th_proto = (duk_hobject *) DUK_HOBJECT_GET_PROTOTYPE(heap, h);\n\tDUK_ASSERT(h_proto == NULL || DUK_HEAPHDR_IS_OBJECT((duk_heaphdr *) h_proto));\n\tDUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, h_proto);\n\n\t/* XXX: Object subclass tests are quite awkward at present, ideally\n\t * we should be able to switch-case here with a dense index (subtype\n\t * number or something).  For now, fast path plain objects and arrays\n\t * and bit test the rest individually.\n\t */\n\n\tif (DUK_HOBJECT_HAS_FASTREFS(h)) {\n\t\t/* Plain object or array, nothing more to do.  While a\n\t\t * duk_harray has additional fields, none of them need\n\t\t * DECREF updates.\n\t\t */\n\t\tDUK_ASSERT(DUK_HOBJECT_ALLOWS_FASTREFS(h));\n\t\treturn;\n\t}\n\tDUK_ASSERT(DUK_HOBJECT_PROHIBITS_FASTREFS(h));\n\n\t/* Slow path: special object, start bit checks from most likely. */\n\n\t/* XXX: reorg, more common first */\n\tif (DUK_HOBJECT_IS_COMPFUNC(h)) {\n\t\tduk_hcompfunc *f = (duk_hcompfunc *) h;\n\t\tduk_tval *tv, *tv_end;\n\t\tduk_hobject **funcs, **funcs_end;\n\n\t\tDUK_ASSERT_HCOMPFUNC_VALID(f);\n\n\t\tif (DUK_LIKELY(DUK_HCOMPFUNC_GET_DATA(heap, f) != NULL)) {\n\t\t\ttv = DUK_HCOMPFUNC_GET_CONSTS_BASE(heap, f);\n\t\t\ttv_end = DUK_HCOMPFUNC_GET_CONSTS_END(heap, f);\n\t\t\twhile (tv < tv_end) {\n\t\t\t\tDUK_TVAL_DECREF_NORZ(thr, tv);\n\t\t\t\ttv++;\n\t\t\t}\n\n\t\t\tfuncs = DUK_HCOMPFUNC_GET_FUNCS_BASE(heap, f);\n\t\t\tfuncs_end = DUK_HCOMPFUNC_GET_FUNCS_END(heap, f);\n\t\t\twhile (funcs < funcs_end) {\n\t\t\t\tduk_hobject *h_func;\n\t\t\t\th_func = *funcs;\n\t\t\t\tDUK_ASSERT(h_func != NULL);\n\t\t\t\tDUK_ASSERT(DUK_HEAPHDR_IS_OBJECT((duk_heaphdr *) h_func));\n\t\t\t\tDUK_HCOMPFUNC_DECREF_NORZ(thr, (duk_hcompfunc *) h_func);\n\t\t\t\tfuncs++;\n\t\t\t}\n\t\t} else {\n\t\t\t/* May happen in some out-of-memory corner cases. */\n\t\t\tDUK_D(DUK_DPRINT(\"duk_hcompfunc 'data' is NULL, skipping decref\"));\n\t\t}\n\n\t\tDUK_HEAPHDR_DECREF_ALLOWNULL(thr, (duk_heaphdr *) DUK_HCOMPFUNC_GET_LEXENV(heap, f));\n\t\tDUK_HEAPHDR_DECREF_ALLOWNULL(thr, (duk_heaphdr *) DUK_HCOMPFUNC_GET_VARENV(heap, f));\n\t\tDUK_HEAPHDR_DECREF_ALLOWNULL(thr, (duk_hbuffer *) DUK_HCOMPFUNC_GET_DATA(heap, f));\n\t} else if (DUK_HOBJECT_IS_DECENV(h)) {\n\t\tduk_hdecenv *e = (duk_hdecenv *) h;\n\t\tDUK_ASSERT_HDECENV_VALID(e);\n\t\tDUK_HTHREAD_DECREF_NORZ_ALLOWNULL(thr, e->thread);\n\t\tDUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, e->varmap);\n\t} else if (DUK_HOBJECT_IS_OBJENV(h)) {\n\t\tduk_hobjenv *e = (duk_hobjenv *) h;\n\t\tDUK_ASSERT_HOBJENV_VALID(e);\n\t\tDUK_ASSERT(e->target != NULL);  /* Required for object environments. */\n\t\tDUK_HOBJECT_DECREF_NORZ(thr, e->target);\n#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)\n\t} else if (DUK_HOBJECT_IS_BUFOBJ(h)) {\n\t\tduk_hbufobj *b = (duk_hbufobj *) h;\n\t\tDUK_ASSERT_HBUFOBJ_VALID(b);\n\t\tDUK_HBUFFER_DECREF_NORZ_ALLOWNULL(thr, (duk_hbuffer *) b->buf);\n\t\tDUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, (duk_hobject *) b->buf_prop);\n#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */\n\t} else if (DUK_HOBJECT_IS_BOUNDFUNC(h)) {\n\t\tduk_hboundfunc *f = (duk_hboundfunc *) h;\n\t\tDUK_ASSERT_HBOUNDFUNC_VALID(f);\n\t\tDUK_TVAL_DECREF_NORZ(thr, &f->target);\n\t\tDUK_TVAL_DECREF_NORZ(thr, &f->this_binding);\n\t\tduk__decref_tvals_norz(thr, f->args, f->nargs);\n#if defined(DUK_USE_ES6_PROXY)\n\t} else if (DUK_HOBJECT_IS_PROXY(h)) {\n\t\tduk_hproxy *p = (duk_hproxy *) h;\n\t\tDUK_ASSERT_HPROXY_VALID(p);\n\t\tDUK_HOBJECT_DECREF_NORZ(thr, p->target);\n\t\tDUK_HOBJECT_DECREF_NORZ(thr, p->handler);\n#endif  /* DUK_USE_ES6_PROXY */\n\t} else if (DUK_HOBJECT_IS_THREAD(h)) {\n\t\tduk_hthread *t = (duk_hthread *) h;\n\t\tduk_activation *act;\n\t\tduk_tval *tv;\n\n\t\tDUK_ASSERT_HTHREAD_VALID(t);\n\n\t\ttv = t->valstack;\n\t\twhile (tv < t->valstack_top) {\n\t\t\tDUK_TVAL_DECREF_NORZ(thr, tv);\n\t\t\ttv++;\n\t\t}\n\n\t\tfor (act = t->callstack_curr; act != NULL; act = act->parent) {\n\t\t\tDUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, (duk_hobject *) DUK_ACT_GET_FUNC(act));\n\t\t\tDUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, (duk_hobject *) act->var_env);\n\t\t\tDUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, (duk_hobject *) act->lex_env);\n#if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)\n\t\t\tDUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, (duk_hobject *) act->prev_caller);\n#endif\n#if 0  /* nothing now */\n\t\t\tfor (cat = act->cat; cat != NULL; cat = cat->parent) {\n\t\t\t}\n#endif\n\t\t}\n\n\n\t\tfor (i = 0; i < DUK_NUM_BUILTINS; i++) {\n\t\t\tDUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, (duk_hobject *) t->builtins[i]);\n\t\t}\n\n\t\tDUK_HTHREAD_DECREF_NORZ_ALLOWNULL(thr, (duk_hthread *) t->resumer);\n\t} else {\n\t\t/* We may come here if the object should have a FASTREFS flag\n\t\t * but it's missing for some reason.  Assert for never getting\n\t\t * here; however, other than performance, this is harmless.\n\t\t */\n\t\tDUK_D(DUK_DPRINT(\"missing FASTREFS flag for: %!iO\", h));\n\t\tDUK_ASSERT(0);\n\t}\n}\n\nDUK_INTERNAL void duk_heaphdr_refcount_finalize_norz(duk_heap *heap, duk_heaphdr *hdr) {\n\tDUK_ASSERT(heap != NULL);\n\tDUK_ASSERT(heap->heap_thread != NULL);\n\tDUK_ASSERT(hdr != NULL);\n\n\tif (DUK_HEAPHDR_IS_OBJECT(hdr)) {\n\t\tduk_hobject_refcount_finalize_norz(heap, (duk_hobject *) hdr);\n\t}\n\t/* DUK_HTYPE_BUFFER: nothing to finalize */\n\t/* DUK_HTYPE_STRING: nothing to finalize */\n}\n\n/*\n *  Refzero processing for duk_hobject: queue a refzero'ed object to either\n *  finalize_list or refzero_list and process the relevent list(s) if\n *  necessary.\n *\n *  Refzero_list is single linked, with only 'prev' pointers set and valid.\n *  All 'next' pointers are intentionally left as garbage.  This doesn't\n *  matter because refzero_list is processed to completion before any other\n *  code (like mark-and-sweep) might walk the list.\n *\n *  In more detail:\n *\n *  - On first insert refzero_list is NULL and the new object becomes the\n *    first and only element on the list; duk__refcount_free_pending() is\n *    called and it starts processing the list from the initial element,\n *    i.e. the list tail.\n *\n *  - As each object is refcount finalized, new objects may be queued to\n *    refzero_list head.  Their 'next' pointers are left as garbage, but\n *    'prev' points are set correctly, with the element at refzero_list\n *    having a NULL 'prev' pointer.  The fact that refzero_list is non-NULL\n *    is used to reject (1) recursive duk__refcount_free_pending() and\n *    (2) finalize_list processing calls.\n *\n *  - When we're done with the current object, read its 'prev' pointer and\n *    free the object.  If 'prev' is NULL, we've reached head of list and are\n *    done: set refzero_list to NULL and process pending finalizers.  Otherwise\n *    continue processing the list.\n *\n *  A refzero cascade is free of side effects because it only involves\n *  queueing more objects and freeing memory; finalizer execution is blocked\n *  in the code path queueing objects to finalize_list.  As a result the\n *  initial refzero call (which triggers duk__refcount_free_pending()) must\n *  check finalize_list so that finalizers are executed snappily.\n *\n *  If finalize_list processing starts first, refzero may occur while we're\n *  processing finalizers.  That's fine: that particular refzero cascade is\n *  handled to completion without side effects.  Once the cascade is complete,\n *  we'll run pending finalizers but notice that we're already doing that and\n *  return.\n *\n *  This could be expanded to allow incremental freeing: just bail out\n *  early and resume at a future alloc/decref/refzero.  However, if that\n *  were done, the list structure would need to be kept consistent at all\n *  times, mark-and-sweep would need to handle refzero_list, etc.\n */\n\nDUK_LOCAL void duk__refcount_free_pending(duk_heap *heap) {\n\tduk_heaphdr *curr;\n#if defined(DUK_USE_DEBUG)\n\tduk_int_t count = 0;\n#endif\n\n\tDUK_ASSERT(heap != NULL);\n\n\tcurr = heap->refzero_list;\n\tDUK_ASSERT(curr != NULL);\n\tDUK_ASSERT(DUK_HEAPHDR_GET_PREV(heap, curr) == NULL);  /* We're called on initial insert only. */\n\t/* curr->next is GARBAGE. */\n\n\tdo {\n\t\tduk_heaphdr *prev;\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"refzero processing %p: %!O\", (void *) curr, (duk_heaphdr *) curr));\n\n#if defined(DUK_USE_DEBUG)\n\t\tcount++;\n#endif\n\n\t\tDUK_ASSERT(curr != NULL);\n\t\tDUK_ASSERT(DUK_HEAPHDR_GET_TYPE(curr) == DUK_HTYPE_OBJECT);  /* currently, always the case */\n\t\t/* FINALIZED may be set; don't care about flags here. */\n\n\t\t/* Refcount finalize 'curr'.  Refzero_list must be non-NULL\n\t\t * here to prevent recursive entry to duk__refcount_free_pending().\n\t\t */\n\t\tDUK_ASSERT(heap->refzero_list != NULL);\n\t\tduk_hobject_refcount_finalize_norz(heap, (duk_hobject *) curr);\n\n\t\tprev = DUK_HEAPHDR_GET_PREV(heap, curr);\n\t\tDUK_ASSERT((prev == NULL && heap->refzero_list == curr) || \\\n\t\t           (prev != NULL && heap->refzero_list != curr));\n\t\t/* prev->next is intentionally not updated and is garbage. */\n\n\t\tduk_free_hobject(heap, (duk_hobject *) curr);  /* Invalidates 'curr'. */\n\n\t\tcurr = prev;\n\t} while (curr != NULL);\n\n\theap->refzero_list = NULL;\n\n\tDUK_DD(DUK_DDPRINT(\"refzero processed %ld objects\", (long) count));\n}\n\nDUK_LOCAL DUK_INLINE void duk__refcount_refzero_hobject(duk_heap *heap, duk_hobject *obj, duk_bool_t skip_free_pending) {\n\tduk_heaphdr *hdr;\n\tduk_heaphdr *root;\n\n\tDUK_ASSERT(heap != NULL);\n\tDUK_ASSERT(heap->heap_thread != NULL);\n\tDUK_ASSERT(obj != NULL);\n\tDUK_ASSERT(DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) obj) == DUK_HTYPE_OBJECT);\n\n\thdr = (duk_heaphdr *) obj;\n\n\t/* Refzero'd objects must be in heap_allocated.  They can't be in\n\t * finalize_list because all objects on finalize_list have an\n\t * artificial +1 refcount bump.\n\t */\n#if defined(DUK_USE_ASSERTIONS)\n\tDUK_ASSERT(duk_heap_in_heap_allocated(heap, (duk_heaphdr *) obj));\n#endif\n\n\tDUK_HEAP_REMOVE_FROM_HEAP_ALLOCATED(heap, hdr);\n\n#if defined(DUK_USE_FINALIZER_SUPPORT)\n\t/* This finalizer check MUST BE side effect free.  It should also be\n\t * as fast as possible because it's applied to every object freed.\n\t */\n\tif (DUK_UNLIKELY(DUK_HOBJECT_HAS_FINALIZER_FAST(heap, (duk_hobject *) hdr) != 0U)) {\n\t\t/* Special case: FINALIZED may be set if mark-and-sweep queued\n\t\t * object for finalization, the finalizer was executed (and\n\t\t * FINALIZED set), mark-and-sweep hasn't yet processed the\n\t\t * object again, but its refcount drops to zero.  Free without\n\t\t * running the finalizer again.\n\t\t */\n\t\tif (DUK_HEAPHDR_HAS_FINALIZED(hdr)) {\n\t\t\tDUK_D(DUK_DPRINT(\"refzero'd object has finalizer and FINALIZED is set -> free\"));\n\t\t} else {\n\t\t\t/* Set FINALIZABLE flag so that all objects on finalize_list\n\t\t\t * will have it set and are thus detectable based on the\n\t\t\t * flag alone.\n\t\t\t */\n\t\t\tDUK_HEAPHDR_SET_FINALIZABLE(hdr);\n\t\t\tDUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZED(hdr));\n\n#if defined(DUK_USE_REFERENCE_COUNTING)\n\t\t\t/* Bump refcount on finalize_list insert so that a\n\t\t\t * refzero can never occur when an object is waiting\n\t\t\t * for its finalizer call.  Refzero might otherwise\n\t\t\t * now happen because we allow duk_push_heapptr() for\n\t\t\t * objects pending finalization.\n\t\t\t */\n\t\t\tDUK_HEAPHDR_PREINC_REFCOUNT(hdr);\n#endif\n\t\t\tDUK_HEAP_INSERT_INTO_FINALIZE_LIST(heap, hdr);\n\n\t\t\t/* Process finalizers unless skipping is explicitly\n\t\t\t * requested (NORZ) or refzero_list is being processed\n\t\t\t * (avoids side effects during a refzero cascade).\n\t\t\t * If refzero_list is processed, the initial refzero\n\t\t\t * call will run pending finalizers when refzero_list\n\t\t\t * is done.\n\t\t\t */\n\t\t\tif (!skip_free_pending && heap->refzero_list == NULL) {\n\t\t\t\tduk_heap_process_finalize_list(heap);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t}\n#endif  /* DUK_USE_FINALIZER_SUPPORT */\n\n\t/* No need to finalize, free object via refzero_list. */\n\n\troot = heap->refzero_list;\n\n\tDUK_HEAPHDR_SET_PREV(heap, hdr, NULL);\n\t/* 'next' is left as GARBAGE. */\n\theap->refzero_list = hdr;\n\n\tif (root == NULL) {\n\t\t/* Object is now queued.  Refzero_list was NULL so\n\t\t * no-one is currently processing it; do it here.\n\t\t * With refzero processing just doing a cascade of\n\t\t * free calls, we can process it directly even when\n\t\t * NORZ macros are used: there are no side effects.\n\t\t */\n\t\tduk__refcount_free_pending(heap);\n\t\tDUK_ASSERT(heap->refzero_list == NULL);\n\n\t\t/* Process finalizers only after the entire cascade\n\t\t * is finished.  In most cases there's nothing to\n\t\t * finalize, so fast path check to avoid a call.\n\t\t */\n#if defined(DUK_USE_FINALIZER_SUPPORT)\n\t\tif (!skip_free_pending && DUK_UNLIKELY(heap->finalize_list != NULL)) {\n\t\t\tduk_heap_process_finalize_list(heap);\n\t\t}\n#endif\n\t} else {\n\t\tDUK_ASSERT(DUK_HEAPHDR_GET_PREV(heap, root) == NULL);\n\t\tDUK_HEAPHDR_SET_PREV(heap, root, hdr);\n\n\t\t/* Object is now queued.  Because refzero_list was\n\t\t * non-NULL, it's already being processed by someone\n\t\t * in the C call stack, so we're done.\n\t\t */\n\t}\n}\n\n#if defined(DUK_USE_FINALIZER_SUPPORT)\nDUK_INTERNAL DUK_ALWAYS_INLINE void duk_refzero_check_fast(duk_hthread *thr) {\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(thr->heap != NULL);\n\tDUK_ASSERT(thr->heap->refzero_list == NULL);  /* Processed to completion inline. */\n\n\tif (DUK_UNLIKELY(thr->heap->finalize_list != NULL)) {\n\t\tduk_heap_process_finalize_list(thr->heap);\n\t}\n}\n\nDUK_INTERNAL void duk_refzero_check_slow(duk_hthread *thr) {\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(thr->heap != NULL);\n\tDUK_ASSERT(thr->heap->refzero_list == NULL);  /* Processed to completion inline. */\n\n\tif (DUK_UNLIKELY(thr->heap->finalize_list != NULL)) {\n\t\tduk_heap_process_finalize_list(thr->heap);\n\t}\n}\n#endif  /* DUK_USE_FINALIZER_SUPPORT */\n\n/*\n *  Refzero processing for duk_hstring.\n */\n\nDUK_LOCAL DUK_INLINE void duk__refcount_refzero_hstring(duk_heap *heap, duk_hstring *str) {\n\tDUK_ASSERT(heap != NULL);\n\tDUK_ASSERT(heap->heap_thread != NULL);\n\tDUK_ASSERT(str != NULL);\n\tDUK_ASSERT(DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) str) == DUK_HTYPE_STRING);\n\n\tduk_heap_strcache_string_remove(heap, str);\n\tduk_heap_strtable_unlink(heap, str);\n\tduk_free_hstring(heap, str);\n}\n\n/*\n *  Refzero processing for duk_hbuffer.\n */\n\nDUK_LOCAL DUK_INLINE void duk__refcount_refzero_hbuffer(duk_heap *heap, duk_hbuffer *buf) {\n\tDUK_ASSERT(heap != NULL);\n\tDUK_ASSERT(heap->heap_thread != NULL);\n\tDUK_ASSERT(buf != NULL);\n\tDUK_ASSERT(DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) buf) == DUK_HTYPE_BUFFER);\n\n\tDUK_HEAP_REMOVE_FROM_HEAP_ALLOCATED(heap, (duk_heaphdr *) buf);\n\tduk_free_hbuffer(heap, buf);\n}\n\n/*\n *  Incref and decref functions.\n *\n *  Decref may trigger immediate refzero handling, which may free and finalize\n *  an arbitrary number of objects (a \"DECREF cascade\").\n *\n *  Refzero handling is skipped entirely if (1) mark-and-sweep is running or\n *  (2) execution is paused in the debugger.  The objects are left in the heap,\n *  and will be freed by mark-and-sweep or eventual heap destruction.\n *\n *  This is necessary during mark-and-sweep because refcounts are also updated\n *  during the sweep phase (otherwise objects referenced by a swept object\n *  would have incorrect refcounts) which then calls here.  This could be\n *  avoided by using separate decref macros in mark-and-sweep; however,\n *  mark-and-sweep also calls finalizers which would use the ordinary decref\n *  macros anyway.\n *\n *  We can't process refzeros (= free objects) when the debugger is running\n *  as the debugger might make an object unreachable but still continue\n *  inspecting it (or even cause it to be pushed back).  So we must rely on\n *  mark-and-sweep to collect them.\n *\n *  The DUK__RZ_SUPPRESS_CHECK() condition is also used in heap destruction\n *  when running finalizers for remaining objects: the flag prevents objects\n *  from being moved around in heap linked lists while that's being done.\n *\n *  The suppress condition is important to performance.\n */\n\n#define DUK__RZ_SUPPRESS_ASSERT1() do { \\\n\t\tDUK_ASSERT(thr != NULL); \\\n\t\tDUK_ASSERT(thr->heap != NULL); \\\n\t\t/* When mark-and-sweep runs, heap_thread must exist. */ \\\n\t\tDUK_ASSERT(thr->heap->ms_running == 0 || thr->heap->heap_thread != NULL); \\\n\t\t/* When mark-and-sweep runs, the 'thr' argument always matches heap_thread. \\\n\t\t * This could be used to e.g. suppress check against 'thr' directly (and \\\n\t\t * knowing it would be heap_thread); not really used now. \\\n\t\t */ \\\n\t\tDUK_ASSERT(thr->heap->ms_running == 0 || thr == thr->heap->heap_thread); \\\n\t\t/* We may be called when the heap is initializing and we process \\\n\t\t * refzeros normally, but mark-and-sweep and finalizers are prevented \\\n\t\t * if that's the case. \\\n\t\t */ \\\n\t\tDUK_ASSERT(thr->heap->heap_initializing == 0 || thr->heap->ms_prevent_count > 0); \\\n\t\tDUK_ASSERT(thr->heap->heap_initializing == 0 || thr->heap->pf_prevent_count > 0); \\\n\t} while (0)\n\n#if defined(DUK_USE_DEBUGGER_SUPPORT)\n#define DUK__RZ_SUPPRESS_ASSERT2() do { \\\n\t\t/* When debugger is paused, ms_running is set. */ \\\n\t\tDUK_ASSERT(!DUK_HEAP_HAS_DEBUGGER_PAUSED(thr->heap) || thr->heap->ms_running != 0); \\\n\t} while (0)\n#define DUK__RZ_SUPPRESS_COND()  (heap->ms_running != 0)\n#else\n#define DUK__RZ_SUPPRESS_ASSERT2() do { } while (0)\n#define DUK__RZ_SUPPRESS_COND()  (heap->ms_running != 0)\n#endif  /* DUK_USE_DEBUGGER_SUPPORT */\n\n#define DUK__RZ_SUPPRESS_CHECK() do { \\\n\t\tDUK__RZ_SUPPRESS_ASSERT1(); \\\n\t\tDUK__RZ_SUPPRESS_ASSERT2(); \\\n\t\tif (DUK_UNLIKELY(DUK__RZ_SUPPRESS_COND())) { \\\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"refzero handling suppressed (not even queued) when mark-and-sweep running, object: %p\", (void *) h)); \\\n\t\t\treturn; \\\n\t\t} \\\n\t} while (0)\n\n#define DUK__RZ_STRING() do { \\\n\t\tduk__refcount_refzero_hstring(heap, (duk_hstring *) h); \\\n\t} while (0)\n#define DUK__RZ_BUFFER() do { \\\n\t\tduk__refcount_refzero_hbuffer(heap, (duk_hbuffer *) h); \\\n\t} while (0)\n#define DUK__RZ_OBJECT() do { \\\n\t\tduk__refcount_refzero_hobject(heap, (duk_hobject *) h, skip_free_pending); \\\n\t} while (0)\n\n/* XXX: test the effect of inlining here vs. NOINLINE in refzero helpers */\n#if defined(DUK_USE_FAST_REFCOUNT_DEFAULT)\n#define DUK__RZ_INLINE DUK_ALWAYS_INLINE\n#else\n#define DUK__RZ_INLINE /*nop*/\n#endif\n\nDUK_LOCAL DUK__RZ_INLINE void duk__hstring_refzero_helper(duk_hthread *thr, duk_hstring *h) {\n\tduk_heap *heap;\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(h != NULL);\n\theap = thr->heap;\n\n\tDUK__RZ_SUPPRESS_CHECK();\n\tDUK__RZ_STRING();\n}\n\nDUK_LOCAL DUK__RZ_INLINE void duk__hbuffer_refzero_helper(duk_hthread *thr, duk_hbuffer *h) {\n\tduk_heap *heap;\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(h != NULL);\n\theap = thr->heap;\n\n\tDUK__RZ_SUPPRESS_CHECK();\n\tDUK__RZ_BUFFER();\n}\n\nDUK_LOCAL DUK__RZ_INLINE void duk__hobject_refzero_helper(duk_hthread *thr, duk_hobject *h, duk_bool_t skip_free_pending) {\n\tduk_heap *heap;\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(h != NULL);\n\theap = thr->heap;\n\n\tDUK__RZ_SUPPRESS_CHECK();\n\tDUK__RZ_OBJECT();\n}\n\nDUK_LOCAL DUK__RZ_INLINE void duk__heaphdr_refzero_helper(duk_hthread *thr, duk_heaphdr *h, duk_bool_t skip_free_pending) {\n\tduk_heap *heap;\n\tduk_small_uint_t htype;\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(h != NULL);\n\theap = thr->heap;\n\n\thtype = (duk_small_uint_t) DUK_HEAPHDR_GET_TYPE(h);\n\tDUK__RZ_SUPPRESS_CHECK();\n\n\tswitch (htype) {\n\tcase DUK_HTYPE_STRING:\n\t\t/* Strings have no internal references but do have \"weak\"\n\t\t * references in the string cache.  Also note that strings\n\t\t * are not on the heap_allocated list like other heap\n\t\t * elements.\n\t\t */\n\n\t\tDUK__RZ_STRING();\n\t\tbreak;\n\n\tcase DUK_HTYPE_OBJECT:\n\t\t/* Objects have internal references.  Must finalize through\n\t\t * the \"refzero\" work list.\n\t\t */\n\n\t\tDUK__RZ_OBJECT();\n\t\tbreak;\n\n\tdefault:\n\t\t/* Buffers have no internal references.  However, a dynamic\n\t\t * buffer has a separate allocation for the buffer.  This is\n\t\t * freed by duk_heap_free_heaphdr_raw().\n\t\t */\n\n\t\tDUK_ASSERT(DUK_HEAPHDR_GET_TYPE(h) == DUK_HTYPE_BUFFER);\n\t\tDUK__RZ_BUFFER();\n\t\tbreak;\n\t}\n}\n\nDUK_INTERNAL DUK_NOINLINE void duk_heaphdr_refzero(duk_hthread *thr, duk_heaphdr *h) {\n\tduk__heaphdr_refzero_helper(thr, h, 0 /*skip_free_pending*/);\n}\n\nDUK_INTERNAL DUK_NOINLINE void duk_heaphdr_refzero_norz(duk_hthread *thr, duk_heaphdr *h) {\n\tduk__heaphdr_refzero_helper(thr, h, 1 /*skip_free_pending*/);\n}\n\nDUK_INTERNAL DUK_NOINLINE void duk_hstring_refzero(duk_hthread *thr, duk_hstring *h) {\n\tduk__hstring_refzero_helper(thr, h);\n}\n\nDUK_INTERNAL DUK_NOINLINE void duk_hbuffer_refzero(duk_hthread *thr, duk_hbuffer *h) {\n\tduk__hbuffer_refzero_helper(thr, h);\n}\n\nDUK_INTERNAL DUK_NOINLINE void duk_hobject_refzero(duk_hthread *thr, duk_hobject *h) {\n\tduk__hobject_refzero_helper(thr, h, 0 /*skip_free_pending*/);\n}\n\nDUK_INTERNAL DUK_NOINLINE void duk_hobject_refzero_norz(duk_hthread *thr, duk_hobject *h) {\n\tduk__hobject_refzero_helper(thr, h, 1 /*skip_free_pending*/);\n}\n\n#if !defined(DUK_USE_FAST_REFCOUNT_DEFAULT)\nDUK_INTERNAL void duk_tval_incref(duk_tval *tv) {\n\tDUK_ASSERT(tv != NULL);\n\n\tif (DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv)) {\n\t\tduk_heaphdr *h = DUK_TVAL_GET_HEAPHDR(tv);\n\t\tDUK_ASSERT(h != NULL);\n\t\tDUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(h));\n\t\tDUK_ASSERT_DISABLE(h->h_refcount >= 0);\n\t\tDUK_HEAPHDR_PREINC_REFCOUNT(h);\n\t\tDUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(h) != 0);  /* No wrapping. */\n\t}\n}\n\nDUK_INTERNAL void duk_tval_decref(duk_hthread *thr, duk_tval *tv) {\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(tv != NULL);\n\n\tif (DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv)) {\n\t\tduk_heaphdr *h = DUK_TVAL_GET_HEAPHDR(tv);\n\t\tDUK_ASSERT(h != NULL);\n\t\tDUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(h));\n\t\tDUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(h) >= 1);\n#if 0\n\t\tif (DUK_HEAPHDR_PREDEC_REFCOUNT(h) != 0) {\n\t\t\treturn;\n\t\t}\n\t\tduk_heaphdr_refzero(thr, h);\n#else\n\t\tduk_heaphdr_decref(thr, h);\n#endif\n\t}\n}\n\nDUK_INTERNAL void duk_tval_decref_norz(duk_hthread *thr, duk_tval *tv) {\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(tv != NULL);\n\n\tif (DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv)) {\n\t\tduk_heaphdr *h = DUK_TVAL_GET_HEAPHDR(tv);\n\t\tDUK_ASSERT(h != NULL);\n\t\tDUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(h));\n\t\tDUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(h) >= 1);\n#if 0\n\t\tif (DUK_HEAPHDR_PREDEC_REFCOUNT(h) != 0) {\n\t\t\treturn;\n\t\t}\n\t\tduk_heaphdr_refzero_norz(thr, h);\n#else\n\t\tduk_heaphdr_decref_norz(thr, h);\n#endif\n\t}\n}\n#endif  /* !DUK_USE_FAST_REFCOUNT_DEFAULT */\n\n#define DUK__DECREF_ASSERTS() do { \\\n\t\tDUK_ASSERT(thr != NULL); \\\n\t\tDUK_ASSERT(thr->heap != NULL); \\\n\t\tDUK_ASSERT(h != NULL); \\\n\t\tDUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID((duk_heaphdr *) h)); \\\n\t\tDUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) h) >= 1); \\\n\t} while (0)\n#if defined(DUK_USE_ROM_OBJECTS)\n#define DUK__INCREF_SHARED() do { \\\n\t\tif (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) h)) { \\\n\t\t\treturn; \\\n\t\t} \\\n\t\tDUK_HEAPHDR_PREINC_REFCOUNT((duk_heaphdr *) h); \\\n\t\tDUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) h) != 0);  /* No wrapping. */ \\\n\t} while (0)\n#define DUK__DECREF_SHARED() do { \\\n\t\tif (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) h)) { \\\n\t\t\treturn; \\\n\t\t} \\\n\t\tif (DUK_HEAPHDR_PREDEC_REFCOUNT((duk_heaphdr *) h) != 0) { \\\n\t\t\treturn; \\\n\t\t} \\\n\t} while (0)\n#else\n#define DUK__INCREF_SHARED() do { \\\n\t\tDUK_HEAPHDR_PREINC_REFCOUNT((duk_heaphdr *) h); \\\n\t\tDUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) h) != 0);  /* No wrapping. */ \\\n\t} while (0)\n#define DUK__DECREF_SHARED() do { \\\n\t\tif (DUK_HEAPHDR_PREDEC_REFCOUNT((duk_heaphdr *) h) != 0) { \\\n\t\t\treturn; \\\n\t\t} \\\n\t} while (0)\n#endif\n\n#if !defined(DUK_USE_FAST_REFCOUNT_DEFAULT)\n/* This will in practice be inlined because it's just an INC instructions\n * and a bit test + INC when ROM objects are enabled.\n */\nDUK_INTERNAL void duk_heaphdr_incref(duk_heaphdr *h) {\n\tDUK_ASSERT(h != NULL);\n\tDUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(h));\n\tDUK_ASSERT_DISABLE(DUK_HEAPHDR_GET_REFCOUNT(h) >= 0);\n\n\tDUK__INCREF_SHARED();\n}\n\nDUK_INTERNAL void duk_heaphdr_decref(duk_hthread *thr, duk_heaphdr *h) {\n\tDUK__DECREF_ASSERTS();\n\tDUK__DECREF_SHARED();\n\tduk_heaphdr_refzero(thr, h);\n\n\t/* Forced mark-and-sweep when GC torture enabled; this could happen\n\t * on any DECREF (but not DECREF_NORZ).\n\t */\n\tDUK_GC_TORTURE(thr->heap);\n}\nDUK_INTERNAL void duk_heaphdr_decref_norz(duk_hthread *thr, duk_heaphdr *h) {\n\tDUK__DECREF_ASSERTS();\n\tDUK__DECREF_SHARED();\n\tduk_heaphdr_refzero_norz(thr, h);\n}\n#endif  /* !DUK_USE_FAST_REFCOUNT_DEFAULT */\n\n#if 0  /* Not needed. */\nDUK_INTERNAL void duk_hstring_decref(duk_hthread *thr, duk_hstring *h) {\n\tDUK__DECREF_ASSERTS();\n\tDUK__DECREF_SHARED();\n\tduk_hstring_refzero(thr, h);\n}\nDUK_INTERNAL void duk_hstring_decref_norz(duk_hthread *thr, duk_hstring *h) {\n\tDUK__DECREF_ASSERTS();\n\tDUK__DECREF_SHARED();\n\tduk_hstring_refzero_norz(thr, h);\n}\nDUK_INTERNAL void duk_hbuffer_decref(duk_hthread *thr, duk_hbuffer *h) {\n\tDUK__DECREF_ASSERTS();\n\tDUK__DECREF_SHARED();\n\tduk_hbuffer_refzero(thr, h);\n}\nDUK_INTERNAL void duk_hbuffer_decref_norz(duk_hthread *thr, duk_hbuffer *h) {\n\tDUK__DECREF_ASSERTS();\n\tDUK__DECREF_SHARED();\n\tduk_hbuffer_refzero_norz(thr, h);\n}\nDUK_INTERNAL void duk_hobject_decref(duk_hthread *thr, duk_hobject *h) {\n\tDUK__DECREF_ASSERTS();\n\tDUK__DECREF_SHARED();\n\tduk_hobject_refzero(thr, h);\n}\nDUK_INTERNAL void duk_hobject_decref_norz(duk_hthread *thr, duk_hobject *h) {\n\tDUK__DECREF_ASSERTS();\n\tDUK__DECREF_SHARED();\n\tduk_hobject_refzero_norz(thr, h);\n}\n#endif\n\n#else  /* DUK_USE_REFERENCE_COUNTING */\n\n/* no refcounting */\n\n#endif  /* DUK_USE_REFERENCE_COUNTING */\n\n/* automatic undefs */\n#undef DUK__DECREF_ASSERTS\n#undef DUK__DECREF_SHARED\n#undef DUK__INCREF_SHARED\n#undef DUK__RZ_BUFFER\n#undef DUK__RZ_INLINE\n#undef DUK__RZ_OBJECT\n#undef DUK__RZ_STRING\n#undef DUK__RZ_SUPPRESS_ASSERT1\n#undef DUK__RZ_SUPPRESS_ASSERT2\n#undef DUK__RZ_SUPPRESS_CHECK\n#undef DUK__RZ_SUPPRESS_COND\n#line 1 \"duk_heap_stringcache.c\"\n/*\n *  String cache.\n *\n *  Provides a cache to optimize indexed string lookups.  The cache keeps\n *  track of (byte offset, char offset) states for a fixed number of strings.\n *  Otherwise we'd need to scan from either end of the string, as we store\n *  strings in (extended) UTF-8.\n */\n\n/* #include duk_internal.h -> already included */\n\n/*\n *  Delete references to given hstring from the heap string cache.\n *\n *  String cache references are 'weak': they are not counted towards\n *  reference counts, nor serve as roots for mark-and-sweep.  When an\n *  object is about to be freed, such references need to be removed.\n */\n\nDUK_INTERNAL void duk_heap_strcache_string_remove(duk_heap *heap, duk_hstring *h) {\n\tduk_small_int_t i;\n\tfor (i = 0; i < DUK_HEAP_STRCACHE_SIZE; i++) {\n\t\tduk_strcache *c = heap->strcache + i;\n\t\tif (c->h == h) {\n\t\t\tDUK_DD(DUK_DDPRINT(\"deleting weak strcache reference to hstring %p from heap %p\",\n\t\t\t                   (void *) h, (void *) heap));\n\t\t\tc->h = NULL;\n\n\t\t\t/* XXX: the string shouldn't appear twice, but we now loop to the\n\t\t\t * end anyway; if fixed, add a looping assertion to ensure there\n\t\t\t * is no duplicate.\n\t\t\t */\n\t\t}\n\t}\n}\n\n/*\n *  String scanning helpers\n *\n *  All bytes other than UTF-8 continuation bytes ([0x80,0xbf]) are\n *  considered to contribute a character.  This must match how string\n *  character length is computed.\n */\n\nDUK_LOCAL const duk_uint8_t *duk__scan_forwards(const duk_uint8_t *p, const duk_uint8_t *q, duk_uint_fast32_t n) {\n\twhile (n > 0) {\n\t\tfor (;;) {\n\t\t\tp++;\n\t\t\tif (p >= q) {\n\t\t\t\treturn NULL;\n\t\t\t}\n\t\t\tif ((*p & 0xc0) != 0x80) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tn--;\n\t}\n\treturn p;\n}\n\nDUK_LOCAL const duk_uint8_t *duk__scan_backwards(const duk_uint8_t *p, const duk_uint8_t *q, duk_uint_fast32_t n) {\n\twhile (n > 0) {\n\t\tfor (;;) {\n\t\t\tp--;\n\t\t\tif (p < q) {\n\t\t\t\treturn NULL;\n\t\t\t}\n\t\t\tif ((*p & 0xc0) != 0x80) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tn--;\n\t}\n\treturn p;\n}\n\n/*\n *  Convert char offset to byte offset\n *\n *  Avoid using the string cache if possible: for ASCII strings byte and\n *  char offsets are equal and for short strings direct scanning may be\n *  better than using the string cache (which may evict a more important\n *  entry).\n *\n *  Typing now assumes 32-bit string byte/char offsets (duk_uint_fast32_t).\n *  Better typing might be to use duk_size_t.\n *\n *  Caller should ensure 'char_offset' is within the string bounds [0,charlen]\n *  (endpoint is inclusive).  If this is not the case, no memory unsafe\n *  behavior will happen but an error will be thrown.\n */\n\nDUK_INTERNAL duk_uint_fast32_t duk_heap_strcache_offset_char2byte(duk_hthread *thr, duk_hstring *h, duk_uint_fast32_t char_offset) {\n\tduk_heap *heap;\n\tduk_strcache *sce;\n\tduk_uint_fast32_t byte_offset;\n\tduk_small_int_t i;\n\tduk_bool_t use_cache;\n\tduk_uint_fast32_t dist_start, dist_end, dist_sce;\n\tduk_uint_fast32_t char_length;\n\tconst duk_uint8_t *p_start;\n\tconst duk_uint8_t *p_end;\n\tconst duk_uint8_t *p_found;\n\n\t/*\n\t *  For ASCII strings, the answer is simple.\n\t */\n\n\tif (DUK_LIKELY(DUK_HSTRING_IS_ASCII(h))) {\n\t\treturn char_offset;\n\t}\n\n\tchar_length = (duk_uint_fast32_t) DUK_HSTRING_GET_CHARLEN(h);\n\tDUK_ASSERT(char_offset <= char_length);\n\n\tif (DUK_LIKELY(DUK_HSTRING_IS_ASCII(h))) {\n\t\t/* Must recheck because the 'is ascii' flag may be set\n\t\t * lazily.  Alternatively, we could just compare charlen\n\t\t * to bytelen.\n\t\t */\n\t\treturn char_offset;\n\t}\n\n\t/*\n\t *  For non-ASCII strings, we need to scan forwards or backwards\n\t *  from some starting point.  The starting point may be the start\n\t *  or end of the string, or some cached midpoint in the string\n\t *  cache.\n\t *\n\t *  For \"short\" strings we simply scan without checking or updating\n\t *  the cache.  For longer strings we check and update the cache as\n\t *  necessary, inserting a new cache entry if none exists.\n\t */\n\n\tDUK_DDD(DUK_DDDPRINT(\"non-ascii string %p, char_offset=%ld, clen=%ld, blen=%ld\",\n\t                     (void *) h, (long) char_offset,\n\t                     (long) DUK_HSTRING_GET_CHARLEN(h),\n\t                     (long) DUK_HSTRING_GET_BYTELEN(h)));\n\n\theap = thr->heap;\n\tsce = NULL;\n\tuse_cache = (char_length > DUK_HEAP_STRINGCACHE_NOCACHE_LIMIT);\n\n\tif (use_cache) {\n#if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)\n\t\tDUK_DDD(DUK_DDDPRINT(\"stringcache before char2byte (using cache):\"));\n\t\tfor (i = 0; i < DUK_HEAP_STRCACHE_SIZE; i++) {\n\t\t\tduk_strcache *c = heap->strcache + i;\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"  [%ld] -> h=%p, cidx=%ld, bidx=%ld\",\n\t\t\t                     (long) i, (void *) c->h, (long) c->cidx, (long) c->bidx));\n\t\t}\n#endif\n\n\t\tfor (i = 0; i < DUK_HEAP_STRCACHE_SIZE; i++) {\n\t\t\tduk_strcache *c = heap->strcache + i;\n\n\t\t\tif (c->h == h) {\n\t\t\t\tsce = c;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t *  Scan from shortest distance:\n\t *    - start of string\n\t *    - end of string\n\t *    - cache entry (if exists)\n\t */\n\n\tDUK_ASSERT(DUK_HSTRING_GET_CHARLEN(h) >= char_offset);\n\tdist_start = char_offset;\n\tdist_end = char_length - char_offset;\n\tdist_sce = 0; DUK_UNREF(dist_sce);  /* initialize for debug prints, needed if sce==NULL */\n\n\tp_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h);\n\tp_end = (const duk_uint8_t *) (p_start + DUK_HSTRING_GET_BYTELEN(h));\n\tp_found = NULL;\n\n\tif (sce) {\n\t\tif (char_offset >= sce->cidx) {\n\t\t\tdist_sce = char_offset - sce->cidx;\n\t\t\tif ((dist_sce <= dist_start) && (dist_sce <= dist_end)) {\n\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"non-ascii string, use_cache=%ld, sce=%p:%ld:%ld, \"\n\t\t\t\t                     \"dist_start=%ld, dist_end=%ld, dist_sce=%ld => \"\n\t\t\t\t                     \"scan forwards from sce\",\n\t\t\t\t                     (long) use_cache, (void *) (sce ? sce->h : NULL),\n\t\t\t\t                     (sce ? (long) sce->cidx : (long) -1),\n\t\t\t\t                     (sce ? (long) sce->bidx : (long) -1),\n\t\t\t\t                     (long) dist_start, (long) dist_end, (long) dist_sce));\n\n\t\t\t\tp_found = duk__scan_forwards(p_start + sce->bidx,\n\t\t\t\t                             p_end,\n\t\t\t\t                             dist_sce);\n\t\t\t\tgoto scan_done;\n\t\t\t}\n\t\t} else {\n\t\t\tdist_sce = sce->cidx - char_offset;\n\t\t\tif ((dist_sce <= dist_start) && (dist_sce <= dist_end)) {\n\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"non-ascii string, use_cache=%ld, sce=%p:%ld:%ld, \"\n\t\t\t\t                     \"dist_start=%ld, dist_end=%ld, dist_sce=%ld => \"\n\t\t\t\t                     \"scan backwards from sce\",\n\t\t\t\t                     (long) use_cache, (void *) (sce ? sce->h : NULL),\n\t\t\t\t                     (sce ? (long) sce->cidx : (long) -1),\n\t\t\t\t                     (sce ? (long) sce->bidx : (long) -1),\n\t\t\t\t                     (long) dist_start, (long) dist_end, (long) dist_sce));\n\n\t\t\t\tp_found = duk__scan_backwards(p_start + sce->bidx,\n\t\t\t\t                              p_start,\n\t\t\t\t                              dist_sce);\n\t\t\t\tgoto scan_done;\n\t\t\t}\n\t\t}\n\t}\n\n\t/* no sce, or sce scan not best */\n\n\tif (dist_start <= dist_end) {\n\t\tDUK_DDD(DUK_DDDPRINT(\"non-ascii string, use_cache=%ld, sce=%p:%ld:%ld, \"\n\t\t                     \"dist_start=%ld, dist_end=%ld, dist_sce=%ld => \"\n\t\t                     \"scan forwards from string start\",\n\t\t                     (long) use_cache, (void *) (sce ? sce->h : NULL),\n\t\t                     (sce ? (long) sce->cidx : (long) -1),\n\t\t                     (sce ? (long) sce->bidx : (long) -1),\n\t\t                     (long) dist_start, (long) dist_end, (long) dist_sce));\n\n\t\tp_found = duk__scan_forwards(p_start,\n\t\t                             p_end,\n\t\t                             dist_start);\n\t} else {\n\t\tDUK_DDD(DUK_DDDPRINT(\"non-ascii string, use_cache=%ld, sce=%p:%ld:%ld, \"\n\t\t                     \"dist_start=%ld, dist_end=%ld, dist_sce=%ld => \"\n\t\t                     \"scan backwards from string end\",\n\t\t                     (long) use_cache, (void *) (sce ? sce->h : NULL),\n\t\t                     (sce ? (long) sce->cidx : (long) -1),\n\t\t                     (sce ? (long) sce->bidx : (long) -1),\n\t\t                     (long) dist_start, (long) dist_end, (long) dist_sce));\n\n\t\tp_found = duk__scan_backwards(p_end,\n\t\t                              p_start,\n\t\t                              dist_end);\n\t}\n\n scan_done:\n\n\tif (DUK_UNLIKELY(p_found == NULL)) {\n\t\t/* Scan error: this shouldn't normally happen; it could happen if\n\t\t * string is not valid UTF-8 data, and clen/blen are not consistent\n\t\t * with the scanning algorithm.\n\t\t */\n\t\tgoto scan_error;\n\t}\n\n\tDUK_ASSERT(p_found >= p_start);\n\tDUK_ASSERT(p_found <= p_end);  /* may be equal */\n\tbyte_offset = (duk_uint32_t) (p_found - p_start);\n\n\tDUK_DDD(DUK_DDDPRINT(\"-> string %p, cidx %ld -> bidx %ld\",\n\t                     (void *) h, (long) char_offset, (long) byte_offset));\n\n\t/*\n\t *  Update cache entry (allocating if necessary), and move the\n\t *  cache entry to the first place (in an \"LRU\" policy).\n\t */\n\n\tif (use_cache) {\n\t\t/* update entry, allocating if necessary */\n\t\tif (!sce) {\n\t\t\tsce = heap->strcache + DUK_HEAP_STRCACHE_SIZE - 1;  /* take last entry */\n\t\t\tsce->h = h;\n\t\t}\n\t\tDUK_ASSERT(sce != NULL);\n\t\tsce->bidx = (duk_uint32_t) (p_found - p_start);\n\t\tsce->cidx = (duk_uint32_t) char_offset;\n\n\t\t/* LRU: move our entry to first */\n\t\tif (sce > &heap->strcache[0]) {\n\t\t\t/*\n\t\t\t *   A                  C\n\t\t\t *   B                  A\n\t\t\t *   C <- sce    ==>    B\n\t\t\t *   D                  D\n\t\t\t */\n\t\t\tduk_strcache tmp;\n\n\t\t\ttmp = *sce;\n\t\t\tDUK_MEMMOVE((void *) (&heap->strcache[1]),\n\t\t\t            (const void *) (&heap->strcache[0]),\n\t\t\t            (size_t) (((char *) sce) - ((char *) &heap->strcache[0])));\n\t\t\theap->strcache[0] = tmp;\n\n\t\t\t/* 'sce' points to the wrong entry here, but is no longer used */\n\t\t}\n#if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)\n\t\tDUK_DDD(DUK_DDDPRINT(\"stringcache after char2byte (using cache):\"));\n\t\tfor (i = 0; i < DUK_HEAP_STRCACHE_SIZE; i++) {\n\t\t\tduk_strcache *c = heap->strcache + i;\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"  [%ld] -> h=%p, cidx=%ld, bidx=%ld\",\n\t\t\t                     (long) i, (void *) c->h, (long) c->cidx, (long) c->bidx));\n\t\t}\n#endif\n\t}\n\n\treturn byte_offset;\n\n scan_error:\n\tDUK_ERROR_INTERNAL(thr);\n\treturn 0;\n}\n#line 1 \"duk_heap_stringtable.c\"\n/*\n *  Heap string table handling, string interning.\n */\n\n/* #include duk_internal.h -> already included */\n\n/* Resize checks not needed if minsize == maxsize, typical for low memory\n * targets.\n */\n#define DUK__STRTAB_RESIZE_CHECK\n#if (DUK_USE_STRTAB_MINSIZE == DUK_USE_STRTAB_MAXSIZE)\n#undef DUK__STRTAB_RESIZE_CHECK\n#endif\n\n#if defined(DUK_USE_STRTAB_PTRCOMP)\n#define DUK__HEAPPTR_ENC16(heap,ptr)    DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (ptr))\n#define DUK__HEAPPTR_DEC16(heap,val)    DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (val))\n#define DUK__GET_STRTABLE(heap)         ((heap)->strtable16)\n#else\n#define DUK__HEAPPTR_ENC16(heap,ptr)    (ptr)\n#define DUK__HEAPPTR_DEC16(heap,val)    (val)\n#define DUK__GET_STRTABLE(heap)         ((heap)->strtable)\n#endif\n\n#define DUK__STRTAB_U32_MAX_STRLEN      10               /* 4'294'967'295 */\n\n/*\n *  Debug dump stringtable.\n */\n\n#if defined(DUK_USE_DEBUG)\nDUK_INTERNAL void duk_heap_strtable_dump(duk_heap *heap) {\n#if defined(DUK_USE_STRTAB_PTRCOMP)\n\tduk_uint16_t *strtable;\n#else\n\tduk_hstring **strtable;\n#endif\n\tduk_uint32_t i;\n\tduk_hstring *h;\n\tduk_size_t count_total = 0;\n\tduk_size_t count_chain;\n\tduk_size_t count_chain_min = DUK_SIZE_MAX;\n\tduk_size_t count_chain_max = 0;\n\tduk_size_t count_len[8];  /* chain lengths from 0 to 7 */\n\n\tif (heap == NULL) {\n\t\tDUK_D(DUK_DPRINT(\"string table, heap=NULL\"));\n\t\treturn;\n\t}\n\n\tstrtable = DUK__GET_STRTABLE(heap);\n\tif (strtable == NULL) {\n\t\tDUK_D(DUK_DPRINT(\"string table, strtab=NULL\"));\n\t\treturn;\n\t}\n\n\tDUK_MEMZERO((void *) count_len, sizeof(count_len));\n\tfor (i = 0; i < heap->st_size; i++) {\n\t\th = DUK__HEAPPTR_DEC16(heap, strtable[i]);\n\t\tcount_chain = 0;\n\t\twhile (h != NULL) {\n\t\t\tcount_chain++;\n\t\t\th = h->hdr.h_next;\n\t\t}\n\t\tif (count_chain < sizeof(count_len) / sizeof(duk_size_t)) {\n\t\t\tcount_len[count_chain]++;\n\t\t}\n\t\tcount_chain_max = (count_chain > count_chain_max ? count_chain : count_chain_max);\n\t\tcount_chain_min = (count_chain < count_chain_min ? count_chain : count_chain_min);\n\t\tcount_total += count_chain;\n\t}\n\n\tDUK_D(DUK_DPRINT(\"string table, strtab=%p, count=%lu, chain min=%lu max=%lu avg=%lf: \"\n\t                 \"counts: %lu %lu %lu %lu %lu %lu %lu %lu ...\",\n\t                 (void *) heap->strtable, (unsigned long) count_total,\n\t                 (unsigned long) count_chain_min, (unsigned long) count_chain_max,\n\t                 (double) count_total / (double) heap->st_size,\n\t                 (unsigned long) count_len[0], (unsigned long) count_len[1],\n\t                 (unsigned long) count_len[2], (unsigned long) count_len[3],\n\t                 (unsigned long) count_len[4], (unsigned long) count_len[5],\n\t                 (unsigned long) count_len[6], (unsigned long) count_len[7]));\n}\n#endif  /* DUK_USE_DEBUG */\n\n/*\n *  Assertion helper to ensure strtable is populated correctly.\n */\n\n#if defined(DUK_USE_ASSERTIONS)\nDUK_LOCAL void duk__strtable_assert_checks(duk_heap *heap) {\n#if defined(DUK_USE_STRTAB_PTRCOMP)\n\tduk_uint16_t *strtable;\n#else\n\tduk_hstring **strtable;\n#endif\n\tduk_uint32_t i;\n\tduk_hstring *h;\n\tduk_size_t count = 0;\n\n\tDUK_ASSERT(heap != NULL);\n\n\tstrtable = DUK__GET_STRTABLE(heap);\n\tif (strtable != NULL) {\n\t\tDUK_ASSERT(heap->st_size != 0);\n\t\tDUK_ASSERT(heap->st_mask == heap->st_size - 1);\n\n\t\tfor (i = 0; i < heap->st_size; i++) {\n\t\t\th = DUK__HEAPPTR_DEC16(heap, strtable[i]);\n\t\t\twhile (h != NULL) {\n\t\t\t\tDUK_ASSERT((DUK_HSTRING_GET_HASH(h) & heap->st_mask) == i);\n\t\t\t\tcount++;\n\t\t\t\th = h->hdr.h_next;\n\t\t\t}\n\t\t}\n\t} else {\n\t\tDUK_ASSERT(heap->st_size == 0);\n\t\tDUK_ASSERT(heap->st_mask == 0);\n\t}\n\n#if defined(DUK__STRTAB_RESIZE_CHECK)\n\tDUK_ASSERT(count == (duk_size_t) heap->st_count);\n#endif\n}\n#endif  /* DUK_USE_ASSERTIONS */\n\n/*\n *  Allocate and initialize a duk_hstring.\n *\n *  Returns a NULL if allocation or initialization fails for some reason.\n *\n *  The string won't be inserted into the string table and isn't tracked in\n *  any way (link pointers will be NULL).  The caller must place the string\n *  into the string table without any risk of a longjmp, otherwise the string\n *  is leaked.\n */\n\nDUK_LOCAL duk_hstring *duk__strtable_alloc_hstring(duk_heap *heap,\n                                                   const duk_uint8_t *str,\n                                                   duk_uint32_t blen,\n                                                   duk_uint32_t strhash,\n                                                   const duk_uint8_t *extdata) {\n\tduk_hstring *res;\n\tconst duk_uint8_t *data;\n#if !defined(DUK_USE_HSTRING_ARRIDX)\n\tduk_uarridx_t dummy;\n#endif\n\n\tDUK_ASSERT(heap != NULL);\n\tDUK_UNREF(extdata);\n\n#if defined(DUK_USE_STRLEN16)\n\t/* If blen <= 0xffffUL, clen is also guaranteed to be <= 0xffffUL. */\n\tif (blen > 0xffffUL) {\n\t\tDUK_D(DUK_DPRINT(\"16-bit string blen/clen active and blen over 16 bits, reject intern\"));\n\t\tgoto alloc_error;\n\t}\n#endif\n\n\t/* XXX: Memzeroing the allocated structure is not really necessary\n\t * because we could just initialize all fields explicitly (almost\n\t * all fields are initialized explicitly anyway).\n\t */\n#if defined(DUK_USE_HSTRING_EXTDATA) && defined(DUK_USE_EXTSTR_INTERN_CHECK)\n\tif (extdata) {\n\t\tres = (duk_hstring *) DUK_ALLOC(heap, sizeof(duk_hstring_external));\n\t\tif (DUK_UNLIKELY(res == NULL)) {\n\t\t\tgoto alloc_error;\n\t\t}\n\t\tDUK_MEMZERO(res, sizeof(duk_hstring_external));\n#if defined(DUK_USE_EXPLICIT_NULL_INIT)\n\t\tDUK_HEAPHDR_STRING_INIT_NULLS(&res->hdr);\n#endif\n\t\tDUK_HEAPHDR_SET_TYPE_AND_FLAGS(&res->hdr, DUK_HTYPE_STRING, DUK_HSTRING_FLAG_EXTDATA);\n\n\t\tDUK_ASSERT(extdata[blen] == 0);  /* Application responsibility. */\n\t\tdata = extdata;\n\t\t((duk_hstring_external *) res)->extdata = extdata;\n\t} else\n#endif  /* DUK_USE_HSTRING_EXTDATA && DUK_USE_EXTSTR_INTERN_CHECK */\n\t{\n\t\tduk_uint8_t *data_tmp;\n\n\t\t/* NUL terminate for convenient C access */\n\t\tDUK_ASSERT(sizeof(duk_hstring) + blen + 1 > blen);  /* No wrap, limits ensure. */\n\t\tres = (duk_hstring *) DUK_ALLOC(heap, sizeof(duk_hstring) + blen + 1);\n\t\tif (DUK_UNLIKELY(res == NULL)) {\n\t\t\tgoto alloc_error;\n\t\t}\n\t\tDUK_MEMZERO(res, sizeof(duk_hstring));\n#if defined(DUK_USE_EXPLICIT_NULL_INIT)\n\t\tDUK_HEAPHDR_STRING_INIT_NULLS(&res->hdr);\n#endif\n\t\tDUK_HEAPHDR_SET_TYPE_AND_FLAGS(&res->hdr, DUK_HTYPE_STRING, 0);\n\n\t\tdata_tmp = (duk_uint8_t *) (res + 1);\n\t\tDUK_MEMCPY(data_tmp, str, blen);\n\t\tdata_tmp[blen] = (duk_uint8_t) 0;\n\t\tdata = (const duk_uint8_t *) data_tmp;\n\t}\n\n\tDUK_HSTRING_SET_BYTELEN(res, blen);\n\tDUK_HSTRING_SET_HASH(res, strhash);\n\n\tDUK_ASSERT(!DUK_HSTRING_HAS_ARRIDX(res));\n#if defined(DUK_USE_HSTRING_ARRIDX)\n\tres->arridx = duk_js_to_arrayindex_string(data, blen);\n\tif (res->arridx != DUK_HSTRING_NO_ARRAY_INDEX) {\n#else\n\tdummy = duk_js_to_arrayindex_string(data, blen);\n\tif (dummy != DUK_HSTRING_NO_ARRAY_INDEX) {\n#endif\n\t\t/* Array index strings cannot be symbol strings,\n\t\t * and they're always pure ASCII so blen == clen.\n\t\t */\n\t\tDUK_HSTRING_SET_ARRIDX(res);\n\t\tDUK_HSTRING_SET_ASCII(res);\n\t\tDUK_ASSERT(duk_unicode_unvalidated_utf8_length(data, (duk_size_t) blen) == blen);\n\t} else {\n\t\t/* Because 'data' is NUL-terminated, we don't need a\n\t\t * blen > 0 check here.  For NUL (0x00) the symbol\n\t\t * checks will be false.\n\t\t */\n\t\tif (DUK_UNLIKELY(data[0] >= 0x80U)) {\n\t\t\tif (data[0] <= 0x81) {\n\t\t\t\tDUK_HSTRING_SET_SYMBOL(res);\n\t\t\t} else if (data[0] == 0x82U || data[0] == 0xffU) {\n\t\t\t\tDUK_HSTRING_SET_HIDDEN(res);\n\t\t\t\tDUK_HSTRING_SET_SYMBOL(res);\n\t\t\t}\n\t\t}\n\n\t\t/* Using an explicit 'ASCII' flag has larger footprint (one call site\n\t\t * only) but is quite useful for the case when there's no explicit\n\t\t * 'clen' in duk_hstring.\n\t\t *\n\t\t * The flag is set lazily for RAM strings.\n\t\t */\n\t\tDUK_ASSERT(!DUK_HSTRING_HAS_ASCII(res));\n\n#if defined(DUK_USE_HSTRING_LAZY_CLEN)\n\t\t/* Charlen initialized to 0, updated on-the-fly. */\n#else\n\t\tduk_hstring_init_charlen(res);  /* Also sets ASCII flag. */\n#endif\n\t}\n\n\tDUK_DDD(DUK_DDDPRINT(\"interned string, hash=0x%08lx, blen=%ld, has_arridx=%ld, has_extdata=%ld\",\n\t                     (unsigned long) DUK_HSTRING_GET_HASH(res),\n\t                     (long) DUK_HSTRING_GET_BYTELEN(res),\n\t                     (long) (DUK_HSTRING_HAS_ARRIDX(res) ? 1 : 0),\n\t                     (long) (DUK_HSTRING_HAS_EXTDATA(res) ? 1 : 0)));\n\n\tDUK_ASSERT(res != NULL);\n\treturn res;\n\n alloc_error:\n\treturn NULL;\n}\n\n/*\n *  Grow strtable allocation in-place.\n */\n\n#if defined(DUK__STRTAB_RESIZE_CHECK)\nDUK_LOCAL void duk__strtable_grow_inplace(duk_heap *heap) {\n\tduk_uint32_t new_st_size;\n\tduk_uint32_t old_st_size;\n\tduk_uint32_t i;\n\tduk_hstring *h;\n\tduk_hstring *next;\n\tduk_hstring *prev;\n#if defined(DUK_USE_STRTAB_PTRCOMP)\n\tduk_uint16_t *new_ptr;\n\tduk_uint16_t *new_ptr_high;\n#else\n\tduk_hstring **new_ptr;\n\tduk_hstring **new_ptr_high;\n#endif\n\n\tDUK_DD(DUK_DDPRINT(\"grow in-place: %lu -> %lu\", (unsigned long) heap->st_size, (unsigned long) heap->st_size * 2));\n\n\tDUK_ASSERT(heap != NULL);\n\tDUK_ASSERT(heap->st_resizing == 1);\n\tDUK_ASSERT(heap->st_size >= 2);\n\tDUK_ASSERT((heap->st_size & (heap->st_size - 1)) == 0);  /* 2^N */\n\tDUK_ASSERT(DUK__GET_STRTABLE(heap) != NULL);\n\n\tDUK_STATS_INC(heap, stats_strtab_resize_grow);\n\n\tnew_st_size = heap->st_size << 1U;\n\tDUK_ASSERT(new_st_size > heap->st_size);  /* No overflow. */\n\n\t/* Reallocate the strtable first and then work in-place to rehash\n\t * strings.  We don't need an indirect allocation here: even if GC\n\t * is triggered to satisfy the allocation, recursive strtable resize\n\t * is prevented by flags.  This is also why we don't need to use\n\t * DUK_REALLOC_INDIRECT().\n\t */\n\n#if defined(DUK_USE_STRTAB_PTRCOMP)\n\tnew_ptr = (duk_uint16_t *) DUK_REALLOC(heap, heap->strtable16, sizeof(duk_uint16_t) * new_st_size);\n#else\n\tnew_ptr = (duk_hstring **) DUK_REALLOC(heap, heap->strtable, sizeof(duk_hstring *) * new_st_size);\n#endif\n\tif (DUK_UNLIKELY(new_ptr == NULL)) {\n\t\t/* If realloc fails we can continue normally: the string table\n\t\t * won't \"fill up\" although chains will gradually get longer.\n\t\t * When string insertions continue, we'll quite soon try again\n\t\t * with no special handling.\n\t\t */\n\t\tDUK_D(DUK_DPRINT(\"string table grow failed, ignoring\"));\n\t\treturn;\n\t}\n#if defined(DUK_USE_STRTAB_PTRCOMP)\n\theap->strtable16 = new_ptr;\n#else\n\theap->strtable = new_ptr;\n#endif\n\n\t/* Rehash a single bucket into two separate ones.  When we grow\n\t * by x2 the highest 'new' bit determines whether a string remains\n\t * in its old position (bit is 0) or goes to a new one (bit is 1).\n\t */\n\n\told_st_size = heap->st_size;\n\tnew_ptr_high = new_ptr + old_st_size;\n\tfor (i = 0; i < old_st_size; i++) {\n\t\tduk_hstring *new_root;\n\t\tduk_hstring *new_root_high;\n\n\t\th = DUK__HEAPPTR_DEC16(heap, new_ptr[i]);\n\t\tnew_root = h;\n\t\tnew_root_high = NULL;\n\n\t\tprev = NULL;\n\t\twhile (h != NULL) {\n\t\t\tduk_uint32_t mask;\n\n\t\t\tDUK_ASSERT((DUK_HSTRING_GET_HASH(h) & heap->st_mask) == i);\n\t\t\tnext = h->hdr.h_next;\n\n\t\t\t/* Example: if previous size was 256, previous mask is 0xFF\n\t\t\t * and size is 0x100 which corresponds to the new bit that\n\t\t\t * comes into play.\n\t\t\t */\n\t\t\tDUK_ASSERT(heap->st_mask == old_st_size - 1);\n\t\t\tmask = old_st_size;\n\t\t\tif (DUK_HSTRING_GET_HASH(h) & mask) {\n\t\t\t\tif (prev != NULL) {\n\t\t\t\t\tprev->hdr.h_next = h->hdr.h_next;\n\t\t\t\t} else {\n\t\t\t\t\tDUK_ASSERT(h == new_root);\n\t\t\t\t\tnew_root = h->hdr.h_next;\n\t\t\t\t}\n\n\t\t\t\th->hdr.h_next = new_root_high;\n\t\t\t\tnew_root_high = h;\n\t\t\t} else {\n\t\t\t\tprev = h;\n\t\t\t}\n\t\t\th = next;\n\t\t}\n\n\t\tnew_ptr[i] = DUK__HEAPPTR_ENC16(heap, new_root);\n\t\tnew_ptr_high[i] = DUK__HEAPPTR_ENC16(heap, new_root_high);\n\t}\n\n\theap->st_size = new_st_size;\n\theap->st_mask = new_st_size - 1;\n\n#if defined(DUK_USE_ASSERTIONS)\n\tduk__strtable_assert_checks(heap);\n#endif\n}\n#endif  /* DUK__STRTAB_RESIZE_CHECK */\n\n/*\n *  Shrink strtable allocation in-place.\n */\n\n#if defined(DUK__STRTAB_RESIZE_CHECK)\nDUK_LOCAL void duk__strtable_shrink_inplace(duk_heap *heap) {\n\tduk_uint32_t new_st_size;\n\tduk_uint32_t i;\n\tduk_hstring *h;\n\tduk_hstring *other;\n\tduk_hstring *root;\n#if defined(DUK_USE_STRTAB_PTRCOMP)\n\tduk_uint16_t *old_ptr;\n\tduk_uint16_t *old_ptr_high;\n\tduk_uint16_t *new_ptr;\n#else\n\tduk_hstring **old_ptr;\n\tduk_hstring **old_ptr_high;\n\tduk_hstring **new_ptr;\n#endif\n\n\tDUK_DD(DUK_DDPRINT(\"shrink in-place: %lu -> %lu\", (unsigned long) heap->st_size, (unsigned long) heap->st_size / 2));\n\n\tDUK_ASSERT(heap != NULL);\n\tDUK_ASSERT(heap->st_resizing == 1);\n\tDUK_ASSERT(heap->st_size >= 2);\n\tDUK_ASSERT((heap->st_size & (heap->st_size - 1)) == 0);  /* 2^N */\n\tDUK_ASSERT(DUK__GET_STRTABLE(heap) != NULL);\n\n\tDUK_STATS_INC(heap, stats_strtab_resize_shrink);\n\n\tnew_st_size = heap->st_size >> 1U;\n\n\t/* Combine two buckets into a single one.  When we shrink, one hash\n\t * bit (highest) disappears.\n\t */\n\told_ptr = DUK__GET_STRTABLE(heap);\n\told_ptr_high = old_ptr + new_st_size;\n\tfor (i = 0; i < new_st_size; i++) {\n\t\th = DUK__HEAPPTR_DEC16(heap, old_ptr[i]);\n\t\tother = DUK__HEAPPTR_DEC16(heap, old_ptr_high[i]);\n\n\t\tif (h == NULL) {\n\t\t\t/* First chain is empty, so use second one as is. */\n\t\t\troot = other;\n\t\t} else {\n\t\t\t/* Find end of first chain, and link in the second. */\n\t\t\troot = h;\n\t\t\twhile (h->hdr.h_next != NULL) {\n\t\t\t\th = h->hdr.h_next;\n\t\t\t}\n\t\t\th->hdr.h_next = other;\n\t\t}\n\n\t\told_ptr[i] = DUK__HEAPPTR_ENC16(heap, root);\n\t}\n\n\theap->st_size = new_st_size;\n\theap->st_mask = new_st_size - 1;\n\n\t/* The strtable is now consistent and we can realloc safely.  Even\n\t * if side effects cause string interning or removal the strtable\n\t * updates are safe.  Recursive resize has been prevented by caller.\n\t * This is also why we don't need to use DUK_REALLOC_INDIRECT().\n\t *\n\t * We assume a realloc() to a smaller size is guaranteed to succeed.\n\t * It would be relatively straightforward to handle the error by\n\t * essentially performing a \"grow\" step to recover.\n\t */\n\n#if defined(DUK_USE_STRTAB_PTRCOMP)\n\tnew_ptr = (duk_uint16_t *) DUK_REALLOC(heap, heap->strtable16, sizeof(duk_uint16_t) * new_st_size);\n\tDUK_ASSERT(new_ptr != NULL);\n\theap->strtable16 = new_ptr;\n#else\n\tnew_ptr = (duk_hstring **) DUK_REALLOC(heap, heap->strtable, sizeof(duk_hstring *) * new_st_size);\n\tDUK_ASSERT(new_ptr != NULL);\n\theap->strtable = new_ptr;\n#endif\n\n#if defined(DUK_USE_ASSERTIONS)\n\tduk__strtable_assert_checks(heap);\n#endif\n}\n#endif  /* DUK__STRTAB_RESIZE_CHECK */\n\n/*\n *  Grow/shrink check.\n */\n\n#if defined(DUK__STRTAB_RESIZE_CHECK)\nDUK_LOCAL DUK_COLD DUK_NOINLINE void duk__strtable_resize_check(duk_heap *heap) {\n\tduk_uint32_t load_factor;  /* fixed point */\n\n\tDUK_ASSERT(heap != NULL);\n#if defined(DUK_USE_STRTAB_PTRCOMP)\n\tDUK_ASSERT(heap->strtable16 != NULL);\n#else\n\tDUK_ASSERT(heap->strtable != NULL);\n#endif\n\n\tDUK_STATS_INC(heap, stats_strtab_resize_check);\n\n\t/* Prevent recursive resizing. */\n\tif (DUK_UNLIKELY(heap->st_resizing != 0U)) {\n\t\tDUK_D(DUK_DPRINT(\"prevent recursive strtable resize\"));\n\t\treturn;\n\t}\n\n\theap->st_resizing = 1;\n\n\tDUK_ASSERT(heap->st_size >= 16U);\n\tDUK_ASSERT((heap->st_size >> 4U) >= 1);\n\tload_factor = heap->st_count / (heap->st_size >> 4U);\n\n\tDUK_DD(DUK_DDPRINT(\"resize check string table: size=%lu, count=%lu, load_factor=%lu (fixed point .4; float %lf)\",\n\t                   (unsigned long) heap->st_size, (unsigned long) heap->st_count,\n\t                   (unsigned long) load_factor,\n\t                   (double) heap->st_count / (double) heap->st_size));\n\n\tif (load_factor >= DUK_USE_STRTAB_GROW_LIMIT) {\n\t\tif (heap->st_size >= DUK_USE_STRTAB_MAXSIZE) {\n\t\t\tDUK_DD(DUK_DDPRINT(\"want to grow strtable (based on load factor) but already maximum size\"));\n\t\t} else {\n\t\t\tDUK_D(DUK_DPRINT(\"grow string table: %lu -> %lu\", (unsigned long) heap->st_size, (unsigned long) heap->st_size * 2));\n#if defined(DUK_USE_DEBUG)\n\t\t\tduk_heap_strtable_dump(heap);\n#endif\n\t\t\tduk__strtable_grow_inplace(heap);\n\t\t}\n\t} else if (load_factor <= DUK_USE_STRTAB_SHRINK_LIMIT) {\n\t\tif (heap->st_size <= DUK_USE_STRTAB_MINSIZE) {\n\t\t\tDUK_DD(DUK_DDPRINT(\"want to shrink strtable (based on load factor) but already minimum size\"));\n\t\t} else {\n\t\t\tDUK_D(DUK_DPRINT(\"shrink string table: %lu -> %lu\", (unsigned long) heap->st_size, (unsigned long) heap->st_size / 2));\n#if defined(DUK_USE_DEBUG)\n\t\t\tduk_heap_strtable_dump(heap);\n#endif\n\t\t\tduk__strtable_shrink_inplace(heap);\n\t\t}\n\t} else {\n\t\tDUK_DD(DUK_DDPRINT(\"no need for strtable resize\"));\n\t}\n\n\theap->st_resizing = 0;\n}\n#endif  /* DUK__STRTAB_RESIZE_CHECK */\n\n/*\n *  Torture grow/shrink: unconditionally grow and shrink back.\n */\n\n#if defined(DUK_USE_STRTAB_TORTURE) && defined(DUK__STRTAB_RESIZE_CHECK)\nDUK_LOCAL void duk__strtable_resize_torture(duk_heap *heap) {\n\tduk_uint32_t old_st_size;\n\n\tDUK_ASSERT(heap != NULL);\n\n\told_st_size = heap->st_size;\n\tif (old_st_size >= DUK_USE_STRTAB_MAXSIZE) {\n\t\treturn;\n\t}\n\n\theap->st_resizing = 1;\n\tduk__strtable_grow_inplace(heap);\n\tif (heap->st_size > old_st_size) {\n\t\tduk__strtable_shrink_inplace(heap);\n\t}\n\theap->st_resizing = 0;\n}\n#endif  /* DUK_USE_STRTAB_TORTURE && DUK__STRTAB_RESIZE_CHECK */\n\n/*\n *  Raw intern; string already checked not to be present.\n */\n\nDUK_LOCAL duk_hstring *duk__strtable_do_intern(duk_heap *heap, const duk_uint8_t *str, duk_uint32_t blen, duk_uint32_t strhash) {\n\tduk_hstring *res;\n\tconst duk_uint8_t *extdata;\n#if defined(DUK_USE_STRTAB_PTRCOMP)\n\tduk_uint16_t *slot;\n#else\n\tduk_hstring **slot;\n#endif\n\n\tDUK_DDD(DUK_DDDPRINT(\"do_intern: heap=%p, str=%p, blen=%lu, strhash=%lx, st_size=%lu, st_count=%lu, load=%lf\",\n\t                     (void *) heap, (const void *) str, (unsigned long) blen, (unsigned long) strhash,\n\t                     (unsigned long) heap->st_size, (unsigned long) heap->st_count,\n\t                     (double) heap->st_count / (double) heap->st_size));\n\n\tDUK_ASSERT(heap != NULL);\n\n\t/* Prevent any side effects on the string table and the caller provided\n\t * str/blen arguments while interning is in progress.  For example, if\n\t * the caller provided str/blen from a dynamic buffer, a finalizer\n\t * might resize or modify that dynamic buffer, invalidating the call\n\t * arguments.\n\t *\n\t * While finalizers must be prevented, mark-and-sweep itself is fine.\n\t * Recursive string table resize is prevented explicitly here.\n\t */\n\n\theap->pf_prevent_count++;\n\tDUK_ASSERT(heap->pf_prevent_count != 0);  /* Wrap. */\n\n#if defined(DUK_USE_STRTAB_TORTURE) && defined(DUK__STRTAB_RESIZE_CHECK)\n\tduk__strtable_resize_torture(heap);\n#endif\n\n\t/* String table grow/shrink check.  Because of chaining (and no\n\t * accumulation issues as with hash probe chains and DELETED\n\t * markers) there's never a mandatory need to resize right now.\n\t * Check for the resize only periodically, based on st_count\n\t * bit pattern.  Because string table removal doesn't do a shrink\n\t * check, we do that also here.\n\t *\n\t * Do the resize and possible grow/shrink before the new duk_hstring\n\t * has been allocated.  Otherwise we may trigger a GC when the result\n\t * duk_hstring is not yet strongly referenced.\n\t */\n\n#if defined(DUK__STRTAB_RESIZE_CHECK)\n\tif (DUK_UNLIKELY((heap->st_count & DUK_USE_STRTAB_RESIZE_CHECK_MASK) == 0)) {\n\t\tduk__strtable_resize_check(heap);\n\t}\n#endif\n\n\t/* External string check (low memory optimization). */\n\n#if defined(DUK_USE_HSTRING_EXTDATA) && defined(DUK_USE_EXTSTR_INTERN_CHECK)\n\textdata = (const duk_uint8_t *) DUK_USE_EXTSTR_INTERN_CHECK(heap->heap_udata, (void *) DUK_LOSE_CONST(str), (duk_size_t) blen);\n#else\n\textdata = (const duk_uint8_t *) NULL;\n#endif\n\n\t/* Allocate and initialize string, not yet linked.  This may cause a\n\t * GC which may cause other strings to be interned and inserted into\n\t * the string table before we insert our string.  Finalizer execution\n\t * is disabled intentionally to avoid a finalizer from e.g. resizing\n\t * a buffer used as a data area for 'str'.\n\t */\n\n\tres = duk__strtable_alloc_hstring(heap, str, blen, strhash, extdata);\n\n\t/* Allow side effects again: GC must be avoided until duk_hstring\n\t * result (if successful) has been INCREF'd.\n\t */\n\tDUK_ASSERT(heap->pf_prevent_count > 0);\n\theap->pf_prevent_count--;\n\n\t/* Alloc error handling. */\n\n\tif (DUK_UNLIKELY(res == NULL)) {\n#if defined(DUK_USE_HSTRING_EXTDATA) && defined(DUK_USE_EXTSTR_INTERN_CHECK)\n\t\tif (extdata != NULL) {\n\t\t\tDUK_USE_EXTSTR_FREE(heap->heap_udata, (const void *) extdata);\n\t\t}\n#endif\n\t\treturn NULL;\n\t}\n\n\t/* Insert into string table. */\n\n#if defined(DUK_USE_STRTAB_PTRCOMP)\n\tslot = heap->strtable16 + (strhash & heap->st_mask);\n#else\n\tslot = heap->strtable + (strhash & heap->st_mask);\n#endif\n\tDUK_ASSERT(res->hdr.h_next == NULL);  /* This is the case now, but unnecessary zeroing/NULLing. */\n\tres->hdr.h_next = DUK__HEAPPTR_DEC16(heap, *slot);\n\t*slot = DUK__HEAPPTR_ENC16(heap, res);\n\n\t/* Update string count only for successful inserts. */\n\n#if defined(DUK__STRTAB_RESIZE_CHECK)\n\theap->st_count++;\n#endif\n\n\t/* The duk_hstring is in the string table but is not yet strongly\n\t * reachable.  Calling code MUST NOT make any allocations or other\n\t * side effects before the duk_hstring has been INCREF'd and made\n\t * reachable.\n\t */\n\n\treturn res;\n}\n\n/*\n *  Intern a string from str/blen, returning either an existing duk_hstring\n *  or adding a new one into the string table.  The input string does -not-\n *  need to be NUL terminated.\n *\n *  The input 'str' argument may point to a Duktape managed data area such as\n *  the data area of a dynamic buffer.  It's crucial to avoid any side effects\n *  that might affect the data area (e.g. resize the dynamic buffer, or write\n *  to the buffer) before the string is fully interned.\n */\n\n#if defined(DUK_USE_ROM_STRINGS)\nDUK_LOCAL duk_hstring *duk__strtab_romstring_lookup(duk_heap *heap, const duk_uint8_t *str, duk_size_t blen, duk_uint32_t strhash) {\n\tduk_size_t lookup_hash;\n\tduk_hstring *curr;\n\n\tDUK_ASSERT(heap != NULL);\n\tDUK_UNREF(heap);\n\n\tlookup_hash = (blen << 4);\n\tif (blen > 0) {\n\t\tlookup_hash += str[0];\n\t}\n\tlookup_hash &= 0xff;\n\n\tcurr = DUK_LOSE_CONST(duk_rom_strings_lookup[lookup_hash]);\n\twhile (curr != NULL) {\n\t\tif (strhash == DUK_HSTRING_GET_HASH(curr) &&\n\t\t    blen == DUK_HSTRING_GET_BYTELEN(curr) &&\n\t\t    DUK_MEMCMP((const void *) str, (const void *) DUK_HSTRING_GET_DATA(curr), blen) == 0) {\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"intern check: rom string: %!O, computed hash 0x%08lx, rom hash 0x%08lx\",\n\t\t\t                     curr, (unsigned long) strhash, (unsigned long) DUK_HSTRING_GET_HASH(curr)));\n\t\t\treturn curr;\n\t\t}\n\t\tcurr = curr->hdr.h_next;\n\t}\n\n\treturn NULL;\n}\n#endif  /* DUK_USE_ROM_STRINGS */\n\nDUK_INTERNAL duk_hstring *duk_heap_strtable_intern(duk_heap *heap, const duk_uint8_t *str, duk_uint32_t blen) {\n\tduk_uint32_t strhash;\n\tduk_hstring *h;\n\n\tDUK_DDD(DUK_DDDPRINT(\"intern check: heap=%p, str=%p, blen=%lu\", (void *) heap, (const void *) str, (unsigned long) blen));\n\n\t/* Preliminaries. */\n\n\tDUK_ASSERT(heap != NULL);\n\tDUK_ASSERT(blen == 0 || str != NULL);\n\tDUK_ASSERT(blen <= DUK_HSTRING_MAX_BYTELEN);  /* Caller is responsible for ensuring this. */\n\tstrhash = duk_heap_hashstring(heap, str, (duk_size_t) blen);\n\n\t/* String table lookup. */\n\n\tDUK_ASSERT(DUK__GET_STRTABLE(heap) != NULL);\n\tDUK_ASSERT(heap->st_size > 0);\n\tDUK_ASSERT(heap->st_size == heap->st_mask + 1);\n#if defined(DUK_USE_STRTAB_PTRCOMP)\n\th = DUK__HEAPPTR_DEC16(heap, heap->strtable16[strhash & heap->st_mask]);\n#else\n\th = heap->strtable[strhash & heap->st_mask];\n#endif\n\twhile (h != NULL) {\n\t\tif (DUK_HSTRING_GET_HASH(h) == strhash &&\n\t\t    DUK_HSTRING_GET_BYTELEN(h) == blen &&\n\t\t    DUK_MEMCMP((const void *) str, (const void *) DUK_HSTRING_GET_DATA(h), (size_t) blen) == 0) {\n\t\t\t/* Found existing entry. */\n\t\t\tDUK_STATS_INC(heap, stats_strtab_intern_hit);\n\t\t\treturn h;\n\t\t}\n\t\th = h->hdr.h_next;\n\t}\n\n\t/* ROM table lookup.  Because this lookup is slower, do it only after\n\t * RAM lookup.  This works because no ROM string is ever interned into\n\t * the RAM string table.\n\t */\n\n#if defined(DUK_USE_ROM_STRINGS)\n\th = duk__strtab_romstring_lookup(heap, str, blen, strhash);\n\tif (h != NULL) {\n\t\tDUK_STATS_INC(heap, stats_strtab_intern_hit);\n\t\treturn h;\n\t}\n#endif\n\n\t/* Not found in string table; insert. */\n\n\tDUK_STATS_INC(heap, stats_strtab_intern_miss);\n\th = duk__strtable_do_intern(heap, str, blen, strhash);\n\treturn h;  /* may be NULL */\n}\n\n/*\n *  Intern a string from u32.\n */\n\n/* XXX: Could arrange some special handling because we know that the result\n * will have an arridx flag and an ASCII flag, won't need a clen check, etc.\n */\n\nDUK_INTERNAL duk_hstring *duk_heap_strtable_intern_u32(duk_heap *heap, duk_uint32_t val) {\n\tduk_uint8_t buf[DUK__STRTAB_U32_MAX_STRLEN];\n\tduk_uint8_t *p;\n\n\tDUK_ASSERT(heap != NULL);\n\n\t/* This is smaller and faster than a %lu sprintf. */\n\tp = buf + sizeof(buf);\n\tdo {\n\t\tp--;\n\t\t*p = duk_lc_digits[val % 10];\n\t\tval = val / 10;\n\t} while (val != 0);  /* For val == 0, emit exactly one '0'. */\n\tDUK_ASSERT(p >= buf);\n\n\treturn duk_heap_strtable_intern(heap, (const duk_uint8_t *) p, (duk_uint32_t) ((buf + sizeof(buf)) - p));\n}\n\n/*\n *  Checked convenience variants.\n *\n *  XXX: Because the main use case is for the checked variants, make them the\n *  main functionality and provide a safe variant separately (it is only needed\n *  during heap init).  The problem with that is that longjmp state and error\n *  creation must already be possible to throw.\n */\n\nDUK_INTERNAL duk_hstring *duk_heap_strtable_intern_checked(duk_hthread *thr, const duk_uint8_t *str, duk_uint32_t blen) {\n\tduk_hstring *res;\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(thr->heap != NULL);\n\tDUK_ASSERT(blen == 0 || str != NULL);\n\n\tres = duk_heap_strtable_intern(thr->heap, str, blen);\n\tif (DUK_UNLIKELY(res == NULL)) {\n\t\tDUK_ERROR_ALLOC_FAILED(thr);\n\t}\n\treturn res;\n}\n\nDUK_INTERNAL duk_hstring *duk_heap_strtable_intern_u32_checked(duk_hthread *thr, duk_uint32_t val) {\n\tduk_hstring *res;\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(thr->heap != NULL);\n\n\tres = duk_heap_strtable_intern_u32(thr->heap, val);\n\tif (DUK_UNLIKELY(res == NULL)) {\n\t\tDUK_ERROR_ALLOC_FAILED(thr);\n\t}\n\treturn res;\n}\n\n/*\n *  Remove (unlink) a string from the string table.\n *\n *  Just unlinks the duk_hstring, leaving link pointers as garbage.\n *  Caller must free the string itself.\n */\n\n#if defined(DUK_USE_REFERENCE_COUNTING)\n/* Unlink without a 'prev' pointer. */\nDUK_INTERNAL void duk_heap_strtable_unlink(duk_heap *heap, duk_hstring *h) {\n#if defined(DUK_USE_STRTAB_PTRCOMP)\n\tduk_uint16_t *slot;\n#else\n\tduk_hstring **slot;\n#endif\n\tduk_hstring *other;\n\tduk_hstring *prev;\n\n\tDUK_DDD(DUK_DDDPRINT(\"remove: heap=%p, h=%p, blen=%lu, strhash=%lx\",\n\t                     (void *) heap, (void *) h,\n\t                     (unsigned long) (h != NULL ? DUK_HSTRING_GET_BYTELEN(h) : 0),\n\t                     (unsigned long) (h != NULL ? DUK_HSTRING_GET_HASH(h) : 0)));\n\n\tDUK_ASSERT(heap != NULL);\n\tDUK_ASSERT(h != NULL);\n\n#if defined(DUK__STRTAB_RESIZE_CHECK)\n\tDUK_ASSERT(heap->st_count > 0);\n\theap->st_count--;\n#endif\n\n#if defined(DUK_USE_STRTAB_PTRCOMP)\n\tslot = heap->strtable16 + (DUK_HSTRING_GET_HASH(h) & heap->st_mask);\n#else\n\tslot = heap->strtable + (DUK_HSTRING_GET_HASH(h) & heap->st_mask);\n#endif\n\tother = DUK__HEAPPTR_DEC16(heap, *slot);\n\tDUK_ASSERT(other != NULL);  /* At least argument string is in the chain. */\n\n\tprev = NULL;\n\twhile (other != h) {\n\t\tprev = other;\n\t\tother = other->hdr.h_next;\n\t\tDUK_ASSERT(other != NULL);  /* We'll eventually find 'h'. */\n\t}\n\tif (prev != NULL) {\n\t\t/* Middle of list. */\n\t\tprev->hdr.h_next = h->hdr.h_next;\n\t} else {\n\t\t/* Head of list. */\n\t\t*slot = DUK__HEAPPTR_ENC16(heap, h->hdr.h_next);\n\t}\n\n\t/* There's no resize check on a string free.  The next string\n\t * intern will do one.\n\t */\n}\n#endif  /* DUK_USE_REFERENCE_COUNTING */\n\n/* Unlink with a 'prev' pointer. */\nDUK_INTERNAL void duk_heap_strtable_unlink_prev(duk_heap *heap, duk_hstring *h, duk_hstring *prev) {\n#if defined(DUK_USE_STRTAB_PTRCOMP)\n\tduk_uint16_t *slot;\n#else\n\tduk_hstring **slot;\n#endif\n\n\tDUK_DDD(DUK_DDDPRINT(\"remove: heap=%p, prev=%p, h=%p, blen=%lu, strhash=%lx\",\n\t                     (void *) heap, (void *) prev, (void *) h,\n\t                     (unsigned long) (h != NULL ? DUK_HSTRING_GET_BYTELEN(h) : 0),\n\t                     (unsigned long) (h != NULL ? DUK_HSTRING_GET_HASH(h) : 0)));\n\n\tDUK_ASSERT(heap != NULL);\n\tDUK_ASSERT(h != NULL);\n\tDUK_ASSERT(prev == NULL || prev->hdr.h_next == h);\n\n#if defined(DUK__STRTAB_RESIZE_CHECK)\n\tDUK_ASSERT(heap->st_count > 0);\n\theap->st_count--;\n#endif\n\n\tif (prev != NULL) {\n\t\t/* Middle of list. */\n\t\tprev->hdr.h_next = h->hdr.h_next;\n\t} else {\n\t\t/* Head of list. */\n#if defined(DUK_USE_STRTAB_PTRCOMP)\n\t\tslot = heap->strtable16 + (DUK_HSTRING_GET_HASH(h) & heap->st_mask);\n#else\n\t\tslot = heap->strtable + (DUK_HSTRING_GET_HASH(h) & heap->st_mask);\n#endif\n\t\tDUK_ASSERT(DUK__HEAPPTR_DEC16(heap, *slot) == h);\n\t\t*slot = DUK__HEAPPTR_ENC16(heap, h->hdr.h_next);\n\t}\n}\n\n/*\n *  Force string table resize check in mark-and-sweep.\n */\n\nDUK_INTERNAL void duk_heap_strtable_force_resize(duk_heap *heap) {\n\t/* Does only one grow/shrink step if needed.  The heap->st_resizing\n\t * flag protects against recursive resizing.\n\t */\n\n\tDUK_ASSERT(heap != NULL);\n\tDUK_UNREF(heap);\n\n#if defined(DUK__STRTAB_RESIZE_CHECK)\n#if defined(DUK_USE_STRTAB_PTRCOMP)\n\tif (heap->strtable16 != NULL) {\n#else\n\tif (heap->strtable != NULL) {\n#endif\n\t\tduk__strtable_resize_check(heap);\n\t}\n#endif\n}\n\n/*\n *  Free strings in the string table and the string table itself.\n */\n\nDUK_INTERNAL void duk_heap_strtable_free(duk_heap *heap) {\n#if defined(DUK_USE_STRTAB_PTRCOMP)\n\tduk_uint16_t *strtable;\n\tduk_uint16_t *st;\n#else\n\tduk_hstring **strtable;\n\tduk_hstring **st;\n#endif\n\tduk_hstring *h;\n\n\tDUK_ASSERT(heap != NULL);\n\n#if defined(DUK_USE_ASSERTIONS)\n\tduk__strtable_assert_checks(heap);\n#endif\n\n\t/* Strtable can be NULL if heap init fails.  However, in that case\n\t * heap->st_size is 0, so strtable == strtable_end and we skip the\n\t * loop without a special check.\n\t */\n\tstrtable = DUK__GET_STRTABLE(heap);\n\tst = strtable + heap->st_size;\n\tDUK_ASSERT(strtable != NULL || heap->st_size == 0);\n\n\twhile (strtable != st) {\n\t\t--st;\n\t\th = DUK__HEAPPTR_DEC16(heap, *st);\n\t\twhile (h) {\n\t\t\tduk_hstring *h_next;\n\t\t\th_next = h->hdr.h_next;\n\n\t\t\t/* Strings may have inner refs (extdata) in some cases. */\n\t\t\tduk_free_hstring(heap, h);\n\n\t\t\th = h_next;\n\t\t}\n\t}\n\n\tDUK_FREE(heap, strtable);\n}\n\n/* automatic undefs */\n#undef DUK__GET_STRTABLE\n#undef DUK__HEAPPTR_DEC16\n#undef DUK__HEAPPTR_ENC16\n#undef DUK__STRTAB_U32_MAX_STRLEN\n#line 1 \"duk_hobject_alloc.c\"\n/*\n *  Hobject allocation.\n *\n *  Provides primitive allocation functions for all object types (plain object,\n *  compiled function, native function, thread).  The object return is not yet\n *  in \"heap allocated\" list and has a refcount of zero, so caller must careful.\n */\n\n/* XXX: In most cases there's no need for plain allocation without pushing\n * to the value stack.  Maybe rework contract?\n */\n\n/* #include duk_internal.h -> already included */\n\n/*\n *  Helpers.\n */\n\nDUK_LOCAL void duk__init_object_parts(duk_heap *heap, duk_uint_t hobject_flags, duk_hobject *obj) {\n\tDUK_ASSERT(obj != NULL);\n\t/* Zeroed by caller. */\n\n\tobj->hdr.h_flags = hobject_flags | DUK_HTYPE_OBJECT;\n\tDUK_ASSERT(DUK_HEAPHDR_GET_TYPE(&obj->hdr) == DUK_HTYPE_OBJECT);  /* Assume zero shift. */\n\n#if defined(DUK_USE_EXPLICIT_NULL_INIT)\n\tDUK_HOBJECT_SET_PROTOTYPE(heap, obj, NULL);\n\tDUK_HOBJECT_SET_PROPS(heap, obj, NULL);\n#endif\n#if defined(DUK_USE_HEAPPTR16)\n\t/* Zero encoded pointer is required to match NULL. */\n\tDUK_HEAPHDR_SET_NEXT(heap, &obj->hdr, NULL);\n#if defined(DUK_USE_DOUBLE_LINKED_HEAP)\n\tDUK_HEAPHDR_SET_PREV(heap, &obj->hdr, NULL);\n#endif\n#endif\n\tDUK_ASSERT_HEAPHDR_LINKS(heap, &obj->hdr);\n\tDUK_HEAP_INSERT_INTO_HEAP_ALLOCATED(heap, &obj->hdr);\n\n\t/* obj->props is intentionally left as NULL, and duk_hobject_props.c must deal\n\t * with this properly.  This is intentional: empty objects consume a minimum\n\t * amount of memory.  Further, an initial allocation might fail and cause\n\t * 'obj' to \"leak\" (require a mark-and-sweep) since it is not reachable yet.\n\t */\n}\n\nDUK_LOCAL void *duk__hobject_alloc_init(duk_hthread *thr, duk_uint_t hobject_flags, duk_size_t size) {\n\tvoid *res;\n\n\tres = (void *) DUK_ALLOC_CHECKED_ZEROED(thr, size);\n\tDUK_ASSERT(res != NULL);\n\tduk__init_object_parts(thr->heap, hobject_flags, (duk_hobject *) res);\n\treturn res;\n}\n\n/*\n *  Allocate an duk_hobject.\n *\n *  The allocated object has no allocation for properties; the caller may\n *  want to force a resize if a desired size is known.\n *\n *  The allocated object has zero reference count and is not reachable.\n *  The caller MUST make the object reachable and increase its reference\n *  count before invoking any operation that might require memory allocation.\n */\n\nDUK_INTERNAL duk_hobject *duk_hobject_alloc_unchecked(duk_heap *heap, duk_uint_t hobject_flags) {\n\tduk_hobject *res;\n\n\tDUK_ASSERT(heap != NULL);\n\n\t/* different memory layout, alloc size, and init */\n\tDUK_ASSERT((hobject_flags & DUK_HOBJECT_FLAG_COMPFUNC) == 0);\n\tDUK_ASSERT((hobject_flags & DUK_HOBJECT_FLAG_NATFUNC) == 0);\n\tDUK_ASSERT((hobject_flags & DUK_HOBJECT_FLAG_BOUNDFUNC) == 0);\n\n\tres = (duk_hobject *) DUK_ALLOC_ZEROED(heap, sizeof(duk_hobject));\n\tif (DUK_UNLIKELY(res == NULL)) {\n\t\treturn NULL;\n\t}\n\tDUK_ASSERT(!DUK_HOBJECT_IS_THREAD(res));\n\n\tduk__init_object_parts(heap, hobject_flags, res);\n\n\tDUK_ASSERT(!DUK_HOBJECT_IS_THREAD(res));\n\treturn res;\n}\n\nDUK_INTERNAL duk_hobject *duk_hobject_alloc(duk_hthread *thr, duk_uint_t hobject_flags) {\n\tduk_hobject *res;\n\n\tres = (duk_hobject *) duk__hobject_alloc_init(thr, hobject_flags, sizeof(duk_hobject));\n\treturn res;\n}\n\nDUK_INTERNAL duk_hcompfunc *duk_hcompfunc_alloc(duk_hthread *thr, duk_uint_t hobject_flags) {\n\tduk_hcompfunc *res;\n\n\tres = (duk_hcompfunc *) duk__hobject_alloc_init(thr, hobject_flags, sizeof(duk_hcompfunc));\n#if defined(DUK_USE_EXPLICIT_NULL_INIT)\n#if defined(DUK_USE_HEAPPTR16)\n\t/* NULL pointer is required to encode to zero, so memset is enough. */\n#else\n\tres->data = NULL;\n\tres->funcs = NULL;\n\tres->bytecode = NULL;\n#endif\n\tres->lex_env = NULL;\n\tres->var_env = NULL;\n#endif\n\n\treturn res;\n}\n\nDUK_INTERNAL duk_hnatfunc *duk_hnatfunc_alloc(duk_hthread *thr, duk_uint_t hobject_flags) {\n\tduk_hnatfunc *res;\n\n\tres = (duk_hnatfunc *) duk__hobject_alloc_init(thr, hobject_flags, sizeof(duk_hnatfunc));\n#if defined(DUK_USE_EXPLICIT_NULL_INIT)\n\tres->func = NULL;\n#endif\n\n\treturn res;\n}\n\nDUK_INTERNAL duk_hboundfunc *duk_hboundfunc_alloc(duk_heap *heap, duk_uint_t hobject_flags) {\n\tduk_hboundfunc *res;\n\n\tres = (duk_hboundfunc *) DUK_ALLOC(heap, sizeof(duk_hboundfunc));\n\tif (!res) {\n\t\treturn NULL;\n\t}\n\tDUK_MEMZERO(res, sizeof(duk_hboundfunc));\n\n\tduk__init_object_parts(heap, hobject_flags, &res->obj);\n\n\tDUK_TVAL_SET_UNDEFINED(&res->target);\n\tDUK_TVAL_SET_UNDEFINED(&res->this_binding);\n\n#if defined(DUK_USE_EXPLICIT_NULL_INIT)\n\tres->args = NULL;\n#endif\n\n\treturn res;\n}\n\n#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)\nDUK_INTERNAL duk_hbufobj *duk_hbufobj_alloc(duk_hthread *thr, duk_uint_t hobject_flags) {\n\tduk_hbufobj *res;\n\n\tres = (duk_hbufobj *) duk__hobject_alloc_init(thr, hobject_flags, sizeof(duk_hbufobj));\n#if defined(DUK_USE_EXPLICIT_NULL_INIT)\n\tres->buf = NULL;\n\tres->buf_prop = NULL;\n#endif\n\n\tDUK_ASSERT_HBUFOBJ_VALID(res);\n\treturn res;\n}\n#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */\n\n/* Allocate a new thread.\n *\n * Leaves the built-ins array uninitialized.  The caller must either\n * initialize a new global context or share existing built-ins from\n * another thread.\n */\nDUK_INTERNAL duk_hthread *duk_hthread_alloc_unchecked(duk_heap *heap, duk_uint_t hobject_flags) {\n\tduk_hthread *res;\n\n\tres = (duk_hthread *) DUK_ALLOC(heap, sizeof(duk_hthread));\n\tif (DUK_UNLIKELY(res == NULL)) {\n\t\treturn NULL;\n\t}\n\tDUK_MEMZERO(res, sizeof(duk_hthread));\n\n\tduk__init_object_parts(heap, hobject_flags, &res->obj);\n\n#if defined(DUK_USE_EXPLICIT_NULL_INIT)\n\tres->ptr_curr_pc = NULL;\n\tres->heap = NULL;\n\tres->valstack = NULL;\n\tres->valstack_end = NULL;\n\tres->valstack_alloc_end = NULL;\n\tres->valstack_bottom = NULL;\n\tres->valstack_top = NULL;\n\tres->callstack_curr = NULL;\n\tres->resumer = NULL;\n\tres->compile_ctx = NULL,\n#if defined(DUK_USE_HEAPPTR16)\n\tres->strs16 = NULL;\n#else\n\tres->strs = NULL;\n#endif\n\t{\n\t\tduk_small_uint_t i;\n\t\tfor (i = 0; i < DUK_NUM_BUILTINS; i++) {\n\t\t\tres->builtins[i] = NULL;\n\t\t}\n\t}\n#endif\n\t/* When nothing is running, API calls are in non-strict mode. */\n\tDUK_ASSERT(res->strict == 0);\n\n\tres->heap = heap;\n\n\t/* XXX: Any reason not to merge duk_hthread_alloc.c here? */\n\treturn res;\n}\n\nDUK_INTERNAL duk_hthread *duk_hthread_alloc(duk_hthread *thr, duk_uint_t hobject_flags) {\n\tduk_hthread *res;\n\n\tres = duk_hthread_alloc_unchecked(thr->heap, hobject_flags);\n\tif (res == NULL) {\n\t\tDUK_ERROR_ALLOC_FAILED(thr);\n\t}\n\treturn res;\n}\n\nDUK_INTERNAL duk_harray *duk_harray_alloc(duk_hthread *thr, duk_uint_t hobject_flags) {\n\tduk_harray *res;\n\n\tres = (duk_harray *) duk__hobject_alloc_init(thr, hobject_flags, sizeof(duk_harray));\n\n\tDUK_ASSERT(res->length == 0);\n\n\treturn res;\n}\n\nDUK_INTERNAL duk_hdecenv *duk_hdecenv_alloc(duk_hthread *thr, duk_uint_t hobject_flags) {\n\tduk_hdecenv *res;\n\n\tres = (duk_hdecenv *) duk__hobject_alloc_init(thr, hobject_flags, sizeof(duk_hdecenv));\n#if defined(DUK_USE_EXPLICIT_NULL_INIT)\n\tres->thread = NULL;\n\tres->varmap = NULL;\n#endif\n\n\tDUK_ASSERT(res->thread == NULL);\n\tDUK_ASSERT(res->varmap == NULL);\n\tDUK_ASSERT(res->regbase_byteoff == 0);\n\n\treturn res;\n}\n\nDUK_INTERNAL duk_hobjenv *duk_hobjenv_alloc(duk_hthread *thr, duk_uint_t hobject_flags) {\n\tduk_hobjenv *res;\n\n\tres = (duk_hobjenv *) duk__hobject_alloc_init(thr, hobject_flags, sizeof(duk_hobjenv));\n#if defined(DUK_USE_EXPLICIT_NULL_INIT)\n\tres->target = NULL;\n#endif\n\n\tDUK_ASSERT(res->target == NULL);\n\n\treturn res;\n}\n\nDUK_INTERNAL duk_hproxy *duk_hproxy_alloc(duk_hthread *thr, duk_uint_t hobject_flags) {\n\tduk_hproxy *res;\n\n\tres = (duk_hproxy *) duk__hobject_alloc_init(thr, hobject_flags, sizeof(duk_hproxy));\n\n\t/* Leave ->target and ->handler uninitialized, as caller will always\n\t * explicitly initialize them before any side effects are possible.\n\t */\n\n\treturn res;\n}\n#line 1 \"duk_hobject_enum.c\"\n/*\n *  Object enumeration support.\n *\n *  Creates an internal enumeration state object to be used e.g. with for-in\n *  enumeration.  The state object contains a snapshot of target object keys\n *  and internal control state for enumeration.  Enumerator flags allow caller\n *  to e.g. request internal/non-enumerable properties, and to enumerate only\n *  \"own\" properties.\n *\n *  Also creates the result value for e.g. Object.keys() based on the same\n *  internal structure.\n *\n *  This snapshot-based enumeration approach is used to simplify enumeration:\n *  non-snapshot-based approaches are difficult to reconcile with mutating\n *  the enumeration target, running multiple long-lived enumerators at the\n *  same time, garbage collection details, etc.  The downside is that the\n *  enumerator object is memory inefficient especially for iterating arrays.\n */\n\n/* #include duk_internal.h -> already included */\n\n/* XXX: identify enumeration target with an object index (not top of stack) */\n\n/* First enumerated key index in enumerator object, must match exactly the\n * number of control properties inserted to the enumerator.\n */\n#define DUK__ENUM_START_INDEX  2\n\n/* Current implementation suffices for ES2015 for now because there's no symbol\n * sorting, so commented out for now.\n */\n\n/*\n *  Helper to sort enumeration keys using a callback for pairwise duk_hstring\n *  comparisons.  The keys are in the enumeration object entry part, starting\n *  from DUK__ENUM_START_INDEX, and the entry part is dense.  Entry part values\n *  are all \"true\", e.g. \"1\" -> true, \"3\" -> true, \"foo\" -> true, \"2\" -> true,\n *  so it suffices to just switch keys without switching values.\n *\n *  ES2015 [[OwnPropertyKeys]] enumeration order for ordinary objects:\n *  (1) array indices in ascending order,\n *  (2) non-array-index keys in insertion order, and\n *  (3) symbols in insertion order.\n *  http://www.ecma-international.org/ecma-262/6.0/#sec-ordinary-object-internal-methods-and-internal-slots-ownpropertykeys.\n *\n *  This rule is applied to \"own properties\" at each inheritance level;\n *  non-duplicate parent keys always follow child keys.  For example,\n *  an inherited array index will enumerate -after- a symbol in the\n *  child.\n *\n *  Insertion sort is used because (1) it's simple and compact, (2) works\n *  in-place, (3) minimizes operations if data is already nearly sorted,\n *  (4) doesn't reorder elements considered equal.\n *  http://en.wikipedia.org/wiki/Insertion_sort\n */\n\n/* Sort key, must hold array indices, \"not array index\" marker, and one more\n * higher value for symbols.\n */\n#if !defined(DUK_USE_SYMBOL_BUILTIN)\ntypedef duk_uint32_t duk__sort_key_t;\n#elif defined(DUK_USE_64BIT_OPS)\ntypedef duk_uint64_t duk__sort_key_t;\n#else\ntypedef duk_double_t duk__sort_key_t;\n#endif\n\n/* Get sort key for a duk_hstring. */\nDUK_LOCAL duk__sort_key_t duk__hstring_sort_key(duk_hstring *x) {\n\tduk__sort_key_t val;\n\n\t/* For array indices [0,0xfffffffe] use the array index as is.\n\t * For strings, use 0xffffffff, the marker 'arridx' already in\n\t * duk_hstring.  For symbols, any value above 0xffffffff works,\n\t * as long as it is the same for all symbols; currently just add\n\t * the masked flag field into the arridx temporary.\n\t */\n\tDUK_ASSERT(x != NULL);\n\tDUK_ASSERT(!DUK_HSTRING_HAS_SYMBOL(x) || DUK_HSTRING_GET_ARRIDX_FAST(x) == DUK_HSTRING_NO_ARRAY_INDEX);\n\n\tval = (duk__sort_key_t) DUK_HSTRING_GET_ARRIDX_FAST(x);\n\n#if defined(DUK_USE_SYMBOL_BUILTIN)\n\tval = val + (duk__sort_key_t) (DUK_HEAPHDR_GET_FLAGS_RAW((duk_heaphdr *) x) & DUK_HSTRING_FLAG_SYMBOL);\n#endif\n\n\treturn (duk__sort_key_t) val;\n}\n\n/* Insert element 'b' after element 'a'? */\nDUK_LOCAL duk_bool_t duk__sort_compare_es6(duk_hstring *a, duk_hstring *b, duk__sort_key_t val_b) {\n\tduk__sort_key_t val_a;\n\n\tDUK_ASSERT(a != NULL);\n\tDUK_ASSERT(b != NULL);\n\tDUK_UNREF(b);  /* Not actually needed now, val_b suffices. */\n\n\tval_a = duk__hstring_sort_key(a);\n\n\tif (val_a > val_b) {\n\t\treturn 0;\n\t} else {\n\t\treturn 1;\n\t}\n}\n\nDUK_LOCAL void duk__sort_enum_keys_es6(duk_hthread *thr, duk_hobject *h_obj, duk_int_fast32_t idx_start, duk_int_fast32_t idx_end) {\n\tduk_hstring **keys;\n\tduk_int_fast32_t idx;\n\n\tDUK_ASSERT(h_obj != NULL);\n\tDUK_ASSERT(idx_start >= DUK__ENUM_START_INDEX);\n\tDUK_ASSERT(idx_end >= idx_start);\n\tDUK_UNREF(thr);\n\n\tif (idx_end <= idx_start + 1) {\n\t\treturn;  /* Zero or one element(s). */\n\t}\n\n\tkeys = DUK_HOBJECT_E_GET_KEY_BASE(thr->heap, h_obj);\n\n\tfor (idx = idx_start + 1; idx < idx_end; idx++) {\n\t\tduk_hstring *h_curr;\n\t\tduk_int_fast32_t idx_insert;\n\t\tduk__sort_key_t val_curr;\n\n\t\th_curr = keys[idx];\n\t\tDUK_ASSERT(h_curr != NULL);\n\n\t\t/* Scan backwards for insertion place.  This works very well\n\t\t * when the elements are nearly in order which is the common\n\t\t * (and optimized for) case.\n\t\t */\n\n\t\tval_curr = duk__hstring_sort_key(h_curr);  /* Remains same during scanning. */\n\t\tfor (idx_insert = idx - 1; idx_insert >= idx_start; idx_insert--) {\n\t\t\tduk_hstring *h_insert;\n\t\t\th_insert = keys[idx_insert];\n\t\t\tDUK_ASSERT(h_insert != NULL);\n\n\t\t\tif (duk__sort_compare_es6(h_insert, h_curr, val_curr)) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\t/* If we're out of indices, idx_insert == idx_start - 1 and idx_insert++\n\t\t * brings us back to idx_start.\n\t\t */\n\t\tidx_insert++;\n\t\tDUK_ASSERT(idx_insert >= 0 && idx_insert <= idx);\n\n\t\t/*        .-- p_insert   .-- p_curr\n\t\t *        v              v\n\t\t *  | ... | insert | ... | curr\n\t\t */\n\n\t\t/* This could also done when the keys are in order, i.e.\n\t\t * idx_insert == idx.  The result would be an unnecessary\n\t\t * memmove() but we use an explicit check because the keys\n\t\t * are very often in order already.\n\t\t */\n\t\tif (idx != idx_insert) {\n\t\t\tDUK_MEMMOVE((void *) (keys + idx_insert + 1),\n\t\t\t            (const void *) (keys + idx_insert),\n\t\t\t            ((size_t) (idx - idx_insert) * sizeof(duk_hstring *)));\n\t\t\tkeys[idx_insert] = h_curr;\n\t\t}\n\t}\n}\n\n/*\n *  Create an internal enumerator object E, which has its keys ordered\n *  to match desired enumeration ordering.  Also initialize internal control\n *  properties for enumeration.\n *\n *  Note: if an array was used to hold enumeration keys instead, an array\n *  scan would be needed to eliminate duplicates found in the prototype chain.\n */\n\nDUK_LOCAL void duk__add_enum_key(duk_hthread *thr, duk_hstring *k) {\n\t/* 'k' may be unreachable on entry so must push without any\n\t * potential for GC.\n\t */\n\tduk_push_hstring(thr, k);\n\tduk_push_true(thr);\n\tduk_put_prop(thr, -3);\n}\n\nDUK_LOCAL void duk__add_enum_key_stridx(duk_hthread *thr, duk_small_uint_t stridx) {\n\tduk__add_enum_key(thr, DUK_HTHREAD_GET_STRING(thr, stridx));\n}\n\nDUK_INTERNAL void duk_hobject_enumerator_create(duk_hthread *thr, duk_small_uint_t enum_flags) {\n\tduk_hobject *enum_target;\n\tduk_hobject *curr;\n\tduk_hobject *res;\n#if defined(DUK_USE_ES6_PROXY)\n\tduk_hobject *h_proxy_target;\n\tduk_hobject *h_proxy_handler;\n\tduk_hobject *h_trap_result;\n#endif\n\tduk_uint_fast32_t i, len;  /* used for array, stack, and entry indices */\n\tduk_uint_fast32_t sort_start_index;\n\n\tDUK_ASSERT(thr != NULL);\n\n\tenum_target = duk_require_hobject(thr, -1);\n\tDUK_ASSERT(enum_target != NULL);\n\n\tduk_push_bare_object(thr);\n\tres = duk_known_hobject(thr, -1);\n\n\t/* [enum_target res] */\n\n\t/* Target must be stored so that we can recheck whether or not\n\t * keys still exist when we enumerate.  This is not done if the\n\t * enumeration result comes from a proxy trap as there is no\n\t * real object to check against.\n\t */\n\tduk_push_hobject(thr, enum_target);\n\tduk_put_prop_stridx_short(thr, -2, DUK_STRIDX_INT_TARGET);\n\n\t/* Initialize index so that we skip internal control keys. */\n\tduk_push_int(thr, DUK__ENUM_START_INDEX);\n\tduk_put_prop_stridx_short(thr, -2, DUK_STRIDX_INT_NEXT);\n\n\t/*\n\t *  Proxy object handling\n\t */\n\n#if defined(DUK_USE_ES6_PROXY)\n\tif (DUK_LIKELY((enum_flags & DUK_ENUM_NO_PROXY_BEHAVIOR) != 0)) {\n\t\tgoto skip_proxy;\n\t}\n\tif (DUK_LIKELY(!duk_hobject_proxy_check(enum_target,\n\t                                        &h_proxy_target,\n\t                                        &h_proxy_handler))) {\n\t\tgoto skip_proxy;\n\t}\n\n\t/* XXX: share code with Object.keys() Proxy handling */\n\n\t/* In ES2015 for-in invoked the \"enumerate\" trap; in ES2016 \"enumerate\"\n\t * has been obsoleted and \"ownKeys\" is used instead.\n\t */\n\tDUK_DDD(DUK_DDDPRINT(\"proxy enumeration\"));\n\tduk_push_hobject(thr, h_proxy_handler);\n\tif (!duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_OWN_KEYS)) {\n\t\t/* No need to replace the 'enum_target' value in stack, only the\n\t\t * enum_target reference.  This also ensures that the original\n\t\t * enum target is reachable, which keeps the proxy and the proxy\n\t\t * target reachable.  We do need to replace the internal _Target.\n\t\t */\n\t\tDUK_DDD(DUK_DDDPRINT(\"no ownKeys trap, enumerate proxy target instead\"));\n\t\tDUK_DDD(DUK_DDDPRINT(\"h_proxy_target=%!O\", (duk_heaphdr *) h_proxy_target));\n\t\tenum_target = h_proxy_target;\n\n\t\tduk_push_hobject(thr, enum_target);  /* -> [ ... enum_target res handler undefined target ] */\n\t\tduk_put_prop_stridx_short(thr, -4, DUK_STRIDX_INT_TARGET);\n\n\t\tduk_pop_2(thr);  /* -> [ ... enum_target res ] */\n\t\tgoto skip_proxy;\n\t}\n\n\t/* [ ... enum_target res handler trap ] */\n\tduk_insert(thr, -2);\n\tduk_push_hobject(thr, h_proxy_target);    /* -> [ ... enum_target res trap handler target ] */\n\tduk_call_method(thr, 1 /*nargs*/);        /* -> [ ... enum_target res trap_result ] */\n\th_trap_result = duk_require_hobject(thr, -1);\n\tDUK_UNREF(h_trap_result);\n\n\tduk_proxy_ownkeys_postprocess(thr, h_proxy_target, enum_flags);\n\t/* -> [ ... enum_target res trap_result keys_array ] */\n\n\t/* Copy cleaned up trap result keys into the enumerator object. */\n\t/* XXX: result is a dense array; could make use of that. */\n\tDUK_ASSERT(duk_is_array(thr, -1));\n\tlen = (duk_uint_fast32_t) duk_get_length(thr, -1);\n\tfor (i = 0; i < len; i++) {\n\t\t(void) duk_get_prop_index(thr, -1, (duk_uarridx_t) i);\n\t\tDUK_ASSERT(duk_is_string(thr, -1));  /* postprocess cleaned up */\n\t\t/* [ ... enum_target res trap_result keys_array val ] */\n\t\tduk_push_true(thr);\n\t\t/* [ ... enum_target res trap_result keys_array val true ] */\n\t\tduk_put_prop(thr, -5);\n\t}\n\t/* [ ... enum_target res trap_result keys_array ] */\n\tduk_pop_2(thr);\n\tduk_remove_m2(thr);\n\n\t/* [ ... res ] */\n\n\t/* The internal _Target property is kept pointing to the original\n\t * enumeration target (the proxy object), so that the enumerator\n\t * 'next' operation can read property values if so requested.  The\n\t * fact that the _Target is a proxy disables key existence check\n\t * during enumeration.\n\t */\n\tDUK_DDD(DUK_DDDPRINT(\"proxy enumeration, final res: %!O\", (duk_heaphdr *) res));\n\tgoto compact_and_return;\n\n skip_proxy:\n#endif  /* DUK_USE_ES6_PROXY */\n\n\tcurr = enum_target;\n\tsort_start_index = DUK__ENUM_START_INDEX;\n\tDUK_ASSERT(DUK_HOBJECT_GET_ENEXT(res) == DUK__ENUM_START_INDEX);\n\twhile (curr) {\n\t\tduk_uint_fast32_t sort_end_index;\n#if !defined(DUK_USE_PREFER_SIZE)\n\t\tduk_bool_t need_sort = 0;\n#endif\n\n\t\t/* Enumeration proceeds by inheritance level.  Virtual\n\t\t * properties need to be handled specially, followed by\n\t\t * array part, and finally entry part.\n\t\t *\n\t\t * If there are array index keys in the entry part or any\n\t\t * other risk of the ES2015 [[OwnPropertyKeys]] order being\n\t\t * violated, need_sort is set and an explicit ES2015 sort is\n\t\t * done for the inheritance level.\n\t\t */\n\n\t\t/* XXX: inheriting from proxy */\n\n\t\t/*\n\t\t *  Virtual properties.\n\t\t *\n\t\t *  String and buffer indices are virtual and always enumerable,\n\t\t *  'length' is virtual and non-enumerable.  Array and arguments\n\t\t *  object props have special behavior but are concrete.\n\t\t *\n\t\t *  String and buffer objects don't have an array part so as long\n\t\t *  as virtual array index keys are enumerated first, we don't\n\t\t *  need to set need_sort.\n\t\t */\n\n#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)\n\t\tif (DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(curr) || DUK_HOBJECT_IS_BUFOBJ(curr)) {\n#else\n\t\tif (DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(curr)) {\n#endif\n\t\t\tduk_bool_t have_length = 1;\n\n\t\t\t/* String and buffer enumeration behavior is identical now,\n\t\t\t * so use shared handler.\n\t\t\t */\n\t\t\tif (DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(curr)) {\n\t\t\t\tduk_hstring *h_val;\n\t\t\t\th_val = duk_hobject_get_internal_value_string(thr->heap, curr);\n\t\t\t\tDUK_ASSERT(h_val != NULL);  /* string objects must not created without internal value */\n\t\t\t\tlen = (duk_uint_fast32_t) DUK_HSTRING_GET_CHARLEN(h_val);\n\t\t\t}\n#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)\n\t\t\telse {\n\t\t\t\tduk_hbufobj *h_bufobj;\n\t\t\t\tDUK_ASSERT(DUK_HOBJECT_IS_BUFOBJ(curr));\n\t\t\t\th_bufobj = (duk_hbufobj *) curr;\n\n\t\t\t\tif (h_bufobj == NULL || !h_bufobj->is_typedarray) {\n\t\t\t\t\t/* Zero length seems like a good behavior for neutered buffers.\n\t\t\t\t\t * ArrayBuffer (non-view) and DataView don't have index properties\n\t\t\t\t\t * or .length property.\n\t\t\t\t\t */\n\t\t\t\t\tlen = 0;\n\t\t\t\t\thave_length = 0;\n\t\t\t\t} else {\n\t\t\t\t\t/* There's intentionally no check for\n\t\t\t\t\t * current underlying buffer length.\n\t\t\t\t\t */\n\t\t\t\t\tlen = (duk_uint_fast32_t) (h_bufobj->length >> h_bufobj->shift);\n\t\t\t\t}\n\t\t\t}\n#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */\n\n\t\t\tfor (i = 0; i < len; i++) {\n\t\t\t\tduk_hstring *k;\n\n\t\t\t\t/* This is a bit fragile: the string is not\n\t\t\t\t * reachable until it is pushed by the helper.\n\t\t\t\t */\n\t\t\t\tk = duk_heap_strtable_intern_u32_checked(thr, (duk_uint32_t) i);\n\t\t\t\tDUK_ASSERT(k);\n\n\t\t\t\tduk__add_enum_key(thr, k);\n\n\t\t\t\t/* [enum_target res] */\n\t\t\t}\n\n\t\t\t/* 'length' and other virtual properties are not\n\t\t\t * enumerable, but are included if non-enumerable\n\t\t\t * properties are requested.\n\t\t\t */\n\n\t\t\tif (have_length && (enum_flags & DUK_ENUM_INCLUDE_NONENUMERABLE)) {\n\t\t\t\tduk__add_enum_key_stridx(thr, DUK_STRIDX_LENGTH);\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t *  Array part\n\t\t */\n\n\t\tfor (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ASIZE(curr); i++) {\n\t\t\tduk_hstring *k;\n\t\t\tduk_tval *tv;\n\n\t\t\ttv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, curr, i);\n\t\t\tif (DUK_TVAL_IS_UNUSED(tv)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tk = duk_heap_strtable_intern_u32_checked(thr, (duk_uint32_t) i);  /* Fragile reachability. */\n\t\t\tDUK_ASSERT(k);\n\n\t\t\tduk__add_enum_key(thr, k);\n\n\t\t\t/* [enum_target res] */\n\t\t}\n\n\t\tif (DUK_HOBJECT_HAS_EXOTIC_ARRAY(curr)) {\n\t\t\t/* Array .length comes after numeric indices. */\n\t\t\tif (enum_flags & DUK_ENUM_INCLUDE_NONENUMERABLE) {\n\t\t\t\tduk__add_enum_key_stridx(thr, DUK_STRIDX_LENGTH);\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t *  Entries part\n\t\t */\n\n\t\tfor (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(curr); i++) {\n\t\t\tduk_hstring *k;\n\n\t\t\tk = DUK_HOBJECT_E_GET_KEY(thr->heap, curr, i);\n\t\t\tif (!k) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (!(enum_flags & DUK_ENUM_INCLUDE_NONENUMERABLE) &&\n\t\t\t    !DUK_HOBJECT_E_SLOT_IS_ENUMERABLE(thr->heap, curr, i)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(k))) {\n\t\t\t\tif (!(enum_flags & DUK_ENUM_INCLUDE_HIDDEN) &&\n\t\t\t\t    DUK_HSTRING_HAS_HIDDEN(k)) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (!(enum_flags & DUK_ENUM_INCLUDE_SYMBOLS)) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n#if !defined(DUK_USE_PREFER_SIZE)\n\t\t\t\tneed_sort = 1;\n#endif\n\t\t\t} else {\n\t\t\t\tDUK_ASSERT(!DUK_HSTRING_HAS_HIDDEN(k));  /* would also have symbol flag */\n\t\t\t\tif (enum_flags & DUK_ENUM_EXCLUDE_STRINGS) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (DUK_HSTRING_HAS_ARRIDX(k)) {\n\t\t\t\t/* This in currently only possible if the\n\t\t\t\t * object has no array part: the array part\n\t\t\t\t * is exhaustive when it is present.\n\t\t\t\t */\n#if !defined(DUK_USE_PREFER_SIZE)\n\t\t\t\tneed_sort = 1;\n#endif\n\t\t\t} else {\n\t\t\t\tif (enum_flags & DUK_ENUM_ARRAY_INDICES_ONLY) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tDUK_ASSERT(DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, curr, i) ||\n\t\t\t           !DUK_TVAL_IS_UNUSED(&DUK_HOBJECT_E_GET_VALUE_PTR(thr->heap, curr, i)->v));\n\n\t\t\tduk__add_enum_key(thr, k);\n\n\t\t\t/* [enum_target res] */\n\t\t}\n\n\t\t/* Sort enumerated keys according to ES2015 requirements for\n\t\t * the \"inheritance level\" just processed.  This is far from\n\t\t * optimal, ES2015 semantics could be achieved more efficiently\n\t\t * by handling array index string keys (and symbol keys)\n\t\t * specially above in effect doing the sort inline.\n\t\t *\n\t\t * Skip the sort if array index sorting is requested because\n\t\t * we must consider all keys, also inherited, so an explicit\n\t\t * sort is done for the whole result after we're done with the\n\t\t * prototype chain.\n\t\t *\n\t\t * Also skip the sort if need_sort == 0, i.e. we know for\n\t\t * certain that the enumerated order is already correct.\n\t\t */\n\t\tsort_end_index = DUK_HOBJECT_GET_ENEXT(res);\n\n\t\tif (!(enum_flags & DUK_ENUM_SORT_ARRAY_INDICES)) {\n#if defined(DUK_USE_PREFER_SIZE)\n\t\t\tduk__sort_enum_keys_es6(thr, res, (duk_int_fast32_t) sort_start_index, (duk_int_fast32_t) sort_end_index);\n#else\n\t\t\tif (need_sort) {\n\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"need to sort\"));\n\t\t\t\tduk__sort_enum_keys_es6(thr, res, (duk_int_fast32_t) sort_start_index, (duk_int_fast32_t) sort_end_index);\n\t\t\t} else {\n\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"no need to sort\"));\n\t\t\t}\n#endif\n\t\t}\n\n\t\tsort_start_index = sort_end_index;\n\n\t\tif (enum_flags & DUK_ENUM_OWN_PROPERTIES_ONLY) {\n\t\t\tbreak;\n\t\t}\n\n\t\tcurr = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, curr);\n\t}\n\n\t/* [enum_target res] */\n\n\tduk_remove_m2(thr);\n\n\t/* [res] */\n\n\tif (enum_flags & DUK_ENUM_SORT_ARRAY_INDICES) {\n\t\t/* Some E5/E5.1 algorithms require that array indices are iterated\n\t\t * in a strictly ascending order.  This is the case for e.g.\n\t\t * Array.prototype.forEach() and JSON.stringify() PropertyList\n\t\t * handling.  The caller can request an explicit sort in these\n\t\t * cases.\n\t\t */\n\n\t\t/* Sort to ES2015 order which works for pure array incides but\n\t\t * also for mixed keys.\n\t\t */\n\t\tduk__sort_enum_keys_es6(thr, res, (duk_int_fast32_t) DUK__ENUM_START_INDEX, (duk_int_fast32_t) DUK_HOBJECT_GET_ENEXT(res));\n\t}\n\n#if defined(DUK_USE_ES6_PROXY)\n compact_and_return:\n#endif\n\t/* compact; no need to seal because object is internal */\n\tduk_hobject_compact_props(thr, res);\n\n\tDUK_DDD(DUK_DDDPRINT(\"created enumerator object: %!iT\", (duk_tval *) duk_get_tval(thr, -1)));\n}\n\n/*\n *  Returns non-zero if a key and/or value was enumerated, and:\n *\n *   [enum] -> [key]        (get_value == 0)\n *   [enum] -> [key value]  (get_value == 1)\n *\n *  Returns zero without pushing anything on the stack otherwise.\n */\nDUK_INTERNAL duk_bool_t duk_hobject_enumerator_next(duk_hthread *thr, duk_bool_t get_value) {\n\tduk_hobject *e;\n\tduk_hobject *enum_target;\n\tduk_hstring *res = NULL;\n\tduk_uint_fast32_t idx;\n\tduk_bool_t check_existence;\n\n\tDUK_ASSERT(thr != NULL);\n\n\t/* [... enum] */\n\n\te = duk_require_hobject(thr, -1);\n\n\t/* XXX use get tval ptr, more efficient */\n\tduk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INT_NEXT);\n\tidx = (duk_uint_fast32_t) duk_require_uint(thr, -1);\n\tduk_pop(thr);\n\tDUK_DDD(DUK_DDDPRINT(\"enumeration: index is: %ld\", (long) idx));\n\n\t/* Enumeration keys are checked against the enumeration target (to see\n\t * that they still exist).  In the proxy enumeration case _Target will\n\t * be the proxy, and checking key existence against the proxy is not\n\t * required (or sensible, as the keys may be fully virtual).\n\t */\n\tduk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INT_TARGET);\n\tenum_target = duk_require_hobject(thr, -1);\n\tDUK_ASSERT(enum_target != NULL);\n#if defined(DUK_USE_ES6_PROXY)\n\tcheck_existence = (!DUK_HOBJECT_IS_PROXY(enum_target));\n#else\n\tcheck_existence = 1;\n#endif\n\tduk_pop(thr);  /* still reachable */\n\n\tDUK_DDD(DUK_DDDPRINT(\"getting next enum value, enum_target=%!iO, enumerator=%!iT\",\n\t                     (duk_heaphdr *) enum_target, (duk_tval *) duk_get_tval(thr, -1)));\n\n\t/* no array part */\n\tfor (;;) {\n\t\tduk_hstring *k;\n\n\t\tif (idx >= DUK_HOBJECT_GET_ENEXT(e)) {\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"enumeration: ran out of elements\"));\n\t\t\tbreak;\n\t\t}\n\n\t\t/* we know these because enum objects are internally created */\n\t\tk = DUK_HOBJECT_E_GET_KEY(thr->heap, e, idx);\n\t\tDUK_ASSERT(k != NULL);\n\t\tDUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, e, idx));\n\t\tDUK_ASSERT(!DUK_TVAL_IS_UNUSED(&DUK_HOBJECT_E_GET_VALUE(thr->heap, e, idx).v));\n\n\t\tidx++;\n\n\t\t/* recheck that the property still exists */\n\t\tif (check_existence && !duk_hobject_hasprop_raw(thr, enum_target, k)) {\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"property deleted during enumeration, skip\"));\n\t\t\tcontinue;\n\t\t}\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"enumeration: found element, key: %!O\", (duk_heaphdr *) k));\n\t\tres = k;\n\t\tbreak;\n\t}\n\n\tDUK_DDD(DUK_DDDPRINT(\"enumeration: updating next index to %ld\", (long) idx));\n\n\tduk_push_u32(thr, (duk_uint32_t) idx);\n\tduk_put_prop_stridx_short(thr, -2, DUK_STRIDX_INT_NEXT);\n\n\t/* [... enum] */\n\n\tif (res) {\n\t\tduk_push_hstring(thr, res);\n\t\tif (get_value) {\n\t\t\tduk_push_hobject(thr, enum_target);\n\t\t\tduk_dup_m2(thr);       /* -> [... enum key enum_target key] */\n\t\t\tduk_get_prop(thr, -2); /* -> [... enum key enum_target val] */\n\t\t\tduk_remove_m2(thr);    /* -> [... enum key val] */\n\t\t\tduk_remove(thr, -3);   /* -> [... key val] */\n\t\t} else {\n\t\t\tduk_remove_m2(thr);    /* -> [... key] */\n\t\t}\n\t\treturn 1;\n\t} else {\n\t\tduk_pop(thr);  /* -> [...] */\n\t\treturn 0;\n\t}\n}\n\n/*\n *  Get enumerated keys in an Ecmascript array.  Matches Object.keys() behavior\n *  described in E5 Section 15.2.3.14.\n */\n\nDUK_INTERNAL duk_ret_t duk_hobject_get_enumerated_keys(duk_hthread *thr, duk_small_uint_t enum_flags) {\n\tduk_hobject *e;\n\tduk_hstring **keys;\n\tduk_tval *tv;\n\tduk_uint_fast32_t count;\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(duk_get_hobject(thr, -1) != NULL);\n\n\t/* Create a temporary enumerator to get the (non-duplicated) key list;\n\t * the enumerator state is initialized without being needed, but that\n\t * has little impact.\n\t */\n\n\tduk_hobject_enumerator_create(thr, enum_flags);\n\te = duk_known_hobject(thr, -1);\n\n\t/* [enum_target enum res] */\n\n\t/* Create dense result array to exact size. */\n\tDUK_ASSERT(DUK_HOBJECT_GET_ENEXT(e) >= DUK__ENUM_START_INDEX);\n\tcount = (duk_uint32_t) (DUK_HOBJECT_GET_ENEXT(e) - DUK__ENUM_START_INDEX);\n\n\t/* XXX: uninit would be OK */\n\ttv = duk_push_harray_with_size_outptr(thr, (duk_uint32_t) count);\n\tDUK_ASSERT(count == 0 || tv != NULL);\n\n\t/* Fill result array, no side effects. */\n\n\tkeys = DUK_HOBJECT_E_GET_KEY_BASE(thr->heap, e);\n\tkeys += DUK__ENUM_START_INDEX;\n\n\twhile (count-- > 0) {\n\t\tduk_hstring *k;\n\n\t\tk = *keys++;\n\t\tDUK_ASSERT(k != NULL);  /* enumerator must have no keys deleted */\n\n\t\tDUK_TVAL_SET_STRING(tv, k);\n\t\ttv++;\n\t\tDUK_HSTRING_INCREF(thr, k);\n\t}\n\n\t/* [enum_target enum res] */\n\tduk_remove_m2(thr);\n\n\t/* [enum_target res] */\n\n\treturn 1;  /* return 1 to allow callers to tail call */\n}\n\n/* automatic undefs */\n#undef DUK__ENUM_START_INDEX\n#line 1 \"duk_hobject_misc.c\"\n/*\n *  Misc support functions\n */\n\n/* #include duk_internal.h -> already included */\n\nDUK_INTERNAL duk_bool_t duk_hobject_prototype_chain_contains(duk_hthread *thr, duk_hobject *h, duk_hobject *p, duk_bool_t ignore_loop) {\n\tduk_uint_t sanity;\n\n\tDUK_ASSERT(thr != NULL);\n\n\t/* False if the object is NULL or the prototype 'p' is NULL.\n\t * In particular, false if both are NULL (don't compare equal).\n\t */\n\tif (h == NULL || p == NULL) {\n\t\treturn 0;\n\t}\n\n\tsanity = DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY;\n\tdo {\n\t\tif (h == p) {\n\t\t\treturn 1;\n\t\t}\n\n\t\tif (sanity-- == 0) {\n\t\t\tif (ignore_loop) {\n\t\t\t\tbreak;\n\t\t\t} else {\n\t\t\t\tDUK_ERROR_RANGE(thr, DUK_STR_PROTOTYPE_CHAIN_LIMIT);\n\t\t\t}\n\t\t}\n\t\th = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h);\n\t} while (h);\n\n\treturn 0;\n}\n\nDUK_INTERNAL void duk_hobject_set_prototype_updref(duk_hthread *thr, duk_hobject *h, duk_hobject *p) {\n#if defined(DUK_USE_REFERENCE_COUNTING)\n\tduk_hobject *tmp;\n\n\tDUK_ASSERT(h);\n\ttmp = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h);\n\tDUK_HOBJECT_SET_PROTOTYPE(thr->heap, h, p);\n\tDUK_HOBJECT_INCREF_ALLOWNULL(thr, p);  /* avoid problems if p == h->prototype */\n\tDUK_HOBJECT_DECREF_ALLOWNULL(thr, tmp);\n#else\n\tDUK_ASSERT(h);\n\tDUK_UNREF(thr);\n\tDUK_HOBJECT_SET_PROTOTYPE(thr->heap, h, p);\n#endif\n}\n#line 1 \"duk_hobject_pc2line.c\"\n/*\n *  Helpers for creating and querying pc2line debug data, which\n *  converts a bytecode program counter to a source line number.\n *\n *  The run-time pc2line data is bit-packed, and documented in:\n *\n *    doc/function-objects.rst\n */\n\n/* #include duk_internal.h -> already included */\n\n#if defined(DUK_USE_PC2LINE)\n\n/* Generate pc2line data for an instruction sequence, leaving a buffer on stack top. */\nDUK_INTERNAL void duk_hobject_pc2line_pack(duk_hthread *thr, duk_compiler_instr *instrs, duk_uint_fast32_t length) {\n\tduk_hbuffer_dynamic *h_buf;\n\tduk_bitencoder_ctx be_ctx_alloc;\n\tduk_bitencoder_ctx *be_ctx = &be_ctx_alloc;\n\tduk_uint32_t *hdr;\n\tduk_size_t new_size;\n\tduk_uint_fast32_t num_header_entries;\n\tduk_uint_fast32_t curr_offset;\n\tduk_int_fast32_t curr_line, next_line, diff_line;\n\tduk_uint_fast32_t curr_pc;\n\tduk_uint_fast32_t hdr_index;\n\n\tDUK_ASSERT(length <= DUK_COMPILER_MAX_BYTECODE_LENGTH);\n\n\tnum_header_entries = (length + DUK_PC2LINE_SKIP - 1) / DUK_PC2LINE_SKIP;\n\tcurr_offset = (duk_uint_fast32_t) (sizeof(duk_uint32_t) + num_header_entries * sizeof(duk_uint32_t) * 2);\n\n\tduk_push_dynamic_buffer(thr, (duk_size_t) curr_offset);\n\th_buf = (duk_hbuffer_dynamic *) duk_known_hbuffer(thr, -1);\n\tDUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(h_buf) && !DUK_HBUFFER_HAS_EXTERNAL(h_buf));\n\n\thdr = (duk_uint32_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, h_buf);\n\tDUK_ASSERT(hdr != NULL);\n\thdr[0] = (duk_uint32_t) length;  /* valid pc range is [0, length[ */\n\n\tcurr_pc = 0U;\n\twhile (curr_pc < length) {\n\t\tnew_size = (duk_size_t) (curr_offset + DUK_PC2LINE_MAX_DIFF_LENGTH);\n\t\tduk_hbuffer_resize(thr, h_buf, new_size);\n\n\t\thdr = (duk_uint32_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, h_buf);\n\t\tDUK_ASSERT(hdr != NULL);\n\t\tDUK_ASSERT(curr_pc < length);\n\t\thdr_index = 1 + (curr_pc / DUK_PC2LINE_SKIP) * 2;\n\t\tcurr_line = (duk_int_fast32_t) instrs[curr_pc].line;\n\t\thdr[hdr_index + 0] = (duk_uint32_t) curr_line;\n\t\thdr[hdr_index + 1] = (duk_uint32_t) curr_offset;\n\n#if 0\n\t\tDUK_DDD(DUK_DDDPRINT(\"hdr[%ld]: pc=%ld line=%ld offset=%ld\",\n\t\t                     (long) (curr_pc / DUK_PC2LINE_SKIP),\n\t\t                     (long) curr_pc,\n\t\t                     (long) hdr[hdr_index + 0],\n\t\t                     (long) hdr[hdr_index + 1]));\n#endif\n\n\t\tDUK_MEMZERO(be_ctx, sizeof(*be_ctx));\n\t\tbe_ctx->data = ((duk_uint8_t *) hdr) + curr_offset;\n\t\tbe_ctx->length = (duk_size_t) DUK_PC2LINE_MAX_DIFF_LENGTH;\n\n\t\tfor (;;) {\n\t\t\tcurr_pc++;\n\t\t\tif ( ((curr_pc % DUK_PC2LINE_SKIP) == 0) ||  /* end of diff run */\n\t\t\t     (curr_pc >= length) ) {                 /* end of bytecode */\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tDUK_ASSERT(curr_pc < length);\n\t\t\tnext_line = (duk_int32_t) instrs[curr_pc].line;\n\t\t\tdiff_line = next_line - curr_line;\n\n#if 0\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"curr_line=%ld, next_line=%ld -> diff_line=%ld\",\n\t\t\t                     (long) curr_line, (long) next_line, (long) diff_line));\n#endif\n\n\t\t\tif (diff_line == 0) {\n\t\t\t\t/* 0 */\n\t\t\t\tduk_be_encode(be_ctx, 0, 1);\n\t\t\t} else if (diff_line >= 1 && diff_line <= 4) {\n\t\t\t\t/* 1 0 <2 bits> */\n\t\t\t\tduk_be_encode(be_ctx, (duk_uint32_t) ((0x02 << 2) + (diff_line - 1)), 4);\n\t\t\t} else if (diff_line >= -0x80 && diff_line <= 0x7f) {\n\t\t\t\t/* 1 1 0 <8 bits> */\n\t\t\t\tDUK_ASSERT(diff_line + 0x80 >= 0 && diff_line + 0x80 <= 0xff);\n\t\t\t\tduk_be_encode(be_ctx, (duk_uint32_t) ((0x06 << 8) + (diff_line + 0x80)), 11);\n\t\t\t} else {\n\t\t\t\t/* 1 1 1 <32 bits>\n\t\t\t\t * Encode in two parts to avoid bitencode 24-bit limitation\n\t\t\t\t */\n\t\t\t\tduk_be_encode(be_ctx, (duk_uint32_t) ((0x07 << 16) + ((next_line >> 16) & 0xffff)), 19);\n\t\t\t\tduk_be_encode(be_ctx, (duk_uint32_t) (next_line & 0xffff), 16);\n\t\t\t}\n\n\t\t\tcurr_line = next_line;\n\t\t}\n\n\t\tduk_be_finish(be_ctx);\n\t\tDUK_ASSERT(!be_ctx->truncated);\n\n\t\t/* be_ctx->offset == length of encoded bitstream */\n\t\tcurr_offset += (duk_uint_fast32_t) be_ctx->offset;\n\t}\n\n\t/* compact */\n\tnew_size = (duk_size_t) curr_offset;\n\tduk_hbuffer_resize(thr, h_buf, new_size);\n\n\t(void) duk_to_fixed_buffer(thr, -1, NULL);\n\n\tDUK_DDD(DUK_DDDPRINT(\"final pc2line data: pc_limit=%ld, length=%ld, %lf bits/opcode --> %!ixT\",\n\t                     (long) length, (long) new_size, (double) new_size * 8.0 / (double) length,\n\t                     (duk_tval *) duk_get_tval(thr, -1)));\n}\n\n/* PC is unsigned.  If caller does PC arithmetic and gets a negative result,\n * it will map to a large PC which is out of bounds and causes a zero to be\n * returned.\n */\nDUK_LOCAL duk_uint_fast32_t duk__hobject_pc2line_query_raw(duk_hthread *thr, duk_hbuffer_fixed *buf, duk_uint_fast32_t pc) {\n\tduk_bitdecoder_ctx bd_ctx_alloc;\n\tduk_bitdecoder_ctx *bd_ctx = &bd_ctx_alloc;\n\tduk_uint32_t *hdr;\n\tduk_uint_fast32_t start_offset;\n\tduk_uint_fast32_t pc_limit;\n\tduk_uint_fast32_t hdr_index;\n\tduk_uint_fast32_t pc_base;\n\tduk_uint_fast32_t n;\n\tduk_uint_fast32_t curr_line;\n\n\tDUK_ASSERT(buf != NULL);\n\tDUK_ASSERT(!DUK_HBUFFER_HAS_DYNAMIC((duk_hbuffer *) buf) && !DUK_HBUFFER_HAS_EXTERNAL((duk_hbuffer *) buf));\n\tDUK_UNREF(thr);\n\n\t/*\n\t *  Use the index in the header to find the right starting point\n\t */\n\n\thdr_index = pc / DUK_PC2LINE_SKIP;\n\tpc_base = hdr_index * DUK_PC2LINE_SKIP;\n\tn = pc - pc_base;\n\n\tif (DUK_HBUFFER_FIXED_GET_SIZE(buf) <= sizeof(duk_uint32_t)) {\n\t\tDUK_DD(DUK_DDPRINT(\"pc2line lookup failed: buffer is smaller than minimal header\"));\n\t\tgoto pc2line_error;\n\t}\n\n\thdr = (duk_uint32_t *) (void *) DUK_HBUFFER_FIXED_GET_DATA_PTR(thr->heap, buf);\n\tpc_limit = hdr[0];\n\tif (pc >= pc_limit) {\n\t\t/* Note: pc is unsigned and cannot be negative */\n\t\tDUK_DD(DUK_DDPRINT(\"pc2line lookup failed: pc out of bounds (pc=%ld, limit=%ld)\",\n\t\t                   (long) pc, (long) pc_limit));\n\t\tgoto pc2line_error;\n\t}\n\n\tcurr_line = hdr[1 + hdr_index * 2];\n\tstart_offset = hdr[1 + hdr_index * 2 + 1];\n\tif ((duk_size_t) start_offset > DUK_HBUFFER_FIXED_GET_SIZE(buf)) {\n\t\tDUK_DD(DUK_DDPRINT(\"pc2line lookup failed: start_offset out of bounds (start_offset=%ld, buffer_size=%ld)\",\n\t\t                   (long) start_offset, (long) DUK_HBUFFER_GET_SIZE((duk_hbuffer *) buf)));\n\t\tgoto pc2line_error;\n\t}\n\n\t/*\n\t *  Iterate the bitstream (line diffs) until PC is reached\n\t */\n\n\tDUK_MEMZERO(bd_ctx, sizeof(*bd_ctx));\n\tbd_ctx->data = ((duk_uint8_t *) hdr) + start_offset;\n\tbd_ctx->length = (duk_size_t) (DUK_HBUFFER_FIXED_GET_SIZE(buf) - start_offset);\n\n#if 0\n\tDUK_DDD(DUK_DDDPRINT(\"pc2line lookup: pc=%ld -> hdr_index=%ld, pc_base=%ld, n=%ld, start_offset=%ld\",\n\t                     (long) pc, (long) hdr_index, (long) pc_base, (long) n, (long) start_offset));\n#endif\n\n\twhile (n > 0) {\n#if 0\n\t\tDUK_DDD(DUK_DDDPRINT(\"lookup: n=%ld, curr_line=%ld\", (long) n, (long) curr_line));\n#endif\n\n\t\tif (duk_bd_decode_flag(bd_ctx)) {\n\t\t\tif (duk_bd_decode_flag(bd_ctx)) {\n\t\t\t\tif (duk_bd_decode_flag(bd_ctx)) {\n\t\t\t\t\t/* 1 1 1 <32 bits> */\n\t\t\t\t\tduk_uint_fast32_t t;\n\t\t\t\t\tt = duk_bd_decode(bd_ctx, 16);  /* workaround: max nbits = 24 now */\n\t\t\t\t\tt = (t << 16) + duk_bd_decode(bd_ctx, 16);\n\t\t\t\t\tcurr_line = t;\n\t\t\t\t} else {\n\t\t\t\t\t/* 1 1 0 <8 bits> */\n\t\t\t\t\tduk_uint_fast32_t t;\n\t\t\t\t\tt = duk_bd_decode(bd_ctx, 8);\n\t\t\t\t\tcurr_line = curr_line + t - 0x80;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t/* 1 0 <2 bits> */\n\t\t\t\tduk_uint_fast32_t t;\n\t\t\t\tt = duk_bd_decode(bd_ctx, 2);\n\t\t\t\tcurr_line = curr_line + t + 1;\n\t\t\t}\n\t\t} else {\n\t\t\t/* 0: no change */\n\t\t}\n\n\t\tn--;\n\t}\n\n\tDUK_DDD(DUK_DDDPRINT(\"pc2line lookup result: pc %ld -> line %ld\", (long) pc, (long) curr_line));\n\treturn curr_line;\n\n pc2line_error:\n\tDUK_D(DUK_DPRINT(\"pc2line conversion failed for pc=%ld\", (long) pc));\n\treturn 0;\n}\n\nDUK_INTERNAL duk_uint_fast32_t duk_hobject_pc2line_query(duk_hthread *thr, duk_idx_t idx_func, duk_uint_fast32_t pc) {\n\tduk_hbuffer_fixed *pc2line;\n\tduk_uint_fast32_t line;\n\n\t/* XXX: now that pc2line is used by the debugger quite heavily in\n\t * checked execution, this should be optimized to avoid value stack\n\t * and perhaps also implement some form of pc2line caching (see\n\t * future work in debugger.rst).\n\t */\n\n\tduk_get_prop_stridx(thr, idx_func, DUK_STRIDX_INT_PC2LINE);\n\tpc2line = (duk_hbuffer_fixed *) duk_get_hbuffer(thr, -1);\n\tif (pc2line != NULL) {\n\t\tDUK_ASSERT(!DUK_HBUFFER_HAS_DYNAMIC((duk_hbuffer *) pc2line) && !DUK_HBUFFER_HAS_EXTERNAL((duk_hbuffer *) pc2line));\n\t\tline = duk__hobject_pc2line_query_raw(thr, pc2line, (duk_uint_fast32_t) pc);\n\t} else {\n\t\tline = 0;\n\t}\n\tduk_pop(thr);\n\n\treturn line;\n}\n\n#endif  /* DUK_USE_PC2LINE */\n#line 1 \"duk_hobject_props.c\"\n/*\n *  duk_hobject property access functionality.\n *\n *  This is very central functionality for size, performance, and compliance.\n *  It is also rather intricate; see hobject-algorithms.rst for discussion on\n *  the algorithms and memory-management.rst for discussion on refcounts and\n *  side effect issues.\n *\n *  Notes:\n *\n *    - It might be tempting to assert \"refcount nonzero\" for objects\n *      being operated on, but that's not always correct: objects with\n *      a zero refcount may be operated on by the refcount implementation\n *      (finalization) for instance.  Hence, no refcount assertions are made.\n *\n *    - Many operations (memory allocation, identifier operations, etc)\n *      may cause arbitrary side effects (e.g. through GC and finalization).\n *      These side effects may invalidate duk_tval pointers which point to\n *      areas subject to reallocation (like value stack).  Heap objects\n *      themselves have stable pointers.  Holding heap object pointers or\n *      duk_tval copies is not problematic with respect to side effects;\n *      care must be taken when holding and using argument duk_tval pointers.\n *\n *    - If a finalizer is executed, it may operate on the the same object\n *      we're currently dealing with.  For instance, the finalizer might\n *      delete a certain property which has already been looked up and\n *      confirmed to exist.  Ideally finalizers would be disabled if GC\n *      happens during property access.  At the moment property table realloc\n *      disables finalizers, and all DECREFs may cause arbitrary changes so\n *      handle DECREF carefully.\n *\n *    - The order of operations for a DECREF matters.  When DECREF is executed,\n *      the entire object graph must be consistent; note that a refzero may\n *      lead to a mark-and-sweep through a refcount finalizer.  Use NORZ macros\n *      and an explicit DUK_REFZERO_CHECK_xxx() if achieving correct order is hard.\n */\n\n/*\n *  XXX: array indices are mostly typed as duk_uint32_t here; duk_uarridx_t\n *  might be more appropriate.\n */\n\n/* #include duk_internal.h -> already included */\n\n/*\n *  Local defines\n */\n\n#define DUK__NO_ARRAY_INDEX             DUK_HSTRING_NO_ARRAY_INDEX\n\n/* Marker values for hash part. */\n#define DUK__HASH_UNUSED                DUK_HOBJECT_HASHIDX_UNUSED\n#define DUK__HASH_DELETED               DUK_HOBJECT_HASHIDX_DELETED\n\n/* Valstack space that suffices for all local calls, excluding any recursion\n * into Ecmascript or Duktape/C calls (Proxy, getters, etc).\n */\n#define DUK__VALSTACK_SPACE             10\n\n/* Valstack space allocated especially for proxy lookup which does a\n * recursive property lookup.\n */\n#define DUK__VALSTACK_PROXY_LOOKUP      20\n\n/*\n *  Local prototypes\n */\n\nDUK_LOCAL_DECL duk_bool_t duk__check_arguments_map_for_get(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_propdesc *temp_desc);\nDUK_LOCAL_DECL void duk__check_arguments_map_for_put(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_propdesc *temp_desc, duk_bool_t throw_flag);\nDUK_LOCAL_DECL void duk__check_arguments_map_for_delete(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_propdesc *temp_desc);\n\nDUK_LOCAL_DECL duk_bool_t duk__handle_put_array_length_smaller(duk_hthread *thr, duk_hobject *obj, duk_uint32_t old_len, duk_uint32_t new_len, duk_bool_t force_flag, duk_uint32_t *out_result_len);\nDUK_LOCAL_DECL duk_bool_t duk__handle_put_array_length(duk_hthread *thr, duk_hobject *obj);\n\nDUK_LOCAL_DECL duk_bool_t duk__get_propdesc(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_propdesc *out_desc, duk_small_uint_t flags);\nDUK_LOCAL_DECL duk_bool_t duk__get_own_propdesc_raw(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_uint32_t arr_idx, duk_propdesc *out_desc, duk_small_uint_t flags);\n\n/*\n *  Misc helpers\n */\n\n/* Convert a duk_tval number (caller checks) to a 32-bit index.  Returns\n * DUK__NO_ARRAY_INDEX if the number is not whole or not a valid array\n * index.\n */\n/* XXX: for fastints, could use a variant which assumes a double duk_tval\n * (and doesn't need to check for fastint again).\n */\nDUK_LOCAL duk_uint32_t duk__tval_number_to_arr_idx(duk_tval *tv) {\n\tduk_double_t dbl;\n\tduk_uint32_t idx;\n\n\tDUK_ASSERT(tv != NULL);\n\tDUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));\n\n\t/* -0 is accepted here as index 0 because ToString(-0) == \"0\" which is\n\t * in canonical form and thus an array index.\n\t */\n\tdbl = DUK_TVAL_GET_NUMBER(tv);\n\tidx = (duk_uint32_t) dbl;\n\tif ((duk_double_t) idx == dbl) {\n\t        /* Is whole and within 32 bit range.  If the value happens to be 0xFFFFFFFF,\n\t\t * it's not a valid array index but will then match DUK__NO_ARRAY_INDEX.\n\t\t */\n\t\treturn idx;\n\t}\n\treturn DUK__NO_ARRAY_INDEX;\n}\n\n#if defined(DUK_USE_FASTINT)\n/* Convert a duk_tval fastint (caller checks) to a 32-bit index. */\nDUK_LOCAL duk_uint32_t duk__tval_fastint_to_arr_idx(duk_tval *tv) {\n\tduk_int64_t t;\n\n\tDUK_ASSERT(tv != NULL);\n\tDUK_ASSERT(DUK_TVAL_IS_FASTINT(tv));\n\n\tt = DUK_TVAL_GET_FASTINT(tv);\n\tif (((duk_uint64_t) t & ~DUK_U64_CONSTANT(0xffffffff)) != 0) {\n\t\t/* Catches >0x100000000 and negative values. */\n\t\treturn DUK__NO_ARRAY_INDEX;\n\t}\n\n\t/* If the value happens to be 0xFFFFFFFF, it's not a valid array index\n\t * but will then match DUK__NO_ARRAY_INDEX.\n\t */\n\treturn (duk_uint32_t) t;\n}\n#endif  /* DUK_USE_FASTINT */\n\n/* Convert a duk_tval on the value stack (in a trusted index we don't validate)\n * to a string or symbol using ES2015 ToPropertyKey():\n * http://www.ecma-international.org/ecma-262/6.0/#sec-topropertykey.\n *\n * Also check if it's a valid array index and return that (or DUK__NO_ARRAY_INDEX\n * if not).\n */\nDUK_LOCAL duk_uint32_t duk__to_property_key(duk_hthread *thr, duk_idx_t idx, duk_hstring **out_h) {\n\tduk_uint32_t arr_idx;\n\tduk_hstring *h;\n\tduk_tval *tv_dst;\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(out_h != NULL);\n\tDUK_ASSERT(duk_is_valid_index(thr, idx));\n\tDUK_ASSERT(idx < 0);\n\n\t/* XXX: The revised ES2015 ToPropertyKey() handling (ES5.1 was just\n\t * ToString()) involves a ToPrimitive(), a symbol check, and finally\n\t * a ToString().  Figure out the best way to have a good fast path\n\t * but still be compliant and share code.\n\t */\n\n\ttv_dst = DUK_GET_TVAL_NEGIDX(thr, idx);  /* intentionally unvalidated */\n\tif (DUK_TVAL_IS_STRING(tv_dst)) {\n\t\t/* Most important path: strings and plain symbols are used as\n\t\t * is.  For symbols the array index check below is unnecessary\n\t\t * (they're never valid array indices) but checking that the\n\t\t * string is a symbol would make the plain string path slower\n\t\t * unnecessarily.\n\t\t */\n\t\th = DUK_TVAL_GET_STRING(tv_dst);\n\t} else {\n\t\th = duk_to_property_key_hstring(thr, idx);\n\t}\n\tDUK_ASSERT(h != NULL);\n\t*out_h = h;\n\n\tarr_idx = DUK_HSTRING_GET_ARRIDX_FAST(h);\n\treturn arr_idx;\n}\n\nDUK_LOCAL duk_uint32_t duk__push_tval_to_property_key(duk_hthread *thr, duk_tval *tv_key, duk_hstring **out_h) {\n\tduk_push_tval(thr, tv_key);  /* XXX: could use an unsafe push here */\n\treturn duk__to_property_key(thr, -1, out_h);\n}\n\n/* String is an own (virtual) property of a plain buffer. */\nDUK_LOCAL duk_bool_t duk__key_is_plain_buf_ownprop(duk_hthread *thr, duk_hbuffer *buf, duk_hstring *key, duk_uint32_t arr_idx) {\n\tDUK_UNREF(thr);\n\n\t/* Virtual index properties.  Checking explicitly for\n\t * 'arr_idx != DUK__NO_ARRAY_INDEX' is not necessary\n\t * because DUK__NO_ARRAY_INDEXi is always larger than\n\t * maximum allowed buffer size.\n\t */\n\tDUK_ASSERT(DUK__NO_ARRAY_INDEX >= DUK_HBUFFER_GET_SIZE(buf));\n\tif (arr_idx < DUK_HBUFFER_GET_SIZE(buf)) {\n\t\treturn 1;\n\t}\n\n\t/* Other virtual properties. */\n\treturn (key == DUK_HTHREAD_STRING_LENGTH(thr));\n}\n\n/*\n *  Helpers for managing property storage size\n */\n\n/* Get default hash part size for a certain entry part size. */\n#if defined(DUK_USE_HOBJECT_HASH_PART)\nDUK_LOCAL duk_uint32_t duk__get_default_h_size(duk_uint32_t e_size) {\n\tDUK_ASSERT(e_size <= DUK_HOBJECT_MAX_PROPERTIES);\n\n\tif (e_size >= DUK_USE_HOBJECT_HASH_PROP_LIMIT) {\n\t\tduk_uint32_t res;\n\t\tduk_uint32_t tmp;\n\n\t\t/* Hash size should be 2^N where N is chosen so that 2^N is\n\t\t * larger than e_size.  Extra shifting is used to ensure hash\n\t\t * is relatively sparse.\n\t\t */\n\t\ttmp = e_size;\n\t\tres = 2;  /* Result will be 2 ** (N + 1). */\n\t\twhile (tmp >= 0x40) {\n\t\t\ttmp >>= 6;\n\t\t\tres <<= 6;\n\t\t}\n\t\twhile (tmp != 0) {\n\t\t\ttmp >>= 1;\n\t\t\tres <<= 1;\n\t\t}\n\t\tDUK_ASSERT((DUK_HOBJECT_MAX_PROPERTIES << 2U) > DUK_HOBJECT_MAX_PROPERTIES);  /* Won't wrap, even shifted by 2. */\n\t\tDUK_ASSERT(res > e_size);\n\t\treturn res;\n\t} else {\n\t\treturn 0;\n\t}\n}\n#endif  /* USE_PROP_HASH_PART */\n\n/* Get minimum entry part growth for a certain size. */\nDUK_LOCAL duk_uint32_t duk__get_min_grow_e(duk_uint32_t e_size) {\n\tduk_uint32_t res;\n\n\tDUK_ASSERT(e_size <= DUK_HOBJECT_MAX_PROPERTIES);\n\n\tres = (e_size + DUK_USE_HOBJECT_ENTRY_MINGROW_ADD) / DUK_USE_HOBJECT_ENTRY_MINGROW_DIVISOR;\n\tDUK_ASSERT(res >= 1);  /* important for callers */\n\treturn res;\n}\n\n/* Get minimum array part growth for a certain size. */\nDUK_LOCAL duk_uint32_t duk__get_min_grow_a(duk_uint32_t a_size) {\n\tduk_uint32_t res;\n\n\tDUK_ASSERT((duk_size_t) a_size <= DUK_HOBJECT_MAX_PROPERTIES);\n\n\tres = (a_size + DUK_USE_HOBJECT_ARRAY_MINGROW_ADD) / DUK_USE_HOBJECT_ARRAY_MINGROW_DIVISOR;\n\tDUK_ASSERT(res >= 1);  /* important for callers */\n\treturn res;\n}\n\n/* Count actually used entry part entries (non-NULL keys). */\nDUK_LOCAL duk_uint32_t duk__count_used_e_keys(duk_hthread *thr, duk_hobject *obj) {\n\tduk_uint_fast32_t i;\n\tduk_uint_fast32_t n = 0;\n\tduk_hstring **e;\n\n\tDUK_ASSERT(obj != NULL);\n\tDUK_UNREF(thr);\n\n\te = DUK_HOBJECT_E_GET_KEY_BASE(thr->heap, obj);\n\tfor (i = 0; i < DUK_HOBJECT_GET_ENEXT(obj); i++) {\n\t\tif (*e++) {\n\t\t\tn++;\n\t\t}\n\t}\n\treturn (duk_uint32_t) n;\n}\n\n/* Count actually used array part entries and array minimum size.\n * NOTE: 'out_min_size' can be computed much faster by starting from the\n * end and breaking out early when finding first used entry, but this is\n * not needed now.\n */\nDUK_LOCAL void duk__compute_a_stats(duk_hthread *thr, duk_hobject *obj, duk_uint32_t *out_used, duk_uint32_t *out_min_size) {\n\tduk_uint_fast32_t i;\n\tduk_uint_fast32_t used = 0;\n\tduk_uint_fast32_t highest_idx = (duk_uint_fast32_t) -1;  /* see below */\n\tduk_tval *a;\n\n\tDUK_ASSERT(obj != NULL);\n\tDUK_ASSERT(out_used != NULL);\n\tDUK_ASSERT(out_min_size != NULL);\n\tDUK_UNREF(thr);\n\n\ta = DUK_HOBJECT_A_GET_BASE(thr->heap, obj);\n\tfor (i = 0; i < DUK_HOBJECT_GET_ASIZE(obj); i++) {\n\t\tduk_tval *tv = a++;\n\t\tif (!DUK_TVAL_IS_UNUSED(tv)) {\n\t\t\tused++;\n\t\t\thighest_idx = i;\n\t\t}\n\t}\n\n\t/* Initial value for highest_idx is -1 coerced to unsigned.  This\n\t * is a bit odd, but (highest_idx + 1) will then wrap to 0 below\n\t * for out_min_size as intended.\n\t */\n\n\t*out_used = (duk_uint32_t) used;\n\t*out_min_size = (duk_uint32_t) (highest_idx + 1);  /* 0 if no used entries */\n}\n\n/* Check array density and indicate whether or not the array part should be abandoned. */\nDUK_LOCAL duk_bool_t duk__abandon_array_density_check(duk_uint32_t a_used, duk_uint32_t a_size) {\n\t/*\n\t *  Array abandon check; abandon if:\n\t *\n\t *    new_used / new_size < limit\n\t *    new_used < limit * new_size        || limit is 3 bits fixed point\n\t *    new_used < limit' / 8 * new_size   || *8\n\t *    8*new_used < limit' * new_size     || :8\n\t *    new_used < limit' * (new_size / 8)\n\t *\n\t *  Here, new_used = a_used, new_size = a_size.\n\t *\n\t *  Note: some callers use approximate values for a_used and/or a_size\n\t *  (e.g. dropping a '+1' term).  This doesn't affect the usefulness\n\t *  of the check, but may confuse debugging.\n\t */\n\n\treturn (a_used < DUK_USE_HOBJECT_ARRAY_ABANDON_LIMIT * (a_size >> 3));\n}\n\n/* Fast check for extending array: check whether or not a slow density check is required. */\nDUK_LOCAL duk_bool_t duk__abandon_array_slow_check_required(duk_uint32_t arr_idx, duk_uint32_t old_size) {\n\t/*\n\t *  In a fast check we assume old_size equals old_used (i.e., existing\n\t *  array is fully dense).\n\t *\n\t *  Slow check if:\n\t *\n\t *    (new_size - old_size) / old_size > limit\n\t *    new_size - old_size > limit * old_size\n\t *    new_size > (1 + limit) * old_size        || limit' is 3 bits fixed point\n\t *    new_size > (1 + (limit' / 8)) * old_size || * 8\n\t *    8 * new_size > (8 + limit') * old_size   || : 8\n\t *    new_size > (8 + limit') * (old_size / 8)\n\t *    new_size > limit'' * (old_size / 8)      || limit'' = 9 -> max 25% increase\n\t *    arr_idx + 1 > limit'' * (old_size / 8)\n\t *\n\t *  This check doesn't work well for small values, so old_size is rounded\n\t *  up for the check (and the '+ 1' of arr_idx can be ignored in practice):\n\t *\n\t *    arr_idx > limit'' * ((old_size + 7) / 8)\n\t */\n\n\treturn (arr_idx > DUK_USE_HOBJECT_ARRAY_FAST_RESIZE_LIMIT * ((old_size + 7) >> 3));\n}\n\n/*\n *  Proxy helpers\n */\n\n#if defined(DUK_USE_ES6_PROXY)\nDUK_INTERNAL duk_bool_t duk_hobject_proxy_check(duk_hobject *obj, duk_hobject **out_target, duk_hobject **out_handler) {\n\tduk_hproxy *h_proxy;\n\n\tDUK_ASSERT(obj != NULL);\n\tDUK_ASSERT(out_target != NULL);\n\tDUK_ASSERT(out_handler != NULL);\n\n\t/* Caller doesn't need to check exotic proxy behavior (but does so for\n\t * some fast paths).\n\t */\n\tif (DUK_LIKELY(!DUK_HOBJECT_IS_PROXY(obj))) {\n\t\treturn 0;\n\t}\n\th_proxy = (duk_hproxy *) obj;\n\tDUK_ASSERT_HPROXY_VALID(h_proxy);\n\n\tDUK_ASSERT(h_proxy->handler != NULL);\n\tDUK_ASSERT(h_proxy->target != NULL);\n\t*out_handler = h_proxy->handler;\n\t*out_target = h_proxy->target;\n\n\treturn 1;\n}\n#endif  /* DUK_USE_ES6_PROXY */\n\n/* Get Proxy target object.  If the argument is not a Proxy, return it as is.\n * If a Proxy is revoked, an error is thrown.\n */\n#if defined(DUK_USE_ES6_PROXY)\nDUK_INTERNAL duk_hobject *duk_hobject_resolve_proxy_target(duk_hobject *obj) {\n\tDUK_ASSERT(obj != NULL);\n\n\t/* Resolve Proxy targets until Proxy chain ends.  No explicit check for\n\t * a Proxy loop: user code cannot create such a loop (it would only be\n\t * possible by editing duk_hproxy references directly).\n\t */\n\n\twhile (DUK_HOBJECT_IS_PROXY(obj)) {\n\t\tduk_hproxy *h_proxy;\n\n\t\th_proxy = (duk_hproxy *) obj;\n\t\tDUK_ASSERT_HPROXY_VALID(h_proxy);\n\t\tobj = h_proxy->target;\n\t\tDUK_ASSERT(obj != NULL);\n\t}\n\n\tDUK_ASSERT(obj != NULL);\n\treturn obj;\n}\n#endif  /* DUK_USE_ES6_PROXY */\n\n#if defined(DUK_USE_ES6_PROXY)\nDUK_LOCAL duk_bool_t duk__proxy_check_prop(duk_hthread *thr, duk_hobject *obj, duk_small_uint_t stridx_trap, duk_tval *tv_key, duk_hobject **out_target) {\n\tduk_hobject *h_handler;\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(obj != NULL);\n\tDUK_ASSERT(tv_key != NULL);\n\tDUK_ASSERT(out_target != NULL);\n\n\tif (!duk_hobject_proxy_check(obj, out_target, &h_handler)) {\n\t\treturn 0;\n\t}\n\tDUK_ASSERT(*out_target != NULL);\n\tDUK_ASSERT(h_handler != NULL);\n\n\t/* XXX: At the moment Duktape accesses internal keys like _Finalizer using a\n\t * normal property set/get which would allow a proxy handler to interfere with\n\t * such behavior and to get access to internal key strings.  This is not a problem\n\t * as such because internal key strings can be created in other ways too (e.g.\n\t * through buffers).  The best fix is to change Duktape internal lookups to\n\t * skip proxy behavior.  Until that, internal property accesses bypass the\n\t * proxy and are applied to the target (as if the handler did not exist).\n\t * This has some side effects, see test-bi-proxy-internal-keys.js.\n\t */\n\n\tif (DUK_TVAL_IS_STRING(tv_key)) {\n\t\tduk_hstring *h_key = (duk_hstring *) DUK_TVAL_GET_STRING(tv_key);\n\t\tDUK_ASSERT(h_key != NULL);\n\t\tif (DUK_HSTRING_HAS_HIDDEN(h_key)) {\n\t\t\t/* Symbol accesses must go through proxy lookup in ES2015.\n\t\t\t * Hidden symbols behave like Duktape 1.x internal keys\n\t\t\t * and currently won't.\n\t\t\t */\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"hidden key, skip proxy handler and apply to target\"));\n\t\t\treturn 0;\n\t\t}\n\t}\n\n\t/* The handler is looked up with a normal property lookup; it may be an\n\t * accessor or the handler object itself may be a proxy object.  If the\n\t * handler is a proxy, we need to extend the valstack as we make a\n\t * recursive proxy check without a function call in between (in fact\n\t * there is no limit to the potential recursion here).\n\t *\n\t * (For sanity, proxy creation rejects another proxy object as either\n\t * the handler or the target at the moment so recursive proxy cases\n\t * are not realized now.)\n\t */\n\n\t/* XXX: C recursion limit if proxies are allowed as handler/target values */\n\n\tduk_require_stack(thr, DUK__VALSTACK_PROXY_LOOKUP);\n\tduk_push_hobject(thr, h_handler);\n\tif (duk_get_prop_stridx_short(thr, -1, stridx_trap)) {\n\t\t/* -> [ ... handler trap ] */\n\t\tduk_insert(thr, -2);  /* -> [ ... trap handler ] */\n\n\t\t/* stack prepped for func call: [ ... trap handler ] */\n\t\treturn 1;\n\t} else {\n\t\tduk_pop_2_unsafe(thr);\n\t\treturn 0;\n\t}\n}\n#endif  /* DUK_USE_ES6_PROXY */\n\n/*\n *  Reallocate property allocation, moving properties to the new allocation.\n *\n *  Includes key compaction, rehashing, and can also optionally abandon\n *  the array part, 'migrating' array entries into the beginning of the\n *  new entry part.\n *\n *  There is no support for in-place reallocation or just compacting keys\n *  without resizing the property allocation.  This is intentional to keep\n *  code size minimal, but would be useful future work.\n *\n *  The implementation is relatively straightforward, except for the array\n *  abandonment process.  Array abandonment requires that new string keys\n *  are interned, which may trigger GC.  All keys interned so far must be\n *  reachable for GC at all times and correctly refcounted for; valstack is\n *  used for that now.\n *\n *  Also, a GC triggered during this reallocation process must not interfere\n *  with the object being resized.  This is currently controlled by preventing\n *  finalizers (as they may affect ANY object) and object compaction in\n *  mark-and-sweep.  It would suffice to protect only this particular object\n *  from compaction, however.  DECREF refzero cascades are side effect free\n *  and OK.\n *\n *  Note: because we need to potentially resize the valstack (as part\n *  of abandoning the array part), any tval pointers to the valstack\n *  will become invalid after this call.\n */\n\nDUK_INTERNAL void duk_hobject_realloc_props(duk_hthread *thr,\n                                            duk_hobject *obj,\n                                            duk_uint32_t new_e_size,\n                                            duk_uint32_t new_a_size,\n                                            duk_uint32_t new_h_size,\n                                            duk_bool_t abandon_array) {\n\tduk_small_uint_t prev_ms_base_flags;\n\tduk_uint32_t new_alloc_size;\n\tduk_uint32_t new_e_size_adjusted;\n\tduk_uint8_t *new_p;\n\tduk_hstring **new_e_k;\n\tduk_propvalue *new_e_pv;\n\tduk_uint8_t *new_e_f;\n\tduk_tval *new_a;\n\tduk_uint32_t *new_h;\n\tduk_uint32_t new_e_next;\n\tduk_uint_fast32_t i;\n\tduk_size_t array_copy_size;\n#if defined(DUK_USE_ASSERTIONS)\n\tduk_bool_t prev_error_not_allowed;\n#endif\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(obj != NULL);\n\tDUK_ASSERT(!abandon_array || new_a_size == 0);  /* if abandon_array, new_a_size must be 0 */\n\tDUK_ASSERT(DUK_HOBJECT_GET_PROPS(thr->heap, obj) != NULL || (DUK_HOBJECT_GET_ESIZE(obj) == 0 && DUK_HOBJECT_GET_ASIZE(obj) == 0));\n\tDUK_ASSERT(new_h_size == 0 || new_h_size >= new_e_size);  /* required to guarantee success of rehashing,\n\t                                                           * intentionally use unadjusted new_e_size\n\t                                                           */\n\tDUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj));\n\tDUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);\n\n\tDUK_STATS_INC(thr->heap, stats_object_realloc_props);\n\n\t/*\n\t *  Pre resize assertions.\n\t */\n\n#if defined(DUK_USE_ASSERTIONS)\n\t/* XXX: pre-checks (such as no duplicate keys) */\n#endif\n\n\t/*\n\t *  For property layout 1, tweak e_size to ensure that the whole entry\n\t *  part (key + val + flags) is a suitable multiple for alignment\n\t *  (platform specific).\n\t *\n\t *  Property layout 2 does not require this tweaking and is preferred\n\t *  on low RAM platforms requiring alignment.\n\t */\n\n#if defined(DUK_USE_HOBJECT_LAYOUT_2) || defined(DUK_USE_HOBJECT_LAYOUT_3)\n\tDUK_DDD(DUK_DDDPRINT(\"using layout 2 or 3, no need to pad e_size: %ld\", (long) new_e_size));\n\tnew_e_size_adjusted = new_e_size;\n#elif defined(DUK_USE_HOBJECT_LAYOUT_1) && (DUK_HOBJECT_ALIGN_TARGET == 1)\n\tDUK_DDD(DUK_DDDPRINT(\"using layout 1, but no need to pad e_size: %ld\", (long) new_e_size));\n\tnew_e_size_adjusted = new_e_size;\n#elif defined(DUK_USE_HOBJECT_LAYOUT_1) && ((DUK_HOBJECT_ALIGN_TARGET == 4) || (DUK_HOBJECT_ALIGN_TARGET == 8))\n\tnew_e_size_adjusted = (new_e_size + (duk_uint32_t) DUK_HOBJECT_ALIGN_TARGET - 1U) &\n\t                      (~((duk_uint32_t) DUK_HOBJECT_ALIGN_TARGET - 1U));\n\tDUK_DDD(DUK_DDDPRINT(\"using layout 1, and alignment target is %ld, adjusted e_size: %ld -> %ld\",\n\t                     (long) DUK_HOBJECT_ALIGN_TARGET, (long) new_e_size, (long) new_e_size_adjusted));\n\tDUK_ASSERT(new_e_size_adjusted >= new_e_size);\n#else\n#error invalid hobject layout defines\n#endif\n\n\t/*\n\t *  Debug logging after adjustment.\n\t */\n\n\tDUK_DDD(DUK_DDDPRINT(\"attempt to resize hobject %p props (%ld -> %ld bytes), from {p=%p,e_size=%ld,e_next=%ld,a_size=%ld,h_size=%ld} to \"\n\t                     \"{e_size=%ld,a_size=%ld,h_size=%ld}, abandon_array=%ld, unadjusted new_e_size=%ld\",\n\t                     (void *) obj,\n\t                     (long) DUK_HOBJECT_P_COMPUTE_SIZE(DUK_HOBJECT_GET_ESIZE(obj),\n\t                                                       DUK_HOBJECT_GET_ASIZE(obj),\n\t                                                       DUK_HOBJECT_GET_HSIZE(obj)),\n\t                     (long) DUK_HOBJECT_P_COMPUTE_SIZE(new_e_size_adjusted, new_a_size, new_h_size),\n\t                     (void *) DUK_HOBJECT_GET_PROPS(thr->heap, obj),\n\t                     (long) DUK_HOBJECT_GET_ESIZE(obj),\n\t                     (long) DUK_HOBJECT_GET_ENEXT(obj),\n\t                     (long) DUK_HOBJECT_GET_ASIZE(obj),\n\t                     (long) DUK_HOBJECT_GET_HSIZE(obj),\n\t                     (long) new_e_size_adjusted,\n\t                     (long) new_a_size,\n\t                     (long) new_h_size,\n\t                     (long) abandon_array,\n\t                     (long) new_e_size));\n\n\t/*\n\t *  Property count check.  This is the only point where we ensure that\n\t *  we don't get more (allocated) property space that we can handle.\n\t *  There aren't hard limits as such, but some algorithms may fail\n\t *  if we get too close to the 4G property limit.\n\t *\n\t *  Since this works based on allocation size (not actually used size),\n\t *  the limit is a bit approximate but good enough in practice.\n\t */\n\n\tif (new_e_size_adjusted + new_a_size > DUK_HOBJECT_MAX_PROPERTIES) {\n\t\tDUK_ERROR_ALLOC_FAILED(thr);\n\t}\n\n\t/*\n\t *  Compute new alloc size and alloc new area.\n\t *\n\t *  The new area is not tracked in the heap at all, so it's critical\n\t *  we get to free/keep it in a controlled manner.\n\t */\n\n#if defined(DUK_USE_ASSERTIONS)\n\t/* Whole path must be error throw free, but we may be called from\n\t * within error handling so can't assert for error_not_allowed == 0.\n\t */\n\tprev_error_not_allowed = thr->heap->error_not_allowed;\n\tthr->heap->error_not_allowed = 1;\n#endif\n\tprev_ms_base_flags = thr->heap->ms_base_flags;\n\tthr->heap->ms_base_flags |=\n\t        DUK_MS_FLAG_NO_OBJECT_COMPACTION;      /* Avoid attempt to compact the current object (all objects really). */\n\tthr->heap->pf_prevent_count++;                 /* Avoid finalizers. */\n\tDUK_ASSERT(thr->heap->pf_prevent_count != 0);  /* Wrap. */\n\n\tnew_alloc_size = DUK_HOBJECT_P_COMPUTE_SIZE(new_e_size_adjusted, new_a_size, new_h_size);\n\tDUK_DDD(DUK_DDDPRINT(\"new hobject allocation size is %ld\", (long) new_alloc_size));\n\tif (new_alloc_size == 0) {\n\t\tDUK_ASSERT(new_e_size_adjusted == 0);\n\t\tDUK_ASSERT(new_a_size == 0);\n\t\tDUK_ASSERT(new_h_size == 0);\n\t\tnew_p = NULL;\n\t} else {\n\t\t/* Alloc may trigger mark-and-sweep but no compaction, and\n\t\t * cannot throw.\n\t\t */\n#if 0  /* XXX: inject test */\n\t\tif (1) {\n\t\t\tnew_p = NULL;\n\t\t\tgoto alloc_failed;\n\t\t}\n#endif\n\t\tnew_p = (duk_uint8_t *) DUK_ALLOC(thr->heap, new_alloc_size);\n\t\tif (new_p == NULL) {\n\t\t\t/* NULL always indicates alloc failure because\n\t\t\t * new_alloc_size > 0.\n\t\t\t */\n\t\t\tgoto alloc_failed;\n\t\t}\n\t}\n\n\t/* Set up pointers to the new property area: this is hidden behind a macro\n\t * because it is memory layout specific.\n\t */\n\tDUK_HOBJECT_P_SET_REALLOC_PTRS(new_p, new_e_k, new_e_pv, new_e_f, new_a, new_h,\n\t                               new_e_size_adjusted, new_a_size, new_h_size);\n\tDUK_UNREF(new_h);  /* happens when hash part dropped */\n\tnew_e_next = 0;\n\n\t/* if new_p == NULL, all of these pointers are NULL */\n\tDUK_ASSERT((new_p != NULL) ||\n\t           (new_e_k == NULL && new_e_pv == NULL && new_e_f == NULL &&\n\t            new_a == NULL && new_h == NULL));\n\n\tDUK_DDD(DUK_DDDPRINT(\"new alloc size %ld, new_e_k=%p, new_e_pv=%p, new_e_f=%p, new_a=%p, new_h=%p\",\n\t                     (long) new_alloc_size, (void *) new_e_k, (void *) new_e_pv, (void *) new_e_f,\n\t                     (void *) new_a, (void *) new_h));\n\n\t/*\n\t *  Migrate array part to start of entries if requested.\n\t *\n\t *  Note: from an enumeration perspective the order of entry keys matters.\n\t *  Array keys should appear wherever they appeared before the array abandon\n\t *  operation.  (This no longer matters much because keys are ES2015 sorted.)\n\t */\n\n\tif (abandon_array) {\n\t\t/* Assuming new_a_size == 0, and that entry part contains\n\t\t * no conflicting keys, refcounts do not need to be adjusted for\n\t\t * the values, as they remain exactly the same.\n\t\t *\n\t\t * The keys, however, need to be interned, incref'd, and be\n\t\t * reachable for GC.  Any intern attempt may trigger a GC and\n\t\t * claim any non-reachable strings, so every key must be reachable\n\t\t * at all times.  Refcounts must be correct to satisfy refcount\n\t\t * assertions.\n\t\t *\n\t\t * A longjmp must not occur here, as the new_p allocation would\n\t\t * leak.  Refcounts would come out correctly as the interned\n\t\t * strings are valstack tracked.\n\t\t */\n\t\tDUK_ASSERT(new_a_size == 0);\n\n\t\tDUK_STATS_INC(thr->heap, stats_object_abandon_array);\n\n\t\tfor (i = 0; i < DUK_HOBJECT_GET_ASIZE(obj); i++) {\n\t\t\tduk_tval *tv1;\n\t\t\tduk_tval *tv2;\n\t\t\tduk_hstring *key;\n\n\t\t\tDUK_ASSERT(DUK_HOBJECT_GET_PROPS(thr->heap, obj) != NULL);\n\n\t\t\ttv1 = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, i);\n\t\t\tif (DUK_TVAL_IS_UNUSED(tv1)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tDUK_ASSERT(new_p != NULL && new_e_k != NULL &&\n\t\t\t           new_e_pv != NULL && new_e_f != NULL);\n\n\t\t\t/*\n\t\t\t *  Intern key via the valstack to ensure reachability behaves\n\t\t\t *  properly.  We must avoid longjmp's here so use non-checked\n\t\t\t *  primitives.\n\t\t\t *\n\t\t\t *  Note: duk_check_stack() potentially reallocs the valstack,\n\t\t\t *  invalidating any duk_tval pointers to valstack.  Callers\n\t\t\t *  must be careful.\n\t\t\t */\n\n#if 0  /* XXX: inject test */\n\t\t\tif (1) {\n\t\t\t\tgoto abandon_error;\n\t\t\t}\n#endif\n\t\t\t/* Never shrinks; auto-adds DUK_VALSTACK_INTERNAL_EXTRA, which\n\t\t\t * is generous.\n\t\t\t */\n\t\t\tif (!duk_check_stack(thr, 1)) {\n\t\t\t\tgoto abandon_error;\n\t\t\t}\n\t\t\tDUK_ASSERT_VALSTACK_SPACE(thr, 1);\n\t\t\tkey = duk_heap_strtable_intern_u32(thr->heap, (duk_uint32_t) i);\n\t\t\tif (key == NULL) {\n\t\t\t\tgoto abandon_error;\n\t\t\t}\n\t\t\tduk_push_hstring(thr, key);  /* keep key reachable for GC etc; guaranteed not to fail */\n\n\t\t\t/* Key is now reachable in the valstack, don't INCREF\n\t\t\t * the new allocation yet (we'll steal the refcounts\n\t\t\t * from the value stack once all keys are done).\n\t\t\t */\n\n\t\t\tnew_e_k[new_e_next] = key;\n\t\t\ttv2 = &new_e_pv[new_e_next].v;  /* array entries are all plain values */\n\t\t\tDUK_TVAL_SET_TVAL(tv2, tv1);\n\t\t\tnew_e_f[new_e_next] = DUK_PROPDESC_FLAG_WRITABLE |\n\t\t\t                      DUK_PROPDESC_FLAG_ENUMERABLE |\n\t\t\t                      DUK_PROPDESC_FLAG_CONFIGURABLE;\n\t\t\tnew_e_next++;\n\n\t\t\t/* Note: new_e_next matches pushed temp key count, and nothing can\n\t\t\t * fail above between the push and this point.\n\t\t\t */\n\t\t}\n\n\t\t/* Steal refcounts from value stack. */\n\t\tDUK_DDD(DUK_DDDPRINT(\"abandon array: pop %ld key temps from valstack\", (long) new_e_next));\n\t\tduk_pop_n_nodecref_unsafe(thr, (duk_idx_t) new_e_next);\n\t}\n\n\t/*\n\t *  Copy keys and values in the entry part (compacting them at the same time).\n\t */\n\n\tfor (i = 0; i < DUK_HOBJECT_GET_ENEXT(obj); i++) {\n\t\tduk_hstring *key;\n\n\t\tDUK_ASSERT(DUK_HOBJECT_GET_PROPS(thr->heap, obj) != NULL);\n\n\t\tkey = DUK_HOBJECT_E_GET_KEY(thr->heap, obj, i);\n\t\tif (key == NULL) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tDUK_ASSERT(new_p != NULL && new_e_k != NULL &&\n\t\t           new_e_pv != NULL && new_e_f != NULL);\n\n\t\tnew_e_k[new_e_next] = key;\n\t\tnew_e_pv[new_e_next] = DUK_HOBJECT_E_GET_VALUE(thr->heap, obj, i);\n\t\tnew_e_f[new_e_next] = DUK_HOBJECT_E_GET_FLAGS(thr->heap, obj, i);\n\t\tnew_e_next++;\n\t}\n\t/* the entries [new_e_next, new_e_size_adjusted[ are left uninitialized on purpose (ok, not gc reachable) */\n\n\t/*\n\t *  Copy array elements to new array part.  If the new array part is\n\t *  larger, initialize the unused entries as UNUSED because they are\n\t *  GC reachable.\n\t */\n\n#if defined(DUK_USE_ASSERTIONS)\n\t/* Caller must have decref'd values above new_a_size (if that is necessary). */\n\tif (!abandon_array) {\n\t\tfor (i = new_a_size; i < DUK_HOBJECT_GET_ASIZE(obj); i++) {\n\t\t\tduk_tval *tv;\n\t\t\ttv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, i);\n\t\t\tDUK_ASSERT(DUK_TVAL_IS_UNUSED(tv));\n\t\t}\n\t}\n#endif\n\tif (new_a_size > DUK_HOBJECT_GET_ASIZE(obj)) {\n\t\tarray_copy_size = sizeof(duk_tval) * DUK_HOBJECT_GET_ASIZE(obj);\n\t} else {\n\t\tarray_copy_size = sizeof(duk_tval) * new_a_size;\n\t}\n\tif (array_copy_size > 0) {\n\t\t/* Avoid zero copy with an invalid pointer.  If obj->p is NULL,\n\t\t * the 'new_a' pointer will be invalid which is not allowed even\n\t\t * when copy size is zero.\n\t\t */\n\t\tDUK_ASSERT(new_a != NULL);\n\t\tDUK_ASSERT(DUK_HOBJECT_GET_PROPS(thr->heap, obj) != NULL);\n\t\tDUK_ASSERT(DUK_HOBJECT_GET_ASIZE(obj) > 0);\n\t\tDUK_MEMCPY((void *) new_a,\n\t\t           (const void *) DUK_HOBJECT_A_GET_BASE(thr->heap, obj),\n\t\t           array_copy_size);\n\t}\n\tfor (i = DUK_HOBJECT_GET_ASIZE(obj); i < new_a_size; i++) {\n\t\tduk_tval *tv = &new_a[i];\n\t\tDUK_TVAL_SET_UNUSED(tv);\n\t}\n\n\t/*\n\t *  Rebuild the hash part always from scratch (guaranteed to finish\n\t *  as long as caller gave consistent parameters).\n\t *\n\t *  Any resize of hash part requires rehashing.  In addition, by rehashing\n\t *  get rid of any elements marked deleted (DUK__HASH_DELETED) which is critical\n\t *  to ensuring the hash part never fills up.\n\t */\n\n#if defined(DUK_USE_HOBJECT_HASH_PART)\n\tif (new_h_size == 0) {\n\t\tDUK_DDD(DUK_DDDPRINT(\"no hash part, no rehash\"));\n\t} else {\n\t\tduk_uint32_t mask;\n\n\t\tDUK_ASSERT(new_h != NULL);\n\n\t\t/* fill new_h with u32 0xff = UNUSED */\n\t\tDUK_ASSERT(new_h_size > 0);\n\t\tDUK_MEMSET(new_h, 0xff, sizeof(duk_uint32_t) * new_h_size);\n\n\t\tDUK_ASSERT(new_e_next <= new_h_size);  /* equality not actually possible */\n\n\t\tmask = new_h_size - 1;\n\t\tfor (i = 0; i < new_e_next; i++) {\n\t\t\tduk_hstring *key = new_e_k[i];\n\t\t\tduk_uint32_t j, step;\n\n\t\t\tDUK_ASSERT(key != NULL);\n\t\t\tj = DUK_HSTRING_GET_HASH(key) & mask;\n\t\t\tstep = 1;  /* Cache friendly but clustering prone. */\n\n\t\t\tfor (;;) {\n\t\t\t\tDUK_ASSERT(new_h[j] != DUK__HASH_DELETED);  /* should never happen */\n\t\t\t\tif (new_h[j] == DUK__HASH_UNUSED) {\n\t\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"rebuild hit %ld -> %ld\", (long) j, (long) i));\n\t\t\t\t\tnew_h[j] = (duk_uint32_t) i;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"rebuild miss %ld, step %ld\", (long) j, (long) step));\n\t\t\t\tj = (j + step) & mask;\n\n\t\t\t\t/* Guaranteed to finish (hash is larger than #props). */\n\t\t\t}\n\t\t}\n\t}\n#endif  /* DUK_USE_HOBJECT_HASH_PART */\n\n\t/*\n\t *  Nice debug log.\n\t */\n\n\tDUK_DD(DUK_DDPRINT(\"resized hobject %p props (%ld -> %ld bytes), from {p=%p,e_size=%ld,e_next=%ld,a_size=%ld,h_size=%ld} to \"\n\t                   \"{p=%p,e_size=%ld,e_next=%ld,a_size=%ld,h_size=%ld}, abandon_array=%ld, unadjusted new_e_size=%ld\",\n\t                   (void *) obj,\n\t                   (long) DUK_HOBJECT_P_COMPUTE_SIZE(DUK_HOBJECT_GET_ESIZE(obj),\n\t                                                     DUK_HOBJECT_GET_ASIZE(obj),\n\t                                                     DUK_HOBJECT_GET_HSIZE(obj)),\n\t                   (long) new_alloc_size,\n\t                   (void *) DUK_HOBJECT_GET_PROPS(thr->heap, obj),\n\t                   (long) DUK_HOBJECT_GET_ESIZE(obj),\n\t                   (long) DUK_HOBJECT_GET_ENEXT(obj),\n\t                   (long) DUK_HOBJECT_GET_ASIZE(obj),\n\t                   (long) DUK_HOBJECT_GET_HSIZE(obj),\n\t                   (void *) new_p,\n\t                   (long) new_e_size_adjusted,\n\t                   (long) new_e_next,\n\t                   (long) new_a_size,\n\t                   (long) new_h_size,\n\t                   (long) abandon_array,\n\t                   (long) new_e_size));\n\n\t/*\n\t *  All done, switch properties ('p') allocation to new one.\n\t */\n\n\tDUK_FREE_CHECKED(thr, DUK_HOBJECT_GET_PROPS(thr->heap, obj));  /* NULL obj->p is OK */\n\tDUK_HOBJECT_SET_PROPS(thr->heap, obj, new_p);\n\tDUK_HOBJECT_SET_ESIZE(obj, new_e_size_adjusted);\n\tDUK_HOBJECT_SET_ENEXT(obj, new_e_next);\n\tDUK_HOBJECT_SET_ASIZE(obj, new_a_size);\n\tDUK_HOBJECT_SET_HSIZE(obj, new_h_size);\n\n\t/* Clear array part flag only after switching. */\n\tif (abandon_array) {\n\t\tDUK_HOBJECT_CLEAR_ARRAY_PART(obj);\n\t}\n\n\tDUK_DDD(DUK_DDDPRINT(\"resize result: %!O\", (duk_heaphdr *) obj));\n\n\tDUK_ASSERT(thr->heap->pf_prevent_count > 0);\n\tthr->heap->pf_prevent_count--;\n\tthr->heap->ms_base_flags = prev_ms_base_flags;\n#if defined(DUK_USE_ASSERTIONS)\n\tDUK_ASSERT(thr->heap->error_not_allowed == 1);\n\tthr->heap->error_not_allowed = prev_error_not_allowed;\n#endif\n\n\t/*\n\t *  Post resize assertions.\n\t */\n\n#if defined(DUK_USE_ASSERTIONS)\n\t/* XXX: post-checks (such as no duplicate keys) */\n#endif\n\treturn;\n\n\t/*\n\t *  Abandon array failed.  We don't need to DECREF anything\n\t *  because the references in the new allocation are not\n\t *  INCREF'd until abandon is complete.  The string interned\n\t *  keys are on the value stack and are handled normally by\n\t *  unwind.\n\t */\n\n abandon_error:\n alloc_failed:\n\tDUK_D(DUK_DPRINT(\"object property table resize failed\"));\n\n\tDUK_FREE_CHECKED(thr, new_p);  /* OK for NULL. */\n\n\tthr->heap->pf_prevent_count--;\n\tthr->heap->ms_base_flags = prev_ms_base_flags;\n#if defined(DUK_USE_ASSERTIONS)\n\tDUK_ASSERT(thr->heap->error_not_allowed == 1);\n\tthr->heap->error_not_allowed = prev_error_not_allowed;\n#endif\n\n\tDUK_ERROR_ALLOC_FAILED(thr);\n}\n\n/*\n *  Helpers to resize properties allocation on specific needs.\n */\n\nDUK_INTERNAL void duk_hobject_resize_entrypart(duk_hthread *thr,\n                                               duk_hobject *obj,\n                                               duk_uint32_t new_e_size) {\n\tduk_uint32_t old_e_size;\n\tduk_uint32_t new_a_size;\n\tduk_uint32_t new_h_size;\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(obj != NULL);\n\n\told_e_size = DUK_HOBJECT_GET_ESIZE(obj);\n\tif (old_e_size > new_e_size) {\n\t\tnew_e_size = old_e_size;\n\t}\n#if defined(DUK_USE_HOBJECT_HASH_PART)\n\tnew_h_size = duk__get_default_h_size(new_e_size);\n#else\n\tnew_h_size = 0;\n#endif\n\tnew_a_size = DUK_HOBJECT_GET_ASIZE(obj);\n\n\tduk_hobject_realloc_props(thr, obj, new_e_size, new_a_size, new_h_size, 0);\n}\n\n#if 0  /*unused */\nDUK_INTERNAL void duk_hobject_resize_arraypart(duk_hthread *thr,\n                                               duk_hobject *obj,\n                                               duk_uint32_t new_a_size) {\n\tduk_uint32_t old_a_size;\n\tduk_uint32_t new_e_size;\n\tduk_uint32_t new_h_size;\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(obj != NULL);\n\n\tif (!DUK_HOBJECT_HAS_ARRAY_PART(obj)) {\n\t\treturn;\n\t}\n\told_a_size = DUK_HOBJECT_GET_ASIZE(obj);\n\tif (old_a_size > new_a_size) {\n\t\tnew_a_size = old_a_size;\n\t}\n\tnew_e_size = DUK_HOBJECT_GET_ESIZE(obj);\n\tnew_h_size = DUK_HOBJECT_GET_HSIZE(obj);\n\n\tduk_hobject_realloc_props(thr, obj, new_e_size, new_a_size, new_h_size, 0);\n}\n#endif\n\n/* Grow entry part allocation for one additional entry. */\nDUK_LOCAL void duk__grow_props_for_new_entry_item(duk_hthread *thr, duk_hobject *obj) {\n\tduk_uint32_t old_e_used;  /* actually used, non-NULL entries */\n\tduk_uint32_t new_e_size;\n\tduk_uint32_t new_a_size;\n\tduk_uint32_t new_h_size;\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(obj != NULL);\n\n\t/* Duktape 0.11.0 and prior tried to optimize the resize by not\n\t * counting the number of actually used keys prior to the resize.\n\t * This worked mostly well but also caused weird leak-like behavior\n\t * as in: test-bug-object-prop-alloc-unbounded.js.  So, now we count\n\t * the keys explicitly to compute the new entry part size.\n\t */\n\n\told_e_used = duk__count_used_e_keys(thr, obj);\n\tnew_e_size = old_e_used + duk__get_min_grow_e(old_e_used);\n#if defined(DUK_USE_HOBJECT_HASH_PART)\n\tnew_h_size = duk__get_default_h_size(new_e_size);\n#else\n\tnew_h_size = 0;\n#endif\n\tnew_a_size = DUK_HOBJECT_GET_ASIZE(obj);\n\tDUK_ASSERT(new_e_size >= old_e_used + 1);  /* duk__get_min_grow_e() is always >= 1 */\n\n\tduk_hobject_realloc_props(thr, obj, new_e_size, new_a_size, new_h_size, 0);\n}\n\n/* Grow array part for a new highest array index. */\nDUK_LOCAL void duk__grow_props_for_array_item(duk_hthread *thr, duk_hobject *obj, duk_uint32_t highest_arr_idx) {\n\tduk_uint32_t new_e_size;\n\tduk_uint32_t new_a_size;\n\tduk_uint32_t new_h_size;\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(obj != NULL);\n\tDUK_ASSERT(highest_arr_idx >= DUK_HOBJECT_GET_ASIZE(obj));\n\n\t/* minimum new length is highest_arr_idx + 1 */\n\n\tnew_e_size = DUK_HOBJECT_GET_ESIZE(obj);\n\tnew_h_size = DUK_HOBJECT_GET_HSIZE(obj);\n\tnew_a_size = highest_arr_idx + duk__get_min_grow_a(highest_arr_idx);\n\tDUK_ASSERT(new_a_size >= highest_arr_idx + 1);  /* duk__get_min_grow_a() is always >= 1 */\n\n\tduk_hobject_realloc_props(thr, obj, new_e_size, new_a_size, new_h_size, 0);\n}\n\n/* Abandon array part, moving array entries into entries part.\n * This requires a props resize, which is a heavy operation.\n * We also compact the entries part while we're at it, although\n * this is not strictly required.\n */\nDUK_LOCAL void duk__abandon_array_checked(duk_hthread *thr, duk_hobject *obj) {\n\tduk_uint32_t new_e_size;\n\tduk_uint32_t new_a_size;\n\tduk_uint32_t new_h_size;\n\tduk_uint32_t e_used;  /* actually used, non-NULL keys */\n\tduk_uint32_t a_used;\n\tduk_uint32_t a_size;\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(obj != NULL);\n\n\te_used = duk__count_used_e_keys(thr, obj);\n\tduk__compute_a_stats(thr, obj, &a_used, &a_size);\n\n\t/*\n\t *  Must guarantee all actually used array entries will fit into\n\t *  new entry part.  Add one growth step to ensure we don't run out\n\t *  of space right away.\n\t */\n\n\tnew_e_size = e_used + a_used;\n\tnew_e_size = new_e_size + duk__get_min_grow_e(new_e_size);\n\tnew_a_size = 0;\n#if defined(DUK_USE_HOBJECT_HASH_PART)\n\tnew_h_size = duk__get_default_h_size(new_e_size);\n#else\n\tnew_h_size = 0;\n#endif\n\n\tDUK_DD(DUK_DDPRINT(\"abandon array part for hobject %p, \"\n\t                   \"array stats before: e_used=%ld, a_used=%ld, a_size=%ld; \"\n\t                   \"resize to e_size=%ld, a_size=%ld, h_size=%ld\",\n\t                   (void *) obj, (long) e_used, (long) a_used, (long) a_size,\n\t                   (long) new_e_size, (long) new_a_size, (long) new_h_size));\n\n\tduk_hobject_realloc_props(thr, obj, new_e_size, new_a_size, new_h_size, 1);\n}\n\n/*\n *  Compact an object.  Minimizes allocation size for objects which are\n *  not likely to be extended.  This is useful for internal and non-\n *  extensible objects, but can also be called for non-extensible objects.\n *  May abandon the array part if it is computed to be too sparse.\n *\n *  This call is relatively expensive, as it needs to scan both the\n *  entries and the array part.\n *\n *  The call may fail due to allocation error.\n */\n\nDUK_INTERNAL void duk_hobject_compact_props(duk_hthread *thr, duk_hobject *obj) {\n\tduk_uint32_t e_size;       /* currently used -> new size */\n\tduk_uint32_t a_size;       /* currently required */\n\tduk_uint32_t a_used;       /* actually used */\n\tduk_uint32_t h_size;\n\tduk_bool_t abandon_array;\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(obj != NULL);\n\n#if defined(DUK_USE_ROM_OBJECTS)\n\tif (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj)) {\n\t\tDUK_DD(DUK_DDPRINT(\"ignore attempt to compact a rom object\"));\n\t\treturn;\n\t}\n#endif\n\n\te_size = duk__count_used_e_keys(thr, obj);\n\tduk__compute_a_stats(thr, obj, &a_used, &a_size);\n\n\tDUK_DD(DUK_DDPRINT(\"compacting hobject, used e keys %ld, used a keys %ld, min a size %ld, \"\n\t                   \"resized array density would be: %ld/%ld = %lf\",\n\t                   (long) e_size, (long) a_used, (long) a_size,\n\t                   (long) a_used, (long) a_size,\n\t                   (double) a_used / (double) a_size));\n\n\tif (duk__abandon_array_density_check(a_used, a_size)) {\n\t\tDUK_DD(DUK_DDPRINT(\"decided to abandon array during compaction, a_used=%ld, a_size=%ld\",\n\t\t                   (long) a_used, (long) a_size));\n\t\tabandon_array = 1;\n\t\te_size += a_used;\n\t\ta_size = 0;\n\t} else {\n\t\tDUK_DD(DUK_DDPRINT(\"decided to keep array during compaction\"));\n\t\tabandon_array = 0;\n\t}\n\n#if defined(DUK_USE_HOBJECT_HASH_PART)\n\tif (e_size >= DUK_USE_HOBJECT_HASH_PROP_LIMIT) {\n\t\th_size = duk__get_default_h_size(e_size);\n\t} else {\n\t\th_size = 0;\n\t}\n#else\n\th_size = 0;\n#endif\n\n\tDUK_DD(DUK_DDPRINT(\"compacting hobject -> new e_size %ld, new a_size=%ld, new h_size=%ld, abandon_array=%ld\",\n\t                   (long) e_size, (long) a_size, (long) h_size, (long) abandon_array));\n\n\tduk_hobject_realloc_props(thr, obj, e_size, a_size, h_size, abandon_array);\n}\n\n/*\n *  Find an existing key from entry part either by linear scan or by\n *  using the hash index (if it exists).\n *\n *  Sets entry index (and possibly the hash index) to output variables,\n *  which allows the caller to update the entry and hash entries in-place.\n *  If entry is not found, both values are set to -1.  If entry is found\n *  but there is no hash part, h_idx is set to -1.\n */\n\nDUK_INTERNAL duk_bool_t duk_hobject_find_existing_entry(duk_heap *heap, duk_hobject *obj, duk_hstring *key, duk_int_t *e_idx, duk_int_t *h_idx) {\n\tDUK_ASSERT(obj != NULL);\n\tDUK_ASSERT(key != NULL);\n\tDUK_ASSERT(e_idx != NULL);\n\tDUK_ASSERT(h_idx != NULL);\n\tDUK_UNREF(heap);\n\n\tif (DUK_LIKELY(DUK_HOBJECT_GET_HSIZE(obj) == 0))\n\t{\n\t\t/* Linear scan: more likely because most objects are small.\n\t\t * This is an important fast path.\n\t\t *\n\t\t * XXX: this might be worth inlining for property lookups.\n\t\t */\n\t\tduk_uint_fast32_t i;\n\t\tduk_uint_fast32_t n;\n\t\tduk_hstring **h_keys_base;\n\t\tDUK_DDD(DUK_DDDPRINT(\"duk_hobject_find_existing_entry() using linear scan for lookup\"));\n\n\t\th_keys_base = DUK_HOBJECT_E_GET_KEY_BASE(heap, obj);\n\t\tn = DUK_HOBJECT_GET_ENEXT(obj);\n\t\tfor (i = 0; i < n; i++) {\n\t\t\tif (h_keys_base[i] == key) {\n\t\t\t\t*e_idx = (duk_int_t) i;\n\t\t\t\t*h_idx = -1;\n\t\t\t\treturn 1;\n\t\t\t}\n\t\t}\n\t}\n#if defined(DUK_USE_HOBJECT_HASH_PART)\n\telse\n\t{\n\t\t/* hash lookup */\n\t\tduk_uint32_t n;\n\t\tduk_uint32_t i, step;\n\t\tduk_uint32_t *h_base;\n\t\tduk_uint32_t mask;\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"duk_hobject_find_existing_entry() using hash part for lookup\"));\n\n\t\th_base = DUK_HOBJECT_H_GET_BASE(heap, obj);\n\t\tn = DUK_HOBJECT_GET_HSIZE(obj);\n\t\tmask = n - 1;\n\t\ti = DUK_HSTRING_GET_HASH(key) & mask;\n\t\tstep = 1;  /* Cache friendly but clustering prone. */\n\n\t\tfor (;;) {\n\t\t\tduk_uint32_t t;\n\n\t\t\tDUK_ASSERT_DISABLE(i >= 0);  /* unsigned */\n\t\t\tDUK_ASSERT(i < DUK_HOBJECT_GET_HSIZE(obj));\n\t\t\tt = h_base[i];\n\t\t\tDUK_ASSERT(t == DUK__HASH_UNUSED || t == DUK__HASH_DELETED ||\n\t\t\t           (t < DUK_HOBJECT_GET_ESIZE(obj)));  /* t >= 0 always true, unsigned */\n\n\t\t\tif (t == DUK__HASH_UNUSED) {\n\t\t\t\tbreak;\n\t\t\t} else if (t == DUK__HASH_DELETED) {\n\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"lookup miss (deleted) i=%ld, t=%ld\",\n\t\t\t\t                     (long) i, (long) t));\n\t\t\t} else {\n\t\t\t\tDUK_ASSERT(t < DUK_HOBJECT_GET_ESIZE(obj));\n\t\t\t\tif (DUK_HOBJECT_E_GET_KEY(heap, obj, t) == key) {\n\t\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"lookup hit i=%ld, t=%ld -> key %p\",\n\t\t\t\t\t                     (long) i, (long) t, (void *) key));\n\t\t\t\t\t*e_idx = (duk_int_t) t;\n\t\t\t\t\t*h_idx = (duk_int_t) i;\n\t\t\t\t\treturn 1;\n\t\t\t\t}\n\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"lookup miss i=%ld, t=%ld\",\n\t\t\t\t                     (long) i, (long) t));\n\t\t\t}\n\t\t\ti = (i + step) & mask;\n\n\t\t\t/* Guaranteed to finish (hash is larger than #props). */\n\t\t}\n\t}\n#endif  /* DUK_USE_HOBJECT_HASH_PART */\n\n\t/* Not found, leave e_idx and h_idx unset. */\n\treturn 0;\n}\n\n/* For internal use: get non-accessor entry value */\nDUK_INTERNAL duk_tval *duk_hobject_find_existing_entry_tval_ptr(duk_heap *heap, duk_hobject *obj, duk_hstring *key) {\n\tduk_int_t e_idx;\n\tduk_int_t h_idx;\n\n\tDUK_ASSERT(obj != NULL);\n\tDUK_ASSERT(key != NULL);\n\tDUK_UNREF(heap);\n\n\tif (duk_hobject_find_existing_entry(heap, obj, key, &e_idx, &h_idx)) {\n\t\tDUK_ASSERT(e_idx >= 0);\n\t\tif (!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(heap, obj, e_idx)) {\n\t\t\treturn DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(heap, obj, e_idx);\n\t\t}\n\t}\n\treturn NULL;\n}\n\n/* For internal use: get non-accessor entry value and attributes */\nDUK_INTERNAL duk_tval *duk_hobject_find_existing_entry_tval_ptr_and_attrs(duk_heap *heap, duk_hobject *obj, duk_hstring *key, duk_uint_t *out_attrs) {\n\tduk_int_t e_idx;\n\tduk_int_t h_idx;\n\n\tDUK_ASSERT(obj != NULL);\n\tDUK_ASSERT(key != NULL);\n\tDUK_ASSERT(out_attrs != NULL);\n\tDUK_UNREF(heap);\n\n\tif (duk_hobject_find_existing_entry(heap, obj, key, &e_idx, &h_idx)) {\n\t\tDUK_ASSERT(e_idx >= 0);\n\t\tif (!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(heap, obj, e_idx)) {\n\t\t\t*out_attrs = DUK_HOBJECT_E_GET_FLAGS(heap, obj, e_idx);\n\t\t\treturn DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(heap, obj, e_idx);\n\t\t}\n\t}\n\t/* If not found, out_attrs is left unset. */\n\treturn NULL;\n}\n\n/* For internal use: get array part value */\nDUK_INTERNAL duk_tval *duk_hobject_find_existing_array_entry_tval_ptr(duk_heap *heap, duk_hobject *obj, duk_uarridx_t i) {\n\tduk_tval *tv;\n\n\tDUK_ASSERT(obj != NULL);\n\tDUK_UNREF(heap);\n\n\tif (!DUK_HOBJECT_HAS_ARRAY_PART(obj)) {\n\t\treturn NULL;\n\t}\n\tif (i >= DUK_HOBJECT_GET_ASIZE(obj)) {\n\t\treturn NULL;\n\t}\n\ttv = DUK_HOBJECT_A_GET_VALUE_PTR(heap, obj, i);\n\treturn tv;\n}\n\n/*\n *  Allocate and initialize a new entry, resizing the properties allocation\n *  if necessary.  Returns entry index (e_idx) or throws an error if alloc fails.\n *\n *  Sets the key of the entry (increasing the key's refcount), and updates\n *  the hash part if it exists.  Caller must set value and flags, and update\n *  the entry value refcount.  A decref for the previous value is not necessary.\n */\n\nDUK_LOCAL duk_int_t duk__hobject_alloc_entry_checked(duk_hthread *thr, duk_hobject *obj, duk_hstring *key) {\n\tduk_uint32_t idx;\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(obj != NULL);\n\tDUK_ASSERT(key != NULL);\n\tDUK_ASSERT(DUK_HOBJECT_GET_ENEXT(obj) <= DUK_HOBJECT_GET_ESIZE(obj));\n\n#if defined(DUK_USE_ASSERTIONS)\n\t/* key must not already exist in entry part */\n\t{\n\t\tduk_uint_fast32_t i;\n\t\tfor (i = 0; i < DUK_HOBJECT_GET_ENEXT(obj); i++) {\n\t\t\tDUK_ASSERT(DUK_HOBJECT_E_GET_KEY(thr->heap, obj, i) != key);\n\t\t}\n\t}\n#endif\n\n\tif (DUK_HOBJECT_GET_ENEXT(obj) >= DUK_HOBJECT_GET_ESIZE(obj)) {\n\t\t/* only need to guarantee 1 more slot, but allocation growth is in chunks */\n\t\tDUK_DDD(DUK_DDDPRINT(\"entry part full, allocate space for one more entry\"));\n\t\tduk__grow_props_for_new_entry_item(thr, obj);\n\t}\n\tDUK_ASSERT(DUK_HOBJECT_GET_ENEXT(obj) < DUK_HOBJECT_GET_ESIZE(obj));\n\tidx = DUK_HOBJECT_POSTINC_ENEXT(obj);\n\n\t/* previous value is assumed to be garbage, so don't touch it */\n\tDUK_HOBJECT_E_SET_KEY(thr->heap, obj, idx, key);\n\tDUK_HSTRING_INCREF(thr, key);\n\n#if defined(DUK_USE_HOBJECT_HASH_PART)\n\tif (DUK_UNLIKELY(DUK_HOBJECT_GET_HSIZE(obj) > 0)) {\n\t\tduk_uint32_t n, mask;\n\t\tduk_uint32_t i, step;\n\t\tduk_uint32_t *h_base = DUK_HOBJECT_H_GET_BASE(thr->heap, obj);\n\n\t\tn = DUK_HOBJECT_GET_HSIZE(obj);\n\t\tmask = n - 1;\n\t\ti = DUK_HSTRING_GET_HASH(key) & mask;\n\t\tstep = 1;  /* Cache friendly but clustering prone. */\n\n\t\tfor (;;) {\n\t\t\tduk_uint32_t t = h_base[i];\n\t\t\tif (t == DUK__HASH_UNUSED || t == DUK__HASH_DELETED) {\n\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"duk__hobject_alloc_entry_checked() inserted key into hash part, %ld -> %ld\",\n\t\t\t\t                     (long) i, (long) idx));\n\t\t\t\tDUK_ASSERT_DISABLE(i >= 0);  /* unsigned */\n\t\t\t\tDUK_ASSERT(i < DUK_HOBJECT_GET_HSIZE(obj));\n\t\t\t\tDUK_ASSERT_DISABLE(idx >= 0);\n\t\t\t\tDUK_ASSERT(idx < DUK_HOBJECT_GET_ESIZE(obj));\n\t\t\t\th_base[i] = idx;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"duk__hobject_alloc_entry_checked() miss %ld\", (long) i));\n\t\t\ti = (i + step) & mask;\n\n\t\t\t/* Guaranteed to finish (hash is larger than #props). */\n\t\t}\n\t}\n#endif  /* DUK_USE_HOBJECT_HASH_PART */\n\n\t/* Note: we could return the hash index here too, but it's not\n\t * needed right now.\n\t */\n\n\tDUK_ASSERT_DISABLE(idx >= 0);\n\tDUK_ASSERT(idx < DUK_HOBJECT_GET_ESIZE(obj));\n\tDUK_ASSERT(idx < DUK_HOBJECT_GET_ENEXT(obj));\n\treturn (duk_int_t) idx;\n}\n\n/*\n *  Object internal value\n *\n *  Returned value is guaranteed to be reachable / incref'd, caller does not need\n *  to incref OR decref.  No proxies or accessors are invoked, no prototype walk.\n */\n\nDUK_INTERNAL duk_bool_t duk_hobject_get_internal_value(duk_heap *heap, duk_hobject *obj, duk_tval *tv_out) {\n\tduk_int_t e_idx;\n\tduk_int_t h_idx;\n\n\tDUK_ASSERT(heap != NULL);\n\tDUK_ASSERT(obj != NULL);\n\tDUK_ASSERT(tv_out != NULL);\n\n\t/* Always in entry part, no need to look up parents etc. */\n\tif (duk_hobject_find_existing_entry(heap, obj, DUK_HEAP_STRING_INT_VALUE(heap), &e_idx, &h_idx)) {\n\t\tDUK_ASSERT(e_idx >= 0);\n\t\tDUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(heap, obj, e_idx));\n\t\tDUK_TVAL_SET_TVAL(tv_out, DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(heap, obj, e_idx));\n\t\treturn 1;\n\t}\n\tDUK_TVAL_SET_UNDEFINED(tv_out);\n\treturn 0;\n}\n\nDUK_INTERNAL duk_hstring *duk_hobject_get_internal_value_string(duk_heap *heap, duk_hobject *obj) {\n\tduk_tval tv;\n\n\tDUK_ASSERT(heap != NULL);\n\tDUK_ASSERT(obj != NULL);\n\n\t/* This is not strictly necessary, but avoids compiler warnings; e.g.\n\t * gcc won't reliably detect that no uninitialized data is read below.\n\t */\n\tDUK_MEMZERO((void *) &tv, sizeof(duk_tval));\n\n\tif (duk_hobject_get_internal_value(heap, obj, &tv)) {\n\t\tduk_hstring *h;\n\t\tDUK_ASSERT(DUK_TVAL_IS_STRING(&tv));\n\t\th = DUK_TVAL_GET_STRING(&tv);\n\t\t/* No explicit check for string vs. symbol, accept both. */\n\t\treturn h;\n\t}\n\n\treturn NULL;\n}\n\n/*\n *  Arguments handling helpers (argument map mainly).\n *\n *  An arguments object has exotic behavior for some numeric indices.\n *  Accesses may translate to identifier operations which may have\n *  arbitrary side effects (potentially invalidating any duk_tval\n *  pointers).\n */\n\n/* Lookup 'key' from arguments internal 'map', perform a variable lookup\n * if mapped, and leave the result on top of stack (and return non-zero).\n * Used in E5 Section 10.6 algorithms [[Get]] and [[GetOwnProperty]].\n */\nDUK_LOCAL\nduk_bool_t duk__lookup_arguments_map(duk_hthread *thr,\n                                     duk_hobject *obj,\n                                     duk_hstring *key,\n                                     duk_propdesc *temp_desc,\n                                     duk_hobject **out_map,\n                                     duk_hobject **out_varenv) {\n\tduk_hobject *map;\n\tduk_hobject *varenv;\n\tduk_bool_t rc;\n\n\tDUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);\n\n\tDUK_DDD(DUK_DDDPRINT(\"arguments map lookup: thr=%p, obj=%p, key=%p, temp_desc=%p \"\n\t                     \"(obj -> %!O, key -> %!O)\",\n\t                     (void *) thr, (void *) obj, (void *) key, (void *) temp_desc,\n\t                     (duk_heaphdr *) obj, (duk_heaphdr *) key));\n\n\tif (!duk_hobject_get_own_propdesc(thr, obj, DUK_HTHREAD_STRING_INT_MAP(thr), temp_desc, DUK_GETDESC_FLAG_PUSH_VALUE)) {\n\t\tDUK_DDD(DUK_DDDPRINT(\"-> no 'map'\"));\n\t\treturn 0;\n\t}\n\n\tmap = duk_require_hobject(thr, -1);\n\tDUK_ASSERT(map != NULL);\n\tduk_pop_unsafe(thr);  /* map is reachable through obj */\n\n\tif (!duk_hobject_get_own_propdesc(thr, map, key, temp_desc, DUK_GETDESC_FLAG_PUSH_VALUE)) {\n\t\tDUK_DDD(DUK_DDDPRINT(\"-> 'map' exists, but key not in map\"));\n\t\treturn 0;\n\t}\n\n\t/* [... varname] */\n\tDUK_DDD(DUK_DDDPRINT(\"-> 'map' exists, and contains key, key is mapped to argument/variable binding %!T\",\n\t                     (duk_tval *) duk_get_tval(thr, -1)));\n\tDUK_ASSERT(duk_is_string(thr, -1));  /* guaranteed when building arguments */\n\n\t/* get varenv for varname (callee's declarative lexical environment) */\n\trc = duk_hobject_get_own_propdesc(thr, obj, DUK_HTHREAD_STRING_INT_VARENV(thr), temp_desc, DUK_GETDESC_FLAG_PUSH_VALUE);\n\tDUK_UNREF(rc);\n\tDUK_ASSERT(rc != 0);  /* arguments MUST have an initialized lexical environment reference */\n\tvarenv = duk_require_hobject(thr, -1);\n\tDUK_ASSERT(varenv != NULL);\n\tduk_pop_unsafe(thr);  /* varenv remains reachable through 'obj' */\n\n\tDUK_DDD(DUK_DDDPRINT(\"arguments varenv is: %!dO\", (duk_heaphdr *) varenv));\n\n\t/* success: leave varname in stack */\n\t*out_map = map;\n\t*out_varenv = varenv;\n\treturn 1;  /* [... varname] */\n}\n\n/* Lookup 'key' from arguments internal 'map', and leave replacement value\n * on stack top if mapped (and return non-zero).\n * Used in E5 Section 10.6 algorithm for [[GetOwnProperty]] (used by [[Get]]).\n */\nDUK_LOCAL duk_bool_t duk__check_arguments_map_for_get(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_propdesc *temp_desc) {\n\tduk_hobject *map;\n\tduk_hobject *varenv;\n\tduk_hstring *varname;\n\n\tDUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);\n\n\tif (!duk__lookup_arguments_map(thr, obj, key, temp_desc, &map, &varenv)) {\n\t\tDUK_DDD(DUK_DDDPRINT(\"arguments: key not mapped, no exotic get behavior\"));\n\t\treturn 0;\n\t}\n\n\t/* [... varname] */\n\n\tvarname = duk_require_hstring(thr, -1);\n\tDUK_ASSERT(varname != NULL);\n\tduk_pop_unsafe(thr);  /* varname is still reachable */\n\n\tDUK_DDD(DUK_DDDPRINT(\"arguments object automatic getvar for a bound variable; \"\n\t                     \"key=%!O, varname=%!O\",\n\t                     (duk_heaphdr *) key,\n\t                     (duk_heaphdr *) varname));\n\n\t(void) duk_js_getvar_envrec(thr, varenv, varname, 1 /*throw*/);\n\n\t/* [... value this_binding] */\n\n\tduk_pop_unsafe(thr);\n\n\t/* leave result on stack top */\n\treturn 1;\n}\n\n/* Lookup 'key' from arguments internal 'map', perform a variable write if mapped.\n * Used in E5 Section 10.6 algorithm for [[DefineOwnProperty]] (used by [[Put]]).\n * Assumes stack top contains 'put' value (which is NOT popped).\n */\nDUK_LOCAL void duk__check_arguments_map_for_put(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_propdesc *temp_desc, duk_bool_t throw_flag) {\n\tduk_hobject *map;\n\tduk_hobject *varenv;\n\tduk_hstring *varname;\n\n\tDUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);\n\n\tif (!duk__lookup_arguments_map(thr, obj, key, temp_desc, &map, &varenv)) {\n\t\tDUK_DDD(DUK_DDDPRINT(\"arguments: key not mapped, no exotic put behavior\"));\n\t\treturn;\n\t}\n\n\t/* [... put_value varname] */\n\n\tvarname = duk_require_hstring(thr, -1);\n\tDUK_ASSERT(varname != NULL);\n\tduk_pop_unsafe(thr);  /* varname is still reachable */\n\n\tDUK_DDD(DUK_DDDPRINT(\"arguments object automatic putvar for a bound variable; \"\n\t                     \"key=%!O, varname=%!O, value=%!T\",\n\t                     (duk_heaphdr *) key,\n\t                     (duk_heaphdr *) varname,\n\t                     (duk_tval *) duk_require_tval(thr, -1)));\n\n\t/* [... put_value] */\n\n\t/*\n\t *  Note: although arguments object variable mappings are only established\n\t *  for non-strict functions (and a call to a non-strict function created\n\t *  the arguments object in question), an inner strict function may be doing\n\t *  the actual property write.  Hence the throw_flag applied here comes from\n\t *  the property write call.\n\t */\n\n\tduk_js_putvar_envrec(thr, varenv, varname, duk_require_tval(thr, -1), throw_flag);\n\n\t/* [... put_value] */\n}\n\n/* Lookup 'key' from arguments internal 'map', delete mapping if found.\n * Used in E5 Section 10.6 algorithm for [[Delete]].  Note that the\n * variable/argument itself (where the map points) is not deleted.\n */\nDUK_LOCAL void duk__check_arguments_map_for_delete(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_propdesc *temp_desc) {\n\tduk_hobject *map;\n\n\tDUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);\n\n\tif (!duk_hobject_get_own_propdesc(thr, obj, DUK_HTHREAD_STRING_INT_MAP(thr), temp_desc, DUK_GETDESC_FLAG_PUSH_VALUE)) {\n\t\tDUK_DDD(DUK_DDDPRINT(\"arguments: key not mapped, no exotic delete behavior\"));\n\t\treturn;\n\t}\n\n\tmap = duk_require_hobject(thr, -1);\n\tDUK_ASSERT(map != NULL);\n\tduk_pop_unsafe(thr);  /* map is reachable through obj */\n\n\tDUK_DDD(DUK_DDDPRINT(\"-> have 'map', delete key %!O from map (if exists)); ignore result\",\n\t                     (duk_heaphdr *) key));\n\n\t/* Note: no recursion issue, we can trust 'map' to behave */\n\tDUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_BEHAVIOR(map));\n\tDUK_DDD(DUK_DDDPRINT(\"map before deletion: %!O\", (duk_heaphdr *) map));\n\t(void) duk_hobject_delprop_raw(thr, map, key, 0);  /* ignore result */\n\tDUK_DDD(DUK_DDDPRINT(\"map after deletion: %!O\", (duk_heaphdr *) map));\n}\n\n/*\n *  Ecmascript compliant [[GetOwnProperty]](P), for internal use only.\n *\n *  If property is found:\n *    - Fills descriptor fields to 'out_desc'\n *    - If DUK_GETDESC_FLAG_PUSH_VALUE is set, pushes a value related to the\n *      property onto the stack ('undefined' for accessor properties).\n *    - Returns non-zero\n *\n *  If property is not found:\n *    - 'out_desc' is left in untouched state (possibly garbage)\n *    - Nothing is pushed onto the stack (not even with DUK_GETDESC_FLAG_PUSH_VALUE\n *      set)\n *    - Returns zero\n *\n *  Notes:\n *\n *    - Getting a property descriptor may cause an allocation (and hence\n *      GC) to take place, hence reachability and refcount of all related\n *      values matter.  Reallocation of value stack, properties, etc may\n *      invalidate many duk_tval pointers (concretely, those which reside\n *      in memory areas subject to reallocation).  However, heap object\n *      pointers are never affected (heap objects have stable pointers).\n *\n *    - The value of a plain property is always reachable and has a non-zero\n *      reference count.\n *\n *    - The value of a virtual property is not necessarily reachable from\n *      elsewhere and may have a refcount of zero.  Hence we push it onto\n *      the valstack for the caller, which ensures it remains reachable\n *      while it is needed.\n *\n *    - There are no virtual accessor properties.  Hence, all getters and\n *      setters are always related to concretely stored properties, which\n *      ensures that the get/set functions in the resulting descriptor are\n *      reachable and have non-zero refcounts.  Should there be virtual\n *      accessor properties later, this would need to change.\n */\n\nDUK_LOCAL duk_bool_t duk__get_own_propdesc_raw(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_uint32_t arr_idx, duk_propdesc *out_desc, duk_small_uint_t flags) {\n\tduk_tval *tv;\n\n\tDUK_DDD(DUK_DDDPRINT(\"duk_hobject_get_own_propdesc: thr=%p, obj=%p, key=%p, out_desc=%p, flags=%lx, \"\n\t                     \"arr_idx=%ld (obj -> %!O, key -> %!O)\",\n\t                     (void *) thr, (void *) obj, (void *) key, (void *) out_desc,\n\t                     (long) flags, (long) arr_idx,\n\t                     (duk_heaphdr *) obj, (duk_heaphdr *) key));\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(thr->heap != NULL);\n\tDUK_ASSERT(obj != NULL);\n\tDUK_ASSERT(key != NULL);\n\tDUK_ASSERT(out_desc != NULL);\n\tDUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);\n\n\tDUK_STATS_INC(thr->heap, stats_getownpropdesc_count);\n\n\t/* Each code path returning 1 (= found) must fill in all the output\n\t * descriptor fields.  We don't do it beforehand because it'd be\n\t * unnecessary work if the property isn't found and would happen\n\t * multiple times for an inheritance chain.\n\t */\n\tDUK_ASSERT_SET_GARBAGE(out_desc, sizeof(*out_desc));\n#if 0\n\tout_desc->flags = 0;\n\tout_desc->get = NULL;\n\tout_desc->set = NULL;\n\tout_desc->e_idx = -1;\n\tout_desc->h_idx = -1;\n\tout_desc->a_idx = -1;\n#endif\n\n\t/*\n\t *  Try entries part first because it's the common case.\n\t *\n\t *  Array part lookups are usually handled by the array fast path, and\n\t *  are not usually inherited.  Array and entry parts never contain the\n\t *  same keys so the entry part vs. array part order doesn't matter.\n\t */\n\n\tif (duk_hobject_find_existing_entry(thr->heap, obj, key, &out_desc->e_idx, &out_desc->h_idx)) {\n\t\tduk_int_t e_idx = out_desc->e_idx;\n\t\tDUK_ASSERT(out_desc->e_idx >= 0);\n\t\tout_desc->a_idx = -1;\n\t\tout_desc->flags = DUK_HOBJECT_E_GET_FLAGS(thr->heap, obj, e_idx);\n\t\tout_desc->get = NULL;\n\t\tout_desc->set = NULL;\n\t\tif (DUK_UNLIKELY(out_desc->flags & DUK_PROPDESC_FLAG_ACCESSOR)) {\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"-> found accessor property in entry part\"));\n\t\t\tout_desc->get = DUK_HOBJECT_E_GET_VALUE_GETTER(thr->heap, obj, e_idx);\n\t\t\tout_desc->set = DUK_HOBJECT_E_GET_VALUE_SETTER(thr->heap, obj, e_idx);\n\t\t\tif (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {\n\t\t\t\t/* a dummy undefined value is pushed to make valstack\n\t\t\t\t * behavior uniform for caller\n\t\t\t\t */\n\t\t\t\tduk_push_undefined(thr);\n\t\t\t}\n\t\t} else {\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"-> found plain property in entry part\"));\n\t\t\ttv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, e_idx);\n\t\t\tif (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {\n\t\t\t\tduk_push_tval(thr, tv);\n\t\t\t}\n\t\t}\n\t\tgoto prop_found;\n\t}\n\n\t/*\n\t *  Try array part.\n\t */\n\n\tif (DUK_HOBJECT_HAS_ARRAY_PART(obj) && arr_idx != DUK__NO_ARRAY_INDEX) {\n\t\tif (arr_idx < DUK_HOBJECT_GET_ASIZE(obj)) {\n\t\t\ttv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, arr_idx);\n\t\t\tif (!DUK_TVAL_IS_UNUSED(tv)) {\n\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"-> found in array part\"));\n\t\t\t\tif (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {\n\t\t\t\t\tduk_push_tval(thr, tv);\n\t\t\t\t}\n\t\t\t\t/* implicit attributes */\n\t\t\t\tout_desc->flags = DUK_PROPDESC_FLAG_WRITABLE |\n\t\t\t\t                  DUK_PROPDESC_FLAG_CONFIGURABLE |\n\t\t\t\t                  DUK_PROPDESC_FLAG_ENUMERABLE;\n\t\t\t\tout_desc->get = NULL;\n\t\t\t\tout_desc->set = NULL;\n\t\t\t\tout_desc->e_idx = -1;\n\t\t\t\tout_desc->h_idx = -1;\n\t\t\t\tout_desc->a_idx = (duk_int_t) arr_idx;  /* XXX: limit 2G due to being signed */\n\t\t\t\tgoto prop_found;\n\t\t\t}\n\t\t}\n\t}\n\n\tDUK_DDD(DUK_DDDPRINT(\"-> not found as a concrete property\"));\n\n\t/*\n\t *  Not found as a concrete property, check for virtual properties.\n\t */\n\n\tif (!DUK_HOBJECT_HAS_VIRTUAL_PROPERTIES(obj)) {\n\t\t/* Quick skip. */\n\t\tgoto prop_not_found;\n\t}\n\n\tif (DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj)) {\n\t\tduk_harray *a;\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"array object exotic property get for key: %!O, arr_idx: %ld\",\n\t\t                     (duk_heaphdr *) key, (long) arr_idx));\n\n\t\ta = (duk_harray *) obj;\n\t\tDUK_ASSERT_HARRAY_VALID(a);\n\n\t\tif (key == DUK_HTHREAD_STRING_LENGTH(thr)) {\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"-> found, key is 'length', length exotic behavior\"));\n\n\t\t\tif (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {\n\t\t\t\tduk_push_uint(thr, (duk_uint_t) a->length);\n\t\t\t}\n\t\t\tout_desc->flags = DUK_PROPDESC_FLAG_VIRTUAL;\n\t\t\tif (DUK_HARRAY_LENGTH_WRITABLE(a)) {\n\t\t\t\tout_desc->flags |= DUK_PROPDESC_FLAG_WRITABLE;\n\t\t\t}\n\t\t\tout_desc->get = NULL;\n\t\t\tout_desc->set = NULL;\n\t\t\tout_desc->e_idx = -1;\n\t\t\tout_desc->h_idx = -1;\n\t\t\tout_desc->a_idx = -1;\n\n\t\t\tDUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj));\n\t\t\tgoto prop_found_noexotic;  /* cannot be arguments exotic */\n\t\t}\n\t} else if (DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(obj)) {\n\t\tDUK_DDD(DUK_DDDPRINT(\"string object exotic property get for key: %!O, arr_idx: %ld\",\n\t\t                     (duk_heaphdr *) key, (long) arr_idx));\n\n\t\t/* XXX: charlen; avoid multiple lookups? */\n\n\t\tif (arr_idx != DUK__NO_ARRAY_INDEX) {\n\t\t\tduk_hstring *h_val;\n\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"array index exists\"));\n\n\t\t\th_val = duk_hobject_get_internal_value_string(thr->heap, obj);\n\t\t\tDUK_ASSERT(h_val);\n\t\t\tif (arr_idx < DUK_HSTRING_GET_CHARLEN(h_val)) {\n\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"-> found, array index inside string\"));\n\t\t\t\tif (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {\n\t\t\t\t\tduk_push_hstring(thr, h_val);\n\t\t\t\t\tduk_substring(thr, -1, arr_idx, arr_idx + 1);  /* [str] -> [substr] */\n\t\t\t\t}\n\t\t\t\tout_desc->flags = DUK_PROPDESC_FLAG_ENUMERABLE |  /* E5 Section 15.5.5.2 */\n\t\t\t\t                  DUK_PROPDESC_FLAG_VIRTUAL;\n\t\t\t\tout_desc->get = NULL;\n\t\t\t\tout_desc->set = NULL;\n\t\t\t\tout_desc->e_idx = -1;\n\t\t\t\tout_desc->h_idx = -1;\n\t\t\t\tout_desc->a_idx = -1;\n\n\t\t\t\tDUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj));\n\t\t\t\tgoto prop_found_noexotic;  /* cannot be arguments exotic */\n\t\t\t} else {\n\t\t\t\t/* index is above internal string length -> property is fully normal */\n\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"array index outside string -> normal property\"));\n\t\t\t}\n\t\t} else if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {\n\t\t\tduk_hstring *h_val;\n\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"-> found, key is 'length', length exotic behavior\"));\n\n\t\t\th_val = duk_hobject_get_internal_value_string(thr->heap, obj);\n\t\t\tDUK_ASSERT(h_val != NULL);\n\t\t\tif (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {\n\t\t\t\tduk_push_uint(thr, (duk_uint_t) DUK_HSTRING_GET_CHARLEN(h_val));\n\t\t\t}\n\t\t\tout_desc->flags = DUK_PROPDESC_FLAG_VIRTUAL;  /* E5 Section 15.5.5.1 */\n\t\t\tout_desc->get = NULL;\n\t\t\tout_desc->set = NULL;\n\t\t\tout_desc->e_idx = -1;\n\t\t\tout_desc->h_idx = -1;\n\t\t\tout_desc->a_idx = -1;\n\n\t\t\tDUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj));\n\t\t\tgoto prop_found_noexotic;  /* cannot be arguments exotic */\n\t\t}\n\t}\n#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)\n\telse if (DUK_HOBJECT_IS_BUFOBJ(obj)) {\n\t\tduk_hbufobj *h_bufobj;\n\t\tduk_uint_t byte_off;\n\t\tduk_small_uint_t elem_size;\n\n\t\th_bufobj = (duk_hbufobj *) obj;\n\t\tDUK_ASSERT_HBUFOBJ_VALID(h_bufobj);\n\t\tDUK_DDD(DUK_DDDPRINT(\"bufobj property get for key: %!O, arr_idx: %ld\",\n\t\t                     (duk_heaphdr *) key, (long) arr_idx));\n\n\t\tif (arr_idx != DUK__NO_ARRAY_INDEX && DUK_HBUFOBJ_HAS_VIRTUAL_INDICES(h_bufobj)) {\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"array index exists\"));\n\n\t\t\t/* Careful with wrapping: arr_idx upshift may easily wrap, whereas\n\t\t\t * length downshift won't.\n\t\t\t */\n\t\t\tif (arr_idx < (h_bufobj->length >> h_bufobj->shift)) {\n\t\t\t\tbyte_off = arr_idx << h_bufobj->shift;  /* no wrap assuming h_bufobj->length is valid */\n\t\t\t\telem_size = (duk_small_uint_t) (1U << h_bufobj->shift);\n\t\t\t\tif (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {\n\t\t\t\t\tduk_uint8_t *data;\n\n\t\t\t\t\tif (h_bufobj->buf != NULL && DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h_bufobj, byte_off + elem_size)) {\n\t\t\t\t\t\tdata = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufobj->buf) + h_bufobj->offset + byte_off;\n\t\t\t\t\t\tduk_hbufobj_push_validated_read(thr, h_bufobj, data, elem_size);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tDUK_D(DUK_DPRINT(\"bufobj access out of underlying buffer, ignoring (read zero)\"));\n\t\t\t\t\t\tduk_push_uint(thr, 0);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tout_desc->flags = DUK_PROPDESC_FLAG_WRITABLE |\n\t\t\t\t                  DUK_PROPDESC_FLAG_VIRTUAL;\n\t\t\t\tif (DUK_HOBJECT_GET_CLASS_NUMBER(obj) != DUK_HOBJECT_CLASS_ARRAYBUFFER) {\n\t\t\t\t\t/* ArrayBuffer indices are non-standard and are\n\t\t\t\t\t * non-enumerable to avoid their serialization.\n\t\t\t\t\t */\n\t\t\t\t\tout_desc->flags |= DUK_PROPDESC_FLAG_ENUMERABLE;\n\t\t\t\t}\n\t\t\t\tout_desc->get = NULL;\n\t\t\t\tout_desc->set = NULL;\n\t\t\t\tout_desc->e_idx = -1;\n\t\t\t\tout_desc->h_idx = -1;\n\t\t\t\tout_desc->a_idx = -1;\n\n\t\t\t\tDUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj));\n\t\t\t\tgoto prop_found_noexotic;  /* cannot be e.g. arguments exotic, since exotic 'traits' are mutually exclusive */\n\t\t\t} else {\n\t\t\t\t/* index is above internal buffer length -> property is fully normal */\n\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"array index outside buffer -> normal property\"));\n\t\t\t}\n\t\t} else if (key == DUK_HTHREAD_STRING_LENGTH(thr) && DUK_HBUFOBJ_HAS_VIRTUAL_INDICES(h_bufobj)) {\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"-> found, key is 'length', length exotic behavior\"));\n\n\t\t\tif (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {\n\t\t\t\t/* Length in elements: take into account shift, but\n\t\t\t\t * intentionally don't check the underlying buffer here.\n\t\t\t\t */\n\t\t\t\tduk_push_uint(thr, h_bufobj->length >> h_bufobj->shift);\n\t\t\t}\n\t\t\tout_desc->flags = DUK_PROPDESC_FLAG_VIRTUAL;\n\t\t\tout_desc->get = NULL;\n\t\t\tout_desc->set = NULL;\n\t\t\tout_desc->e_idx = -1;\n\t\t\tout_desc->h_idx = -1;\n\t\t\tout_desc->a_idx = -1;\n\n\t\t\tDUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj));\n\t\t\tgoto prop_found_noexotic;  /* cannot be arguments exotic */\n\t\t}\n\t}\n#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */\n\n\t/* Array properties have exotic behavior but they are concrete,\n\t * so no special handling here.\n\t *\n\t * Arguments exotic behavior (E5 Section 10.6, [[GetOwnProperty]]\n\t * is only relevant as a post-check implemented below; hence no\n\t * check here.\n\t */\n\n\t/*\n\t *  Not found as concrete or virtual.\n\t */\n\n prop_not_found:\n\tDUK_DDD(DUK_DDDPRINT(\"-> not found (virtual, entry part, or array part)\"));\n\tDUK_STATS_INC(thr->heap, stats_getownpropdesc_miss);\n\treturn 0;\n\n\t/*\n\t *  Found.\n\t *\n\t *  Arguments object has exotic post-processing, see E5 Section 10.6,\n\t *  description of [[GetOwnProperty]] variant for arguments.\n\t */\n\n prop_found:\n\tDUK_DDD(DUK_DDDPRINT(\"-> property found, checking for arguments exotic post-behavior\"));\n\n\t/* Notes:\n\t *  - Only numbered indices are relevant, so arr_idx fast reject is good\n\t *    (this is valid unless there are more than 4**32-1 arguments).\n\t *  - Since variable lookup has no side effects, this can be skipped if\n\t *    DUK_GETDESC_FLAG_PUSH_VALUE is not set.\n\t */\n\n\tif (DUK_UNLIKELY(DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj) &&\n\t                 arr_idx != DUK__NO_ARRAY_INDEX &&\n\t                 (flags & DUK_GETDESC_FLAG_PUSH_VALUE))) {\n\t\tduk_propdesc temp_desc;\n\n\t\t/* Magically bound variable cannot be an accessor.  However,\n\t\t * there may be an accessor property (or a plain property) in\n\t\t * place with magic behavior removed.  This happens e.g. when\n\t\t * a magic property is redefined with defineProperty().\n\t\t * Cannot assert for \"not accessor\" here.\n\t\t */\n\n\t\t/* replaces top of stack with new value if necessary */\n\t\tDUK_ASSERT((flags & DUK_GETDESC_FLAG_PUSH_VALUE) != 0);\n\n\t\t/* This can perform a variable lookup but only into a declarative\n\t\t * environment which has no side effects.\n\t\t */\n\t\tif (duk__check_arguments_map_for_get(thr, obj, key, &temp_desc)) {\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"-> arguments exotic behavior overrides result: %!T -> %!T\",\n\t\t\t                     (duk_tval *) duk_get_tval(thr, -2),\n\t\t\t                     (duk_tval *) duk_get_tval(thr, -1)));\n\t\t\t/* [... old_result result] -> [... result] */\n\t\t\tduk_remove_m2(thr);\n\t\t}\n\t}\n\n prop_found_noexotic:\n\tDUK_STATS_INC(thr->heap, stats_getownpropdesc_hit);\n\treturn 1;\n}\n\nDUK_INTERNAL duk_bool_t duk_hobject_get_own_propdesc(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_propdesc *out_desc, duk_small_uint_t flags) {\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(obj != NULL);\n\tDUK_ASSERT(key != NULL);\n\tDUK_ASSERT(out_desc != NULL);\n\tDUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);\n\n\treturn duk__get_own_propdesc_raw(thr, obj, key, DUK_HSTRING_GET_ARRIDX_SLOW(key), out_desc, flags);\n}\n\n/*\n *  Ecmascript compliant [[GetProperty]](P), for internal use only.\n *\n *  If property is found:\n *    - Fills descriptor fields to 'out_desc'\n *    - If DUK_GETDESC_FLAG_PUSH_VALUE is set, pushes a value related to the\n *      property onto the stack ('undefined' for accessor properties).\n *    - Returns non-zero\n *\n *  If property is not found:\n *    - 'out_desc' is left in untouched state (possibly garbage)\n *    - Nothing is pushed onto the stack (not even with DUK_GETDESC_FLAG_PUSH_VALUE\n *      set)\n *    - Returns zero\n *\n *  May cause arbitrary side effects and invalidate (most) duk_tval\n *  pointers.\n */\n\nDUK_LOCAL duk_bool_t duk__get_propdesc(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_propdesc *out_desc, duk_small_uint_t flags) {\n\tduk_hobject *curr;\n\tduk_uint32_t arr_idx;\n\tduk_uint_t sanity;\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(thr->heap != NULL);\n\tDUK_ASSERT(obj != NULL);\n\tDUK_ASSERT(key != NULL);\n\tDUK_ASSERT(out_desc != NULL);\n\tDUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);\n\n\tDUK_STATS_INC(thr->heap, stats_getpropdesc_count);\n\n\tarr_idx = DUK_HSTRING_GET_ARRIDX_FAST(key);\n\n\tDUK_DDD(DUK_DDDPRINT(\"duk__get_propdesc: thr=%p, obj=%p, key=%p, out_desc=%p, flags=%lx, \"\n\t                     \"arr_idx=%ld (obj -> %!O, key -> %!O)\",\n\t                     (void *) thr, (void *) obj, (void *) key, (void *) out_desc,\n\t                     (long) flags, (long) arr_idx,\n\t                     (duk_heaphdr *) obj, (duk_heaphdr *) key));\n\n\tcurr = obj;\n\tDUK_ASSERT(curr != NULL);\n\tsanity = DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY;\n\tdo {\n\t\tif (duk__get_own_propdesc_raw(thr, curr, key, arr_idx, out_desc, flags)) {\n\t\t\t/* stack contains value (if requested), 'out_desc' is set */\n\t\t\tDUK_STATS_INC(thr->heap, stats_getpropdesc_hit);\n\t\t\treturn 1;\n\t\t}\n\n\t\t/* not found in 'curr', next in prototype chain; impose max depth */\n\t\tif (DUK_UNLIKELY(sanity-- == 0)) {\n\t\t\tif (flags & DUK_GETDESC_FLAG_IGNORE_PROTOLOOP) {\n\t\t\t\t/* treat like property not found */\n\t\t\t\tbreak;\n\t\t\t} else {\n\t\t\t\tDUK_ERROR_RANGE(thr, DUK_STR_PROTOTYPE_CHAIN_LIMIT);\n\t\t\t}\n\t\t}\n\t\tcurr = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, curr);\n\t} while (curr != NULL);\n\n\t/* out_desc is left untouched (possibly garbage), caller must use return\n\t * value to determine whether out_desc can be looked up\n\t */\n\n\tDUK_STATS_INC(thr->heap, stats_getpropdesc_miss);\n\treturn 0;\n}\n\n/*\n *  Shallow fast path checks for accessing array elements with numeric\n *  indices.  The goal is to try to avoid coercing an array index to an\n *  (interned) string for the most common lookups, in particular, for\n *  standard Array objects.\n *\n *  Interning is avoided but only for a very narrow set of cases:\n *    - Object has array part, index is within array allocation, and\n *      value is not unused (= key exists)\n *    - Object has no interfering exotic behavior (e.g. arguments or\n *      string object exotic behaviors interfere, array exotic\n *      behavior does not).\n *\n *  Current shortcoming: if key does not exist (even if it is within\n *  the array allocation range) a slow path lookup with interning is\n *  always required.  This can probably be fixed so that there is a\n *  quick fast path for non-existent elements as well, at least for\n *  standard Array objects.\n */\n\n#if defined(DUK_USE_ARRAY_PROP_FASTPATH)\nDUK_LOCAL duk_tval *duk__getprop_shallow_fastpath_array_tval(duk_hthread *thr, duk_hobject *obj, duk_tval *tv_key) {\n\tduk_tval *tv;\n\tduk_uint32_t idx;\n\n\tDUK_UNREF(thr);\n\n\tif (!(DUK_HOBJECT_HAS_ARRAY_PART(obj) &&\n\t     !DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj) &&\n\t     !DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(obj) &&\n\t     !DUK_HOBJECT_IS_BUFOBJ(obj) &&\n\t     !DUK_HOBJECT_IS_PROXY(obj))) {\n\t\t/* Must have array part and no conflicting exotic behaviors.\n\t\t * Doesn't need to have array special behavior, e.g. Arguments\n\t\t * object has array part.\n\t\t */\n\t\treturn NULL;\n\t}\n\n\t/* Arrays never have other exotic behaviors. */\n\n\tDUK_DDD(DUK_DDDPRINT(\"fast path attempt (no exotic string/arguments/buffer \"\n\t                     \"behavior, object has array part)\"));\n\n#if defined(DUK_USE_FASTINT)\n\tif (DUK_TVAL_IS_FASTINT(tv_key)) {\n\t\tidx = duk__tval_fastint_to_arr_idx(tv_key);\n\t} else\n#endif\n\tif (DUK_TVAL_IS_DOUBLE(tv_key)) {\n\t\tidx = duk__tval_number_to_arr_idx(tv_key);\n\t} else {\n\t\tDUK_DDD(DUK_DDDPRINT(\"key is not a number\"));\n\t\treturn NULL;\n\t}\n\n\t/* If index is not valid, idx will be DUK__NO_ARRAY_INDEX which\n\t * is 0xffffffffUL.  We don't need to check for that explicitly\n\t * because 0xffffffffUL will never be inside object 'a_size'.\n\t */\n\n\tif (idx >= DUK_HOBJECT_GET_ASIZE(obj)) {\n\t\tDUK_DDD(DUK_DDDPRINT(\"key is not an array index or outside array part\"));\n\t\treturn NULL;\n\t}\n\tDUK_ASSERT(idx != 0xffffffffUL);\n\tDUK_ASSERT(idx != DUK__NO_ARRAY_INDEX);\n\n\t/* XXX: for array instances we could take a shortcut here and assume\n\t * Array.prototype doesn't contain an array index property.\n\t */\n\n\tDUK_DDD(DUK_DDDPRINT(\"key is a valid array index and inside array part\"));\n\ttv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, idx);\n\tif (!DUK_TVAL_IS_UNUSED(tv)) {\n\t\tDUK_DDD(DUK_DDDPRINT(\"-> fast path successful\"));\n\t\treturn tv;\n\t}\n\n\tDUK_DDD(DUK_DDDPRINT(\"fast path attempt failed, fall back to slow path\"));\n\treturn NULL;\n}\n\nDUK_LOCAL duk_bool_t duk__putprop_shallow_fastpath_array_tval(duk_hthread *thr, duk_hobject *obj, duk_tval *tv_key, duk_tval *tv_val) {\n\tduk_tval *tv;\n\tduk_harray *a;\n\tduk_uint32_t idx;\n\tduk_uint32_t old_len, new_len;\n\n\tif (!(DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj) &&\n\t      DUK_HOBJECT_HAS_ARRAY_PART(obj) &&\n\t      DUK_HOBJECT_HAS_EXTENSIBLE(obj))) {\n\t\treturn 0;\n\t}\n\tDUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj));  /* caller ensures */\n\n\ta = (duk_harray *) obj;\n\tDUK_ASSERT_HARRAY_VALID(a);\n\n#if defined(DUK_USE_FASTINT)\n\tif (DUK_TVAL_IS_FASTINT(tv_key)) {\n\t\tidx = duk__tval_fastint_to_arr_idx(tv_key);\n\t} else\n#endif\n\tif (DUK_TVAL_IS_DOUBLE(tv_key)) {\n\t\tidx = duk__tval_number_to_arr_idx(tv_key);\n\t} else {\n\t\tDUK_DDD(DUK_DDDPRINT(\"key is not a number\"));\n\t\treturn 0;\n\t}\n\n\t/* If index is not valid, idx will be DUK__NO_ARRAY_INDEX which\n\t * is 0xffffffffUL.  We don't need to check for that explicitly\n\t * because 0xffffffffUL will never be inside object 'a_size'.\n\t */\n\n\tif (idx >= DUK_HOBJECT_GET_ASIZE(obj)) {  /* for resizing of array part, use slow path */\n\t\treturn 0;\n\t}\n\tDUK_ASSERT(idx != 0xffffffffUL);\n\tDUK_ASSERT(idx != DUK__NO_ARRAY_INDEX);\n\n\told_len = a->length;\n\n\tif (idx >= old_len) {\n\t\tDUK_DDD(DUK_DDDPRINT(\"write new array entry requires length update \"\n\t\t                     \"(arr_idx=%ld, old_len=%ld)\",\n\t\t                     (long) idx, (long) old_len));\n\t\tif (DUK_HARRAY_LENGTH_NONWRITABLE(a)) {\n\t\t\t/* The correct behavior here is either a silent error\n\t\t\t * or a TypeError, depending on strictness.  Fall back\n\t\t\t * to the slow path to handle the situation.\n\t\t\t */\n\t\t\treturn 0;\n\t\t}\n\t\tnew_len = idx + 1;\n\n\t\t((duk_harray *) obj)->length = new_len;\n\t}\n\n\ttv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, idx);\n\tDUK_TVAL_SET_TVAL_UPDREF(thr, tv, tv_val);  /* side effects */\n\n\tDUK_DDD(DUK_DDDPRINT(\"array fast path success for index %ld\", (long) idx));\n\treturn 1;\n}\n#endif  /* DUK_USE_ARRAY_PROP_FASTPATH */\n\n/*\n *  Fast path for bufobj getprop/putprop\n */\n\n#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)\nDUK_LOCAL duk_bool_t duk__getprop_fastpath_bufobj_tval(duk_hthread *thr, duk_hobject *obj, duk_tval *tv_key) {\n\tduk_uint32_t idx;\n\tduk_hbufobj *h_bufobj;\n\tduk_uint_t byte_off;\n\tduk_small_uint_t elem_size;\n\tduk_uint8_t *data;\n\n\tif (!DUK_HOBJECT_IS_BUFOBJ(obj)) {\n\t\treturn 0;\n\t}\n\th_bufobj = (duk_hbufobj *) obj;\n\tif (!DUK_HBUFOBJ_HAS_VIRTUAL_INDICES(h_bufobj)) {\n\t\treturn 0;\n\t}\n\n#if defined(DUK_USE_FASTINT)\n\tif (DUK_TVAL_IS_FASTINT(tv_key)) {\n\t\tidx = duk__tval_fastint_to_arr_idx(tv_key);\n\t} else\n#endif\n\tif (DUK_TVAL_IS_DOUBLE(tv_key)) {\n\t\tidx = duk__tval_number_to_arr_idx(tv_key);\n\t} else {\n\t\treturn 0;\n\t}\n\n\t/* If index is not valid, idx will be DUK__NO_ARRAY_INDEX which\n\t * is 0xffffffffUL.  We don't need to check for that explicitly\n\t * because 0xffffffffUL will never be inside bufobj length.\n\t */\n\n\t/* Careful with wrapping (left shifting idx would be unsafe). */\n\tif (idx >= (h_bufobj->length >> h_bufobj->shift)) {\n\t\treturn 0;\n\t}\n\tDUK_ASSERT(idx != DUK__NO_ARRAY_INDEX);\n\n\tbyte_off = idx << h_bufobj->shift;  /* no wrap assuming h_bufobj->length is valid */\n\telem_size = (duk_small_uint_t) (1U << h_bufobj->shift);\n\n\tif (h_bufobj->buf != NULL && DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h_bufobj, byte_off + elem_size)) {\n\t\tdata = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufobj->buf) + h_bufobj->offset + byte_off;\n\t\tduk_hbufobj_push_validated_read(thr, h_bufobj, data, elem_size);\n\t} else {\n\t\tDUK_D(DUK_DPRINT(\"bufobj access out of underlying buffer, ignoring (read zero)\"));\n\t\tduk_push_uint(thr, 0);\n\t}\n\n\treturn 1;\n}\n#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */\n\n#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)\nDUK_LOCAL duk_bool_t duk__putprop_fastpath_bufobj_tval(duk_hthread *thr, duk_hobject *obj, duk_tval *tv_key, duk_tval *tv_val) {\n\tduk_uint32_t idx;\n\tduk_hbufobj *h_bufobj;\n\tduk_uint_t byte_off;\n\tduk_small_uint_t elem_size;\n\tduk_uint8_t *data;\n\n\tif (!(DUK_HOBJECT_IS_BUFOBJ(obj) &&\n\t      DUK_TVAL_IS_NUMBER(tv_val))) {\n\t\treturn 0;\n\t}\n\tDUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj));  /* caller ensures; rom objects are never bufobjs now */\n\n\th_bufobj = (duk_hbufobj *) obj;\n\tif (!DUK_HBUFOBJ_HAS_VIRTUAL_INDICES(h_bufobj)) {\n\t\treturn 0;\n\t}\n\n#if defined(DUK_USE_FASTINT)\n\tif (DUK_TVAL_IS_FASTINT(tv_key)) {\n\t\tidx = duk__tval_fastint_to_arr_idx(tv_key);\n\t} else\n#endif\n\tif (DUK_TVAL_IS_DOUBLE(tv_key)) {\n\t\tidx = duk__tval_number_to_arr_idx(tv_key);\n\t} else {\n\t\treturn 0;\n\t}\n\n\t/* If index is not valid, idx will be DUK__NO_ARRAY_INDEX which\n\t * is 0xffffffffUL.  We don't need to check for that explicitly\n\t * because 0xffffffffUL will never be inside bufobj length.\n\t */\n\n\t/* Careful with wrapping (left shifting idx would be unsafe). */\n\tif (idx >= (h_bufobj->length >> h_bufobj->shift)) {\n\t\treturn 0;\n\t}\n\tDUK_ASSERT(idx != DUK__NO_ARRAY_INDEX);\n\n\tbyte_off = idx << h_bufobj->shift;  /* no wrap assuming h_bufobj->length is valid */\n\telem_size = (duk_small_uint_t) (1U << h_bufobj->shift);\n\n\t/* Value is required to be a number in the fast path so there\n\t * are no side effects in write coercion.\n\t */\n\tduk_push_tval(thr, tv_val);\n\tDUK_ASSERT(duk_is_number(thr, -1));\n\n\tif (h_bufobj->buf != NULL && DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h_bufobj, byte_off + elem_size)) {\n\t\tdata = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufobj->buf) + h_bufobj->offset + byte_off;\n\t\tduk_hbufobj_validated_write(thr, h_bufobj, data, elem_size);\n\t} else {\n\t\tDUK_D(DUK_DPRINT(\"bufobj access out of underlying buffer, ignoring (write skipped)\"));\n\t}\n\n\tduk_pop_unsafe(thr);\n\treturn 1;\n}\n#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */\n\n/*\n *  GETPROP: Ecmascript property read.\n */\n\nDUK_INTERNAL duk_bool_t duk_hobject_getprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key) {\n\tduk_tval tv_obj_copy;\n\tduk_tval tv_key_copy;\n\tduk_hobject *curr = NULL;\n\tduk_hstring *key = NULL;\n\tduk_uint32_t arr_idx = DUK__NO_ARRAY_INDEX;\n\tduk_propdesc desc;\n\tduk_uint_t sanity;\n\n\tDUK_DDD(DUK_DDDPRINT(\"getprop: thr=%p, obj=%p, key=%p (obj -> %!T, key -> %!T)\",\n\t                     (void *) thr, (void *) tv_obj, (void *) tv_key,\n\t                     (duk_tval *) tv_obj, (duk_tval *) tv_key));\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(thr->heap != NULL);\n\tDUK_ASSERT(tv_obj != NULL);\n\tDUK_ASSERT(tv_key != NULL);\n\n\tDUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);\n\n\tDUK_STATS_INC(thr->heap, stats_getprop_all);\n\n\t/*\n\t *  Make a copy of tv_obj, tv_key, and tv_val to avoid any issues of\n\t *  them being invalidated by a valstack resize.\n\t *\n\t *  XXX: this is now an overkill for many fast paths.  Rework this\n\t *  to be faster (although switching to a valstack discipline might\n\t *  be a better solution overall).\n\t */\n\n\tDUK_TVAL_SET_TVAL(&tv_obj_copy, tv_obj);\n\tDUK_TVAL_SET_TVAL(&tv_key_copy, tv_key);\n\ttv_obj = &tv_obj_copy;\n\ttv_key = &tv_key_copy;\n\n\t/*\n\t *  Coercion and fast path processing\n\t */\n\n\tswitch (DUK_TVAL_GET_TAG(tv_obj)) {\n\tcase DUK_TAG_UNDEFINED:\n\tcase DUK_TAG_NULL: {\n\t\t/* Note: unconditional throw */\n\t\tDUK_DDD(DUK_DDDPRINT(\"base object is undefined or null -> reject\"));\n#if defined(DUK_USE_PARANOID_ERRORS)\n\t\tDUK_ERROR_TYPE(thr, DUK_STR_INVALID_BASE);\n#else\n\t\tDUK_ERROR_FMT2(thr, DUK_ERR_TYPE_ERROR, \"cannot read property %s of %s\",\n\t\t               duk_push_string_tval_readable(thr, tv_key), duk_push_string_tval_readable(thr, tv_obj));\n#endif\n\t\treturn 0;\n\t}\n\n\tcase DUK_TAG_BOOLEAN: {\n\t\tDUK_DDD(DUK_DDDPRINT(\"base object is a boolean, start lookup from boolean prototype\"));\n\t\tcurr = thr->builtins[DUK_BIDX_BOOLEAN_PROTOTYPE];\n\t\tbreak;\n\t}\n\n\tcase DUK_TAG_STRING: {\n\t\tduk_hstring *h = DUK_TVAL_GET_STRING(tv_obj);\n\t\tduk_int_t pop_count;\n\n\t\tif (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(h))) {\n\t\t\t/* Symbols (ES2015 or hidden) don't have virtual properties. */\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"base object is a symbol, start lookup from symbol prototype\"));\n\t\t\tcurr = thr->builtins[DUK_BIDX_SYMBOL_PROTOTYPE];\n\t\t\tbreak;\n\t\t}\n\n#if defined(DUK_USE_FASTINT)\n\t\tif (DUK_TVAL_IS_FASTINT(tv_key)) {\n\t\t\tarr_idx = duk__tval_fastint_to_arr_idx(tv_key);\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"base object string, key is a fast-path fastint; arr_idx %ld\", (long) arr_idx));\n\t\t\tpop_count = 0;\n\t\t} else\n#endif\n\t\tif (DUK_TVAL_IS_NUMBER(tv_key)) {\n\t\t\tarr_idx = duk__tval_number_to_arr_idx(tv_key);\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"base object string, key is a fast-path number; arr_idx %ld\", (long) arr_idx));\n\t\t\tpop_count = 0;\n\t\t} else {\n\t\t\tarr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);\n\t\t\tDUK_ASSERT(key != NULL);\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"base object string, key is a non-fast-path number; after \"\n\t\t\t                     \"coercion key is %!T, arr_idx %ld\",\n\t\t\t                     (duk_tval *) duk_get_tval(thr, -1), (long) arr_idx));\n\t\t\tpop_count = 1;\n\t\t}\n\n\t\tif (arr_idx != DUK__NO_ARRAY_INDEX &&\n\t\t    arr_idx < DUK_HSTRING_GET_CHARLEN(h)) {\n\t\t\tduk_pop_n_unsafe(thr, pop_count);\n\t\t\tduk_push_hstring(thr, h);\n\t\t\tduk_substring(thr, -1, arr_idx, arr_idx + 1);  /* [str] -> [substr] */\n\n\t\t\tDUK_STATS_INC(thr->heap, stats_getprop_stringidx);\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"-> %!T (base is string, key is an index inside string length \"\n\t\t\t                     \"after coercion -> return char)\",\n\t\t\t                     (duk_tval *) duk_get_tval(thr, -1)));\n\t\t\treturn 1;\n\t\t}\n\n\t\tif (pop_count == 0) {\n\t\t\t/* This is a pretty awkward control flow, but we need to recheck the\n\t\t\t * key coercion here.\n\t\t\t */\n\t\t\tarr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);\n\t\t\tDUK_ASSERT(key != NULL);\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"base object string, key is a non-fast-path number; after \"\n\t\t\t                     \"coercion key is %!T, arr_idx %ld\",\n\t\t\t                     (duk_tval *) duk_get_tval(thr, -1), (long) arr_idx));\n\t\t}\n\n\t\tif (key == DUK_HTHREAD_STRING_LENGTH(thr)) {\n\t\t\tduk_pop_unsafe(thr);  /* [key] -> [] */\n\t\t\tduk_push_uint(thr, (duk_uint_t) DUK_HSTRING_GET_CHARLEN(h));  /* [] -> [res] */\n\n\t\t\tDUK_STATS_INC(thr->heap, stats_getprop_stringlen);\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"-> %!T (base is string, key is 'length' after coercion -> \"\n\t\t\t                     \"return string length)\",\n\t\t\t                     (duk_tval *) duk_get_tval(thr, -1)));\n\t\t\treturn 1;\n\t\t}\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"base object is a string, start lookup from string prototype\"));\n\t\tcurr = thr->builtins[DUK_BIDX_STRING_PROTOTYPE];\n\t\tgoto lookup;  /* avoid double coercion */\n\t}\n\n\tcase DUK_TAG_OBJECT: {\n#if defined(DUK_USE_ARRAY_PROP_FASTPATH)\n\t\tduk_tval *tmp;\n#endif\n\n\t\tcurr = DUK_TVAL_GET_OBJECT(tv_obj);\n\t\tDUK_ASSERT(curr != NULL);\n\n\t\t/* XXX: array .length fast path (important in e.g. loops)? */\n\n#if defined(DUK_USE_ARRAY_PROP_FASTPATH)\n\t\ttmp = duk__getprop_shallow_fastpath_array_tval(thr, curr, tv_key);\n\t\tif (tmp) {\n\t\t\tduk_push_tval(thr, tmp);\n\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"-> %!T (base is object, key is a number, array part \"\n\t\t\t                     \"fast path)\",\n\t\t\t                     (duk_tval *) duk_get_tval(thr, -1)));\n\t\t\tDUK_STATS_INC(thr->heap, stats_getprop_arrayidx);\n\t\t\treturn 1;\n\t\t}\n#endif\n\n#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)\n\t\tif (duk__getprop_fastpath_bufobj_tval(thr, curr, tv_key) != 0) {\n\t\t\t/* Read value pushed on stack. */\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"-> %!T (base is bufobj, key is a number, bufobj \"\n\t\t\t                     \"fast path)\",\n\t\t\t                     (duk_tval *) duk_get_tval(thr, -1)));\n\t\t\tDUK_STATS_INC(thr->heap, stats_getprop_bufobjidx);\n\t\t\treturn 1;\n\t\t}\n#endif\n\n#if defined(DUK_USE_ES6_PROXY)\n\t\tif (DUK_UNLIKELY(DUK_HOBJECT_IS_PROXY(curr))) {\n\t\t\tduk_hobject *h_target;\n\n\t\t\tif (duk__proxy_check_prop(thr, curr, DUK_STRIDX_GET, tv_key, &h_target)) {\n\t\t\t\t/* -> [ ... trap handler ] */\n\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"-> proxy object 'get' for key %!T\", (duk_tval *) tv_key));\n\t\t\t\tDUK_STATS_INC(thr->heap, stats_getprop_proxy);\n\t\t\t\tduk_push_hobject(thr, h_target);  /* target */\n\t\t\t\tduk_push_tval(thr, tv_key);       /* P */\n\t\t\t\tduk_push_tval(thr, tv_obj);       /* Receiver: Proxy object */\n\t\t\t\tduk_call_method(thr, 3 /*nargs*/);\n\n\t\t\t\t/* Target object must be checked for a conflicting\n\t\t\t\t * non-configurable property.\n\t\t\t\t */\n\t\t\t\tarr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);\n\t\t\t\tDUK_ASSERT(key != NULL);\n\n\t\t\t\tif (duk__get_own_propdesc_raw(thr, h_target, key, arr_idx, &desc, DUK_GETDESC_FLAG_PUSH_VALUE)) {\n\t\t\t\t\tduk_tval *tv_hook = duk_require_tval(thr, -3);  /* value from hook */\n\t\t\t\t\tduk_tval *tv_targ = duk_require_tval(thr, -1);  /* value from target */\n\t\t\t\t\tduk_bool_t datadesc_reject;\n\t\t\t\t\tduk_bool_t accdesc_reject;\n\n\t\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"proxy 'get': target has matching property %!O, check for \"\n\t\t\t\t\t                     \"conflicting property; tv_hook=%!T, tv_targ=%!T, desc.flags=0x%08lx, \"\n\t\t\t\t\t                     \"desc.get=%p, desc.set=%p\",\n\t\t\t\t\t                     (duk_heaphdr *) key, (duk_tval *) tv_hook, (duk_tval *) tv_targ,\n\t\t\t\t\t                     (unsigned long) desc.flags,\n\t\t\t\t\t                     (void *) desc.get, (void *) desc.set));\n\n\t\t\t\t\tdatadesc_reject = !(desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) &&\n\t\t\t\t\t                  !(desc.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) &&\n\t\t\t\t\t                  !(desc.flags & DUK_PROPDESC_FLAG_WRITABLE) &&\n\t\t\t\t\t                  !duk_js_samevalue(tv_hook, tv_targ);\n\t\t\t\t\taccdesc_reject = (desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) &&\n\t\t\t\t\t                 !(desc.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) &&\n\t\t\t\t\t                 (desc.get == NULL) &&\n\t\t\t\t\t                 !DUK_TVAL_IS_UNDEFINED(tv_hook);\n\t\t\t\t\tif (datadesc_reject || accdesc_reject) {\n\t\t\t\t\t\tDUK_ERROR_TYPE(thr, DUK_STR_PROXY_REJECTED);\n\t\t\t\t\t}\n\n\t\t\t\t\tduk_pop_2_unsafe(thr);\n\t\t\t\t} else {\n\t\t\t\t\tduk_pop_unsafe(thr);\n\t\t\t\t}\n\t\t\t\treturn 1;  /* return value */\n\t\t\t}\n\n\t\t\tcurr = h_target;  /* resume lookup from target */\n\t\t\tDUK_TVAL_SET_OBJECT(tv_obj, curr);\n\t\t}\n#endif  /* DUK_USE_ES6_PROXY */\n\n\t\tif (DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(curr)) {\n\t\t\tarr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);\n\t\t\tDUK_ASSERT(key != NULL);\n\n\t\t\tDUK_STATS_INC(thr->heap, stats_getprop_arguments);\n\t\t\tif (duk__check_arguments_map_for_get(thr, curr, key, &desc)) {\n\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"-> %!T (base is object with arguments exotic behavior, \"\n\t\t\t\t                     \"key matches magically bound property -> skip standard \"\n\t\t\t\t                     \"Get with replacement value)\",\n\t\t\t\t                     (duk_tval *) duk_get_tval(thr, -1)));\n\n\t\t\t\t/* no need for 'caller' post-check, because 'key' must be an array index */\n\n\t\t\t\tduk_remove_m2(thr);  /* [key result] -> [result] */\n\t\t\t\treturn 1;\n\t\t\t}\n\n\t\t\tgoto lookup;  /* avoid double coercion */\n\t\t}\n\t\tbreak;\n\t}\n\n\t/* Buffer has virtual properties similar to string, but indexed values\n\t * are numbers, not 1-byte buffers/strings which would perform badly.\n\t */\n\tcase DUK_TAG_BUFFER: {\n\t\tduk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv_obj);\n\t\tduk_int_t pop_count;\n\n\t\t/*\n\t\t *  Because buffer values are often looped over, a number fast path\n\t\t *  is important.\n\t\t */\n\n#if defined(DUK_USE_FASTINT)\n\t\tif (DUK_TVAL_IS_FASTINT(tv_key)) {\n\t\t\tarr_idx = duk__tval_fastint_to_arr_idx(tv_key);\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"base object buffer, key is a fast-path fastint; arr_idx %ld\", (long) arr_idx));\n\t\t\tpop_count = 0;\n\t\t}\n\t\telse\n#endif\n\t\tif (DUK_TVAL_IS_NUMBER(tv_key)) {\n\t\t\tarr_idx = duk__tval_number_to_arr_idx(tv_key);\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"base object buffer, key is a fast-path number; arr_idx %ld\", (long) arr_idx));\n\t\t\tpop_count = 0;\n\t\t} else {\n\t\t\tarr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);\n\t\t\tDUK_ASSERT(key != NULL);\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"base object buffer, key is a non-fast-path number; after \"\n\t\t\t                     \"coercion key is %!T, arr_idx %ld\",\n\t\t\t                     (duk_tval *) duk_get_tval(thr, -1), (long) arr_idx));\n\t\t\tpop_count = 1;\n\t\t}\n\n\t\tif (arr_idx != DUK__NO_ARRAY_INDEX &&\n\t\t    arr_idx < DUK_HBUFFER_GET_SIZE(h)) {\n\t\t\tduk_pop_n_unsafe(thr, pop_count);\n\t\t\tduk_push_uint(thr, ((duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h))[arr_idx]);\n\t\t\tDUK_STATS_INC(thr->heap, stats_getprop_bufferidx);\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"-> %!T (base is buffer, key is an index inside buffer length \"\n\t\t\t                     \"after coercion -> return byte as number)\",\n\t\t\t                     (duk_tval *) duk_get_tval(thr, -1)));\n\t\t\treturn 1;\n\t\t}\n\n\t\tif (pop_count == 0) {\n\t\t\t/* This is a pretty awkward control flow, but we need to recheck the\n\t\t\t * key coercion here.\n\t\t\t */\n\t\t\tarr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);\n\t\t\tDUK_ASSERT(key != NULL);\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"base object buffer, key is a non-fast-path number; after \"\n\t\t\t                     \"coercion key is %!T, arr_idx %ld\",\n\t\t\t                     (duk_tval *) duk_get_tval(thr, -1), (long) arr_idx));\n\t\t}\n\n\t\tif (key == DUK_HTHREAD_STRING_LENGTH(thr)) {\n\t\t\tduk_pop_unsafe(thr);  /* [key] -> [] */\n\t\t\tduk_push_uint(thr, (duk_uint_t) DUK_HBUFFER_GET_SIZE(h));  /* [] -> [res] */\n\t\t\tDUK_STATS_INC(thr->heap, stats_getprop_bufferlen);\n\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"-> %!T (base is buffer, key is 'length' \"\n\t\t\t                     \"after coercion -> return buffer length)\",\n\t\t\t                     (duk_tval *) duk_get_tval(thr, -1)));\n\t\t\treturn 1;\n\t\t}\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"base object is a buffer, start lookup from Uint8Array prototype\"));\n\t\tcurr = thr->builtins[DUK_BIDX_UINT8ARRAY_PROTOTYPE];\n\t\tgoto lookup;  /* avoid double coercion */\n\t}\n\n\tcase DUK_TAG_POINTER: {\n\t\tDUK_DDD(DUK_DDDPRINT(\"base object is a pointer, start lookup from pointer prototype\"));\n\t\tcurr = thr->builtins[DUK_BIDX_POINTER_PROTOTYPE];\n\t\tbreak;\n\t}\n\n\tcase DUK_TAG_LIGHTFUNC: {\n\t\t/* Lightfuncs inherit getter .name and .length from %NativeFunctionPrototype%. */\n\t\tDUK_DDD(DUK_DDDPRINT(\"base object is a lightfunc, start lookup from function prototype\"));\n\t\tcurr = thr->builtins[DUK_BIDX_NATIVE_FUNCTION_PROTOTYPE];\n\t\tbreak;\n\t}\n\n#if defined(DUK_USE_FASTINT)\n\tcase DUK_TAG_FASTINT:\n#endif\n\tdefault: {\n\t\t/* number */\n\t\tDUK_DDD(DUK_DDDPRINT(\"base object is a number, start lookup from number prototype\"));\n\t\tDUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv_obj));\n\t\tDUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_obj));\n\t\tcurr = thr->builtins[DUK_BIDX_NUMBER_PROTOTYPE];\n\t\tbreak;\n\t}\n\t}\n\n\t/* key coercion (unless already coerced above) */\n\tDUK_ASSERT(key == NULL);\n\tarr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);\n\tDUK_ASSERT(key != NULL);\n\t/*\n\t *  Property lookup\n\t */\n\n lookup:\n\t/* [key] (coerced) */\n\tDUK_ASSERT(curr != NULL);\n\tDUK_ASSERT(key != NULL);\n\n\tsanity = DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY;\n\tdo {\n\t\tif (!duk__get_own_propdesc_raw(thr, curr, key, arr_idx, &desc, DUK_GETDESC_FLAG_PUSH_VALUE)) {\n\t\t\tgoto next_in_chain;\n\t\t}\n\n\t\tif (desc.get != NULL) {\n\t\t\t/* accessor with defined getter */\n\t\t\tDUK_ASSERT((desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) != 0);\n\n\t\t\tduk_pop_unsafe(thr);              /* [key undefined] -> [key] */\n\t\t\tduk_push_hobject(thr, desc.get);\n\t\t\tduk_push_tval(thr, tv_obj);       /* note: original, uncoerced base */\n#if defined(DUK_USE_NONSTD_GETTER_KEY_ARGUMENT)\n\t\t\tduk_dup_m3(thr);\n\t\t\tduk_call_method(thr, 1);          /* [key getter this key] -> [key retval] */\n#else\n\t\t\tduk_call_method(thr, 0);          /* [key getter this] -> [key retval] */\n#endif\n\t\t} else {\n\t\t\t/* [key value] or [key undefined] */\n\n\t\t\t/* data property or accessor without getter */\n\t\t\tDUK_ASSERT(((desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) == 0) ||\n\t\t\t           (desc.get == NULL));\n\n\t\t\t/* if accessor without getter, return value is undefined */\n\t\t\tDUK_ASSERT(((desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) == 0) ||\n\t\t\t           duk_is_undefined(thr, -1));\n\n\t\t\t/* Note: for an accessor without getter, falling through to\n\t\t\t * check for \"caller\" exotic behavior is unnecessary as\n\t\t\t * \"undefined\" will never activate the behavior.  But it does\n\t\t\t * no harm, so we'll do it anyway.\n\t\t\t */\n\t\t}\n\n\t\tgoto found;  /* [key result] */\n\n\t next_in_chain:\n\t\t/* XXX: option to pretend property doesn't exist if sanity limit is\n\t\t * hit might be useful.\n\t\t */\n\t\tif (DUK_UNLIKELY(sanity-- == 0)) {\n\t\t\tDUK_ERROR_RANGE(thr, DUK_STR_PROTOTYPE_CHAIN_LIMIT);\n\t\t}\n\t\tcurr = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, curr);\n\t} while (curr != NULL);\n\n\t/*\n\t *  Not found\n\t */\n\n\tduk_to_undefined(thr, -1);  /* [key] -> [undefined] (default value) */\n\n\tDUK_DDD(DUK_DDDPRINT(\"-> %!T (not found)\", (duk_tval *) duk_get_tval(thr, -1)));\n\treturn 0;\n\n\t/*\n\t *  Found; post-processing (Function and arguments objects)\n\t */\n\n found:\n\t/* [key result] */\n\n#if !defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)\n\t/* Special behavior for 'caller' property of (non-bound) function objects\n\t * and non-strict Arguments objects: if 'caller' -value- (!) is a strict\n\t * mode function, throw a TypeError (E5 Sections 15.3.5.4, 10.6).\n\t * Quite interestingly, a non-strict function with no formal arguments\n\t * will get an arguments object -without- special 'caller' behavior!\n\t *\n\t * The E5.1 spec is a bit ambiguous if this special behavior applies when\n\t * a bound function is the base value (not the 'caller' value): Section\n\t * 15.3.4.5 (describing bind()) states that [[Get]] for bound functions\n\t * matches that of Section 15.3.5.4 ([[Get]] for Function instances).\n\t * However, Section 13.3.5.4 has \"NOTE: Function objects created using\n\t * Function.prototype.bind use the default [[Get]] internal method.\"\n\t * The current implementation assumes this means that bound functions\n\t * should not have the special [[Get]] behavior.\n\t *\n\t * The E5.1 spec is also a bit unclear if the TypeError throwing is\n\t * applied if the 'caller' value is a strict bound function.  The\n\t * current implementation will throw even for both strict non-bound\n\t * and strict bound functions.\n\t *\n\t * See test-dev-strict-func-as-caller-prop-value.js for quite extensive\n\t * tests.\n\t *\n\t * This exotic behavior is disabled when the non-standard 'caller' property\n\t * is enabled, as it conflicts with the free use of 'caller'.\n\t */\n\tif (key == DUK_HTHREAD_STRING_CALLER(thr) &&\n\t    DUK_TVAL_IS_OBJECT(tv_obj)) {\n\t\tduk_hobject *orig = DUK_TVAL_GET_OBJECT(tv_obj);\n\t\tDUK_ASSERT(orig != NULL);\n\n\t\tif (DUK_HOBJECT_IS_NONBOUND_FUNCTION(orig) ||\n\t\t    DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(orig)) {\n\t\t\tduk_hobject *h;\n\n\t\t\t/* XXX: The TypeError is currently not applied to bound\n\t\t\t * functions because the 'strict' flag is not copied by\n\t\t\t * bind().  This may or may not be correct, the specification\n\t\t\t * only refers to the value being a \"strict mode Function\n\t\t\t * object\" which is ambiguous.\n\t\t\t */\n\t\t\tDUK_ASSERT(!DUK_HOBJECT_HAS_BOUNDFUNC(orig));\n\n\t\t\th = duk_get_hobject(thr, -1);  /* NULL if not an object */\n\t\t\tif (h &&\n\t\t\t    DUK_HOBJECT_IS_FUNCTION(h) &&\n\t\t\t    DUK_HOBJECT_HAS_STRICT(h)) {\n\t\t\t\t/* XXX: sufficient to check 'strict', assert for 'is function' */\n\t\t\t\tDUK_ERROR_TYPE(thr, DUK_STR_STRICT_CALLER_READ);\n\t\t\t}\n\t\t}\n\t}\n#endif   /* !DUK_USE_NONSTD_FUNC_CALLER_PROPERTY */\n\n\tduk_remove_m2(thr);  /* [key result] -> [result] */\n\n\tDUK_DDD(DUK_DDDPRINT(\"-> %!T (found)\", (duk_tval *) duk_get_tval(thr, -1)));\n\treturn 1;\n}\n\n/*\n *  HASPROP: Ecmascript property existence check (\"in\" operator).\n *\n *  Interestingly, the 'in' operator does not do any coercion of\n *  the target object.\n */\n\nDUK_INTERNAL duk_bool_t duk_hobject_hasprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key) {\n\tduk_tval tv_key_copy;\n\tduk_hobject *obj;\n\tduk_hstring *key;\n\tduk_uint32_t arr_idx;\n\tduk_bool_t rc;\n\tduk_propdesc desc;\n\n\tDUK_DDD(DUK_DDDPRINT(\"hasprop: thr=%p, obj=%p, key=%p (obj -> %!T, key -> %!T)\",\n\t                     (void *) thr, (void *) tv_obj, (void *) tv_key,\n\t                     (duk_tval *) tv_obj, (duk_tval *) tv_key));\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(thr->heap != NULL);\n\tDUK_ASSERT(tv_obj != NULL);\n\tDUK_ASSERT(tv_key != NULL);\n\tDUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);\n\n\tDUK_TVAL_SET_TVAL(&tv_key_copy, tv_key);\n\ttv_key = &tv_key_copy;\n\n\t/*\n\t *  The 'in' operator requires an object as its right hand side,\n\t *  throwing a TypeError unconditionally if this is not the case.\n\t *\n\t *  However, lightfuncs need to behave like fully fledged objects\n\t *  here to be maximally transparent, so we need to handle them\n\t *  here.  Same goes for plain buffers which behave like ArrayBuffers.\n\t */\n\n\t/* XXX: Refactor key coercion so that it's only called once.  It can't\n\t * be trivially lifted here because the object must be type checked\n\t * first.\n\t */\n\n\tif (DUK_TVAL_IS_OBJECT(tv_obj)) {\n\t\tobj = DUK_TVAL_GET_OBJECT(tv_obj);\n\t\tDUK_ASSERT(obj != NULL);\n\n\t\tarr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);\n\t} else if (DUK_TVAL_IS_BUFFER(tv_obj)) {\n\t\tarr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);\n\t\tif (duk__key_is_plain_buf_ownprop(thr, DUK_TVAL_GET_BUFFER(tv_obj), key, arr_idx)) {\n\t\t\trc = 1;\n\t\t\tgoto pop_and_return;\n\t\t}\n\t\tobj = thr->builtins[DUK_BIDX_UINT8ARRAY_PROTOTYPE];\n\t} else if (DUK_TVAL_IS_LIGHTFUNC(tv_obj)) {\n\t\tarr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);\n\n\t\t/* If not found, resume existence check from %NativeFunctionPrototype%.\n\t\t * We can just substitute the value in this case; nothing will\n\t\t * need the original base value (as would be the case with e.g.\n\t\t * setters/getters.\n\t\t */\n\t\tobj = thr->builtins[DUK_BIDX_NATIVE_FUNCTION_PROTOTYPE];\n\t} else {\n\t\t/* Note: unconditional throw */\n\t\tDUK_DDD(DUK_DDDPRINT(\"base object is not an object -> reject\"));\n\t\tDUK_ERROR_TYPE(thr, DUK_STR_INVALID_BASE);\n\t}\n\n\t/* XXX: fast path for arrays? */\n\n\tDUK_ASSERT(key != NULL);\n\tDUK_ASSERT(obj != NULL);\n\tDUK_UNREF(arr_idx);\n\n#if defined(DUK_USE_ES6_PROXY)\n\tif (DUK_UNLIKELY(DUK_HOBJECT_IS_PROXY(obj))) {\n\t\tduk_hobject *h_target;\n\t\tduk_bool_t tmp_bool;\n\n\t\t/* XXX: the key in 'key in obj' is string coerced before we're called\n\t\t * (which is the required behavior in E5/E5.1/E6) so the key is a string\n\t\t * here already.\n\t\t */\n\n\t\tif (duk__proxy_check_prop(thr, obj, DUK_STRIDX_HAS, tv_key, &h_target)) {\n\t\t\t/* [ ... key trap handler ] */\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"-> proxy object 'has' for key %!T\", (duk_tval *) tv_key));\n\t\t\tduk_push_hobject(thr, h_target);  /* target */\n\t\t\tduk_push_tval(thr, tv_key);       /* P */\n\t\t\tduk_call_method(thr, 2 /*nargs*/);\n\t\t\ttmp_bool = duk_to_boolean(thr, -1);\n\t\t\tif (!tmp_bool) {\n\t\t\t\t/* Target object must be checked for a conflicting\n\t\t\t\t * non-configurable property.\n\t\t\t\t */\n\n\t\t\t\tif (duk__get_own_propdesc_raw(thr, h_target, key, arr_idx, &desc, 0 /*flags*/)) {  /* don't push value */\n\t\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"proxy 'has': target has matching property %!O, check for \"\n\t\t\t\t\t                     \"conflicting property; desc.flags=0x%08lx, \"\n\t\t\t\t\t                     \"desc.get=%p, desc.set=%p\",\n\t\t\t\t\t                     (duk_heaphdr *) key, (unsigned long) desc.flags,\n\t\t\t\t\t                     (void *) desc.get, (void *) desc.set));\n\t\t\t\t\t/* XXX: Extensibility check for target uses IsExtensible().  If we\n\t\t\t\t\t * implemented the isExtensible trap and didn't reject proxies as\n\t\t\t\t\t * proxy targets, it should be respected here.\n\t\t\t\t\t */\n\t\t\t\t\tif (!((desc.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) &&  /* property is configurable and */\n\t\t\t\t\t      DUK_HOBJECT_HAS_EXTENSIBLE(h_target))) {          /* ... target is extensible */\n\t\t\t\t\t\tDUK_ERROR_TYPE(thr, DUK_STR_PROXY_REJECTED);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tduk_pop_2_unsafe(thr);  /* [ key trap_result ] -> [] */\n\t\t\treturn tmp_bool;\n\t\t}\n\n\t\tobj = h_target;  /* resume check from proxy target */\n\t}\n#endif  /* DUK_USE_ES6_PROXY */\n\n\t/* XXX: inline into a prototype walking loop? */\n\n\trc = duk__get_propdesc(thr, obj, key, &desc, 0 /*flags*/);  /* don't push value */\n\t/* fall through */\n\n pop_and_return:\n\tduk_pop_unsafe(thr);  /* [ key ] -> [] */\n\treturn rc;\n}\n\n/*\n *  HASPROP variant used internally.\n *\n *  This primitive must never throw an error, callers rely on this.\n *  In particular, don't throw an error for prototype loops; instead,\n *  pretend like the property doesn't exist if a prototype sanity limit\n *  is reached.\n *\n *  Does not implement proxy behavior: if applied to a proxy object,\n *  returns key existence on the proxy object itself.\n */\n\nDUK_INTERNAL duk_bool_t duk_hobject_hasprop_raw(duk_hthread *thr, duk_hobject *obj, duk_hstring *key) {\n\tduk_propdesc dummy;\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(thr->heap != NULL);\n\tDUK_ASSERT(obj != NULL);\n\tDUK_ASSERT(key != NULL);\n\n\tDUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);\n\n\treturn duk__get_propdesc(thr, obj, key, &dummy, DUK_GETDESC_FLAG_IGNORE_PROTOLOOP);  /* don't push value */\n}\n\n/*\n *  Helper: handle Array object 'length' write which automatically\n *  deletes properties, see E5 Section 15.4.5.1, step 3.  This is\n *  quite tricky to get right.\n *\n *  Used by duk_hobject_putprop().\n */\n\n/* Coerce a new .length candidate to a number and check that it's a valid\n * .length.\n */\nDUK_LOCAL duk_uint32_t duk__to_new_array_length_checked(duk_hthread *thr, duk_tval *tv) {\n\tduk_uint32_t res;\n\tduk_double_t d;\n\n#if !defined(DUK_USE_PREFER_SIZE)\n#if defined(DUK_USE_FASTINT)\n\t/* When fastints are enabled, the most interesting case is assigning\n\t * a fastint to .length (e.g. arr.length = 0).\n\t */\n\tif (DUK_TVAL_IS_FASTINT(tv)) {\n\t\t/* Very common case. */\n\t\tduk_int64_t fi;\n\t\tfi = DUK_TVAL_GET_FASTINT(tv);\n\t\tif (fi < 0 || fi > DUK_I64_CONSTANT(0xffffffff)) {\n\t\t\tgoto fail_range;\n\t\t}\n\t\treturn (duk_uint32_t) fi;\n\t}\n#else  /* DUK_USE_FASTINT */\n\t/* When fastints are not enabled, the most interesting case is any\n\t * number.\n\t */\n\tif (DUK_TVAL_IS_DOUBLE(tv)) {\n\t\td = DUK_TVAL_GET_NUMBER(tv);\n\t}\n#endif  /* DUK_USE_FASTINT */\n\telse\n#endif  /* !DUK_USE_PREFER_SIZE */\n\t{\n\t\t/* In all other cases, and when doing a size optimized build,\n\t\t * fall back to the comprehensive handler.\n\t\t */\n\t\td = duk_js_tonumber(thr, tv);\n\t}\n\n\t/* Refuse to update an Array's 'length' to a value outside the\n\t * 32-bit range.  Negative zero is accepted as zero.\n\t */\n\tres = (duk_uint32_t) d;\n\tif ((duk_double_t) res != d) {\n\t\tgoto fail_range;\n\t}\n\n\treturn res;\n\n fail_range:\n\tDUK_ERROR_RANGE(thr, DUK_STR_INVALID_ARRAY_LENGTH);\n\treturn 0;  /* unreachable */\n}\n\n/* Delete elements required by a smaller length, taking into account\n * potentially non-configurable elements.  Returns non-zero if all\n * elements could be deleted, and zero if all or some elements could\n * not be deleted.  Also writes final \"target length\" to 'out_result_len'.\n * This is the length value that should go into the 'length' property\n * (must be set by the caller).  Never throws an error.\n */\nDUK_LOCAL\nduk_bool_t duk__handle_put_array_length_smaller(duk_hthread *thr,\n                                                duk_hobject *obj,\n                                                duk_uint32_t old_len,\n                                                duk_uint32_t new_len,\n                                                duk_bool_t force_flag,\n                                                duk_uint32_t *out_result_len) {\n\tduk_uint32_t target_len;\n\tduk_uint_fast32_t i;\n\tduk_uint32_t arr_idx;\n\tduk_hstring *key;\n\tduk_tval *tv;\n\tduk_bool_t rc;\n\n\tDUK_DDD(DUK_DDDPRINT(\"new array length smaller than old (%ld -> %ld), \"\n\t                     \"probably need to remove elements\",\n\t                     (long) old_len, (long) new_len));\n\n\t/*\n\t *  New length is smaller than old length, need to delete properties above\n\t *  the new length.\n\t *\n\t *  If array part exists, this is straightforward: array entries cannot\n\t *  be non-configurable so this is guaranteed to work.\n\t *\n\t *  If array part does not exist, array-indexed values are scattered\n\t *  in the entry part, and some may not be configurable (preventing length\n\t *  from becoming lower than their index + 1).  To handle the algorithm\n\t *  in E5 Section 15.4.5.1, step l correctly, we scan the entire property\n\t *  set twice.\n\t */\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(obj != NULL);\n\tDUK_ASSERT(new_len < old_len);\n\tDUK_ASSERT(out_result_len != NULL);\n\tDUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);\n\n\tDUK_ASSERT(DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj));\n\tDUK_ASSERT(DUK_HOBJECT_IS_ARRAY(obj));\n\n\tif (DUK_HOBJECT_HAS_ARRAY_PART(obj)) {\n\t\t/*\n\t\t *  All defined array-indexed properties are in the array part\n\t\t *  (we assume the array part is comprehensive), and all array\n\t\t *  entries are writable, configurable, and enumerable.  Thus,\n\t\t *  nothing can prevent array entries from being deleted.\n\t\t */\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"have array part, easy case\"));\n\n\t\tif (old_len < DUK_HOBJECT_GET_ASIZE(obj)) {\n\t\t\t/* XXX: assertion that entries >= old_len are already unused */\n\t\t\ti = old_len;\n\t\t} else {\n\t\t\ti = DUK_HOBJECT_GET_ASIZE(obj);\n\t\t}\n\t\tDUK_ASSERT(i <= DUK_HOBJECT_GET_ASIZE(obj));\n\n\t\twhile (i > new_len) {\n\t\t\ti--;\n\t\t\ttv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, i);\n\t\t\tDUK_TVAL_SET_UNUSED_UPDREF(thr, tv);  /* side effects */\n\t\t}\n\n\t\t*out_result_len = new_len;\n\t\treturn 1;\n\t} else {\n\t\t/*\n\t\t *  Entries part is a bit more complex.\n\t\t */\n\n\t\t/* Stage 1: find highest preventing non-configurable entry (if any).\n\t\t * When forcing, ignore non-configurability.\n\t\t */\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"no array part, slow case\"));\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"array length write, no array part, stage 1: find target_len \"\n\t\t                     \"(highest preventing non-configurable entry (if any))\"));\n\n\t\ttarget_len = new_len;\n\t\tif (force_flag) {\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"array length write, no array part; force flag -> skip stage 1\"));\n\t\t\tgoto skip_stage1;\n\t\t}\n\t\tfor (i = 0; i < DUK_HOBJECT_GET_ENEXT(obj); i++) {\n\t\t\tkey = DUK_HOBJECT_E_GET_KEY(thr->heap, obj, i);\n\t\t\tif (!key) {\n\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"skip entry index %ld: null key\", (long) i));\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (!DUK_HSTRING_HAS_ARRIDX(key)) {\n\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"skip entry index %ld: key not an array index\", (long) i));\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tDUK_ASSERT(DUK_HSTRING_HAS_ARRIDX(key));  /* XXX: macro checks for array index flag, which is unnecessary here */\n\t\t\tarr_idx = DUK_HSTRING_GET_ARRIDX_SLOW(key);\n\t\t\tDUK_ASSERT(arr_idx != DUK__NO_ARRAY_INDEX);\n\t\t\tDUK_ASSERT(arr_idx < old_len);  /* consistency requires this */\n\n\t\t\tif (arr_idx < new_len) {\n\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"skip entry index %ld: key is array index %ld, below new_len\",\n\t\t\t\t                     (long) i, (long) arr_idx));\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (DUK_HOBJECT_E_SLOT_IS_CONFIGURABLE(thr->heap, obj, i)) {\n\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"skip entry index %ld: key is a relevant array index %ld, but configurable\",\n\t\t\t\t                     (long) i, (long) arr_idx));\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t/* relevant array index is non-configurable, blocks write */\n\t\t\tif (arr_idx >= target_len) {\n\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"entry at index %ld has arr_idx %ld, is not configurable, \"\n\t\t\t\t                     \"update target_len %ld -> %ld\",\n\t\t\t\t                     (long) i, (long) arr_idx, (long) target_len,\n\t\t\t\t                     (long) (arr_idx + 1)));\n\t\t\t\ttarget_len = arr_idx + 1;\n\t\t\t}\n\t\t}\n\t skip_stage1:\n\n\t\t/* stage 2: delete configurable entries above target length */\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"old_len=%ld, new_len=%ld, target_len=%ld\",\n\t\t                     (long) old_len, (long) new_len, (long) target_len));\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"array length write, no array part, stage 2: remove \"\n\t\t                     \"entries >= target_len\"));\n\n\t\tfor (i = 0; i < DUK_HOBJECT_GET_ENEXT(obj); i++) {\n\t\t\tkey = DUK_HOBJECT_E_GET_KEY(thr->heap, obj, i);\n\t\t\tif (!key) {\n\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"skip entry index %ld: null key\", (long) i));\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (!DUK_HSTRING_HAS_ARRIDX(key)) {\n\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"skip entry index %ld: key not an array index\", (long) i));\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tDUK_ASSERT(DUK_HSTRING_HAS_ARRIDX(key));  /* XXX: macro checks for array index flag, which is unnecessary here */\n\t\t\tarr_idx = DUK_HSTRING_GET_ARRIDX_SLOW(key);\n\t\t\tDUK_ASSERT(arr_idx != DUK__NO_ARRAY_INDEX);\n\t\t\tDUK_ASSERT(arr_idx < old_len);  /* consistency requires this */\n\n\t\t\tif (arr_idx < target_len) {\n\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"skip entry index %ld: key is array index %ld, below target_len\",\n\t\t\t\t                     (long) i, (long) arr_idx));\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tDUK_ASSERT(force_flag || DUK_HOBJECT_E_SLOT_IS_CONFIGURABLE(thr->heap, obj, i));  /* stage 1 guarantees */\n\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"delete entry index %ld: key is array index %ld\",\n\t\t\t                     (long) i, (long) arr_idx));\n\n\t\t\t/*\n\t\t\t *  Slow delete, but we don't care as we're already in a very slow path.\n\t\t\t *  The delete always succeeds: key has no exotic behavior, property\n\t\t\t *  is configurable, and no resize occurs.\n\t\t\t */\n\t\t\trc = duk_hobject_delprop_raw(thr, obj, key, force_flag ? DUK_DELPROP_FLAG_FORCE : 0);\n\t\t\tDUK_UNREF(rc);\n\t\t\tDUK_ASSERT(rc != 0);\n\t\t}\n\n\t\t/* stage 3: update length (done by caller), decide return code */\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"array length write, no array part, stage 3: update length (done by caller)\"));\n\n\t\t*out_result_len = target_len;\n\n\t\tif (target_len == new_len) {\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"target_len matches new_len, return success\"));\n\t\t\treturn 1;\n\t\t}\n\t\tDUK_DDD(DUK_DDDPRINT(\"target_len does not match new_len (some entry prevented \"\n\t\t                     \"full length adjustment), return error\"));\n\t\treturn 0;\n\t}\n\n\tDUK_UNREACHABLE();\n}\n\n/* XXX: is valstack top best place for argument? */\nDUK_LOCAL duk_bool_t duk__handle_put_array_length(duk_hthread *thr, duk_hobject *obj) {\n\tduk_harray *a;\n\tduk_uint32_t old_len;\n\tduk_uint32_t new_len;\n\tduk_uint32_t result_len;\n\tduk_bool_t rc;\n\n\tDUK_DDD(DUK_DDDPRINT(\"handling a put operation to array 'length' exotic property, \"\n\t                     \"new val: %!T\",\n\t                     (duk_tval *) duk_get_tval(thr, -1)));\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(obj != NULL);\n\n\tDUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);\n\n\tDUK_ASSERT(DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj));\n\tDUK_ASSERT(DUK_HOBJECT_IS_ARRAY(obj));\n\ta = (duk_harray *) obj;\n\tDUK_ASSERT_HARRAY_VALID(a);\n\n\tDUK_ASSERT(duk_is_valid_index(thr, -1));\n\n\t/*\n\t *  Get old and new length\n\t */\n\n\told_len = a->length;\n\tnew_len = duk__to_new_array_length_checked(thr, DUK_GET_TVAL_NEGIDX(thr, -1));\n\tDUK_DDD(DUK_DDDPRINT(\"old_len=%ld, new_len=%ld\", (long) old_len, (long) new_len));\n\n\t/*\n\t *  Writability check\n\t */\n\n\tif (DUK_HARRAY_LENGTH_NONWRITABLE(a)) {\n\t\tDUK_DDD(DUK_DDDPRINT(\"length is not writable, fail\"));\n\t\treturn 0;\n\t}\n\n\t/*\n\t *  New length not lower than old length => no changes needed\n\t *  (not even array allocation).\n\t */\n\n\tif (new_len >= old_len) {\n\t\tDUK_DDD(DUK_DDDPRINT(\"new length is same or higher than old length, just update length, no deletions\"));\n\t\ta->length = new_len;\n\t\treturn 1;\n\t}\n\n\tDUK_DDD(DUK_DDDPRINT(\"new length is lower than old length, probably must delete entries\"));\n\n\t/*\n\t *  New length lower than old length => delete elements, then\n\t *  update length.\n\t *\n\t *  Note: even though a bunch of elements have been deleted, the 'desc' is\n\t *  still valid as properties haven't been resized (and entries compacted).\n\t */\n\n\trc = duk__handle_put_array_length_smaller(thr, obj, old_len, new_len, 0 /*force_flag*/, &result_len);\n\tDUK_ASSERT(result_len >= new_len && result_len <= old_len);\n\n\ta->length = result_len;\n\n\t/* XXX: shrink array allocation or entries compaction here? */\n\n\treturn rc;\n}\n\n/*\n *  PUTPROP: Ecmascript property write.\n *\n *  Unlike Ecmascript primitive which returns nothing, returns 1 to indicate\n *  success and 0 to indicate failure (assuming throw is not set).\n *\n *  This is an extremely tricky function.  Some examples:\n *\n *    * Currently a decref may trigger a GC, which may compact an object's\n *      property allocation.  Consequently, any entry indices (e_idx) will\n *      be potentially invalidated by a decref.\n *\n *    * Exotic behaviors (strings, arrays, arguments object) require,\n *      among other things:\n *\n *      - Preprocessing before and postprocessing after an actual property\n *        write.  For example, array index write requires pre-checking the\n *        array 'length' property for access control, and may require an\n *        array 'length' update after the actual write has succeeded (but\n *        not if it fails).\n *\n *      - Deletion of multiple entries, as a result of array 'length' write.\n *\n *    * Input values are taken as pointers which may point to the valstack.\n *      If valstack is resized because of the put (this may happen at least\n *      when the array part is abandoned), the pointers can be invalidated.\n *      (We currently make a copy of all of the input values to avoid issues.)\n */\n\nDUK_INTERNAL duk_bool_t duk_hobject_putprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key, duk_tval *tv_val, duk_bool_t throw_flag) {\n\tduk_tval tv_obj_copy;\n\tduk_tval tv_key_copy;\n\tduk_tval tv_val_copy;\n\tduk_hobject *orig = NULL;  /* NULL if tv_obj is primitive */\n\tduk_hobject *curr;\n\tduk_hstring *key = NULL;\n\tduk_propdesc desc;\n\tduk_tval *tv;\n\tduk_uint32_t arr_idx;\n\tduk_bool_t rc;\n\tduk_int_t e_idx;\n\tduk_uint_t sanity;\n\tduk_uint32_t new_array_length = 0;  /* 0 = no update */\n\n\tDUK_DDD(DUK_DDDPRINT(\"putprop: thr=%p, obj=%p, key=%p, val=%p, throw=%ld \"\n\t                     \"(obj -> %!T, key -> %!T, val -> %!T)\",\n\t                     (void *) thr, (void *) tv_obj, (void *) tv_key, (void *) tv_val,\n\t                     (long) throw_flag, (duk_tval *) tv_obj, (duk_tval *) tv_key, (duk_tval *) tv_val));\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(thr->heap != NULL);\n\tDUK_ASSERT(tv_obj != NULL);\n\tDUK_ASSERT(tv_key != NULL);\n\tDUK_ASSERT(tv_val != NULL);\n\n\tDUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);\n\n\tDUK_STATS_INC(thr->heap, stats_putprop_all);\n\n\t/*\n\t *  Make a copy of tv_obj, tv_key, and tv_val to avoid any issues of\n\t *  them being invalidated by a valstack resize.\n\t *\n\t *  XXX: this is an overkill for some paths, so optimize this later\n\t *  (or maybe switch to a stack arguments model entirely).\n\t */\n\n\tDUK_TVAL_SET_TVAL(&tv_obj_copy, tv_obj);\n\tDUK_TVAL_SET_TVAL(&tv_key_copy, tv_key);\n\tDUK_TVAL_SET_TVAL(&tv_val_copy, tv_val);\n\ttv_obj = &tv_obj_copy;\n\ttv_key = &tv_key_copy;\n\ttv_val = &tv_val_copy;\n\n\t/*\n\t *  Coercion and fast path processing.\n\t */\n\n\tswitch (DUK_TVAL_GET_TAG(tv_obj)) {\n\tcase DUK_TAG_UNDEFINED:\n\tcase DUK_TAG_NULL: {\n\t\t/* Note: unconditional throw */\n\t\tDUK_DDD(DUK_DDDPRINT(\"base object is undefined or null -> reject (object=%!iT)\",\n\t\t                     (duk_tval *) tv_obj));\n#if defined(DUK_USE_PARANOID_ERRORS)\n\t\tDUK_ERROR_TYPE(thr, DUK_STR_INVALID_BASE);\n#else\n\t\tDUK_ERROR_FMT2(thr, DUK_ERR_TYPE_ERROR, \"cannot write property %s of %s\",\n\t\t               duk_push_string_tval_readable(thr, tv_key), duk_push_string_tval_readable(thr, tv_obj));\n#endif\n\t\treturn 0;\n\t}\n\n\tcase DUK_TAG_BOOLEAN: {\n\t\tDUK_DDD(DUK_DDDPRINT(\"base object is a boolean, start lookup from boolean prototype\"));\n\t\tcurr = thr->builtins[DUK_BIDX_BOOLEAN_PROTOTYPE];\n\t\tbreak;\n\t}\n\n\tcase DUK_TAG_STRING: {\n\t\tduk_hstring *h = DUK_TVAL_GET_STRING(tv_obj);\n\n\t\t/*\n\t\t *  Note: currently no fast path for array index writes.\n\t\t *  They won't be possible anyway as strings are immutable.\n\t\t */\n\n\t\tDUK_ASSERT(key == NULL);\n\t\tarr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);\n\t\tDUK_ASSERT(key != NULL);\n\n\t\tif (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(h))) {\n\t\t\t/* Symbols (ES2015 or hidden) don't have virtual properties. */\n\t\t\tcurr = thr->builtins[DUK_BIDX_SYMBOL_PROTOTYPE];\n\t\t\tgoto lookup;\n\t\t}\n\n\t\tif (key == DUK_HTHREAD_STRING_LENGTH(thr)) {\n\t\t\tgoto fail_not_writable;\n\t\t}\n\n\t\tif (arr_idx != DUK__NO_ARRAY_INDEX &&\n\t\t    arr_idx < DUK_HSTRING_GET_CHARLEN(h)) {\n\t\t\tgoto fail_not_writable;\n\t\t}\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"base object is a string, start lookup from string prototype\"));\n\t\tcurr = thr->builtins[DUK_BIDX_STRING_PROTOTYPE];\n\t\tgoto lookup;  /* avoid double coercion */\n\t}\n\n\tcase DUK_TAG_OBJECT: {\n\t\torig = DUK_TVAL_GET_OBJECT(tv_obj);\n\t\tDUK_ASSERT(orig != NULL);\n\n#if defined(DUK_USE_ROM_OBJECTS)\n\t\t/* With this check in place fast paths won't need read-only\n\t\t * object checks.  This is technically incorrect if there are\n\t\t * setters that cause no writes to ROM objects, but current\n\t\t * built-ins don't have such setters.\n\t\t */\n\t\tif (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) orig)) {\n\t\t\tDUK_DD(DUK_DDPRINT(\"attempt to putprop on read-only target object\"));\n\t\t\tgoto fail_not_writable_no_pop;  /* Must avoid duk_pop() in exit path */\n\t\t}\n#endif\n\n\t\t/* The fast path for array property put is not fully compliant:\n\t\t * If one places conflicting number-indexed properties into\n\t\t * Array.prototype (for example, a non-writable Array.prototype[7])\n\t\t * the fast path will incorrectly ignore them.\n\t\t *\n\t\t * This fast path could be made compliant by falling through\n\t\t * to the slow path if the previous value was UNUSED.  This would\n\t\t * also remove the need to check for extensibility.  Right now a\n\t\t * non-extensible array is slower than an extensible one as far\n\t\t * as writes are concerned.\n\t\t *\n\t\t * The fast path behavior is documented in more detail here:\n\t\t * tests/ecmascript/test-misc-array-fast-write.js\n\t\t */\n\n\t\t/* XXX: array .length? */\n\n#if defined(DUK_USE_ARRAY_PROP_FASTPATH)\n\t\tif (duk__putprop_shallow_fastpath_array_tval(thr, orig, tv_key, tv_val) != 0) {\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"array fast path success\"));\n\t\t\tDUK_STATS_INC(thr->heap, stats_putprop_arrayidx);\n\t\t\treturn 1;\n\t\t}\n#endif\n\n#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)\n\t\tif (duk__putprop_fastpath_bufobj_tval(thr, orig, tv_key, tv_val) != 0) {\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"base is bufobj, key is a number, bufobj fast path\"));\n\t\t\tDUK_STATS_INC(thr->heap, stats_putprop_bufobjidx);\n\t\t\treturn 1;\n\t\t}\n#endif\n\n#if defined(DUK_USE_ES6_PROXY)\n\t\tif (DUK_UNLIKELY(DUK_HOBJECT_IS_PROXY(orig))) {\n\t\t\tduk_hobject *h_target;\n\t\t\tduk_bool_t tmp_bool;\n\n\t\t\tif (duk__proxy_check_prop(thr, orig, DUK_STRIDX_SET, tv_key, &h_target)) {\n\t\t\t\t/* -> [ ... trap handler ] */\n\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"-> proxy object 'set' for key %!T\", (duk_tval *) tv_key));\n\t\t\t\tDUK_STATS_INC(thr->heap, stats_putprop_proxy);\n\t\t\t\tduk_push_hobject(thr, h_target);  /* target */\n\t\t\t\tduk_push_tval(thr, tv_key);       /* P */\n\t\t\t\tduk_push_tval(thr, tv_val);       /* V */\n\t\t\t\tduk_push_tval(thr, tv_obj);       /* Receiver: Proxy object */\n\t\t\t\tduk_call_method(thr, 4 /*nargs*/);\n\t\t\t\ttmp_bool = duk_to_boolean(thr, -1);\n\t\t\t\tduk_pop_nodecref_unsafe(thr);\n\t\t\t\tif (!tmp_bool) {\n\t\t\t\t\tgoto fail_proxy_rejected;\n\t\t\t\t}\n\n\t\t\t\t/* Target object must be checked for a conflicting\n\t\t\t\t * non-configurable property.\n\t\t\t\t */\n\t\t\t\tarr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);\n\t\t\t\tDUK_ASSERT(key != NULL);\n\n\t\t\t\tif (duk__get_own_propdesc_raw(thr, h_target, key, arr_idx, &desc, DUK_GETDESC_FLAG_PUSH_VALUE)) {\n\t\t\t\t\tduk_tval *tv_targ = duk_require_tval(thr, -1);\n\t\t\t\t\tduk_bool_t datadesc_reject;\n\t\t\t\t\tduk_bool_t accdesc_reject;\n\n\t\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"proxy 'set': target has matching property %!O, check for \"\n\t\t\t\t\t                     \"conflicting property; tv_val=%!T, tv_targ=%!T, desc.flags=0x%08lx, \"\n\t\t\t\t\t                     \"desc.get=%p, desc.set=%p\",\n\t\t\t\t\t                     (duk_heaphdr *) key, (duk_tval *) tv_val, (duk_tval *) tv_targ,\n\t\t\t\t\t                     (unsigned long) desc.flags,\n\t\t\t\t\t                     (void *) desc.get, (void *) desc.set));\n\n\t\t\t\t\tdatadesc_reject = !(desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) &&\n\t\t\t\t\t                  !(desc.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) &&\n\t\t\t\t\t                  !(desc.flags & DUK_PROPDESC_FLAG_WRITABLE) &&\n\t\t\t\t\t                  !duk_js_samevalue(tv_val, tv_targ);\n\t\t\t\t\taccdesc_reject = (desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) &&\n\t\t\t\t\t                 !(desc.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) &&\n\t\t\t\t\t                 (desc.set == NULL);\n\t\t\t\t\tif (datadesc_reject || accdesc_reject) {\n\t\t\t\t\t\tDUK_ERROR_TYPE(thr, DUK_STR_PROXY_REJECTED);\n\t\t\t\t\t}\n\n\t\t\t\t\tduk_pop_2_unsafe(thr);\n\t\t\t\t} else {\n\t\t\t\t\tduk_pop_unsafe(thr);\n\t\t\t\t}\n\t\t\t\treturn 1;  /* success */\n\t\t\t}\n\n\t\t\torig = h_target;  /* resume write to target */\n\t\t\tDUK_TVAL_SET_OBJECT(tv_obj, orig);\n\t\t}\n#endif  /* DUK_USE_ES6_PROXY */\n\n\t\tcurr = orig;\n\t\tbreak;\n\t}\n\n\tcase DUK_TAG_BUFFER: {\n\t\tduk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv_obj);\n\t\tduk_int_t pop_count = 0;\n\n\t\t/*\n\t\t *  Because buffer values may be looped over and read/written\n\t\t *  from, an array index fast path is important.\n\t\t */\n\n#if defined(DUK_USE_FASTINT)\n\t\tif (DUK_TVAL_IS_FASTINT(tv_key)) {\n\t\t\tarr_idx = duk__tval_fastint_to_arr_idx(tv_key);\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"base object buffer, key is a fast-path fastint; arr_idx %ld\", (long) arr_idx));\n\t\t\tpop_count = 0;\n\t\t} else\n#endif\n\t\tif (DUK_TVAL_IS_NUMBER(tv_key)) {\n\t\t\tarr_idx = duk__tval_number_to_arr_idx(tv_key);\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"base object buffer, key is a fast-path number; arr_idx %ld\", (long) arr_idx));\n\t\t\tpop_count = 0;\n\t\t} else {\n\t\t\tarr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);\n\t\t\tDUK_ASSERT(key != NULL);\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"base object buffer, key is a non-fast-path number; after \"\n\t\t\t                     \"coercion key is %!T, arr_idx %ld\",\n\t\t\t                     (duk_tval *) duk_get_tval(thr, -1), (long) arr_idx));\n\t\t\tpop_count = 1;\n\t\t}\n\n\t\tif (arr_idx != DUK__NO_ARRAY_INDEX &&\n\t\t    arr_idx < DUK_HBUFFER_GET_SIZE(h)) {\n\t\t\tduk_uint8_t *data;\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"writing to buffer data at index %ld\", (long) arr_idx));\n\t\t\tdata = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h);\n\n\t\t\t/* XXX: duk_to_int() ensures we'll get 8 lowest bits as\n\t\t\t * as input is within duk_int_t range (capped outside it).\n\t\t\t */\n#if defined(DUK_USE_FASTINT)\n\t\t\t/* Buffer writes are often integers. */\n\t\t\tif (DUK_TVAL_IS_FASTINT(tv_val)) {\n\t\t\t\tdata[arr_idx] = (duk_uint8_t) DUK_TVAL_GET_FASTINT_U32(tv_val);\n\t\t\t}\n\t\t\telse\n#endif\n\t\t\t{\n\t\t\t\tduk_push_tval(thr, tv_val);\n\t\t\t\tdata[arr_idx] = (duk_uint8_t) duk_to_uint32(thr, -1);\n\t\t\t\tpop_count++;\n\t\t\t}\n\n\t\t\tduk_pop_n_unsafe(thr, pop_count);\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"result: success (buffer data write)\"));\n\t\t\tDUK_STATS_INC(thr->heap, stats_putprop_bufferidx);\n\t\t\treturn 1;\n\t\t}\n\n\t\tif (pop_count == 0) {\n\t\t\t/* This is a pretty awkward control flow, but we need to recheck the\n\t\t\t * key coercion here.\n\t\t\t */\n\t\t\tarr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);\n\t\t\tDUK_ASSERT(key != NULL);\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"base object buffer, key is a non-fast-path number; after \"\n\t\t\t                     \"coercion key is %!T, arr_idx %ld\",\n\t\t\t                     (duk_tval *) duk_get_tval(thr, -1), (long) arr_idx));\n\t\t}\n\n\t\tif (key == DUK_HTHREAD_STRING_LENGTH(thr)) {\n\t\t\tgoto fail_not_writable;\n\t\t}\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"base object is a buffer, start lookup from Uint8Array prototype\"));\n\t\tcurr = thr->builtins[DUK_BIDX_UINT8ARRAY_PROTOTYPE];\n\t\tgoto lookup;  /* avoid double coercion */\n\t}\n\n\tcase DUK_TAG_POINTER: {\n\t\tDUK_DDD(DUK_DDDPRINT(\"base object is a pointer, start lookup from pointer prototype\"));\n\t\tcurr = thr->builtins[DUK_BIDX_POINTER_PROTOTYPE];\n\t\tbreak;\n\t}\n\n\tcase DUK_TAG_LIGHTFUNC: {\n\t\t/* Lightfuncs have no own properties and are considered non-extensible.\n\t\t * However, the write may be captured by an inherited setter which\n\t\t * means we can't stop the lookup here.\n\t\t */\n\t\tDUK_DDD(DUK_DDDPRINT(\"base object is a lightfunc, start lookup from function prototype\"));\n\t\tcurr = thr->builtins[DUK_BIDX_NATIVE_FUNCTION_PROTOTYPE];\n\t\tbreak;\n\t}\n\n#if defined(DUK_USE_FASTINT)\n\tcase DUK_TAG_FASTINT:\n#endif\n\tdefault: {\n\t\t/* number */\n\t\tDUK_DDD(DUK_DDDPRINT(\"base object is a number, start lookup from number prototype\"));\n\t\tDUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_obj));\n\t\tcurr = thr->builtins[DUK_BIDX_NUMBER_PROTOTYPE];\n\t\tbreak;\n\t}\n\t}\n\n\tDUK_ASSERT(key == NULL);\n\tarr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);\n\tDUK_ASSERT(key != NULL);\n\n lookup:\n\n\t/*\n\t *  Check whether the property already exists in the prototype chain.\n\t *  Note that the actual write goes into the original base object\n\t *  (except if an accessor property captures the write).\n\t */\n\n\t/* [key] */\n\n\tDUK_ASSERT(curr != NULL);\n\tsanity = DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY;\n\tdo {\n\t\tif (!duk__get_own_propdesc_raw(thr, curr, key, arr_idx, &desc, 0 /*flags*/)) {  /* don't push value */\n\t\t\tgoto next_in_chain;\n\t\t}\n\n\t\tif (desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) {\n\t\t\t/*\n\t\t\t *  Found existing accessor property (own or inherited).\n\t\t\t *  Call setter with 'this' set to orig, and value as the only argument.\n\t\t\t *  Setter calls are OK even for ROM objects.\n\t\t\t *\n\t\t\t *  Note: no exotic arguments object behavior, because [[Put]] never\n\t\t\t *  calls [[DefineOwnProperty]] (E5 Section 8.12.5, step 5.b).\n\t\t\t */\n\n\t\t\tduk_hobject *setter;\n\n\t\t\tDUK_DD(DUK_DDPRINT(\"put to an own or inherited accessor, calling setter\"));\n\n\t\t\tsetter = DUK_HOBJECT_E_GET_VALUE_SETTER(thr->heap, curr, desc.e_idx);\n\t\t\tif (!setter) {\n\t\t\t\tgoto fail_no_setter;\n\t\t\t}\n\t\t\tduk_push_hobject(thr, setter);\n\t\t\tduk_push_tval(thr, tv_obj);  /* note: original, uncoerced base */\n\t\t\tduk_push_tval(thr, tv_val);  /* [key setter this val] */\n#if defined(DUK_USE_NONSTD_SETTER_KEY_ARGUMENT)\n\t\t\tduk_dup_m4(thr);\n\t\t\tduk_call_method(thr, 2);     /* [key setter this val key] -> [key retval] */\n#else\n\t\t\tduk_call_method(thr, 1);     /* [key setter this val] -> [key retval] */\n#endif\n\t\t\tduk_pop_unsafe(thr);         /* ignore retval -> [key] */\n\t\t\tgoto success_no_arguments_exotic;\n\t\t}\n\n\t\tif (orig == NULL) {\n\t\t\t/*\n\t\t\t *  Found existing own or inherited plain property, but original\n\t\t\t *  base is a primitive value.\n\t\t\t */\n\t\t\tDUK_DD(DUK_DDPRINT(\"attempt to create a new property in a primitive base object\"));\n\t\t\tgoto fail_base_primitive;\n\t\t}\n\n\t\tif (curr != orig) {\n\t\t\t/*\n\t\t\t *  Found existing inherited plain property.\n\t\t\t *  Do an access control check, and if OK, write\n\t\t\t *  new property to 'orig'.\n\t\t\t */\n\t\t\tif (!DUK_HOBJECT_HAS_EXTENSIBLE(orig)) {\n\t\t\t\tDUK_DD(DUK_DDPRINT(\"found existing inherited plain property, but original object is not extensible\"));\n\t\t\t\tgoto fail_not_extensible;\n\t\t\t}\n\t\t\tif (!(desc.flags & DUK_PROPDESC_FLAG_WRITABLE)) {\n\t\t\t\tDUK_DD(DUK_DDPRINT(\"found existing inherited plain property, original object is extensible, but inherited property is not writable\"));\n\t\t\t\tgoto fail_not_writable;\n\t\t\t}\n\t\t\tDUK_DD(DUK_DDPRINT(\"put to new property, object extensible, inherited property found and is writable\"));\n\t\t\tgoto create_new;\n\t\t} else {\n\t\t\t/*\n\t\t\t *  Found existing own (non-inherited) plain property.\n\t\t\t *  Do an access control check and update in place.\n\t\t\t */\n\n\t\t\tif (!(desc.flags & DUK_PROPDESC_FLAG_WRITABLE)) {\n\t\t\t\tDUK_DD(DUK_DDPRINT(\"found existing own (non-inherited) plain property, but property is not writable\"));\n\t\t\t\tgoto fail_not_writable;\n\t\t\t}\n\t\t\tif (desc.flags & DUK_PROPDESC_FLAG_VIRTUAL) {\n\t\t\t\tDUK_DD(DUK_DDPRINT(\"found existing own (non-inherited) virtual property, property is writable\"));\n\n\t\t\t\tif (DUK_HOBJECT_IS_ARRAY(curr)) {\n\t\t\t\t\t/*\n\t\t\t\t\t *  Write to 'length' of an array is a very complex case\n\t\t\t\t\t *  handled in a helper which updates both the array elements\n\t\t\t\t\t *  and writes the new 'length'.  The write may result in an\n\t\t\t\t\t *  unconditional RangeError or a partial write (indicated\n\t\t\t\t\t *  by a return code).\n\t\t\t\t\t *\n\t\t\t\t\t *  Note: the helper has an unnecessary writability check\n\t\t\t\t\t *  for 'length', we already know it is writable.\n\t\t\t\t\t */\n\t\t\t\t\tDUK_ASSERT(key == DUK_HTHREAD_STRING_LENGTH(thr));  /* only virtual array property */\n\n\t\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"writing existing 'length' property to array exotic, invoke complex helper\"));\n\n\t\t\t\t\t/* XXX: the helper currently assumes stack top contains new\n\t\t\t\t\t * 'length' value and the whole calling convention is not very\n\t\t\t\t\t * compatible with what we need.\n\t\t\t\t\t */\n\n\t\t\t\t\tduk_push_tval(thr, tv_val);  /* [key val] */\n\t\t\t\t\trc = duk__handle_put_array_length(thr, orig);\n\t\t\t\t\tduk_pop_unsafe(thr);  /* [key val] -> [key] */\n\t\t\t\t\tif (!rc) {\n\t\t\t\t\t\tgoto fail_array_length_partial;\n\t\t\t\t\t}\n\n\t\t\t\t\t/* key is 'length', cannot match argument exotic behavior */\n\t\t\t\t\tgoto success_no_arguments_exotic;\n\t\t\t\t}\n#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)\n\t\t\t\telse if (DUK_HOBJECT_IS_BUFOBJ(curr)) {\n\t\t\t\t\tduk_hbufobj *h_bufobj;\n\t\t\t\t\tduk_uint_t byte_off;\n\t\t\t\t\tduk_small_uint_t elem_size;\n\n\t\t\t\t\th_bufobj = (duk_hbufobj *) curr;\n\t\t\t\t\tDUK_ASSERT_HBUFOBJ_VALID(h_bufobj);\n\n\t\t\t\t\tDUK_DD(DUK_DDPRINT(\"writable virtual property is in buffer object\"));\n\n\t\t\t\t\t/* Careful with wrapping: arr_idx upshift may easily wrap, whereas\n\t\t\t\t\t * length downshift won't.\n\t\t\t\t\t */\n\t\t\t\t\tif (arr_idx < (h_bufobj->length >> h_bufobj->shift) && DUK_HBUFOBJ_HAS_VIRTUAL_INDICES(h_bufobj)) {\n\t\t\t\t\t\tduk_uint8_t *data;\n\t\t\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"writing to buffer data at index %ld\", (long) arr_idx));\n\n\t\t\t\t\t\tDUK_ASSERT(arr_idx != DUK__NO_ARRAY_INDEX);  /* index/length check guarantees */\n\t\t\t\t\t\tbyte_off = arr_idx << h_bufobj->shift;       /* no wrap assuming h_bufobj->length is valid */\n\t\t\t\t\t\telem_size = (duk_small_uint_t) (1U << h_bufobj->shift);\n\n\t\t\t\t\t\t/* Coerce to number before validating pointers etc so that the\n\t\t\t\t\t\t * number coercions in duk_hbufobj_validated_write() are\n\t\t\t\t\t\t * guaranteed to be side effect free and not invalidate the\n\t\t\t\t\t\t * pointer checks we do here.\n\t\t\t\t\t\t */\n\t\t\t\t\t\tduk_push_tval(thr, tv_val);\n\t\t\t\t\t\t(void) duk_to_number_m1(thr);\n\n\t\t\t\t\t\tif (h_bufobj->buf != NULL && DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h_bufobj, byte_off + elem_size)) {\n\t\t\t\t\t\t\tdata = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufobj->buf) + h_bufobj->offset + byte_off;\n\t\t\t\t\t\t\tduk_hbufobj_validated_write(thr, h_bufobj, data, elem_size);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tDUK_D(DUK_DPRINT(\"bufobj access out of underlying buffer, ignoring (write skipped)\"));\n\t\t\t\t\t\t}\n\t\t\t\t\t\tduk_pop_unsafe(thr);\n\t\t\t\t\t\tgoto success_no_arguments_exotic;\n\t\t\t\t\t}\n\t\t\t\t}\n#endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */\n\n\t\t\t\tDUK_D(DUK_DPRINT(\"should not happen, key %!O\", key));\n\t\t\t\tgoto fail_internal;  /* should not happen */\n\t\t\t}\n\t\t\tDUK_DD(DUK_DDPRINT(\"put to existing own plain property, property is writable\"));\n\t\t\tgoto update_old;\n\t\t}\n\t\tDUK_UNREACHABLE();\n\n\t next_in_chain:\n\t\t/* XXX: option to pretend property doesn't exist if sanity limit is\n\t\t * hit might be useful.\n\t\t */\n\t\tif (DUK_UNLIKELY(sanity-- == 0)) {\n\t\t\tDUK_ERROR_RANGE(thr, DUK_STR_PROTOTYPE_CHAIN_LIMIT);\n\t\t}\n\t\tcurr = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, curr);\n\t} while (curr != NULL);\n\n\t/*\n\t *  Property not found in prototype chain.\n\t */\n\n\tDUK_DDD(DUK_DDDPRINT(\"property not found in prototype chain\"));\n\n\tif (orig == NULL) {\n\t\tDUK_DD(DUK_DDPRINT(\"attempt to create a new property in a primitive base object\"));\n\t\tgoto fail_base_primitive;\n\t}\n\n\tif (!DUK_HOBJECT_HAS_EXTENSIBLE(orig)) {\n\t\tDUK_DD(DUK_DDPRINT(\"put to a new property (not found in prototype chain), but original object not extensible\"));\n\t\tgoto fail_not_extensible;\n\t}\n\n\tgoto create_new;\n\n update_old:\n\n\t/*\n\t *  Update an existing property of the base object.\n\t */\n\n\t/* [key] */\n\n\tDUK_DDD(DUK_DDDPRINT(\"update an existing property of the original object\"));\n\n\tDUK_ASSERT(orig != NULL);\n#if defined(DUK_USE_ROM_OBJECTS)\n\t/* This should not happen because DUK_TAG_OBJECT case checks\n\t * for this already, but check just in case.\n\t */\n\tif (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) orig)) {\n\t\tgoto fail_not_writable;\n\t}\n#endif\n\n\t/* Although there are writable virtual properties (e.g. plain buffer\n\t * and buffer object number indices), they are handled before we come\n\t * here.\n\t */\n\tDUK_ASSERT((desc.flags & DUK_PROPDESC_FLAG_VIRTUAL) == 0);\n\tDUK_ASSERT(desc.a_idx >= 0 || desc.e_idx >= 0);\n\n\t/* Array own property .length is handled above. */\n\tDUK_ASSERT(!(DUK_HOBJECT_IS_ARRAY(orig) && key == DUK_HTHREAD_STRING_LENGTH(thr)));\n\n\tif (desc.e_idx >= 0) {\n\t\ttv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, orig, desc.e_idx);\n\t\tDUK_DDD(DUK_DDDPRINT(\"previous entry value: %!iT\", (duk_tval *) tv));\n\t\tDUK_TVAL_SET_TVAL_UPDREF(thr, tv, tv_val);  /* side effects; e_idx may be invalidated */\n\t\t/* don't touch property attributes or hash part */\n\t\tDUK_DD(DUK_DDPRINT(\"put to an existing entry at index %ld -> new value %!iT\",\n\t\t                   (long) desc.e_idx, (duk_tval *) tv));\n\t} else {\n\t\t/* Note: array entries are always writable, so the writability check\n\t\t * above is pointless for them.  The check could be avoided with some\n\t\t * refactoring but is probably not worth it.\n\t\t */\n\n\t\tDUK_ASSERT(desc.a_idx >= 0);\n\t\ttv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, orig, desc.a_idx);\n\t\tDUK_DDD(DUK_DDDPRINT(\"previous array value: %!iT\", (duk_tval *) tv));\n\t\tDUK_TVAL_SET_TVAL_UPDREF(thr, tv, tv_val);  /* side effects; a_idx may be invalidated */\n\t\tDUK_DD(DUK_DDPRINT(\"put to an existing array entry at index %ld -> new value %!iT\",\n\t\t                   (long) desc.a_idx, (duk_tval *) tv));\n\t}\n\n\t/* Regardless of whether property is found in entry or array part,\n\t * it may have arguments exotic behavior (array indices may reside\n\t * in entry part for abandoned / non-existent array parts).\n\t */\n\tgoto success_with_arguments_exotic;\n\n create_new:\n\n\t/*\n\t *  Create a new property in the original object.\n\t *\n\t *  Exotic properties need to be reconsidered here from a write\n\t *  perspective (not just property attributes perspective).\n\t *  However, the property does not exist in the object already,\n\t *  so this limits the kind of exotic properties that apply.\n\t */\n\n\t/* [key] */\n\n\tDUK_DDD(DUK_DDDPRINT(\"create new property to original object\"));\n\n\tDUK_ASSERT(orig != NULL);\n\n\t/* Array own property .length is handled above. */\n\tDUK_ASSERT(!(DUK_HOBJECT_IS_ARRAY(orig) && key == DUK_HTHREAD_STRING_LENGTH(thr)));\n\n#if defined(DUK_USE_ROM_OBJECTS)\n\t/* This should not happen because DUK_TAG_OBJECT case checks\n\t * for this already, but check just in case.\n\t */\n\tif (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) orig)) {\n\t\tgoto fail_not_writable;\n\t}\n#endif\n\n\t/* Not possible because array object 'length' is present\n\t * from its creation and cannot be deleted, and is thus\n\t * caught as an existing property above.\n\t */\n\tDUK_ASSERT(!(DUK_HOBJECT_HAS_EXOTIC_ARRAY(orig) &&\n\t             key == DUK_HTHREAD_STRING_LENGTH(thr)));\n\n\tif (DUK_HOBJECT_HAS_EXOTIC_ARRAY(orig) &&\n\t    arr_idx != DUK__NO_ARRAY_INDEX) {\n\t\t/* automatic length update */\n\t\tduk_uint32_t old_len;\n\t\tduk_harray *a;\n\n\t\ta = (duk_harray *) orig;\n\t\tDUK_ASSERT_HARRAY_VALID(a);\n\n\t\told_len = a->length;\n\n\t\tif (arr_idx >= old_len) {\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"write new array entry requires length update \"\n\t\t\t                     \"(arr_idx=%ld, old_len=%ld)\",\n\t\t\t                     (long) arr_idx, (long) old_len));\n\n\t\t\tif (DUK_HARRAY_LENGTH_NONWRITABLE(a)) {\n\t\t\t\tDUK_DD(DUK_DDPRINT(\"attempt to extend array, but array 'length' is not writable\"));\n\t\t\t\tgoto fail_not_writable;\n\t\t\t}\n\n\t\t\t/* Note: actual update happens once write has been completed\n\t\t\t * without error below.  The write should always succeed\n\t\t\t * from a specification viewpoint, but we may e.g. run out\n\t\t\t * of memory.  It's safer in this order.\n\t\t\t */\n\n\t\t\tDUK_ASSERT(arr_idx != 0xffffffffUL);\n\t\t\tnew_array_length = arr_idx + 1;  /* flag for later write */\n\t\t} else {\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"write new array entry does not require length update \"\n\t\t\t                     \"(arr_idx=%ld, old_len=%ld)\",\n\t\t\t                     (long) arr_idx, (long) old_len));\n\t\t}\n\t}\n\n /* write_to_array_part: */\n\n\t/*\n\t *  Write to array part?\n\t *\n\t *  Note: array abandonding requires a property resize which uses\n\t *  'rechecks' valstack for temporaries and may cause any existing\n\t *  valstack pointers to be invalidated.  To protect against this,\n\t *  tv_obj, tv_key, and tv_val are copies of the original inputs.\n\t */\n\n\tif (arr_idx != DUK__NO_ARRAY_INDEX &&\n\t    DUK_HOBJECT_HAS_ARRAY_PART(orig)) {\n\t\tif (arr_idx < DUK_HOBJECT_GET_ASIZE(orig)) {\n\t\t\tgoto no_array_growth;\n\t\t}\n\n\t\t/*\n\t\t *  Array needs to grow, but we don't want it becoming too sparse.\n\t\t *  If it were to become sparse, abandon array part, moving all\n\t\t *  array entries into the entries part (for good).\n\t\t *\n\t\t *  Since we don't keep track of actual density (used vs. size) of\n\t\t *  the array part, we need to estimate somehow.  The check is made\n\t\t *  in two parts:\n\t\t *\n\t\t *    - Check whether the resize need is small compared to the\n\t\t *      current size (relatively); if so, resize without further\n\t\t *      checking (essentially we assume that the original part is\n\t\t *      \"dense\" so that the result would be dense enough).\n\t\t *\n\t\t *    - Otherwise, compute the resize using an actual density\n\t\t *      measurement based on counting the used array entries.\n\t\t */\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"write to new array requires array resize, decide whether to do a \"\n\t\t                     \"fast resize without abandon check (arr_idx=%ld, old_size=%ld)\",\n\t\t                     (long) arr_idx, (long) DUK_HOBJECT_GET_ASIZE(orig)));\n\n\t\tif (duk__abandon_array_slow_check_required(arr_idx, DUK_HOBJECT_GET_ASIZE(orig))) {\n\t\t\tduk_uint32_t old_used;\n\t\t\tduk_uint32_t old_size;\n\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"=> fast check is NOT OK, do slow check for array abandon\"));\n\n\t\t\tduk__compute_a_stats(thr, orig, &old_used, &old_size);\n\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"abandon check, array stats: old_used=%ld, old_size=%ld, arr_idx=%ld\",\n\t\t\t                     (long) old_used, (long) old_size, (long) arr_idx));\n\n\t\t\t/* Note: intentionally use approximations to shave a few instructions:\n\t\t\t *   a_used = old_used  (accurate: old_used + 1)\n\t\t\t *   a_size = arr_idx   (accurate: arr_idx + 1)\n\t\t\t */\n\t\t\tif (duk__abandon_array_density_check(old_used, arr_idx)) {\n\t\t\t\tDUK_DD(DUK_DDPRINT(\"write to new array entry beyond current length, \"\n\t\t\t\t                   \"decided to abandon array part (would become too sparse)\"));\n\n\t\t\t\t/* abandoning requires a props allocation resize and\n\t\t\t\t * 'rechecks' the valstack, invalidating any existing\n\t\t\t\t * valstack value pointers!\n\t\t\t\t */\n\t\t\t\tduk__abandon_array_checked(thr, orig);\n\t\t\t\tDUK_ASSERT(!DUK_HOBJECT_HAS_ARRAY_PART(orig));\n\n\t\t\t\tgoto write_to_entry_part;\n\t\t\t}\n\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"=> decided to keep array part\"));\n\t\t} else {\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"=> fast resize is OK\"));\n\t\t}\n\n\t\tDUK_DD(DUK_DDPRINT(\"write to new array entry beyond current length, \"\n\t\t                   \"decided to extend current allocation\"));\n\n\t\tduk__grow_props_for_array_item(thr, orig, arr_idx);\n\n\t no_array_growth:\n\n\t\t/* Note: assume array part is comprehensive, so that either\n\t\t * the write goes to the array part, or we've abandoned the\n\t\t * array above (and will not come here).\n\t\t */\n\n\t\tDUK_ASSERT(DUK_HOBJECT_HAS_ARRAY_PART(orig));\n\t\tDUK_ASSERT(arr_idx < DUK_HOBJECT_GET_ASIZE(orig));\n\n\t\ttv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, orig, arr_idx);\n\t\t/* prev value must be unused, no decref */\n\t\tDUK_ASSERT(DUK_TVAL_IS_UNUSED(tv));\n\t\tDUK_TVAL_SET_TVAL(tv, tv_val);\n\t\tDUK_TVAL_INCREF(thr, tv);\n\t\tDUK_DD(DUK_DDPRINT(\"put to new array entry: %ld -> %!T\",\n\t\t                   (long) arr_idx, (duk_tval *) tv));\n\n\t\t/* Note: array part values are [[Writable]], [[Enumerable]],\n\t\t * and [[Configurable]] which matches the required attributes\n\t\t * here.\n\t\t */\n\t\tgoto entry_updated;\n\t}\n\n write_to_entry_part:\n\n\t/*\n\t *  Write to entry part\n\t */\n\n\t/* entry allocation updates hash part and increases the key\n\t * refcount; may need a props allocation resize but doesn't\n\t * 'recheck' the valstack.\n\t */\n\te_idx = duk__hobject_alloc_entry_checked(thr, orig, key);\n\tDUK_ASSERT(e_idx >= 0);\n\n\ttv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, orig, e_idx);\n\t/* prev value can be garbage, no decref */\n\tDUK_TVAL_SET_TVAL(tv, tv_val);\n\tDUK_TVAL_INCREF(thr, tv);\n\tDUK_HOBJECT_E_SET_FLAGS(thr->heap, orig, e_idx, DUK_PROPDESC_FLAGS_WEC);\n\tgoto entry_updated;\n\n entry_updated:\n\n\t/*\n\t *  Possible pending array length update, which must only be done\n\t *  if the actual entry write succeeded.\n\t */\n\n\tif (new_array_length > 0) {\n\t\t/* Note: zero works as a \"no update\" marker because the new length\n\t\t * can never be zero after a new property is written.\n\t\t */\n\n\t\tDUK_ASSERT(DUK_HOBJECT_HAS_EXOTIC_ARRAY(orig));\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"write successful, pending array length update to: %ld\",\n\t\t                     (long) new_array_length));\n\n\t\t((duk_harray *) orig)->length = new_array_length;\n\t}\n\n\t/*\n\t *  Arguments exotic behavior not possible for new properties: all\n\t *  magically bound properties are initially present in the arguments\n\t *  object, and if they are deleted, the binding is also removed from\n\t *  parameter map.\n\t */\n\n\tgoto success_no_arguments_exotic;\n\n success_with_arguments_exotic:\n\n\t/*\n\t *  Arguments objects have exotic [[DefineOwnProperty]] which updates\n\t *  the internal 'map' of arguments for writes to currently mapped\n\t *  arguments.  More conretely, writes to mapped arguments generate\n\t *  a write to a bound variable.\n\t *\n\t *  The [[Put]] algorithm invokes [[DefineOwnProperty]] for existing\n\t *  data properties and new properties, but not for existing accessors.\n\t *  Hence, in E5 Section 10.6 ([[DefinedOwnProperty]] algorithm), we\n\t *  have a Desc with 'Value' (and possibly other properties too), and\n\t *  we end up in step 5.b.i.\n\t */\n\n\tif (arr_idx != DUK__NO_ARRAY_INDEX &&\n\t    DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(orig)) {\n\t\t/* Note: only numbered indices are relevant, so arr_idx fast reject\n\t\t * is good (this is valid unless there are more than 4**32-1 arguments).\n\t\t */\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"putprop successful, arguments exotic behavior needed\"));\n\n\t\t/* Note: we can reuse 'desc' here */\n\n\t\t/* XXX: top of stack must contain value, which helper doesn't touch,\n\t\t * rework to use tv_val directly?\n\t\t */\n\n\t\tduk_push_tval(thr, tv_val);\n\t\t(void) duk__check_arguments_map_for_put(thr, orig, key, &desc, throw_flag);\n\t\tduk_pop_unsafe(thr);\n\t}\n\t/* fall thru */\n\n success_no_arguments_exotic:\n\t/* shared exit path now */\n\tDUK_DDD(DUK_DDDPRINT(\"result: success\"));\n\tduk_pop_unsafe(thr);  /* remove key */\n\treturn 1;\n\n#if defined(DUK_USE_ES6_PROXY)\n fail_proxy_rejected:\n\tDUK_DDD(DUK_DDDPRINT(\"result: error, proxy rejects\"));\n\tif (throw_flag) {\n\t\tDUK_ERROR_TYPE(thr, DUK_STR_PROXY_REJECTED);\n\t}\n\t/* Note: no key on stack */\n\treturn 0;\n#endif\n\n fail_base_primitive:\n\tDUK_DDD(DUK_DDDPRINT(\"result: error, base primitive\"));\n\tif (throw_flag) {\n#if defined(DUK_USE_PARANOID_ERRORS)\n\t\tDUK_ERROR_TYPE(thr, DUK_STR_INVALID_BASE);\n#else\n\t\tDUK_ERROR_FMT2(thr, DUK_ERR_TYPE_ERROR, \"cannot write property %s of %s\",\n\t\t               duk_push_string_tval_readable(thr, tv_key), duk_push_string_tval_readable(thr, tv_obj));\n#endif\n\t}\n\tduk_pop_unsafe(thr);  /* remove key */\n\treturn 0;\n\n fail_not_extensible:\n\tDUK_DDD(DUK_DDDPRINT(\"result: error, not extensible\"));\n\tif (throw_flag) {\n\t\tDUK_ERROR_TYPE(thr, DUK_STR_NOT_EXTENSIBLE);\n\t}\n\tduk_pop_unsafe(thr);  /* remove key */\n\treturn 0;\n\n fail_not_writable:\n\tDUK_DDD(DUK_DDDPRINT(\"result: error, not writable\"));\n\tif (throw_flag) {\n\t\tDUK_ERROR_TYPE(thr, DUK_STR_NOT_WRITABLE);\n\t}\n\tduk_pop_unsafe(thr);  /* remove key */\n\treturn 0;\n\n#if defined(DUK_USE_ROM_OBJECTS)\n fail_not_writable_no_pop:\n\tDUK_DDD(DUK_DDDPRINT(\"result: error, not writable\"));\n\tif (throw_flag) {\n\t\tDUK_ERROR_TYPE(thr, DUK_STR_NOT_WRITABLE);\n\t}\n\treturn 0;\n#endif\n\n fail_array_length_partial:\n\tDUK_DD(DUK_DDPRINT(\"result: error, array length write only partially successful\"));\n\tif (throw_flag) {\n\t\tDUK_ERROR_TYPE(thr, DUK_STR_NOT_CONFIGURABLE);\n\t}\n\tduk_pop_unsafe(thr);  /* remove key */\n\treturn 0;\n\n fail_no_setter:\n\tDUK_DDD(DUK_DDDPRINT(\"result: error, accessor property without setter\"));\n\tif (throw_flag) {\n\t\tDUK_ERROR_TYPE(thr, DUK_STR_SETTER_UNDEFINED);\n\t}\n\tduk_pop_unsafe(thr);  /* remove key */\n\treturn 0;\n\n fail_internal:\n\tDUK_DDD(DUK_DDDPRINT(\"result: error, internal\"));\n\tif (throw_flag) {\n\t\tDUK_ERROR_INTERNAL(thr);\n\t}\n\tduk_pop_unsafe(thr);  /* remove key */\n\treturn 0;\n}\n\n/*\n *  Ecmascript compliant [[Delete]](P, Throw).\n */\n\nDUK_INTERNAL duk_bool_t duk_hobject_delprop_raw(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_small_uint_t flags) {\n\tduk_propdesc desc;\n\tduk_tval *tv;\n\tduk_uint32_t arr_idx;\n\tduk_bool_t throw_flag;\n\tduk_bool_t force_flag;\n\n\tthrow_flag = (flags & DUK_DELPROP_FLAG_THROW);\n\tforce_flag = (flags & DUK_DELPROP_FLAG_FORCE);\n\n\tDUK_DDD(DUK_DDDPRINT(\"delprop_raw: thr=%p, obj=%p, key=%p, throw=%ld, force=%ld (obj -> %!O, key -> %!O)\",\n\t                     (void *) thr, (void *) obj, (void *) key, (long) throw_flag, (long) force_flag,\n\t                     (duk_heaphdr *) obj, (duk_heaphdr *) key));\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(thr->heap != NULL);\n\tDUK_ASSERT(obj != NULL);\n\tDUK_ASSERT(key != NULL);\n\n\tDUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);\n\n\tarr_idx = DUK_HSTRING_GET_ARRIDX_FAST(key);\n\n\t/* 0 = don't push current value */\n\tif (!duk__get_own_propdesc_raw(thr, obj, key, arr_idx, &desc, 0 /*flags*/)) {  /* don't push value */\n\t\tDUK_DDD(DUK_DDDPRINT(\"property not found, succeed always\"));\n\t\tgoto success;\n\t}\n\n#if defined(DUK_USE_ROM_OBJECTS)\n\tif (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj)) {\n\t\tDUK_DD(DUK_DDPRINT(\"attempt to delprop on read-only target object\"));\n\t\tgoto fail_not_configurable;\n\t}\n#endif\n\n\tif ((desc.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) == 0 && !force_flag) {\n\t\tgoto fail_not_configurable;\n\t}\n\tif (desc.a_idx < 0 && desc.e_idx < 0) {\n\t\t/* Currently there are no deletable virtual properties, but\n\t\t * with force_flag we might attempt to delete one.\n\t\t */\n\t\tDUK_DD(DUK_DDPRINT(\"delete failed: property found, force flag, but virtual (and implicitly non-configurable)\"));\n\t\tgoto fail_virtual;\n\t}\n\n\tif (desc.a_idx >= 0) {\n\t\tDUK_ASSERT(desc.e_idx < 0);\n\n\t\ttv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, desc.a_idx);\n\t\tDUK_TVAL_SET_UNUSED_UPDREF(thr, tv);  /* side effects */\n\t\tgoto success;\n\t} else {\n\t\tDUK_ASSERT(desc.a_idx < 0);\n\n\t\t/* remove hash entry (no decref) */\n#if defined(DUK_USE_HOBJECT_HASH_PART)\n\t\tif (desc.h_idx >= 0) {\n\t\t\tduk_uint32_t *h_base = DUK_HOBJECT_H_GET_BASE(thr->heap, obj);\n\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"removing hash entry at h_idx %ld\", (long) desc.h_idx));\n\t\t\tDUK_ASSERT(DUK_HOBJECT_GET_HSIZE(obj) > 0);\n\t\t\tDUK_ASSERT((duk_uint32_t) desc.h_idx < DUK_HOBJECT_GET_HSIZE(obj));\n\t\t\th_base[desc.h_idx] = DUK__HASH_DELETED;\n\t\t} else {\n\t\t\tDUK_ASSERT(DUK_HOBJECT_GET_HSIZE(obj) == 0);\n\t\t}\n#else\n\t\tDUK_ASSERT(DUK_HOBJECT_GET_HSIZE(obj) == 0);\n#endif\n\n\t\t/* Remove value.  This requires multiple writes so avoid side\n\t\t * effects via no-refzero macros so that e_idx is not\n\t\t * invalidated.\n\t\t */\n\t\tDUK_DDD(DUK_DDDPRINT(\"before removing value, e_idx %ld, key %p, key at slot %p\",\n\t\t                     (long) desc.e_idx, (void *) key, (void *) DUK_HOBJECT_E_GET_KEY(thr->heap, obj, desc.e_idx)));\n\t\tDUK_DDD(DUK_DDDPRINT(\"removing value at e_idx %ld\", (long) desc.e_idx));\n\t\tif (DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, obj, desc.e_idx)) {\n\t\t\tduk_hobject *tmp;\n\n\t\t\ttmp = DUK_HOBJECT_E_GET_VALUE_GETTER(thr->heap, obj, desc.e_idx);\n\t\t\tDUK_HOBJECT_E_SET_VALUE_GETTER(thr->heap, obj, desc.e_idx, NULL);\n\t\t\tDUK_UNREF(tmp);\n\t\t\tDUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, tmp);\n\n\t\t\ttmp = DUK_HOBJECT_E_GET_VALUE_SETTER(thr->heap, obj, desc.e_idx);\n\t\t\tDUK_HOBJECT_E_SET_VALUE_SETTER(thr->heap, obj, desc.e_idx, NULL);\n\t\t\tDUK_UNREF(tmp);\n\t\t\tDUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, tmp);\n\t\t} else {\n\t\t\ttv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, desc.e_idx);\n\t\t\tDUK_TVAL_SET_UNDEFINED_UPDREF_NORZ(thr, tv);\n\t\t}\n#if 0\n\t\t/* Not strictly necessary because if key == NULL, flag MUST be ignored. */\n\t\tDUK_HOBJECT_E_SET_FLAGS(thr->heap, obj, desc.e_idx, 0);\n#endif\n\n\t\t/* Remove key. */\n\t\tDUK_DDD(DUK_DDDPRINT(\"before removing key, e_idx %ld, key %p, key at slot %p\",\n\t\t                     (long) desc.e_idx, (void *) key, (void *) DUK_HOBJECT_E_GET_KEY(thr->heap, obj, desc.e_idx)));\n\t\tDUK_DDD(DUK_DDDPRINT(\"removing key at e_idx %ld\", (long) desc.e_idx));\n\t\tDUK_ASSERT(key == DUK_HOBJECT_E_GET_KEY(thr->heap, obj, desc.e_idx));\n\t\tDUK_HOBJECT_E_SET_KEY(thr->heap, obj, desc.e_idx, NULL);\n\t\tDUK_HSTRING_DECREF_NORZ(thr, key);\n\n\t\t/* Trigger refzero side effects only when we're done as a\n\t\t * finalizer might operate on the object and affect the\n\t\t * e_idx we're supposed to use.\n\t\t */\n\t\tDUK_REFZERO_CHECK_SLOW(thr);\n\t\tgoto success;\n\t}\n\n\tDUK_UNREACHABLE();\n\n success:\n\t/*\n\t *  Argument exotic [[Delete]] behavior (E5 Section 10.6) is\n\t *  a post-check, keeping arguments internal 'map' in sync with\n\t *  any successful deletes (note that property does not need to\n\t *  exist for delete to 'succeed').\n\t *\n\t *  Delete key from 'map'.  Since 'map' only contains array index\n\t *  keys, we can use arr_idx for a fast skip.\n\t */\n\n\tDUK_DDD(DUK_DDDPRINT(\"delete successful, check for arguments exotic behavior\"));\n\n\tif (arr_idx != DUK__NO_ARRAY_INDEX && DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj)) {\n\t\t/* Note: only numbered indices are relevant, so arr_idx fast reject\n\t\t * is good (this is valid unless there are more than 4**32-1 arguments).\n\t\t */\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"delete successful, arguments exotic behavior needed\"));\n\n\t\t/* Note: we can reuse 'desc' here */\n\t\t(void) duk__check_arguments_map_for_delete(thr, obj, key, &desc);\n\t}\n\n\tDUK_DDD(DUK_DDDPRINT(\"delete successful\"));\n\treturn 1;\n\n fail_virtual:  /* just use the same \"not configurable\" error message */\n fail_not_configurable:\n\tDUK_DDD(DUK_DDDPRINT(\"delete failed: property found, not configurable\"));\n\n\tif (throw_flag) {\n\t\tDUK_ERROR_TYPE(thr, DUK_STR_NOT_CONFIGURABLE);\n\t}\n\treturn 0;\n}\n\n/*\n *  DELPROP: Ecmascript property deletion.\n */\n\nDUK_INTERNAL duk_bool_t duk_hobject_delprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key, duk_bool_t throw_flag) {\n\tduk_hstring *key = NULL;\n#if defined(DUK_USE_ES6_PROXY)\n\tduk_propdesc desc;\n#endif\n\tduk_int_t entry_top;\n\tduk_uint32_t arr_idx = DUK__NO_ARRAY_INDEX;\n\tduk_bool_t rc;\n\n\tDUK_DDD(DUK_DDDPRINT(\"delprop: thr=%p, obj=%p, key=%p (obj -> %!T, key -> %!T)\",\n\t                     (void *) thr, (void *) tv_obj, (void *) tv_key,\n\t                     (duk_tval *) tv_obj, (duk_tval *) tv_key));\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(thr->heap != NULL);\n\tDUK_ASSERT(tv_obj != NULL);\n\tDUK_ASSERT(tv_key != NULL);\n\n\tDUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);\n\n\t/* Storing the entry top is cheaper here to ensure stack is correct at exit,\n\t * as there are several paths out.\n\t */\n\tentry_top = duk_get_top(thr);\n\n\tif (DUK_TVAL_IS_UNDEFINED(tv_obj) ||\n\t    DUK_TVAL_IS_NULL(tv_obj)) {\n\t\tDUK_DDD(DUK_DDDPRINT(\"base object is undefined or null -> reject\"));\n\t\tgoto fail_invalid_base_uncond;\n\t}\n\n\tduk_push_tval(thr, tv_obj);\n\tduk_push_tval(thr, tv_key);\n\n\ttv_obj = DUK_GET_TVAL_NEGIDX(thr, -2);\n\tif (DUK_TVAL_IS_OBJECT(tv_obj)) {\n\t\tduk_hobject *obj = DUK_TVAL_GET_OBJECT(tv_obj);\n\t\tDUK_ASSERT(obj != NULL);\n\n#if defined(DUK_USE_ES6_PROXY)\n\t\tif (DUK_UNLIKELY(DUK_HOBJECT_IS_PROXY(obj))) {\n\t\t\tduk_hobject *h_target;\n\t\t\tduk_bool_t tmp_bool;\n\n\t\t\t/* Note: proxy handling must happen before key is string coerced. */\n\n\t\t\tif (duk__proxy_check_prop(thr, obj, DUK_STRIDX_DELETE_PROPERTY, tv_key, &h_target)) {\n\t\t\t\t/* -> [ ... obj key trap handler ] */\n\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"-> proxy object 'deleteProperty' for key %!T\", (duk_tval *) tv_key));\n\t\t\t\tduk_push_hobject(thr, h_target);  /* target */\n\t\t\t\tduk_dup_m4(thr);  /* P */\n\t\t\t\tduk_call_method(thr, 2 /*nargs*/);\n\t\t\t\ttmp_bool = duk_to_boolean(thr, -1);\n\t\t\t\tduk_pop_nodecref_unsafe(thr);\n\t\t\t\tif (!tmp_bool) {\n\t\t\t\t\tgoto fail_proxy_rejected;  /* retval indicates delete failed */\n\t\t\t\t}\n\n\t\t\t\t/* Target object must be checked for a conflicting\n\t\t\t\t * non-configurable property.\n\t\t\t\t */\n\t\t\t\ttv_key = DUK_GET_TVAL_NEGIDX(thr, -1);\n\t\t\t\tarr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);\n\t\t\t\tDUK_ASSERT(key != NULL);\n\n\t\t\t\tif (duk__get_own_propdesc_raw(thr, h_target, key, arr_idx, &desc, 0 /*flags*/)) {  /* don't push value */\n\t\t\t\t\tduk_small_int_t desc_reject;\n\n\t\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"proxy 'deleteProperty': target has matching property %!O, check for \"\n\t\t\t\t\t                     \"conflicting property; desc.flags=0x%08lx, \"\n\t\t\t\t\t                     \"desc.get=%p, desc.set=%p\",\n\t\t\t\t\t                     (duk_heaphdr *) key, (unsigned long) desc.flags,\n\t\t\t\t\t                     (void *) desc.get, (void *) desc.set));\n\n\t\t\t\t\tdesc_reject = !(desc.flags & DUK_PROPDESC_FLAG_CONFIGURABLE);\n\t\t\t\t\tif (desc_reject) {\n\t\t\t\t\t\t/* unconditional */\n\t\t\t\t\t\tDUK_ERROR_TYPE(thr, DUK_STR_PROXY_REJECTED);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\trc = 1;  /* success */\n\t\t\t\tgoto done_rc;\n\t\t\t}\n\n\t\t\tobj = h_target;  /* resume delete to target */\n\t\t}\n#endif  /* DUK_USE_ES6_PROXY */\n\n\t\tarr_idx = duk__to_property_key(thr, -1, &key);\n\t\tDUK_ASSERT(key != NULL);\n\n\t\trc = duk_hobject_delprop_raw(thr, obj, key, throw_flag ? DUK_DELPROP_FLAG_THROW : 0);\n\t\tgoto done_rc;\n\t} else if (DUK_TVAL_IS_STRING(tv_obj)) {\n\t\t/* String has .length and array index virtual properties\n\t\t * which can't be deleted.  No need for a symbol check;\n\t\t * no offending virtual symbols exist.\n\t\t */\n\t\t/* XXX: unnecessary string coercion for array indices,\n\t\t * intentional to keep small.\n\t\t */\n\t\tduk_hstring *h = DUK_TVAL_GET_STRING(tv_obj);\n\t\tDUK_ASSERT(h != NULL);\n\n\t\tarr_idx = duk__to_property_key(thr, -1, &key);\n\t\tDUK_ASSERT(key != NULL);\n\n\t\tif (key == DUK_HTHREAD_STRING_LENGTH(thr)) {\n\t\t\tgoto fail_not_configurable;\n\t\t}\n\n\t\tif (arr_idx != DUK__NO_ARRAY_INDEX &&\n\t\t    arr_idx < DUK_HSTRING_GET_CHARLEN(h)) {\n\t\t\tgoto fail_not_configurable;\n\t\t}\n\t} else if (DUK_TVAL_IS_BUFFER(tv_obj)) {\n\t\t/* XXX: unnecessary string coercion for array indices,\n\t\t * intentional to keep small; some overlap with string\n\t\t * handling.\n\t\t */\n\t\tduk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv_obj);\n\t\tDUK_ASSERT(h != NULL);\n\n\t\tarr_idx = duk__to_property_key(thr, -1, &key);\n\t\tDUK_ASSERT(key != NULL);\n\n\t\tif (key == DUK_HTHREAD_STRING_LENGTH(thr)) {\n\t\t\tgoto fail_not_configurable;\n\t\t}\n\n\t\tif (arr_idx != DUK__NO_ARRAY_INDEX &&\n\t\t    arr_idx < DUK_HBUFFER_GET_SIZE(h)) {\n\t\t\tgoto fail_not_configurable;\n\t\t}\n\t} else if (DUK_TVAL_IS_LIGHTFUNC(tv_obj)) {\n\t\t/* Lightfunc has no virtual properties since Duktape 2.2\n\t\t * so success.  Still must coerce key for side effects.\n\t\t */\n\n\t\tarr_idx = duk__to_property_key(thr, -1, &key);\n\t\tDUK_ASSERT(key != NULL);\n\t\tDUK_UNREF(key);\n\t}\n\n\t/* non-object base, no offending virtual property */\n\trc = 1;\n\tgoto done_rc;\n\n done_rc:\n\tduk_set_top_unsafe(thr, entry_top);\n\treturn rc;\n\n fail_invalid_base_uncond:\n\t/* Note: unconditional throw */\n\tDUK_ASSERT(duk_get_top(thr) == entry_top);\n#if defined(DUK_USE_PARANOID_ERRORS)\n\tDUK_ERROR_TYPE(thr, DUK_STR_INVALID_BASE);\n#else\n\tDUK_ERROR_FMT2(thr, DUK_ERR_TYPE_ERROR, \"cannot delete property %s of %s\",\n\t               duk_push_string_tval_readable(thr, tv_key), duk_push_string_tval_readable(thr, tv_obj));\n#endif\n\treturn 0;\n\n#if defined(DUK_USE_ES6_PROXY)\n fail_proxy_rejected:\n\tif (throw_flag) {\n\t\tDUK_ERROR_TYPE(thr, DUK_STR_PROXY_REJECTED);\n\t}\n\tduk_set_top_unsafe(thr, entry_top);\n\treturn 0;\n#endif\n\n fail_not_configurable:\n\tif (throw_flag) {\n\t\tDUK_ERROR_TYPE(thr, DUK_STR_NOT_CONFIGURABLE);\n\t}\n\tduk_set_top_unsafe(thr, entry_top);\n\treturn 0;\n}\n\n/*\n *  Internal helper to define a property with specific flags, ignoring\n *  normal semantics such as extensibility, write protection etc.\n *  Overwrites any existing value and attributes unless caller requests\n *  that value only be updated if it doesn't already exists.\n *\n *  Does not support:\n *    - virtual properties (error if write attempted)\n *    - getter/setter properties (error if write attempted)\n *    - non-default (!= WEC) attributes for array entries (error if attempted)\n *    - array abandoning: if array part exists, it is always extended\n *    - array 'length' updating\n *\n *  Stack: [... in_val] -> []\n *\n *  Used for e.g. built-in initialization and environment record\n *  operations.\n */\n\nDUK_INTERNAL void duk_hobject_define_property_internal(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_small_uint_t flags) {\n\tduk_propdesc desc;\n\tduk_uint32_t arr_idx;\n\tduk_int_t e_idx;\n\tduk_tval *tv1 = NULL;\n\tduk_tval *tv2 = NULL;\n\tduk_small_uint_t propflags = flags & DUK_PROPDESC_FLAGS_MASK;  /* mask out flags not actually stored */\n\n\tDUK_DDD(DUK_DDDPRINT(\"define new property (internal): thr=%p, obj=%!O, key=%!O, flags=0x%02lx, val=%!T\",\n\t                     (void *) thr, (duk_heaphdr *) obj, (duk_heaphdr *) key,\n\t                     (unsigned long) flags, (duk_tval *) duk_get_tval(thr, -1)));\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(thr->heap != NULL);\n\tDUK_ASSERT(obj != NULL);\n\tDUK_ASSERT(key != NULL);\n\tDUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj));\n\tDUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);\n\tDUK_ASSERT(duk_is_valid_index(thr, -1));  /* contains value */\n\n\tarr_idx = DUK_HSTRING_GET_ARRIDX_SLOW(key);\n\n\tif (duk__get_own_propdesc_raw(thr, obj, key, arr_idx, &desc, 0 /*flags*/)) {  /* don't push value */\n\t\tif (desc.e_idx >= 0) {\n\t\t\tif (flags & DUK_PROPDESC_FLAG_NO_OVERWRITE) {\n\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"property already exists in the entry part -> skip as requested\"));\n\t\t\t\tgoto pop_exit;\n\t\t\t}\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"property already exists in the entry part -> update value and attributes\"));\n\t\t\tif (DUK_UNLIKELY(DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, obj, desc.e_idx))) {\n\t\t\t\tDUK_D(DUK_DPRINT(\"existing property is an accessor, not supported\"));\n\t\t\t\tgoto error_internal;\n\t\t\t}\n\n\t\t\tDUK_HOBJECT_E_SET_FLAGS(thr->heap, obj, desc.e_idx, propflags);\n\t\t\ttv1 = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, desc.e_idx);\n\t\t} else if (desc.a_idx >= 0) {\n\t\t\tif (flags & DUK_PROPDESC_FLAG_NO_OVERWRITE) {\n\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"property already exists in the array part -> skip as requested\"));\n\t\t\t\tgoto pop_exit;\n\t\t\t}\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"property already exists in the array part -> update value (assert attributes)\"));\n\t\t\tif (propflags != DUK_PROPDESC_FLAGS_WEC) {\n\t\t\t\tDUK_D(DUK_DPRINT(\"existing property in array part, but propflags not WEC (0x%02lx)\",\n\t\t\t\t                 (unsigned long) propflags));\n\t\t\t\tgoto error_internal;\n\t\t\t}\n\n\t\t\ttv1 = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, desc.a_idx);\n\t\t} else {\n\t\t\tif (flags & DUK_PROPDESC_FLAG_NO_OVERWRITE) {\n\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"property already exists but is virtual -> skip as requested\"));\n\t\t\t\tgoto pop_exit;\n\t\t\t}\n\t\t\tif (key == DUK_HTHREAD_STRING_LENGTH(thr) && DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj)) {\n\t\t\t\tduk_uint32_t new_len;\n#if defined(DUK_USE_DEBUG)\n\t\t\t\tduk_uint32_t prev_len;\n\t\t\t\tprev_len = ((duk_harray *) obj)->length;\n#endif\n\t\t\t\tnew_len = duk__to_new_array_length_checked(thr, DUK_GET_TVAL_NEGIDX(thr, -1));\n\t\t\t\t((duk_harray *) obj)->length = new_len;\n\t\t\t\tDUK_D(DUK_DPRINT(\"internal define property for array .length: %ld -> %ld\",\n\t\t\t\t                 (long) prev_len, (long) ((duk_harray *) obj)->length));\n\t\t\t\tgoto pop_exit;\n\t\t\t}\n\t\t\tDUK_DD(DUK_DDPRINT(\"property already exists but is virtual -> failure\"));\n\t\t\tgoto error_virtual;\n\t\t}\n\n\t\tgoto write_value;\n\t}\n\n\tif (DUK_HOBJECT_HAS_ARRAY_PART(obj)) {\n\t\tif (arr_idx != DUK__NO_ARRAY_INDEX) {\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"property does not exist, object has array part -> possibly extend array part and write value (assert attributes)\"));\n\t\t\tDUK_ASSERT(propflags == DUK_PROPDESC_FLAGS_WEC);\n\n\t\t\t/* always grow the array, no sparse / abandon support here */\n\t\t\tif (arr_idx >= DUK_HOBJECT_GET_ASIZE(obj)) {\n\t\t\t\tduk__grow_props_for_array_item(thr, obj, arr_idx);\n\t\t\t}\n\n\t\t\tDUK_ASSERT(arr_idx < DUK_HOBJECT_GET_ASIZE(obj));\n\t\t\ttv1 = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, arr_idx);\n\t\t\tgoto write_value;\n\t\t}\n\t}\n\n\tDUK_DDD(DUK_DDDPRINT(\"property does not exist, object belongs in entry part -> allocate new entry and write value and attributes\"));\n\te_idx = duk__hobject_alloc_entry_checked(thr, obj, key);  /* increases key refcount */\n\tDUK_ASSERT(e_idx >= 0);\n\tDUK_HOBJECT_E_SET_FLAGS(thr->heap, obj, e_idx, propflags);\n\ttv1 = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, e_idx);\n\t/* new entry: previous value is garbage; set to undefined to share write_value */\n\tDUK_TVAL_SET_UNDEFINED(tv1);\n\tgoto write_value;\n\n write_value:\n\t/* tv1 points to value storage */\n\n\ttv2 = duk_require_tval(thr, -1);  /* late lookup, avoid side effects */\n\tDUK_DDD(DUK_DDDPRINT(\"writing/updating value: %!T -> %!T\",\n\t                     (duk_tval *) tv1, (duk_tval *) tv2));\n\n\tDUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv2);  /* side effects */\n\tgoto pop_exit;\n\n pop_exit:\n\tduk_pop_unsafe(thr);  /* remove in_val */\n\treturn;\n\n error_virtual:  /* share error message */\n error_internal:\n\tDUK_ERROR_INTERNAL(thr);\n\treturn;\n}\n\n/*\n *  Fast path for defining array indexed values without interning the key.\n *  This is used by e.g. code for Array prototype and traceback creation so\n *  must avoid interning.\n */\n\nDUK_INTERNAL void duk_hobject_define_property_internal_arridx(duk_hthread *thr, duk_hobject *obj, duk_uarridx_t arr_idx, duk_small_uint_t flags) {\n\tduk_hstring *key;\n\tduk_tval *tv1, *tv2;\n\n\tDUK_DDD(DUK_DDDPRINT(\"define new property (internal) arr_idx fast path: thr=%p, obj=%!O, \"\n\t                     \"arr_idx=%ld, flags=0x%02lx, val=%!T\",\n\t                     (void *) thr, obj, (long) arr_idx, (unsigned long) flags,\n\t                     (duk_tval *) duk_get_tval(thr, -1)));\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(thr->heap != NULL);\n\tDUK_ASSERT(obj != NULL);\n\tDUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj));\n\n\tif (DUK_HOBJECT_HAS_ARRAY_PART(obj) &&\n\t    arr_idx != DUK__NO_ARRAY_INDEX &&\n\t    flags == DUK_PROPDESC_FLAGS_WEC) {\n\t\tDUK_ASSERT((flags & DUK_PROPDESC_FLAG_NO_OVERWRITE) == 0);  /* covered by comparison */\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"define property to array part (property may or may not exist yet)\"));\n\n\t\t/* always grow the array, no sparse / abandon support here */\n\t\tif (arr_idx >= DUK_HOBJECT_GET_ASIZE(obj)) {\n\t\t\tduk__grow_props_for_array_item(thr, obj, arr_idx);\n\t\t}\n\n\t\tDUK_ASSERT(arr_idx < DUK_HOBJECT_GET_ASIZE(obj));\n\t\ttv1 = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, arr_idx);\n\t\ttv2 = duk_require_tval(thr, -1);\n\n\t\tDUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv2);  /* side effects */\n\n\t\tduk_pop_unsafe(thr);  /* [ ...val ] -> [ ... ] */\n\t\treturn;\n\t}\n\n\tDUK_DDD(DUK_DDDPRINT(\"define property fast path didn't work, use slow path\"));\n\n\tkey = duk_push_uint_to_hstring(thr, (duk_uint_t) arr_idx);\n\tDUK_ASSERT(key != NULL);\n\tduk_insert(thr, -2);  /* [ ... val key ] -> [ ... key val ] */\n\n\tduk_hobject_define_property_internal(thr, obj, key, flags);\n\n\tduk_pop_unsafe(thr);  /* [ ... key ] -> [ ... ] */\n}\n\n/*\n *  Internal helpers for managing object 'length'\n */\n\nDUK_INTERNAL duk_size_t duk_hobject_get_length(duk_hthread *thr, duk_hobject *obj) {\n\tduk_double_t val;\n\n\tDUK_ASSERT_CTX_VALID(thr);\n\tDUK_ASSERT(obj != NULL);\n\n\t/* Fast path for Arrays. */\n\tif (DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj)) {\n\t\treturn ((duk_harray *) obj)->length;\n\t}\n\n\t/* Slow path, .length can be e.g. accessor, obj can be a Proxy, etc. */\n\tduk_push_hobject(thr, obj);\n\tduk_push_hstring_stridx(thr, DUK_STRIDX_LENGTH);\n\t(void) duk_hobject_getprop(thr,\n\t                           DUK_GET_TVAL_NEGIDX(thr, -2),\n\t                           DUK_GET_TVAL_NEGIDX(thr, -1));\n\tval = duk_to_number_m1(thr);\n\tduk_pop_3_unsafe(thr);\n\n\t/* This isn't part of Ecmascript semantics; return a value within\n\t * duk_size_t range, or 0 otherwise.\n\t */\n\tif (val >= 0.0 && val <= (duk_double_t) DUK_SIZE_MAX) {\n\t\treturn (duk_size_t) val;\n\t}\n\treturn 0;\n}\n\n/*\n *  Fast finalizer check for an object.  Walks the prototype chain, checking\n *  for finalizer presence using DUK_HOBJECT_FLAG_HAVE_FINALIZER which is kept\n *  in sync with the actual property when setting/removing the finalizer.\n */\n\n#if defined(DUK_USE_HEAPPTR16)\nDUK_INTERNAL duk_bool_t duk_hobject_has_finalizer_fast_raw(duk_heap *heap, duk_hobject *obj) {\n#else\nDUK_INTERNAL duk_bool_t duk_hobject_has_finalizer_fast_raw(duk_hobject *obj) {\n#endif\n\tduk_uint_t sanity;\n\n\tDUK_ASSERT(obj != NULL);\n\n\tsanity = DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY;\n\tdo {\n\t\tif (DUK_UNLIKELY(DUK_HOBJECT_HAS_HAVE_FINALIZER(obj))) {\n\t\t\treturn 1;\n\t\t}\n\t\tif (DUK_UNLIKELY(sanity-- == 0)) {\n\t\t\tDUK_D(DUK_DPRINT(\"prototype loop when checking for finalizer existence; returning false\"));\n\t\t\treturn 0;\n\t\t}\n#if defined(DUK_USE_HEAPPTR16)\n\t\tDUK_ASSERT(heap != NULL);\n\t\tobj = DUK_HOBJECT_GET_PROTOTYPE(heap, obj);\n#else\n\t\tobj = DUK_HOBJECT_GET_PROTOTYPE(NULL, obj);  /* 'heap' arg ignored */\n#endif\n\t} while (obj != NULL);\n\n\treturn 0;\n}\n\n/*\n *  Object.getOwnPropertyDescriptor()  (E5 Sections 15.2.3.3, 8.10.4)\n *\n *  [ ... key ] -> [ ... desc/undefined ]\n */\n\nDUK_INTERNAL void duk_hobject_object_get_own_property_descriptor(duk_hthread *thr, duk_idx_t obj_idx) {\n\tduk_hobject *obj;\n\tduk_hstring *key;\n\tduk_propdesc pd;\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(thr->heap != NULL);\n\n\tobj = duk_require_hobject_promote_mask(thr, obj_idx, DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER);\n\tkey = duk_to_property_key_hstring(thr, -1);\n\tDUK_ASSERT(key != NULL);\n\n\tDUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);\n\n\tif (!duk_hobject_get_own_propdesc(thr, obj, key, &pd, DUK_GETDESC_FLAG_PUSH_VALUE)) {\n\t\tduk_push_undefined(thr);\n\t\tduk_remove_m2(thr);\n\t\treturn;\n\t}\n\n\tduk_push_object(thr);\n\n\t/* [ ... key value desc ] */\n\n\tif (DUK_PROPDESC_IS_ACCESSOR(&pd)) {\n\t\t/* If a setter/getter is missing (undefined), the descriptor must\n\t\t * still have the property present with the value 'undefined'.\n\t\t */\n\t\tif (pd.get) {\n\t\t\tduk_push_hobject(thr, pd.get);\n\t\t} else {\n\t\t\tduk_push_undefined(thr);\n\t\t}\n\t\tduk_put_prop_stridx_short(thr, -2, DUK_STRIDX_GET);\n\t\tif (pd.set) {\n\t\t\tduk_push_hobject(thr, pd.set);\n\t\t} else {\n\t\t\tduk_push_undefined(thr);\n\t\t}\n\t\tduk_put_prop_stridx_short(thr, -2, DUK_STRIDX_SET);\n\t} else {\n\t\tduk_dup_m2(thr);\n\t\tduk_put_prop_stridx_short(thr, -2, DUK_STRIDX_VALUE);\n\t\tduk_push_boolean(thr, DUK_PROPDESC_IS_WRITABLE(&pd));\n\t\tduk_put_prop_stridx_short(thr, -2, DUK_STRIDX_WRITABLE);\n\t}\n\tduk_push_boolean(thr, DUK_PROPDESC_IS_ENUMERABLE(&pd));\n\tduk_put_prop_stridx_short(thr, -2, DUK_STRIDX_ENUMERABLE);\n\tduk_push_boolean(thr, DUK_PROPDESC_IS_CONFIGURABLE(&pd));\n\tduk_put_prop_stridx_short(thr, -2, DUK_STRIDX_CONFIGURABLE);\n\n\t/* [ ... key value desc ] */\n\n\tduk_replace(thr, -3);\n\tduk_pop_unsafe(thr);  /* -> [ ... desc ] */\n}\n\n/*\n *  NormalizePropertyDescriptor() related helper.\n *\n *  Internal helper which validates and normalizes a property descriptor\n *  represented as an Ecmascript object (e.g. argument to defineProperty()).\n *  The output of this conversion is a set of defprop_flags and possibly\n *  some values pushed on the value stack to (1) ensure borrowed pointers\n *  remain valid, and (2) avoid unnecessary pops for footprint reasons.\n *  Caller must manage stack top carefully because the number of values\n *  pushed depends on the input property descriptor.\n *\n *  The original descriptor object must not be altered in the process.\n */\n\n/* XXX: very basic optimization -> duk_get_prop_stridx_top */\n\nDUK_INTERNAL\nvoid duk_hobject_prepare_property_descriptor(duk_hthread *thr,\n                                             duk_idx_t idx_in,\n                                             duk_uint_t *out_defprop_flags,\n                                             duk_idx_t *out_idx_value,\n                                             duk_hobject **out_getter,\n                                             duk_hobject **out_setter) {\n\tduk_idx_t idx_value = -1;\n\tduk_hobject *getter = NULL;\n\tduk_hobject *setter = NULL;\n\tduk_bool_t is_data_desc = 0;\n\tduk_bool_t is_acc_desc = 0;\n\tduk_uint_t defprop_flags = 0;\n\n\tDUK_ASSERT(out_defprop_flags != NULL);\n\tDUK_ASSERT(out_idx_value != NULL);\n\tDUK_ASSERT(out_getter != NULL);\n\tDUK_ASSERT(out_setter != NULL);\n\tDUK_ASSERT(idx_in <= 0x7fffL);  /* short variants would be OK, but not used to avoid shifts */\n\n\t/* Must be an object, otherwise TypeError (E5.1 Section 8.10.5, step 1). */\n\tidx_in = duk_require_normalize_index(thr, idx_in);\n\t(void) duk_require_hobject(thr, idx_in);\n\n\t/* The coercion order must match the ToPropertyDescriptor() algorithm\n\t * so that side effects in coercion happen in the correct order.\n\t * (This order also happens to be compatible with duk_def_prop(),\n\t * although it doesn't matter in practice.)\n\t */\n\n\tif (duk_get_prop_stridx(thr, idx_in, DUK_STRIDX_VALUE)) {\n\t\tis_data_desc = 1;\n\t\tdefprop_flags |= DUK_DEFPROP_HAVE_VALUE;\n\t\tidx_value = duk_get_top_index(thr);\n\t}\n\n\tif (duk_get_prop_stridx(thr, idx_in, DUK_STRIDX_WRITABLE)) {\n\t\tis_data_desc = 1;\n\t\tif (duk_to_boolean(thr, -1)) {\n\t\t\tdefprop_flags |= DUK_DEFPROP_HAVE_WRITABLE | DUK_DEFPROP_WRITABLE;\n\t\t} else {\n\t\t\tdefprop_flags |= DUK_DEFPROP_HAVE_WRITABLE;\n\t\t}\n\t}\n\n\tif (duk_get_prop_stridx(thr, idx_in, DUK_STRIDX_GET)) {\n\t\tduk_tval *tv = duk_require_tval(thr, -1);\n\t\tduk_hobject *h_get;\n\n\t\tif (DUK_TVAL_IS_UNDEFINED(tv)) {\n\t\t\t/* undefined is accepted */\n\t\t\tDUK_ASSERT(getter == NULL);\n\t\t} else {\n\t\t\t/* NOTE: lightfuncs are coerced to full functions because\n\t\t\t * lightfuncs don't fit into a property value slot.  This\n\t\t\t * has some side effects, see test-dev-lightfunc-accessor.js.\n\t\t\t */\n\t\t\th_get = duk_get_hobject_promote_lfunc(thr, -1);\n\t\t\tif (h_get == NULL || !DUK_HOBJECT_IS_CALLABLE(h_get)) {\n\t\t\t\tgoto type_error;\n\t\t\t}\n\t\t\tgetter = h_get;\n\t\t}\n\t\tis_acc_desc = 1;\n\t\tdefprop_flags |= DUK_DEFPROP_HAVE_GETTER;\n\t}\n\n\tif (duk_get_prop_stridx(thr, idx_in, DUK_STRIDX_SET)) {\n\t\tduk_tval *tv = duk_require_tval(thr, -1);\n\t\tduk_hobject *h_set;\n\n\t\tif (DUK_TVAL_IS_UNDEFINED(tv)) {\n\t\t\t/* undefined is accepted */\n\t\t\tDUK_ASSERT(setter == NULL);\n\t\t}  else {\n\t\t\t/* NOTE: lightfuncs are coerced to full functions because\n\t\t\t * lightfuncs don't fit into a property value slot.  This\n\t\t\t * has some side effects, see test-dev-lightfunc-accessor.js.\n\t\t\t */\n\t\t\th_set = duk_get_hobject_promote_lfunc(thr, -1);\n\t\t\tif (h_set == NULL || !DUK_HOBJECT_IS_CALLABLE(h_set)) {\n\t\t\t\tgoto type_error;\n\t\t\t}\n\t\t\tsetter = h_set;\n\t\t}\n\t\tis_acc_desc = 1;\n\t\tdefprop_flags |= DUK_DEFPROP_HAVE_SETTER;\n\t}\n\n\tif (duk_get_prop_stridx(thr, idx_in, DUK_STRIDX_ENUMERABLE)) {\n\t\tif (duk_to_boolean(thr, -1)) {\n\t\t\tdefprop_flags |= DUK_DEFPROP_HAVE_ENUMERABLE | DUK_DEFPROP_ENUMERABLE;\n\t\t} else {\n\t\t\tdefprop_flags |= DUK_DEFPROP_HAVE_ENUMERABLE;\n\t\t}\n\t}\n\n\tif (duk_get_prop_stridx(thr, idx_in, DUK_STRIDX_CONFIGURABLE)) {\n\t\tif (duk_to_boolean(thr, -1)) {\n\t\t\tdefprop_flags |= DUK_DEFPROP_HAVE_CONFIGURABLE | DUK_DEFPROP_CONFIGURABLE;\n\t\t} else {\n\t\t\tdefprop_flags |= DUK_DEFPROP_HAVE_CONFIGURABLE;\n\t\t}\n\t}\n\n\tif (is_data_desc && is_acc_desc) {\n\t\tgoto type_error;\n\t}\n\n\t*out_defprop_flags = defprop_flags;\n\t*out_idx_value = idx_value;\n\t*out_getter = getter;\n\t*out_setter = setter;\n\n\t/* [ ... [multiple values] ] */\n\treturn;\n\n type_error:\n\tDUK_ERROR_TYPE(thr, DUK_STR_INVALID_DESCRIPTOR);\n}\n\n/*\n *  Object.defineProperty() related helper (E5 Section 15.2.3.6).\n *  Also handles ES2015 Reflect.defineProperty().\n *\n *  Inlines all [[DefineOwnProperty]] exotic behaviors.\n *\n *  Note: Ecmascript compliant [[DefineOwnProperty]](P, Desc, Throw) is not\n *  implemented directly, but Object.defineProperty() serves its purpose.\n *  We don't need the [[DefineOwnProperty]] internally and we don't have a\n *  property descriptor with 'missing values' so it's easier to avoid it\n *  entirely.\n *\n *  Note: this is only called for actual objects, not primitive values.\n *  This must support virtual properties for full objects (e.g. Strings)\n *  but not for plain values (e.g. strings).  Lightfuncs, even though\n *  primitive in a sense, are treated like objects and accepted as target\n *  values.\n */\n\n/* XXX: this is a major target for size optimization */\nDUK_INTERNAL\nduk_bool_t duk_hobject_define_property_helper(duk_hthread *thr,\n                                              duk_uint_t defprop_flags,\n                                              duk_hobject *obj,\n                                              duk_hstring *key,\n                                              duk_idx_t idx_value,\n                                              duk_hobject *get,\n                                              duk_hobject *set,\n                                              duk_bool_t throw_flag) {\n\tduk_uint32_t arr_idx;\n\tduk_tval tv;\n\tduk_bool_t has_enumerable;\n\tduk_bool_t has_configurable;\n\tduk_bool_t has_writable;\n\tduk_bool_t has_value;\n\tduk_bool_t has_get;\n\tduk_bool_t has_set;\n\tduk_bool_t is_enumerable;\n\tduk_bool_t is_configurable;\n\tduk_bool_t is_writable;\n\tduk_bool_t force_flag;\n\tduk_small_uint_t new_flags;\n\tduk_propdesc curr;\n\tduk_uint32_t arridx_new_array_length;  /* != 0 => post-update for array 'length' (used when key is an array index) */\n\tduk_uint32_t arrlen_old_len;\n\tduk_uint32_t arrlen_new_len;\n\tduk_bool_t pending_write_protect;\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(thr->heap != NULL);\n\tDUK_ASSERT(obj != NULL);\n\tDUK_ASSERT(key != NULL);\n\t/* idx_value may be < 0 (no value), set and get may be NULL */\n\n\tDUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);\n\n\t/* All the flags fit in 16 bits, so will fit into duk_bool_t. */\n\n\thas_writable = (defprop_flags & DUK_DEFPROP_HAVE_WRITABLE);\n\thas_enumerable = (defprop_flags & DUK_DEFPROP_HAVE_ENUMERABLE);\n\thas_configurable = (defprop_flags & DUK_DEFPROP_HAVE_CONFIGURABLE);\n\thas_value = (defprop_flags & DUK_DEFPROP_HAVE_VALUE);\n\thas_get = (defprop_flags & DUK_DEFPROP_HAVE_GETTER);\n\thas_set = (defprop_flags & DUK_DEFPROP_HAVE_SETTER);\n\tis_writable = (defprop_flags & DUK_DEFPROP_WRITABLE);\n\tis_enumerable = (defprop_flags & DUK_DEFPROP_ENUMERABLE);\n\tis_configurable = (defprop_flags & DUK_DEFPROP_CONFIGURABLE);\n\tforce_flag = (defprop_flags & DUK_DEFPROP_FORCE);\n\n\tarr_idx = DUK_HSTRING_GET_ARRIDX_SLOW(key);\n\n\tarridx_new_array_length = 0;\n\tpending_write_protect = 0;\n\tarrlen_old_len = 0;\n\tarrlen_new_len = 0;\n\n\tDUK_DDD(DUK_DDDPRINT(\"has_enumerable=%ld is_enumerable=%ld \"\n\t                     \"has_configurable=%ld is_configurable=%ld \"\n\t                     \"has_writable=%ld is_writable=%ld \"\n\t                     \"has_value=%ld value=%!T \"\n\t                     \"has_get=%ld get=%p=%!O \"\n\t                     \"has_set=%ld set=%p=%!O \"\n\t                     \"arr_idx=%ld throw_flag=!%ld\",\n\t                     (long) has_enumerable, (long) is_enumerable,\n\t                     (long) has_configurable, (long) is_configurable,\n\t                     (long) has_writable, (long) is_writable,\n\t                     (long) has_value, (duk_tval *) (idx_value >= 0 ? duk_get_tval(thr, idx_value) : NULL),\n\t                     (long) has_get, (void *) get, (duk_heaphdr *) get,\n\t                     (long) has_set, (void *) set, (duk_heaphdr *) set,\n\t                     (long) arr_idx, (long) throw_flag));\n\n\t/*\n\t *  Array exotic behaviors can be implemented at this point.  The local variables\n\t *  are essentially a 'value copy' of the input descriptor (Desc), which is modified\n\t *  by the Array [[DefineOwnProperty]] (E5 Section 15.4.5.1).\n\t */\n\n\tif (!DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj)) {\n\t\tgoto skip_array_exotic;\n\t}\n\n\tif (key == DUK_HTHREAD_STRING_LENGTH(thr)) {\n\t\tduk_harray *a;\n\n\t\t/* E5 Section 15.4.5.1, step 3, steps a - i are implemented here, j - n at the end */\n\t\tif (!has_value) {\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"exotic array behavior for 'length', but no value in descriptor -> normal behavior\"));\n\t\t\tgoto skip_array_exotic;\n\t\t}\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"exotic array behavior for 'length', value present in descriptor -> exotic behavior\"));\n\n\t\t/*\n\t\t *  Get old and new length\n\t\t */\n\n\t\ta = (duk_harray *) obj;\n\t\tDUK_ASSERT_HARRAY_VALID(a);\n\t\tarrlen_old_len = a->length;\n\n\t\tDUK_ASSERT(idx_value >= 0);\n\t\tarrlen_new_len = duk__to_new_array_length_checked(thr, DUK_GET_TVAL_POSIDX(thr, idx_value));\n\t\tduk_push_u32(thr, arrlen_new_len);\n\t\tduk_replace(thr, idx_value);  /* step 3.e: replace 'Desc.[[Value]]' */\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"old_len=%ld, new_len=%ld\", (long) arrlen_old_len, (long) arrlen_new_len));\n\n\t\tif (arrlen_new_len >= arrlen_old_len) {\n\t\t\t/* standard behavior, step 3.f.i */\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"new length is same or higher as previous => standard behavior\"));\n\t\t\tgoto skip_array_exotic;\n\t\t}\n\t\tDUK_DDD(DUK_DDDPRINT(\"new length is smaller than previous => exotic post behavior\"));\n\n\t\t/* XXX: consolidated algorithm step 15.f -> redundant? */\n\t\tif (DUK_HARRAY_LENGTH_NONWRITABLE(a) && !force_flag) {\n\t\t\t/* Array .length is always non-configurable; if it's also\n\t\t\t * non-writable, don't allow it to be written.\n\t\t\t */\n\t\t\tgoto fail_not_configurable;\n\t\t}\n\n\t\t/* steps 3.h and 3.i */\n\t\tif (has_writable && !is_writable) {\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"desc writable is false, force it back to true, and flag pending write protect\"));\n\t\t\tis_writable = 1;\n\t\t\tpending_write_protect = 1;\n\t\t}\n\n\t\t/* remaining actual steps are carried out if standard DefineOwnProperty succeeds */\n\t} else if (arr_idx != DUK__NO_ARRAY_INDEX) {\n\t\t/* XXX: any chance of unifying this with the 'length' key handling? */\n\n\t\t/* E5 Section 15.4.5.1, step 4 */\n\t\tduk_uint32_t old_len;\n\t\tduk_harray *a;\n\n\t\ta = (duk_harray *) obj;\n\t\tDUK_ASSERT_HARRAY_VALID(a);\n\n\t\told_len = a->length;\n\n\t\tif (arr_idx >= old_len) {\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"defineProperty requires array length update \"\n\t\t\t                     \"(arr_idx=%ld, old_len=%ld)\",\n\t\t\t                     (long) arr_idx, (long) old_len));\n\n\t\t\tif (DUK_HARRAY_LENGTH_NONWRITABLE(a) && !force_flag) {\n\t\t\t\t/* Array .length is always non-configurable, so\n\t\t\t\t * if it's also non-writable, don't allow a value\n\t\t\t\t * write.  With force flag allow writing.\n\t\t\t\t */\n\t\t\t\tgoto fail_not_configurable;\n\t\t\t}\n\n\t\t\t/* actual update happens once write has been completed without\n\t\t\t * error below.\n\t\t\t */\n\t\t\tDUK_ASSERT(arr_idx != 0xffffffffUL);\n\t\t\tarridx_new_array_length = arr_idx + 1;\n\t\t} else {\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"defineProperty does not require length update \"\n\t\t\t                     \"(arr_idx=%ld, old_len=%ld) -> standard behavior\",\n\t\t\t                     (long) arr_idx, (long) old_len));\n\t\t}\n\t}\n skip_array_exotic:\n\n\t/* XXX: There is currently no support for writing buffer object\n\t * indexed elements here.  Attempt to do so will succeed and\n\t * write a concrete property into the buffer object.  This should\n\t * be fixed at some point but because buffers are a custom feature\n\t * anyway, this is relatively unimportant.\n\t */\n\n\t/*\n\t *  Actual Object.defineProperty() default algorithm.\n\t */\n\n\t/*\n\t *  First check whether property exists; if not, simple case.  This covers\n\t *  steps 1-4.\n\t */\n\n\tif (!duk__get_own_propdesc_raw(thr, obj, key, arr_idx, &curr, DUK_GETDESC_FLAG_PUSH_VALUE)) {\n\t\tDUK_DDD(DUK_DDDPRINT(\"property does not exist\"));\n\n\t\tif (!DUK_HOBJECT_HAS_EXTENSIBLE(obj) && !force_flag) {\n\t\t\tgoto fail_not_extensible;\n\t\t}\n\n#if defined(DUK_USE_ROM_OBJECTS)\n\t\t/* ROM objects are never extensible but force flag may\n\t\t * allow us to come here anyway.\n\t\t */\n\t\tDUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj) || !DUK_HOBJECT_HAS_EXTENSIBLE(obj));\n\t\tif (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj)) {\n\t\t\tDUK_D(DUK_DPRINT(\"attempt to define property on a read-only target object\"));\n\t\t\tgoto fail_not_configurable;\n\t\t}\n#endif\n\n\t\t/* XXX: share final setting code for value and flags?  difficult because\n\t\t * refcount code is different.  Share entry allocation?  But can't allocate\n\t\t * until array index checked.\n\t\t */\n\n\t\t/* steps 4.a and 4.b are tricky */\n\t\tif (has_set || has_get) {\n\t\t\tduk_int_t e_idx;\n\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"create new accessor property\"));\n\n\t\t\tDUK_ASSERT(has_set || set == NULL);\n\t\t\tDUK_ASSERT(has_get || get == NULL);\n\t\t\tDUK_ASSERT(!has_value);\n\t\t\tDUK_ASSERT(!has_writable);\n\n\t\t\tnew_flags = DUK_PROPDESC_FLAG_ACCESSOR;  /* defaults, E5 Section 8.6.1, Table 7 */\n\t\t\tif (has_enumerable && is_enumerable) {\n\t\t\t\tnew_flags |= DUK_PROPDESC_FLAG_ENUMERABLE;\n\t\t\t}\n\t\t\tif (has_configurable && is_configurable) {\n\t\t\t\tnew_flags |= DUK_PROPDESC_FLAG_CONFIGURABLE;\n\t\t\t}\n\n\t\t\tif (arr_idx != DUK__NO_ARRAY_INDEX && DUK_HOBJECT_HAS_ARRAY_PART(obj)) {\n\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"accessor cannot go to array part, abandon array\"));\n\t\t\t\tduk__abandon_array_checked(thr, obj);\n\t\t\t}\n\n\t\t\t/* write to entry part */\n\t\t\te_idx = duk__hobject_alloc_entry_checked(thr, obj, key);\n\t\t\tDUK_ASSERT(e_idx >= 0);\n\n\t\t\tDUK_HOBJECT_E_SET_VALUE_GETTER(thr->heap, obj, e_idx, get);\n\t\t\tDUK_HOBJECT_E_SET_VALUE_SETTER(thr->heap, obj, e_idx, set);\n\t\t\tDUK_HOBJECT_INCREF_ALLOWNULL(thr, get);\n\t\t\tDUK_HOBJECT_INCREF_ALLOWNULL(thr, set);\n\n\t\t\tDUK_HOBJECT_E_SET_FLAGS(thr->heap, obj, e_idx, new_flags);\n\t\t\tgoto success_exotics;\n\t\t} else {\n\t\t\tduk_int_t e_idx;\n\t\t\tduk_tval *tv2;\n\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"create new data property\"));\n\n\t\t\tDUK_ASSERT(!has_set);\n\t\t\tDUK_ASSERT(!has_get);\n\n\t\t\tnew_flags = 0;  /* defaults, E5 Section 8.6.1, Table 7 */\n\t\t\tif (has_writable && is_writable) {\n\t\t\t\tnew_flags |= DUK_PROPDESC_FLAG_WRITABLE;\n\t\t\t}\n\t\t\tif (has_enumerable && is_enumerable) {\n\t\t\t\tnew_flags |= DUK_PROPDESC_FLAG_ENUMERABLE;\n\t\t\t}\n\t\t\tif (has_configurable && is_configurable) {\n\t\t\t\tnew_flags |= DUK_PROPDESC_FLAG_CONFIGURABLE;\n\t\t\t}\n\t\t\tif (has_value) {\n\t\t\t\tduk_tval *tv_tmp = duk_require_tval(thr, idx_value);\n\t\t\t\tDUK_TVAL_SET_TVAL(&tv, tv_tmp);\n\t\t\t} else {\n\t\t\t\tDUK_TVAL_SET_UNDEFINED(&tv);  /* default value */\n\t\t\t}\n\n\t\t\tif (arr_idx != DUK__NO_ARRAY_INDEX && DUK_HOBJECT_HAS_ARRAY_PART(obj)) {\n\t\t\t\tif (new_flags == DUK_PROPDESC_FLAGS_WEC) {\n#if 0\n\t\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"new data property attributes match array defaults, attempt to write to array part\"));\n\t\t\t\t\t/* may become sparse...*/\n#endif\n\t\t\t\t\t/* XXX: handling for array part missing now; this doesn't affect\n\t\t\t\t\t * compliance but causes array entry writes using defineProperty()\n\t\t\t\t\t * to always abandon array part.\n\t\t\t\t\t */\n\t\t\t\t}\n\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"new data property cannot go to array part, abandon array\"));\n\t\t\t\tduk__abandon_array_checked(thr, obj);\n\t\t\t\t/* fall through */\n\t\t\t}\n\n\t\t\t/* write to entry part */\n\t\t\te_idx = duk__hobject_alloc_entry_checked(thr, obj, key);\n\t\t\tDUK_ASSERT(e_idx >= 0);\n\t\t\ttv2 = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, e_idx);\n\t\t\tDUK_TVAL_SET_TVAL(tv2, &tv);\n\t\t\tDUK_TVAL_INCREF(thr, tv2);\n\n\t\t\tDUK_HOBJECT_E_SET_FLAGS(thr->heap, obj, e_idx, new_flags);\n\t\t\tgoto success_exotics;\n\t\t}\n\t\tDUK_UNREACHABLE();\n\t}\n\n\t/* we currently assume virtual properties are not configurable (as none of them are) */\n\tDUK_ASSERT((curr.e_idx >= 0 || curr.a_idx >= 0) || !(curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE));\n\n\t/* [obj key desc value get set curr_value] */\n\n\t/*\n\t *  Property already exists.  Steps 5-6 detect whether any changes need\n\t *  to be made.\n\t */\n\n\tif (has_enumerable) {\n\t\tif (is_enumerable) {\n\t\t\tif (!(curr.flags & DUK_PROPDESC_FLAG_ENUMERABLE)) {\n\t\t\t\tgoto need_check;\n\t\t\t}\n\t\t} else {\n\t\t\tif (curr.flags & DUK_PROPDESC_FLAG_ENUMERABLE) {\n\t\t\t\tgoto need_check;\n\t\t\t}\n\t\t}\n\t}\n\tif (has_configurable) {\n\t\tif (is_configurable) {\n\t\t\tif (!(curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE)) {\n\t\t\t\tgoto need_check;\n\t\t\t}\n\t\t} else {\n\t\t\tif (curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) {\n\t\t\t\tgoto need_check;\n\t\t\t}\n\t\t}\n\t}\n\tif (has_value) {\n\t\tduk_tval *tmp1;\n\t\tduk_tval *tmp2;\n\n\t\t/* attempt to change from accessor to data property */\n\t\tif (curr.flags & DUK_PROPDESC_FLAG_ACCESSOR) {\n\t\t\tgoto need_check;\n\t\t}\n\n\t\ttmp1 = duk_require_tval(thr, -1);         /* curr value */\n\t\ttmp2 = duk_require_tval(thr, idx_value);  /* new value */\n\t\tif (!duk_js_samevalue(tmp1, tmp2)) {\n\t\t\tgoto need_check;\n\t\t}\n\t}\n\tif (has_writable) {\n\t\t/* attempt to change from accessor to data property */\n\t\tif (curr.flags & DUK_PROPDESC_FLAG_ACCESSOR) {\n\t\t\tgoto need_check;\n\t\t}\n\n\t\tif (is_writable) {\n\t\t\tif (!(curr.flags & DUK_PROPDESC_FLAG_WRITABLE)) {\n\t\t\t\tgoto need_check;\n\t\t\t}\n\t\t} else {\n\t\t\tif (curr.flags & DUK_PROPDESC_FLAG_WRITABLE) {\n\t\t\t\tgoto need_check;\n\t\t\t}\n\t\t}\n\t}\n\tif (has_set) {\n\t\tif (curr.flags & DUK_PROPDESC_FLAG_ACCESSOR) {\n\t\t\tif (set != curr.set) {\n\t\t\t\tgoto need_check;\n\t\t\t}\n\t\t} else {\n\t\t\tgoto need_check;\n\t\t}\n\t}\n\tif (has_get) {\n\t\tif (curr.flags & DUK_PROPDESC_FLAG_ACCESSOR) {\n\t\t\tif (get != curr.get) {\n\t\t\t\tgoto need_check;\n\t\t\t}\n\t\t} else {\n\t\t\tgoto need_check;\n\t\t}\n\t}\n\n\t/* property exists, either 'desc' is empty, or all values\n\t * match (SameValue)\n\t */\n\tgoto success_no_exotics;\n\n need_check:\n\n\t/*\n\t *  Some change(s) need to be made.  Steps 7-11.\n\t */\n\n\t/* shared checks for all descriptor types */\n\tif (!(curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) && !force_flag) {\n\t\tif (has_configurable && is_configurable) {\n\t\t\tgoto fail_not_configurable;\n\t\t}\n\t\tif (has_enumerable) {\n\t\t\tif (curr.flags & DUK_PROPDESC_FLAG_ENUMERABLE) {\n\t\t\t\tif (!is_enumerable) {\n\t\t\t\t\tgoto fail_not_configurable;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (is_enumerable) {\n\t\t\t\t\tgoto fail_not_configurable;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/* Virtual properties don't have backing so they can't mostly be\n\t * edited.  Some virtual properties are, however, writable: for\n\t * example, virtual index properties of buffer objects and Array\n\t * instance .length.  These are not configurable so the checks\n\t * above mostly cover attempts to change them, except when the\n\t * duk_def_prop() call is used with DUK_DEFPROP_FORCE; even in\n\t * that case we can't forcibly change the property attributes\n\t * because they don't have concrete backing.\n\t */\n\n\t/* XXX: for ROM objects too it'd be best if value modify was\n\t * allowed if the value matches SameValue.\n\t */\n\t/* Reject attempt to change a read-only object. */\n#if defined(DUK_USE_ROM_OBJECTS)\n\tif (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj)) {\n\t\tDUK_DD(DUK_DDPRINT(\"attempt to define property on read-only target object\"));\n\t\tgoto fail_not_configurable;\n\t}\n#endif\n\n\t/* descriptor type specific checks */\n\tif (has_set || has_get) {\n\t\t/* IsAccessorDescriptor(desc) == true */\n\t\tDUK_ASSERT(!has_writable);\n\t\tDUK_ASSERT(!has_value);\n\n\t\tif (curr.flags & DUK_PROPDESC_FLAG_ACCESSOR) {\n\t\t\t/* curr and desc are accessors */\n\t\t\tif (!(curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) && !force_flag) {\n\t\t\t\tif (has_set && set != curr.set) {\n\t\t\t\t\tgoto fail_not_configurable;\n\t\t\t\t}\n\t\t\t\tif (has_get && get != curr.get) {\n\t\t\t\t\tgoto fail_not_configurable;\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tduk_bool_t rc;\n\t\t\tduk_tval *tv1;\n\n\t\t\t/* curr is data, desc is accessor */\n\t\t\tif (!(curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) && !force_flag) {\n\t\t\t\tgoto fail_not_configurable;\n\t\t\t}\n\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"convert property to accessor property\"));\n\t\t\tif (curr.a_idx >= 0) {\n\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"property to convert is stored in an array entry, abandon array and re-lookup\"));\n\t\t\t\tduk__abandon_array_checked(thr, obj);\n\t\t\t\tduk_pop_unsafe(thr);  /* remove old value */\n\t\t\t\trc = duk__get_own_propdesc_raw(thr, obj, key, arr_idx, &curr, DUK_GETDESC_FLAG_PUSH_VALUE);\n\t\t\t\tDUK_UNREF(rc);\n\t\t\t\tDUK_ASSERT(rc != 0);\n\t\t\t\tDUK_ASSERT(curr.e_idx >= 0 && curr.a_idx < 0);\n\t\t\t}\n\t\t\tif (curr.e_idx < 0) {\n\t\t\t\tDUK_ASSERT(curr.a_idx < 0 && curr.e_idx < 0);\n\t\t\t\tgoto fail_virtual;  /* safeguard for virtual property */\n\t\t\t}\n\n\t\t\tDUK_ASSERT(curr.e_idx >= 0);\n\t\t\tDUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, obj, curr.e_idx));\n\n\t\t\ttv1 = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, curr.e_idx);\n\t\t\tDUK_TVAL_SET_UNDEFINED_UPDREF_NORZ(thr, tv1);  /* XXX: just decref */\n\n\t\t\tDUK_HOBJECT_E_SET_VALUE_GETTER(thr->heap, obj, curr.e_idx, NULL);\n\t\t\tDUK_HOBJECT_E_SET_VALUE_SETTER(thr->heap, obj, curr.e_idx, NULL);\n\t\t\tDUK_HOBJECT_E_SLOT_CLEAR_WRITABLE(thr->heap, obj, curr.e_idx);\n\t\t\tDUK_HOBJECT_E_SLOT_SET_ACCESSOR(thr->heap, obj, curr.e_idx);\n\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"flags after data->accessor conversion: 0x%02lx\",\n\t\t\t                     (unsigned long) DUK_HOBJECT_E_GET_FLAGS(thr->heap, obj, curr.e_idx)));\n\t\t\t/* Update curr.flags; faster than a re-lookup. */\n\t\t\tcurr.flags &= ~DUK_PROPDESC_FLAG_WRITABLE;\n\t\t\tcurr.flags |= DUK_PROPDESC_FLAG_ACCESSOR;\n\t\t}\n\t} else if (has_value || has_writable) {\n\t\t/* IsDataDescriptor(desc) == true */\n\t\tDUK_ASSERT(!has_set);\n\t\tDUK_ASSERT(!has_get);\n\n\t\tif (curr.flags & DUK_PROPDESC_FLAG_ACCESSOR) {\n\t\t\tduk_hobject *tmp;\n\n\t\t\t/* curr is accessor, desc is data */\n\t\t\tif (!(curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) && !force_flag) {\n\t\t\t\tgoto fail_not_configurable;\n\t\t\t}\n\n\t\t\t/* curr is accessor -> cannot be in array part. */\n\t\t\tDUK_ASSERT(curr.a_idx < 0);\n\t\t\tif (curr.e_idx < 0) {\n\t\t\t\tgoto fail_virtual;  /* safeguard; no virtual accessors now */\n\t\t\t}\n\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"convert property to data property\"));\n\n\t\t\tDUK_ASSERT(DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, obj, curr.e_idx));\n\t\t\ttmp = DUK_HOBJECT_E_GET_VALUE_GETTER(thr->heap, obj, curr.e_idx);\n\t\t\tDUK_UNREF(tmp);\n\t\t\tDUK_HOBJECT_E_SET_VALUE_GETTER(thr->heap, obj, curr.e_idx, NULL);\n\t\t\tDUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, tmp);\n\t\t\ttmp = DUK_HOBJECT_E_GET_VALUE_SETTER(thr->heap, obj, curr.e_idx);\n\t\t\tDUK_UNREF(tmp);\n\t\t\tDUK_HOBJECT_E_SET_VALUE_SETTER(thr->heap, obj, curr.e_idx, NULL);\n\t\t\tDUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, tmp);\n\n\t\t\tDUK_TVAL_SET_UNDEFINED(DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, curr.e_idx));\n\t\t\tDUK_HOBJECT_E_SLOT_CLEAR_WRITABLE(thr->heap, obj, curr.e_idx);\n\t\t\tDUK_HOBJECT_E_SLOT_CLEAR_ACCESSOR(thr->heap, obj, curr.e_idx);\n\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"flags after accessor->data conversion: 0x%02lx\",\n\t\t\t                     (unsigned long) DUK_HOBJECT_E_GET_FLAGS(thr->heap, obj, curr.e_idx)));\n\n\t\t\t/* Update curr.flags; faster than a re-lookup. */\n\t\t\tcurr.flags &= ~(DUK_PROPDESC_FLAG_WRITABLE | DUK_PROPDESC_FLAG_ACCESSOR);\n\t\t} else {\n\t\t\t/* curr and desc are data */\n\t\t\tif (!(curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) && !force_flag) {\n\t\t\t\tif (!(curr.flags & DUK_PROPDESC_FLAG_WRITABLE) && has_writable && is_writable) {\n\t\t\t\t\tgoto fail_not_configurable;\n\t\t\t\t}\n\t\t\t\t/* Note: changing from writable to non-writable is OK */\n\t\t\t\tif (!(curr.flags & DUK_PROPDESC_FLAG_WRITABLE) && has_value) {\n\t\t\t\t\tduk_tval *tmp1 = duk_require_tval(thr, -1);         /* curr value */\n\t\t\t\t\tduk_tval *tmp2 = duk_require_tval(thr, idx_value);  /* new value */\n\t\t\t\t\tif (!duk_js_samevalue(tmp1, tmp2)) {\n\t\t\t\t\t\tgoto fail_not_configurable;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} else {\n\t\t/* IsGenericDescriptor(desc) == true; this means in practice that 'desc'\n\t\t * only has [[Enumerable]] or [[Configurable]] flag updates, which are\n\t\t * allowed at this point.\n\t\t */\n\n\t\tDUK_ASSERT(!has_value && !has_writable && !has_get && !has_set);\n\t}\n\n\t/*\n\t *  Start doing property attributes updates.  Steps 12-13.\n\t *\n\t *  Start by computing new attribute flags without writing yet.\n\t *  Property type conversion is done above if necessary.\n\t */\n\n\tnew_flags = curr.flags;\n\n\tif (has_enumerable) {\n\t\tif (is_enumerable) {\n\t\t\tnew_flags |= DUK_PROPDESC_FLAG_ENUMERABLE;\n\t\t} else {\n\t\t\tnew_flags &= ~DUK_PROPDESC_FLAG_ENUMERABLE;\n\t\t}\n\t}\n\tif (has_configurable) {\n\t\tif (is_configurable) {\n\t\t\tnew_flags |= DUK_PROPDESC_FLAG_CONFIGURABLE;\n\t\t} else {\n\t\t\tnew_flags &= ~DUK_PROPDESC_FLAG_CONFIGURABLE;\n\t\t}\n\t}\n\tif (has_writable) {\n\t\tif (is_writable) {\n\t\t\tnew_flags |= DUK_PROPDESC_FLAG_WRITABLE;\n\t\t} else {\n\t\t\tnew_flags &= ~DUK_PROPDESC_FLAG_WRITABLE;\n\t\t}\n\t}\n\n\t/* XXX: write protect after flag? -> any chance of handling it here? */\n\n\tDUK_DDD(DUK_DDDPRINT(\"new flags that we want to write: 0x%02lx\",\n\t                     (unsigned long) new_flags));\n\n\t/*\n\t *  Check whether we need to abandon an array part (if it exists)\n\t */\n\n\tif (curr.a_idx >= 0) {\n\t\tduk_bool_t rc;\n\n\t\tDUK_ASSERT(curr.e_idx < 0);\n\n\t\tif (new_flags == DUK_PROPDESC_FLAGS_WEC) {\n\t\t\tduk_tval *tv1, *tv2;\n\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"array index, new property attributes match array defaults, update in-place\"));\n\n\t\t\tDUK_ASSERT(curr.flags == DUK_PROPDESC_FLAGS_WEC);  /* must have been, since in array part */\n\t\t\tDUK_ASSERT(!has_set);\n\t\t\tDUK_ASSERT(!has_get);\n\t\t\tDUK_ASSERT(idx_value >= 0);  /* must be: if attributes match and we get here the value must differ (otherwise no change) */\n\n\t\t\ttv2 = duk_require_tval(thr, idx_value);\n\t\t\ttv1 = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, curr.a_idx);\n\t\t\tDUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv2);  /* side effects; may invalidate a_idx */\n\t\t\tgoto success_exotics;\n\t\t}\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"array index, new property attributes do not match array defaults, abandon array and re-lookup\"));\n\t\tduk__abandon_array_checked(thr, obj);\n\t\tduk_pop_unsafe(thr);  /* remove old value */\n\t\trc = duk__get_own_propdesc_raw(thr, obj, key, arr_idx, &curr, DUK_GETDESC_FLAG_PUSH_VALUE);\n\t\tDUK_UNREF(rc);\n\t\tDUK_ASSERT(rc != 0);\n\t\tDUK_ASSERT(curr.e_idx >= 0 && curr.a_idx < 0);\n\t}\n\n\tDUK_DDD(DUK_DDDPRINT(\"updating existing property in entry part\"));\n\n\t/* Array case is handled comprehensively above: either in entry\n\t * part or a virtual property.\n\t */\n\tDUK_ASSERT(curr.a_idx < 0);\n\n\tDUK_DDD(DUK_DDDPRINT(\"update existing property attributes\"));\n\tif (curr.e_idx >= 0) {\n\t\tDUK_HOBJECT_E_SET_FLAGS(thr->heap, obj, curr.e_idx, new_flags);\n\t} else {\n\t\t/* For Array .length the only allowed transition is for .length\n\t\t * to become non-writable.\n\t\t */\n\t\tif (key == DUK_HTHREAD_STRING_LENGTH(thr) && DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj)) {\n\t\t\tduk_harray *a;\n\t\t\ta = (duk_harray *) obj;\n\t\t\tDUK_DD(DUK_DDPRINT(\"Object.defineProperty() attribute update for duk_harray .length -> %02lx\", (unsigned long) new_flags));\n\t\t\tDUK_ASSERT_HARRAY_VALID(a);\n\t\t\tif ((new_flags & DUK_PROPDESC_FLAGS_EC) != (curr.flags & DUK_PROPDESC_FLAGS_EC)) {\n\t\t\t\tDUK_D(DUK_DPRINT(\"Object.defineProperty() attempt to change virtual array .length enumerable or configurable attribute, fail\"));\n\t\t\t\tgoto fail_virtual;\n\t\t\t}\n\t\t\tif (new_flags & DUK_PROPDESC_FLAG_WRITABLE) {\n\t\t\t\tDUK_HARRAY_SET_LENGTH_WRITABLE(a);\n\t\t\t} else {\n\t\t\t\tDUK_HARRAY_SET_LENGTH_NONWRITABLE(a);\n\t\t\t}\n\t\t}\n\t}\n\n\tif (has_set) {\n\t\tduk_hobject *tmp;\n\n\t\t/* Virtual properties are non-configurable but with a 'force'\n\t\t * flag we might come here so check explicitly for virtual.\n\t\t */\n\t\tif (curr.e_idx < 0) {\n\t\t\tgoto fail_virtual;\n\t\t}\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"update existing property setter\"));\n\t\tDUK_ASSERT(DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, obj, curr.e_idx));\n\n\t\ttmp = DUK_HOBJECT_E_GET_VALUE_SETTER(thr->heap, obj, curr.e_idx);\n\t\tDUK_UNREF(tmp);\n\t\tDUK_HOBJECT_E_SET_VALUE_SETTER(thr->heap, obj, curr.e_idx, set);\n\t\tDUK_HOBJECT_INCREF_ALLOWNULL(thr, set);\n\t\tDUK_HOBJECT_DECREF_ALLOWNULL(thr, tmp);  /* side effects; may invalidate e_idx */\n\t}\n\tif (has_get) {\n\t\tduk_hobject *tmp;\n\n\t\tif (curr.e_idx < 0) {\n\t\t\tgoto fail_virtual;\n\t\t}\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"update existing property getter\"));\n\t\tDUK_ASSERT(DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, obj, curr.e_idx));\n\n\t\ttmp = DUK_HOBJECT_E_GET_VALUE_GETTER(thr->heap, obj, curr.e_idx);\n\t\tDUK_UNREF(tmp);\n\t\tDUK_HOBJECT_E_SET_VALUE_GETTER(thr->heap, obj, curr.e_idx, get);\n\t\tDUK_HOBJECT_INCREF_ALLOWNULL(thr, get);\n\t\tDUK_HOBJECT_DECREF_ALLOWNULL(thr, tmp);  /* side effects; may invalidate e_idx */\n\t}\n\tif (has_value) {\n\t\tduk_tval *tv1, *tv2;\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"update existing property value\"));\n\n\t\tif (curr.e_idx >= 0) {\n\t\t\tDUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, obj, curr.e_idx));\n\t\t\ttv2 = duk_require_tval(thr, idx_value);\n\t\t\ttv1 = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, curr.e_idx);\n\t\t\tDUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv2);  /* side effects; may invalidate e_idx */\n\t\t} else {\n\t\t\tDUK_ASSERT(curr.a_idx < 0);  /* array part case handled comprehensively previously */\n\n\t\t\tDUK_DD(DUK_DDPRINT(\"Object.defineProperty(), value update for virtual property\"));\n\t\t\t/* XXX: Uint8Array and other typed array virtual writes not currently\n\t\t\t * handled.\n\t\t\t */\n\t\t\tif (key == DUK_HTHREAD_STRING_LENGTH(thr) && DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj)) {\n\t\t\t\tduk_harray *a;\n\t\t\t\ta = (duk_harray *) obj;\n\t\t\t\tDUK_DD(DUK_DDPRINT(\"Object.defineProperty() value update for duk_harray .length -> %ld\", (long) arrlen_new_len));\n\t\t\t\tDUK_ASSERT_HARRAY_VALID(a);\n\t\t\t\ta->length = arrlen_new_len;\n\t\t\t} else {\n\t\t\t\tgoto fail_virtual;  /* should not happen */\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t *  Standard algorithm succeeded without errors, check for exotic post-behaviors.\n\t *\n\t *  Arguments exotic behavior in E5 Section 10.6 occurs after the standard\n\t *  [[DefineOwnProperty]] has completed successfully.\n\t *\n\t *  Array exotic behavior in E5 Section 15.4.5.1 is implemented partly\n\t *  prior to the default [[DefineOwnProperty]], but:\n\t *    - for an array index key (e.g. \"10\") the final 'length' update occurs here\n\t *    - for 'length' key the element deletion and 'length' update occurs here\n\t */\n\n success_exotics:\n\n\t/* curr.a_idx or curr.e_idx may have been invalidated by side effects\n\t * above.\n\t */\n\n\t/* [obj key desc value get set curr_value] */\n\n\tif (DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj)) {\n\t\tduk_harray *a;\n\n\t\ta = (duk_harray *) obj;\n\t\tDUK_ASSERT_HARRAY_VALID(a);\n\n\t\tif (arridx_new_array_length > 0) {\n\t\t\t/*\n\t\t\t *  Note: zero works as a \"no update\" marker because the new length\n\t\t\t *  can never be zero after a new property is written.\n\t\t\t */\n\n\t\t\t/* E5 Section 15.4.5.1, steps 4.e.i - 4.e.ii */\n\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"defineProperty successful, pending array length update to: %ld\",\n\t\t\t                     (long) arridx_new_array_length));\n\n\t\t\ta->length = arridx_new_array_length;\n\t\t}\n\n\t\tif (key == DUK_HTHREAD_STRING_LENGTH(thr) && arrlen_new_len < arrlen_old_len) {\n\t\t\t/*\n\t\t\t *  E5 Section 15.4.5.1, steps 3.k - 3.n.  The order at the end combines\n\t\t\t *  the error case 3.l.iii and the success case 3.m-3.n.\n\t\t\t */\n\n\t\t\t/* XXX: investigate whether write protect can be handled above, if we\n\t\t\t * just update length here while ignoring its protected status\n\t\t\t */\n\n\t\t\tduk_uint32_t result_len;\n\t\t\tduk_bool_t rc;\n\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"defineProperty successful, key is 'length', exotic array behavior, \"\n\t\t\t                     \"doing array element deletion and length update\"));\n\n\t\t\trc = duk__handle_put_array_length_smaller(thr, obj, arrlen_old_len, arrlen_new_len, force_flag, &result_len);\n\n\t\t\t/* update length (curr points to length, and we assume it's still valid) */\n\t\t\tDUK_ASSERT(result_len >= arrlen_new_len && result_len <= arrlen_old_len);\n\n\t\t\ta->length = result_len;\n\n\t\t\tif (pending_write_protect) {\n\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"setting array length non-writable (pending writability update)\"));\n\t\t\t\tDUK_HARRAY_SET_LENGTH_NONWRITABLE(a);\n\t\t\t}\n\n\t\t\t/* XXX: shrink array allocation or entries compaction here? */\n\t\t\tif (!rc) {\n\t\t\t\tDUK_DD(DUK_DDPRINT(\"array length write only partially successful\"));\n\t\t\t\tgoto fail_not_configurable;\n\t\t\t}\n\t\t}\n\t} else if (arr_idx != DUK__NO_ARRAY_INDEX && DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj)) {\n\t\tduk_hobject *map;\n\t\tduk_hobject *varenv;\n\n\t\tDUK_ASSERT(arridx_new_array_length == 0);\n\t\tDUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj));  /* traits are separate; in particular, arguments not an array */\n\n\t\tmap = NULL;\n\t\tvarenv = NULL;\n\t\tif (!duk__lookup_arguments_map(thr, obj, key, &curr, &map, &varenv)) {\n\t\t\tgoto success_no_exotics;\n\t\t}\n\t\tDUK_ASSERT(map != NULL);\n\t\tDUK_ASSERT(varenv != NULL);\n\n\t\t/* [obj key desc value get set curr_value varname] */\n\n\t\tif (has_set || has_get) {\n\t\t\t/* = IsAccessorDescriptor(Desc) */\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"defineProperty successful, key mapped to arguments 'map' \"\n\t\t\t                     \"changed to an accessor, delete arguments binding\"));\n\n\t\t\t(void) duk_hobject_delprop_raw(thr, map, key, 0);  /* ignore result */\n\t\t} else {\n\t\t\t/* Note: this order matters (final value before deleting map entry must be done) */\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"defineProperty successful, key mapped to arguments 'map', \"\n\t\t\t                     \"check for value update / binding deletion\"));\n\n\t\t\tif (has_value) {\n\t\t\t\tduk_hstring *varname;\n\n\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"defineProperty successful, key mapped to arguments 'map', \"\n\t\t\t\t                     \"update bound value (variable/argument)\"));\n\n\t\t\t\tvarname = duk_require_hstring(thr, -1);\n\t\t\t\tDUK_ASSERT(varname != NULL);\n\n\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"arguments object automatic putvar for a bound variable; \"\n\t\t\t\t                     \"key=%!O, varname=%!O, value=%!T\",\n\t\t\t\t                     (duk_heaphdr *) key,\n\t\t\t\t                     (duk_heaphdr *) varname,\n\t\t\t\t                     (duk_tval *) duk_require_tval(thr, idx_value)));\n\n\t\t\t\t/* strict flag for putvar comes from our caller (currently: fixed) */\n\t\t\t\tduk_js_putvar_envrec(thr, varenv, varname, duk_require_tval(thr, idx_value), 1 /*throw_flag*/);\n\t\t\t}\n\t\t\tif (has_writable && !is_writable) {\n\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"defineProperty successful, key mapped to arguments 'map', \"\n\t\t\t\t                     \"changed to non-writable, delete arguments binding\"));\n\n\t\t\t\t(void) duk_hobject_delprop_raw(thr, map, key, 0);  /* ignore result */\n\t\t\t}\n\t\t}\n\n\t\t/* 'varname' is in stack in this else branch, leaving an unbalanced stack below,\n\t\t * but this doesn't matter now.\n\t\t */\n\t}\n\n success_no_exotics:\n\t/* Some code paths use NORZ macros for simplicity, ensure refzero\n\t * handling is completed.\n\t */\n\tDUK_REFZERO_CHECK_SLOW(thr);\n\treturn 1;\n\n fail_not_extensible:\n\tif (throw_flag) {\n\t\tDUK_ERROR_TYPE(thr, DUK_STR_NOT_EXTENSIBLE);\n\t}\n\treturn 0;\n\n fail_virtual:  /* just use the same \"not configurable\" error message\" */\n fail_not_configurable:\n\tif (throw_flag) {\n\t\tDUK_ERROR_TYPE(thr, DUK_STR_NOT_CONFIGURABLE);\n\t}\n\treturn 0;\n}\n\n/*\n *  Object.prototype.hasOwnProperty() and Object.prototype.propertyIsEnumerable().\n */\n\nDUK_INTERNAL duk_bool_t duk_hobject_object_ownprop_helper(duk_hthread *thr, duk_small_uint_t required_desc_flags) {\n\tduk_hstring *h_v;\n\tduk_hobject *h_obj;\n\tduk_propdesc desc;\n\tduk_bool_t ret;\n\n\t/* coercion order matters */\n\th_v = duk_to_hstring_acceptsymbol(thr, 0);\n\tDUK_ASSERT(h_v != NULL);\n\n\th_obj = duk_push_this_coercible_to_object(thr);\n\tDUK_ASSERT(h_obj != NULL);\n\n\tret = duk_hobject_get_own_propdesc(thr, h_obj, h_v, &desc, 0 /*flags*/);  /* don't push value */\n\n\tduk_push_boolean(thr, ret && ((desc.flags & required_desc_flags) == required_desc_flags));\n\treturn 1;\n}\n\n/*\n *  Object.seal() and Object.freeze()  (E5 Sections 15.2.3.8 and 15.2.3.9)\n *\n *  Since the algorithms are similar, a helper provides both functions.\n *  Freezing is essentially sealing + making plain properties non-writable.\n *\n *  Note: virtual (non-concrete) properties which are non-configurable but\n *  writable would pose some problems, but such properties do not currently\n *  exist (all virtual properties are non-configurable and non-writable).\n *  If they did exist, the non-configurability does NOT prevent them from\n *  becoming non-writable.  However, this change should be recorded somehow\n *  so that it would turn up (e.g. when getting the property descriptor),\n *  requiring some additional flags in the object.\n */\n\nDUK_INTERNAL void duk_hobject_object_seal_freeze_helper(duk_hthread *thr, duk_hobject *obj, duk_bool_t is_freeze) {\n\tduk_uint_fast32_t i;\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(thr->heap != NULL);\n\tDUK_ASSERT(obj != NULL);\n\n\tDUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);\n\n#if defined(DUK_USE_ROM_OBJECTS)\n\tif (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj)) {\n\t\tDUK_DD(DUK_DDPRINT(\"attempt to seal/freeze a readonly object, reject\"));\n\t\tDUK_ERROR_TYPE(thr, DUK_STR_NOT_CONFIGURABLE);\n\t}\n#endif\n\n\t/*\n\t *  Abandon array part because all properties must become non-configurable.\n\t *  Note that this is now done regardless of whether this is always the case\n\t *  (skips check, but performance problem if caller would do this many times\n\t *  for the same object; not likely).\n\t */\n\n\tduk__abandon_array_checked(thr, obj);\n\tDUK_ASSERT(DUK_HOBJECT_GET_ASIZE(obj) == 0);\n\n\tfor (i = 0; i < DUK_HOBJECT_GET_ENEXT(obj); i++) {\n\t\tduk_uint8_t *fp;\n\n\t\t/* since duk__abandon_array_checked() causes a resize, there should be no gaps in keys */\n\t\tDUK_ASSERT(DUK_HOBJECT_E_GET_KEY(thr->heap, obj, i) != NULL);\n\n\t\t/* avoid multiple computations of flags address; bypasses macros */\n\t\tfp = DUK_HOBJECT_E_GET_FLAGS_PTR(thr->heap, obj, i);\n\t\tif (is_freeze && !((*fp) & DUK_PROPDESC_FLAG_ACCESSOR)) {\n\t\t\t*fp &= ~(DUK_PROPDESC_FLAG_WRITABLE | DUK_PROPDESC_FLAG_CONFIGURABLE);\n\t\t} else {\n\t\t\t*fp &= ~DUK_PROPDESC_FLAG_CONFIGURABLE;\n\t\t}\n\t}\n\n\tDUK_HOBJECT_CLEAR_EXTENSIBLE(obj);\n\n\t/* no need to compact since we already did that in duk__abandon_array_checked()\n\t * (regardless of whether an array part existed or not.\n\t */\n\n\treturn;\n}\n\n/*\n *  Object.isSealed() and Object.isFrozen()  (E5 Sections 15.2.3.11, 15.2.3.13)\n *\n *  Since the algorithms are similar, a helper provides both functions.\n *  Freezing is essentially sealing + making plain properties non-writable.\n *\n *  Note: all virtual (non-concrete) properties are currently non-configurable\n *  and non-writable (and there are no accessor virtual properties), so they don't\n *  need to be considered here now.\n */\n\nDUK_INTERNAL duk_bool_t duk_hobject_object_is_sealed_frozen_helper(duk_hthread *thr, duk_hobject *obj, duk_bool_t is_frozen) {\n\tduk_uint_fast32_t i;\n\n\tDUK_ASSERT(obj != NULL);\n\tDUK_UNREF(thr);\n\n\t/* Note: no allocation pressure, no need to check refcounts etc */\n\n\t/* must not be extensible */\n\tif (DUK_HOBJECT_HAS_EXTENSIBLE(obj)) {\n\t\treturn 0;\n\t}\n\n\t/* all virtual properties are non-configurable and non-writable */\n\n\t/* entry part must not contain any configurable properties, or\n\t * writable properties (if is_frozen).\n\t */\n\tfor (i = 0; i < DUK_HOBJECT_GET_ENEXT(obj); i++) {\n\t\tduk_small_uint_t flags;\n\n\t\tif (!DUK_HOBJECT_E_GET_KEY(thr->heap, obj, i)) {\n\t\t\tcontinue;\n\t\t}\n\n\t\t/* avoid multiple computations of flags address; bypasses macros */\n\t\tflags = (duk_small_uint_t) DUK_HOBJECT_E_GET_FLAGS(thr->heap, obj, i);\n\n\t\tif (flags & DUK_PROPDESC_FLAG_CONFIGURABLE) {\n\t\t\treturn 0;\n\t\t}\n\t\tif (is_frozen &&\n\t\t    !(flags & DUK_PROPDESC_FLAG_ACCESSOR) &&\n\t\t    (flags & DUK_PROPDESC_FLAG_WRITABLE)) {\n\t\t\treturn 0;\n\t\t}\n\t}\n\n\t/* array part must not contain any non-unused properties, as they would\n\t * be configurable and writable.\n\t */\n\tfor (i = 0; i < DUK_HOBJECT_GET_ASIZE(obj); i++) {\n\t\tduk_tval *tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, i);\n\t\tif (!DUK_TVAL_IS_UNUSED(tv)) {\n\t\t\treturn 0;\n\t\t}\n\t}\n\n\treturn 1;\n}\n\n/*\n *  Object.preventExtensions() and Object.isExtensible()  (E5 Sections 15.2.3.10, 15.2.3.13)\n *\n *  Not needed, implemented by macros DUK_HOBJECT_{HAS,CLEAR,SET}_EXTENSIBLE\n *  and the Object built-in bindings.\n */\n\n/* automatic undefs */\n#undef DUK__HASH_DELETED\n#undef DUK__HASH_UNUSED\n#undef DUK__NO_ARRAY_INDEX\n#undef DUK__VALSTACK_PROXY_LOOKUP\n#undef DUK__VALSTACK_SPACE\n#line 1 \"duk_hstring_misc.c\"\n/*\n *  Misc support functions\n */\n\n/* #include duk_internal.h -> already included */\n\n/*\n *  duk_hstring charCodeAt, with and without surrogate awareness\n */\n\nDUK_INTERNAL duk_ucodepoint_t duk_hstring_char_code_at_raw(duk_hthread *thr, duk_hstring *h, duk_uint_t pos, duk_bool_t surrogate_aware) {\n\tduk_uint32_t boff;\n\tconst duk_uint8_t *p, *p_start, *p_end;\n\tduk_ucodepoint_t cp1;\n\tduk_ucodepoint_t cp2;\n\n\t/* Caller must check character offset to be inside the string. */\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(h != NULL);\n\tDUK_ASSERT_DISABLE(pos >= 0);  /* unsigned */\n\tDUK_ASSERT(pos < (duk_uint_t) DUK_HSTRING_GET_CHARLEN(h));\n\n\tboff = (duk_uint32_t) duk_heap_strcache_offset_char2byte(thr, h, (duk_uint32_t) pos);\n\tDUK_DDD(DUK_DDDPRINT(\"charCodeAt: pos=%ld -> boff=%ld, str=%!O\",\n\t                     (long) pos, (long) boff, (duk_heaphdr *) h));\n\tDUK_ASSERT_DISABLE(boff >= 0);\n\tDUK_ASSERT(boff < DUK_HSTRING_GET_BYTELEN(h));\n\n\tp_start = DUK_HSTRING_GET_DATA(h);\n\tp_end = p_start + DUK_HSTRING_GET_BYTELEN(h);\n\tp = p_start + boff;\n\tDUK_DDD(DUK_DDDPRINT(\"p_start=%p, p_end=%p, p=%p\",\n\t                     (const void *) p_start, (const void *) p_end,\n\t                     (const void *) p));\n\n\t/* For invalid UTF-8 (never happens for standard Ecmascript strings)\n\t * return U+FFFD replacement character.\n\t */\n\tif (duk_unicode_decode_xutf8(thr, &p, p_start, p_end, &cp1)) {\n\t\tif (surrogate_aware && cp1 >= 0xd800UL && cp1 <= 0xdbffUL) {\n\t\t\t/* The decode helper is memory safe even if 'cp1' was\n\t\t\t * decoded at the end of the string and 'p' is no longer\n\t\t\t * within string memory range.\n\t\t\t */\n\t\t\tcp2 = 0;  /* If call fails, this is left untouched and won't match cp2 check. */\n\t\t\t(void) duk_unicode_decode_xutf8(thr, &p, p_start, p_end, &cp2);\n\t\t\tif (cp2 >= 0xdc00UL && cp2 <= 0xdfffUL) {\n\t\t\t\tcp1 = (duk_ucodepoint_t) (((cp1 - 0xd800UL) << 10) + (cp2 - 0xdc00UL) + 0x10000UL);\n\t\t\t}\n\t\t}\n\t} else {\n\t\tcp1 = DUK_UNICODE_CP_REPLACEMENT_CHARACTER;\n\t}\n\n\treturn cp1;\n}\n\n/*\n *  duk_hstring charlen, when lazy charlen disabled\n */\n\n#if !defined(DUK_USE_HSTRING_LAZY_CLEN)\n#if !defined(DUK_USE_HSTRING_CLEN)\n#error non-lazy duk_hstring charlen but DUK_USE_HSTRING_CLEN not set\n#endif\nDUK_INTERNAL void duk_hstring_init_charlen(duk_hstring *h) {\n\tduk_uint32_t clen;\n\n\tDUK_ASSERT(h != NULL);\n\tDUK_ASSERT(!DUK_HSTRING_HAS_ASCII(h));\n\tDUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) h));\n\n\tclen = duk_unicode_unvalidated_utf8_length(DUK_HSTRING_GET_DATA(h), DUK_HSTRING_GET_BYTELEN(h));\n#if defined(DUK_USE_STRLEN16)\n\tDUK_ASSERT(clen <= 0xffffUL);  /* Bytelength checked during interning. */\n\th->clen16 = (duk_uint16_t) clen;\n#else\n\th->clen = (duk_uint32_t) clen;\n#endif\n\tif (DUK_LIKELY(clen == DUK_HSTRING_GET_BYTELEN(h))) {\n\t\tDUK_HSTRING_SET_ASCII(h);\n\t}\n}\n\nDUK_INTERNAL DUK_HOT duk_size_t duk_hstring_get_charlen(duk_hstring *h) {\n#if defined(DUK_USE_STRLEN16)\n\treturn h->clen16;\n#else\n\treturn h->clen;\n#endif\n}\n#endif  /* !DUK_USE_HSTRING_LAZY_CLEN */\n\n/*\n *  duk_hstring charlen, when lazy charlen enabled\n */\n\n#if defined(DUK_USE_HSTRING_LAZY_CLEN)\n#if defined(DUK_USE_HSTRING_CLEN)\nDUK_LOCAL DUK_COLD duk_size_t duk__hstring_get_charlen_slowpath(duk_hstring *h) {\n\tduk_size_t res;\n\n\tDUK_ASSERT(h->clen == 0);  /* Checked by caller. */\n\n#if defined(DUK_USE_ROM_STRINGS)\n\t/* ROM strings have precomputed clen, but if the computed clen is zero\n\t * we can still come here and can't write anything.\n\t */\n\tif (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) h)) {\n\t\treturn 0;\n\t}\n#endif\n\n\tres = duk_unicode_unvalidated_utf8_length(DUK_HSTRING_GET_DATA(h), DUK_HSTRING_GET_BYTELEN(h));\n#if defined(DUK_USE_STRLEN16)\n\tDUK_ASSERT(res <= 0xffffUL);  /* Bytelength checked during interning. */\n\th->clen16 = (duk_uint16_t) res;\n#else\n\th->clen = (duk_uint32_t) res;\n#endif\n\tif (DUK_LIKELY(res == DUK_HSTRING_GET_BYTELEN(h))) {\n\t\tDUK_HSTRING_SET_ASCII(h);\n\t}\n\treturn res;\n}\n#else  /* DUK_USE_HSTRING_CLEN */\nDUK_LOCAL duk_size_t duk__hstring_get_charlen_slowpath(duk_hstring *h) {\n\tif (DUK_LIKELY(DUK_HSTRING_HAS_ASCII(h))) {\n\t\t/* Most practical strings will go here. */\n\t\treturn DUK_HSTRING_GET_BYTELEN(h);\n\t} else {\n\t\t/* ASCII flag is lazy, so set it here. */\n\t\tduk_size_t res;\n\n\t\t/* XXX: here we could use the strcache to speed up the\n\t\t * computation (matters for 'i < str.length' loops).\n\t\t */\n\n\t\tres = duk_unicode_unvalidated_utf8_length(DUK_HSTRING_GET_DATA(h), DUK_HSTRING_GET_BYTELEN(h));\n\n#if defined(DUK_USE_ROM_STRINGS)\n\t\tif (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) h)) {\n\t\t\t/* For ROM strings, can't write anything; ASCII flag\n\t\t\t * is preset so we don't need to update it.\n\t\t\t */\n\t\t\treturn res;\n\t\t}\n#endif\n\t\tif (DUK_LIKELY(res == DUK_HSTRING_GET_BYTELEN(h))) {\n\t\t\tDUK_HSTRING_SET_ASCII(h);\n\t\t}\n\t\treturn res;\n\t}\n}\n#endif  /* DUK_USE_HSTRING_CLEN */\n\n#if defined(DUK_USE_HSTRING_CLEN)\nDUK_INTERNAL DUK_HOT duk_size_t duk_hstring_get_charlen(duk_hstring *h) {\n#if defined(DUK_USE_STRLEN16)\n\tif (DUK_LIKELY(h->clen16 != 0)) {\n\t\treturn h->clen16;\n\t}\n#else\n\tif (DUK_LIKELY(h->clen != 0)) {\n\t\treturn h->clen;\n\t}\n#endif\n\treturn duk__hstring_get_charlen_slowpath(h);\n}\n#else  /* DUK_USE_HSTRING_CLEN */\nDUK_INTERNAL DUK_HOT duk_size_t duk_hstring_get_charlen(duk_hstring *h) {\n\t/* Always use slow path. */\n\treturn duk__hstring_get_charlen_slowpath(h);\n}\n#endif  /* DUK_USE_HSTRING_CLEN */\n#endif  /* DUK_USE_HSTRING_LAZY_CLEN */\n\n/*\n *  Compare duk_hstring to an ASCII cstring.\n */\n\nDUK_INTERNAL duk_bool_t duk_hstring_equals_ascii_cstring(duk_hstring *h, const char *cstr) {\n\tduk_size_t len;\n\n\tDUK_ASSERT(h != NULL);\n\tDUK_ASSERT(cstr != NULL);\n\n\tlen = DUK_STRLEN(cstr);\n\tif (len != DUK_HSTRING_GET_BYTELEN(h)) {\n\t\treturn 0;\n\t}\n\tif (DUK_MEMCMP((const void *) cstr, (const void *) DUK_HSTRING_GET_DATA(h), len) == 0) {\n\t\treturn 1;\n\t}\n\treturn 0;\n}\n#line 1 \"duk_hthread_alloc.c\"\n/*\n *  duk_hthread allocation and freeing.\n */\n\n/* #include duk_internal.h -> already included */\n\n/*\n *  Allocate initial stacks for a thread.  Note that 'thr' must be reachable\n *  as a garbage collection may be triggered by the allocation attempts.\n *  Returns zero (without leaking memory) if init fails.\n */\n\nDUK_INTERNAL duk_bool_t duk_hthread_init_stacks(duk_heap *heap, duk_hthread *thr) {\n\tduk_size_t alloc_size;\n\tduk_size_t i;\n\n\tDUK_ASSERT(heap != NULL);\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(thr->valstack == NULL);\n\tDUK_ASSERT(thr->valstack_end == NULL);\n\tDUK_ASSERT(thr->valstack_alloc_end == NULL);\n\tDUK_ASSERT(thr->valstack_bottom == NULL);\n\tDUK_ASSERT(thr->valstack_top == NULL);\n\tDUK_ASSERT(thr->callstack_curr == NULL);\n\n\t/* valstack */\n\tDUK_ASSERT(DUK_VALSTACK_API_ENTRY_MINIMUM <= DUK_VALSTACK_INITIAL_SIZE);\n\talloc_size = sizeof(duk_tval) * DUK_VALSTACK_INITIAL_SIZE;\n\tthr->valstack = (duk_tval *) DUK_ALLOC(heap, alloc_size);\n\tif (!thr->valstack) {\n\t\tgoto fail;\n\t}\n\tDUK_MEMZERO(thr->valstack, alloc_size);\n\tthr->valstack_end = thr->valstack + DUK_VALSTACK_API_ENTRY_MINIMUM;\n\tthr->valstack_alloc_end = thr->valstack + DUK_VALSTACK_INITIAL_SIZE;\n\tthr->valstack_bottom = thr->valstack;\n\tthr->valstack_top = thr->valstack;\n\n\tfor (i = 0; i < DUK_VALSTACK_INITIAL_SIZE; i++) {\n\t\tDUK_TVAL_SET_UNDEFINED(&thr->valstack[i]);\n\t}\n\n\treturn 1;\n\n fail:\n\tDUK_FREE(heap, thr->valstack);\n\tDUK_ASSERT(thr->callstack_curr == NULL);\n\n\tthr->valstack = NULL;\n\treturn 0;\n}\n\n/* For indirect allocs. */\n\nDUK_INTERNAL void *duk_hthread_get_valstack_ptr(duk_heap *heap, void *ud) {\n\tduk_hthread *thr = (duk_hthread *) ud;\n\tDUK_UNREF(heap);\n\treturn (void *) thr->valstack;\n}\n#line 1 \"duk_hthread_builtins.c\"\n/*\n *  Initialize built-in objects.  Current thread must have a valstack\n *  and initialization errors may longjmp, so a setjmp() catch point\n *  must exist.\n */\n\n/* #include duk_internal.h -> already included */\n\n/*\n *  Encoding constants, must match genbuiltins.py\n */\n\n#define DUK__PROP_FLAGS_BITS             3\n#define DUK__LENGTH_PROP_BITS            3\n#define DUK__NARGS_BITS                  3\n#define DUK__PROP_TYPE_BITS              3\n\n#define DUK__NARGS_VARARGS_MARKER        0x07\n\n#define DUK__PROP_TYPE_DOUBLE            0\n#define DUK__PROP_TYPE_STRING            1\n#define DUK__PROP_TYPE_STRIDX            2\n#define DUK__PROP_TYPE_BUILTIN           3\n#define DUK__PROP_TYPE_UNDEFINED         4\n#define DUK__PROP_TYPE_BOOLEAN_TRUE      5\n#define DUK__PROP_TYPE_BOOLEAN_FALSE     6\n#define DUK__PROP_TYPE_ACCESSOR          7\n\n/*\n *  Create built-in objects by parsing an init bitstream generated\n *  by genbuiltins.py.\n */\n\n#if defined(DUK_USE_ROM_OBJECTS)\n#if defined(DUK_USE_ROM_GLOBAL_CLONE) || defined(DUK_USE_ROM_GLOBAL_INHERIT)\nDUK_LOCAL void duk__duplicate_ram_global_object(duk_hthread *thr) {\n\tduk_hobject *h_global;\n#if defined(DUK_USE_ROM_GLOBAL_CLONE)\n\tduk_hobject *h_oldglobal;\n\tduk_uint8_t *props;\n\tduk_size_t alloc_size;\n#endif\n\tduk_hobject *h_objenv;\n\n\t/* XXX: refactor into internal helper, duk_clone_hobject() */\n\n#if defined(DUK_USE_ROM_GLOBAL_INHERIT)\n\t/* Inherit from ROM-based global object: less RAM usage, less transparent. */\n\th_global = duk_push_object_helper(thr,\n\t                                  DUK_HOBJECT_FLAG_EXTENSIBLE |\n\t                                  DUK_HOBJECT_FLAG_FASTREFS |\n\t                                  DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_GLOBAL),\n\t                                  DUK_BIDX_GLOBAL);\n\tDUK_ASSERT(h_global != NULL);\n#elif defined(DUK_USE_ROM_GLOBAL_CLONE)\n\t/* Clone the properties of the ROM-based global object to create a\n\t * fully RAM-based global object.  Uses more memory than the inherit\n\t * model but more compliant.\n\t */\n\th_global = duk_push_object_helper(thr,\n\t                                  DUK_HOBJECT_FLAG_EXTENSIBLE |\n\t                                  DUK_HOBJECT_FLAG_FASTREFS |\n\t                                  DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_GLOBAL),\n\t                                  DUK_BIDX_OBJECT_PROTOTYPE);\n\tDUK_ASSERT(h_global != NULL);\n\th_oldglobal = thr->builtins[DUK_BIDX_GLOBAL];\n\tDUK_ASSERT(h_oldglobal != NULL);\n\n\t/* Copy the property table verbatim; this handles attributes etc.\n\t * For ROM objects it's not necessary (or possible) to update\n\t * refcounts so leave them as is.\n\t */\n\talloc_size = DUK_HOBJECT_P_ALLOC_SIZE(h_oldglobal);\n\tDUK_ASSERT(alloc_size > 0);\n\tprops = DUK_ALLOC_CHECKED(thr, alloc_size);\n\tDUK_ASSERT(props != NULL);\n\tDUK_ASSERT(DUK_HOBJECT_GET_PROPS(thr->heap, h_oldglobal) != NULL);\n\tDUK_MEMCPY((void *) props, (const void *) DUK_HOBJECT_GET_PROPS(thr->heap, h_oldglobal), alloc_size);\n\n\t/* XXX: keep property attributes or tweak them here?\n\t * Properties will now be non-configurable even when they're\n\t * normally configurable for the global object.\n\t */\n\n\tDUK_ASSERT(DUK_HOBJECT_GET_PROPS(thr->heap, h_global) == NULL);\n\tDUK_HOBJECT_SET_PROPS(thr->heap, h_global, props);\n\tDUK_HOBJECT_SET_ESIZE(h_global, DUK_HOBJECT_GET_ESIZE(h_oldglobal));\n\tDUK_HOBJECT_SET_ENEXT(h_global, DUK_HOBJECT_GET_ENEXT(h_oldglobal));\n\tDUK_HOBJECT_SET_ASIZE(h_global, DUK_HOBJECT_GET_ASIZE(h_oldglobal));\n\tDUK_HOBJECT_SET_HSIZE(h_global, DUK_HOBJECT_GET_HSIZE(h_oldglobal));\n#else\n#error internal error in config defines\n#endif\n\n\tduk_hobject_compact_props(thr, h_global);\n\tDUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL);\n\tDUK_ASSERT(!DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE((duk_heaphdr *) thr->builtins[DUK_BIDX_GLOBAL]));  /* no need to decref: ROM object */\n\tthr->builtins[DUK_BIDX_GLOBAL] = h_global;\n\tDUK_HOBJECT_INCREF(thr, h_global);\n\tDUK_D(DUK_DPRINT(\"duplicated global object: %!O\", h_global));\n\n\t/* Create a fresh object environment for the global scope.  This is\n\t * needed so that the global scope points to the newly created RAM-based\n\t * global object.\n\t */\n\th_objenv = (duk_hobject *) duk_hobjenv_alloc(thr,\n\t                                             DUK_HOBJECT_FLAG_EXTENSIBLE |\n\t                                             DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJENV));\n\tDUK_ASSERT(h_objenv != NULL);\n\tDUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h_objenv) == NULL);\n\tduk_push_hobject(thr, h_objenv);\n\n\tDUK_ASSERT(h_global != NULL);\n\t((duk_hobjenv *) h_objenv)->target = h_global;\n\tDUK_HOBJECT_INCREF(thr, h_global);\n\tDUK_ASSERT(((duk_hobjenv *) h_objenv)->has_this == 0);\n\n\tDUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL_ENV] != NULL);\n\tDUK_ASSERT(!DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE((duk_heaphdr *) thr->builtins[DUK_BIDX_GLOBAL_ENV]));  /* no need to decref: ROM object */\n\tthr->builtins[DUK_BIDX_GLOBAL_ENV] = h_objenv;\n\tDUK_HOBJECT_INCREF(thr, h_objenv);\n\tDUK_D(DUK_DPRINT(\"duplicated global env: %!O\", h_objenv));\n\n\tDUK_ASSERT_HOBJENV_VALID((duk_hobjenv *) h_objenv);\n\n\tduk_pop_2(thr);  /* Pop global object and global env. */\n}\n#endif  /* DUK_USE_ROM_GLOBAL_CLONE || DUK_USE_ROM_GLOBAL_INHERIT */\n\nDUK_INTERNAL void duk_hthread_create_builtin_objects(duk_hthread *thr) {\n\t/* Setup builtins from ROM objects.  All heaps/threads will share\n\t * the same readonly objects.\n\t */\n\tduk_small_uint_t i;\n\n\tfor (i = 0; i < DUK_NUM_BUILTINS; i++) {\n\t\tduk_hobject *h;\n\t\th = (duk_hobject *) DUK_LOSE_CONST(duk_rom_builtins_bidx[i]);\n\t\tDUK_ASSERT(h != NULL);\n\t\tthr->builtins[i] = h;\n\t}\n\n#if defined(DUK_USE_ROM_GLOBAL_CLONE) || defined(DUK_USE_ROM_GLOBAL_INHERIT)\n\t/* By default the global object is read-only which is often much\n\t * more of an issue than having read-only built-in objects (like\n\t * RegExp, Date, etc).  Use a RAM-based copy of the global object\n\t * and the global environment object for convenience.\n\t */\n\tduk__duplicate_ram_global_object(thr);\n#endif\n}\n#else  /* DUK_USE_ROM_OBJECTS */\nDUK_LOCAL void duk__push_stridx(duk_hthread *thr, duk_bitdecoder_ctx *bd) {\n\tduk_small_uint_t n;\n\n\tn = (duk_small_uint_t) duk_bd_decode_varuint(bd);\n\tDUK_ASSERT_DISABLE(n >= 0);  /* unsigned */\n\tDUK_ASSERT(n < DUK_HEAP_NUM_STRINGS);\n\tduk_push_hstring_stridx(thr, n);\n}\nDUK_LOCAL void duk__push_string(duk_hthread *thr, duk_bitdecoder_ctx *bd) {\n\t/* XXX: built-ins data could provide a maximum length that is\n\t * actually needed; bitpacked max length is now 256 bytes.\n\t */\n\tduk_uint8_t tmp[DUK_BD_BITPACKED_STRING_MAXLEN];\n\tduk_small_uint_t len;\n\n\tlen = duk_bd_decode_bitpacked_string(bd, tmp);\n\tduk_push_lstring(thr, (const char *) tmp, (duk_size_t) len);\n}\nDUK_LOCAL void duk__push_stridx_or_string(duk_hthread *thr, duk_bitdecoder_ctx *bd) {\n\tduk_small_uint_t n;\n\n\tn = (duk_small_uint_t) duk_bd_decode_varuint(bd);\n\tif (n == 0) {\n\t\tduk__push_string(thr, bd);\n\t} else {\n\t\tn--;\n\t\tDUK_ASSERT(n < DUK_HEAP_NUM_STRINGS);\n\t\tduk_push_hstring_stridx(thr, n);\n\t}\n}\nDUK_LOCAL void duk__push_double(duk_hthread *thr, duk_bitdecoder_ctx *bd) {\n\tduk_double_union du;\n\tduk_small_uint_t i;\n\n\tfor (i = 0; i < 8; i++) {\n\t\t/* Encoding endianness must match target memory layout,\n\t\t * build scripts and genbuiltins.py must ensure this.\n\t\t */\n\t\tdu.uc[i] = (duk_uint8_t) duk_bd_decode(bd, 8);\n\t}\n\n\tduk_push_number(thr, du.d);  /* push operation normalizes NaNs */\n}\n\nDUK_INTERNAL void duk_hthread_create_builtin_objects(duk_hthread *thr) {\n\tduk_bitdecoder_ctx bd_ctx;\n\tduk_bitdecoder_ctx *bd = &bd_ctx;  /* convenience */\n\tduk_hobject *h;\n\tduk_small_uint_t i, j;\n\n\tDUK_D(DUK_DPRINT(\"INITBUILTINS BEGIN: DUK_NUM_BUILTINS=%d, DUK_NUM_BUILTINS_ALL=%d\", (int) DUK_NUM_BUILTINS, (int) DUK_NUM_ALL_BUILTINS));\n\n\tDUK_MEMZERO(&bd_ctx, sizeof(bd_ctx));\n\tbd->data = (const duk_uint8_t *) duk_builtins_data;\n\tbd->length = (duk_size_t) DUK_BUILTINS_DATA_LENGTH;\n\n\t/*\n\t *  First create all built-in bare objects on the empty valstack.\n\t *\n\t *  Built-ins in the index range [0,DUK_NUM_BUILTINS-1] have value\n\t *  stack indices matching their eventual thr->builtins[] index.\n\t *\n\t *  Built-ins in the index range [DUK_NUM_BUILTINS,DUK_NUM_ALL_BUILTINS]\n\t *  will exist on the value stack during init but won't be placed\n\t *  into thr->builtins[].  These are objects referenced in some way\n\t *  from thr->builtins[] roots but which don't need to be indexed by\n\t *  Duktape through thr->builtins[] (e.g. user custom objects).\n\t *\n\t *  Internal prototypes will be incorrect (NULL) at this stage.\n\t */\n\n\tduk_require_stack(thr, DUK_NUM_ALL_BUILTINS);\n\n\tDUK_DD(DUK_DDPRINT(\"create empty built-ins\"));\n\tDUK_ASSERT_TOP(thr, 0);\n\tfor (i = 0; i < DUK_NUM_ALL_BUILTINS; i++) {\n\t\tduk_small_uint_t class_num;\n\t\tduk_small_int_t len = -1;  /* must be signed */\n\n\t\tclass_num = (duk_small_uint_t) duk_bd_decode_varuint(bd);\n\t\tlen = (duk_small_int_t) duk_bd_decode_flagged_signed(bd, DUK__LENGTH_PROP_BITS, (duk_int32_t) -1 /*def_value*/);\n\n\t\tif (class_num == DUK_HOBJECT_CLASS_FUNCTION) {\n\t\t\tduk_small_uint_t natidx;\n\t\t\tduk_small_int_t c_nargs;  /* must hold DUK_VARARGS */\n\t\t\tduk_c_function c_func;\n\t\t\tduk_int16_t magic;\n\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"len=%ld\", (long) len));\n\t\t\tDUK_ASSERT(len >= 0);\n\n\t\t\tnatidx = (duk_small_uint_t) duk_bd_decode_varuint(bd);\n\t\t\tDUK_ASSERT(natidx != 0);\n\t\t\tc_func = duk_bi_native_functions[natidx];\n\t\t\tDUK_ASSERT(c_func != NULL);\n\n\t\t\tc_nargs = (duk_small_int_t) duk_bd_decode_flagged_signed(bd, DUK__NARGS_BITS, len /*def_value*/);\n\t\t\tif (c_nargs == DUK__NARGS_VARARGS_MARKER) {\n\t\t\t\tc_nargs = DUK_VARARGS;\n\t\t\t}\n\n\t\t\t/* XXX: set magic directly here? (it could share the c_nargs arg) */\n\t\t\t(void) duk_push_c_function_builtin(thr, c_func, c_nargs);\n\t\t\th = duk_known_hobject(thr, -1);\n\n\t\t\t/* Currently all built-in native functions are strict.\n\t\t\t * duk_push_c_function() now sets strict flag, so\n\t\t\t * assert for it.\n\t\t\t */\n\t\t\tDUK_ASSERT(DUK_HOBJECT_HAS_STRICT(h));\n\n\t\t\t/* XXX: function properties */\n\n\t\t\tduk__push_stridx_or_string(thr, bd);\n#if defined(DUK_USE_FUNC_NAME_PROPERTY)\n\t\t\tduk_xdef_prop_stridx_short(thr,\n\t\t\t                           -2,\n\t\t\t                           DUK_STRIDX_NAME,\n\t\t\t                           DUK_PROPDESC_FLAGS_C);\n#else\n\t\t\tduk_pop(thr);  /* Not very ideal but good enough for now. */\n#endif\n\n\t\t\t/* Almost all global level Function objects are constructable\n\t\t\t * but not all: Function.prototype is a non-constructable,\n\t\t\t * callable Function.\n\t\t\t */\n\t\t\tif (duk_bd_decode_flag(bd)) {\n\t\t\t\tDUK_ASSERT(DUK_HOBJECT_HAS_CONSTRUCTABLE(h));\n\t\t\t} else {\n\t\t\t\tDUK_HOBJECT_CLEAR_CONSTRUCTABLE(h);\n\t\t\t}\n\n\t\t\t/* Cast converts magic to 16-bit signed value */\n\t\t\tmagic = (duk_int16_t) duk_bd_decode_varuint(bd);\n\t\t\t((duk_hnatfunc *) h)->magic = magic;\n\t\t} else if (class_num == DUK_HOBJECT_CLASS_ARRAY) {\n\t\t\tduk_push_array(thr);\n\t\t} else if (class_num == DUK_HOBJECT_CLASS_OBJENV) {\n\t\t\tduk_hobjenv *env;\n\t\t\tduk_hobject *global;\n\n\t\t\tDUK_ASSERT(i == DUK_BIDX_GLOBAL_ENV);\n\t\t\tDUK_ASSERT(DUK_BIDX_GLOBAL_ENV > DUK_BIDX_GLOBAL);\n\n\t\t\tenv = duk_hobjenv_alloc(thr,\n\t                                        DUK_HOBJECT_FLAG_EXTENSIBLE |\n\t                                        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJENV));\n\t\t\tDUK_ASSERT(env->target == NULL);\n\t\t\tduk_push_hobject(thr, (duk_hobject *) env);\n\n\t\t\tglobal = duk_known_hobject(thr, DUK_BIDX_GLOBAL);\n\t\t\tDUK_ASSERT(global != NULL);\n\t\t\tenv->target = global;\n\t\t\tDUK_HOBJECT_INCREF(thr, global);\n\t\t\tDUK_ASSERT(env->has_this == 0);\n\n\t\t\tDUK_ASSERT_HOBJENV_VALID(env);\n\t\t} else {\n\t\t\tDUK_ASSERT(class_num != DUK_HOBJECT_CLASS_DECENV);\n\n\t\t\t(void) duk_push_object_helper(thr,\n\t\t\t                              DUK_HOBJECT_FLAG_FASTREFS |\n\t\t\t                              DUK_HOBJECT_FLAG_EXTENSIBLE,\n\t\t\t                              -1);  /* no prototype or class yet */\n\n\t\t}\n\n\t\th = duk_known_hobject(thr, -1);\n\t\tDUK_HOBJECT_SET_CLASS_NUMBER(h, class_num);\n\n\t\tif (i < DUK_NUM_BUILTINS) {\n\t\t\tthr->builtins[i] = h;\n\t\t\tDUK_HOBJECT_INCREF(thr, &h->hdr);\n\t\t}\n\n\t\tif (len >= 0) {\n\t\t\t/* In ES2015+ built-in function object .length property\n\t\t\t * has property attributes C (configurable only):\n\t\t\t * http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-standard-built-in-objects\n\t\t\t *\n\t\t\t * Array.prototype remains an Array instance in ES2015+\n\t\t\t * and its length has attributes W (writable only).\n\t\t\t * Because .length is now virtual for duk_harray, it is\n\t\t\t * not encoded explicitly in init data.\n\t\t\t */\n\n\t\t\tDUK_ASSERT(class_num != DUK_HOBJECT_CLASS_ARRAY);  /* .length is virtual */\n\t\t\tduk_push_int(thr, len);\n\t\t\tduk_xdef_prop_stridx_short(thr,\n\t\t\t                           -2,\n\t\t\t                           DUK_STRIDX_LENGTH,\n\t\t\t                           DUK_PROPDESC_FLAGS_C);\n\t\t}\n\n\t\t/* enable exotic behaviors last */\n\n\t\tif (class_num == DUK_HOBJECT_CLASS_ARRAY) {\n\t\t\tDUK_ASSERT(DUK_HOBJECT_HAS_EXOTIC_ARRAY(h));  /* set by duk_push_array() */\n\t\t}\n\t\tif (class_num == DUK_HOBJECT_CLASS_STRING) {\n\t\t\tDUK_HOBJECT_SET_EXOTIC_STRINGOBJ(h);\n\t\t}\n\n\t\t/* some assertions */\n\n\t\tDUK_ASSERT(DUK_HOBJECT_HAS_EXTENSIBLE(h));\n\t\t/* DUK_HOBJECT_FLAG_CONSTRUCTABLE varies */\n\t\tDUK_ASSERT(!DUK_HOBJECT_HAS_BOUNDFUNC(h));\n\t\tDUK_ASSERT(!DUK_HOBJECT_HAS_COMPFUNC(h));\n\t\t/* DUK_HOBJECT_FLAG_NATFUNC varies */\n\t\tDUK_ASSERT(!DUK_HOBJECT_IS_THREAD(h));\n\t\tDUK_ASSERT(!DUK_HOBJECT_HAS_ARRAY_PART(h) || class_num == DUK_HOBJECT_CLASS_ARRAY);\n\t\t/* DUK_HOBJECT_FLAG_STRICT varies */\n\t\tDUK_ASSERT(!DUK_HOBJECT_HAS_NATFUNC(h) ||  /* all native functions have NEWENV */\n\t\t           DUK_HOBJECT_HAS_NEWENV(h));\n\t\tDUK_ASSERT(!DUK_HOBJECT_HAS_NAMEBINDING(h));\n\t\tDUK_ASSERT(!DUK_HOBJECT_HAS_CREATEARGS(h));\n\t\t/* DUK_HOBJECT_FLAG_EXOTIC_ARRAY varies */\n\t\t/* DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ varies */\n\t\tDUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(h));\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"created built-in %ld, class=%ld, length=%ld\", (long) i, (long) class_num, (long) len));\n\t}\n\n\t/*\n\t *  Then decode the builtins init data (see genbuiltins.py) to\n\t *  init objects.  Internal prototypes are set at this stage,\n\t *  with thr->builtins[] populated.\n\t */\n\n\tDUK_DD(DUK_DDPRINT(\"initialize built-in object properties\"));\n\tfor (i = 0; i < DUK_NUM_ALL_BUILTINS; i++) {\n\t\tduk_small_uint_t t;\n\t\tduk_small_uint_t num;\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"initializing built-in object at index %ld\", (long) i));\n\t\th = duk_known_hobject(thr, (duk_idx_t) i);\n\n\t\tt = (duk_small_uint_t) duk_bd_decode_varuint(bd);\n\t\tif (t > 0) {\n\t\t\tt--;\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"set internal prototype: built-in %ld\", (long) t));\n\t\t\tDUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, h, duk_known_hobject(thr, (duk_idx_t) t));\n\t\t} else if (DUK_HOBJECT_IS_NATFUNC(h)) {\n\t\t\t/* Standard native built-ins cannot inherit from\n\t\t\t * %NativeFunctionPrototype%, they are required to\n\t\t\t * inherit from Function.prototype directly.\n\t\t\t */\n\t\t\tDUK_ASSERT(thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE] != NULL);\n\t\t\tDUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, h, thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]);\n\t\t}\n\n\t\tt = (duk_small_uint_t) duk_bd_decode_varuint(bd);\n\t\tif (t > 0) {\n\t\t\t/* 'prototype' property for all built-in objects (which have it) has attributes:\n\t\t\t *  [[Writable]] = false,\n\t\t\t *  [[Enumerable]] = false,\n\t\t\t *  [[Configurable]] = false\n\t\t\t */\n\t\t\tt--;\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"set external prototype: built-in %ld\", (long) t));\n\t\t\tduk_dup(thr, (duk_idx_t) t);\n\t\t\tduk_xdef_prop_stridx(thr, (duk_idx_t) i, DUK_STRIDX_PROTOTYPE, DUK_PROPDESC_FLAGS_NONE);\n\t\t}\n\n\t\tt = (duk_small_uint_t) duk_bd_decode_varuint(bd);\n\t\tif (t > 0) {\n\t\t\t/* 'constructor' property for all built-in objects (which have it) has attributes:\n\t\t\t *  [[Writable]] = true,\n\t\t\t *  [[Enumerable]] = false,\n\t\t\t *  [[Configurable]] = true\n\t\t\t */\n\t\t\tt--;\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"set external constructor: built-in %ld\", (long) t));\n\t\t\tduk_dup(thr, (duk_idx_t) t);\n\t\t\tduk_xdef_prop_stridx(thr, (duk_idx_t) i, DUK_STRIDX_CONSTRUCTOR, DUK_PROPDESC_FLAGS_WC);\n\t\t}\n\n\t\t/* normal valued properties */\n\t\tnum = (duk_small_uint_t) duk_bd_decode_varuint(bd);\n\t\tDUK_DDD(DUK_DDDPRINT(\"built-in object %ld, %ld normal valued properties\", (long) i, (long) num));\n\t\tfor (j = 0; j < num; j++) {\n\t\t\tduk_small_uint_t defprop_flags;\n\n\t\t\tduk__push_stridx_or_string(thr, bd);\n\n\t\t\t/*\n\t\t\t *  Property attribute defaults are defined in E5 Section 15 (first\n\t\t\t *  few pages); there is a default for all properties and a special\n\t\t\t *  default for 'length' properties.  Variation from the defaults is\n\t\t\t *  signaled using a single flag bit in the bitstream.\n\t\t\t */\n\n\t\t\tif (duk_bd_decode_flag(bd)) {\n\t\t\t\tdefprop_flags = (duk_small_uint_t) duk_bd_decode(bd, DUK__PROP_FLAGS_BITS);\n\t\t\t} else {\n\t\t\t\tdefprop_flags = DUK_PROPDESC_FLAGS_WC;\n\t\t\t}\n\t\t\tdefprop_flags |= DUK_DEFPROP_FORCE |\n\t\t\t                 DUK_DEFPROP_HAVE_VALUE |\n\t\t\t                 DUK_DEFPROP_HAVE_WRITABLE |\n\t\t\t                 DUK_DEFPROP_HAVE_ENUMERABLE |\n\t\t\t                 DUK_DEFPROP_HAVE_CONFIGURABLE;  /* Defaults for data properties. */\n\n\t\t\t/* The writable, enumerable, configurable flags in prop_flags\n\t\t\t * match both duk_def_prop() and internal property flags.\n\t\t\t */\n\t\t\tDUK_ASSERT(DUK_PROPDESC_FLAG_WRITABLE == DUK_DEFPROP_WRITABLE);\n\t\t\tDUK_ASSERT(DUK_PROPDESC_FLAG_ENUMERABLE == DUK_DEFPROP_ENUMERABLE);\n\t\t\tDUK_ASSERT(DUK_PROPDESC_FLAG_CONFIGURABLE == DUK_DEFPROP_CONFIGURABLE);\n\n\t\t\tt = (duk_small_uint_t) duk_bd_decode(bd, DUK__PROP_TYPE_BITS);\n\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"built-in %ld, normal-valued property %ld, key %!T, flags 0x%02lx, type %ld\",\n\t\t\t                     (long) i, (long) j, duk_get_tval(thr, -1), (unsigned long) defprop_flags, (long) t));\n\n\t\t\tswitch (t) {\n\t\t\tcase DUK__PROP_TYPE_DOUBLE: {\n\t\t\t\tduk__push_double(thr, bd);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase DUK__PROP_TYPE_STRING: {\n\t\t\t\tduk__push_string(thr, bd);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase DUK__PROP_TYPE_STRIDX: {\n\t\t\t\tduk__push_stridx(thr, bd);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase DUK__PROP_TYPE_BUILTIN: {\n\t\t\t\tduk_small_uint_t bidx;\n\n\t\t\t\tbidx = (duk_small_uint_t) duk_bd_decode_varuint(bd);\n\t\t\t\tduk_dup(thr, (duk_idx_t) bidx);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase DUK__PROP_TYPE_UNDEFINED: {\n\t\t\t\tduk_push_undefined(thr);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase DUK__PROP_TYPE_BOOLEAN_TRUE: {\n\t\t\t\tduk_push_true(thr);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase DUK__PROP_TYPE_BOOLEAN_FALSE: {\n\t\t\t\tduk_push_false(thr);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase DUK__PROP_TYPE_ACCESSOR: {\n\t\t\t\tduk_small_uint_t natidx_getter = (duk_small_uint_t) duk_bd_decode_varuint(bd);\n\t\t\t\tduk_small_uint_t natidx_setter = (duk_small_uint_t) duk_bd_decode_varuint(bd);\n\t\t\t\tduk_small_uint_t accessor_magic = (duk_small_uint_t) duk_bd_decode_varuint(bd);\n\t\t\t\tduk_c_function c_func_getter;\n\t\t\t\tduk_c_function c_func_setter;\n\n\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"built-in accessor property: objidx=%ld, key=%!T, getteridx=%ld, setteridx=%ld, flags=0x%04lx\",\n\t\t\t\t                     (long) i, duk_get_tval(thr, -1), (long) natidx_getter, (long) natidx_setter, (unsigned long) defprop_flags));\n\n\t\t\t\tc_func_getter = duk_bi_native_functions[natidx_getter];\n\t\t\t\tif (c_func_getter != NULL) {\n\t\t\t\t\tduk_push_c_function_builtin_noconstruct(thr, c_func_getter, 0);  /* always 0 args */\n\t\t\t\t\tduk_set_magic(thr, -1, (duk_int_t) accessor_magic);\n\t\t\t\t\tdefprop_flags |= DUK_DEFPROP_HAVE_GETTER;\n\t\t\t\t}\n\t\t\t\tc_func_setter = duk_bi_native_functions[natidx_setter];\n\t\t\t\tif (c_func_setter != NULL) {\n\t\t\t\t\tduk_push_c_function_builtin_noconstruct(thr, c_func_setter, 1);  /* always 1 arg */\n\t\t\t\t\tduk_set_magic(thr, -1, (duk_int_t) accessor_magic);\n\t\t\t\t\tdefprop_flags |= DUK_DEFPROP_HAVE_SETTER;\n\t\t\t\t}\n\n\t\t\t\t/* Writable flag doesn't make sense for an accessor. */\n\t\t\t\tDUK_ASSERT((defprop_flags & DUK_PROPDESC_FLAG_WRITABLE) == 0);  /* genbuiltins.py ensures */\n\n\t\t\t\tdefprop_flags &= ~(DUK_DEFPROP_HAVE_VALUE | DUK_DEFPROP_HAVE_WRITABLE);\n\t\t\t\tdefprop_flags |= DUK_DEFPROP_HAVE_ENUMERABLE | DUK_DEFPROP_HAVE_CONFIGURABLE;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tdefault: {\n\t\t\t\t/* exhaustive */\n\t\t\t\tDUK_UNREACHABLE();\n\t\t\t}\n\t\t\t}\n\n\t\t\tduk_def_prop(thr, (duk_idx_t) i, defprop_flags);\n\t\t\tDUK_ASSERT_TOP(thr, DUK_NUM_ALL_BUILTINS);\n\t\t}\n\n\t\t/* native function properties */\n\t\tnum = (duk_small_uint_t) duk_bd_decode_varuint(bd);\n\t\tDUK_DDD(DUK_DDDPRINT(\"built-in object %ld, %ld function valued properties\", (long) i, (long) num));\n\t\tfor (j = 0; j < num; j++) {\n\t\t\tduk_hstring *h_key;\n\t\t\tduk_small_uint_t natidx;\n\t\t\tduk_int_t c_nargs;  /* must hold DUK_VARARGS */\n\t\t\tduk_small_uint_t c_length;\n\t\t\tduk_int16_t magic;\n\t\t\tduk_c_function c_func;\n\t\t\tduk_hnatfunc *h_func;\n#if defined(DUK_USE_LIGHTFUNC_BUILTINS)\n\t\t\tduk_small_int_t lightfunc_eligible;\n#endif\n\n\t\t\tduk__push_stridx_or_string(thr, bd);\n\t\t\th_key = duk_known_hstring(thr, -1);\n\t\t\tDUK_UNREF(h_key);\n\t\t\tnatidx = (duk_small_uint_t) duk_bd_decode_varuint(bd);\n\n\t\t\tc_length = (duk_small_uint_t) duk_bd_decode(bd, DUK__LENGTH_PROP_BITS);\n\t\t\tc_nargs = (duk_int_t) duk_bd_decode_flagged(bd, DUK__NARGS_BITS, (duk_uint32_t) c_length /*def_value*/);\n\t\t\tif (c_nargs == DUK__NARGS_VARARGS_MARKER) {\n\t\t\t\tc_nargs = DUK_VARARGS;\n\t\t\t}\n\n\t\t\tc_func = duk_bi_native_functions[natidx];\n\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"built-in %ld, function-valued property %ld, key %!O, natidx %ld, length %ld, nargs %ld\",\n\t\t\t                     (long) i, (long) j, (duk_heaphdr *) h_key, (long) natidx, (long) c_length,\n\t\t\t                     (c_nargs == DUK_VARARGS ? (long) -1 : (long) c_nargs)));\n\n\t\t\t/* Cast converts magic to 16-bit signed value */\n\t\t\tmagic = (duk_int16_t) duk_bd_decode_varuint(bd);\n\n#if defined(DUK_USE_LIGHTFUNC_BUILTINS)\n\t\t\tlightfunc_eligible =\n\t\t\t\t((c_nargs >= DUK_LFUNC_NARGS_MIN && c_nargs <= DUK_LFUNC_NARGS_MAX) || (c_nargs == DUK_VARARGS)) &&\n\t\t\t\t(c_length <= DUK_LFUNC_LENGTH_MAX) &&\n\t\t\t\t(magic >= DUK_LFUNC_MAGIC_MIN && magic <= DUK_LFUNC_MAGIC_MAX);\n\n\t\t\t/* These functions have trouble working as lightfuncs.\n\t\t\t * Some of them have specific asserts and some may have\n\t\t         * additional properties (e.g. 'require.id' may be written).\n\t\t\t */\n\t\t\tif (c_func == duk_bi_global_object_eval) {\n\t\t\t\tlightfunc_eligible = 0;\n\t\t\t}\n#if defined(DUK_USE_COROUTINE_SUPPORT)\n\t\t\tif (c_func == duk_bi_thread_yield ||\n\t\t\t    c_func == duk_bi_thread_resume) {\n\t\t\t\tlightfunc_eligible = 0;\n\t\t\t}\n#endif\n\t\t\tif (c_func == duk_bi_function_prototype_call ||\n\t\t\t    c_func == duk_bi_function_prototype_apply ||\n\t\t\t    c_func == duk_bi_reflect_apply ||\n\t\t\t    c_func == duk_bi_reflect_construct) {\n\t\t\t\tlightfunc_eligible = 0;\n\t\t\t}\n\n\t\t\tif (lightfunc_eligible) {\n\t\t\t\tduk_tval tv_lfunc;\n\t\t\t\tduk_small_uint_t lf_nargs = (duk_small_uint_t) (c_nargs == DUK_VARARGS ? DUK_LFUNC_NARGS_VARARGS : c_nargs);\n\t\t\t\tduk_small_uint_t lf_flags = DUK_LFUNC_FLAGS_PACK(magic, c_length, lf_nargs);\n\t\t\t\tDUK_TVAL_SET_LIGHTFUNC(&tv_lfunc, c_func, lf_flags);\n\t\t\t\tduk_push_tval(thr, &tv_lfunc);\n\t\t\t\tDUK_D(DUK_DPRINT(\"built-in function eligible as light function: i=%d, j=%d c_length=%ld, c_nargs=%ld, magic=%ld -> %!iT\", (int) i, (int) j, (long) c_length, (long) c_nargs, (long) magic, duk_get_tval(thr, -1)));\n\t\t\t\tgoto lightfunc_skip;\n\t\t\t}\n\n\t\t\tDUK_D(DUK_DPRINT(\"built-in function NOT ELIGIBLE as light function: i=%d, j=%d c_length=%ld, c_nargs=%ld, magic=%ld\", (int) i, (int) j, (long) c_length, (long) c_nargs, (long) magic));\n#endif  /* DUK_USE_LIGHTFUNC_BUILTINS */\n\n\t\t\t/* [ (builtin objects) name ] */\n\n\t\t\tduk_push_c_function_builtin_noconstruct(thr, c_func, c_nargs);\n\t\t\th_func = duk_known_hnatfunc(thr, -1);\n\t\t\tDUK_UNREF(h_func);\n\n\t\t\t/* XXX: add into init data? */\n\n\t\t\t/* Special call handling, not described in init data. */\n\t\t\tif (c_func == duk_bi_global_object_eval ||\n\t\t\t    c_func == duk_bi_function_prototype_call ||\n\t\t\t    c_func == duk_bi_function_prototype_apply ||\n\t\t\t    c_func == duk_bi_reflect_apply ||\n\t\t\t    c_func == duk_bi_reflect_construct) {\n\t\t\t\tDUK_HOBJECT_SET_SPECIAL_CALL((duk_hobject *) h_func);\n\t\t\t}\n\n\t\t\t/* Currently all built-in native functions are strict.\n\t\t\t * This doesn't matter for many functions, but e.g.\n\t\t\t * String.prototype.charAt (and other string functions)\n\t\t\t * rely on being strict so that their 'this' binding is\n\t\t\t * not automatically coerced.\n\t\t\t */\n\t\t\tDUK_HOBJECT_SET_STRICT((duk_hobject *) h_func);\n\n\t\t\t/* No built-in functions are constructable except the top\n\t\t\t * level ones (Number, etc).\n\t\t\t */\n\t\t\tDUK_ASSERT(!DUK_HOBJECT_HAS_CONSTRUCTABLE((duk_hobject *) h_func));\n\n\t\t\t/* XXX: any way to avoid decoding magic bit; there are quite\n\t\t\t * many function properties and relatively few with magic values.\n\t\t\t */\n\t\t\th_func->magic = magic;\n\n\t\t\t/* [ (builtin objects) name func ] */\n\n\t\t\tduk_push_uint(thr, c_length);\n\t\t\tduk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_C);\n\n\t\t\tduk_dup_m2(thr);\n\t\t\tduk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_NAME, DUK_PROPDESC_FLAGS_C);\n\n\t\t\t/* XXX: other properties of function instances; 'arguments', 'caller'. */\n\n\t\t\tDUK_DD(DUK_DDPRINT(\"built-in object %ld, function property %ld -> %!T\",\n\t\t\t                   (long) i, (long) j, (duk_tval *) duk_get_tval(thr, -1)));\n\n\t\t\t/* [ (builtin objects) name func ] */\n\n\t\t\t/*\n\t\t\t *  The default property attributes are correct for all\n\t\t\t *  function valued properties of built-in objects now.\n\t\t\t */\n\n#if defined(DUK_USE_LIGHTFUNC_BUILTINS)\n\t\t lightfunc_skip:\n#endif\n\n\t\t\t/* XXX: So far all ES builtins are 'wc' but e.g.\n\t\t\t * performance.now() should be 'wec'.\n\t\t\t */\n\t\t\tduk_xdef_prop(thr, (duk_idx_t) i, DUK_PROPDESC_FLAGS_WC);\n\n\t\t\t/* [ (builtin objects) ] */\n\t\t}\n\t}\n\n\t/*\n\t *  Special post-tweaks, for cases not covered by the init data format.\n\t *\n\t *  - Set Date.prototype.toGMTString to Date.prototype.toUTCString.\n\t *    toGMTString is required to have the same Function object as\n\t *    toUTCString in E5 Section B.2.6.  Note that while Smjs respects\n\t *    this, V8 does not (the Function objects are distinct).\n\t *\n\t *  - Make DoubleError non-extensible.\n\t *\n\t *  - Add info about most important effective compile options to Duktape.\n\t *\n\t *  - Possibly remove some properties (values or methods) which are not\n\t *    desirable with current feature options but are not currently\n\t *    conditional in init data.\n\t */\n\n#if defined(DUK_USE_DATE_BUILTIN)\n\tduk_get_prop_stridx_short(thr, DUK_BIDX_DATE_PROTOTYPE, DUK_STRIDX_TO_UTC_STRING);\n\tduk_xdef_prop_stridx_short(thr, DUK_BIDX_DATE_PROTOTYPE, DUK_STRIDX_TO_GMT_STRING, DUK_PROPDESC_FLAGS_WC);\n#endif\n\n\th = duk_known_hobject(thr, DUK_BIDX_DOUBLE_ERROR);\n\tDUK_HOBJECT_CLEAR_EXTENSIBLE(h);\n\n#if !defined(DUK_USE_ES6_OBJECT_PROTO_PROPERTY)\n\tDUK_DD(DUK_DDPRINT(\"delete Object.prototype.__proto__ built-in which is not enabled in features\"));\n\t(void) duk_hobject_delprop_raw(thr, thr->builtins[DUK_BIDX_OBJECT_PROTOTYPE], DUK_HTHREAD_STRING___PROTO__(thr), DUK_DELPROP_FLAG_THROW);\n#endif\n\n#if !defined(DUK_USE_ES6_OBJECT_SETPROTOTYPEOF)\n\tDUK_DD(DUK_DDPRINT(\"delete Object.setPrototypeOf built-in which is not enabled in features\"));\n\t(void) duk_hobject_delprop_raw(thr, thr->builtins[DUK_BIDX_OBJECT_CONSTRUCTOR], DUK_HTHREAD_STRING_SET_PROTOTYPE_OF(thr), DUK_DELPROP_FLAG_THROW);\n#endif\n\n\t/* XXX: relocate */\n\tduk_push_string(thr,\n\t\t\t/* Endianness indicator */\n#if defined(DUK_USE_INTEGER_LE)\n\t                \"l\"\n#elif defined(DUK_USE_INTEGER_BE)\n\t                \"b\"\n#elif defined(DUK_USE_INTEGER_ME)  /* integer mixed endian not really used now */\n\t                \"m\"\n#else\n\t                \"?\"\n#endif\n#if defined(DUK_USE_DOUBLE_LE)\n\t                \"l\"\n#elif defined(DUK_USE_DOUBLE_BE)\n\t                \"b\"\n#elif defined(DUK_USE_DOUBLE_ME)\n\t                \"m\"\n#else\n\t                \"?\"\n#endif\n\t                \" \"\n\t\t\t/* Packed or unpacked tval */\n#if defined(DUK_USE_PACKED_TVAL)\n\t                \"p\"\n#else\n\t                \"u\"\n#endif\n#if defined(DUK_USE_FASTINT)\n\t\t\t\"f\"\n#endif\n\t\t\t\" \"\n\t\t\t/* Low memory options */\n#if defined(DUK_USE_STRTAB_PTRCOMP)\n\t\t\t\"s\"\n#endif\n#if !defined(DUK_USE_HEAPPTR16) && !defined(DUK_DATAPTR16) && !defined(DUK_FUNCPTR16)\n\t\t\t\"n\"\n#endif\n#if defined(DUK_USE_HEAPPTR16)\n\t\t\t\"h\"\n#endif\n#if defined(DUK_USE_DATAPTR16)\n\t\t\t\"d\"\n#endif\n#if defined(DUK_USE_FUNCPTR16)\n\t\t\t\"f\"\n#endif\n#if defined(DUK_USE_REFCOUNT16)\n\t\t\t\"R\"\n#endif\n#if defined(DUK_USE_STRHASH16)\n\t\t\t\"H\"\n#endif\n#if defined(DUK_USE_STRLEN16)\n\t\t\t\"S\"\n#endif\n#if defined(DUK_USE_BUFLEN16)\n\t\t\t\"B\"\n#endif\n#if defined(DUK_USE_OBJSIZES16)\n\t\t\t\"O\"\n#endif\n#if defined(DUK_USE_LIGHTFUNC_BUILTINS)\n\t\t\t\"L\"\n#endif\n#if defined(DUK_USE_ROM_STRINGS) || defined(DUK_USE_ROM_OBJECTS)\n\t\t\t/* XXX: This won't be shown in practice now\n\t\t\t * because this code is not run when builtins\n\t\t\t * are in ROM.\n\t\t\t */\n\t\t\t\"Z\"\n#endif\n\t                \" \"\n\t\t\t/* Object property allocation layout */\n#if defined(DUK_USE_HOBJECT_LAYOUT_1)\n\t\t\t\"p1\"\n#elif defined(DUK_USE_HOBJECT_LAYOUT_2)\n\t\t\t\"p2\"\n#elif defined(DUK_USE_HOBJECT_LAYOUT_3)\n\t\t\t\"p3\"\n#else\n\t\t\t\"p?\"\n#endif\n\t\t\t\" \"\n\t\t\t/* Alignment guarantee */\n#if (DUK_USE_ALIGN_BY == 4)\n\t\t\t\"a4\"\n#elif (DUK_USE_ALIGN_BY == 8)\n\t\t\t\"a8\"\n#elif (DUK_USE_ALIGN_BY == 1)\n\t\t\t\"a1\"\n#else\n#error invalid DUK_USE_ALIGN_BY\n#endif\n\t\t\t\" \"\n\t\t\t/* Architecture, OS, and compiler strings */\n\t                DUK_USE_ARCH_STRING\n\t\t\t\" \"\n\t                DUK_USE_OS_STRING\n\t\t\t\" \"\n\t                DUK_USE_COMPILER_STRING);\n\tduk_xdef_prop_stridx_short(thr, DUK_BIDX_DUKTAPE, DUK_STRIDX_ENV, DUK_PROPDESC_FLAGS_WC);\n\n\t/*\n\t *  Since built-ins are not often extended, compact them.\n\t */\n\n\tDUK_DD(DUK_DDPRINT(\"compact built-ins\"));\n\tfor (i = 0; i < DUK_NUM_ALL_BUILTINS; i++) {\n\t\tduk_hobject_compact_props(thr, duk_known_hobject(thr, (duk_idx_t) i));\n\t}\n\n\tDUK_D(DUK_DPRINT(\"INITBUILTINS END\"));\n\n#if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 1)\n\tfor (i = 0; i < DUK_NUM_ALL_BUILTINS; i++) {\n\t\tDUK_DD(DUK_DDPRINT(\"built-in object %ld after initialization and compacting: %!@iO\",\n\t\t                   (long) i, (duk_heaphdr *) duk_require_hobject(thr, i)));\n\t}\n#endif\n\n\t/*\n\t *  Pop built-ins from stack: they are now INCREF'd and\n\t *  reachable from the builtins[] array or indirectly\n\t *  through builtins[].\n\t */\n\n\tduk_set_top(thr, 0);\n\tDUK_ASSERT_TOP(thr, 0);\n}\n#endif  /* DUK_USE_ROM_OBJECTS */\n\nDUK_INTERNAL void duk_hthread_copy_builtin_objects(duk_hthread *thr_from, duk_hthread *thr_to) {\n\tduk_small_uint_t i;\n\n\tfor (i = 0; i < DUK_NUM_BUILTINS; i++) {\n\t\tthr_to->builtins[i] = thr_from->builtins[i];\n\t\tDUK_HOBJECT_INCREF_ALLOWNULL(thr_to, thr_to->builtins[i]);  /* side effect free */\n\t}\n}\n\n/* automatic undefs */\n#undef DUK__LENGTH_PROP_BITS\n#undef DUK__NARGS_BITS\n#undef DUK__NARGS_VARARGS_MARKER\n#undef DUK__PROP_FLAGS_BITS\n#undef DUK__PROP_TYPE_ACCESSOR\n#undef DUK__PROP_TYPE_BITS\n#undef DUK__PROP_TYPE_BOOLEAN_FALSE\n#undef DUK__PROP_TYPE_BOOLEAN_TRUE\n#undef DUK__PROP_TYPE_BUILTIN\n#undef DUK__PROP_TYPE_DOUBLE\n#undef DUK__PROP_TYPE_STRIDX\n#undef DUK__PROP_TYPE_STRING\n#undef DUK__PROP_TYPE_UNDEFINED\n#line 1 \"duk_hthread_misc.c\"\n/*\n *  Thread support.\n */\n\n/* #include duk_internal.h -> already included */\n\nDUK_INTERNAL void duk_hthread_terminate(duk_hthread *thr) {\n\tDUK_ASSERT(thr != NULL);\n\n\twhile (thr->callstack_curr != NULL) {\n\t\tduk_hthread_activation_unwind_norz(thr);\n\t}\n\n\tthr->valstack_bottom = thr->valstack;\n\tduk_set_top(thr, 0);  /* unwinds valstack, updating refcounts */\n\n\tthr->state = DUK_HTHREAD_STATE_TERMINATED;\n\n\t/* Here we could remove references to built-ins, but it may not be\n\t * worth the effort because built-ins are quite likely to be shared\n\t * with another (unterminated) thread, and terminated threads are also\n\t * usually garbage collected quite quickly.\n\t *\n\t * We could also shrink the value stack here, but that also may not\n\t * be worth the effort for the same reason.\n\t */\n\n\tDUK_REFZERO_CHECK_SLOW(thr);\n}\n\n#if defined(DUK_USE_DEBUGGER_SUPPORT)\nDUK_INTERNAL duk_uint_fast32_t duk_hthread_get_act_curr_pc(duk_hthread *thr, duk_activation *act) {\n\tduk_instr_t *bcode;\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(act != NULL);\n\tDUK_UNREF(thr);\n\n\t/* XXX: store 'bcode' pointer to activation for faster lookup? */\n\tif (act->func && DUK_HOBJECT_IS_COMPFUNC(act->func)) {\n\t\tbcode = DUK_HCOMPFUNC_GET_CODE_BASE(thr->heap, (duk_hcompfunc *) (act->func));\n\t\treturn (duk_uint_fast32_t) (act->curr_pc - bcode);\n\t}\n\treturn 0;\n}\n#endif  /* DUK_USE_DEBUGGER_SUPPORT */\n\nDUK_INTERNAL duk_uint_fast32_t duk_hthread_get_act_prev_pc(duk_hthread *thr, duk_activation *act) {\n\tduk_instr_t *bcode;\n\tduk_uint_fast32_t ret;\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(act != NULL);\n\tDUK_UNREF(thr);\n\n\tif (act->func && DUK_HOBJECT_IS_COMPFUNC(act->func)) {\n\t\tbcode = DUK_HCOMPFUNC_GET_CODE_BASE(thr->heap, (duk_hcompfunc *) (act->func));\n\t\tret = (duk_uint_fast32_t) (act->curr_pc - bcode);\n\t\tif (ret > 0) {\n\t\t\tret--;\n\t\t}\n\t\treturn ret;\n\t}\n\treturn 0;\n}\n\n/* Write bytecode executor's curr_pc back to topmost activation (if any). */\nDUK_INTERNAL void duk_hthread_sync_currpc(duk_hthread *thr) {\n\tduk_activation *act;\n\n\tDUK_ASSERT(thr != NULL);\n\n\tif (thr->ptr_curr_pc != NULL) {\n\t\t/* ptr_curr_pc != NULL only when bytecode executor is active. */\n\t\tDUK_ASSERT(thr->callstack_top > 0);\n\t\tDUK_ASSERT(thr->callstack_curr != NULL);\n\t\tact = thr->callstack_curr;\n\t\tDUK_ASSERT(act != NULL);\n\t\tact->curr_pc = *thr->ptr_curr_pc;\n\t}\n}\n\nDUK_INTERNAL void duk_hthread_sync_and_null_currpc(duk_hthread *thr) {\n\tduk_activation *act;\n\n\tDUK_ASSERT(thr != NULL);\n\n\tif (thr->ptr_curr_pc != NULL) {\n\t\t/* ptr_curr_pc != NULL only when bytecode executor is active. */\n\t\tDUK_ASSERT(thr->callstack_top > 0);\n\t\tDUK_ASSERT(thr->callstack_curr != NULL);\n\t\tact = thr->callstack_curr;\n\t\tDUK_ASSERT(act != NULL);\n\t\tact->curr_pc = *thr->ptr_curr_pc;\n\t\tthr->ptr_curr_pc = NULL;\n\t}\n}\n#line 1 \"duk_hthread_stacks.c\"\n/*\n *  Thread stack (mainly call stack) primitives: allocation of activations,\n *  unwinding catchers and activations, etc.\n *\n *  Value stack handling is a part of the API implementation.\n */\n\n/* #include duk_internal.h -> already included */\n\n/* Unwind the topmost catcher of the current activation (caller must check that\n * both exist) without side effects.\n */\nDUK_INTERNAL void duk_hthread_catcher_unwind_norz(duk_hthread *thr, duk_activation *act) {\n\tduk_catcher *cat;\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(act != NULL);\n\tDUK_ASSERT(act->cat != NULL);  /* caller must check */\n\tcat = act->cat;\n\tDUK_ASSERT(cat != NULL);\n\n\tDUK_DDD(DUK_DDDPRINT(\"unwinding catch stack entry %p (lexenv check is done)\", (void *) cat));\n\n\tif (DUK_CAT_HAS_LEXENV_ACTIVE(cat)) {\n\t\tduk_hobject *env;\n\n\t\tenv = act->lex_env;             /* current lex_env of the activation (created for catcher) */\n\t\tDUK_ASSERT(env != NULL);        /* must be, since env was created when catcher was created */\n\t\tact->lex_env = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, env);  /* prototype is lex_env before catcher created */\n\t\tDUK_HOBJECT_INCREF(thr, act->lex_env);\n\t\tDUK_HOBJECT_DECREF_NORZ(thr, env);\n\n\t\t/* There is no need to decref anything else than 'env': if 'env'\n\t\t * becomes unreachable, refzero will handle decref'ing its prototype.\n\t\t */\n\t}\n\n\tact->cat = cat->parent;\n\tduk_hthread_catcher_free(thr, cat);\n}\n\n/* Same as above, but caller is certain no catcher-related lexenv may exist. */\nDUK_INTERNAL void duk_hthread_catcher_unwind_nolexenv_norz(duk_hthread *thr, duk_activation *act) {\n\tduk_catcher *cat;\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(act != NULL);\n\tDUK_ASSERT(act->cat != NULL);  /* caller must check */\n\tcat = act->cat;\n\tDUK_ASSERT(cat != NULL);\n\n\tDUK_DDD(DUK_DDDPRINT(\"unwinding catch stack entry %p (lexenv check is not done)\", (void *) cat));\n\n\tDUK_ASSERT(!DUK_CAT_HAS_LEXENV_ACTIVE(cat));\n\n\tact->cat = cat->parent;\n\tduk_hthread_catcher_free(thr, cat);\n}\n\nDUK_LOCAL\n#if defined(DUK_USE_CACHE_CATCHER)\nDUK_NOINLINE\n#endif\nduk_catcher *duk__hthread_catcher_alloc_slow(duk_hthread *thr) {\n\tduk_catcher *cat;\n\n\tcat = (duk_catcher *) DUK_ALLOC_CHECKED(thr, sizeof(duk_catcher));\n\tDUK_ASSERT(cat != NULL);\n\treturn cat;\n}\n\n#if defined(DUK_USE_CACHE_CATCHER)\nDUK_INTERNAL DUK_INLINE duk_catcher *duk_hthread_catcher_alloc(duk_hthread *thr) {\n\tduk_catcher *cat;\n\n\tDUK_ASSERT(thr != NULL);\n\n\tcat = thr->heap->catcher_free;\n\tif (DUK_LIKELY(cat != NULL)) {\n\t\tthr->heap->catcher_free = cat->parent;\n\t\treturn cat;\n\t}\n\n\treturn duk__hthread_catcher_alloc_slow(thr);\n}\n#else  /* DUK_USE_CACHE_CATCHER */\nDUK_INTERNAL duk_catcher *duk_hthread_catcher_alloc(duk_hthread *thr) {\n\treturn duk__hthread_catcher_alloc_slow(thr);\n}\n#endif  /* DUK_USE_CACHE_CATCHER */\n\nDUK_INTERNAL void duk_hthread_catcher_free(duk_hthread *thr, duk_catcher *cat) {\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(cat != NULL);\n\n#if defined(DUK_USE_CACHE_CATCHER)\n\t/* Unconditional caching for now; freed in mark-and-sweep. */\n\tcat->parent = thr->heap->catcher_free;\n\tthr->heap->catcher_free = cat;\n#else\n\tDUK_FREE_CHECKED(thr, (void *) cat);\n#endif\n}\n\nDUK_LOCAL\n#if defined(DUK_USE_CACHE_ACTIVATION)\nDUK_NOINLINE\n#endif\nduk_activation *duk__hthread_activation_alloc_slow(duk_hthread *thr) {\n\tduk_activation *act;\n\n\tact = (duk_activation *) DUK_ALLOC_CHECKED(thr, sizeof(duk_activation));\n\tDUK_ASSERT(act != NULL);\n\treturn act;\n}\n\n#if defined(DUK_USE_CACHE_ACTIVATION)\nDUK_INTERNAL DUK_INLINE duk_activation *duk_hthread_activation_alloc(duk_hthread *thr) {\n\tduk_activation *act;\n\n\tDUK_ASSERT(thr != NULL);\n\n\tact = thr->heap->activation_free;\n\tif (DUK_LIKELY(act != NULL)) {\n\t\tthr->heap->activation_free = act->parent;\n\t\treturn act;\n\t}\n\n\treturn duk__hthread_activation_alloc_slow(thr);\n}\n#else  /* DUK_USE_CACHE_ACTIVATION */\nDUK_INTERNAL duk_activation *duk_hthread_activation_alloc(duk_hthread *thr) {\n\treturn duk__hthread_activation_alloc_slow(thr);\n}\n#endif  /* DUK_USE_CACHE_ACTIVATION */\n\n\nDUK_INTERNAL void duk_hthread_activation_free(duk_hthread *thr, duk_activation *act) {\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(act != NULL);\n\n#if defined(DUK_USE_CACHE_ACTIVATION)\n\t/* Unconditional caching for now; freed in mark-and-sweep. */\n\tact->parent = thr->heap->activation_free;\n\tthr->heap->activation_free = act;\n#else\n\tDUK_FREE_CHECKED(thr, (void *) act);\n#endif\n}\n\n/* Internal helper: process the unwind for the topmost activation of a thread,\n * but leave the duk_activation in place for possible tailcall reuse.\n */\nDUK_LOCAL void duk__activation_unwind_nofree_norz(duk_hthread *thr) {\n#if defined(DUK_USE_DEBUGGER_SUPPORT)\n\tduk_heap *heap;\n#endif\n\tduk_activation *act;\n\tduk_hobject *func;\n\tduk_hobject *tmp;\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(thr->callstack_curr != NULL);  /* caller must check */\n\tDUK_ASSERT(thr->callstack_top > 0);\n\tact = thr->callstack_curr;\n\tDUK_ASSERT(act != NULL);\n\t/* With lightfuncs, act 'func' may be NULL. */\n\n\t/* With duk_activation records allocated separately, 'act' is a stable\n\t * pointer and not affected by side effects.\n\t */\n\n#if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)\n\t/*\n\t *  Restore 'caller' property for non-strict callee functions.\n\t */\n\n\tfunc = DUK_ACT_GET_FUNC(act);\n\tif (func != NULL && !DUK_HOBJECT_HAS_STRICT(func)) {\n\t\tduk_tval *tv_caller;\n\t\tduk_tval tv_tmp;\n\t\tduk_hobject *h_tmp;\n\n\t\ttv_caller = duk_hobject_find_existing_entry_tval_ptr(thr->heap, func, DUK_HTHREAD_STRING_CALLER(thr));\n\n\t\t/* The act->prev_caller should only be set if the entry for 'caller'\n\t\t * exists (as it is only set in that case, and the property is not\n\t\t * configurable), but handle all the cases anyway.\n\t\t */\n\n\t\tif (tv_caller) {\n\t\t\tDUK_TVAL_SET_TVAL(&tv_tmp, tv_caller);\n\t\t\tif (act->prev_caller) {\n\t\t\t\t/* Just transfer the refcount from act->prev_caller to tv_caller,\n\t\t\t\t * so no need for a refcount update.  This is the expected case.\n\t\t\t\t */\n\t\t\t\tDUK_TVAL_SET_OBJECT(tv_caller, act->prev_caller);\n\t\t\t\tact->prev_caller = NULL;\n\t\t\t} else {\n\t\t\t\tDUK_TVAL_SET_NULL(tv_caller);   /* no incref needed */\n\t\t\t\tDUK_ASSERT(act->prev_caller == NULL);\n\t\t\t}\n\t\t\tDUK_TVAL_DECREF_NORZ(thr, &tv_tmp);\n\t\t} else {\n\t\t\th_tmp = act->prev_caller;\n\t\t\tif (h_tmp) {\n\t\t\t\tact->prev_caller = NULL;\n\t\t\t\tDUK_HOBJECT_DECREF_NORZ(thr, h_tmp);\n\t\t\t}\n\t\t}\n\t\tDUK_ASSERT(act->prev_caller == NULL);\n\t}\n#endif\n\n\t/*\n\t *  Unwind debugger state.  If we unwind while stepping\n\t *  (for any step type), pause execution.  This is the\n\t *  only place explicitly handling a step out.\n\t */\n\n#if defined(DUK_USE_DEBUGGER_SUPPORT)\n\theap = thr->heap;\n\tif (heap->dbg_pause_act == thr->callstack_curr) {\n\t\tif (heap->dbg_pause_flags & DUK_PAUSE_FLAG_FUNC_EXIT) {\n\t\t\tDUK_D(DUK_DPRINT(\"PAUSE TRIGGERED by function exit\"));\n\t\t\tduk_debug_set_paused(heap);\n\t\t} else {\n\t\t\tDUK_D(DUK_DPRINT(\"unwound past dbg_pause_act, set to NULL\"));\n\t\t\theap->dbg_pause_act = NULL;  /* avoid stale pointers */\n\t\t}\n\t\tDUK_ASSERT(heap->dbg_pause_act == NULL);\n\t}\n#endif\n\n\t/*\n\t *  Unwind catchers.\n\t *\n\t *  Since there are no references in the catcher structure,\n\t *  unwinding is quite simple.  The only thing we need to\n\t *  look out for is popping a possible lexical environment\n\t *  established for an active catch clause.\n\t */\n\n\twhile (act->cat != NULL) {\n\t\tduk_hthread_catcher_unwind_norz(thr, act);\n\t}\n\n\t/*\n\t *  Close environment record(s) if they exist.\n\t *\n\t *  Only variable environments are closed.  If lex_env != var_env, it\n\t *  cannot currently contain any register bound declarations.\n\t *\n\t *  Only environments created for a NEWENV function are closed.  If an\n\t *  environment is created for e.g. an eval call, it must not be closed.\n\t */\n\n\tfunc = DUK_ACT_GET_FUNC(act);\n\tif (func != NULL && !DUK_HOBJECT_HAS_NEWENV(func)) {\n\t\tDUK_DDD(DUK_DDDPRINT(\"skip closing environments, envs not owned by this activation\"));\n\t\tgoto skip_env_close;\n\t}\n\t/* func is NULL for lightfunc */\n\n\t/* Catch sites are required to clean up their environments\n\t * in FINALLY part before propagating, so this should\n\t * always hold here.\n\t */\n\tDUK_ASSERT(act->lex_env == act->var_env);\n\n\t/* XXX: Closing the environment record copies values from registers\n\t * into the scope object.  It's side effect free as such, but may\n\t * currently run out of memory which causes an error throw.  This is\n\t * an actual sandboxing problem for error unwinds, and needs to be\n\t * fixed e.g. by preallocating the scope property slots.\n\t */\n\tif (act->var_env != NULL) {\n\t\tDUK_DDD(DUK_DDDPRINT(\"closing var_env record %p -> %!O\",\n\t\t                     (void *) act->var_env, (duk_heaphdr *) act->var_env));\n\t\tduk_js_close_environment_record(thr, act->var_env);\n\t}\n\n skip_env_close:\n\n\t/*\n\t *  Update preventcount\n\t */\n\n\tif (act->flags & DUK_ACT_FLAG_PREVENT_YIELD) {\n\t\tDUK_ASSERT(thr->callstack_preventcount >= 1);\n\t\tthr->callstack_preventcount--;\n\t}\n\n\t/*\n\t *  Reference count updates, using NORZ macros so we don't\n\t *  need to handle side effects.\n\t *\n\t *  duk_activation pointers like act->var_env are intentionally\n\t *  left as garbage and not NULLed.  Without side effects they\n\t *  can't be used when the values are dangling/garbage.\n\t */\n\n\tDUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, act->var_env);\n\tDUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, act->lex_env);\n\ttmp = DUK_ACT_GET_FUNC(act);\n\tDUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, tmp);\n\tDUK_UNREF(tmp);\n}\n\n/* Unwind topmost duk_activation of a thread, caller must ensure that an\n * activation exists.  The call is side effect free, except that scope\n * closure may currently throw an out-of-memory error.\n */\nDUK_INTERNAL void duk_hthread_activation_unwind_norz(duk_hthread *thr) {\n\tduk_activation *act;\n\n\tduk__activation_unwind_nofree_norz(thr);\n\n\tDUK_ASSERT(thr->callstack_curr != NULL);\n\tDUK_ASSERT(thr->callstack_top > 0);\n\tact = thr->callstack_curr;\n\tthr->callstack_curr = act->parent;\n\tthr->callstack_top--;\n\n\t/* Ideally we'd restore value stack reserve here to caller's value.\n\t * This doesn't work for current unwind call sites however, because\n\t * the current (unwound) value stack top may be above the reserve.\n\t * Thus value stack reserve is restored by the call sites.\n\t */\n\n\t/* XXX: inline for performance builds? */\n\tduk_hthread_activation_free(thr, act);\n\n\t/* We could clear the book-keeping variables like retval_byteoff for\n\t * the topmost activation, but don't do so now as it's not necessary.\n\t */\n}\n\nDUK_INTERNAL void duk_hthread_activation_unwind_reuse_norz(duk_hthread *thr) {\n\tduk__activation_unwind_nofree_norz(thr);\n}\n\n/* Get duk_activation for given callstack level or NULL if level is invalid\n * or deeper than the call stack.  Level -1 refers to current activation, -2\n * to its caller, etc.  Starting from Duktape 2.2 finding the activation is\n * a linked list scan which gets more expensive the deeper the lookup is.\n */\nDUK_INTERNAL duk_activation *duk_hthread_get_activation_for_level(duk_hthread *thr, duk_int_t level) {\n\tduk_activation *act;\n\n\tif (level >= 0) {\n\t\treturn NULL;\n\t}\n\tact = thr->callstack_curr;\n\tfor (;;) {\n\t\tif (act == NULL) {\n\t\t\treturn act;\n\t\t}\n\t\tif (level == -1) {\n\t\t\treturn act;\n\t\t}\n\t\tlevel++;\n\t\tact = act->parent;\n\t}\n\t/* never here */\n}\n\n#if defined(DUK_USE_FINALIZER_TORTURE)\nDUK_INTERNAL void duk_hthread_valstack_torture_realloc(duk_hthread *thr) {\n\tduk_size_t alloc_size;\n\tduk_tval *new_ptr;\n\tduk_ptrdiff_t alloc_end_off;\n\tduk_ptrdiff_t end_off;\n\tduk_ptrdiff_t bottom_off;\n\tduk_ptrdiff_t top_off;\n\n\tif (thr->valstack == NULL) {\n\t\tDUK_D(DUK_DPRINT(\"skip valstack torture realloc, valstack is NULL\"));\n\t\treturn;\n\t}\n\n\talloc_end_off = (duk_ptrdiff_t) ((duk_uint8_t *) thr->valstack_alloc_end - (duk_uint8_t *) thr->valstack);\n\tend_off = (duk_ptrdiff_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack);\n\tbottom_off = (duk_ptrdiff_t) ((duk_uint8_t *) thr->valstack_bottom - (duk_uint8_t *) thr->valstack);\n\ttop_off = (duk_ptrdiff_t) ((duk_uint8_t *) thr->valstack_top - (duk_uint8_t *) thr->valstack);\n\talloc_size = (duk_size_t) alloc_end_off;\n\tif (alloc_size == 0) {\n\t\tDUK_D(DUK_DPRINT(\"skip valstack torture realloc, alloc_size is zero\"));\n\t\treturn;\n\t}\n\n\t/* Use DUK_ALLOC_RAW() to avoid side effects. */\n\tnew_ptr = (duk_tval *) DUK_ALLOC_RAW(thr->heap, alloc_size);\n\tif (new_ptr != NULL) {\n\t\tDUK_MEMCPY((void *) new_ptr, (const void *) thr->valstack, alloc_size);\n\t\tDUK_MEMSET((void *) thr->valstack, 0x55, alloc_size);\n\t\tDUK_FREE_CHECKED(thr, (void *) thr->valstack);\n\t\tthr->valstack = new_ptr;\n\t\tthr->valstack_alloc_end = (duk_tval *) ((duk_uint8_t *) new_ptr + alloc_end_off);\n\t\tthr->valstack_end = (duk_tval *) ((duk_uint8_t *) new_ptr + end_off);\n\t\tthr->valstack_bottom = (duk_tval *) ((duk_uint8_t *) new_ptr + bottom_off);\n\t\tthr->valstack_top = (duk_tval *) ((duk_uint8_t *) new_ptr + top_off);\n\t} else {\n\t\tDUK_D(DUK_DPRINT(\"failed to realloc valstack for torture, ignore\"));\n\t}\n}\n#endif  /* DUK_USE_FINALIZER_TORTURE */\n#line 1 \"duk_js_arith.c\"\n/*\n *  Shared helpers for arithmetic operations\n */\n\n/* #include duk_internal.h -> already included */\n\n/* Ecmascript modulus ('%') does not match IEEE 754 \"remainder\" operation\n * (implemented by remainder() in C99) but does seem to match ANSI C fmod().\n * Compare E5 Section 11.5.3 and \"man fmod\".\n */\nDUK_INTERNAL double duk_js_arith_mod(double d1, double d2) {\n#if defined(DUK_USE_POW_WORKAROUNDS)\n\t/* Specific fixes to common fmod() implementation issues:\n\t * - test-bug-mingw-math-issues.js\n\t */\n\tif (DUK_ISINF(d2)) {\n\t\tif (DUK_ISINF(d1)) {\n\t\t\treturn DUK_DOUBLE_NAN;\n\t\t} else {\n\t\t\treturn d1;\n\t\t}\n\t} else if (d1 == 0.0) {\n\t\t/* d1 +/-0 is returned as is (preserving sign) except when\n\t\t * d2 is zero or NaN.\n\t\t */\n\t\tif (d2 == 0.0 || DUK_ISNAN(d2)) {\n\t\t\treturn DUK_DOUBLE_NAN;\n\t\t} else {\n\t\t\treturn d1;\n\t\t}\n\t}\n#else\n\t/* Some ISO C assumptions. */\n\tDUK_ASSERT(DUK_FMOD(1.0, DUK_DOUBLE_INFINITY) == 1.0);\n\tDUK_ASSERT(DUK_FMOD(-1.0, DUK_DOUBLE_INFINITY) == -1.0);\n\tDUK_ASSERT(DUK_FMOD(1.0, -DUK_DOUBLE_INFINITY) == 1.0);\n\tDUK_ASSERT(DUK_FMOD(-1.0, -DUK_DOUBLE_INFINITY) == -1.0);\n\tDUK_ASSERT(DUK_ISNAN(DUK_FMOD(DUK_DOUBLE_INFINITY, DUK_DOUBLE_INFINITY)));\n\tDUK_ASSERT(DUK_ISNAN(DUK_FMOD(DUK_DOUBLE_INFINITY, -DUK_DOUBLE_INFINITY)));\n\tDUK_ASSERT(DUK_ISNAN(DUK_FMOD(-DUK_DOUBLE_INFINITY, DUK_DOUBLE_INFINITY)));\n\tDUK_ASSERT(DUK_ISNAN(DUK_FMOD(-DUK_DOUBLE_INFINITY, -DUK_DOUBLE_INFINITY)));\n\tDUK_ASSERT(DUK_FMOD(0.0, 1.0) == 0.0 && DUK_SIGNBIT(DUK_FMOD(0.0, 1.0)) == 0);\n\tDUK_ASSERT(DUK_FMOD(-0.0, 1.0) == 0.0 && DUK_SIGNBIT(DUK_FMOD(-0.0, 1.0)) != 0);\n\tDUK_ASSERT(DUK_FMOD(0.0, DUK_DOUBLE_INFINITY) == 0.0 && DUK_SIGNBIT(DUK_FMOD(0.0, DUK_DOUBLE_INFINITY)) == 0);\n\tDUK_ASSERT(DUK_FMOD(-0.0, DUK_DOUBLE_INFINITY) == 0.0 && DUK_SIGNBIT(DUK_FMOD(-0.0, DUK_DOUBLE_INFINITY)) != 0);\n\tDUK_ASSERT(DUK_FMOD(0.0, -DUK_DOUBLE_INFINITY) == 0.0 && DUK_SIGNBIT(DUK_FMOD(0.0, DUK_DOUBLE_INFINITY)) == 0);\n\tDUK_ASSERT(DUK_FMOD(-0.0, -DUK_DOUBLE_INFINITY) == 0.0 && DUK_SIGNBIT(DUK_FMOD(-0.0, -DUK_DOUBLE_INFINITY)) != 0);\n\tDUK_ASSERT(DUK_ISNAN(DUK_FMOD(0.0, 0.0)));\n\tDUK_ASSERT(DUK_ISNAN(DUK_FMOD(-0.0, 0.0)));\n\tDUK_ASSERT(DUK_ISNAN(DUK_FMOD(0.0, -0.0)));\n\tDUK_ASSERT(DUK_ISNAN(DUK_FMOD(-0.0, -0.0)));\n\tDUK_ASSERT(DUK_ISNAN(DUK_FMOD(0.0, DUK_DOUBLE_NAN)));\n\tDUK_ASSERT(DUK_ISNAN(DUK_FMOD(-0.0, DUK_DOUBLE_NAN)));\n#endif\n\n\treturn (duk_double_t) DUK_FMOD((double) d1, (double) d2);\n}\n\n/* Shared helper for Math.pow() and exponentiation operator. */\nDUK_INTERNAL double duk_js_arith_pow(double x, double y) {\n\t/* The ANSI C pow() semantics differ from Ecmascript.\n\t *\n\t * E.g. when x==1 and y is +/- infinite, the Ecmascript required\n\t * result is NaN, while at least Linux pow() returns 1.\n\t */\n\n\tduk_small_int_t cx, cy, sx;\n\n\tDUK_UNREF(cx);\n\tDUK_UNREF(sx);\n\tcy = (duk_small_int_t) DUK_FPCLASSIFY(y);\n\n\tif (cy == DUK_FP_NAN) {\n\t\tgoto ret_nan;\n\t}\n\tif (DUK_FABS(x) == 1.0 && cy == DUK_FP_INFINITE) {\n\t\tgoto ret_nan;\n\t}\n\n#if defined(DUK_USE_POW_WORKAROUNDS)\n\t/* Specific fixes to common pow() implementation issues:\n\t *   - test-bug-netbsd-math-pow.js: NetBSD 6.0 on x86 (at least)\n\t *   - test-bug-mingw-math-issues.js\n\t */\n\tcx = (duk_small_int_t) DUK_FPCLASSIFY(x);\n\tif (cx == DUK_FP_ZERO && y < 0.0) {\n\t\tsx = (duk_small_int_t) DUK_SIGNBIT(x);\n\t\tif (sx == 0) {\n\t\t\t/* Math.pow(+0,y) should be Infinity when y<0.  NetBSD pow()\n\t\t\t * returns -Infinity instead when y is <0 and finite.  The\n\t\t\t * if-clause also catches y == -Infinity (which works even\n\t\t\t * without the fix).\n\t\t\t */\n\t\t\treturn DUK_DOUBLE_INFINITY;\n\t\t} else {\n\t\t\t/* Math.pow(-0,y) where y<0 should be:\n\t\t\t *   - -Infinity if y<0 and an odd integer\n\t\t\t *   - Infinity if y<0 but not an odd integer\n\t\t\t * NetBSD pow() returns -Infinity for all finite y<0.  The\n\t\t\t * if-clause also catches y == -Infinity (which works even\n\t\t\t * without the fix).\n\t\t\t */\n\n\t\t\t/* fmod() return value has same sign as input (negative) so\n\t\t\t * the result here will be in the range ]-2,0], -1 indicates\n\t\t\t * odd.  If x is -Infinity, NaN is returned and the odd check\n\t\t\t * always concludes \"not odd\" which results in desired outcome.\n\t\t\t */\n\t\t\tdouble tmp = DUK_FMOD(y, 2);\n\t\t\tif (tmp == -1.0) {\n\t\t\t\treturn -DUK_DOUBLE_INFINITY;\n\t\t\t} else {\n\t\t\t\t/* Not odd, or y == -Infinity */\n\t\t\t\treturn DUK_DOUBLE_INFINITY;\n\t\t\t}\n\t\t}\n\t} else if (cx == DUK_FP_NAN) {\n\t\tif (y == 0.0) {\n\t\t\t/* NaN ** +/- 0 should always be 1, but is NaN on\n\t\t\t * at least some Cygwin/MinGW versions.\n\t\t\t */\n\t\t\treturn 1.0;\n\t\t}\n\t}\n#else\n\t/* Some ISO C assumptions. */\n\tDUK_ASSERT(DUK_POW(DUK_DOUBLE_NAN, 0.0) == 1.0);\n\tDUK_ASSERT(DUK_ISINF(DUK_POW(0.0, -1.0)) && DUK_SIGNBIT(DUK_POW(0.0, -1.0)) == 0);\n\tDUK_ASSERT(DUK_ISINF(DUK_POW(-0.0, -2.0)) && DUK_SIGNBIT(DUK_POW(-0.0, -2.0)) == 0);\n\tDUK_ASSERT(DUK_ISINF(DUK_POW(-0.0, -3.0)) && DUK_SIGNBIT(DUK_POW(-0.0, -3.0)) != 0);\n#endif\n\n\treturn DUK_POW(x, y);\n\n ret_nan:\n\treturn DUK_DOUBLE_NAN;\n}\n#line 1 \"duk_js_call.c\"\n/*\n *  Call handling.\n *\n *  duk_handle_call_unprotected():\n *\n *    - Unprotected call to Ecmascript or Duktape/C function, from native\n *      code or bytecode executor.\n *\n *    - Also handles Ecma-to-Ecma calls which reuses a currently running\n *      executor instance to avoid native recursion.  Call setup is done\n *      normally, but just before calling the bytecode executor a special\n *      return code is used to indicate that a calling executor is reused.\n *\n *    - Also handles tailcalls, i.e. reuse of current duk_activation.\n *\n *    - Also handles setup for initial Duktape.Thread.resume().\n *\n *  duk_handle_safe_call():\n *\n *    - Protected C call within current activation.\n *\n *  setjmp() and local variables have a nasty interaction, see execution.rst;\n *  non-volatile locals modified after setjmp() call are not guaranteed to\n *  keep their value and can cause compiler or compiler version specific\n *  difficult to replicate issues.\n *\n *  See 'execution.rst'.\n */\n\n/* #include duk_internal.h -> already included */\n\n/* XXX: heap->error_not_allowed for success path too? */\n\n/*\n *  Limit check helpers.\n */\n\n/* Allow headroom for calls during error augmentation (see GH-191).\n * We allow space for 10 additional recursions, with one extra\n * for, e.g. a print() call at the deepest level, and an extra\n * +1 for protected call wrapping.\n */\n#define DUK__AUGMENT_CALL_RELAX_COUNT  (10 + 2)\n\nDUK_LOCAL DUK_NOINLINE void duk__call_c_recursion_limit_check_slowpath(duk_hthread *thr) {\n\t/* When augmenting an error, the effective limit is a bit higher.\n\t * Check for it only if the fast path check fails.\n\t */\n#if defined(DUK_USE_AUGMENT_ERROR_THROW) || defined(DUK_USE_AUGMENT_ERROR_CREATE)\n\tif (thr->heap->augmenting_error) {\n\t\tif (thr->heap->call_recursion_depth < thr->heap->call_recursion_limit + DUK__AUGMENT_CALL_RELAX_COUNT) {\n\t\t\tDUK_D(DUK_DPRINT(\"C recursion limit reached but augmenting error and within relaxed limit\"));\n\t\t\treturn;\n\t\t}\n\t}\n#endif\n\n\tDUK_D(DUK_DPRINT(\"call prevented because C recursion limit reached\"));\n\tDUK_ERROR_RANGE(thr, DUK_STR_C_CALLSTACK_LIMIT);\n}\n\nDUK_LOCAL DUK_ALWAYS_INLINE void duk__call_c_recursion_limit_check(duk_hthread *thr) {\n\tDUK_ASSERT(thr->heap->call_recursion_depth >= 0);\n\tDUK_ASSERT(thr->heap->call_recursion_depth <= thr->heap->call_recursion_limit);\n\n\t/* This check is forcibly inlined because it's very cheap and almost\n\t * always passes.  The slow path is forcibly noinline.\n\t */\n\tif (DUK_LIKELY(thr->heap->call_recursion_depth < thr->heap->call_recursion_limit)) {\n\t\treturn;\n\t}\n\n\tduk__call_c_recursion_limit_check_slowpath(thr);\n}\n\nDUK_LOCAL DUK_NOINLINE void duk__call_callstack_limit_check_slowpath(duk_hthread *thr) {\n\t/* When augmenting an error, the effective limit is a bit higher.\n\t * Check for it only if the fast path check fails.\n\t */\n#if defined(DUK_USE_AUGMENT_ERROR_THROW) || defined(DUK_USE_AUGMENT_ERROR_CREATE)\n\tif (thr->heap->augmenting_error) {\n\t\tif (thr->callstack_top < DUK_USE_CALLSTACK_LIMIT + DUK__AUGMENT_CALL_RELAX_COUNT) {\n\t\t\tDUK_D(DUK_DPRINT(\"call stack limit reached but augmenting error and within relaxed limit\"));\n\t\t\treturn;\n\t\t}\n\t}\n#endif\n\n\t/* XXX: error message is a bit misleading: we reached a recursion\n\t * limit which is also essentially the same as a C callstack limit\n\t * (except perhaps with some relaxed threading assumptions).\n\t */\n\tDUK_D(DUK_DPRINT(\"call prevented because call stack limit reached\"));\n\tDUK_ERROR_RANGE(thr, DUK_STR_CALLSTACK_LIMIT);\n}\n\nDUK_LOCAL DUK_ALWAYS_INLINE void duk__call_callstack_limit_check(duk_hthread *thr) {\n\t/* This check is forcibly inlined because it's very cheap and almost\n\t * always passes.  The slow path is forcibly noinline.\n\t */\n\tif (DUK_LIKELY(thr->callstack_top < DUK_USE_CALLSTACK_LIMIT)) {\n\t\treturn;\n\t}\n\n\tduk__call_callstack_limit_check_slowpath(thr);\n}\n\n/*\n *  Interrupt counter fixup (for development only).\n */\n\n#if defined(DUK_USE_INTERRUPT_COUNTER) && defined(DUK_USE_DEBUG)\nDUK_LOCAL void duk__interrupt_fixup(duk_hthread *thr, duk_hthread *entry_curr_thread) {\n\t/* Currently the bytecode executor and executor interrupt\n\t * instruction counts are off because we don't execute the\n\t * interrupt handler when we're about to exit from the initial\n\t * user call into Duktape.\n\t *\n\t * If we were to execute the interrupt handler here, the counts\n\t * would match.  You can enable this block manually to check\n\t * that this is the case.\n\t */\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(thr->heap != NULL);\n\n#if defined(DUK_USE_INTERRUPT_DEBUG_FIXUP)\n\tif (entry_curr_thread == NULL) {\n\t\tthr->interrupt_init = thr->interrupt_init - thr->interrupt_counter;\n\t\tthr->heap->inst_count_interrupt += thr->interrupt_init;\n\t\tDUK_DD(DUK_DDPRINT(\"debug test: updated interrupt count on exit to \"\n\t\t                   \"user code, instruction counts: executor=%ld, interrupt=%ld\",\n\t\t                   (long) thr->heap->inst_count_exec, (long) thr->heap->inst_count_interrupt));\n\t\tDUK_ASSERT(thr->heap->inst_count_exec == thr->heap->inst_count_interrupt);\n\t}\n#else\n\tDUK_UNREF(thr);\n\tDUK_UNREF(entry_curr_thread);\n#endif\n}\n#endif\n\n/*\n *  Arguments object creation.\n *\n *  Creating arguments objects involves many small details, see E5 Section\n *  10.6 for the specific requirements.  Much of the arguments object exotic\n *  behavior is implemented in duk_hobject_props.c, and is enabled by the\n *  object flag DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS.\n */\n\nDUK_LOCAL void duk__create_arguments_object(duk_hthread *thr,\n                                            duk_hobject *func,\n                                            duk_hobject *varenv,\n                                            duk_idx_t idx_args) {\n\tduk_hobject *arg;          /* 'arguments' */\n\tduk_hobject *formals;      /* formals for 'func' (may be NULL if func is a C function) */\n\tduk_idx_t i_arg;\n\tduk_idx_t i_map;\n\tduk_idx_t i_mappednames;\n\tduk_idx_t i_formals;\n\tduk_idx_t i_argbase;\n\tduk_idx_t n_formals;\n\tduk_idx_t idx;\n\tduk_idx_t num_stack_args;\n\tduk_bool_t need_map;\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(func != NULL);\n\tDUK_ASSERT(DUK_HOBJECT_IS_NONBOUND_FUNCTION(func));\n\tDUK_ASSERT(varenv != NULL);\n\n\t/* [ ... func this arg1(@idx_args) ... argN envobj ]\n\t * [ arg1(@idx_args) ... argN envobj ] (for tailcalls)\n\t */\n\n\tneed_map = 0;\n\n\ti_argbase = idx_args;\n\tnum_stack_args = duk_get_top(thr) - i_argbase - 1;\n\tDUK_ASSERT(i_argbase >= 0);\n\tDUK_ASSERT(num_stack_args >= 0);\n\n\tduk_push_hobject(thr, func);\n\tduk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INT_FORMALS);\n\tformals = duk_get_hobject(thr, -1);\n\tif (formals) {\n\t\tn_formals = (duk_idx_t) duk_get_length(thr, -1);\n\t} else {\n\t\t/* This shouldn't happen without tampering of internal\n\t\t * properties: if a function accesses 'arguments', _Formals\n\t\t * is kept.  Check for the case anyway in case internal\n\t\t * properties have been modified manually.\n\t\t */\n\t\tDUK_D(DUK_DPRINT(\"_Formals is undefined when creating arguments, use n_formals == 0\"));\n\t\tn_formals = 0;\n\t}\n\tduk_remove_m2(thr);  /* leave formals on stack for later use */\n\ti_formals = duk_require_top_index(thr);\n\n\tDUK_ASSERT(n_formals >= 0);\n\tDUK_ASSERT(formals != NULL || n_formals == 0);\n\n\tDUK_DDD(DUK_DDDPRINT(\"func=%!O, formals=%!O, n_formals=%ld\",\n\t                     (duk_heaphdr *) func, (duk_heaphdr *) formals,\n\t                     (long) n_formals));\n\n\t/* [ ... formals ] */\n\n\t/*\n\t *  Create required objects:\n\t *    - 'arguments' object: array-like, but not an array\n\t *    - 'map' object: internal object, tied to 'arguments'\n\t *    - 'mappedNames' object: temporary value used during construction\n\t */\n\n\targ = duk_push_object_helper(thr,\n\t                             DUK_HOBJECT_FLAG_EXTENSIBLE |\n\t                             DUK_HOBJECT_FLAG_FASTREFS |\n\t                             DUK_HOBJECT_FLAG_ARRAY_PART |\n\t                             DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ARGUMENTS),\n\t                             DUK_BIDX_OBJECT_PROTOTYPE);\n\tDUK_ASSERT(arg != NULL);\n\t(void) duk_push_object_helper(thr,\n\t                              DUK_HOBJECT_FLAG_EXTENSIBLE |\n\t                              DUK_HOBJECT_FLAG_FASTREFS |\n\t                              DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT),\n\t                              -1);  /* no prototype */\n\t(void) duk_push_object_helper(thr,\n\t                              DUK_HOBJECT_FLAG_EXTENSIBLE |\n\t                              DUK_HOBJECT_FLAG_FASTREFS |\n\t                              DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT),\n\t                              -1);  /* no prototype */\n\ti_arg = duk_get_top(thr) - 3;\n\ti_map = i_arg + 1;\n\ti_mappednames = i_arg + 2;\n\n\t/* [ ... formals arguments map mappedNames ] */\n\n\tDUK_DDD(DUK_DDDPRINT(\"created arguments related objects: \"\n\t                     \"arguments at index %ld -> %!O \"\n\t                     \"map at index %ld -> %!O \"\n\t                     \"mappednames at index %ld -> %!O\",\n\t                     (long) i_arg, (duk_heaphdr *) duk_get_hobject(thr, i_arg),\n\t                     (long) i_map, (duk_heaphdr *) duk_get_hobject(thr, i_map),\n\t                     (long) i_mappednames, (duk_heaphdr *) duk_get_hobject(thr, i_mappednames)));\n\n\t/*\n\t *  Init arguments properties, map, etc.\n\t */\n\n\tduk_push_int(thr, num_stack_args);\n\tduk_xdef_prop_stridx(thr, i_arg, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_WC);\n\n\t/*\n\t *  Init argument related properties.\n\t */\n\n\t/* step 11 */\n\tidx = num_stack_args - 1;\n\twhile (idx >= 0) {\n\t\tDUK_DDD(DUK_DDDPRINT(\"arg idx %ld, argbase=%ld, argidx=%ld\",\n\t\t                     (long) idx, (long) i_argbase, (long) (i_argbase + idx)));\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"define arguments[%ld]=arg\", (long) idx));\n\t\tduk_dup(thr, i_argbase + idx);\n\t\tduk_xdef_prop_index_wec(thr, i_arg, (duk_uarridx_t) idx);\n\t\tDUK_DDD(DUK_DDDPRINT(\"defined arguments[%ld]=arg\", (long) idx));\n\n\t\t/* step 11.c is relevant only if non-strict (checked in 11.c.ii) */\n\t\tif (!DUK_HOBJECT_HAS_STRICT(func) && idx < n_formals) {\n\t\t\tDUK_ASSERT(formals != NULL);\n\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"strict function, index within formals (%ld < %ld)\",\n\t\t\t                     (long) idx, (long) n_formals));\n\n\t\t\tduk_get_prop_index(thr, i_formals, (duk_uarridx_t) idx);\n\t\t\tDUK_ASSERT(duk_is_string(thr, -1));\n\n\t\t\tduk_dup_top(thr);  /* [ ... name name ] */\n\n\t\t\tif (!duk_has_prop(thr, i_mappednames)) {\n\t\t\t\t/* steps 11.c.ii.1 - 11.c.ii.4, but our internal book-keeping\n\t\t\t\t * differs from the reference model\n\t\t\t\t */\n\n\t\t\t\t/* [ ... name ] */\n\n\t\t\t\tneed_map = 1;\n\n\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"set mappednames[%s]=%ld\",\n\t\t\t\t                     (const char *) duk_get_string(thr, -1),\n\t\t\t\t                     (long) idx));\n\t\t\t\tduk_dup_top(thr);                      /* name */\n\t\t\t\t(void) duk_push_uint_to_hstring(thr, (duk_uint_t) idx);  /* index */\n\t\t\t\tduk_xdef_prop_wec(thr, i_mappednames);  /* out of spec, must be configurable */\n\n\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"set map[%ld]=%s\",\n\t\t\t\t                     (long) idx,\n\t\t\t\t                     duk_get_string(thr, -1)));\n\t\t\t\tduk_dup_top(thr);         /* name */\n\t\t\t\tduk_xdef_prop_index_wec(thr, i_map, (duk_uarridx_t) idx);  /* out of spec, must be configurable */\n\t\t\t} else {\n\t\t\t\t/* duk_has_prop() popped the second 'name' */\n\t\t\t}\n\n\t\t\t/* [ ... name ] */\n\t\t\tduk_pop(thr);  /* pop 'name' */\n\t\t}\n\n\t\tidx--;\n\t}\n\n\tDUK_DDD(DUK_DDDPRINT(\"actual arguments processed\"));\n\n\t/* step 12 */\n\tif (need_map) {\n\t\tDUK_DDD(DUK_DDDPRINT(\"adding 'map' and 'varenv' to arguments object\"));\n\n\t\t/* should never happen for a strict callee */\n\t\tDUK_ASSERT(!DUK_HOBJECT_HAS_STRICT(func));\n\n\t\tduk_dup(thr, i_map);\n\t\tduk_xdef_prop_stridx(thr, i_arg, DUK_STRIDX_INT_MAP, DUK_PROPDESC_FLAGS_NONE);  /* out of spec, don't care */\n\n\t\t/* The variable environment for magic variable bindings needs to be\n\t\t * given by the caller and recorded in the arguments object.\n\t\t *\n\t\t * See E5 Section 10.6, the creation of setters/getters.\n\t\t *\n\t\t * The variable environment also provides access to the callee, so\n\t\t * an explicit (internal) callee property is not needed.\n\t\t */\n\n\t\tduk_push_hobject(thr, varenv);\n\t\tduk_xdef_prop_stridx(thr, i_arg, DUK_STRIDX_INT_VARENV, DUK_PROPDESC_FLAGS_NONE);  /* out of spec, don't care */\n\t}\n\n\t/* steps 13-14 */\n\tif (DUK_HOBJECT_HAS_STRICT(func)) {\n\t\t/* Callee/caller are throwers and are not deletable etc.  They\n\t\t * could be implemented as virtual properties, but currently\n\t\t * there is no support for virtual properties which are accessors\n\t\t * (only plain virtual properties).  This would not be difficult\n\t\t * to change in duk_hobject_props, but we can make the throwers\n\t\t * normal, concrete properties just as easily.\n\t\t *\n\t\t * Note that the specification requires that the *same* thrower\n\t\t * built-in object is used here!  See E5 Section 10.6 main\n\t\t * algoritm, step 14, and Section 13.2.3 which describes the\n\t\t * thrower.  See test case test-arguments-throwers.js.\n\t\t */\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"strict function, setting caller/callee to throwers\"));\n\n\t\tduk_xdef_prop_stridx_thrower(thr, i_arg, DUK_STRIDX_CALLER);\n\t\tduk_xdef_prop_stridx_thrower(thr, i_arg, DUK_STRIDX_CALLEE);\n\t} else {\n\t\tDUK_DDD(DUK_DDDPRINT(\"non-strict function, setting callee to actual value\"));\n\t\tduk_push_hobject(thr, func);\n\t\tduk_xdef_prop_stridx(thr, i_arg, DUK_STRIDX_CALLEE, DUK_PROPDESC_FLAGS_WC);\n\t}\n\n\t/* set exotic behavior only after we're done */\n\tif (need_map) {\n\t\t/* Exotic behaviors are only enabled for arguments objects\n\t\t * which have a parameter map (see E5 Section 10.6 main\n\t\t * algorithm, step 12).\n\t\t *\n\t\t * In particular, a non-strict arguments object with no\n\t\t * mapped formals does *NOT* get exotic behavior, even\n\t\t * for e.g. \"caller\" property.  This seems counterintuitive\n\t\t * but seems to be the case.\n\t\t */\n\n\t\t/* cannot be strict (never mapped variables) */\n\t\tDUK_ASSERT(!DUK_HOBJECT_HAS_STRICT(func));\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"enabling exotic behavior for arguments object\"));\n\t\tDUK_HOBJECT_SET_EXOTIC_ARGUMENTS(arg);\n\t} else {\n\t\tDUK_DDD(DUK_DDDPRINT(\"not enabling exotic behavior for arguments object\"));\n\t}\n\n\tDUK_DDD(DUK_DDDPRINT(\"final arguments related objects: \"\n\t                     \"arguments at index %ld -> %!O \"\n\t                     \"map at index %ld -> %!O \"\n\t                     \"mappednames at index %ld -> %!O\",\n\t                     (long) i_arg, (duk_heaphdr *) duk_get_hobject(thr, i_arg),\n\t                     (long) i_map, (duk_heaphdr *) duk_get_hobject(thr, i_map),\n\t                     (long) i_mappednames, (duk_heaphdr *) duk_get_hobject(thr, i_mappednames)));\n\n\t/* [ args(n) envobj formals arguments map mappednames ] */\n\n\tduk_pop_2(thr);\n\tduk_remove_m2(thr);\n\n\t/* [ args(n) envobj arguments ] */\n}\n\n/* Helper for creating the arguments object and adding it to the env record\n * on top of the value stack.\n */\nDUK_LOCAL void duk__handle_createargs_for_call(duk_hthread *thr,\n                                               duk_hobject *func,\n                                               duk_hobject *env,\n                                               duk_idx_t idx_args) {\n\tDUK_DDD(DUK_DDDPRINT(\"creating arguments object for function call\"));\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(func != NULL);\n\tDUK_ASSERT(env != NULL);\n\tDUK_ASSERT(DUK_HOBJECT_HAS_CREATEARGS(func));\n\n\t/* [ ... arg1 ... argN envobj ] */\n\n\tduk__create_arguments_object(thr,\n\t                             func,\n\t                             env,\n\t                             idx_args);\n\n\t/* [ ... arg1 ... argN envobj argobj ] */\n\n\tduk_xdef_prop_stridx_short(thr,\n\t                           -2,\n\t                           DUK_STRIDX_LC_ARGUMENTS,\n\t                           DUK_HOBJECT_HAS_STRICT(func) ? DUK_PROPDESC_FLAGS_E :   /* strict: non-deletable, non-writable */\n\t                                                          DUK_PROPDESC_FLAGS_WE);  /* non-strict: non-deletable, writable */\n\t/* [ ... arg1 ... argN envobj ] */\n}\n\n/*\n *  Helpers for constructor call handling.\n *\n *  There are two [[Construct]] operations in the specification:\n *\n *    - E5 Section 13.2.2: for Function objects\n *    - E5 Section 15.3.4.5.2: for \"bound\" Function objects\n *\n *  The chain of bound functions is resolved in Section 15.3.4.5.2,\n *  with arguments \"piling up\" until the [[Construct]] internal\n *  method is called on the final, actual Function object.  Note\n *  that the \"prototype\" property is looked up *only* from the\n *  final object, *before* calling the constructor.\n *\n *  Since Duktape 2.2 bound functions are represented with the\n *  duk_hboundfunc internal type, and bound function chains are\n *  collapsed when a bound function is created.  As a result, the\n *  direct target of a duk_hboundfunc is always non-bound and the\n *  this/argument lists have been resolved.\n *\n *  When constructing new Array instances, an unnecessary object is\n *  created and discarded now: the standard [[Construct]] creates an\n *  object, and calls the Array constructor.  The Array constructor\n *  returns an Array instance, which is used as the result value for\n *  the \"new\" operation; the object created before the Array constructor\n *  call is discarded.\n *\n *  This would be easy to fix, e.g. by knowing that the Array constructor\n *  will always create a replacement object and skip creating the fallback\n *  object in that case.\n */\n\n/* Update default instance prototype for constructor call. */\nDUK_LOCAL void duk__update_default_instance_proto(duk_hthread *thr, duk_idx_t idx_func) {\n\tduk_hobject *proto;\n\tduk_hobject *fallback;\n\n\tDUK_ASSERT(duk_is_constructable(thr, idx_func));\n\n\tduk_get_prop_stridx_short(thr, idx_func, DUK_STRIDX_PROTOTYPE);\n\tproto = duk_get_hobject(thr, -1);\n\tif (proto == NULL) {\n\t\tDUK_DDD(DUK_DDDPRINT(\"constructor has no 'prototype' property, or value not an object \"\n\t\t                     \"-> leave standard Object prototype as fallback prototype\"));\n\t} else {\n\t\tDUK_DDD(DUK_DDDPRINT(\"constructor has 'prototype' property with object value \"\n\t\t                     \"-> set fallback prototype to that value: %!iO\", (duk_heaphdr *) proto));\n\t\t/* Original fallback (default instance) is untouched when\n\t\t * resolving bound functions etc.\n\t\t */\n\t\tfallback = duk_known_hobject(thr, idx_func + 1);\n\t\tDUK_ASSERT(fallback != NULL);\n\t\tDUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, fallback, proto);\n\t}\n\tduk_pop(thr);\n}\n\n/* Postprocess: return value special handling, error augmentation. */\nDUK_INTERNAL void duk_call_construct_postprocess(duk_hthread *thr, duk_small_uint_t proxy_invariant) {\n\t/* Use either fallback (default instance) or retval depending\n\t * on retval type.  Needs to be called before unwind because\n\t * the default instance is read from the current (immutable)\n\t * 'this' binding.\n\t *\n\t * For Proxy 'construct' calls the return value must be an\n\t * Object (we accept object-like values like buffers and\n\t * lightfuncs too).  If not, TypeError.\n\t */\n\tif (duk_check_type_mask(thr, -1, DUK_TYPE_MASK_OBJECT |\n\t                                 DUK_TYPE_MASK_BUFFER |\n\t                                 DUK_TYPE_MASK_LIGHTFUNC)) {\n\t\tDUK_DDD(DUK_DDDPRINT(\"replacement value\"));\n\t} else {\n\t\tif (DUK_UNLIKELY(proxy_invariant != 0U)) {\n\t\t\t/* Proxy 'construct' return value invariant violated. */\n\t\t\tDUK_ERROR_TYPE_INVALID_TRAP_RESULT(thr);\n\t\t}\n\t\t/* XXX: direct value stack access */\n\t\tduk_pop(thr);\n\t\tduk_push_this(thr);\n\t}\n\n#if defined(DUK_USE_AUGMENT_ERROR_CREATE)\n\t/* Augment created errors upon creation, not when they are thrown or\n\t * rethrown.  __FILE__ and __LINE__ are not desirable here; the call\n\t * stack reflects the caller which is correct.  Skip topmost, unwound\n\t * activation when creating a traceback.  If thr->ptr_curr_pc was !=\n\t * NULL we'd need to sync the current PC so that the traceback comes\n\t * out right; however it is always synced here so just assert for it.\n\t */\n\tDUK_ASSERT(thr->ptr_curr_pc == NULL);\n\tduk_err_augment_error_create(thr, thr, NULL, 0, DUK_AUGMENT_FLAG_NOBLAME_FILELINE |\n\t                                                DUK_AUGMENT_FLAG_SKIP_ONE);\n#endif\n}\n\n/*\n *  Helper for handling a bound function when a call is being made.\n *\n *  Assumes that bound function chains have been \"collapsed\" so that either\n *  the target is non-bound or there is one bound function that points to a\n *  nonbound target.\n *\n *  Prepends the bound arguments to the value stack (at idx_func + 2).\n *  The 'this' binding is also updated if necessary (at idx_func + 1).\n *  Note that for constructor calls the 'this' binding is never updated by\n *  [[BoundThis]].\n */\n\nDUK_LOCAL void duk__handle_bound_chain_for_call(duk_hthread *thr,\n                                                duk_idx_t idx_func,\n                                                duk_bool_t is_constructor_call) {\n\tduk_tval *tv_func;\n\tduk_hobject *func;\n\tduk_idx_t len;\n\n\tDUK_ASSERT(thr != NULL);\n\n\t/* On entry, item at idx_func is a bound, non-lightweight function,\n\t * but we don't rely on that below.\n\t */\n\n\tDUK_ASSERT(duk_get_top(thr) >= idx_func + 2);\n\n\ttv_func = duk_require_tval(thr, idx_func);\n\tDUK_ASSERT(tv_func != NULL);\n\n\tif (DUK_TVAL_IS_OBJECT(tv_func)) {\n\t\tfunc = DUK_TVAL_GET_OBJECT(tv_func);\n\n\t\t/* XXX: separate helper function, out of fast path? */\n\t\tif (DUK_HOBJECT_HAS_BOUNDFUNC(func)) {\n\t\t\tduk_hboundfunc *h_bound;\n\t\t\tduk_tval *tv_args;\n\t\t\tduk_tval *tv_gap;\n\n\t\t\th_bound = (duk_hboundfunc *) func;\n\t\t\ttv_args = h_bound->args;\n\t\t\tlen = h_bound->nargs;\n\t\t\tDUK_ASSERT(len == 0 || tv_args != NULL);\n\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"bound function encountered, ptr=%p: %!T\",\n\t\t\t                     (void *) DUK_TVAL_GET_OBJECT(tv_func), tv_func));\n\n\t\t\t/* [ ... func this arg1 ... argN ] */\n\n\t\t\tif (is_constructor_call) {\n\t\t\t\t/* See: tests/ecmascript/test-spec-bound-constructor.js */\n\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"constructor call: don't update this binding\"));\n\t\t\t} else {\n\t\t\t\t/* XXX: duk_replace_tval */\n\t\t\t\tduk_push_tval(thr, &h_bound->this_binding);\n\t\t\t\tduk_replace(thr, idx_func + 1);  /* idx_this = idx_func + 1 */\n\t\t\t}\n\n\t\t\t/* [ ... func this arg1 ... argN ] */\n\n\t\t\tduk_require_stack(thr, len);\n\n\t\t\ttv_gap = duk_reserve_gap(thr, idx_func + 2, len);\n\t\t\tduk_copy_tvals_incref(thr, tv_gap, tv_args, (duk_size_t) len);\n\n\t\t\t/* [ ... func this <bound args> arg1 ... argN ] */\n\n\t\t\tduk_push_tval(thr, &h_bound->target);\n\t\t\tduk_replace(thr, idx_func);  /* replace in stack */\n\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"bound function handled, idx_func=%ld, curr func=%!T\",\n\t\t\t                     (long) idx_func, duk_get_tval(thr, idx_func)));\n\t\t}\n\t} else if (DUK_TVAL_IS_LIGHTFUNC(tv_func)) {\n\t\t/* Lightweight function: never bound, so terminate. */\n\t\t;\n\t} else {\n\t\t/* Shouldn't happen, so ugly error is enough. */\n\t\tDUK_ERROR_INTERNAL(thr);\n\t}\n\n\tDUK_ASSERT(duk_get_top(thr) >= idx_func + 2);\n\n\tDUK_DDD(DUK_DDDPRINT(\"final non-bound function is: %!T\", duk_get_tval(thr, idx_func)));\n\n#if defined(DUK_USE_ASSERTIONS)\n\ttv_func = duk_require_tval(thr, idx_func);\n\tDUK_ASSERT(DUK_TVAL_IS_LIGHTFUNC(tv_func) || DUK_TVAL_IS_OBJECT(tv_func));\n\tif (DUK_TVAL_IS_OBJECT(tv_func)) {\n\t\tfunc = DUK_TVAL_GET_OBJECT(tv_func);\n\t\tDUK_ASSERT(func != NULL);\n\t\tDUK_ASSERT(!DUK_HOBJECT_HAS_BOUNDFUNC(func));\n\t\tDUK_ASSERT(DUK_HOBJECT_HAS_COMPFUNC(func) ||\n\t\t           DUK_HOBJECT_HAS_NATFUNC(func));\n\t}\n#endif\n}\n\n/*\n *  Helper for inline handling of .call(), .apply(), and .construct().\n */\n\nDUK_LOCAL duk_bool_t duk__handle_specialfuncs_for_call(duk_hthread *thr, duk_idx_t idx_func, duk_hobject *func, duk_small_uint_t *call_flags, duk_bool_t first) {\n#if defined(DUK_USE_ASSERTIONS)\n\tduk_c_function natfunc;\n#endif\n\tduk_tval *tv_args;\n\n\tDUK_ASSERT(func != NULL);\n\tDUK_ASSERT((*call_flags & DUK_CALL_FLAG_CONSTRUCT) == 0);  /* Caller. */\n\n#if defined(DUK_USE_ASSERTIONS)\n\tnatfunc = ((duk_hnatfunc *) func)->func;\n\tDUK_ASSERT(natfunc != NULL);\n#endif\n\n\t/* On every round of function resolution at least target function and\n\t * 'this' binding are set.  We can assume that here, and must guarantee\n\t * it on exit.  Value stack reserve is extended for bound function and\n\t * .apply() unpacking so we don't need to extend it here when we need a\n\t * few slots.\n\t */\n\tDUK_ASSERT(duk_get_top(thr) >= idx_func + 2);\n\n\t/* Handle native 'eval' specially.  A direct eval check is only made\n\t * for the first resolution attempt; e.g. a bound eval call is -not-\n\t * a direct eval call.\n\t */\n\tif (DUK_UNLIKELY(((duk_hnatfunc *) func)->magic == 15)) {\n\t\t/* For now no special handling except for direct eval\n\t\t * detection.\n\t\t */\n\t\tDUK_ASSERT(((duk_hnatfunc *) func)->func == duk_bi_global_object_eval);\n\t\tif (first && (*call_flags & DUK_CALL_FLAG_CALLED_AS_EVAL)) {\n\t\t\t*call_flags = (*call_flags & ~DUK_CALL_FLAG_CALLED_AS_EVAL) | DUK_CALL_FLAG_DIRECT_EVAL;\n\t\t}\n\t\tDUK_ASSERT(duk_get_top(thr) >= idx_func + 2);\n\t\treturn 1;  /* stop resolving */\n\t}\n\n\t/* Handle special functions based on the DUK_HOBJECT_FLAG_SPECIAL_CALL\n\t * flag; their magic value is used for switch-case.\n\t *\n\t * NOTE: duk_unpack_array_like() reserves value stack space\n\t * for the result values (unlike most other value stack calls).\n\t */\n\tswitch (((duk_hnatfunc *) func)->magic) {\n\tcase 0: {  /* 0=Function.prototype.call() */\n\t\t/* Value stack:\n\t\t * idx_func + 0: Function.prototype.call()  [removed]\n\t\t * idx_func + 1: this binding for .call (target function)\n\t\t * idx_func + 2: 1st argument to .call, desired 'this' binding\n\t\t * idx_func + 3: 2nd argument to .call, desired 1st argument for ultimate target\n\t\t * ...\n\t\t *\n\t\t * Remove idx_func + 0 to get:\n\t\t * idx_func + 0: target function\n\t\t * idx_func + 1: this binding\n\t\t * idx_func + 2: call arguments\n\t\t * ...\n\t\t */\n\t\tDUK_ASSERT(natfunc == duk_bi_function_prototype_call);\n\t\tduk_remove_unsafe(thr, idx_func);\n\t\ttv_args = thr->valstack_bottom + idx_func + 2;\n\t\tif (thr->valstack_top < tv_args) {\n\t\t\tDUK_ASSERT(tv_args <= thr->valstack_end);\n\t\t\tthr->valstack_top = tv_args;  /* at least target function and 'this' binding present */\n\t\t}\n\t\tbreak;\n\t}\n\tcase 1: {  /* 1=Function.prototype.apply() */\n\t\t/* Value stack:\n\t\t * idx_func + 0: Function.prototype.apply()  [removed]\n\t\t * idx_func + 1: this binding for .apply (target function)\n\t\t * idx_func + 2: 1st argument to .apply, desired 'this' binding\n\t\t * idx_func + 3: 2nd argument to .apply, argArray\n\t\t * [anything after this MUST be ignored]\n\t\t *\n\t\t * Remove idx_func + 0 and unpack the argArray to get:\n\t\t * idx_func + 0: target function\n\t\t * idx_func + 1: this binding\n\t\t * idx_func + 2: call arguments\n\t\t * ...\n\t\t */\n\t\tDUK_ASSERT(natfunc == duk_bi_function_prototype_apply);\n\t\tduk_remove_unsafe(thr, idx_func);\n\t\tgoto apply_shared;\n\t}\n#if defined(DUK_USE_REFLECT_BUILTIN)\n\tcase 2: {  /* 2=Reflect.apply() */\n\t\t/* Value stack:\n\t\t * idx_func + 0: Reflect.apply()  [removed]\n\t\t * idx_func + 1: this binding for .apply (ignored, usually Reflect)  [removed]\n\t\t * idx_func + 2: 1st argument to .apply, target function\n\t\t * idx_func + 3: 2nd argument to .apply, desired 'this' binding\n\t\t * idx_func + 4: 3rd argument to .apply, argArray\n\t\t * [anything after this MUST be ignored]\n\t\t *\n\t\t * Remove idx_func + 0 and idx_func + 1, and unpack the argArray to get:\n\t\t * idx_func + 0: target function\n\t\t * idx_func + 1: this binding\n\t\t * idx_func + 2: call arguments\n\t\t * ...\n\t\t */\n\t\tDUK_ASSERT(natfunc == duk_bi_reflect_apply);\n\t\tduk_remove_n_unsafe(thr, idx_func, 2);\n\t\tgoto apply_shared;\n\t}\n\tcase 3: {  /* 3=Reflect.construct() */\n\t\t/* Value stack:\n\t\t * idx_func + 0: Reflect.construct()  [removed]\n\t\t * idx_func + 1: this binding for .construct (ignored, usually Reflect)  [removed]\n\t\t * idx_func + 2: 1st argument to .construct, target function\n\t\t * idx_func + 3: 2nd argument to .construct, argArray\n\t\t * idx_func + 4: 3rd argument to .construct, newTarget\n\t\t * [anything after this MUST be ignored]\n\t\t *\n\t\t * Remove idx_func + 0 and idx_func + 1, unpack the argArray,\n\t\t * and insert default instance (prototype not yet updated), to get:\n\t\t * idx_func + 0: target function\n\t\t * idx_func + 1: this binding (default instance)\n\t\t * idx_func + 2: constructor call arguments\n\t\t * ...\n\t\t *\n\t\t * Call flags must be updated to reflect the fact that we're\n\t\t * now dealing with a constructor call, and e.g. the 'this'\n\t\t * binding cannot be overwritten if the target is bound.\n\t\t *\n\t\t * newTarget is checked but not yet passed onwards.\n\t\t */\n\n\t\tduk_idx_t top;\n\n\t\tDUK_ASSERT(natfunc == duk_bi_reflect_construct);\n\t\t*call_flags |= DUK_CALL_FLAG_CONSTRUCT;\n\t\tduk_remove_n_unsafe(thr, idx_func, 2);\n\t\ttop = duk_get_top(thr);\n\t\tif (!duk_is_constructable(thr, idx_func)) {\n\t\t\t/* Target constructability must be checked before\n\t\t\t * unpacking argArray (which may cause side effects).\n\t\t\t * Just return; caller will throw the error.\n\t\t\t */\n\t\t\tduk_set_top_unsafe(thr, idx_func + 2);  /* satisfy asserts */\n\t\t\tbreak;\n\t\t}\n\t\tduk_push_object(thr);\n\t\tduk_insert(thr, idx_func + 1);  /* default instance */\n\n\t\t/* [ ... func default_instance argArray newTarget? ] */\n\n\t\ttop = duk_get_top(thr);\n\t\tif (top < idx_func + 3) {\n\t\t\t/* argArray is a mandatory argument for Reflect.construct(). */\n\t\t\tDUK_ERROR_TYPE_INVALID_ARGS(thr);\n\t\t}\n\t\tif (top > idx_func + 3) {\n\t\t\tif (!duk_strict_equals(thr, idx_func, idx_func + 3)) {\n\t\t\t\t/* XXX: [[Construct]] newTarget currently unsupported */\n\t\t\t\tDUK_ERROR_UNSUPPORTED(thr);\n\t\t\t}\n\t\t\tduk_set_top_unsafe(thr, idx_func + 3);  /* remove any args beyond argArray */\n\t\t}\n\t\tDUK_ASSERT(duk_get_top(thr) == idx_func + 3);\n\t\tDUK_ASSERT(duk_is_valid_index(thr, idx_func + 2));\n\t\t(void) duk_unpack_array_like(thr, idx_func + 2);  /* XXX: should also remove target to be symmetric with duk_pack()? */\n\t\tduk_remove(thr, idx_func + 2);\n\t\tDUK_ASSERT(duk_get_top(thr) >= idx_func + 2);\n\t\tbreak;\n\t}\n#endif  /* DUK_USE_REFLECT_BUILTIN */\n\tdefault: {\n\t\tDUK_ASSERT(0);\n\t\tDUK_UNREACHABLE();\n\t}\n\t}\n\n\tDUK_ASSERT(duk_get_top(thr) >= idx_func + 2);\n\treturn 0;  /* keep resolving */\n\n apply_shared:\n\ttv_args = thr->valstack_bottom + idx_func + 2;\n\tif (thr->valstack_top <= tv_args) {\n\t\tDUK_ASSERT(tv_args <= thr->valstack_end);\n\t\tthr->valstack_top = tv_args;  /* at least target func and 'this' binding present */\n\t\t/* No need to check for argArray. */\n\t} else {\n\t\tDUK_ASSERT(duk_get_top(thr) >= idx_func + 3);  /* idx_func + 2 covered above */\n\t\tif (thr->valstack_top > tv_args + 1) {\n\t\t\tduk_set_top_unsafe(thr, idx_func + 3);  /* remove any args beyond argArray */\n\t\t}\n\t\tDUK_ASSERT(duk_is_valid_index(thr, idx_func + 2));\n\t\tif (!duk_is_callable(thr, idx_func)) {\n\t\t\t/* Avoid unpack side effects if the target isn't callable.\n\t\t\t * Calling code will throw the actual error.\n\t\t\t */\n\t\t} else {\n\t\t\t(void) duk_unpack_array_like(thr, idx_func + 2);\n\t\t\tduk_remove(thr, idx_func + 2);\n\t\t}\n\t}\n\tDUK_ASSERT(duk_get_top(thr) >= idx_func + 2);\n\treturn 0;  /* keep resolving */\n}\n\n/*\n *  Helper for Proxy handling.\n */\n\n#if defined(DUK_USE_ES6_PROXY)\nDUK_LOCAL void duk__handle_proxy_for_call(duk_hthread *thr, duk_idx_t idx_func, duk_hproxy *h_proxy, duk_small_uint_t *call_flags) {\n\tduk_bool_t rc;\n\n\t/* Value stack:\n\t * idx_func + 0: Proxy object\n\t * idx_func + 1: this binding for call\n\t * idx_func + 2: 1st argument for call\n\t * idx_func + 3: 2nd argument for call\n\t * ...\n\t *\n\t * If Proxy doesn't have a trap for the call ('apply' or 'construct'),\n\t * replace Proxy object with target object.\n\t *\n\t * If we're dealing with a normal call and the Proxy has an 'apply'\n\t * trap, manipulate value stack to:\n\t *\n\t * idx_func + 0: trap\n\t * idx_func + 1: Proxy's handler\n\t * idx_func + 2: Proxy's target\n\t * idx_func + 3: this binding for call (from idx_func + 1)\n\t * idx_func + 4: call arguments packed to an array\n\t *\n\t * If we're dealing with a constructor call and the Proxy has a\n\t * 'construct' trap, manipulate value stack to:\n\t *\n\t * idx_func + 0: trap\n\t * idx_func + 1: Proxy's handler\n\t * idx_func + 2: Proxy's target\n\t * idx_func + 3: call arguments packed to an array\n\t * idx_func + 4: newTarget == Proxy object here\n\t *\n\t * As we don't yet have proper newTarget support, the newTarget at\n\t * idx_func + 3 is just the original constructor being called, i.e.\n\t * the Proxy object (not the target).  Note that the default instance\n\t * (original 'this' binding) is dropped and ignored.\n\t */\n\n\tduk_push_hobject(thr, h_proxy->handler);\n\trc = duk_get_prop_stridx_short(thr, -1, (*call_flags & DUK_CALL_FLAG_CONSTRUCT) ? DUK_STRIDX_CONSTRUCT : DUK_STRIDX_APPLY);\n\tif (rc == 0) {\n\t\t/* Not found, continue to target.  If this is a construct\n\t\t * call, update default instance prototype using the Proxy,\n\t\t * not the target.\n\t\t */\n\t\tif (*call_flags & DUK_CALL_FLAG_CONSTRUCT) {\n\t\t\tif (!(*call_flags & DUK_CALL_FLAG_DEFAULT_INSTANCE_UPDATED)) {\n\t\t\t\t*call_flags |= DUK_CALL_FLAG_DEFAULT_INSTANCE_UPDATED;\n\t\t\t\tduk__update_default_instance_proto(thr, idx_func);\n\t\t\t}\n\t\t}\n\t\tduk_pop_2(thr);\n\t\tduk_push_hobject(thr, h_proxy->target);\n\t\tduk_replace(thr, idx_func);\n\t\treturn;\n\t}\n\n\t/* Here we must be careful not to replace idx_func while\n\t * h_proxy is still needed, otherwise h_proxy may become\n\t * dangling.  This could be improved e.g. using a\n\t * duk_pack_slice() with a freeform slice.\n\t */\n\n\t/* Here:\n\t * idx_func + 0: Proxy object\n\t * idx_func + 1: this binding for call\n\t * idx_func + 2: 1st argument for call\n\t * idx_func + 3: 2nd argument for call\n\t * ...\n\t * idx_func + N: handler\n\t * idx_func + N + 1: trap\n\t */\n\n\tduk_insert(thr, idx_func + 1);\n\tduk_insert(thr, idx_func + 2);\n\tduk_push_hobject(thr, h_proxy->target);\n\tduk_insert(thr, idx_func + 3);\n\tduk_pack(thr, duk_get_top(thr) - (idx_func + 5));\n\n\t/* Here:\n\t * idx_func + 0: Proxy object\n\t * idx_func + 1: trap\n\t * idx_func + 2: Proxy's handler\n\t * idx_func + 3: Proxy's target\n\t * idx_func + 4: this binding for call\n\t * idx_func + 5: arguments array\n\t */\n\tDUK_ASSERT(duk_get_top(thr) == idx_func + 6);\n\n\tif (*call_flags & DUK_CALL_FLAG_CONSTRUCT) {\n\t\t*call_flags |= DUK_CALL_FLAG_CONSTRUCT_PROXY;  /* Enable 'construct' trap return invariant check. */\n\t\t*call_flags &= ~(DUK_CALL_FLAG_CONSTRUCT);     /* Resume as non-constructor call to the trap. */\n\n\t\t/* 'apply' args: target, thisArg, argArray\n\t\t * 'construct' args: target, argArray, newTarget\n\t\t */\n\t\tduk_remove(thr, idx_func + 4);\n\t\tduk_push_hobject(thr, (duk_hobject *) h_proxy);\n\t}\n\n\t/* Finalize value stack layout by removing Proxy reference. */\n\tduk_remove(thr, idx_func);\n\th_proxy = NULL;  /* invalidated */\n\tDUK_ASSERT(duk_get_top(thr) == idx_func + 5);\n}\n#endif  /* DUK_USE_ES6_PROXY */\n\n/*\n *  Helper for setting up var_env and lex_env of an activation,\n *  assuming it does NOT have the DUK_HOBJECT_FLAG_NEWENV flag.\n */\n\nDUK_LOCAL void duk__handle_oldenv_for_call(duk_hthread *thr,\n                                           duk_hobject *func,\n                                           duk_activation *act) {\n\tduk_hcompfunc *f;\n\tduk_hobject *h_lex;\n\tduk_hobject *h_var;\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(func != NULL);\n\tDUK_ASSERT(act != NULL);\n\tDUK_ASSERT(!DUK_HOBJECT_HAS_NEWENV(func));\n\tDUK_ASSERT(!DUK_HOBJECT_HAS_CREATEARGS(func));\n\tDUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(func));\n\tDUK_UNREF(thr);\n\n\tf = (duk_hcompfunc *) func;\n\th_lex = DUK_HCOMPFUNC_GET_LEXENV(thr->heap, f);\n\th_var = DUK_HCOMPFUNC_GET_VARENV(thr->heap, f);\n\tDUK_ASSERT(h_lex != NULL);  /* Always true for closures (not for templates) */\n\tDUK_ASSERT(h_var != NULL);\n\tact->lex_env = h_lex;\n\tact->var_env = h_var;\n\tDUK_HOBJECT_INCREF(thr, h_lex);\n\tDUK_HOBJECT_INCREF(thr, h_var);\n}\n\n/*\n *  Helper for updating callee 'caller' property.\n */\n\n#if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)\nDUK_LOCAL void duk__update_func_caller_prop(duk_hthread *thr, duk_hobject *func) {\n\tduk_tval *tv_caller;\n\tduk_hobject *h_tmp;\n\tduk_activation *act_callee;\n\tduk_activation *act_caller;\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(func != NULL);\n\tDUK_ASSERT(!DUK_HOBJECT_HAS_BOUNDFUNC(func));  /* bound chain resolved */\n\tDUK_ASSERT(thr->callstack_top >= 1);\n\n\tif (DUK_HOBJECT_HAS_STRICT(func)) {\n\t\t/* Strict functions don't get their 'caller' updated. */\n\t\treturn;\n\t}\n\n\tDUK_ASSERT(thr->callstack_top > 0);\n\tact_callee = thr->callstack_curr;\n\tDUK_ASSERT(act_callee != NULL);\n\tact_caller = (thr->callstack_top >= 2 ? act_callee->parent : NULL);\n\n\t/* XXX: check .caller writability? */\n\n\t/* Backup 'caller' property and update its value. */\n\ttv_caller = duk_hobject_find_existing_entry_tval_ptr(thr->heap, func, DUK_HTHREAD_STRING_CALLER(thr));\n\tif (tv_caller) {\n\t\t/* If caller is global/eval code, 'caller' should be set to\n\t\t * 'null'.\n\t\t *\n\t\t * XXX: there is no exotic flag to infer this correctly now.\n\t\t * The NEWENV flag is used now which works as intended for\n\t\t * everything (global code, non-strict eval code, and functions)\n\t\t * except strict eval code.  Bound functions are never an issue\n\t\t * because 'func' has been resolved to a non-bound function.\n\t\t */\n\n\t\tif (act_caller != NULL) {\n\t\t\t/* act_caller->func may be NULL in some finalization cases,\n\t\t\t * just treat like we don't know the caller.\n\t\t\t */\n\t\t\tif (act_caller->func && !DUK_HOBJECT_HAS_NEWENV(act_caller->func)) {\n\t\t\t\t/* Setting to NULL causes 'caller' to be set to\n\t\t\t\t * 'null' as desired.\n\t\t\t\t */\n\t\t\t\tact_caller = NULL;\n\t\t\t}\n\t\t}\n\n\t\tif (DUK_TVAL_IS_OBJECT(tv_caller)) {\n\t\t\th_tmp = DUK_TVAL_GET_OBJECT(tv_caller);\n\t\t\tDUK_ASSERT(h_tmp != NULL);\n\t\t\tact_callee->prev_caller = h_tmp;\n\n\t\t\t/* Previous value doesn't need refcount changes because its ownership\n\t\t\t * is transferred to prev_caller.\n\t\t\t */\n\n\t\t\tif (act_caller != NULL) {\n\t\t\t\tDUK_ASSERT(act_caller->func != NULL);\n\t\t\t\tDUK_TVAL_SET_OBJECT(tv_caller, act_caller->func);\n\t\t\t\tDUK_TVAL_INCREF(thr, tv_caller);\n\t\t\t} else {\n\t\t\t\tDUK_TVAL_SET_NULL(tv_caller);  /* no incref */\n\t\t\t}\n\t\t} else {\n\t\t\t/* 'caller' must only take on 'null' or function value */\n\t\t\tDUK_ASSERT(!DUK_TVAL_IS_HEAP_ALLOCATED(tv_caller));\n\t\t\tDUK_ASSERT(act_callee->prev_caller == NULL);\n\t\t\tif (act_caller != NULL && act_caller->func) {\n\t\t\t\t/* Tolerate act_caller->func == NULL which happens in\n\t\t\t\t * some finalization cases; treat like unknown caller.\n\t\t\t\t */\n\t\t\t\tDUK_TVAL_SET_OBJECT(tv_caller, act_caller->func);\n\t\t\t\tDUK_TVAL_INCREF(thr, tv_caller);\n\t\t\t} else {\n\t\t\t\tDUK_TVAL_SET_NULL(tv_caller);  /* no incref */\n\t\t\t}\n\t\t}\n\t}\n}\n#endif  /* DUK_USE_NONSTD_FUNC_CALLER_PROPERTY */\n\n/*\n *  Shared helpers for resolving the final, non-bound target function of the\n *  call and the effective 'this' binding.  Resolves bound functions and\n *  applies .call(), .apply(), and .construct() inline.\n *\n *  Proxy traps are also handled inline so that if the target is a Proxy with\n *  a 'call' or 'construct' trap, the trap handler is called with a modified\n *  argument list.\n *\n *  Once the bound function / .call() / .apply() / .construct() sequence has\n *  been resolved, the value at idx_func + 1 may need coercion described in\n *  E5 Section 10.4.3.\n *\n *  A call that begins as a non-constructor call may be converted into a\n *  constructor call during the resolution process if Reflect.construct()\n *  is invoked.  This is handled by updating the caller's call_flags.\n *\n *  For global and eval code (E5 Sections 10.4.1 and 10.4.2), we assume\n *  that the caller has provided the correct 'this' binding explicitly\n *  when calling, i.e.:\n *\n *    - global code: this=global object\n *    - direct eval: this=copy from eval() caller's this binding\n *    - other eval:  this=global object\n *\n *  The 'this' coercion may cause a recursive function call with arbitrary\n *  side effects, because ToObject() may be called.\n */\n\nDUK_LOCAL DUK_INLINE void duk__coerce_nonstrict_this_binding(duk_hthread *thr, duk_idx_t idx_this) {\n\tduk_tval *tv_this;\n\tduk_hobject *obj_global;\n\n\ttv_this = thr->valstack_bottom + idx_this;\n\tswitch (DUK_TVAL_GET_TAG(tv_this)) {\n\tcase DUK_TAG_OBJECT:\n\t\tDUK_DDD(DUK_DDDPRINT(\"this binding: non-strict, object -> use directly\"));\n\t\tbreak;\n\tcase DUK_TAG_UNDEFINED:\n\tcase DUK_TAG_NULL:\n\t\tDUK_DDD(DUK_DDDPRINT(\"this binding: non-strict, undefined/null -> use global object\"));\n\t\tobj_global = thr->builtins[DUK_BIDX_GLOBAL];\n\t\t/* XXX: avoid this check somehow */\n\t\tif (DUK_LIKELY(obj_global != NULL)) {\n\t\t\tDUK_ASSERT(!DUK_TVAL_IS_HEAP_ALLOCATED(tv_this));  /* no need to decref previous value */\n\t\t\tDUK_TVAL_SET_OBJECT(tv_this, obj_global);\n\t\t\tDUK_HOBJECT_INCREF(thr, obj_global);\n\t\t} else {\n\t\t\t/* This may only happen if built-ins are being \"torn down\".\n\t\t\t * This behavior is out of specification scope.\n\t\t\t */\n\t\t\tDUK_D(DUK_DPRINT(\"this binding: wanted to use global object, but it is NULL -> using undefined instead\"));\n\t\t\tDUK_ASSERT(!DUK_TVAL_IS_HEAP_ALLOCATED(tv_this));  /* no need to decref previous value */\n\t\t\tDUK_TVAL_SET_UNDEFINED(tv_this);  /* nothing to incref */\n\t\t}\n\t\tbreak;\n\tdefault:\n\t\t/* Plain buffers and lightfuncs are object coerced.  Lightfuncs\n\t\t * very rarely come here however, because the call target would\n\t\t * need to be a non-strict non-lightfunc (lightfuncs are considered\n\t\t * strict) with an explicit lightfunc 'this' binding.\n\t\t */\n\t\tDUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv_this));\n\t\tDUK_DDD(DUK_DDDPRINT(\"this binding: non-strict, not object/undefined/null -> use ToObject(value)\"));\n\t\tduk_to_object(thr, idx_this);  /* may have side effects */\n\t\tbreak;\n\t}\n}\n\nDUK_LOCAL DUK_ALWAYS_INLINE duk_bool_t duk__resolve_target_fastpath_check(duk_hthread *thr, duk_idx_t idx_func, duk_hobject **out_func, duk_small_uint_t call_flags) {\n#if defined(DUK_USE_PREFER_SIZE)\n\tDUK_UNREF(thr);\n\tDUK_UNREF(idx_func);\n\tDUK_UNREF(out_func);\n\tDUK_UNREF(call_flags);\n#else  /* DUK_USE_PREFER_SIZE */\n\tduk_tval *tv_func;\n\tduk_hobject *func;\n\n\tif (DUK_UNLIKELY(call_flags & DUK_CALL_FLAG_CONSTRUCT)) {\n\t\treturn 0;\n\t}\n\n\ttv_func = DUK_GET_TVAL_POSIDX(thr, idx_func);\n\tDUK_ASSERT(tv_func != NULL);\n\n\tif (DUK_LIKELY(DUK_TVAL_IS_OBJECT(tv_func))) {\n\t\tfunc = DUK_TVAL_GET_OBJECT(tv_func);\n\t\tif (DUK_HOBJECT_IS_CALLABLE(func) &&\n\t\t    !DUK_HOBJECT_HAS_BOUNDFUNC(func) &&\n\t\t    !DUK_HOBJECT_HAS_SPECIAL_CALL(func)) {\n\t\t\t*out_func = func;\n\n\t\t\tif (DUK_HOBJECT_HAS_STRICT(func)) {\n\t\t\t\t/* Strict function: no 'this' coercion. */\n\t\t\t\treturn 1;\n\t\t\t}\n\n\t\t\tduk__coerce_nonstrict_this_binding(thr, idx_func + 1);\n\t\t\treturn 1;\n\t\t}\n\t} else if (DUK_TVAL_IS_LIGHTFUNC(tv_func)) {\n\t\t*out_func = NULL;\n\n\t\t/* Lightfuncs are considered strict, so 'this' binding is\n\t\t * used as is.  They're never bound, always constructable,\n\t\t * and never special functions.\n\t\t */\n\t\treturn 1;\n\t}\n#endif  /* DUK_USE_PREFER_SIZE */\n\treturn 0;  /* let slow path deal with it */\n}\n\nDUK_LOCAL duk_hobject *duk__resolve_target_func_and_this_binding(duk_hthread *thr,\n                                                                 duk_idx_t idx_func,\n                                                                 duk_small_uint_t *call_flags) {\n\tduk_tval *tv_func;\n\tduk_hobject *func;\n\tduk_bool_t first;\n\n\tDUK_ASSERT(duk_get_top(thr) >= idx_func + 2);\n\n\tfor (first = 1;; first = 0) {\n\t\tDUK_ASSERT(duk_get_top(thr) >= idx_func + 2);\n\n\t\ttv_func = DUK_GET_TVAL_POSIDX(thr, idx_func);\n\t\tDUK_ASSERT(tv_func != NULL);\n\n\t\tif (DUK_TVAL_IS_OBJECT(tv_func)) {\n\t\t\tfunc = DUK_TVAL_GET_OBJECT(tv_func);\n\n\t\t\tif (*call_flags & DUK_CALL_FLAG_CONSTRUCT) {\n\t\t\t\tif (DUK_UNLIKELY(!DUK_HOBJECT_HAS_CONSTRUCTABLE(func))) {\n\t\t\t\t\tgoto not_constructable;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (DUK_UNLIKELY(!DUK_HOBJECT_IS_CALLABLE(func))) {\n\t\t\t\t\tgoto not_callable;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (DUK_LIKELY(!DUK_HOBJECT_HAS_BOUNDFUNC(func) &&\n\t\t\t               !DUK_HOBJECT_HAS_SPECIAL_CALL(func) &&\n\t\t\t               !DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(func))) {\n\t\t\t\t/* Common case, so test for using a single bitfield test.\n\t\t\t\t * Break out to handle this coercion etc.\n\t\t\t\t */\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t/* XXX: could set specialcall for boundfuncs too, simplify check above */\n\n\t\t\tif (DUK_HOBJECT_HAS_BOUNDFUNC(func)) {\n\t\t\t\tDUK_ASSERT(!DUK_HOBJECT_HAS_SPECIAL_CALL(func));\n\t\t\t\tDUK_ASSERT(!DUK_HOBJECT_IS_NATFUNC(func));\n\n\t\t\t\t/* Callable/constructable flags are the same\n\t\t\t\t * for the bound function and its target, so\n\t\t\t\t * we don't need to check them here, we can\n\t\t\t\t * check them from the target only.\n\t\t\t\t */\n\t\t\t\tduk__handle_bound_chain_for_call(thr, idx_func, *call_flags & DUK_CALL_FLAG_CONSTRUCT);\n\n\t\t\t\tDUK_ASSERT(DUK_TVAL_IS_OBJECT(duk_require_tval(thr, idx_func)) ||\n\t\t\t\t           DUK_TVAL_IS_LIGHTFUNC(duk_require_tval(thr, idx_func)));\n\t\t\t} else {\n\t\t\t\tDUK_ASSERT(DUK_HOBJECT_HAS_SPECIAL_CALL(func));\n\n#if defined(DUK_USE_ES6_PROXY)\n\t\t\t\tif (DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(func)) {\n\t\t\t\t\t/* If no trap, resume processing from Proxy trap.\n\t\t\t\t\t * If trap exists, helper converts call into a trap\n\t\t\t\t\t * call; this may change a constructor call into a\n\t\t\t\t\t * normal (non-constructor) trap call.  We must\n\t\t\t\t\t * continue processing even when a trap is found as\n\t\t\t\t\t * the trap may be bound.\n\t\t\t\t\t */\n\t\t\t\t\tduk__handle_proxy_for_call(thr, idx_func, (duk_hproxy *) func, call_flags);\n\t\t\t\t}\n\t\t\t\telse\n#endif\n\t\t\t\t{\n\t\t\t\t\tDUK_ASSERT(DUK_HOBJECT_IS_NATFUNC(func));\n\t\t\t\t\tDUK_ASSERT(DUK_HOBJECT_HAS_CALLABLE(func));\n\t\t\t\t\tDUK_ASSERT(!DUK_HOBJECT_HAS_CONSTRUCTABLE(func));\n\t\t\t\t\t/* Constructable check already done above. */\n\n\t\t\t\t\tif (duk__handle_specialfuncs_for_call(thr, idx_func, func, call_flags, first) != 0) {\n\t\t\t\t\t\t/* Encountered native eval call, normal call\n\t\t\t\t\t\t * context.  Break out, handle this coercion etc.\n\t\t\t\t\t\t */\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t/* Retry loop. */\n\t\t} else if (DUK_TVAL_IS_LIGHTFUNC(tv_func)) {\n\t\t\t/* Lightfuncs are:\n\t\t\t *   - Always strict, so no 'this' coercion.\n\t\t\t *   - Always callable.\n\t\t\t *   - Always constructable.\n\t\t\t *   - Never specialfuncs.\n\t\t\t */\n\t\t\tfunc = NULL;\n\t\t\tgoto finished;\n\t\t} else {\n\t\t\tgoto not_callable;\n\t\t}\n\t}\n\n\tDUK_ASSERT(func != NULL);\n\n\tif (!DUK_HOBJECT_HAS_STRICT(func)) {\n\t\t/* Non-strict target needs 'this' coercion.\n\t\t * This has potential side effects invalidating\n\t\t * 'tv_func'.\n\t\t */\n\t\tduk__coerce_nonstrict_this_binding(thr, idx_func + 1);\n\t}\n\tif (*call_flags & DUK_CALL_FLAG_CONSTRUCT) {\n\t\tif (!(*call_flags & DUK_CALL_FLAG_DEFAULT_INSTANCE_UPDATED)) {\n\t\t\t*call_flags |= DUK_CALL_FLAG_DEFAULT_INSTANCE_UPDATED;\n\t\t\tduk__update_default_instance_proto(thr, idx_func);\n\t\t}\n\t}\n\n finished:\n\n#if defined(DUK_USE_ASSERTIONS)\n\t{\n\t\tduk_tval *tv_tmp;\n\n\t\ttv_tmp = duk_get_tval(thr, idx_func);\n\t\tDUK_ASSERT(tv_tmp != NULL);\n\n\t\tDUK_ASSERT((DUK_TVAL_IS_OBJECT(tv_tmp) && DUK_HOBJECT_IS_CALLABLE(DUK_TVAL_GET_OBJECT(tv_tmp))) ||\n\t\t           DUK_TVAL_IS_LIGHTFUNC(tv_tmp));\n\t\tDUK_ASSERT(func == NULL || !DUK_HOBJECT_HAS_BOUNDFUNC(func));\n\t\tDUK_ASSERT(func == NULL || (DUK_HOBJECT_IS_COMPFUNC(func) ||\n\t\t                            DUK_HOBJECT_IS_NATFUNC(func)));\n\t\tDUK_ASSERT(func == NULL || (DUK_HOBJECT_HAS_CONSTRUCTABLE(func) ||\n\t\t                            (*call_flags & DUK_CALL_FLAG_CONSTRUCT) == 0));\n\t}\n#endif\n\n\treturn func;\n\n not_callable:\n\tDUK_ASSERT(tv_func != NULL);\n\n#if defined(DUK_USE_VERBOSE_ERRORS)\n\t/* GETPROPC delayed error handling: when target is not callable,\n\t * GETPROPC replaces idx_func+0 with an Error (non-callable) with\n\t * a hidden Symbol to signify it's to be thrown as is here.  The\n\t * hidden Symbol is only checked as an own property, not inherited\n\t * (which would be dangerous).\n\t */\n\tif (DUK_TVAL_IS_OBJECT(tv_func)) {\n\t\tif (duk_hobject_find_existing_entry_tval_ptr(thr->heap, DUK_TVAL_GET_OBJECT(tv_func), DUK_HTHREAD_STRING_INT_TARGET(thr)) != NULL) {\n\t\t\tduk_push_tval(thr, tv_func);\n\t\t\t(void) duk_throw(thr);\n\t\t}\n\t}\n#endif\n\n#if defined(DUK_USE_VERBOSE_ERRORS)\n#if defined(DUK_USE_PARANOID_ERRORS)\n\tDUK_ERROR_FMT1(thr, DUK_ERR_TYPE_ERROR, \"%s not callable\", duk_get_type_name(thr, idx_func));\n#else\n\tDUK_ERROR_FMT1(thr, DUK_ERR_TYPE_ERROR, \"%s not callable\", duk_push_string_tval_readable(thr, tv_func));\n#endif\n#else\n\tDUK_ERROR_TYPE(thr, DUK_STR_NOT_CALLABLE);\n#endif\n\tDUK_UNREACHABLE();\n\treturn NULL;  /* never executed */\n\n not_constructable:\n\t/* For now GETPROPC delayed error not needed for constructor calls. */\n#if defined(DUK_USE_VERBOSE_ERRORS)\n#if defined(DUK_USE_PARANOID_ERRORS)\n\tDUK_ERROR_FMT1(thr, DUK_ERR_TYPE_ERROR, \"%s not constructable\", duk_get_type_name(thr, idx_func));\n#else\n\tDUK_ERROR_FMT1(thr, DUK_ERR_TYPE_ERROR, \"%s not constructable\", duk_push_string_tval_readable(thr, tv_func));\n#endif\n#else\n\tDUK_ERROR_TYPE(thr, DUK_STR_NOT_CONSTRUCTABLE);\n#endif\n\tDUK_UNREACHABLE();\n\treturn NULL;  /* never executed */\n}\n\n/*\n *  Manipulate value stack so that exactly 'num_stack_rets' return\n *  values are at 'idx_retbase' in every case, assuming there are\n *  'rc' return values on top of stack.\n *\n *  This is a bit tricky, because the called C function operates in\n *  the same activation record and may have e.g. popped the stack\n *  empty (below idx_retbase).\n */\n\nDUK_LOCAL void duk__safe_call_adjust_valstack(duk_hthread *thr, duk_idx_t idx_retbase, duk_idx_t num_stack_rets, duk_idx_t num_actual_rets) {\n\tduk_idx_t idx_rcbase;\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(idx_retbase >= 0);\n\tDUK_ASSERT(num_stack_rets >= 0);\n\tDUK_ASSERT(num_actual_rets >= 0);\n\n\tidx_rcbase = duk_get_top(thr) - num_actual_rets;  /* base of known return values */\n\tif (DUK_UNLIKELY(idx_rcbase < 0)) {\n\t\tDUK_ERROR_TYPE(thr, DUK_STR_INVALID_CFUNC_RC);\n\t}\n\n\tDUK_DDD(DUK_DDDPRINT(\"adjust valstack after func call: \"\n\t                     \"num_stack_rets=%ld, num_actual_rets=%ld, stack_top=%ld, idx_retbase=%ld, idx_rcbase=%ld\",\n\t                     (long) num_stack_rets, (long) num_actual_rets, (long) duk_get_top(thr),\n\t                     (long) idx_retbase, (long) idx_rcbase));\n\n\tDUK_ASSERT(idx_rcbase >= 0);  /* caller must check */\n\n\t/* Space for num_stack_rets was reserved before the safe call.\n\t * Because value stack reserve cannot shrink except in call returns,\n\t * the reserve is still in place.  Adjust valstack, carefully\n\t * ensuring we don't overstep the reserve.\n\t */\n\n\t/* Match idx_rcbase with idx_retbase so that the return values\n\t * start at the correct index.\n\t */\n\tif (idx_rcbase > idx_retbase) {\n\t\tduk_idx_t count = idx_rcbase - idx_retbase;\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"elements at/after idx_retbase have enough to cover func retvals \"\n\t\t                     \"(idx_retbase=%ld, idx_rcbase=%ld)\", (long) idx_retbase, (long) idx_rcbase));\n\n\t\t/* Remove values between irc_rcbase (start of intended return\n\t\t * values) and idx_retbase to lower return values to idx_retbase.\n\t\t */\n\t\tDUK_ASSERT(count > 0);\n\t\tduk_remove_n(thr, idx_retbase, count);  /* may be NORZ */\n\t} else {\n\t\tduk_idx_t count = idx_retbase - idx_rcbase;\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"not enough elements at/after idx_retbase to cover func retvals \"\n\t\t                     \"(idx_retbase=%ld, idx_rcbase=%ld)\", (long) idx_retbase, (long) idx_rcbase));\n\n\t\t/* Insert 'undefined' at idx_rcbase (start of intended return\n\t\t * values) to lift return values to idx_retbase.\n\t\t */\n\t\tDUK_ASSERT(count >= 0);\n\t\tDUK_ASSERT(thr->valstack_end - thr->valstack_top >= count);  /* reserve cannot shrink */\n\t\tduk_insert_undefined_n(thr, idx_rcbase, count);\n\t}\n\n\t/* Chop extra retvals away / extend with undefined. */\n\tduk_set_top_unsafe(thr, idx_retbase + num_stack_rets);\n}\n\n/*\n *  Activation setup for tailcalls and non-tailcalls.\n */\n\n#if defined(DUK_USE_TAILCALL)\nDUK_LOCAL duk_small_uint_t duk__call_setup_act_attempt_tailcall(duk_hthread *thr,\n                                                                duk_small_uint_t call_flags,\n                                                                duk_idx_t idx_func,\n                                                                duk_hobject *func,\n                                                                duk_size_t entry_valstack_bottom_byteoff,\n                                                                duk_size_t entry_valstack_end_byteoff,\n                                                                duk_idx_t *out_nargs,\n                                                                duk_idx_t *out_nregs,\n                                                                duk_size_t *out_vs_min_bytes,\n                                                                duk_activation **out_act) {\n\tduk_activation *act;\n\tduk_tval *tv1, *tv2;\n\tduk_idx_t idx_args;\n\tduk_small_uint_t flags1, flags2;\n#if defined(DUK_USE_DEBUGGER_SUPPORT)\n\tduk_activation *prev_pause_act;\n#endif\n\n\tDUK_UNREF(entry_valstack_end_byteoff);\n\n\t/* Tailcall cannot be flagged to resume calls, and a\n\t * previous frame must exist.\n\t */\n\tDUK_ASSERT(thr->callstack_top >= 1);\n\n\tact = thr->callstack_curr;\n\tDUK_ASSERT(act != NULL);\n\t*out_act = act;\n\n\tif (func == NULL || !DUK_HOBJECT_IS_COMPFUNC(func)) {\n\t\tDUK_DDD(DUK_DDDPRINT(\"tail call prevented by target not being ecma function\"));\n\t\treturn 0;\n\t}\n\tif (act->flags & DUK_ACT_FLAG_PREVENT_YIELD) {\n\t\tDUK_DDD(DUK_DDDPRINT(\"tail call prevented by current activation having DUK_ACT_FLAG_PREVENT_YIELD\"));\n\t\treturn 0;\n\t}\n\t/* Tailcall is only allowed if current and candidate\n\t * function have identical return value handling.  There\n\t * are three possible return value handling cases:\n\t *   1. Normal function call, no special return value handling.\n\t *   2. Constructor call, return value replacement object check.\n\t *   3. Proxy 'construct' trap call, return value invariant check.\n\t */\n\tflags1 = (duk_small_uint_t) ((act->flags & DUK_ACT_FLAG_CONSTRUCT) ? 1 : 0)\n#if defined(DUK_USE_ES6_PROXY)\n\t         | (duk_small_uint_t) ((act->flags & DUK_ACT_FLAG_CONSTRUCT_PROXY) ? 2 : 0)\n#endif\n\t         ;\n\tflags2 = (duk_small_uint_t) ((call_flags & DUK_CALL_FLAG_CONSTRUCT) ? 1 : 0)\n#if defined(DUK_USE_ES6_PROXY)\n\t         | (duk_small_uint_t) ((call_flags & DUK_CALL_FLAG_CONSTRUCT_PROXY) ? 2 : 0);\n#endif\n\t         ;\n\tif (flags1 != flags2) {\n\t\tDUK_DDD(DUK_DDDPRINT(\"tail call prevented by incompatible return value handling\"));\n\t\treturn 0;\n\t}\n\tDUK_ASSERT(((act->flags & DUK_ACT_FLAG_CONSTRUCT) && (call_flags & DUK_CALL_FLAG_CONSTRUCT)) ||\n\t           (!(act->flags & DUK_ACT_FLAG_CONSTRUCT) && !(call_flags & DUK_CALL_FLAG_CONSTRUCT)));\n\tDUK_ASSERT(((act->flags & DUK_ACT_FLAG_CONSTRUCT_PROXY) && (call_flags & DUK_CALL_FLAG_CONSTRUCT_PROXY)) ||\n\t           (!(act->flags & DUK_ACT_FLAG_CONSTRUCT_PROXY) && !(call_flags & DUK_CALL_FLAG_CONSTRUCT_PROXY)));\n\tif (DUK_HOBJECT_HAS_NOTAIL(func)) {\n\t\t/* See: test-bug-tailcall-preventyield-assert.c. */\n\t\tDUK_DDD(DUK_DDDPRINT(\"tail call prevented by function having a notail flag\"));\n\t\treturn 0;\n\t}\n\n\t/*\n\t *  Tailcall handling\n\t *\n\t *  Although the callstack entry is reused, we need to explicitly unwind\n\t *  the current activation (or simulate an unwind).  In particular, the\n\t *  current activation must be closed, otherwise something like\n\t *  test-bug-reduce-judofyr.js results.  Also catchers need to be unwound\n\t *  because there may be non-error-catching label entries in valid tail calls.\n\t *\n\t *  Special attention is needed for debugger and pause behavior when\n\t *  reusing an activation.\n\t *    - Disable StepOut processing for the activation unwind because\n\t *      we reuse the activation, see:\n\t *      https://github.com/svaarala/duktape/issues/1684.\n\t *    - Disable line change pause flag permanently (if set) because\n\t *      it would no longer be relevant, see:\n\t *      https://github.com/svaarala/duktape/issues/1726.\n\t *    - Check for function entry (e.g. StepInto) pause flag here, because\n\t *      the executor pause check won't trigger due to shared activation, see:\n\t *      https://github.com/svaarala/duktape/issues/1726.\n\t */\n\n\tDUK_DDD(DUK_DDDPRINT(\"is tail call, reusing activation at callstack top, at index %ld\",\n                             (long) (thr->callstack_top - 1)));\n\n\tDUK_ASSERT(!DUK_HOBJECT_HAS_BOUNDFUNC(func));\n\tDUK_ASSERT(!DUK_HOBJECT_HAS_NATFUNC(func));\n\tDUK_ASSERT(DUK_HOBJECT_HAS_COMPFUNC(func));\n\tDUK_ASSERT((act->flags & DUK_ACT_FLAG_PREVENT_YIELD) == 0);\n\tDUK_ASSERT(call_flags & DUK_CALL_FLAG_ALLOW_ECMATOECMA);\n\n\t/* Unwind the topmost callstack entry before reusing it.  This\n\t * also unwinds the catchers related to the topmost entry.\n\t */\n\tDUK_ASSERT(thr->callstack_top > 0);\n\tDUK_ASSERT(thr->callstack_curr != NULL);\n#if defined(DUK_USE_DEBUGGER_SUPPORT)\n\tprev_pause_act = thr->heap->dbg_pause_act;\n\tthr->heap->dbg_pause_act = NULL;\n\tthr->heap->dbg_pause_flags &= ~DUK_PAUSE_FLAG_LINE_CHANGE;\n\tif (thr->heap->dbg_pause_flags & DUK_PAUSE_FLAG_FUNC_ENTRY) {\n\t\tDUK_D(DUK_DPRINT(\"PAUSE TRIGGERED by function entry (tailcall)\"));\n\t\tduk_debug_set_paused(thr->heap);\n\t}\n#endif\n\tduk_hthread_activation_unwind_reuse_norz(thr);\n#if defined(DUK_USE_DEBUGGER_SUPPORT)\n\tthr->heap->dbg_pause_act = prev_pause_act;\n#endif\n\tDUK_ASSERT(act == thr->callstack_curr);\n\n\t/* XXX: We could restore the caller's value stack reserve\n\t * here, as if we did an actual unwind-and-call.  Without\n\t * the restoration, value stack reserve may remain higher\n\t * than would otherwise be possible until we return to a\n\t * non-tailcall.\n\t */\n\n\t/* Then reuse the unwound activation. */\n\tact->cat = NULL;\n\tact->var_env = NULL;\n\tact->lex_env = NULL;\n\tDUK_ASSERT(func != NULL);\n\tDUK_ASSERT(DUK_HOBJECT_HAS_COMPFUNC(func));\n\tact->func = func;  /* don't want an intermediate exposed state with func == NULL */\n#if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)\n\tact->prev_caller = NULL;\n#endif\n\t/* don't want an intermediate exposed state with invalid pc */\n\tact->curr_pc = DUK_HCOMPFUNC_GET_CODE_BASE(thr->heap, (duk_hcompfunc *) func);\n#if defined(DUK_USE_DEBUGGER_SUPPORT)\n\tact->prev_line = 0;\n#endif\n\tDUK_TVAL_SET_OBJECT(&act->tv_func, func);  /* borrowed, no refcount */\n\tDUK_HOBJECT_INCREF(thr, func);\n\n\tact->flags = DUK_ACT_FLAG_TAILCALLED;\n\tif (DUK_HOBJECT_HAS_STRICT(func)) {\n\t\tact->flags |= DUK_ACT_FLAG_STRICT;\n\t}\n\tif (call_flags & DUK_CALL_FLAG_CONSTRUCT) {\n\t\tact->flags |= DUK_ACT_FLAG_CONSTRUCT;\n\t}\n#if defined(DUK_USE_ES6_PROXY)\n\tif (call_flags & DUK_CALL_FLAG_CONSTRUCT_PROXY) {\n\t\tact->flags |= DUK_ACT_FLAG_CONSTRUCT_PROXY;\n\t}\n#endif\n\n\tDUK_ASSERT(DUK_ACT_GET_FUNC(act) == func);      /* already updated */\n\tDUK_ASSERT(act->var_env == NULL);\n\tDUK_ASSERT(act->lex_env == NULL);\n\tact->bottom_byteoff = entry_valstack_bottom_byteoff;  /* tail call -> reuse current \"frame\" */\n#if 0\n\t/* Topmost activation retval_byteoff is considered garbage, no need to init. */\n\tact->retval_byteoff = 0;\n#endif\n\t/* Filled in when final reserve is known, dummy value doesn't matter\n\t * even in error unwind because reserve_byteoff is only used when\n\t * returning to -this- activation.\n\t */\n\tact->reserve_byteoff = 0;\n\n\t/*\n\t *  Manipulate valstack so that args are on the current bottom and the\n\t *  previous caller's 'this' binding (which is the value preceding the\n\t *  current bottom) is replaced with the new 'this' binding:\n\t *\n\t *       [ ... this_old | (crud) func this_new arg1 ... argN ]\n\t *  -->  [ ... this_new | arg1 ... argN ]\n\t *\n\t *  For tail calling to work properly, the valstack bottom must not grow\n\t *  here; otherwise crud would accumulate on the valstack.\n\t */\n\n\ttv1 = thr->valstack_bottom - 1;\n\ttv2 = thr->valstack_bottom + idx_func + 1;\n\tDUK_ASSERT(tv1 >= thr->valstack && tv1 < thr->valstack_top);  /* tv1 is -below- valstack_bottom */\n\tDUK_ASSERT(tv2 >= thr->valstack_bottom && tv2 < thr->valstack_top);\n\tDUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv2);  /* side effects */\n\n\tidx_args = idx_func + 2;\n\tduk_remove_n(thr, 0, idx_args);  /* may be NORZ */\n\n\tidx_func = 0; DUK_UNREF(idx_func);  /* really 'not applicable' anymore, should not be referenced after this */\n\tidx_args = 0;\n\n\t*out_nargs = ((duk_hcompfunc *) func)->nargs;\n\t*out_nregs = ((duk_hcompfunc *) func)->nregs;\n\tDUK_ASSERT(*out_nregs >= 0);\n\tDUK_ASSERT(*out_nregs >= *out_nargs);\n\t*out_vs_min_bytes = entry_valstack_bottom_byteoff + sizeof(duk_tval) * ((duk_size_t) *out_nregs + DUK_VALSTACK_INTERNAL_EXTRA);\n\n\n#if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)\n#if defined(DUK_USE_TAILCALL)\n#error incorrect options: tail calls enabled with function caller property\n#endif\n\t/* XXX: This doesn't actually work properly for tail calls, so\n\t * tail calls are disabled when DUK_USE_NONSTD_FUNC_CALLER_PROPERTY\n\t * is in use.\n\t */\n\tduk__update_func_caller_prop(thr, func);\n#endif\n\n\t/* [ ... this_new | arg1 ... argN ] */\n\n\treturn 1;\n}\n#endif  /* DUK_USE_TAILCALL */\n\nDUK_LOCAL void duk__call_setup_act_not_tailcall(duk_hthread *thr,\n                                                duk_small_uint_t call_flags,\n                                                duk_idx_t idx_func,\n                                                duk_hobject *func,\n                                                duk_size_t entry_valstack_bottom_byteoff,\n                                                duk_size_t entry_valstack_end_byteoff,\n                                                duk_idx_t *out_nargs,\n                                                duk_idx_t *out_nregs,\n                                                duk_size_t *out_vs_min_bytes,\n                                                duk_activation **out_act) {\n\tduk_activation *act;\n\tduk_activation *new_act;\n\n\tDUK_UNREF(entry_valstack_end_byteoff);\n\n\tDUK_DDD(DUK_DDDPRINT(\"not a tail call, pushing a new activation to callstack, to index %ld\",\n\t                     (long) (thr->callstack_top)));\n\n\tduk__call_callstack_limit_check(thr);\n\tnew_act = duk_hthread_activation_alloc(thr);\n\tDUK_ASSERT(new_act != NULL);\n\n\tact = thr->callstack_curr;\n\tif (act != NULL) {\n\t\t/*\n\t\t *  Update return value stack index of current activation (if any).\n\t\t *\n\t\t *  Although it might seem this is not necessary (bytecode executor\n\t\t *  does this for Ecmascript-to-Ecmascript calls; other calls are\n\t\t *  handled here), this turns out to be necessary for handling yield\n\t\t *  and resume.  For them, an Ecmascript-to-native call happens, and\n\t\t *  the Ecmascript call's retval_byteoff must be set for things to work.\n\t\t */\n\n\t\tact->retval_byteoff = entry_valstack_bottom_byteoff + (duk_size_t) idx_func * sizeof(duk_tval);\n\t}\n\n\tnew_act->parent = act;\n\tthr->callstack_curr = new_act;\n\tthr->callstack_top++;\n\tact = new_act;\n\t*out_act = act;\n\n\tDUK_ASSERT(thr->valstack_top > thr->valstack_bottom);  /* at least effective 'this' */\n\tDUK_ASSERT(func == NULL || !DUK_HOBJECT_HAS_BOUNDFUNC(func));\n\n\tact->cat = NULL;\n\n\tact->flags = 0;\n\tif (call_flags & DUK_CALL_FLAG_CONSTRUCT) {\n\t\tact->flags |= DUK_ACT_FLAG_CONSTRUCT;\n\t}\n#if defined(DUK_USE_ES6_PROXY)\n\tif (call_flags & DUK_CALL_FLAG_CONSTRUCT_PROXY) {\n\t\tact->flags |= DUK_ACT_FLAG_CONSTRUCT_PROXY;\n\t}\n#endif\n\tif (call_flags & DUK_CALL_FLAG_DIRECT_EVAL) {\n\t\tact->flags |= DUK_ACT_FLAG_DIRECT_EVAL;\n\t}\n\n\t/* start of arguments: idx_func + 2. */\n\tact->func = func;  /* NULL for lightfunc */\n\tif (DUK_LIKELY(func != NULL)) {\n\t\tDUK_TVAL_SET_OBJECT(&act->tv_func, func);  /* borrowed, no refcount */\n\t\tif (DUK_HOBJECT_HAS_STRICT(func)) {\n\t\t\tact->flags |= DUK_ACT_FLAG_STRICT;\n\t\t}\n\t\tif (DUK_HOBJECT_IS_COMPFUNC(func)) {\n\t\t\t*out_nargs = ((duk_hcompfunc *) func)->nargs;\n\t\t\t*out_nregs = ((duk_hcompfunc *) func)->nregs;\n\t\t\tDUK_ASSERT(*out_nregs >= 0);\n\t\t\tDUK_ASSERT(*out_nregs >= *out_nargs);\n\t\t\t*out_vs_min_bytes = entry_valstack_bottom_byteoff +\n\t\t\t\tsizeof(duk_tval) * ((duk_size_t) idx_func + 2U + (duk_size_t) *out_nregs + DUK_VALSTACK_INTERNAL_EXTRA);\n\t\t} else {\n\t\t\t/* True because of call target lookup checks. */\n\t\t\tDUK_ASSERT(DUK_HOBJECT_IS_NATFUNC(func));\n\n\t\t\t*out_nargs = ((duk_hnatfunc *) func)->nargs;\n\t\t\t*out_nregs = *out_nargs;\n\t\t\tif (*out_nargs >= 0) {\n\t\t\t\t*out_vs_min_bytes = entry_valstack_bottom_byteoff +\n\t\t\t\t\tsizeof(duk_tval) * ((duk_size_t) idx_func + 2U + (duk_size_t) *out_nregs + DUK_VALSTACK_API_ENTRY_MINIMUM + DUK_VALSTACK_INTERNAL_EXTRA);\n\t\t\t} else {\n\t\t\t\t/* Vararg function. */\n\t\t\t\tduk_size_t valstack_top_byteoff = (duk_size_t) ((duk_uint8_t *) thr->valstack_top - ((duk_uint8_t *) thr->valstack));\n\t\t\t\t*out_vs_min_bytes = valstack_top_byteoff +\n\t\t\t\t\tsizeof(duk_tval) * (DUK_VALSTACK_API_ENTRY_MINIMUM + DUK_VALSTACK_INTERNAL_EXTRA);\n\t\t\t}\n\t\t}\n\t} else {\n\t\tduk_small_uint_t lf_flags;\n\t\tduk_tval *tv_func;\n\n\t\tact->flags |= DUK_ACT_FLAG_STRICT;\n\n\t\ttv_func = DUK_GET_TVAL_POSIDX(thr, idx_func);\n\t\tDUK_ASSERT(DUK_TVAL_IS_LIGHTFUNC(tv_func));\n\t\tDUK_TVAL_SET_TVAL(&act->tv_func, tv_func);  /* borrowed, no refcount */\n\n\t\tlf_flags = DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv_func);\n\t\t*out_nargs = DUK_LFUNC_FLAGS_GET_NARGS(lf_flags);\n\t\tif (*out_nargs != DUK_LFUNC_NARGS_VARARGS) {\n\t\t\t*out_vs_min_bytes = entry_valstack_bottom_byteoff +\n\t\t\t\tsizeof(duk_tval) * ((duk_size_t) idx_func + 2U + (duk_size_t) *out_nargs + DUK_VALSTACK_API_ENTRY_MINIMUM + DUK_VALSTACK_INTERNAL_EXTRA);\n\t\t} else {\n\t\t\tduk_size_t valstack_top_byteoff = (duk_size_t) ((duk_uint8_t *) thr->valstack_top - ((duk_uint8_t *) thr->valstack));\n\t\t\t*out_vs_min_bytes = valstack_top_byteoff +\n\t\t\t\tsizeof(duk_tval) * (DUK_VALSTACK_API_ENTRY_MINIMUM + DUK_VALSTACK_INTERNAL_EXTRA);\n\t\t\t*out_nargs = -1;  /* vararg */\n\t\t}\n\t\t*out_nregs = *out_nargs;\n\t}\n\n\tact->var_env = NULL;\n\tact->lex_env = NULL;\n#if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)\n\tact->prev_caller = NULL;\n#endif\n\tact->curr_pc = NULL;\n#if defined(DUK_USE_DEBUGGER_SUPPORT)\n\tact->prev_line = 0;\n#endif\n\tact->bottom_byteoff = entry_valstack_bottom_byteoff + sizeof(duk_tval) * ((duk_size_t) idx_func + 2U);\n#if 0\n\tact->retval_byteoff = 0;   /* topmost activation retval_byteoff is considered garbage, no need to init */\n#endif\n\t/* Filled in when final reserve is known, dummy value doesn't matter\n\t * even in error unwind because reserve_byteoff is only used when\n\t * returning to -this- activation.\n\t */\n\tact->reserve_byteoff = 0;  /* filled in by caller */\n\n\t/* XXX: Is this INCREF necessary? 'func' is always a borrowed\n\t * reference reachable through the value stack?  If changed, stack\n\t * unwind code also needs to be fixed to match.\n\t */\n\tDUK_HOBJECT_INCREF_ALLOWNULL(thr, func);  /* act->func */\n\n#if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)\n\tif (func) {\n\t\tduk__update_func_caller_prop(thr, func);\n\t}\n#endif\n}\n\n/*\n *  Environment setup.\n */\n\nDUK_LOCAL void duk__call_env_setup(duk_hthread *thr, duk_hobject *func, duk_activation *act, duk_idx_t idx_args) {\n\tduk_hobject *env;\n\n\tDUK_ASSERT(func == NULL || !DUK_HOBJECT_HAS_BOUNDFUNC(func));  /* bound function has already been resolved */\n\n\tif (DUK_LIKELY(func != NULL)) {\n\t\tif (DUK_LIKELY(DUK_HOBJECT_HAS_NEWENV(func))) {\n\t\t\tif (DUK_LIKELY(!DUK_HOBJECT_HAS_CREATEARGS(func))) {\n\t\t\t\t/* Use a new environment but there's no 'arguments' object;\n\t\t\t\t * delayed environment initialization.  This is the most\n\t\t\t\t * common case.\n\t\t\t\t */\n\t\t\t\tDUK_ASSERT(act->lex_env == NULL);\n\t\t\t\tDUK_ASSERT(act->var_env == NULL);\n\t\t\t} else {\n\t\t\t\t/* Use a new environment and there's an 'arguments' object.\n\t\t\t\t * We need to initialize it right now.\n\t\t\t\t */\n\n\t\t\t\t/* third arg: absolute index (to entire valstack) of bottom_byteoff of new activation */\n\t\t\t\tenv = duk_create_activation_environment_record(thr, func, act->bottom_byteoff);\n\t\t\t\tDUK_ASSERT(env != NULL);\n\n\t\t\t\t/* [ ... func this arg1 ... argN envobj ] */\n\n\t\t\t\tDUK_ASSERT(DUK_HOBJECT_HAS_CREATEARGS(func));\n\t\t\t\tduk__handle_createargs_for_call(thr, func, env, idx_args);\n\n\t\t\t\t/* [ ... func this arg1 ... argN envobj ] */\n\n\t\t\t\tact->lex_env = env;\n\t\t\t\tact->var_env = env;\n\t\t\t\tDUK_HOBJECT_INCREF(thr, env);\n\t\t\t\tDUK_HOBJECT_INCREF(thr, env);  /* XXX: incref by count (2) directly */\n\t\t\t\tduk_pop(thr);\n\t\t\t}\n\t\t} else {\n\t\t\t/* Use existing env (e.g. for non-strict eval); cannot have\n\t\t\t * an own 'arguments' object (but can refer to an existing one).\n\t\t\t */\n\n\t\t\tDUK_ASSERT(!DUK_HOBJECT_HAS_CREATEARGS(func));\n\n\t\t\tduk__handle_oldenv_for_call(thr, func, act);\n\n\t\t\tDUK_ASSERT(act->lex_env != NULL);\n\t\t\tDUK_ASSERT(act->var_env != NULL);\n\t\t}\n\t} else {\n\t\t/* Lightfuncs are always native functions and have \"newenv\". */\n\t\tDUK_ASSERT(act->lex_env == NULL);\n\t\tDUK_ASSERT(act->var_env == NULL);\n\t}\n}\n\n/*\n *  Misc shared helpers.\n */\n\n/* Check thread state, update current thread. */\nDUK_LOCAL void duk__call_thread_state_update(duk_hthread *thr) {\n\tDUK_ASSERT(thr != NULL);\n\n\tif (DUK_LIKELY(thr == thr->heap->curr_thread)) {\n\t\tif (DUK_UNLIKELY(thr->state != DUK_HTHREAD_STATE_RUNNING)) {\n\t\t\t/* Should actually never happen, but check anyway. */\n\t\t\tgoto thread_state_error;\n\t\t}\n\t} else {\n\t\tDUK_ASSERT(thr->heap->curr_thread == NULL ||\n\t\t           thr->heap->curr_thread->state == DUK_HTHREAD_STATE_RUNNING);\n\t\tif (DUK_UNLIKELY(thr->state != DUK_HTHREAD_STATE_INACTIVE)) {\n\t\t\tgoto thread_state_error;\n\t\t}\n\t\tDUK_HEAP_SWITCH_THREAD(thr->heap, thr);\n\t\tthr->state = DUK_HTHREAD_STATE_RUNNING;\n\n\t\t/* Multiple threads may be simultaneously in the RUNNING\n\t\t * state, but not in the same \"resume chain\".\n\t\t */\n\t}\n\tDUK_ASSERT(thr->heap->curr_thread == thr);\n\tDUK_ASSERT(thr->state == DUK_HTHREAD_STATE_RUNNING);\n\treturn;\n\n thread_state_error:\n\tDUK_ERROR_FMT1(thr, DUK_ERR_TYPE_ERROR, \"invalid thread state (%ld)\", (long) thr->state);\n\tDUK_UNREACHABLE();\n}\n\n/*\n *  Main unprotected call handler, handles:\n *\n *    - All combinations of native/Ecmascript caller and native/Ecmascript\n *      target.\n *\n *    - Optimized Ecmascript-to-Ecmascript call where call handling only\n *      sets up a new duk_activation but reuses an existing bytecode executor\n *      (the caller) without native recursion.\n *\n *    - Tailcalls, where an activation is reused without increasing call\n *      stack (duk_activation) depth.\n *\n *    - Setup for an initial Duktape.Thread.resume().\n *\n *  The call handler doesn't provide any protection guarantees, protected calls\n *  must be implemented e.g. by wrapping the call in a duk_safe_call().\n *  Call setup may fail at any stage, even when the new activation is in\n *  place; the only guarantee is that the state is consistent for unwinding.\n */\n\nDUK_LOCAL duk_int_t duk__handle_call_raw(duk_hthread *thr,\n                                         duk_idx_t idx_func,\n                                         duk_small_uint_t call_flags) {\n#if defined(DUK_USE_ASSERTIONS)\n\tduk_activation *entry_act;\n\tduk_size_t entry_callstack_top;\n#endif\n\tduk_size_t entry_valstack_bottom_byteoff;\n\tduk_size_t entry_valstack_end_byteoff;\n\tduk_int_t entry_call_recursion_depth;\n\tduk_hthread *entry_curr_thread;\n\tduk_uint_fast8_t entry_thread_state;\n\tduk_instr_t **entry_ptr_curr_pc;\n\tduk_idx_t idx_args;\n\tduk_idx_t nargs;            /* # argument registers target function wants (< 0 => \"as is\") */\n\tduk_idx_t nregs;            /* # total registers target function wants on entry (< 0 => \"as is\") */\n\tduk_size_t vs_min_bytes;    /* minimum value stack size (bytes) for handling call */\n\tduk_hobject *func;          /* 'func' on stack (borrowed reference) */\n\tduk_activation *act;\n\tduk_ret_t rc;\n\tduk_small_uint_t use_tailcall;\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(thr->heap != NULL);\n\t/* Asserts for heap->curr_thread omitted: it may be NULL, 'thr', or\n\t * any other thread (e.g. when heap thread is used to run finalizers).\n\t */\n\tDUK_ASSERT_CTX_VALID(thr);\n\tDUK_ASSERT(duk_is_valid_index(thr, idx_func));\n\tDUK_ASSERT(idx_func >= 0);\n\n\tDUK_STATS_INC(thr->heap, stats_call_all);\n\n\t/* If a tail call:\n\t *   - an Ecmascript activation must be on top of the callstack\n\t *   - there cannot be any catch stack entries that would catch\n\t *     a return\n\t */\n#if defined(DUK_USE_ASSERTIONS)\n\tif (call_flags & DUK_CALL_FLAG_TAILCALL) {\n\t\tduk_activation *tmp_act;\n\t\tduk_catcher *tmp_cat;\n\n\t\tDUK_ASSERT(thr->callstack_top >= 1);\n\t\tDUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack_curr) != NULL);\n\t\tDUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(thr->callstack_curr)));\n\n\t\t/* No entry in the catch stack which would actually catch a\n\t\t * throw can refer to the callstack entry being reused.\n\t\t * There *can* be catch stack entries referring to the current\n\t\t * callstack entry as long as they don't catch (e.g. label sites).\n\t\t */\n\n\t\ttmp_act = thr->callstack_curr;\n\t\tfor (tmp_cat = tmp_act->cat; tmp_cat != NULL; tmp_cat = tmp_cat->parent) {\n\t\t\tDUK_ASSERT(DUK_CAT_GET_TYPE(tmp_cat) == DUK_CAT_TYPE_LABEL); /* a non-catching entry */\n\t\t}\n\t}\n#endif  /* DUK_USE_ASSERTIONS */\n\n\t/*\n\t *  Store entry state.\n\t */\n\n#if defined(DUK_USE_ASSERTIONS)\n\tentry_act = thr->callstack_curr;\n\tentry_callstack_top = thr->callstack_top;\n#endif\n\tentry_valstack_bottom_byteoff = (duk_size_t) ((duk_uint8_t *) thr->valstack_bottom - (duk_uint8_t *) thr->valstack);\n\tentry_valstack_end_byteoff = (duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack);\n\tentry_call_recursion_depth = thr->heap->call_recursion_depth;\n\tentry_curr_thread = thr->heap->curr_thread;  /* may be NULL if first call */\n\tentry_thread_state = thr->state;\n\tentry_ptr_curr_pc = thr->ptr_curr_pc;  /* may be NULL */\n\n\t/* If thr->ptr_curr_pc is set, sync curr_pc to act->pc.  Then NULL\n\t * thr->ptr_curr_pc so that it's not accidentally used with an incorrect\n\t * activation when side effects occur.\n\t */\n\tduk_hthread_sync_and_null_currpc(thr);\n\tDUK_ASSERT(thr->ptr_curr_pc == NULL);\n\n\tDUK_DD(DUK_DDPRINT(\"duk__handle_call_raw: thr=%p, idx_func=%ld, \"\n\t                   \"call_flags=0x%08lx (constructor=%ld), \"\n\t                   \"valstack_top=%ld, idx_func=%ld, idx_args=%ld, rec_depth=%ld/%ld, \"\n\t                   \"entry_valstack_bottom_byteoff=%ld, entry_valstack_end_byteoff=%ld, \"\n\t                   \"entry_call_recursion_depth=%ld, \"\n\t                   \"entry_curr_thread=%p, entry_thread_state=%ld\",\n\t                   (void *) thr,\n\t                   (long) idx_func,\n\t                   (unsigned long) call_flags,\n\t                   (long) ((call_flags & DUK_CALL_FLAG_CONSTRUCT) != 0 ? 1 : 0),\n\t                   (long) duk_get_top(thr),\n\t                   (long) idx_func,\n\t                   (long) (idx_func + 2),\n\t                   (long) thr->heap->call_recursion_depth,\n\t                   (long) thr->heap->call_recursion_limit,\n\t                   (long) entry_valstack_bottom_byteoff,\n\t                   (long) entry_valstack_end_byteoff,\n\t                   (long) entry_call_recursion_depth,\n\t                   (void *) entry_curr_thread,\n\t                   (long) entry_thread_state));\n\n\t/*\n\t *  Thread state check and book-keeping.\n\t */\n\n\tduk__call_thread_state_update(thr);\n\n\t/*\n\t *  Resolve final target function; handle bound functions and special\n\t *  functions like .call() and .apply().  Also figure out the effective\n\t *  'this' binding, which replaces the current value at idx_func + 1.\n\t */\n\n\tif (DUK_LIKELY(duk__resolve_target_fastpath_check(thr, idx_func, &func, call_flags) != 0U)) {\n\t\tDUK_DDD(DUK_DDDPRINT(\"fast path target resolve\"));\n\t} else {\n\t\tDUK_DDD(DUK_DDDPRINT(\"slow path target resolve\"));\n\t\tfunc = duk__resolve_target_func_and_this_binding(thr, idx_func, &call_flags);\n\t}\n\tDUK_ASSERT(duk_get_top(thr) - idx_func >= 2);  /* at least func and this present */\n\n\tDUK_ASSERT(func == NULL || !DUK_HOBJECT_HAS_BOUNDFUNC(func));\n\tDUK_ASSERT(func == NULL || (DUK_HOBJECT_IS_COMPFUNC(func) ||\n\t                            DUK_HOBJECT_IS_NATFUNC(func)));\n\n\t/* [ ... func this arg1 ... argN ] */\n\n\t/*\n\t *  Setup a preliminary activation and figure out nargs/nregs and\n\t *  value stack minimum size.\n\t *\n\t *  Don't touch valstack_bottom or valstack_top yet so that Duktape API\n\t *  calls work normally.\n\t *\n\t *  Because 'act' is not zeroed, all fields must be filled in.\n\t */\n\n#if defined(DUK_USE_TAILCALL)\n\tuse_tailcall = (call_flags & DUK_CALL_FLAG_TAILCALL);\n\tif (use_tailcall) {\n\t\tuse_tailcall = duk__call_setup_act_attempt_tailcall(thr,\n\t\t                                                    call_flags,\n\t\t                                                    idx_func,\n\t\t                                                    func,\n\t\t                                                    entry_valstack_bottom_byteoff,\n\t\t                                                    entry_valstack_end_byteoff,\n\t\t                                                    &nargs,\n\t\t                                                    &nregs,\n\t\t                                                    &vs_min_bytes,\n\t\t                                                    &act);\n\t}\n#else\n\tDUK_ASSERT((call_flags & DUK_CALL_FLAG_TAILCALL) == 0);  /* compiler ensures this */\n\tuse_tailcall = 0;\n#endif\n\n\tif (use_tailcall) {\n\t\tidx_args = 0;\n\t\tDUK_STATS_INC(thr->heap, stats_call_tailcall);\n\t} else {\n\t\tduk__call_setup_act_not_tailcall(thr,\n\t\t                                 call_flags,\n\t\t                                 idx_func,\n\t\t                                 func,\n\t\t                                 entry_valstack_bottom_byteoff,\n\t\t                                 entry_valstack_end_byteoff,\n\t\t                                 &nargs,\n\t\t                                 &nregs,\n\t\t                                 &vs_min_bytes,\n\t\t                                 &act);\n\t\tidx_args = idx_func + 2;\n\t}\n\t/* After this point idx_func is no longer valid for tailcalls. */\n\n\tDUK_ASSERT(act != NULL);\n\n\t/* [ ... func this arg1 ... argN ] */\n\n\t/*\n\t *  Environment record creation and 'arguments' object creation.\n\t *  Named function expression name binding is handled by the\n\t *  compiler; the compiled function's parent env will contain\n\t *  the (immutable) binding already.\n\t *\n\t *  This handling is now identical for C and Ecmascript functions.\n\t *  C functions always have the 'NEWENV' flag set, so their\n\t *  environment record initialization is delayed (which is good).\n\t *\n\t *  Delayed creation (on demand) is handled in duk_js_var.c.\n\t */\n\n\tduk__call_env_setup(thr, func, act, idx_args);\n\n\t/* [ ... func this arg1 ... argN ] */\n\n\t/*\n\t *  Setup value stack: clamp to 'nargs', fill up to 'nregs',\n\t *  ensure value stack size matches target requirements, and\n\t *  switch value stack bottom.  Valstack top is kept.\n\t *\n\t *  Value stack can only grow here.\n\t */\n\n\tduk_valstack_grow_check_throw(thr, vs_min_bytes);\n\tact->reserve_byteoff = (duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack);\n\n\tif (use_tailcall) {\n\t\tDUK_ASSERT(nregs >= 0);\n\t\tDUK_ASSERT(nregs >= nargs);\n\t\tduk_set_top_and_wipe(thr, nregs, nargs);\n\t} else {\n\t\tif (nregs >= 0) {\n\t\t\tDUK_ASSERT(nregs >= nargs);\n\t\t\tduk_set_top_and_wipe(thr, idx_func + 2 + nregs, idx_func + 2 + nargs);\n\t\t} else {\n\t\t\t;\n\t\t}\n\t\tthr->valstack_bottom = thr->valstack_bottom + idx_func + 2;\n\t}\n\tDUK_ASSERT(thr->valstack_bottom >= thr->valstack);\n\tDUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);\n\tDUK_ASSERT(thr->valstack_end >= thr->valstack_top);\n\n\t/*\n\t *  Make the actual call.  For Ecma-to-Ecma calls detect that\n\t *  setup is complete, then return with a status code that allows\n\t *  the caller to reuse the running executor.\n\t */\n\n\tif (func != NULL && DUK_HOBJECT_IS_COMPFUNC(func)) {\n\t\t/*\n\t\t *  Ecmascript call.\n\t\t */\n\n\t\tDUK_ASSERT(func != NULL);\n\t\tDUK_ASSERT(DUK_HOBJECT_HAS_COMPFUNC(func));\n\t\tact->curr_pc = DUK_HCOMPFUNC_GET_CODE_BASE(thr->heap, (duk_hcompfunc *) func);\n\n\t\tif (call_flags & DUK_CALL_FLAG_ALLOW_ECMATOECMA) {\n\t\t\tDUK_DD(DUK_DDPRINT(\"avoid native call, use existing executor\"));\n\t\t\tDUK_STATS_INC(thr->heap, stats_call_ecmatoecma);\n\t\t\tDUK_ASSERT((act->flags & DUK_ACT_FLAG_PREVENT_YIELD) == 0);\n\t\t\tDUK_REFZERO_CHECK_FAST(thr);\n\t\t\tDUK_ASSERT(thr->ptr_curr_pc == NULL);\n\t\t\treturn 1;  /* 1=reuse executor */\n\t\t}\n\t\tDUK_ASSERT(use_tailcall == 0);\n\n\t\t/* duk_hthread_activation_unwind_norz() will decrease this on unwind */\n\t\tDUK_ASSERT((act->flags & DUK_ACT_FLAG_PREVENT_YIELD) == 0);\n\t\tact->flags |= DUK_ACT_FLAG_PREVENT_YIELD;\n\t\tthr->callstack_preventcount++;\n\n\t\t/* XXX: we could just do this on entry regardless of reuse, as long\n\t\t * as recursion depth is decreased for e2e case.\n\t\t */\n\t\tduk__call_c_recursion_limit_check(thr);\n\t\tthr->heap->call_recursion_depth++;\n\n\t\t/* [ ... func this | arg1 ... argN ] ('this' must precede new bottom) */\n\n\t\t/*\n\t\t *  Bytecode executor call.\n\t\t *\n\t\t *  Execute bytecode, handling any recursive function calls and\n\t\t *  thread resumptions.  Returns when execution would return from\n\t\t *  the entry level activation.  When the executor returns, a\n\t\t *  single return value is left on the stack top.\n\t\t *\n\t\t *  The only possible longjmp() is an error (DUK_LJ_TYPE_THROW),\n\t\t *  other types are handled internally by the executor.\n\t\t */\n\n\t\t/* thr->ptr_curr_pc is set by bytecode executor early on entry */\n\t\tDUK_ASSERT(thr->ptr_curr_pc == NULL);\n\t\tDUK_DDD(DUK_DDDPRINT(\"entering bytecode execution\"));\n\t\tduk_js_execute_bytecode(thr);\n\t\tDUK_DDD(DUK_DDDPRINT(\"returned from bytecode execution\"));\n\t} else {\n\t\t/*\n\t\t *  Native call.\n\t\t */\n\n\t\tDUK_ASSERT(func == NULL || ((duk_hnatfunc *) func)->func != NULL);\n\t\tDUK_ASSERT(use_tailcall == 0);\n\n\t\t/* [ ... func this | arg1 ... argN ] ('this' must precede new bottom) */\n\n\t\t/* duk_hthread_activation_unwind_norz() will decrease this on unwind */\n\t\tDUK_ASSERT((act->flags & DUK_ACT_FLAG_PREVENT_YIELD) == 0);\n\t\tact->flags |= DUK_ACT_FLAG_PREVENT_YIELD;\n\t\tthr->callstack_preventcount++;\n\n\t\t/* XXX: we could just do this on entry regardless of reuse, as long\n\t\t * as recursion depth is decreased for e2e case.\n\t\t */\n\t\tduk__call_c_recursion_limit_check(thr);\n\t\tthr->heap->call_recursion_depth++;\n\n\t\t/* For native calls must be NULL so we don't sync back */\n\t\tDUK_ASSERT(thr->ptr_curr_pc == NULL);\n\n\t\t/* XXX: native funcptr could come out of call setup. */\n\t\tif (func) {\n\t\t\trc = ((duk_hnatfunc *) func)->func(thr);\n\t\t} else {\n\t\t\tduk_tval *tv_func;\n\t\t\tduk_c_function funcptr;\n\n\t\t\ttv_func = &act->tv_func;\n\t\t\tDUK_ASSERT(DUK_TVAL_IS_LIGHTFUNC(tv_func));\n\t\t\tfuncptr = DUK_TVAL_GET_LIGHTFUNC_FUNCPTR(tv_func);\n\t\t\trc = funcptr(thr);\n\t\t}\n\n\t\t/* Automatic error throwing, retval check. */\n\n\t\tif (rc == 0) {\n\t\t\tDUK_ASSERT(thr->valstack < thr->valstack_end);\n\t\t\tDUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top));\n\t\t\tthr->valstack_top++;\n\t\t} else if (rc == 1) {\n\t\t\t;\n\t\t} else if (rc < 0) {\n\t\t\tduk_error_throw_from_negative_rc(thr, rc);\n\t\t\tDUK_UNREACHABLE();\n\t\t} else {\n\t\t\tDUK_ERROR_TYPE(thr, DUK_STR_INVALID_CFUNC_RC);\n\t\t}\n\t}\n\tDUK_ASSERT(thr->ptr_curr_pc == NULL);\n\tDUK_ASSERT(use_tailcall == 0);\n\n\t/*\n\t *  Constructor call post processing.\n\t */\n\n#if defined(DUK_USE_ES6_PROXY)\n\tif (call_flags & (DUK_CALL_FLAG_CONSTRUCT | DUK_CALL_FLAG_CONSTRUCT_PROXY)) {\n\t\tduk_call_construct_postprocess(thr, call_flags & DUK_CALL_FLAG_CONSTRUCT_PROXY);\n\t}\n#else\n\tif (call_flags & DUK_CALL_FLAG_CONSTRUCT) {\n\t\tduk_call_construct_postprocess(thr, 0);\n\t}\n#endif\n\n\t/*\n\t *  Unwind, restore valstack bottom and other book-keeping.\n\t */\n\n\tDUK_ASSERT(thr->callstack_curr != NULL);\n\tDUK_ASSERT(thr->callstack_curr->parent == entry_act);\n\tDUK_ASSERT(thr->callstack_top == entry_callstack_top + 1);\n\tduk_hthread_activation_unwind_norz(thr);\n\tDUK_ASSERT(thr->callstack_curr == entry_act);\n\tDUK_ASSERT(thr->callstack_top == entry_callstack_top);\n\n\tthr->valstack_bottom = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + entry_valstack_bottom_byteoff);\n\t/* keep current valstack_top */\n\tDUK_ASSERT(thr->valstack_bottom >= thr->valstack);\n\tDUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);\n\tDUK_ASSERT(thr->valstack_end >= thr->valstack_top);\n\tDUK_ASSERT(thr->valstack_top - thr->valstack_bottom >= idx_func + 1);\n\n\t/* Return value handling. */\n\n\t/* [ ... func this (crud) retval ] */\n\n\t{\n\t\tduk_tval *tv_ret;\n\t\tduk_tval *tv_funret;\n\n\t\ttv_ret = thr->valstack_bottom + idx_func;\n\t\ttv_funret = thr->valstack_top - 1;\n#if defined(DUK_USE_FASTINT)\n\t\t/* Explicit check for fastint downgrade. */\n\t\tDUK_TVAL_CHKFAST_INPLACE_FAST(tv_funret);\n#endif\n\t\tDUK_TVAL_SET_TVAL_UPDREF(thr, tv_ret, tv_funret);  /* side effects */\n\t}\n\n\tduk_set_top_unsafe(thr, idx_func + 1);\n\n\t/* [ ... retval ] */\n\n\t/* Restore caller's value stack reserve (cannot fail). */\n\tDUK_ASSERT((duk_uint8_t *) thr->valstack + entry_valstack_end_byteoff >= (duk_uint8_t *) thr->valstack_top);\n\tDUK_ASSERT((duk_uint8_t *) thr->valstack + entry_valstack_end_byteoff <= (duk_uint8_t *) thr->valstack_alloc_end);\n\tthr->valstack_end = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + entry_valstack_end_byteoff);\n\n\t/* XXX: Trial value stack shrink would be OK here, but we'd need\n\t * to prevent side effects of the potential realloc.\n\t */\n\n\t/* Restore entry thread executor curr_pc stack frame pointer. */\n\tthr->ptr_curr_pc = entry_ptr_curr_pc;\n\n\tDUK_HEAP_SWITCH_THREAD(thr->heap, entry_curr_thread);  /* may be NULL */\n\tthr->state = (duk_uint8_t) entry_thread_state;\n\n\t/* Disabled assert: triggered with some torture tests. */\n#if 0\n\tDUK_ASSERT((thr->state == DUK_HTHREAD_STATE_INACTIVE && thr->heap->curr_thread == NULL) ||  /* first call */\n\t           (thr->state == DUK_HTHREAD_STATE_INACTIVE && thr->heap->curr_thread != NULL) ||  /* other call */\n\t           (thr->state == DUK_HTHREAD_STATE_RUNNING && thr->heap->curr_thread == thr));     /* current thread */\n#endif\n\n\tthr->heap->call_recursion_depth = entry_call_recursion_depth;\n\n\t/* If the debugger is active we need to force an interrupt so that\n\t * debugger breakpoints are rechecked.  This is important for function\n\t * calls caused by side effects (e.g. when doing a DUK_OP_GETPROP), see\n\t * GH-303.  Only needed for success path, error path always causes a\n\t * breakpoint recheck in the executor.  It would be enough to set this\n\t * only when returning to an Ecmascript activation, but setting the flag\n\t * on every return should have no ill effect.\n\t */\n#if defined(DUK_USE_DEBUGGER_SUPPORT)\n\tif (duk_debug_is_attached(thr->heap)) {\n\t\tDUK_DD(DUK_DDPRINT(\"returning with debugger enabled, force interrupt\"));\n\t\tDUK_ASSERT(thr->interrupt_counter <= thr->interrupt_init);\n\t\tthr->interrupt_init -= thr->interrupt_counter;\n\t\tthr->interrupt_counter = 0;\n\t\tthr->heap->dbg_force_restart = 1;\n\t}\n#endif\n\n#if defined(DUK_USE_INTERRUPT_COUNTER) && defined(DUK_USE_DEBUG)\n\tduk__interrupt_fixup(thr, entry_curr_thread);\n#endif\n\n\t/* Restored by success path. */\n\tDUK_ASSERT(thr->heap->call_recursion_depth == entry_call_recursion_depth);\n\tDUK_ASSERT(thr->ptr_curr_pc == entry_ptr_curr_pc);\n\tDUK_ASSERT_LJSTATE_UNSET(thr->heap);\n\n\tDUK_REFZERO_CHECK_FAST(thr);\n\n\treturn 0;  /* 0=call handled inline */\n}\n\nDUK_INTERNAL duk_int_t duk_handle_call_unprotected_nargs(duk_hthread *thr,\n                                                         duk_idx_t nargs,\n                                                         duk_small_uint_t call_flags) {\n\tduk_idx_t idx_func;\n\tDUK_ASSERT(duk_get_top(thr) >= nargs + 2);\n\tidx_func = duk_get_top(thr) - (nargs + 2);\n\tDUK_ASSERT(idx_func >= 0);\n\treturn duk_handle_call_unprotected(thr, idx_func, call_flags);\n}\n\nDUK_INTERNAL duk_int_t duk_handle_call_unprotected(duk_hthread *thr,\n                                                   duk_idx_t idx_func,\n                                                   duk_small_uint_t call_flags) {\n\tDUK_ASSERT(duk_is_valid_index(thr, idx_func));\n\tDUK_ASSERT(idx_func >= 0);\n\treturn duk__handle_call_raw(thr, idx_func, call_flags);\n}\n\n/*\n *  duk_handle_safe_call(): make a \"C protected call\" within the\n *  current activation.\n *\n *  The allowed thread states for making a call are the same as for\n *  duk_handle_call_protected().\n *\n *  Even though this call is protected, errors are thrown for insane arguments\n *  and may result in a fatal error unless there's another protected call which\n *  catches such errors.\n *\n *  The error handling path should be error free, even for out-of-memory\n *  errors, to ensure safe sandboxing.  (As of Duktape 2.2.0 this is not\n *  yet the case for environment closing which may run out of memory, see\n *  XXX notes below.)\n */\n\nDUK_LOCAL void duk__handle_safe_call_inner(duk_hthread *thr,\n                                           duk_safe_call_function func,\n                                           void *udata,\n#if defined(DUK_USE_ASSERTIONS)\n                                           duk_size_t entry_valstack_bottom_byteoff,\n                                           duk_size_t entry_callstack_top,\n#endif\n                                           duk_hthread *entry_curr_thread,\n                                           duk_uint_fast8_t entry_thread_state,\n                                           duk_idx_t idx_retbase,\n                                           duk_idx_t num_stack_rets) {\n\tduk_ret_t rc;\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT_CTX_VALID(thr);\n\n\t/*\n\t *  Thread state check and book-keeping.\n\t */\n\n\tduk__call_thread_state_update(thr);\n\n\t/*\n\t *  Recursion limit check.\n\t */\n\n\tduk__call_c_recursion_limit_check(thr);\n\tthr->heap->call_recursion_depth++;\n\n\t/*\n\t *  Make the C call.\n\t */\n\n\trc = func(thr, udata);\n\n\tDUK_DDD(DUK_DDDPRINT(\"safe_call, func rc=%ld\", (long) rc));\n\n\t/*\n\t *  Valstack manipulation for results.\n\t */\n\n\t/* we're running inside the caller's activation, so no change in call/catch stack or valstack bottom */\n\tDUK_ASSERT(thr->callstack_top == entry_callstack_top);\n\tDUK_ASSERT(thr->valstack_bottom >= thr->valstack);\n\tDUK_ASSERT((duk_size_t) ((duk_uint8_t *) thr->valstack_bottom - (duk_uint8_t *) thr->valstack) == entry_valstack_bottom_byteoff);\n\tDUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);\n\tDUK_ASSERT(thr->valstack_end >= thr->valstack_top);\n\n\tif (DUK_UNLIKELY(rc < 0)) {\n\t\tduk_error_throw_from_negative_rc(thr, rc);\n\t}\n\tDUK_ASSERT(rc >= 0);\n\n\tduk__safe_call_adjust_valstack(thr, idx_retbase, num_stack_rets, rc);  /* throws for insane rc */\n\n\tDUK_HEAP_SWITCH_THREAD(thr->heap, entry_curr_thread);  /* may be NULL */\n\tthr->state = (duk_uint8_t) entry_thread_state;\n}\n\nDUK_LOCAL void duk__handle_safe_call_error(duk_hthread *thr,\n                                           duk_activation *entry_act,\n#if defined(DUK_USE_ASSERTIONS)\n                                           duk_size_t entry_callstack_top,\n#endif\n                                           duk_hthread *entry_curr_thread,\n                                           duk_uint_fast8_t entry_thread_state,\n                                           duk_idx_t idx_retbase,\n                                           duk_idx_t num_stack_rets,\n                                           duk_size_t entry_valstack_bottom_byteoff,\n                                           duk_jmpbuf *old_jmpbuf_ptr) {\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT_CTX_VALID(thr);\n\n\t/*\n\t *  Error during call.  The error value is at heap->lj.value1.\n\t *\n\t *  The very first thing we do is restore the previous setjmp catcher.\n\t *  This means that any error in error handling will propagate outwards\n\t *  instead of causing a setjmp() re-entry above.\n\t */\n\n\tDUK_DDD(DUK_DDDPRINT(\"error caught during protected duk_handle_safe_call()\"));\n\n\t/* Other longjmp types are handled by executor before propagating\n\t * the error here.\n\t */\n\tDUK_ASSERT(thr->heap->lj.type == DUK_LJ_TYPE_THROW);\n\tDUK_ASSERT_LJSTATE_SET(thr->heap);\n\n\t/* Either pointer may be NULL (at entry), so don't assert. */\n\tthr->heap->lj.jmpbuf_ptr = old_jmpbuf_ptr;\n\n\t/* XXX: callstack unwind may now throw an error when closing\n\t * scopes; this is a sandboxing issue, described in:\n\t * https://github.com/svaarala/duktape/issues/476\n\t */\n\t/* XXX: \"unwind to\" primitive? */\n\n\tDUK_ASSERT(thr->callstack_top >= entry_callstack_top);\n\twhile (thr->callstack_curr != entry_act) {\n\t\tDUK_ASSERT(thr->callstack_curr != NULL);\n\t\tduk_hthread_activation_unwind_norz(thr);\n\t}\n\tDUK_ASSERT(thr->callstack_top == entry_callstack_top);\n\n\t/* Switch active thread before any side effects to avoid a\n\t * dangling curr_thread pointer.\n\t */\n\tDUK_HEAP_SWITCH_THREAD(thr->heap, entry_curr_thread);  /* may be NULL */\n\tthr->state = (duk_uint8_t) entry_thread_state;\n\n\tDUK_ASSERT(thr->heap->curr_thread == entry_curr_thread);\n\tDUK_ASSERT(thr->state == entry_thread_state);\n\n\t/* Restore valstack bottom. */\n\tthr->valstack_bottom = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + entry_valstack_bottom_byteoff);\n\n\t/* [ ... | (crud) ] */\n\n\t/* XXX: ensure space in valstack (now relies on internal reserve)? */\n\tduk_push_tval(thr, &thr->heap->lj.value1);\n\n\t/* [ ... | (crud) errobj ] */\n\n\tDUK_ASSERT(duk_get_top(thr) >= 1);  /* at least errobj must be on stack */\n\n\tduk__safe_call_adjust_valstack(thr, idx_retbase, num_stack_rets, 1);  /* 1 = num actual 'return values' */\n\n\t/* [ ... | ] or [ ... | errobj (M * undefined)] where M = num_stack_rets - 1 */\n\n\t/* Reset longjmp state. */\n\tthr->heap->lj.type = DUK_LJ_TYPE_UNKNOWN;\n\tthr->heap->lj.iserror = 0;\n\tDUK_TVAL_SET_UNDEFINED_UPDREF_NORZ(thr, &thr->heap->lj.value1);\n\tDUK_TVAL_SET_UNDEFINED_UPDREF_NORZ(thr, &thr->heap->lj.value2);\n\n\t/* Error handling complete, remove side effect protections.  Caller\n\t * will process pending finalizers.\n\t */\n#if defined(DUK_USE_ASSERTIONS)\n\tDUK_ASSERT(thr->heap->error_not_allowed == 1);\n\tthr->heap->error_not_allowed = 0;\n#endif\n\tDUK_ASSERT(thr->heap->pf_prevent_count > 0);\n\tthr->heap->pf_prevent_count--;\n\tDUK_DD(DUK_DDPRINT(\"safe call error handled, pf_prevent_count updated to %ld\", (long) thr->heap->pf_prevent_count));\n\n\t/* thr->ptr_curr_pc is restored by\n\t * duk__handle_safe_call_shared_unwind() which is also used for\n\t * success path.\n\t */\n}\n\nDUK_LOCAL void duk__handle_safe_call_shared_unwind(duk_hthread *thr,\n                                                   duk_idx_t idx_retbase,\n                                                   duk_idx_t num_stack_rets,\n#if defined(DUK_USE_ASSERTIONS)\n                                                   duk_size_t entry_callstack_top,\n#endif\n                                                   duk_int_t entry_call_recursion_depth,\n                                                   duk_hthread *entry_curr_thread,\n                                                   duk_instr_t **entry_ptr_curr_pc) {\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT_CTX_VALID(thr);\n\tDUK_UNREF(idx_retbase);\n\tDUK_UNREF(num_stack_rets);\n\tDUK_UNREF(entry_curr_thread);\n\n\tDUK_ASSERT(thr->callstack_top == entry_callstack_top);\n\n\t/* Restore entry thread executor curr_pc stack frame pointer.\n\t * XXX: would be enough to do in error path only, should nest\n\t * cleanly in success path.\n\t */\n\tthr->ptr_curr_pc = entry_ptr_curr_pc;\n\n\tthr->heap->call_recursion_depth = entry_call_recursion_depth;\n\n\t/* stack discipline consistency check */\n\tDUK_ASSERT(duk_get_top(thr) == idx_retbase + num_stack_rets);\n\n\t/* A debugger forced interrupt check is not needed here, as\n\t * problematic safe calls are not caused by side effects.\n\t */\n\n#if defined(DUK_USE_INTERRUPT_COUNTER) && defined(DUK_USE_DEBUG)\n\tduk__interrupt_fixup(thr, entry_curr_thread);\n#endif\n}\n\nDUK_INTERNAL duk_int_t duk_handle_safe_call(duk_hthread *thr,\n                                            duk_safe_call_function func,\n                                            void *udata,\n                                            duk_idx_t num_stack_args,\n                                            duk_idx_t num_stack_rets) {\n\tduk_activation *entry_act;\n\tduk_size_t entry_valstack_bottom_byteoff;\n#if defined(DUK_USE_ASSERTIONS)\n\tduk_size_t entry_valstack_end_byteoff;\n\tduk_size_t entry_callstack_top;\n\tduk_size_t entry_callstack_preventcount;\n#endif\n\tduk_int_t entry_call_recursion_depth;\n\tduk_hthread *entry_curr_thread;\n\tduk_uint_fast8_t entry_thread_state;\n\tduk_instr_t **entry_ptr_curr_pc;\n\tduk_jmpbuf *old_jmpbuf_ptr = NULL;\n\tduk_jmpbuf our_jmpbuf;\n\tduk_idx_t idx_retbase;\n\tduk_int_t retval;\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(duk_get_top(thr) >= num_stack_args);  /* Caller ensures. */\n\n\tDUK_STATS_INC(thr->heap, stats_safecall_all);\n\n\t/* Value stack reserve handling: safe call assumes caller has reserved\n\t * space for nrets (assuming optimal unwind processing).  Value stack\n\t * reserve is not stored/restored as for normal calls because a safe\n\t * call conceptually happens in the same activation.\n\t */\n\n\t/* Careful with indices like '-x'; if 'x' is zero, it refers to bottom */\n\tentry_act = thr->callstack_curr;\n\tentry_valstack_bottom_byteoff = (duk_size_t) ((duk_uint8_t *) thr->valstack_bottom - (duk_uint8_t *) thr->valstack);\n#if defined(DUK_USE_ASSERTIONS)\n\tentry_valstack_end_byteoff = (duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack);\n\tentry_callstack_top = thr->callstack_top;\n\tentry_callstack_preventcount = thr->callstack_preventcount;\n#endif\n\tentry_call_recursion_depth = thr->heap->call_recursion_depth;\n\tentry_curr_thread = thr->heap->curr_thread;  /* may be NULL if first call */\n\tentry_thread_state = thr->state;\n\tentry_ptr_curr_pc = thr->ptr_curr_pc;  /* may be NULL */\n\tidx_retbase = duk_get_top(thr) - num_stack_args;  /* not a valid stack index if num_stack_args == 0 */\n\tDUK_ASSERT(idx_retbase >= 0);\n\n\tDUK_ASSERT((duk_idx_t) (thr->valstack_top - thr->valstack_bottom) >= num_stack_args);  /* Caller ensures. */\n\tDUK_ASSERT((duk_idx_t) (thr->valstack_end - (thr->valstack_bottom + idx_retbase)) >= num_stack_rets);  /* Caller ensures. */\n\n\t/* Cannot portably debug print a function pointer, hence 'func' not printed! */\n\tDUK_DD(DUK_DDPRINT(\"duk_handle_safe_call: thr=%p, num_stack_args=%ld, num_stack_rets=%ld, \"\n\t                   \"valstack_top=%ld, idx_retbase=%ld, rec_depth=%ld/%ld, \"\n\t                   \"entry_act=%p, entry_valstack_bottom_byteoff=%ld, entry_call_recursion_depth=%ld, \"\n\t                   \"entry_curr_thread=%p, entry_thread_state=%ld\",\n\t                   (void *) thr,\n\t                   (long) num_stack_args,\n\t                   (long) num_stack_rets,\n\t                   (long) duk_get_top(thr),\n\t                   (long) idx_retbase,\n\t                   (long) thr->heap->call_recursion_depth,\n\t                   (long) thr->heap->call_recursion_limit,\n\t                   (void *) entry_act,\n\t                   (long) entry_valstack_bottom_byteoff,\n\t                   (long) entry_call_recursion_depth,\n\t                   (void *) entry_curr_thread,\n\t                   (long) entry_thread_state));\n\n\t/* Setjmp catchpoint setup. */\n\told_jmpbuf_ptr = thr->heap->lj.jmpbuf_ptr;\n\tthr->heap->lj.jmpbuf_ptr = &our_jmpbuf;\n\n\t/* Prevent yields for the duration of the safe call.  This only\n\t * matters if the executor makes safe calls to functions that\n\t * yield, this doesn't currently happen.\n\t */\n\tthr->callstack_preventcount++;\n\n#if defined(DUK_USE_CPP_EXCEPTIONS)\n\ttry {\n#else\n\tDUK_ASSERT(thr->heap->lj.jmpbuf_ptr == &our_jmpbuf);\n\tif (DUK_SETJMP(our_jmpbuf.jb) == 0) {\n\t\t/* Success path. */\n#endif\n\t\tDUK_DDD(DUK_DDDPRINT(\"safe_call setjmp catchpoint setup complete\"));\n\n\t\tduk__handle_safe_call_inner(thr,\n\t\t                            func,\n\t\t                            udata,\n#if defined(DUK_USE_ASSERTIONS)\n\t\t                            entry_valstack_bottom_byteoff,\n\t\t                            entry_callstack_top,\n#endif\n\t\t                            entry_curr_thread,\n\t\t                            entry_thread_state,\n\t\t                            idx_retbase,\n\t\t                            num_stack_rets);\n\n\t\tDUK_STATS_INC(thr->heap, stats_safecall_nothrow);\n\n\t\t/* Either pointer may be NULL (at entry), so don't assert */\n\t\tthr->heap->lj.jmpbuf_ptr = old_jmpbuf_ptr;\n\n\t\t/* If calls happen inside the safe call, these are restored by\n\t\t * whatever calls are made.  Reserve cannot decrease.\n\t\t */\n\t\tDUK_ASSERT(thr->callstack_curr == entry_act);\n\t\tDUK_ASSERT((duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack) >= entry_valstack_end_byteoff);\n\n\t\tretval = DUK_EXEC_SUCCESS;\n#if defined(DUK_USE_CPP_EXCEPTIONS)\n\t} catch (duk_internal_exception &exc) {\n\t\tDUK_UNREF(exc);\n#else\n\t} else {\n\t\t/* Error path. */\n#endif\n\t\tDUK_ASSERT((duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack) >= entry_valstack_end_byteoff);\n\n\t\tDUK_STATS_INC(thr->heap, stats_safecall_throw);\n\n\t\tduk__handle_safe_call_error(thr,\n\t\t                            entry_act,\n#if defined(DUK_USE_ASSERTIONS)\n\t\t                            entry_callstack_top,\n#endif\n\t\t                            entry_curr_thread,\n\t\t                            entry_thread_state,\n\t\t                            idx_retbase,\n\t\t                            num_stack_rets,\n\t\t                            entry_valstack_bottom_byteoff,\n\t\t                            old_jmpbuf_ptr);\n\n\t\tretval = DUK_EXEC_ERROR;\n\t}\n#if defined(DUK_USE_CPP_EXCEPTIONS)\n\tcatch (std::exception &exc) {\n\t\tconst char *what = exc.what();\n\t\tDUK_ASSERT((duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack) >= entry_valstack_end_byteoff);\n\t\tDUK_STATS_INC(thr->heap, stats_safecall_throw);\n\t\tif (!what) {\n\t\t\twhat = \"unknown\";\n\t\t}\n\t\tDUK_D(DUK_DPRINT(\"unexpected c++ std::exception (perhaps thrown by user code)\"));\n\t\ttry {\n\t\t\tDUK_ERROR_FMT1(thr, DUK_ERR_TYPE_ERROR, \"caught invalid c++ std::exception '%s' (perhaps thrown by user code)\", what);\n\t\t} catch (duk_internal_exception exc) {\n\t\t\tDUK_D(DUK_DPRINT(\"caught api error thrown from unexpected c++ std::exception\"));\n\t\t\tDUK_UNREF(exc);\n\t\t\tduk__handle_safe_call_error(thr,\n\t\t\t                            entry_act,\n#if defined(DUK_USE_ASSERTIONS)\n\t\t\t                            entry_callstack_top,\n#endif\n\t\t\t                            entry_curr_thread,\n\t\t\t                            entry_thread_state,\n\t\t\t                            idx_retbase,\n\t\t\t                            num_stack_rets,\n\t\t\t                            entry_valstack_bottom_byteoff,\n\t\t\t                            old_jmpbuf_ptr);\n\t\t\tretval = DUK_EXEC_ERROR;\n\t\t}\n\t} catch (...) {\n\t\tDUK_D(DUK_DPRINT(\"unexpected c++ exception (perhaps thrown by user code)\"));\n\t\tDUK_ASSERT((duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack) >= entry_valstack_end_byteoff);\n\t\tDUK_STATS_INC(thr->heap, stats_safecall_throw);\n\t\ttry {\n\t\t\tDUK_ERROR_TYPE(thr, \"caught invalid c++ exception (perhaps thrown by user code)\");\n\t\t} catch (duk_internal_exception exc) {\n\t\t\tDUK_D(DUK_DPRINT(\"caught api error thrown from unexpected c++ exception\"));\n\t\t\tDUK_UNREF(exc);\n\t\t\tduk__handle_safe_call_error(thr,\n\t\t\t                            entry_act,\n#if defined(DUK_USE_ASSERTIONS)\n\t\t\t                            entry_callstack_top,\n#endif\n\t\t\t                            entry_curr_thread,\n\t\t\t                            entry_thread_state,\n\t\t\t                            idx_retbase,\n\t\t\t                            num_stack_rets,\n\t\t\t                            entry_valstack_bottom_byteoff,\n\t\t\t                            old_jmpbuf_ptr);\n\t\t\tretval = DUK_EXEC_ERROR;\n\t\t}\n\t}\n#endif\n\n\tDUK_ASSERT(thr->heap->lj.jmpbuf_ptr == old_jmpbuf_ptr);  /* success/error path both do this */\n\n\tDUK_ASSERT_LJSTATE_UNSET(thr->heap);\n\n\tDUK_ASSERT((duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack) >= entry_valstack_end_byteoff);\n\tduk__handle_safe_call_shared_unwind(thr,\n\t                                    idx_retbase,\n\t                                    num_stack_rets,\n#if defined(DUK_USE_ASSERTIONS)\n\t                                    entry_callstack_top,\n#endif\n\t                                    entry_call_recursion_depth,\n\t                                    entry_curr_thread,\n\t                                    entry_ptr_curr_pc);\n\n\t/* Restore preventcount. */\n\tthr->callstack_preventcount--;\n\tDUK_ASSERT(thr->callstack_preventcount == entry_callstack_preventcount);\n\n\t/* Final asserts. */\n\tDUK_ASSERT(thr->callstack_curr == entry_act);\n\tDUK_ASSERT((duk_size_t) ((duk_uint8_t *) thr->valstack_bottom - (duk_uint8_t *) thr->valstack) == entry_valstack_bottom_byteoff);\n\tDUK_ASSERT((duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack) >= entry_valstack_end_byteoff);\n\tDUK_ASSERT(thr->callstack_top == entry_callstack_top);\n\tDUK_ASSERT(thr->heap->call_recursion_depth == entry_call_recursion_depth);\n\tDUK_ASSERT(thr->heap->curr_thread == entry_curr_thread);\n\tDUK_ASSERT(thr->state == entry_thread_state);\n\tDUK_ASSERT(thr->ptr_curr_pc == entry_ptr_curr_pc);\n\tDUK_ASSERT(duk_get_top(thr) == idx_retbase + num_stack_rets);\n\tDUK_ASSERT_LJSTATE_UNSET(thr->heap);\n\n\t/* Pending side effects. */\n\tDUK_REFZERO_CHECK_FAST(thr);\n\n\treturn retval;\n}\n\n/*\n *  Property-based call (foo.noSuch()) error setup: replace target function\n *  on stack top with a specially tagged (hidden Symbol) error which gets\n *  thrown in call handling at the proper spot to follow Ecmascript semantics.\n */\n\n#if defined(DUK_USE_VERBOSE_ERRORS)\nDUK_INTERNAL DUK_NOINLINE DUK_COLD void duk_call_setup_propcall_error(duk_hthread *thr, duk_tval *tv_targ, duk_tval *tv_base, duk_tval *tv_key) {\n\tconst char *str1, *str2, *str3;\n\tduk_idx_t entry_top;\n\n\tentry_top = duk_get_top(thr);\n\n\t/* Must stabilize pointers first.  Argument convention is a bit awkward,\n\t * it comes from the executor call site where some arguments may not be\n\t * on the value stack (consts).\n\t */\n\tduk_push_tval(thr, tv_base);\n\tduk_push_tval(thr, tv_key);\n\tduk_push_tval(thr, tv_targ);\n\n\tDUK_GC_TORTURE(thr->heap);\n\n\t/* We only push an error, replacing the call target (at idx_func)\n\t * with the error to ensure side effects come out correctly:\n\t * - Property read\n\t * - Call argument evaluation\n\t * - Callability check and error thrown.\n\t *\n\t * A hidden Symbol on the error object pushed here is used by\n\t * call handling to figure out the error is to be thrown as is.\n\t * It is CRITICAL that the hidden Symbol can never occur on a\n\t * user visible object that may get thrown.\n\t */\n\n#if defined(DUK_USE_PARANOID_ERRORS)\n\tstr1 = duk_get_type_name(thr, -1);\n\tstr2 = duk_get_type_name(thr, -2);\n\tstr3 = duk_get_type_name(thr, -3);\n\tduk_push_error_object(thr, DUK_ERR_TYPE_ERROR | DUK_ERRCODE_FLAG_NOBLAME_FILELINE, \"%s not callable (property %s of %s)\", str1, str2, str3);\n#else\n\tstr1 = duk_push_string_readable(thr, -1);\n\tstr2 = duk_push_string_readable(thr, -3);\n\tstr3 = duk_push_string_readable(thr, -5);\n\tduk_push_error_object(thr, DUK_ERR_TYPE_ERROR | DUK_ERRCODE_FLAG_NOBLAME_FILELINE, \"%s not callable (property %s of %s)\", str1, str2, str3);\n#endif\n\n\tduk_push_true(thr);\n\tduk_put_prop_stridx(thr, -2, DUK_STRIDX_INT_TARGET);  /* Marker property, reuse _Target. */\n\n\t/* [ <nregs> propValue <variable> error ] */\n\tduk_replace(thr, entry_top - 1);\n\tduk_set_top(thr, entry_top);\n\n\tDUK_ASSERT(!duk_is_callable(thr, -1));  /* Critical so that call handling will throw the error. */\n}\n#endif  /* DUK_USE_VERBOSE_ERRORS */\n\n/* automatic undefs */\n#undef DUK__AUGMENT_CALL_RELAX_COUNT\n#line 1 \"duk_js_compiler.c\"\n/*\n *  Ecmascript compiler.\n *\n *  Parses an input string and generates a function template result.\n *  Compilation may happen in multiple contexts (global code, eval\n *  code, function code).\n *\n *  The parser uses a traditional top-down recursive parsing for the\n *  statement level, and an operator precedence based top-down approach\n *  for the expression level.  The attempt is to minimize the C stack\n *  depth.  Bytecode is generated directly without an intermediate\n *  representation (tree), at the cost of needing two (and sometimes\n *  three) passes over each function.\n *\n *  The top-down recursive parser functions are named \"duk__parse_XXX\".\n *\n *  Recursion limits are in key functions to prevent arbitrary C recursion:\n *  function body parsing, statement parsing, and expression parsing.\n *\n *  See doc/compiler.rst for discussion on the design.\n *\n *  A few typing notes:\n *\n *    - duk_regconst_t: signed, highest bit set (< 0) means constant,\n *      some call sites use -1 for \"none\" (equivalent to constant 0x7fffffff)\n *    - PC values: duk_int_t, negative values used as markers\n */\n\n/* #include duk_internal.h -> already included */\n\n/* If highest bit of a register number is set, it refers to a constant instead.\n * When interpreted as a signed value, this means const values are always\n * negative (when interpreted as two's complement).  For example DUK__ISREG_TEMP()\n * uses this approach to avoid an explicit DUK__ISREG() check (the condition is\n * logically \"'x' is a register AND 'x' >= temp_first\").\n */\n#define DUK__CONST_MARKER                   DUK_REGCONST_CONST_MARKER\n#define DUK__REMOVECONST(x)                 ((x) & ~DUK__CONST_MARKER)\n#define DUK__ISREG(x)                       ((x) >= 0)\n#define DUK__ISCONST(x)                     ((x) < 0)\n#define DUK__ISREG_TEMP(comp_ctx,x)         ((duk_int32_t) (x) >= (duk_int32_t) ((comp_ctx)->curr_func.temp_first))   /* Check for x >= temp_first && x >= 0 by comparing as signed. */\n#define DUK__ISREG_NOTTEMP(comp_ctx,x)      ((duk_uint32_t) (x) < (duk_uint32_t) ((comp_ctx)->curr_func.temp_first))  /* Check for x >= 0 && x < temp_first by interpreting as unsigned. */\n#define DUK__GETTEMP(comp_ctx)              ((comp_ctx)->curr_func.temp_next)\n#define DUK__SETTEMP(comp_ctx,x)            ((comp_ctx)->curr_func.temp_next = (x))  /* dangerous: must only lower (temp_max not updated) */\n#define DUK__SETTEMP_CHECKMAX(comp_ctx,x)   duk__settemp_checkmax((comp_ctx),(x))\n#define DUK__ALLOCTEMP(comp_ctx)            duk__alloctemp((comp_ctx))\n#define DUK__ALLOCTEMPS(comp_ctx,count)     duk__alloctemps((comp_ctx),(count))\n\n/* Init value set size for array and object literals. */\n#define DUK__MAX_ARRAY_INIT_VALUES        20\n#define DUK__MAX_OBJECT_INIT_PAIRS        10\n\n/* XXX: hack, remove when const lookup is not O(n) */\n#define DUK__GETCONST_MAX_CONSTS_CHECK    256\n\n/* These limits are based on bytecode limits.  Max temps is limited\n * by duk_hcompfunc nargs/nregs fields being 16 bits.\n */\n#define DUK__MAX_CONSTS                   DUK_BC_BC_MAX\n#define DUK__MAX_FUNCS                    DUK_BC_BC_MAX\n#define DUK__MAX_TEMPS                    0xffffL\n\n/* Initial bytecode size allocation. */\n#if defined(DUK_USE_PREFER_SIZE)\n#define DUK__BC_INITIAL_INSTS             16\n#else\n#define DUK__BC_INITIAL_INSTS             256\n#endif\n\n#define DUK__RECURSION_INCREASE(comp_ctx,thr)  do { \\\n\t\tDUK_DDD(DUK_DDDPRINT(\"RECURSION INCREASE: %s:%ld\", (const char *) DUK_FILE_MACRO, (long) DUK_LINE_MACRO)); \\\n\t\tduk__comp_recursion_increase((comp_ctx)); \\\n\t} while (0)\n\n#define DUK__RECURSION_DECREASE(comp_ctx,thr)  do { \\\n\t\tDUK_DDD(DUK_DDDPRINT(\"RECURSION DECREASE: %s:%ld\", (const char *) DUK_FILE_MACRO, (long) DUK_LINE_MACRO)); \\\n\t\tduk__comp_recursion_decrease((comp_ctx)); \\\n\t} while (0)\n\n/* Value stack slot limits: these are quite approximate right now, and\n * because they overlap in control flow, some could be eliminated.\n */\n#define DUK__COMPILE_ENTRY_SLOTS          8\n#define DUK__FUNCTION_INIT_REQUIRE_SLOTS  16\n#define DUK__FUNCTION_BODY_REQUIRE_SLOTS  16\n#define DUK__PARSE_STATEMENTS_SLOTS       16\n#define DUK__PARSE_EXPR_SLOTS             16\n\n/* Temporary structure used to pass a stack allocated region through\n * duk_safe_call().\n */\ntypedef struct {\n\tduk_small_uint_t flags;\n\tduk_compiler_ctx comp_ctx_alloc;\n\tduk_lexer_point lex_pt_alloc;\n} duk__compiler_stkstate;\n\n/*\n *  Prototypes\n */\n\n/* lexing */\nDUK_LOCAL_DECL void duk__advance_helper(duk_compiler_ctx *comp_ctx, duk_small_int_t expect);\nDUK_LOCAL_DECL void duk__advance_expect(duk_compiler_ctx *comp_ctx, duk_small_int_t expect);\nDUK_LOCAL_DECL void duk__advance(duk_compiler_ctx *ctx);\n\n/* function helpers */\nDUK_LOCAL_DECL void duk__init_func_valstack_slots(duk_compiler_ctx *comp_ctx);\nDUK_LOCAL_DECL void duk__reset_func_for_pass2(duk_compiler_ctx *comp_ctx);\nDUK_LOCAL_DECL void duk__init_varmap_and_prologue_for_pass2(duk_compiler_ctx *comp_ctx, duk_regconst_t *out_stmt_value_reg);\nDUK_LOCAL_DECL void duk__convert_to_func_template(duk_compiler_ctx *comp_ctx);\nDUK_LOCAL_DECL duk_int_t duk__cleanup_varmap(duk_compiler_ctx *comp_ctx);\n\n/* code emission */\nDUK_LOCAL_DECL duk_int_t duk__get_current_pc(duk_compiler_ctx *comp_ctx);\nDUK_LOCAL_DECL duk_compiler_instr *duk__get_instr_ptr(duk_compiler_ctx *comp_ctx, duk_int_t pc);\nDUK_LOCAL_DECL void duk__emit(duk_compiler_ctx *comp_ctx, duk_instr_t ins);\nDUK_LOCAL_DECL void duk__emit_op_only(duk_compiler_ctx *comp_ctx, duk_small_uint_t op);\nDUK_LOCAL_DECL void duk__emit_a_b_c(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_flags, duk_regconst_t a, duk_regconst_t b, duk_regconst_t c);\nDUK_LOCAL_DECL void duk__emit_a_b(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_flags, duk_regconst_t a, duk_regconst_t b);\nDUK_LOCAL_DECL void duk__emit_b_c(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_flags, duk_regconst_t b, duk_regconst_t c);\n#if 0  /* unused */\nDUK_LOCAL_DECL void duk__emit_a(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_flags, duk_regconst_t a);\nDUK_LOCAL_DECL void duk__emit_b(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_flags, duk_regconst_t b);\n#endif\nDUK_LOCAL_DECL void duk__emit_a_bc(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_flags, duk_regconst_t a, duk_regconst_t bc);\nDUK_LOCAL_DECL void duk__emit_bc(duk_compiler_ctx *comp_ctx, duk_small_uint_t op, duk_regconst_t bc);\nDUK_LOCAL_DECL void duk__emit_abc(duk_compiler_ctx *comp_ctx, duk_small_uint_t op, duk_regconst_t abc);\nDUK_LOCAL_DECL void duk__emit_load_int32(duk_compiler_ctx *comp_ctx, duk_regconst_t reg, duk_int32_t val);\nDUK_LOCAL_DECL void duk__emit_load_int32_noshuffle(duk_compiler_ctx *comp_ctx, duk_regconst_t reg, duk_int32_t val);\nDUK_LOCAL_DECL void duk__emit_jump(duk_compiler_ctx *comp_ctx, duk_int_t target_pc);\nDUK_LOCAL_DECL duk_int_t duk__emit_jump_empty(duk_compiler_ctx *comp_ctx);\nDUK_LOCAL_DECL void duk__insert_jump_entry(duk_compiler_ctx *comp_ctx, duk_int_t jump_pc);\nDUK_LOCAL_DECL void duk__patch_jump(duk_compiler_ctx *comp_ctx, duk_int_t jump_pc, duk_int_t target_pc);\nDUK_LOCAL_DECL void duk__patch_jump_here(duk_compiler_ctx *comp_ctx, duk_int_t jump_pc);\nDUK_LOCAL_DECL void duk__patch_trycatch(duk_compiler_ctx *comp_ctx, duk_int_t ldconst_pc, duk_int_t trycatch_pc, duk_regconst_t reg_catch, duk_regconst_t const_varname, duk_small_uint_t flags);\nDUK_LOCAL_DECL void duk__emit_if_false_skip(duk_compiler_ctx *comp_ctx, duk_regconst_t regconst);\nDUK_LOCAL_DECL void duk__emit_if_true_skip(duk_compiler_ctx *comp_ctx, duk_regconst_t regconst);\nDUK_LOCAL_DECL void duk__emit_invalid(duk_compiler_ctx *comp_ctx);\n\n/* ivalue/ispec helpers */\nDUK_LOCAL_DECL void duk__ivalue_regconst(duk_ivalue *x, duk_regconst_t regconst);\nDUK_LOCAL_DECL void duk__ivalue_plain_fromstack(duk_compiler_ctx *comp_ctx, duk_ivalue *x);\nDUK_LOCAL_DECL void duk__ivalue_var_fromstack(duk_compiler_ctx *comp_ctx, duk_ivalue *x);\nDUK_LOCAL_DECL void duk__ivalue_var_hstring(duk_compiler_ctx *comp_ctx, duk_ivalue *x, duk_hstring *h);\nDUK_LOCAL_DECL void duk__copy_ispec(duk_compiler_ctx *comp_ctx, duk_ispec *src, duk_ispec *dst);\nDUK_LOCAL_DECL void duk__copy_ivalue(duk_compiler_ctx *comp_ctx, duk_ivalue *src, duk_ivalue *dst);\nDUK_LOCAL_DECL duk_regconst_t duk__alloctemps(duk_compiler_ctx *comp_ctx, duk_small_int_t num);\nDUK_LOCAL_DECL duk_regconst_t duk__alloctemp(duk_compiler_ctx *comp_ctx);\nDUK_LOCAL_DECL void duk__settemp_checkmax(duk_compiler_ctx *comp_ctx, duk_regconst_t temp_next);\nDUK_LOCAL_DECL duk_regconst_t duk__getconst(duk_compiler_ctx *comp_ctx);\nDUK_LOCAL_DECL\nduk_regconst_t duk__ispec_toregconst_raw(duk_compiler_ctx *comp_ctx,\n                                         duk_ispec *x,\n                                         duk_regconst_t forced_reg,\n                                         duk_small_uint_t flags);\nDUK_LOCAL_DECL void duk__ispec_toforcedreg(duk_compiler_ctx *comp_ctx, duk_ispec *x, duk_regconst_t forced_reg);\nDUK_LOCAL_DECL void duk__ivalue_toplain_raw(duk_compiler_ctx *comp_ctx, duk_ivalue *x, duk_regconst_t forced_reg);\nDUK_LOCAL_DECL void duk__ivalue_toplain(duk_compiler_ctx *comp_ctx, duk_ivalue *x);\nDUK_LOCAL_DECL void duk__ivalue_toplain_ignore(duk_compiler_ctx *comp_ctx, duk_ivalue *x);\nDUK_LOCAL_DECL\nduk_regconst_t duk__ivalue_toregconst_raw(duk_compiler_ctx *comp_ctx,\n                                          duk_ivalue *x,\n                                          duk_regconst_t forced_reg,\n                                          duk_small_uint_t flags);\nDUK_LOCAL_DECL duk_regconst_t duk__ivalue_toreg(duk_compiler_ctx *comp_ctx, duk_ivalue *x);\n#if 0  /* unused */\nDUK_LOCAL_DECL duk_regconst_t duk__ivalue_totemp(duk_compiler_ctx *comp_ctx, duk_ivalue *x);\n#endif\nDUK_LOCAL_DECL void duk__ivalue_toforcedreg(duk_compiler_ctx *comp_ctx, duk_ivalue *x, duk_int_t forced_reg);\nDUK_LOCAL_DECL duk_regconst_t duk__ivalue_toregconst(duk_compiler_ctx *comp_ctx, duk_ivalue *x);\nDUK_LOCAL_DECL duk_regconst_t duk__ivalue_totempconst(duk_compiler_ctx *comp_ctx, duk_ivalue *x);\n\n/* identifier handling */\nDUK_LOCAL_DECL duk_regconst_t duk__lookup_active_register_binding(duk_compiler_ctx *comp_ctx);\nDUK_LOCAL_DECL duk_bool_t duk__lookup_lhs(duk_compiler_ctx *ctx, duk_regconst_t *out_reg_varbind, duk_regconst_t *out_rc_varname);\n\n/* label handling */\nDUK_LOCAL_DECL void duk__add_label(duk_compiler_ctx *comp_ctx, duk_hstring *h_label, duk_int_t pc_label, duk_int_t label_id);\nDUK_LOCAL_DECL void duk__update_label_flags(duk_compiler_ctx *comp_ctx, duk_int_t label_id, duk_small_uint_t flags);\nDUK_LOCAL_DECL void duk__lookup_active_label(duk_compiler_ctx *comp_ctx, duk_hstring *h_label, duk_bool_t is_break, duk_int_t *out_label_id, duk_int_t *out_label_catch_depth, duk_int_t *out_label_pc, duk_bool_t *out_is_closest);\nDUK_LOCAL_DECL void duk__reset_labels_to_length(duk_compiler_ctx *comp_ctx, duk_size_t len);\n\n/* top-down expression parser */\nDUK_LOCAL_DECL void duk__expr_nud(duk_compiler_ctx *comp_ctx, duk_ivalue *res);\nDUK_LOCAL_DECL void duk__expr_led(duk_compiler_ctx *comp_ctx, duk_ivalue *left, duk_ivalue *res);\nDUK_LOCAL_DECL duk_small_uint_t duk__expr_lbp(duk_compiler_ctx *comp_ctx);\nDUK_LOCAL_DECL duk_bool_t duk__expr_is_empty(duk_compiler_ctx *comp_ctx);\n\n/* exprtop is the top level variant which resets nud/led counts */\nDUK_LOCAL_DECL void duk__expr(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);\nDUK_LOCAL_DECL void duk__exprtop(duk_compiler_ctx *ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);\n\n/* convenience helpers */\n#if 0  /* unused */\nDUK_LOCAL_DECL duk_regconst_t duk__expr_toreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);\n#endif\n#if 0  /* unused */\nDUK_LOCAL_DECL duk_regconst_t duk__expr_totemp(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);\n#endif\nDUK_LOCAL_DECL void duk__expr_toforcedreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags, duk_regconst_t forced_reg);\nDUK_LOCAL_DECL duk_regconst_t duk__expr_toregconst(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);\n#if 0  /* unused */\nDUK_LOCAL_DECL duk_regconst_t duk__expr_totempconst(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);\n#endif\nDUK_LOCAL_DECL void duk__expr_toplain(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);\nDUK_LOCAL_DECL void duk__expr_toplain_ignore(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);\nDUK_LOCAL_DECL duk_regconst_t duk__exprtop_toreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);\n#if 0  /* unused */\nDUK_LOCAL_DECL duk_regconst_t duk__exprtop_totemp(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);\n#endif\nDUK_LOCAL_DECL void duk__exprtop_toforcedreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags, duk_regconst_t forced_reg);\nDUK_LOCAL_DECL duk_regconst_t duk__exprtop_toregconst(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);\n#if 0  /* unused */\nDUK_LOCAL_DECL void duk__exprtop_toplain_ignore(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);\n#endif\n\n/* expression parsing helpers */\nDUK_LOCAL_DECL duk_int_t duk__parse_arguments(duk_compiler_ctx *comp_ctx, duk_ivalue *res);\nDUK_LOCAL_DECL void duk__nud_array_literal(duk_compiler_ctx *comp_ctx, duk_ivalue *res);\nDUK_LOCAL_DECL void duk__nud_object_literal(duk_compiler_ctx *comp_ctx, duk_ivalue *res);\n\n/* statement parsing */\nDUK_LOCAL_DECL void duk__parse_var_decl(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t expr_flags, duk_regconst_t *out_reg_varbind, duk_regconst_t *out_rc_varname);\nDUK_LOCAL_DECL void duk__parse_var_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t expr_flags);\nDUK_LOCAL_DECL void duk__parse_for_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site);\nDUK_LOCAL_DECL void duk__parse_switch_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site);\nDUK_LOCAL_DECL void duk__parse_if_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res);\nDUK_LOCAL_DECL void duk__parse_do_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site);\nDUK_LOCAL_DECL void duk__parse_while_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site);\nDUK_LOCAL_DECL void duk__parse_break_or_continue_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res);\nDUK_LOCAL_DECL void duk__parse_return_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res);\nDUK_LOCAL_DECL void duk__parse_throw_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res);\nDUK_LOCAL_DECL void duk__parse_try_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res);\nDUK_LOCAL_DECL void duk__parse_with_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res);\nDUK_LOCAL_DECL void duk__parse_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_bool_t allow_source_elem);\nDUK_LOCAL_DECL duk_int_t duk__stmt_label_site(duk_compiler_ctx *comp_ctx, duk_int_t label_id);\nDUK_LOCAL_DECL void duk__parse_stmts(duk_compiler_ctx *comp_ctx, duk_bool_t allow_source_elem, duk_bool_t expect_eof);\n\nDUK_LOCAL_DECL void duk__parse_func_body(duk_compiler_ctx *comp_ctx, duk_bool_t expect_eof, duk_bool_t implicit_return_value, duk_small_int_t expect_token);\nDUK_LOCAL_DECL void duk__parse_func_formals(duk_compiler_ctx *comp_ctx);\nDUK_LOCAL_DECL void duk__parse_func_like_raw(duk_compiler_ctx *comp_ctx, duk_small_uint_t flags);\nDUK_LOCAL_DECL duk_int_t duk__parse_func_like_fnum(duk_compiler_ctx *comp_ctx, duk_small_uint_t flags);\n\n#define DUK__FUNC_FLAG_DECL            (1 << 0)   /* Parsing a function declaration. */\n#define DUK__FUNC_FLAG_GETSET          (1 << 1)   /* Parsing an object literal getter/setter. */\n#define DUK__FUNC_FLAG_METDEF          (1 << 2)   /* Parsing an object literal method definition shorthand. */\n#define DUK__FUNC_FLAG_PUSHNAME_PASS1  (1 << 3)   /* Push function name when creating template (first pass only). */\n#define DUK__FUNC_FLAG_USE_PREVTOKEN   (1 << 4)   /* Use prev_token to start function parsing (workaround for object literal). */\n\n/*\n *  Parser control values for tokens.  The token table is ordered by the\n *  DUK_TOK_XXX defines.\n *\n *  The binding powers are for lbp() use (i.e. for use in led() context).\n *  Binding powers are positive for typing convenience, and bits at the\n *  top should be reserved for flags.  Binding power step must be higher\n *  than 1 so that binding power \"lbp - 1\" can be used for right associative\n *  operators.  Currently a step of 2 is used (which frees one more bit for\n *  flags).\n */\n\n/* XXX: actually single step levels would work just fine, clean up */\n\n/* binding power \"levels\" (see doc/compiler.rst) */\n#define DUK__BP_INVALID                0             /* always terminates led() */\n#define DUK__BP_EOF                    2\n#define DUK__BP_CLOSING                4             /* token closes expression, e.g. ')', ']' */\n#define DUK__BP_FOR_EXPR               DUK__BP_CLOSING    /* bp to use when parsing a top level Expression */\n#define DUK__BP_COMMA                  6\n#define DUK__BP_ASSIGNMENT             8\n#define DUK__BP_CONDITIONAL            10\n#define DUK__BP_LOR                    12\n#define DUK__BP_LAND                   14\n#define DUK__BP_BOR                    16\n#define DUK__BP_BXOR                   18\n#define DUK__BP_BAND                   20\n#define DUK__BP_EQUALITY               22\n#define DUK__BP_RELATIONAL             24\n#define DUK__BP_SHIFT                  26\n#define DUK__BP_ADDITIVE               28\n#define DUK__BP_MULTIPLICATIVE         30\n#define DUK__BP_EXPONENTIATION         32\n#define DUK__BP_POSTFIX                34\n#define DUK__BP_CALL                   36\n#define DUK__BP_MEMBER                 38\n\n#define DUK__TOKEN_LBP_BP_MASK         0x1f\n#define DUK__TOKEN_LBP_FLAG_NO_REGEXP  (1 << 5)   /* regexp literal must not follow this token */\n#define DUK__TOKEN_LBP_FLAG_TERMINATES (1 << 6)   /* terminates expression; e.g. post-increment/-decrement */\n#define DUK__TOKEN_LBP_FLAG_UNUSED     (1 << 7)   /* unused */\n\n#define DUK__TOKEN_LBP_GET_BP(x)       ((duk_small_uint_t) (((x) & DUK__TOKEN_LBP_BP_MASK) * 2))\n\n#define DUK__MK_LBP(bp)                ((bp) >> 1)    /* bp is assumed to be even */\n#define DUK__MK_LBP_FLAGS(bp,flags)    (((bp) >> 1) | (flags))\n\nDUK_LOCAL const duk_uint8_t duk__token_lbp[] = {\n\tDUK__MK_LBP(DUK__BP_EOF),                                 /* DUK_TOK_EOF */\n\tDUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_IDENTIFIER */\n\tDUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_BREAK */\n\tDUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_CASE */\n\tDUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_CATCH */\n\tDUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_CONTINUE */\n\tDUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_DEBUGGER */\n\tDUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_DEFAULT */\n\tDUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_DELETE */\n\tDUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_DO */\n\tDUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_ELSE */\n\tDUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_FINALLY */\n\tDUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_FOR */\n\tDUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_FUNCTION */\n\tDUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_IF */\n\tDUK__MK_LBP(DUK__BP_RELATIONAL),                          /* DUK_TOK_IN */\n\tDUK__MK_LBP(DUK__BP_RELATIONAL),                          /* DUK_TOK_INSTANCEOF */\n\tDUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_NEW */\n\tDUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_RETURN */\n\tDUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_SWITCH */\n\tDUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_THIS */\n\tDUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_THROW */\n\tDUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_TRY */\n\tDUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_TYPEOF */\n\tDUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_VAR */\n\tDUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_CONST */\n\tDUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_VOID */\n\tDUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_WHILE */\n\tDUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_WITH */\n\tDUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_CLASS */\n\tDUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_ENUM */\n\tDUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_EXPORT */\n\tDUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_EXTENDS */\n\tDUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_IMPORT */\n\tDUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_SUPER */\n\tDUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_NULL */\n\tDUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_TRUE */\n\tDUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_FALSE */\n\tDUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_GET */\n\tDUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_SET */\n\tDUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_IMPLEMENTS */\n\tDUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_INTERFACE */\n\tDUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_LET */\n\tDUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_PACKAGE */\n\tDUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_PRIVATE */\n\tDUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_PROTECTED */\n\tDUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_PUBLIC */\n\tDUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_STATIC */\n\tDUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_YIELD */\n\tDUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_LCURLY */\n\tDUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_RCURLY */\n\tDUK__MK_LBP(DUK__BP_MEMBER),                              /* DUK_TOK_LBRACKET */\n\tDUK__MK_LBP_FLAGS(DUK__BP_CLOSING, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_RBRACKET */\n\tDUK__MK_LBP(DUK__BP_CALL),                                /* DUK_TOK_LPAREN */\n\tDUK__MK_LBP_FLAGS(DUK__BP_CLOSING, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_RPAREN */\n\tDUK__MK_LBP(DUK__BP_MEMBER),                              /* DUK_TOK_PERIOD */\n\tDUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_SEMICOLON */\n\tDUK__MK_LBP(DUK__BP_COMMA),                               /* DUK_TOK_COMMA */\n\tDUK__MK_LBP(DUK__BP_RELATIONAL),                          /* DUK_TOK_LT */\n\tDUK__MK_LBP(DUK__BP_RELATIONAL),                          /* DUK_TOK_GT */\n\tDUK__MK_LBP(DUK__BP_RELATIONAL),                          /* DUK_TOK_LE */\n\tDUK__MK_LBP(DUK__BP_RELATIONAL),                          /* DUK_TOK_GE */\n\tDUK__MK_LBP(DUK__BP_EQUALITY),                            /* DUK_TOK_EQ */\n\tDUK__MK_LBP(DUK__BP_EQUALITY),                            /* DUK_TOK_NEQ */\n\tDUK__MK_LBP(DUK__BP_EQUALITY),                            /* DUK_TOK_SEQ */\n\tDUK__MK_LBP(DUK__BP_EQUALITY),                            /* DUK_TOK_SNEQ */\n\tDUK__MK_LBP(DUK__BP_ADDITIVE),                            /* DUK_TOK_ADD */\n\tDUK__MK_LBP(DUK__BP_ADDITIVE),                            /* DUK_TOK_SUB */\n\tDUK__MK_LBP(DUK__BP_MULTIPLICATIVE),                      /* DUK_TOK_MUL */\n\tDUK__MK_LBP(DUK__BP_MULTIPLICATIVE),                      /* DUK_TOK_DIV */\n\tDUK__MK_LBP(DUK__BP_MULTIPLICATIVE),                      /* DUK_TOK_MOD */\n\tDUK__MK_LBP(DUK__BP_EXPONENTIATION),                      /* DUK_TOK_EXP */\n\tDUK__MK_LBP(DUK__BP_POSTFIX),                             /* DUK_TOK_INCREMENT */\n\tDUK__MK_LBP(DUK__BP_POSTFIX),                             /* DUK_TOK_DECREMENT */\n\tDUK__MK_LBP(DUK__BP_SHIFT),                               /* DUK_TOK_ALSHIFT */\n\tDUK__MK_LBP(DUK__BP_SHIFT),                               /* DUK_TOK_ARSHIFT */\n\tDUK__MK_LBP(DUK__BP_SHIFT),                               /* DUK_TOK_RSHIFT */\n\tDUK__MK_LBP(DUK__BP_BAND),                                /* DUK_TOK_BAND */\n\tDUK__MK_LBP(DUK__BP_BOR),                                 /* DUK_TOK_BOR */\n\tDUK__MK_LBP(DUK__BP_BXOR),                                /* DUK_TOK_BXOR */\n\tDUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_LNOT */\n\tDUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_BNOT */\n\tDUK__MK_LBP(DUK__BP_LAND),                                /* DUK_TOK_LAND */\n\tDUK__MK_LBP(DUK__BP_LOR),                                 /* DUK_TOK_LOR */\n\tDUK__MK_LBP(DUK__BP_CONDITIONAL),                         /* DUK_TOK_QUESTION */\n\tDUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_COLON */\n\tDUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_EQUALSIGN */\n\tDUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_ADD_EQ */\n\tDUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_SUB_EQ */\n\tDUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_MUL_EQ */\n\tDUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_DIV_EQ */\n\tDUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_MOD_EQ */\n\tDUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_EXP_EQ */\n\tDUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_ALSHIFT_EQ */\n\tDUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_ARSHIFT_EQ */\n\tDUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_RSHIFT_EQ */\n\tDUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_BAND_EQ */\n\tDUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_BOR_EQ */\n\tDUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_BXOR_EQ */\n\tDUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_NUMBER */\n\tDUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_STRING */\n\tDUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_REGEXP */\n};\n\n/*\n *  Misc helpers\n */\n\nDUK_LOCAL void duk__comp_recursion_increase(duk_compiler_ctx *comp_ctx) {\n\tDUK_ASSERT(comp_ctx != NULL);\n\tDUK_ASSERT(comp_ctx->recursion_depth >= 0);\n\tif (comp_ctx->recursion_depth >= comp_ctx->recursion_limit) {\n\t\tDUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_COMPILER_RECURSION_LIMIT);\n\t}\n\tcomp_ctx->recursion_depth++;\n}\n\nDUK_LOCAL void duk__comp_recursion_decrease(duk_compiler_ctx *comp_ctx) {\n\tDUK_ASSERT(comp_ctx != NULL);\n\tDUK_ASSERT(comp_ctx->recursion_depth > 0);\n\tcomp_ctx->recursion_depth--;\n}\n\nDUK_LOCAL duk_bool_t duk__hstring_is_eval_or_arguments(duk_compiler_ctx *comp_ctx, duk_hstring *h) {\n\tDUK_UNREF(comp_ctx);\n\tDUK_ASSERT(h != NULL);\n\treturn DUK_HSTRING_HAS_EVAL_OR_ARGUMENTS(h);\n}\n\nDUK_LOCAL duk_bool_t duk__hstring_is_eval_or_arguments_in_strict_mode(duk_compiler_ctx *comp_ctx, duk_hstring *h) {\n\tDUK_ASSERT(h != NULL);\n\treturn (comp_ctx->curr_func.is_strict &&\n\t        DUK_HSTRING_HAS_EVAL_OR_ARGUMENTS(h));\n}\n\n/*\n *  Parser duk__advance() token eating functions\n */\n\n/* XXX: valstack handling is awkward.  Add a valstack helper which\n * avoids dup():ing; valstack_copy(src, dst)?\n */\n\nDUK_LOCAL void duk__advance_helper(duk_compiler_ctx *comp_ctx, duk_small_int_t expect) {\n\tduk_hthread *thr = comp_ctx->thr;\n\tduk_bool_t regexp;\n\n\tDUK_ASSERT_DISABLE(comp_ctx->curr_token.t >= 0);  /* unsigned */\n\tDUK_ASSERT(comp_ctx->curr_token.t <= DUK_TOK_MAXVAL);  /* MAXVAL is inclusive */\n\n\t/*\n\t *  Use current token to decide whether a RegExp can follow.\n\t *\n\t *  We can use either 't' or 't_nores'; the latter would not\n\t *  recognize keywords.  Some keywords can be followed by a\n\t *  RegExp (e.g. \"return\"), so using 't' is better.  This is\n\t *  not trivial, see doc/compiler.rst.\n\t */\n\n\tregexp = 1;\n\tif (duk__token_lbp[comp_ctx->curr_token.t] & DUK__TOKEN_LBP_FLAG_NO_REGEXP) {\n\t\tregexp = 0;\n\t}\n\tif (comp_ctx->curr_func.reject_regexp_in_adv) {\n\t\tcomp_ctx->curr_func.reject_regexp_in_adv = 0;\n\t\tregexp = 0;\n\t}\n\n\tif (expect >= 0 && comp_ctx->curr_token.t != (duk_small_uint_t) expect) {\n\t\tDUK_D(DUK_DPRINT(\"parse error: expect=%ld, got=%ld\",\n\t\t                 (long) expect, (long) comp_ctx->curr_token.t));\n\t\tDUK_ERROR_SYNTAX(thr, DUK_STR_PARSE_ERROR);\n\t}\n\n\t/* make current token the previous; need to fiddle with valstack \"backing store\" */\n\tDUK_MEMCPY(&comp_ctx->prev_token, &comp_ctx->curr_token, sizeof(duk_token));\n\tduk_copy(thr, comp_ctx->tok11_idx, comp_ctx->tok21_idx);\n\tduk_copy(thr, comp_ctx->tok12_idx, comp_ctx->tok22_idx);\n\n\t/* parse new token */\n\tduk_lexer_parse_js_input_element(&comp_ctx->lex,\n\t                                 &comp_ctx->curr_token,\n\t                                 comp_ctx->curr_func.is_strict,\n\t                                 regexp);\n\n\tDUK_DDD(DUK_DDDPRINT(\"advance: curr: tok=%ld/%ld,%ld,term=%ld,%!T,%!T \"\n\t                     \"prev: tok=%ld/%ld,%ld,term=%ld,%!T,%!T\",\n\t                     (long) comp_ctx->curr_token.t,\n\t                     (long) comp_ctx->curr_token.t_nores,\n\t                     (long) comp_ctx->curr_token.start_line,\n\t                     (long) comp_ctx->curr_token.lineterm,\n\t                     (duk_tval *) duk_get_tval(thr, comp_ctx->tok11_idx),\n\t                     (duk_tval *) duk_get_tval(thr, comp_ctx->tok12_idx),\n\t                     (long) comp_ctx->prev_token.t,\n\t                     (long) comp_ctx->prev_token.t_nores,\n\t                     (long) comp_ctx->prev_token.start_line,\n\t                     (long) comp_ctx->prev_token.lineterm,\n\t                     (duk_tval *) duk_get_tval(thr, comp_ctx->tok21_idx),\n\t                     (duk_tval *) duk_get_tval(thr, comp_ctx->tok22_idx)));\n}\n\n/* advance, expecting current token to be a specific token; parse next token in regexp context */\nDUK_LOCAL void duk__advance_expect(duk_compiler_ctx *comp_ctx, duk_small_int_t expect) {\n\tduk__advance_helper(comp_ctx, expect);\n}\n\n/* advance, whatever the current token is; parse next token in regexp context */\nDUK_LOCAL void duk__advance(duk_compiler_ctx *comp_ctx) {\n\tduk__advance_helper(comp_ctx, -1);\n}\n\n/*\n *  Helpers for duk_compiler_func.\n */\n\n/* init function state: inits valstack allocations */\nDUK_LOCAL void duk__init_func_valstack_slots(duk_compiler_ctx *comp_ctx) {\n\tduk_compiler_func *func = &comp_ctx->curr_func;\n\tduk_hthread *thr = comp_ctx->thr;\n\tduk_idx_t entry_top;\n\n\tentry_top = duk_get_top(thr);\n\n\tDUK_MEMZERO(func, sizeof(*func));  /* intentional overlap with earlier memzero */\n#if defined(DUK_USE_EXPLICIT_NULL_INIT)\n\tfunc->h_name = NULL;\n\tfunc->h_consts = NULL;\n\tfunc->h_funcs = NULL;\n\tfunc->h_decls = NULL;\n\tfunc->h_labelnames = NULL;\n\tfunc->h_labelinfos = NULL;\n\tfunc->h_argnames = NULL;\n\tfunc->h_varmap = NULL;\n#endif\n\n\tduk_require_stack(thr, DUK__FUNCTION_INIT_REQUIRE_SLOTS);\n\n\tDUK_BW_INIT_PUSHBUF(thr, &func->bw_code, DUK__BC_INITIAL_INSTS * sizeof(duk_compiler_instr));\n\t/* code_idx = entry_top + 0 */\n\n\tduk_push_array(thr);\n\tfunc->consts_idx = entry_top + 1;\n\tfunc->h_consts = DUK_GET_HOBJECT_POSIDX(thr, entry_top + 1);\n\tDUK_ASSERT(func->h_consts != NULL);\n\n\tduk_push_array(thr);\n\tfunc->funcs_idx = entry_top + 2;\n\tfunc->h_funcs = DUK_GET_HOBJECT_POSIDX(thr, entry_top + 2);\n\tDUK_ASSERT(func->h_funcs != NULL);\n\tDUK_ASSERT(func->fnum_next == 0);\n\n\tduk_push_array(thr);\n\tfunc->decls_idx = entry_top + 3;\n\tfunc->h_decls = DUK_GET_HOBJECT_POSIDX(thr, entry_top + 3);\n\tDUK_ASSERT(func->h_decls != NULL);\n\n\tduk_push_array(thr);\n\tfunc->labelnames_idx = entry_top + 4;\n\tfunc->h_labelnames = DUK_GET_HOBJECT_POSIDX(thr, entry_top + 4);\n\tDUK_ASSERT(func->h_labelnames != NULL);\n\n\tduk_push_dynamic_buffer(thr, 0);\n\tfunc->labelinfos_idx = entry_top + 5;\n\tfunc->h_labelinfos = (duk_hbuffer_dynamic *) duk_known_hbuffer(thr, entry_top + 5);\n\tDUK_ASSERT(func->h_labelinfos != NULL);\n\tDUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(func->h_labelinfos) && !DUK_HBUFFER_HAS_EXTERNAL(func->h_labelinfos));\n\n\tduk_push_array(thr);\n\tfunc->argnames_idx = entry_top + 6;\n\tfunc->h_argnames = DUK_GET_HOBJECT_POSIDX(thr, entry_top + 6);\n\tDUK_ASSERT(func->h_argnames != NULL);\n\n\tduk_push_bare_object(thr);\n\tfunc->varmap_idx = entry_top + 7;\n\tfunc->h_varmap = DUK_GET_HOBJECT_POSIDX(thr, entry_top + 7);\n\tDUK_ASSERT(func->h_varmap != NULL);\n}\n\n/* reset function state (prepare for pass 2) */\nDUK_LOCAL void duk__reset_func_for_pass2(duk_compiler_ctx *comp_ctx) {\n\tduk_compiler_func *func = &comp_ctx->curr_func;\n\tduk_hthread *thr = comp_ctx->thr;\n\n\t/* reset bytecode buffer but keep current size; pass 2 will\n\t * require same amount or more.\n\t */\n\tDUK_BW_RESET_SIZE(thr, &func->bw_code);\n\n\tduk_set_length(thr, func->consts_idx, 0);\n\t/* keep func->h_funcs; inner functions are not reparsed to avoid O(depth^2) parsing */\n\tfunc->fnum_next = 0;\n\t/* duk_set_length(thr, func->funcs_idx, 0); */\n\tduk_set_length(thr, func->labelnames_idx, 0);\n\tduk_hbuffer_reset(thr, func->h_labelinfos);\n\t/* keep func->h_argnames; it is fixed for all passes */\n\n\t/* truncated in case pass 3 needed */\n\tduk_push_bare_object(thr);\n\tduk_replace(thr, func->varmap_idx);\n\tfunc->h_varmap = DUK_GET_HOBJECT_POSIDX(thr, func->varmap_idx);\n\tDUK_ASSERT(func->h_varmap != NULL);\n}\n\n/* cleanup varmap from any null entries, compact it, etc; returns number\n * of final entries after cleanup.\n */\nDUK_LOCAL duk_int_t duk__cleanup_varmap(duk_compiler_ctx *comp_ctx) {\n\tduk_hthread *thr = comp_ctx->thr;\n\tduk_hobject *h_varmap;\n\tduk_hstring *h_key;\n\tduk_tval *tv;\n\tduk_uint32_t i, e_next;\n\tduk_int_t ret;\n\n\t/* [ ... varmap ] */\n\n\th_varmap = DUK_GET_HOBJECT_NEGIDX(thr, -1);\n\tDUK_ASSERT(h_varmap != NULL);\n\n\tret = 0;\n\te_next = DUK_HOBJECT_GET_ENEXT(h_varmap);\n\tfor (i = 0; i < e_next; i++) {\n\t\th_key = DUK_HOBJECT_E_GET_KEY(thr->heap, h_varmap, i);\n\t\tif (!h_key) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tDUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, h_varmap, i));\n\n\t\t/* The entries can either be register numbers or 'null' values.\n\t\t * Thus, no need to DECREF them and get side effects.  DECREF'ing\n\t\t * the keys (strings) can cause memory to be freed but no side\n\t\t * effects as strings don't have finalizers.  This is why we can\n\t\t * rely on the object properties not changing from underneath us.\n\t\t */\n\n\t\ttv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, h_varmap, i);\n\t\tif (!DUK_TVAL_IS_NUMBER(tv)) {\n\t\t\tDUK_ASSERT(!DUK_TVAL_IS_HEAP_ALLOCATED(tv));\n\t\t\tDUK_HOBJECT_E_SET_KEY(thr->heap, h_varmap, i, NULL);\n\t\t\tDUK_HSTRING_DECREF(thr, h_key);\n\t\t\t/* when key is NULL, value is garbage so no need to set */\n\t\t} else {\n\t\t\tret++;\n\t\t}\n\t}\n\n\tduk_compact_m1(thr);\n\n\treturn ret;\n}\n\n/* Convert duk_compiler_func into a function template, leaving the result\n * on top of stack.\n */\n/* XXX: awkward and bloated asm -- use faster internal accesses */\nDUK_LOCAL void duk__convert_to_func_template(duk_compiler_ctx *comp_ctx) {\n\tduk_compiler_func *func = &comp_ctx->curr_func;\n\tduk_hthread *thr = comp_ctx->thr;\n\tduk_hcompfunc *h_res;\n\tduk_hbuffer_fixed *h_data;\n\tduk_size_t consts_count;\n\tduk_size_t funcs_count;\n\tduk_size_t code_count;\n\tduk_size_t code_size;\n\tduk_size_t data_size;\n\tduk_size_t i;\n\tduk_tval *p_const;\n\tduk_hobject **p_func;\n\tduk_instr_t *p_instr;\n\tduk_compiler_instr *q_instr;\n\tduk_tval *tv;\n\tduk_bool_t keep_varmap;\n\tduk_bool_t keep_formals;\n#if !defined(DUK_USE_DEBUGGER_SUPPORT)\n\tduk_size_t formals_length;\n#endif\n\n\tDUK_DDD(DUK_DDDPRINT(\"converting duk_compiler_func to function/template\"));\n\n\t/*\n\t *  Push result object and init its flags\n\t */\n\n\t/* Valstack should suffice here, required on function valstack init */\n\n\th_res = duk_push_hcompfunc(thr);\n\tDUK_ASSERT(h_res != NULL);\n\tDUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) h_res) == thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]);\n\tDUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, (duk_hobject *) h_res, NULL);  /* Function templates are \"bare objects\". */\n\n\tif (func->is_function) {\n\t\tDUK_DDD(DUK_DDDPRINT(\"function -> set NEWENV\"));\n\t\tDUK_HOBJECT_SET_NEWENV((duk_hobject *) h_res);\n\n\t\tif (!func->is_arguments_shadowed) {\n\t\t\t/* arguments object would be accessible; note that shadowing\n\t\t\t * bindings are arguments or function declarations, neither\n\t\t\t * of which are deletable, so this is safe.\n\t\t\t */\n\n\t\t\tif (func->id_access_arguments || func->may_direct_eval) {\n\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"function may access 'arguments' object directly or \"\n\t\t\t\t                     \"indirectly -> set CREATEARGS\"));\n\t\t\t\tDUK_HOBJECT_SET_CREATEARGS((duk_hobject *) h_res);\n\t\t\t}\n\t\t}\n\t} else if (func->is_eval && func->is_strict) {\n\t\tDUK_DDD(DUK_DDDPRINT(\"strict eval code -> set NEWENV\"));\n\t\tDUK_HOBJECT_SET_NEWENV((duk_hobject *) h_res);\n\t} else {\n\t\t/* non-strict eval: env is caller's env or global env (direct vs. indirect call)\n\t\t * global code: env is is global env\n\t\t */\n\t\tDUK_DDD(DUK_DDDPRINT(\"non-strict eval code or global code -> no NEWENV\"));\n\t\tDUK_ASSERT(!DUK_HOBJECT_HAS_NEWENV((duk_hobject *) h_res));\n\t}\n\n#if defined(DUK_USE_FUNC_NAME_PROPERTY)\n\tif (func->is_function && func->is_namebinding && func->h_name != NULL) {\n\t\t/* Object literal set/get functions have a name (property\n\t\t * name) but must not have a lexical name binding, see\n\t\t * test-bug-getset-func-name.js.\n\t\t */\n\t\tDUK_DDD(DUK_DDDPRINT(\"function expression with a name -> set NAMEBINDING\"));\n\t\tDUK_HOBJECT_SET_NAMEBINDING((duk_hobject *) h_res);\n\t}\n#endif\n\n\tif (func->is_strict) {\n\t\tDUK_DDD(DUK_DDDPRINT(\"function is strict -> set STRICT\"));\n\t\tDUK_HOBJECT_SET_STRICT((duk_hobject *) h_res);\n\t}\n\n\tif (func->is_notail) {\n\t\tDUK_DDD(DUK_DDDPRINT(\"function is notail -> set NOTAIL\"));\n\t\tDUK_HOBJECT_SET_NOTAIL((duk_hobject *) h_res);\n\t}\n\n\tif (func->is_constructable) {\n\t\tDUK_DDD(DUK_DDDPRINT(\"function is constructable -> set CONSTRUCTABLE\"));\n\t\tDUK_HOBJECT_SET_CONSTRUCTABLE((duk_hobject *) h_res);\n\t}\n\n\t/*\n\t *  Build function fixed size 'data' buffer, which contains bytecode,\n\t *  constants, and inner function references.\n\t *\n\t *  During the building phase 'data' is reachable but incomplete.\n\t *  Only incref's occur during building (no refzero or GC happens),\n\t *  so the building process is atomic.\n\t */\n\n\tconsts_count = duk_hobject_get_length(thr, func->h_consts);\n\tfuncs_count = duk_hobject_get_length(thr, func->h_funcs) / 3;\n\tcode_count = DUK_BW_GET_SIZE(thr, &func->bw_code) / sizeof(duk_compiler_instr);\n\tcode_size = code_count * sizeof(duk_instr_t);\n\n\tdata_size = consts_count * sizeof(duk_tval) +\n\t            funcs_count * sizeof(duk_hobject *) +\n\t            code_size;\n\n\tDUK_DDD(DUK_DDDPRINT(\"consts_count=%ld, funcs_count=%ld, code_size=%ld -> \"\n\t                     \"data_size=%ld*%ld + %ld*%ld + %ld = %ld\",\n\t                     (long) consts_count, (long) funcs_count, (long) code_size,\n\t                     (long) consts_count, (long) sizeof(duk_tval),\n\t                     (long) funcs_count, (long) sizeof(duk_hobject *),\n\t                     (long) code_size, (long) data_size));\n\n\tduk_push_fixed_buffer_nozero(thr, data_size);\n\th_data = (duk_hbuffer_fixed *) duk_known_hbuffer(thr, -1);\n\n\tDUK_HCOMPFUNC_SET_DATA(thr->heap, h_res, (duk_hbuffer *) h_data);\n\tDUK_HEAPHDR_INCREF(thr, h_data);\n\n\tp_const = (duk_tval *) (void *) DUK_HBUFFER_FIXED_GET_DATA_PTR(thr->heap, h_data);\n\tfor (i = 0; i < consts_count; i++) {\n\t\tDUK_ASSERT(i <= DUK_UARRIDX_MAX);  /* const limits */\n\t\ttv = duk_hobject_find_existing_array_entry_tval_ptr(thr->heap, func->h_consts, (duk_uarridx_t) i);\n\t\tDUK_ASSERT(tv != NULL);\n\t\tDUK_TVAL_SET_TVAL(p_const, tv);\n\t\tp_const++;\n\t\tDUK_TVAL_INCREF(thr, tv);  /* may be a string constant */\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"constant: %!T\", (duk_tval *) tv));\n\t}\n\n\tp_func = (duk_hobject **) p_const;\n\tDUK_HCOMPFUNC_SET_FUNCS(thr->heap, h_res, p_func);\n\tfor (i = 0; i < funcs_count; i++) {\n\t\tduk_hobject *h;\n\t\tDUK_ASSERT(i * 3 <= DUK_UARRIDX_MAX);  /* func limits */\n\t\ttv = duk_hobject_find_existing_array_entry_tval_ptr(thr->heap, func->h_funcs, (duk_uarridx_t) (i * 3));\n\t\tDUK_ASSERT(tv != NULL);\n\t\tDUK_ASSERT(DUK_TVAL_IS_OBJECT(tv));\n\t\th = DUK_TVAL_GET_OBJECT(tv);\n\t\tDUK_ASSERT(h != NULL);\n\t\tDUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(h));\n\t\t*p_func++ = h;\n\t\tDUK_HOBJECT_INCREF(thr, h);\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"inner function: %p -> %!iO\",\n\t\t                     (void *) h, (duk_heaphdr *) h));\n\t}\n\n\tp_instr = (duk_instr_t *) p_func;\n\tDUK_HCOMPFUNC_SET_BYTECODE(thr->heap, h_res, p_instr);\n\n\t/* copy bytecode instructions one at a time */\n\tq_instr = (duk_compiler_instr *) (void *) DUK_BW_GET_BASEPTR(thr, &func->bw_code);\n\tfor (i = 0; i < code_count; i++) {\n\t\tp_instr[i] = q_instr[i].ins;\n\t}\n\t/* Note: 'q_instr' is still used below */\n\n\tDUK_ASSERT((duk_uint8_t *) (p_instr + code_count) == DUK_HBUFFER_FIXED_GET_DATA_PTR(thr->heap, h_data) + data_size);\n\n\tduk_pop(thr);  /* 'data' (and everything in it) is reachable through h_res now */\n\n\t/*\n\t *  Init non-property result fields\n\t *\n\t *  'nregs' controls how large a register frame is allocated.\n\t *\n\t *  'nargs' controls how many formal arguments are written to registers:\n\t *  r0, ... r(nargs-1).  The remaining registers are initialized to\n\t *  undefined.\n\t */\n\n\tDUK_ASSERT(func->temp_max >= 0);\n\th_res->nregs = (duk_uint16_t) func->temp_max;\n\th_res->nargs = (duk_uint16_t) duk_hobject_get_length(thr, func->h_argnames);\n\tDUK_ASSERT(h_res->nregs >= h_res->nargs);  /* pass2 allocation handles this */\n#if defined(DUK_USE_DEBUGGER_SUPPORT)\n\th_res->start_line = (duk_uint32_t) func->min_line;\n\th_res->end_line = (duk_uint32_t) func->max_line;\n#endif\n\n\t/*\n\t *  Init object properties\n\t *\n\t *  Properties should be added in decreasing order of access frequency.\n\t *  (Not very critical for function templates.)\n\t */\n\n\tDUK_DDD(DUK_DDDPRINT(\"init function properties\"));\n\n\t/* [ ... res ] */\n\n\t/* _Varmap: omitted if function is guaranteed not to do a slow path\n\t * identifier access that might be caught by locally declared variables.\n\t * The varmap can also be omitted if it turns out empty of actual\n\t * register mappings after a cleanup.  When debugging is enabled, we\n\t * always need the varmap to be able to lookup variables at any point.\n\t */\n\n#if defined(DUK_USE_DEBUGGER_SUPPORT)\n\tDUK_DD(DUK_DDPRINT(\"keeping _Varmap because debugger support is enabled\"));\n\tkeep_varmap = 1;\n#else\n\tif (func->id_access_slow_own ||   /* directly uses slow accesses that may match own variables */\n\t    func->id_access_arguments ||  /* accesses 'arguments' directly */\n\t    func->may_direct_eval ||      /* may indirectly slow access through a direct eval */\n\t    funcs_count > 0) {            /* has inner functions which may slow access (XXX: this can be optimized by looking at the inner functions) */\n\t\tDUK_DD(DUK_DDPRINT(\"keeping _Varmap because of direct eval, slow path access that may match local variables, or presence of inner functions\"));\n\t\tkeep_varmap = 1;\n\t} else {\n\t\tDUK_DD(DUK_DDPRINT(\"dropping _Varmap\"));\n\t\tkeep_varmap = 0;\n\t}\n#endif\n\n\tif (keep_varmap) {\n\t\tduk_int_t num_used;\n\t\tduk_dup(thr, func->varmap_idx);\n\t\tnum_used = duk__cleanup_varmap(comp_ctx);\n\t\tDUK_DDD(DUK_DDDPRINT(\"cleaned up varmap: %!T (num_used=%ld)\",\n\t\t                     (duk_tval *) duk_get_tval(thr, -1), (long) num_used));\n\n\t\tif (num_used > 0) {\n\t\t\tduk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_VARMAP, DUK_PROPDESC_FLAGS_NONE);\n\t\t} else {\n\t\t\tDUK_DD(DUK_DDPRINT(\"varmap is empty after cleanup -> no need to add\"));\n\t\t\tduk_pop(thr);\n\t\t}\n\t}\n\n\t/* _Formals: omitted if function is guaranteed not to need a (non-strict)\n\t * arguments object, and _Formals.length matches nargs exactly.\n\t *\n\t * Non-arrow functions can't see an outer function's 'argument' binding\n\t * (because they have their own), but arrow functions can.  When arrow\n\t * functions are added, this condition would need to be added:\n\t *     inner_arrow_funcs_count > 0   inner arrow functions may access 'arguments'\n\t */\n#if defined(DUK_USE_DEBUGGER_SUPPORT)\n\tDUK_DD(DUK_DDPRINT(\"keeping _Formals because debugger support is enabled\"));\n\tkeep_formals = 1;\n#else\n\tformals_length = duk_get_length(thr, func->argnames_idx);\n\tif (formals_length != (duk_size_t) h_res->nargs) {\n\t\t/* Nargs not enough for closure .length: keep _Formals regardless\n\t\t * of its length.  Shouldn't happen in practice at the moment.\n\t\t */\n\t\tDUK_DD(DUK_DDPRINT(\"keeping _Formals because _Formals.length != nargs\"));\n\t\tkeep_formals = 1;\n\t} else if ((func->id_access_arguments || func->may_direct_eval) &&\n\t           (formals_length > 0)) {\n\t\t/* Direct eval (may access 'arguments') or accesses 'arguments'\n\t\t * explicitly: keep _Formals unless it is zero length.\n\t\t */\n\t\tDUK_DD(DUK_DDPRINT(\"keeping _Formals because of direct eval or explicit access to 'arguments', and _Formals.length != 0\"));\n\t\tkeep_formals = 1;\n\t} else {\n\t\tDUK_DD(DUK_DDPRINT(\"omitting _Formals, nargs matches _Formals.length, so no properties added\"));\n\t\tkeep_formals = 0;\n\t}\n#endif\n\n\tif (keep_formals) {\n\t\tduk_dup(thr, func->argnames_idx);\n\t\tduk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_FORMALS, DUK_PROPDESC_FLAGS_NONE);\n\t}\n\n\t/* name */\n#if defined(DUK_USE_FUNC_NAME_PROPERTY)\n\tif (func->h_name) {\n\t\tduk_push_hstring(thr, func->h_name);\n\t\tDUK_DD(DUK_DDPRINT(\"setting function template .name to %!T\", duk_get_tval(thr, -1)));\n\t\tduk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_NAME, DUK_PROPDESC_FLAGS_NONE);\n\t}\n#endif  /* DUK_USE_FUNC_NAME_PROPERTY */\n\n\t/* _Source */\n#if defined(DUK_USE_NONSTD_FUNC_SOURCE_PROPERTY)\n\tif (0) {\n\t\t/* XXX: Currently function source code is not stored, as it is not\n\t\t * required by the standard.  Source code should not be stored by\n\t\t * default (user should enable it explicitly), and the source should\n\t\t * probably be compressed with a trivial text compressor; average\n\t\t * compression of 20-30% is quite easy to achieve even with a trivial\n\t\t * compressor (RLE + backwards lookup).\n\t\t *\n\t\t * Debugging needs source code to be useful: sometimes input code is\n\t\t * not found in files as it may be generated and then eval()'d, given\n\t\t * by dynamic C code, etc.\n\t\t *\n\t\t * Other issues:\n\t\t *\n\t\t *   - Need tokenizer indices for start and end to substring\n\t\t *   - Always normalize function declaration part?\n\t\t *   - If we keep _Formals, only need to store body\n\t\t */\n\n\t\t/*\n\t\t *  For global or eval code this is straightforward.  For functions\n\t\t *  created with the Function constructor we only get the source for\n\t\t *  the body and must manufacture the \"function ...\" part.\n\t\t *\n\t\t *  For instance, for constructed functions (v8):\n\t\t *\n\t\t *    > a = new Function(\"foo\", \"bar\", \"print(foo)\");\n\t\t *    [Function]\n\t\t *    > a.toString()\n\t\t *    'function anonymous(foo,bar) {\\nprint(foo)\\n}'\n\t\t *\n\t\t *  Similarly for e.g. getters (v8):\n\t\t *\n\t\t *    > x = { get a(foo,bar) { print(foo); } }\n\t\t *    { a: [Getter] }\n\t\t *    > Object.getOwnPropertyDescriptor(x, 'a').get.toString()\n\t\t *    'function a(foo,bar) { print(foo); }'\n\t\t */\n\n#if 0\n\t\tduk_push_string(thr, \"XXX\");\n\t\tduk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_SOURCE, DUK_PROPDESC_FLAGS_NONE);\n#endif\n\t}\n#endif  /* DUK_USE_NONSTD_FUNC_SOURCE_PROPERTY */\n\n\t/* _Pc2line */\n#if defined(DUK_USE_PC2LINE)\n\tif (1) {\n\t\t/*\n\t\t *  Size-optimized pc->line mapping.\n\t\t */\n\n\t\tDUK_ASSERT(code_count <= DUK_COMPILER_MAX_BYTECODE_LENGTH);\n\t\tduk_hobject_pc2line_pack(thr, q_instr, (duk_uint_fast32_t) code_count);  /* -> pushes fixed buffer */\n\t\tduk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_PC2LINE, DUK_PROPDESC_FLAGS_NONE);\n\n\t\t/* XXX: if assertions enabled, walk through all valid PCs\n\t\t * and check line mapping.\n\t\t */\n\t}\n#endif  /* DUK_USE_PC2LINE */\n\n\t/* fileName */\n#if defined(DUK_USE_FUNC_FILENAME_PROPERTY)\n\tif (comp_ctx->h_filename) {\n\t\t/*\n\t\t *  Source filename (or equivalent), for identifying thrown errors.\n\t\t */\n\n\t\tduk_push_hstring(thr, comp_ctx->h_filename);\n\t\tduk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_FILE_NAME, DUK_PROPDESC_FLAGS_NONE);\n\t}\n#endif\n\n\tDUK_DD(DUK_DDPRINT(\"converted function: %!ixT\",\n\t                   (duk_tval *) duk_get_tval(thr, -1)));\n\n\t/*\n\t *  Compact the function template.\n\t */\n\n\tduk_compact_m1(thr);\n\n\t/*\n\t *  Debug dumping\n\t */\n\n#if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)\n\t{\n\t\tduk_hcompfunc *h;\n\t\tduk_instr_t *p, *p_start, *p_end;\n\n\t\th = (duk_hcompfunc *) duk_get_hobject(thr, -1);\n\t\tp_start = (duk_instr_t *) DUK_HCOMPFUNC_GET_CODE_BASE(thr->heap, h);\n\t\tp_end = (duk_instr_t *) DUK_HCOMPFUNC_GET_CODE_END(thr->heap, h);\n\n\t\tp = p_start;\n\t\twhile (p < p_end) {\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"BC %04ld: %!I        ; 0x%08lx op=%ld (%!C) a=%ld b=%ld c=%ld\",\n\t\t\t                     (long) (p - p_start),\n\t\t\t                     (duk_instr_t) (*p),\n\t\t\t                     (unsigned long) (*p),\n\t\t\t                     (long) DUK_DEC_OP(*p),\n\t\t\t                     (long) DUK_DEC_OP(*p),\n\t\t\t                     (long) DUK_DEC_A(*p),\n\t\t\t                     (long) DUK_DEC_B(*p),\n\t\t\t                     (long) DUK_DEC_C(*p)));\n\t\t\tp++;\n\t\t}\n\t}\n#endif\n}\n\n/*\n *  Code emission helpers\n *\n *  Some emission helpers understand the range of target and source reg/const\n *  values and automatically emit shuffling code if necessary.  This is the\n *  case when the slot in question (A, B, C) is used in the standard way and\n *  for opcodes the emission helpers explicitly understand (like DUK_OP_MPUTOBJ).\n *\n *  The standard way is that:\n *    - slot A is a target register\n *    - slot B is a source register/constant\n *    - slot C is a source register/constant\n *\n *  If a slot is used in a non-standard way the caller must indicate this\n *  somehow.  If a slot is used as a target instead of a source (or vice\n *  versa), this can be indicated with a flag to trigger proper shuffling\n *  (e.g. DUK__EMIT_FLAG_B_IS_TARGET).  If the value in the slot is not\n *  register/const related at all, the caller must ensure that the raw value\n *  fits into the corresponding slot so as to not trigger shuffling.  The\n *  caller must set a \"no shuffle\" flag to ensure compilation fails if\n *  shuffling were to be triggered because of an internal error.\n *\n *  For slots B and C the raw slot size is 9 bits but one bit is reserved for\n *  the reg/const indicator.  To use the full 9-bit range for a raw value,\n *  shuffling must be disabled with the DUK__EMIT_FLAG_NO_SHUFFLE_{B,C} flag.\n *  Shuffling is only done for A, B, and C slots, not the larger BC or ABC slots.\n *\n *  There is call handling specific understanding in the A-B-C emitter to\n *  convert call setup and call instructions into indirect ones if necessary.\n */\n\n/* Code emission flags, passed in the 'opcode' field.  Opcode + flags\n * fit into 16 bits for now, so use duk_small_uint_t.\n */\n#define DUK__EMIT_FLAG_NO_SHUFFLE_A      (1 << 8)\n#define DUK__EMIT_FLAG_NO_SHUFFLE_B      (1 << 9)\n#define DUK__EMIT_FLAG_NO_SHUFFLE_C      (1 << 10)\n#define DUK__EMIT_FLAG_A_IS_SOURCE       (1 << 11)  /* slot A is a source (default: target) */\n#define DUK__EMIT_FLAG_B_IS_TARGET       (1 << 12)  /* slot B is a target (default: source) */\n#define DUK__EMIT_FLAG_C_IS_TARGET       (1 << 13)  /* slot C is a target (default: source) */\n#define DUK__EMIT_FLAG_BC_REGCONST       (1 << 14)  /* slots B and C are reg/const */\n#define DUK__EMIT_FLAG_RESERVE_JUMPSLOT  (1 << 15)  /* reserve a jumpslot after instr before target spilling, used for NEXTENUM */\n\n/* XXX: macro smaller than call? */\nDUK_LOCAL duk_int_t duk__get_current_pc(duk_compiler_ctx *comp_ctx) {\n\tduk_compiler_func *func;\n\tfunc = &comp_ctx->curr_func;\n\treturn (duk_int_t) (DUK_BW_GET_SIZE(comp_ctx->thr, &func->bw_code) / sizeof(duk_compiler_instr));\n}\n\nDUK_LOCAL duk_compiler_instr *duk__get_instr_ptr(duk_compiler_ctx *comp_ctx, duk_int_t pc) {\n\tDUK_ASSERT(pc >= 0);\n\tDUK_ASSERT((duk_size_t) pc < (duk_size_t) (DUK_BW_GET_SIZE(comp_ctx->thr, &comp_ctx->curr_func.bw_code) / sizeof(duk_compiler_instr)));\n\treturn ((duk_compiler_instr *) (void *) DUK_BW_GET_BASEPTR(comp_ctx->thr, &comp_ctx->curr_func.bw_code)) + pc;\n}\n\n/* emit instruction; could return PC but that's not needed in the majority\n * of cases.\n */\nDUK_LOCAL void duk__emit(duk_compiler_ctx *comp_ctx, duk_instr_t ins) {\n#if defined(DUK_USE_PC2LINE)\n\tduk_int_t line;\n#endif\n\tduk_compiler_instr *instr;\n\n\tDUK_DDD(DUK_DDDPRINT(\"duk__emit: 0x%08lx curr_token.start_line=%ld prev_token.start_line=%ld pc=%ld --> %!I\",\n\t                     (unsigned long) ins,\n\t                     (long) comp_ctx->curr_token.start_line,\n\t                     (long) comp_ctx->prev_token.start_line,\n\t                     (long) duk__get_current_pc(comp_ctx),\n\t                     (duk_instr_t) ins));\n\n\tinstr = (duk_compiler_instr *) (void *) DUK_BW_ENSURE_GETPTR(comp_ctx->thr, &comp_ctx->curr_func.bw_code, sizeof(duk_compiler_instr));\n\tDUK_BW_ADD_PTR(comp_ctx->thr, &comp_ctx->curr_func.bw_code, sizeof(duk_compiler_instr));\n\n#if defined(DUK_USE_PC2LINE)\n\t/* The line number tracking is a bit inconsistent right now, which\n\t * affects debugger accuracy.  Mostly call sites emit opcodes when\n\t * they have parsed a token (say a terminating semicolon) and called\n\t * duk__advance().  In this case the line number of the previous\n\t * token is the most accurate one (except in prologue where\n\t * prev_token.start_line is 0).  This is probably not 100% correct\n\t * right now.\n\t */\n\t/* approximation, close enough */\n\tline = comp_ctx->prev_token.start_line;\n\tif (line == 0) {\n\t\tline = comp_ctx->curr_token.start_line;\n\t}\n#endif\n\n\tinstr->ins = ins;\n#if defined(DUK_USE_PC2LINE)\n\tinstr->line = (duk_uint32_t) line;\n#endif\n#if defined(DUK_USE_DEBUGGER_SUPPORT)\n\tif (line < comp_ctx->curr_func.min_line) {\n\t\tcomp_ctx->curr_func.min_line = line;\n\t}\n\tif (line > comp_ctx->curr_func.max_line) {\n\t\tcomp_ctx->curr_func.max_line = line;\n\t}\n#endif\n\n\t/* Limit checks for bytecode byte size and line number. */\n\tif (DUK_UNLIKELY(DUK_BW_GET_SIZE(comp_ctx->thr, &comp_ctx->curr_func.bw_code) > DUK_USE_ESBC_MAX_BYTES)) {\n\t\tgoto fail_bc_limit;\n\t}\n#if defined(DUK_USE_PC2LINE) && defined(DUK_USE_ESBC_LIMITS)\n#if defined(DUK_USE_BUFLEN16)\n\t/* Buffer length is bounded to 0xffff automatically, avoid compile warning. */\n\tif (DUK_UNLIKELY(line > DUK_USE_ESBC_MAX_LINENUMBER)) {\n\t\tgoto fail_bc_limit;\n\t}\n#else\n\tif (DUK_UNLIKELY(line > DUK_USE_ESBC_MAX_LINENUMBER)) {\n\t\tgoto fail_bc_limit;\n\t}\n#endif\n#endif\n\n\treturn;\n\n  fail_bc_limit:\n\tDUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_BYTECODE_LIMIT);\n}\n\n/* Update function min/max line from current token.  Needed to improve\n * function line range information for debugging, so that e.g. opening\n * curly brace is covered by line range even when no opcodes are emitted\n * for the line containing the brace.\n */\nDUK_LOCAL void duk__update_lineinfo_currtoken(duk_compiler_ctx *comp_ctx) {\n#if defined(DUK_USE_DEBUGGER_SUPPORT)\n\tduk_int_t line;\n\n\tline = comp_ctx->curr_token.start_line;\n\tif (line == 0) {\n\t\treturn;\n\t}\n\tif (line < comp_ctx->curr_func.min_line) {\n\t\tcomp_ctx->curr_func.min_line = line;\n\t}\n\tif (line > comp_ctx->curr_func.max_line) {\n\t\tcomp_ctx->curr_func.max_line = line;\n\t}\n#else\n\tDUK_UNREF(comp_ctx);\n#endif\n}\n\nDUK_LOCAL void duk__emit_op_only(duk_compiler_ctx *comp_ctx, duk_small_uint_t op) {\n\tduk__emit(comp_ctx, DUK_ENC_OP_ABC(op, 0));\n}\n\n/* Important main primitive. */\nDUK_LOCAL void duk__emit_a_b_c(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_flags, duk_regconst_t a, duk_regconst_t b, duk_regconst_t c) {\n\tduk_instr_t ins = 0;\n\tduk_int_t a_out = -1;\n\tduk_int_t b_out = -1;\n\tduk_int_t c_out = -1;\n\tduk_int_t tmp;\n\tduk_small_uint_t op = op_flags & 0xffU;\n\n\tDUK_DDD(DUK_DDDPRINT(\"emit: op_flags=%04lx, a=%ld, b=%ld, c=%ld\",\n\t                     (unsigned long) op_flags, (long) a, (long) b, (long) c));\n\n\t/* We could rely on max temp/const checks: if they don't exceed BC\n\t * limit, nothing here can either (just asserts would be enough).\n\t * Currently we check for the limits, which provides additional\n\t * protection against creating invalid bytecode due to compiler\n\t * bugs.\n\t */\n\n\tDUK_ASSERT_DISABLE((op_flags & 0xff) >= DUK_BC_OP_MIN);  /* unsigned */\n\tDUK_ASSERT((op_flags & 0xff) <= DUK_BC_OP_MAX);\n\tDUK_ASSERT(DUK__ISREG(a));\n\tDUK_ASSERT(b != -1);  /* Not 'none'. */\n\tDUK_ASSERT(c != -1);  /* Not 'none'. */\n\n\t/* Input shuffling happens before the actual operation, while output\n\t * shuffling happens afterwards.  Output shuffling decisions are still\n\t * made at the same time to reduce branch clutter; output shuffle decisions\n\t * are recorded into X_out variables.\n\t */\n\n\t/* Slot A: currently no support for reg/const. */\n\n#if defined(DUK_USE_SHUFFLE_TORTURE)\n\tif (a <= DUK_BC_A_MAX && (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_A)) {\n#else\n\tif (a <= DUK_BC_A_MAX) {\n#endif\n\t\t;\n\t} else if (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_A) {\n\t\tDUK_D(DUK_DPRINT(\"out of regs: 'a' (reg) needs shuffling but shuffle prohibited, a: %ld\", (long) a));\n\t\tgoto error_outofregs;\n\t} else if (a <= DUK_BC_BC_MAX) {\n\t\tcomp_ctx->curr_func.needs_shuffle = 1;\n\t\ttmp = comp_ctx->curr_func.shuffle1;\n\t\tif (op_flags & DUK__EMIT_FLAG_A_IS_SOURCE) {\n\t\t\tduk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_LDREG, tmp, a));\n\t\t} else {\n\t\t\t/* Output shuffle needed after main operation */\n\t\t\ta_out = a;\n\n\t\t\t/* The DUK_OP_CSVAR output shuffle assumes shuffle registers are\n\t\t\t * consecutive.\n\t\t\t */\n\t\t\tDUK_ASSERT((comp_ctx->curr_func.shuffle1 == 0 && comp_ctx->curr_func.shuffle2 == 0) ||\n\t\t\t           (comp_ctx->curr_func.shuffle2 == comp_ctx->curr_func.shuffle1 + 1));\n\t\t\tif (op == DUK_OP_CSVAR) {\n\t\t\t\t/* For CSVAR the limit is one smaller because output shuffle\n\t\t\t\t * must be able to express 'a + 1' in BC.\n\t\t\t\t */\n\t\t\t\tif (a + 1 > DUK_BC_BC_MAX) {\n\t\t\t\t\tgoto error_outofregs;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\ta = tmp;\n\t} else {\n\t\tDUK_D(DUK_DPRINT(\"out of regs: 'a' (reg) needs shuffling but does not fit into BC, a: %ld\", (long) a));\n\t\tgoto error_outofregs;\n\t}\n\n\t/* Slot B: reg/const support, mapped to bit 0 of opcode. */\n\n\tif ((b & DUK__CONST_MARKER) != 0) {\n\t\tDUK_ASSERT((op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_B) == 0);\n\t\tDUK_ASSERT((op_flags & DUK__EMIT_FLAG_B_IS_TARGET) == 0);\n\t\tb = b & ~DUK__CONST_MARKER;\n#if defined(DUK_USE_SHUFFLE_TORTURE)\n\t\tif (0) {\n#else\n\t\tif (b <= 0xff) {\n#endif\n\t\t\tif (op_flags & DUK__EMIT_FLAG_BC_REGCONST) {\n\t\t\t\t/* Opcode follows B/C reg/const convention. */\n\t\t\t\tDUK_ASSERT((op & 0x01) == 0);\n\t\t\t\tins |= DUK_ENC_OP_A_B_C(0x01, 0, 0, 0);  /* const flag for B */\n\t\t\t} else {\n\t\t\t\tDUK_D(DUK_DPRINT(\"B is const, opcode is not B/C reg/const: %x\", op_flags));\n\t\t\t}\n\t\t} else if (b <= DUK_BC_BC_MAX) {\n\t\t\tcomp_ctx->curr_func.needs_shuffle = 1;\n\t\t\ttmp = comp_ctx->curr_func.shuffle2;\n\t\t\tduk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_LDCONST, tmp, b));\n\t\t\tb = tmp;\n\t\t} else {\n\t\t\tDUK_D(DUK_DPRINT(\"out of regs: 'b' (const) needs shuffling but does not fit into BC, b: %ld\", (long) b));\n\t\t\tgoto error_outofregs;\n\t\t}\n\t} else {\n#if defined(DUK_USE_SHUFFLE_TORTURE)\n\t\tif (b <= 0xff && (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_B)) {\n#else\n\t\tif (b <= 0xff) {\n#endif\n\t\t\t;\n\t\t} else if (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_B) {\n\t\t\tif (b > DUK_BC_B_MAX) {\n\t\t\t\t/* Note: 0xff != DUK_BC_B_MAX */\n\t\t\t\tDUK_D(DUK_DPRINT(\"out of regs: 'b' (reg) needs shuffling but shuffle prohibited, b: %ld\", (long) b));\n\t\t\t\tgoto error_outofregs;\n\t\t\t}\n\t\t} else if (b <= DUK_BC_BC_MAX) {\n\t\t\tcomp_ctx->curr_func.needs_shuffle = 1;\n\t\t\ttmp = comp_ctx->curr_func.shuffle2;\n\t\t\tif (op_flags & DUK__EMIT_FLAG_B_IS_TARGET) {\n\t\t\t\t/* Output shuffle needed after main operation */\n\t\t\t\tb_out = b;\n\t\t\t}\n\t\t\tif (!(op_flags & DUK__EMIT_FLAG_B_IS_TARGET)) {\n\t\t\t\tif (op == DUK_OP_MPUTOBJ || op == DUK_OP_MPUTARR) {\n\t\t\t\t\t/* Special handling for MPUTOBJ/MPUTARR shuffling.\n\t\t\t\t\t * For each, slot B identifies the first register of a range\n\t\t\t\t\t * of registers, so normal shuffling won't work.  Instead,\n\t\t\t\t\t * an indirect version of the opcode is used.\n\t\t\t\t\t */\n\t\t\t\t\tDUK_ASSERT((op_flags & DUK__EMIT_FLAG_B_IS_TARGET) == 0);\n\t\t\t\t\tduk__emit_load_int32_noshuffle(comp_ctx, tmp, b);\n\t\t\t\t\tDUK_ASSERT(DUK_OP_MPUTOBJI == DUK_OP_MPUTOBJ + 1);\n\t\t\t\t\tDUK_ASSERT(DUK_OP_MPUTARRI == DUK_OP_MPUTARR + 1);\n\t\t\t\t\top_flags++;  /* indirect opcode follows direct */\n\t\t\t\t} else {\n\t\t\t\t\tduk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_LDREG, tmp, b));\n\t\t\t\t}\n\t\t\t}\n\t\t\tb = tmp;\n\t\t} else {\n\t\t\tDUK_D(DUK_DPRINT(\"out of regs: 'b' (reg) needs shuffling but does not fit into BC, b: %ld\", (long) b));\n\t\t\tgoto error_outofregs;\n\t\t}\n\t}\n\n\t/* Slot C: reg/const support, mapped to bit 1 of opcode. */\n\n\tif ((c & DUK__CONST_MARKER) != 0) {\n\t\tDUK_ASSERT((op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_C) == 0);\n\t\tDUK_ASSERT((op_flags & DUK__EMIT_FLAG_C_IS_TARGET) == 0);\n\t\tc = c & ~DUK__CONST_MARKER;\n#if defined(DUK_USE_SHUFFLE_TORTURE)\n\t\tif (0) {\n#else\n\t\tif (c <= 0xff) {\n#endif\n\t\t\tif (op_flags & DUK__EMIT_FLAG_BC_REGCONST) {\n\t\t\t\t/* Opcode follows B/C reg/const convention. */\n\t\t\t\tDUK_ASSERT((op & 0x02) == 0);\n\t\t\t\tins |= DUK_ENC_OP_A_B_C(0x02, 0, 0, 0);  /* const flag for C */\n\t\t\t} else {\n\t\t\t\tDUK_D(DUK_DPRINT(\"C is const, opcode is not B/C reg/const: %x\", op_flags));\n\t\t\t}\n\t\t} else if (c <= DUK_BC_BC_MAX) {\n\t\t\tcomp_ctx->curr_func.needs_shuffle = 1;\n\t\t\ttmp = comp_ctx->curr_func.shuffle3;\n\t\t\tduk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_LDCONST, tmp, c));\n\t\t\tc = tmp;\n\t\t} else {\n\t\t\tDUK_D(DUK_DPRINT(\"out of regs: 'c' (const) needs shuffling but does not fit into BC, c: %ld\", (long) c));\n\t\t\tgoto error_outofregs;\n\t\t}\n\t} else {\n#if defined(DUK_USE_SHUFFLE_TORTURE)\n\t\tif (c <= 0xff && (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_C)) {\n#else\n\t\tif (c <= 0xff) {\n#endif\n\t\t\t;\n\t\t} else if (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_C) {\n\t\t\tif (c > DUK_BC_C_MAX) {\n\t\t\t\t/* Note: 0xff != DUK_BC_C_MAX */\n\t\t\t\tDUK_D(DUK_DPRINT(\"out of regs: 'c' (reg) needs shuffling but shuffle prohibited, c: %ld\", (long) c));\n\t\t\t\tgoto error_outofregs;\n\t\t\t}\n\t\t} else if (c <= DUK_BC_BC_MAX) {\n\t\t\tcomp_ctx->curr_func.needs_shuffle = 1;\n\t\t\ttmp = comp_ctx->curr_func.shuffle3;\n\t\t\tif (op_flags & DUK__EMIT_FLAG_C_IS_TARGET) {\n\t\t\t\t/* Output shuffle needed after main operation */\n\t\t\t\tc_out = c;\n\t\t\t} else {\n\t\t\t\tduk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_LDREG, tmp, c));\n\t\t\t}\n\t\t\tc = tmp;\n\t\t} else {\n\t\t\tDUK_D(DUK_DPRINT(\"out of regs: 'c' (reg) needs shuffling but does not fit into BC, c: %ld\", (long) c));\n\t\t\tgoto error_outofregs;\n\t\t}\n\t}\n\n\t/* Main operation */\n\n\tDUK_ASSERT(a >= DUK_BC_A_MIN);\n\tDUK_ASSERT(a <= DUK_BC_A_MAX);\n\tDUK_ASSERT(b >= DUK_BC_B_MIN);\n\tDUK_ASSERT(b <= DUK_BC_B_MAX);\n\tDUK_ASSERT(c >= DUK_BC_C_MIN);\n\tDUK_ASSERT(c <= DUK_BC_C_MAX);\n\n\tins |= DUK_ENC_OP_A_B_C(op_flags & 0xff, a, b, c);\n\tduk__emit(comp_ctx, ins);\n\n\t/* NEXTENUM needs a jump slot right after the main instruction.\n\t * When the JUMP is taken, output spilling is not needed so this\n\t * workaround is possible.  The jump slot PC is exceptionally\n\t * plumbed through comp_ctx to minimize call sites.\n\t */\n\tif (op_flags & DUK__EMIT_FLAG_RESERVE_JUMPSLOT) {\n\t\tcomp_ctx->emit_jumpslot_pc = duk__get_current_pc(comp_ctx);\n\t\tduk__emit_abc(comp_ctx, DUK_OP_JUMP, 0);\n\t}\n\n\t/* Output shuffling: only one output register is realistically possible.\n\t *\n\t * (Zero would normally be an OK marker value: if the target register\n\t * was zero, it would never be shuffled.  But with DUK_USE_SHUFFLE_TORTURE\n\t * this is no longer true, so use -1 as a marker instead.)\n\t */\n\n\tif (a_out >= 0) {\n\t\tDUK_ASSERT(b_out < 0);\n\t\tDUK_ASSERT(c_out < 0);\n\t\tduk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_STREG, a, a_out));\n\n\t\tif (op == DUK_OP_CSVAR) {\n\t\t\t/* Special handling for CSVAR shuffling.  The variable lookup\n\t\t\t * results in a <value, this binding> pair in successive\n\t\t\t * registers so use two shuffle registers and two output\n\t\t\t * loads.  (In practice this is dead code because temp/const\n\t\t\t * limit is reached first.)\n\t\t\t */\n\t\t\tduk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_STREG, a + 1, a_out + 1));\n\t\t}\n\t} else if (b_out >= 0) {\n\t\tDUK_ASSERT(a_out < 0);\n\t\tDUK_ASSERT(c_out < 0);\n\t\tduk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_STREG, b, b_out));\n\t} else if (c_out >= 0) {\n\t\tDUK_ASSERT(b_out < 0);\n\t\tDUK_ASSERT(c_out < 0);\n\t\tduk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_STREG, c, c_out));\n\t}\n\n\treturn;\n\n error_outofregs:\n\tDUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_REG_LIMIT);\n}\n\n/* For many of the helpers below it'd be technically correct to add\n * \"no shuffle\" flags for parameters passed in as zero.  For example,\n * duk__emit_a_b() should call duk__emit_a_b_c() with C set to 0, and\n * DUK__EMIT_FLAG_NO_SHUFFLE_C added to op_flags.  However, since the\n * C value is 0, it'll never get shuffled so adding the flag is just\n * unnecessary additional code.  This is unfortunately not true for\n * \"shuffle torture\" mode which needs special handling.\n */\n\nDUK_LOCAL void duk__emit_a_b(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_flags, duk_regconst_t a, duk_regconst_t b) {\n#if defined(DUK_USE_SHUFFLE_TORTURE)\n\top_flags |= DUK__EMIT_FLAG_NO_SHUFFLE_C;\n#endif\n\tduk__emit_a_b_c(comp_ctx, op_flags, a, b, 0);\n}\n\nDUK_LOCAL void duk__emit_b_c(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_flags, duk_regconst_t b, duk_regconst_t c) {\n#if defined(DUK_USE_SHUFFLE_TORTURE)\n\top_flags |= DUK__EMIT_FLAG_NO_SHUFFLE_A;\n#endif\n\tduk__emit_a_b_c(comp_ctx, op_flags, 0, b, c);\n}\n\n#if 0  /* unused */\nDUK_LOCAL void duk__emit_a(duk_compiler_ctx *comp_ctx, int op_flags, int a) {\n#if defined(DUK_USE_SHUFFLE_TORTURE)\n\top_flags |= DUK__EMIT_FLAG_NO_SHUFFLE_B | DUK__EMIT_FLAG_NO_SHUFFLE_C;\n#endif\n\tduk__emit_a_b_c(comp_ctx, op_flags, a, 0, 0);\n}\n#endif\n\n#if 0  /* unused */\nDUK_LOCAL void duk__emit_b(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_flags, duk_regconst_t b) {\n#if defined(DUK_USE_SHUFFLE_TORTURE)\n\top_flags |= DUK__EMIT_FLAG_NO_SHUFFLE_A | DUK__EMIT_FLAG_NO_SHUFFLE_C;\n#endif\n\tduk__emit_a_b_c(comp_ctx, op_flags, 0, b, 0);\n}\n#endif\n\nDUK_LOCAL void duk__emit_a_bc(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_flags, duk_regconst_t a, duk_regconst_t bc) {\n\tduk_instr_t ins;\n\tduk_int_t tmp;\n\n\t/* allow caller to give a const number with the DUK__CONST_MARKER */\n\tDUK_ASSERT(bc != -1);  /* Not 'none'. */\n\tbc = bc & (~DUK__CONST_MARKER);\n\n\tDUK_ASSERT_DISABLE((op_flags & 0xff) >= DUK_BC_OP_MIN);  /* unsigned */\n\tDUK_ASSERT((op_flags & 0xff) <= DUK_BC_OP_MAX);\n\tDUK_ASSERT(bc >= DUK_BC_BC_MIN);\n\tDUK_ASSERT(bc <= DUK_BC_BC_MAX);\n\tDUK_ASSERT((bc & DUK__CONST_MARKER) == 0);\n\n\tif (bc <= DUK_BC_BC_MAX) {\n\t\t;\n\t} else {\n\t\t/* No BC shuffling now. */\n\t\tgoto error_outofregs;\n\t}\n\n#if defined(DUK_USE_SHUFFLE_TORTURE)\n\tif (a <= DUK_BC_A_MAX && (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_A)) {\n#else\n\tif (a <= DUK_BC_A_MAX) {\n#endif\n\t\tins = DUK_ENC_OP_A_BC(op_flags & 0xff, a, bc);\n\t\tduk__emit(comp_ctx, ins);\n\t} else if (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_A) {\n\t\tgoto error_outofregs;\n\t} else if ((op_flags & 0xf0U) == DUK_OP_CALL0) {\n\t\tcomp_ctx->curr_func.needs_shuffle = 1;\n\t\ttmp = comp_ctx->curr_func.shuffle1;\n\t\tduk__emit_load_int32_noshuffle(comp_ctx, tmp, a);\n\t\top_flags |= DUK_BC_CALL_FLAG_INDIRECT;\n\t\tins = DUK_ENC_OP_A_BC(op_flags & 0xff, tmp, bc);\n\t\tduk__emit(comp_ctx, ins);\n\t} else if (a <= DUK_BC_BC_MAX) {\n\t\tcomp_ctx->curr_func.needs_shuffle = 1;\n\t\ttmp = comp_ctx->curr_func.shuffle1;\n\t\tins = DUK_ENC_OP_A_BC(op_flags & 0xff, tmp, bc);\n\t\tif (op_flags & DUK__EMIT_FLAG_A_IS_SOURCE) {\n\t\t\tduk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_LDREG, tmp, a));\n\t\t\tduk__emit(comp_ctx, ins);\n\t\t} else {\n\t\t\tduk__emit(comp_ctx, ins);\n\t\t\tduk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_STREG, tmp, a));\n\t\t}\n\t} else {\n\t\tgoto error_outofregs;\n\t}\n\treturn;\n\n error_outofregs:\n\tDUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_REG_LIMIT);\n}\n\nDUK_LOCAL void duk__emit_bc(duk_compiler_ctx *comp_ctx, duk_small_uint_t op, duk_regconst_t bc) {\n#if defined(DUK_USE_SHUFFLE_TORTURE)\n\top |= DUK__EMIT_FLAG_NO_SHUFFLE_A;\n#endif\n\tduk__emit_a_bc(comp_ctx, op, 0, bc);\n}\n\nDUK_LOCAL void duk__emit_abc(duk_compiler_ctx *comp_ctx, duk_small_uint_t op, duk_regconst_t abc) {\n\tduk_instr_t ins;\n\n\tDUK_ASSERT_DISABLE(op >= DUK_BC_OP_MIN);  /* unsigned */\n\tDUK_ASSERT(op <= DUK_BC_OP_MAX);\n\tDUK_ASSERT_DISABLE(abc >= DUK_BC_ABC_MIN);  /* unsigned */\n\tDUK_ASSERT(abc <= DUK_BC_ABC_MAX);\n\tDUK_ASSERT((abc & DUK__CONST_MARKER) == 0);\n\tDUK_ASSERT(abc != -1);  /* Not 'none'. */\n\n\tif (abc <= DUK_BC_ABC_MAX) {\n\t\t;\n\t} else {\n\t\tgoto error_outofregs;\n\t}\n\tins = DUK_ENC_OP_ABC(op, abc);\n\tDUK_DDD(DUK_DDDPRINT(\"duk__emit_abc: 0x%08lx line=%ld pc=%ld op=%ld (%!C) abc=%ld (%!I)\",\n\t                     (unsigned long) ins, (long) comp_ctx->curr_token.start_line,\n\t                     (long) duk__get_current_pc(comp_ctx), (long) op, (long) op,\n\t                     (long) abc, (duk_instr_t) ins));\n\tduk__emit(comp_ctx, ins);\n\treturn;\n\n error_outofregs:\n\tDUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_REG_LIMIT);\n}\n\nDUK_LOCAL void duk__emit_load_int32_raw(duk_compiler_ctx *comp_ctx, duk_regconst_t reg, duk_int32_t val, duk_small_uint_t op_flags) {\n\t/* XXX: Shuffling support could be implemented here so that LDINT+LDINTX\n\t * would only shuffle once (instead of twice).  The current code works\n\t * though, and has a smaller compiler footprint.\n\t */\n\n\tif ((val >= (duk_int32_t) DUK_BC_BC_MIN - (duk_int32_t) DUK_BC_LDINT_BIAS) &&\n\t    (val <= (duk_int32_t) DUK_BC_BC_MAX - (duk_int32_t) DUK_BC_LDINT_BIAS)) {\n\t\tDUK_DDD(DUK_DDDPRINT(\"emit LDINT to reg %ld for %ld\", (long) reg, (long) val));\n\t\tduk__emit_a_bc(comp_ctx, DUK_OP_LDINT | op_flags, reg, (duk_regconst_t) (val + (duk_int32_t) DUK_BC_LDINT_BIAS));\n\t} else {\n\t\tduk_int32_t hi = val >> DUK_BC_LDINTX_SHIFT;\n\t\tduk_int32_t lo = val & ((((duk_int32_t) 1) << DUK_BC_LDINTX_SHIFT) - 1);\n\t\tDUK_ASSERT(lo >= 0);\n\t\tDUK_DDD(DUK_DDDPRINT(\"emit LDINT+LDINTX to reg %ld for %ld -> hi %ld, lo %ld\",\n\t\t                     (long) reg, (long) val, (long) hi, (long) lo));\n\t\tduk__emit_a_bc(comp_ctx, DUK_OP_LDINT | op_flags, reg, (duk_regconst_t) (hi + (duk_int32_t) DUK_BC_LDINT_BIAS));\n\t\tduk__emit_a_bc(comp_ctx, DUK_OP_LDINTX | op_flags, reg, (duk_regconst_t) lo);\n\t}\n}\n\nDUK_LOCAL void duk__emit_load_int32(duk_compiler_ctx *comp_ctx, duk_regconst_t reg, duk_int32_t val) {\n\tduk__emit_load_int32_raw(comp_ctx, reg, val, 0 /*op_flags*/);\n}\n\n#if defined(DUK_USE_SHUFFLE_TORTURE)\n/* Used by duk__emit*() calls so that we don't shuffle the loadints that\n * are needed to handle indirect opcodes.\n */\nDUK_LOCAL void duk__emit_load_int32_noshuffle(duk_compiler_ctx *comp_ctx, duk_regconst_t reg, duk_int32_t val) {\n\tduk__emit_load_int32_raw(comp_ctx, reg, val, DUK__EMIT_FLAG_NO_SHUFFLE_A /*op_flags*/);\n}\n#else\nDUK_LOCAL void duk__emit_load_int32_noshuffle(duk_compiler_ctx *comp_ctx, duk_regconst_t reg, duk_int32_t val) {\n\t/* When torture not enabled, can just use the same helper because\n\t * 'reg' won't get spilled.\n\t */\n\tDUK_ASSERT(reg <= DUK_BC_A_MAX);\n\tduk__emit_load_int32(comp_ctx, reg, val);\n}\n#endif\n\nDUK_LOCAL void duk__emit_jump(duk_compiler_ctx *comp_ctx, duk_int_t target_pc) {\n\tduk_int_t curr_pc;\n\tduk_int_t offset;\n\n\tcurr_pc = (duk_int_t) (DUK_BW_GET_SIZE(comp_ctx->thr, &comp_ctx->curr_func.bw_code) / sizeof(duk_compiler_instr));\n\toffset = (duk_int_t) target_pc - (duk_int_t) curr_pc - 1;\n\tDUK_ASSERT(offset + DUK_BC_JUMP_BIAS >= DUK_BC_ABC_MIN);\n\tDUK_ASSERT(offset + DUK_BC_JUMP_BIAS <= DUK_BC_ABC_MAX);\n\tduk__emit_abc(comp_ctx, DUK_OP_JUMP, (duk_regconst_t) (offset + DUK_BC_JUMP_BIAS));\n}\n\nDUK_LOCAL duk_int_t duk__emit_jump_empty(duk_compiler_ctx *comp_ctx) {\n\tduk_int_t ret;\n\n\tret = duk__get_current_pc(comp_ctx);  /* useful for patching jumps later */\n\tduk__emit_op_only(comp_ctx, DUK_OP_JUMP);\n\treturn ret;\n}\n\n/* Insert an empty jump in the middle of code emitted earlier.  This is\n * currently needed for compiling for-in.\n */\nDUK_LOCAL void duk__insert_jump_entry(duk_compiler_ctx *comp_ctx, duk_int_t jump_pc) {\n#if defined(DUK_USE_PC2LINE)\n\tduk_int_t line;\n#endif\n\tduk_compiler_instr *instr;\n\tduk_size_t offset;\n\n\tDUK_ASSERT(jump_pc >= 0);\n\toffset = (duk_size_t) jump_pc * sizeof(duk_compiler_instr);\n\tinstr = (duk_compiler_instr *) (void *)\n\t        DUK_BW_INSERT_ENSURE_AREA(comp_ctx->thr,\n\t                                  &comp_ctx->curr_func.bw_code,\n\t                                  offset,\n\t                                  sizeof(duk_compiler_instr));\n\n#if defined(DUK_USE_PC2LINE)\n\tline = comp_ctx->curr_token.start_line;  /* approximation, close enough */\n#endif\n\tinstr->ins = DUK_ENC_OP_ABC(DUK_OP_JUMP, 0);\n#if defined(DUK_USE_PC2LINE)\n\tinstr->line = (duk_uint32_t) line;\n#endif\n\n\tDUK_BW_ADD_PTR(comp_ctx->thr, &comp_ctx->curr_func.bw_code, sizeof(duk_compiler_instr));\n\tif (DUK_UNLIKELY(DUK_BW_GET_SIZE(comp_ctx->thr, &comp_ctx->curr_func.bw_code) > DUK_USE_ESBC_MAX_BYTES)) {\n\t\tgoto fail_bc_limit;\n\t}\n\treturn;\n\n  fail_bc_limit:\n\tDUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_BYTECODE_LIMIT);\n}\n\n/* Does not assume that jump_pc contains a DUK_OP_JUMP previously; this is intentional\n * to allow e.g. an INVALID opcode be overwritten with a JUMP (label management uses this).\n */\nDUK_LOCAL void duk__patch_jump(duk_compiler_ctx *comp_ctx, duk_int_t jump_pc, duk_int_t target_pc) {\n\tduk_compiler_instr *instr;\n\tduk_int_t offset;\n\n\t/* allow negative PCs, behave as a no-op */\n\tif (jump_pc < 0) {\n\t\tDUK_DDD(DUK_DDDPRINT(\"duk__patch_jump(): nop call, jump_pc=%ld (<0), target_pc=%ld\",\n\t\t                     (long) jump_pc, (long) target_pc));\n\t\treturn;\n\t}\n\tDUK_ASSERT(jump_pc >= 0);\n\n\t/* XXX: range assert */\n\tinstr = duk__get_instr_ptr(comp_ctx, jump_pc);\n\tDUK_ASSERT(instr != NULL);\n\n\t/* XXX: range assert */\n\toffset = target_pc - jump_pc - 1;\n\n\tinstr->ins = DUK_ENC_OP_ABC(DUK_OP_JUMP, offset + DUK_BC_JUMP_BIAS);\n\tDUK_DDD(DUK_DDDPRINT(\"duk__patch_jump(): jump_pc=%ld, target_pc=%ld, offset=%ld\",\n\t                     (long) jump_pc, (long) target_pc, (long) offset));\n}\n\nDUK_LOCAL void duk__patch_jump_here(duk_compiler_ctx *comp_ctx, duk_int_t jump_pc) {\n\tduk__patch_jump(comp_ctx, jump_pc, duk__get_current_pc(comp_ctx));\n}\n\nDUK_LOCAL void duk__patch_trycatch(duk_compiler_ctx *comp_ctx, duk_int_t ldconst_pc, duk_int_t trycatch_pc, duk_regconst_t reg_catch, duk_regconst_t const_varname, duk_small_uint_t flags) {\n\tduk_compiler_instr *instr;\n\n\tDUK_ASSERT(DUK__ISREG(reg_catch));\n\n\tinstr = duk__get_instr_ptr(comp_ctx, ldconst_pc);\n\tDUK_ASSERT(DUK_DEC_OP(instr->ins) == DUK_OP_LDCONST);\n\tDUK_ASSERT(instr != NULL);\n\tif (const_varname & DUK__CONST_MARKER) {\n\t\t/* Have a catch variable. */\n\t\tconst_varname = const_varname & (~DUK__CONST_MARKER);\n\t\tif (reg_catch > DUK_BC_BC_MAX || const_varname > DUK_BC_BC_MAX) {\n\t\t\t/* Catch attempts to use out-of-range reg/const.  Without this\n\t\t\t * check Duktape 0.12.0 could generate invalid code which caused\n\t\t\t * an assert failure on execution.  This error is triggered e.g.\n\t\t\t * for functions with a lot of constants and a try-catch statement.\n\t\t\t * Shuffling or opcode semantics change is needed to fix the issue.\n\t\t\t * See: test-bug-trycatch-many-constants.js.\n\t\t\t */\n\t\t\tDUK_D(DUK_DPRINT(\"failed to patch trycatch: flags=%ld, reg_catch=%ld, const_varname=%ld (0x%08lx)\",\n\t\t\t                 (long) flags, (long) reg_catch, (long) const_varname, (long) const_varname));\n\t\t\tDUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_REG_LIMIT);\n\t\t}\n\t\tinstr->ins |= DUK_ENC_OP_A_BC(0, 0, const_varname);\n\t} else {\n\t\t/* No catch variable, e.g. a try-finally; replace LDCONST with\n\t\t * NOP to avoid a bogus LDCONST.\n\t\t */\n\t\tinstr->ins = DUK_ENC_OP(DUK_OP_NOP);\n\t}\n\n\tinstr = duk__get_instr_ptr(comp_ctx, trycatch_pc);\n\tDUK_ASSERT(instr != NULL);\n\tDUK_ASSERT_DISABLE(flags >= DUK_BC_A_MIN);\n\tDUK_ASSERT(flags <= DUK_BC_A_MAX);\n\tinstr->ins = DUK_ENC_OP_A_BC(DUK_OP_TRYCATCH, flags, reg_catch);\n}\n\nDUK_LOCAL void duk__emit_if_false_skip(duk_compiler_ctx *comp_ctx, duk_regconst_t regconst) {\n\tduk_small_uint_t op;\n\n\top = DUK__ISREG(regconst) ? DUK_OP_IFFALSE_R : DUK_OP_IFFALSE_C;\n\tduk__emit_bc(comp_ctx, op, regconst);  /* helper will remove const flag */\n}\n\nDUK_LOCAL void duk__emit_if_true_skip(duk_compiler_ctx *comp_ctx, duk_regconst_t regconst) {\n\tduk_small_uint_t op;\n\n\top = DUK__ISREG(regconst) ? DUK_OP_IFTRUE_R : DUK_OP_IFTRUE_C;\n\tduk__emit_bc(comp_ctx, op, regconst);  /* helper will remove const flag */\n}\n\nDUK_LOCAL void duk__emit_invalid(duk_compiler_ctx *comp_ctx) {\n\tduk__emit_op_only(comp_ctx, DUK_OP_INVALID);\n}\n\n/*\n *  Peephole optimizer for finished bytecode.\n *\n *  Does not remove opcodes; currently only straightens out unconditional\n *  jump chains which are generated by several control structures.\n */\n\nDUK_LOCAL void duk__peephole_optimize_bytecode(duk_compiler_ctx *comp_ctx) {\n\tduk_compiler_instr *bc;\n\tduk_small_uint_t iter;\n\tduk_int_t i, n;\n\tduk_int_t count_opt;\n\n\tbc = (duk_compiler_instr *) (void *) DUK_BW_GET_BASEPTR(comp_ctx->thr, &comp_ctx->curr_func.bw_code);\n#if defined(DUK_USE_BUFLEN16)\n\t/* No need to assert, buffer size maximum is 0xffff. */\n#else\n\tDUK_ASSERT((duk_size_t) DUK_BW_GET_SIZE(comp_ctx->thr, &comp_ctx->curr_func.bw_code) / sizeof(duk_compiler_instr) <= (duk_size_t) DUK_INT_MAX);  /* bytecode limits */\n#endif\n\tn = (duk_int_t) (DUK_BW_GET_SIZE(comp_ctx->thr, &comp_ctx->curr_func.bw_code) / sizeof(duk_compiler_instr));\n\n\tfor (iter = 0; iter < DUK_COMPILER_PEEPHOLE_MAXITER; iter++) {\n\t\tcount_opt = 0;\n\n\t\tfor (i = 0; i < n; i++) {\n\t\t\tduk_instr_t ins;\n\t\t\tduk_int_t target_pc1;\n\t\t\tduk_int_t target_pc2;\n\n\t\t\tins = bc[i].ins;\n\t\t\tif (DUK_DEC_OP(ins) != DUK_OP_JUMP) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\ttarget_pc1 = i + 1 + (duk_int_t) DUK_DEC_ABC(ins) - (duk_int_t) DUK_BC_JUMP_BIAS;\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"consider jump at pc %ld; target_pc=%ld\", (long) i, (long) target_pc1));\n\t\t\tDUK_ASSERT(target_pc1 >= 0);\n\t\t\tDUK_ASSERT(target_pc1 < n);\n\n\t\t\t/* Note: if target_pc1 == i, we'll optimize a jump to itself.\n\t\t\t * This does not need to be checked for explicitly; the case\n\t\t\t * is rare and max iter breaks us out.\n\t\t\t */\n\n\t\t\tins = bc[target_pc1].ins;\n\t\t\tif (DUK_DEC_OP(ins) != DUK_OP_JUMP) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\ttarget_pc2 = target_pc1 + 1 + (duk_int_t) DUK_DEC_ABC(ins) - (duk_int_t) DUK_BC_JUMP_BIAS;\n\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"optimizing jump at pc %ld; old target is %ld -> new target is %ld\",\n\t\t\t                     (long) i, (long) target_pc1, (long) target_pc2));\n\n\t\t\tbc[i].ins = DUK_ENC_OP_ABC(DUK_OP_JUMP, target_pc2 - (i + 1) + DUK_BC_JUMP_BIAS);\n\n\t\t\tcount_opt++;\n\t\t}\n\n\t\tDUK_DD(DUK_DDPRINT(\"optimized %ld jumps on peephole round %ld\", (long) count_opt, (long) (iter + 1)));\n\n\t\tif (count_opt == 0) {\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\n/*\n *  Intermediate value helpers\n */\n\n/* Flags for intermediate value coercions.  A flag for using a forced reg\n * is not needed, the forced_reg argument suffices and generates better\n * code (it is checked as it is used).\n */\n/* XXX: DUK__IVAL_FLAG_REQUIRE_SHORT is passed but not currently implemented\n * by ispec/ivalue operations.\n */\n#define DUK__IVAL_FLAG_ALLOW_CONST          (1 << 0)  /* allow a constant to be returned */\n#define DUK__IVAL_FLAG_REQUIRE_TEMP         (1 << 1)  /* require a (mutable) temporary as a result (or a const if allowed) */\n#define DUK__IVAL_FLAG_REQUIRE_SHORT        (1 << 2)  /* require a short (8-bit) reg/const which fits into bytecode B/C slot */\n\n/* XXX: some code might benefit from DUK__SETTEMP_IFTEMP(thr,x) */\n\n#if 0  /* enable manually for dumping */\n#define DUK__DUMP_ISPEC(compctx,ispec) do { duk__dump_ispec((compctx), (ispec)); } while (0)\n#define DUK__DUMP_IVALUE(compctx,ivalue) do { duk__dump_ivalue((compctx), (ivalue)); } while (0)\n\nDUK_LOCAL void duk__dump_ispec(duk_compiler_ctx *comp_ctx, duk_ispec *x) {\n\tDUK_D(DUK_DPRINT(\"ispec dump: t=%ld regconst=0x%08lx, valstack_idx=%ld, value=%!T\",\n\t                 (long) x->t, (unsigned long) x->regconst, (long) x->valstack_idx,\n\t                 duk_get_tval(comp_ctx->thr, x->valstack_idx)));\n}\nDUK_LOCAL void duk__dump_ivalue(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {\n\tDUK_D(DUK_DPRINT(\"ivalue dump: t=%ld op=%ld \"\n\t                 \"x1={t=%ld regconst=0x%08lx valstack_idx=%ld value=%!T} \"\n\t                 \"x2={t=%ld regconst=0x%08lx valstack_idx=%ld value=%!T}\",\n\t\t         (long) x->t, (long) x->op,\n\t                 (long) x->x1.t, (unsigned long) x->x1.regconst, (long) x->x1.valstack_idx,\n\t                 duk_get_tval(comp_ctx->thr, x->x1.valstack_idx),\n\t                 (long) x->x2.t, (unsigned long) x->x2.regconst, (long) x->x2.valstack_idx,\n\t                 duk_get_tval(comp_ctx->thr, x->x2.valstack_idx)));\n}\n#else\n#define DUK__DUMP_ISPEC(comp_ctx,x) do {} while (0)\n#define DUK__DUMP_IVALUE(comp_ctx,x) do {} while (0)\n#endif\n\nDUK_LOCAL void duk__ivalue_regconst(duk_ivalue *x, duk_regconst_t regconst) {\n\tx->t = DUK_IVAL_PLAIN;\n\tx->x1.t = DUK_ISPEC_REGCONST;\n\tx->x1.regconst = regconst;\n}\n\nDUK_LOCAL void duk__ivalue_plain_fromstack(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {\n\tx->t = DUK_IVAL_PLAIN;\n\tx->x1.t = DUK_ISPEC_VALUE;\n\tduk_replace(comp_ctx->thr, x->x1.valstack_idx);\n}\n\nDUK_LOCAL void duk__ivalue_var_fromstack(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {\n\tx->t = DUK_IVAL_VAR;\n\tx->x1.t = DUK_ISPEC_VALUE;\n\tduk_replace(comp_ctx->thr, x->x1.valstack_idx);\n}\n\nDUK_LOCAL_DECL void duk__ivalue_var_hstring(duk_compiler_ctx *comp_ctx, duk_ivalue *x, duk_hstring *h) {\n\tDUK_ASSERT(h != NULL);\n\tduk_push_hstring(comp_ctx->thr, h);\n\tduk__ivalue_var_fromstack(comp_ctx, x);\n}\n\nDUK_LOCAL void duk__copy_ispec(duk_compiler_ctx *comp_ctx, duk_ispec *src, duk_ispec *dst) {\n\tdst->t = src->t;\n\tdst->regconst = src->regconst;\n\tduk_copy(comp_ctx->thr, src->valstack_idx, dst->valstack_idx);\n}\n\nDUK_LOCAL void duk__copy_ivalue(duk_compiler_ctx *comp_ctx, duk_ivalue *src, duk_ivalue *dst) {\n\tdst->t = src->t;\n\tdst->op = src->op;\n\tdst->x1.t = src->x1.t;\n\tdst->x1.regconst = src->x1.regconst;\n\tdst->x2.t = src->x2.t;\n\tdst->x2.regconst = src->x2.regconst;\n\tduk_copy(comp_ctx->thr, src->x1.valstack_idx, dst->x1.valstack_idx);\n\tduk_copy(comp_ctx->thr, src->x2.valstack_idx, dst->x2.valstack_idx);\n}\n\nDUK_LOCAL duk_regconst_t duk__alloctemps(duk_compiler_ctx *comp_ctx, duk_small_int_t num) {\n\tduk_regconst_t res;\n\n\tres = comp_ctx->curr_func.temp_next;\n\tcomp_ctx->curr_func.temp_next += num;\n\n\tif (comp_ctx->curr_func.temp_next > DUK__MAX_TEMPS) {  /* == DUK__MAX_TEMPS is OK */\n\t\tDUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_TEMP_LIMIT);\n\t}\n\n\t/* maintain highest 'used' temporary, needed to figure out nregs of function */\n\tif (comp_ctx->curr_func.temp_next > comp_ctx->curr_func.temp_max) {\n\t\tcomp_ctx->curr_func.temp_max = comp_ctx->curr_func.temp_next;\n\t}\n\n\treturn res;\n}\n\nDUK_LOCAL duk_regconst_t duk__alloctemp(duk_compiler_ctx *comp_ctx) {\n\treturn duk__alloctemps(comp_ctx, 1);\n}\n\nDUK_LOCAL void duk__settemp_checkmax(duk_compiler_ctx *comp_ctx, duk_regconst_t temp_next) {\n\tcomp_ctx->curr_func.temp_next = temp_next;\n\tif (temp_next > comp_ctx->curr_func.temp_max) {\n\t\tcomp_ctx->curr_func.temp_max = temp_next;\n\t}\n}\n\n/* get const for value at valstack top */\nDUK_LOCAL duk_regconst_t duk__getconst(duk_compiler_ctx *comp_ctx) {\n\tduk_hthread *thr = comp_ctx->thr;\n\tduk_compiler_func *f = &comp_ctx->curr_func;\n\tduk_tval *tv1;\n\tduk_int_t i, n, n_check;\n\n\tn = (duk_int_t) duk_get_length(thr, f->consts_idx);\n\n\ttv1 = DUK_GET_TVAL_NEGIDX(thr, -1);\n\tDUK_ASSERT(tv1 != NULL);\n\n#if defined(DUK_USE_FASTINT)\n\t/* Explicit check for fastint downgrade. */\n\tDUK_TVAL_CHKFAST_INPLACE_SLOW(tv1);\n#endif\n\n\t/* Sanity workaround for handling functions with a large number of\n\t * constants at least somewhat reasonably.  Otherwise checking whether\n\t * we already have the constant would grow very slow (as it is O(N^2)).\n\t */\n\tn_check = (n > DUK__GETCONST_MAX_CONSTS_CHECK ? DUK__GETCONST_MAX_CONSTS_CHECK : n);\n\tfor (i = 0; i < n_check; i++) {\n\t\tduk_tval *tv2 = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, f->h_consts, i);\n\n\t\t/* Strict equality is NOT enough, because we cannot use the same\n\t\t * constant for e.g. +0 and -0.\n\t\t */\n\t\tif (duk_js_samevalue(tv1, tv2)) {\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"reused existing constant for %!T -> const index %ld\",\n\t\t\t                     (duk_tval *) tv1, (long) i));\n\t\t\tduk_pop(thr);\n\t\t\treturn (duk_regconst_t) i | (duk_regconst_t) DUK__CONST_MARKER;\n\t\t}\n\t}\n\n\tif (n > DUK__MAX_CONSTS) {\n\t\tDUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_CONST_LIMIT);\n\t}\n\n\tDUK_DDD(DUK_DDDPRINT(\"allocating new constant for %!T -> const index %ld\",\n\t                     (duk_tval *) tv1, (long) n));\n\t(void) duk_put_prop_index(thr, f->consts_idx, (duk_uarridx_t) n);  /* invalidates tv1, tv2 */\n\treturn (duk_regconst_t) n | (duk_regconst_t) DUK__CONST_MARKER;\n}\n\nDUK_LOCAL duk_bool_t duk__const_needs_refcount(duk_compiler_ctx *comp_ctx, duk_regconst_t rc) {\n#if defined(DUK_USE_REFERENCE_COUNTING)\n\tduk_compiler_func *f = &comp_ctx->curr_func;\n\tduk_bool_t ret;\n\n\tDUK_ASSERT((rc & DUK__CONST_MARKER) == 0);  /* caller removes const marker */\n\t(void) duk_get_prop_index(comp_ctx->thr, f->consts_idx, (duk_uarridx_t) rc);\n\tret = !duk_is_number(comp_ctx->thr, -1);  /* now only number/string, so conservative check */\n\tduk_pop(comp_ctx->thr);\n\treturn ret;\n#else\n\tDUK_UNREF(comp_ctx);\n\tDUK_UNREF(rc);\n\tDUK_ASSERT((rc & DUK__CONST_MARKER) == 0);  /* caller removes const marker */\n\treturn 0;\n#endif\n}\n\n/* Get the value represented by an duk_ispec to a register or constant.\n * The caller can control the result by indicating whether or not:\n *\n *   (1) a constant is allowed (sometimes the caller needs the result to\n *       be in a register)\n *\n *   (2) a temporary register is required (usually when caller requires\n *       the register to be safely mutable; normally either a bound\n *       register or a temporary register are both OK)\n *\n *   (3) a forced register target needs to be used\n *\n * Bytecode may be emitted to generate the necessary value.  The return\n * value is either a register or a constant.\n */\n\nDUK_LOCAL\nduk_regconst_t duk__ispec_toregconst_raw(duk_compiler_ctx *comp_ctx,\n                                         duk_ispec *x,\n                                         duk_regconst_t forced_reg,\n                                         duk_small_uint_t flags) {\n\tduk_hthread *thr = comp_ctx->thr;\n\n\tDUK_DDD(DUK_DDDPRINT(\"duk__ispec_toregconst_raw(): x={%ld:%ld:%!T}, \"\n\t                     \"forced_reg=%ld, flags 0x%08lx: allow_const=%ld require_temp=%ld require_short=%ld\",\n\t                     (long) x->t,\n\t                     (long) x->regconst,\n\t                     (duk_tval *) duk_get_tval(thr, x->valstack_idx),\n\t                     (long) forced_reg,\n\t                     (unsigned long) flags,\n\t                     (long) ((flags & DUK__IVAL_FLAG_ALLOW_CONST) ? 1 : 0),\n\t                     (long) ((flags & DUK__IVAL_FLAG_REQUIRE_TEMP) ? 1 : 0),\n\t                     (long) ((flags & DUK__IVAL_FLAG_REQUIRE_SHORT) ? 1 : 0)));\n\n\tswitch (x->t) {\n\tcase DUK_ISPEC_VALUE: {\n\t\tduk_tval *tv;\n\n\t\ttv = DUK_GET_TVAL_POSIDX(thr, x->valstack_idx);\n\t\tDUK_ASSERT(tv != NULL);\n\n\t\tswitch (DUK_TVAL_GET_TAG(tv)) {\n\t\tcase DUK_TAG_UNDEFINED: {\n\t\t\t/* Note: although there is no 'undefined' literal, undefined\n\t\t\t * values can occur during compilation as a result of e.g.\n\t\t\t * the 'void' operator.\n\t\t\t */\n\t\t\tduk_regconst_t dest = (forced_reg >= 0 ? forced_reg : DUK__ALLOCTEMP(comp_ctx));\n\t\t\tduk__emit_bc(comp_ctx, DUK_OP_LDUNDEF, dest);\n\t\t\treturn dest;\n\t\t}\n\t\tcase DUK_TAG_NULL: {\n\t\t\tduk_regconst_t dest = (forced_reg >= 0 ? forced_reg : DUK__ALLOCTEMP(comp_ctx));\n\t\t\tduk__emit_bc(comp_ctx, DUK_OP_LDNULL, dest);\n\t\t\treturn dest;\n\t\t}\n\t\tcase DUK_TAG_BOOLEAN: {\n\t\t\tduk_regconst_t dest = (forced_reg >= 0 ? forced_reg : DUK__ALLOCTEMP(comp_ctx));\n\t\t\tduk__emit_bc(comp_ctx,\n\t\t\t             (DUK_TVAL_GET_BOOLEAN(tv) ? DUK_OP_LDTRUE : DUK_OP_LDFALSE),\n\t\t\t             dest);\n\t\t\treturn dest;\n\t\t}\n\t\tcase DUK_TAG_POINTER: {\n\t\t\tDUK_UNREACHABLE();\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_TAG_STRING: {\n\t\t\tduk_hstring *h;\n\t\t\tduk_regconst_t dest;\n\t\t\tduk_regconst_t constidx;\n\n\t\t\th = DUK_TVAL_GET_STRING(tv);\n\t\t\tDUK_UNREF(h);\n\t\t\tDUK_ASSERT(h != NULL);\n\n#if 0  /* XXX: to be implemented? */\n\t\t\t/* Use special opcodes to load short strings */\n\t\t\tif (DUK_HSTRING_GET_BYTELEN(h) <= 2) {\n\t\t\t\t/* Encode into a single opcode (18 bits can encode 1-2 bytes + length indicator) */\n\t\t\t} else if (DUK_HSTRING_GET_BYTELEN(h) <= 6) {\n\t\t\t\t/* Encode into a double constant (53 bits can encode 6*8 = 48 bits + 3-bit length */\n\t\t\t}\n#endif\n\t\t\tduk_dup(thr, x->valstack_idx);\n\t\t\tconstidx = duk__getconst(comp_ctx);\n\n\t\t\tif (flags & DUK__IVAL_FLAG_ALLOW_CONST) {\n\t\t\t\treturn constidx;\n\t\t\t}\n\n\t\t\tdest = (forced_reg >= 0 ? forced_reg : DUK__ALLOCTEMP(comp_ctx));\n\t\t\tduk__emit_a_bc(comp_ctx, DUK_OP_LDCONST, dest, constidx);\n\t\t\treturn dest;\n\t\t}\n\t\tcase DUK_TAG_OBJECT: {\n\t\t\tDUK_UNREACHABLE();\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_TAG_BUFFER: {\n\t\t\tDUK_UNREACHABLE();\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_TAG_LIGHTFUNC: {\n\t\t\tDUK_UNREACHABLE();\n\t\t\tbreak;\n\t\t}\n#if defined(DUK_USE_FASTINT)\n\t\tcase DUK_TAG_FASTINT:\n#endif\n\t\tdefault: {\n\t\t\t/* number */\n\t\t\tduk_regconst_t dest;\n\t\t\tduk_regconst_t constidx;\n\t\t\tduk_double_t dval;\n\t\t\tduk_int32_t ival;\n\n\t\t\tDUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));\n\t\t\tDUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));\n\t\t\tdval = DUK_TVAL_GET_NUMBER(tv);\n\n\t\t\tif (!(flags & DUK__IVAL_FLAG_ALLOW_CONST)) {\n\t\t\t\t/* A number can be loaded either through a constant, using\n\t\t\t\t * LDINT, or using LDINT+LDINTX.  LDINT is always a size win,\n\t\t\t\t * LDINT+LDINTX is not if the constant is used multiple times.\n\t\t\t\t * Currently always prefer LDINT+LDINTX over a double constant.\n\t\t\t\t */\n\n\t\t\t\tif (duk_is_whole_get_int32_nonegzero(dval, &ival)) {\n\t\t\t\t\tdest = (forced_reg >= 0 ? forced_reg : DUK__ALLOCTEMP(comp_ctx));\n\t\t\t\t\tduk__emit_load_int32(comp_ctx, dest, ival);\n\t\t\t\t\treturn dest;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tduk_dup(thr, x->valstack_idx);\n\t\t\tconstidx = duk__getconst(comp_ctx);\n\n\t\t\tif (flags & DUK__IVAL_FLAG_ALLOW_CONST) {\n\t\t\t\treturn constidx;\n\t\t\t} else {\n\t\t\t\tdest = (forced_reg >= 0 ? forced_reg : DUK__ALLOCTEMP(comp_ctx));\n\t\t\t\tduk__emit_a_bc(comp_ctx, DUK_OP_LDCONST, dest, constidx);\n\t\t\t\treturn dest;\n\t\t\t}\n\t\t}\n\t\t}  /* end switch */\n\t}\n\tcase DUK_ISPEC_REGCONST: {\n\t\tif (forced_reg >= 0) {\n\t\t\tif (DUK__ISCONST(x->regconst)) {\n\t\t\t\tduk__emit_a_bc(comp_ctx, DUK_OP_LDCONST, forced_reg, x->regconst);\n\t\t\t} else if (x->regconst != forced_reg) {\n\t\t\t\tduk__emit_a_bc(comp_ctx, DUK_OP_LDREG, forced_reg, x->regconst);\n\t\t\t} else {\n\t\t\t\t; /* already in correct reg */\n\t\t\t}\n\t\t\treturn forced_reg;\n\t\t}\n\n\t\tDUK_ASSERT(forced_reg < 0);\n\t\tif (DUK__ISCONST(x->regconst)) {\n\t\t\tif (!(flags & DUK__IVAL_FLAG_ALLOW_CONST)) {\n\t\t\t\tduk_regconst_t dest = DUK__ALLOCTEMP(comp_ctx);\n\t\t\t\tduk__emit_a_bc(comp_ctx, DUK_OP_LDCONST, dest, x->regconst);\n\t\t\t\treturn dest;\n\t\t\t}\n\t\t\treturn x->regconst;\n\t\t}\n\n\t\tDUK_ASSERT(forced_reg < 0 && !DUK__ISCONST(x->regconst));\n\t\tif ((flags & DUK__IVAL_FLAG_REQUIRE_TEMP) && !DUK__ISREG_TEMP(comp_ctx, x->regconst)) {\n\t\t\tduk_regconst_t dest = DUK__ALLOCTEMP(comp_ctx);\n\t\t\tduk__emit_a_bc(comp_ctx, DUK_OP_LDREG, dest, x->regconst);\n\t\t\treturn dest;\n\t\t}\n\t\treturn x->regconst;\n\t}\n\tdefault: {\n\t\tbreak;\n\t}\n\t}\n\n\tDUK_ERROR_INTERNAL(thr);\n\treturn 0;\n}\n\nDUK_LOCAL void duk__ispec_toforcedreg(duk_compiler_ctx *comp_ctx, duk_ispec *x, duk_regconst_t forced_reg) {\n\tDUK_ASSERT(forced_reg >= 0);\n\t(void) duk__ispec_toregconst_raw(comp_ctx, x, forced_reg, 0 /*flags*/);\n}\n\n/* Coerce an duk_ivalue to a 'plain' value by generating the necessary\n * arithmetic operations, property access, or variable access bytecode.\n * The duk_ivalue argument ('x') is converted into a plain value as a\n * side effect.\n */\nDUK_LOCAL void duk__ivalue_toplain_raw(duk_compiler_ctx *comp_ctx, duk_ivalue *x, duk_regconst_t forced_reg) {\n\tduk_hthread *thr = comp_ctx->thr;\n\n\tDUK_DDD(DUK_DDDPRINT(\"duk__ivalue_toplain_raw(): x={t=%ld,op=%ld,x1={%ld:%ld:%!T},x2={%ld:%ld:%!T}}, \"\n\t                     \"forced_reg=%ld\",\n\t                     (long) x->t, (long) x->op,\n\t                     (long) x->x1.t, (long) x->x1.regconst,\n\t                     (duk_tval *) duk_get_tval(thr, x->x1.valstack_idx),\n\t                     (long) x->x2.t, (long) x->x2.regconst,\n\t                     (duk_tval *) duk_get_tval(thr, x->x2.valstack_idx),\n\t                     (long) forced_reg));\n\n\tswitch (x->t) {\n\tcase DUK_IVAL_PLAIN: {\n\t\treturn;\n\t}\n\t/* XXX: support unary arithmetic ivalues (useful?) */\n\tcase DUK_IVAL_ARITH: {\n\t\tduk_regconst_t arg1;\n\t\tduk_regconst_t arg2;\n\t\tduk_regconst_t dest;\n\t\tduk_tval *tv1;\n\t\tduk_tval *tv2;\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"arith to plain conversion\"));\n\n\t\t/* inline arithmetic check for constant values */\n\t\t/* XXX: use the exactly same arithmetic function here as in executor */\n\t\tif (x->x1.t == DUK_ISPEC_VALUE && x->x2.t == DUK_ISPEC_VALUE && x->t == DUK_IVAL_ARITH) {\n\t\t\ttv1 = DUK_GET_TVAL_POSIDX(thr, x->x1.valstack_idx);\n\t\t\ttv2 = DUK_GET_TVAL_POSIDX(thr, x->x2.valstack_idx);\n\t\t\tDUK_ASSERT(tv1 != NULL);\n\t\t\tDUK_ASSERT(tv2 != NULL);\n\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"arith: tv1=%!T, tv2=%!T\",\n\t\t\t                     (duk_tval *) tv1,\n\t\t\t                     (duk_tval *) tv2));\n\n\t\t\tif (DUK_TVAL_IS_NUMBER(tv1) && DUK_TVAL_IS_NUMBER(tv2)) {\n\t\t\t\tduk_double_t d1 = DUK_TVAL_GET_NUMBER(tv1);\n\t\t\t\tduk_double_t d2 = DUK_TVAL_GET_NUMBER(tv2);\n\t\t\t\tduk_double_t d3;\n\t\t\t\tduk_bool_t accept_fold = 1;\n\n\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"arith inline check: d1=%lf, d2=%lf, op=%ld\",\n\t\t\t\t                     (double) d1, (double) d2, (long) x->op));\n\t\t\t\tswitch (x->op) {\n\t\t\t\tcase DUK_OP_ADD: {\n\t\t\t\t\td3 = d1 + d2;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase DUK_OP_SUB: {\n\t\t\t\t\td3 = d1 - d2;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase DUK_OP_MUL: {\n\t\t\t\t\td3 = d1 * d2;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase DUK_OP_DIV: {\n\t\t\t\t\td3 = d1 / d2;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase DUK_OP_EXP: {\n\t\t\t\t\td3 = (duk_double_t) duk_js_arith_pow((double) d1, (double) d2);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tdefault: {\n\t\t\t\t\td3 = 0.0;  /* Won't be used, but silence MSVC /W4 warning. */\n\t\t\t\t\taccept_fold = 0;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (accept_fold) {\n\t\t\t\t\tduk_double_union du;\n\t\t\t\t\tdu.d = d3;\n\t\t\t\t\tDUK_DBLUNION_NORMALIZE_NAN_CHECK(&du);\n\t\t\t\t\td3 = du.d;\n\n\t\t\t\t\tx->t = DUK_IVAL_PLAIN;\n\t\t\t\t\tDUK_ASSERT(x->x1.t == DUK_ISPEC_VALUE);\n\t\t\t\t\tDUK_TVAL_SET_NUMBER(tv1, d3);  /* old value is number: no refcount */\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t} else if (x->op == DUK_OP_ADD && DUK_TVAL_IS_STRING(tv1) && DUK_TVAL_IS_STRING(tv2)) {\n\t\t\t\t/* Inline string concatenation.  No need to check for\n\t\t\t\t * symbols, as all inputs are valid Ecmascript strings.\n\t\t\t\t */\n\t\t\t\tduk_dup(thr, x->x1.valstack_idx);\n\t\t\t\tduk_dup(thr, x->x2.valstack_idx);\n\t\t\t\tduk_concat(thr, 2);\n\t\t\t\tduk_replace(thr, x->x1.valstack_idx);\n\t\t\t\tx->t = DUK_IVAL_PLAIN;\n\t\t\t\tDUK_ASSERT(x->x1.t == DUK_ISPEC_VALUE);\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\targ1 = duk__ispec_toregconst_raw(comp_ctx, &x->x1, -1, DUK__IVAL_FLAG_ALLOW_CONST | DUK__IVAL_FLAG_REQUIRE_SHORT /*flags*/);\n\t\targ2 = duk__ispec_toregconst_raw(comp_ctx, &x->x2, -1, DUK__IVAL_FLAG_ALLOW_CONST | DUK__IVAL_FLAG_REQUIRE_SHORT /*flags*/);\n\n\t\t/* If forced reg, use it as destination.  Otherwise try to\n\t\t * use either coerced ispec if it is a temporary.\n\t\t */\n\t\tif (forced_reg >= 0) {\n\t\t\tdest = forced_reg;\n\t\t} else if (DUK__ISREG_TEMP(comp_ctx, arg1)) {\n\t\t\tdest = arg1;\n\t\t} else if (DUK__ISREG_TEMP(comp_ctx, arg2)) {\n\t\t\tdest = arg2;\n\t\t} else {\n\t\t\tdest = DUK__ALLOCTEMP(comp_ctx);\n\t\t}\n\n\t\tDUK_ASSERT(DUK__ISREG(dest));\n\t\tduk__emit_a_b_c(comp_ctx, x->op | DUK__EMIT_FLAG_BC_REGCONST, dest, arg1, arg2);\n\n\t\tduk__ivalue_regconst(x, dest);\n\t\treturn;\n\t}\n\tcase DUK_IVAL_PROP: {\n\t\t/* XXX: very similar to DUK_IVAL_ARITH - merge? */\n\t\tduk_regconst_t arg1;\n\t\tduk_regconst_t arg2;\n\t\tduk_regconst_t dest;\n\n\t\t/* Need a short reg/const, does not have to be a mutable temp. */\n\t\targ1 = duk__ispec_toregconst_raw(comp_ctx, &x->x1, -1, DUK__IVAL_FLAG_ALLOW_CONST | DUK__IVAL_FLAG_REQUIRE_SHORT /*flags*/);\n\t\targ2 = duk__ispec_toregconst_raw(comp_ctx, &x->x2, -1, DUK__IVAL_FLAG_ALLOW_CONST | DUK__IVAL_FLAG_REQUIRE_SHORT /*flags*/);\n\n\t\t/* Pick a destination register.  If either base value or key\n\t\t * happens to be a temp value, reuse it as the destination.\n\t\t *\n\t\t * XXX: The temp must be a \"mutable\" one, i.e. such that no\n\t\t * other expression is using it anymore.  Here this should be\n\t\t * the case because the value of a property access expression\n\t\t * is neither the base nor the key, but the lookup result.\n\t\t */\n\n\t\tif (forced_reg >= 0) {\n\t\t\tdest = forced_reg;\n\t\t} else if (DUK__ISREG_TEMP(comp_ctx, arg1)) {\n\t\t\tdest = arg1;\n\t\t} else if (DUK__ISREG_TEMP(comp_ctx, arg2)) {\n\t\t\tdest = arg2;\n\t\t} else {\n\t\t\tdest = DUK__ALLOCTEMP(comp_ctx);\n\t\t}\n\n\t\tduk__emit_a_b_c(comp_ctx,\n\t\t                DUK_OP_GETPROP | DUK__EMIT_FLAG_BC_REGCONST,\n\t\t                dest,\n\t\t                arg1,\n\t\t                arg2);\n\n\t\tduk__ivalue_regconst(x, dest);\n\t\treturn;\n\t}\n\tcase DUK_IVAL_VAR: {\n\t\t/* x1 must be a string */\n\t\tduk_regconst_t dest;\n\t\tduk_regconst_t reg_varbind;\n\t\tduk_regconst_t rc_varname;\n\n\t\tDUK_ASSERT(x->x1.t == DUK_ISPEC_VALUE);\n\n\t\tduk_dup(thr, x->x1.valstack_idx);\n\t\tif (duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname)) {\n\t\t\tduk__ivalue_regconst(x, reg_varbind);\n\t\t} else {\n\t\t\tdest = (forced_reg >= 0 ? forced_reg : DUK__ALLOCTEMP(comp_ctx));\n\t\t\tduk__emit_a_bc(comp_ctx, DUK_OP_GETVAR, dest, rc_varname);\n\t\t\tduk__ivalue_regconst(x, dest);\n\t\t}\n\t\treturn;\n\t}\n\tcase DUK_IVAL_NONE:\n\tdefault: {\n\t\tDUK_D(DUK_DPRINT(\"invalid ivalue type: %ld\", (long) x->t));\n\t\tbreak;\n\t}\n\t}\n\n\tDUK_ERROR_INTERNAL(thr);\n\treturn;\n}\n\n/* evaluate to plain value, no forced register (temp/bound reg both ok) */\nDUK_LOCAL void duk__ivalue_toplain(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {\n\tduk__ivalue_toplain_raw(comp_ctx, x, -1 /*forced_reg*/);\n}\n\n/* evaluate to final form (e.g. coerce GETPROP to code), throw away temp */\nDUK_LOCAL void duk__ivalue_toplain_ignore(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {\n\tduk_regconst_t temp;\n\n\t/* If duk__ivalue_toplain_raw() allocates a temp, forget it and\n\t * restore next temp state.\n\t */\n\ttemp = DUK__GETTEMP(comp_ctx);\n\tduk__ivalue_toplain_raw(comp_ctx, x, -1 /*forced_reg*/);\n\tDUK__SETTEMP(comp_ctx, temp);\n}\n\n/* Coerce an duk_ivalue to a register or constant; result register may\n * be a temp or a bound register.\n *\n * The duk_ivalue argument ('x') is converted into a regconst as a\n * side effect.\n */\nDUK_LOCAL\nduk_regconst_t duk__ivalue_toregconst_raw(duk_compiler_ctx *comp_ctx,\n                                          duk_ivalue *x,\n                                          duk_regconst_t forced_reg,\n                                          duk_small_uint_t flags) {\n\tduk_hthread *thr = comp_ctx->thr;\n\tduk_regconst_t reg;\n\tDUK_UNREF(thr);\n\n\tDUK_DDD(DUK_DDDPRINT(\"duk__ivalue_toregconst_raw(): x={t=%ld,op=%ld,x1={%ld:%ld:%!T},x2={%ld:%ld:%!T}}, \"\n\t                     \"forced_reg=%ld, flags 0x%08lx: allow_const=%ld require_temp=%ld require_short=%ld\",\n\t                     (long) x->t, (long) x->op,\n\t                     (long) x->x1.t, (long) x->x1.regconst,\n\t                     (duk_tval *) duk_get_tval(thr, x->x1.valstack_idx),\n\t                     (long) x->x2.t, (long) x->x2.regconst,\n\t                     (duk_tval *) duk_get_tval(thr, x->x2.valstack_idx),\n\t                     (long) forced_reg,\n\t                     (unsigned long) flags,\n\t                     (long) ((flags & DUK__IVAL_FLAG_ALLOW_CONST) ? 1 : 0),\n\t                     (long) ((flags & DUK__IVAL_FLAG_REQUIRE_TEMP) ? 1 : 0),\n\t                     (long) ((flags & DUK__IVAL_FLAG_REQUIRE_SHORT) ? 1 : 0)));\n\n\t/* first coerce to a plain value */\n\tduk__ivalue_toplain_raw(comp_ctx, x, forced_reg);\n\tDUK_ASSERT(x->t == DUK_IVAL_PLAIN);\n\n\t/* then to a register */\n\treg = duk__ispec_toregconst_raw(comp_ctx, &x->x1, forced_reg, flags);\n\tduk__ivalue_regconst(x, reg);\n\n\treturn reg;\n}\n\nDUK_LOCAL duk_regconst_t duk__ivalue_toreg(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {\n\treturn duk__ivalue_toregconst_raw(comp_ctx, x, -1, 0 /*flags*/);\n}\n\n#if 0  /* unused */\nDUK_LOCAL duk_regconst_t duk__ivalue_totemp(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {\n\treturn duk__ivalue_toregconst_raw(comp_ctx, x, -1, DUK__IVAL_FLAG_REQUIRE_TEMP /*flags*/);\n}\n#endif\n\nDUK_LOCAL void duk__ivalue_toforcedreg(duk_compiler_ctx *comp_ctx, duk_ivalue *x, duk_int_t forced_reg) {\n\tDUK_ASSERT(forced_reg >= 0);\n\t(void) duk__ivalue_toregconst_raw(comp_ctx, x, forced_reg, 0 /*flags*/);\n}\n\nDUK_LOCAL duk_regconst_t duk__ivalue_toregconst(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {\n\treturn duk__ivalue_toregconst_raw(comp_ctx, x, -1, DUK__IVAL_FLAG_ALLOW_CONST /*flags*/);\n}\n\nDUK_LOCAL duk_regconst_t duk__ivalue_totempconst(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {\n\treturn duk__ivalue_toregconst_raw(comp_ctx, x, -1, DUK__IVAL_FLAG_ALLOW_CONST | DUK__IVAL_FLAG_REQUIRE_TEMP /*flags*/);\n}\n\n/* The issues below can be solved with better flags */\n\n/* XXX: many operations actually want toforcedtemp() -- brand new temp? */\n/* XXX: need a toplain_ignore() which will only coerce a value to a temp\n * register if it might have a side effect.  Side-effect free values do not\n * need to be coerced.\n */\n\n/*\n *  Identifier handling\n */\n\nDUK_LOCAL duk_regconst_t duk__lookup_active_register_binding(duk_compiler_ctx *comp_ctx) {\n\tduk_hthread *thr = comp_ctx->thr;\n\tduk_hstring *h_varname;\n\tduk_regconst_t ret;\n\n\tDUK_DDD(DUK_DDDPRINT(\"resolving identifier reference to '%!T'\",\n\t                     (duk_tval *) duk_get_tval(thr, -1)));\n\n\t/*\n\t *  Special name handling\n\t */\n\n\th_varname = duk_known_hstring(thr, -1);\n\n\tif (h_varname == DUK_HTHREAD_STRING_LC_ARGUMENTS(thr)) {\n\t\tDUK_DDD(DUK_DDDPRINT(\"flagging function as accessing 'arguments'\"));\n\t\tcomp_ctx->curr_func.id_access_arguments = 1;\n\t}\n\n\t/*\n\t *  Inside one or more 'with' statements fall back to slow path always.\n\t *  (See e.g. test-stmt-with.js.)\n\t */\n\n\tif (comp_ctx->curr_func.with_depth > 0) {\n\t\tDUK_DDD(DUK_DDDPRINT(\"identifier lookup inside a 'with' -> fall back to slow path\"));\n\t\tgoto slow_path_own;\n\t}\n\n\t/*\n\t *  Any catch bindings (\"catch (e)\") also affect identifier binding.\n\t *\n\t *  Currently, the varmap is modified for the duration of the catch\n\t *  clause to ensure any identifier accesses with the catch variable\n\t *  name will use slow path.\n\t */\n\n\tduk_get_prop(thr, comp_ctx->curr_func.varmap_idx);\n\tif (duk_is_number(thr, -1)) {\n\t\tret = duk_to_int(thr, -1);\n\t\tduk_pop(thr);\n\t} else {\n\t\tduk_pop(thr);\n\t\tif (comp_ctx->curr_func.catch_depth > 0 || comp_ctx->curr_func.with_depth > 0) {\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"slow path access from inside a try-catch or with needs _Varmap\"));\n\t\t\tgoto slow_path_own;\n\t\t} else {\n\t\t\t/* In this case we're doing a variable lookup that doesn't\n\t\t\t * match our own variables, so _Varmap won't be needed at\n\t\t\t * run time.\n\t\t\t */\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"slow path access outside of try-catch and with, no need for _Varmap\"));\n\t\t\tgoto slow_path_notown;\n\t\t}\n\t}\n\n\tDUK_DDD(DUK_DDDPRINT(\"identifier lookup -> reg %ld\", (long) ret));\n\treturn ret;\n\n slow_path_notown:\n\tDUK_DDD(DUK_DDDPRINT(\"identifier lookup -> slow path, not own variable\"));\n\n\tcomp_ctx->curr_func.id_access_slow = 1;\n\treturn (duk_regconst_t) -1;\n\n slow_path_own:\n\tDUK_DDD(DUK_DDDPRINT(\"identifier lookup -> slow path, may be own variable\"));\n\n\tcomp_ctx->curr_func.id_access_slow = 1;\n\tcomp_ctx->curr_func.id_access_slow_own = 1;\n\treturn (duk_regconst_t) -1;\n}\n\n/* Lookup an identifier name in the current varmap, indicating whether the\n * identifier is register-bound and if not, allocating a constant for the\n * identifier name.  Returns 1 if register-bound, 0 otherwise.  Caller can\n * also check (out_reg_varbind >= 0) to check whether or not identifier is\n * register bound.  The caller must NOT use out_rc_varname at all unless\n * return code is 0 or out_reg_varbind is < 0; this is becuase out_rc_varname\n * is unsigned and doesn't have a \"unused\" / none value.\n */\nDUK_LOCAL duk_bool_t duk__lookup_lhs(duk_compiler_ctx *comp_ctx, duk_regconst_t *out_reg_varbind, duk_regconst_t *out_rc_varname) {\n\tduk_hthread *thr = comp_ctx->thr;\n\tduk_regconst_t reg_varbind;\n\tduk_regconst_t rc_varname;\n\n\t/* [ ... varname ] */\n\n\tduk_dup_top(thr);\n\treg_varbind = duk__lookup_active_register_binding(comp_ctx);\n\n\tif (reg_varbind >= 0) {\n\t\t*out_reg_varbind = reg_varbind;\n\t\t*out_rc_varname = 0;  /* duk_regconst_t is unsigned, so use 0 as dummy value (ignored by caller) */\n\t\tduk_pop(thr);\n\t\treturn 1;\n\t} else {\n\t\trc_varname = duk__getconst(comp_ctx);\n\t\t*out_reg_varbind = -1;\n\t\t*out_rc_varname = rc_varname;\n\t\treturn 0;\n\t}\n}\n\n/*\n *  Label handling\n *\n *  Labels are initially added with flags prohibiting both break and continue.\n *  When the statement type is finally uncovered (after potentially multiple\n *  labels), all the labels are updated to allow/prohibit break and continue.\n */\n\nDUK_LOCAL void duk__add_label(duk_compiler_ctx *comp_ctx, duk_hstring *h_label, duk_int_t pc_label, duk_int_t label_id) {\n\tduk_hthread *thr = comp_ctx->thr;\n\tduk_size_t n;\n\tduk_size_t new_size;\n\tduk_uint8_t *p;\n\tduk_labelinfo *li_start, *li;\n\n\t/* Duplicate (shadowing) labels are not allowed, except for the empty\n\t * labels (which are used as default labels for switch and iteration\n\t * statements).\n\t *\n\t * We could also allow shadowing of non-empty pending labels without any\n\t * other issues than breaking the required label shadowing requirements\n\t * of the E5 specification, see Section 12.12.\n\t */\n\n\tp = (duk_uint8_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, comp_ctx->curr_func.h_labelinfos);\n\tli_start = (duk_labelinfo *) (void *) p;\n\tli = (duk_labelinfo *) (void *) (p + DUK_HBUFFER_GET_SIZE(comp_ctx->curr_func.h_labelinfos));\n\tn = (duk_size_t) (li - li_start);\n\n\twhile (li > li_start) {\n\t\tli--;\n\n\t\tif (li->h_label == h_label && h_label != DUK_HTHREAD_STRING_EMPTY_STRING(thr)) {\n\t\t\tDUK_ERROR_SYNTAX(thr, DUK_STR_DUPLICATE_LABEL);\n\t\t}\n\t}\n\n\tduk_push_hstring(thr, h_label);\n\tDUK_ASSERT(n <= DUK_UARRIDX_MAX);  /* label limits */\n\t(void) duk_put_prop_index(thr, comp_ctx->curr_func.labelnames_idx, (duk_uarridx_t) n);\n\n\tnew_size = (n + 1) * sizeof(duk_labelinfo);\n\tduk_hbuffer_resize(thr, comp_ctx->curr_func.h_labelinfos, new_size);\n\t/* XXX: slack handling, slow now */\n\n\t/* relookup after possible realloc */\n\tp = (duk_uint8_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, comp_ctx->curr_func.h_labelinfos);\n\tli_start = (duk_labelinfo *) (void *) p;\n\tDUK_UNREF(li_start);  /* silence scan-build warning */\n\tli = (duk_labelinfo *) (void *) (p + DUK_HBUFFER_GET_SIZE(comp_ctx->curr_func.h_labelinfos));\n\tli--;\n\n\t/* Labels can be used for iteration statements but also for other statements,\n\t * in particular a label can be used for a block statement.  All cases of a\n\t * named label accept a 'break' so that flag is set here.  Iteration statements\n\t * also allow 'continue', so that flag is updated when we figure out the\n\t * statement type.\n\t */\n\n\tli->flags = DUK_LABEL_FLAG_ALLOW_BREAK;\n\tli->label_id = label_id;\n\tli->h_label = h_label;\n\tli->catch_depth = comp_ctx->curr_func.catch_depth;   /* catch depth from current func */\n\tli->pc_label = pc_label;\n\n\tDUK_DDD(DUK_DDDPRINT(\"registered label: flags=0x%08lx, id=%ld, name=%!O, catch_depth=%ld, pc_label=%ld\",\n\t                     (unsigned long) li->flags, (long) li->label_id, (duk_heaphdr *) li->h_label,\n\t                     (long) li->catch_depth, (long) li->pc_label));\n}\n\n/* Update all labels with matching label_id. */\nDUK_LOCAL void duk__update_label_flags(duk_compiler_ctx *comp_ctx, duk_int_t label_id, duk_small_uint_t flags) {\n\tduk_uint8_t *p;\n\tduk_labelinfo *li_start, *li;\n\n\tp = (duk_uint8_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(comp_ctx->thr->heap, comp_ctx->curr_func.h_labelinfos);\n\tli_start = (duk_labelinfo *) (void *) p;\n\tli = (duk_labelinfo *) (void *) (p + DUK_HBUFFER_GET_SIZE(comp_ctx->curr_func.h_labelinfos));\n\n\t/* Match labels starting from latest; once label_id no longer matches, we can\n\t * safely exit without checking the rest of the labels (only the topmost labels\n\t * are ever updated).\n\t */\n\twhile (li > li_start) {\n\t\tli--;\n\n\t\tif (li->label_id != label_id) {\n\t\t\tbreak;\n\t\t}\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"updating (overwriting) label flags for li=%p, label_id=%ld, flags=%ld\",\n\t\t                     (void *) li, (long) label_id, (long) flags));\n\n\t\tli->flags = flags;\n\t}\n}\n\n/* Lookup active label information.  Break/continue distinction is necessary to handle switch\n * statement related labels correctly: a switch will only catch a 'break', not a 'continue'.\n *\n * An explicit label cannot appear multiple times in the active set, but empty labels (unlabelled\n * iteration and switch statements) can.  A break will match the closest unlabelled or labelled\n * statement.  A continue will match the closest unlabelled or labelled iteration statement.  It is\n * a syntax error if a continue matches a labelled switch statement; because an explicit label cannot\n * be duplicated, the continue cannot match any valid label outside the switch.\n *\n * A side effect of these rules is that a LABEL statement related to a switch should never actually\n * catch a continue abrupt completion at run-time.  Hence an INVALID opcode can be placed in the\n * continue slot of the switch's LABEL statement.\n */\n\n/* XXX: awkward, especially the bunch of separate output values -> output struct? */\nDUK_LOCAL void duk__lookup_active_label(duk_compiler_ctx *comp_ctx, duk_hstring *h_label, duk_bool_t is_break, duk_int_t *out_label_id, duk_int_t *out_label_catch_depth, duk_int_t *out_label_pc, duk_bool_t *out_is_closest) {\n\tduk_hthread *thr = comp_ctx->thr;\n\tduk_uint8_t *p;\n\tduk_labelinfo *li_start, *li_end, *li;\n\tduk_bool_t match = 0;\n\n\tDUK_DDD(DUK_DDDPRINT(\"looking up active label: label='%!O', is_break=%ld\",\n\t                     (duk_heaphdr *) h_label, (long) is_break));\n\n\tDUK_UNREF(thr);\n\n\tp = (duk_uint8_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, comp_ctx->curr_func.h_labelinfos);\n\tli_start = (duk_labelinfo *) (void *) p;\n\tli_end = (duk_labelinfo *) (void *) (p + DUK_HBUFFER_GET_SIZE(comp_ctx->curr_func.h_labelinfos));\n\tli = li_end;\n\n\t/* Match labels starting from latest label because there can be duplicate empty\n\t * labels in the label set.\n\t */\n\twhile (li > li_start) {\n\t\tli--;\n\n\t\tif (li->h_label != h_label) {\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"labelinfo[%ld] ->'%!O' != %!O\",\n\t\t\t                     (long) (li - li_start),\n\t\t\t                     (duk_heaphdr *) li->h_label,\n\t\t\t                     (duk_heaphdr *) h_label));\n\t\t\tcontinue;\n\t\t}\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"labelinfo[%ld] -> '%!O' label name matches (still need to check type)\",\n\t\t                     (long) (li - li_start), (duk_heaphdr *) h_label));\n\n\t\t/* currently all labels accept a break, so no explicit check for it now */\n\t\tDUK_ASSERT(li->flags & DUK_LABEL_FLAG_ALLOW_BREAK);\n\n\t\tif (is_break) {\n\t\t\t/* break matches always */\n\t\t\tmatch = 1;\n\t\t\tbreak;\n\t\t} else if (li->flags & DUK_LABEL_FLAG_ALLOW_CONTINUE) {\n\t\t\t/* iteration statements allow continue */\n\t\t\tmatch = 1;\n\t\t\tbreak;\n\t\t} else {\n\t\t\t/* continue matched this label -- we can only continue if this is the empty\n\t\t\t * label, for which duplication is allowed, and thus there is hope of\n\t\t\t * finding a match deeper in the label stack.\n\t\t\t */\n\t\t\tif (h_label != DUK_HTHREAD_STRING_EMPTY_STRING(thr)) {\n\t\t\t\tDUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_LABEL);\n\t\t\t} else {\n\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"continue matched an empty label which does not \"\n\t\t\t\t                     \"allow a continue -> continue lookup deeper in label stack\"));\n\t\t\t}\n\t\t}\n\t}\n\t/* XXX: match flag is awkward, rework */\n\tif (!match) {\n\t\tDUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_LABEL);\n\t}\n\n\tDUK_DDD(DUK_DDDPRINT(\"label match: %!O -> label_id %ld, catch_depth=%ld, pc_label=%ld\",\n\t                     (duk_heaphdr *) h_label, (long) li->label_id,\n\t                     (long) li->catch_depth, (long) li->pc_label));\n\n\t*out_label_id = li->label_id;\n\t*out_label_catch_depth = li->catch_depth;\n\t*out_label_pc = li->pc_label;\n\t*out_is_closest = (li == li_end - 1);\n}\n\nDUK_LOCAL void duk__reset_labels_to_length(duk_compiler_ctx *comp_ctx, duk_size_t len) {\n\tduk_hthread *thr = comp_ctx->thr;\n\n\tduk_set_length(thr, comp_ctx->curr_func.labelnames_idx, len);\n\tduk_hbuffer_resize(thr, comp_ctx->curr_func.h_labelinfos, sizeof(duk_labelinfo) * len);\n}\n\n/*\n *  Expression parsing: duk__expr_nud(), duk__expr_led(), duk__expr_lbp(), and helpers.\n *\n *  - duk__expr_nud(): (\"null denotation\"): process prev_token as a \"start\" of an expression (e.g. literal)\n *  - duk__expr_led(): (\"left denotation\"): process prev_token in the \"middle\" of an expression (e.g. operator)\n *  - duk__expr_lbp(): (\"left-binding power\"): return left-binding power of curr_token\n */\n\n/* object literal key tracking flags */\n#define DUK__OBJ_LIT_KEY_PLAIN  (1 << 0)  /* key encountered as a plain property */\n#define DUK__OBJ_LIT_KEY_GET    (1 << 1)  /* key encountered as a getter */\n#define DUK__OBJ_LIT_KEY_SET    (1 << 2)  /* key encountered as a setter */\n\nDUK_LOCAL void duk__nud_array_literal(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {\n\tduk_hthread *thr = comp_ctx->thr;\n\tduk_regconst_t reg_obj;                 /* result reg */\n\tduk_regconst_t reg_temp;                /* temp reg */\n\tduk_regconst_t temp_start;              /* temp reg value for start of loop */\n\tduk_small_uint_t max_init_values;  /* max # of values initialized in one MPUTARR set */\n\tduk_small_uint_t num_values;       /* number of values in current MPUTARR set */\n\tduk_uarridx_t curr_idx;            /* current (next) array index */\n\tduk_uarridx_t start_idx;           /* start array index of current MPUTARR set */\n\tduk_uarridx_t init_idx;            /* last array index explicitly initialized, +1 */\n\tduk_bool_t require_comma;          /* next loop requires a comma */\n#if !defined(DUK_USE_PREFER_SIZE)\n\tduk_int_t pc_newarr;\n\tduk_compiler_instr *instr;\n#endif\n\n\t/* DUK_TOK_LBRACKET already eaten, current token is right after that */\n\tDUK_ASSERT(comp_ctx->prev_token.t == DUK_TOK_LBRACKET);\n\n\tmax_init_values = DUK__MAX_ARRAY_INIT_VALUES;  /* XXX: depend on available temps? */\n\n\treg_obj = DUK__ALLOCTEMP(comp_ctx);\n#if !defined(DUK_USE_PREFER_SIZE)\n\tpc_newarr = duk__get_current_pc(comp_ctx);\n#endif\n\tduk__emit_bc(comp_ctx, DUK_OP_NEWARR, reg_obj);  /* XXX: patch initial size hint afterwards? */\n\ttemp_start = DUK__GETTEMP(comp_ctx);\n\n\t/*\n\t *  Emit initializers in sets of maximum max_init_values.\n\t *  Corner cases such as single value initializers do not have\n\t *  special handling now.\n\t *\n\t *  Elided elements must not be emitted as 'undefined' values,\n\t *  because such values would be enumerable (which is incorrect).\n\t *  Also note that trailing elisions must be reflected in the\n\t *  length of the final array but cause no elements to be actually\n\t *  inserted.\n\t */\n\n\tcurr_idx = 0;\n\tinit_idx = 0;         /* tracks maximum initialized index + 1 */\n\tstart_idx = 0;\n\trequire_comma = 0;\n\n\tfor (;;) {\n\t\tnum_values = 0;\n\t\tDUK__SETTEMP(comp_ctx, temp_start);\n\n\t\tif (comp_ctx->curr_token.t == DUK_TOK_RBRACKET) {\n\t\t\tbreak;\n\t\t}\n\n\t\tfor (;;) {\n\t\t\tif (comp_ctx->curr_token.t == DUK_TOK_RBRACKET) {\n\t\t\t\t/* the outer loop will recheck and exit */\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t/* comma check */\n\t\t\tif (require_comma) {\n\t\t\t\tif (comp_ctx->curr_token.t == DUK_TOK_COMMA) {\n\t\t\t\t\t/* comma after a value, expected */\n\t\t\t\t\tduk__advance(comp_ctx);\n\t\t\t\t\trequire_comma = 0;\n\t\t\t\t\tcontinue;\n\t\t\t\t} else {\n\t\t\t\t\tgoto syntax_error;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (comp_ctx->curr_token.t == DUK_TOK_COMMA) {\n\t\t\t\t\t/* elision - flush */\n\t\t\t\t\tcurr_idx++;\n\t\t\t\t\tduk__advance(comp_ctx);\n\t\t\t\t\t/* if num_values > 0, MPUTARR emitted by outer loop after break */\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\t/* else an array initializer element */\n\n\t\t\t/* initial index */\n\t\t\tif (num_values == 0) {\n\t\t\t\tstart_idx = curr_idx;\n\t\t\t\treg_temp = DUK__ALLOCTEMP(comp_ctx);\n\t\t\t\tduk__emit_load_int32(comp_ctx, reg_temp, (duk_int32_t) start_idx);\n\t\t\t}\n\n\t\t\treg_temp = DUK__ALLOCTEMP(comp_ctx);   /* alloc temp just in case, to update max temp */\n\t\t\tDUK__SETTEMP(comp_ctx, reg_temp);\n\t\t\tduk__expr_toforcedreg(comp_ctx, res, DUK__BP_COMMA /*rbp_flags*/, reg_temp /*forced_reg*/);\n\t\t\tDUK__SETTEMP(comp_ctx, reg_temp + 1);\n\n\t\t\tnum_values++;\n\t\t\tcurr_idx++;\n\t\t\trequire_comma = 1;\n\n\t\t\tif (num_values >= max_init_values) {\n\t\t\t\t/* MPUTARR emitted by outer loop */\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif (num_values > 0) {\n\t\t\t/* - A is a source register (it's not a write target, but used\n\t\t\t *   to identify the target object) but can be shuffled.\n\t\t\t * - B cannot be shuffled normally because it identifies a range\n\t\t\t *   of registers, the emitter has special handling for this\n\t\t\t *   (the \"no shuffle\" flag must not be set).\n\t\t\t * - C is a non-register number and cannot be shuffled, but\n\t\t\t *   never needs to be.\n\t\t\t */\n\t\t\tduk__emit_a_b_c(comp_ctx,\n\t\t\t                DUK_OP_MPUTARR |\n\t\t\t                    DUK__EMIT_FLAG_NO_SHUFFLE_C |\n\t\t\t                    DUK__EMIT_FLAG_A_IS_SOURCE,\n\t\t\t                reg_obj,\n\t\t\t                temp_start,\n\t\t\t                (duk_regconst_t) (num_values + 1));\n\t\t\tinit_idx = start_idx + num_values;\n\n\t\t\t/* num_values and temp_start reset at top of outer loop */\n\t\t}\n\t}\n\n\t/* Update initil size for NEWARR, doesn't need to be exact and is\n\t * capped at A field limit.\n\t */\n#if !defined(DUK_USE_PREFER_SIZE)\n\tinstr = duk__get_instr_ptr(comp_ctx, pc_newarr);\n\tinstr->ins |= DUK_ENC_OP_A(0, curr_idx > DUK_BC_A_MAX ? DUK_BC_A_MAX : curr_idx);\n#endif\n\n\tDUK_ASSERT(comp_ctx->curr_token.t == DUK_TOK_RBRACKET);\n\tduk__advance(comp_ctx);\n\n\tDUK_DDD(DUK_DDDPRINT(\"array literal done, curridx=%ld, initidx=%ld\",\n\t                     (long) curr_idx, (long) init_idx));\n\n\t/* trailing elisions? */\n\tif (curr_idx > init_idx) {\n\t\t/* yes, must set array length explicitly */\n\t\tDUK_DDD(DUK_DDDPRINT(\"array literal has trailing elisions which affect its length\"));\n\t\treg_temp = DUK__ALLOCTEMP(comp_ctx);\n\t\tduk__emit_load_int32(comp_ctx, reg_temp, (duk_int_t) curr_idx);\n\t\tduk__emit_a_bc(comp_ctx,\n\t\t               DUK_OP_SETALEN | DUK__EMIT_FLAG_A_IS_SOURCE,\n\t\t               reg_obj,\n\t\t               reg_temp);\n\t}\n\n\tDUK__SETTEMP(comp_ctx, temp_start);\n\n\tduk__ivalue_regconst(res, reg_obj);\n\treturn;\n\n syntax_error:\n\tDUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_ARRAY_LITERAL);\n}\n\ntypedef struct {\n\tduk_regconst_t reg_obj;\n\tduk_regconst_t temp_start;\n\tduk_small_uint_t num_pairs;\n\tduk_small_uint_t num_total_pairs;\n} duk__objlit_state;\n\nDUK_LOCAL void duk__objlit_flush_keys(duk_compiler_ctx *comp_ctx, duk__objlit_state *st) {\n\tif (st->num_pairs > 0) {\n\t\t/* - A is a source register (it's not a write target, but used\n\t\t *   to identify the target object) but can be shuffled.\n\t\t * - B cannot be shuffled normally because it identifies a range\n\t\t *   of registers, the emitter has special handling for this\n\t\t *   (the \"no shuffle\" flag must not be set).\n\t\t * - C is a non-register number and cannot be shuffled, but\n\t\t *   never needs to be.\n\t\t */\n\t\tDUK_ASSERT(st->num_pairs > 0);\n\t\tduk__emit_a_b_c(comp_ctx,\n\t\t                DUK_OP_MPUTOBJ |\n\t\t                    DUK__EMIT_FLAG_NO_SHUFFLE_C |\n\t\t                    DUK__EMIT_FLAG_A_IS_SOURCE,\n\t\t                st->reg_obj,\n\t\t                st->temp_start,\n\t\t                (duk_regconst_t) (st->num_pairs * 2));\n\t\tst->num_total_pairs += st->num_pairs;\n\t\tst->num_pairs = 0;\n\t}\n\tDUK__SETTEMP(comp_ctx, st->temp_start);\n}\n\nDUK_LOCAL duk_bool_t duk__objlit_load_key(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_token *tok, duk_regconst_t reg_temp) {\n\tif (tok->t_nores == DUK_TOK_IDENTIFIER || tok->t_nores == DUK_TOK_STRING) {\n\t\t/* same handling for identifiers and strings */\n\t\tDUK_ASSERT(tok->str1 != NULL);\n\t\tduk_push_hstring(comp_ctx->thr, tok->str1);\n\t} else if (tok->t == DUK_TOK_NUMBER) {\n\t\t/* numbers can be loaded as numbers and coerced on the fly */\n\t\tduk_push_number(comp_ctx->thr, tok->num);\n\t} else {\n\t\treturn 1;  /* error */\n\t}\n\n\tduk__ivalue_plain_fromstack(comp_ctx, res);\n\tDUK__SETTEMP(comp_ctx, reg_temp + 1);\n\tduk__ivalue_toforcedreg(comp_ctx, res, reg_temp);\n\tDUK__SETTEMP(comp_ctx, reg_temp + 1);\n\treturn 0;\n}\n\nDUK_LOCAL void duk__nud_object_literal(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {\n\tduk_hthread *thr = comp_ctx->thr;\n\tduk__objlit_state st;\n\tduk_regconst_t reg_temp;          /* temp reg */\n\tduk_small_uint_t max_init_pairs;  /* max # of key-value pairs initialized in one MPUTOBJ set */\n\tduk_bool_t first;                 /* first value: comma must not precede the value */\n\tduk_bool_t is_set, is_get;        /* temps */\n#if !defined(DUK_USE_PREFER_SIZE)\n\tduk_int_t pc_newobj;\n\tduk_compiler_instr *instr;\n#endif\n\n\tDUK_ASSERT(comp_ctx->prev_token.t == DUK_TOK_LCURLY);\n\n\tmax_init_pairs = DUK__MAX_OBJECT_INIT_PAIRS;  /* XXX: depend on available temps? */\n\n\tst.reg_obj = DUK__ALLOCTEMP(comp_ctx);    /* target object */\n\tst.temp_start = DUK__GETTEMP(comp_ctx);   /* start of MPUTOBJ argument list */\n\tst.num_pairs = 0;                         /* number of key/value pairs emitted for current MPUTOBJ set */\n\tst.num_total_pairs = 0;                   /* number of key/value pairs emitted overall */\n\n#if !defined(DUK_USE_PREFER_SIZE)\n\tpc_newobj = duk__get_current_pc(comp_ctx);\n#endif\n\tduk__emit_bc(comp_ctx, DUK_OP_NEWOBJ, st.reg_obj);\n\n\t/*\n\t *  Emit initializers in sets of maximum max_init_pairs keys.\n\t *  Setter/getter is handled separately and terminates the\n\t *  current set of initializer values.  Corner cases such as\n\t *  single value initializers do not have special handling now.\n\t */\n\n\tfirst = 1;\n\tfor (;;) {\n\t\t/*\n\t\t *  ES5 and ES2015+ provide a lot of different PropertyDefinition\n\t\t *  formats, see http://www.ecma-international.org/ecma-262/6.0/#sec-object-initializer.\n\t\t *\n\t\t *  PropertyName can be IdentifierName (includes reserved words), a string\n\t\t *  literal, or a number literal.  Note that IdentifierName allows 'get' and\n\t\t *  'set' too, so we need to look ahead to the next token to distinguish:\n\t\t *\n\t\t *     { get : 1 }\n\t\t *\n\t\t *  and\n\t\t *\n\t\t *     { get foo() { return 1 } }\n\t\t *     { get get() { return 1 } }    // 'get' as getter propertyname\n\t\t *\n\t\t *  Finally, a trailing comma is allowed.\n\t\t *\n\t\t *  Key name is coerced to string at compile time (and ends up as a\n\t\t *  a string constant) even for numeric keys (e.g. \"{1:'foo'}\").\n\t\t *  These could be emitted using e.g. LDINT, but that seems hardly\n\t\t *  worth the effort and would increase code size.\n\t\t */\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"object literal loop, curr_token->t = %ld\",\n\t\t                     (long) comp_ctx->curr_token.t));\n\n\t\tif (comp_ctx->curr_token.t == DUK_TOK_RCURLY) {\n\t\t\tbreak;\n\t\t}\n\n\t\tif (first) {\n\t\t\tfirst = 0;\n\t\t} else {\n\t\t\tif (comp_ctx->curr_token.t != DUK_TOK_COMMA) {\n\t\t\t\tgoto syntax_error;\n\t\t\t}\n\t\t\tduk__advance(comp_ctx);\n\t\t\tif (comp_ctx->curr_token.t == DUK_TOK_RCURLY) {\n\t\t\t\t/* trailing comma followed by rcurly */\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t/* Advance to get one step of lookup. */\n\t\tduk__advance(comp_ctx);\n\n\t\t/* Flush current MPUTOBJ if enough many pairs gathered. */\n\t\tif (st.num_pairs >= max_init_pairs) {\n\t\t\tduk__objlit_flush_keys(comp_ctx, &st);\n\t\t\tDUK_ASSERT(st.num_pairs == 0);\n\t\t}\n\n\t\t/* Reset temp register state and reserve reg_temp and\n\t\t * reg_temp + 1 for handling the current property.\n\t\t */\n\t\tDUK__SETTEMP(comp_ctx, st.temp_start + 2 * (duk_regconst_t) st.num_pairs);\n\t\treg_temp = DUK__ALLOCTEMPS(comp_ctx, 2);\n\n\t\t/* NOTE: \"get\" and \"set\" are not officially ReservedWords and the lexer\n\t\t * currently treats them always like ordinary identifiers (DUK_TOK_GET\n\t\t * and DUK_TOK_SET are unused).  They need to be detected based on the\n\t\t * identifier string content.\n\t\t */\n\n\t\tis_get = (comp_ctx->prev_token.t == DUK_TOK_IDENTIFIER &&\n\t\t          comp_ctx->prev_token.str1 == DUK_HTHREAD_STRING_GET(thr));\n\t\tis_set = (comp_ctx->prev_token.t == DUK_TOK_IDENTIFIER &&\n\t\t          comp_ctx->prev_token.str1 == DUK_HTHREAD_STRING_SET(thr));\n\t\tif ((is_get || is_set) && comp_ctx->curr_token.t != DUK_TOK_COLON) {\n\t\t\t/* getter/setter */\n\t\t\tduk_int_t fnum;\n\n\t\t\tduk__objlit_flush_keys(comp_ctx, &st);\n\t\t\tDUK_ASSERT(DUK__GETTEMP(comp_ctx) == st.temp_start);  /* 2 regs are guaranteed to be allocated w.r.t. temp_max */\n\t\t\treg_temp = DUK__ALLOCTEMPS(comp_ctx, 2);\n\n\t\t\tif (duk__objlit_load_key(comp_ctx, res, &comp_ctx->curr_token, reg_temp) != 0) {\n\t\t\t\tgoto syntax_error;\n\t\t\t}\n\n\t\t\t/* curr_token = get/set name */\n\t\t\tfnum = duk__parse_func_like_fnum(comp_ctx, DUK__FUNC_FLAG_GETSET);\n\n\t\t\tduk__emit_a_bc(comp_ctx,\n\t\t\t               DUK_OP_CLOSURE,\n\t\t\t               st.temp_start + 1,\n\t\t\t               (duk_regconst_t) fnum);\n\n\t\t\t/* Slot C is used in a non-standard fashion (range of regs),\n\t\t\t * emitter code has special handling for it (must not set the\n\t\t\t * \"no shuffle\" flag).\n\t\t\t */\n\t\t\tduk__emit_a_bc(comp_ctx,\n\t\t\t              (is_get ? DUK_OP_INITGET : DUK_OP_INITSET) | DUK__EMIT_FLAG_A_IS_SOURCE,\n\t\t\t              st.reg_obj,\n\t\t\t              st.temp_start);   /* temp_start+0 = key, temp_start+1 = closure */\n\n\t\t\tDUK_ASSERT(st.num_pairs == 0);  /* temp state is reset on next loop */\n#if defined(DUK_USE_ES6)\n\t\t} else if (comp_ctx->prev_token.t == DUK_TOK_IDENTIFIER &&\n\t\t           (comp_ctx->curr_token.t == DUK_TOK_COMMA || comp_ctx->curr_token.t == DUK_TOK_RCURLY)) {\n\t\t\tduk_bool_t load_rc;\n\n\t\t\tload_rc = duk__objlit_load_key(comp_ctx, res, &comp_ctx->prev_token, reg_temp);\n\t\t\tDUK_UNREF(load_rc);\n\t\t\tDUK_ASSERT(load_rc == 0);  /* always succeeds because token is identifier */\n\n\t\t\tduk__ivalue_var_hstring(comp_ctx, res, comp_ctx->prev_token.str1);\n\t\t\tDUK_ASSERT(DUK__GETTEMP(comp_ctx) == reg_temp + 1);\n\t\t\tduk__ivalue_toforcedreg(comp_ctx, res, reg_temp + 1);\n\n\t\t\tst.num_pairs++;\n\t\t} else if ((comp_ctx->prev_token.t == DUK_TOK_IDENTIFIER ||\n\t\t            comp_ctx->prev_token.t == DUK_TOK_STRING ||\n\t\t            comp_ctx->prev_token.t == DUK_TOK_NUMBER) &&\n\t\t           comp_ctx->curr_token.t == DUK_TOK_LPAREN) {\n\t\t\tduk_int_t fnum;\n\n\t\t\t/* Parsing-wise there's a small hickup here: the token parsing\n\t\t\t * state is one step too advanced for the function parse helper\n\t\t\t * compared to other cases.  The current solution is an extra\n\t\t\t * flag to indicate whether function parsing should use the\n\t\t\t * current or the previous token to starting parsing from.\n\t\t\t */\n\n\t\t\tif (duk__objlit_load_key(comp_ctx, res, &comp_ctx->prev_token, reg_temp) != 0) {\n\t\t\t\tgoto syntax_error;\n\t\t\t}\n\n\t\t\tfnum = duk__parse_func_like_fnum(comp_ctx, DUK__FUNC_FLAG_USE_PREVTOKEN | DUK__FUNC_FLAG_METDEF);\n\n\t\t\tduk__emit_a_bc(comp_ctx,\n\t\t\t               DUK_OP_CLOSURE,\n\t\t\t               reg_temp + 1,\n\t\t\t               (duk_regconst_t) fnum);\n\n\t\t\tst.num_pairs++;\n#endif  /* DUK_USE_ES6 */\n\t\t} else {\n#if defined(DUK_USE_ES6)\n\t\t\tif (comp_ctx->prev_token.t == DUK_TOK_LBRACKET) {\n\t\t\t\t/* ES2015 computed property name.  Executor ToPropertyKey()\n\t\t\t\t * coerces the key at runtime.\n\t\t\t\t */\n\t\t\t\tDUK__SETTEMP(comp_ctx, reg_temp);\n\t\t\t\tduk__expr_toforcedreg(comp_ctx, res, DUK__BP_FOR_EXPR, reg_temp);\n\t\t\t\tduk__advance_expect(comp_ctx, DUK_TOK_RBRACKET);\n\n\t\t\t\t/* XXX: If next token is '(' we're dealing with\n\t\t\t\t * the method shorthand with a computed name,\n\t\t\t\t * e.g. { [Symbol.for('foo')](a,b) {} }.  This\n\t\t\t\t * form is not yet supported and causes a\n\t\t\t\t * SyntaxError on the DUK_TOK_COLON check below.\n\t\t\t\t */\n\t\t\t}\n\t\t\telse\n#endif  /* DUK_USE_ES6 */\n\t\t\t{\n\t\t\t\tif (duk__objlit_load_key(comp_ctx, res, &comp_ctx->prev_token, reg_temp) != 0) {\n\t\t\t\t\tgoto syntax_error;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tduk__advance_expect(comp_ctx, DUK_TOK_COLON);\n\n\t\t\tDUK__SETTEMP(comp_ctx, reg_temp + 1);\n\t\t\tduk__expr_toforcedreg(comp_ctx, res, DUK__BP_COMMA /*rbp_flags*/, reg_temp + 1 /*forced_reg*/);\n\n\t\t\tst.num_pairs++;\n\t\t}\n\t}  /* property loop */\n\n\t/* Flush remaining properties. */\n\tduk__objlit_flush_keys(comp_ctx, &st);\n\tDUK_ASSERT(st.num_pairs == 0);\n\tDUK_ASSERT(DUK__GETTEMP(comp_ctx) == st.temp_start);\n\n\t/* Update initial size for NEWOBJ.  The init size doesn't need to be\n\t * exact as the purpose is just to avoid object resizes in common\n\t * cases.  The size is capped to field A limit, and will be too high\n\t * if the object literal contains duplicate keys (this is harmless but\n\t * increases memory traffic if the object is compacted later on).\n\t */\n#if !defined(DUK_USE_PREFER_SIZE)\n\tinstr = duk__get_instr_ptr(comp_ctx, pc_newobj);\n\tinstr->ins |= DUK_ENC_OP_A(0, st.num_total_pairs > DUK_BC_A_MAX ? DUK_BC_A_MAX : st.num_total_pairs);\n#endif\n\n\tDUK_ASSERT(comp_ctx->curr_token.t == DUK_TOK_RCURLY);\n\tduk__advance(comp_ctx);\n\n\tduk__ivalue_regconst(res, st.reg_obj);\n\treturn;\n\n syntax_error:\n\tDUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_OBJECT_LITERAL);\n}\n\n/* Parse argument list.  Arguments are written to temps starting from\n * \"next temp\".  Returns number of arguments parsed.  Expects left paren\n * to be already eaten, and eats the right paren before returning.\n */\nDUK_LOCAL duk_int_t duk__parse_arguments(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {\n\tduk_int_t nargs = 0;\n\tduk_regconst_t reg_temp;\n\n\t/* Note: expect that caller has already eaten the left paren */\n\n\tDUK_DDD(DUK_DDDPRINT(\"start parsing arguments, prev_token.t=%ld, curr_token.t=%ld\",\n\t                     (long) comp_ctx->prev_token.t, (long) comp_ctx->curr_token.t));\n\n\tfor (;;) {\n\t\tif (comp_ctx->curr_token.t == DUK_TOK_RPAREN) {\n\t\t\tbreak;\n\t\t}\n\t\tif (nargs > 0) {\n\t\t\tduk__advance_expect(comp_ctx, DUK_TOK_COMMA);\n\t\t}\n\n\t\t/* We want the argument expression value to go to \"next temp\"\n\t\t * without additional moves.  That should almost always be the\n\t\t * case, but we double check after expression parsing.\n\t\t *\n\t\t * This is not the cleanest possible approach.\n\t\t */\n\n\t\treg_temp = DUK__ALLOCTEMP(comp_ctx);  /* bump up \"allocated\" reg count, just in case */\n\t\tDUK__SETTEMP(comp_ctx, reg_temp);\n\n\t\t/* binding power must be high enough to NOT allow comma expressions directly */\n\t\tduk__expr_toforcedreg(comp_ctx, res, DUK__BP_COMMA /*rbp_flags*/, reg_temp);  /* always allow 'in', coerce to 'tr' just in case */\n\n\t\tDUK__SETTEMP(comp_ctx, reg_temp + 1);\n\t\tnargs++;\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"argument #%ld written into reg %ld\", (long) nargs, (long) reg_temp));\n\t}\n\n\t/* eat the right paren */\n\tduk__advance_expect(comp_ctx, DUK_TOK_RPAREN);\n\n\tDUK_DDD(DUK_DDDPRINT(\"end parsing arguments\"));\n\n\treturn nargs;\n}\n\nDUK_LOCAL duk_bool_t duk__expr_is_empty(duk_compiler_ctx *comp_ctx) {\n\t/* empty expressions can be detected conveniently with nud/led counts */\n\treturn (comp_ctx->curr_func.nud_count == 0) &&\n\t       (comp_ctx->curr_func.led_count == 0);\n}\n\nDUK_LOCAL void duk__expr_nud(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {\n\tduk_hthread *thr = comp_ctx->thr;\n\tduk_token *tk;\n\tduk_regconst_t temp_at_entry;\n\tduk_small_uint_t tok;\n\tduk_uint32_t args;  /* temp variable to pass constants and flags to shared code */\n\n\t/*\n\t *  ctx->prev_token     token to process with duk__expr_nud()\n\t *  ctx->curr_token     updated by caller\n\t *\n\t *  Note: the token in the switch below has already been eaten.\n\t */\n\n\ttemp_at_entry = DUK__GETTEMP(comp_ctx);\n\n\tcomp_ctx->curr_func.nud_count++;\n\n\ttk = &comp_ctx->prev_token;\n\ttok = tk->t;\n\tres->t = DUK_IVAL_NONE;\n\n\tDUK_DDD(DUK_DDDPRINT(\"duk__expr_nud(), prev_token.t=%ld, allow_in=%ld, paren_level=%ld\",\n\t                     (long) tk->t, (long) comp_ctx->curr_func.allow_in, (long) comp_ctx->curr_func.paren_level));\n\n\tswitch (tok) {\n\n\t/* PRIMARY EXPRESSIONS */\n\n\tcase DUK_TOK_THIS: {\n\t\tduk_regconst_t reg_temp;\n\t\treg_temp = DUK__ALLOCTEMP(comp_ctx);\n\t\tduk__emit_bc(comp_ctx,\n\t\t             DUK_OP_LDTHIS,\n\t\t             reg_temp);\n\t\tduk__ivalue_regconst(res, reg_temp);\n\t\treturn;\n\t}\n\tcase DUK_TOK_IDENTIFIER: {\n\t\tduk__ivalue_var_hstring(comp_ctx, res, tk->str1);\n\t\treturn;\n\t}\n\tcase DUK_TOK_NULL: {\n\t\tduk_push_null(thr);\n\t\tgoto plain_value;\n\t}\n\tcase DUK_TOK_TRUE: {\n\t\tduk_push_true(thr);\n\t\tgoto plain_value;\n\t}\n\tcase DUK_TOK_FALSE: {\n\t\tduk_push_false(thr);\n\t\tgoto plain_value;\n\t}\n\tcase DUK_TOK_NUMBER: {\n\t\tduk_push_number(thr, tk->num);\n\t\tgoto plain_value;\n\t}\n\tcase DUK_TOK_STRING: {\n\t\tDUK_ASSERT(tk->str1 != NULL);\n\t\tduk_push_hstring(thr, tk->str1);\n\t\tgoto plain_value;\n\t}\n\tcase DUK_TOK_REGEXP: {\n#if defined(DUK_USE_REGEXP_SUPPORT)\n\t\tduk_regconst_t reg_temp;\n\t\tduk_regconst_t rc_re_bytecode;  /* const */\n\t\tduk_regconst_t rc_re_source;    /* const */\n\n\t\tDUK_ASSERT(tk->str1 != NULL);\n\t\tDUK_ASSERT(tk->str2 != NULL);\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"emitting regexp op, str1=%!O, str2=%!O\",\n\t\t                     (duk_heaphdr *) tk->str1,\n\t\t                     (duk_heaphdr *) tk->str2));\n\n\t\treg_temp = DUK__ALLOCTEMP(comp_ctx);\n\t\tduk_push_hstring(thr, tk->str1);\n\t\tduk_push_hstring(thr, tk->str2);\n\n\t\t/* [ ... pattern flags ] */\n\n\t\tduk_regexp_compile(thr);\n\n\t\t/* [ ... escaped_source bytecode ] */\n\n\t\trc_re_bytecode = duk__getconst(comp_ctx);\n\t\trc_re_source = duk__getconst(comp_ctx);\n\n\t\tduk__emit_a_b_c(comp_ctx,\n\t\t                DUK_OP_REGEXP | DUK__EMIT_FLAG_BC_REGCONST,\n\t\t                reg_temp /*a*/,\n\t\t                rc_re_bytecode /*b*/,\n\t\t                rc_re_source /*c*/);\n\n\t\tduk__ivalue_regconst(res, reg_temp);\n\t\treturn;\n#else  /* DUK_USE_REGEXP_SUPPORT */\n\t\tgoto syntax_error;\n#endif  /* DUK_USE_REGEXP_SUPPORT */\n\t}\n\tcase DUK_TOK_LBRACKET: {\n\t\tDUK_DDD(DUK_DDDPRINT(\"parsing array literal\"));\n\t\tduk__nud_array_literal(comp_ctx, res);\n\t\treturn;\n\t}\n\tcase DUK_TOK_LCURLY: {\n\t\tDUK_DDD(DUK_DDDPRINT(\"parsing object literal\"));\n\t\tduk__nud_object_literal(comp_ctx, res);\n\t\treturn;\n\t}\n\tcase DUK_TOK_LPAREN: {\n\t\tduk_bool_t prev_allow_in;\n\n\t\tcomp_ctx->curr_func.paren_level++;\n\t\tprev_allow_in = comp_ctx->curr_func.allow_in;\n\t\tcomp_ctx->curr_func.allow_in = 1; /* reset 'allow_in' for parenthesized expression */\n\n\t\tduk__expr(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);  /* Expression, terminates at a ')' */\n\n\t\tduk__advance_expect(comp_ctx, DUK_TOK_RPAREN);\n\t\tcomp_ctx->curr_func.allow_in = prev_allow_in;\n\t\tcomp_ctx->curr_func.paren_level--;\n\t\treturn;\n\t}\n\n\t/* MEMBER/NEW/CALL EXPRESSIONS */\n\n\tcase DUK_TOK_NEW: {\n\t\t/*\n\t\t *  Parsing an expression starting with 'new' is tricky because\n\t\t *  there are multiple possible productions deriving from\n\t\t *  LeftHandSideExpression which begin with 'new'.\n\t\t *\n\t\t *  We currently resort to one-token lookahead to distinguish the\n\t\t *  cases.  Hopefully this is correct.  The binding power must be\n\t\t *  such that parsing ends at an LPAREN (CallExpression) but not at\n\t\t *  a PERIOD or LBRACKET (MemberExpression).\n\t\t *\n\t\t *  See doc/compiler.rst for discussion on the parsing approach,\n\t\t *  and testcases/test-dev-new.js for a bunch of documented tests.\n\t\t */\n\n\t\tduk_regconst_t reg_target;\n\t\tduk_int_t nargs;\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"begin parsing new expression\"));\n\n\t\treg_target = DUK__ALLOCTEMPS(comp_ctx, 2);\n\n#if defined(DUK_USE_ES6)\n\t\tif (comp_ctx->curr_token.t == DUK_TOK_PERIOD) {\n\t\t\t/* new.target */\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"new.target\"));\n\t\t\tduk__advance(comp_ctx);\n\t\t\tif (comp_ctx->curr_token.t_nores != DUK_TOK_IDENTIFIER ||\n\t\t\t    !duk_hstring_equals_ascii_cstring(comp_ctx->curr_token.str1, \"target\")) {\n\t\t\t\tgoto syntax_error_newtarget;\n\t\t\t}\n\t\t\tif (comp_ctx->curr_func.is_global) {\n\t\t\t\tgoto syntax_error_newtarget;\n\t\t\t}\n\t\t\tduk__advance(comp_ctx);\n\t\t\tduk__emit_bc(comp_ctx,\n\t\t\t             DUK_OP_NEWTARGET,\n\t\t\t             reg_target);\n\t\t\tduk__ivalue_regconst(res, reg_target);\n\t\t\treturn;\n\t\t}\n#endif  /* DUK_USE_ES6 */\n\n\t\tduk__expr_toforcedreg(comp_ctx, res, DUK__BP_CALL /*rbp_flags*/, reg_target /*forced_reg*/);\n\t\tduk__emit_bc(comp_ctx, DUK_OP_NEWOBJ, reg_target + 1);  /* default instance */\n\t\tDUK__SETTEMP(comp_ctx, reg_target + 2);\n\n\t\t/* XXX: 'new obj.noSuch()' doesn't use GETPROPC now which\n\t\t * makes the error message worse than for obj.noSuch().\n\t\t */\n\n\t\tif (comp_ctx->curr_token.t == DUK_TOK_LPAREN) {\n\t\t\t/* 'new' MemberExpression Arguments */\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"new expression has argument list\"));\n\t\t\tduk__advance(comp_ctx);\n\t\t\tnargs = duk__parse_arguments(comp_ctx, res);  /* parse args starting from \"next temp\", reg_target + 1 */\n\t\t\t/* right paren eaten */\n\t\t} else {\n\t\t\t/* 'new' MemberExpression */\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"new expression has no argument list\"));\n\t\t\tnargs = 0;\n\t\t}\n\n\t\tduk__emit_a_bc(comp_ctx,\n\t\t              DUK_OP_CALL0 | DUK_BC_CALL_FLAG_CONSTRUCT,\n\t\t              nargs /*num_args*/,\n\t\t              reg_target /*target*/);\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"end parsing new expression\"));\n\n\t\tduk__ivalue_regconst(res, reg_target);\n\t\treturn;\n\t}\n\n\t/* FUNCTION EXPRESSIONS */\n\n\tcase DUK_TOK_FUNCTION: {\n\t\t/* Function expression.  Note that any statement beginning with 'function'\n\t\t * is handled by the statement parser as a function declaration, or a\n\t\t * non-standard function expression/statement (or a SyntaxError).  We only\n\t\t * handle actual function expressions (occurring inside an expression) here.\n\t\t *\n\t\t * O(depth^2) parse count for inner functions is handled by recording a\n\t\t * lexer offset on the first compilation pass, so that the function can\n\t\t * be efficiently skipped on the second pass.  This is encapsulated into\n\t\t * duk__parse_func_like_fnum().\n\t\t */\n\n\t\tduk_regconst_t reg_temp;\n\t\tduk_int_t fnum;\n\n\t\treg_temp = DUK__ALLOCTEMP(comp_ctx);\n\n\t\t/* curr_token follows 'function' */\n\t\tfnum = duk__parse_func_like_fnum(comp_ctx, 0 /*flags*/);\n\t\tDUK_DDD(DUK_DDDPRINT(\"parsed inner function -> fnum %ld\", (long) fnum));\n\n\t\tduk__emit_a_bc(comp_ctx,\n\t\t               DUK_OP_CLOSURE,\n\t\t               reg_temp /*a*/,\n\t\t               (duk_regconst_t) fnum /*bc*/);\n\n\t\tduk__ivalue_regconst(res, reg_temp);\n\t\treturn;\n\t}\n\n\t/* UNARY EXPRESSIONS */\n\n\tcase DUK_TOK_DELETE: {\n\t\t/* Delete semantics are a bit tricky.  The description in E5 specification\n\t\t * is kind of confusing, because it distinguishes between resolvability of\n\t\t * a reference (which is only known at runtime) seemingly at compile time\n\t\t * (= SyntaxError throwing).\n\t\t */\n\t\tduk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/);  /* UnaryExpression */\n\t\tif (res->t == DUK_IVAL_VAR) {\n\t\t\t/* not allowed in strict mode, regardless of whether resolves;\n\t\t\t * in non-strict mode DELVAR handles both non-resolving and\n\t\t\t * resolving cases (the specification description is a bit confusing).\n\t\t\t */\n\n\t\t\tduk_regconst_t reg_temp;\n\t\t\tduk_regconst_t reg_varbind;\n\t\t\tduk_regconst_t rc_varname;\n\n\t\t\tif (comp_ctx->curr_func.is_strict) {\n\t\t\t\tDUK_ERROR_SYNTAX(thr, DUK_STR_CANNOT_DELETE_IDENTIFIER);\n\t\t\t}\n\n\t\t\tDUK__SETTEMP(comp_ctx, temp_at_entry);\n\t\t\treg_temp = DUK__ALLOCTEMP(comp_ctx);\n\n\t\t\tduk_dup(thr, res->x1.valstack_idx);\n\t\t\tif (duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname)) {\n\t\t\t\t/* register bound variables are non-configurable -> always false */\n\t\t\t\tduk__emit_bc(comp_ctx,\n\t\t\t\t             DUK_OP_LDFALSE,\n\t\t\t\t             reg_temp);\n\t\t\t} else {\n\t\t\t\tduk_dup(thr, res->x1.valstack_idx);\n\t\t\t\trc_varname = duk__getconst(comp_ctx);\n\t\t\t\tduk__emit_a_bc(comp_ctx,\n\t\t\t\t               DUK_OP_DELVAR,\n\t\t\t\t               reg_temp,\n\t\t\t\t               rc_varname);\n\t\t\t}\n\t\t\tduk__ivalue_regconst(res, reg_temp);\n\t\t} else if (res->t == DUK_IVAL_PROP) {\n\t\t\tduk_regconst_t reg_temp;\n\t\t\tduk_regconst_t reg_obj;\n\t\t\tduk_regconst_t rc_key;\n\n\t\t\tDUK__SETTEMP(comp_ctx, temp_at_entry);\n\t\t\treg_temp = DUK__ALLOCTEMP(comp_ctx);\n\t\t\treg_obj = duk__ispec_toregconst_raw(comp_ctx, &res->x1, -1 /*forced_reg*/, 0 /*flags*/);  /* don't allow const */\n\t\t\trc_key = duk__ispec_toregconst_raw(comp_ctx, &res->x2, -1 /*forced_reg*/, DUK__IVAL_FLAG_ALLOW_CONST /*flags*/);\n\t\t\tduk__emit_a_b_c(comp_ctx,\n\t\t\t                DUK_OP_DELPROP | DUK__EMIT_FLAG_BC_REGCONST,\n\t\t\t                reg_temp,\n\t\t\t                reg_obj,\n\t\t\t                rc_key);\n\n\t\t\tduk__ivalue_regconst(res, reg_temp);\n\t\t} else {\n\t\t\t/* non-Reference deletion is always 'true', even in strict mode */\n\t\t\tduk_push_true(thr);\n\t\t\tgoto plain_value;\n\t\t}\n\t\treturn;\n\t}\n\tcase DUK_TOK_VOID: {\n\t\tduk__expr_toplain_ignore(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/);  /* UnaryExpression */\n\t\tduk_push_undefined(thr);\n\t\tgoto plain_value;\n\t}\n\tcase DUK_TOK_TYPEOF: {\n\t\t/* 'typeof' must handle unresolvable references without throwing\n\t\t * a ReferenceError (E5 Section 11.4.3).  Register mapped values\n\t\t * will never be unresolvable so special handling is only required\n\t\t * when an identifier is a \"slow path\" one.\n\t\t */\n\t\tduk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/);  /* UnaryExpression */\n\n\t\tif (res->t == DUK_IVAL_VAR) {\n\t\t\tduk_regconst_t reg_varbind;\n\t\t\tduk_regconst_t rc_varname;\n\t\t\tduk_regconst_t reg_temp;\n\n\t\t\tduk_dup(thr, res->x1.valstack_idx);\n\t\t\tif (!duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname)) {\n\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"typeof for an identifier name which could not be resolved \"\n\t\t\t\t                     \"at compile time, need to use special run-time handling\"));\n\t\t\t\treg_temp = DUK__ALLOCTEMP(comp_ctx);\n\t\t\t\tduk__emit_a_bc(comp_ctx,\n\t\t\t\t               DUK_OP_TYPEOFID,\n\t\t\t\t               reg_temp,\n\t\t\t\t               rc_varname);\n\t\t\t\tduk__ivalue_regconst(res, reg_temp);\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\targs = DUK_OP_TYPEOF;\n\t\tgoto unary;\n\t}\n\tcase DUK_TOK_INCREMENT: {\n\t\targs = (DUK_OP_PREINCP << 8) + DUK_OP_PREINCR;\n\t\tgoto preincdec;\n\t}\n\tcase DUK_TOK_DECREMENT: {\n\t\targs = (DUK_OP_PREDECP << 8) + DUK_OP_PREDECR;\n\t\tgoto preincdec;\n\t}\n\tcase DUK_TOK_ADD: {\n\t\t/* unary plus */\n\t\tduk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/);  /* UnaryExpression */\n\t\tif (res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_VALUE &&\n\t\t    duk_is_number(thr, res->x1.valstack_idx)) {\n\t\t\t/* unary plus of a number is identity */\n\t\t\treturn;\n\t\t}\n\t\targs = DUK_OP_UNP;\n\t\tgoto unary;\n\t}\n\tcase DUK_TOK_SUB: {\n\t\t/* unary minus */\n\t\tduk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/);  /* UnaryExpression */\n\t\tif (res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_VALUE &&\n\t\t    duk_is_number(thr, res->x1.valstack_idx)) {\n\t\t\t/* this optimization is important to handle negative literals\n\t\t\t * (which are not directly provided by the lexical grammar)\n\t\t\t */\n\t\t\tduk_tval *tv_num;\n\t\t\tduk_double_union du;\n\n\t\t\ttv_num = DUK_GET_TVAL_POSIDX(thr, res->x1.valstack_idx);\n\t\t\tDUK_ASSERT(tv_num != NULL);\n\t\t\tDUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_num));\n\t\t\tdu.d = DUK_TVAL_GET_NUMBER(tv_num);\n\t\t\tdu.d = -du.d;\n\t\t\tDUK_DBLUNION_NORMALIZE_NAN_CHECK(&du);\n\t\t\tDUK_TVAL_SET_NUMBER(tv_num, du.d);\n\t\t\treturn;\n\t\t}\n\t\targs = DUK_OP_UNM;\n\t\tgoto unary;\n\t}\n\tcase DUK_TOK_BNOT: {\n\t\tduk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/);  /* UnaryExpression */\n\t\targs = DUK_OP_BNOT;\n\t\tgoto unary;\n\t}\n\tcase DUK_TOK_LNOT: {\n\t\tduk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/);  /* UnaryExpression */\n\t\tif (res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_VALUE) {\n\t\t\t/* Very minimal inlining to handle common idioms '!0' and '!1',\n\t\t\t * and also boolean arguments like '!false' and '!true'.\n\t\t\t */\n\t\t\tduk_tval *tv_val;\n\n\t\t\ttv_val = DUK_GET_TVAL_POSIDX(thr, res->x1.valstack_idx);\n\t\t\tDUK_ASSERT(tv_val != NULL);\n\t\t\tif (DUK_TVAL_IS_NUMBER(tv_val)) {\n\t\t\t\tduk_double_t d;\n\t\t\t\td = DUK_TVAL_GET_NUMBER(tv_val);\n\t\t\t\tif (d == 0.0) {\n\t\t\t\t\t/* Matches both +0 and -0 on purpose. */\n\t\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"inlined lnot: !0 -> true\"));\n\t\t\t\t\tDUK_TVAL_SET_BOOLEAN_TRUE(tv_val);\n\t\t\t\t\treturn;\n\t\t\t\t} else if (d == 1.0) {\n\t\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"inlined lnot: !1 -> false\"));\n\t\t\t\t\tDUK_TVAL_SET_BOOLEAN_FALSE(tv_val);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t} else if (DUK_TVAL_IS_BOOLEAN(tv_val)) {\n\t\t\t\tduk_small_uint_t v;\n\t\t\t\tv = DUK_TVAL_GET_BOOLEAN(tv_val);\n\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"inlined lnot boolean: %ld\", (long) v));\n\t\t\t\tDUK_ASSERT(v == 0 || v == 1);\n\t\t\t\tDUK_TVAL_SET_BOOLEAN(tv_val, v ^ 0x01);\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\targs = DUK_OP_LNOT;\n\t\tgoto unary;\n\t}\n\n\t}  /* end switch */\n\n\tDUK_ERROR_SYNTAX(thr, DUK_STR_PARSE_ERROR);\n\treturn;\n\n unary:\n\t{\n\t\t/* Unary opcodes use just the 'BC' register source because it\n\t\t * matches current shuffle limits, and maps cleanly to 16 high\n\t\t * bits of the opcode.\n\t\t */\n\n\t\tduk_regconst_t reg_src, reg_res;\n\n\t\treg_src = duk__ivalue_toregconst_raw(comp_ctx, res, -1 /*forced_reg*/, 0 /*flags*/);\n\t\tif (DUK__ISREG_TEMP(comp_ctx, reg_src)) {\n\t\t\treg_res = reg_src;\n\t\t} else {\n\t\t\treg_res = DUK__ALLOCTEMP(comp_ctx);\n\t\t}\n\t\tduk__emit_a_bc(comp_ctx,\n\t\t             args,\n\t\t             reg_res,\n\t\t             reg_src);\n\t\tduk__ivalue_regconst(res, reg_res);\n\t\treturn;\n\t}\n\n preincdec:\n\t{\n\t\t/* preincrement and predecrement */\n\t\tduk_regconst_t reg_res;\n\t\tduk_small_uint_t args_op1 = args & 0xff;  /* DUK_OP_PREINCR/DUK_OP_PREDECR */\n\t\tduk_small_uint_t args_op2 = args >> 8;    /* DUK_OP_PREINCP_RR/DUK_OP_PREDECP_RR */\n\n\t\t/* Specific assumptions for opcode numbering. */\n\t\tDUK_ASSERT(DUK_OP_PREINCR + 4 == DUK_OP_PREINCV);\n\t\tDUK_ASSERT(DUK_OP_PREDECR + 4 == DUK_OP_PREDECV);\n\n\t\treg_res = DUK__ALLOCTEMP(comp_ctx);\n\n\t\tduk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/);  /* UnaryExpression */\n\t\tif (res->t == DUK_IVAL_VAR) {\n\t\t\tduk_hstring *h_varname;\n\t\t\tduk_regconst_t reg_varbind;\n\t\t\tduk_regconst_t rc_varname;\n\n\t\t\th_varname = duk_known_hstring(thr, res->x1.valstack_idx);\n\n\t\t\tif (duk__hstring_is_eval_or_arguments_in_strict_mode(comp_ctx, h_varname)) {\n\t\t\t\tgoto syntax_error;\n\t\t\t}\n\n\t\t\tduk_dup(thr, res->x1.valstack_idx);\n\t\t\tif (duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname)) {\n\t\t\t\tduk__emit_a_bc(comp_ctx,\n\t\t\t\t               args_op1,  /* e.g. DUK_OP_PREINCR */\n\t\t\t\t               reg_res,\n\t\t\t\t               reg_varbind);\n\t\t\t} else {\n\t\t\t\tduk__emit_a_bc(comp_ctx,\n\t\t\t\t                args_op1 + 4,  /* e.g. DUK_OP_PREINCV */\n\t\t\t\t                reg_res,\n\t\t\t\t                rc_varname);\n\t\t\t}\n\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"preincdec to '%!O' -> reg_varbind=%ld, rc_varname=%ld\",\n\t\t\t                     (duk_heaphdr *) h_varname, (long) reg_varbind, (long) rc_varname));\n\t\t} else if (res->t == DUK_IVAL_PROP) {\n\t\t\tduk_regconst_t reg_obj;  /* allocate to reg only (not const) */\n\t\t\tduk_regconst_t rc_key;\n\t\t\treg_obj = duk__ispec_toregconst_raw(comp_ctx, &res->x1, -1 /*forced_reg*/, 0 /*flags*/);  /* don't allow const */\n\t\t\trc_key = duk__ispec_toregconst_raw(comp_ctx, &res->x2, -1 /*forced_reg*/, DUK__IVAL_FLAG_ALLOW_CONST /*flags*/);\n\t\t\tduk__emit_a_b_c(comp_ctx,\n\t\t\t                args_op2 | DUK__EMIT_FLAG_BC_REGCONST,  /* e.g. DUK_OP_PREINCP */\n\t\t\t                reg_res,\n\t\t\t                reg_obj,\n\t\t\t                rc_key);\n\t\t} else {\n\t\t\t/* Technically return value is not needed because INVLHS will\n\t\t\t * unconditially throw a ReferenceError.  Coercion is necessary\n\t\t\t * for proper semantics (consider ToNumber() called for an object).\n\t\t\t * Use DUK_OP_UNP with a dummy register to get ToNumber().\n\t\t\t */\n\n\t\t\tduk__ivalue_toforcedreg(comp_ctx, res, reg_res);\n\t\t\tduk__emit_bc(comp_ctx,\n\t\t\t             DUK_OP_UNP,\n\t\t\t             reg_res);  /* for side effects, result ignored */\n\t\t\tduk__emit_op_only(comp_ctx,\n\t\t\t                  DUK_OP_INVLHS);\n\t\t}\n\t\tDUK__SETTEMP(comp_ctx, reg_res + 1);\n\t\tduk__ivalue_regconst(res, reg_res);\n\t\treturn;\n\t}\n\n plain_value:\n\t{\n\t\t/* Stack top contains plain value */\n\t\tduk__ivalue_plain_fromstack(comp_ctx, res);\n\t\treturn;\n\t}\n\n#if defined(DUK_USE_ES6)\n syntax_error_newtarget:\n\tDUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_NEWTARGET);\n#endif\n\n syntax_error:\n\tDUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_EXPRESSION);\n}\n\n/* XXX: add flag to indicate whether caller cares about return value; this\n * affects e.g. handling of assignment expressions.  This change needs API\n * changes elsewhere too.\n */\nDUK_LOCAL void duk__expr_led(duk_compiler_ctx *comp_ctx, duk_ivalue *left, duk_ivalue *res) {\n\tduk_hthread *thr = comp_ctx->thr;\n\tduk_token *tk;\n\tduk_small_uint_t tok;\n\tduk_uint32_t args;  /* temp variable to pass constants and flags to shared code */\n\n\t/*\n\t *  ctx->prev_token     token to process with duk__expr_led()\n\t *  ctx->curr_token     updated by caller\n\t */\n\n\tcomp_ctx->curr_func.led_count++;\n\n\t/* The token in the switch has already been eaten here */\n\ttk = &comp_ctx->prev_token;\n\ttok = tk->t;\n\n\tDUK_DDD(DUK_DDDPRINT(\"duk__expr_led(), prev_token.t=%ld, allow_in=%ld, paren_level=%ld\",\n\t                     (long) tk->t, (long) comp_ctx->curr_func.allow_in, (long) comp_ctx->curr_func.paren_level));\n\n\t/* XXX: default priority for infix operators is duk__expr_lbp(tok) -> get it here? */\n\n\tswitch (tok) {\n\n\t/* PRIMARY EXPRESSIONS */\n\n\tcase DUK_TOK_PERIOD: {\n\t\t/* Property access expressions are critical for correct LHS ordering,\n\t\t * see comments in duk__expr()!\n\t\t *\n\t\t * A conservative approach would be to use duk__ivalue_totempconst()\n\t\t * for 'left'.  However, allowing a reg-bound variable seems safe here\n\t\t * and is nice because \"foo.bar\" is a common expression.  If the ivalue\n\t\t * is used in an expression a GETPROP will occur before any changes to\n\t\t * the base value can occur.  If the ivalue is used as an assignment\n\t\t * LHS, the assignment code will ensure the base value is safe from\n\t\t * RHS mutation.\n\t\t */\n\n\t\t/* XXX: This now coerces an identifier into a GETVAR to a temp, which\n\t\t * causes an extra LDREG in call setup.  It's sufficient to coerce to a\n\t\t * unary ivalue?\n\t\t */\n\t\tduk__ivalue_toplain(comp_ctx, left);\n\n\t\t/* NB: must accept reserved words as property name */\n\t\tif (comp_ctx->curr_token.t_nores != DUK_TOK_IDENTIFIER) {\n\t\t\tDUK_ERROR_SYNTAX(thr, DUK_STR_EXPECTED_IDENTIFIER);\n\t\t}\n\n\t\tres->t = DUK_IVAL_PROP;\n\t\tduk__copy_ispec(comp_ctx, &left->x1, &res->x1);  /* left.x1 -> res.x1 */\n\t\tDUK_ASSERT(comp_ctx->curr_token.str1 != NULL);\n\t\tduk_push_hstring(thr, comp_ctx->curr_token.str1);\n\t\tduk_replace(thr, res->x2.valstack_idx);\n\t\tres->x2.t = DUK_ISPEC_VALUE;\n\n\t\t/* special RegExp literal handling after IdentifierName */\n\t\tcomp_ctx->curr_func.reject_regexp_in_adv = 1;\n\n\t\tduk__advance(comp_ctx);\n\t\treturn;\n\t}\n\tcase DUK_TOK_LBRACKET: {\n\t\t/* Property access expressions are critical for correct LHS ordering,\n\t\t * see comments in duk__expr()!\n\t\t */\n\n\t\t/* XXX: optimize temp reg use */\n\t\t/* XXX: similar coercion issue as in DUK_TOK_PERIOD */\n\t\t/* XXX: coerce to regs? it might be better for enumeration use, where the\n\t\t * same PROP ivalue is used multiple times.  Or perhaps coerce PROP further\n\t\t * there?\n\t\t */\n\t\t/* XXX: for simple cases like x['y'] an unnecessary LDREG is\n\t\t * emitted for the base value; could avoid it if we knew that\n\t\t * the key expression is safe (e.g. just a single literal).\n\t\t */\n\n\t\t/* The 'left' value must not be a register bound variable\n\t\t * because it may be mutated during the rest of the expression\n\t\t * and E5.1 Section 11.2.1 specifies the order of evaluation\n\t\t * so that the base value is evaluated first.\n\t\t * See: test-bug-nested-prop-mutate.js.\n\t\t */\n\t\tduk__ivalue_totempconst(comp_ctx, left);\n\t\tduk__expr_toplain(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);  /* Expression, ']' terminates */\n\t\tduk__advance_expect(comp_ctx, DUK_TOK_RBRACKET);\n\n\t\tres->t = DUK_IVAL_PROP;\n\t\tduk__copy_ispec(comp_ctx, &res->x1, &res->x2);   /* res.x1 -> res.x2 */\n\t\tduk__copy_ispec(comp_ctx, &left->x1, &res->x1);  /* left.x1 -> res.x1 */\n\t\treturn;\n\t}\n\tcase DUK_TOK_LPAREN: {\n\t\t/* function call */\n\t\tduk_regconst_t reg_cs = DUK__ALLOCTEMPS(comp_ctx, 2);\n\t\tduk_int_t nargs;\n\t\tduk_small_uint_t call_op = DUK_OP_CALL0;\n\n\t\t/* XXX: attempt to get the call result to \"next temp\" whenever\n\t\t * possible to avoid unnecessary register shuffles.\n\t\t */\n\n\t\t/*\n\t\t *  Setup call: target and 'this' binding.  Three cases:\n\t\t *\n\t\t *    1. Identifier base (e.g. \"foo()\")\n\t\t *    2. Property base (e.g. \"foo.bar()\")\n\t\t *    3. Register base (e.g. \"foo()()\"; i.e. when a return value is a function)\n\t\t */\n\n\t\tif (left->t == DUK_IVAL_VAR) {\n\t\t\tduk_hstring *h_varname;\n\t\t\tduk_regconst_t reg_varbind;\n\t\t\tduk_regconst_t rc_varname;\n\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"function call with identifier base\"));\n\n\t\t\th_varname = duk_known_hstring(thr, left->x1.valstack_idx);\n\t\t\tif (h_varname == DUK_HTHREAD_STRING_EVAL(thr)) {\n\t\t\t\t/* Potential direct eval call detected, flag the CALL\n\t\t\t\t * so that a run-time \"direct eval\" check is made and\n\t\t\t\t * special behavior may be triggered.  Note that this\n\t\t\t\t * does not prevent 'eval' from being register bound.\n\t\t\t\t */\n\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"function call with identifier 'eval' \"\n\t\t\t\t                     \"-> using EVALCALL, marking function \"\n\t\t\t\t                     \"as may_direct_eval\"));\n\t\t\t\tcall_op |= DUK_BC_CALL_FLAG_CALLED_AS_EVAL;\n\t\t\t\tcomp_ctx->curr_func.may_direct_eval = 1;\n\t\t\t}\n\n\t\t\tduk_dup(thr, left->x1.valstack_idx);\n\t\t\tif (duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname)) {\n\t\t\t\tduk__emit_a_bc(comp_ctx,\n\t\t\t\t              DUK_OP_CSREG | DUK__EMIT_FLAG_A_IS_SOURCE,\n\t\t\t\t              reg_varbind,\n\t\t\t\t              reg_cs + 0);\n\t\t\t} else {\n\t\t\t\t/* XXX: expand target register or constant field to\n\t\t\t\t * reduce shuffling.\n\t\t\t\t */\n\t\t\t\tDUK_ASSERT(DUK__ISCONST(rc_varname));\n\t\t\t\tduk__emit_a_b(comp_ctx,\n\t\t\t\t              DUK_OP_CSVAR | DUK__EMIT_FLAG_BC_REGCONST,\n\t\t\t\t              reg_cs + 0,\n\t\t\t\t              rc_varname);\n\t\t\t}\n\t\t} else if (left->t == DUK_IVAL_PROP) {\n\t\t\t/* Call through a property lookup, E5 Section 11.2.3, step 6.a.i,\n\t\t\t * E5 Section 10.4.3.  There used to be a separate CSPROP opcode\n\t\t\t * but a typical call setup took 3 opcodes (e.g. LDREG, LDCONST,\n\t\t\t * CSPROP) and the same can be achieved with ordinary loads.\n\t\t\t */\n#if defined(DUK_USE_VERBOSE_ERRORS)\n\t\t\tduk_regconst_t reg_key;\n#endif\n\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"function call with property base\"));\n\n\t\t\t/* XXX: For Math.sin() this generates: LDCONST + LDREG +\n\t\t\t * GETPROPC + call.  The LDREG is unnecessary because LDCONST\n\t\t\t * could be loaded directly into reg_cs + 1.  This doesn't\n\t\t\t * happen now because a variable cannot be in left->x1 of a\n\t\t\t * DUK_IVAL_PROP.  We could notice that left->x1 is a temp\n\t\t\t * and reuse, but it would still be in the wrong position\n\t\t\t * (reg_cs + 0 rather than reg_cs + 1).\n\t\t\t */\n\t\t\tduk__ispec_toforcedreg(comp_ctx, &left->x1, reg_cs + 1);  /* base */\n#if defined(DUK_USE_VERBOSE_ERRORS)\n\t\t\treg_key = duk__ispec_toregconst_raw(comp_ctx, &left->x2, -1, DUK__IVAL_FLAG_ALLOW_CONST /*flags*/);\n\t\t\tduk__emit_a_b_c(comp_ctx,\n\t\t\t                DUK_OP_GETPROPC | DUK__EMIT_FLAG_BC_REGCONST,\n\t\t\t                reg_cs + 0,\n\t\t\t                reg_cs + 1,\n\t\t\t                reg_key);\n#else\n\t\t\tduk__ivalue_toforcedreg(comp_ctx, left, reg_cs + 0);  /* base[key] */\n#endif\n\t\t} else {\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"function call with register base\"));\n\n\t\t\tduk__ivalue_toforcedreg(comp_ctx, left, reg_cs + 0);\n#if 0\n\t\t\tduk__emit_a_bc(comp_ctx,\n\t\t\t               DUK_OP_CSREG | DUK__EMIT_FLAG_A_IS_SOURCE,\n\t\t\t               reg_cs + 0,\n\t\t\t               reg_cs + 0);  /* in-place setup */\n#endif\n\t\t\t/* Because of in-place setup, REGCS is equivalent to\n\t\t\t * just this LDUNDEF.\n\t\t\t */\n\t\t\tduk__emit_bc(comp_ctx, DUK_OP_LDUNDEF, reg_cs + 1);\n\t\t}\n\n\t\tDUK__SETTEMP(comp_ctx, reg_cs + 2);\n\t\tnargs = duk__parse_arguments(comp_ctx, res);  /* parse args starting from \"next temp\" */\n\n\t\t/* Tailcalls are handled by back-patching the already emitted opcode\n\t\t * later in return statement parser.\n\t\t */\n\n\t\tduk__emit_a_bc(comp_ctx,\n\t\t               call_op,\n\t\t               (duk_regconst_t) nargs /*numargs*/,\n\t\t               reg_cs /*basereg*/);\n\t\tDUK__SETTEMP(comp_ctx, reg_cs + 1);    /* result in csreg */\n\n\t\tduk__ivalue_regconst(res, reg_cs);\n\t\treturn;\n\t}\n\n\t/* POSTFIX EXPRESSION */\n\n\tcase DUK_TOK_INCREMENT: {\n\t\targs = (DUK_OP_POSTINCP_RR << 16) + (DUK_OP_POSTINCR << 8) + 0;\n\t\tgoto postincdec;\n\t}\n\tcase DUK_TOK_DECREMENT: {\n\t\targs = (DUK_OP_POSTDECP_RR << 16) + (DUK_OP_POSTDECR << 8) + 0;\n\t\tgoto postincdec;\n\t}\n\n\t/* EXPONENTIATION EXPRESSION */\n\n#if defined(DUK_USE_ES7_EXP_OPERATOR)\n\tcase DUK_TOK_EXP: {\n\t\targs = (DUK_OP_EXP << 8) + DUK__BP_EXPONENTIATION - 1;  /* UnaryExpression */\n\t\tgoto binary;\n\t}\n#endif\n\n\t/* MULTIPLICATIVE EXPRESSION */\n\n\tcase DUK_TOK_MUL: {\n\t\targs = (DUK_OP_MUL << 8) + DUK__BP_MULTIPLICATIVE;  /* ExponentiationExpression */\n\t\tgoto binary;\n\t}\n\tcase DUK_TOK_DIV: {\n\t\targs = (DUK_OP_DIV << 8) + DUK__BP_MULTIPLICATIVE;  /* ExponentiationExpression */\n\t\tgoto binary;\n\t}\n\tcase DUK_TOK_MOD: {\n\t\targs = (DUK_OP_MOD << 8) + DUK__BP_MULTIPLICATIVE;  /* ExponentiationExpression */\n\t\tgoto binary;\n\t}\n\n\t/* ADDITIVE EXPRESSION */\n\n\tcase DUK_TOK_ADD: {\n\t\targs = (DUK_OP_ADD << 8) + DUK__BP_ADDITIVE;  /* MultiplicativeExpression */\n\t\tgoto binary;\n\t}\n\tcase DUK_TOK_SUB: {\n\t\targs = (DUK_OP_SUB << 8) + DUK__BP_ADDITIVE;  /* MultiplicativeExpression */\n\t\tgoto binary;\n\t}\n\n\t/* SHIFT EXPRESSION */\n\n\tcase DUK_TOK_ALSHIFT: {\n\t\t/* << */\n\t\targs = (DUK_OP_BASL << 8) + DUK__BP_SHIFT;\n\t\tgoto binary;\n\t}\n\tcase DUK_TOK_ARSHIFT: {\n\t\t/* >> */\n\t\targs = (DUK_OP_BASR << 8) + DUK__BP_SHIFT;\n\t\tgoto binary;\n\t}\n\tcase DUK_TOK_RSHIFT: {\n\t\t/* >>> */\n\t\targs = (DUK_OP_BLSR << 8) + DUK__BP_SHIFT;\n\t\tgoto binary;\n\t}\n\n\t/* RELATIONAL EXPRESSION */\n\n\tcase DUK_TOK_LT: {\n\t\t/* < */\n\t\targs = (DUK_OP_LT << 8) + DUK__BP_RELATIONAL;\n\t\tgoto binary;\n\t}\n\tcase DUK_TOK_GT: {\n\t\targs = (DUK_OP_GT << 8) + DUK__BP_RELATIONAL;\n\t\tgoto binary;\n\t}\n\tcase DUK_TOK_LE: {\n\t\targs = (DUK_OP_LE << 8) + DUK__BP_RELATIONAL;\n\t\tgoto binary;\n\t}\n\tcase DUK_TOK_GE: {\n\t\targs = (DUK_OP_GE << 8) + DUK__BP_RELATIONAL;\n\t\tgoto binary;\n\t}\n\tcase DUK_TOK_INSTANCEOF: {\n\t\targs = (DUK_OP_INSTOF << 8) + DUK__BP_RELATIONAL;\n\t\tgoto binary;\n\t}\n\tcase DUK_TOK_IN: {\n\t\targs = (DUK_OP_IN << 8) + DUK__BP_RELATIONAL;\n\t\tgoto binary;\n\t}\n\n\t/* EQUALITY EXPRESSION */\n\n\tcase DUK_TOK_EQ: {\n\t\targs = (DUK_OP_EQ << 8) + DUK__BP_EQUALITY;\n\t\tgoto binary;\n\t}\n\tcase DUK_TOK_NEQ: {\n\t\targs = (DUK_OP_NEQ << 8) + DUK__BP_EQUALITY;\n\t\tgoto binary;\n\t}\n\tcase DUK_TOK_SEQ: {\n\t\targs = (DUK_OP_SEQ << 8) + DUK__BP_EQUALITY;\n\t\tgoto binary;\n\t}\n\tcase DUK_TOK_SNEQ: {\n\t\targs = (DUK_OP_SNEQ << 8) + DUK__BP_EQUALITY;\n\t\tgoto binary;\n\t}\n\n\t/* BITWISE EXPRESSIONS */\n\n\tcase DUK_TOK_BAND: {\n\t\targs = (DUK_OP_BAND << 8) + DUK__BP_BAND;\n\t\tgoto binary;\n\t}\n\tcase DUK_TOK_BXOR: {\n\t\targs = (DUK_OP_BXOR << 8) + DUK__BP_BXOR;\n\t\tgoto binary;\n\t}\n\tcase DUK_TOK_BOR: {\n\t\targs = (DUK_OP_BOR << 8) + DUK__BP_BOR;\n\t\tgoto binary;\n\t}\n\n\t/* LOGICAL EXPRESSIONS */\n\n\tcase DUK_TOK_LAND: {\n\t\t/* syntactically left-associative but parsed as right-associative */\n\t\targs = (1 << 8) + DUK__BP_LAND - 1;\n\t\tgoto binary_logical;\n\t}\n\tcase DUK_TOK_LOR: {\n\t\t/* syntactically left-associative but parsed as right-associative */\n\t\targs = (0 << 8) + DUK__BP_LOR - 1;\n\t\tgoto binary_logical;\n\t}\n\n\t/* CONDITIONAL EXPRESSION */\n\n\tcase DUK_TOK_QUESTION: {\n\t\t/* XXX: common reg allocation need is to reuse a sub-expression's temp reg,\n\t\t * but only if it really is a temp.  Nothing fancy here now.\n\t\t */\n\t\tduk_regconst_t reg_temp;\n\t\tduk_int_t pc_jump1;\n\t\tduk_int_t pc_jump2;\n\n\t\treg_temp = DUK__ALLOCTEMP(comp_ctx);\n\t\tduk__ivalue_toforcedreg(comp_ctx, left, reg_temp);\n\t\tduk__emit_if_true_skip(comp_ctx, reg_temp);\n\t\tpc_jump1 = duk__emit_jump_empty(comp_ctx);  /* jump to false */\n\t\tduk__expr_toforcedreg(comp_ctx, res, DUK__BP_COMMA /*rbp_flags*/, reg_temp /*forced_reg*/);  /* AssignmentExpression */\n\t\tduk__advance_expect(comp_ctx, DUK_TOK_COLON);\n\t\tpc_jump2 = duk__emit_jump_empty(comp_ctx);  /* jump to end */\n\t\tduk__patch_jump_here(comp_ctx, pc_jump1);\n\t\tduk__expr_toforcedreg(comp_ctx, res, DUK__BP_COMMA /*rbp_flags*/, reg_temp /*forced_reg*/);  /* AssignmentExpression */\n\t\tduk__patch_jump_here(comp_ctx, pc_jump2);\n\n\t\tDUK__SETTEMP(comp_ctx, reg_temp + 1);\n\t\tduk__ivalue_regconst(res, reg_temp);\n\t\treturn;\n\t}\n\n\t/* ASSIGNMENT EXPRESSION */\n\n\tcase DUK_TOK_EQUALSIGN: {\n\t\t/*\n\t\t *  Assignments are right associative, allows e.g.\n\t\t *    a = 5;\n\t\t *    a += b = 9;   // same as a += (b = 9)\n\t\t *  -> expression value 14, a = 14, b = 9\n\t\t *\n\t\t *  Right associativiness is reflected in the BP for recursion,\n\t\t *  \"-1\" ensures assignment operations are allowed.\n\t\t *\n\t\t *  XXX: just use DUK__BP_COMMA (i.e. no need for 2-step bp levels)?\n\t\t */\n\t\targs = (DUK_OP_NONE << 8) + DUK__BP_ASSIGNMENT - 1;   /* DUK_OP_NONE marks a 'plain' assignment */\n\t\tgoto assign;\n\t}\n\tcase DUK_TOK_ADD_EQ: {\n\t\t/* right associative */\n\t\targs = (DUK_OP_ADD << 8) + DUK__BP_ASSIGNMENT - 1;\n\t\tgoto assign;\n\t}\n\tcase DUK_TOK_SUB_EQ: {\n\t\t/* right associative */\n\t\targs = (DUK_OP_SUB << 8) + DUK__BP_ASSIGNMENT - 1;\n\t\tgoto assign;\n\t}\n\tcase DUK_TOK_MUL_EQ: {\n\t\t/* right associative */\n\t\targs = (DUK_OP_MUL << 8) + DUK__BP_ASSIGNMENT - 1;\n\t\tgoto assign;\n\t}\n\tcase DUK_TOK_DIV_EQ: {\n\t\t/* right associative */\n\t\targs = (DUK_OP_DIV << 8) + DUK__BP_ASSIGNMENT - 1;\n\t\tgoto assign;\n\t}\n\tcase DUK_TOK_MOD_EQ: {\n\t\t/* right associative */\n\t\targs = (DUK_OP_MOD << 8) + DUK__BP_ASSIGNMENT - 1;\n\t\tgoto assign;\n\t}\n#if defined(DUK_USE_ES7_EXP_OPERATOR)\n\tcase DUK_TOK_EXP_EQ: {\n\t\t/* right associative */\n\t\targs = (DUK_OP_EXP << 8) + DUK__BP_ASSIGNMENT - 1;\n\t\tgoto assign;\n\t}\n#endif\n\tcase DUK_TOK_ALSHIFT_EQ: {\n\t\t/* right associative */\n\t\targs = (DUK_OP_BASL << 8) + DUK__BP_ASSIGNMENT - 1;\n\t\tgoto assign;\n\t}\n\tcase DUK_TOK_ARSHIFT_EQ: {\n\t\t/* right associative */\n\t\targs = (DUK_OP_BASR << 8) + DUK__BP_ASSIGNMENT - 1;\n\t\tgoto assign;\n\t}\n\tcase DUK_TOK_RSHIFT_EQ: {\n\t\t/* right associative */\n\t\targs = (DUK_OP_BLSR << 8) + DUK__BP_ASSIGNMENT - 1;\n\t\tgoto assign;\n\t}\n\tcase DUK_TOK_BAND_EQ: {\n\t\t/* right associative */\n\t\targs = (DUK_OP_BAND << 8) + DUK__BP_ASSIGNMENT - 1;\n\t\tgoto assign;\n\t}\n\tcase DUK_TOK_BOR_EQ: {\n\t\t/* right associative */\n\t\targs = (DUK_OP_BOR << 8) + DUK__BP_ASSIGNMENT - 1;\n\t\tgoto assign;\n\t}\n\tcase DUK_TOK_BXOR_EQ: {\n\t\t/* right associative */\n\t\targs = (DUK_OP_BXOR << 8) + DUK__BP_ASSIGNMENT - 1;\n\t\tgoto assign;\n\t}\n\n\t/* COMMA */\n\n\tcase DUK_TOK_COMMA: {\n\t\t/* right associative */\n\n\t\tduk__ivalue_toplain_ignore(comp_ctx, left);  /* need side effects, not value */\n\t\tduk__expr_toplain(comp_ctx, res, DUK__BP_COMMA - 1 /*rbp_flags*/);\n\n\t\t/* return 'res' (of right part) as our result */\n\t\treturn;\n\t}\n\n\tdefault: {\n\t\tbreak;\n\t}\n\t}\n\n\tDUK_D(DUK_DPRINT(\"parse error: unexpected token: %ld\", (long) tok));\n\tDUK_ERROR_SYNTAX(thr, DUK_STR_PARSE_ERROR);\n\treturn;\n\n#if 0\n\t/* XXX: shared handling for 'duk__expr_lhs'? */\n\tif (comp_ctx->curr_func.paren_level == 0 && XXX) {\n\t\tcomp_ctx->curr_func.duk__expr_lhs = 0;\n\t}\n#endif\n\n binary:\n\t/*\n\t *  Shared handling of binary operations\n\t *\n\t *  args = (opcode << 8) + rbp\n\t */\n\t{\n\t\tduk__ivalue_toplain(comp_ctx, left);\n\t\tduk__expr_toplain(comp_ctx, res, args & 0xff /*rbp_flags*/);\n\n\t\t/* combine left->x1 and res->x1 (right->x1, really) -> (left->x1 OP res->x1) */\n\t\tDUK_ASSERT(left->t == DUK_IVAL_PLAIN);\n\t\tDUK_ASSERT(res->t == DUK_IVAL_PLAIN);\n\n\t\tres->t = DUK_IVAL_ARITH;\n\t\tres->op = (args >> 8) & 0xff;\n\n\t\tres->x2.t = res->x1.t;\n\t\tres->x2.regconst = res->x1.regconst;\n\t\tduk_copy(thr, res->x1.valstack_idx, res->x2.valstack_idx);\n\n\t\tres->x1.t = left->x1.t;\n\t\tres->x1.regconst = left->x1.regconst;\n\t\tduk_copy(thr, left->x1.valstack_idx, res->x1.valstack_idx);\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"binary op, res: t=%ld, x1.t=%ld, x1.regconst=0x%08lx, x2.t=%ld, x2.regconst=0x%08lx\",\n\t\t                     (long) res->t, (long) res->x1.t, (unsigned long) res->x1.regconst, (long) res->x2.t, (unsigned long) res->x2.regconst));\n\t\treturn;\n\t}\n\n binary_logical:\n\t/*\n\t *  Shared handling for logical AND and logical OR.\n\t *\n\t *  args = (truthval << 8) + rbp\n\t *\n\t *  Truthval determines when to skip right-hand-side.\n\t *  For logical AND truthval=1, for logical OR truthval=0.\n\t *\n\t *  See doc/compiler.rst for discussion on compiling logical\n\t *  AND and OR expressions.  The approach here is very simplistic,\n\t *  generating extra jumps and multiple evaluations of truth values,\n\t *  but generates code on-the-fly with only local back-patching.\n\t *\n\t *  Both logical AND and OR are syntactically left-associated.\n\t *  However, logical ANDs are compiled as right associative\n\t *  expressions, i.e. \"A && B && C\" as \"A && (B && C)\", to allow\n\t *  skip jumps to skip over the entire tail.  Similarly for logical OR.\n\t */\n\n\t{\n\t\tduk_regconst_t reg_temp;\n\t\tduk_int_t pc_jump;\n\t\tduk_small_uint_t args_truthval = args >> 8;\n\t\tduk_small_uint_t args_rbp = args & 0xff;\n\n\t\t/* XXX: unoptimal use of temps, resetting */\n\n\t\treg_temp = DUK__ALLOCTEMP(comp_ctx);\n\n\t\tduk__ivalue_toforcedreg(comp_ctx, left, reg_temp);\n\t\tDUK_ASSERT(DUK__ISREG(reg_temp));\n\t\tduk__emit_bc(comp_ctx,\n\t\t            (args_truthval ? DUK_OP_IFTRUE_R : DUK_OP_IFFALSE_R),\n\t\t            reg_temp);  /* skip jump conditionally */\n\t\tpc_jump = duk__emit_jump_empty(comp_ctx);\n\t\tduk__expr_toforcedreg(comp_ctx, res, args_rbp /*rbp_flags*/, reg_temp /*forced_reg*/);\n\t\tduk__patch_jump_here(comp_ctx, pc_jump);\n\n\t\tduk__ivalue_regconst(res, reg_temp);\n\t\treturn;\n\t}\n\n assign:\n\t/*\n\t *  Shared assignment expression handling\n\t *\n\t *  args = (opcode << 8) + rbp\n\t *\n\t *  If 'opcode' is DUK_OP_NONE, plain assignment without arithmetic.\n\t *  Syntactically valid left-hand-side forms which are not accepted as\n\t *  left-hand-side values (e.g. as in \"f() = 1\") must NOT cause a\n\t *  SyntaxError, but rather a run-time ReferenceError.\n\t *\n\t *  When evaluating X <op>= Y, the LHS (X) is conceptually evaluated\n\t *  to a temporary first.  The RHS is then evaluated.  Finally, the\n\t *  <op> is applied to the initial value of RHS (not the value after\n\t *  RHS evaluation), and written to X.  Doing so concretely generates\n\t *  inefficient code so we'd like to avoid the temporary when possible.\n\t *  See: https://github.com/svaarala/duktape/pull/992.\n\t *\n\t *  The expression value (final LHS value, written to RHS) is\n\t *  conceptually copied into a fresh temporary so that it won't\n\t *  change even if the LHS/RHS values change in outer expressions.\n\t *  For example, it'd be generally incorrect for the expression value\n\t *  to be the RHS register binding, unless there's a guarantee that it\n\t *  won't change during further expression evaluation.  Using the\n\t *  temporary concretely produces inefficient bytecode, so we try to\n\t *  avoid the extra temporary for some known-to-be-safe cases.\n\t *  Currently the only safe case we detect is a \"top level assignment\",\n\t *  for example \"x = y + z;\", where the assignment expression value is\n\t *  ignored.\n\t *  See: test-dev-assign-expr.js and test-bug-assign-mutate-gh381.js.\n\t */\n\n\t{\n\t\tduk_small_uint_t args_op = args >> 8;\n\t\tduk_small_uint_t args_rbp = args & 0xff;\n\t\tduk_bool_t toplevel_assign;\n\n\t\t/* XXX: here we need to know if 'left' is left-hand-side compatible.\n\t\t * That information is no longer available from current expr parsing\n\t\t * state; it would need to be carried into the 'left' ivalue or by\n\t\t * some other means.\n\t\t */\n\n\t\t/* A top-level assignment is e.g. \"x = y;\".  For these it's safe\n\t\t * to use the RHS as-is as the expression value, even if the RHS\n\t\t * is a reg-bound identifier.  The RHS ('res') is right associative\n\t\t * so it has consumed all other assignment level operations; the\n\t\t * only relevant lower binding power construct is comma operator\n\t\t * which will ignore the expression value provided here.  Usually\n\t\t * the top level assignment expression value is ignored, but it\n\t\t * is relevant for e.g. eval code.\n\t\t */\n\t\ttoplevel_assign = (comp_ctx->curr_func.nud_count == 1 && /* one token before */\n\t\t                   comp_ctx->curr_func.led_count == 1);  /* one operator (= assign) */\n\t\tDUK_DDD(DUK_DDDPRINT(\"assignment: nud_count=%ld, led_count=%ld, toplevel_assign=%ld\",\n\t\t                     (long) comp_ctx->curr_func.nud_count,\n\t\t                     (long) comp_ctx->curr_func.led_count,\n\t\t                     (long) toplevel_assign));\n\n\t\tif (left->t == DUK_IVAL_VAR) {\n\t\t\tduk_hstring *h_varname;\n\t\t\tduk_regconst_t reg_varbind;\n\t\t\tduk_regconst_t rc_varname;\n\n\t\t\tDUK_ASSERT(left->x1.t == DUK_ISPEC_VALUE);  /* LHS is already side effect free */\n\n\t\t\th_varname = duk_known_hstring(thr, left->x1.valstack_idx);\n\t\t\tif (duk__hstring_is_eval_or_arguments_in_strict_mode(comp_ctx, h_varname)) {\n\t\t\t\t/* E5 Section 11.13.1 (and others for other assignments), step 4. */\n\t\t\t\tgoto syntax_error_lvalue;\n\t\t\t}\n\t\t\tduk_dup(thr, left->x1.valstack_idx);\n\t\t\t(void) duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname);\n\n\t\t\tif (args_op == DUK_OP_NONE) {\n\t\t\t\tduk__expr(comp_ctx, res, args_rbp /*rbp_flags*/);\n\t\t\t\tif (toplevel_assign) {\n\t\t\t\t\t/* Any 'res' will do. */\n\t\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"plain assignment, toplevel assign, use as is\"));\n\t\t\t\t} else {\n\t\t\t\t\t/* 'res' must be a plain ivalue, and not register-bound variable. */\n\t\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"plain assignment, not toplevel assign, ensure not a reg-bound identifier\"));\n\t\t\t\t\tif (res->t != DUK_IVAL_PLAIN || (res->x1.t == DUK_ISPEC_REGCONST &&\n\t\t\t\t\t                                 DUK__ISREG_NOTTEMP(comp_ctx, res->x1.regconst))) {\n\t\t\t\t\t\tduk__ivalue_totempconst(comp_ctx, res);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t/* For X <op>= Y we need to evaluate the pre-op\n\t\t\t\t * value of X before evaluating the RHS: the RHS\n\t\t\t\t * can change X, but when we do <op> we must use\n\t\t\t\t * the pre-op value.\n\t\t\t\t */\n\t\t\t\tduk_regconst_t reg_temp;\n\n\t\t\t\treg_temp = DUK__ALLOCTEMP(comp_ctx);\n\n\t\t\t\tif (reg_varbind >= 0) {\n\t\t\t\t\tduk_regconst_t reg_res;\n\t\t\t\t\tduk_regconst_t reg_src;\n\t\t\t\t\tduk_int_t pc_temp_load;\n\t\t\t\t\tduk_int_t pc_before_rhs;\n\t\t\t\t\tduk_int_t pc_after_rhs;\n\n\t\t\t\t\tif (toplevel_assign) {\n\t\t\t\t\t\t/* 'reg_varbind' is the operation result and can also\n\t\t\t\t\t\t * become the expression value for top level assignments\n\t\t\t\t\t\t * such as: \"var x; x += y;\".\n\t\t\t\t\t\t */\n\t\t\t\t\t\tDUK_DD(DUK_DDPRINT(\"<op>= expression is top level, write directly to reg_varbind\"));\n\t\t\t\t\t\treg_res = reg_varbind;\n\t\t\t\t\t} else {\n\t\t\t\t\t\t/* Not safe to use 'reg_varbind' as assignment expression\n\t\t\t\t\t\t * value, so go through a temp.\n\t\t\t\t\t\t */\n\t\t\t\t\t\tDUK_DD(DUK_DDPRINT(\"<op>= expression is not top level, write to reg_temp\"));\n\t\t\t\t\t\treg_res = reg_temp;  /* reg_res should be smallest possible */\n\t\t\t\t\t\treg_temp = DUK__ALLOCTEMP(comp_ctx);\n\t\t\t\t\t}\n\n\t\t\t\t\t/* Try to optimize X <op>= Y for reg-bound\n\t\t\t\t\t * variables.  Detect side-effect free RHS\n\t\t\t\t\t * narrowly by seeing whether it emits code.\n\t\t\t\t\t * If not, rewind the code emitter and overwrite\n\t\t\t\t\t * the unnecessary temp reg load.\n\t\t\t\t\t */\n\n\t\t\t\t\tpc_temp_load = duk__get_current_pc(comp_ctx);\n\t\t\t\t\tduk__emit_a_bc(comp_ctx,\n\t\t\t\t\t               DUK_OP_LDREG,\n\t\t\t\t\t               reg_temp,\n\t\t\t\t\t               reg_varbind);\n\n\t\t\t\t\tpc_before_rhs = duk__get_current_pc(comp_ctx);\n\t\t\t\t\tduk__expr_toregconst(comp_ctx, res, args_rbp /*rbp_flags*/);\n\t\t\t\t\tDUK_ASSERT(res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_REGCONST);\n\t\t\t\t\tpc_after_rhs = duk__get_current_pc(comp_ctx);\n\n\t\t\t\t\tDUK_DD(DUK_DDPRINT(\"pc_temp_load=%ld, pc_before_rhs=%ld, pc_after_rhs=%ld\",\n\t\t\t\t\t                   (long) pc_temp_load, (long) pc_before_rhs,\n\t\t\t\t\t                   (long) pc_after_rhs));\n\n\t\t\t\t\tif (pc_after_rhs == pc_before_rhs) {\n\t\t\t\t\t\t/* Note: if the reg_temp load generated shuffling\n\t\t\t\t\t\t * instructions, we may need to rewind more than\n\t\t\t\t\t\t * one instruction, so use explicit PC computation.\n\t\t\t\t\t\t */\n\t\t\t\t\t\tDUK_DD(DUK_DDPRINT(\"rhs is side effect free, rewind and avoid unnecessary temp for reg-based <op>=\"));\n\t\t\t\t\t\tDUK_BW_ADD_PTR(comp_ctx->thr, &comp_ctx->curr_func.bw_code, (duk_size_t) (pc_temp_load - pc_before_rhs) * sizeof(duk_compiler_instr));\n\t\t\t\t\t\treg_src = reg_varbind;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tDUK_DD(DUK_DDPRINT(\"rhs evaluation emitted code, not sure if rhs is side effect free; use temp reg for LHS\"));\n\t\t\t\t\t\treg_src = reg_temp;\n\t\t\t\t\t}\n\n\t\t\t\t\tduk__emit_a_b_c(comp_ctx,\n\t\t\t\t\t                args_op | DUK__EMIT_FLAG_BC_REGCONST,\n\t\t\t\t\t                reg_res,\n\t\t\t\t\t                reg_src,\n\t\t\t\t\t                res->x1.regconst);\n\n\t\t\t\t\tres->x1.regconst = reg_res;\n\n\t\t\t\t\t/* Ensure compact use of temps. */\n\t\t\t\t\tif (DUK__ISREG_TEMP(comp_ctx, reg_res)) {\n\t\t\t\t\t\tDUK__SETTEMP(comp_ctx, reg_res + 1);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t/* When LHS is not register bound, always go through a\n\t\t\t\t\t * temporary.  No optimization for top level assignment.\n\t\t\t\t\t */\n\n\t\t\t\t\tduk__emit_a_bc(comp_ctx,\n\t\t\t\t\t               DUK_OP_GETVAR,\n\t\t\t\t\t               reg_temp,\n\t\t\t\t\t               rc_varname);\n\n\t\t\t\t\tduk__expr_toregconst(comp_ctx, res, args_rbp /*rbp_flags*/);\n\t\t\t\t\tDUK_ASSERT(res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_REGCONST);\n\n\t\t\t\t\tduk__emit_a_b_c(comp_ctx,\n\t\t\t\t\t                args_op | DUK__EMIT_FLAG_BC_REGCONST,\n\t\t\t\t\t                reg_temp,\n\t\t\t\t\t                reg_temp,\n\t\t\t\t\t                res->x1.regconst);\n\t\t\t\t\tres->x1.regconst = reg_temp;\n\t\t\t\t}\n\n\t\t\t\tDUK_ASSERT(res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_REGCONST);\n\t\t\t}\n\n\t\t\t/* At this point 'res' holds the potential expression value.\n\t\t\t * It can be basically any ivalue here, including a reg-bound\n\t\t\t * identifier (if code above deems it safe) or a unary/binary\n\t\t\t * operation.  Operations must be resolved to a side effect free\n\t\t\t * plain value, and the side effects must happen exactly once.\n\t\t\t */\n\n\t\t\tif (reg_varbind >= 0) {\n\t\t\t\tif (res->t != DUK_IVAL_PLAIN) {\n\t\t\t\t\t/* Resolve 'res' directly into the LHS binding, and use\n\t\t\t\t\t * that as the expression value if safe.  If not safe,\n\t\t\t\t\t * resolve to a temp/const and copy to LHS.\n\t\t\t\t\t */\n\t\t\t\t\tif (toplevel_assign) {\n\t\t\t\t\t\tduk__ivalue_toforcedreg(comp_ctx, res, (duk_int_t) reg_varbind);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tduk__ivalue_totempconst(comp_ctx, res);\n\t\t\t\t\t\tduk__copy_ivalue(comp_ctx, res, left);  /* use 'left' as a temp */\n\t\t\t\t\t\tduk__ivalue_toforcedreg(comp_ctx, left, (duk_int_t) reg_varbind);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t/* Use 'res' as the expression value (it's side effect\n\t\t\t\t\t * free and may be a plain value, a register, or a\n\t\t\t\t\t * constant) and write it to the LHS binding too.\n\t\t\t\t\t */\n\t\t\t\t\tduk__copy_ivalue(comp_ctx, res, left);  /* use 'left' as a temp */\n\t\t\t\t\tduk__ivalue_toforcedreg(comp_ctx, left, (duk_int_t) reg_varbind);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t/* Only a reg fits into 'A' so coerce 'res' into a register\n\t\t\t\t * for PUTVAR.\n\t\t\t\t *\n\t\t\t\t * XXX: here the current A/B/C split is suboptimal: we could\n\t\t\t\t * just use 9 bits for reg_res (and support constants) and 17\n\t\t\t\t * instead of 18 bits for the varname const index.\n\t\t\t\t */\n\n\t\t\t\tduk__ivalue_toreg(comp_ctx, res);\n\t\t\t\tduk__emit_a_bc(comp_ctx,\n\t\t\t\t               DUK_OP_PUTVAR | DUK__EMIT_FLAG_A_IS_SOURCE,\n\t\t\t\t               res->x1.regconst,\n\t\t\t\t               rc_varname);\n\t\t\t}\n\n\t\t\t/* 'res' contains expression value */\n\t\t} else if (left->t == DUK_IVAL_PROP) {\n\t\t\t/* E5 Section 11.13.1 (and others) step 4 never matches for prop writes -> no check */\n\t\t\tduk_regconst_t reg_obj;\n\t\t\tduk_regconst_t rc_key;\n\t\t\tduk_regconst_t rc_res;\n\t\t\tduk_regconst_t reg_temp;\n\n\t\t\t/* Property access expressions ('a[b]') are critical to correct\n\t\t\t * LHS evaluation ordering, see test-dev-assign-eval-order*.js.\n\t\t\t * We must make sure that the LHS target slot (base object and\n\t\t\t * key) don't change during RHS evaluation.  The only concrete\n\t\t\t * problem is a register reference to a variable-bound register\n\t\t\t * (i.e., non-temp).  Require temp regs for both key and base.\n\t\t\t *\n\t\t\t * Don't allow a constant for the object (even for a number\n\t\t\t * etc), as it goes into the 'A' field of the opcode.\n\t\t\t */\n\n\t\t\treg_obj = duk__ispec_toregconst_raw(comp_ctx,\n\t\t\t                                    &left->x1,\n\t\t\t                                    -1 /*forced_reg*/,\n\t\t\t                                    DUK__IVAL_FLAG_REQUIRE_TEMP /*flags*/);\n\n\t\t\trc_key = duk__ispec_toregconst_raw(comp_ctx,\n\t\t\t                                   &left->x2,\n\t\t\t                                   -1 /*forced_reg*/,\n\t\t\t                                   DUK__IVAL_FLAG_REQUIRE_TEMP | DUK__IVAL_FLAG_ALLOW_CONST /*flags*/);\n\n\t\t\t/* Evaluate RHS only when LHS is safe. */\n\n\t\t\tif (args_op == DUK_OP_NONE) {\n\t\t\t\tduk__expr_toregconst(comp_ctx, res, args_rbp /*rbp_flags*/);\n\t\t\t\tDUK_ASSERT(res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_REGCONST);\n\t\t\t\trc_res = res->x1.regconst;\n\t\t\t} else {\n\t\t\t\treg_temp = DUK__ALLOCTEMP(comp_ctx);\n\t\t\t\tduk__emit_a_b_c(comp_ctx,\n\t\t\t\t                DUK_OP_GETPROP | DUK__EMIT_FLAG_BC_REGCONST,\n\t\t\t\t                reg_temp,\n\t\t\t\t                reg_obj,\n\t\t\t\t                rc_key);\n\n\t\t\t\tduk__expr_toregconst(comp_ctx, res, args_rbp /*rbp_flags*/);\n\t\t\t\tDUK_ASSERT(res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_REGCONST);\n\n\t\t\t\tduk__emit_a_b_c(comp_ctx,\n\t\t\t\t                args_op | DUK__EMIT_FLAG_BC_REGCONST,\n\t\t\t\t                reg_temp,\n\t\t\t\t                reg_temp,\n\t\t\t\t                res->x1.regconst);\n\t\t\t\trc_res = reg_temp;\n\t\t\t}\n\n\t\t\tduk__emit_a_b_c(comp_ctx,\n\t\t\t                DUK_OP_PUTPROP | DUK__EMIT_FLAG_A_IS_SOURCE | DUK__EMIT_FLAG_BC_REGCONST,\n\t\t\t                reg_obj,\n\t\t\t                rc_key,\n\t\t\t                rc_res);\n\n\t\t\tduk__ivalue_regconst(res, rc_res);\n\t\t} else {\n\t\t\t/* No support for lvalues returned from new or function call expressions.\n\t\t\t * However, these must NOT cause compile-time SyntaxErrors, but run-time\n\t\t\t * ReferenceErrors.  Both left and right sides of the assignment must be\n\t\t\t * evaluated before throwing a ReferenceError.  For instance:\n\t\t\t *\n\t\t\t *     f() = g();\n\t\t\t *\n\t\t\t * must result in f() being evaluated, then g() being evaluated, and\n\t\t\t * finally, a ReferenceError being thrown.  See E5 Section 11.13.1.\n\t\t\t */\n\n\t\t\tduk_regconst_t rc_res;\n\n\t\t\t/* First evaluate LHS fully to ensure all side effects are out. */\n\t\t\tduk__ivalue_toplain_ignore(comp_ctx, left);\n\n\t\t\t/* Then evaluate RHS fully (its value becomes the expression value too).\n\t\t\t * Technically we'd need the side effect safety check here too, but because\n\t\t\t * we always throw using INVLHS the result doesn't matter.\n\t\t\t */\n\t\t\trc_res = duk__expr_toregconst(comp_ctx, res, args_rbp /*rbp_flags*/);\n\n\t\t\tduk__emit_op_only(comp_ctx, DUK_OP_INVLHS);\n\n\t\t\tduk__ivalue_regconst(res, rc_res);\n\t\t}\n\n\t\treturn;\n\t}\n\n postincdec:\n\t{\n\t\t/*\n\t\t *  Post-increment/decrement will return the original value as its\n\t\t *  result value.  However, even that value will be coerced using\n\t\t *  ToNumber() which is quite awkward.  Specific bytecode opcodes\n\t\t *  are used to handle these semantics.\n\t\t *\n\t\t *  Note that post increment/decrement has a \"no LineTerminator here\"\n\t\t *  restriction.  This is handled by duk__expr_lbp(), which forcibly terminates\n\t\t *  the previous expression if a LineTerminator occurs before '++'/'--'.\n\t\t */\n\n\t\tduk_regconst_t reg_res;\n\t\tduk_small_uint_t args_op1 = (args >> 8) & 0xff;  /* DUK_OP_POSTINCR/DUK_OP_POSTDECR */\n\t\tduk_small_uint_t args_op2 = args >> 16;          /* DUK_OP_POSTINCP_RR/DUK_OP_POSTDECP_RR */\n\n\t\t/* Specific assumptions for opcode numbering. */\n\t\tDUK_ASSERT(DUK_OP_POSTINCR + 4 == DUK_OP_POSTINCV);\n\t\tDUK_ASSERT(DUK_OP_POSTDECR + 4 == DUK_OP_POSTDECV);\n\n\t\treg_res = DUK__ALLOCTEMP(comp_ctx);\n\n\t\tif (left->t == DUK_IVAL_VAR) {\n\t\t\tduk_hstring *h_varname;\n\t\t\tduk_regconst_t reg_varbind;\n\t\t\tduk_regconst_t rc_varname;\n\n\t\t\th_varname = duk_known_hstring(thr, left->x1.valstack_idx);\n\n\t\t\tif (duk__hstring_is_eval_or_arguments_in_strict_mode(comp_ctx, h_varname)) {\n\t\t\t\tgoto syntax_error;\n\t\t\t}\n\n\t\t\tduk_dup(thr, left->x1.valstack_idx);\n\t\t\tif (duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname)) {\n\t\t\t\tduk__emit_a_bc(comp_ctx,\n\t\t\t\t               args_op1,  /* e.g. DUK_OP_POSTINCR */\n\t\t\t\t               reg_res,\n\t\t\t\t               reg_varbind);\n\t\t\t} else {\n\t\t\t\tduk__emit_a_bc(comp_ctx,\n\t\t\t\t               args_op1 + 4,  /* e.g. DUK_OP_POSTINCV */\n\t\t\t\t               reg_res,\n\t\t\t\t               rc_varname);\n\t\t\t}\n\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"postincdec to '%!O' -> reg_varbind=%ld, rc_varname=%ld\",\n\t\t\t                     (duk_heaphdr *) h_varname, (long) reg_varbind, (long) rc_varname));\n\t\t} else if (left->t == DUK_IVAL_PROP) {\n\t\t\tduk_regconst_t reg_obj;  /* allocate to reg only (not const) */\n\t\t\tduk_regconst_t rc_key;\n\n\t\t\treg_obj = duk__ispec_toregconst_raw(comp_ctx, &left->x1, -1 /*forced_reg*/, 0 /*flags*/);  /* don't allow const */\n\t\t\trc_key = duk__ispec_toregconst_raw(comp_ctx, &left->x2, -1 /*forced_reg*/, DUK__IVAL_FLAG_ALLOW_CONST /*flags*/);\n\t\t\tduk__emit_a_b_c(comp_ctx,\n\t\t\t                args_op2 | DUK__EMIT_FLAG_BC_REGCONST,  /* e.g. DUK_OP_POSTINCP */\n\t\t\t                reg_res,\n\t\t\t                reg_obj,\n\t\t\t                rc_key);\n\t\t} else {\n\t\t\t/* Technically return value is not needed because INVLHS will\n\t\t\t * unconditially throw a ReferenceError.  Coercion is necessary\n\t\t\t * for proper semantics (consider ToNumber() called for an object).\n\t\t\t * Use DUK_OP_UNP with a dummy register to get ToNumber().\n\t\t\t */\n\t\t\tduk__ivalue_toforcedreg(comp_ctx, left, reg_res);\n\t\t\tduk__emit_bc(comp_ctx,\n\t\t\t             DUK_OP_UNP,\n\t\t\t             reg_res);  /* for side effects, result ignored */\n\t\t\tduk__emit_op_only(comp_ctx,\n\t\t\t                  DUK_OP_INVLHS);\n\t\t}\n\n\t\tDUK__SETTEMP(comp_ctx, reg_res + 1);\n\t\tduk__ivalue_regconst(res, reg_res);\n\t\treturn;\n\t}\n\n syntax_error:\n\tDUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_EXPRESSION);\n\treturn;\n\n syntax_error_lvalue:\n\tDUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_LVALUE);\n\treturn;\n}\n\nDUK_LOCAL duk_small_uint_t duk__expr_lbp(duk_compiler_ctx *comp_ctx) {\n\tduk_small_uint_t tok = comp_ctx->curr_token.t;\n\n\tDUK_ASSERT_DISABLE(tok >= DUK_TOK_MINVAL);  /* unsigned */\n\tDUK_ASSERT(tok <= DUK_TOK_MAXVAL);\n\tDUK_ASSERT(sizeof(duk__token_lbp) == DUK_TOK_MAXVAL + 1);\n\n\t/* XXX: integrate support for this into led() instead?\n\t * Similar issue as post-increment/post-decrement.\n\t */\n\n\t/* prevent duk__expr_led() by using a binding power less than anything valid */\n\tif (tok == DUK_TOK_IN && !comp_ctx->curr_func.allow_in) {\n\t\treturn 0;\n\t}\n\n\tif ((tok == DUK_TOK_DECREMENT || tok == DUK_TOK_INCREMENT) &&\n\t    (comp_ctx->curr_token.lineterm)) {\n\t\t/* '++' or '--' in a post-increment/decrement position,\n\t\t * and a LineTerminator occurs between the operator and\n\t\t * the preceding expression.  Force the previous expr\n\t\t * to terminate, in effect treating e.g. \"a,b\\n++\" as\n\t\t * \"a,b;++\" (= SyntaxError).\n\t\t */\n\t\treturn 0;\n\t}\n\n\treturn DUK__TOKEN_LBP_GET_BP(duk__token_lbp[tok]);  /* format is bit packed */\n}\n\n/*\n *  Expression parsing.\n *\n *  Upon entry to 'expr' and its variants, 'curr_tok' is assumed to be the\n *  first token of the expression.  Upon exit, 'curr_tok' will be the first\n *  token not part of the expression (e.g. semicolon terminating an expression\n *  statement).\n */\n\n#define DUK__EXPR_RBP_MASK           0xff\n#define DUK__EXPR_FLAG_REJECT_IN     (1 << 8)   /* reject 'in' token (used for for-in) */\n#define DUK__EXPR_FLAG_ALLOW_EMPTY   (1 << 9)   /* allow empty expression */\n#define DUK__EXPR_FLAG_REQUIRE_INIT  (1 << 10)  /* require initializer for var/const */\n\n/* main expression parser function */\nDUK_LOCAL void duk__expr(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {\n\tduk_hthread *thr = comp_ctx->thr;\n\tduk_ivalue tmp_alloc;   /* 'res' is used for \"left\", and 'tmp' for \"right\" */\n\tduk_ivalue *tmp = &tmp_alloc;\n\tduk_small_uint_t rbp;\n\n\tDUK__RECURSION_INCREASE(comp_ctx, thr);\n\n\tduk_require_stack(thr, DUK__PARSE_EXPR_SLOTS);\n\n\t/* filter out flags from exprtop rbp_flags here to save space */\n\trbp = rbp_flags & DUK__EXPR_RBP_MASK;\n\n\tDUK_DDD(DUK_DDDPRINT(\"duk__expr(), rbp_flags=%ld, rbp=%ld, allow_in=%ld, paren_level=%ld\",\n\t                     (long) rbp_flags, (long) rbp, (long) comp_ctx->curr_func.allow_in,\n\t                     (long) comp_ctx->curr_func.paren_level));\n\n\tDUK_MEMZERO(&tmp_alloc, sizeof(tmp_alloc));\n\ttmp->x1.valstack_idx = duk_get_top(thr);\n\ttmp->x2.valstack_idx = tmp->x1.valstack_idx + 1;\n\tduk_push_undefined(thr);\n\tduk_push_undefined(thr);\n\n\t/* XXX: where to release temp regs in intermediate expressions?\n\t * e.g. 1+2+3 -> don't inflate temp register count when parsing this.\n\t * that particular expression temp regs can be forced here.\n\t */\n\n\t/* XXX: increase ctx->expr_tokens here for every consumed token\n\t * (this would be a nice statistic)?\n\t */\n\n\tif (comp_ctx->curr_token.t == DUK_TOK_SEMICOLON || comp_ctx->curr_token.t == DUK_TOK_RPAREN) {\n\t\t/* XXX: possibly incorrect handling of empty expression */\n\t\tDUK_DDD(DUK_DDDPRINT(\"empty expression\"));\n\t\tif (!(rbp_flags & DUK__EXPR_FLAG_ALLOW_EMPTY)) {\n\t\t\tDUK_ERROR_SYNTAX(thr, DUK_STR_EMPTY_EXPR_NOT_ALLOWED);\n\t\t}\n\t\tduk_push_undefined(thr);\n\t\tduk__ivalue_plain_fromstack(comp_ctx, res);\n\t\tgoto cleanup;\n\t}\n\n\tduk__advance(comp_ctx);\n\tduk__expr_nud(comp_ctx, res);  /* reuse 'res' as 'left' */\n\twhile (rbp < duk__expr_lbp(comp_ctx)) {\n\t\tduk__advance(comp_ctx);\n\t\tduk__expr_led(comp_ctx, res, tmp);\n\t\tduk__copy_ivalue(comp_ctx, tmp, res);  /* tmp -> res */\n\t}\n\n cleanup:\n\t/* final result is already in 'res' */\n\n\tduk_pop_2(thr);\n\n\tDUK__RECURSION_DECREASE(comp_ctx, thr);\n}\n\nDUK_LOCAL void duk__exprtop(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {\n\tduk_hthread *thr = comp_ctx->thr;\n\n\t/* Note: these variables must reside in 'curr_func' instead of the global\n\t * context: when parsing function expressions, expression parsing is nested.\n\t */\n\tcomp_ctx->curr_func.nud_count = 0;\n\tcomp_ctx->curr_func.led_count = 0;\n\tcomp_ctx->curr_func.paren_level = 0;\n\tcomp_ctx->curr_func.expr_lhs = 1;\n\tcomp_ctx->curr_func.allow_in = (rbp_flags & DUK__EXPR_FLAG_REJECT_IN ? 0 : 1);\n\n\tduk__expr(comp_ctx, res, rbp_flags);\n\n\tif (!(rbp_flags & DUK__EXPR_FLAG_ALLOW_EMPTY) && duk__expr_is_empty(comp_ctx)) {\n\t\tDUK_ERROR_SYNTAX(thr, DUK_STR_EMPTY_EXPR_NOT_ALLOWED);\n\t}\n}\n\n/* A bunch of helpers (for size optimization) that combine duk__expr()/duk__exprtop()\n * and result conversions.\n *\n * Each helper needs at least 2-3 calls to make it worth while to wrap.\n */\n\n#if 0  /* unused */\nDUK_LOCAL duk_regconst_t duk__expr_toreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {\n\tduk__expr(comp_ctx, res, rbp_flags);\n\treturn duk__ivalue_toreg(comp_ctx, res);\n}\n#endif\n\n#if 0  /* unused */\nDUK_LOCAL duk_regconst_t duk__expr_totemp(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {\n\tduk__expr(comp_ctx, res, rbp_flags);\n\treturn duk__ivalue_totemp(comp_ctx, res);\n}\n#endif\n\nDUK_LOCAL void duk__expr_toforcedreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags, duk_regconst_t forced_reg) {\n\tDUK_ASSERT(forced_reg >= 0);\n\tduk__expr(comp_ctx, res, rbp_flags);\n\tduk__ivalue_toforcedreg(comp_ctx, res, forced_reg);\n}\n\nDUK_LOCAL duk_regconst_t duk__expr_toregconst(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {\n\tduk__expr(comp_ctx, res, rbp_flags);\n\treturn duk__ivalue_toregconst(comp_ctx, res);\n}\n\n#if 0  /* unused */\nDUK_LOCAL duk_regconst_t duk__expr_totempconst(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {\n\tduk__expr(comp_ctx, res, rbp_flags);\n\treturn duk__ivalue_totempconst(comp_ctx, res);\n}\n#endif\n\nDUK_LOCAL void duk__expr_toplain(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {\n\tduk__expr(comp_ctx, res, rbp_flags);\n\tduk__ivalue_toplain(comp_ctx, res);\n}\n\nDUK_LOCAL void duk__expr_toplain_ignore(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {\n\tduk__expr(comp_ctx, res, rbp_flags);\n\tduk__ivalue_toplain_ignore(comp_ctx, res);\n}\n\nDUK_LOCAL duk_regconst_t duk__exprtop_toreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {\n\tduk__exprtop(comp_ctx, res, rbp_flags);\n\treturn duk__ivalue_toreg(comp_ctx, res);\n}\n\n#if 0  /* unused */\nDUK_LOCAL duk_regconst_t duk__exprtop_totemp(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {\n\tduk__exprtop(comp_ctx, res, rbp_flags);\n\treturn duk__ivalue_totemp(comp_ctx, res);\n}\n#endif\n\nDUK_LOCAL void duk__exprtop_toforcedreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags, duk_regconst_t forced_reg) {\n\tDUK_ASSERT(forced_reg >= 0);\n\tduk__exprtop(comp_ctx, res, rbp_flags);\n\tduk__ivalue_toforcedreg(comp_ctx, res, forced_reg);\n}\n\nDUK_LOCAL duk_regconst_t duk__exprtop_toregconst(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {\n\tduk__exprtop(comp_ctx, res, rbp_flags);\n\treturn duk__ivalue_toregconst(comp_ctx, res);\n}\n\n#if 0  /* unused */\nDUK_LOCAL void duk__exprtop_toplain_ignore(duk_compiler_ctx *comp_ctx, duk_ivalue *res, int rbp_flags) {\n\tduk__exprtop(comp_ctx, res, rbp_flags);\n\tduk__ivalue_toplain_ignore(comp_ctx, res);\n}\n#endif\n\n/*\n *  Parse an individual source element (top level statement) or a statement.\n *\n *  Handles labeled statements automatically (peeling away labels before\n *  parsing an expression that follows the label(s)).\n *\n *  Upon entry, 'curr_tok' contains the first token of the statement (parsed\n *  in \"allow regexp literal\" mode).  Upon exit, 'curr_tok' contains the first\n *  token following the statement (if the statement has a terminator, this is\n *  the token after the terminator).\n */\n\n#define DUK__HAS_VAL                  (1 << 0)  /* stmt has non-empty value */\n#define DUK__HAS_TERM                 (1 << 1)  /* stmt has explicit/implicit semicolon terminator */\n#define DUK__ALLOW_AUTO_SEMI_ALWAYS   (1 << 2)  /* allow automatic semicolon even without lineterm (compatibility) */\n#define DUK__STILL_PROLOGUE           (1 << 3)  /* statement does not terminate directive prologue */\n#define DUK__IS_TERMINAL              (1 << 4)  /* statement is guaranteed to be terminal (control doesn't flow to next statement) */\n\n/* Parse a single variable declaration (e.g. \"i\" or \"i=10\").  A leading 'var'\n * has already been eaten.  These is no return value in 'res', it is used only\n * as a temporary.\n *\n * When called from 'for-in' statement parser, the initializer expression must\n * not allow the 'in' token.  The caller supply additional expression parsing\n * flags (like DUK__EXPR_FLAG_REJECT_IN) in 'expr_flags'.\n *\n * Finally, out_rc_varname and out_reg_varbind are updated to reflect where\n * the identifier is bound:\n *\n *    If register bound:      out_reg_varbind >= 0, out_rc_varname == 0 (ignore)\n *    If not register bound:  out_reg_varbind < 0, out_rc_varname >= 0\n *\n * These allow the caller to use the variable for further assignment, e.g.\n * as is done in 'for-in' parsing.\n */\n\nDUK_LOCAL void duk__parse_var_decl(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t expr_flags, duk_regconst_t *out_reg_varbind, duk_regconst_t *out_rc_varname) {\n\tduk_hthread *thr = comp_ctx->thr;\n\tduk_hstring *h_varname;\n\tduk_regconst_t reg_varbind;\n\tduk_regconst_t rc_varname;\n\n\t/* assume 'var' has been eaten */\n\n\t/* Note: Identifier rejects reserved words */\n\tif (comp_ctx->curr_token.t != DUK_TOK_IDENTIFIER) {\n\t\tgoto syntax_error;\n\t}\n\th_varname = comp_ctx->curr_token.str1;\n\n\tDUK_ASSERT(h_varname != NULL);\n\n\t/* strict mode restrictions (E5 Section 12.2.1) */\n\tif (duk__hstring_is_eval_or_arguments_in_strict_mode(comp_ctx, h_varname)) {\n\t\tgoto syntax_error;\n\t}\n\n\t/* register declarations in first pass */\n\tif (comp_ctx->curr_func.in_scanning) {\n\t\tduk_uarridx_t n;\n\t\tDUK_DDD(DUK_DDDPRINT(\"register variable declaration %!O in pass 1\",\n\t\t                     (duk_heaphdr *) h_varname));\n\t\tn = (duk_uarridx_t) duk_get_length(thr, comp_ctx->curr_func.decls_idx);\n\t\tduk_push_hstring(thr, h_varname);\n\t\tduk_put_prop_index(thr, comp_ctx->curr_func.decls_idx, n);\n\t\tduk_push_int(thr, DUK_DECL_TYPE_VAR + (0 << 8));\n\t\tduk_put_prop_index(thr, comp_ctx->curr_func.decls_idx, n + 1);\n\t}\n\n\tduk_push_hstring(thr, h_varname);  /* push before advancing to keep reachable */\n\n\t/* register binding lookup is based on varmap (even in first pass) */\n\tduk_dup_top(thr);\n\t(void) duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname);\n\n\tduk__advance(comp_ctx);  /* eat identifier */\n\n\tif (comp_ctx->curr_token.t == DUK_TOK_EQUALSIGN) {\n\t\tduk__advance(comp_ctx);\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"vardecl, assign to '%!O' -> reg_varbind=%ld, rc_varname=%ld\",\n\t\t                     (duk_heaphdr *) h_varname, (long) reg_varbind, (long) rc_varname));\n\n\t\tduk__exprtop(comp_ctx, res, DUK__BP_COMMA | expr_flags /*rbp_flags*/);  /* AssignmentExpression */\n\n\t\tif (reg_varbind >= 0) {\n\t\t\tduk__ivalue_toforcedreg(comp_ctx, res, reg_varbind);\n\t\t} else {\n\t\t\tduk_regconst_t reg_val;\n\t\t\treg_val = duk__ivalue_toreg(comp_ctx, res);\n\t\t\tduk__emit_a_bc(comp_ctx,\n\t\t\t               DUK_OP_PUTVAR | DUK__EMIT_FLAG_A_IS_SOURCE,\n\t\t\t               reg_val,\n\t\t\t               rc_varname);\n\t\t}\n\t} else {\n\t\tif (expr_flags & DUK__EXPR_FLAG_REQUIRE_INIT) {\n\t\t\t/* Used for minimal 'const': initializer required. */\n\t\t\tgoto syntax_error;\n\t\t}\n\t}\n\n\tduk_pop(thr);  /* pop varname */\n\n\t*out_rc_varname = rc_varname;\n\t*out_reg_varbind = reg_varbind;\n\n\treturn;\n\n syntax_error:\n\tDUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_VAR_DECLARATION);\n}\n\nDUK_LOCAL void duk__parse_var_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t expr_flags) {\n\tduk_regconst_t reg_varbind;\n\tduk_regconst_t rc_varname;\n\n\tduk__advance(comp_ctx);  /* eat 'var' */\n\n\tfor (;;) {\n\t\t/* rc_varname and reg_varbind are ignored here */\n\t\tduk__parse_var_decl(comp_ctx, res, 0 | expr_flags, &reg_varbind, &rc_varname);\n\n\t\tif (comp_ctx->curr_token.t != DUK_TOK_COMMA) {\n\t\t\tbreak;\n\t\t}\n\t\tduk__advance(comp_ctx);\n\t}\n}\n\nDUK_LOCAL void duk__parse_for_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site) {\n\tduk_hthread *thr = comp_ctx->thr;\n\tduk_int_t pc_v34_lhs;         /* start variant 3/4 left-hand-side code (L1 in doc/compiler.rst example) */\n\tduk_regconst_t temp_reset;    /* knock back \"next temp\" to this whenever possible */\n\tduk_regconst_t reg_temps;     /* preallocated temporaries (2) for variants 3 and 4 */\n\n\tDUK_DDD(DUK_DDDPRINT(\"start parsing a for/for-in statement\"));\n\n\t/* Two temporaries are preallocated here for variants 3 and 4 which need\n\t * registers which are never clobbered by expressions in the loop\n\t * (concretely: for the enumerator object and the next enumerated value).\n\t * Variants 1 and 2 \"release\" these temps.\n\t */\n\n\treg_temps = DUK__ALLOCTEMPS(comp_ctx, 2);\n\n\ttemp_reset = DUK__GETTEMP(comp_ctx);\n\n\t/*\n\t *  For/for-in main variants are:\n\t *\n\t *    1. for (ExpressionNoIn_opt; Expression_opt; Expression_opt) Statement\n\t *    2. for (var VariableDeclarationNoIn; Expression_opt; Expression_opt) Statement\n\t *    3. for (LeftHandSideExpression in Expression) Statement\n\t *    4. for (var VariableDeclarationNoIn in Expression) Statement\n\t *\n\t *  Parsing these without arbitrary lookahead or backtracking is relatively\n\t *  tricky but we manage to do so for now.\n\t *\n\t *  See doc/compiler.rst for a detailed discussion of control flow\n\t *  issues, evaluation order issues, etc.\n\t */\n\n\tduk__advance(comp_ctx);  /* eat 'for' */\n\tduk__advance_expect(comp_ctx, DUK_TOK_LPAREN);\n\n\tDUK_DDD(DUK_DDDPRINT(\"detecting for/for-in loop variant, pc=%ld\", (long) duk__get_current_pc(comp_ctx)));\n\n\t/* a label site has been emitted by duk__parse_stmt() automatically\n\t * (it will also emit the ENDLABEL).\n\t */\n\n\tif (comp_ctx->curr_token.t == DUK_TOK_VAR) {\n\t\t/*\n\t\t *  Variant 2 or 4\n\t\t */\n\n\t\tduk_regconst_t reg_varbind;  /* variable binding register if register-bound (otherwise < 0) */\n\t\tduk_regconst_t rc_varname;   /* variable name reg/const, if variable not register-bound */\n\n\t\tduk__advance(comp_ctx);  /* eat 'var' */\n\t\tduk__parse_var_decl(comp_ctx, res, DUK__EXPR_FLAG_REJECT_IN, &reg_varbind, &rc_varname);\n\t\tDUK__SETTEMP(comp_ctx, temp_reset);\n\n\t\tif (comp_ctx->curr_token.t == DUK_TOK_IN) {\n\t\t\t/*\n\t\t\t *  Variant 4\n\t\t\t */\n\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"detected for variant 4: for (var VariableDeclarationNoIn in Expression) Statement\"));\n\t\t\tpc_v34_lhs = duk__get_current_pc(comp_ctx);  /* jump is inserted here */\n\t\t\tif (reg_varbind >= 0) {\n\t\t\t\tduk__emit_a_bc(comp_ctx,\n\t\t\t\t               DUK_OP_LDREG,\n\t\t\t\t               reg_varbind,\n\t\t\t\t               reg_temps + 0);\n\t\t\t} else {\n\t\t\t\tduk__emit_a_bc(comp_ctx,\n\t\t\t\t               DUK_OP_PUTVAR | DUK__EMIT_FLAG_A_IS_SOURCE,\n\t\t\t\t               reg_temps + 0,\n\t\t\t\t               rc_varname);\n\t\t\t}\n\t\t\tgoto parse_3_or_4;\n\t\t} else {\n\t\t\t/*\n\t\t\t *  Variant 2\n\t\t\t */\n\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"detected for variant 2: for (var VariableDeclarationNoIn; Expression_opt; Expression_opt) Statement\"));\n\t\t\tfor (;;) {\n\t\t\t\t/* more initializers */\n\t\t\t\tif (comp_ctx->curr_token.t != DUK_TOK_COMMA) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"variant 2 has another variable initializer\"));\n\n\t\t\t\tduk__advance(comp_ctx);  /* eat comma */\n\t\t\t\tduk__parse_var_decl(comp_ctx, res, DUK__EXPR_FLAG_REJECT_IN, &reg_varbind, &rc_varname);\n\t\t\t}\n\t\t\tgoto parse_1_or_2;\n\t\t}\n\t} else {\n\t\t/*\n\t\t *  Variant 1 or 3\n\t\t */\n\n\t\tpc_v34_lhs = duk__get_current_pc(comp_ctx);  /* jump is inserted here (variant 3) */\n\n\t\t/* Note that duk__exprtop() here can clobber any reg above current temp_next,\n\t\t * so any loop variables (e.g. enumerator) must be \"preallocated\".\n\t\t */\n\n\t\t/* don't coerce yet to a plain value (variant 3 needs special handling) */\n\t\tduk__exprtop(comp_ctx, res, DUK__BP_FOR_EXPR | DUK__EXPR_FLAG_REJECT_IN | DUK__EXPR_FLAG_ALLOW_EMPTY /*rbp_flags*/);  /* Expression */\n\t\tif (comp_ctx->curr_token.t == DUK_TOK_IN) {\n\t\t\t/*\n\t\t\t *  Variant 3\n\t\t\t */\n\n\t\t\t/* XXX: need to determine LHS type, and check that it is LHS compatible */\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"detected for variant 3: for (LeftHandSideExpression in Expression) Statement\"));\n\t\t\tif (duk__expr_is_empty(comp_ctx)) {\n\t\t\t\tgoto syntax_error;  /* LeftHandSideExpression does not allow empty expression */\n\t\t\t}\n\n\t\t\tif (res->t == DUK_IVAL_VAR) {\n\t\t\t\tduk_regconst_t reg_varbind;\n\t\t\t\tduk_regconst_t rc_varname;\n\n\t\t\t\tduk_dup(thr, res->x1.valstack_idx);\n\t\t\t\tif (duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname)) {\n\t\t\t\t\tduk__emit_a_bc(comp_ctx,\n\t\t\t\t\t               DUK_OP_LDREG,\n\t\t\t\t\t               reg_varbind,\n\t\t\t\t\t               reg_temps + 0);\n\t\t\t\t} else {\n\t\t\t\t\tduk__emit_a_bc(comp_ctx,\n\t\t\t\t\t               DUK_OP_PUTVAR | DUK__EMIT_FLAG_A_IS_SOURCE,\n\t\t\t\t\t               reg_temps + 0,\n\t\t\t\t\t               rc_varname);\n\t\t\t\t}\n\t\t\t} else if (res->t == DUK_IVAL_PROP) {\n\t\t\t\t/* Don't allow a constant for the object (even for a number etc), as\n\t\t\t\t * it goes into the 'A' field of the opcode.\n\t\t\t\t */\n\t\t\t\tduk_regconst_t reg_obj;\n\t\t\t\tduk_regconst_t rc_key;\n\t\t\t\treg_obj = duk__ispec_toregconst_raw(comp_ctx, &res->x1, -1 /*forced_reg*/, 0 /*flags*/);  /* don't allow const */\n\t\t\t\trc_key = duk__ispec_toregconst_raw(comp_ctx, &res->x2, -1 /*forced_reg*/, DUK__IVAL_FLAG_ALLOW_CONST /*flags*/);\n\t\t\t\tduk__emit_a_b_c(comp_ctx,\n\t\t\t\t                DUK_OP_PUTPROP | DUK__EMIT_FLAG_A_IS_SOURCE | DUK__EMIT_FLAG_BC_REGCONST,\n\t\t\t\t                reg_obj,\n\t\t\t\t                rc_key,\n\t\t\t\t                reg_temps + 0);\n\t\t\t} else {\n\t\t\t\tduk__ivalue_toplain_ignore(comp_ctx, res);  /* just in case */\n\t\t\t\tduk__emit_op_only(comp_ctx,\n\t\t\t\t                  DUK_OP_INVLHS);\n\t\t\t}\n\t\t\tgoto parse_3_or_4;\n\t\t} else {\n\t\t\t/*\n\t\t\t *  Variant 1\n\t\t\t */\n\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"detected for variant 1: for (ExpressionNoIn_opt; Expression_opt; Expression_opt) Statement\"));\n\t\t\tduk__ivalue_toplain_ignore(comp_ctx, res);\n\t\t\tgoto parse_1_or_2;\n\t\t}\n\t}\n\n parse_1_or_2:\n\t/*\n\t *  Parse variant 1 or 2.  The first part expression (which differs\n\t *  in the variants) has already been parsed and its code emitted.\n\t *\n\t *  reg_temps + 0: unused\n\t *  reg_temps + 1: unused\n\t */\n\t{\n\t\tduk_regconst_t rc_cond;\n\t\tduk_int_t pc_l1, pc_l2, pc_l3, pc_l4;\n\t\tduk_int_t pc_jumpto_l3, pc_jumpto_l4;\n\t\tduk_bool_t expr_c_empty;\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"shared code for parsing variants 1 and 2\"));\n\n\t\t/* \"release\" preallocated temps since we won't need them */\n\t\ttemp_reset = reg_temps + 0;\n\t\tDUK__SETTEMP(comp_ctx, temp_reset);\n\n\t\tduk__advance_expect(comp_ctx, DUK_TOK_SEMICOLON);\n\n\t\tpc_l1 = duk__get_current_pc(comp_ctx);\n\t\tduk__exprtop(comp_ctx, res, DUK__BP_FOR_EXPR | DUK__EXPR_FLAG_ALLOW_EMPTY /*rbp_flags*/);  /* Expression_opt */\n\t\tif (duk__expr_is_empty(comp_ctx)) {\n\t\t\t/* no need to coerce */\n\t\t\tpc_jumpto_l3 = duk__emit_jump_empty(comp_ctx);  /* to body */\n\t\t\tpc_jumpto_l4 = -1;  /* omitted */\n\t\t} else {\n\t\t\trc_cond = duk__ivalue_toregconst(comp_ctx, res);\n\t\t\tduk__emit_if_false_skip(comp_ctx, rc_cond);\n\t\t\tpc_jumpto_l3 = duk__emit_jump_empty(comp_ctx);  /* to body */\n\t\t\tpc_jumpto_l4 = duk__emit_jump_empty(comp_ctx);  /* to exit */\n\t\t}\n\t\tDUK__SETTEMP(comp_ctx, temp_reset);\n\n\t\tduk__advance_expect(comp_ctx, DUK_TOK_SEMICOLON);\n\n\t\tpc_l2 = duk__get_current_pc(comp_ctx);\n\t\tduk__exprtop(comp_ctx, res, DUK__BP_FOR_EXPR | DUK__EXPR_FLAG_ALLOW_EMPTY /*rbp_flags*/);  /* Expression_opt */\n\t\tif (duk__expr_is_empty(comp_ctx)) {\n\t\t\t/* no need to coerce */\n\t\t\texpr_c_empty = 1;\n\t\t\t/* JUMP L1 omitted */\n\t\t} else {\n\t\t\tduk__ivalue_toplain_ignore(comp_ctx, res);\n\t\t\texpr_c_empty = 0;\n\t\t\tduk__emit_jump(comp_ctx, pc_l1);\n\t\t}\n\t\tDUK__SETTEMP(comp_ctx, temp_reset);\n\n\t\tduk__advance_expect(comp_ctx, DUK_TOK_RPAREN);\n\n\t\tpc_l3 = duk__get_current_pc(comp_ctx);\n\t\tduk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);\n\t\tif (expr_c_empty) {\n\t\t\tduk__emit_jump(comp_ctx, pc_l1);\n\t\t} else {\n\t\t\tduk__emit_jump(comp_ctx, pc_l2);\n\t\t}\n\t\t/* temp reset is not necessary after duk__parse_stmt(), which already does it */\n\n\t\tpc_l4 = duk__get_current_pc(comp_ctx);\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"patching jumps: jumpto_l3: %ld->%ld, jumpto_l4: %ld->%ld, \"\n\t\t                     \"break: %ld->%ld, continue: %ld->%ld\",\n\t\t\t             (long) pc_jumpto_l3, (long) pc_l3, (long) pc_jumpto_l4, (long) pc_l4,\n\t\t                     (long) (pc_label_site + 1), (long) pc_l4, (long) (pc_label_site + 2), (long) pc_l2));\n\n\t\tduk__patch_jump(comp_ctx, pc_jumpto_l3, pc_l3);\n\t\tduk__patch_jump(comp_ctx, pc_jumpto_l4, pc_l4);\n\t\tduk__patch_jump(comp_ctx,\n\t\t                pc_label_site + 1,\n\t\t                pc_l4);                         /* break jump */\n\t\tduk__patch_jump(comp_ctx,\n\t\t                pc_label_site + 2,\n\t\t                expr_c_empty ? pc_l1 : pc_l2);  /* continue jump */\n\t}\n\tgoto finished;\n\n parse_3_or_4:\n\t/*\n\t *  Parse variant 3 or 4.\n\t *\n\t *  For variant 3 (e.g. \"for (A in C) D;\") the code for A (except the\n\t *  final property/variable write) has already been emitted.  The first\n\t *  instruction of that code is at pc_v34_lhs; a JUMP needs to be inserted\n\t *  there to satisfy control flow needs.\n\t *\n\t *  For variant 4, if the variable declaration had an initializer\n\t *  (e.g. \"for (var A = B in C) D;\") the code for the assignment\n\t *  (B) has already been emitted.\n\t *\n\t *  Variables set before entering here:\n\t *\n\t *    pc_v34_lhs:    insert a \"JUMP L2\" here (see doc/compiler.rst example).\n\t *    reg_temps + 0: iteration target value (written to LHS)\n\t *    reg_temps + 1: enumerator object\n\t */\n\t{\n\t\tduk_int_t pc_l1, pc_l2, pc_l3, pc_l4, pc_l5;\n\t\tduk_int_t pc_jumpto_l2, pc_jumpto_l3, pc_jumpto_l4, pc_jumpto_l5;\n\t\tduk_regconst_t reg_target;\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"shared code for parsing variants 3 and 4, pc_v34_lhs=%ld\", (long) pc_v34_lhs));\n\n\t\tDUK__SETTEMP(comp_ctx, temp_reset);\n\n\t\t/* First we need to insert a jump in the middle of previously\n\t\t * emitted code to get the control flow right.  No jumps can\n\t\t * cross the position where the jump is inserted.  See doc/compiler.rst\n\t\t * for discussion on the intricacies of control flow and side effects\n\t\t * for variants 3 and 4.\n\t\t */\n\n\t\tduk__insert_jump_entry(comp_ctx, pc_v34_lhs);\n\t\tpc_jumpto_l2 = pc_v34_lhs;  /* inserted jump */\n\t\tpc_l1 = pc_v34_lhs + 1;     /* +1, right after inserted jump */\n\n\t\t/* The code for writing reg_temps + 0 to the left hand side has already\n\t\t * been emitted.\n\t\t */\n\n\t\tpc_jumpto_l3 = duk__emit_jump_empty(comp_ctx);  /* -> loop body */\n\n\t\tduk__advance(comp_ctx);  /* eat 'in' */\n\n\t\t/* Parse enumeration target and initialize enumerator.  For 'null' and 'undefined',\n\t\t * INITENUM will creates a 'null' enumerator which works like an empty enumerator\n\t\t * (E5 Section 12.6.4, step 3).  Note that INITENUM requires the value to be in a\n\t\t * register (constant not allowed).\n\t\t */\n\n\t\tpc_l2 = duk__get_current_pc(comp_ctx);\n\t\treg_target = duk__exprtop_toreg(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);  /* Expression */\n\t\tduk__emit_b_c(comp_ctx,\n\t\t              DUK_OP_INITENUM | DUK__EMIT_FLAG_B_IS_TARGET,\n\t\t              reg_temps + 1,\n\t\t              reg_target);\n\t\tpc_jumpto_l4 = duk__emit_jump_empty(comp_ctx);\n\t\tDUK__SETTEMP(comp_ctx, temp_reset);\n\n\t\tduk__advance_expect(comp_ctx, DUK_TOK_RPAREN);\n\n\t\tpc_l3 = duk__get_current_pc(comp_ctx);\n\t\tduk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);\n\t\t/* temp reset is not necessary after duk__parse_stmt(), which already does it */\n\n\t\t/* NEXTENUM needs a jump slot right after the main opcode.\n\t\t * We need the code emitter to reserve the slot: if there's\n\t\t * target shuffling, the target shuffle opcodes must happen\n\t\t * after the jump slot (for NEXTENUM the shuffle opcodes are\n\t\t * not needed if the enum is finished).\n\t\t */\n\t\tpc_l4 = duk__get_current_pc(comp_ctx);\n\t\tduk__emit_b_c(comp_ctx,\n\t\t              DUK_OP_NEXTENUM | DUK__EMIT_FLAG_B_IS_TARGET | DUK__EMIT_FLAG_RESERVE_JUMPSLOT,\n\t\t              reg_temps + 0,\n\t\t              reg_temps + 1);\n\t\tpc_jumpto_l5 = comp_ctx->emit_jumpslot_pc;  /* NEXTENUM jump slot: executed when enum finished */\n\t\tduk__emit_jump(comp_ctx, pc_l1);  /* jump to next loop, using reg_v34_iter as iterated value */\n\n\t\tpc_l5 = duk__get_current_pc(comp_ctx);\n\n\t\t/* XXX: since the enumerator may be a memory expensive object,\n\t\t * perhaps clear it explicitly here?  If so, break jump must\n\t\t * go through this clearing operation.\n\t\t */\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"patching jumps: jumpto_l2: %ld->%ld, jumpto_l3: %ld->%ld, \"\n\t\t                     \"jumpto_l4: %ld->%ld, jumpto_l5: %ld->%ld, \"\n\t\t                     \"break: %ld->%ld, continue: %ld->%ld\",\n\t\t\t             (long) pc_jumpto_l2, (long) pc_l2, (long) pc_jumpto_l3, (long) pc_l3,\n\t\t\t             (long) pc_jumpto_l4, (long) pc_l4, (long) pc_jumpto_l5, (long) pc_l5,\n\t\t                     (long) (pc_label_site + 1), (long) pc_l5, (long) (pc_label_site + 2), (long) pc_l4));\n\n\t\tduk__patch_jump(comp_ctx, pc_jumpto_l2, pc_l2);\n\t\tduk__patch_jump(comp_ctx, pc_jumpto_l3, pc_l3);\n\t\tduk__patch_jump(comp_ctx, pc_jumpto_l4, pc_l4);\n\t\tduk__patch_jump(comp_ctx, pc_jumpto_l5, pc_l5);\n\t\tduk__patch_jump(comp_ctx, pc_label_site + 1, pc_l5);  /* break jump */\n\t\tduk__patch_jump(comp_ctx, pc_label_site + 2, pc_l4);  /* continue jump */\n\t}\n\tgoto finished;\n\n finished:\n\tDUK_DDD(DUK_DDDPRINT(\"end parsing a for/for-in statement\"));\n\treturn;\n\n syntax_error:\n\tDUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_FOR);\n}\n\nDUK_LOCAL void duk__parse_switch_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site) {\n\tduk_hthread *thr = comp_ctx->thr;\n\tduk_regconst_t temp_at_loop;\n\tduk_regconst_t rc_switch;    /* reg/const for switch value */\n\tduk_regconst_t rc_case;      /* reg/const for case value */\n\tduk_regconst_t reg_temp;     /* general temp register */\n\tduk_int_t pc_prevcase = -1;\n\tduk_int_t pc_prevstmt = -1;\n\tduk_int_t pc_default = -1;   /* -1 == not set, -2 == pending (next statement list) */\n\n\t/* Note: negative pc values are ignored when patching jumps, so no explicit checks needed */\n\n\t/*\n\t *  Switch is pretty complicated because of several conflicting concerns:\n\t *\n\t *    - Want to generate code without an intermediate representation,\n\t *      i.e., in one go\n\t *\n\t *    - Case selectors are expressions, not values, and may thus e.g. throw\n\t *      exceptions (which causes evaluation order concerns)\n\t *\n\t *    - Evaluation semantics of case selectors and default clause need to be\n\t *      carefully implemented to provide correct behavior even with case value\n\t *      side effects\n\t *\n\t *    - Fall through case and default clauses; avoiding dead JUMPs if case\n\t *      ends with an unconditional jump (a break or a continue)\n\t *\n\t *    - The same case value may occur multiple times, but evaluation rules\n\t *      only process the first match before switching to a \"propagation\" mode\n\t *      where case values are no longer evaluated\n\t *\n\t *  See E5 Section 12.11.  Also see doc/compiler.rst for compilation\n\t *  discussion.\n\t */\n\n\tduk__advance(comp_ctx);\n\tduk__advance_expect(comp_ctx, DUK_TOK_LPAREN);\n\trc_switch = duk__exprtop_toregconst(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);\n\tduk__advance_expect(comp_ctx, DUK_TOK_RPAREN);\n\tduk__advance_expect(comp_ctx, DUK_TOK_LCURLY);\n\n\tDUK_DDD(DUK_DDDPRINT(\"switch value in register %ld\", (long) rc_switch));\n\n\ttemp_at_loop = DUK__GETTEMP(comp_ctx);\n\n\tfor (;;) {\n\t\tduk_int_t num_stmts;\n\t\tduk_small_uint_t tok;\n\n\t\t/* sufficient for keeping temp reg numbers in check */\n\t\tDUK__SETTEMP(comp_ctx, temp_at_loop);\n\n\t\tif (comp_ctx->curr_token.t == DUK_TOK_RCURLY) {\n\t\t\tbreak;\n\t\t}\n\n\t\t/*\n\t\t *  Parse a case or default clause.\n\t\t */\n\n\t\tif (comp_ctx->curr_token.t == DUK_TOK_CASE) {\n\t\t\t/*\n\t\t\t *  Case clause.\n\t\t\t *\n\t\t\t *  Note: cannot use reg_case as a temp register (for SEQ target)\n\t\t\t *  because it may be a constant.\n\t\t\t */\n\n\t\t\tduk__patch_jump_here(comp_ctx, pc_prevcase);  /* chain jumps for case\n\t\t\t                                               * evaluation and checking\n\t\t\t                                               */\n\n\t\t\tduk__advance(comp_ctx);\n\t\t\trc_case = duk__exprtop_toregconst(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);\n\t\t\tduk__advance_expect(comp_ctx, DUK_TOK_COLON);\n\n\t\t\treg_temp = DUK__ALLOCTEMP(comp_ctx);\n\t\t\tduk__emit_a_b_c(comp_ctx,\n\t\t\t                DUK_OP_SEQ | DUK__EMIT_FLAG_BC_REGCONST,\n\t\t\t                reg_temp,\n\t\t\t                rc_switch,\n\t\t\t                rc_case);\n\t\t\tduk__emit_if_true_skip(comp_ctx, reg_temp);\n\n\t\t\t/* jump to next case clause */\n\t\t\tpc_prevcase = duk__emit_jump_empty(comp_ctx);  /* no match, next case */\n\n\t\t\t/* statements go here (if any) on next loop */\n\t\t} else if (comp_ctx->curr_token.t == DUK_TOK_DEFAULT) {\n\t\t\t/*\n\t\t\t *  Default clause.\n\t\t\t */\n\n\t\t\tif (pc_default >= 0) {\n\t\t\t\tgoto syntax_error;\n\t\t\t}\n\t\t\tduk__advance(comp_ctx);\n\t\t\tduk__advance_expect(comp_ctx, DUK_TOK_COLON);\n\n\t\t\t/* Fix for https://github.com/svaarala/duktape/issues/155:\n\t\t\t * If 'default' is first clause (detected by pc_prevcase < 0)\n\t\t\t * we need to ensure we stay in the matching chain.\n\t\t\t */\n\t\t\tif (pc_prevcase < 0) {\n\t\t\t\tDUK_DD(DUK_DDPRINT(\"default clause is first, emit prevcase jump\"));\n\t\t\t\tpc_prevcase = duk__emit_jump_empty(comp_ctx);\n\t\t\t}\n\n\t\t\t/* default clause matches next statement list (if any) */\n\t\t\tpc_default = -2;\n\t\t} else {\n\t\t\t/* Code is not accepted before the first case/default clause */\n\t\t\tgoto syntax_error;\n\t\t}\n\n\t\t/*\n\t\t *  Parse code after the clause.  Possible terminators are\n\t\t *  'case', 'default', and '}'.\n\t\t *\n\t\t *  Note that there may be no code at all, not even an empty statement,\n\t\t *  between case clauses.  This must be handled just like an empty statement\n\t\t *  (omitting seemingly pointless JUMPs), to avoid situations like\n\t\t *  test-bug-case-fallthrough.js.\n\t\t */\n\n\t\tnum_stmts = 0;\n\t\tif (pc_default == -2) {\n\t\t\tpc_default = duk__get_current_pc(comp_ctx);\n\t\t}\n\n\t\t/* Note: this is correct even for default clause statements:\n\t\t * they participate in 'fall-through' behavior even if the\n\t\t * default clause is in the middle.\n\t\t */\n\t\tduk__patch_jump_here(comp_ctx, pc_prevstmt);  /* chain jumps for 'fall-through'\n\t\t                                               * after a case matches.\n\t\t                                               */\n\n\t\tfor (;;) {\n\t\t\ttok = comp_ctx->curr_token.t;\n\t\t\tif (tok == DUK_TOK_CASE || tok == DUK_TOK_DEFAULT ||\n\t\t\t    tok == DUK_TOK_RCURLY) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tnum_stmts++;\n\t\t\tduk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);\n\t\t}\n\n\t\t/* fall-through jump to next code of next case (backpatched) */\n\t\tpc_prevstmt = duk__emit_jump_empty(comp_ctx);\n\n\t\t/* XXX: would be nice to omit this jump when the jump is not\n\t\t * reachable, at least in the obvious cases (such as the case\n\t\t * ending with a 'break'.\n\t\t *\n\t\t * Perhaps duk__parse_stmt() could provide some info on whether\n\t\t * the statement is a \"dead end\"?\n\t\t *\n\t\t * If implemented, just set pc_prevstmt to -1 when not needed.\n\t\t */\n\t}\n\n\tDUK_ASSERT(comp_ctx->curr_token.t == DUK_TOK_RCURLY);\n\tduk__advance(comp_ctx);\n\n\t/* default case control flow patchup; note that if pc_prevcase < 0\n\t * (i.e. no case clauses), control enters default case automatically.\n\t */\n\tif (pc_default >= 0) {\n\t\t/* default case exists: go there if no case matches */\n\t\tduk__patch_jump(comp_ctx, pc_prevcase, pc_default);\n\t} else {\n\t\t/* default case does not exist, or no statements present\n\t\t * after default case: finish case evaluation\n\t\t */\n\t\tduk__patch_jump_here(comp_ctx, pc_prevcase);\n\t}\n\n\t/* fall-through control flow patchup; note that pc_prevstmt may be\n\t * < 0 (i.e. no case clauses), in which case this is a no-op.\n\t */\n\tduk__patch_jump_here(comp_ctx, pc_prevstmt);\n\n\t/* continue jump not patched, an INVALID opcode remains there */\n\tduk__patch_jump_here(comp_ctx, pc_label_site + 1);  /* break jump */\n\n\t/* Note: 'fast' breaks will jump to pc_label_site + 1, which will\n\t * then jump here.  The double jump will be eliminated by a\n\t * peephole pass, resulting in an optimal jump here.  The label\n\t * site jumps will remain in bytecode and will waste code size.\n\t */\n\n\treturn;\n\n syntax_error:\n\tDUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_SWITCH);\n}\n\nDUK_LOCAL void duk__parse_if_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {\n\tduk_regconst_t temp_reset;\n\tduk_regconst_t rc_cond;\n\tduk_int_t pc_jump_false;\n\n\tDUK_DDD(DUK_DDDPRINT(\"begin parsing if statement\"));\n\n\ttemp_reset = DUK__GETTEMP(comp_ctx);\n\n\tduk__advance(comp_ctx);  /* eat 'if' */\n\tduk__advance_expect(comp_ctx, DUK_TOK_LPAREN);\n\n\trc_cond = duk__exprtop_toregconst(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);\n\tduk__emit_if_true_skip(comp_ctx, rc_cond);\n\tpc_jump_false = duk__emit_jump_empty(comp_ctx);  /* jump to end or else part */\n\tDUK__SETTEMP(comp_ctx, temp_reset);\n\n\tduk__advance_expect(comp_ctx, DUK_TOK_RPAREN);\n\n\tduk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);\n\n\t/* The 'else' ambiguity is resolved by 'else' binding to the innermost\n\t * construct, so greedy matching is correct here.\n\t */\n\n\tif (comp_ctx->curr_token.t == DUK_TOK_ELSE) {\n\t\tduk_int_t pc_jump_end;\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"if has else part\"));\n\n\t\tduk__advance(comp_ctx);\n\n\t\tpc_jump_end = duk__emit_jump_empty(comp_ctx);  /* jump from true part to end */\n\t\tduk__patch_jump_here(comp_ctx, pc_jump_false);\n\n\t\tduk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);\n\n\t\tduk__patch_jump_here(comp_ctx, pc_jump_end);\n\t} else {\n\t\tDUK_DDD(DUK_DDDPRINT(\"if does not have else part\"));\n\n\t\tduk__patch_jump_here(comp_ctx, pc_jump_false);\n\t}\n\n\tDUK_DDD(DUK_DDDPRINT(\"end parsing if statement\"));\n}\n\nDUK_LOCAL void duk__parse_do_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site) {\n\tduk_regconst_t rc_cond;\n\tduk_int_t pc_start;\n\n\tDUK_DDD(DUK_DDDPRINT(\"begin parsing do statement\"));\n\n\tduk__advance(comp_ctx);  /* eat 'do' */\n\n\tpc_start = duk__get_current_pc(comp_ctx);\n\tduk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);\n\tduk__patch_jump_here(comp_ctx, pc_label_site + 2);  /* continue jump */\n\n\tduk__advance_expect(comp_ctx, DUK_TOK_WHILE);\n\tduk__advance_expect(comp_ctx, DUK_TOK_LPAREN);\n\n\trc_cond = duk__exprtop_toregconst(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);\n\tduk__emit_if_false_skip(comp_ctx, rc_cond);\n\tduk__emit_jump(comp_ctx, pc_start);\n\t/* no need to reset temps, as we're finished emitting code */\n\n\tduk__advance_expect(comp_ctx, DUK_TOK_RPAREN);\n\n\tduk__patch_jump_here(comp_ctx, pc_label_site + 1);  /* break jump */\n\n\tDUK_DDD(DUK_DDDPRINT(\"end parsing do statement\"));\n}\n\nDUK_LOCAL void duk__parse_while_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site) {\n\tduk_regconst_t temp_reset;\n\tduk_regconst_t rc_cond;\n\tduk_int_t pc_start;\n\tduk_int_t pc_jump_false;\n\n\tDUK_DDD(DUK_DDDPRINT(\"begin parsing while statement\"));\n\n\ttemp_reset = DUK__GETTEMP(comp_ctx);\n\n\tduk__advance(comp_ctx);  /* eat 'while' */\n\n\tduk__advance_expect(comp_ctx, DUK_TOK_LPAREN);\n\n\tpc_start = duk__get_current_pc(comp_ctx);\n\tduk__patch_jump_here(comp_ctx, pc_label_site + 2);  /* continue jump */\n\n\trc_cond = duk__exprtop_toregconst(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);\n\tduk__emit_if_true_skip(comp_ctx, rc_cond);\n\tpc_jump_false = duk__emit_jump_empty(comp_ctx);\n\tDUK__SETTEMP(comp_ctx, temp_reset);\n\n\tduk__advance_expect(comp_ctx, DUK_TOK_RPAREN);\n\n\tduk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);\n\tduk__emit_jump(comp_ctx, pc_start);\n\n\tduk__patch_jump_here(comp_ctx, pc_jump_false);\n\tduk__patch_jump_here(comp_ctx, pc_label_site + 1);  /* break jump */\n\n\tDUK_DDD(DUK_DDDPRINT(\"end parsing while statement\"));\n}\n\nDUK_LOCAL void duk__parse_break_or_continue_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {\n\tduk_hthread *thr = comp_ctx->thr;\n\tduk_bool_t is_break = (comp_ctx->curr_token.t == DUK_TOK_BREAK);\n\tduk_int_t label_id;\n\tduk_int_t label_catch_depth;\n\tduk_int_t label_pc;  /* points to LABEL; pc+1 = jump site for break; pc+2 = jump site for continue */\n\tduk_bool_t label_is_closest;\n\n\tDUK_UNREF(res);\n\n\tduk__advance(comp_ctx);  /* eat 'break' or 'continue' */\n\n\tif (comp_ctx->curr_token.t == DUK_TOK_SEMICOLON ||  /* explicit semi follows */\n\t    comp_ctx->curr_token.lineterm ||                /* automatic semi will be inserted */\n\t    comp_ctx->curr_token.allow_auto_semi) {         /* automatic semi will be inserted */\n\t\t/* break/continue without label */\n\n\t\tduk__lookup_active_label(comp_ctx, DUK_HTHREAD_STRING_EMPTY_STRING(thr), is_break, &label_id, &label_catch_depth, &label_pc, &label_is_closest);\n\t} else if (comp_ctx->curr_token.t == DUK_TOK_IDENTIFIER) {\n\t\t/* break/continue with label (label cannot be a reserved word, production is 'Identifier' */\n\t\tDUK_ASSERT(comp_ctx->curr_token.str1 != NULL);\n\t\tduk__lookup_active_label(comp_ctx, comp_ctx->curr_token.str1, is_break, &label_id, &label_catch_depth, &label_pc, &label_is_closest);\n\t\tduk__advance(comp_ctx);\n\t} else {\n\t\tDUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_BREAK_CONT_LABEL);\n\t}\n\n\t/* Use a fast break/continue when possible.  A fast break/continue is\n\t * just a jump to the LABEL break/continue jump slot, which then jumps\n\t * to an appropriate place (for break, going through ENDLABEL correctly).\n\t * The peephole optimizer will optimize the jump to a direct one.\n\t */\n\n\tif (label_catch_depth == comp_ctx->curr_func.catch_depth &&\n\t    label_is_closest) {\n\t\tDUK_DDD(DUK_DDDPRINT(\"break/continue: is_break=%ld, label_id=%ld, label_is_closest=%ld, \"\n\t\t                     \"label_catch_depth=%ld, catch_depth=%ld \"\n\t\t                     \"-> use fast variant (direct jump)\",\n\t\t                     (long) is_break, (long) label_id, (long) label_is_closest,\n\t\t                     (long) label_catch_depth, (long) comp_ctx->curr_func.catch_depth));\n\n\t\tduk__emit_jump(comp_ctx, label_pc + (is_break ? 1 : 2));\n\t} else {\n\t\tDUK_DDD(DUK_DDDPRINT(\"break/continue: is_break=%ld, label_id=%ld, label_is_closest=%ld, \"\n\t\t                     \"label_catch_depth=%ld, catch_depth=%ld \"\n\t\t                     \"-> use slow variant (longjmp)\",\n\t\t                     (long) is_break, (long) label_id, (long) label_is_closest,\n\t\t                     (long) label_catch_depth, (long) comp_ctx->curr_func.catch_depth));\n\n\t\tduk__emit_bc(comp_ctx,\n\t\t             is_break ? DUK_OP_BREAK : DUK_OP_CONTINUE,\n\t\t             (duk_regconst_t) label_id);\n\t}\n}\n\nDUK_LOCAL void duk__parse_return_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {\n\tduk_hthread *thr = comp_ctx->thr;\n\tduk_regconst_t rc_val;\n\n\tduk__advance(comp_ctx);  /* eat 'return' */\n\n\t/* A 'return' statement is only allowed inside an actual function body,\n\t * not as part of eval or global code.\n\t */\n\tif (!comp_ctx->curr_func.is_function) {\n\t\tDUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_RETURN);\n\t}\n\n\tif (comp_ctx->curr_token.t == DUK_TOK_SEMICOLON ||  /* explicit semi follows */\n\t    comp_ctx->curr_token.lineterm ||                /* automatic semi will be inserted */\n\t    comp_ctx->curr_token.allow_auto_semi) {         /* automatic semi will be inserted */\n\t\tDUK_DDD(DUK_DDDPRINT(\"empty return value -> undefined\"));\n\t\tduk__emit_op_only(comp_ctx, DUK_OP_RETUNDEF);\n\t} else {\n\t\tduk_int_t pc_before_expr;\n\t\tduk_int_t pc_after_expr;\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"return with a value\"));\n\n\t\tDUK_UNREF(pc_before_expr);\n\t\tDUK_UNREF(pc_after_expr);\n\n\t\tpc_before_expr = duk__get_current_pc(comp_ctx);\n\t\trc_val = duk__exprtop_toregconst(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);\n\t\tpc_after_expr = duk__get_current_pc(comp_ctx);\n\n\t\t/* Tail call check: if last opcode emitted was CALL, and\n\t\t * the context allows it, add a tailcall flag to the CALL.\n\t\t * This doesn't guarantee that a tail call will be allowed at\n\t\t * runtime, so the RETURN must still be emitted.  (Duktape\n\t\t * 0.10.0 avoided this and simulated a RETURN if a tail call\n\t\t * couldn't be used at runtime; but this didn't work\n\t\t * correctly with a thread yield/resume, see\n\t\t * test-bug-tailcall-thread-yield-resume.js for discussion.)\n\t\t *\n\t\t * In addition to the last opcode being CALL, we also need to\n\t\t * be sure that 'rc_val' is the result register of the CALL.\n\t\t * For instance, for the expression 'return 0, (function ()\n\t\t * { return 1; }), 2' the last opcode emitted is CALL (no\n\t\t * bytecode is emitted for '2') but 'rc_val' indicates\n\t\t * constant '2'.  Similarly if '2' is replaced by a register\n\t\t * bound variable, no opcodes are emitted but tail call would\n\t\t * be incorrect.\n\t\t *\n\t\t * This is tricky and easy to get wrong.  It would be best to\n\t\t * track enough expression metadata to check that 'rc_val' came\n\t\t * from that last CALL instruction.  We don't have that metadata\n\t\t * now, so we check that 'rc_val' is a temporary register result\n\t\t * (not a constant or a register bound variable).  There should\n\t\t * be no way currently for 'rc_val' to be a temporary for an\n\t\t * expression following the CALL instruction without emitting\n\t\t * some opcodes following the CALL.  This proxy check is used\n\t\t * below.\n\t\t *\n\t\t * See: test-bug-comma-expr-gh131.js.\n\t\t *\n\t\t * The non-standard 'caller' property disables tail calls\n\t\t * because they pose some special cases which haven't been\n\t\t * fixed yet.\n\t\t */\n\n#if defined(DUK_USE_TAILCALL)\n\t\tif (comp_ctx->curr_func.catch_depth == 0 &&   /* no catchers */\n\t\t    pc_after_expr > pc_before_expr) {         /* at least one opcode emitted */\n\t\t\tduk_compiler_instr *instr;\n\t\t\tduk_instr_t ins;\n\t\t\tduk_small_uint_t op;\n\n\t\t\tinstr = duk__get_instr_ptr(comp_ctx, pc_after_expr - 1);\n\t\t\tDUK_ASSERT(instr != NULL);\n\n\t\t\tins = instr->ins;\n\t\t\top = (duk_small_uint_t) DUK_DEC_OP(ins);\n\t\t\tif ((op & ~0x0fU) == DUK_OP_CALL0 &&\n\t\t\t    DUK__ISREG_TEMP(comp_ctx, rc_val) /* see above */) {\n\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"return statement detected a tail call opportunity: \"\n\t\t\t\t                     \"catch depth is 0, duk__exprtop() emitted >= 1 instructions, \"\n\t\t\t\t                     \"and last instruction is a CALL \"\n\t\t\t\t                     \"-> change to TAILCALL\"));\n\t\t\t\tins |= DUK_ENC_OP(DUK_BC_CALL_FLAG_TAILCALL);\n\t\t\t\tinstr->ins = ins;\n\t\t\t}\n\t\t}\n#endif  /* DUK_USE_TAILCALL */\n\n\t\tif (DUK__ISREG(rc_val)) {\n\t\t\tduk__emit_bc(comp_ctx, DUK_OP_RETREG, rc_val);\n\t\t} else {\n\t\t\trc_val = DUK__REMOVECONST(rc_val);\n\t\t\tif (duk__const_needs_refcount(comp_ctx, rc_val)) {\n\t\t\t\tduk__emit_bc(comp_ctx, DUK_OP_RETCONST, rc_val);\n\t\t\t} else {\n\t\t\t\tduk__emit_bc(comp_ctx, DUK_OP_RETCONSTN, rc_val);\n\t\t\t}\n\t\t}\n\t}\n}\n\nDUK_LOCAL void duk__parse_throw_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {\n\tduk_regconst_t reg_val;\n\n\tduk__advance(comp_ctx);  /* eat 'throw' */\n\n\t/* Unlike break/continue, throw statement does not allow an empty value. */\n\n\tif (comp_ctx->curr_token.lineterm) {\n\t\tDUK_ERROR_SYNTAX(comp_ctx->thr, DUK_STR_INVALID_THROW);\n\t}\n\n\treg_val = duk__exprtop_toreg(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);\n\tduk__emit_bc(comp_ctx,\n\t             DUK_OP_THROW,\n\t             reg_val);\n}\n\nDUK_LOCAL void duk__parse_try_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {\n\tduk_hthread *thr = comp_ctx->thr;\n\tduk_regconst_t reg_catch;      /* reg_catch+0 and reg_catch+1 are reserved for TRYCATCH */\n\tduk_regconst_t rc_varname = 0;\n\tduk_small_uint_t trycatch_flags = 0;\n\tduk_int_t pc_ldconst = -1;\n\tduk_int_t pc_trycatch = -1;\n\tduk_int_t pc_catch = -1;\n\tduk_int_t pc_finally = -1;\n\n\tDUK_UNREF(res);\n\n\t/*\n\t *  See the following documentation for discussion:\n\t *\n\t *    doc/execution.rst: control flow details\n\t *\n\t *  Try, catch, and finally \"parts\" are Blocks, not Statements, so\n\t *  they must always be delimited by curly braces.  This is unlike e.g.\n\t *  the if statement, which accepts any Statement.  This eliminates any\n\t *  questions of matching parts of nested try statements.  The Block\n\t *  parsing is implemented inline here (instead of calling out).\n\t *\n\t *  Finally part has a 'let scoped' variable, which requires a few kinks\n\t *  here.\n\t */\n\n\tcomp_ctx->curr_func.catch_depth++;\n\n\tduk__advance(comp_ctx);  /* eat 'try' */\n\n\treg_catch = DUK__ALLOCTEMPS(comp_ctx, 2);\n\n\t/* The target for this LDCONST may need output shuffling, but we assume\n\t * that 'pc_ldconst' will be the LDCONST that we can patch later.  This\n\t * should be the case because there's no input shuffling.  (If there's\n\t * no catch clause, this LDCONST will be replaced with a NOP.)\n\t */\n\tpc_ldconst = duk__get_current_pc(comp_ctx);\n\tduk__emit_a_bc(comp_ctx, DUK_OP_LDCONST, reg_catch, 0 /*patched later*/);\n\n\tpc_trycatch = duk__get_current_pc(comp_ctx);\n\tduk__emit_invalid(comp_ctx);  /* TRYCATCH, cannot emit now (not enough info) */\n\tduk__emit_invalid(comp_ctx);  /* jump for 'catch' case */\n\tduk__emit_invalid(comp_ctx);  /* jump for 'finally' case or end (if no finally) */\n\n\t/* try part */\n\tduk__advance_expect(comp_ctx, DUK_TOK_LCURLY);\n\tduk__parse_stmts(comp_ctx, 0 /*allow_source_elem*/, 0 /*expect_eof*/);\n\t/* the DUK_TOK_RCURLY is eaten by duk__parse_stmts() */\n\tduk__emit_op_only(comp_ctx,\n\t                  DUK_OP_ENDTRY);\n\n\tif (comp_ctx->curr_token.t == DUK_TOK_CATCH) {\n\t\t/*\n\t\t *  The catch variable must be updated to reflect the new allocated\n\t\t *  register for the duration of the catch clause.  We need to store\n\t\t *  and restore the original value for the varmap entry (if any).\n\t\t */\n\n\t\t/*\n\t\t *  Note: currently register bindings must be fixed for the entire\n\t\t *  function.  So, even though the catch variable is in a register\n\t\t *  we know, we must use an explicit environment record and slow path\n\t\t *  accesses to read/write the catch binding to make closures created\n\t\t *  within the catch clause work correctly.  This restriction should\n\t\t *  be fixable (at least in common cases) later.\n\t\t *\n\t\t *  See: test-bug-catch-binding-2.js.\n\t\t *\n\t\t *  XXX: improve to get fast path access to most catch clauses.\n\t\t */\n\n\t\tduk_hstring *h_var;\n\t\tduk_int_t varmap_value;  /* for storing/restoring the varmap binding for catch variable */\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"stack top at start of catch clause: %ld\", (long) duk_get_top(thr)));\n\n\t\ttrycatch_flags |= DUK_BC_TRYCATCH_FLAG_HAVE_CATCH;\n\n\t\tpc_catch = duk__get_current_pc(comp_ctx);\n\n\t\tduk__advance(comp_ctx);\n\t\tduk__advance_expect(comp_ctx, DUK_TOK_LPAREN);\n\n\t\tif (comp_ctx->curr_token.t != DUK_TOK_IDENTIFIER) {\n\t\t\t/* Identifier, i.e. don't allow reserved words */\n\t\t\tgoto syntax_error;\n\t\t}\n\t\th_var = comp_ctx->curr_token.str1;\n\t\tDUK_ASSERT(h_var != NULL);\n\n\t\tduk_push_hstring(thr, h_var);  /* keep in on valstack, use borrowed ref below */\n\n\t\tif (comp_ctx->curr_func.is_strict &&\n\t\t    ((h_var == DUK_HTHREAD_STRING_EVAL(thr)) ||\n\t\t     (h_var == DUK_HTHREAD_STRING_LC_ARGUMENTS(thr)))) {\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"catch identifier 'eval' or 'arguments' in strict mode -> SyntaxError\"));\n\t\t\tgoto syntax_error;\n\t\t}\n\n\t\tduk_dup_top(thr);\n\t\trc_varname = duk__getconst(comp_ctx);\n\t\tDUK_DDD(DUK_DDDPRINT(\"catch clause, rc_varname=0x%08lx (%ld)\",\n\t\t                     (unsigned long) rc_varname, (long) rc_varname));\n\n\t\tduk__advance(comp_ctx);\n\t\tduk__advance_expect(comp_ctx, DUK_TOK_RPAREN);\n\n\t\tduk__advance_expect(comp_ctx, DUK_TOK_LCURLY);\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"varmap before modifying for catch clause: %!iT\",\n\t\t                     (duk_tval *) duk_get_tval(thr, comp_ctx->curr_func.varmap_idx)));\n\n\t\tduk_dup_top(thr);\n\t\tduk_get_prop(thr, comp_ctx->curr_func.varmap_idx);\n\t\tif (duk_is_undefined(thr, -1)) {\n\t\t\tvarmap_value = -2;\n\t\t} else if (duk_is_null(thr, -1)) {\n\t\t\tvarmap_value = -1;\n\t\t} else {\n\t\t\tDUK_ASSERT(duk_is_number(thr, -1));\n\t\t\tvarmap_value = duk_get_int(thr, -1);\n\t\t\tDUK_ASSERT(varmap_value >= 0);\n\t\t}\n\t\tduk_pop(thr);\n\n#if 0\n\t\t/* It'd be nice to do something like this - but it doesn't\n\t\t * work for closures created inside the catch clause.\n\t\t */\n\t\tduk_dup_top(thr);\n\t\tduk_push_int(thr, (duk_int_t) (reg_catch + 0));\n\t\tduk_put_prop(thr, comp_ctx->curr_func.varmap_idx);\n#endif\n\t\tduk_dup_top(thr);\n\t\tduk_push_null(thr);\n\t\tduk_put_prop(thr, comp_ctx->curr_func.varmap_idx);\n\n\t\tduk__emit_a_bc(comp_ctx,\n\t\t               DUK_OP_PUTVAR | DUK__EMIT_FLAG_A_IS_SOURCE,\n\t\t               reg_catch + 0 /*value*/,\n\t\t               rc_varname /*varname*/);\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"varmap before parsing catch clause: %!iT\",\n\t\t                     (duk_tval *) duk_get_tval(thr, comp_ctx->curr_func.varmap_idx)));\n\n\t\tduk__parse_stmts(comp_ctx, 0 /*allow_source_elem*/, 0 /*expect_eof*/);\n\t\t/* the DUK_TOK_RCURLY is eaten by duk__parse_stmts() */\n\n\t\tif (varmap_value == -2) {\n\t\t\t/* not present */\n\t\t\tduk_del_prop(thr, comp_ctx->curr_func.varmap_idx);\n\t\t} else {\n\t\t\tif (varmap_value == -1) {\n\t\t\t\tduk_push_null(thr);\n\t\t\t} else {\n\t\t\t\tDUK_ASSERT(varmap_value >= 0);\n\t\t\t\tduk_push_int(thr, varmap_value);\n\t\t\t}\n\t\t\tduk_put_prop(thr, comp_ctx->curr_func.varmap_idx);\n\t\t}\n\t\t/* varname is popped by above code */\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"varmap after restore catch clause: %!iT\",\n\t\t                     (duk_tval *) duk_get_tval(thr, comp_ctx->curr_func.varmap_idx)));\n\n\t\tduk__emit_op_only(comp_ctx,\n\t\t                  DUK_OP_ENDCATCH);\n\n\t\t/*\n\t\t *  XXX: for now, indicate that an expensive catch binding\n\t\t *  declarative environment is always needed.  If we don't\n\t\t *  need it, we don't need the const_varname either.\n\t\t */\n\n\t\ttrycatch_flags |= DUK_BC_TRYCATCH_FLAG_CATCH_BINDING;\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"stack top at end of catch clause: %ld\", (long) duk_get_top(thr)));\n\t}\n\n\tif (comp_ctx->curr_token.t == DUK_TOK_FINALLY) {\n\t\ttrycatch_flags |= DUK_BC_TRYCATCH_FLAG_HAVE_FINALLY;\n\n\t\tpc_finally = duk__get_current_pc(comp_ctx);\n\n\t\tduk__advance(comp_ctx);\n\n\t\tduk__advance_expect(comp_ctx, DUK_TOK_LCURLY);\n\t\tduk__parse_stmts(comp_ctx, 0 /*allow_source_elem*/, 0 /*expect_eof*/);\n\t\t/* the DUK_TOK_RCURLY is eaten by duk__parse_stmts() */\n\t\tduk__emit_abc(comp_ctx,\n\t\t              DUK_OP_ENDFIN,\n\t\t              reg_catch);  /* rethrow */\n\t}\n\n\tif (!(trycatch_flags & DUK_BC_TRYCATCH_FLAG_HAVE_CATCH) &&\n\t    !(trycatch_flags & DUK_BC_TRYCATCH_FLAG_HAVE_FINALLY)) {\n\t\t/* must have catch and/or finally */\n\t\tgoto syntax_error;\n\t}\n\n\t/* If there's no catch block, rc_varname will be 0 and duk__patch_trycatch()\n\t * will replace the LDCONST with a NOP.  For any actual constant (including\n\t * constant 0) the DUK__CONST_MARKER flag will be set in rc_varname.\n\t */\n\n\tduk__patch_trycatch(comp_ctx,\n\t                    pc_ldconst,\n\t                    pc_trycatch,\n\t                    reg_catch,\n\t                    rc_varname,\n\t                    trycatch_flags);\n\n\tif (trycatch_flags & DUK_BC_TRYCATCH_FLAG_HAVE_CATCH) {\n\t\tDUK_ASSERT(pc_catch >= 0);\n\t\tduk__patch_jump(comp_ctx, pc_trycatch + 1, pc_catch);\n\t}\n\n\tif (trycatch_flags & DUK_BC_TRYCATCH_FLAG_HAVE_FINALLY) {\n\t\tDUK_ASSERT(pc_finally >= 0);\n\t\tduk__patch_jump(comp_ctx, pc_trycatch + 2, pc_finally);\n\t} else {\n\t\t/* without finally, the second jump slot is used to jump to end of stmt */\n\t\tduk__patch_jump_here(comp_ctx, pc_trycatch + 2);\n\t}\n\n\tcomp_ctx->curr_func.catch_depth--;\n\treturn;\n\n syntax_error:\n\tDUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_TRY);\n}\n\nDUK_LOCAL void duk__parse_with_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {\n\tduk_int_t pc_trycatch;\n\tduk_int_t pc_finished;\n\tduk_regconst_t reg_catch;\n\tduk_small_uint_t trycatch_flags;\n\n\tif (comp_ctx->curr_func.is_strict) {\n\t\tDUK_ERROR_SYNTAX(comp_ctx->thr, DUK_STR_WITH_IN_STRICT_MODE);\n\t}\n\n\tcomp_ctx->curr_func.catch_depth++;\n\n\tduk__advance(comp_ctx);  /* eat 'with' */\n\n\treg_catch = DUK__ALLOCTEMPS(comp_ctx, 2);\n\n\tduk__advance_expect(comp_ctx, DUK_TOK_LPAREN);\n\tduk__exprtop_toforcedreg(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/, reg_catch);\n\tduk__advance_expect(comp_ctx, DUK_TOK_RPAREN);\n\n\tpc_trycatch = duk__get_current_pc(comp_ctx);\n\ttrycatch_flags = DUK_BC_TRYCATCH_FLAG_WITH_BINDING;\n\tduk__emit_a_bc(comp_ctx,\n\t                DUK_OP_TRYCATCH | DUK__EMIT_FLAG_NO_SHUFFLE_A,\n\t                (duk_regconst_t) trycatch_flags /*a*/,\n\t                reg_catch /*bc*/);\n\tduk__emit_invalid(comp_ctx);  /* catch jump */\n\tduk__emit_invalid(comp_ctx);  /* finished jump */\n\n\tduk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);\n\tduk__emit_op_only(comp_ctx,\n\t                  DUK_OP_ENDTRY);\n\n\tpc_finished = duk__get_current_pc(comp_ctx);\n\n\tduk__patch_jump(comp_ctx, pc_trycatch + 2, pc_finished);\n\n\tcomp_ctx->curr_func.catch_depth--;\n}\n\nDUK_LOCAL duk_int_t duk__stmt_label_site(duk_compiler_ctx *comp_ctx, duk_int_t label_id) {\n\t/* if a site already exists, nop: max one label site per statement */\n\tif (label_id >= 0) {\n\t\treturn label_id;\n\t}\n\n\tlabel_id = comp_ctx->curr_func.label_next++;\n\tDUK_DDD(DUK_DDDPRINT(\"allocated new label id for label site: %ld\", (long) label_id));\n\n\tduk__emit_bc(comp_ctx,\n\t             DUK_OP_LABEL,\n\t             (duk_regconst_t) label_id);\n\tduk__emit_invalid(comp_ctx);\n\tduk__emit_invalid(comp_ctx);\n\n\treturn label_id;\n}\n\n/* Parse a single statement.\n *\n * Creates a label site (with an empty label) automatically for iteration\n * statements.  Also \"peels off\" any label statements for explicit labels.\n */\nDUK_LOCAL void duk__parse_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_bool_t allow_source_elem) {\n\tduk_hthread *thr = comp_ctx->thr;\n\tduk_bool_t dir_prol_at_entry;    /* directive prologue status at entry */\n\tduk_regconst_t temp_at_entry;\n\tduk_size_t labels_len_at_entry;\n\tduk_int_t pc_at_entry;           /* assumed to also be PC of \"LABEL\" */\n\tduk_int_t stmt_id;\n\tduk_small_uint_t stmt_flags = 0;\n\tduk_int_t label_id = -1;\n\tduk_small_uint_t tok;\n\tduk_bool_t test_func_decl;\n\n\tDUK__RECURSION_INCREASE(comp_ctx, thr);\n\n\ttemp_at_entry = DUK__GETTEMP(comp_ctx);\n\tpc_at_entry = duk__get_current_pc(comp_ctx);\n\tlabels_len_at_entry = duk_get_length(thr, comp_ctx->curr_func.labelnames_idx);\n\tstmt_id = comp_ctx->curr_func.stmt_next++;\n\tdir_prol_at_entry = comp_ctx->curr_func.in_directive_prologue;\n\n\tDUK_UNREF(stmt_id);\n\n\tDUK_DDD(DUK_DDDPRINT(\"parsing a statement, stmt_id=%ld, temp_at_entry=%ld, labels_len_at_entry=%ld, \"\n\t                     \"is_strict=%ld, in_directive_prologue=%ld, catch_depth=%ld\",\n\t                     (long) stmt_id, (long) temp_at_entry, (long) labels_len_at_entry,\n\t                     (long) comp_ctx->curr_func.is_strict, (long) comp_ctx->curr_func.in_directive_prologue,\n\t                     (long) comp_ctx->curr_func.catch_depth));\n\n\t/* The directive prologue flag is cleared by default so that it is\n\t * unset for any recursive statement parsing.  It is only \"revived\"\n\t * if a directive is detected.  (We could also make directives only\n\t * allowed if 'allow_source_elem' was true.)\n\t */\n\tcomp_ctx->curr_func.in_directive_prologue = 0;\n\n retry_parse:\n\n\tDUK_DDD(DUK_DDDPRINT(\"try stmt parse, stmt_id=%ld, label_id=%ld, allow_source_elem=%ld, catch_depth=%ld\",\n\t                     (long) stmt_id, (long) label_id, (long) allow_source_elem,\n\t                     (long) comp_ctx->curr_func.catch_depth));\n\n\t/*\n\t *  Detect iteration statements; if encountered, establish an\n\t *  empty label.\n\t */\n\n\ttok = comp_ctx->curr_token.t;\n\tif (tok == DUK_TOK_FOR || tok == DUK_TOK_DO || tok == DUK_TOK_WHILE ||\n\t    tok == DUK_TOK_SWITCH) {\n\t\tDUK_DDD(DUK_DDDPRINT(\"iteration/switch statement -> add empty label\"));\n\n\t\tlabel_id = duk__stmt_label_site(comp_ctx, label_id);\n\t\tduk__add_label(comp_ctx,\n\t\t               DUK_HTHREAD_STRING_EMPTY_STRING(thr),\n\t\t               pc_at_entry /*pc_label*/,\n\t\t               label_id);\n\t}\n\n\t/*\n\t *  Main switch for statement / source element type.\n\t */\n\n\tswitch (comp_ctx->curr_token.t) {\n\tcase DUK_TOK_FUNCTION: {\n\t\t/*\n\t\t *  Function declaration, function expression, or (non-standard)\n\t\t *  function statement.\n\t\t *\n\t\t *  The E5 specification only allows function declarations at\n\t\t *  the top level (in \"source elements\").  An ExpressionStatement\n\t\t *  is explicitly not allowed to begin with a \"function\" keyword\n\t\t *  (E5 Section 12.4).  Hence any non-error semantics for such\n\t\t *  non-top-level statements are non-standard.  Duktape semantics\n\t\t *  for function statements are modelled after V8, see\n\t\t *  test-dev-func-decl-outside-top.js.\n\t\t */\n\t\ttest_func_decl = allow_source_elem;\n#if defined(DUK_USE_NONSTD_FUNC_STMT)\n\t\t/* Lenient: allow function declarations outside top level in\n\t\t * non-strict mode but reject them in strict mode.\n\t\t */\n\t\ttest_func_decl = test_func_decl || !comp_ctx->curr_func.is_strict;\n#endif  /* DUK_USE_NONSTD_FUNC_STMT */\n\t\t/* Strict: never allow function declarations outside top level. */\n\t\tif (test_func_decl) {\n\t\t\t/* FunctionDeclaration: not strictly a statement but handled as such.\n\t\t\t *\n\t\t\t * O(depth^2) parse count for inner functions is handled by recording a\n\t\t\t * lexer offset on the first compilation pass, so that the function can\n\t\t\t * be efficiently skipped on the second pass.  This is encapsulated into\n\t\t\t * duk__parse_func_like_fnum().\n\t\t\t */\n\n\t\t\tduk_int_t fnum;\n#if defined(DUK_USE_ASSERTIONS)\n\t\t\tduk_idx_t top_before;\n#endif\n\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"function declaration statement\"));\n\n#if defined(DUK_USE_ASSERTIONS)\n\t\t\ttop_before = duk_get_top(thr);\n#endif\n\n\t\t\tduk__advance(comp_ctx);  /* eat 'function' */\n\t\t\tfnum = duk__parse_func_like_fnum(comp_ctx, DUK__FUNC_FLAG_DECL | DUK__FUNC_FLAG_PUSHNAME_PASS1);\n\n\t\t\t/* The value stack convention here is a bit odd: the function\n\t\t\t * name is only pushed on pass 1 (in_scanning), and is needed\n\t\t\t * to process function declarations.\n\t\t\t */\n\t\t\tif (comp_ctx->curr_func.in_scanning) {\n\t\t\t\tduk_uarridx_t n;\n\n#if defined(DUK_USE_ASSERTIONS)\n\t\t\t\tDUK_ASSERT(duk_get_top(thr) == top_before + 1);\n#endif\n\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"register function declaration %!T in pass 1, fnum %ld\",\n\t\t\t\t                     duk_get_tval(thr, -1), (long) fnum));\n\t\t\t\tn = (duk_uarridx_t) duk_get_length(thr, comp_ctx->curr_func.decls_idx);\n\t\t\t\t/* funcname is at index -1 */\n\t\t\t\tduk_put_prop_index(thr, comp_ctx->curr_func.decls_idx, n);\n\t\t\t\tduk_push_int(thr, (duk_int_t) (DUK_DECL_TYPE_FUNC + (fnum << 8)));\n\t\t\t\tduk_put_prop_index(thr, comp_ctx->curr_func.decls_idx, n + 1);\n\t\t\t} else {\n#if defined(DUK_USE_ASSERTIONS)\n\t\t\t\tDUK_ASSERT(duk_get_top(thr) == top_before);\n#endif\n\t\t\t}\n\n\t\t\t/* no statement value (unlike function expression) */\n\t\t\tstmt_flags = 0;\n\t\t\tbreak;\n\t\t} else {\n\t\t\tDUK_ERROR_SYNTAX(thr, DUK_STR_FUNC_STMT_NOT_ALLOWED);\n\t\t}\n\t\tbreak;\n\t}\n\tcase DUK_TOK_LCURLY: {\n\t\tDUK_DDD(DUK_DDDPRINT(\"block statement\"));\n\t\tduk__advance(comp_ctx);\n\t\tduk__parse_stmts(comp_ctx, 0 /*allow_source_elem*/, 0 /*expect_eof*/);\n\t\t/* the DUK_TOK_RCURLY is eaten by duk__parse_stmts() */\n\t\tif (label_id >= 0) {\n\t\t\tduk__patch_jump_here(comp_ctx, pc_at_entry + 1);  /* break jump */\n\t\t}\n\t\tstmt_flags = 0;\n\t\tbreak;\n\t}\n\tcase DUK_TOK_CONST: {\n\t\tDUK_DDD(DUK_DDDPRINT(\"constant declaration statement\"));\n\t\tduk__parse_var_stmt(comp_ctx, res, DUK__EXPR_FLAG_REQUIRE_INIT /*expr_flags*/);\n\t\tstmt_flags = DUK__HAS_TERM;\n\t\tbreak;\n\t}\n\tcase DUK_TOK_VAR: {\n\t\tDUK_DDD(DUK_DDDPRINT(\"variable declaration statement\"));\n\t\tduk__parse_var_stmt(comp_ctx, res, 0 /*expr_flags*/);\n\t\tstmt_flags = DUK__HAS_TERM;\n\t\tbreak;\n\t}\n\tcase DUK_TOK_SEMICOLON: {\n\t\t/* empty statement with an explicit semicolon */\n\t\tDUK_DDD(DUK_DDDPRINT(\"empty statement\"));\n\t\tstmt_flags = DUK__HAS_TERM;\n\t\tbreak;\n\t}\n\tcase DUK_TOK_IF: {\n\t\tDUK_DDD(DUK_DDDPRINT(\"if statement\"));\n\t\tduk__parse_if_stmt(comp_ctx, res);\n\t\tif (label_id >= 0) {\n\t\t\tduk__patch_jump_here(comp_ctx, pc_at_entry + 1);  /* break jump */\n\t\t}\n\t\tstmt_flags = 0;\n\t\tbreak;\n\t}\n\tcase DUK_TOK_DO: {\n\t\t/*\n\t\t *  Do-while statement is mostly trivial, but there is special\n\t\t *  handling for automatic semicolon handling (triggered by the\n\t\t *  DUK__ALLOW_AUTO_SEMI_ALWAYS) flag related to a bug filed at:\n\t\t *\n\t\t *    https://bugs.ecmascript.org/show_bug.cgi?id=8\n\t\t *\n\t\t *  See doc/compiler.rst for details.\n\t\t */\n\t\tDUK_DDD(DUK_DDDPRINT(\"do statement\"));\n\t\tDUK_ASSERT(label_id >= 0);\n\t\tduk__update_label_flags(comp_ctx,\n\t\t                        label_id,\n\t\t                        DUK_LABEL_FLAG_ALLOW_BREAK | DUK_LABEL_FLAG_ALLOW_CONTINUE);\n\t\tduk__parse_do_stmt(comp_ctx, res, pc_at_entry);\n\t\tstmt_flags = DUK__HAS_TERM | DUK__ALLOW_AUTO_SEMI_ALWAYS;  /* DUK__ALLOW_AUTO_SEMI_ALWAYS workaround */\n\t\tbreak;\n\t}\n\tcase DUK_TOK_WHILE: {\n\t\tDUK_DDD(DUK_DDDPRINT(\"while statement\"));\n\t\tDUK_ASSERT(label_id >= 0);\n\t\tduk__update_label_flags(comp_ctx,\n\t\t                        label_id,\n\t\t                        DUK_LABEL_FLAG_ALLOW_BREAK | DUK_LABEL_FLAG_ALLOW_CONTINUE);\n\t\tduk__parse_while_stmt(comp_ctx, res, pc_at_entry);\n\t\tstmt_flags = 0;\n\t\tbreak;\n\t}\n\tcase DUK_TOK_FOR: {\n\t\t/*\n\t\t *  For/for-in statement is complicated to parse because\n\t\t *  determining the statement type (three-part for vs. a\n\t\t *  for-in) requires potential backtracking.\n\t\t *\n\t\t *  See the helper for the messy stuff.\n\t\t */\n\t\tDUK_DDD(DUK_DDDPRINT(\"for/for-in statement\"));\n\t\tDUK_ASSERT(label_id >= 0);\n\t\tduk__update_label_flags(comp_ctx,\n\t\t                        label_id,\n\t\t                        DUK_LABEL_FLAG_ALLOW_BREAK | DUK_LABEL_FLAG_ALLOW_CONTINUE);\n\t\tduk__parse_for_stmt(comp_ctx, res, pc_at_entry);\n\t\tstmt_flags = 0;\n\t\tbreak;\n\t}\n\tcase DUK_TOK_CONTINUE:\n\tcase DUK_TOK_BREAK: {\n\t\tDUK_DDD(DUK_DDDPRINT(\"break/continue statement\"));\n\t\tduk__parse_break_or_continue_stmt(comp_ctx, res);\n\t\tstmt_flags = DUK__HAS_TERM | DUK__IS_TERMINAL;\n\t\tbreak;\n\t}\n\tcase DUK_TOK_RETURN: {\n\t\tDUK_DDD(DUK_DDDPRINT(\"return statement\"));\n\t\tduk__parse_return_stmt(comp_ctx, res);\n\t\tstmt_flags = DUK__HAS_TERM | DUK__IS_TERMINAL;\n\t\tbreak;\n\t}\n\tcase DUK_TOK_WITH: {\n\t\tDUK_DDD(DUK_DDDPRINT(\"with statement\"));\n\t\tcomp_ctx->curr_func.with_depth++;\n\t\tduk__parse_with_stmt(comp_ctx, res);\n\t\tif (label_id >= 0) {\n\t\t\tduk__patch_jump_here(comp_ctx, pc_at_entry + 1);  /* break jump */\n\t\t}\n\t\tcomp_ctx->curr_func.with_depth--;\n\t\tstmt_flags = 0;\n\t\tbreak;\n\t}\n\tcase DUK_TOK_SWITCH: {\n\t\t/*\n\t\t *  The switch statement is pretty messy to compile.\n\t\t *  See the helper for details.\n\t\t */\n\t\tDUK_DDD(DUK_DDDPRINT(\"switch statement\"));\n\t\tDUK_ASSERT(label_id >= 0);\n\t\tduk__update_label_flags(comp_ctx,\n\t\t                        label_id,\n\t\t                        DUK_LABEL_FLAG_ALLOW_BREAK);  /* don't allow continue */\n\t\tduk__parse_switch_stmt(comp_ctx, res, pc_at_entry);\n\t\tstmt_flags = 0;\n\t\tbreak;\n\t}\n\tcase DUK_TOK_THROW: {\n\t\tDUK_DDD(DUK_DDDPRINT(\"throw statement\"));\n\t\tduk__parse_throw_stmt(comp_ctx, res);\n\t\tstmt_flags = DUK__HAS_TERM | DUK__IS_TERMINAL;\n\t\tbreak;\n\t}\n\tcase DUK_TOK_TRY: {\n\t\tDUK_DDD(DUK_DDDPRINT(\"try statement\"));\n\t\tduk__parse_try_stmt(comp_ctx, res);\n\t\tstmt_flags = 0;\n\t\tbreak;\n\t}\n\tcase DUK_TOK_DEBUGGER: {\n\t\tduk__advance(comp_ctx);\n#if defined(DUK_USE_DEBUGGER_SUPPORT)\n\t\tDUK_DDD(DUK_DDDPRINT(\"debugger statement: debugging enabled, emit debugger opcode\"));\n\t\tduk__emit_op_only(comp_ctx, DUK_OP_DEBUGGER);\n#else\n\t\tDUK_DDD(DUK_DDDPRINT(\"debugger statement: ignored\"));\n#endif\n\t\tstmt_flags = DUK__HAS_TERM;\n\t\tbreak;\n\t}\n\tdefault: {\n\t\t/*\n\t\t *  Else, must be one of:\n\t\t *    - ExpressionStatement, possibly a directive (String)\n\t\t *    - LabelledStatement (Identifier followed by ':')\n\t\t *\n\t\t *  Expressions beginning with 'function' keyword are covered by a case\n\t\t *  above (such expressions are not allowed in standard E5 anyway).\n\t\t *  Also expressions starting with '{' are interpreted as block\n\t\t *  statements.  See E5 Section 12.4.\n\t\t *\n\t\t *  Directive detection is tricky; see E5 Section 14.1 on directive\n\t\t *  prologue.  A directive is an expression statement with a single\n\t\t *  string literal and an explicit or automatic semicolon.  Escape\n\t\t *  characters are significant and no parens etc are allowed:\n\t\t *\n\t\t *    'use strict';          // valid 'use strict' directive\n\t\t *    'use\\u0020strict';     // valid directive, not a 'use strict' directive\n\t\t *    ('use strict');        // not a valid directive\n\t\t *\n\t\t *  The expression is determined to consist of a single string literal\n\t\t *  based on duk__expr_nud() and duk__expr_led() call counts.  The string literal\n\t\t *  of a 'use strict' directive is determined to lack any escapes based\n\t\t *  num_escapes count from the lexer.  Note that other directives may be\n\t\t *  allowed to contain escapes, so a directive with escapes does not\n\t\t *  terminate a directive prologue.\n\t\t *\n\t\t *  We rely on the fact that the expression parser will not emit any\n\t\t *  code for a single token expression.  However, it will generate an\n\t\t *  intermediate value which we will then successfully ignore.\n\t\t *\n\t\t *  A similar approach is used for labels.\n\t\t */\n\n\t\tduk_bool_t single_token;\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"expression statement\"));\n\t\tduk__exprtop(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);\n\n\t\tsingle_token = (comp_ctx->curr_func.nud_count == 1 &&  /* one token */\n\t\t                comp_ctx->curr_func.led_count == 0);   /* no operators */\n\n\t\tif (single_token &&\n\t\t    comp_ctx->prev_token.t == DUK_TOK_IDENTIFIER &&\n\t\t    comp_ctx->curr_token.t == DUK_TOK_COLON) {\n\t\t\t/*\n\t\t\t *  Detected label\n\t\t\t */\n\n\t\t\tduk_hstring *h_lab;\n\n\t\t\t/* expected ival */\n\t\t\tDUK_ASSERT(res->t == DUK_IVAL_VAR);\n\t\t\tDUK_ASSERT(res->x1.t == DUK_ISPEC_VALUE);\n\t\t\tDUK_ASSERT(DUK_TVAL_IS_STRING(duk_get_tval(thr, res->x1.valstack_idx)));\n\t\t\th_lab = comp_ctx->prev_token.str1;\n\t\t\tDUK_ASSERT(h_lab != NULL);\n\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"explicit label site for label '%!O'\",\n\t\t\t                     (duk_heaphdr *) h_lab));\n\n\t\t\tduk__advance(comp_ctx);  /* eat colon */\n\n\t\t\tlabel_id = duk__stmt_label_site(comp_ctx, label_id);\n\n\t\t\tduk__add_label(comp_ctx,\n\t\t\t               h_lab,\n\t\t\t               pc_at_entry /*pc_label*/,\n\t\t\t               label_id);\n\n\t\t\t/* a statement following a label cannot be a source element\n\t\t\t * (a function declaration).\n\t\t\t */\n\t\t\tallow_source_elem = 0;\n\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"label handled, retry statement parsing\"));\n\t\t\tgoto retry_parse;\n\t\t}\n\n\t\tstmt_flags = 0;\n\n\t\tif (dir_prol_at_entry &&                           /* still in prologue */\n\t\t    single_token &&                                /* single string token */\n\t\t    comp_ctx->prev_token.t == DUK_TOK_STRING) {\n\t\t\t/*\n\t\t\t *  Detected a directive\n\t\t\t */\n\t\t\tduk_hstring *h_dir;\n\n\t\t\t/* expected ival */\n\t\t\tDUK_ASSERT(res->t == DUK_IVAL_PLAIN);\n\t\t\tDUK_ASSERT(res->x1.t == DUK_ISPEC_VALUE);\n\t\t\tDUK_ASSERT(DUK_TVAL_IS_STRING(duk_get_tval(thr, res->x1.valstack_idx)));\n\t\t\th_dir = comp_ctx->prev_token.str1;\n\t\t\tDUK_ASSERT(h_dir != NULL);\n\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"potential directive: %!O\", h_dir));\n\n\t\t\tstmt_flags |= DUK__STILL_PROLOGUE;\n\n\t\t\t/* Note: escaped characters differentiate directives */\n\n\t\t\tif (comp_ctx->prev_token.num_escapes > 0) {\n\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"directive contains escapes: valid directive \"\n\t\t\t\t                     \"but we ignore such directives\"));\n\t\t\t} else {\n\t\t\t\t/*\n\t\t\t\t * The length comparisons are present to handle\n\t\t\t\t * strings like \"use strict\\u0000foo\" as required.\n\t\t\t\t */\n\n\t\t\t\tif (DUK_HSTRING_GET_BYTELEN(h_dir) == 10 &&\n\t\t\t\t    DUK_STRNCMP((const char *) DUK_HSTRING_GET_DATA(h_dir), \"use strict\", 10) == 0) {\n#if defined(DUK_USE_STRICT_DECL)\n\t\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"use strict directive detected: strict flag %ld -> %ld\",\n\t\t\t\t\t                     (long) comp_ctx->curr_func.is_strict, (long) 1));\n\t\t\t\t\tcomp_ctx->curr_func.is_strict = 1;\n#else\n\t\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"use strict detected but strict declarations disabled, ignoring\"));\n#endif\n\t\t\t\t} else if (DUK_HSTRING_GET_BYTELEN(h_dir) == 14 &&\n\t\t\t\t           DUK_STRNCMP((const char *) DUK_HSTRING_GET_DATA(h_dir), \"use duk notail\", 14) == 0) {\n\t\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"use duk notail directive detected: notail flag %ld -> %ld\",\n\t\t\t\t\t                     (long) comp_ctx->curr_func.is_notail, (long) 1));\n\t\t\t\t\tcomp_ctx->curr_func.is_notail = 1;\n\t\t\t\t} else {\n\t\t\t\t\tDUK_DD(DUK_DDPRINT(\"unknown directive: '%!O', ignoring but not terminating \"\n\t\t\t\t\t                   \"directive prologue\", (duk_hobject *) h_dir));\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"non-directive expression statement or no longer in prologue; \"\n\t\t\t                     \"prologue terminated if still active\"));\n                }\n\n\t\tstmt_flags |= DUK__HAS_VAL | DUK__HAS_TERM;\n\t}\n\t}  /* end switch (tok) */\n\n\t/*\n\t *  Statement value handling.\n\t *\n\t *  Global code and eval code has an implicit return value\n\t *  which comes from the last statement with a value\n\t *  (technically a non-\"empty\" continuation, which is\n\t *  different from an empty statement).\n\t *\n\t *  Since we don't know whether a later statement will\n\t *  override the value of the current statement, we need\n\t *  to coerce the statement value to a register allocated\n\t *  for implicit return values.  In other cases we need\n\t *  to coerce the statement value to a plain value to get\n\t *  any side effects out (consider e.g. \"foo.bar;\").\n\t */\n\n\t/* XXX: what about statements which leave a half-cooked value in 'res'\n\t * but have no stmt value?  Any such statements?\n\t */\n\n\tif (stmt_flags & DUK__HAS_VAL) {\n\t\tduk_regconst_t reg_stmt_value = comp_ctx->curr_func.reg_stmt_value;\n\t\tif (reg_stmt_value >= 0) {\n\t\t\tduk__ivalue_toforcedreg(comp_ctx, res, reg_stmt_value);\n\t\t} else {\n\t\t\tduk__ivalue_toplain_ignore(comp_ctx, res);\n\t\t}\n\t} else {\n\t\t;\n\t}\n\n\t/*\n\t *  Statement terminator check, including automatic semicolon\n\t *  handling.  After this step, 'curr_tok' should be the first\n\t *  token after a possible statement terminator.\n\t */\n\n\tif (stmt_flags & DUK__HAS_TERM) {\n\t\tif (comp_ctx->curr_token.t == DUK_TOK_SEMICOLON) {\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"explicit semicolon terminates statement\"));\n\t\t\tduk__advance(comp_ctx);\n\t\t} else {\n\t\t\tif (comp_ctx->curr_token.allow_auto_semi) {\n\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"automatic semicolon terminates statement\"));\n\t\t\t} else if (stmt_flags & DUK__ALLOW_AUTO_SEMI_ALWAYS) {\n\t\t\t\t/* XXX: make this lenience dependent on flags or strictness? */\n\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"automatic semicolon terminates statement (allowed for compatibility \"\n\t\t\t\t                     \"even though no lineterm present before next token)\"));\n\t\t\t} else {\n\t\t\t\tDUK_ERROR_SYNTAX(thr, DUK_STR_UNTERMINATED_STMT);\n\t\t\t}\n\t\t}\n\t} else {\n\t\tDUK_DDD(DUK_DDDPRINT(\"statement has no terminator\"));\n\t}\n\n\t/*\n\t *  Directive prologue tracking.\n\t */\n\n\tif (stmt_flags & DUK__STILL_PROLOGUE) {\n\t\tDUK_DDD(DUK_DDDPRINT(\"setting in_directive_prologue\"));\n\t\tcomp_ctx->curr_func.in_directive_prologue = 1;\n\t}\n\n\t/*\n\t *  Cleanups (all statement parsing flows through here).\n\t *\n\t *  Pop label site and reset labels.  Reset 'next temp' to value at\n\t *  entry to reuse temps.\n\t */\n\n\tif (label_id >= 0) {\n\t\tduk__emit_bc(comp_ctx,\n\t\t             DUK_OP_ENDLABEL,\n\t\t             (duk_regconst_t) label_id);\n\t}\n\n\tDUK__SETTEMP(comp_ctx, temp_at_entry);\n\n\tduk__reset_labels_to_length(comp_ctx, labels_len_at_entry);\n\n\t/* XXX: return indication of \"terminalness\" (e.g. a 'throw' is terminal) */\n\n\tDUK__RECURSION_DECREASE(comp_ctx, thr);\n}\n\n/*\n *  Parse a statement list.\n *\n *  Handles automatic semicolon insertion and implicit return value.\n *\n *  Upon entry, 'curr_tok' should contain the first token of the first\n *  statement (parsed in the \"allow regexp literal\" mode).  Upon exit,\n *  'curr_tok' contains the token following the statement list terminator\n *  (EOF or closing brace).\n */\n\nDUK_LOCAL void duk__parse_stmts(duk_compiler_ctx *comp_ctx, duk_bool_t allow_source_elem, duk_bool_t expect_eof) {\n\tduk_hthread *thr = comp_ctx->thr;\n\tduk_ivalue res_alloc;\n\tduk_ivalue *res = &res_alloc;\n\n\t/* Setup state.  Initial ivalue is 'undefined'. */\n\n\tduk_require_stack(thr, DUK__PARSE_STATEMENTS_SLOTS);\n\n\t/* XXX: 'res' setup can be moved to function body level; in fact, two 'res'\n\t * intermediate values suffice for parsing of each function.  Nesting is needed\n\t * for nested functions (which may occur inside expressions).\n\t */\n\n\tDUK_MEMZERO(&res_alloc, sizeof(res_alloc));\n\tres->t = DUK_IVAL_PLAIN;\n\tres->x1.t = DUK_ISPEC_VALUE;\n\tres->x1.valstack_idx = duk_get_top(thr);\n\tres->x2.valstack_idx = res->x1.valstack_idx + 1;\n\tduk_push_undefined(thr);\n\tduk_push_undefined(thr);\n\n\t/* Parse statements until a closing token (EOF or '}') is found. */\n\n\tfor (;;) {\n\t\t/* Check whether statement list ends. */\n\n\t\tif (expect_eof) {\n\t\t\tif (comp_ctx->curr_token.t == DUK_TOK_EOF) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t} else {\n\t\t\tif (comp_ctx->curr_token.t == DUK_TOK_RCURLY) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t/* Check statement type based on the first token type.\n\t\t *\n\t\t * Note: expression parsing helpers expect 'curr_tok' to\n\t\t * contain the first token of the expression upon entry.\n\t\t */\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"TOKEN %ld (non-whitespace, non-comment)\", (long) comp_ctx->curr_token.t));\n\n\t\tduk__parse_stmt(comp_ctx, res, allow_source_elem);\n\t}\n\n\tduk__advance(comp_ctx);\n\n\t/* Tear down state. */\n\n\tduk_pop_2(thr);\n}\n\n/*\n *  Declaration binding instantiation conceptually happens when calling a\n *  function; for us it essentially means that function prologue.  The\n *  conceptual process is described in E5 Section 10.5.\n *\n *  We need to keep track of all encountered identifiers to (1) create an\n *  identifier-to-register map (\"varmap\"); and (2) detect duplicate\n *  declarations.  Identifiers which are not bound to registers still need\n *  to be tracked for detecting duplicates.  Currently such identifiers\n *  are put into the varmap with a 'null' value, which is later cleaned up.\n *\n *  To support functions with a large number of variable and function\n *  declarations, registers are not allocated beyond a certain limit;\n *  after that limit, variables and functions need slow path access.\n *  Arguments are currently always register bound, which imposes a hard\n *  (and relatively small) argument count limit.\n *\n *  Some bindings in E5 are not configurable (= deletable) and almost all\n *  are mutable (writable).  Exceptions are:\n *\n *    - The 'arguments' binding, established only if no shadowing argument\n *      or function declaration exists.  We handle 'arguments' creation\n *      and binding through an explicit slow path environment record.\n *\n *    - The \"name\" binding for a named function expression.  This is also\n *      handled through an explicit slow path environment record.\n */\n\n/* XXX: add support for variables to not be register bound always, to\n * handle cases with a very large number of variables?\n */\n\nDUK_LOCAL void duk__init_varmap_and_prologue_for_pass2(duk_compiler_ctx *comp_ctx, duk_regconst_t *out_stmt_value_reg) {\n\tduk_hthread *thr = comp_ctx->thr;\n\tduk_hstring *h_name;\n\tduk_bool_t configurable_bindings;\n\tduk_uarridx_t num_args;\n\tduk_uarridx_t num_decls;\n\tduk_regconst_t rc_name;\n\tduk_small_uint_t declvar_flags;\n\tduk_uarridx_t i;\n#if defined(DUK_USE_ASSERTIONS)\n\tduk_idx_t entry_top;\n#endif\n\n#if defined(DUK_USE_ASSERTIONS)\n\tentry_top = duk_get_top(thr);\n#endif\n\n\t/*\n\t *  Preliminaries\n\t */\n\n\tconfigurable_bindings = comp_ctx->curr_func.is_eval;\n\tDUK_DDD(DUK_DDDPRINT(\"configurable_bindings=%ld\", (long) configurable_bindings));\n\n\t/* varmap is already in comp_ctx->curr_func.varmap_idx */\n\n\t/*\n\t *  Function formal arguments, always bound to registers\n\t *  (there's no support for shuffling them now).\n\t */\n\n\tnum_args = (duk_uarridx_t) duk_get_length(thr, comp_ctx->curr_func.argnames_idx);\n\tDUK_DDD(DUK_DDDPRINT(\"num_args=%ld\", (long) num_args));\n\t/* XXX: check num_args */\n\n\tfor (i = 0; i < num_args; i++) {\n\t\tduk_get_prop_index(thr, comp_ctx->curr_func.argnames_idx, i);\n\t\th_name = duk_known_hstring(thr, -1);\n\n\t\tif (comp_ctx->curr_func.is_strict) {\n\t\t\tif (duk__hstring_is_eval_or_arguments(comp_ctx, h_name)) {\n\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"arg named 'eval' or 'arguments' in strict mode -> SyntaxError\"));\n\t\t\t\tgoto error_argname;\n\t\t\t}\n\t\t\tduk_dup_top(thr);\n\t\t\tif (duk_has_prop(thr, comp_ctx->curr_func.varmap_idx)) {\n\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"duplicate arg name in strict mode -> SyntaxError\"));\n\t\t\t\tgoto error_argname;\n\t\t\t}\n\n\t\t\t/* Ensure argument name is not a reserved word in current\n\t\t\t * (final) strictness.  Formal argument parsing may not\n\t\t\t * catch reserved names if strictness changes during\n\t\t\t * parsing.\n\t\t\t *\n\t\t\t * We only need to do this in strict mode because non-strict\n\t\t\t * keyword are always detected in formal argument parsing.\n\t\t\t */\n\n\t\t\tif (DUK_HSTRING_HAS_STRICT_RESERVED_WORD(h_name)) {\n\t\t\t\tgoto error_argname;\n\t\t\t}\n\t\t}\n\n\t\t/* overwrite any previous binding of the same name; the effect is\n\t\t * that last argument of a certain name wins.\n\t\t */\n\n\t\t/* only functions can have arguments */\n\t\tDUK_ASSERT(comp_ctx->curr_func.is_function);\n\t\tduk_push_uarridx(thr, i);  /* -> [ ... name index ] */\n\t\tduk_put_prop(thr, comp_ctx->curr_func.varmap_idx); /* -> [ ... ] */\n\n\t\t/* no code needs to be emitted, the regs already have values */\n\t}\n\n\t/* use temp_next for tracking register allocations */\n\tDUK__SETTEMP_CHECKMAX(comp_ctx, (duk_regconst_t) num_args);\n\n\t/*\n\t *  After arguments, allocate special registers (like shuffling temps)\n\t */\n\n\tif (out_stmt_value_reg) {\n\t\t*out_stmt_value_reg = DUK__ALLOCTEMP(comp_ctx);\n\t}\n\tif (comp_ctx->curr_func.needs_shuffle) {\n\t\tduk_regconst_t shuffle_base = DUK__ALLOCTEMPS(comp_ctx, 3);\n\t\tcomp_ctx->curr_func.shuffle1 = shuffle_base;\n\t\tcomp_ctx->curr_func.shuffle2 = shuffle_base + 1;\n\t\tcomp_ctx->curr_func.shuffle3 = shuffle_base + 2;\n\t\tDUK_D(DUK_DPRINT(\"shuffle registers needed by function, allocated: %ld %ld %ld\",\n\t\t                 (long) comp_ctx->curr_func.shuffle1,\n\t\t                 (long) comp_ctx->curr_func.shuffle2,\n\t\t                 (long) comp_ctx->curr_func.shuffle3));\n\t}\n\tif (comp_ctx->curr_func.temp_next > 0x100) {\n\t\tDUK_D(DUK_DPRINT(\"not enough 8-bit regs: temp_next=%ld\", (long) comp_ctx->curr_func.temp_next));\n\t\tgoto error_outofregs;\n\t}\n\n\t/*\n\t *  Function declarations\n\t */\n\n\tnum_decls = (duk_uarridx_t) duk_get_length(thr, comp_ctx->curr_func.decls_idx);\n\tDUK_DDD(DUK_DDDPRINT(\"num_decls=%ld -> %!T\",\n\t                     (long) num_decls,\n\t                     (duk_tval *) duk_get_tval(thr, comp_ctx->curr_func.decls_idx)));\n\tfor (i = 0; i < num_decls; i += 2) {\n\t\tduk_int_t decl_type;\n\t\tduk_int_t fnum;\n\n\t\tduk_get_prop_index(thr, comp_ctx->curr_func.decls_idx, i + 1);  /* decl type */\n\t\tdecl_type = duk_to_int(thr, -1);\n\t\tfnum = decl_type >> 8;  /* XXX: macros */\n\t\tdecl_type = decl_type & 0xff;\n\t\tduk_pop(thr);\n\n\t\tif (decl_type != DUK_DECL_TYPE_FUNC) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tduk_get_prop_index(thr, comp_ctx->curr_func.decls_idx, i);  /* decl name */\n\n\t\t/* XXX: spilling */\n\t\tif (comp_ctx->curr_func.is_function) {\n\t\t\tduk_regconst_t reg_bind;\n\t\t\tduk_dup_top(thr);\n\t\t\tif (duk_has_prop(thr, comp_ctx->curr_func.varmap_idx)) {\n\t\t\t\t/* shadowed; update value */\n\t\t\t\tduk_dup_top(thr);\n\t\t\t\tduk_get_prop(thr, comp_ctx->curr_func.varmap_idx);\n\t\t\t\treg_bind = duk_to_int(thr, -1);  /* [ ... name reg_bind ] */\n\t\t\t\tduk__emit_a_bc(comp_ctx,\n\t\t\t\t               DUK_OP_CLOSURE,\n\t\t\t\t               reg_bind,\n\t\t\t\t               (duk_regconst_t) fnum);\n\t\t\t} else {\n\t\t\t\t/* function: always register bound */\n\t\t\t\treg_bind = DUK__ALLOCTEMP(comp_ctx);\n\t\t\t\tduk__emit_a_bc(comp_ctx,\n\t\t\t\t               DUK_OP_CLOSURE,\n\t\t\t\t               reg_bind,\n\t\t\t\t               (duk_regconst_t) fnum);\n\t\t\t\tduk_push_int(thr, (duk_int_t) reg_bind);\n\t\t\t}\n\t\t} else {\n\t\t\t/* Function declaration for global/eval code is emitted even\n\t\t\t * for duplicates, because of E5 Section 10.5, step 5.e of\n\t\t\t * E5.1 (special behavior for variable bound to global object).\n\t\t\t *\n\t\t\t * DECLVAR will not re-declare a variable as such, but will\n\t\t\t * update the binding value.\n\t\t\t */\n\n\t\t\tduk_regconst_t reg_temp = DUK__ALLOCTEMP(comp_ctx);\n\t\t\tduk_dup_top(thr);\n\t\t\trc_name = duk__getconst(comp_ctx);\n\t\t\tduk_push_null(thr);\n\n\t\t\tduk__emit_a_bc(comp_ctx,\n\t\t\t               DUK_OP_CLOSURE,\n\t\t\t               reg_temp,\n\t\t\t               (duk_regconst_t) fnum);\n\n\t\t\tdeclvar_flags = DUK_PROPDESC_FLAG_WRITABLE |\n\t\t\t                DUK_PROPDESC_FLAG_ENUMERABLE |\n\t\t\t                DUK_BC_DECLVAR_FLAG_FUNC_DECL;\n\n\t\t\tif (configurable_bindings) {\n\t\t\t\tdeclvar_flags |= DUK_PROPDESC_FLAG_CONFIGURABLE;\n\t\t\t}\n\n\t\t\tduk__emit_a_b_c(comp_ctx,\n\t\t\t                DUK_OP_DECLVAR | DUK__EMIT_FLAG_NO_SHUFFLE_A | DUK__EMIT_FLAG_BC_REGCONST,\n\t\t\t                (duk_regconst_t) declvar_flags /*flags*/,\n\t\t\t                rc_name /*name*/,\n\t\t\t                reg_temp /*value*/);\n\n\t\t\tDUK__SETTEMP(comp_ctx, reg_temp);  /* forget temp */\n\t\t}\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"function declaration to varmap: %!T -> %!T\",\n\t\t                     (duk_tval *) duk_get_tval(thr, -2),\n\t\t                     (duk_tval *) duk_get_tval(thr, -1)));\n\n#if defined(DUK_USE_FASTINT)\n\t\tDUK_ASSERT(DUK_TVAL_IS_NULL(duk_get_tval(thr, -1)) || DUK_TVAL_IS_FASTINT(duk_get_tval(thr, -1)));\n#endif\n\t\tduk_put_prop(thr, comp_ctx->curr_func.varmap_idx);  /* [ ... name reg/null ] -> [ ... ] */\n\t}\n\n\t/*\n\t *  'arguments' binding is special; if a shadowing argument or\n\t *  function declaration exists, an arguments object will\n\t *  definitely not be needed, regardless of whether the identifier\n\t *  'arguments' is referenced inside the function body.\n\t */\n\n\tif (duk_has_prop_stridx(thr, comp_ctx->curr_func.varmap_idx, DUK_STRIDX_LC_ARGUMENTS)) {\n\t\tDUK_DDD(DUK_DDDPRINT(\"'arguments' is shadowed by argument or function declaration \"\n\t\t                     \"-> arguments object creation can be skipped\"));\n\t\tcomp_ctx->curr_func.is_arguments_shadowed = 1;\n\t}\n\n\t/*\n\t *  Variable declarations.\n\t *\n\t *  Unlike function declarations, variable declaration values don't get\n\t *  assigned on entry.  If a binding of the same name already exists, just\n\t *  ignore it silently.\n\t */\n\n\tfor (i = 0; i < num_decls; i += 2) {\n\t\tduk_int_t decl_type;\n\n\t\tduk_get_prop_index(thr, comp_ctx->curr_func.decls_idx, i + 1);  /* decl type */\n\t\tdecl_type = duk_to_int(thr, -1);\n\t\tdecl_type = decl_type & 0xff;\n\t\tduk_pop(thr);\n\n\t\tif (decl_type != DUK_DECL_TYPE_VAR) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tduk_get_prop_index(thr, comp_ctx->curr_func.decls_idx, i);  /* decl name */\n\n\t\tif (duk_has_prop(thr, comp_ctx->curr_func.varmap_idx)) {\n\t\t\t/* shadowed, ignore */\n\t\t} else {\n\t\t\tduk_get_prop_index(thr, comp_ctx->curr_func.decls_idx, i);  /* decl name */\n\t\t\th_name = duk_known_hstring(thr, -1);\n\n\t\t\tif (h_name == DUK_HTHREAD_STRING_LC_ARGUMENTS(thr) &&\n\t\t\t    !comp_ctx->curr_func.is_arguments_shadowed) {\n\t\t\t\t/* E5 Section steps 7-8 */\n\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"'arguments' not shadowed by a function declaration, \"\n\t\t\t\t                     \"but appears as a variable declaration -> treat as \"\n\t\t\t\t                     \"a no-op for variable declaration purposes\"));\n\t\t\t\tduk_pop(thr);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t/* XXX: spilling */\n\t\t\tif (comp_ctx->curr_func.is_function) {\n\t\t\t\tduk_regconst_t reg_bind = DUK__ALLOCTEMP(comp_ctx);\n\t\t\t\t/* no need to init reg, it will be undefined on entry */\n\t\t\t\tduk_push_int(thr, (duk_int_t) reg_bind);\n\t\t\t} else {\n\t\t\t\tduk_dup_top(thr);\n\t\t\t\trc_name = duk__getconst(comp_ctx);\n\t\t\t\tduk_push_null(thr);\n\n\t\t\t\tdeclvar_flags = DUK_PROPDESC_FLAG_WRITABLE |\n\t\t\t                        DUK_PROPDESC_FLAG_ENUMERABLE;\n\t\t\t\tif (configurable_bindings) {\n\t\t\t\t\tdeclvar_flags |= DUK_PROPDESC_FLAG_CONFIGURABLE;\n\t\t\t\t}\n\n\t\t\t\tduk__emit_a_b_c(comp_ctx,\n\t\t\t\t                DUK_OP_DECLVAR | DUK__EMIT_FLAG_NO_SHUFFLE_A | DUK__EMIT_FLAG_BC_REGCONST,\n\t\t\t\t                (duk_regconst_t) declvar_flags /*flags*/,\n\t\t\t\t                rc_name /*name*/,\n\t\t\t\t                0 /*value*/);\n\t\t\t}\n\n\t\t\tduk_put_prop(thr, comp_ctx->curr_func.varmap_idx);  /* [ ... name reg/null ] -> [ ... ] */\n\t\t}\n\t}\n\n\t/*\n\t *  Wrap up\n\t */\n\n\tDUK_DDD(DUK_DDDPRINT(\"varmap: %!T, is_arguments_shadowed=%ld\",\n\t                     (duk_tval *) duk_get_tval(thr, comp_ctx->curr_func.varmap_idx),\n\t                     (long) comp_ctx->curr_func.is_arguments_shadowed));\n\n\tDUK_ASSERT_TOP(thr, entry_top);\n\treturn;\n\n error_outofregs:\n\tDUK_ERROR_RANGE(thr, DUK_STR_REG_LIMIT);\n\tDUK_UNREACHABLE();\n\treturn;\n\n error_argname:\n\tDUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_ARG_NAME);\n\tDUK_UNREACHABLE();\n\treturn;\n}\n\n/*\n *  Parse a function-body-like expression (FunctionBody or Program\n *  in E5 grammar) using a two-pass parse.  The productions appear\n *  in the following contexts:\n *\n *    - function expression\n *    - function statement\n *    - function declaration\n *    - getter in object literal\n *    - setter in object literal\n *    - global code\n *    - eval code\n *    - Function constructor body\n *\n *  This function only parses the statement list of the body; the argument\n *  list and possible function name must be initialized by the caller.\n *  For instance, for Function constructor, the argument names are originally\n *  on the value stack.  The parsing of statements ends either at an EOF or\n *  a closing brace; this is controlled by an input flag.\n *\n *  Note that there are many differences affecting parsing and even code\n *  generation:\n *\n *    - Global and eval code have an implicit return value generated\n *      by the last statement; function code does not\n *\n *    - Global code, eval code, and Function constructor body end in\n *      an EOF, other bodies in a closing brace ('}')\n *\n *  Upon entry, 'curr_tok' is ignored and the function will pull in the\n *  first token on its own.  Upon exit, 'curr_tok' is the terminating\n *  token (EOF or closing brace).\n */\n\nDUK_LOCAL void duk__parse_func_body(duk_compiler_ctx *comp_ctx, duk_bool_t expect_eof, duk_bool_t implicit_return_value, duk_small_int_t expect_token) {\n\tduk_compiler_func *func;\n\tduk_hthread *thr;\n\tduk_regconst_t reg_stmt_value = -1;\n\tduk_lexer_point lex_pt;\n\tduk_regconst_t temp_first;\n\tduk_small_int_t compile_round = 1;\n\n\tDUK_ASSERT(comp_ctx != NULL);\n\n\tthr = comp_ctx->thr;\n\tDUK_ASSERT(thr != NULL);\n\n\tfunc = &comp_ctx->curr_func;\n\tDUK_ASSERT(func != NULL);\n\n\tDUK__RECURSION_INCREASE(comp_ctx, thr);\n\n\tduk_require_stack(thr, DUK__FUNCTION_BODY_REQUIRE_SLOTS);\n\n\t/*\n\t *  Store lexer position for a later rewind\n\t */\n\n\tDUK_LEXER_GETPOINT(&comp_ctx->lex, &lex_pt);\n\n\t/*\n\t *  Program code (global and eval code) has an implicit return value\n\t *  from the last statement value (e.g. eval(\"1; 2+3;\") returns 3).\n\t *  This is not the case with functions.  If implicit statement return\n\t *  value is requested, all statements are coerced to a register\n\t *  allocated here, and used in the implicit return statement below.\n\t */\n\n\t/* XXX: this is pointless here because pass 1 is throw-away */\n\tif (implicit_return_value) {\n\t\treg_stmt_value = DUK__ALLOCTEMP(comp_ctx);\n\n\t\t/* If an implicit return value is needed by caller, it must be\n\t\t * initialized to 'undefined' because we don't know whether any\n\t\t * non-empty (where \"empty\" is a continuation type, and different\n\t\t * from an empty statement) statements will be executed.\n\t\t *\n\t\t * However, since 1st pass is a throwaway one, no need to emit\n\t\t * it here.\n\t\t */\n#if 0\n\t\tduk__emit_bc(comp_ctx,\n\t\t             DUK_OP_LDUNDEF,\n\t\t             0);\n#endif\n\t}\n\n\t/*\n\t *  First pass.\n\t *\n\t *  Gather variable/function declarations needed for second pass.\n\t *  Code generated is dummy and discarded.\n\t */\n\n\tfunc->in_directive_prologue = 1;\n\tfunc->in_scanning = 1;\n\tfunc->may_direct_eval = 0;\n\tfunc->id_access_arguments = 0;\n\tfunc->id_access_slow = 0;\n\tfunc->id_access_slow_own = 0;\n\tfunc->reg_stmt_value = reg_stmt_value;\n#if defined(DUK_USE_DEBUGGER_SUPPORT)\n\tfunc->min_line = DUK_INT_MAX;\n\tfunc->max_line = 0;\n#endif\n\n\t/* duk__parse_stmts() expects curr_tok to be set; parse in \"allow regexp literal\" mode with current strictness */\n\tif (expect_token >= 0) {\n\t\t/* Eating a left curly; regexp mode is allowed by left curly\n\t\t * based on duk__token_lbp[] automatically.\n\t\t */\n\t\tDUK_ASSERT(expect_token == DUK_TOK_LCURLY);\n\t\tduk__update_lineinfo_currtoken(comp_ctx);\n\t\tduk__advance_expect(comp_ctx, expect_token);\n\t} else {\n\t\t/* Need to set curr_token.t because lexing regexp mode depends on current\n\t\t * token type.  Zero value causes \"allow regexp\" mode.\n\t\t */\n\t\tcomp_ctx->curr_token.t = 0;\n\t\tduk__advance(comp_ctx);\n\t}\n\n\tDUK_DDD(DUK_DDDPRINT(\"begin 1st pass\"));\n\tduk__parse_stmts(comp_ctx,\n\t                 1,             /* allow source elements */\n\t                 expect_eof);   /* expect EOF instead of } */\n\tDUK_DDD(DUK_DDDPRINT(\"end 1st pass\"));\n\n\t/*\n\t *  Second (and possibly third) pass.\n\t *\n\t *  Generate actual code.  In most cases the need for shuffle\n\t *  registers is detected during pass 1, but in some corner cases\n\t *  we'll only detect it during pass 2 and a third pass is then\n\t *  needed (see GH-115).\n\t */\n\n\tfor (;;) {\n\t\tduk_bool_t needs_shuffle_before = comp_ctx->curr_func.needs_shuffle;\n\t\tcompile_round++;\n\n\t\t/*\n\t\t *  Rewind lexer.\n\t\t *\n\t\t *  duk__parse_stmts() expects curr_tok to be set; parse in \"allow regexp\n\t\t *  literal\" mode with current strictness.\n\t\t *\n\t\t *  curr_token line number info should be initialized for pass 2 before\n\t\t *  generating prologue, to ensure prologue bytecode gets nice line numbers.\n\t\t */\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"rewind lexer\"));\n\t\tDUK_LEXER_SETPOINT(&comp_ctx->lex, &lex_pt);\n\t\tcomp_ctx->curr_token.t = 0;  /* this is needed for regexp mode */\n\t\tcomp_ctx->curr_token.start_line = 0;  /* needed for line number tracking (becomes prev_token.start_line) */\n\t\tduk__advance(comp_ctx);\n\n\t\t/*\n\t\t *  Reset function state and perform register allocation, which creates\n\t\t *  'varmap' for second pass.  Function prologue for variable declarations,\n\t\t *  binding value initializations etc is emitted as a by-product.\n\t\t *\n\t\t *  Strict mode restrictions for duplicate and invalid argument\n\t\t *  names are checked here now that we know whether the function\n\t\t *  is actually strict.  See: test-dev-strict-mode-boundary.js.\n\t\t *\n\t\t *  Inner functions are compiled during pass 1 and are not reset.\n\t\t */\n\n\t\tduk__reset_func_for_pass2(comp_ctx);\n\t\tfunc->in_directive_prologue = 1;\n\t\tfunc->in_scanning = 0;\n\n\t\t/* must be able to emit code, alloc consts, etc. */\n\n\t\tduk__init_varmap_and_prologue_for_pass2(comp_ctx,\n\t\t                                        (implicit_return_value ? &reg_stmt_value : NULL));\n\t\tfunc->reg_stmt_value = reg_stmt_value;\n\n\t\ttemp_first = DUK__GETTEMP(comp_ctx);\n\n\t\tfunc->temp_first = temp_first;\n\t\tfunc->temp_next = temp_first;\n\t\tfunc->stmt_next = 0;\n\t\tfunc->label_next = 0;\n\n\t\t/* XXX: init or assert catch depth etc -- all values */\n\t\tfunc->id_access_arguments = 0;\n\t\tfunc->id_access_slow = 0;\n\t\tfunc->id_access_slow_own = 0;\n\n\t\t/*\n\t\t *  Check function name validity now that we know strictness.\n\t\t *  This only applies to function declarations and expressions,\n\t\t *  not setter/getter name.\n\t\t *\n\t\t *  See: test-dev-strict-mode-boundary.js\n\t\t */\n\n\t\tif (func->is_function && !func->is_setget && func->h_name != NULL) {\n\t\t\tif (func->is_strict) {\n\t\t\t\tif (duk__hstring_is_eval_or_arguments(comp_ctx, func->h_name)) {\n\t\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"func name is 'eval' or 'arguments' in strict mode\"));\n\t\t\t\t\tgoto error_funcname;\n\t\t\t\t}\n\t\t\t\tif (DUK_HSTRING_HAS_STRICT_RESERVED_WORD(func->h_name)) {\n\t\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"func name is a reserved word in strict mode\"));\n\t\t\t\t\tgoto error_funcname;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (DUK_HSTRING_HAS_RESERVED_WORD(func->h_name) &&\n\t\t\t\t    !DUK_HSTRING_HAS_STRICT_RESERVED_WORD(func->h_name)) {\n\t\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"func name is a reserved word in non-strict mode\"));\n\t\t\t\t\tgoto error_funcname;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t *  Second pass parsing.\n\t\t */\n\n\t\tif (implicit_return_value) {\n\t\t\t/* Default implicit return value. */\n\t\t\tduk__emit_bc(comp_ctx,\n\t\t\t             DUK_OP_LDUNDEF,\n\t\t\t             0);\n\t\t}\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"begin 2nd pass\"));\n\t\tduk__parse_stmts(comp_ctx,\n\t\t                 1,             /* allow source elements */\n\t\t                 expect_eof);   /* expect EOF instead of } */\n\t\tDUK_DDD(DUK_DDDPRINT(\"end 2nd pass\"));\n\n\t\tduk__update_lineinfo_currtoken(comp_ctx);\n\n\t\tif (needs_shuffle_before == comp_ctx->curr_func.needs_shuffle) {\n\t\t\t/* Shuffle decision not changed. */\n\t\t\tbreak;\n\t\t}\n\t\tif (compile_round >= 3) {\n\t\t\t/* Should never happen but avoid infinite loop just in case. */\n\t\t\tDUK_D(DUK_DPRINT(\"more than 3 compile passes needed, should never happen\"));\n\t\t\tDUK_ERROR_INTERNAL(thr);\n\t\t}\n\t\tDUK_D(DUK_DPRINT(\"need additional round to compile function, round now %d\", (int) compile_round));\n\t}\n\n\t/*\n\t *  Emit a final RETURN.\n\t *\n\t *  It would be nice to avoid emitting an unnecessary \"return\" opcode\n\t *  if the current PC is not reachable.  However, this cannot be reliably\n\t *  detected; even if the previous instruction is an unconditional jump,\n\t *  there may be a previous jump which jumps to current PC (which is the\n\t *  case for iteration and conditional statements, for instance).\n\t */\n\n\t/* XXX: request a \"last statement is terminal\" from duk__parse_stmt() and duk__parse_stmts();\n\t * we could avoid the last RETURN if we could ensure there is no way to get here\n\t * (directly or via a jump)\n\t */\n\n\tDUK_ASSERT(comp_ctx->curr_func.catch_depth == 0);\n\tif (reg_stmt_value >= 0) {\n\t\tDUK_ASSERT(DUK__ISREG(reg_stmt_value));\n\t\tduk__emit_bc(comp_ctx, DUK_OP_RETREG, reg_stmt_value /*reg*/);\n\t} else {\n\t\tduk__emit_op_only(comp_ctx, DUK_OP_RETUNDEF);\n\t}\n\n\t/*\n\t *  Peephole optimize JUMP chains.\n\t */\n\n\tduk__peephole_optimize_bytecode(comp_ctx);\n\n\t/*\n\t *  comp_ctx->curr_func is now ready to be converted into an actual\n\t *  function template.\n\t */\n\n\tDUK__RECURSION_DECREASE(comp_ctx, thr);\n\treturn;\n\n error_funcname:\n\tDUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_FUNC_NAME);\n}\n\n/*\n *  Parse a function-like expression:\n *\n *    - function expression\n *    - function declaration\n *    - function statement (non-standard)\n *    - setter/getter\n *\n *  Adds the function to comp_ctx->curr_func function table and returns the\n *  function number.\n *\n *  On entry, curr_token points to:\n *\n *    - the token after 'function' for function expression/declaration/statement\n *    - the token after 'set' or 'get' for setter/getter\n */\n\n/* Parse formals. */\nDUK_LOCAL void duk__parse_func_formals(duk_compiler_ctx *comp_ctx) {\n\tduk_hthread *thr = comp_ctx->thr;\n\tduk_bool_t first = 1;\n\tduk_uarridx_t n;\n\n\tfor (;;) {\n\t\tif (comp_ctx->curr_token.t == DUK_TOK_RPAREN) {\n\t\t\tbreak;\n\t\t}\n\n\t\tif (first) {\n\t\t\t/* no comma */\n\t\t\tfirst = 0;\n\t\t} else {\n\t\t\tduk__advance_expect(comp_ctx, DUK_TOK_COMMA);\n\t\t}\n\n\t\t/* Note: when parsing a formal list in non-strict context, e.g.\n\t\t * \"implements\" is parsed as an identifier.  When the function is\n\t\t * later detected to be strict, the argument list must be rechecked\n\t\t * against a larger set of reserved words (that of strict mode).\n\t\t * This is handled by duk__parse_func_body().  Here we recognize\n\t\t * whatever tokens are considered reserved in current strictness\n\t\t * (which is not always enough).\n\t\t */\n\n\t\tif (comp_ctx->curr_token.t != DUK_TOK_IDENTIFIER) {\n\t\t\tDUK_ERROR_SYNTAX(thr, DUK_STR_EXPECTED_IDENTIFIER);\n\t\t}\n\t\tDUK_ASSERT(comp_ctx->curr_token.t == DUK_TOK_IDENTIFIER);\n\t\tDUK_ASSERT(comp_ctx->curr_token.str1 != NULL);\n\t\tDUK_DDD(DUK_DDDPRINT(\"formal argument: %!O\",\n\t\t                     (duk_heaphdr *) comp_ctx->curr_token.str1));\n\n\t\t/* XXX: append primitive */\n\t\tduk_push_hstring(thr, comp_ctx->curr_token.str1);\n\t\tn = (duk_uarridx_t) duk_get_length(thr, comp_ctx->curr_func.argnames_idx);\n\t\tduk_put_prop_index(thr, comp_ctx->curr_func.argnames_idx, n);\n\n\t\tduk__advance(comp_ctx);  /* eat identifier */\n\t}\n}\n\n/* Parse a function-like expression, assuming that 'comp_ctx->curr_func' is\n * correctly set up.  Assumes that curr_token is just after 'function' (or\n * 'set'/'get' etc).\n */\nDUK_LOCAL void duk__parse_func_like_raw(duk_compiler_ctx *comp_ctx, duk_small_uint_t flags) {\n\tduk_hthread *thr = comp_ctx->thr;\n\tduk_token *tok;\n\tduk_bool_t no_advance;\n\n\tDUK_ASSERT(comp_ctx->curr_func.num_formals == 0);\n\tDUK_ASSERT(comp_ctx->curr_func.is_function == 1);\n\tDUK_ASSERT(comp_ctx->curr_func.is_eval == 0);\n\tDUK_ASSERT(comp_ctx->curr_func.is_global == 0);\n\tDUK_ASSERT(comp_ctx->curr_func.is_setget == ((flags & DUK__FUNC_FLAG_GETSET) != 0));\n\n\tduk__update_lineinfo_currtoken(comp_ctx);\n\n\t/*\n\t *  Function name (if any)\n\t *\n\t *  We don't check for prohibited names here, because we don't\n\t *  yet know whether the function will be strict.  Function body\n\t *  parsing handles this retroactively.\n\t *\n\t *  For function expressions and declarations function name must\n\t *  be an Identifer (excludes reserved words).  For setter/getter\n\t *  it is a PropertyName which allows reserved words and also\n\t *  strings and numbers (e.g. \"{ get 1() { ... } }\").\n\t *\n\t *  Function parsing may start either from prev_token or curr_token\n\t *  (object literal method definition uses prev_token for example).\n\t *  This is dealt with for the initial token.\n\t */\n\n\tno_advance = (flags & DUK__FUNC_FLAG_USE_PREVTOKEN);\n\tif (no_advance) {\n\t\ttok = &comp_ctx->prev_token;\n\t} else {\n\t\ttok = &comp_ctx->curr_token;\n\t}\n\n\tif (flags & DUK__FUNC_FLAG_GETSET) {\n\t\t/* PropertyName -> IdentifierName | StringLiteral | NumericLiteral */\n\t\tif (tok->t_nores == DUK_TOK_IDENTIFIER || tok->t == DUK_TOK_STRING) {\n\t\t\tduk_push_hstring(thr, tok->str1);       /* keep in valstack */\n\t\t} else if (tok->t == DUK_TOK_NUMBER) {\n\t\t\tduk_push_number(thr, tok->num);\n\t\t\tduk_to_string(thr, -1);\n\t\t} else {\n\t\t\tDUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_GETSET_NAME);\n\t\t}\n\t\tcomp_ctx->curr_func.h_name = duk_known_hstring(thr, -1);  /* borrowed reference */\n\t} else {\n\t\t/* Function name is an Identifier (not IdentifierName), but we get\n\t\t * the raw name (not recognizing keywords) here and perform the name\n\t\t * checks only after pass 1.\n\t\t */\n\t\tif (tok->t_nores == DUK_TOK_IDENTIFIER) {\n\t\t\tduk_push_hstring(thr, tok->str1);       /* keep in valstack */\n\t\t\tcomp_ctx->curr_func.h_name = duk_known_hstring(thr, -1);  /* borrowed reference */\n\t\t} else {\n\t\t\t/* valstack will be unbalanced, which is OK */\n\t\t\tDUK_ASSERT((flags & DUK__FUNC_FLAG_GETSET) == 0);\n\t\t\tDUK_ASSERT(comp_ctx->curr_func.h_name == NULL);\n\t\t\tno_advance = 1;\n\t\t\tif (flags & DUK__FUNC_FLAG_DECL) {\n\t\t\t\tDUK_ERROR_SYNTAX(thr, DUK_STR_FUNC_NAME_REQUIRED);\n\t\t\t}\n\t\t}\n\t}\n\n\tDUK_DD(DUK_DDPRINT(\"function name: %!O\",\n\t                   (duk_heaphdr *) comp_ctx->curr_func.h_name));\n\n\tif (!no_advance) {\n\t\tduk__advance(comp_ctx);\n\t}\n\n\t/*\n\t *  Formal argument list\n\t *\n\t *  We don't check for prohibited names or for duplicate argument\n\t *  names here, becase we don't yet know whether the function will\n\t *  be strict.  Function body parsing handles this retroactively.\n\t */\n\n\tduk__advance_expect(comp_ctx, DUK_TOK_LPAREN);\n\n\tduk__parse_func_formals(comp_ctx);\n\n\tDUK_ASSERT(comp_ctx->curr_token.t == DUK_TOK_RPAREN);\n\tduk__advance(comp_ctx);\n\n\t/*\n\t *  Parse function body\n\t */\n\n\tduk__parse_func_body(comp_ctx,\n\t                     0,   /* expect_eof */\n\t                     0,   /* implicit_return_value */\n\t                     DUK_TOK_LCURLY);  /* expect_token */\n\n\t/*\n\t *  Convert duk_compiler_func to a function template and add it\n\t *  to the parent function table.\n\t */\n\n\tduk__convert_to_func_template(comp_ctx);  /* -> [ ... func ] */\n}\n\n/* Parse an inner function, adding the function template to the current function's\n * function table.  Return a function number to be used by the outer function.\n *\n * Avoiding O(depth^2) inner function parsing is handled here.  On the first pass,\n * compile and register the function normally into the 'funcs' array, also recording\n * a lexer point (offset/line) to the closing brace of the function.  On the second\n * pass, skip the function and return the same 'fnum' as on the first pass by using\n * a running counter.\n *\n * An unfortunate side effect of this is that when parsing the inner function, almost\n * nothing is known of the outer function, i.e. the inner function's scope.  We don't\n * need that information at the moment, but it would allow some optimizations if it\n * were used.\n */\nDUK_LOCAL duk_int_t duk__parse_func_like_fnum(duk_compiler_ctx *comp_ctx, duk_small_uint_t flags) {\n\tduk_hthread *thr = comp_ctx->thr;\n\tduk_compiler_func old_func;\n\tduk_idx_t entry_top;\n\tduk_int_t fnum;\n\n\t/*\n\t *  On second pass, skip the function.\n\t */\n\n\tif (!comp_ctx->curr_func.in_scanning) {\n\t\tduk_lexer_point lex_pt;\n\n\t\tfnum = comp_ctx->curr_func.fnum_next++;\n\t\tduk_get_prop_index(thr, comp_ctx->curr_func.funcs_idx, (duk_uarridx_t) (fnum * 3 + 1));\n\t\tlex_pt.offset = (duk_size_t) duk_to_uint(thr, -1);\n\t\tduk_pop(thr);\n\t\tduk_get_prop_index(thr, comp_ctx->curr_func.funcs_idx, (duk_uarridx_t) (fnum * 3 + 2));\n\t\tlex_pt.line = duk_to_int(thr, -1);\n\t\tduk_pop(thr);\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"second pass of an inner func, skip the function, reparse closing brace; lex offset=%ld, line=%ld\",\n\t\t                     (long) lex_pt.offset, (long) lex_pt.line));\n\n\t\tDUK_LEXER_SETPOINT(&comp_ctx->lex, &lex_pt);\n\t\tcomp_ctx->curr_token.t = 0;  /* this is needed for regexp mode */\n\t\tcomp_ctx->curr_token.start_line = 0;  /* needed for line number tracking (becomes prev_token.start_line) */\n\t\tduk__advance(comp_ctx);\n\t\tduk__advance_expect(comp_ctx, DUK_TOK_RCURLY);\n\n\t\treturn fnum;\n\t}\n\n\t/*\n\t *  On first pass, perform actual parsing.  Remember valstack top on entry\n\t *  to restore it later, and switch to using a new function in comp_ctx.\n\t */\n\n\tentry_top = duk_get_top(thr);\n\tDUK_DDD(DUK_DDDPRINT(\"before func: entry_top=%ld, curr_tok.start_offset=%ld\",\n\t                     (long) entry_top, (long) comp_ctx->curr_token.start_offset));\n\n\tDUK_MEMCPY(&old_func, &comp_ctx->curr_func, sizeof(duk_compiler_func));\n\n\tDUK_MEMZERO(&comp_ctx->curr_func, sizeof(duk_compiler_func));\n\tduk__init_func_valstack_slots(comp_ctx);\n\tDUK_ASSERT(comp_ctx->curr_func.num_formals == 0);\n\n\t/* inherit initial strictness from parent */\n\tcomp_ctx->curr_func.is_strict = old_func.is_strict;\n\n\t/* XXX: It might be better to just store the flags into the curr_func\n\t * struct and use them as is without this flag interpretation step\n\t * here.\n\t */\n\tDUK_ASSERT(comp_ctx->curr_func.is_notail == 0);\n\tcomp_ctx->curr_func.is_function = 1;\n\tDUK_ASSERT(comp_ctx->curr_func.is_eval == 0);\n\tDUK_ASSERT(comp_ctx->curr_func.is_global == 0);\n\tcomp_ctx->curr_func.is_setget = ((flags & DUK__FUNC_FLAG_GETSET) != 0);\n\tcomp_ctx->curr_func.is_namebinding = !(flags & (DUK__FUNC_FLAG_GETSET |\n\t                                                DUK__FUNC_FLAG_METDEF |\n\t                                                DUK__FUNC_FLAG_DECL));  /* no name binding for: declarations, objlit getset, objlit method def */\n\tcomp_ctx->curr_func.is_constructable = !(flags & (DUK__FUNC_FLAG_GETSET |\n\t                                                  DUK__FUNC_FLAG_METDEF));  /* not constructable: objlit getset, objlit method def */\n\n\t/*\n\t *  Parse inner function\n\t */\n\n\tduk__parse_func_like_raw(comp_ctx, flags);  /* pushes function template */\n\n\t/* prev_token.start_offset points to the closing brace here; when skipping\n\t * we're going to reparse the closing brace to ensure semicolon insertion\n\t * etc work as expected.\n\t */\n\tDUK_DDD(DUK_DDDPRINT(\"after func: prev_tok.start_offset=%ld, curr_tok.start_offset=%ld\",\n\t                     (long) comp_ctx->prev_token.start_offset, (long) comp_ctx->curr_token.start_offset));\n\tDUK_ASSERT(comp_ctx->lex.input[comp_ctx->prev_token.start_offset] == (duk_uint8_t) DUK_ASC_RCURLY);\n\n\t/* XXX: append primitive */\n\tDUK_ASSERT(duk_get_length(thr, old_func.funcs_idx) == (duk_size_t) (old_func.fnum_next * 3));\n\tfnum = old_func.fnum_next++;\n\n\tif (fnum > DUK__MAX_FUNCS) {\n\t\tDUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_FUNC_LIMIT);\n\t}\n\n\t/* array writes autoincrement length */\n\t(void) duk_put_prop_index(thr, old_func.funcs_idx, (duk_uarridx_t) (fnum * 3));\n\tduk_push_size_t(thr, comp_ctx->prev_token.start_offset);\n\t(void) duk_put_prop_index(thr, old_func.funcs_idx, (duk_uarridx_t) (fnum * 3 + 1));\n\tduk_push_int(thr, comp_ctx->prev_token.start_line);\n\t(void) duk_put_prop_index(thr, old_func.funcs_idx, (duk_uarridx_t) (fnum * 3 + 2));\n\n\t/*\n\t *  Cleanup: restore original function, restore valstack state.\n\t *\n\t *  Function declaration handling needs the function name to be pushed\n\t *  on the value stack.\n\t */\n\n\tif (flags & DUK__FUNC_FLAG_PUSHNAME_PASS1) {\n\t\tDUK_ASSERT(comp_ctx->curr_func.h_name != NULL);\n\t\tduk_push_hstring(thr, comp_ctx->curr_func.h_name);\n\t\tduk_replace(thr, entry_top);\n\t\tduk_set_top(thr, entry_top + 1);\n\t} else {\n\t\tduk_set_top(thr, entry_top);\n\t}\n\tDUK_MEMCPY((void *) &comp_ctx->curr_func, (void *) &old_func, sizeof(duk_compiler_func));\n\n\treturn fnum;\n}\n\n/*\n *  Compile input string into an executable function template without\n *  arguments.\n *\n *  The string is parsed as the \"Program\" production of Ecmascript E5.\n *  Compilation context can be either global code or eval code (see E5\n *  Sections 14 and 15.1.2.1).\n *\n *  Input stack:  [ ... filename ]\n *  Output stack: [ ... func_template ]\n */\n\n/* XXX: source code property */\n\nDUK_LOCAL duk_ret_t duk__js_compile_raw(duk_hthread *thr, void *udata) {\n\tduk_hstring *h_filename;\n\tduk__compiler_stkstate *comp_stk;\n\tduk_compiler_ctx *comp_ctx;\n\tduk_lexer_point *lex_pt;\n\tduk_compiler_func *func;\n\tduk_idx_t entry_top;\n\tduk_bool_t is_strict;\n\tduk_bool_t is_eval;\n\tduk_bool_t is_funcexpr;\n\tduk_small_uint_t flags;\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(udata != NULL);\n\n\t/*\n\t *  Arguments check\n\t */\n\n\tentry_top = duk_get_top(thr);\n\tDUK_ASSERT(entry_top >= 1);\n\n\tcomp_stk = (duk__compiler_stkstate *) udata;\n\tcomp_ctx = &comp_stk->comp_ctx_alloc;\n\tlex_pt = &comp_stk->lex_pt_alloc;\n\tDUK_ASSERT(comp_ctx != NULL);\n\tDUK_ASSERT(lex_pt != NULL);\n\n\tflags = comp_stk->flags;\n\tis_eval = (flags & DUK_COMPILE_EVAL ? 1 : 0);\n\tis_strict = (flags & DUK_COMPILE_STRICT ? 1 : 0);\n\tis_funcexpr = (flags & DUK_COMPILE_FUNCEXPR ? 1 : 0);\n\n\th_filename = duk_get_hstring(thr, -1);  /* may be undefined */\n\n\t/*\n\t *  Init compiler and lexer contexts\n\t */\n\n\tfunc = &comp_ctx->curr_func;\n#if defined(DUK_USE_EXPLICIT_NULL_INIT)\n\tcomp_ctx->thr = NULL;\n\tcomp_ctx->h_filename = NULL;\n\tcomp_ctx->prev_token.str1 = NULL;\n\tcomp_ctx->prev_token.str2 = NULL;\n\tcomp_ctx->curr_token.str1 = NULL;\n\tcomp_ctx->curr_token.str2 = NULL;\n#endif\n\n\tduk_require_stack(thr, DUK__COMPILE_ENTRY_SLOTS);\n\n\tduk_push_dynamic_buffer(thr, 0);       /* entry_top + 0 */\n\tduk_push_undefined(thr);               /* entry_top + 1 */\n\tduk_push_undefined(thr);               /* entry_top + 2 */\n\tduk_push_undefined(thr);               /* entry_top + 3 */\n\tduk_push_undefined(thr);               /* entry_top + 4 */\n\n\tcomp_ctx->thr = thr;\n\tcomp_ctx->h_filename = h_filename;\n\tcomp_ctx->tok11_idx = entry_top + 1;\n\tcomp_ctx->tok12_idx = entry_top + 2;\n\tcomp_ctx->tok21_idx = entry_top + 3;\n\tcomp_ctx->tok22_idx = entry_top + 4;\n\tcomp_ctx->recursion_limit = DUK_USE_COMPILER_RECLIMIT;\n\n\t/* comp_ctx->lex has been pre-initialized by caller: it has been\n\t * zeroed and input/input_length has been set.\n\t */\n\tcomp_ctx->lex.thr = thr;\n\t/* comp_ctx->lex.input and comp_ctx->lex.input_length filled by caller */\n\tcomp_ctx->lex.slot1_idx = comp_ctx->tok11_idx;\n\tcomp_ctx->lex.slot2_idx = comp_ctx->tok12_idx;\n\tcomp_ctx->lex.buf_idx = entry_top + 0;\n\tcomp_ctx->lex.buf = (duk_hbuffer_dynamic *) duk_known_hbuffer(thr, entry_top + 0);\n\tDUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(comp_ctx->lex.buf) && !DUK_HBUFFER_HAS_EXTERNAL(comp_ctx->lex.buf));\n\tcomp_ctx->lex.token_limit = DUK_COMPILER_TOKEN_LIMIT;\n\n\tlex_pt->offset = 0;\n\tlex_pt->line = 1;\n\tDUK_LEXER_SETPOINT(&comp_ctx->lex, lex_pt);    /* fills window */\n\tcomp_ctx->curr_token.start_line = 0;  /* needed for line number tracking (becomes prev_token.start_line) */\n\n\t/*\n\t *  Initialize function state for a zero-argument function\n\t */\n\n\tduk__init_func_valstack_slots(comp_ctx);\n\tDUK_ASSERT(func->num_formals == 0);\n\n\tif (is_funcexpr) {\n\t\t/* Name will be filled from function expression, not by caller.\n\t\t * This case is used by Function constructor and duk_compile()\n\t\t * API with the DUK_COMPILE_FUNCTION option.\n\t\t */\n\t\tDUK_ASSERT(func->h_name == NULL);\n\t} else {\n\t\tduk_push_hstring_stridx(thr, (is_eval ? DUK_STRIDX_EVAL :\n\t\t                                        DUK_STRIDX_GLOBAL));\n\t\tfunc->h_name = duk_get_hstring(thr, -1);\n\t}\n\n\t/*\n\t *  Parse a function body or a function-like expression, depending\n\t *  on flags.\n\t */\n\n\tDUK_ASSERT(func->is_setget == 0);\n\tfunc->is_strict = (duk_uint8_t) is_strict;\n\tDUK_ASSERT(func->is_notail == 0);\n\n\tif (is_funcexpr) {\n\t\tfunc->is_function = 1;\n\t\tDUK_ASSERT(func->is_eval == 0);\n\t\tDUK_ASSERT(func->is_global == 0);\n\t\tfunc->is_namebinding = 1;\n\t\tfunc->is_constructable = 1;\n\n\t\tduk__advance(comp_ctx);  /* init 'curr_token' */\n\t\tduk__advance_expect(comp_ctx, DUK_TOK_FUNCTION);\n\t\t(void) duk__parse_func_like_raw(comp_ctx, 0 /*flags*/);\n\t} else {\n\t\tDUK_ASSERT(func->is_function == 0);\n\t\tDUK_ASSERT(is_eval == 0 || is_eval == 1);\n\t\tfunc->is_eval = (duk_uint8_t) is_eval;\n\t\tfunc->is_global = (duk_uint8_t) !is_eval;\n\t\tDUK_ASSERT(func->is_namebinding == 0);\n\t\tDUK_ASSERT(func->is_constructable == 0);\n\n\t\tduk__parse_func_body(comp_ctx,\n\t\t                     1,             /* expect_eof */\n\t\t                     1,             /* implicit_return_value */\n\t\t                     -1);           /* expect_token */\n\t}\n\n\t/*\n\t *  Convert duk_compiler_func to a function template\n\t */\n\n\tduk__convert_to_func_template(comp_ctx);\n\n\t/*\n\t *  Wrapping duk_safe_call() will mangle the stack, just return stack top\n\t */\n\n\t/* [ ... filename (temps) func ] */\n\n\treturn 1;\n}\n\nDUK_INTERNAL void duk_js_compile(duk_hthread *thr, const duk_uint8_t *src_buffer, duk_size_t src_length, duk_small_uint_t flags) {\n\tduk__compiler_stkstate comp_stk;\n\tduk_compiler_ctx *prev_ctx;\n\tduk_ret_t safe_rc;\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(src_buffer != NULL);\n\n\t/* preinitialize lexer state partially */\n\tDUK_MEMZERO(&comp_stk, sizeof(comp_stk));\n\tcomp_stk.flags = flags;\n\tDUK_LEXER_INITCTX(&comp_stk.comp_ctx_alloc.lex);\n\tcomp_stk.comp_ctx_alloc.lex.input = src_buffer;\n\tcomp_stk.comp_ctx_alloc.lex.input_length = src_length;\n\tcomp_stk.comp_ctx_alloc.lex.flags = flags;  /* Forward flags directly for now. */\n\n\t/* [ ... filename ] */\n\n\tprev_ctx = thr->compile_ctx;\n\tthr->compile_ctx = &comp_stk.comp_ctx_alloc;  /* for duk_error_augment.c */\n\tsafe_rc = duk_safe_call(thr, duk__js_compile_raw, (void *) &comp_stk /*udata*/, 1 /*nargs*/, 1 /*nrets*/);\n\tthr->compile_ctx = prev_ctx;  /* must restore reliably before returning */\n\n\tif (safe_rc != DUK_EXEC_SUCCESS) {\n\t\tDUK_D(DUK_DPRINT(\"compilation failed: %!T\", duk_get_tval(thr, -1)));\n\t\t(void) duk_throw(thr);\n\t}\n\n\t/* [ ... template ] */\n}\n\n/* automatic undefs */\n#undef DUK__ALLOCTEMP\n#undef DUK__ALLOCTEMPS\n#undef DUK__ALLOW_AUTO_SEMI_ALWAYS\n#undef DUK__BC_INITIAL_INSTS\n#undef DUK__BP_ADDITIVE\n#undef DUK__BP_ASSIGNMENT\n#undef DUK__BP_BAND\n#undef DUK__BP_BOR\n#undef DUK__BP_BXOR\n#undef DUK__BP_CALL\n#undef DUK__BP_CLOSING\n#undef DUK__BP_COMMA\n#undef DUK__BP_CONDITIONAL\n#undef DUK__BP_EOF\n#undef DUK__BP_EQUALITY\n#undef DUK__BP_EXPONENTIATION\n#undef DUK__BP_FOR_EXPR\n#undef DUK__BP_INVALID\n#undef DUK__BP_LAND\n#undef DUK__BP_LOR\n#undef DUK__BP_MEMBER\n#undef DUK__BP_MULTIPLICATIVE\n#undef DUK__BP_POSTFIX\n#undef DUK__BP_RELATIONAL\n#undef DUK__BP_SHIFT\n#undef DUK__COMPILE_ENTRY_SLOTS\n#undef DUK__CONST_MARKER\n#undef DUK__DUMP_ISPEC\n#undef DUK__DUMP_IVALUE\n#undef DUK__EMIT_FLAG_A_IS_SOURCE\n#undef DUK__EMIT_FLAG_BC_REGCONST\n#undef DUK__EMIT_FLAG_B_IS_TARGET\n#undef DUK__EMIT_FLAG_C_IS_TARGET\n#undef DUK__EMIT_FLAG_NO_SHUFFLE_A\n#undef DUK__EMIT_FLAG_NO_SHUFFLE_B\n#undef DUK__EMIT_FLAG_NO_SHUFFLE_C\n#undef DUK__EMIT_FLAG_RESERVE_JUMPSLOT\n#undef DUK__EXPR_FLAG_ALLOW_EMPTY\n#undef DUK__EXPR_FLAG_REJECT_IN\n#undef DUK__EXPR_FLAG_REQUIRE_INIT\n#undef DUK__EXPR_RBP_MASK\n#undef DUK__FUNCTION_BODY_REQUIRE_SLOTS\n#undef DUK__FUNCTION_INIT_REQUIRE_SLOTS\n#undef DUK__FUNC_FLAG_DECL\n#undef DUK__FUNC_FLAG_GETSET\n#undef DUK__FUNC_FLAG_METDEF\n#undef DUK__FUNC_FLAG_PUSHNAME_PASS1\n#undef DUK__FUNC_FLAG_USE_PREVTOKEN\n#undef DUK__GETCONST_MAX_CONSTS_CHECK\n#undef DUK__GETTEMP\n#undef DUK__HAS_TERM\n#undef DUK__HAS_VAL\n#undef DUK__ISCONST\n#undef DUK__ISREG\n#undef DUK__ISREG_NOTTEMP\n#undef DUK__ISREG_TEMP\n#undef DUK__IS_TERMINAL\n#undef DUK__IVAL_FLAG_ALLOW_CONST\n#undef DUK__IVAL_FLAG_REQUIRE_SHORT\n#undef DUK__IVAL_FLAG_REQUIRE_TEMP\n#undef DUK__MAX_ARRAY_INIT_VALUES\n#undef DUK__MAX_CONSTS\n#undef DUK__MAX_FUNCS\n#undef DUK__MAX_OBJECT_INIT_PAIRS\n#undef DUK__MAX_TEMPS\n#undef DUK__MK_LBP\n#undef DUK__MK_LBP_FLAGS\n#undef DUK__OBJ_LIT_KEY_GET\n#undef DUK__OBJ_LIT_KEY_PLAIN\n#undef DUK__OBJ_LIT_KEY_SET\n#undef DUK__PARSE_EXPR_SLOTS\n#undef DUK__PARSE_STATEMENTS_SLOTS\n#undef DUK__RECURSION_DECREASE\n#undef DUK__RECURSION_INCREASE\n#undef DUK__REMOVECONST\n#undef DUK__SETTEMP\n#undef DUK__SETTEMP_CHECKMAX\n#undef DUK__STILL_PROLOGUE\n#undef DUK__TOKEN_LBP_BP_MASK\n#undef DUK__TOKEN_LBP_FLAG_NO_REGEXP\n#undef DUK__TOKEN_LBP_FLAG_TERMINATES\n#undef DUK__TOKEN_LBP_FLAG_UNUSED\n#undef DUK__TOKEN_LBP_GET_BP\n#line 1 \"duk_js_executor.c\"\n/*\n *  Ecmascript bytecode executor.\n */\n\n/* #include duk_internal.h -> already included */\n\n/*\n *  Local declarations.\n */\n\nDUK_LOCAL_DECL void duk__js_execute_bytecode_inner(duk_hthread *entry_thread, duk_activation *entry_act);\n\n/*\n *  Misc helpers.\n */\n\n/* Forced inline declaration, only applied for performance oriented build. */\n#if defined(DUK_USE_EXEC_PREFER_SIZE)\n#define DUK__INLINE_PERF\n#define DUK__NOINLINE_PERF\n#else\n#define DUK__INLINE_PERF DUK_ALWAYS_INLINE\n#define DUK__NOINLINE_PERF DUK_NOINLINE\n#endif\n\n/* Replace value stack top to value at 'tv_ptr'.  Optimize for\n * performance by only applying the net refcount change.\n */\n#define DUK__REPLACE_TO_TVPTR(thr,tv_ptr) do { \\\n\t\tduk_hthread *duk__thr; \\\n\t\tduk_tval *duk__tvsrc; \\\n\t\tduk_tval *duk__tvdst; \\\n\t\tduk_tval duk__tvtmp; \\\n\t\tduk__thr = (thr); \\\n\t\tduk__tvsrc = DUK_GET_TVAL_NEGIDX(duk__thr, -1); \\\n\t\tduk__tvdst = (tv_ptr); \\\n\t\tDUK_TVAL_SET_TVAL(&duk__tvtmp, duk__tvdst); \\\n\t\tDUK_TVAL_SET_TVAL(duk__tvdst, duk__tvsrc); \\\n\t\tDUK_TVAL_SET_UNDEFINED(duk__tvsrc);  /* value stack init policy */ \\\n\t\tduk__thr->valstack_top = duk__tvsrc; \\\n\t\tDUK_TVAL_DECREF(duk__thr, &duk__tvtmp); \\\n\t} while (0)\n\n/* XXX: candidate of being an internal shared API call */\n#if 0  /* unused */\nDUK_LOCAL void duk__push_tvals_incref_only(duk_hthread *thr, duk_tval *tv_src, duk_small_uint_fast_t count) {\n\tduk_tval *tv_dst;\n\tduk_size_t copy_size;\n\tduk_size_t i;\n\n\ttv_dst = thr->valstack_top;\n\tcopy_size = sizeof(duk_tval) * count;\n\tDUK_MEMCPY((void *) tv_dst, (const void *) tv_src, copy_size);\n\tfor (i = 0; i < count; i++) {\n\t\tDUK_TVAL_INCREF(thr, tv_dst);\n\t\ttv_dst++;\n\t}\n\tthr->valstack_top = tv_dst;\n}\n#endif\n\n/*\n *  Arithmetic, binary, and logical helpers.\n *\n *  Note: there is no opcode for logical AND or logical OR; this is on\n *  purpose, because the evalution order semantics for them make such\n *  opcodes pretty pointless: short circuiting means they are most\n *  comfortably implemented as jumps.  However, a logical NOT opcode\n *  is useful.\n *\n *  Note: careful with duk_tval pointers here: they are potentially\n *  invalidated by any DECREF and almost any API call.  It's still\n *  preferable to work without making a copy but that's not always\n *  possible.\n */\n\nDUK_LOCAL DUK__INLINE_PERF duk_double_t duk__compute_mod(duk_double_t d1, duk_double_t d2) {\n\treturn (duk_double_t) duk_js_arith_mod((double) d1, (double) d2);\n}\n\n#if defined(DUK_USE_ES7_EXP_OPERATOR)\nDUK_LOCAL DUK__INLINE_PERF duk_double_t duk__compute_exp(duk_double_t d1, duk_double_t d2) {\n\treturn (duk_double_t) duk_js_arith_pow((double) d1, (double) d2);\n}\n#endif\n\nDUK_LOCAL DUK__INLINE_PERF void duk__vm_arith_add(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y, duk_small_uint_fast_t idx_z) {\n\t/*\n\t *  Addition operator is different from other arithmetic\n\t *  operations in that it also provides string concatenation.\n\t *  Hence it is implemented separately.\n\t *\n\t *  There is a fast path for number addition.  Other cases go\n\t *  through potentially multiple coercions as described in the\n\t *  E5 specification.  It may be possible to reduce the number\n\t *  of coercions, but this must be done carefully to preserve\n\t *  the exact semantics.\n\t *\n\t *  E5 Section 11.6.1.\n\t *\n\t *  Custom types also have special behavior implemented here.\n\t */\n\n\tduk_double_union du;\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(tv_x != NULL);  /* may be reg or const */\n\tDUK_ASSERT(tv_y != NULL);  /* may be reg or const */\n\tDUK_ASSERT_DISABLE(idx_z >= 0);  /* unsigned */\n\tDUK_ASSERT((duk_uint_t) idx_z < (duk_uint_t) duk_get_top(thr));\n\n\t/*\n\t *  Fast paths\n\t */\n\n#if defined(DUK_USE_FASTINT)\n\tif (DUK_TVAL_IS_FASTINT(tv_x) && DUK_TVAL_IS_FASTINT(tv_y)) {\n\t\tduk_int64_t v1, v2, v3;\n\t\tduk_int32_t v3_hi;\n\t\tduk_tval *tv_z;\n\n\t\t/* Input values are signed 48-bit so we can detect overflow\n\t\t * reliably from high bits or just a comparison.\n\t\t */\n\n\t\tv1 = DUK_TVAL_GET_FASTINT(tv_x);\n\t\tv2 = DUK_TVAL_GET_FASTINT(tv_y);\n\t\tv3 = v1 + v2;\n\t\tv3_hi = (duk_int32_t) (v3 >> 32);\n\t\tif (DUK_LIKELY(v3_hi >= DUK_I64_CONSTANT(-0x8000) && v3_hi <= DUK_I64_CONSTANT(0x7fff))) {\n\t\t\ttv_z = thr->valstack_bottom + idx_z;\n\t\t\tDUK_TVAL_SET_FASTINT_UPDREF(thr, tv_z, v3);  /* side effects */\n\t\t\treturn;\n\t\t} else {\n\t\t\t/* overflow, fall through */\n\t\t\t;\n\t\t}\n\t}\n#endif  /* DUK_USE_FASTINT */\n\n\tif (DUK_TVAL_IS_NUMBER(tv_x) && DUK_TVAL_IS_NUMBER(tv_y)) {\n#if !defined(DUK_USE_EXEC_PREFER_SIZE)\n\t\tduk_tval *tv_z;\n#endif\n\n\t\tdu.d = DUK_TVAL_GET_NUMBER(tv_x) + DUK_TVAL_GET_NUMBER(tv_y);\n#if defined(DUK_USE_EXEC_PREFER_SIZE)\n\t\tduk_push_number(thr, du.d);  /* will NaN normalize result */\n\t\tduk_replace(thr, (duk_idx_t) idx_z);\n#else  /* DUK_USE_EXEC_PREFER_SIZE */\n\t\tDUK_DBLUNION_NORMALIZE_NAN_CHECK(&du);\n\t\tDUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&du));\n\t\ttv_z = thr->valstack_bottom + idx_z;\n\t\tDUK_TVAL_SET_NUMBER_UPDREF(thr, tv_z, du.d);  /* side effects */\n#endif  /* DUK_USE_EXEC_PREFER_SIZE */\n\t\treturn;\n\t}\n\n\t/*\n\t *  Slow path: potentially requires function calls for coercion\n\t */\n\n\tduk_push_tval(thr, tv_x);\n\tduk_push_tval(thr, tv_y);\n\tduk_to_primitive(thr, -2, DUK_HINT_NONE);  /* side effects -> don't use tv_x, tv_y after */\n\tduk_to_primitive(thr, -1, DUK_HINT_NONE);\n\n\t/* Since Duktape 2.x plain buffers are treated like ArrayBuffer. */\n\tif (duk_is_string(thr, -2) || duk_is_string(thr, -1)) {\n\t\t/* Symbols shouldn't technically be handled here, but should\n\t\t * go into the default ToNumber() coercion path instead and\n\t\t * fail there with a TypeError.  However, there's a ToString()\n\t\t * in duk_concat_2() which also fails with TypeError so no\n\t\t * explicit check is needed.\n\t\t */\n\t\tduk_concat_2(thr);  /* [... s1 s2] -> [... s1+s2] */\n\t} else {\n\t\tduk_double_t d1, d2;\n\n\t\td1 = duk_to_number_m2(thr);\n\t\td2 = duk_to_number_m1(thr);\n\t\tDUK_ASSERT(duk_is_number(thr, -2));\n\t\tDUK_ASSERT(duk_is_number(thr, -1));\n\t\tDUK_ASSERT_DOUBLE_IS_NORMALIZED(d1);\n\t\tDUK_ASSERT_DOUBLE_IS_NORMALIZED(d2);\n\n\t\tdu.d = d1 + d2;\n\t\tduk_pop_2_unsafe(thr);\n\t\tduk_push_number(thr, du.d);  /* will NaN normalize result */\n\t}\n\tduk_replace(thr, (duk_idx_t) idx_z);  /* side effects */\n}\n\nDUK_LOCAL DUK__INLINE_PERF void duk__vm_arith_binary_op(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y, duk_uint_fast_t idx_z, duk_small_uint_fast_t opcode) {\n\t/*\n\t *  Arithmetic operations other than '+' have number-only semantics\n\t *  and are implemented here.  The separate switch-case here means a\n\t *  \"double dispatch\" of the arithmetic opcode, but saves code space.\n\t *\n\t *  E5 Sections 11.5, 11.5.1, 11.5.2, 11.5.3, 11.6, 11.6.1, 11.6.2, 11.6.3.\n\t */\n\n\tduk_double_t d1, d2;\n\tduk_double_union du;\n\tduk_small_uint_fast_t opcode_shifted;\n#if defined(DUK_USE_FASTINT) || !defined(DUK_USE_EXEC_PREFER_SIZE)\n\tduk_tval *tv_z;\n#endif\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(tv_x != NULL);  /* may be reg or const */\n\tDUK_ASSERT(tv_y != NULL);  /* may be reg or const */\n\tDUK_ASSERT_DISABLE(idx_z >= 0);  /* unsigned */\n\tDUK_ASSERT((duk_uint_t) idx_z < (duk_uint_t) duk_get_top(thr));\n\n\topcode_shifted = opcode >> 2;  /* Get base opcode without reg/const modifiers. */\n\n#if defined(DUK_USE_FASTINT)\n\tif (DUK_TVAL_IS_FASTINT(tv_x) && DUK_TVAL_IS_FASTINT(tv_y)) {\n\t\tduk_int64_t v1, v2, v3;\n\t\tduk_int32_t v3_hi;\n\n\t\tv1 = DUK_TVAL_GET_FASTINT(tv_x);\n\t\tv2 = DUK_TVAL_GET_FASTINT(tv_y);\n\n\t\tswitch (opcode_shifted) {\n\t\tcase DUK_OP_SUB >> 2: {\n\t\t\tv3 = v1 - v2;\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_OP_MUL >> 2: {\n\t\t\t/* Must ensure result is 64-bit (no overflow); a\n\t\t\t * simple and sufficient fast path is to allow only\n\t\t\t * 32-bit inputs.  Avoid zero inputs to avoid\n\t\t\t * negative zero issues (-1 * 0 = -0, for instance).\n\t\t\t */\n\t\t\tif (v1 >= DUK_I64_CONSTANT(-0x80000000) && v1 <= DUK_I64_CONSTANT(0x7fffffff) && v1 != 0 &&\n\t\t\t    v2 >= DUK_I64_CONSTANT(-0x80000000) && v2 <= DUK_I64_CONSTANT(0x7fffffff) && v2 != 0) {\n\t\t\t\tv3 = v1 * v2;\n\t\t\t} else {\n\t\t\t\tgoto skip_fastint;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_OP_DIV >> 2: {\n\t\t\t/* Don't allow a zero divisor.  Fast path check by\n\t\t\t * \"verifying\" with multiplication.  Also avoid zero\n\t\t\t * dividend to avoid negative zero issues (0 / -1 = -0\n\t\t\t * for instance).\n\t\t\t */\n\t\t\tif (v1 == 0 || v2 == 0) {\n\t\t\t\tgoto skip_fastint;\n\t\t\t}\n\t\t\tv3 = v1 / v2;\n\t\t\tif (v3 * v2 != v1) {\n\t\t\t\tgoto skip_fastint;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_OP_MOD >> 2: {\n\t\t\t/* Don't allow a zero divisor.  Restrict both v1 and\n\t\t\t * v2 to positive values to avoid compiler specific\n\t\t\t * behavior.\n\t\t\t */\n\t\t\tif (v1 < 1 || v2 < 1) {\n\t\t\t\tgoto skip_fastint;\n\t\t\t}\n\t\t\tv3 = v1 % v2;\n\t\t\tDUK_ASSERT(v3 >= 0);\n\t\t\tDUK_ASSERT(v3 < v2);\n\t\t\tDUK_ASSERT(v1 - (v1 / v2) * v2 == v3);\n\t\t\tbreak;\n\t\t}\n\t\tdefault: {\n\t\t\t/* Possible with DUK_OP_EXP. */\n\t\t\tgoto skip_fastint;\n\t\t}\n\t\t}\n\n\t\tv3_hi = (duk_int32_t) (v3 >> 32);\n\t\tif (DUK_LIKELY(v3_hi >= DUK_I64_CONSTANT(-0x8000) && v3_hi <= DUK_I64_CONSTANT(0x7fff))) {\n\t\t\ttv_z = thr->valstack_bottom + idx_z;\n\t\t\tDUK_TVAL_SET_FASTINT_UPDREF(thr, tv_z, v3);  /* side effects */\n\t\t\treturn;\n\t\t}\n\t\t/* fall through if overflow etc */\n\t}\n skip_fastint:\n#endif  /* DUK_USE_FASTINT */\n\n\tif (DUK_TVAL_IS_NUMBER(tv_x) && DUK_TVAL_IS_NUMBER(tv_y)) {\n\t\t/* fast path */\n\t\td1 = DUK_TVAL_GET_NUMBER(tv_x);\n\t\td2 = DUK_TVAL_GET_NUMBER(tv_y);\n\t} else {\n\t\tduk_push_tval(thr, tv_x);\n\t\tduk_push_tval(thr, tv_y);\n\t\td1 = duk_to_number_m2(thr);  /* side effects */\n\t\td2 = duk_to_number_m1(thr);\n\t\tDUK_ASSERT(duk_is_number(thr, -2));\n\t\tDUK_ASSERT(duk_is_number(thr, -1));\n\t\tDUK_ASSERT_DOUBLE_IS_NORMALIZED(d1);\n\t\tDUK_ASSERT_DOUBLE_IS_NORMALIZED(d2);\n\t\tduk_pop_2_unsafe(thr);\n\t}\n\n\tswitch (opcode_shifted) {\n\tcase DUK_OP_SUB >> 2: {\n\t\tdu.d = d1 - d2;\n\t\tbreak;\n\t}\n\tcase DUK_OP_MUL >> 2: {\n\t\tdu.d = d1 * d2;\n\t\tbreak;\n\t}\n\tcase DUK_OP_DIV >> 2: {\n\t\tdu.d = d1 / d2;\n\t\tbreak;\n\t}\n\tcase DUK_OP_MOD >> 2: {\n\t\tdu.d = duk__compute_mod(d1, d2);\n\t\tbreak;\n\t}\n#if defined(DUK_USE_ES7_EXP_OPERATOR)\n\tcase DUK_OP_EXP >> 2: {\n\t\tdu.d = duk__compute_exp(d1, d2);\n\t\tbreak;\n\t}\n#endif\n\tdefault: {\n\t\tDUK_UNREACHABLE();\n\t\tdu.d = DUK_DOUBLE_NAN;  /* should not happen */\n\t\tbreak;\n\t}\n\t}\n\n#if defined(DUK_USE_EXEC_PREFER_SIZE)\n\tduk_push_number(thr, du.d);  /* will NaN normalize result */\n\tduk_replace(thr, (duk_idx_t) idx_z);\n#else  /* DUK_USE_EXEC_PREFER_SIZE */\n\t/* important to use normalized NaN with 8-byte tagged types */\n\tDUK_DBLUNION_NORMALIZE_NAN_CHECK(&du);\n\tDUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&du));\n\ttv_z = thr->valstack_bottom + idx_z;\n\tDUK_TVAL_SET_NUMBER_UPDREF(thr, tv_z, du.d);  /* side effects */\n#endif  /* DUK_USE_EXEC_PREFER_SIZE */\n}\n\nDUK_LOCAL DUK__INLINE_PERF void duk__vm_bitwise_binary_op(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y, duk_small_uint_fast_t idx_z, duk_small_uint_fast_t opcode) {\n\t/*\n\t *  Binary bitwise operations use different coercions (ToInt32, ToUint32)\n\t *  depending on the operation.  We coerce the arguments first using\n\t *  ToInt32(), and then cast to an 32-bit value if necessary.  Note that\n\t *  such casts must be correct even if there is no native 32-bit type\n\t *  (e.g., duk_int32_t and duk_uint32_t are 64-bit).\n\t *\n\t *  E5 Sections 11.10, 11.7.1, 11.7.2, 11.7.3\n\t */\n\n\tduk_int32_t i1, i2, i3;\n\tduk_uint32_t u1, u2, u3;\n#if defined(DUK_USE_FASTINT)\n\tduk_int64_t fi3;\n#else\n\tduk_double_t d3;\n#endif\n\tduk_small_uint_fast_t opcode_shifted;\n#if defined(DUK_USE_FASTINT) || !defined(DUK_USE_EXEC_PREFER_SIZE)\n\tduk_tval *tv_z;\n#endif\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(tv_x != NULL);  /* may be reg or const */\n\tDUK_ASSERT(tv_y != NULL);  /* may be reg or const */\n\tDUK_ASSERT_DISABLE(idx_z >= 0);  /* unsigned */\n\tDUK_ASSERT((duk_uint_t) idx_z < (duk_uint_t) duk_get_top(thr));\n\n\topcode_shifted = opcode >> 2;  /* Get base opcode without reg/const modifiers. */\n\n#if defined(DUK_USE_FASTINT)\n\tif (DUK_TVAL_IS_FASTINT(tv_x) && DUK_TVAL_IS_FASTINT(tv_y)) {\n\t\ti1 = (duk_int32_t) DUK_TVAL_GET_FASTINT_I32(tv_x);\n\t\ti2 = (duk_int32_t) DUK_TVAL_GET_FASTINT_I32(tv_y);\n\t}\n\telse\n#endif  /* DUK_USE_FASTINT */\n\t{\n\t\tduk_push_tval(thr, tv_x);\n\t\tduk_push_tval(thr, tv_y);\n\t\ti1 = duk_to_int32(thr, -2);\n\t\ti2 = duk_to_int32(thr, -1);\n\t\tduk_pop_2_unsafe(thr);\n\t}\n\n\tswitch (opcode_shifted) {\n\tcase DUK_OP_BAND >> 2: {\n\t\ti3 = i1 & i2;\n\t\tbreak;\n\t}\n\tcase DUK_OP_BOR >> 2: {\n\t\ti3 = i1 | i2;\n\t\tbreak;\n\t}\n\tcase DUK_OP_BXOR >> 2: {\n\t\ti3 = i1 ^ i2;\n\t\tbreak;\n\t}\n\tcase DUK_OP_BASL >> 2: {\n\t\t/* Signed shift, named \"arithmetic\" (asl) because the result\n\t\t * is signed, e.g. 4294967295 << 1 -> -2.  Note that result\n\t\t * must be masked.\n\t\t */\n\n\t\tu2 = ((duk_uint32_t) i2) & 0xffffffffUL;\n\t\ti3 = (duk_int32_t) (((duk_uint32_t) i1) << (u2 & 0x1fUL));  /* E5 Section 11.7.1, steps 7 and 8 */\n\t\ti3 = i3 & ((duk_int32_t) 0xffffffffUL);                     /* Note: left shift, should mask */\n\t\tbreak;\n\t}\n\tcase DUK_OP_BASR >> 2: {\n\t\t/* signed shift */\n\n\t\tu2 = ((duk_uint32_t) i2) & 0xffffffffUL;\n\t\ti3 = i1 >> (u2 & 0x1fUL);                      /* E5 Section 11.7.2, steps 7 and 8 */\n\t\tbreak;\n\t}\n\tcase DUK_OP_BLSR >> 2: {\n\t\t/* unsigned shift */\n\n\t\tu1 = ((duk_uint32_t) i1) & 0xffffffffUL;\n\t\tu2 = ((duk_uint32_t) i2) & 0xffffffffUL;\n\n\t\t/* special result value handling */\n\t\tu3 = u1 >> (u2 & 0x1fUL);     /* E5 Section 11.7.2, steps 7 and 8 */\n#if defined(DUK_USE_FASTINT)\n\t\tfi3 = (duk_int64_t) u3;\n\t\tgoto fastint_result_set;\n#else\n\t\td3 = (duk_double_t) u3;\n\t\tgoto result_set;\n#endif\n\t}\n\tdefault: {\n\t\tDUK_UNREACHABLE();\n\t\ti3 = 0;  /* should not happen */\n\t\tbreak;\n\t}\n\t}\n\n#if defined(DUK_USE_FASTINT)\n\t/* Result is always fastint compatible. */\n\t/* XXX: Set 32-bit result (but must then handle signed and\n\t * unsigned results separately).\n\t */\n\tfi3 = (duk_int64_t) i3;\n\n fastint_result_set:\n\ttv_z = thr->valstack_bottom + idx_z;\n\tDUK_TVAL_SET_FASTINT_UPDREF(thr, tv_z, fi3);  /* side effects */\n#else  /* DUK_USE_FASTINT */\n\td3 = (duk_double_t) i3;\n\n result_set:\n\tDUK_ASSERT(!DUK_ISNAN(d3));            /* 'd3' is never NaN, so no need to normalize */\n\tDUK_ASSERT_DOUBLE_IS_NORMALIZED(d3);   /* always normalized */\n\n#if defined(DUK_USE_EXEC_PREFER_SIZE)\n\tduk_push_number(thr, d3);  /* would NaN normalize result, but unnecessary */\n\tduk_replace(thr, (duk_idx_t) idx_z);\n#else  /* DUK_USE_EXEC_PREFER_SIZE */\n\ttv_z = thr->valstack_bottom + idx_z;\n\tDUK_TVAL_SET_NUMBER_UPDREF(thr, tv_z, d3);  /* side effects */\n#endif  /* DUK_USE_EXEC_PREFER_SIZE */\n#endif  /* DUK_USE_FASTINT */\n}\n\n/* In-place unary operation. */\nDUK_LOCAL DUK__INLINE_PERF void duk__vm_arith_unary_op(duk_hthread *thr, duk_uint_fast_t idx_src, duk_uint_fast_t idx_dst, duk_small_uint_fast_t opcode) {\n\t/*\n\t *  Arithmetic operations other than '+' have number-only semantics\n\t *  and are implemented here.  The separate switch-case here means a\n\t *  \"double dispatch\" of the arithmetic opcode, but saves code space.\n\t *\n\t *  E5 Sections 11.5, 11.5.1, 11.5.2, 11.5.3, 11.6, 11.6.1, 11.6.2, 11.6.3.\n\t */\n\n\tduk_tval *tv;\n\tduk_double_t d1;\n\tduk_double_union du;\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(opcode == DUK_OP_UNM || opcode == DUK_OP_UNP);\n\tDUK_ASSERT_DISABLE(idx_src >= 0);\n\tDUK_ASSERT_DISABLE(idx_dst >= 0);\n\n\ttv = DUK_GET_TVAL_POSIDX(thr, (duk_idx_t) idx_src);\n\n#if defined(DUK_USE_FASTINT)\n\tif (DUK_TVAL_IS_FASTINT(tv)) {\n\t\tduk_int64_t v1, v2;\n\n\t\tv1 = DUK_TVAL_GET_FASTINT(tv);\n\t\tif (opcode == DUK_OP_UNM) {\n\t\t\t/* The smallest fastint is no longer 48-bit when\n\t\t\t * negated.  Positive zero becames negative zero\n\t\t\t * (cannot be represented) when negated.\n\t\t\t */\n\t\t\tif (DUK_LIKELY(v1 != DUK_FASTINT_MIN && v1 != 0)) {\n\t\t\t\tv2 = -v1;\n\t\t\t\ttv = DUK_GET_TVAL_POSIDX(thr, (duk_idx_t) idx_dst);\n\t\t\t\tDUK_TVAL_SET_FASTINT_UPDREF(thr, tv, v2);\n\t\t\t\treturn;\n\t\t\t}\n\t\t} else {\n\t\t\t/* ToNumber() for a fastint is a no-op. */\n\t\t\tDUK_ASSERT(opcode == DUK_OP_UNP);\n\t\t\tv2 = v1;\n\t\t\ttv = DUK_GET_TVAL_POSIDX(thr, (duk_idx_t) idx_dst);\n\t\t\tDUK_TVAL_SET_FASTINT_UPDREF(thr, tv, v2);\n\t\t\treturn;\n\t\t}\n\t\t/* fall through if overflow etc */\n\t}\n#endif  /* DUK_USE_FASTINT */\n\n\tif (DUK_TVAL_IS_NUMBER(tv)) {\n\t\td1 = DUK_TVAL_GET_NUMBER(tv);\n\t} else {\n\t\td1 = duk_to_number_tval(thr, tv);  /* side effects */\n\t}\n\n\tif (opcode == DUK_OP_UNP) {\n\t\t/* ToNumber() for a double is a no-op, but unary plus is\n\t\t * used to force a fastint check so do that here.\n\t\t */\n\t\tdu.d = d1;\n\t\tDUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&du));\n#if defined(DUK_USE_FASTINT)\n\t\ttv = DUK_GET_TVAL_POSIDX(thr, (duk_idx_t) idx_dst);\n\t\tDUK_TVAL_SET_NUMBER_CHKFAST_UPDREF(thr, tv, du.d);  /* always 'fast', i.e. inlined */\n\t\treturn;\n#endif\n\t} else {\n\t\tDUK_ASSERT(opcode == DUK_OP_UNM);\n\t\tdu.d = -d1;\n\t\tDUK_DBLUNION_NORMALIZE_NAN_CHECK(&du);  /* mandatory if du.d is a NaN */\n\t\tDUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&du));\n\t}\n\n\t/* XXX: size optimize: push+replace? */\n\ttv = DUK_GET_TVAL_POSIDX(thr, (duk_idx_t) idx_dst);\n\tDUK_TVAL_SET_NUMBER_UPDREF(thr, tv, du.d);\n}\n\nDUK_LOCAL DUK__INLINE_PERF void duk__vm_bitwise_not(duk_hthread *thr, duk_uint_fast_t idx_src, duk_uint_fast_t idx_dst) {\n\t/*\n\t *  E5 Section 11.4.8\n\t */\n\n\tduk_tval *tv;\n\tduk_int32_t i1, i2;\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT_DISABLE(idx_src >= 0);\n\tDUK_ASSERT_DISABLE(idx_dst >= 0);\n\tDUK_ASSERT((duk_uint_t) idx_src < (duk_uint_t) duk_get_top(thr));\n\tDUK_ASSERT((duk_uint_t) idx_dst < (duk_uint_t) duk_get_top(thr));\n\n\ttv = DUK_GET_TVAL_POSIDX(thr, (duk_idx_t) idx_src);\n\n#if defined(DUK_USE_FASTINT)\n\tif (DUK_TVAL_IS_FASTINT(tv)) {\n\t\ti1 = (duk_int32_t) DUK_TVAL_GET_FASTINT_I32(tv);\n\t}\n\telse\n#endif  /* DUK_USE_FASTINT */\n\t{\n\t\tduk_push_tval(thr, tv);\n\t\ti1 = duk_to_int32(thr, -1);  /* side effects */\n\t\tduk_pop_unsafe(thr);\n\t}\n\n\t/* Result is always fastint compatible. */\n\ti2 = ~i1;\n\ttv = DUK_GET_TVAL_POSIDX(thr, (duk_idx_t) idx_dst);\n\tDUK_TVAL_SET_I32_UPDREF(thr, tv, i2);  /* side effects */\n}\n\nDUK_LOCAL DUK__INLINE_PERF void duk__vm_logical_not(duk_hthread *thr, duk_uint_fast_t idx_src, duk_uint_fast_t idx_dst) {\n\t/*\n\t *  E5 Section 11.4.9\n\t */\n\n\tduk_tval *tv;\n\tduk_bool_t res;\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT_DISABLE(idx_src >= 0);\n\tDUK_ASSERT_DISABLE(idx_dst >= 0);\n\tDUK_ASSERT((duk_uint_t) idx_src < (duk_uint_t) duk_get_top(thr));\n\tDUK_ASSERT((duk_uint_t) idx_dst < (duk_uint_t) duk_get_top(thr));\n\n\t/* ToBoolean() does not require any operations with side effects so\n\t * we can do it efficiently.  For footprint it would be better to use\n\t * duk_js_toboolean() and then push+replace to the result slot.\n\t */\n\ttv = DUK_GET_TVAL_POSIDX(thr, (duk_idx_t) idx_src);\n\tres = duk_js_toboolean(tv);  /* does not modify 'tv' */\n\tDUK_ASSERT(res == 0 || res == 1);\n\tres ^= 1;\n\ttv = DUK_GET_TVAL_POSIDX(thr, (duk_idx_t) idx_dst);\n\t/* XXX: size optimize: push+replace? */\n\tDUK_TVAL_SET_BOOLEAN_UPDREF(thr, tv, res);  /* side effects */\n}\n\n/* XXX: size optimized variant */\nDUK_LOCAL DUK__INLINE_PERF void duk__prepost_incdec_reg_helper(duk_hthread *thr, duk_tval *tv_dst, duk_tval *tv_src, duk_small_uint_t op) {\n\tduk_double_t x, y, z;\n\n\t/* Two lowest bits of opcode are used to distinguish\n\t * variants.  Bit 0 = inc(0)/dec(1), bit 1 = pre(0)/post(1).\n\t */\n\tDUK_ASSERT((DUK_OP_PREINCR & 0x03) == 0x00);\n\tDUK_ASSERT((DUK_OP_PREDECR & 0x03) == 0x01);\n\tDUK_ASSERT((DUK_OP_POSTINCR & 0x03) == 0x02);\n\tDUK_ASSERT((DUK_OP_POSTDECR & 0x03) == 0x03);\n\n#if defined(DUK_USE_FASTINT)\n\tif (DUK_TVAL_IS_FASTINT(tv_src)) {\n\t\tduk_int64_t x_fi, y_fi, z_fi;\n\t\tx_fi = DUK_TVAL_GET_FASTINT(tv_src);\n\t\tif (op & 0x01) {\n\t\t\tif (DUK_UNLIKELY(x_fi == DUK_FASTINT_MIN)) {\n\t\t\t\tgoto skip_fastint;\n\t\t\t}\n\t\t\ty_fi = x_fi - 1;\n\t\t} else {\n\t\t\tif (DUK_UNLIKELY(x_fi == DUK_FASTINT_MAX)) {\n\t\t\t\tgoto skip_fastint;\n\t\t\t}\n\t\t\ty_fi = x_fi + 1;\n\t\t}\n\n\t\tDUK_TVAL_SET_FASTINT(tv_src, y_fi);  /* no need for refcount update */\n\n\t\tz_fi = (op & 0x02) ? x_fi : y_fi;\n\t\tDUK_TVAL_SET_FASTINT_UPDREF(thr, tv_dst, z_fi);  /* side effects */\n\t\treturn;\n\t}\n skip_fastint:\n#endif\n\tif (DUK_TVAL_IS_NUMBER(tv_src)) {\n\t\t/* Fast path for the case where the register\n\t\t * is a number (e.g. loop counter).\n\t\t */\n\n\t\tx = DUK_TVAL_GET_NUMBER(tv_src);\n\t\tif (op & 0x01) {\n\t\t\ty = x - 1.0;\n\t\t} else {\n\t\t\ty = x + 1.0;\n\t\t}\n\n\t\tDUK_TVAL_SET_NUMBER(tv_src, y);  /* no need for refcount update */\n\t} else {\n\t\t/* Preserve duk_tval pointer(s) across a potential valstack\n\t\t * resize by converting them into offsets temporarily.\n\t\t */\n\t\tduk_idx_t bc;\n\t\tduk_size_t off_dst;\n\n\t\toff_dst = (duk_size_t) ((duk_uint8_t *) tv_dst - (duk_uint8_t *) thr->valstack_bottom);\n\t\tbc = (duk_idx_t) (tv_src - thr->valstack_bottom);  /* XXX: pass index explicitly? */\n\t\ttv_src = NULL;  /* no longer referenced */\n\n\t\tx = duk_to_number(thr, bc);\n\t\tif (op & 0x01) {\n\t\t\ty = x - 1.0;\n\t\t} else {\n\t\t\ty = x + 1.0;\n\t\t}\n\n\t\tduk_push_number(thr, y);\n\t\tduk_replace(thr, bc);\n\n\t\ttv_dst = (duk_tval *) (void *) (((duk_uint8_t *) thr->valstack_bottom) + off_dst);\n\t}\n\n\tz = (op & 0x02) ? x : y;\n\tDUK_TVAL_SET_NUMBER_UPDREF(thr, tv_dst, z);  /* side effects */\n}\n\nDUK_LOCAL DUK__INLINE_PERF void duk__prepost_incdec_var_helper(duk_hthread *thr, duk_small_uint_t idx_dst, duk_tval *tv_id, duk_small_uint_t op, duk_small_uint_t is_strict) {\n\tduk_activation *act;\n\tduk_double_t x, y;\n\tduk_hstring *name;\n\n\t/* XXX: The pre/post inc/dec for an identifier lookup is\n\t * missing the important fast path where the identifier\n\t * has a storage location e.g. in a scope object so that\n\t * it can be updated in-place.  In particular, the case\n\t * where the identifier has a storage location AND the\n\t * previous value is a number should be optimized because\n\t * it's side effect free.\n\t */\n\n\t/* Two lowest bits of opcode are used to distinguish\n\t * variants.  Bit 0 = inc(0)/dec(1), bit 1 = pre(0)/post(1).\n\t */\n\tDUK_ASSERT((DUK_OP_PREINCV & 0x03) == 0x00);\n\tDUK_ASSERT((DUK_OP_PREDECV & 0x03) == 0x01);\n\tDUK_ASSERT((DUK_OP_POSTINCV & 0x03) == 0x02);\n\tDUK_ASSERT((DUK_OP_POSTDECV & 0x03) == 0x03);\n\n\tDUK_ASSERT(DUK_TVAL_IS_STRING(tv_id));\n\tname = DUK_TVAL_GET_STRING(tv_id);\n\tDUK_ASSERT(name != NULL);\n\tact = thr->callstack_curr;\n\t(void) duk_js_getvar_activation(thr, act, name, 1 /*throw*/);  /* -> [ ... val this ] */\n\n\t/* XXX: Fastint fast path would be useful here.  Also fastints\n\t * now lose their fastint status in current handling which is\n\t * not intuitive.\n\t */\n\n\tx = duk_to_number_m2(thr);\n\tif (op & 0x01) {\n\t\ty = x - 1.0;\n\t} else {\n\t\ty = x + 1.0;\n\t}\n\n\t/* [... x this] */\n\n\tif (op & 0x02) {\n\t\tduk_push_number(thr, y);  /* -> [ ... x this y ] */\n\t\tDUK_ASSERT(act == thr->callstack_curr);\n\t\tduk_js_putvar_activation(thr, act, name, DUK_GET_TVAL_NEGIDX(thr, -1), is_strict);\n\t\tduk_pop_2_unsafe(thr);  /* -> [ ... x ] */\n\t} else {\n\t\tduk_pop_2_unsafe(thr);  /* -> [ ... ] */\n\t\tduk_push_number(thr, y);  /* -> [ ... y ] */\n\t\tDUK_ASSERT(act == thr->callstack_curr);\n\t\tduk_js_putvar_activation(thr, act, name, DUK_GET_TVAL_NEGIDX(thr, -1), is_strict);\n\t}\n\n#if defined(DUK_USE_EXEC_PREFER_SIZE)\n\tduk_replace(thr, (duk_idx_t) idx_dst);\n#else  /* DUK_USE_EXEC_PREFER_SIZE */\n\tDUK__REPLACE_TO_TVPTR(thr, DUK_GET_TVAL_POSIDX(thr, (duk_idx_t) idx_dst));\n#endif  /* DUK_USE_EXEC_PREFER_SIZE */\n}\n\n/*\n *  Longjmp and other control flow transfer for the bytecode executor.\n *\n *  The longjmp handler can handle all longjmp types: error, yield, and\n *  resume (pseudotypes are never actually thrown).\n *\n *  Error policy for longjmp: should not ordinarily throw errors; if errors\n *  occur (e.g. due to out-of-memory) they bubble outwards rather than being\n *  handled recursively.\n */\n\n#define DUK__LONGJMP_RESTART   0  /* state updated, restart bytecode execution */\n#define DUK__LONGJMP_RETHROW   1  /* exit bytecode executor by rethrowing an error to caller */\n\n#define DUK__RETHAND_RESTART   0  /* state updated, restart bytecode execution */\n#define DUK__RETHAND_FINISHED  1  /* exit bytecode execution with return value */\n\n/* XXX: optimize reconfig valstack operations so that resize, clamp, and setting\n * top are combined into one pass.\n */\n\n/* Reconfigure value stack for return to an Ecmascript function at\n * callstack top (caller unwinds).\n */\nDUK_LOCAL void duk__reconfig_valstack_ecma_return(duk_hthread *thr) {\n\tduk_activation *act;\n\tduk_hcompfunc *h_func;\n\tduk_idx_t clamp_top;\n\n\tDUK_ASSERT(thr != NULL);\n\tact = thr->callstack_curr;\n\tDUK_ASSERT(act != NULL);\n\tDUK_ASSERT(DUK_ACT_GET_FUNC(act) != NULL);\n\tDUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(act)));\n\n\t/* Clamp so that values at 'clamp_top' and above are wiped and won't\n\t * retain reachable garbage.  Then extend to 'nregs' because we're\n\t * returning to an Ecmascript function.\n\t */\n\n\th_func = (duk_hcompfunc *) DUK_ACT_GET_FUNC(act);\n\n\tthr->valstack_bottom = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + act->bottom_byteoff);\n\tDUK_ASSERT(act->retval_byteoff >= act->bottom_byteoff);\n\tclamp_top = (duk_idx_t) ((act->retval_byteoff - act->bottom_byteoff + sizeof(duk_tval)) / sizeof(duk_tval));  /* +1 = one retval */\n\tduk_set_top_and_wipe(thr, h_func->nregs, clamp_top);\n\n\tDUK_ASSERT((duk_uint8_t *) thr->valstack_end >= (duk_uint8_t *) thr->valstack + act->reserve_byteoff);\n\tthr->valstack_end = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + act->reserve_byteoff);\n\n\t/* XXX: a best effort shrink check would be OK here */\n}\n\n/* Reconfigure value stack for an Ecmascript catcher.  Use topmost catcher\n * in 'act'.\n */\nDUK_LOCAL void duk__reconfig_valstack_ecma_catcher(duk_hthread *thr, duk_activation *act) {\n\tduk_catcher *cat;\n\tduk_hcompfunc *h_func;\n\tduk_size_t idx_bottom;\n\tduk_idx_t clamp_top;\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(act != NULL);\n\tDUK_ASSERT(DUK_ACT_GET_FUNC(act) != NULL);\n\tDUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(act)));\n\tcat = act->cat;\n\tDUK_ASSERT(cat != NULL);\n\n\th_func = (duk_hcompfunc *) DUK_ACT_GET_FUNC(act);\n\n\tthr->valstack_bottom = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + act->bottom_byteoff);\n\tidx_bottom = (duk_size_t) (thr->valstack_bottom - thr->valstack);\n\tDUK_ASSERT(cat->idx_base >= idx_bottom);\n\tclamp_top = (duk_idx_t) (cat->idx_base - idx_bottom + 2);  /* +2 = catcher value, catcher lj_type */\n\tduk_set_top_and_wipe(thr, h_func->nregs, clamp_top);\n\n\tDUK_ASSERT((duk_uint8_t *) thr->valstack_end >= (duk_uint8_t *) thr->valstack + act->reserve_byteoff);\n\tthr->valstack_end = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + act->reserve_byteoff);\n\n\t/* XXX: a best effort shrink check would be OK here */\n}\n\n/* Set catcher regs: idx_base+0 = value, idx_base+1 = lj_type.\n * No side effects.\n */\nDUK_LOCAL void duk__set_catcher_regs_norz(duk_hthread *thr, duk_catcher *cat, duk_tval *tv_val_unstable, duk_small_uint_t lj_type) {\n\tduk_tval *tv1;\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(tv_val_unstable != NULL);\n\n\ttv1 = thr->valstack + cat->idx_base;\n\tDUK_ASSERT(tv1 < thr->valstack_top);\n\tDUK_TVAL_SET_TVAL_UPDREF_NORZ(thr, tv1, tv_val_unstable);\n\n\ttv1++;\n\tDUK_ASSERT(tv1 == thr->valstack + cat->idx_base + 1);\n\tDUK_ASSERT(tv1 < thr->valstack_top);\n\tDUK_TVAL_SET_U32_UPDREF_NORZ(thr, tv1, (duk_uint32_t) lj_type);\n}\n\nDUK_LOCAL void duk__handle_catch(duk_hthread *thr, duk_tval *tv_val_unstable, duk_small_uint_t lj_type) {\n\tduk_activation *act;\n\tduk_catcher *cat;\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(tv_val_unstable != NULL);\n\n\tact = thr->callstack_curr;\n\tDUK_ASSERT(act != NULL);\n\tDUK_ASSERT(act->cat != NULL);\n\tDUK_ASSERT(DUK_CAT_GET_TYPE(act->cat) == DUK_CAT_TYPE_TCF);\n\n\tduk__set_catcher_regs_norz(thr, act->cat, tv_val_unstable, lj_type);\n\n\tDUK_ASSERT(thr->callstack_top >= 1);\n\tDUK_ASSERT(thr->callstack_curr != NULL);\n\tDUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack_curr) != NULL);\n\tDUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(thr->callstack_curr)));\n\n\tDUK_ASSERT(thr->callstack_top >= 1);\n\tDUK_ASSERT(act == thr->callstack_curr);\n\tDUK_ASSERT(act != NULL);\n\tduk__reconfig_valstack_ecma_catcher(thr, act);\n\n\tDUK_ASSERT(thr->callstack_top >= 1);\n\tDUK_ASSERT(act == thr->callstack_curr);\n\tDUK_ASSERT(act != NULL);\n\tcat = act->cat;\n\tDUK_ASSERT(cat != NULL);\n\n\tact->curr_pc = cat->pc_base + 0;  /* +0 = catch */\n\n\t/*\n\t *  If entering a 'catch' block which requires an automatic\n\t *  catch variable binding, create the lexical environment.\n\t *\n\t *  The binding is mutable (= writable) but not deletable.\n\t *  Step 4 for the catch production in E5 Section 12.14;\n\t *  no value is given for CreateMutableBinding 'D' argument,\n\t *  which implies the binding is not deletable.\n\t */\n\n\tif (DUK_CAT_HAS_CATCH_BINDING_ENABLED(cat)) {\n\t\tduk_hdecenv *new_env;\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"catcher has an automatic catch binding\"));\n\n\t\tDUK_ASSERT(thr->callstack_top >= 1);\n\t\tDUK_ASSERT(act == thr->callstack_curr);\n\t\tDUK_ASSERT(act != NULL);\n\n\t\tif (act->lex_env == NULL) {\n\t\t\tDUK_ASSERT(act->var_env == NULL);\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"delayed environment initialization\"));\n\n\t\t\tduk_js_init_activation_environment_records_delayed(thr, act);\n\t\t\tDUK_ASSERT(act == thr->callstack_curr);\n\t\t\tDUK_ASSERT(act != NULL);\n\t\t}\n\t\tDUK_ASSERT(act->lex_env != NULL);\n\t\tDUK_ASSERT(act->var_env != NULL);\n\t\tDUK_ASSERT(DUK_ACT_GET_FUNC(act) != NULL);\n\n\t\t/* XXX: If an out-of-memory happens here, longjmp state asserts\n\t\t * will be triggered at present and a try-catch fails to catch.\n\t\t * That's not sandboxing fatal (C API protected calls are what\n\t\t * matters), and script catch code can immediately throw anyway\n\t\t * for almost any operation.\n\t\t */\n\t\tnew_env = duk_hdecenv_alloc(thr,\n\t\t                            DUK_HOBJECT_FLAG_EXTENSIBLE |\n\t\t                            DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_DECENV));\n\t\tDUK_ASSERT(new_env != NULL);\n\t\tduk_push_hobject(thr, (duk_hobject *) new_env);\n\t\tDUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) new_env) == NULL);\n\t\tDUK_DDD(DUK_DDDPRINT(\"new_env allocated: %!iO\", (duk_heaphdr *) new_env));\n\n\t\t/* Note: currently the catch binding is handled without a register\n\t\t * binding because we don't support dynamic register bindings (they\n\t\t * must be fixed for an entire function).  So, there is no need to\n\t\t * record regbases etc.\n\t\t */\n\n\t\t/* XXX: duk_xdef_prop() may cause an out-of-memory, see above. */\n\t\tDUK_ASSERT(cat->h_varname != NULL);\n\t\tduk_push_hstring(thr, cat->h_varname);\n\t\tduk_push_tval(thr, thr->valstack + cat->idx_base);\n\t\tduk_xdef_prop(thr, -3, DUK_PROPDESC_FLAGS_W);  /* writable, not configurable */\n\n\t\tDUK_ASSERT(act == thr->callstack_curr);\n\t\tDUK_ASSERT(act != NULL);\n\t\tDUK_HOBJECT_SET_PROTOTYPE(thr->heap, (duk_hobject *) new_env, act->lex_env);\n\t\tact->lex_env = (duk_hobject *) new_env;\n\t\tDUK_HOBJECT_INCREF(thr, (duk_hobject *) new_env);  /* reachable through activation */\n\t\t/* Net refcount change to act->lex_env is 0: incref for new_env's\n\t\t * prototype, decref for act->lex_env overwrite.\n\t\t */\n\n\t\tDUK_CAT_SET_LEXENV_ACTIVE(cat);\n\n\t\tduk_pop_unsafe(thr);\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"new_env finished: %!iO\", (duk_heaphdr *) new_env));\n\t}\n\n\tDUK_CAT_CLEAR_CATCH_ENABLED(cat);\n}\n\nDUK_LOCAL void duk__handle_finally(duk_hthread *thr, duk_tval *tv_val_unstable, duk_small_uint_t lj_type) {\n\tduk_activation *act;\n\tduk_catcher *cat;\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(tv_val_unstable != NULL);\n\n\tact = thr->callstack_curr;\n\tDUK_ASSERT(act != NULL);\n\tDUK_ASSERT(act->cat != NULL);\n\tDUK_ASSERT(DUK_CAT_GET_TYPE(act->cat) == DUK_CAT_TYPE_TCF);\n\n\tduk__set_catcher_regs_norz(thr, act->cat, tv_val_unstable, lj_type);\n\n\tDUK_ASSERT(thr->callstack_top >= 1);\n\tDUK_ASSERT(thr->callstack_curr != NULL);\n\tDUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack_curr) != NULL);\n\tDUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(thr->callstack_curr)));\n\n\tDUK_ASSERT(thr->callstack_top >= 1);\n\tDUK_ASSERT(act == thr->callstack_curr);\n\tDUK_ASSERT(act != NULL);\n\tduk__reconfig_valstack_ecma_catcher(thr, act);\n\n\tDUK_ASSERT(thr->callstack_top >= 1);\n\tDUK_ASSERT(act == thr->callstack_curr);\n\tDUK_ASSERT(act != NULL);\n\tcat = act->cat;\n\tDUK_ASSERT(cat != NULL);\n\n\tact->curr_pc = cat->pc_base + 1;  /* +1 = finally */\n\n\tDUK_CAT_CLEAR_FINALLY_ENABLED(cat);\n}\n\nDUK_LOCAL void duk__handle_label(duk_hthread *thr, duk_small_uint_t lj_type) {\n\tduk_activation *act;\n\tduk_catcher *cat;\n\n\tDUK_ASSERT(thr != NULL);\n\n\tDUK_ASSERT(thr->callstack_top >= 1);\n\tact = thr->callstack_curr;\n\tDUK_ASSERT(act != NULL);\n\tDUK_ASSERT(DUK_ACT_GET_FUNC(act) != NULL);\n\tDUK_ASSERT(DUK_HOBJECT_HAS_COMPFUNC(DUK_ACT_GET_FUNC(act)));\n\n\t/* +0 = break, +1 = continue */\n\tcat = act->cat;\n\tDUK_ASSERT(cat != NULL);\n\tDUK_ASSERT(DUK_CAT_GET_TYPE(cat) == DUK_CAT_TYPE_LABEL);\n\n\tact->curr_pc = cat->pc_base + (lj_type == DUK_LJ_TYPE_CONTINUE ? 1 : 0);\n\n\t/* valstack should not need changes */\n#if defined(DUK_USE_ASSERTIONS)\n\tDUK_ASSERT(thr->callstack_top >= 1);\n\tDUK_ASSERT(act == thr->callstack_curr);\n\tDUK_ASSERT(act != NULL);\n\tDUK_ASSERT((duk_size_t) (thr->valstack_top - thr->valstack_bottom) ==\n\t           (duk_size_t) ((duk_hcompfunc *) DUK_ACT_GET_FUNC(act))->nregs);\n#endif\n}\n\n/* Called for handling both a longjmp() with type DUK_LJ_TYPE_YIELD and\n * when a RETURN opcode terminates a thread and yields to the resumer.\n * Caller unwinds so that top of callstack is the activation we return to.\n */\n#if defined(DUK_USE_COROUTINE_SUPPORT)\nDUK_LOCAL void duk__handle_yield(duk_hthread *thr, duk_hthread *resumer, duk_tval *tv_val_unstable) {\n\tduk_activation *act_resumer;\n\tduk_tval *tv1;\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(resumer != NULL);\n\tDUK_ASSERT(tv_val_unstable != NULL);\n\tact_resumer = resumer->callstack_curr;\n\tDUK_ASSERT(act_resumer != NULL);\n\tDUK_ASSERT(DUK_ACT_GET_FUNC(act_resumer) != NULL);\n\tDUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(act_resumer)));  /* resume caller must be an ecmascript func */\n\n\ttv1 = (duk_tval *) (void *) ((duk_uint8_t *) resumer->valstack + act_resumer->retval_byteoff);  /* return value from Duktape.Thread.resume() */\n\tDUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv_val_unstable);  /* side effects */  /* XXX: avoid side effects */\n\n\tduk__reconfig_valstack_ecma_return(resumer);\n\n\t/* caller must change active thread, and set thr->resumer to NULL */\n}\n#endif  /* DUK_USE_COROUTINE_SUPPORT */\n\nDUK_LOCAL duk_small_uint_t duk__handle_longjmp(duk_hthread *thr, duk_activation *entry_act) {\n\tduk_small_uint_t retval = DUK__LONGJMP_RESTART;\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(entry_act != NULL);\n\n\t/* 'thr' is the current thread, as no-one resumes except us and we\n\t * switch 'thr' in that case.\n\t */\n\tDUK_ASSERT(thr == thr->heap->curr_thread);\n\n\t/*\n\t *  (Re)try handling the longjmp.\n\t *\n\t *  A longjmp handler may convert the longjmp to a different type and\n\t *  \"virtually\" rethrow by goto'ing to 'check_longjmp'.  Before the goto,\n\t *  the following must be updated:\n\t *    - the heap 'lj' state\n\t *    - 'thr' must reflect the \"throwing\" thread\n\t */\n\n check_longjmp:\n\n\tDUK_DD(DUK_DDPRINT(\"handling longjmp: type=%ld, value1=%!T, value2=%!T, iserror=%ld\",\n\t                   (long) thr->heap->lj.type,\n\t                   (duk_tval *) &thr->heap->lj.value1,\n\t                   (duk_tval *) &thr->heap->lj.value2,\n\t                   (long) thr->heap->lj.iserror));\n\n\tswitch (thr->heap->lj.type) {\n\n#if defined(DUK_USE_COROUTINE_SUPPORT)\n\tcase DUK_LJ_TYPE_RESUME: {\n\t\t/*\n\t\t *  Note: lj.value1 is 'value', lj.value2 is 'resumee'.\n\t\t *  This differs from YIELD.\n\t\t */\n\n\t\tduk_tval *tv;\n\t\tduk_tval *tv2;\n\t\tduk_hthread *resumee;\n\n\t\t/* duk_bi_duk_object_yield() and duk_bi_duk_object_resume() ensure all of these are met */\n\n\t\tDUK_ASSERT(thr->state == DUK_HTHREAD_STATE_RUNNING);                                                         /* unchanged by Duktape.Thread.resume() */\n\t\tDUK_ASSERT(thr->callstack_top >= 2);                                                                         /* Ecmascript activation + Duktape.Thread.resume() activation */\n\t\tDUK_ASSERT(thr->callstack_curr != NULL);\n\t\tDUK_ASSERT(thr->callstack_curr->parent != NULL);\n\t\tDUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack_curr) != NULL &&\n\t\t           DUK_HOBJECT_IS_NATFUNC(DUK_ACT_GET_FUNC(thr->callstack_curr)) &&\n\t\t           ((duk_hnatfunc *) DUK_ACT_GET_FUNC(thr->callstack_curr))->func == duk_bi_thread_resume);\n\n\t\ttv = &thr->heap->lj.value2;  /* resumee */\n\t\tDUK_ASSERT(DUK_TVAL_IS_OBJECT(tv));\n\t\tDUK_ASSERT(DUK_TVAL_GET_OBJECT(tv) != NULL);\n\t\tDUK_ASSERT(DUK_HOBJECT_IS_THREAD(DUK_TVAL_GET_OBJECT(tv)));\n\t\tresumee = (duk_hthread *) DUK_TVAL_GET_OBJECT(tv);\n\n\t\tDUK_ASSERT(resumee != NULL);\n\t\tDUK_ASSERT(resumee->resumer == NULL);\n\t\tDUK_ASSERT(resumee->state == DUK_HTHREAD_STATE_INACTIVE ||\n\t\t           resumee->state == DUK_HTHREAD_STATE_YIELDED);                                                     /* checked by Duktape.Thread.resume() */\n\t\tDUK_ASSERT(resumee->state != DUK_HTHREAD_STATE_YIELDED ||\n\t\t           resumee->callstack_top >= 2);                                                                     /* YIELDED: Ecmascript activation + Duktape.Thread.yield() activation */\n\t\tDUK_ASSERT(resumee->state != DUK_HTHREAD_STATE_YIELDED ||\n\t\t           (DUK_ACT_GET_FUNC(resumee->callstack_curr) != NULL &&\n\t\t            DUK_HOBJECT_IS_NATFUNC(DUK_ACT_GET_FUNC(resumee->callstack_curr)) &&\n\t\t            ((duk_hnatfunc *) DUK_ACT_GET_FUNC(resumee->callstack_curr))->func == duk_bi_thread_yield));\n\t\tDUK_ASSERT(resumee->state != DUK_HTHREAD_STATE_INACTIVE ||\n\t\t           resumee->callstack_top == 0);                                                                     /* INACTIVE: no activation, single function value on valstack */\n\n\t\tif (thr->heap->lj.iserror) {\n\t\t\t/*\n\t\t\t *  Throw the error in the resumed thread's context; the\n\t\t\t *  error value is pushed onto the resumee valstack.\n\t\t\t *\n\t\t\t *  Note: the callstack of the target may empty in this case\n\t\t\t *  too (i.e. the target thread has never been resumed).  The\n\t\t\t *  value stack will contain the initial function in that case,\n\t\t\t *  which we simply ignore.\n\t\t\t */\n\n\t\t\tDUK_ASSERT(resumee->resumer == NULL);\n\t\t\tresumee->resumer = thr;\n\t\t\tDUK_HTHREAD_INCREF(thr, thr);\n\t\t\tresumee->state = DUK_HTHREAD_STATE_RUNNING;\n\t\t\tthr->state = DUK_HTHREAD_STATE_RESUMED;\n\t\t\tDUK_HEAP_SWITCH_THREAD(thr->heap, resumee);\n\t\t\tthr = resumee;\n\n\t\t\tthr->heap->lj.type = DUK_LJ_TYPE_THROW;\n\n\t\t\t/* thr->heap->lj.value1 is already the value to throw */\n\t\t\t/* thr->heap->lj.value2 is 'thread', will be wiped out at the end */\n\n\t\t\tDUK_ASSERT(thr->heap->lj.iserror);  /* already set */\n\n\t\t\tDUK_DD(DUK_DDPRINT(\"-> resume with an error, converted to a throw in the resumee, propagate\"));\n\t\t\tgoto check_longjmp;\n\t\t} else if (resumee->state == DUK_HTHREAD_STATE_YIELDED) {\n\t\t\t/* Unwind previous Duktape.Thread.yield() call.  The\n\t\t\t * activation remaining must always be an Ecmascript\n\t\t\t * call now (yield() accepts calls from Ecmascript\n\t\t\t * only).\n\t\t\t */\n\t\t\tduk_activation *act_resumee;\n\n\t\t\tDUK_ASSERT(resumee->callstack_top >= 2);\n\t\t\tact_resumee = resumee->callstack_curr;  /* Duktape.Thread.yield() */\n\t\t\tDUK_ASSERT(act_resumee != NULL);\n\t\t\tact_resumee = act_resumee->parent;      /* Ecmascript call site for yield() */\n\t\t\tDUK_ASSERT(act_resumee != NULL);\n\n\t\t\ttv = (duk_tval *) (void *) ((duk_uint8_t *) resumee->valstack + act_resumee->retval_byteoff);  /* return value from Duktape.Thread.yield() */\n\t\t\tDUK_ASSERT(tv >= resumee->valstack && tv < resumee->valstack_top);\n\t\t\ttv2 = &thr->heap->lj.value1;\n\t\t\tDUK_TVAL_SET_TVAL_UPDREF(thr, tv, tv2);  /* side effects */  /* XXX: avoid side effects */\n\n\t\t\tduk_hthread_activation_unwind_norz(resumee);  /* unwind to 'yield' caller */\n\t\t\t/* no need to unwind catch stack */\n\n\t\t\tduk__reconfig_valstack_ecma_return(resumee);\n\n\t\t\tDUK_ASSERT(resumee->resumer == NULL);\n\t\t\tresumee->resumer = thr;\n\t\t\tDUK_HTHREAD_INCREF(thr, thr);\n\t\t\tresumee->state = DUK_HTHREAD_STATE_RUNNING;\n\t\t\tthr->state = DUK_HTHREAD_STATE_RESUMED;\n\t\t\tDUK_HEAP_SWITCH_THREAD(thr->heap, resumee);\n#if 0\n\t\t\tthr = resumee;  /* not needed, as we exit right away */\n#endif\n\t\t\tDUK_DD(DUK_DDPRINT(\"-> resume with a value, restart execution in resumee\"));\n\t\t\tretval = DUK__LONGJMP_RESTART;\n\t\t\tgoto wipe_and_return;\n\t\t} else {\n\t\t\t/* Initial resume call. */\n\t\t\tduk_small_uint_t call_flags;\n\t\t\tduk_int_t setup_rc;\n\n\t\t\t/* resumee: [... initial_func]  (currently actually: [initial_func]) */\n\n\t\t\tduk_push_undefined(resumee);\n\t\t\ttv = &thr->heap->lj.value1;\n\t\t\tduk_push_tval(resumee, tv);\n\n\t\t\t/* resumee: [... initial_func undefined(= this) resume_value ] */\n\n\t\t\tcall_flags = DUK_CALL_FLAG_ALLOW_ECMATOECMA;  /* not tailcall, ecma-to-ecma (assumed to succeed) */\n\n\t\t\tsetup_rc = duk_handle_call_unprotected_nargs(resumee, 1 /*nargs*/, call_flags);\n\t\t\tif (setup_rc == 0) {\n\t\t\t\t/* This shouldn't happen; Duktape.Thread.resume()\n\t\t\t\t * should make sure of that.  If it does happen\n\t\t\t\t * this internal error will propagate out of the\n\t\t\t\t * executor which can be quite misleading.\n\t\t\t\t */\n\t\t\t\tDUK_ERROR_INTERNAL(thr);\n\t\t\t}\n\n\t\t\tDUK_ASSERT(resumee->resumer == NULL);\n\t\t\tresumee->resumer = thr;\n\t\t\tDUK_HTHREAD_INCREF(thr, thr);\n\t\t\tresumee->state = DUK_HTHREAD_STATE_RUNNING;\n\t\t\tthr->state = DUK_HTHREAD_STATE_RESUMED;\n\t\t\tDUK_HEAP_SWITCH_THREAD(thr->heap, resumee);\n#if 0\n\t\t\tthr = resumee;  /* not needed, as we exit right away */\n#endif\n\t\t\tDUK_DD(DUK_DDPRINT(\"-> resume with a value, restart execution in resumee\"));\n\t\t\tretval = DUK__LONGJMP_RESTART;\n\t\t\tgoto wipe_and_return;\n\t\t}\n\t\tDUK_UNREACHABLE();\n\t\tbreak;  /* never here */\n\t}\n\n\tcase DUK_LJ_TYPE_YIELD: {\n\t\t/*\n\t\t *  Currently only allowed only if yielding thread has only\n\t\t *  Ecmascript activations (except for the Duktape.Thread.yield()\n\t\t *  call at the callstack top) and none of them constructor\n\t\t *  calls.\n\t\t *\n\t\t *  This excludes the 'entry' thread which will always have\n\t\t *  a preventcount > 0.\n\t\t */\n\n\t\tduk_hthread *resumer;\n\n\t\t/* duk_bi_duk_object_yield() and duk_bi_duk_object_resume() ensure all of these are met */\n\n#if 0  /* entry_thread not available for assert */\n\t\tDUK_ASSERT(thr != entry_thread);                                                                             /* Duktape.Thread.yield() should prevent */\n#endif\n\t\tDUK_ASSERT(thr->state == DUK_HTHREAD_STATE_RUNNING);                                                         /* unchanged from Duktape.Thread.yield() */\n\t\tDUK_ASSERT(thr->callstack_top >= 2);                                                                         /* Ecmascript activation + Duktape.Thread.yield() activation */\n\t\tDUK_ASSERT(thr->callstack_curr != NULL);\n\t\tDUK_ASSERT(thr->callstack_curr->parent != NULL);\n\t\tDUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack_curr) != NULL &&\n\t\t           DUK_HOBJECT_IS_NATFUNC(DUK_ACT_GET_FUNC(thr->callstack_curr)) &&\n\t\t           ((duk_hnatfunc *) DUK_ACT_GET_FUNC(thr->callstack_curr))->func == duk_bi_thread_yield);\n\t\tDUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack_curr->parent) != NULL &&\n\t\t           DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(thr->callstack_curr->parent)));                              /* an Ecmascript function */\n\n\t\tresumer = thr->resumer;\n\n\t\tDUK_ASSERT(resumer != NULL);\n\t\tDUK_ASSERT(resumer->state == DUK_HTHREAD_STATE_RESUMED);                                                     /* written by a previous RESUME handling */\n\t\tDUK_ASSERT(resumer->callstack_top >= 2);                                                                     /* Ecmascript activation + Duktape.Thread.resume() activation */\n\t\tDUK_ASSERT(resumer->callstack_curr != NULL);\n\t\tDUK_ASSERT(resumer->callstack_curr->parent != NULL);\n\t\tDUK_ASSERT(DUK_ACT_GET_FUNC(resumer->callstack_curr) != NULL &&\n\t\t           DUK_HOBJECT_IS_NATFUNC(DUK_ACT_GET_FUNC(resumer->callstack_curr)) &&\n\t\t           ((duk_hnatfunc *) DUK_ACT_GET_FUNC(resumer->callstack_curr))->func == duk_bi_thread_resume);\n\t\tDUK_ASSERT(DUK_ACT_GET_FUNC(resumer->callstack_curr->parent) != NULL &&\n\t\t           DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(resumer->callstack_curr->parent)));                            /* an Ecmascript function */\n\n\t\tif (thr->heap->lj.iserror) {\n\t\t\tthr->state = DUK_HTHREAD_STATE_YIELDED;\n\t\t\tthr->resumer = NULL;\n\t\t\tDUK_HTHREAD_DECREF_NORZ(thr, resumer);\n\t\t\tresumer->state = DUK_HTHREAD_STATE_RUNNING;\n\t\t\tDUK_HEAP_SWITCH_THREAD(thr->heap, resumer);\n\t\t\tthr = resumer;\n\n\t\t\tthr->heap->lj.type = DUK_LJ_TYPE_THROW;\n\t\t\t/* lj.value1 is already set */\n\t\t\tDUK_ASSERT(thr->heap->lj.iserror);  /* already set */\n\n\t\t\tDUK_DD(DUK_DDPRINT(\"-> yield an error, converted to a throw in the resumer, propagate\"));\n\t\t\tgoto check_longjmp;\n\t\t} else {\n\t\t\tduk_hthread_activation_unwind_norz(resumer);\n\t\t\tduk__handle_yield(thr, resumer, &thr->heap->lj.value1);\n\n\t\t\tthr->state = DUK_HTHREAD_STATE_YIELDED;\n\t\t\tthr->resumer = NULL;\n\t\t\tDUK_HTHREAD_DECREF_NORZ(thr, resumer);\n\t\t\tresumer->state = DUK_HTHREAD_STATE_RUNNING;\n\t\t\tDUK_HEAP_SWITCH_THREAD(thr->heap, resumer);\n#if 0\n\t\t\tthr = resumer;  /* not needed, as we exit right away */\n#endif\n\n\t\t\tDUK_DD(DUK_DDPRINT(\"-> yield a value, restart execution in resumer\"));\n\t\t\tretval = DUK__LONGJMP_RESTART;\n\t\t\tgoto wipe_and_return;\n\t\t}\n\t\tDUK_UNREACHABLE();\n\t\tbreak;  /* never here */\n\t}\n#endif  /* DUK_USE_COROUTINE_SUPPORT */\n\n\tcase DUK_LJ_TYPE_THROW: {\n\t\t/*\n\t\t *  Three possible outcomes:\n\t\t *    * A try or finally catcher is found => resume there.\n\t\t *      (or)\n\t\t *    * The error propagates to the bytecode executor entry\n\t\t *      level (and we're in the entry thread) => rethrow\n\t\t *      with a new longjmp(), after restoring the previous\n\t\t *      catchpoint.\n\t\t *    * The error is not caught in the current thread, so\n\t\t *      the thread finishes with an error.  This works like\n\t\t *      a yielded error, except that the thread is finished\n\t\t *      and can no longer be resumed.  (There is always a\n\t\t *      resumer in this case.)\n\t\t *\n\t\t *  Note: until we hit the entry level, there can only be\n\t\t *  Ecmascript activations.\n\t\t */\n\n\t\tduk_activation *act;\n\t\tduk_catcher *cat;\n\t\tduk_hthread *resumer;\n\n\t\tfor (;;) {\n\t\t\tact = thr->callstack_curr;\n\t\t\tif (act == NULL) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tfor (;;) {\n\t\t\t\tcat = act->cat;\n\t\t\t\tif (cat == NULL) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tif (DUK_CAT_HAS_CATCH_ENABLED(cat)) {\n\t\t\t\t\tDUK_ASSERT(DUK_CAT_GET_TYPE(cat) == DUK_CAT_TYPE_TCF);\n\n\t\t\t\t\tduk__handle_catch(thr,\n\t\t\t\t\t                  &thr->heap->lj.value1,\n\t\t\t\t\t                  DUK_LJ_TYPE_THROW);\n\n\t\t\t\t\tDUK_DD(DUK_DDPRINT(\"-> throw caught by a 'catch' clause, restart execution\"));\n\t\t\t\t\tretval = DUK__LONGJMP_RESTART;\n\t\t\t\t\tgoto wipe_and_return;\n\t\t\t\t}\n\n\t\t\t\tif (DUK_CAT_HAS_FINALLY_ENABLED(cat)) {\n\t\t\t\t\tDUK_ASSERT(DUK_CAT_GET_TYPE(cat) == DUK_CAT_TYPE_TCF);\n\t\t\t\t\tDUK_ASSERT(!DUK_CAT_HAS_CATCH_ENABLED(cat));\n\n\t\t\t\t\tduk__handle_finally(thr,\n\t\t\t\t\t                    &thr->heap->lj.value1,\n\t\t\t\t\t                    DUK_LJ_TYPE_THROW);\n\n\t\t\t\t\tDUK_DD(DUK_DDPRINT(\"-> throw caught by a 'finally' clause, restart execution\"));\n\t\t\t\t\tretval = DUK__LONGJMP_RESTART;\n\t\t\t\t\tgoto wipe_and_return;\n\t\t\t\t}\n\n\t\t\t\tduk_hthread_catcher_unwind_norz(thr, act);\n\t\t\t}\n\n\t\t\tif (act == entry_act) {\n\t\t\t\t/* Not caught by anything before entry level; rethrow and let the\n\t\t\t\t * final catcher finish unwinding (esp. value stack).\n\t\t\t\t */\n\t\t\t\tDUK_D(DUK_DPRINT(\"-> throw propagated up to entry level, rethrow and exit bytecode executor\"));\n\t\t\t\tretval = DUK__LONGJMP_RETHROW;\n\t\t\t\tgoto just_return;\n\t\t\t}\n\n\t\t\tduk_hthread_activation_unwind_norz(thr);\n\t\t}\n\n\t\tDUK_DD(DUK_DDPRINT(\"-> throw not caught by current thread, yield error to resumer and recheck longjmp\"));\n\n\t\t/* Not caught by current thread, thread terminates (yield error to resumer);\n\t\t * note that this may cause a cascade if the resumer terminates with an uncaught\n\t\t * exception etc (this is OK, but needs careful testing).\n\t\t */\n\n\t\tDUK_ASSERT(thr->resumer != NULL);\n\t\tDUK_ASSERT(thr->resumer->callstack_top >= 2);  /* Ecmascript activation + Duktape.Thread.resume() activation */\n\t\tDUK_ASSERT(thr->resumer->callstack_curr != NULL);\n\t\tDUK_ASSERT(thr->resumer->callstack_curr->parent != NULL);\n\t\tDUK_ASSERT(DUK_ACT_GET_FUNC(thr->resumer->callstack_curr->parent) != NULL &&\n\t\t           DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(thr->resumer->callstack_curr->parent)));  /* an Ecmascript function */\n\n\t\tresumer = thr->resumer;\n\n\t\t/* reset longjmp */\n\n\t\tDUK_ASSERT(thr->heap->lj.type == DUK_LJ_TYPE_THROW);  /* already set */\n\t\t/* lj.value1 already set */\n\n\t\tduk_hthread_terminate(thr);  /* updates thread state, minimizes its allocations */\n\t\tDUK_ASSERT(thr->state == DUK_HTHREAD_STATE_TERMINATED);\n\n\t\tthr->resumer = NULL;\n\t\tDUK_HTHREAD_DECREF_NORZ(thr, resumer);\n\t\tresumer->state = DUK_HTHREAD_STATE_RUNNING;\n\t\tDUK_HEAP_SWITCH_THREAD(thr->heap, resumer);\n\t\tthr = resumer;\n\t\tgoto check_longjmp;\n\t}\n\n\tcase DUK_LJ_TYPE_BREAK:  /* pseudotypes, not used in actual longjmps */\n\tcase DUK_LJ_TYPE_CONTINUE:\n\tcase DUK_LJ_TYPE_RETURN:\n\tcase DUK_LJ_TYPE_NORMAL:\n\tdefault: {\n\t\t/* should never happen, but be robust */\n\t\tDUK_D(DUK_DPRINT(\"caught unknown longjmp type %ld, treat as internal error\", (long) thr->heap->lj.type));\n\t\tgoto convert_to_internal_error;\n\t}\n\n\t}  /* end switch */\n\n\tDUK_UNREACHABLE();\n\n wipe_and_return:\n\t/* this is not strictly necessary, but helps debugging */\n\tthr->heap->lj.type = DUK_LJ_TYPE_UNKNOWN;\n\tthr->heap->lj.iserror = 0;\n\n\tDUK_TVAL_SET_UNDEFINED_UPDREF(thr, &thr->heap->lj.value1);  /* side effects */\n\tDUK_TVAL_SET_UNDEFINED_UPDREF(thr, &thr->heap->lj.value2);  /* side effects */\n\n\tDUK_GC_TORTURE(thr->heap);\n\n just_return:\n\treturn retval;\n\n convert_to_internal_error:\n\t/* This could also be thrown internally (set the error, goto check_longjmp),\n\t * but it's better for internal errors to bubble outwards so that we won't\n\t * infinite loop in this catchpoint.\n\t */\n\tDUK_ERROR_INTERNAL(thr);\n\tDUK_UNREACHABLE();\n\treturn retval;\n}\n\n/* Handle a BREAK/CONTINUE opcode.  Avoid using longjmp() for BREAK/CONTINUE\n * handling because it has a measurable performance impact in ordinary\n * environments and an extreme impact in Emscripten (GH-342).\n */\nDUK_LOCAL DUK__NOINLINE_PERF void duk__handle_break_or_continue(duk_hthread *thr,\n                                                                duk_uint_t label_id,\n                                                                duk_small_uint_t lj_type) {\n\tduk_activation *act;\n\tduk_catcher *cat;\n\n\tDUK_ASSERT(thr != NULL);\n\n\t/* Find a matching label catcher or 'finally' catcher in\n\t * the same function, unwinding catchers as we go.\n\t *\n\t * A label catcher must always exist and will match unless\n\t * a 'finally' captures the break/continue first.  It is the\n\t * compiler's responsibility to ensure that labels are used\n\t * correctly.\n\t */\n\n\tact = thr->callstack_curr;\n\tDUK_ASSERT(act != NULL);\n\n\tfor (;;) {\n\t\tcat = act->cat;\n\t\tif (cat == NULL) {\n\t\t\tbreak;\n\t\t}\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"considering catcher %p: type=%ld label=%ld\",\n\t\t                     (void *) cat,\n\t\t                     (long) DUK_CAT_GET_TYPE(cat),\n\t\t                     (long) DUK_CAT_GET_LABEL(cat)));\n\n\t\t/* XXX: bit mask test; FINALLY <-> TCF, single bit mask would suffice? */\n\n\t\tif (DUK_CAT_GET_TYPE(cat) == DUK_CAT_TYPE_TCF &&\n\t\t    DUK_CAT_HAS_FINALLY_ENABLED(cat)) {\n\t\t\tduk_tval tv_tmp;\n\n\t\t\tDUK_TVAL_SET_U32(&tv_tmp, (duk_uint32_t) label_id);\n\t\t\tduk__handle_finally(thr, &tv_tmp, lj_type);\n\n\t\t\tDUK_DD(DUK_DDPRINT(\"-> break/continue caught by 'finally', restart execution\"));\n\t\t\treturn;\n\t\t}\n\t\tif (DUK_CAT_GET_TYPE(cat) == DUK_CAT_TYPE_LABEL &&\n\t\t    (duk_uint_t) DUK_CAT_GET_LABEL(cat) == label_id) {\n\t\t\tduk__handle_label(thr, lj_type);\n\n\t\t\tDUK_DD(DUK_DDPRINT(\"-> break/continue caught by a label catcher (in the same function), restart execution\"));\n\t\t\treturn;\n\t\t}\n\n\t\tduk_hthread_catcher_unwind_norz(thr, act);\n\t}\n\n\t/* Should never happen, but be robust. */\n\tDUK_D(DUK_DPRINT(\"-> break/continue not caught by anything in the current function (should never happen), throw internal error\"));\n\tDUK_ERROR_INTERNAL(thr);\n\treturn;\n}\n\n/* Handle a RETURN opcode.  Avoid using longjmp() for return handling because\n * it has a measurable performance impact in ordinary environments and an extreme\n * impact in Emscripten (GH-342).  Return value is on value stack top.\n */\nDUK_LOCAL duk_small_uint_t duk__handle_return(duk_hthread *thr, duk_activation *entry_act) {\n\tduk_tval *tv1;\n\tduk_tval *tv2;\n#if defined(DUK_USE_COROUTINE_SUPPORT)\n\tduk_hthread *resumer;\n#endif\n\tduk_activation *act;\n\tduk_catcher *cat;\n\n\t/* We can directly access value stack here. */\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(entry_act != NULL);\n\tDUK_ASSERT(thr->valstack_top - 1 >= thr->valstack_bottom);\n\ttv1 = thr->valstack_top - 1;\n\tDUK_TVAL_CHKFAST_INPLACE_FAST(tv1);  /* fastint downgrade check for return values */\n\n\t/*\n\t *  Four possible outcomes:\n\t *\n\t *    1. A 'finally' in the same function catches the 'return'.\n\t *       It may continue to propagate when 'finally' is finished,\n\t *       or it may be neutralized by 'finally' (both handled by\n\t *       ENDFIN).\n\t *\n\t *    2. The return happens at the entry level of the bytecode\n\t *       executor, so return from the executor (in C stack).\n\t *\n\t *    3. There is a calling (Ecmascript) activation in the call\n\t *       stack => return to it, in the same executor instance.\n\t *\n\t *    4. There is no calling activation, and the thread is\n\t *       terminated.  There is always a resumer in this case,\n\t *       which gets the return value similarly to a 'yield'\n\t *       (except that the current thread can no longer be\n\t *       resumed).\n\t */\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(thr->callstack_top >= 1);\n\n\tact = thr->callstack_curr;\n\tDUK_ASSERT(act != NULL);\n\n\tfor (;;) {\n\t\tcat = act->cat;\n\t\tif (cat == NULL) {\n\t\t\tbreak;\n\t\t}\n\n\t\tif (DUK_CAT_GET_TYPE(cat) == DUK_CAT_TYPE_TCF &&\n\t\t    DUK_CAT_HAS_FINALLY_ENABLED(cat)) {\n\t\t\tDUK_ASSERT(thr->valstack_top - 1 >= thr->valstack_bottom);\n\t\t\tduk__handle_finally(thr, thr->valstack_top - 1, DUK_LJ_TYPE_RETURN);\n\n\t\t\tDUK_DD(DUK_DDPRINT(\"-> return caught by 'finally', restart execution\"));\n\t\t\treturn DUK__RETHAND_RESTART;\n\t\t}\n\n\t\tduk_hthread_catcher_unwind_norz(thr, act);\n\t}\n\n\tif (act == entry_act) {\n\t\t/* Return to the bytecode executor caller who will unwind stacks\n\t\t * and handle constructor post-processing.\n\t\t * Return value is already on the stack top: [ ... retval ].\n\t\t */\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"-> return propagated up to entry level, exit bytecode executor\"));\n\t\treturn DUK__RETHAND_FINISHED;\n\t}\n\n\tif (thr->callstack_top >= 2) {\n\t\t/* There is a caller; it MUST be an Ecmascript caller (otherwise it would\n\t\t * match entry_act check).\n\t\t */\n\t\tDUK_DDD(DUK_DDDPRINT(\"return to Ecmascript caller, retval_byteoff=%ld, lj_value1=%!T\",\n\t\t                     (long) (thr->callstack_curr->parent->retval_byteoff),\n\t\t                     (duk_tval *) &thr->heap->lj.value1));\n\n\t\tDUK_ASSERT(thr->callstack_curr != NULL);\n\t\tDUK_ASSERT(thr->callstack_curr->parent != NULL);\n\t\tDUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(thr->callstack_curr->parent)));   /* must be ecmascript */\n\n#if defined(DUK_USE_ES6_PROXY)\n\t\tif (thr->callstack_curr->flags & (DUK_ACT_FLAG_CONSTRUCT | DUK_ACT_FLAG_CONSTRUCT_PROXY)) {\n\t\t\tduk_call_construct_postprocess(thr, thr->callstack_curr->flags & DUK_ACT_FLAG_CONSTRUCT_PROXY);  /* side effects */\n\t\t}\n#else\n\t\tif (thr->callstack_curr->flags & DUK_ACT_FLAG_CONSTRUCT) {\n\t\t\tduk_call_construct_postprocess(thr, 0);  /* side effects */\n\t\t}\n#endif\n\n\t\ttv1 = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + thr->callstack_curr->parent->retval_byteoff);\n\t\tDUK_ASSERT(thr->valstack_top - 1 >= thr->valstack_bottom);\n\t\ttv2 = thr->valstack_top - 1;\n\t\tDUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv2);  /* side effects */\n\n\t\t/* Catch stack unwind happens inline in callstack unwind. */\n\t\tduk_hthread_activation_unwind_norz(thr);\n\n\t\tduk__reconfig_valstack_ecma_return(thr);\n\n\t\tDUK_DD(DUK_DDPRINT(\"-> return not intercepted, restart execution in caller\"));\n\t\treturn DUK__RETHAND_RESTART;\n\t}\n\n#if defined(DUK_USE_COROUTINE_SUPPORT)\n\tDUK_DD(DUK_DDPRINT(\"no calling activation, thread finishes (similar to yield)\"));\n\n\tDUK_ASSERT(thr->resumer != NULL);\n\tDUK_ASSERT(thr->resumer->callstack_top >= 2);  /* Ecmascript activation + Duktape.Thread.resume() activation */\n\tDUK_ASSERT(thr->resumer->callstack_curr != NULL);\n\tDUK_ASSERT(thr->resumer->callstack_curr->parent != NULL);\n\tDUK_ASSERT(DUK_ACT_GET_FUNC(thr->resumer->callstack_curr) != NULL &&\n\t\t\tDUK_HOBJECT_IS_NATFUNC(DUK_ACT_GET_FUNC(thr->resumer->callstack_curr)) &&\n\t\t\t((duk_hnatfunc *) DUK_ACT_GET_FUNC(thr->resumer->callstack_curr))->func == duk_bi_thread_resume);  /* Duktape.Thread.resume() */\n\tDUK_ASSERT(DUK_ACT_GET_FUNC(thr->resumer->callstack_curr->parent) != NULL &&\n\t\t\tDUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(thr->resumer->callstack_curr->parent)));  /* an Ecmascript function */\n\tDUK_ASSERT(thr->state == DUK_HTHREAD_STATE_RUNNING);\n\tDUK_ASSERT(thr->resumer->state == DUK_HTHREAD_STATE_RESUMED);\n\n\tresumer = thr->resumer;\n\n\t/* Share yield longjmp handler. */\n\tDUK_ASSERT(thr->valstack_top - 1 >= thr->valstack_bottom);\n\tduk_hthread_activation_unwind_norz(resumer);\n\tduk__handle_yield(thr, resumer, thr->valstack_top - 1);\n\n\tduk_hthread_terminate(thr);  /* updates thread state, minimizes its allocations */\n\tDUK_ASSERT(thr->state == DUK_HTHREAD_STATE_TERMINATED);\n\n\tthr->resumer = NULL;\n\tDUK_HTHREAD_DECREF(thr, resumer);\n\tresumer->state = DUK_HTHREAD_STATE_RUNNING;\n\tDUK_HEAP_SWITCH_THREAD(thr->heap, resumer);\n#if 0\n\tthr = resumer;  /* not needed */\n#endif\n\n\tDUK_DD(DUK_DDPRINT(\"-> return not caught, thread terminated; handle like yield, restart execution in resumer\"));\n\treturn DUK__RETHAND_RESTART;\n#else\n\t/* Without coroutine support this case should never happen. */\n\tDUK_ERROR_INTERNAL(thr);\n\treturn DUK__RETHAND_FINISHED;  /* not executed */\n#endif\n}\n\n/*\n *  Executor interrupt handling\n *\n *  The handler is called whenever the interrupt countdown reaches zero\n *  (or below).  The handler must perform whatever checks are activated,\n *  e.g. check for cumulative step count to impose an execution step\n *  limit or check for breakpoints or other debugger interaction.\n *\n *  When the actions are done, the handler must reinit the interrupt\n *  init and counter values.  The 'init' value must indicate how many\n *  bytecode instructions are executed before the next interrupt.  The\n *  counter must interface with the bytecode executor loop.  Concretely,\n *  the new init value is normally one higher than the new counter value.\n *  For instance, to execute exactly one bytecode instruction the init\n *  value is set to 1 and the counter to 0.  If an error is thrown by the\n *  interrupt handler, the counters are set to the same value (e.g. both\n *  to 0 to cause an interrupt when the next bytecode instruction is about\n *  to be executed after error handling).\n *\n *  Maintaining the init/counter value properly is important for accurate\n *  behavior.  For instance, executor step limit needs a cumulative step\n *  count which is simply computed as a sum of 'init' values.  This must\n *  work accurately even when single stepping.\n */\n\n#if defined(DUK_USE_INTERRUPT_COUNTER)\n\n#define DUK__INT_NOACTION    0    /* no specific action, resume normal execution */\n#define DUK__INT_RESTART     1    /* must \"goto restart_execution\", e.g. breakpoints changed */\n\n#if defined(DUK_USE_DEBUGGER_SUPPORT)\nDUK_LOCAL void duk__interrupt_handle_debugger(duk_hthread *thr, duk_bool_t *out_immediate, duk_small_uint_t *out_interrupt_retval) {\n\tduk_activation *act;\n\tduk_breakpoint *bp;\n\tduk_breakpoint **bp_active;\n\tduk_uint_fast32_t line = 0;\n\tduk_bool_t process_messages;\n\tduk_bool_t processed_messages = 0;\n\n\tDUK_ASSERT(thr->heap->dbg_processing == 0);  /* don't re-enter e.g. during Eval */\n\n\tact = thr->callstack_curr;\n\tDUK_ASSERT(act != NULL);\n\n\t/* It might seem that replacing 'thr->heap' with just 'heap' below\n\t * might be a good idea, but it increases code size slightly\n\t * (probably due to unnecessary spilling) at least on x64.\n\t */\n\n\t/*\n\t *  Single opcode step check\n\t */\n\n\tif (thr->heap->dbg_pause_flags & DUK_PAUSE_FLAG_ONE_OPCODE_ACTIVE) {\n\t\tDUK_D(DUK_DPRINT(\"PAUSE TRIGGERED by one opcode step\"));\n\t\tduk_debug_set_paused(thr->heap);\n\t}\n\n\t/*\n\t *  Breakpoint and step state checks\n\t */\n\n\tif (act->flags & DUK_ACT_FLAG_BREAKPOINT_ACTIVE ||\n\t    (thr->heap->dbg_pause_act == thr->callstack_curr)) {\n\t\tline = duk_debug_curr_line(thr);\n\n\t\tif (act->prev_line != line) {\n\t\t\t/* Stepped?  Step out is handled by callstack unwind. */\n\t\t\tif ((thr->heap->dbg_pause_flags & DUK_PAUSE_FLAG_LINE_CHANGE) &&\n\t\t\t    (thr->heap->dbg_pause_act == thr->callstack_curr) &&\n\t\t\t    (line != thr->heap->dbg_pause_startline)) {\n\t\t\t\tDUK_D(DUK_DPRINT(\"PAUSE TRIGGERED by line change, at line %ld\",\n\t\t\t\t                 (long) line));\n\t\t\t\tduk_debug_set_paused(thr->heap);\n\t\t\t}\n\n\t\t\t/* Check for breakpoints only on line transition.\n\t\t\t * Breakpoint is triggered when we enter the target\n\t\t\t * line from a different line, and the previous line\n\t\t\t * was within the same function.\n\t\t\t *\n\t\t\t * This condition is tricky: the condition used to be\n\t\t\t * that transition to -or across- the breakpoint line\n\t\t\t * triggered the breakpoint.  This seems intuitively\n\t\t\t * better because it handles breakpoints on lines with\n\t\t\t * no emitted opcodes; but this leads to the issue\n\t\t\t * described in: https://github.com/svaarala/duktape/issues/263.\n\t\t\t */\n\t\t\tbp_active = thr->heap->dbg_breakpoints_active;\n\t\t\tfor (;;) {\n\t\t\t\tbp = *bp_active++;\n\t\t\t\tif (bp == NULL) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tDUK_ASSERT(bp->filename != NULL);\n\t\t\t\tif (act->prev_line != bp->line && line == bp->line) {\n\t\t\t\t\tDUK_D(DUK_DPRINT(\"PAUSE TRIGGERED by breakpoint at %!O:%ld\",\n\t\t\t\t\t                 (duk_heaphdr *) bp->filename, (long) bp->line));\n\t\t\t\t\tduk_debug_set_paused(thr->heap);\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\t;\n\t\t}\n\n\t\tact->prev_line = (duk_uint32_t) line;\n\t}\n\n\t/*\n\t *  Rate limit check for sending status update or peeking into\n\t *  the debug transport.  Both can be expensive operations that\n\t *  we don't want to do on every opcode.\n\t *\n\t *  Making sure the interval remains reasonable on a wide variety\n\t *  of targets and bytecode is difficult without a timestamp, so\n\t *  we use a Date-provided timestamp for the rate limit check.\n\t *  But since it's also expensive to get a timestamp, a bytecode\n\t *  counter is used to rate limit getting timestamps.\n\t */\n\n\tprocess_messages = 0;\n\tif (thr->heap->dbg_state_dirty || DUK_HEAP_HAS_DEBUGGER_PAUSED(thr->heap) || thr->heap->dbg_detaching) {\n\t\t/* Enter message processing loop for sending Status notifys and\n\t\t * to finish a pending detach.\n\t\t */\n\t\tprocess_messages = 1;\n\t}\n\n\t/* XXX: remove heap->dbg_exec_counter, use heap->inst_count_interrupt instead? */\n\tDUK_ASSERT(thr->interrupt_init >= 0);\n\tthr->heap->dbg_exec_counter += (duk_uint_t) thr->interrupt_init;\n\tif (thr->heap->dbg_exec_counter - thr->heap->dbg_last_counter >= DUK_HEAP_DBG_RATELIMIT_OPCODES) {\n\t\t/* Overflow of the execution counter is fine and doesn't break\n\t\t * anything here.\n\t\t */\n\n\t\tduk_double_t now, diff_last;\n\n\t\tthr->heap->dbg_last_counter = thr->heap->dbg_exec_counter;\n\t\tnow = duk_time_get_monotonic_time(thr);\n\n\t\tdiff_last = now - thr->heap->dbg_last_time;\n\t\tif (diff_last < 0.0 || diff_last >= (duk_double_t) DUK_HEAP_DBG_RATELIMIT_MILLISECS) {\n\t\t\t/* Monotonic time should not experience time jumps,\n\t\t\t * but the provider may be missing and we're actually\n\t\t\t * using Ecmascript time.  So, tolerate negative values\n\t\t\t * so that a time jump works reasonably.\n\t\t\t *\n\t\t\t * Same interval is now used for status sending and\n\t\t\t * peeking.\n\t\t\t */\n\n\t\t\tthr->heap->dbg_last_time = now;\n\t\t\tthr->heap->dbg_state_dirty = 1;\n\t\t\tprocess_messages = 1;\n\t\t}\n\t}\n\n\t/*\n\t *  Process messages and send status if necessary.\n\t *\n\t *  If we're paused, we'll block for new messages.  If we're not\n\t *  paused, we'll process anything we can peek but won't block\n\t *  for more.  Detach (and re-attach) handling is all localized\n\t *  to duk_debug_process_messages() too.\n\t *\n\t *  Debugger writes outside the message loop may cause debugger\n\t *  detach1 phase to run, after which dbg_read_cb == NULL and\n\t *  dbg_detaching != 0.  The message loop will finish the detach\n\t *  by running detach2 phase, so enter the message loop also when\n\t *  detaching.\n\t */\n\n\tif (process_messages) {\n\t\tDUK_ASSERT(thr->heap->dbg_processing == 0);\n\t\tprocessed_messages = duk_debug_process_messages(thr, 0 /*no_block*/);\n\t\tDUK_ASSERT(thr->heap->dbg_processing == 0);\n\t}\n\n\t/* Continue checked execution if there are breakpoints or we're stepping.\n\t * Also use checked execution if paused flag is active - it shouldn't be\n\t * because the debug message loop shouldn't terminate if it was.  Step out\n\t * is handled by callstack unwind and doesn't need checked execution.\n\t * Note that debugger may have detached due to error or explicit request\n\t * above, so we must recheck attach status.\n\t */\n\n\tif (duk_debug_is_attached(thr->heap)) {\n\t\tDUK_ASSERT(act == thr->callstack_curr);\n\t\tDUK_ASSERT(act != NULL);\n\t\tif (act->flags & DUK_ACT_FLAG_BREAKPOINT_ACTIVE ||\n\t\t    (thr->heap->dbg_pause_flags & DUK_PAUSE_FLAG_ONE_OPCODE) ||\n\t\t    ((thr->heap->dbg_pause_flags & DUK_PAUSE_FLAG_LINE_CHANGE) &&\n\t\t     thr->heap->dbg_pause_act == thr->callstack_curr) ||\n\t\t     DUK_HEAP_HAS_DEBUGGER_PAUSED(thr->heap)) {\n\t\t\t*out_immediate = 1;\n\t\t}\n\n\t\t/* If we processed any debug messages breakpoints may have\n\t\t * changed; restart execution to re-check active breakpoints.\n\t\t */\n\t\tif (processed_messages) {\n\t\t\tDUK_D(DUK_DPRINT(\"processed debug messages, restart execution to recheck possibly changed breakpoints\"));\n\t\t\t*out_interrupt_retval = DUK__INT_RESTART;\n\t\t} else {\n\t\t\tif (thr->heap->dbg_pause_flags & DUK_PAUSE_FLAG_ONE_OPCODE) {\n\t\t\t\t/* Set 'pause after one opcode' active only when we're\n\t\t\t\t * actually just about to execute code.\n\t\t\t\t */\n\t\t\t\tthr->heap->dbg_pause_flags |= DUK_PAUSE_FLAG_ONE_OPCODE_ACTIVE;\n\t\t\t}\n\t\t}\n\t} else {\n\t\tDUK_D(DUK_DPRINT(\"debugger became detached, resume normal execution\"));\n\t}\n}\n#endif  /* DUK_USE_DEBUGGER_SUPPORT */\n\nDUK_LOCAL DUK__NOINLINE_PERF DUK_COLD duk_small_uint_t duk__executor_interrupt(duk_hthread *thr) {\n\tduk_int_t ctr;\n\tduk_activation *act;\n\tduk_hcompfunc *fun;\n\tduk_bool_t immediate = 0;\n\tduk_small_uint_t retval;\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(thr->heap != NULL);\n\tDUK_ASSERT(thr->callstack_top > 0);\n\n#if defined(DUK_USE_DEBUG)\n\tthr->heap->inst_count_interrupt += thr->interrupt_init;\n\tDUK_DD(DUK_DDPRINT(\"execution interrupt, counter=%ld, init=%ld, \"\n\t                   \"instruction counts: executor=%ld, interrupt=%ld\",\n\t                   (long) thr->interrupt_counter, (long) thr->interrupt_init,\n\t                   (long) thr->heap->inst_count_exec, (long) thr->heap->inst_count_interrupt));\n#endif\n\n\tretval = DUK__INT_NOACTION;\n\tctr = DUK_HTHREAD_INTCTR_DEFAULT;\n\n\t/*\n\t *  Avoid nested calls.  Concretely this happens during debugging, e.g.\n\t *  when we eval() an expression.\n\t *\n\t *  Also don't interrupt if we're currently doing debug processing\n\t *  (which can be initiated outside the bytecode executor) as this\n\t *  may cause the debugger to be called recursively.  Check required\n\t *  for correct operation of throw intercept and other \"exotic\" halting\n\t * scenarios.\n\t */\n\n#if defined(DUK_USE_DEBUGGER_SUPPORT)\n\tif (DUK_HEAP_HAS_INTERRUPT_RUNNING(thr->heap) || thr->heap->dbg_processing) {\n#else\n\tif (DUK_HEAP_HAS_INTERRUPT_RUNNING(thr->heap)) {\n#endif\n\t\tDUK_DD(DUK_DDPRINT(\"nested executor interrupt, ignoring\"));\n\n\t\t/* Set a high interrupt counter; the original executor\n\t\t * interrupt invocation will rewrite before exiting.\n\t\t */\n\t\tthr->interrupt_init = ctr;\n\t\tthr->interrupt_counter = ctr - 1;\n\t\treturn DUK__INT_NOACTION;\n\t}\n\tDUK_HEAP_SET_INTERRUPT_RUNNING(thr->heap);\n\n\tact = thr->callstack_curr;\n\tDUK_ASSERT(act != NULL);\n\n\tfun = (duk_hcompfunc *) DUK_ACT_GET_FUNC(act);\n\tDUK_ASSERT(DUK_HOBJECT_HAS_COMPFUNC((duk_hobject *) fun));\n\n\tDUK_UNREF(fun);\n\n#if defined(DUK_USE_EXEC_TIMEOUT_CHECK)\n\t/*\n\t *  Execution timeout check\n\t */\n\n\tif (DUK_USE_EXEC_TIMEOUT_CHECK(thr->heap->heap_udata)) {\n\t\t/* Keep throwing an error whenever we get here.  The unusual values\n\t\t * are set this way because no instruction is ever executed, we just\n\t\t * throw an error until all try/catch/finally and other catchpoints\n\t\t * have been exhausted.  Duktape/C code gets control at each protected\n\t\t * call but whenever it enters back into Duktape the RangeError gets\n\t\t * raised.  User exec timeout check must consistently indicate a timeout\n\t\t * until we've fully bubbled out of Duktape.\n\t\t */\n\t\tDUK_D(DUK_DPRINT(\"execution timeout, throwing a RangeError\"));\n\t\tthr->interrupt_init = 0;\n\t\tthr->interrupt_counter = 0;\n\t\tDUK_HEAP_CLEAR_INTERRUPT_RUNNING(thr->heap);\n\t\tDUK_ERROR_RANGE(thr, \"execution timeout\");\n\t}\n#endif  /* DUK_USE_EXEC_TIMEOUT_CHECK */\n\n#if defined(DUK_USE_DEBUGGER_SUPPORT)\n\tif (!thr->heap->dbg_processing &&\n\t    (thr->heap->dbg_read_cb != NULL || thr->heap->dbg_detaching)) {\n\t\t/* Avoid recursive re-entry; enter when we're attached or\n\t\t * detaching (to finish off the pending detach).\n\t\t */\n\t\tduk__interrupt_handle_debugger(thr, &immediate, &retval);\n\t\tDUK_ASSERT(act == thr->callstack_curr);\n\t}\n#endif  /* DUK_USE_DEBUGGER_SUPPORT */\n\n\t/*\n\t *  Update the interrupt counter\n\t */\n\n\tif (immediate) {\n\t\t/* Cause an interrupt after executing one instruction. */\n\t\tctr = 1;\n\t}\n\n\t/* The counter value is one less than the init value: init value should\n\t * indicate how many instructions are executed before interrupt.  To\n\t * execute 1 instruction (after interrupt handler return), counter must\n\t * be 0.\n\t */\n\tDUK_ASSERT(ctr >= 1);\n\tthr->interrupt_init = ctr;\n\tthr->interrupt_counter = ctr - 1;\n\tDUK_HEAP_CLEAR_INTERRUPT_RUNNING(thr->heap);\n\n\treturn retval;\n}\n#endif  /* DUK_USE_INTERRUPT_COUNTER */\n\n/*\n *  Debugger handling for executor restart\n *\n *  Check for breakpoints, stepping, etc, and figure out if we should execute\n *  in checked or normal mode.  Note that we can't do this when an activation\n *  is created, because breakpoint status (and stepping status) may change\n *  later, so we must recheck every time we're executing an activation.\n *  This primitive should be side effect free to avoid changes during check.\n */\n\n#if defined(DUK_USE_DEBUGGER_SUPPORT)\nDUK_LOCAL void duk__executor_recheck_debugger(duk_hthread *thr, duk_activation *act, duk_hcompfunc *fun) {\n\tduk_heap *heap;\n\tduk_tval *tv_tmp;\n\tduk_hstring *filename;\n\tduk_small_uint_t bp_idx;\n\tduk_breakpoint **bp_active;\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(act != NULL);\n\tDUK_ASSERT(fun != NULL);\n\n\theap = thr->heap;\n\tbp_active = heap->dbg_breakpoints_active;\n\tact->flags &= ~DUK_ACT_FLAG_BREAKPOINT_ACTIVE;\n\n\ttv_tmp = duk_hobject_find_existing_entry_tval_ptr(thr->heap, (duk_hobject *) fun, DUK_HTHREAD_STRING_FILE_NAME(thr));\n\tif (tv_tmp && DUK_TVAL_IS_STRING(tv_tmp)) {\n\t\tfilename = DUK_TVAL_GET_STRING(tv_tmp);\n\n\t\t/* Figure out all active breakpoints.  A breakpoint is\n\t\t * considered active if the current function's fileName\n\t\t * matches the breakpoint's fileName, AND there is no\n\t\t * inner function that has matching line numbers\n\t\t * (otherwise a breakpoint would be triggered both\n\t\t * inside and outside of the inner function which would\n\t\t * be confusing).  Example:\n\t\t *\n\t\t *     function foo() {\n\t\t *         print('foo');\n\t\t *         function bar() {    <-.  breakpoints in these\n\t\t *             print('bar');     |  lines should not affect\n\t\t *         }                   <-'  foo() execution\n\t\t *         bar();\n\t\t *     }\n\t\t *\n\t\t * We need a few things that are only available when\n\t\t * debugger support is enabled: (1) a line range for\n\t\t * each function, and (2) access to the function\n\t\t * template to access the inner functions (and their\n\t\t * line ranges).\n\t\t *\n\t\t * It's important to have a narrow match for active\n\t\t * breakpoints so that we don't enter checked execution\n\t\t * when that's not necessary.  For instance, if we're\n\t\t * running inside a certain function and there's\n\t\t * breakpoint outside in (after the call site), we\n\t\t * don't want to slow down execution of the function.\n\t\t */\n\n\t\tfor (bp_idx = 0; bp_idx < heap->dbg_breakpoint_count; bp_idx++) {\n\t\t\tduk_breakpoint *bp = heap->dbg_breakpoints + bp_idx;\n\t\t\tduk_hobject **funcs, **funcs_end;\n\t\t\tduk_hcompfunc *inner_fun;\n\t\t\tduk_bool_t bp_match;\n\n\t\t\tif (bp->filename == filename &&\n\t\t\t    bp->line >= fun->start_line && bp->line <= fun->end_line) {\n\t\t\t\tbp_match = 1;\n\t\t\t\tDUK_DD(DUK_DDPRINT(\"breakpoint filename and line match: \"\n\t\t\t\t                   \"%s:%ld vs. %s (line %ld vs. %ld-%ld)\",\n\t\t\t\t                   DUK_HSTRING_GET_DATA(bp->filename),\n\t\t\t\t                   (long) bp->line,\n\t\t\t\t                   DUK_HSTRING_GET_DATA(filename),\n\t\t\t\t                   (long) bp->line,\n\t\t\t\t                   (long) fun->start_line,\n\t\t\t\t                   (long) fun->end_line));\n\n\t\t\t\tfuncs = DUK_HCOMPFUNC_GET_FUNCS_BASE(thr->heap, fun);\n\t\t\t\tfuncs_end = DUK_HCOMPFUNC_GET_FUNCS_END(thr->heap, fun);\n\t\t\t\twhile (funcs != funcs_end) {\n\t\t\t\t\tinner_fun = (duk_hcompfunc *) *funcs;\n\t\t\t\t\tDUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC((duk_hobject *) inner_fun));\n\t\t\t\t\tif (bp->line >= inner_fun->start_line && bp->line <= inner_fun->end_line) {\n\t\t\t\t\t\tDUK_DD(DUK_DDPRINT(\"inner function masks ('captures') breakpoint\"));\n\t\t\t\t\t\tbp_match = 0;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tfuncs++;\n\t\t\t\t}\n\n\t\t\t\tif (bp_match) {\n\t\t\t\t\t/* No need to check for size of bp_active list,\n\t\t\t\t\t * it's always larger than maximum number of\n\t\t\t\t\t * breakpoints.\n\t\t\t\t\t */\n\t\t\t\t\tact->flags |= DUK_ACT_FLAG_BREAKPOINT_ACTIVE;\n\t\t\t\t\t*bp_active = heap->dbg_breakpoints + bp_idx;\n\t\t\t\t\tbp_active++;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t*bp_active = NULL;  /* terminate */\n\n\tDUK_DD(DUK_DDPRINT(\"ACTIVE BREAKPOINTS: %ld\", (long) (bp_active - thr->heap->dbg_breakpoints_active)));\n\n\t/* Force pause if we were doing \"step into\" in another activation. */\n\tif ((thr->heap->dbg_pause_flags & DUK_PAUSE_FLAG_FUNC_ENTRY) &&\n\t    thr->heap->dbg_pause_act != thr->callstack_curr) {\n\t\tDUK_D(DUK_DPRINT(\"PAUSE TRIGGERED by function entry\"));\n\t\tduk_debug_set_paused(thr->heap);\n\t}\n\n\t/* Force interrupt right away if we're paused or in \"checked mode\".\n\t * Step out is handled by callstack unwind.\n\t */\n\tif ((act->flags & DUK_ACT_FLAG_BREAKPOINT_ACTIVE) ||\n\t    DUK_HEAP_HAS_DEBUGGER_PAUSED(thr->heap) ||\n\t    ((thr->heap->dbg_pause_flags & DUK_PAUSE_FLAG_LINE_CHANGE) &&\n\t     thr->heap->dbg_pause_act == thr->callstack_curr)) {\n\t\t/* We'll need to interrupt early so recompute the init\n\t\t * counter to reflect the number of bytecode instructions\n\t\t * executed so that step counts for e.g. debugger rate\n\t\t * limiting are accurate.\n\t\t */\n\t\tDUK_ASSERT(thr->interrupt_counter <= thr->interrupt_init);\n\t\tthr->interrupt_init = thr->interrupt_init - thr->interrupt_counter;\n\t\tthr->interrupt_counter = 0;\n\t}\n}\n#endif  /* DUK_USE_DEBUGGER_SUPPORT */\n\n/*\n *  Opcode handlers for opcodes with a lot of code and which are relatively\n *  rare; NOINLINE to reduce amount of code in main bytecode dispatcher.\n */\n\nDUK_LOCAL DUK__NOINLINE_PERF void duk__handle_op_initset_initget(duk_hthread *thr, duk_uint_fast32_t ins) {\n\tduk_bool_t is_set = (DUK_DEC_OP(ins) == DUK_OP_INITSET);\n\tduk_uint_fast_t idx;\n\tduk_uint_t defprop_flags;\n\n\t/* A -> object register (acts as a source)\n\t * BC -> BC+0 contains key, BC+1 closure (value)\n\t */\n\n\t/* INITSET/INITGET are only used to initialize object literal keys.\n\t * There may be a previous propery in ES2015 because duplicate property\n\t * names are allowed.\n\t */\n\n\t/* This could be made more optimal by accessing internals directly. */\n\n\tidx = (duk_uint_fast_t) DUK_DEC_BC(ins);\n\tduk_dup(thr, (duk_idx_t) (idx + 0));  /* key */\n\tduk_dup(thr, (duk_idx_t) (idx + 1));  /* getter/setter */\n\tif (is_set) {\n\t        defprop_flags = DUK_DEFPROP_HAVE_SETTER |\n\t                        DUK_DEFPROP_FORCE |\n\t                        DUK_DEFPROP_SET_ENUMERABLE |\n\t                        DUK_DEFPROP_SET_CONFIGURABLE;\n\t} else {\n\t        defprop_flags = DUK_DEFPROP_HAVE_GETTER |\n\t                        DUK_DEFPROP_FORCE |\n\t                        DUK_DEFPROP_SET_ENUMERABLE |\n\t                        DUK_DEFPROP_SET_CONFIGURABLE;\n\t}\n\tduk_def_prop(thr, (duk_idx_t) DUK_DEC_A(ins), defprop_flags);\n}\n\nDUK_LOCAL DUK__NOINLINE_PERF void duk__handle_op_trycatch(duk_hthread *thr, duk_uint_fast32_t ins, duk_instr_t *curr_pc) {\n\tduk_activation *act;\n\tduk_catcher *cat;\n\tduk_tval *tv1;\n\tduk_small_uint_fast_t a;\n\tduk_small_uint_fast_t bc;\n\n\t/* A -> flags\n\t * BC -> reg_catch; base register for two registers used both during\n\t *       trycatch setup and when catch is triggered\n\t *\n\t *      If DUK_BC_TRYCATCH_FLAG_CATCH_BINDING set:\n\t *          reg_catch + 0: catch binding variable name (string).\n\t *          Automatic declarative environment is established for\n\t *          the duration of the 'catch' clause.\n\t *\n\t *      If DUK_BC_TRYCATCH_FLAG_WITH_BINDING set:\n\t *          reg_catch + 0: with 'target value', which is coerced to\n\t *          an object and then used as a bindind object for an\n\t *          environment record.  The binding is initialized here, for\n\t *          the 'try' clause.\n\t *\n\t * Note that a TRYCATCH generated for a 'with' statement has no\n\t * catch or finally parts.\n\t */\n\n\t/* XXX: TRYCATCH handling should be reworked to avoid creating\n\t * an explicit scope unless it is actually needed (e.g. function\n\t * instances or eval is executed inside the catch block).  This\n\t * rework is not trivial because the compiler doesn't have an\n\t * intermediate representation.  When the rework is done, the\n\t * opcode format can also be made more straightforward.\n\t */\n\n\t/* XXX: side effect handling is quite awkward here */\n\n\tDUK_DDD(DUK_DDDPRINT(\"TRYCATCH: reg_catch=%ld, have_catch=%ld, \"\n\t                     \"have_finally=%ld, catch_binding=%ld, with_binding=%ld (flags=0x%02lx)\",\n\t                     (long) DUK_DEC_BC(ins),\n\t                     (long) (DUK_DEC_A(ins) & DUK_BC_TRYCATCH_FLAG_HAVE_CATCH ? 1 : 0),\n\t                     (long) (DUK_DEC_A(ins) & DUK_BC_TRYCATCH_FLAG_HAVE_FINALLY ? 1 : 0),\n\t                     (long) (DUK_DEC_A(ins) & DUK_BC_TRYCATCH_FLAG_CATCH_BINDING ? 1 : 0),\n\t                     (long) (DUK_DEC_A(ins) & DUK_BC_TRYCATCH_FLAG_WITH_BINDING ? 1 : 0),\n\t                     (unsigned long) DUK_DEC_A(ins)));\n\n\ta = DUK_DEC_A(ins);\n\tbc = DUK_DEC_BC(ins);\n\n\t/* Registers 'bc' and 'bc + 1' are written in longjmp handling\n\t * and if their previous values (which are temporaries) become\n\t * unreachable -and- have a finalizer, there'll be a function\n\t * call during error handling which is not supported now (GH-287).\n\t * Ensure that both 'bc' and 'bc + 1' have primitive values to\n\t * guarantee no finalizer calls in error handling.  Scrubbing also\n\t * ensures finalizers for the previous values run here rather than\n\t * later.  Error handling related values are also written to 'bc'\n\t * and 'bc + 1' but those values never become unreachable during\n\t * error handling, so there's no side effect problem even if the\n\t * error value has a finalizer.\n\t */\n\tduk_dup(thr, (duk_idx_t) bc);  /* Stabilize value. */\n\tduk_to_undefined(thr, (duk_idx_t) bc);\n\tduk_to_undefined(thr, (duk_idx_t) (bc + 1));\n\n\t/* Allocate catcher and populate it.  Doesn't have to\n\t * be fully atomic, but the catcher must be in a\n\t * consistent state if side effects (such as finalizer\n\t * calls) occur.\n\t */\n\n\tcat = duk_hthread_catcher_alloc(thr);\n\tDUK_ASSERT(cat != NULL);\n\n\tcat->flags = DUK_CAT_TYPE_TCF;\n\tcat->h_varname = NULL;\n\tcat->pc_base = (duk_instr_t *) curr_pc;  /* pre-incremented, points to first jump slot */\n\tcat->idx_base = (duk_size_t) (thr->valstack_bottom - thr->valstack) + bc;\n\n\tact = thr->callstack_curr;\n\tDUK_ASSERT(act != NULL);\n\tcat->parent = act->cat;\n\tact->cat = cat;\n\n\tif (a & DUK_BC_TRYCATCH_FLAG_HAVE_CATCH) {\n\t\tcat->flags |= DUK_CAT_FLAG_CATCH_ENABLED;\n\t}\n\tif (a & DUK_BC_TRYCATCH_FLAG_HAVE_FINALLY) {\n\t\tcat->flags |= DUK_CAT_FLAG_FINALLY_ENABLED;\n\t}\n\tif (a & DUK_BC_TRYCATCH_FLAG_CATCH_BINDING) {\n\t\tDUK_DDD(DUK_DDDPRINT(\"catch binding flag set to catcher\"));\n\t\tcat->flags |= DUK_CAT_FLAG_CATCH_BINDING_ENABLED;\n\t\ttv1 = DUK_GET_TVAL_NEGIDX(thr, -1);\n\t\tDUK_ASSERT(DUK_TVAL_IS_STRING(tv1));\n\n\t\t/* borrowed reference; although 'tv1' comes from a register,\n\t\t * its value was loaded using LDCONST so the constant will\n\t\t * also exist and be reachable.\n\t\t */\n\t\tcat->h_varname = DUK_TVAL_GET_STRING(tv1);\n\t} else if (a & DUK_BC_TRYCATCH_FLAG_WITH_BINDING) {\n\t\tduk_hobjenv *env;\n\t\tduk_hobject *target;\n\n\t\t/* Delayed env initialization for activation (if needed). */\n\t\tDUK_ASSERT(thr->callstack_top >= 1);\n\t\tDUK_ASSERT(act == thr->callstack_curr);\n\t\tDUK_ASSERT(act != NULL);\n\t\tif (act->lex_env == NULL) {\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"delayed environment initialization\"));\n\t\t\tDUK_ASSERT(act->var_env == NULL);\n\n\t\t\tduk_js_init_activation_environment_records_delayed(thr, act);\n\t\t\tDUK_ASSERT(act == thr->callstack_curr);\n\t\t\tDUK_UNREF(act);  /* 'act' is no longer accessed, scanbuild fix */\n\t\t}\n\t\tDUK_ASSERT(act->lex_env != NULL);\n\t\tDUK_ASSERT(act->var_env != NULL);\n\n\t\t/* Coerce 'with' target. */\n\t\ttarget = duk_to_hobject(thr, -1);\n\t\tDUK_ASSERT(target != NULL);\n\n\t\t/* Create an object environment; it is not pushed\n\t\t * so avoid side effects very carefully until it is\n\t\t * referenced.\n\t\t */\n\t\tenv = duk_hobjenv_alloc(thr,\n\t\t                        DUK_HOBJECT_FLAG_EXTENSIBLE |\n\t\t                        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJENV));\n\t\tDUK_ASSERT(env != NULL);\n\t\tDUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) env) == NULL);\n\t\tenv->target = target;  /* always provideThis=true */\n\t\tDUK_HOBJECT_INCREF(thr, target);\n\t\tenv->has_this = 1;\n\t\tDUK_ASSERT_HOBJENV_VALID(env);\n\t\tDUK_DDD(DUK_DDDPRINT(\"environment for with binding: %!iO\", env));\n\n\t\tDUK_ASSERT(act == thr->callstack_curr);\n\t\tDUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) env) == NULL);\n\t\tDUK_ASSERT(act->lex_env != NULL);\n\t\tDUK_HOBJECT_SET_PROTOTYPE(thr->heap, (duk_hobject *) env, act->lex_env);\n\t\tact->lex_env = (duk_hobject *) env;  /* Now reachable. */\n\t\tDUK_HOBJECT_INCREF(thr, (duk_hobject *) env);\n\t\t/* Net refcount change to act->lex_env is 0: incref for env's\n\t\t * prototype, decref for act->lex_env overwrite.\n\t\t */\n\n\t\t/* Set catcher lex_env active (affects unwind)\n\t\t * only when the whole setup is complete.\n\t\t */\n\t\tcat = act->cat;  /* XXX: better to relookup? not mandatory because 'cat' is stable */\n\t\tcat->flags |= DUK_CAT_FLAG_LEXENV_ACTIVE;\n\t} else {\n\t\t;\n\t}\n\n\tDUK_DDD(DUK_DDDPRINT(\"TRYCATCH catcher: flags=0x%08lx, pc_base=%ld, \"\n\t                     \"idx_base=%ld, h_varname=%!O\",\n\t                     (unsigned long) cat->flags,\n\t                     (long) cat->pc_base, (long) cat->idx_base, (duk_heaphdr *) cat->h_varname));\n\n\tduk_pop_unsafe(thr);\n}\n\nDUK_LOCAL DUK__NOINLINE_PERF duk_instr_t *duk__handle_op_endtry(duk_hthread *thr, duk_uint_fast32_t ins) {\n\tduk_activation *act;\n\tduk_catcher *cat;\n\tduk_tval *tv1;\n\tduk_instr_t *pc_base;\n\n\tDUK_UNREF(ins);\n\n\tDUK_ASSERT(thr->callstack_top >= 1);\n\tact = thr->callstack_curr;\n\tDUK_ASSERT(act != NULL);\n\tcat = act->cat;\n\tDUK_ASSERT(cat != NULL);\n\tDUK_ASSERT(DUK_CAT_GET_TYPE(act->cat) == DUK_CAT_TYPE_TCF);\n\n\tDUK_DDD(DUK_DDDPRINT(\"ENDTRY: clearing catch active flag (regardless of whether it was set or not)\"));\n\tDUK_CAT_CLEAR_CATCH_ENABLED(cat);\n\n\tpc_base = cat->pc_base;\n\n\tif (DUK_CAT_HAS_FINALLY_ENABLED(cat)) {\n\t\tDUK_DDD(DUK_DDDPRINT(\"ENDTRY: finally part is active, jump through 2nd jump slot with 'normal continuation'\"));\n\n\t\ttv1 = thr->valstack + cat->idx_base;\n\t\tDUK_ASSERT(tv1 >= thr->valstack && tv1 < thr->valstack_top);\n\t\tDUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv1);  /* side effects */\n\t\ttv1 = NULL;\n\n\t\ttv1 = thr->valstack + cat->idx_base + 1;\n\t\tDUK_ASSERT(tv1 >= thr->valstack && tv1 < thr->valstack_top);\n\t\tDUK_TVAL_SET_U32_UPDREF(thr, tv1, (duk_uint32_t) DUK_LJ_TYPE_NORMAL);  /* side effects */\n\t\ttv1 = NULL;\n\n\t\tDUK_CAT_CLEAR_FINALLY_ENABLED(cat);\n\t} else {\n\t\tDUK_DDD(DUK_DDDPRINT(\"ENDTRY: no finally part, dismantle catcher, jump through 2nd jump slot (to end of statement)\"));\n\n\t\tduk_hthread_catcher_unwind_norz(thr, act);  /* lexenv may be set for 'with' binding */\n\t\t/* no need to unwind callstack */\n\t}\n\n\treturn pc_base + 1;  /* new curr_pc value */\n}\n\nDUK_LOCAL DUK__NOINLINE_PERF duk_instr_t *duk__handle_op_endcatch(duk_hthread *thr, duk_uint_fast32_t ins) {\n\tduk_activation *act;\n\tduk_catcher *cat;\n\tduk_tval *tv1;\n\tduk_instr_t *pc_base;\n\n\tDUK_UNREF(ins);\n\n\tDUK_ASSERT(thr->callstack_top >= 1);\n\tact = thr->callstack_curr;\n\tDUK_ASSERT(act != NULL);\n\tcat = act->cat;\n\tDUK_ASSERT(cat != NULL);\n\tDUK_ASSERT(!DUK_CAT_HAS_CATCH_ENABLED(cat));  /* cleared before entering catch part */\n\n\tif (DUK_CAT_HAS_LEXENV_ACTIVE(cat)) {\n\t\tduk_hobject *prev_env;\n\n\t\t/* 'with' binding has no catch clause, so can't be here unless a normal try-catch */\n\t\tDUK_ASSERT(DUK_CAT_HAS_CATCH_BINDING_ENABLED(cat));\n\t\tDUK_ASSERT(act->lex_env != NULL);\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"ENDCATCH: popping catcher part lexical environment\"));\n\n\t\tprev_env = act->lex_env;\n\t\tDUK_ASSERT(prev_env != NULL);\n\t\tact->lex_env = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, prev_env);\n\t\tDUK_CAT_CLEAR_LEXENV_ACTIVE(cat);\n\t\tDUK_HOBJECT_INCREF(thr, act->lex_env);\n\t\tDUK_HOBJECT_DECREF(thr, prev_env);  /* side effects */\n\n\t\tDUK_ASSERT(act == thr->callstack_curr);\n\t\tDUK_ASSERT(act != NULL);\n\t}\n\n\tpc_base = cat->pc_base;\n\n\tif (DUK_CAT_HAS_FINALLY_ENABLED(cat)) {\n\t\tDUK_DDD(DUK_DDDPRINT(\"ENDCATCH: finally part is active, jump through 2nd jump slot with 'normal continuation'\"));\n\n\t\ttv1 = thr->valstack + cat->idx_base;\n\t\tDUK_ASSERT(tv1 >= thr->valstack && tv1 < thr->valstack_top);\n\t\tDUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv1);  /* side effects */\n\t\ttv1 = NULL;\n\n\t\ttv1 = thr->valstack + cat->idx_base + 1;\n\t\tDUK_ASSERT(tv1 >= thr->valstack && tv1 < thr->valstack_top);\n\t\tDUK_TVAL_SET_U32_UPDREF(thr, tv1, (duk_uint32_t) DUK_LJ_TYPE_NORMAL);  /* side effects */\n\t\ttv1 = NULL;\n\n\t\tDUK_CAT_CLEAR_FINALLY_ENABLED(cat);\n\t} else {\n\t\tDUK_DDD(DUK_DDDPRINT(\"ENDCATCH: no finally part, dismantle catcher, jump through 2nd jump slot (to end of statement)\"));\n\n\t\tduk_hthread_catcher_unwind_norz(thr, act);\n\t\t/* no need to unwind callstack */\n\t}\n\n\treturn pc_base + 1;  /* new curr_pc value */\n}\n\nDUK_LOCAL DUK__NOINLINE_PERF duk_small_uint_t duk__handle_op_endfin(duk_hthread *thr, duk_uint_fast32_t ins, duk_activation *entry_act) {\n\tduk_activation *act;\n\tduk_tval *tv1;\n\tduk_uint_t reg_catch;\n\tduk_small_uint_t cont_type;\n\tduk_small_uint_t ret_result;\n\n\tDUK_ASSERT(thr->ptr_curr_pc == NULL);\n\tDUK_ASSERT(thr->callstack_top >= 1);\n\tact = thr->callstack_curr;\n\tDUK_ASSERT(act != NULL);\n\treg_catch = DUK_DEC_ABC(ins);\n\n\t/* CATCH flag may be enabled or disabled here; it may be enabled if\n\t * the statement has a catch block but the try block does not throw\n\t * an error.\n\t */\n\n\tDUK_DDD(DUK_DDDPRINT(\"ENDFIN: completion value=%!T, type=%!T\",\n\t                     (duk_tval *) (thr->valstack_bottom + reg_catch + 0),\n\t                     (duk_tval *) (thr->valstack_bottom + reg_catch + 1)));\n\n\ttv1 = thr->valstack_bottom + reg_catch + 1;  /* type */\n\tDUK_ASSERT(DUK_TVAL_IS_NUMBER(tv1));\n#if defined(DUK_USE_FASTINT)\n\tDUK_ASSERT(DUK_TVAL_IS_FASTINT(tv1));\n\tcont_type = (duk_small_uint_t) DUK_TVAL_GET_FASTINT_U32(tv1);\n#else\n\tcont_type = (duk_small_uint_t) DUK_TVAL_GET_NUMBER(tv1);\n#endif\n\n\ttv1--;  /* value */\n\n\tswitch (cont_type) {\n\tcase DUK_LJ_TYPE_NORMAL: {\n\t\tDUK_DDD(DUK_DDDPRINT(\"ENDFIN: finally part finishing with 'normal' (non-abrupt) completion -> \"\n\t\t                     \"dismantle catcher, resume execution after ENDFIN\"));\n\n\t\tduk_hthread_catcher_unwind_norz(thr, act);\n\t\t/* no need to unwind callstack */\n\t\treturn 0;  /* restart execution */\n\t}\n\tcase DUK_LJ_TYPE_RETURN: {\n\t\tDUK_DDD(DUK_DDDPRINT(\"ENDFIN: finally part finishing with 'return' complation -> dismantle \"\n\t\t                     \"catcher, handle return, lj.value1=%!T\", tv1));\n\n\t\t/* Not necessary to unwind catch stack: return handling will\n\t\t * do it.  The finally flag of 'cat' is no longer set.  The\n\t\t * catch flag may be set, but it's not checked by return handling.\n\t\t */\n\n\t\tduk_push_tval(thr, tv1);\n\t\tret_result = duk__handle_return(thr, entry_act);\n\t\tif (ret_result == DUK__RETHAND_RESTART) {\n\t\t\treturn 0;  /* restart execution */\n\t\t}\n\t\tDUK_ASSERT(ret_result == DUK__RETHAND_FINISHED);\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"exiting executor after ENDFIN and RETURN (pseudo) longjmp type\"));\n\t\treturn 1;  /* exit executor */\n\t}\n\tcase DUK_LJ_TYPE_BREAK:\n\tcase DUK_LJ_TYPE_CONTINUE: {\n\t\tduk_uint_t label_id;\n\t\tduk_small_uint_t lj_type;\n\n\t\t/* Not necessary to unwind catch stack: break/continue\n\t\t * handling will do it.  The finally flag of 'cat' is\n\t\t * no longer set.  The catch flag may be set, but it's\n\t\t * not checked by break/continue handling.\n\t\t */\n\n\t\tDUK_ASSERT(DUK_TVAL_IS_NUMBER(tv1));\n#if defined(DUK_USE_FASTINT)\n\t\tDUK_ASSERT(DUK_TVAL_IS_FASTINT(tv1));\n\t\tlabel_id = (duk_small_uint_t) DUK_TVAL_GET_FASTINT_U32(tv1);\n#else\n\t\tlabel_id = (duk_small_uint_t) DUK_TVAL_GET_NUMBER(tv1);\n#endif\n\t\tlj_type = cont_type;\n\t\tduk__handle_break_or_continue(thr, label_id, lj_type);\n\t\treturn 0;  /* restart execution */\n\t}\n\tdefault: {\n\t\tDUK_DDD(DUK_DDDPRINT(\"ENDFIN: finally part finishing with abrupt completion, lj_type=%ld -> \"\n\t\t                     \"dismantle catcher, re-throw error\",\n\t\t                     (long) cont_type));\n\n\t\tduk_err_setup_ljstate1(thr, (duk_small_uint_t) cont_type, tv1);\n\t\t/* No debugger Throw notify check on purpose (rethrow). */\n\n\t\tDUK_ASSERT(thr->heap->lj.jmpbuf_ptr != NULL);  /* always in executor */\n\t\tduk_err_longjmp(thr);\n\t\tDUK_UNREACHABLE();\n\t}\n\t}\n\n\tDUK_UNREACHABLE();\n\treturn 0;\n}\n\nDUK_LOCAL DUK__NOINLINE_PERF void duk__handle_op_initenum(duk_hthread *thr, duk_uint_fast32_t ins) {\n\tduk_small_uint_t b;\n\tduk_small_uint_t c;\n\n\t/*\n\t *  Enumeration semantics come from for-in statement, E5 Section 12.6.4.\n\t *  If called with 'null' or 'undefined', this opcode returns 'null' as\n\t *  the enumerator, which is special cased in NEXTENUM.  This simplifies\n\t *  the compiler part\n\t */\n\n\t/* B -> register for writing enumerator object\n\t * C -> value to be enumerated (register)\n\t */\n\tb = DUK_DEC_B(ins);\n\tc = DUK_DEC_C(ins);\n\n\tif (duk_is_null_or_undefined(thr, (duk_idx_t) c)) {\n\t\tduk_push_null(thr);\n\t\tduk_replace(thr, (duk_idx_t) b);\n\t} else {\n\t\tduk_dup(thr, (duk_idx_t) c);\n\t\tduk_to_object(thr, -1);\n\t\tduk_hobject_enumerator_create(thr, 0 /*enum_flags*/);  /* [ ... val ] --> [ ... enum ] */\n\t\tduk_replace(thr, (duk_idx_t) b);\n\t}\n}\n\nDUK_LOCAL DUK__NOINLINE_PERF duk_small_uint_t duk__handle_op_nextenum(duk_hthread *thr, duk_uint_fast32_t ins) {\n\tduk_small_uint_t b;\n\tduk_small_uint_t c;\n\tduk_small_uint_t pc_skip = 0;\n\n\t/*\n\t *  NEXTENUM checks whether the enumerator still has unenumerated\n\t *  keys.  If so, the next key is loaded to the target register\n\t *  and the next instruction is skipped.  Otherwise the next instruction\n\t *  will be executed, jumping out of the enumeration loop.\n\t */\n\n\t/* B -> target register for next key\n\t * C -> enum register\n\t */\n\tb = DUK_DEC_B(ins);\n\tc = DUK_DEC_C(ins);\n\n\tDUK_DDD(DUK_DDDPRINT(\"NEXTENUM: b->%!T, c->%!T\",\n\t                     (duk_tval *) duk_get_tval(thr, (duk_idx_t) b),\n\t                     (duk_tval *) duk_get_tval(thr, (duk_idx_t) c)));\n\n\tif (duk_is_object(thr, (duk_idx_t) c)) {\n\t\t/* XXX: assert 'c' is an enumerator */\n\t\tduk_dup(thr, (duk_idx_t) c);\n\t\tif (duk_hobject_enumerator_next(thr, 0 /*get_value*/)) {\n\t\t\t/* [ ... enum ] -> [ ... next_key ] */\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"enum active, next key is %!T, skip jump slot \",\n\t\t\t                     (duk_tval *) duk_get_tval(thr, -1)));\n\t\t\tpc_skip = 1;\n\t\t} else {\n\t\t\t/* [ ... enum ] -> [ ... ] */\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"enum finished, execute jump slot\"));\n\t\t\tDUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top));  /* valstack policy */\n\t\t\tthr->valstack_top++;\n\t\t}\n\t\tduk_replace(thr, (duk_idx_t) b);\n\t} else {\n\t\t/* 'null' enumerator case -> behave as with an empty enumerator */\n\t\tDUK_ASSERT(duk_is_null(thr, (duk_idx_t) c));\n\t\tDUK_DDD(DUK_DDDPRINT(\"enum is null, execute jump slot\"));\n\t}\n\n\treturn pc_skip;\n}\n\n/*\n *  Call handling helpers.\n */\n\nDUK_LOCAL duk_bool_t duk__executor_handle_call(duk_hthread *thr, duk_idx_t idx, duk_idx_t nargs, duk_small_uint_t call_flags) {\n\tduk_bool_t rc;\n\n\tduk_set_top_unsafe(thr, (duk_idx_t) (idx + nargs + 2));   /* [ ... func this arg1 ... argN ] */\n\n\t/* Attempt an Ecma-to-Ecma call setup.  If the call\n\t * target is (directly or indirectly) Reflect.construct(),\n\t * the call may change into a constructor call on the fly.\n\t */\n\trc = (duk_bool_t) duk_handle_call_unprotected(thr, idx, call_flags);\n\tif (rc != 0) {\n\t\t/* Ecma-to-ecma call possible, may or may not\n\t\t * be a tail call.  Avoid C recursion by\n\t\t * reusing current executor instance.\n\t\t */\n\t\tDUK_DDD(DUK_DDDPRINT(\"ecma-to-ecma call setup possible, restart execution\"));\n\t\t/* curr_pc synced by duk_handle_call_unprotected() */\n\t\tDUK_ASSERT(thr->ptr_curr_pc == NULL);\n\t\treturn rc;\n\t} else {\n\t\t/* Call was handled inline. */\n\t}\n\tDUK_ASSERT(thr->ptr_curr_pc != NULL);\n\treturn rc;\n}\n\n/*\n *  Ecmascript bytecode executor.\n *\n *  Resume execution for the current thread from its current activation.\n *  Returns when execution would return from the entry level activation,\n *  leaving a single return value on top of the stack.  Function calls\n *  and thread resumptions are handled internally.  If an error occurs,\n *  a longjmp() with type DUK_LJ_TYPE_THROW is called on the entry level\n *  setjmp() jmpbuf.\n *\n *  Ecmascript function calls and coroutine resumptions are handled\n *  internally (by the outer executor function) without recursive C calls.\n *  Other function calls are handled using duk_handle_call(), increasing\n *  C recursion depth.\n *\n *  Abrupt completions (= long control tranfers) are handled either\n *  directly by reconfiguring relevant stacks and restarting execution,\n *  or via a longjmp.  Longjmp-free handling is preferable for performance\n *  (especially Emscripten performance), and is used for: break, continue,\n *  and return.\n *\n *  For more detailed notes, see doc/execution.rst.\n *\n *  Also see doc/code-issues.rst for discussion of setjmp(), longjmp(),\n *  and volatile.\n */\n\n/* Presence of 'fun' is config based, there's a marginal performance\n * difference and the best option is architecture dependent.\n */\n#if defined(DUK_USE_EXEC_FUN_LOCAL)\n#define DUK__FUN()          fun\n#else\n#define DUK__FUN()          ((duk_hcompfunc *) DUK_ACT_GET_FUNC((thr)->callstack_curr))\n#endif\n\n/* Strict flag. */\n#define DUK__STRICT()       ((duk_small_uint_t) DUK_HOBJECT_HAS_STRICT((duk_hobject *) DUK__FUN()))\n\n/* Reg/const access macros: these are very footprint and performance sensitive\n * so modify with care.  Arguments are sometimes evaluated multiple times which\n * is not ideal.\n */\n#define DUK__REG(x)         (*(thr->valstack_bottom + (x)))\n#define DUK__REGP(x)        (thr->valstack_bottom + (x))\n#define DUK__CONST(x)       (*(consts + (x)))\n#define DUK__CONSTP(x)      (consts + (x))\n\n/* Reg/const access macros which take the 32-bit instruction and avoid an\n * explicit field decoding step by using shifts and masks.  These must be\n * kept in sync with duk_js_bytecode.h.  The shift/mask values are chosen\n * so that 'ins' can be shifted and masked and used as a -byte- offset\n * instead of a duk_tval offset which needs further shifting (which is an\n * issue on some, but not all, CPUs).\n */\n#define DUK__RCBIT_B           DUK_BC_REGCONST_B\n#define DUK__RCBIT_C           DUK_BC_REGCONST_C\n#if defined(DUK_USE_EXEC_REGCONST_OPTIMIZE)\n#if defined(DUK_USE_PACKED_TVAL)\n#define DUK__TVAL_SHIFT        3  /* sizeof(duk_tval) == 8 */\n#else\n#define DUK__TVAL_SHIFT        4  /* sizeof(duk_tval) == 16; not always the case so also asserted for */\n#endif\n#define DUK__SHIFT_A           (DUK_BC_SHIFT_A - DUK__TVAL_SHIFT)\n#define DUK__SHIFT_B           (DUK_BC_SHIFT_B - DUK__TVAL_SHIFT)\n#define DUK__SHIFT_C           (DUK_BC_SHIFT_C - DUK__TVAL_SHIFT)\n#define DUK__SHIFT_BC          (DUK_BC_SHIFT_BC - DUK__TVAL_SHIFT)\n#define DUK__MASK_A            (DUK_BC_UNSHIFTED_MASK_A << DUK__TVAL_SHIFT)\n#define DUK__MASK_B            (DUK_BC_UNSHIFTED_MASK_B << DUK__TVAL_SHIFT)\n#define DUK__MASK_C            (DUK_BC_UNSHIFTED_MASK_C << DUK__TVAL_SHIFT)\n#define DUK__MASK_BC           (DUK_BC_UNSHIFTED_MASK_BC << DUK__TVAL_SHIFT)\n#define DUK__BYTEOFF_A(ins)    (((ins) >> DUK__SHIFT_A) & DUK__MASK_A)\n#define DUK__BYTEOFF_B(ins)    (((ins) >> DUK__SHIFT_B) & DUK__MASK_B)\n#define DUK__BYTEOFF_C(ins)    (((ins) >> DUK__SHIFT_C) & DUK__MASK_C)\n#define DUK__BYTEOFF_BC(ins)   (((ins) >> DUK__SHIFT_BC) & DUK__MASK_BC)\n\n#define DUK__REGP_A(ins)       ((duk_tval *) (void *) ((duk_uint8_t *) thr->valstack_bottom + DUK__BYTEOFF_A((ins))))\n#define DUK__REGP_B(ins)       ((duk_tval *) (void *) ((duk_uint8_t *) thr->valstack_bottom + DUK__BYTEOFF_B((ins))))\n#define DUK__REGP_C(ins)       ((duk_tval *) (void *) ((duk_uint8_t *) thr->valstack_bottom + DUK__BYTEOFF_C((ins))))\n#define DUK__REGP_BC(ins)      ((duk_tval *) (void *) ((duk_uint8_t *) thr->valstack_bottom + DUK__BYTEOFF_BC((ins))))\n#define DUK__CONSTP_A(ins)     ((duk_tval *) (void *) ((duk_uint8_t *) consts + DUK__BYTEOFF_A((ins))))\n#define DUK__CONSTP_B(ins)     ((duk_tval *) (void *) ((duk_uint8_t *) consts + DUK__BYTEOFF_B((ins))))\n#define DUK__CONSTP_C(ins)     ((duk_tval *) (void *) ((duk_uint8_t *) consts + DUK__BYTEOFF_C((ins))))\n#define DUK__CONSTP_BC(ins)    ((duk_tval *) (void *) ((duk_uint8_t *) consts + DUK__BYTEOFF_BC((ins))))\n#define DUK__REGCONSTP_B(ins)  ((duk_tval *) (void *) ((duk_uint8_t *) (((ins) & DUK__RCBIT_B) ? consts : thr->valstack_bottom) + DUK__BYTEOFF_B((ins))))\n#define DUK__REGCONSTP_C(ins)  ((duk_tval *) (void *) ((duk_uint8_t *) (((ins) & DUK__RCBIT_C) ? consts : thr->valstack_bottom) + DUK__BYTEOFF_C((ins))))\n#else  /* DUK_USE_EXEC_REGCONST_OPTIMIZE */\n/* Safe alternatives, no assumption about duk_tval size. */\n#define DUK__REGP_A(ins)       DUK__REGP(DUK_DEC_A((ins)))\n#define DUK__REGP_B(ins)       DUK__REGP(DUK_DEC_B((ins)))\n#define DUK__REGP_C(ins)       DUK__REGP(DUK_DEC_C((ins)))\n#define DUK__REGP_BC(ins)      DUK__REGP(DUK_DEC_BC((ins)))\n#define DUK__CONSTP_A(ins)     DUK__CONSTP(DUK_DEC_A((ins)))\n#define DUK__CONSTP_B(ins)     DUK__CONSTP(DUK_DEC_B((ins)))\n#define DUK__CONSTP_C(ins)     DUK__CONSTP(DUK_DEC_C((ins)))\n#define DUK__CONSTP_BC(ins)    DUK__CONSTP(DUK_DEC_BC((ins)))\n#define DUK__REGCONSTP_B(ins)  ((((ins) & DUK__RCBIT_B) ? consts : thr->valstack_bottom) + DUK_DEC_B((ins)))\n#define DUK__REGCONSTP_C(ins)  ((((ins) & DUK__RCBIT_C) ? consts : thr->valstack_bottom) + DUK_DEC_C((ins)))\n#endif  /* DUK_USE_EXEC_REGCONST_OPTIMIZE */\n\n#if defined(DUK_USE_VERBOSE_EXECUTOR_ERRORS)\n#define DUK__INTERNAL_ERROR(msg)  do { \\\n\t\tDUK_ERROR_ERROR(thr, (msg)); \\\n\t} while (0)\n#else\n#define DUK__INTERNAL_ERROR(msg)  do { \\\n\t\tgoto internal_error; \\\n\t} while (0)\n#endif\n\n#define DUK__SYNC_CURR_PC()  do { \\\n\t\tduk_activation *duk__act; \\\n\t\tduk__act = thr->callstack_curr; \\\n\t\tduk__act->curr_pc = curr_pc; \\\n\t} while (0)\n#define DUK__SYNC_AND_NULL_CURR_PC()  do { \\\n\t\tduk_activation *duk__act; \\\n\t\tduk__act = thr->callstack_curr; \\\n\t\tduk__act->curr_pc = curr_pc; \\\n\t\tthr->ptr_curr_pc = NULL; \\\n\t} while (0)\n\n#if defined(DUK_USE_EXEC_PREFER_SIZE)\n#define DUK__LOOKUP_INDIRECT(idx) do { \\\n\t\t(idx) = (duk_uint_fast_t) duk_get_uint(thr, (duk_idx_t) (idx)); \\\n\t} while (0)\n#elif defined(DUK_USE_FASTINT)\n#define DUK__LOOKUP_INDIRECT(idx) do { \\\n\t\tduk_tval *tv_ind; \\\n\t\ttv_ind = DUK__REGP((idx)); \\\n\t\tDUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_ind)); \\\n\t\tDUK_ASSERT(DUK_TVAL_IS_FASTINT(tv_ind));  /* compiler guarantees */ \\\n\t\t(idx) = (duk_uint_fast_t) DUK_TVAL_GET_FASTINT_U32(tv_ind); \\\n\t} while (0)\n#else\n#define DUK__LOOKUP_INDIRECT(idx) do { \\\n\t\tduk_tval *tv_ind; \\\n\t\ttv_ind = DUK__REGP(idx); \\\n\t\tDUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_ind)); \\\n\t\tidx = (duk_uint_fast_t) DUK_TVAL_GET_NUMBER(tv_ind); \\\n\t} while (0)\n#endif\n\nDUK_LOCAL void duk__handle_executor_error(duk_heap *heap,\n                                          duk_activation *entry_act,\n                                          duk_int_t entry_call_recursion_depth,\n                                          duk_jmpbuf *entry_jmpbuf_ptr) {\n\tduk_small_uint_t lj_ret;\n\n\t/* Longjmp callers are required to sync-and-null thr->ptr_curr_pc\n\t * before longjmp.\n\t */\n\tDUK_ASSERT(heap->curr_thread != NULL);\n\tDUK_ASSERT(heap->curr_thread->ptr_curr_pc == NULL);\n\n\t/* XXX: signalling the need to shrink check (only if unwound) */\n\n\t/* Must be restored here to handle e.g. yields properly. */\n\theap->call_recursion_depth = entry_call_recursion_depth;\n\n\t/* Switch to caller's setjmp() catcher so that if an error occurs\n\t * during error handling, it is always propagated outwards instead\n\t * of causing an infinite loop in our own handler.\n\t */\n\theap->lj.jmpbuf_ptr = (duk_jmpbuf *) entry_jmpbuf_ptr;\n\n\tlj_ret = duk__handle_longjmp(heap->curr_thread, entry_act);\n\n\t/* Error handling complete, remove side effect protections.\n\t */\n#if defined(DUK_USE_ASSERTIONS)\n\tDUK_ASSERT(heap->error_not_allowed == 1);\n\theap->error_not_allowed = 0;\n#endif\n\tDUK_ASSERT(heap->pf_prevent_count > 0);\n\theap->pf_prevent_count--;\n\tDUK_DD(DUK_DDPRINT(\"executor error handled, pf_prevent_count updated to %ld\", (long) heap->pf_prevent_count));\n\n\tif (lj_ret == DUK__LONGJMP_RESTART) {\n\t\t/* Restart bytecode execution, possibly with a changed thread. */\n\t\tDUK_REFZERO_CHECK_SLOW(heap->curr_thread);\n\t} else {\n\t\t/* If an error is propagated, don't run refzero checks here.\n\t\t * The next catcher will deal with that.  Pf_prevent_count\n\t\t * will be re-bumped by the longjmp.\n\t\t */\n\n\t\tDUK_ASSERT(lj_ret == DUK__LONGJMP_RETHROW);  /* Rethrow error to calling state. */\n\t\tDUK_ASSERT(heap->lj.jmpbuf_ptr == entry_jmpbuf_ptr);  /* Longjmp handling has restored jmpbuf_ptr. */\n\n\t\t/* Thread may have changed, e.g. YIELD converted to THROW. */\n\t\tduk_err_longjmp(heap->curr_thread);\n\t\tDUK_UNREACHABLE();\n\t}\n}\n\n/* Outer executor with setjmp/longjmp handling. */\nDUK_INTERNAL void duk_js_execute_bytecode(duk_hthread *exec_thr) {\n\t/* Entry level info. */\n\tduk_hthread *entry_thread;\n\tduk_activation *entry_act;\n\tduk_int_t entry_call_recursion_depth;\n\tduk_jmpbuf *entry_jmpbuf_ptr;\n\tduk_jmpbuf our_jmpbuf;\n\tduk_heap *heap;\n\n\tDUK_ASSERT(exec_thr != NULL);\n\tDUK_ASSERT(exec_thr->heap != NULL);\n\tDUK_ASSERT(exec_thr->heap->curr_thread != NULL);\n\tDUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR((duk_heaphdr *) exec_thr);\n\tDUK_ASSERT(exec_thr->callstack_top >= 1);  /* at least one activation, ours */\n\tDUK_ASSERT(exec_thr->callstack_curr != NULL);\n\tDUK_ASSERT(DUK_ACT_GET_FUNC(exec_thr->callstack_curr) != NULL);\n\tDUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(exec_thr->callstack_curr)));\n\n\tDUK_GC_TORTURE(exec_thr->heap);\n\n\tentry_thread = exec_thr;\n\theap = entry_thread->heap;\n\tentry_act = entry_thread->callstack_curr;\n\tDUK_ASSERT(entry_act != NULL);\n\tentry_call_recursion_depth = entry_thread->heap->call_recursion_depth;\n\tentry_jmpbuf_ptr = entry_thread->heap->lj.jmpbuf_ptr;\n\n\t/*\n\t *  Note: we currently assume that the setjmp() catchpoint is\n\t *  not re-entrant (longjmp() cannot be called more than once\n\t *  for a single setjmp()).\n\t *\n\t *  See doc/code-issues.rst for notes on variable assignment\n\t *  before and after setjmp().\n\t */\n\n\tfor (;;) {\n\t\theap->lj.jmpbuf_ptr = &our_jmpbuf;\n\t\tDUK_ASSERT(heap->lj.jmpbuf_ptr != NULL);\n\n#if defined(DUK_USE_CPP_EXCEPTIONS)\n\t\ttry {\n#else\n\t\tDUK_ASSERT(heap->lj.jmpbuf_ptr == &our_jmpbuf);\n\t\tif (DUK_SETJMP(our_jmpbuf.jb) == 0) {\n#endif\n\t\t\t/* Execute bytecode until returned or longjmp(). */\n\t\t\tduk__js_execute_bytecode_inner(entry_thread, entry_act);\n\n\t\t\t/* Successful return: restore jmpbuf and return to caller. */\n\t\t\theap->lj.jmpbuf_ptr = entry_jmpbuf_ptr;\n\n\t\t\treturn;\n#if defined(DUK_USE_CPP_EXCEPTIONS)\n\t\t} catch (duk_internal_exception &exc) {\n#else\n\t\t} else {\n#endif\n#if defined(DUK_USE_CPP_EXCEPTIONS)\n\t\t\tDUK_UNREF(exc);\n#endif\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"longjmp caught by bytecode executor\"));\n\t\t\tDUK_STATS_INC(exec_thr->heap, stats_exec_throw);\n\n\t\t\tduk__handle_executor_error(heap,\n\t\t\t                           entry_act,\n\t\t\t                           entry_call_recursion_depth,\n\t\t\t                           entry_jmpbuf_ptr);\n\t\t}\n#if defined(DUK_USE_CPP_EXCEPTIONS)\n\t\tcatch (std::exception &exc) {\n\t\t\tconst char *what = exc.what();\n\t\t\tif (!what) {\n\t\t\t\twhat = \"unknown\";\n\t\t\t}\n\t\t\tDUK_D(DUK_DPRINT(\"unexpected c++ std::exception (perhaps thrown by user code)\"));\n\t\t\tDUK_STATS_INC(exec_thr->heap, stats_exec_throw);\n\t\t\ttry {\n\t\t\t\tDUK_ASSERT(heap->curr_thread != NULL);\n\t\t\t\tDUK_ERROR_FMT1(heap->curr_thread, DUK_ERR_TYPE_ERROR, \"caught invalid c++ std::exception '%s' (perhaps thrown by user code)\", what);\n\t\t\t} catch (duk_internal_exception exc) {\n\t\t\t\tDUK_D(DUK_DPRINT(\"caught api error thrown from unexpected c++ std::exception\"));\n\t\t\t\tDUK_UNREF(exc);\n\t\t\t\tduk__handle_executor_error(heap,\n\t\t\t\t                           entry_act,\n\t\t\t\t                           entry_call_recursion_depth,\n\t\t\t\t                           entry_jmpbuf_ptr);\n\t\t\t}\n\t\t} catch (...) {\n\t\t\tDUK_D(DUK_DPRINT(\"unexpected c++ exception (perhaps thrown by user code)\"));\n\t\t\tDUK_STATS_INC(exec_thr->heap, stats_exec_throw);\n\t\t\ttry {\n\t\t\t\tDUK_ASSERT(heap->curr_thread != NULL);\n\t\t\t\tDUK_ERROR_TYPE(heap->curr_thread, \"caught invalid c++ exception (perhaps thrown by user code)\");\n\t\t\t} catch (duk_internal_exception exc) {\n\t\t\t\tDUK_D(DUK_DPRINT(\"caught api error thrown from unexpected c++ exception\"));\n\t\t\t\tDUK_UNREF(exc);\n\t\t\t\tduk__handle_executor_error(heap,\n\t\t\t\t                           entry_act,\n\t\t\t\t                           entry_call_recursion_depth,\n\t\t\t\t                           entry_jmpbuf_ptr);\n\t\t\t}\n\t\t}\n#endif\n\t}\n\n\tDUK_UNREACHABLE();\n}\n\n/* Inner executor, performance critical. */\nDUK_LOCAL DUK_NOINLINE DUK_HOT void duk__js_execute_bytecode_inner(duk_hthread *entry_thread, duk_activation *entry_act) {\n\t/* Current PC, accessed by other functions through thr->ptr_to_curr_pc.\n\t * Critical for performance.  It would be safest to make this volatile,\n\t * but that eliminates performance benefits; aliasing guarantees\n\t * should be enough though.\n\t */\n\tduk_instr_t *curr_pc;         /* bytecode has a stable pointer */\n\n\t/* Hot variables for interpretation.  Critical for performance,\n\t * but must add sparingly to minimize register shuffling.\n\t */\n\tduk_hthread *thr;             /* stable */\n\tduk_tval *consts;             /* stable */\n\tduk_uint_fast32_t ins;\n\t/* 'funcs' is quite rarely used, so no local for it */\n#if defined(DUK_USE_EXEC_FUN_LOCAL)\n\tduk_hcompfunc *fun;\n#else\n\t/* 'fun' is quite rarely used, so no local for it */\n#endif\n\n#if defined(DUK_USE_INTERRUPT_COUNTER)\n\tduk_int_t int_ctr;\n#endif\n\n#if defined(DUK_USE_ASSERTIONS)\n\tduk_size_t valstack_top_base;    /* valstack top, should match before interpreting each op (no leftovers) */\n#endif\n\n\t/* Optimized reg/const access macros assume sizeof(duk_tval) to be\n\t * either 8 or 16.  Heap allocation checks this even without asserts\n\t * enabled now because it can't be autodetected in duk_config.h.\n\t */\n#if 1\n#if defined(DUK_USE_PACKED_TVAL)\n\tDUK_ASSERT(sizeof(duk_tval) == 8);\n#else\n\tDUK_ASSERT(sizeof(duk_tval) == 16);\n#endif\n#endif\n\n\tDUK_GC_TORTURE(entry_thread->heap);\n\n\t/*\n\t *  Restart execution by reloading thread state.\n\t *\n\t *  Note that 'thr' and any thread configuration may have changed,\n\t *  so all local variables are suspect and we need to reinitialize.\n\t *\n\t *  The number of local variables should be kept to a minimum: if\n\t *  the variables are spilled, they will need to be loaded from\n\t *  memory anyway.\n\t *\n\t *  Any 'goto restart_execution;' code path in opcode dispatch must\n\t *  ensure 'curr_pc' is synced back to act->curr_pc before the goto\n\t *  takes place.\n\t *\n\t *  The interpreter must be very careful with memory pointers, as\n\t *  many pointers are not guaranteed to be 'stable' and may be\n\t *  reallocated and relocated on-the-fly quite easily (e.g. by a\n\t *  memory allocation or a property access).\n\t *\n\t *  The following are assumed to have stable pointers:\n\t *    - the current thread\n\t *    - the current function\n\t *    - the bytecode, constant table, inner function table of the\n\t *      current function (as they are a part of the function allocation)\n\t *\n\t *  The following are assumed to have semi-stable pointers:\n\t *    - the current activation entry: stable as long as callstack\n\t *      is not changed (reallocated by growing or shrinking), or\n\t *      by any garbage collection invocation (through finalizers)\n\t *    - Note in particular that ANY DECREF can invalidate the\n\t *      activation pointer, so for the most part a fresh lookup\n\t *      is required\n\t *\n\t *  The following are not assumed to have stable pointers at all:\n\t *    - the value stack (registers) of the current thread\n\t *\n\t *  See execution.rst for discussion.\n\t */\n\n restart_execution:\n\n\t/* Lookup current thread; use the stable 'entry_thread' for this to\n\t * avoid clobber warnings.  Any valid, reachable 'thr' value would be\n\t * fine for this, so using 'entry_thread' is just to silence warnings.\n\t */\n\tthr = entry_thread->heap->curr_thread;\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(thr->callstack_top >= 1);\n\tDUK_ASSERT(thr->callstack_curr != NULL);\n\tDUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack_curr) != NULL);\n\tDUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(thr->callstack_curr)));\n\n\tDUK_GC_TORTURE(thr->heap);\n\n\tthr->ptr_curr_pc = &curr_pc;\n\n\t/* Relookup and initialize dispatch loop variables.  Debugger check. */\n\t{\n\t\tduk_activation *act;\n#if !defined(DUK_USE_EXEC_FUN_LOCAL)\n\t\tduk_hcompfunc *fun;\n#endif\n\n\t\t/* Assume interrupt init/counter are properly initialized here. */\n\t\t/* Assume that thr->valstack_bottom has been set-up before getting here. */\n\n\t\tact = thr->callstack_curr;\n\t\tDUK_ASSERT(act != NULL);\n\t\tfun = (duk_hcompfunc *) DUK_ACT_GET_FUNC(act);\n\t\tDUK_ASSERT(fun != NULL);\n\t\tDUK_ASSERT(thr->valstack_top - thr->valstack_bottom == fun->nregs);\n\t\tconsts = DUK_HCOMPFUNC_GET_CONSTS_BASE(thr->heap, fun);\n\t\tDUK_ASSERT(consts != NULL);\n\n#if defined(DUK_USE_DEBUGGER_SUPPORT)\n\t\tif (DUK_UNLIKELY(duk_debug_is_attached(thr->heap) && !thr->heap->dbg_processing)) {\n\t\t\tduk__executor_recheck_debugger(thr, act, fun);\n\t\t\tDUK_ASSERT(act == thr->callstack_curr);\n\t\t\tDUK_ASSERT(act != NULL);\n\t\t}\n#endif  /* DUK_USE_DEBUGGER_SUPPORT */\n\n#if defined(DUK_USE_ASSERTIONS)\n\t\tvalstack_top_base = (duk_size_t) (thr->valstack_top - thr->valstack);\n#endif\n\n\t\t/* Set up curr_pc for opcode dispatch. */\n\t\tcurr_pc = act->curr_pc;\n\t}\n\n\tDUK_DD(DUK_DDPRINT(\"restarting execution, thr %p, act idx %ld, fun %p,\"\n\t                   \"consts %p, funcs %p, lev %ld, regbot %ld, regtop %ld, \"\n\t                   \"preventcount=%ld\",\n\t                   (void *) thr,\n\t                   (long) (thr->callstack_top - 1),\n\t                   (void *) DUK__FUN(),\n\t                   (void *) DUK_HCOMPFUNC_GET_CONSTS_BASE(thr->heap, DUK__FUN()),\n\t                   (void *) DUK_HCOMPFUNC_GET_FUNCS_BASE(thr->heap, DUK__FUN()),\n\t                   (long) (thr->callstack_top - 1),\n\t                   (long) (thr->valstack_bottom - thr->valstack),\n\t                   (long) (thr->valstack_top - thr->valstack),\n\t                   (long) thr->callstack_preventcount));\n\n\t/* Dispatch loop. */\n\n\tfor (;;) {\n\t\tduk_uint8_t op;\n\n\t\tDUK_ASSERT(thr->callstack_top >= 1);\n\t\tDUK_ASSERT(thr->valstack_top - thr->valstack_bottom == DUK__FUN()->nregs);\n\t\tDUK_ASSERT((duk_size_t) (thr->valstack_top - thr->valstack) == valstack_top_base);\n\n\t\t/* Executor interrupt counter check, used to implement breakpoints,\n\t\t * debugging interface, execution timeouts, etc.  The counter is heap\n\t\t * specific but is maintained in the current thread to make the check\n\t\t * as fast as possible.  The counter is copied back to the heap struct\n\t\t * whenever a thread switch occurs by the DUK_HEAP_SWITCH_THREAD() macro.\n\t\t */\n#if defined(DUK_USE_INTERRUPT_COUNTER)\n\t\tint_ctr = thr->interrupt_counter;\n\t\tif (DUK_LIKELY(int_ctr > 0)) {\n\t\t\tthr->interrupt_counter = int_ctr - 1;\n\t\t} else {\n\t\t\t/* Trigger at zero or below */\n\t\t\tduk_small_uint_t exec_int_ret;\n\n\t\t\tDUK_STATS_INC(thr->heap, stats_exec_interrupt);\n\n\t\t\t/* Write curr_pc back for the debugger. */\n\t\t\t{\n\t\t\t\tduk_activation *act;\n\t\t\t\tDUK_ASSERT(thr->callstack_top > 0);\n\t\t\t\tact = thr->callstack_curr;\n\t\t\t\tDUK_ASSERT(act != NULL);\n\t\t\t\tact->curr_pc = (duk_instr_t *) curr_pc;\n\t\t\t}\n\n\t\t\t/* Forced restart caused by a function return; must recheck\n\t\t\t * debugger breakpoints before checking line transitions,\n\t\t\t * see GH-303.  Restart and then handle interrupt_counter\n\t\t\t * zero again.\n\t\t\t */\n#if defined(DUK_USE_DEBUGGER_SUPPORT)\n\t\t\tif (thr->heap->dbg_force_restart) {\n\t\t\t\tDUK_DD(DUK_DDPRINT(\"dbg_force_restart flag forced restart execution\"));  /* GH-303 */\n\t\t\t\tthr->heap->dbg_force_restart = 0;\n\t\t\t\tgoto restart_execution;\n\t\t\t}\n#endif\n\n\t\t\texec_int_ret = duk__executor_interrupt(thr);\n\t\t\tif (exec_int_ret == DUK__INT_RESTART) {\n\t\t\t\t/* curr_pc synced back above */\n\t\t\t\tgoto restart_execution;\n\t\t\t}\n\t\t}\n#endif  /* DUK_USE_INTERRUPT_COUNTER */\n#if defined(DUK_USE_INTERRUPT_COUNTER) && defined(DUK_USE_DEBUG)\n\t\t/* For cross-checking during development: ensure dispatch count\n\t\t * matches cumulative interrupt counter init value sums.\n\t\t */\n\t\tthr->heap->inst_count_exec++;\n#endif\n\n#if defined(DUK_USE_ASSERTIONS) || defined(DUK_USE_DEBUG)\n\t\t{\n\t\t\tduk_activation *act;\n\t\t\tact = thr->callstack_curr;\n\t\t\tDUK_ASSERT(curr_pc >= DUK_HCOMPFUNC_GET_CODE_BASE(thr->heap, DUK__FUN()));\n\t\t\tDUK_ASSERT(curr_pc < DUK_HCOMPFUNC_GET_CODE_END(thr->heap, DUK__FUN()));\n\t\t\tDUK_UNREF(act);  /* if debugging disabled */\n\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"executing bytecode: pc=%ld, ins=0x%08lx, op=%ld, valstack_top=%ld/%ld, nregs=%ld  -->  %!I\",\n\t\t\t                     (long) (curr_pc - DUK_HCOMPFUNC_GET_CODE_BASE(thr->heap, DUK__FUN())),\n\t\t\t                     (unsigned long) *curr_pc,\n\t\t\t                     (long) DUK_DEC_OP(*curr_pc),\n\t\t\t                     (long) (thr->valstack_top - thr->valstack),\n\t\t\t                     (long) (thr->valstack_end - thr->valstack),\n\t\t\t                     (long) (DUK__FUN() ? DUK__FUN()->nregs : -1),\n\t\t\t                     (duk_instr_t) *curr_pc));\n\t\t}\n#endif\n\n#if defined(DUK_USE_ASSERTIONS)\n\t\t/* Quite heavy assert: check valstack policy.  Improper\n\t\t * shuffle instructions can write beyond valstack_top/end\n\t\t * so this check catches them in the act.\n\t\t */\n\t\t{\n\t\t\tduk_tval *tv;\n\t\t\ttv = thr->valstack_top;\n\t\t\twhile (tv != thr->valstack_end) {\n\t\t\t\tDUK_ASSERT(DUK_TVAL_IS_UNDEFINED(tv));\n\t\t\t\ttv++;\n\t\t\t}\n\t\t}\n#endif\n\n\t\tins = *curr_pc++;\n\t\tDUK_STATS_INC(thr->heap, stats_exec_opcodes);\n\n\t\t/* Typing: use duk_small_(u)int_fast_t when decoding small\n\t\t * opcode fields (op, A, B, C, BC) which fit into 16 bits\n\t\t * and duk_(u)int_fast_t when decoding larger fields (e.g.\n\t\t * ABC).  Use unsigned variant by default, signed when the\n\t\t * value is used in signed arithmetic.  Using variable names\n\t\t * such as 'a', 'b', 'c', 'bc', etc makes it easier to spot\n\t\t * typing mismatches.\n\t\t */\n\n\t\t/* Switch based on opcode.  Cast to 8-bit unsigned value and\n\t\t * use a fully populated case clauses so that the compiler\n\t\t * will (at least usually) omit a bounds check.\n\t\t */\n\t\top = (duk_uint8_t) DUK_DEC_OP(ins);\n\t\tswitch (op) {\n\n\t\t/* Some useful macros.  These access inner executor variables\n\t\t * directly so they only apply within the executor.\n\t\t */\n#if defined(DUK_USE_EXEC_PREFER_SIZE)\n#define DUK__REPLACE_TOP_A_BREAK() { goto replace_top_a; }\n#define DUK__REPLACE_TOP_BC_BREAK() { goto replace_top_bc; }\n#define DUK__REPLACE_BOOL_A_BREAK(bval) { \\\n\t\tduk_bool_t duk__bval; \\\n\t\tduk__bval = (bval); \\\n\t\tDUK_ASSERT(duk__bval == 0 || duk__bval == 1); \\\n\t\tduk_push_boolean(thr, duk__bval); \\\n\t\tDUK__REPLACE_TOP_A_BREAK(); \\\n\t}\n#else\n#define DUK__REPLACE_TOP_A_BREAK() { DUK__REPLACE_TO_TVPTR(thr, DUK__REGP_A(ins)); break; }\n#define DUK__REPLACE_TOP_BC_BREAK() { DUK__REPLACE_TO_TVPTR(thr, DUK__REGP_BC(ins)); break; }\n#define DUK__REPLACE_BOOL_A_BREAK(bval) { \\\n\t\tduk_bool_t duk__bval; \\\n\t\tduk_tval *duk__tvdst; \\\n\t\tduk__bval = (bval); \\\n\t\tDUK_ASSERT(duk__bval == 0 || duk__bval == 1); \\\n\t\tduk__tvdst = DUK__REGP_A(ins); \\\n\t\tDUK_TVAL_SET_BOOLEAN_UPDREF(thr, duk__tvdst, duk__bval); \\\n\t\tbreak; \\\n\t}\n#endif\n\n\t\t/* XXX: 12 + 12 bit variant might make sense too, for both reg and\n\t\t * const loads.\n\t\t */\n\n\t\t/* For LDREG, STREG, LDCONST footprint optimized variants would just\n\t\t * duk_dup() + duk_replace(), but because they're used quite a lot\n\t\t * they're currently intentionally not size optimized.\n\t\t */\n\t\tcase DUK_OP_LDREG: {\n\t\t\tduk_tval *tv1, *tv2;\n\n\t\t\ttv1 = DUK__REGP_A(ins);\n\t\t\ttv2 = DUK__REGP_BC(ins);\n\t\t\tDUK_TVAL_SET_TVAL_UPDREF_FAST(thr, tv1, tv2);  /* side effects */\n\t\t\tbreak;\n\t\t}\n\n\t\tcase DUK_OP_STREG: {\n\t\t\tduk_tval *tv1, *tv2;\n\n\t\t\ttv1 = DUK__REGP_A(ins);\n\t\t\ttv2 = DUK__REGP_BC(ins);\n\t\t\tDUK_TVAL_SET_TVAL_UPDREF_FAST(thr, tv2, tv1);  /* side effects */\n\t\t\tbreak;\n\t\t}\n\n\t\tcase DUK_OP_LDCONST: {\n\t\t\tduk_tval *tv1, *tv2;\n\n\t\t\ttv1 = DUK__REGP_A(ins);\n\t\t\ttv2 = DUK__CONSTP_BC(ins);\n\t\t\tDUK_TVAL_SET_TVAL_UPDREF_FAST(thr, tv1, tv2);  /* side effects */\n\t\t\tbreak;\n\t\t}\n\n\t\t/* LDINT and LDINTX are intended to load an arbitrary signed\n\t\t * 32-bit value.  Only an LDINT+LDINTX sequence is supported.\n\t\t * This also guarantees all values remain fastints.\n\t\t */\n#if defined(DUK_USE_EXEC_PREFER_SIZE)\n\t\tcase DUK_OP_LDINT: {\n\t\t\tduk_int32_t val;\n\n\t\t\tval = (duk_int32_t) DUK_DEC_BC(ins) - (duk_int32_t) DUK_BC_LDINT_BIAS;\n\t\t\tduk_push_int(thr, val);\n\t\t\tDUK__REPLACE_TOP_A_BREAK();\n\t\t}\n\t\tcase DUK_OP_LDINTX: {\n\t\t\tduk_int32_t val;\n\n\t\t\tval = (duk_int32_t) duk_get_int(thr, DUK_DEC_A(ins));\n\t\t\tval = (val << DUK_BC_LDINTX_SHIFT) + (duk_int32_t) DUK_DEC_BC(ins);  /* no bias */\n\t\t\tduk_push_int(thr, val);\n\t\t\tDUK__REPLACE_TOP_A_BREAK();\n\t\t}\n#else  /* DUK_USE_EXEC_PREFER_SIZE */\n\t\tcase DUK_OP_LDINT: {\n\t\t\tduk_tval *tv1;\n\t\t\tduk_int32_t val;\n\n\t\t\tval = (duk_int32_t) DUK_DEC_BC(ins) - (duk_int32_t) DUK_BC_LDINT_BIAS;\n\t\t\ttv1 = DUK__REGP_A(ins);\n\t\t\tDUK_TVAL_SET_I32_UPDREF(thr, tv1, val);  /* side effects */\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_OP_LDINTX: {\n\t\t\tduk_tval *tv1;\n\t\t\tduk_int32_t val;\n\n\t\t\ttv1 = DUK__REGP_A(ins);\n\t\t\tDUK_ASSERT(DUK_TVAL_IS_NUMBER(tv1));\n#if defined(DUK_USE_FASTINT)\n\t\t\tDUK_ASSERT(DUK_TVAL_IS_FASTINT(tv1));\n\t\t\tval = DUK_TVAL_GET_FASTINT_I32(tv1);\n#else\n\t\t\t/* XXX: fast double-to-int conversion, we know number is integer in [-0x80000000,0xffffffff]. */\n\t\t\tval = (duk_int32_t) DUK_TVAL_GET_NUMBER(tv1);\n#endif\n\t\t\tval = (val << DUK_BC_LDINTX_SHIFT) + (duk_int32_t) DUK_DEC_BC(ins);  /* no bias */\n\t\t\tDUK_TVAL_SET_I32_UPDREF(thr, tv1, val);  /* side effects */\n\t\t\tbreak;\n\t\t}\n#endif  /* DUK_USE_EXEC_PREFER_SIZE */\n\n#if defined(DUK_USE_EXEC_PREFER_SIZE)\n\t\tcase DUK_OP_LDTHIS: {\n\t\t\tduk_push_this(thr);\n\t\t\tDUK__REPLACE_TOP_BC_BREAK();\n\t\t}\n\t\tcase DUK_OP_LDUNDEF: {\n\t\t\tduk_to_undefined(thr, (duk_idx_t) DUK_DEC_BC(ins));\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_OP_LDNULL: {\n\t\t\tduk_to_null(thr, (duk_idx_t) DUK_DEC_BC(ins));\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_OP_LDTRUE: {\n\t\t\tduk_push_true(thr);\n\t\t\tDUK__REPLACE_TOP_BC_BREAK();\n\t\t}\n\t\tcase DUK_OP_LDFALSE: {\n\t\t\tduk_push_false(thr);\n\t\t\tDUK__REPLACE_TOP_BC_BREAK();\n\t\t}\n#else  /* DUK_USE_EXEC_PREFER_SIZE */\n\t\tcase DUK_OP_LDTHIS: {\n\t\t\t/* Note: 'this' may be bound to any value, not just an object */\n\t\t\tduk_tval *tv1, *tv2;\n\n\t\t\ttv1 = DUK__REGP_BC(ins);\n\t\t\ttv2 = thr->valstack_bottom - 1;  /* 'this binding' is just under bottom */\n\t\t\tDUK_ASSERT(tv2 >= thr->valstack);\n\t\t\tDUK_TVAL_SET_TVAL_UPDREF_FAST(thr, tv1, tv2);  /* side effects */\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_OP_LDUNDEF: {\n\t\t\tduk_tval *tv1;\n\n\t\t\ttv1 = DUK__REGP_BC(ins);\n\t\t\tDUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv1);  /* side effects */\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_OP_LDNULL: {\n\t\t\tduk_tval *tv1;\n\n\t\t\ttv1 = DUK__REGP_BC(ins);\n\t\t\tDUK_TVAL_SET_NULL_UPDREF(thr, tv1);  /* side effects */\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_OP_LDTRUE: {\n\t\t\tduk_tval *tv1;\n\n\t\t\ttv1 = DUK__REGP_BC(ins);\n\t\t\tDUK_TVAL_SET_BOOLEAN_UPDREF(thr, tv1, 1);  /* side effects */\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_OP_LDFALSE: {\n\t\t\tduk_tval *tv1;\n\n\t\t\ttv1 = DUK__REGP_BC(ins);\n\t\t\tDUK_TVAL_SET_BOOLEAN_UPDREF(thr, tv1, 0);  /* side effects */\n\t\t\tbreak;\n\t\t}\n#endif  /* DUK_USE_EXEC_PREFER_SIZE */\n\n\t\tcase DUK_OP_BNOT: {\n\t\t\tduk__vm_bitwise_not(thr, DUK_DEC_BC(ins), DUK_DEC_A(ins));\n\t\t\tbreak;\n\t\t}\n\n\t\tcase DUK_OP_LNOT: {\n\t\t\tduk__vm_logical_not(thr, DUK_DEC_BC(ins), DUK_DEC_A(ins));\n\t\t\tbreak;\n\t\t}\n\n#if defined(DUK_USE_EXEC_PREFER_SIZE)\n\t\tcase DUK_OP_UNM:\n\t\tcase DUK_OP_UNP: {\n\t\t\tduk__vm_arith_unary_op(thr, DUK_DEC_BC(ins), DUK_DEC_A(ins), op);\n\t\t\tbreak;\n\t\t}\n#else  /* DUK_USE_EXEC_PREFER_SIZE */\n\t\tcase DUK_OP_UNM: {\n\t\t\tduk__vm_arith_unary_op(thr, DUK_DEC_BC(ins), DUK_DEC_A(ins), DUK_OP_UNM);\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_OP_UNP: {\n\t\t\tduk__vm_arith_unary_op(thr, DUK_DEC_BC(ins), DUK_DEC_A(ins), DUK_OP_UNP);\n\t\t\tbreak;\n\t\t}\n#endif  /* DUK_USE_EXEC_PREFER_SIZE */\n\n#if defined(DUK_USE_EXEC_PREFER_SIZE)\n\t\tcase DUK_OP_TYPEOF: {\n\t\t\tduk_small_uint_t stridx;\n\n\t\t\tstridx = duk_js_typeof_stridx(DUK__REGP_BC(ins));\n\t\t\tDUK_ASSERT_STRIDX_VALID(stridx);\n\t\t\tduk_push_hstring_stridx(thr, stridx);\n\t\t\tDUK__REPLACE_TOP_A_BREAK();\n\t\t}\n#else  /* DUK_USE_EXEC_PREFER_SIZE */\n\t\tcase DUK_OP_TYPEOF: {\n\t\t\tduk_tval *tv;\n\t\t\tduk_small_uint_t stridx;\n\t\t\tduk_hstring *h_str;\n\n\t\t\ttv = DUK__REGP_BC(ins);\n\t\t\tstridx = duk_js_typeof_stridx(tv);\n\t\t\tDUK_ASSERT_STRIDX_VALID(stridx);\n\t\t\th_str = DUK_HTHREAD_GET_STRING(thr, stridx);\n\t\t\ttv = DUK__REGP_A(ins);\n\t\t\tDUK_TVAL_SET_STRING_UPDREF(thr, tv, h_str);\n\t\t\tbreak;\n\t\t}\n#endif  /* DUK_USE_EXEC_PREFER_SIZE */\n\n\t\tcase DUK_OP_TYPEOFID: {\n\t\t\tduk_small_uint_t stridx;\n#if !defined(DUK_USE_EXEC_PREFER_SIZE)\n\t\t\tduk_hstring *h_str;\n#endif\n\t\t\tduk_activation *act;\n\t\t\tduk_hstring *name;\n\t\t\tduk_tval *tv;\n\n\t\t\t/* A -> target register\n\t\t\t * BC -> constant index of identifier name\n\t\t\t */\n\n\t\t\ttv = DUK__CONSTP_BC(ins);\n\t\t\tDUK_ASSERT(DUK_TVAL_IS_STRING(tv));\n\t\t\tname = DUK_TVAL_GET_STRING(tv);\n\t\t\ttv = NULL;  /* lookup has side effects */\n\t\t\tact = thr->callstack_curr;\n\t\t\tif (duk_js_getvar_activation(thr, act, name, 0 /*throw*/)) {\n\t\t\t\t/* -> [... val this] */\n\t\t\t\ttv = DUK_GET_TVAL_NEGIDX(thr, -2);\n\t\t\t\tstridx = duk_js_typeof_stridx(tv);\n\t\t\t\ttv = NULL;  /* no longer needed */\n\t\t\t\tduk_pop_2_unsafe(thr);\n\t\t\t} else {\n\t\t\t\t/* unresolvable, no stack changes */\n\t\t\t\tstridx = DUK_STRIDX_LC_UNDEFINED;\n\t\t\t}\n\t\t\tDUK_ASSERT_STRIDX_VALID(stridx);\n#if defined(DUK_USE_EXEC_PREFER_SIZE)\n\t\t\tduk_push_hstring_stridx(thr, stridx);\n\t\t\tDUK__REPLACE_TOP_A_BREAK();\n#else  /* DUK_USE_EXEC_PREFER_SIZE */\n\t\t\th_str = DUK_HTHREAD_GET_STRING(thr, stridx);\n\t\t\ttv = DUK__REGP_A(ins);\n\t\t\tDUK_TVAL_SET_STRING_UPDREF(thr, tv, h_str);\n\t\t\tbreak;\n#endif  /* DUK_USE_EXEC_PREFER_SIZE */\n\t\t}\n\n\t\t/* Equality: E5 Sections 11.9.1, 11.9.3 */\n\n#define DUK__EQ_BODY(barg,carg) { \\\n\t\tduk_bool_t tmp; \\\n\t\ttmp = duk_js_equals(thr, (barg), (carg)); \\\n\t\tDUK_ASSERT(tmp == 0 || tmp == 1); \\\n\t\tDUK__REPLACE_BOOL_A_BREAK(tmp); \\\n\t}\n#define DUK__NEQ_BODY(barg,carg) { \\\n\t\tduk_bool_t tmp; \\\n\t\ttmp = duk_js_equals(thr, (barg), (carg)); \\\n\t\tDUK_ASSERT(tmp == 0 || tmp == 1); \\\n\t\ttmp ^= 1; \\\n\t\tDUK__REPLACE_BOOL_A_BREAK(tmp); \\\n\t}\n#define DUK__SEQ_BODY(barg,carg) { \\\n\t\tduk_bool_t tmp; \\\n\t\ttmp = duk_js_strict_equals((barg), (carg)); \\\n\t\tDUK_ASSERT(tmp == 0 || tmp == 1); \\\n\t\tDUK__REPLACE_BOOL_A_BREAK(tmp); \\\n\t}\n#define DUK__SNEQ_BODY(barg,carg) { \\\n\t\tduk_bool_t tmp; \\\n\t\ttmp = duk_js_strict_equals((barg), (carg)); \\\n\t\tDUK_ASSERT(tmp == 0 || tmp == 1); \\\n\t\ttmp ^= 1; \\\n\t\tDUK__REPLACE_BOOL_A_BREAK(tmp); \\\n\t}\n#if defined(DUK_USE_EXEC_PREFER_SIZE)\n\t\tcase DUK_OP_EQ_RR:\n\t\tcase DUK_OP_EQ_CR:\n\t\tcase DUK_OP_EQ_RC:\n\t\tcase DUK_OP_EQ_CC:\n\t\t\tDUK__EQ_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));\n\t\tcase DUK_OP_NEQ_RR:\n\t\tcase DUK_OP_NEQ_CR:\n\t\tcase DUK_OP_NEQ_RC:\n\t\tcase DUK_OP_NEQ_CC:\n\t\t\tDUK__NEQ_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));\n\t\tcase DUK_OP_SEQ_RR:\n\t\tcase DUK_OP_SEQ_CR:\n\t\tcase DUK_OP_SEQ_RC:\n\t\tcase DUK_OP_SEQ_CC:\n\t\t\tDUK__SEQ_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));\n\t\tcase DUK_OP_SNEQ_RR:\n\t\tcase DUK_OP_SNEQ_CR:\n\t\tcase DUK_OP_SNEQ_RC:\n\t\tcase DUK_OP_SNEQ_CC:\n\t\t\tDUK__SNEQ_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));\n#else  /* DUK_USE_EXEC_PREFER_SIZE */\n\t\tcase DUK_OP_EQ_RR:\n\t\t\tDUK__EQ_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));\n\t\tcase DUK_OP_EQ_CR:\n\t\t\tDUK__EQ_BODY(DUK__CONSTP_B(ins), DUK__REGP_C(ins));\n\t\tcase DUK_OP_EQ_RC:\n\t\t\tDUK__EQ_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));\n\t\tcase DUK_OP_EQ_CC:\n\t\t\tDUK__EQ_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));\n\t\tcase DUK_OP_NEQ_RR:\n\t\t\tDUK__NEQ_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));\n\t\tcase DUK_OP_NEQ_CR:\n\t\t\tDUK__NEQ_BODY(DUK__CONSTP_B(ins), DUK__REGP_C(ins));\n\t\tcase DUK_OP_NEQ_RC:\n\t\t\tDUK__NEQ_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));\n\t\tcase DUK_OP_NEQ_CC:\n\t\t\tDUK__NEQ_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));\n\t\tcase DUK_OP_SEQ_RR:\n\t\t\tDUK__SEQ_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));\n\t\tcase DUK_OP_SEQ_CR:\n\t\t\tDUK__SEQ_BODY(DUK__CONSTP_B(ins), DUK__REGP_C(ins));\n\t\tcase DUK_OP_SEQ_RC:\n\t\t\tDUK__SEQ_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));\n\t\tcase DUK_OP_SEQ_CC:\n\t\t\tDUK__SEQ_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));\n\t\tcase DUK_OP_SNEQ_RR:\n\t\t\tDUK__SNEQ_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));\n\t\tcase DUK_OP_SNEQ_CR:\n\t\t\tDUK__SNEQ_BODY(DUK__CONSTP_B(ins), DUK__REGP_C(ins));\n\t\tcase DUK_OP_SNEQ_RC:\n\t\t\tDUK__SNEQ_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));\n\t\tcase DUK_OP_SNEQ_CC:\n\t\t\tDUK__SNEQ_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));\n#endif  /* DUK_USE_EXEC_PREFER_SIZE */\n\n#define DUK__COMPARE_BODY(arg1,arg2,flags) { \\\n\t\tduk_bool_t tmp; \\\n\t\ttmp = duk_js_compare_helper(thr, (arg1), (arg2), (flags)); \\\n\t\tDUK_ASSERT(tmp == 0 || tmp == 1); \\\n\t\tDUK__REPLACE_BOOL_A_BREAK(tmp); \\\n\t}\n#define DUK__GT_BODY(barg,carg) DUK__COMPARE_BODY((carg), (barg), 0)\n#define DUK__GE_BODY(barg,carg) DUK__COMPARE_BODY((barg), (carg), DUK_COMPARE_FLAG_EVAL_LEFT_FIRST | DUK_COMPARE_FLAG_NEGATE)\n#define DUK__LT_BODY(barg,carg) DUK__COMPARE_BODY((barg), (carg), DUK_COMPARE_FLAG_EVAL_LEFT_FIRST)\n#define DUK__LE_BODY(barg,carg) DUK__COMPARE_BODY((carg), (barg), DUK_COMPARE_FLAG_NEGATE)\n#if defined(DUK_USE_EXEC_PREFER_SIZE)\n\t\tcase DUK_OP_GT_RR:\n\t\tcase DUK_OP_GT_CR:\n\t\tcase DUK_OP_GT_RC:\n\t\tcase DUK_OP_GT_CC:\n\t\t\tDUK__GT_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));\n\t\tcase DUK_OP_GE_RR:\n\t\tcase DUK_OP_GE_CR:\n\t\tcase DUK_OP_GE_RC:\n\t\tcase DUK_OP_GE_CC:\n\t\t\tDUK__GE_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));\n\t\tcase DUK_OP_LT_RR:\n\t\tcase DUK_OP_LT_CR:\n\t\tcase DUK_OP_LT_RC:\n\t\tcase DUK_OP_LT_CC:\n\t\t\tDUK__LT_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));\n\t\tcase DUK_OP_LE_RR:\n\t\tcase DUK_OP_LE_CR:\n\t\tcase DUK_OP_LE_RC:\n\t\tcase DUK_OP_LE_CC:\n\t\t\tDUK__LE_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));\n#else  /* DUK_USE_EXEC_PREFER_SIZE */\n\t\tcase DUK_OP_GT_RR:\n\t\t\tDUK__GT_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));\n\t\tcase DUK_OP_GT_CR:\n\t\t\tDUK__GT_BODY(DUK__CONSTP_B(ins), DUK__REGP_C(ins));\n\t\tcase DUK_OP_GT_RC:\n\t\t\tDUK__GT_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));\n\t\tcase DUK_OP_GT_CC:\n\t\t\tDUK__GT_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));\n\t\tcase DUK_OP_GE_RR:\n\t\t\tDUK__GE_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));\n\t\tcase DUK_OP_GE_CR:\n\t\t\tDUK__GE_BODY(DUK__CONSTP_B(ins), DUK__REGP_C(ins));\n\t\tcase DUK_OP_GE_RC:\n\t\t\tDUK__GE_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));\n\t\tcase DUK_OP_GE_CC:\n\t\t\tDUK__GE_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));\n\t\tcase DUK_OP_LT_RR:\n\t\t\tDUK__LT_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));\n\t\tcase DUK_OP_LT_CR:\n\t\t\tDUK__LT_BODY(DUK__CONSTP_B(ins), DUK__REGP_C(ins));\n\t\tcase DUK_OP_LT_RC:\n\t\t\tDUK__LT_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));\n\t\tcase DUK_OP_LT_CC:\n\t\t\tDUK__LT_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));\n\t\tcase DUK_OP_LE_RR:\n\t\t\tDUK__LE_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));\n\t\tcase DUK_OP_LE_CR:\n\t\t\tDUK__LE_BODY(DUK__CONSTP_B(ins), DUK__REGP_C(ins));\n\t\tcase DUK_OP_LE_RC:\n\t\t\tDUK__LE_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));\n\t\tcase DUK_OP_LE_CC:\n\t\t\tDUK__LE_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));\n#endif  /* DUK_USE_EXEC_PREFER_SIZE */\n\n\t\t/* No size optimized variant at present for IF. */\n\t\tcase DUK_OP_IFTRUE_R: {\n\t\t\tif (duk_js_toboolean(DUK__REGP_BC(ins)) != 0) {\n\t\t\t\tcurr_pc++;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_OP_IFTRUE_C: {\n\t\t\tif (duk_js_toboolean(DUK__CONSTP_BC(ins)) != 0) {\n\t\t\t\tcurr_pc++;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_OP_IFFALSE_R: {\n\t\t\tif (duk_js_toboolean(DUK__REGP_BC(ins)) == 0) {\n\t\t\t\tcurr_pc++;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_OP_IFFALSE_C: {\n\t\t\tif (duk_js_toboolean(DUK__CONSTP_BC(ins)) == 0) {\n\t\t\t\tcurr_pc++;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\n#if defined(DUK_USE_EXEC_PREFER_SIZE)\n\t\tcase DUK_OP_ADD_RR:\n\t\tcase DUK_OP_ADD_CR:\n\t\tcase DUK_OP_ADD_RC:\n\t\tcase DUK_OP_ADD_CC: {\n\t\t\t/* XXX: could leave value on stack top and goto replace_top_a; */\n\t\t\tduk__vm_arith_add(thr, DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins), DUK_DEC_A(ins));\n\t\t\tbreak;\n\t\t}\n#else  /* DUK_USE_EXEC_PREFER_SIZE */\n\t\tcase DUK_OP_ADD_RR: {\n\t\t\tduk__vm_arith_add(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins));\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_OP_ADD_CR: {\n\t\t\tduk__vm_arith_add(thr, DUK__CONSTP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins));\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_OP_ADD_RC: {\n\t\t\tduk__vm_arith_add(thr, DUK__REGP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins));\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_OP_ADD_CC: {\n\t\t\tduk__vm_arith_add(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins));\n\t\t\tbreak;\n\t\t}\n#endif  /* DUK_USE_EXEC_PREFER_SIZE */\n\n#if defined(DUK_USE_EXEC_PREFER_SIZE)\n\t\tcase DUK_OP_SUB_RR:\n\t\tcase DUK_OP_SUB_CR:\n\t\tcase DUK_OP_SUB_RC:\n\t\tcase DUK_OP_SUB_CC:\n\t\tcase DUK_OP_MUL_RR:\n\t\tcase DUK_OP_MUL_CR:\n\t\tcase DUK_OP_MUL_RC:\n\t\tcase DUK_OP_MUL_CC:\n\t\tcase DUK_OP_DIV_RR:\n\t\tcase DUK_OP_DIV_CR:\n\t\tcase DUK_OP_DIV_RC:\n\t\tcase DUK_OP_DIV_CC:\n\t\tcase DUK_OP_MOD_RR:\n\t\tcase DUK_OP_MOD_CR:\n\t\tcase DUK_OP_MOD_RC:\n\t\tcase DUK_OP_MOD_CC:\n#if defined(DUK_USE_ES7_EXP_OPERATOR)\n\t\tcase DUK_OP_EXP_RR:\n\t\tcase DUK_OP_EXP_CR:\n\t\tcase DUK_OP_EXP_RC:\n\t\tcase DUK_OP_EXP_CC:\n#endif  /* DUK_USE_ES7_EXP_OPERATOR */\n\t\t{\n\t\t\t/* XXX: could leave value on stack top and goto replace_top_a; */\n\t\t\tduk__vm_arith_binary_op(thr, DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins), DUK_DEC_A(ins), op);\n\t\t\tbreak;\n\t\t}\n#else  /* DUK_USE_EXEC_PREFER_SIZE */\n\t\tcase DUK_OP_SUB_RR: {\n\t\t\tduk__vm_arith_binary_op(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_SUB);\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_OP_SUB_CR: {\n\t\t\tduk__vm_arith_binary_op(thr, DUK__CONSTP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_SUB);\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_OP_SUB_RC: {\n\t\t\tduk__vm_arith_binary_op(thr, DUK__REGP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_SUB);\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_OP_SUB_CC: {\n\t\t\tduk__vm_arith_binary_op(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_SUB);\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_OP_MUL_RR: {\n\t\t\tduk__vm_arith_binary_op(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_MUL);\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_OP_MUL_CR: {\n\t\t\tduk__vm_arith_binary_op(thr, DUK__CONSTP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_MUL);\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_OP_MUL_RC: {\n\t\t\tduk__vm_arith_binary_op(thr, DUK__REGP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_MUL);\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_OP_MUL_CC: {\n\t\t\tduk__vm_arith_binary_op(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_MUL);\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_OP_DIV_RR: {\n\t\t\tduk__vm_arith_binary_op(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_DIV);\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_OP_DIV_CR: {\n\t\t\tduk__vm_arith_binary_op(thr, DUK__CONSTP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_DIV);\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_OP_DIV_RC: {\n\t\t\tduk__vm_arith_binary_op(thr, DUK__REGP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_DIV);\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_OP_DIV_CC: {\n\t\t\tduk__vm_arith_binary_op(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_DIV);\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_OP_MOD_RR: {\n\t\t\tduk__vm_arith_binary_op(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_MOD);\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_OP_MOD_CR: {\n\t\t\tduk__vm_arith_binary_op(thr, DUK__CONSTP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_MOD);\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_OP_MOD_RC: {\n\t\t\tduk__vm_arith_binary_op(thr, DUK__REGP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_MOD);\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_OP_MOD_CC: {\n\t\t\tduk__vm_arith_binary_op(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_MOD);\n\t\t\tbreak;\n\t\t}\n#if defined(DUK_USE_ES7_EXP_OPERATOR)\n\t\tcase DUK_OP_EXP_RR: {\n\t\t\tduk__vm_arith_binary_op(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_EXP);\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_OP_EXP_CR: {\n\t\t\tduk__vm_arith_binary_op(thr, DUK__CONSTP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_EXP);\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_OP_EXP_RC: {\n\t\t\tduk__vm_arith_binary_op(thr, DUK__REGP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_EXP);\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_OP_EXP_CC: {\n\t\t\tduk__vm_arith_binary_op(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_EXP);\n\t\t\tbreak;\n\t\t}\n#endif  /* DUK_USE_ES7_EXP_OPERATOR */\n#endif  /* DUK_USE_EXEC_PREFER_SIZE */\n\n#if defined(DUK_USE_EXEC_PREFER_SIZE)\n\t\tcase DUK_OP_BAND_RR:\n\t\tcase DUK_OP_BAND_CR:\n\t\tcase DUK_OP_BAND_RC:\n\t\tcase DUK_OP_BAND_CC:\n\t\tcase DUK_OP_BOR_RR:\n\t\tcase DUK_OP_BOR_CR:\n\t\tcase DUK_OP_BOR_RC:\n\t\tcase DUK_OP_BOR_CC:\n\t\tcase DUK_OP_BXOR_RR:\n\t\tcase DUK_OP_BXOR_CR:\n\t\tcase DUK_OP_BXOR_RC:\n\t\tcase DUK_OP_BXOR_CC:\n\t\tcase DUK_OP_BASL_RR:\n\t\tcase DUK_OP_BASL_CR:\n\t\tcase DUK_OP_BASL_RC:\n\t\tcase DUK_OP_BASL_CC:\n\t\tcase DUK_OP_BLSR_RR:\n\t\tcase DUK_OP_BLSR_CR:\n\t\tcase DUK_OP_BLSR_RC:\n\t\tcase DUK_OP_BLSR_CC:\n\t\tcase DUK_OP_BASR_RR:\n\t\tcase DUK_OP_BASR_CR:\n\t\tcase DUK_OP_BASR_RC:\n\t\tcase DUK_OP_BASR_CC: {\n\t\t\t/* XXX: could leave value on stack top and goto replace_top_a; */\n\t\t\tduk__vm_bitwise_binary_op(thr, DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins), DUK_DEC_A(ins), op);\n\t\t\tbreak;\n\t\t}\n#else  /* DUK_USE_EXEC_PREFER_SIZE */\n\t\tcase DUK_OP_BAND_RR: {\n\t\t\tduk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BAND);\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_OP_BAND_CR: {\n\t\t\tduk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BAND);\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_OP_BAND_RC: {\n\t\t\tduk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BAND);\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_OP_BAND_CC: {\n\t\t\tduk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BAND);\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_OP_BOR_RR: {\n\t\t\tduk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BOR);\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_OP_BOR_CR: {\n\t\t\tduk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BOR);\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_OP_BOR_RC: {\n\t\t\tduk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BOR);\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_OP_BOR_CC: {\n\t\t\tduk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BOR);\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_OP_BXOR_RR: {\n\t\t\tduk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BXOR);\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_OP_BXOR_CR: {\n\t\t\tduk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BXOR);\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_OP_BXOR_RC: {\n\t\t\tduk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BXOR);\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_OP_BXOR_CC: {\n\t\t\tduk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BXOR);\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_OP_BASL_RR: {\n\t\t\tduk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BASL);\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_OP_BASL_CR: {\n\t\t\tduk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BASL);\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_OP_BASL_RC: {\n\t\t\tduk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BASL);\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_OP_BASL_CC: {\n\t\t\tduk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BASL);\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_OP_BLSR_RR: {\n\t\t\tduk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BLSR);\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_OP_BLSR_CR: {\n\t\t\tduk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BLSR);\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_OP_BLSR_RC: {\n\t\t\tduk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BLSR);\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_OP_BLSR_CC: {\n\t\t\tduk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BLSR);\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_OP_BASR_RR: {\n\t\t\tduk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BASR);\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_OP_BASR_CR: {\n\t\t\tduk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BASR);\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_OP_BASR_RC: {\n\t\t\tduk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BASR);\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_OP_BASR_CC: {\n\t\t\tduk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BASR);\n\t\t\tbreak;\n\t\t}\n#endif  /* DUK_USE_EXEC_PREFER_SIZE */\n\n\t\t/* For INSTOF and IN, B is always a register. */\n#define DUK__INSTOF_BODY(barg,carg) { \\\n\t\tduk_bool_t tmp; \\\n\t\ttmp = duk_js_instanceof(thr, (barg), (carg)); \\\n\t\tDUK_ASSERT(tmp == 0 || tmp == 1); \\\n\t\tDUK__REPLACE_BOOL_A_BREAK(tmp); \\\n\t}\n#define DUK__IN_BODY(barg,carg) { \\\n\t\tduk_bool_t tmp; \\\n\t\ttmp = duk_js_in(thr, (barg), (carg)); \\\n\t\tDUK_ASSERT(tmp == 0 || tmp == 1); \\\n\t\tDUK__REPLACE_BOOL_A_BREAK(tmp); \\\n\t}\n#if defined(DUK_USE_EXEC_PREFER_SIZE)\n\t\tcase DUK_OP_INSTOF_RR:\n\t\tcase DUK_OP_INSTOF_CR:\n\t\tcase DUK_OP_INSTOF_RC:\n\t\tcase DUK_OP_INSTOF_CC:\n\t\t\tDUK__INSTOF_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));\n\t\tcase DUK_OP_IN_RR:\n\t\tcase DUK_OP_IN_CR:\n\t\tcase DUK_OP_IN_RC:\n\t\tcase DUK_OP_IN_CC:\n\t\t\tDUK__IN_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));\n#else  /* DUK_USE_EXEC_PREFER_SIZE */\n\t\tcase DUK_OP_INSTOF_RR:\n\t\t\tDUK__INSTOF_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));\n\t\tcase DUK_OP_INSTOF_CR:\n\t\t\tDUK__INSTOF_BODY(DUK__CONSTP_B(ins), DUK__REGP_C(ins));\n\t\tcase DUK_OP_INSTOF_RC:\n\t\t\tDUK__INSTOF_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));\n\t\tcase DUK_OP_INSTOF_CC:\n\t\t\tDUK__INSTOF_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));\n\t\tcase DUK_OP_IN_RR:\n\t\t\tDUK__IN_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));\n\t\tcase DUK_OP_IN_CR:\n\t\t\tDUK__IN_BODY(DUK__CONSTP_B(ins), DUK__REGP_C(ins));\n\t\tcase DUK_OP_IN_RC:\n\t\t\tDUK__IN_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));\n\t\tcase DUK_OP_IN_CC:\n\t\t\tDUK__IN_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));\n#endif  /* DUK_USE_EXEC_PREFER_SIZE */\n\n\t\t/* Pre/post inc/dec for register variables, important for loops. */\n#if defined(DUK_USE_EXEC_PREFER_SIZE)\n\t\tcase DUK_OP_PREINCR:\n\t\tcase DUK_OP_PREDECR:\n\t\tcase DUK_OP_POSTINCR:\n\t\tcase DUK_OP_POSTDECR: {\n\t\t\tduk__prepost_incdec_reg_helper(thr, DUK__REGP_A(ins), DUK__REGP_BC(ins), op);\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_OP_PREINCV:\n\t\tcase DUK_OP_PREDECV:\n\t\tcase DUK_OP_POSTINCV:\n\t\tcase DUK_OP_POSTDECV: {\n\t\t\tduk__prepost_incdec_var_helper(thr, DUK_DEC_A(ins), DUK__CONSTP_BC(ins), op, DUK__STRICT());\n\t\t\tbreak;\n\t\t}\n#else  /* DUK_USE_EXEC_PREFER_SIZE */\n\t\tcase DUK_OP_PREINCR: {\n\t\t\tduk__prepost_incdec_reg_helper(thr, DUK__REGP_A(ins), DUK__REGP_BC(ins), DUK_OP_PREINCR);\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_OP_PREDECR: {\n\t\t\tduk__prepost_incdec_reg_helper(thr, DUK__REGP_A(ins), DUK__REGP_BC(ins), DUK_OP_PREDECR);\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_OP_POSTINCR: {\n\t\t\tduk__prepost_incdec_reg_helper(thr, DUK__REGP_A(ins), DUK__REGP_BC(ins), DUK_OP_POSTINCR);\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_OP_POSTDECR: {\n\t\t\tduk__prepost_incdec_reg_helper(thr, DUK__REGP_A(ins), DUK__REGP_BC(ins), DUK_OP_POSTDECR);\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_OP_PREINCV: {\n\t\t\tduk__prepost_incdec_var_helper(thr, DUK_DEC_A(ins), DUK__CONSTP_BC(ins), DUK_OP_PREINCV, DUK__STRICT());\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_OP_PREDECV: {\n\t\t\tduk__prepost_incdec_var_helper(thr, DUK_DEC_A(ins), DUK__CONSTP_BC(ins), DUK_OP_PREDECV, DUK__STRICT());\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_OP_POSTINCV: {\n\t\t\tduk__prepost_incdec_var_helper(thr, DUK_DEC_A(ins), DUK__CONSTP_BC(ins), DUK_OP_POSTINCV, DUK__STRICT());\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_OP_POSTDECV: {\n\t\t\tduk__prepost_incdec_var_helper(thr, DUK_DEC_A(ins), DUK__CONSTP_BC(ins), DUK_OP_POSTDECV, DUK__STRICT());\n\t\t\tbreak;\n\t\t}\n#endif  /* DUK_USE_EXEC_PREFER_SIZE */\n\n\t\t/* XXX: Move to separate helper, optimize for perf/size separately. */\n\t\t/* Preinc/predec for object properties. */\n\t\tcase DUK_OP_PREINCP_RR:\n\t\tcase DUK_OP_PREINCP_CR:\n\t\tcase DUK_OP_PREINCP_RC:\n\t\tcase DUK_OP_PREINCP_CC:\n\t\tcase DUK_OP_PREDECP_RR:\n\t\tcase DUK_OP_PREDECP_CR:\n\t\tcase DUK_OP_PREDECP_RC:\n\t\tcase DUK_OP_PREDECP_CC:\n\t\tcase DUK_OP_POSTINCP_RR:\n\t\tcase DUK_OP_POSTINCP_CR:\n\t\tcase DUK_OP_POSTINCP_RC:\n\t\tcase DUK_OP_POSTINCP_CC:\n\t\tcase DUK_OP_POSTDECP_RR:\n\t\tcase DUK_OP_POSTDECP_CR:\n\t\tcase DUK_OP_POSTDECP_RC:\n\t\tcase DUK_OP_POSTDECP_CC: {\n\t\t\tduk_tval *tv_obj;\n\t\t\tduk_tval *tv_key;\n\t\t\tduk_tval *tv_val;\n\t\t\tduk_bool_t rc;\n\t\t\tduk_double_t x, y, z;\n#if !defined(DUK_USE_EXEC_PREFER_SIZE)\n\t\t\tduk_tval *tv_dst;\n#endif  /* DUK_USE_EXEC_PREFER_SIZE */\n\n\t\t\t/* A -> target reg\n\t\t\t * B -> object reg/const (may be const e.g. in \"'foo'[1]\")\n\t\t\t * C -> key reg/const\n\t\t\t */\n\n\t\t\t/* Opcode bits 0-1 are used to distinguish reg/const variants.\n\t\t\t * Opcode bits 2-3 are used to distinguish inc/dec variants:\n\t\t\t * Bit 2 = inc(0)/dec(1), bit 3 = pre(0)/post(1).\n\t\t\t */\n\t\t\tDUK_ASSERT((DUK_OP_PREINCP_RR & 0x0c) == 0x00);\n\t\t\tDUK_ASSERT((DUK_OP_PREDECP_RR & 0x0c) == 0x04);\n\t\t\tDUK_ASSERT((DUK_OP_POSTINCP_RR & 0x0c) == 0x08);\n\t\t\tDUK_ASSERT((DUK_OP_POSTDECP_RR & 0x0c) == 0x0c);\n\n\t\t\ttv_obj = DUK__REGCONSTP_B(ins);\n\t\t\ttv_key = DUK__REGCONSTP_C(ins);\n\t\t\trc = duk_hobject_getprop(thr, tv_obj, tv_key);  /* -> [val] */\n\t\t\tDUK_UNREF(rc);  /* ignore */\n\t\t\ttv_obj = NULL;  /* invalidated */\n\t\t\ttv_key = NULL;  /* invalidated */\n\n\t\t\t/* XXX: Fastint fast path would be useful here.  Also fastints\n\t\t\t * now lose their fastint status in current handling which is\n\t\t\t * not intuitive.\n\t\t\t */\n\n\t\t\tx = duk_to_number_m1(thr);\n\t\t\tduk_pop_unsafe(thr);\n\t\t\tif (ins & DUK_BC_INCDECP_FLAG_DEC) {\n\t\t\t\ty = x - 1.0;\n\t\t\t} else {\n\t\t\t\ty = x + 1.0;\n\t\t\t}\n\n\t\t\tduk_push_number(thr, y);\n\t\t\ttv_val = DUK_GET_TVAL_NEGIDX(thr, -1);\n\t\t\tDUK_ASSERT(tv_val != NULL);\n\t\t\ttv_obj = DUK__REGCONSTP_B(ins);\n\t\t\ttv_key = DUK__REGCONSTP_C(ins);\n\t\t\trc = duk_hobject_putprop(thr, tv_obj, tv_key, tv_val, DUK__STRICT());\n\t\t\tDUK_UNREF(rc);  /* ignore */\n\t\t\ttv_obj = NULL;  /* invalidated */\n\t\t\ttv_key = NULL;  /* invalidated */\n\t\t\tduk_pop_unsafe(thr);\n\n\t\t\tz = (ins & DUK_BC_INCDECP_FLAG_POST) ? x : y;\n#if defined(DUK_USE_EXEC_PREFER_SIZE)\n\t\t\tduk_push_number(thr, z);\n\t\t\tDUK__REPLACE_TOP_A_BREAK();\n#else\n\t\t\ttv_dst = DUK__REGP_A(ins);\n\t\t\tDUK_TVAL_SET_NUMBER_UPDREF(thr, tv_dst, z);\n\t\t\tbreak;\n#endif\n\t\t}\n\n\t\t/* XXX: GETPROP where object is 'this', GETPROPT?\n\t\t * Occurs relatively often in object oriented code.\n\t\t */\n\n#define DUK__GETPROP_BODY(barg,carg) { \\\n\t\t/* A -> target reg \\\n\t\t * B -> object reg/const (may be const e.g. in \"'foo'[1]\") \\\n\t\t * C -> key reg/const \\\n\t\t */ \\\n\t\t(void) duk_hobject_getprop(thr, (barg), (carg)); \\\n\t\tDUK__REPLACE_TOP_A_BREAK(); \\\n\t}\n#define DUK__GETPROPC_BODY(barg,carg) { \\\n\t\t/* Same as GETPROP but callability check for property-based calls. */ \\\n\t\tduk_tval *tv__targ; \\\n\t\t(void) duk_hobject_getprop(thr, (barg), (carg)); \\\n\t\tDUK_GC_TORTURE(thr->heap); \\\n\t\ttv__targ = DUK_GET_TVAL_NEGIDX(thr, -1); \\\n\t\tif (DUK_UNLIKELY(!duk_is_callable_tval(thr, tv__targ))) { \\\n\t\t\t/* Here we intentionally re-evaluate the macro \\\n\t\t\t * arguments to deal with potentially changed \\\n\t\t\t * valstack base pointer! \\\n\t\t\t */ \\\n\t\t\tduk_call_setup_propcall_error(thr, tv__targ, (barg), (carg)); \\\n\t\t} \\\n\t\tDUK__REPLACE_TOP_A_BREAK(); \\\n\t}\n#define DUK__PUTPROP_BODY(aarg,barg,carg) { \\\n\t\t/* A -> object reg \\\n\t\t * B -> key reg/const \\\n\t\t * C -> value reg/const \\\n\t\t * \\\n\t\t * Note: intentional difference to register arrangement \\\n\t\t * of e.g. GETPROP; 'A' must contain a register-only value. \\\n\t\t */ \\\n\t\t(void) duk_hobject_putprop(thr, (aarg), (barg), (carg), DUK__STRICT()); \\\n\t\tbreak; \\\n\t}\n#define DUK__DELPROP_BODY(barg,carg) { \\\n\t\t/* A -> result reg \\\n\t\t * B -> object reg \\\n\t\t * C -> key reg/const \\\n\t\t */ \\\n\t\tduk_bool_t rc; \\\n\t\trc = duk_hobject_delprop(thr, (barg), (carg), DUK__STRICT()); \\\n\t\tDUK_ASSERT(rc == 0 || rc == 1); \\\n\t\tDUK__REPLACE_BOOL_A_BREAK(rc); \\\n\t}\n#if defined(DUK_USE_EXEC_PREFER_SIZE)\n\t\tcase DUK_OP_GETPROP_RR:\n\t\tcase DUK_OP_GETPROP_CR:\n\t\tcase DUK_OP_GETPROP_RC:\n\t\tcase DUK_OP_GETPROP_CC:\n\t\t\tDUK__GETPROP_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));\n#if defined(DUK_USE_VERBOSE_ERRORS)\n\t\tcase DUK_OP_GETPROPC_RR:\n\t\tcase DUK_OP_GETPROPC_CR:\n\t\tcase DUK_OP_GETPROPC_RC:\n\t\tcase DUK_OP_GETPROPC_CC:\n\t\t\tDUK__GETPROPC_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));\n#endif\n\t\tcase DUK_OP_PUTPROP_RR:\n\t\tcase DUK_OP_PUTPROP_CR:\n\t\tcase DUK_OP_PUTPROP_RC:\n\t\tcase DUK_OP_PUTPROP_CC:\n\t\t\tDUK__PUTPROP_BODY(DUK__REGP_A(ins), DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));\n\t\tcase DUK_OP_DELPROP_RR:\n\t\tcase DUK_OP_DELPROP_RC:  /* B is always reg */\n\t\t\tDUK__DELPROP_BODY(DUK__REGP_B(ins), DUK__REGCONSTP_C(ins));\n#else  /* DUK_USE_EXEC_PREFER_SIZE */\n\t\tcase DUK_OP_GETPROP_RR:\n\t\t\tDUK__GETPROP_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));\n\t\tcase DUK_OP_GETPROP_CR:\n\t\t\tDUK__GETPROP_BODY(DUK__CONSTP_B(ins), DUK__REGP_C(ins));\n\t\tcase DUK_OP_GETPROP_RC:\n\t\t\tDUK__GETPROP_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));\n\t\tcase DUK_OP_GETPROP_CC:\n\t\t\tDUK__GETPROP_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));\n#if defined(DUK_USE_VERBOSE_ERRORS)\n\t\tcase DUK_OP_GETPROPC_RR:\n\t\t\tDUK__GETPROPC_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));\n\t\tcase DUK_OP_GETPROPC_CR:\n\t\t\tDUK__GETPROPC_BODY(DUK__CONSTP_B(ins), DUK__REGP_C(ins));\n\t\tcase DUK_OP_GETPROPC_RC:\n\t\t\tDUK__GETPROPC_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));\n\t\tcase DUK_OP_GETPROPC_CC:\n\t\t\tDUK__GETPROPC_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));\n#endif\n\t\tcase DUK_OP_PUTPROP_RR:\n\t\t\tDUK__PUTPROP_BODY(DUK__REGP_A(ins), DUK__REGP_B(ins), DUK__REGP_C(ins));\n\t\tcase DUK_OP_PUTPROP_CR:\n\t\t\tDUK__PUTPROP_BODY(DUK__REGP_A(ins), DUK__CONSTP_B(ins), DUK__REGP_C(ins));\n\t\tcase DUK_OP_PUTPROP_RC:\n\t\t\tDUK__PUTPROP_BODY(DUK__REGP_A(ins), DUK__REGP_B(ins), DUK__CONSTP_C(ins));\n\t\tcase DUK_OP_PUTPROP_CC:\n\t\t\tDUK__PUTPROP_BODY(DUK__REGP_A(ins), DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));\n\t\tcase DUK_OP_DELPROP_RR:  /* B is always reg */\n\t\t\tDUK__DELPROP_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));\n\t\tcase DUK_OP_DELPROP_RC:\n\t\t\tDUK__DELPROP_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));\n#endif  /* DUK_USE_EXEC_PREFER_SIZE */\n\n\t\t/* No fast path for DECLVAR now, it's quite a rare instruction. */\n\t\tcase DUK_OP_DECLVAR_RR:\n\t\tcase DUK_OP_DECLVAR_CR:\n\t\tcase DUK_OP_DECLVAR_RC:\n\t\tcase DUK_OP_DECLVAR_CC: {\n\t\t\tduk_activation *act;\n\t\t\tduk_small_uint_fast_t a = DUK_DEC_A(ins);\n\t\t\tduk_tval *tv1;\n\t\t\tduk_hstring *name;\n\t\t\tduk_small_uint_t prop_flags;\n\t\t\tduk_bool_t is_func_decl;\n\n\t\t\ttv1 = DUK__REGCONSTP_B(ins);\n\t\t\tDUK_ASSERT(DUK_TVAL_IS_STRING(tv1));\n\t\t\tname = DUK_TVAL_GET_STRING(tv1);\n\t\t\tDUK_ASSERT(name != NULL);\n\n\t\t\tis_func_decl = ((a & DUK_BC_DECLVAR_FLAG_FUNC_DECL) != 0);\n\n\t\t\t/* XXX: declvar takes an duk_tval pointer, which is awkward and\n\t\t\t * should be reworked.\n\t\t\t */\n\n\t\t\t/* Compiler is responsible for selecting property flags (configurability,\n\t\t\t * writability, etc).\n\t\t\t */\n\t\t\tprop_flags = a & DUK_PROPDESC_FLAGS_MASK;\n\n\t\t\tif (is_func_decl) {\n\t\t\t\tduk_push_tval(thr, DUK__REGCONSTP_C(ins));\n\t\t\t} else {\n\t\t\t\tDUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top));  /* valstack policy */\n\t\t\t\tthr->valstack_top++;\n\t\t\t}\n\t\t\ttv1 = DUK_GET_TVAL_NEGIDX(thr, -1);\n\n\t\t\tact = thr->callstack_curr;\n\t\t\tif (duk_js_declvar_activation(thr, act, name, tv1, prop_flags, is_func_decl)) {\n\t\t\t\tif (is_func_decl) {\n\t\t\t\t\t/* Already declared, update value. */\n\t\t\t\t\ttv1 = DUK_GET_TVAL_NEGIDX(thr, -1);\n\t\t\t\t\tduk_js_putvar_activation(thr, act, name, tv1, DUK__STRICT());\n\t\t\t\t} else {\n\t\t\t\t\t/* Already declared but no initializer value\n\t\t\t\t\t * (e.g. 'var xyz;'), no-op.\n\t\t\t\t\t */\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tduk_pop_unsafe(thr);\n\t\t\tbreak;\n\t\t}\n\n#if defined(DUK_USE_REGEXP_SUPPORT)\n\t\t/* The compiler should never emit DUK_OP_REGEXP if there is no\n\t\t * regexp support.\n\t\t */\n\t\tcase DUK_OP_REGEXP_RR:\n\t\tcase DUK_OP_REGEXP_CR:\n\t\tcase DUK_OP_REGEXP_RC:\n\t\tcase DUK_OP_REGEXP_CC: {\n\t\t\t/* A -> target register\n\t\t\t * B -> bytecode (also contains flags)\n\t\t\t * C -> escaped source\n\t\t\t */\n\n\t\t\tduk_push_tval(thr, DUK__REGCONSTP_C(ins));\n\t\t\tduk_push_tval(thr, DUK__REGCONSTP_B(ins));  /* -> [ ... escaped_source bytecode ] */\n\t\t\tduk_regexp_create_instance(thr);   /* -> [ ... regexp_instance ] */\n\t\t\tDUK__REPLACE_TOP_A_BREAK();\n\t\t}\n#endif  /* DUK_USE_REGEXP_SUPPORT */\n\n\t\t/* XXX: 'c' is unused, use whole BC, etc. */\n\t\tcase DUK_OP_CSVAR_RR:\n\t\tcase DUK_OP_CSVAR_CR:\n\t\tcase DUK_OP_CSVAR_RC:\n\t\tcase DUK_OP_CSVAR_CC: {\n\t\t\t/* The speciality of calling through a variable binding is that the\n\t\t\t * 'this' value may be provided by the variable lookup: E5 Section 6.b.i.\n\t\t\t *\n\t\t\t * The only (standard) case where the 'this' binding is non-null is when\n\t\t\t *   (1) the variable is found in an object environment record, and\n\t\t\t *   (2) that object environment record is a 'with' block.\n\t\t\t */\n\n\t\t\tduk_activation *act;\n\t\t\tduk_uint_fast_t idx;\n\t\t\tduk_tval *tv1;\n\t\t\tduk_hstring *name;\n\n\t\t\t/* A -> target registers (A, A + 1) for call setup\n\t\t\t * B -> identifier name, usually constant but can be a register due to shuffling\n\t\t\t */\n\n\t\t\ttv1 = DUK__REGCONSTP_B(ins);\n\t\t\tDUK_ASSERT(DUK_TVAL_IS_STRING(tv1));\n\t\t\tname = DUK_TVAL_GET_STRING(tv1);\n\t\t\tDUK_ASSERT(name != NULL);\n\t\t\tact = thr->callstack_curr;\n\t\t\t(void) duk_js_getvar_activation(thr, act, name, 1 /*throw*/);  /* -> [... val this] */\n\n\t\t\tidx = (duk_uint_fast_t) DUK_DEC_A(ins);\n\n\t\t\t/* Could add direct value stack handling. */\n\t\t\tduk_replace(thr, (duk_idx_t) (idx + 1));  /* 'this' binding */\n\t\t\tduk_replace(thr, (duk_idx_t) idx);        /* variable value (function, we hope, not checked here) */\n\t\t\tbreak;\n\t\t}\n\n\t\tcase DUK_OP_CLOSURE: {\n\t\t\tduk_activation *act;\n\t\t\tduk_hcompfunc *fun_act;\n\t\t\tduk_small_uint_fast_t bc = DUK_DEC_BC(ins);\n\t\t\tduk_hobject *fun_temp;\n\n\t\t\t/* A -> target reg\n\t\t\t * BC -> inner function index\n\t\t\t */\n\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"CLOSURE to target register %ld, fnum %ld (count %ld)\",\n\t\t\t                     (long) DUK_DEC_A(ins), (long) DUK_DEC_BC(ins), (long) DUK_HCOMPFUNC_GET_FUNCS_COUNT(thr->heap, DUK__FUN())));\n\n\t\t\tDUK_ASSERT_DISABLE(bc >= 0); /* unsigned */\n\t\t\tDUK_ASSERT((duk_uint_t) bc < (duk_uint_t) DUK_HCOMPFUNC_GET_FUNCS_COUNT(thr->heap, DUK__FUN()));\n\n\t\t\tact = thr->callstack_curr;\n\t\t\tfun_act = (duk_hcompfunc *) DUK_ACT_GET_FUNC(act);\n\t\t\tfun_temp = DUK_HCOMPFUNC_GET_FUNCS_BASE(thr->heap, fun_act)[bc];\n\t\t\tDUK_ASSERT(fun_temp != NULL);\n\t\t\tDUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(fun_temp));\n\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"CLOSURE: function template is: %p -> %!O\",\n\t\t\t                     (void *) fun_temp, (duk_heaphdr *) fun_temp));\n\n\t\t\tif (act->lex_env == NULL) {\n\t\t\t\tDUK_ASSERT(act->var_env == NULL);\n\t\t\t\tduk_js_init_activation_environment_records_delayed(thr, act);\n\t\t\t\tact = thr->callstack_curr;\n\t\t\t}\n\t\t\tDUK_ASSERT(act->lex_env != NULL);\n\t\t\tDUK_ASSERT(act->var_env != NULL);\n\n\t\t\t/* functions always have a NEWENV flag, i.e. they get a\n\t\t\t * new variable declaration environment, so only lex_env\n\t\t\t * matters here.\n\t\t\t */\n\t\t\tduk_js_push_closure(thr,\n\t\t\t                    (duk_hcompfunc *) fun_temp,\n\t\t\t                    act->var_env,\n\t\t\t                    act->lex_env,\n\t\t\t                    1 /*add_auto_proto*/);\n\t\t\tDUK__REPLACE_TOP_A_BREAK();\n\t\t}\n\n\t\tcase DUK_OP_GETVAR: {\n\t\t\tduk_activation *act;\n\t\t\tduk_tval *tv1;\n\t\t\tduk_hstring *name;\n\n\t\t\ttv1 = DUK__CONSTP_BC(ins);\n\t\t\tDUK_ASSERT(DUK_TVAL_IS_STRING(tv1));\n\t\t\tname = DUK_TVAL_GET_STRING(tv1);\n\t\t\tDUK_ASSERT(name != NULL);\n\t\t\tact = thr->callstack_curr;\n\t\t\tDUK_ASSERT(act != NULL);\n\t\t\t(void) duk_js_getvar_activation(thr, act, name, 1 /*throw*/);  /* -> [... val this] */\n\t\t\tduk_pop_unsafe(thr);  /* 'this' binding is not needed here */\n\t\t\tDUK__REPLACE_TOP_A_BREAK();\n\t\t}\n\n\t\tcase DUK_OP_PUTVAR: {\n\t\t\tduk_activation *act;\n\t\t\tduk_tval *tv1;\n\t\t\tduk_hstring *name;\n\n\t\t\ttv1 = DUK__CONSTP_BC(ins);\n\t\t\tDUK_ASSERT(DUK_TVAL_IS_STRING(tv1));\n\t\t\tname = DUK_TVAL_GET_STRING(tv1);\n\t\t\tDUK_ASSERT(name != NULL);\n\n\t\t\t/* XXX: putvar takes a duk_tval pointer, which is awkward and\n\t\t\t * should be reworked.\n\t\t\t */\n\n\t\t\ttv1 = DUK__REGP_A(ins);  /* val */\n\t\t\tact = thr->callstack_curr;\n\t\t\tduk_js_putvar_activation(thr, act, name, tv1, DUK__STRICT());\n\t\t\tbreak;\n\t\t}\n\n\t\tcase DUK_OP_DELVAR: {\n\t\t\tduk_activation *act;\n\t\t\tduk_tval *tv1;\n\t\t\tduk_hstring *name;\n\t\t\tduk_bool_t rc;\n\n\t\t\ttv1 = DUK__CONSTP_BC(ins);\n\t\t\tDUK_ASSERT(DUK_TVAL_IS_STRING(tv1));\n\t\t\tname = DUK_TVAL_GET_STRING(tv1);\n\t\t\tDUK_ASSERT(name != NULL);\n\t\t\tact = thr->callstack_curr;\n\t\t\trc = duk_js_delvar_activation(thr, act, name);\n\t\t\tDUK__REPLACE_BOOL_A_BREAK(rc);\n\t\t}\n\n\t\tcase DUK_OP_JUMP: {\n\t\t\t/* Note: without explicit cast to signed, MSVC will\n\t\t\t * apparently generate a large positive jump when the\n\t\t\t * bias-corrected value would normally be negative.\n\t\t\t */\n\t\t\tcurr_pc += (duk_int_fast_t) DUK_DEC_ABC(ins) - (duk_int_fast_t) DUK_BC_JUMP_BIAS;\n\t\t\tbreak;\n\t\t}\n\n#define DUK__RETURN_SHARED() do { \\\n\t\tduk_small_uint_t ret_result; \\\n\t\t/* duk__handle_return() is guaranteed never to throw, except \\\n\t\t * for potential out-of-memory situations which will then \\\n\t\t * propagate out of the executor longjmp handler. \\\n\t\t */ \\\n\t\tDUK_ASSERT(thr->ptr_curr_pc == NULL); \\\n\t\tret_result = duk__handle_return(thr, entry_act); \\\n\t\tif (ret_result == DUK__RETHAND_RESTART) { \\\n\t\t\tgoto restart_execution; \\\n\t\t} \\\n\t\tDUK_ASSERT(ret_result == DUK__RETHAND_FINISHED); \\\n\t\treturn; \\\n\t} while (0)\n#if defined(DUK_USE_EXEC_PREFER_SIZE)\n\t\tcase DUK_OP_RETREG:\n\t\tcase DUK_OP_RETCONST:\n\t\tcase DUK_OP_RETCONSTN:\n\t\tcase DUK_OP_RETUNDEF: {\n\t\t\t /* BC -> return value reg/const */\n\n\t\t\tDUK__SYNC_AND_NULL_CURR_PC();\n\n\t\t\tif (op == DUK_OP_RETREG) {\n\t\t\t\tduk_push_tval(thr, DUK__REGP_BC(ins));\n\t\t\t} else if (op == DUK_OP_RETUNDEF) {\n\t\t\t\tDUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top));  /* valstack policy */\n\t\t\t\tthr->valstack_top++;\n\t\t\t} else {\n\t\t\t\tDUK_ASSERT(op == DUK_OP_RETCONST || op == DUK_OP_RETCONSTN);\n\t\t\t\tduk_push_tval(thr, DUK__CONSTP_BC(ins));\n\t\t\t}\n\n\t\t\tDUK__RETURN_SHARED();\n\t\t}\n#else  /* DUK_USE_EXEC_PREFER_SIZE */\n\t\tcase DUK_OP_RETREG: {\n\t\t\tduk_tval *tv;\n\n\t\t\tDUK__SYNC_AND_NULL_CURR_PC();\n\t\t\ttv = DUK__REGP_BC(ins);\n\t\t\tDUK_TVAL_SET_TVAL(thr->valstack_top, tv);\n\t\t\tDUK_TVAL_INCREF(thr, tv);\n\t\t\tthr->valstack_top++;\n\t\t\tDUK__RETURN_SHARED();\n\t\t}\n\t\t/* This will be unused without refcounting. */\n\t\tcase DUK_OP_RETCONST: {\n\t\t\tduk_tval *tv;\n\n\t\t\tDUK__SYNC_AND_NULL_CURR_PC();\n\t\t\ttv = DUK__CONSTP_BC(ins);\n\t\t\tDUK_TVAL_SET_TVAL(thr->valstack_top, tv);\n\t\t\tDUK_TVAL_INCREF(thr, tv);\n\t\t\tthr->valstack_top++;\n\t\t\tDUK__RETURN_SHARED();\n\t\t}\n\t\tcase DUK_OP_RETCONSTN: {\n\t\t\tduk_tval *tv;\n\n\t\t\tDUK__SYNC_AND_NULL_CURR_PC();\n\t\t\ttv = DUK__CONSTP_BC(ins);\n\t\t\tDUK_TVAL_SET_TVAL(thr->valstack_top, tv);\n#if defined(DUK_USE_REFERENCE_COUNTING)\n\t\t\t/* Without refcounting only RETCONSTN is used. */\n\t\t\tDUK_ASSERT(!DUK_TVAL_IS_HEAP_ALLOCATED(tv));  /* no INCREF for this constant */\n#endif\n\t\t\tthr->valstack_top++;\n\t\t\tDUK__RETURN_SHARED();\n\t\t}\n\t\tcase DUK_OP_RETUNDEF: {\n\t\t\tDUK__SYNC_AND_NULL_CURR_PC();\n\t\t\tthr->valstack_top++;  /* value at valstack top is already undefined by valstack policy */\n\t\t\tDUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top));\n\t\t\tDUK__RETURN_SHARED();\n\t\t}\n#endif  /* DUK_USE_EXEC_PREFER_SIZE */\n\n\t\tcase DUK_OP_LABEL: {\n\t\t\tduk_activation *act;\n\t\t\tduk_catcher *cat;\n\t\t\tduk_small_uint_fast_t bc = DUK_DEC_BC(ins);\n\n\t\t\t/* Allocate catcher and populate it (must be atomic). */\n\n\t\t\tcat = duk_hthread_catcher_alloc(thr);\n\t\t\tDUK_ASSERT(cat != NULL);\n\n\t\t\tcat->flags = (duk_uint32_t) (DUK_CAT_TYPE_LABEL | (bc << DUK_CAT_LABEL_SHIFT));\n\t\t\tcat->pc_base = (duk_instr_t *) curr_pc;  /* pre-incremented, points to first jump slot */\n\t\t\tcat->idx_base = 0;  /* unused for label */\n\t\t\tcat->h_varname = NULL;\n\n\t\t\tact = thr->callstack_curr;\n\t\t\tDUK_ASSERT(act != NULL);\n\t\t\tcat->parent = act->cat;\n\t\t\tact->cat = cat;\n\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"LABEL catcher: flags=0x%08lx, pc_base=%ld, \"\n\t\t\t                     \"idx_base=%ld, h_varname=%!O, label_id=%ld\",\n\t\t\t                     (long) cat->flags, (long) cat->pc_base,\n\t\t\t                     (long) cat->idx_base, (duk_heaphdr *) cat->h_varname, (long) DUK_CAT_GET_LABEL(cat)));\n\n\t\t\tcurr_pc += 2;  /* skip jump slots */\n\t\t\tbreak;\n\t\t}\n\n\t\tcase DUK_OP_ENDLABEL: {\n\t\t\tduk_activation *act;\n#if (defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)) || defined(DUK_USE_ASSERTIONS)\n\t\t\tduk_small_uint_fast_t bc = DUK_DEC_BC(ins);\n#endif\n#if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"ENDLABEL %ld\", (long) bc));\n#endif\n\n\t\t\tact = thr->callstack_curr;\n\t\t\tDUK_ASSERT(act->cat != NULL);\n\t\t\tDUK_ASSERT(DUK_CAT_GET_TYPE(act->cat) == DUK_CAT_TYPE_LABEL);\n\t\t\tDUK_ASSERT((duk_uint_fast_t) DUK_CAT_GET_LABEL(act->cat) == bc);\n\t\t\tduk_hthread_catcher_unwind_nolexenv_norz(thr, act);\n\n\t\t\t/* no need to unwind callstack */\n\t\t\tbreak;\n\t\t}\n\n\t\tcase DUK_OP_BREAK: {\n\t\t\tduk_small_uint_fast_t bc = DUK_DEC_BC(ins);\n\n\t\t\tDUK__SYNC_AND_NULL_CURR_PC();\n\t\t\tduk__handle_break_or_continue(thr, (duk_uint_t) bc, DUK_LJ_TYPE_BREAK);\n\t\t\tgoto restart_execution;\n\t\t}\n\n\t\tcase DUK_OP_CONTINUE: {\n\t\t\tduk_small_uint_fast_t bc = DUK_DEC_BC(ins);\n\n\t\t\tDUK__SYNC_AND_NULL_CURR_PC();\n\t\t\tduk__handle_break_or_continue(thr, (duk_uint_t) bc, DUK_LJ_TYPE_CONTINUE);\n\t\t\tgoto restart_execution;\n\t\t}\n\n\t\t/* XXX: move to helper, too large to be inline here */\n\t\tcase DUK_OP_TRYCATCH: {\n\t\t\tduk__handle_op_trycatch(thr, ins, curr_pc);\n\t\t\tcurr_pc += 2;  /* skip jump slots */\n\t\t\tbreak;\n\t\t}\n\n\t\tcase DUK_OP_ENDTRY: {\n\t\t\tcurr_pc = duk__handle_op_endtry(thr, ins);\n\t\t\tbreak;\n\t\t}\n\n\t\tcase DUK_OP_ENDCATCH: {\n\t\t\tduk__handle_op_endcatch(thr, ins);\n\t\t\tbreak;\n\t\t}\n\n\t\tcase DUK_OP_ENDFIN: {\n\t\t\t/* Sync and NULL early. */\n\t\t\tDUK__SYNC_AND_NULL_CURR_PC();\n\n\t\t\tif (duk__handle_op_endfin(thr, ins, entry_act) != 0) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t/* Must restart because we NULLed out curr_pc. */\n\t\t\tgoto restart_execution;\n\t\t}\n\n\t\tcase DUK_OP_THROW: {\n\t\t\tduk_small_uint_fast_t bc = DUK_DEC_BC(ins);\n\n\t\t\t/* Note: errors are augmented when they are created, not\n\t\t\t * when they are thrown.  So, don't augment here, it would\n\t\t\t * break re-throwing for instance.\n\t\t\t */\n\n\t\t\t/* Sync so that augmentation sees up-to-date activations, NULL\n\t\t\t * thr->ptr_curr_pc so that it's not used if side effects occur\n\t\t\t * in augmentation or longjmp handling.\n\t\t\t */\n\t\t\tDUK__SYNC_AND_NULL_CURR_PC();\n\n\t\t\tduk_dup(thr, (duk_idx_t) bc);\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"THROW ERROR (BYTECODE): %!dT (before throw augment)\",\n\t\t\t                     (duk_tval *) duk_get_tval(thr, -1)));\n#if defined(DUK_USE_AUGMENT_ERROR_THROW)\n\t\t\tduk_err_augment_error_throw(thr);\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"THROW ERROR (BYTECODE): %!dT (after throw augment)\",\n\t\t\t                     (duk_tval *) duk_get_tval(thr, -1)));\n#endif\n\n\t\t\tduk_err_setup_ljstate1(thr, DUK_LJ_TYPE_THROW, DUK_GET_TVAL_NEGIDX(thr, -1));\n#if defined(DUK_USE_DEBUGGER_SUPPORT)\n\t\t\tduk_err_check_debugger_integration(thr);\n#endif\n\n\t\t\tDUK_ASSERT(thr->heap->lj.jmpbuf_ptr != NULL);  /* always in executor */\n\t\t\tduk_err_longjmp(thr);\n\t\t\tDUK_UNREACHABLE();\n\t\t\tbreak;\n\t\t}\n\n\t\tcase DUK_OP_CSREG: {\n\t\t\t/*\n\t\t\t *  Assuming a register binds to a variable declared within this\n\t\t\t *  function (a declarative binding), the 'this' for the call\n\t\t\t *  setup is always 'undefined'.  E5 Section 10.2.1.1.6.\n\t\t\t */\n\n\t\t\tduk_small_uint_fast_t a = DUK_DEC_A(ins);\n\t\t\tduk_small_uint_fast_t bc = DUK_DEC_BC(ins);\n\n\t\t\t/* A -> register containing target function (not type checked here)\n\t\t\t * BC -> target registers (BC, BC + 1) for call setup\n\t\t\t */\n\n#if defined(DUK_USE_PREFER_SIZE)\n\t\t\tduk_dup(thr, (duk_idx_t) a);\n\t\t\tduk_replace(thr, (duk_idx_t) bc);\n\t\t\tduk_to_undefined(thr, (duk_idx_t) (bc + 1));\n#else\n\t\t\tduk_tval *tv1;\n\t\t\tduk_tval *tv2;\n\t\t\tduk_tval *tv3;\n\t\t\tduk_tval tv_tmp1;\n\t\t\tduk_tval tv_tmp2;\n\n\t\t\ttv1 = DUK__REGP(bc);\n\t\t\ttv2 = tv1 + 1;\n\t\t\tDUK_TVAL_SET_TVAL(&tv_tmp1, tv1);\n\t\t\tDUK_TVAL_SET_TVAL(&tv_tmp2, tv2);\n\t\t\ttv3 = DUK__REGP(a);\n\t\t\tDUK_TVAL_SET_TVAL(tv1, tv3);\n\t\t\tDUK_TVAL_INCREF(thr, tv1);  /* no side effects */\n\t\t\tDUK_TVAL_SET_UNDEFINED(tv2);  /* no need for incref */\n\t\t\tDUK_TVAL_DECREF(thr, &tv_tmp1);\n\t\t\tDUK_TVAL_DECREF(thr, &tv_tmp2);\n#endif\n\t\t\tbreak;\n\t\t}\n\n\n\t\t/* XXX: in some cases it's faster NOT to reuse the value\n\t\t * stack but rather copy the arguments on top of the stack\n\t\t * (mainly when the calling value stack is large and the value\n\t\t * stack resize would be large).\n\t\t */\n\n\t\tcase DUK_OP_CALL0:\n\t\tcase DUK_OP_CALL1:\n\t\tcase DUK_OP_CALL2:\n\t\tcase DUK_OP_CALL3:\n\t\tcase DUK_OP_CALL4:\n\t\tcase DUK_OP_CALL5:\n\t\tcase DUK_OP_CALL6:\n\t\tcase DUK_OP_CALL7: {\n\t\t\t/* Opcode packs 4 flag bits: 1 for indirect, 3 map\n\t\t\t * 1:1 to three lowest call handling flags.\n\t\t\t *\n\t\t\t * A -> nargs or register with nargs (indirect)\n\t\t\t * BC -> base register for call (base -> func, base+1 -> this, base+2 -> arg1 ... base+2+N-1 -> argN)\n\t\t\t */\n\n\t\t\tduk_idx_t nargs;\n\t\t\tduk_idx_t idx;\n\t\t\tduk_small_uint_t call_flags;\n#if !defined(DUK_USE_EXEC_FUN_LOCAL)\n\t\t\tduk_hcompfunc *fun;\n#endif\n\n\t\t\tDUK_ASSERT((DUK_OP_CALL0 & 0x0fU) == 0);\n\t\t\tDUK_ASSERT((ins & DUK_BC_CALL_FLAG_INDIRECT) == 0);\n\n\t\t\tnargs = (duk_idx_t) DUK_DEC_A(ins);\n\t\t\tcall_flags = (ins & 0x07U) | DUK_CALL_FLAG_ALLOW_ECMATOECMA;\n\t\t\tidx = (duk_idx_t) DUK_DEC_BC(ins);\n\n\t\t\tif (duk__executor_handle_call(thr, idx, nargs, call_flags)) {\n\t\t\t\t/* curr_pc synced by duk_handle_call_unprotected() */\n\t\t\t\tDUK_ASSERT(thr->ptr_curr_pc == NULL);\n\t\t\t\tgoto restart_execution;\n\t\t\t}\n\t\t\tDUK_ASSERT(thr->ptr_curr_pc != NULL);\n\n\t\t\t/* duk_js_call.c is required to restore the stack reserve\n\t\t\t * so we only need to reset the top.\n\t\t\t */\n#if !defined(DUK_USE_EXEC_FUN_LOCAL)\n\t\t\tfun = DUK__FUN();\n#endif\n\t\t\tduk_set_top_unsafe(thr, (duk_idx_t) fun->nregs);\n\n\t\t\t/* No need to reinit setjmp() catchpoint, as call handling\n\t\t\t * will store and restore our state.\n\t\t\t *\n\t\t\t * When debugger is enabled, we need to recheck the activation\n\t\t\t * status after returning.  This is now handled by call handling\n\t\t\t * and heap->dbg_force_restart.\n\t\t\t */\n\t\t\tbreak;\n\t\t}\n\n\t\tcase DUK_OP_CALL8:\n\t\tcase DUK_OP_CALL9:\n\t\tcase DUK_OP_CALL10:\n\t\tcase DUK_OP_CALL11:\n\t\tcase DUK_OP_CALL12:\n\t\tcase DUK_OP_CALL13:\n\t\tcase DUK_OP_CALL14:\n\t\tcase DUK_OP_CALL15: {\n\t\t\t/* Indirect variant. */\n\t\t\tduk_uint_fast_t nargs;\n\t\t\tduk_idx_t idx;\n\t\t\tduk_small_uint_t call_flags;\n#if !defined(DUK_USE_EXEC_FUN_LOCAL)\n\t\t\tduk_hcompfunc *fun;\n#endif\n\n\t\t\tDUK_ASSERT((DUK_OP_CALL0 & 0x0fU) == 0);\n\t\t\tDUK_ASSERT((ins & DUK_BC_CALL_FLAG_INDIRECT) != 0);\n\n\t\t\tnargs = (duk_uint_fast_t) DUK_DEC_A(ins);\n\t\t\tDUK__LOOKUP_INDIRECT(nargs);\n\t\t\tcall_flags = (ins & 0x07U) | DUK_CALL_FLAG_ALLOW_ECMATOECMA;\n\t\t\tidx = (duk_idx_t) DUK_DEC_BC(ins);\n\n\t\t\tif (duk__executor_handle_call(thr, idx, (duk_idx_t) nargs, call_flags)) {\n\t\t\t\tDUK_ASSERT(thr->ptr_curr_pc == NULL);\n\t\t\t\tgoto restart_execution;\n\t\t\t}\n\t\t\tDUK_ASSERT(thr->ptr_curr_pc != NULL);\n\n#if !defined(DUK_USE_EXEC_FUN_LOCAL)\n\t\t\tfun = DUK__FUN();\n#endif\n\t\t\tduk_set_top_unsafe(thr, (duk_idx_t) fun->nregs);\n\t\t\tbreak;\n\t\t}\n\n\t\tcase DUK_OP_NEWOBJ: {\n\t\t\tduk_push_object(thr);\n#if defined(DUK_USE_ASSERTIONS)\n\t\t\t{\n\t\t\t\tduk_hobject *h;\n\t\t\t\th = duk_require_hobject(thr, -1);\n\t\t\t\tDUK_ASSERT(DUK_HOBJECT_GET_ESIZE(h) == 0);\n\t\t\t\tDUK_ASSERT(DUK_HOBJECT_GET_ENEXT(h) == 0);\n\t\t\t\tDUK_ASSERT(DUK_HOBJECT_GET_ASIZE(h) == 0);\n\t\t\t\tDUK_ASSERT(DUK_HOBJECT_GET_HSIZE(h) == 0);\n\t\t\t}\n#endif\n#if !defined(DUK_USE_PREFER_SIZE)\n\t\t\t/* XXX: could do a direct props realloc, but need hash size */\n\t\t\tduk_hobject_resize_entrypart(thr, duk_known_hobject(thr, -1), DUK_DEC_A(ins));\n#endif\n\t\t\tDUK__REPLACE_TOP_BC_BREAK();\n\t\t}\n\n\t\tcase DUK_OP_NEWARR: {\n\t\t\tduk_push_array(thr);\n#if defined(DUK_USE_ASSERTIONS)\n\t\t\t{\n\t\t\t\tduk_hobject *h;\n\t\t\t\th = duk_require_hobject(thr, -1);\n\t\t\t\tDUK_ASSERT(DUK_HOBJECT_GET_ESIZE(h) == 0);\n\t\t\t\tDUK_ASSERT(DUK_HOBJECT_GET_ENEXT(h) == 0);\n\t\t\t\tDUK_ASSERT(DUK_HOBJECT_GET_ASIZE(h) == 0);\n\t\t\t\tDUK_ASSERT(DUK_HOBJECT_GET_HSIZE(h) == 0);\n\t\t\t\tDUK_ASSERT(DUK_HOBJECT_HAS_ARRAY_PART(h));\n\t\t\t}\n#endif\n#if !defined(DUK_USE_PREFER_SIZE)\n\t\t\tduk_hobject_realloc_props(thr,\n\t\t\t                          duk_known_hobject(thr, -1),\n\t\t\t                          0 /*new_e_size*/,\n\t\t\t                          DUK_DEC_A(ins) /*new_a_size*/,\n\t\t\t                          0 /*new_h_size*/,\n\t\t\t                          0 /*abandon_array*/);\n#if 0\n\t\t\tduk_hobject_resize_arraypart(thr, duk_known_hobject(thr, -1), DUK_DEC_A(ins));\n#endif\n#endif\n\t\t\tDUK__REPLACE_TOP_BC_BREAK();\n\t\t}\n\n\t\tcase DUK_OP_MPUTOBJ:\n\t\tcase DUK_OP_MPUTOBJI: {\n\t\t\tduk_idx_t obj_idx;\n\t\t\tduk_uint_fast_t idx, idx_end;\n\t\t\tduk_small_uint_fast_t count;\n\n\t\t\t/* A -> register of target object\n\t\t\t * B -> first register of key/value pair list\n\t\t\t *      or register containing first register number if indirect\n\t\t\t * C -> number of key/value pairs * 2\n\t\t\t *      (= number of value stack indices used starting from 'B')\n\t\t\t */\n\n\t\t\tobj_idx = DUK_DEC_A(ins);\n\t\t\tDUK_ASSERT(duk_is_object(thr, obj_idx));\n\n\t\t\tidx = (duk_uint_fast_t) DUK_DEC_B(ins);\n\t\t\tif (DUK_DEC_OP(ins) == DUK_OP_MPUTOBJI) {\n\t\t\t\tDUK__LOOKUP_INDIRECT(idx);\n\t\t\t}\n\n\t\t\tcount = (duk_small_uint_fast_t) DUK_DEC_C(ins);\n\t\t\tDUK_ASSERT(count > 0);  /* compiler guarantees */\n\t\t\tidx_end = idx + count;\n\n#if defined(DUK_USE_EXEC_INDIRECT_BOUND_CHECK)\n\t\t\tif (DUK_UNLIKELY(idx_end > (duk_uint_fast_t) duk_get_top(thr))) {\n\t\t\t\t/* XXX: use duk_is_valid_index() instead? */\n\t\t\t\t/* XXX: improve check; check against nregs, not against top */\n\t\t\t\tDUK__INTERNAL_ERROR(\"MPUTOBJ out of bounds\");\n\t\t\t}\n#endif\n\n\t\t\t/* Use 'force' flag to duk_def_prop() to ensure that any\n\t\t\t * inherited properties don't prevent the operation.\n\t\t\t * With ES2015 duplicate properties are allowed, so that we\n\t\t\t * must overwrite any previous data or accessor property.\n\t\t\t *\n\t\t\t * With ES2015 computed property names the literal keys\n\t\t\t * may be arbitrary values and need to be ToPropertyKey()\n\t\t\t * coerced at runtime.\n\t\t\t */\n\t\t\tdo {\n\t\t\t\t/* XXX: faster initialization (direct access or better primitives) */\n\t\t\t\tduk_dup(thr, (duk_idx_t) idx);\n\t\t\t\tduk_dup(thr, (duk_idx_t) (idx + 1));\n\t\t\t\tduk_def_prop(thr, obj_idx, DUK_DEFPROP_HAVE_VALUE |\n\t\t\t\t                           DUK_DEFPROP_FORCE |\n\t\t\t\t                           DUK_DEFPROP_SET_WRITABLE |\n\t\t\t\t                           DUK_DEFPROP_SET_ENUMERABLE |\n\t\t\t\t                           DUK_DEFPROP_SET_CONFIGURABLE);\n\t\t\t\tidx += 2;\n\t\t\t} while (idx < idx_end);\n\t\t\tbreak;\n\t\t}\n\n\t\tcase DUK_OP_INITSET:\n\t\tcase DUK_OP_INITGET: {\n\t\t\tduk__handle_op_initset_initget(thr, ins);\n\t\t\tbreak;\n\t\t}\n\n\t\tcase DUK_OP_MPUTARR:\n\t\tcase DUK_OP_MPUTARRI: {\n\t\t\tduk_idx_t obj_idx;\n\t\t\tduk_uint_fast_t idx, idx_end;\n\t\t\tduk_small_uint_fast_t count;\n\t\t\tduk_tval *tv1;\n\t\t\tduk_uint32_t arr_idx;\n\n\t\t\t/* A -> register of target object\n\t\t\t * B -> first register of value data (start_index, value1, value2, ..., valueN)\n\t\t\t *      or register containing first register number if indirect\n\t\t\t * C -> number of key/value pairs (N)\n\t\t\t */\n\n\t\t\tobj_idx = DUK_DEC_A(ins);\n\t\t\tDUK_ASSERT(duk_is_object(thr, obj_idx));\n\n\t\t\tidx = (duk_uint_fast_t) DUK_DEC_B(ins);\n\t\t\tif (DUK_DEC_OP(ins) == DUK_OP_MPUTARRI) {\n\t\t\t\tDUK__LOOKUP_INDIRECT(idx);\n\t\t\t}\n\n\t\t\tcount = (duk_small_uint_fast_t) DUK_DEC_C(ins);\n\t\t\tDUK_ASSERT(count > 0 + 1);  /* compiler guarantees */\n\t\t\tidx_end = idx + count;\n\n#if defined(DUK_USE_EXEC_INDIRECT_BOUND_CHECK)\n\t\t\tif (idx_end > (duk_uint_fast_t) duk_get_top(thr)) {\n\t\t\t\t/* XXX: use duk_is_valid_index() instead? */\n\t\t\t\t/* XXX: improve check; check against nregs, not against top */\n\t\t\t\tDUK__INTERNAL_ERROR(\"MPUTARR out of bounds\");\n\t\t\t}\n#endif\n\n\t\t\ttv1 = DUK__REGP(idx);\n\t\t\tDUK_ASSERT(DUK_TVAL_IS_NUMBER(tv1));\n#if defined(DUK_USE_FASTINT)\n\t\t\tDUK_ASSERT(DUK_TVAL_IS_FASTINT(tv1));\n\t\t\tarr_idx = (duk_uint32_t) DUK_TVAL_GET_FASTINT_U32(tv1);\n#else\n\t\t\tarr_idx = (duk_uint32_t) DUK_TVAL_GET_NUMBER(tv1);\n#endif\n\t\t\tidx++;\n\n\t\t\tdo {\n\t\t\t\t/* duk_xdef_prop() will define an own property without any array\n\t\t\t\t * special behaviors.  We'll need to set the array length explicitly\n\t\t\t\t * in the end.  For arrays with elisions, the compiler will emit an\n\t\t\t\t * explicit SETALEN which will update the length.\n\t\t\t\t */\n\n\t\t\t\t/* XXX: because we're dealing with 'own' properties of a fresh array,\n\t\t\t\t * the array initializer should just ensure that the array has a large\n\t\t\t\t * enough array part and write the values directly into array part,\n\t\t\t\t * and finally set 'length' manually in the end (as already happens now).\n\t\t\t\t */\n\n\t\t\t\tduk_dup(thr, (duk_idx_t) idx);\n\t\t\t\tduk_xdef_prop_index_wec(thr, obj_idx, arr_idx);\n\n\t\t\t\tidx++;\n\t\t\t\tarr_idx++;\n\t\t\t} while (idx < idx_end);\n\n\t\t\t/* XXX: E5.1 Section 11.1.4 coerces the final length through\n\t\t\t * ToUint32() which is odd but happens now as a side effect of\n\t\t\t * 'arr_idx' type.\n\t\t\t */\n\t\t\tduk_set_length(thr, obj_idx, (duk_size_t) (duk_uarridx_t) arr_idx);\n\t\t\tbreak;\n\t\t}\n\n\t\tcase DUK_OP_SETALEN: {\n\t\t\tduk_tval *tv1;\n\t\t\tduk_hobject *h;\n\t\t\tduk_uint32_t len;\n\n\t\t\ttv1 = DUK__REGP_A(ins);\n\t\t\tDUK_ASSERT(DUK_TVAL_IS_OBJECT(tv1));\n\t\t\th = DUK_TVAL_GET_OBJECT(tv1);\n\t\t\tDUK_ASSERT(DUK_HOBJECT_IS_ARRAY(h));\n\n\t\t\ttv1 = DUK__REGP_BC(ins);\n\t\t\tDUK_ASSERT(DUK_TVAL_IS_NUMBER(tv1));\n#if defined(DUK_USE_FASTINT)\n\t\t\tDUK_ASSERT(DUK_TVAL_IS_FASTINT(tv1));\n\t\t\tlen = (duk_uint32_t) DUK_TVAL_GET_FASTINT_U32(tv1);\n#else\n\t\t\tlen = (duk_uint32_t) DUK_TVAL_GET_NUMBER(tv1);\n#endif\n\t\t\t((duk_harray *) h)->length = len;\n\t\t\tbreak;\n\t\t}\n\n\t\tcase DUK_OP_INITENUM: {\n\t\t\tduk__handle_op_initenum(thr, ins);\n\t\t\tbreak;\n\t\t}\n\n\t\tcase DUK_OP_NEXTENUM: {\n\t\t\tcurr_pc += duk__handle_op_nextenum(thr, ins);\n\t\t\tbreak;\n\t\t}\n\n\t\tcase DUK_OP_INVLHS: {\n\t\t\tDUK_ERROR_REFERENCE(thr, DUK_STR_INVALID_LVALUE);\n\t\t\tDUK_UNREACHABLE();\n\t\t\tbreak;\n\t\t}\n\n\t\tcase DUK_OP_DEBUGGER: {\n\t\t\t/* Opcode only emitted by compiler when debugger\n\t\t\t * support is enabled.  Ignore it silently without\n\t\t\t * debugger support, in case it has been loaded\n\t\t\t * from precompiled bytecode.\n\t\t\t */\n#if defined(DUK_USE_DEBUGGER_SUPPORT)\n\t\t\tif (duk_debug_is_attached(thr->heap)) {\n\t\t\t\tDUK_D(DUK_DPRINT(\"DEBUGGER statement encountered, halt execution\"));\n\t\t\t\tDUK__SYNC_AND_NULL_CURR_PC();\n\t\t\t\tduk_debug_halt_execution(thr, 1 /*use_prev_pc*/);\n\t\t\t\tDUK_D(DUK_DPRINT(\"DEBUGGER statement finished, resume execution\"));\n\t\t\t\tgoto restart_execution;\n\t\t\t} else {\n\t\t\t\tDUK_D(DUK_DPRINT(\"DEBUGGER statement ignored, debugger not attached\"));\n\t\t\t}\n#else\n\t\t\tDUK_D(DUK_DPRINT(\"DEBUGGER statement ignored, no debugger support\"));\n#endif\n\t\t\tbreak;\n\t\t}\n\n\t\tcase DUK_OP_NOP: {\n\t\t\t/* Nop, ignored, but ABC fields may carry a value e.g.\n\t\t\t * for indirect opcode handling.\n\t\t\t */\n\t\t\tbreak;\n\t\t}\n\n\t\tcase DUK_OP_INVALID: {\n\t\t\tDUK_ERROR_FMT1(thr, DUK_ERR_ERROR, \"INVALID opcode (%ld)\", (long) DUK_DEC_ABC(ins));\n\t\t\tbreak;\n\t\t}\n\n#if defined(DUK_USE_ES6)\n\t\tcase DUK_OP_NEWTARGET: {\n\t\t\t/* https://www.ecma-international.org/ecma-262/6.0/#sec-meta-properties-runtime-semantics-evaluation\n\t\t\t * https://www.ecma-international.org/ecma-262/6.0/#sec-getnewtarget\n\t\t\t *\n\t\t\t * No newTarget support now, so as a first approximation\n\t\t\t * use the resolved (non-bound) target function.\n\t\t\t */\n\t\t\t/* XXX: C API: push_new_target()? */\n\t\t\tduk_activation *act;\n\n\t\t\tact = thr->callstack_curr;\n\t\t\tDUK_ASSERT(act != NULL);\n\n\t\t\t/* Check CONSTRUCT flag from current function, or if running\n\t\t\t * direct eval, from a non-direct-eval parent (with possibly\n\t\t\t * more than one nested direct eval).  An alternative to this\n\t\t\t * would be to store [[NewTarget]] as a hidden symbol of the\n\t\t\t * lexical scope, and then just look up that variable.\n\t\t\t */\n\t\t\tfor (;;) {\n\t\t\t\tif (act == NULL) {\n\t\t\t\t\tduk_push_undefined(thr);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tif (act->flags & DUK_ACT_FLAG_CONSTRUCT) {\n\t\t\t\t\tduk_push_tval(thr, &act->tv_func);\n\t\t\t\t\tbreak;\n\t\t\t\t} else if (act->flags & DUK_ACT_FLAG_DIRECT_EVAL) {\n\t\t\t\t\tact = act->parent;\n\t\t\t\t} else {\n\t\t\t\t\tduk_push_undefined(thr);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tDUK__REPLACE_TOP_BC_BREAK();\n\t\t}\n#endif  /* DUK_USE_ES6 */\n\n#if !defined(DUK_USE_EXEC_PREFER_SIZE)\n#if !defined(DUK_USE_ES7_EXP_OPERATOR)\n\t\tcase DUK_OP_EXP_RR:\n\t\tcase DUK_OP_EXP_CR:\n\t\tcase DUK_OP_EXP_RC:\n\t\tcase DUK_OP_EXP_CC:\n#endif\n#if !defined(DUK_USE_ES6)\n\t\tcase DUK_OP_NEWTARGET:\n#endif\n#if !defined(DUK_USE_VERBOSE_ERRORS)\n\t\tcase DUK_OP_GETPROPC_RR:\n\t\tcase DUK_OP_GETPROPC_CR:\n\t\tcase DUK_OP_GETPROPC_RC:\n\t\tcase DUK_OP_GETPROPC_CC:\n#endif\n\t\tcase DUK_OP_UNUSED207:\n\t\tcase DUK_OP_UNUSED212:\n\t\tcase DUK_OP_UNUSED213:\n\t\tcase DUK_OP_UNUSED214:\n\t\tcase DUK_OP_UNUSED215:\n\t\tcase DUK_OP_UNUSED216:\n\t\tcase DUK_OP_UNUSED217:\n\t\tcase DUK_OP_UNUSED218:\n\t\tcase DUK_OP_UNUSED219:\n\t\tcase DUK_OP_UNUSED220:\n\t\tcase DUK_OP_UNUSED221:\n\t\tcase DUK_OP_UNUSED222:\n\t\tcase DUK_OP_UNUSED223:\n\t\tcase DUK_OP_UNUSED224:\n\t\tcase DUK_OP_UNUSED225:\n\t\tcase DUK_OP_UNUSED226:\n\t\tcase DUK_OP_UNUSED227:\n\t\tcase DUK_OP_UNUSED228:\n\t\tcase DUK_OP_UNUSED229:\n\t\tcase DUK_OP_UNUSED230:\n\t\tcase DUK_OP_UNUSED231:\n\t\tcase DUK_OP_UNUSED232:\n\t\tcase DUK_OP_UNUSED233:\n\t\tcase DUK_OP_UNUSED234:\n\t\tcase DUK_OP_UNUSED235:\n\t\tcase DUK_OP_UNUSED236:\n\t\tcase DUK_OP_UNUSED237:\n\t\tcase DUK_OP_UNUSED238:\n\t\tcase DUK_OP_UNUSED239:\n\t\tcase DUK_OP_UNUSED240:\n\t\tcase DUK_OP_UNUSED241:\n\t\tcase DUK_OP_UNUSED242:\n\t\tcase DUK_OP_UNUSED243:\n\t\tcase DUK_OP_UNUSED244:\n\t\tcase DUK_OP_UNUSED245:\n\t\tcase DUK_OP_UNUSED246:\n\t\tcase DUK_OP_UNUSED247:\n\t\tcase DUK_OP_UNUSED248:\n\t\tcase DUK_OP_UNUSED249:\n\t\tcase DUK_OP_UNUSED250:\n\t\tcase DUK_OP_UNUSED251:\n\t\tcase DUK_OP_UNUSED252:\n\t\tcase DUK_OP_UNUSED253:\n\t\tcase DUK_OP_UNUSED254:\n\t\tcase DUK_OP_UNUSED255:\n\t\t/* Force all case clauses to map to an actual handler\n\t\t * so that the compiler can emit a jump without a bounds\n\t\t * check: the switch argument is a duk_uint8_t so that\n\t\t * the compiler may be able to figure it out.  This is\n\t\t * a small detail and obviously compiler dependent.\n\t\t */\n\t\t/* default: clause omitted on purpose */\n#else  /* DUK_USE_EXEC_PREFER_SIZE */\n\t\tdefault:\n#endif  /* DUK_USE_EXEC_PREFER_SIZE */\n\t\t{\n\t\t\t/* Default case catches invalid/unsupported opcodes. */\n\t\t\tDUK_D(DUK_DPRINT(\"invalid opcode: %ld - %!I\", (long) op, ins));\n\t\t\tDUK__INTERNAL_ERROR(\"invalid opcode\");\n\t\t\tbreak;\n\t\t}\n\n\t\t}  /* end switch */\n\n\t\tcontinue;\n\n\t\t/* Some shared exit paths for opcode handling below.  These\n\t\t * are mostly useful to reduce code footprint when multiple\n\t\t * opcodes have a similar epilogue (like replacing stack top\n\t\t * with index 'a').\n\t\t */\n\n#if defined(DUK_USE_EXEC_PREFER_SIZE)\n\t replace_top_a:\n\t\tDUK__REPLACE_TO_TVPTR(thr, DUK__REGP_A(ins));\n\t\tcontinue;\n\t replace_top_bc:\n\t\tDUK__REPLACE_TO_TVPTR(thr, DUK__REGP_BC(ins));\n\t\tcontinue;\n#endif\n\t}\n\tDUK_UNREACHABLE();\n\n#if !defined(DUK_USE_VERBOSE_EXECUTOR_ERRORS)\n internal_error:\n\tDUK_ERROR_INTERNAL(thr);\n#endif\n}\n\n/* automatic undefs */\n#undef DUK__BYTEOFF_A\n#undef DUK__BYTEOFF_B\n#undef DUK__BYTEOFF_BC\n#undef DUK__BYTEOFF_C\n#undef DUK__COMPARE_BODY\n#undef DUK__CONST\n#undef DUK__CONSTP\n#undef DUK__CONSTP_A\n#undef DUK__CONSTP_B\n#undef DUK__CONSTP_BC\n#undef DUK__CONSTP_C\n#undef DUK__DELPROP_BODY\n#undef DUK__EQ_BODY\n#undef DUK__FUN\n#undef DUK__GETPROPC_BODY\n#undef DUK__GETPROP_BODY\n#undef DUK__GE_BODY\n#undef DUK__GT_BODY\n#undef DUK__INLINE_PERF\n#undef DUK__INSTOF_BODY\n#undef DUK__INTERNAL_ERROR\n#undef DUK__INT_NOACTION\n#undef DUK__INT_RESTART\n#undef DUK__IN_BODY\n#undef DUK__LE_BODY\n#undef DUK__LONGJMP_RESTART\n#undef DUK__LONGJMP_RETHROW\n#undef DUK__LOOKUP_INDIRECT\n#undef DUK__LT_BODY\n#undef DUK__MASK_A\n#undef DUK__MASK_B\n#undef DUK__MASK_BC\n#undef DUK__MASK_C\n#undef DUK__NEQ_BODY\n#undef DUK__NOINLINE_PERF\n#undef DUK__PUTPROP_BODY\n#undef DUK__RCBIT_B\n#undef DUK__RCBIT_C\n#undef DUK__REG\n#undef DUK__REGCONSTP_B\n#undef DUK__REGCONSTP_C\n#undef DUK__REGP\n#undef DUK__REGP_A\n#undef DUK__REGP_B\n#undef DUK__REGP_BC\n#undef DUK__REGP_C\n#undef DUK__REPLACE_BOOL_A_BREAK\n#undef DUK__REPLACE_TOP_A_BREAK\n#undef DUK__REPLACE_TOP_BC_BREAK\n#undef DUK__REPLACE_TO_TVPTR\n#undef DUK__RETHAND_FINISHED\n#undef DUK__RETHAND_RESTART\n#undef DUK__RETURN_SHARED\n#undef DUK__SEQ_BODY\n#undef DUK__SHIFT_A\n#undef DUK__SHIFT_B\n#undef DUK__SHIFT_BC\n#undef DUK__SHIFT_C\n#undef DUK__SNEQ_BODY\n#undef DUK__STRICT\n#undef DUK__SYNC_AND_NULL_CURR_PC\n#undef DUK__SYNC_CURR_PC\n#undef DUK__TVAL_SHIFT\n#line 1 \"duk_js_ops.c\"\n/*\n *  Ecmascript specification algorithm and conversion helpers.\n *\n *  These helpers encapsulate the primitive Ecmascript operation semantics,\n *  and are used by the bytecode executor and the API (among other places).\n *  Some primitives are only implemented as part of the API and have no\n *  \"internal\" helper.  This is the case when an internal helper would not\n *  really be useful; e.g. the operation is rare, uses value stack heavily,\n *  etc.\n *\n *  The operation arguments depend on what is required to implement\n *  the operation:\n *\n *    - If an operation is simple and stateless, and has no side\n *      effects, it won't take an duk_hthread argument and its\n *      arguments may be duk_tval pointers (which are safe as long\n *      as no side effects take place).\n *\n *    - If complex coercions are required (e.g. a \"ToNumber\" coercion)\n *      or errors may be thrown, the operation takes an duk_hthread\n *      argument.  This also implies that the operation may have\n *      arbitrary side effects, invalidating any duk_tval pointers.\n *\n *    - For operations with potential side effects, arguments can be\n *      taken in several ways:\n *\n *      a) as duk_tval pointers, which makes sense if the \"common case\"\n *         can be resolved without side effects (e.g. coercion); the\n *         arguments are pushed to the valstack for coercion if\n *         necessary\n *\n *      b) as duk_tval values\n *\n *      c) implicitly on value stack top\n *\n *      d) as indices to the value stack\n *\n *  Future work:\n *\n *     - Argument styles may not be the most sensible in every case now.\n *\n *     - In-place coercions might be useful for several operations, if\n *       in-place coercion is OK for the bytecode executor and the API.\n */\n\n/* #include duk_internal.h -> already included */\n\n/*\n *  ToPrimitive()  (E5 Section 9.1)\n *\n *  ==> implemented in the API.\n */\n\n/*\n *  ToBoolean()  (E5 Section 9.2)\n */\n\nDUK_INTERNAL duk_bool_t duk_js_toboolean(duk_tval *tv) {\n\tswitch (DUK_TVAL_GET_TAG(tv)) {\n\tcase DUK_TAG_UNDEFINED:\n\tcase DUK_TAG_NULL:\n\t\treturn 0;\n\tcase DUK_TAG_BOOLEAN:\n\t\tDUK_ASSERT(DUK_TVAL_GET_BOOLEAN(tv) == 0 || DUK_TVAL_GET_BOOLEAN(tv) == 1);\n\t\treturn DUK_TVAL_GET_BOOLEAN(tv);\n\tcase DUK_TAG_STRING: {\n\t\t/* Symbols ToBoolean() coerce to true, regardless of their\n\t\t * description.  This happens with no explicit check because\n\t\t * of the symbol representation byte prefix.\n\t\t */\n\t\tduk_hstring *h = DUK_TVAL_GET_STRING(tv);\n\t\tDUK_ASSERT(h != NULL);\n\t\treturn (DUK_HSTRING_GET_BYTELEN(h) > 0 ? 1 : 0);\n\t}\n\tcase DUK_TAG_OBJECT: {\n\t\treturn 1;\n\t}\n\tcase DUK_TAG_BUFFER: {\n\t\t/* Mimic Uint8Array semantics: objects coerce true, regardless\n\t\t * of buffer length (zero or not) or context.\n\t\t */\n\t\treturn 1;\n\t}\n\tcase DUK_TAG_POINTER: {\n\t\tvoid *p = DUK_TVAL_GET_POINTER(tv);\n\t\treturn (p != NULL ? 1 : 0);\n\t}\n\tcase DUK_TAG_LIGHTFUNC: {\n\t\treturn 1;\n\t}\n#if defined(DUK_USE_FASTINT)\n\tcase DUK_TAG_FASTINT:\n\t\tif (DUK_TVAL_GET_FASTINT(tv) != 0) {\n\t\t\treturn 1;\n\t\t} else {\n\t\t\treturn 0;\n\t\t}\n#endif\n\tdefault: {\n\t\t/* number */\n\t\tduk_double_t d;\n#if defined(DUK_USE_PREFER_SIZE)\n\t\tint c;\n#endif\n\t\tDUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));\n\t\tDUK_ASSERT(DUK_TVAL_IS_DOUBLE(tv));\n\t\td = DUK_TVAL_GET_DOUBLE(tv);\n#if defined(DUK_USE_PREFER_SIZE)\n\t\tc = DUK_FPCLASSIFY((double) d);\n\t\tif (c == DUK_FP_ZERO || c == DUK_FP_NAN) {\n\t\t\treturn 0;\n\t\t} else {\n\t\t\treturn 1;\n\t\t}\n#else\n\t\tDUK_ASSERT(duk_double_is_nan_or_zero(d) == 0 || duk_double_is_nan_or_zero(d) == 1);\n\t\treturn duk_double_is_nan_or_zero(d) ^ 1;\n#endif\n\t}\n\t}\n\tDUK_UNREACHABLE();\n}\n\n/*\n *  ToNumber()  (E5 Section 9.3)\n *\n *  Value to convert must be on stack top, and is popped before exit.\n *\n *  See: http://www.cs.indiana.edu/~burger/FP-Printing-PLDI96.pdf\n *       http://www.cs.indiana.edu/~burger/fp/index.html\n *\n *  Notes on the conversion:\n *\n *    - There are specific requirements on the accuracy of the conversion\n *      through a \"Mathematical Value\" (MV), so this conversion is not\n *      trivial.\n *\n *    - Quick rejects (e.g. based on first char) are difficult because\n *      the grammar allows leading and trailing white space.\n *\n *    - Quick reject based on string length is difficult even after\n *      accounting for white space; there may be arbitrarily many\n *      decimal digits.\n *\n *    - Standard grammar allows decimal values (\"123\"), hex values\n *      (\"0x123\") and infinities\n *\n *    - Unlike source code literals, ToNumber() coerces empty strings\n *      and strings with only whitespace to zero (not NaN).\n */\n\n/* E5 Section 9.3.1 */\nDUK_LOCAL duk_double_t duk__tonumber_string_raw(duk_hthread *thr) {\n\tduk_small_uint_t s2n_flags;\n\tduk_double_t d;\n\n\tDUK_ASSERT(duk_is_string(thr, -1));\n\n\t/* Quite lenient, e.g. allow empty as zero, but don't allow trailing\n\t * garbage.\n\t */\n\ts2n_flags = DUK_S2N_FLAG_TRIM_WHITE |\n\t            DUK_S2N_FLAG_ALLOW_EXP |\n\t            DUK_S2N_FLAG_ALLOW_PLUS |\n\t            DUK_S2N_FLAG_ALLOW_MINUS |\n\t            DUK_S2N_FLAG_ALLOW_INF |\n\t            DUK_S2N_FLAG_ALLOW_FRAC |\n\t            DUK_S2N_FLAG_ALLOW_NAKED_FRAC |\n\t            DUK_S2N_FLAG_ALLOW_EMPTY_FRAC |\n\t            DUK_S2N_FLAG_ALLOW_EMPTY_AS_ZERO |\n\t            DUK_S2N_FLAG_ALLOW_LEADING_ZERO |\n\t            DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT |\n\t            DUK_S2N_FLAG_ALLOW_AUTO_OCT_INT |\n\t            DUK_S2N_FLAG_ALLOW_AUTO_BIN_INT;\n\n\tduk_numconv_parse(thr, 10 /*radix*/, s2n_flags);\n\n#if defined(DUK_USE_PREFER_SIZE)\n\td = duk_get_number(thr, -1);\n\tduk_pop_unsafe(thr);\n#else\n\tthr->valstack_top--;\n\tDUK_ASSERT(DUK_TVAL_IS_NUMBER(thr->valstack_top));\n\tDUK_ASSERT(DUK_TVAL_IS_DOUBLE(thr->valstack_top));  /* no fastint conversion in numconv now */\n\tDUK_ASSERT(!DUK_TVAL_NEEDS_REFCOUNT_UPDATE(thr->valstack_top));\n\td = DUK_TVAL_GET_DOUBLE(thr->valstack_top);  /* assumes not a fastint */\n\tDUK_TVAL_SET_UNDEFINED(thr->valstack_top);\n#endif\n\n\treturn d;\n}\n\nDUK_INTERNAL duk_double_t duk_js_tonumber(duk_hthread *thr, duk_tval *tv) {\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(tv != NULL);\n\n\tswitch (DUK_TVAL_GET_TAG(tv)) {\n\tcase DUK_TAG_UNDEFINED: {\n\t\t/* return a specific NaN (although not strictly necessary) */\n\t\tduk_double_union du;\n\t\tDUK_DBLUNION_SET_NAN(&du);\n\t\tDUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&du));\n\t\treturn du.d;\n\t}\n\tcase DUK_TAG_NULL: {\n\t\t/* +0.0 */\n\t\treturn 0.0;\n\t}\n\tcase DUK_TAG_BOOLEAN: {\n\t\tif (DUK_TVAL_IS_BOOLEAN_TRUE(tv)) {\n\t\t\treturn 1.0;\n\t\t}\n\t\treturn 0.0;\n\t}\n\tcase DUK_TAG_STRING: {\n\t\t/* For Symbols ToNumber() is always a TypeError. */\n\t\tduk_hstring *h = DUK_TVAL_GET_STRING(tv);\n\t\tif (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(h))) {\n\t\t\tDUK_ERROR_TYPE(thr, DUK_STR_CANNOT_NUMBER_COERCE_SYMBOL);\n\t\t}\n\t\tduk_push_hstring(thr, h);\n\t\treturn duk__tonumber_string_raw(thr);\n\t}\n\tcase DUK_TAG_BUFFER:  /* plain buffer treated like object */\n\tcase DUK_TAG_OBJECT: {\n\t\tduk_double_t d;\n\t\tduk_push_tval(thr, tv);\n\t\tduk_to_primitive(thr, -1, DUK_HINT_NUMBER);  /* 'tv' becomes invalid */\n\n\t\t/* recursive call for a primitive value (guaranteed not to cause second\n\t\t * recursion).\n\t\t */\n\t\tDUK_ASSERT(duk_get_tval(thr, -1) != NULL);\n\t\td = duk_js_tonumber(thr, duk_get_tval(thr, -1));\n\n\t\tduk_pop_unsafe(thr);\n\t\treturn d;\n\t}\n\tcase DUK_TAG_POINTER: {\n\t\t/* Coerce like boolean */\n\t\tvoid *p = DUK_TVAL_GET_POINTER(tv);\n\t\treturn (p != NULL ? 1.0 : 0.0);\n\t}\n\tcase DUK_TAG_LIGHTFUNC: {\n\t\t/* +(function(){}) -> NaN */\n\t\treturn DUK_DOUBLE_NAN;\n\t}\n#if defined(DUK_USE_FASTINT)\n\tcase DUK_TAG_FASTINT:\n\t\treturn (duk_double_t) DUK_TVAL_GET_FASTINT(tv);\n#endif\n\tdefault: {\n\t\t/* number */\n\t\tDUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));\n\t\tDUK_ASSERT(DUK_TVAL_IS_DOUBLE(tv));\n\t\treturn DUK_TVAL_GET_DOUBLE(tv);\n\t}\n\t}\n\n\tDUK_UNREACHABLE();\n}\n\n/*\n *  ToInteger()  (E5 Section 9.4)\n */\n\n/* exposed, used by e.g. duk_bi_date.c */\nDUK_INTERNAL duk_double_t duk_js_tointeger_number(duk_double_t x) {\n#if defined(DUK_USE_PREFER_SIZE)\n\tduk_small_int_t c = (duk_small_int_t) DUK_FPCLASSIFY(x);\n\n\tif (DUK_UNLIKELY(c == DUK_FP_NAN)) {\n\t\treturn 0.0;\n\t} else if (DUK_UNLIKELY(c == DUK_FP_INFINITE)) {\n\t\treturn x;\n\t} else {\n\t\t/* Finite, including neg/pos zero.  Neg zero sign must be\n\t\t * preserved.\n\t\t */\n\t\treturn duk_double_trunc_towards_zero(x);\n\t}\n#else  /* DUK_USE_PREFER_SIZE */\n\t/* NaN and Infinity have the same exponent so it's a cheap\n\t * initial check for the rare path.\n\t */\n\tif (DUK_UNLIKELY(duk_double_is_nan_or_inf(x) != 0U)) {\n\t\tif (duk_double_is_nan(x)) {\n\t\t\treturn 0.0;\n\t\t} else {\n\t\t\treturn x;\n\t\t}\n\t} else {\n\t\treturn duk_double_trunc_towards_zero(x);\n\t}\n#endif  /* DUK_USE_PREFER_SIZE */\n}\n\nDUK_INTERNAL duk_double_t duk_js_tointeger(duk_hthread *thr, duk_tval *tv) {\n\t/* XXX: fastint */\n\tduk_double_t d = duk_js_tonumber(thr, tv);  /* invalidates tv */\n\treturn duk_js_tointeger_number(d);\n}\n\n/*\n *  ToInt32(), ToUint32(), ToUint16()  (E5 Sections 9.5, 9.6, 9.7)\n */\n\n/* combined algorithm matching E5 Sections 9.5 and 9.6 */\nDUK_LOCAL duk_double_t duk__toint32_touint32_helper(duk_double_t x, duk_bool_t is_toint32) {\n#if defined (DUK_USE_PREFER_SIZE)\n\tduk_small_int_t c;\n#endif\n\n#if defined (DUK_USE_PREFER_SIZE)\n\tc = (duk_small_int_t) DUK_FPCLASSIFY(x);\n\tif (c == DUK_FP_NAN || c == DUK_FP_ZERO || c == DUK_FP_INFINITE) {\n\t\treturn 0.0;\n\t}\n#else\n\tif (duk_double_is_nan_zero_inf(x)) {\n\t\treturn 0.0;\n\t}\n#endif\n\n\t/* x = sign(x) * floor(abs(x)), i.e. truncate towards zero, keep sign */\n\tx = duk_double_trunc_towards_zero(x);\n\n\t/* NOTE: fmod(x) result sign is same as sign of x, which\n\t * differs from what Javascript wants (see Section 9.6).\n\t */\n\n\tx = DUK_FMOD(x, DUK_DOUBLE_2TO32);    /* -> x in ]-2**32, 2**32[ */\n\n\tif (x < 0.0) {\n\t\tx += DUK_DOUBLE_2TO32;\n\t}\n\tDUK_ASSERT(x >= 0 && x < DUK_DOUBLE_2TO32);  /* -> x in [0, 2**32[ */\n\n\tif (is_toint32) {\n\t\tif (x >= DUK_DOUBLE_2TO31) {\n\t\t\t/* x in [2**31, 2**32[ */\n\n\t\t\tx -= DUK_DOUBLE_2TO32;  /* -> x in [-2**31,2**31[ */\n\t\t}\n\t}\n\n\treturn x;\n}\n\nDUK_INTERNAL duk_int32_t duk_js_toint32(duk_hthread *thr, duk_tval *tv) {\n\tduk_double_t d;\n\n#if defined(DUK_USE_FASTINT)\n\tif (DUK_TVAL_IS_FASTINT(tv)) {\n\t\treturn DUK_TVAL_GET_FASTINT_I32(tv);\n\t}\n#endif\n\n\td = duk_js_tonumber(thr, tv);  /* invalidates tv */\n\td = duk__toint32_touint32_helper(d, 1);\n\tDUK_ASSERT(DUK_FPCLASSIFY(d) == DUK_FP_ZERO || DUK_FPCLASSIFY(d) == DUK_FP_NORMAL);\n\tDUK_ASSERT(d >= -2147483648.0 && d <= 2147483647.0);  /* [-0x80000000,0x7fffffff] */\n\tDUK_ASSERT(d == ((duk_double_t) ((duk_int32_t) d)));  /* whole, won't clip */\n\treturn (duk_int32_t) d;\n}\n\n\nDUK_INTERNAL duk_uint32_t duk_js_touint32(duk_hthread *thr, duk_tval *tv) {\n\tduk_double_t d;\n\n#if defined(DUK_USE_FASTINT)\n\tif (DUK_TVAL_IS_FASTINT(tv)) {\n\t\treturn DUK_TVAL_GET_FASTINT_U32(tv);\n\t}\n#endif\n\n\td = duk_js_tonumber(thr, tv);  /* invalidates tv */\n\td = duk__toint32_touint32_helper(d, 0);\n\tDUK_ASSERT(DUK_FPCLASSIFY(d) == DUK_FP_ZERO || DUK_FPCLASSIFY(d) == DUK_FP_NORMAL);\n\tDUK_ASSERT(d >= 0.0 && d <= 4294967295.0);  /* [0x00000000, 0xffffffff] */\n\tDUK_ASSERT(d == ((duk_double_t) ((duk_uint32_t) d)));  /* whole, won't clip */\n\treturn (duk_uint32_t) d;\n\n}\n\nDUK_INTERNAL duk_uint16_t duk_js_touint16(duk_hthread *thr, duk_tval *tv) {\n\t/* should be a safe way to compute this */\n\treturn (duk_uint16_t) (duk_js_touint32(thr, tv) & 0x0000ffffU);\n}\n\n/*\n *  ToString()  (E5 Section 9.8)\n *  ToObject()  (E5 Section 9.9)\n *  CheckObjectCoercible()  (E5 Section 9.10)\n *  IsCallable()  (E5 Section 9.11)\n *\n *  ==> implemented in the API.\n */\n\n/*\n *  Loose equality, strict equality, and SameValue (E5 Sections 11.9.1, 11.9.4,\n *  9.12).  These have much in common so they can share some helpers.\n *\n *  Future work notes:\n *\n *    - Current implementation (and spec definition) has recursion; this should\n *      be fixed if possible.\n *\n *    - String-to-number coercion should be possible without going through the\n *      value stack (and be more compact) if a shared helper is invoked.\n */\n\n/* Note that this is the same operation for strict and loose equality:\n *  - E5 Section 11.9.3, step 1.c (loose)\n *  - E5 Section 11.9.6, step 4 (strict)\n */\n\nDUK_LOCAL duk_bool_t duk__js_equals_number(duk_double_t x, duk_double_t y) {\n#if defined(DUK_USE_PARANOID_MATH)\n\t/* Straightforward algorithm, makes fewer compiler assumptions. */\n\tduk_small_int_t cx = (duk_small_int_t) DUK_FPCLASSIFY(x);\n\tduk_small_int_t cy = (duk_small_int_t) DUK_FPCLASSIFY(y);\n\tif (cx == DUK_FP_NAN || cy == DUK_FP_NAN) {\n\t\treturn 0;\n\t}\n\tif (cx == DUK_FP_ZERO && cy == DUK_FP_ZERO) {\n\t\treturn 1;\n\t}\n\tif (x == y) {\n\t\treturn 1;\n\t}\n\treturn 0;\n#else  /* DUK_USE_PARANOID_MATH */\n\t/* Better equivalent algorithm.  If the compiler is compliant, C and\n\t * Ecmascript semantics are identical for this particular comparison.\n\t * In particular, NaNs must never compare equal and zeroes must compare\n\t * equal regardless of sign.  Could also use a macro, but this inlines\n\t * already nicely (no difference on gcc, for instance).\n\t */\n\tif (x == y) {\n\t\t/* IEEE requires that NaNs compare false */\n\t\tDUK_ASSERT(DUK_FPCLASSIFY(x) != DUK_FP_NAN);\n\t\tDUK_ASSERT(DUK_FPCLASSIFY(y) != DUK_FP_NAN);\n\t\treturn 1;\n\t} else {\n\t\t/* IEEE requires that zeros compare the same regardless\n\t\t * of their signed, so if both x and y are zeroes, they\n\t\t * are caught above.\n\t\t */\n\t\tDUK_ASSERT(!(DUK_FPCLASSIFY(x) == DUK_FP_ZERO && DUK_FPCLASSIFY(y) == DUK_FP_ZERO));\n\t\treturn 0;\n\t}\n#endif  /* DUK_USE_PARANOID_MATH */\n}\n\nDUK_LOCAL duk_bool_t duk__js_samevalue_number(duk_double_t x, duk_double_t y) {\n#if defined(DUK_USE_PARANOID_MATH)\n\tduk_small_int_t cx = (duk_small_int_t) DUK_FPCLASSIFY(x);\n\tduk_small_int_t cy = (duk_small_int_t) DUK_FPCLASSIFY(y);\n\n\tif (cx == DUK_FP_NAN && cy == DUK_FP_NAN) {\n\t\t/* SameValue(NaN, NaN) = true, regardless of NaN sign or extra bits */\n\t\treturn 1;\n\t}\n\tif (cx == DUK_FP_ZERO && cy == DUK_FP_ZERO) {\n\t\t/* Note: cannot assume that a non-zero return value of signbit() would\n\t\t * always be the same -- hence cannot (portably) use something like:\n\t\t *\n\t\t *     signbit(x) == signbit(y)\n\t\t */\n\t\tduk_small_int_t sx = DUK_SIGNBIT(x) ? 1 : 0;\n\t\tduk_small_int_t sy = DUK_SIGNBIT(y) ? 1 : 0;\n\t\treturn (sx == sy);\n\t}\n\n\t/* normal comparison; known:\n\t *   - both x and y are not NaNs (but one of them can be)\n\t *   - both x and y are not zero (but one of them can be)\n\t *   - x and y may be denormal or infinite\n\t */\n\n\treturn (x == y);\n#else  /* DUK_USE_PARANOID_MATH */\n\tduk_small_int_t cx = (duk_small_int_t) DUK_FPCLASSIFY(x);\n\tduk_small_int_t cy = (duk_small_int_t) DUK_FPCLASSIFY(y);\n\n\tif (x == y) {\n\t\t/* IEEE requires that NaNs compare false */\n\t\tDUK_ASSERT(DUK_FPCLASSIFY(x) != DUK_FP_NAN);\n\t\tDUK_ASSERT(DUK_FPCLASSIFY(y) != DUK_FP_NAN);\n\n\t\t/* Using classification has smaller footprint than direct comparison. */\n\t\tif (DUK_UNLIKELY(cx == DUK_FP_ZERO && cy == DUK_FP_ZERO)) {\n\t\t\t/* Note: cannot assume that a non-zero return value of signbit() would\n\t\t\t * always be the same -- hence cannot (portably) use something like:\n\t\t\t *\n\t\t\t *     signbit(x) == signbit(y)\n\t\t\t */\n\t\t\treturn duk_double_same_sign(x, y);\n\t\t}\n\t\treturn 1;\n\t} else {\n\t\t/* IEEE requires that zeros compare the same regardless\n\t\t * of their sign, so if both x and y are zeroes, they\n\t\t * are caught above.\n\t\t */\n\t\tDUK_ASSERT(!(DUK_FPCLASSIFY(x) == DUK_FP_ZERO && DUK_FPCLASSIFY(y) == DUK_FP_ZERO));\n\n\t\t/* Difference to non-strict/strict comparison is that NaNs compare\n\t\t * equal and signed zero signs matter.\n\t\t */\n\t\tif (DUK_UNLIKELY(cx == DUK_FP_NAN && cy == DUK_FP_NAN)) {\n\t\t\t/* SameValue(NaN, NaN) = true, regardless of NaN sign or extra bits */\n\t\t\treturn 1;\n\t\t}\n\t\treturn 0;\n\t}\n#endif  /* DUK_USE_PARANOID_MATH */\n}\n\nDUK_INTERNAL duk_bool_t duk_js_equals_helper(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y, duk_small_uint_t flags) {\n\tduk_uint_t type_mask_x;\n\tduk_uint_t type_mask_y;\n\n\t/* If flags != 0 (strict or SameValue), thr can be NULL.  For loose\n\t * equals comparison it must be != NULL.\n\t */\n\tDUK_ASSERT(flags != 0 || thr != NULL);\n\n\t/*\n\t *  Same type?\n\t *\n\t *  Note: since number values have no explicit tag in the 8-byte\n\t *  representation, need the awkward if + switch.\n\t */\n\n#if defined(DUK_USE_FASTINT)\n\tif (DUK_TVAL_IS_FASTINT(tv_x) && DUK_TVAL_IS_FASTINT(tv_y)) {\n\t\tif (DUK_TVAL_GET_FASTINT(tv_x) == DUK_TVAL_GET_FASTINT(tv_y)) {\n\t\t\treturn 1;\n\t\t} else {\n\t\t\treturn 0;\n\t\t}\n\t}\n\telse\n#endif\n\tif (DUK_TVAL_IS_NUMBER(tv_x) && DUK_TVAL_IS_NUMBER(tv_y)) {\n\t\tduk_double_t d1, d2;\n\n\t\t/* Catches both doubles and cases where only one argument is\n\t\t * a fastint so can't assume a double.\n\t\t */\n\t\td1 = DUK_TVAL_GET_NUMBER(tv_x);\n\t\td2 = DUK_TVAL_GET_NUMBER(tv_y);\n\t\tif (DUK_UNLIKELY((flags & DUK_EQUALS_FLAG_SAMEVALUE) != 0)) {\n\t\t\t/* SameValue */\n\t\t\treturn duk__js_samevalue_number(d1, d2);\n\t\t} else {\n\t\t\t/* equals and strict equals */\n\t\t\treturn duk__js_equals_number(d1, d2);\n\t\t}\n\t} else if (DUK_TVAL_GET_TAG(tv_x) == DUK_TVAL_GET_TAG(tv_y)) {\n\t\tswitch (DUK_TVAL_GET_TAG(tv_x)) {\n\t\tcase DUK_TAG_UNDEFINED:\n\t\tcase DUK_TAG_NULL: {\n\t\t\treturn 1;\n\t\t}\n\t\tcase DUK_TAG_BOOLEAN: {\n\t\t\treturn DUK_TVAL_GET_BOOLEAN(tv_x) == DUK_TVAL_GET_BOOLEAN(tv_y);\n\t\t}\n\t\tcase DUK_TAG_POINTER: {\n\t\t\treturn DUK_TVAL_GET_POINTER(tv_x) == DUK_TVAL_GET_POINTER(tv_y);\n\t\t}\n\t\tcase DUK_TAG_STRING:\n\t\tcase DUK_TAG_OBJECT: {\n\t\t\t/* Heap pointer comparison suffices for strings and objects.\n\t\t\t * Symbols compare equal if they have the same internal\n\t\t\t * representation; again heap pointer comparison suffices.\n\t\t\t */\n\t\t\treturn DUK_TVAL_GET_HEAPHDR(tv_x) == DUK_TVAL_GET_HEAPHDR(tv_y);\n\t\t}\n\t\tcase DUK_TAG_BUFFER: {\n\t\t\t/* In Duktape 2.x plain buffers mimic Uint8Array objects\n\t\t\t * so always compare by heap pointer.  In Duktape 1.x\n\t\t\t * strict comparison would compare heap pointers and\n\t\t\t * non-strict would compare contents.\n\t\t\t */\n\t\t\treturn DUK_TVAL_GET_HEAPHDR(tv_x) == DUK_TVAL_GET_HEAPHDR(tv_y);\n\t\t}\n\t\tcase DUK_TAG_LIGHTFUNC: {\n\t\t\t/* At least 'magic' has a significant impact on function\n\t\t\t * identity.\n\t\t\t */\n\t\t\tduk_small_uint_t lf_flags_x;\n\t\t\tduk_small_uint_t lf_flags_y;\n\t\t\tduk_c_function func_x;\n\t\t\tduk_c_function func_y;\n\n\t\t\tDUK_TVAL_GET_LIGHTFUNC(tv_x, func_x, lf_flags_x);\n\t\t\tDUK_TVAL_GET_LIGHTFUNC(tv_y, func_y, lf_flags_y);\n\t\t\treturn ((func_x == func_y) && (lf_flags_x == lf_flags_y)) ? 1 : 0;\n\t\t}\n#if defined(DUK_USE_FASTINT)\n\t\tcase DUK_TAG_FASTINT:\n#endif\n\t\tdefault: {\n\t\t\tDUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv_x));\n\t\t\tDUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv_y));\n\t\t\tDUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_x));\n\t\t\tDUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_y));\n\t\t\tDUK_UNREACHABLE();\n\t\t\treturn 0;\n\t\t}\n\t\t}\n\t}\n\n\tif ((flags & (DUK_EQUALS_FLAG_STRICT | DUK_EQUALS_FLAG_SAMEVALUE)) != 0) {\n\t\treturn 0;\n\t}\n\n\tDUK_ASSERT(flags == 0);  /* non-strict equality from here on */\n\n\t/*\n\t *  Types are different; various cases for non-strict comparison\n\t *\n\t *  Since comparison is symmetric, we use a \"swap trick\" to reduce\n\t *  code size.\n\t */\n\n\ttype_mask_x = duk_get_type_mask_tval(tv_x);\n\ttype_mask_y = duk_get_type_mask_tval(tv_y);\n\n\t/* Undefined/null are considered equal (e.g. \"null == undefined\" -> true). */\n\tif ((type_mask_x & (DUK_TYPE_MASK_UNDEFINED | DUK_TYPE_MASK_NULL)) &&\n\t    (type_mask_y & (DUK_TYPE_MASK_NULL | DUK_TYPE_MASK_UNDEFINED))) {\n\t\treturn 1;\n\t}\n\n\t/* Number/string -> coerce string to number (e.g. \"'1.5' == 1.5\" -> true). */\n\tif ((type_mask_x & DUK_TYPE_MASK_NUMBER) && (type_mask_y & DUK_TYPE_MASK_STRING)) {\n\t\tif (!DUK_TVAL_STRING_IS_SYMBOL(tv_y)) {\n\t\t\tduk_double_t d1, d2;\n\t\t\td1 = DUK_TVAL_GET_NUMBER(tv_x);\n\t\t\td2 = duk_to_number_tval(thr, tv_y);\n\t\t\treturn duk__js_equals_number(d1, d2);\n\t\t}\n\t}\n\tif ((type_mask_x & DUK_TYPE_MASK_STRING) && (type_mask_y & DUK_TYPE_MASK_NUMBER)) {\n\t\tif (!DUK_TVAL_STRING_IS_SYMBOL(tv_x)) {\n\t\t\tduk_double_t d1, d2;\n\t\t\td1 = DUK_TVAL_GET_NUMBER(tv_y);\n\t\t\td2 = duk_to_number_tval(thr, tv_x);\n\t\t\treturn duk__js_equals_number(d1, d2);\n\t\t}\n\t}\n\n\t/* Boolean/any -> coerce boolean to number and try again.  If boolean is\n\t * compared to a pointer, the final comparison after coercion now always\n\t * yields false (as pointer vs. number compares to false), but this is\n\t * not special cased.\n\t *\n\t * ToNumber(bool) is +1.0 or 0.0.  Tagged boolean value is always 0 or 1.\n\t */\n\tif (type_mask_x & DUK_TYPE_MASK_BOOLEAN) {\n\t\tDUK_ASSERT(DUK_TVAL_GET_BOOLEAN(tv_x) == 0 || DUK_TVAL_GET_BOOLEAN(tv_x) == 1);\n\t\tduk_push_uint(thr, DUK_TVAL_GET_BOOLEAN(tv_x));\n\t\tduk_push_tval(thr, tv_y);\n\t\tgoto recursive_call;\n\t}\n\tif (type_mask_y & DUK_TYPE_MASK_BOOLEAN) {\n\t\tDUK_ASSERT(DUK_TVAL_GET_BOOLEAN(tv_y) == 0 || DUK_TVAL_GET_BOOLEAN(tv_y) == 1);\n\t\tduk_push_tval(thr, tv_x);\n\t\tduk_push_uint(thr, DUK_TVAL_GET_BOOLEAN(tv_y));\n\t\tgoto recursive_call;\n\t}\n\n\t/* String-number-symbol/object -> coerce object to primitive (apparently without hint), then try again. */\n\tif ((type_mask_x & (DUK_TYPE_MASK_STRING | DUK_TYPE_MASK_NUMBER)) &&\n\t    (type_mask_y & DUK_TYPE_MASK_OBJECT)) {\n\t\t/* No symbol check needed because symbols and strings are accepted. */\n\t\tduk_push_tval(thr, tv_x);\n\t\tduk_push_tval(thr, tv_y);\n\t\tduk_to_primitive(thr, -1, DUK_HINT_NONE);  /* apparently no hint? */\n\t\tgoto recursive_call;\n\t}\n\tif ((type_mask_x & DUK_TYPE_MASK_OBJECT) &&\n\t    (type_mask_y & (DUK_TYPE_MASK_STRING | DUK_TYPE_MASK_NUMBER))) {\n\t\t/* No symbol check needed because symbols and strings are accepted. */\n\t\tduk_push_tval(thr, tv_x);\n\t\tduk_push_tval(thr, tv_y);\n\t\tduk_to_primitive(thr, -2, DUK_HINT_NONE);  /* apparently no hint? */\n\t\tgoto recursive_call;\n\t}\n\n\t/* Nothing worked -> not equal. */\n\treturn 0;\n\n recursive_call:\n\t/* Shared code path to call the helper again with arguments on stack top. */\n\t{\n\t\tduk_bool_t rc;\n\t\trc = duk_js_equals_helper(thr,\n\t\t                          DUK_GET_TVAL_NEGIDX(thr, -2),\n\t\t                          DUK_GET_TVAL_NEGIDX(thr, -1),\n\t\t                          0 /*flags:nonstrict*/);\n\t\tduk_pop_2_unsafe(thr);\n\t\treturn rc;\n\t}\n}\n\n/*\n *  Comparisons (x >= y, x > y, x <= y, x < y)\n *\n *  E5 Section 11.8.5: implement 'x < y' and then use negate and eval_left_first\n *  flags to get the rest.\n */\n\n/* XXX: this should probably just operate on the stack top, because it\n * needs to push stuff on the stack anyway...\n */\n\nDUK_INTERNAL duk_small_int_t duk_js_data_compare(const duk_uint8_t *buf1, const duk_uint8_t *buf2, duk_size_t len1, duk_size_t len2) {\n\tduk_size_t prefix_len;\n\tduk_small_int_t rc;\n\n\tprefix_len = (len1 <= len2 ? len1 : len2);\n\n\t/* DUK_MEMCMP() is guaranteed to return zero (equal) for zero length\n\t * inputs so no zero length check is needed.\n\t */\n\trc = DUK_MEMCMP((const void *) buf1,\n\t                (const void *) buf2,\n\t                (size_t) prefix_len);\n\n\tif (rc < 0) {\n\t\treturn -1;\n\t} else if (rc > 0) {\n\t\treturn 1;\n\t}\n\n\t/* prefix matches, lengths matter now */\n\tif (len1 < len2) {\n\t\t/* e.g. \"x\" < \"xx\" */\n\t\treturn -1;\n\t} else if (len1 > len2) {\n\t\treturn 1;\n\t}\n\n\treturn 0;\n}\n\nDUK_INTERNAL duk_small_int_t duk_js_string_compare(duk_hstring *h1, duk_hstring *h2) {\n\t/*\n\t *  String comparison (E5 Section 11.8.5, step 4), which\n\t *  needs to compare codepoint by codepoint.\n\t *\n\t *  However, UTF-8 allows us to use strcmp directly: the shared\n\t *  prefix will be encoded identically (UTF-8 has unique encoding)\n\t *  and the first differing character can be compared with a simple\n\t *  unsigned byte comparison (which strcmp does).\n\t *\n\t *  This will not work properly for non-xutf-8 strings, but this\n\t *  is not an issue for compliance.\n\t */\n\n\tDUK_ASSERT(h1 != NULL);\n\tDUK_ASSERT(h2 != NULL);\n\n\treturn duk_js_data_compare((const duk_uint8_t *) DUK_HSTRING_GET_DATA(h1),\n\t                           (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h2),\n\t                           (duk_size_t) DUK_HSTRING_GET_BYTELEN(h1),\n\t                           (duk_size_t) DUK_HSTRING_GET_BYTELEN(h2));\n}\n\n#if 0  /* unused */\nDUK_INTERNAL duk_small_int_t duk_js_buffer_compare(duk_heap *heap, duk_hbuffer *h1, duk_hbuffer *h2) {\n\t/* Similar to String comparison. */\n\n\tDUK_ASSERT(h1 != NULL);\n\tDUK_ASSERT(h2 != NULL);\n\tDUK_UNREF(heap);\n\n\treturn duk_js_data_compare((const duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(heap, h1),\n\t                           (const duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(heap, h2),\n\t                           (duk_size_t) DUK_HBUFFER_GET_SIZE(h1),\n\t                           (duk_size_t) DUK_HBUFFER_GET_SIZE(h2));\n}\n#endif\n\n#if defined(DUK_USE_FASTINT)\nDUK_LOCAL duk_bool_t duk__compare_fastint(duk_bool_t retval, duk_int64_t v1, duk_int64_t v2) {\n\tDUK_ASSERT(retval == 0 || retval == 1);\n\tif (v1 < v2) {\n\t\treturn retval ^ 1;\n\t} else {\n\t\treturn retval;\n\t}\n}\n#endif\n\n#if defined(DUK_USE_PARANOID_MATH)\nDUK_LOCAL duk_bool_t duk__compare_number(duk_bool_t retval, duk_double_t d1, duk_double_t d2) {\n\tduk_small_int_t c1, s1, c2, s2;\n\n\tDUK_ASSERT(retval == 0 || retval == 1);\n\tc1 = (duk_small_int_t) DUK_FPCLASSIFY(d1);\n\ts1 = (duk_small_int_t) DUK_SIGNBIT(d1);\n\tc2 = (duk_small_int_t) DUK_FPCLASSIFY(d2);\n\ts2 = (duk_small_int_t) DUK_SIGNBIT(d2);\n\n\tif (c1 == DUK_FP_NAN || c2 == DUK_FP_NAN) {\n\t\treturn 0;  /* Always false, regardless of negation. */\n\t}\n\n\tif (c1 == DUK_FP_ZERO && c2 == DUK_FP_ZERO) {\n\t\t/* For all combinations: +0 < +0, +0 < -0, -0 < +0, -0 < -0,\n\t\t * steps e, f, and g.\n\t\t */\n\t\treturn retval;  /* false */\n\t}\n\n\tif (d1 == d2) {\n\t\treturn retval;  /* false */\n\t}\n\n\tif (c1 == DUK_FP_INFINITE && s1 == 0) {\n\t\t/* x == +Infinity */\n\t\treturn retval;  /* false */\n\t}\n\n\tif (c2 == DUK_FP_INFINITE && s2 == 0) {\n\t\t/* y == +Infinity */\n\t\treturn retval ^ 1;  /* true */\n\t}\n\n\tif (c2 == DUK_FP_INFINITE && s2 != 0) {\n\t\t/* y == -Infinity */\n\t\treturn retval;  /* false */\n\t}\n\n\tif (c1 == DUK_FP_INFINITE && s1 != 0) {\n\t\t/* x == -Infinity */\n\t\treturn retval ^ 1;  /* true */\n\t}\n\n\tif (d1 < d2) {\n\t\treturn retval ^ 1;  /* true */\n\t}\n\n\treturn retval;  /* false */\n}\n#else  /* DUK_USE_PARANOID_MATH */\nDUK_LOCAL duk_bool_t duk__compare_number(duk_bool_t retval, duk_double_t d1, duk_double_t d2) {\n\t/* This comparison tree relies doesn't match the exact steps in\n\t * E5 Section 11.8.5 but should produce the same results.  The\n\t * steps rely on exact IEEE semantics for NaNs, etc.\n\t */\n\n\tDUK_ASSERT(retval == 0 || retval == 1);\n\tif (d1 < d2) {\n\t\t/* In no case should both (d1 < d2) and (d2 < d1) be true.\n\t\t * It's possible that neither is true though, and that's\n\t\t * handled below.\n\t\t */\n\t\tDUK_ASSERT(!(d2 < d1));\n\n\t\t/* - d1 < d2, both d1/d2 are normals (not Infinity, not NaN)\n\t\t * - d2 is +Infinity, d1 != +Infinity and NaN\n\t\t * - d1 is -Infinity, d2 != -Infinity and NaN\n\t\t */\n\t\treturn retval ^ 1;\n\t} else {\n\t\tif (d2 < d1) {\n\t\t\t/* - !(d1 < d2), both d1/d2 are normals (not Infinity, not NaN)\n\t\t\t * - d1 is +Infinity, d2 != +Infinity and NaN\n\t\t\t * - d2 is -Infinity, d1 != -Infinity and NaN\n\t\t\t */\n\t\t\treturn retval;\n\t\t} else {\n\t\t\t/* - d1 and/or d2 is NaN\n\t\t\t * - d1 and d2 are both +/- 0\n\t\t\t * - d1 == d2 (including infinities)\n\t\t\t */\n\t\t\tif (duk_double_is_nan(d1) || duk_double_is_nan(d2)) {\n\t\t\t\t/* Note: undefined from Section 11.8.5 always\n\t\t\t\t * results in false return (see e.g. Section\n\t\t\t\t * 11.8.3) - hence special treatment here.\n\t\t\t\t */\n\t\t\t\treturn 0;  /* zero regardless of negation */\n\t\t\t} else {\n\t\t\t\treturn retval;\n\t\t\t}\n\t\t}\n\t}\n}\n#endif  /* DUK_USE_PARANOID_MATH */\n\nDUK_INTERNAL duk_bool_t duk_js_compare_helper(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y, duk_small_uint_t flags) {\n\tduk_double_t d1, d2;\n\tduk_small_int_t rc;\n\tduk_bool_t retval;\n\n\tDUK_ASSERT(DUK_COMPARE_FLAG_NEGATE == 1);  /* Rely on this flag being lowest. */\n\tretval = flags & DUK_COMPARE_FLAG_NEGATE;\n\tDUK_ASSERT(retval == 0 || retval == 1);\n\n\t/* Fast path for fastints */\n#if defined(DUK_USE_FASTINT)\n\tif (DUK_LIKELY(DUK_TVAL_IS_FASTINT(tv_x) && DUK_TVAL_IS_FASTINT(tv_y))) {\n\t\treturn duk__compare_fastint(retval,\n\t\t                            DUK_TVAL_GET_FASTINT(tv_x),\n\t\t                            DUK_TVAL_GET_FASTINT(tv_y));\n\t}\n#endif  /* DUK_USE_FASTINT */\n\n\t/* Fast path for numbers (one of which may be a fastint) */\n#if !defined(DUK_USE_PREFER_SIZE)\n\tif (DUK_LIKELY(DUK_TVAL_IS_NUMBER(tv_x) && DUK_TVAL_IS_NUMBER(tv_y))) {\n\t\treturn duk__compare_number(retval,\n\t\t                           DUK_TVAL_GET_NUMBER(tv_x),\n\t\t                           DUK_TVAL_GET_NUMBER(tv_y));\n\t}\n#endif\n\n\t/* Slow path */\n\n\tduk_push_tval(thr, tv_x);\n\tduk_push_tval(thr, tv_y);\n\n\tif (flags & DUK_COMPARE_FLAG_EVAL_LEFT_FIRST) {\n\t\tduk_to_primitive(thr, -2, DUK_HINT_NUMBER);\n\t\tduk_to_primitive(thr, -1, DUK_HINT_NUMBER);\n\t} else {\n\t\tduk_to_primitive(thr, -1, DUK_HINT_NUMBER);\n\t\tduk_to_primitive(thr, -2, DUK_HINT_NUMBER);\n\t}\n\n\t/* Note: reuse variables */\n\ttv_x = DUK_GET_TVAL_NEGIDX(thr, -2);\n\ttv_y = DUK_GET_TVAL_NEGIDX(thr, -1);\n\n\tif (DUK_TVAL_IS_STRING(tv_x) && DUK_TVAL_IS_STRING(tv_y)) {\n\t\tduk_hstring *h1 = DUK_TVAL_GET_STRING(tv_x);\n\t\tduk_hstring *h2 = DUK_TVAL_GET_STRING(tv_y);\n\t\tDUK_ASSERT(h1 != NULL);\n\t\tDUK_ASSERT(h2 != NULL);\n\n\t\tif (DUK_LIKELY(!DUK_HSTRING_HAS_SYMBOL(h1) && !DUK_HSTRING_HAS_SYMBOL(h2))) {\n\t\t\trc = duk_js_string_compare(h1, h2);\n\t\t\tduk_pop_2_unsafe(thr);\n\t\t\tif (rc < 0) {\n\t\t\t\treturn retval ^ 1;\n\t\t\t} else {\n\t\t\t\treturn retval;\n\t\t\t}\n\t\t}\n\n\t\t/* One or both are Symbols: fall through to handle in the\n\t\t * generic path.  Concretely, ToNumber() will fail.\n\t\t */\n\t}\n\n\t/* Ordering should not matter (E5 Section 11.8.5, step 3.a). */\n#if 0\n\tif (flags & DUK_COMPARE_FLAG_EVAL_LEFT_FIRST) {\n\t\td1 = duk_to_number_m2(thr);\n\t\td2 = duk_to_number_m1(thr);\n\t} else {\n\t\td2 = duk_to_number_m1(thr);\n\t\td1 = duk_to_number_m2(thr);\n\t}\n#endif\n\td1 = duk_to_number_m2(thr);\n\td2 = duk_to_number_m1(thr);\n\n\t/* We want to duk_pop_2_unsafe(thr); because the values are numbers\n\t * no decref check is needed.\n\t */\n#if defined(DUK_USE_PREFER_SIZE)\n\tduk_pop_2_nodecref_unsafe(thr);\n#else\n\tDUK_ASSERT(!DUK_TVAL_NEEDS_REFCOUNT_UPDATE(duk_get_tval(thr, -2)));\n\tDUK_ASSERT(!DUK_TVAL_NEEDS_REFCOUNT_UPDATE(duk_get_tval(thr, -1)));\n\tDUK_ASSERT(duk_get_top(thr) >= 2);\n\tthr->valstack_top -= 2;\n\ttv_x = thr->valstack_top;\n\ttv_y = tv_x + 1;\n\tDUK_TVAL_SET_UNDEFINED(tv_x);  /* Value stack policy */\n\tDUK_TVAL_SET_UNDEFINED(tv_y);\n#endif\n\n\treturn duk__compare_number(retval, d1, d2);\n}\n\n/*\n *  instanceof\n */\n\n/*\n *  E5 Section 11.8.6 describes the main algorithm, which uses\n *  [[HasInstance]].  [[HasInstance]] is defined for only\n *  function objects:\n *\n *    - Normal functions:\n *      E5 Section 15.3.5.3\n *    - Functions established with Function.prototype.bind():\n *      E5 Section 15.3.4.5.3\n *\n *  For other objects, a TypeError is thrown.\n *\n *  Limited Proxy support: don't support 'getPrototypeOf' trap but\n *  continue lookup in Proxy target if the value is a Proxy.\n */\n\nDUK_INTERNAL duk_bool_t duk_js_instanceof(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y) {\n\tduk_hobject *func;\n\tduk_hobject *val;\n\tduk_hobject *proto;\n\tduk_tval *tv;\n\tduk_bool_t skip_first;\n\tduk_uint_t sanity;\n\n\t/*\n\t *  Get the values onto the stack first.  It would be possible to cover\n\t *  some normal cases without resorting to the value stack.\n\t *\n\t *  The right hand side could be a light function (as they generally\n\t *  behave like objects).  Light functions never have a 'prototype'\n\t *  property so E5.1 Section 15.3.5.3 step 3 always throws a TypeError.\n\t *  Using duk_require_hobject() is thus correct (except for error msg).\n\t */\n\n\tduk_push_tval(thr, tv_x);\n\tduk_push_tval(thr, tv_y);\n\tfunc = duk_require_hobject(thr, -1);\n\tDUK_ASSERT(func != NULL);\n\n\t/*\n\t *  For bound objects, [[HasInstance]] just calls the target function\n\t *  [[HasInstance]].  If that is again a bound object, repeat until\n\t *  we find a non-bound Function object.\n\t *\n\t *  The bound function chain is now \"collapsed\" so there can be only\n\t *  one bound function in the chain.\n\t */\n\n\tif (!DUK_HOBJECT_IS_CALLABLE(func)) {\n\t\t/*\n\t\t *  Note: of native Ecmascript objects, only Function instances\n\t\t *  have a [[HasInstance]] internal property.  Custom objects might\n\t\t *  also have it, but not in current implementation.\n\t\t *\n\t\t *  XXX: add a separate flag, DUK_HOBJECT_FLAG_ALLOW_INSTANCEOF?\n\t\t */\n\t\tgoto error_invalid_rval;\n\t}\n\n\tif (DUK_HOBJECT_HAS_BOUNDFUNC(func)) {\n\t\tduk_push_tval(thr, &((duk_hboundfunc *) func)->target);\n\t\tduk_replace(thr, -2);\n\t\tfunc = duk_require_hobject(thr, -1);  /* lightfunc throws */\n\n\t\t/* Rely on Function.prototype.bind() never creating bound\n\t\t * functions whose target is not proper.\n\t\t */\n\t\tDUK_ASSERT(func != NULL);\n\t\tDUK_ASSERT(DUK_HOBJECT_IS_CALLABLE(func));\n\t}\n\n\t/*\n\t *  'func' is now a non-bound object which supports [[HasInstance]]\n\t *  (which here just means DUK_HOBJECT_FLAG_CALLABLE).  Move on\n\t *  to execute E5 Section 15.3.5.3.\n\t */\n\n\tDUK_ASSERT(func != NULL);\n\tDUK_ASSERT(!DUK_HOBJECT_HAS_BOUNDFUNC(func));\n\tDUK_ASSERT(DUK_HOBJECT_IS_CALLABLE(func));\n\n\t/* [ ... lval rval(func) ] */\n\n\t/* For lightfuncs, buffers, and pointers start the comparison directly\n\t * from the virtual prototype object.\n\t */\n\tskip_first = 0;\n\ttv = DUK_GET_TVAL_NEGIDX(thr, -2);\n\tswitch (DUK_TVAL_GET_TAG(tv)) {\n\tcase DUK_TAG_LIGHTFUNC:\n\t\tval = thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE];\n\t\tDUK_ASSERT(val != NULL);\n\t\tbreak;\n\tcase DUK_TAG_BUFFER:\n\t\tval = thr->builtins[DUK_BIDX_UINT8ARRAY_PROTOTYPE];\n\t\tDUK_ASSERT(val != NULL);\n\t\tbreak;\n\tcase DUK_TAG_POINTER:\n\t\tval = thr->builtins[DUK_BIDX_POINTER_PROTOTYPE];\n\t\tDUK_ASSERT(val != NULL);\n\t\tbreak;\n\tcase DUK_TAG_OBJECT:\n\t\tskip_first = 1;  /* Ignore object itself on first round. */\n\t\tval = DUK_TVAL_GET_OBJECT(tv);\n\t\tDUK_ASSERT(val != NULL);\n\t\tbreak;\n\tdefault:\n\t\tgoto pop2_and_false;\n\t}\n\tDUK_ASSERT(val != NULL);  /* Loop doesn't actually rely on this. */\n\n\t/* Look up .prototype of rval.  Leave it on the value stack in case it\n\t * has been virtualized (e.g. getter, Proxy trap).\n\t */\n\tduk_get_prop_stridx_short(thr, -1, DUK_STRIDX_PROTOTYPE);  /* -> [ ... lval rval rval.prototype ] */\n#if defined(DUK_USE_VERBOSE_ERRORS)\n\tproto = duk_get_hobject(thr, -1);\n\tif (proto == NULL) {\n\t\tgoto error_invalid_rval_noproto;\n\t}\n#else\n\tproto = duk_require_hobject(thr, -1);\n#endif\n\n\tsanity = DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY;\n\tdo {\n\t\t/*\n\t\t *  Note: prototype chain is followed BEFORE first comparison.  This\n\t\t *  means that the instanceof lval is never itself compared to the\n\t\t *  rval.prototype property.  This is apparently intentional, see E5\n\t\t *  Section 15.3.5.3, step 4.a.\n\t\t *\n\t\t *  Also note:\n\t\t *\n\t\t *      js> (function() {}) instanceof Function\n\t\t *      true\n\t\t *      js> Function instanceof Function\n\t\t *      true\n\t\t *\n\t\t *  For the latter, h_proto will be Function.prototype, which is the\n\t\t *  built-in Function prototype.  Because Function.[[Prototype]] is\n\t\t *  also the built-in Function prototype, the result is true.\n\t\t */\n\n\t\tif (!val) {\n\t\t\tgoto pop3_and_false;\n\t\t}\n\n\t\tDUK_ASSERT(val != NULL);\n#if defined(DUK_USE_ES6_PROXY)\n\t\tval = duk_hobject_resolve_proxy_target(val);\n#endif\n\n\t\tif (skip_first) {\n\t\t\tskip_first = 0;\n\t\t} else if (val == proto) {\n\t\t\tgoto pop3_and_true;\n\t\t}\n\n\t\tDUK_ASSERT(val != NULL);\n\t\tval = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, val);\n\t} while (--sanity > 0);\n\n\tif (DUK_UNLIKELY(sanity == 0)) {\n\t\tDUK_ERROR_RANGE(thr, DUK_STR_PROTOTYPE_CHAIN_LIMIT);\n\t}\n\tDUK_UNREACHABLE();\n\n pop2_and_false:\n\tduk_pop_2_unsafe(thr);\n\treturn 0;\n\n pop3_and_false:\n\tduk_pop_3_unsafe(thr);\n\treturn 0;\n\n pop3_and_true:\n\tduk_pop_3_unsafe(thr);\n\treturn 1;\n\n error_invalid_rval:\n\tDUK_ERROR_TYPE(thr, DUK_STR_INVALID_INSTANCEOF_RVAL);\n\treturn 0;\n\n#if defined(DUK_USE_VERBOSE_ERRORS)\n error_invalid_rval_noproto:\n\tDUK_ERROR_TYPE(thr, DUK_STR_INVALID_INSTANCEOF_RVAL_NOPROTO);\n\treturn 0;\n#endif\n}\n\n/*\n *  in\n */\n\n/*\n *  E5 Sections 11.8.7, 8.12.6.\n *\n *  Basically just a property existence check using [[HasProperty]].\n */\n\nDUK_INTERNAL duk_bool_t duk_js_in(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y) {\n\tduk_bool_t retval;\n\n\t/*\n\t *  Get the values onto the stack first.  It would be possible to cover\n\t *  some normal cases without resorting to the value stack (e.g. if\n\t *  lval is already a string).\n\t */\n\n\t/* XXX: The ES5/5.1/6 specifications require that the key in 'key in obj'\n\t * must be string coerced before the internal HasProperty() algorithm is\n\t * invoked.  A fast path skipping coercion could be safely implemented for\n\t * numbers (as number-to-string coercion has no side effects).  For ES2015\n\t * proxy behavior, the trap 'key' argument must be in a string coerced\n\t * form (which is a shame).\n\t */\n\n\t/* TypeError if rval is not an object or object like (e.g. lightfunc\n\t * or plain buffer).\n\t */\n\tduk_push_tval(thr, tv_x);\n\tduk_push_tval(thr, tv_y);\n\tduk_require_type_mask(thr, -1, DUK_TYPE_MASK_OBJECT | DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER);\n\n\t(void) duk_to_property_key_hstring(thr, -2);\n\n\tretval = duk_hobject_hasprop(thr,\n\t                             DUK_GET_TVAL_NEGIDX(thr, -1),\n\t                             DUK_GET_TVAL_NEGIDX(thr, -2));\n\n\tduk_pop_2_unsafe(thr);\n\treturn retval;\n}\n\n/*\n *  typeof\n *\n *  E5 Section 11.4.3.\n *\n *  Very straightforward.  The only question is what to return for our\n *  non-standard tag / object types.\n *\n *  There is an unfortunate string constant define naming problem with\n *  typeof return values for e.g. \"Object\" and \"object\"; careful with\n *  the built-in string defines.  The LC_XXX defines are used for the\n *  lowercase variants now.\n */\n\nDUK_INTERNAL duk_small_uint_t duk_js_typeof_stridx(duk_tval *tv_x) {\n\tduk_small_uint_t stridx = 0;\n\n\tswitch (DUK_TVAL_GET_TAG(tv_x)) {\n\tcase DUK_TAG_UNDEFINED: {\n\t\tstridx = DUK_STRIDX_LC_UNDEFINED;\n\t\tbreak;\n\t}\n\tcase DUK_TAG_NULL: {\n\t\t/* Note: not a typo, \"object\" is returned for a null value. */\n\t\tstridx = DUK_STRIDX_LC_OBJECT;\n\t\tbreak;\n\t}\n\tcase DUK_TAG_BOOLEAN: {\n\t\tstridx = DUK_STRIDX_LC_BOOLEAN;\n\t\tbreak;\n\t}\n\tcase DUK_TAG_POINTER: {\n\t\t/* Implementation specific. */\n\t\tstridx = DUK_STRIDX_LC_POINTER;\n\t\tbreak;\n\t}\n\tcase DUK_TAG_STRING: {\n\t\tduk_hstring *str;\n\n\t\t/* All internal keys are identified as Symbols. */\n\t\tstr = DUK_TVAL_GET_STRING(tv_x);\n\t\tDUK_ASSERT(str != NULL);\n\t\tif (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(str))) {\n\t\t\tstridx = DUK_STRIDX_LC_SYMBOL;\n\t\t} else {\n\t\t\tstridx = DUK_STRIDX_LC_STRING;\n\t\t}\n\t\tbreak;\n\t}\n\tcase DUK_TAG_OBJECT: {\n\t\tduk_hobject *obj = DUK_TVAL_GET_OBJECT(tv_x);\n\t\tDUK_ASSERT(obj != NULL);\n\t\tif (DUK_HOBJECT_IS_CALLABLE(obj)) {\n\t\t\tstridx = DUK_STRIDX_LC_FUNCTION;\n\t\t} else {\n\t\t\tstridx = DUK_STRIDX_LC_OBJECT;\n\t\t}\n\t\tbreak;\n\t}\n\tcase DUK_TAG_BUFFER: {\n\t\t/* Implementation specific.  In Duktape 1.x this would be\n\t\t * 'buffer', in Duktape 2.x changed to 'object' because plain\n\t\t * buffers now mimic Uint8Array objects.\n\t\t */\n\t\tstridx = DUK_STRIDX_LC_OBJECT;\n\t\tbreak;\n\t}\n\tcase DUK_TAG_LIGHTFUNC: {\n\t\tstridx = DUK_STRIDX_LC_FUNCTION;\n\t\tbreak;\n\t}\n#if defined(DUK_USE_FASTINT)\n\tcase DUK_TAG_FASTINT:\n#endif\n\tdefault: {\n\t\t/* number */\n\t\tDUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv_x));\n\t\tDUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_x));\n\t\tstridx = DUK_STRIDX_LC_NUMBER;\n\t\tbreak;\n\t}\n\t}\n\n\tDUK_ASSERT_STRIDX_VALID(stridx);\n\treturn stridx;\n}\n\n/*\n *  Array index and length\n *\n *  Array index: E5 Section 15.4\n *  Array length: E5 Section 15.4.5.1 steps 3.c - 3.d (array length write)\n */\n\n/* Compure array index from string context, or return a \"not array index\"\n * indicator.\n */\nDUK_INTERNAL duk_uarridx_t duk_js_to_arrayindex_string(const duk_uint8_t *str, duk_uint32_t blen) {\n\tduk_uarridx_t res;\n\n\t/* Only strings with byte length 1-10 can be 32-bit array indices.\n\t * Leading zeroes (except '0' alone), plus/minus signs are not allowed.\n\t * We could do a lot of prechecks here, but since most strings won't\n\t * start with any digits, it's simpler to just parse the number and\n\t * fail quickly.\n\t */\n\n\tres = 0;\n\tif (blen == 0) {\n\t\tgoto parse_fail;\n\t}\n\tdo {\n\t\tduk_uarridx_t dig;\n\t\tdig = (duk_uarridx_t) (*str++) - DUK_ASC_0;\n\n\t\tif (dig <= 9U) {\n\t\t\t/* Careful overflow handling.  When multiplying by 10:\n\t\t\t * - 0x19999998 x 10 = 0xfffffff0: no overflow, and adding\n\t\t\t *   0...9 is safe.\n\t\t\t * - 0x19999999 x 10 = 0xfffffffa: no overflow, adding\n\t\t\t *   0...5 is safe, 6...9 overflows.\n\t\t\t * - 0x1999999a x 10 = 0x100000004: always overflow.\n\t\t\t */\n\t\t\tif (DUK_UNLIKELY(res >= 0x19999999UL)) {\n\t\t\t\tif (res >= 0x1999999aUL) {\n\t\t\t\t\t/* Always overflow. */\n\t\t\t\t\tgoto parse_fail;\n\t\t\t\t}\n\t\t\t\tDUK_ASSERT(res == 0x19999999UL);\n\t\t\t\tif (dig >= 6U) {\n\t\t\t\t\tgoto parse_fail;\n\t\t\t\t}\n\t\t\t\tres = 0xfffffffaUL + dig;\n\t\t\t\tDUK_ASSERT(res >= 0xfffffffaUL);\n\t\t\t\tDUK_ASSERT_DISABLE(res <= 0xffffffffUL);  /* range */\n\t\t\t} else {\n\t\t\t\tres = res * 10U + dig;\n\t\t\t\tif (DUK_UNLIKELY(res == 0)) {\n\t\t\t\t\t/* If 'res' is 0, previous 'res' must\n\t\t\t\t\t * have been 0 and we scanned in a zero.\n\t\t\t\t\t * This is only allowed if blen == 1,\n\t\t\t\t\t * i.e. the exact string '0'.\n\t\t\t\t\t */\n\t\t\t\t\tif (blen == (duk_uint32_t) 1) {\n\t\t\t\t\t\treturn 0;\n\t\t\t\t\t}\n\t\t\t\t\tgoto parse_fail;\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\t/* Because 'dig' is unsigned, catches both values\n\t\t\t * above '9' and below '0'.\n\t\t\t */\n\t\t\tgoto parse_fail;\n\t\t}\n\t} while (--blen > 0);\n\n\treturn res;\n\n parse_fail:\n\treturn DUK_HSTRING_NO_ARRAY_INDEX;\n}\n\n#if !defined(DUK_USE_HSTRING_ARRIDX)\n/* Get array index for a string which is known to be an array index.  This helper\n * is needed when duk_hstring doesn't concretely store the array index, but strings\n * are flagged as array indices at intern time.\n */\nDUK_INTERNAL duk_uarridx_t duk_js_to_arrayindex_hstring_fast_known(duk_hstring *h) {\n\tconst duk_uint8_t *p;\n\tduk_uarridx_t res;\n\tduk_uint8_t t;\n\n\tDUK_ASSERT(h != NULL);\n\tDUK_ASSERT(DUK_HSTRING_HAS_ARRIDX(h));\n\n\tp = DUK_HSTRING_GET_DATA(h);\n\tres = 0;\n\tfor (;;) {\n\t\tt = *p++;\n\t\tif (DUK_UNLIKELY(t == 0)) {\n\t\t\t/* Scanning to NUL is always safe for interned strings. */\n\t\t\tbreak;\n\t\t}\n\t\tDUK_ASSERT(t >= (duk_uint8_t) DUK_ASC_0 && t <= (duk_uint8_t) DUK_ASC_9);\n\t\tres = res * 10U + (duk_uarridx_t) t - (duk_uarridx_t) DUK_ASC_0;\n\t}\n\treturn res;\n}\n\nDUK_INTERNAL duk_uarridx_t duk_js_to_arrayindex_hstring_fast(duk_hstring *h) {\n\tDUK_ASSERT(h != NULL);\n\tif (!DUK_HSTRING_HAS_ARRIDX(h)) {\n\t\treturn DUK_HSTRING_NO_ARRAY_INDEX;\n\t}\n\treturn duk_js_to_arrayindex_hstring_fast_known(h);\n}\n#endif  /* DUK_USE_HSTRING_ARRIDX */\n#line 1 \"duk_js_var.c\"\n/*\n *  Identifier access and function closure handling.\n *\n *  Provides the primitives for slow path identifier accesses: GETVAR,\n *  PUTVAR, DELVAR, etc.  The fast path, direct register accesses, should\n *  be used for most identifier accesses.  Consequently, these slow path\n *  primitives should be optimized for maximum compactness.\n *\n *  Ecmascript environment records (declarative and object) are represented\n *  as internal objects with control keys.  Environment records have a\n *  parent record (\"outer environment reference\") which is represented by\n *  the implicit prototype for technical reasons (in other words, it is a\n *  convenient field).  The prototype chain is not followed in the ordinary\n *  sense for variable lookups.\n *\n *  See identifier-handling.rst for more details on the identifier algorithms\n *  and the internal representation.  See function-objects.rst for details on\n *  what function templates and instances are expected to look like.\n *\n *  Care must be taken to avoid duk_tval pointer invalidation caused by\n *  e.g. value stack or object resizing.\n *\n *  TODO: properties for function instances could be initialized much more\n *  efficiently by creating a property allocation for a certain size and\n *  filling in keys and values directly (and INCREFing both with \"bulk incref\"\n *  primitives.\n *\n *  XXX: duk_hobject_getprop() and duk_hobject_putprop() calls are a bit\n *  awkward (especially because they follow the prototype chain); rework\n *  if \"raw\" own property helpers are added.\n */\n\n/* #include duk_internal.h -> already included */\n\n/*\n *  Local result type for duk__get_identifier_reference() lookup.\n */\n\ntypedef struct {\n\tduk_hobject *env;\n\tduk_hobject *holder;      /* for object-bound identifiers */\n\tduk_tval *value;          /* for register-bound and declarative env identifiers */\n\tduk_uint_t attrs;         /* property attributes for identifier (relevant if value != NULL) */\n\tduk_bool_t has_this;      /* for object-bound identifiers: provide 'this' binding */\n} duk__id_lookup_result;\n\n/*\n *  Create a new function object based on a \"template function\" which contains\n *  compiled bytecode, constants, etc, but lacks a lexical environment.\n *\n *  Ecmascript requires that each created closure is a separate object, with\n *  its own set of editable properties.  However, structured property values\n *  (such as the formal arguments list and the variable map) are shared.\n *  Also the bytecode, constants, and inner functions are shared.\n *\n *  See E5 Section 13.2 for detailed requirements on the function objects;\n *  there are no similar requirements for function \"templates\" which are an\n *  implementation dependent internal feature.  Also see function-objects.rst\n *  for a discussion on the function instance properties provided by this\n *  implementation.\n *\n *  Notes:\n *\n *   * Order of internal properties should match frequency of use, since the\n *     properties will be linearly scanned on lookup (functions usually don't\n *     have enough properties to warrant a hash part).\n *\n *   * The created closure is independent of its template; they do share the\n *     same 'data' buffer object, but the template object itself can be freed\n *     even if the closure object remains reachable.\n */\n\nDUK_LOCAL void duk__inc_data_inner_refcounts(duk_hthread *thr, duk_hcompfunc *f) {\n\tduk_tval *tv, *tv_end;\n\tduk_hobject **funcs, **funcs_end;\n\n\tDUK_UNREF(thr);\n\n\t/* If function creation fails due to out-of-memory, the data buffer\n\t * pointer may be NULL in some cases.  That's actually possible for\n\t * GC code, but shouldn't be possible here because the incomplete\n\t * function will be unwound from the value stack and never instantiated.\n\t */\n\tDUK_ASSERT(DUK_HCOMPFUNC_GET_DATA(thr->heap, f) != NULL);\n\n\ttv = DUK_HCOMPFUNC_GET_CONSTS_BASE(thr->heap, f);\n\ttv_end = DUK_HCOMPFUNC_GET_CONSTS_END(thr->heap, f);\n\twhile (tv < tv_end) {\n\t\tDUK_TVAL_INCREF(thr, tv);\n\t\ttv++;\n\t}\n\n\tfuncs = DUK_HCOMPFUNC_GET_FUNCS_BASE(thr->heap, f);\n\tfuncs_end = DUK_HCOMPFUNC_GET_FUNCS_END(thr->heap, f);\n\twhile (funcs < funcs_end) {\n\t\tDUK_HEAPHDR_INCREF(thr, (duk_heaphdr *) *funcs);\n\t\tfuncs++;\n\t}\n}\n\n/* Push a new closure on the stack.\n *\n * Note: if fun_temp has NEWENV, i.e. a new lexical and variable declaration\n * is created when the function is called, only outer_lex_env matters\n * (outer_var_env is ignored and may or may not be same as outer_lex_env).\n */\n\nDUK_LOCAL const duk_uint16_t duk__closure_copy_proplist[] = {\n\t/* order: most frequent to least frequent */\n\tDUK_STRIDX_INT_VARMAP,\n\tDUK_STRIDX_INT_FORMALS,\n#if defined(DUK_USE_PC2LINE)\n\tDUK_STRIDX_INT_PC2LINE,\n#endif\n#if defined(DUK_USE_FUNC_FILENAME_PROPERTY)\n\tDUK_STRIDX_FILE_NAME,\n#endif\n#if defined(DUK_USE_NONSTD_FUNC_SOURCE_PROPERTY)\n\tDUK_STRIDX_INT_SOURCE\n#endif\n};\n\nDUK_INTERNAL\nvoid duk_js_push_closure(duk_hthread *thr,\n                         duk_hcompfunc *fun_temp,\n                         duk_hobject *outer_var_env,\n                         duk_hobject *outer_lex_env,\n                         duk_bool_t add_auto_proto) {\n\tduk_hcompfunc *fun_clos;\n\tduk_small_uint_t i;\n\tduk_uint_t len_value;\n\n\tDUK_ASSERT(fun_temp != NULL);\n\tDUK_ASSERT(DUK_HCOMPFUNC_GET_DATA(thr->heap, fun_temp) != NULL);\n\tDUK_ASSERT(DUK_HCOMPFUNC_GET_FUNCS(thr->heap, fun_temp) != NULL);\n\tDUK_ASSERT(DUK_HCOMPFUNC_GET_BYTECODE(thr->heap, fun_temp) != NULL);\n\tDUK_ASSERT(outer_var_env != NULL);\n\tDUK_ASSERT(outer_lex_env != NULL);\n\tDUK_UNREF(len_value);\n\n\tfun_clos = duk_push_hcompfunc(thr);\n\tDUK_ASSERT(fun_clos != NULL);\n\tDUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) fun_clos) == thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]);\n\n\tduk_push_hobject(thr, &fun_temp->obj);  /* -> [ ... closure template ] */\n\n\tDUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC((duk_hobject *) fun_clos));\n\tDUK_ASSERT(DUK_HCOMPFUNC_GET_DATA(thr->heap, fun_clos) == NULL);\n\tDUK_ASSERT(DUK_HCOMPFUNC_GET_FUNCS(thr->heap, fun_clos) == NULL);\n\tDUK_ASSERT(DUK_HCOMPFUNC_GET_BYTECODE(thr->heap, fun_clos) == NULL);\n\n\tDUK_HCOMPFUNC_SET_DATA(thr->heap, fun_clos, DUK_HCOMPFUNC_GET_DATA(thr->heap, fun_temp));\n\tDUK_HCOMPFUNC_SET_FUNCS(thr->heap, fun_clos, DUK_HCOMPFUNC_GET_FUNCS(thr->heap, fun_temp));\n\tDUK_HCOMPFUNC_SET_BYTECODE(thr->heap, fun_clos, DUK_HCOMPFUNC_GET_BYTECODE(thr->heap, fun_temp));\n\n\t/* Note: all references inside 'data' need to get their refcounts\n\t * upped too.  This is the case because refcounts are decreased\n\t * through every function referencing 'data' independently.\n\t */\n\n\tDUK_HBUFFER_INCREF(thr, DUK_HCOMPFUNC_GET_DATA(thr->heap, fun_clos));\n\tduk__inc_data_inner_refcounts(thr, fun_temp);\n\n\tfun_clos->nregs = fun_temp->nregs;\n\tfun_clos->nargs = fun_temp->nargs;\n#if defined(DUK_USE_DEBUGGER_SUPPORT)\n\tfun_clos->start_line = fun_temp->start_line;\n\tfun_clos->end_line = fun_temp->end_line;\n#endif\n\n\tDUK_ASSERT(DUK_HCOMPFUNC_GET_DATA(thr->heap, fun_clos) != NULL);\n\tDUK_ASSERT(DUK_HCOMPFUNC_GET_FUNCS(thr->heap, fun_clos) != NULL);\n\tDUK_ASSERT(DUK_HCOMPFUNC_GET_BYTECODE(thr->heap, fun_clos) != NULL);\n\n\t/* XXX: Could also copy from template, but there's no way to have any\n\t * other value here now (used code has no access to the template).\n\t * Prototype is set by duk_push_hcompfunc().\n\t */\n\tDUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, &fun_clos->obj) == thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]);\n#if 0\n\tDUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, &fun_clos->obj, thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]);\n#endif\n\n\t/* Copy duk_hobject flags as is from the template using a mask.\n\t * Leave out duk_heaphdr owned flags just in case (e.g. if there's\n\t * some GC flag or similar).  Some flags can then be adjusted\n\t * separately if necessary.\n\t */\n\n\t/* DUK_HEAPHDR_SET_FLAGS() masks changes to non-duk_heaphdr flags only. */\n\tDUK_HEAPHDR_SET_FLAGS((duk_heaphdr *) fun_clos, DUK_HEAPHDR_GET_FLAGS_RAW((duk_heaphdr *) fun_temp));\n\tDUK_DD(DUK_DDPRINT(\"fun_temp heaphdr flags: 0x%08lx, fun_clos heaphdr flags: 0x%08lx\",\n\t                   (unsigned long) DUK_HEAPHDR_GET_FLAGS_RAW((duk_heaphdr *) fun_temp),\n\t                   (unsigned long) DUK_HEAPHDR_GET_FLAGS_RAW((duk_heaphdr *) fun_clos)));\n\n\tDUK_ASSERT(DUK_HOBJECT_HAS_EXTENSIBLE(&fun_clos->obj));\n\tDUK_ASSERT(!DUK_HOBJECT_HAS_BOUNDFUNC(&fun_clos->obj));\n\tDUK_ASSERT(DUK_HOBJECT_HAS_COMPFUNC(&fun_clos->obj));\n\tDUK_ASSERT(!DUK_HOBJECT_HAS_NATFUNC(&fun_clos->obj));\n\tDUK_ASSERT(!DUK_HOBJECT_IS_THREAD(&fun_clos->obj));\n\t/* DUK_HOBJECT_FLAG_ARRAY_PART: don't care */\n\t/* DUK_HOBJECT_FLAG_NEWENV: handled below */\n\tDUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARRAY(&fun_clos->obj));\n\tDUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(&fun_clos->obj));\n\tDUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(&fun_clos->obj));\n\n\tif (!DUK_HOBJECT_HAS_CONSTRUCTABLE(&fun_clos->obj)) {\n\t\t/* If the template is not constructable don't add an automatic\n\t\t * .prototype property.  This is the case for e.g. ES2015 object\n\t\t * literal getters/setters and method definitions.\n\t\t */\n\t\tadd_auto_proto = 0;\n\t}\n\n\t/*\n\t *  Setup environment record properties based on the template and\n\t *  its flags.\n\t *\n\t *  If DUK_HOBJECT_HAS_NEWENV(fun_temp) is true, the environment\n\t *  records represent identifiers \"outside\" the function; the\n\t *  \"inner\" environment records are created on demand.  Otherwise,\n\t *  the environment records are those that will be directly used\n\t *  (e.g. for declarations).\n\t *\n\t *  _Lexenv is always set; _Varenv defaults to _Lexenv if missing,\n\t *  so _Varenv is only set if _Lexenv != _Varenv.\n\t *\n\t *  This is relatively complex, see doc/identifier-handling.rst.\n\t */\n\n\tif (DUK_HOBJECT_HAS_NEWENV(&fun_clos->obj)) {\n#if defined(DUK_USE_FUNC_NAME_PROPERTY)\n\t\tif (DUK_HOBJECT_HAS_NAMEBINDING(&fun_clos->obj)) {\n\t\t\tduk_hobject *proto;\n\t\t\tduk_hdecenv *new_env;\n\n\t\t\t/*\n\t\t\t *  Named function expression, name needs to be bound\n\t\t\t *  in an intermediate environment record.  The \"outer\"\n\t\t\t *  lexical/variable environment will thus be:\n\t\t\t *\n\t\t\t *  a) { funcname: <func>, __prototype: outer_lex_env }\n\t\t\t *  b) { funcname: <func>, __prototype:  <globalenv> }  (if outer_lex_env missing)\n\t\t\t */\n\n\t\t\tif (outer_lex_env) {\n\t\t\t\tproto = outer_lex_env;\n\t\t\t} else {\n\t\t\t\tproto = thr->builtins[DUK_BIDX_GLOBAL_ENV];\n\t\t\t}\n\n\t\t\t/* -> [ ... closure template env ] */\n\t\t\tnew_env = duk_hdecenv_alloc(thr,\n\t\t\t                            DUK_HOBJECT_FLAG_EXTENSIBLE |\n\t\t\t                            DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_DECENV));\n\t\t\tDUK_ASSERT(new_env != NULL);\n\t\t\tduk_push_hobject(thr, (duk_hobject *) new_env);\n\n\t\t\tDUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) new_env) == NULL);\n\t\t\tDUK_HOBJECT_SET_PROTOTYPE(thr->heap, (duk_hobject *) new_env, proto);\n\t\t\tDUK_HOBJECT_INCREF_ALLOWNULL(thr, proto);\n\n\t\t\tDUK_ASSERT(new_env->thread == NULL);  /* Closed. */\n\t\t\tDUK_ASSERT(new_env->varmap == NULL);\n\n\t\t\t/* It's important that duk_xdef_prop() is a 'raw define' so that any\n\t\t\t * properties in an ancestor are never an issue (they should never be\n\t\t\t * e.g. non-writable, but just in case).\n\t\t\t *\n\t\t\t * Because template objects are not visible to user code, the case\n\t\t\t * where .name is missing shouldn't happen in practice.  It it does,\n\t\t\t * the name 'undefined' gets bound and maps to the closure (which is\n\t\t\t * a bit odd, but safe).\n\t\t\t */\n\t\t\t(void) duk_get_prop_stridx_short(thr, -2, DUK_STRIDX_NAME);\n\t\t\t/* -> [ ... closure template env funcname ] */\n\t\t\tduk_dup_m4(thr);                                           /* -> [ ... closure template env funcname closure ] */\n\t\t\tduk_xdef_prop(thr, -3, DUK_PROPDESC_FLAGS_NONE);           /* -> [ ... closure template env ] */\n\t\t\t/* env[funcname] = closure */\n\n\t\t\t/* [ ... closure template env ] */\n\n\t\t\tDUK_HCOMPFUNC_SET_LEXENV(thr->heap, fun_clos, (duk_hobject *) new_env);\n\t\t\tDUK_HCOMPFUNC_SET_VARENV(thr->heap, fun_clos, (duk_hobject *) new_env);\n\t\t\tDUK_HOBJECT_INCREF(thr, (duk_hobject *) new_env);\n\t\t\tDUK_HOBJECT_INCREF(thr, (duk_hobject *) new_env);\n\t\t\tduk_pop_unsafe(thr);\n\n\t\t\t/* [ ... closure template ] */\n\t\t}\n\t\telse\n#endif  /* DUK_USE_FUNC_NAME_PROPERTY */\n\t\t{\n\t\t\t/*\n\t\t\t *  Other cases (function declaration, anonymous function expression,\n\t\t\t *  strict direct eval code).  The \"outer\" environment will be whatever\n\t\t\t *  the caller gave us.\n\t\t\t */\n\n\t\t\tDUK_HCOMPFUNC_SET_LEXENV(thr->heap, fun_clos, outer_lex_env);\n\t\t\tDUK_HCOMPFUNC_SET_VARENV(thr->heap, fun_clos, outer_lex_env);\n\t\t\tDUK_HOBJECT_INCREF(thr, outer_lex_env);\n\t\t\tDUK_HOBJECT_INCREF(thr, outer_lex_env);\n\n\t\t\t/* [ ... closure template ] */\n\t\t}\n\t} else {\n\t\t/*\n\t\t *  Function gets no new environment when called.  This is the\n\t\t *  case for global code, indirect eval code, and non-strict\n\t\t *  direct eval code.  There is no direct correspondence to the\n\t\t *  E5 specification, as global/eval code is not exposed as a\n\t\t *  function.\n\t\t */\n\n\t\tDUK_ASSERT(!DUK_HOBJECT_HAS_NAMEBINDING(&fun_temp->obj));\n\n\t\tDUK_HCOMPFUNC_SET_LEXENV(thr->heap, fun_clos, outer_lex_env);\n\t\tDUK_HCOMPFUNC_SET_VARENV(thr->heap, fun_clos, outer_var_env);\n\t\tDUK_HOBJECT_INCREF(thr, outer_lex_env);  /* NULLs not allowed; asserted on entry */\n\t\tDUK_HOBJECT_INCREF(thr, outer_var_env);\n\t}\n\tDUK_DDD(DUK_DDDPRINT(\"closure varenv -> %!ipO, lexenv -> %!ipO\",\n\t                     (duk_heaphdr *) fun_clos->var_env,\n\t                     (duk_heaphdr *) fun_clos->lex_env));\n\n\t/* Call handling assumes this for all callable closures. */\n\tDUK_ASSERT(DUK_HCOMPFUNC_GET_LEXENV(thr->heap, fun_clos) != NULL);\n\tDUK_ASSERT(DUK_HCOMPFUNC_GET_VARENV(thr->heap, fun_clos) != NULL);\n\n\t/*\n\t *  Copy some internal properties directly\n\t *\n\t *  The properties will be non-writable and non-enumerable, but\n\t *  configurable.\n\t */\n\n\t/* [ ... closure template ] */\n\n\tDUK_DDD(DUK_DDDPRINT(\"copying properties: closure=%!iT, template=%!iT\",\n\t                     (duk_tval *) duk_get_tval(thr, -2),\n\t                     (duk_tval *) duk_get_tval(thr, -1)));\n\n\tfor (i = 0; i < (duk_small_uint_t) (sizeof(duk__closure_copy_proplist) / sizeof(duk_uint16_t)); i++) {\n\t\tduk_small_int_t stridx = (duk_small_int_t) duk__closure_copy_proplist[i];\n\t\tif (duk_get_prop_stridx_short(thr, -1, stridx)) {\n\t\t\t/* [ ... closure template val ] */\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"copying property, stridx=%ld -> found\", (long) stridx));\n\t\t\tduk_xdef_prop_stridx_short(thr, -3, stridx, DUK_PROPDESC_FLAGS_C);\n\t\t} else {\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"copying property, stridx=%ld -> not found\", (long) stridx));\n\t\t\tduk_pop_unsafe(thr);\n\t\t}\n\t}\n\n\t/*\n\t *  \"length\" maps to number of formals (E5 Section 13.2) for function\n\t *  declarations/expressions (non-bound functions).  Note that 'nargs'\n\t *  is NOT necessarily equal to the number of arguments.  Use length\n\t *  of _Formals; if missing, assume nargs matches .length.\n\t */\n\n\t/* [ ... closure template ] */\n\n\t/* XXX: these lookups should be just own property lookups instead of\n\t * looking up the inheritance chain.\n\t */\n\tif (duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INT_FORMALS)) {\n\t\t/* [ ... closure template formals ] */\n\t\tlen_value = (duk_uint_t) duk_get_length(thr, -1);  /* could access duk_harray directly, not important */\n\t\tDUK_DD(DUK_DDPRINT(\"closure length from _Formals -> %ld\", (long) len_value));\n\t} else {\n\t\tlen_value = fun_temp->nargs;\n\t\tDUK_DD(DUK_DDPRINT(\"closure length defaulted from nargs -> %ld\", (long) len_value));\n\t}\n\tduk_pop_unsafe(thr);\n\n\tduk_push_uint(thr, len_value);  /* [ ... closure template len_value ] */\n\tduk_xdef_prop_stridx_short(thr, -3, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_C);\n\n\t/*\n\t *  \"prototype\" is, by default, a fresh object with the \"constructor\"\n\t *  property.\n\t *\n\t *  Note that this creates a circular reference for every function\n\t *  instance (closure) which prevents refcount-based collection of\n\t *  function instances.\n\t *\n\t *  XXX: Try to avoid creating the default prototype object, because\n\t *  many functions are not used as constructors and the default\n\t *  prototype is unnecessary.  Perhaps it could be created on-demand\n\t *  when it is first accessed?\n\t */\n\n\t/* [ ... closure template ] */\n\n\tif (add_auto_proto) {\n\t\tduk_push_object(thr);  /* -> [ ... closure template newobj ] */\n\t\tduk_dup_m3(thr);       /* -> [ ... closure template newobj closure ] */\n\t\tduk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_CONSTRUCTOR, DUK_PROPDESC_FLAGS_WC);  /* -> [ ... closure template newobj ] */\n\t\tduk_compact(thr, -1);  /* compact the prototype */\n\t\tduk_xdef_prop_stridx_short(thr, -3, DUK_STRIDX_PROTOTYPE, DUK_PROPDESC_FLAGS_W);     /* -> [ ... closure template ] */\n\t}\n\n\t/*\n\t *  \"arguments\" and \"caller\" must be mapped to throwers for strict\n\t *  mode and bound functions (E5 Section 15.3.5).\n\t *\n\t *  XXX: This is expensive to have for every strict function instance.\n\t *  Try to implement as virtual properties or on-demand created properties.\n\t */\n\n\t/* [ ... closure template ] */\n\n\tif (DUK_HOBJECT_HAS_STRICT(&fun_clos->obj)) {\n\t\tduk_xdef_prop_stridx_thrower(thr, -2, DUK_STRIDX_CALLER);\n\t\tduk_xdef_prop_stridx_thrower(thr, -2, DUK_STRIDX_LC_ARGUMENTS);\n\t} else {\n#if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)\n\t\tDUK_DDD(DUK_DDDPRINT(\"function is non-strict and non-standard 'caller' property in use, add initial 'null' value\"));\n\t\tduk_push_null(thr);\n\t\tduk_xdef_prop_stridx_short(thr, -3, DUK_STRIDX_CALLER, DUK_PROPDESC_FLAGS_NONE);\n#else\n\t\tDUK_DDD(DUK_DDDPRINT(\"function is non-strict and non-standard 'caller' property not used\"));\n#endif\n\t}\n\n\t/*\n\t *  \"name\" used to be non-standard but is now defined by ES2015.\n\t *  In ES2015/ES2016 the .name property is configurable.\n\t */\n\n\t/* [ ... closure template ] */\n\n#if defined(DUK_USE_FUNC_NAME_PROPERTY)\n\t/* XXX: Look for own property only; doesn't matter much because\n\t * templates are bare objects.\n\t */\n\tif (duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_NAME)) {\n\t\t/* [ ... closure template name ] */\n\t\tDUK_ASSERT(duk_is_string(thr, -1));\n\t\tDUK_DD(DUK_DDPRINT(\"setting function instance name to %!T\", duk_get_tval(thr, -1)));\n\t\tduk_xdef_prop_stridx_short(thr, -3, DUK_STRIDX_NAME, DUK_PROPDESC_FLAGS_C);  /* -> [ ... closure template ] */\n\t} else {\n\t\t/* Anonymous functions don't have a .name in ES2015, so don't set\n\t\t * it on the instance either.  The instance will then inherit\n\t\t * it from Function.prototype.name.\n\t\t */\n\t\tDUK_DD(DUK_DDPRINT(\"not setting function instance .name\"));\n\t\tduk_pop_unsafe(thr);\n\t}\n#endif\n\n\t/*\n\t *  Compact the closure, in most cases no properties will be added later.\n\t *  Also, without this the closures end up having unused property slots\n\t *  (e.g. in Duktape 0.9.0, 8 slots would be allocated and only 7 used).\n\t *  A better future solution would be to allocate the closure directly\n\t *  to correct size (and setup the properties directly without going\n\t *  through the API).\n\t */\n\n\tduk_compact(thr, -2);\n\n\t/*\n\t *  Some assertions (E5 Section 13.2).\n\t */\n\n\tDUK_ASSERT(DUK_HOBJECT_GET_CLASS_NUMBER(&fun_clos->obj) == DUK_HOBJECT_CLASS_FUNCTION);\n\tDUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, &fun_clos->obj) == thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]);\n\tDUK_ASSERT(DUK_HOBJECT_HAS_EXTENSIBLE(&fun_clos->obj));\n\tDUK_ASSERT(duk_has_prop_stridx(thr, -2, DUK_STRIDX_LENGTH) != 0);\n\tDUK_ASSERT(add_auto_proto == 0 || duk_has_prop_stridx(thr, -2, DUK_STRIDX_PROTOTYPE) != 0);\n\t/* May be missing .name */\n\tDUK_ASSERT(!DUK_HOBJECT_HAS_STRICT(&fun_clos->obj) ||\n\t           duk_has_prop_stridx(thr, -2, DUK_STRIDX_CALLER) != 0);\n\tDUK_ASSERT(!DUK_HOBJECT_HAS_STRICT(&fun_clos->obj) ||\n\t           duk_has_prop_stridx(thr, -2, DUK_STRIDX_LC_ARGUMENTS) != 0);\n\n\t/*\n\t *  Finish\n\t */\n\n\t/* [ ... closure template ] */\n\n\tDUK_DDD(DUK_DDDPRINT(\"created function instance: template=%!iT -> closure=%!iT\",\n\t                     (duk_tval *) duk_get_tval(thr, -1),\n\t                     (duk_tval *) duk_get_tval(thr, -2)));\n\n\tduk_pop_unsafe(thr);\n\n\t/* [ ... closure ] */\n}\n\n/*\n *  Delayed activation environment record initialization (for functions\n *  with NEWENV).\n *\n *  The non-delayed initialization is handled by duk_handle_call().\n */\n\n/* shared helper */\nDUK_INTERNAL\nduk_hobject *duk_create_activation_environment_record(duk_hthread *thr,\n                                                      duk_hobject *func,\n                                                      duk_size_t bottom_byteoff) {\n\tduk_hdecenv *env;\n\tduk_hobject *parent;\n\tduk_hcompfunc *f;\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(func != NULL);\n\n\tf = (duk_hcompfunc *) func;\n\tparent = DUK_HCOMPFUNC_GET_LEXENV(thr->heap, f);\n\tif (!parent) {\n\t\tparent = thr->builtins[DUK_BIDX_GLOBAL_ENV];\n\t}\n\n\tenv = duk_hdecenv_alloc(thr,\n\t                        DUK_HOBJECT_FLAG_EXTENSIBLE |\n\t                        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_DECENV));\n\tDUK_ASSERT(env != NULL);\n\tduk_push_hobject(thr, (duk_hobject *) env);\n\n\tDUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) env) == NULL);\n\tDUK_HOBJECT_SET_PROTOTYPE(thr->heap, (duk_hobject *) env, parent);\n\tDUK_HOBJECT_INCREF_ALLOWNULL(thr, parent);  /* parent env is the prototype */\n\n\t/* open scope information, for compiled functions only */\n\n\tDUK_ASSERT(env->thread == NULL);\n\tDUK_ASSERT(env->varmap == NULL);\n\tDUK_ASSERT(env->regbase_byteoff == 0);\n\tif (DUK_HOBJECT_IS_COMPFUNC(func)) {\n\t\tduk_hobject *varmap;\n\t\tduk_tval *tv;\n\n\t\ttv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, func, DUK_HTHREAD_STRING_INT_VARMAP(thr));\n\t\tif (tv != NULL && DUK_TVAL_IS_OBJECT(tv)) {\n\t\t\tDUK_ASSERT(DUK_TVAL_IS_OBJECT(tv));\n\t\t\tvarmap = DUK_TVAL_GET_OBJECT(tv);\n\t\t\tDUK_ASSERT(varmap != NULL);\n\t\t\tenv->varmap = varmap;\n\t\t\tDUK_HOBJECT_INCREF(thr, varmap);\n\t\t\tenv->thread = thr;\n\t\t\tDUK_HTHREAD_INCREF(thr, thr);\n\t\t\tenv->regbase_byteoff = bottom_byteoff;\n\t\t} else {\n\t\t\t/* If function has no _Varmap, leave the environment closed. */\n\t\t\tDUK_ASSERT(env->thread == NULL);\n\t\t\tDUK_ASSERT(env->varmap == NULL);\n\t\t\tDUK_ASSERT(env->regbase_byteoff == 0);\n\t\t}\n\t}\n\n\treturn (duk_hobject *) env;\n}\n\nDUK_INTERNAL\nvoid duk_js_init_activation_environment_records_delayed(duk_hthread *thr,\n                                                        duk_activation *act) {\n\tduk_hobject *func;\n\tduk_hobject *env;\n\n\tDUK_ASSERT(thr != NULL);\n\tfunc = DUK_ACT_GET_FUNC(act);\n\tDUK_ASSERT(func != NULL);\n\tDUK_ASSERT(!DUK_HOBJECT_HAS_BOUNDFUNC(func));  /* bound functions are never in act 'func' */\n\n\t/*\n\t *  Delayed initialization only occurs for 'NEWENV' functions.\n\t */\n\n\tDUK_ASSERT(DUK_HOBJECT_HAS_NEWENV(func));\n\tDUK_ASSERT(act->lex_env == NULL);\n\tDUK_ASSERT(act->var_env == NULL);\n\n\tenv = duk_create_activation_environment_record(thr, func, act->bottom_byteoff);\n\tDUK_ASSERT(env != NULL);\n\t/* 'act' is a stable pointer, so still OK. */\n\n\tDUK_DDD(DUK_DDDPRINT(\"created delayed fresh env: %!ipO\", (duk_heaphdr *) env));\n#if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)\n\t{\n\t\tduk_hobject *p = env;\n\t\twhile (p) {\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"  -> %!ipO\", (duk_heaphdr *) p));\n\t\t\tp = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, p);\n\t\t}\n\t}\n#endif\n\n\tact->lex_env = env;\n\tact->var_env = env;\n\tDUK_HOBJECT_INCREF(thr, env);  /* XXX: incref by count (here 2 times) */\n\tDUK_HOBJECT_INCREF(thr, env);\n\n\tduk_pop_unsafe(thr);\n}\n\n/*\n *  Closing environment records.\n *\n *  The environment record MUST be closed with the thread where its activation\n *  is; i.e. if 'env' is open, 'thr' must match env->thread, and the regbase\n *  and varmap must still be valid.  On entry, 'env' must be reachable.\n */\n\nDUK_INTERNAL void duk_js_close_environment_record(duk_hthread *thr, duk_hobject *env) {\n\tduk_uint_fast32_t i;\n\tduk_hobject *varmap;\n\tduk_hstring *key;\n\tduk_tval *tv;\n\tduk_uint_t regnum;\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(env != NULL);\n\n\tif (DUK_UNLIKELY(!DUK_HOBJECT_IS_DECENV(env))) {\n\t\tDUK_DDD(DUK_DDDPRINT(\"env not a declarative record: %!iO\", (duk_heaphdr *) env));\n\t\treturn;\n\t}\n\n\tvarmap = ((duk_hdecenv *) env)->varmap;\n\tif (varmap == NULL) {\n\t\tDUK_DDD(DUK_DDDPRINT(\"env already closed: %!iO\", (duk_heaphdr *) env));\n\n\t\treturn;\n\t}\n\tDUK_ASSERT(((duk_hdecenv *) env)->thread != NULL);\n\tDUK_ASSERT_HDECENV_VALID((duk_hdecenv *) env);\n\n\tDUK_DDD(DUK_DDDPRINT(\"closing env: %!iO\", (duk_heaphdr *) env));\n\tDUK_DDD(DUK_DDDPRINT(\"varmap: %!O\", (duk_heaphdr *) varmap));\n\n\t/* Env must be closed in the same thread as where it runs. */\n\tDUK_ASSERT(((duk_hdecenv *) env)->thread == thr);\n\n\t/* XXX: additional conditions when to close variables? we don't want to do it\n\t * unless the environment may have \"escaped\" (referenced in a function closure).\n\t * With delayed environments, the existence is probably good enough of a check.\n\t */\n\n\t/* Note: we rely on the _Varmap having a bunch of nice properties, like:\n\t *  - being compacted and unmodified during this process\n\t *  - not containing an array part\n\t *  - having correct value types\n\t */\n\n\tDUK_DDD(DUK_DDDPRINT(\"copying bound register values, %ld bound regs\", (long) DUK_HOBJECT_GET_ENEXT(varmap)));\n\n\t/* Copy over current variable values from value stack to the\n\t * environment record.  The scope object is empty but may\n\t * inherit from another scope which has conflicting names.\n\t */\n\n\t/* XXX: Do this using a once allocated entry area, no side effects.\n\t * Hash part would need special treatment however (maybe copy, and\n\t * then realloc with hash part if large enough).\n\t */\n\tfor (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(varmap); i++) {\n\t\tduk_size_t regbase_byteoff;\n\n\t\tkey = DUK_HOBJECT_E_GET_KEY(thr->heap, varmap, i);\n\t\tDUK_ASSERT(key != NULL);   /* assume keys are compact in _Varmap */\n\t\tDUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, varmap, i));  /* assume plain values */\n\n\t\ttv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, varmap, i);\n\t\tDUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));\n\t\tDUK_ASSERT(DUK_TVAL_GET_NUMBER(tv) <= (duk_double_t) DUK_UINT32_MAX);  /* limits */\n#if defined(DUK_USE_FASTINT)\n\t\tDUK_ASSERT(DUK_TVAL_IS_FASTINT(tv));\n\t\tregnum = (duk_uint_t) DUK_TVAL_GET_FASTINT_U32(tv);\n#else\n\t\tregnum = (duk_uint_t) DUK_TVAL_GET_NUMBER(tv);\n#endif\n\n\t\tregbase_byteoff = ((duk_hdecenv *) env)->regbase_byteoff;\n\t\tDUK_ASSERT((duk_uint8_t *) thr->valstack + regbase_byteoff + sizeof(duk_tval) * regnum >= (duk_uint8_t *) thr->valstack);\n\t\tDUK_ASSERT((duk_uint8_t *) thr->valstack + regbase_byteoff + sizeof(duk_tval) * regnum < (duk_uint8_t *) thr->valstack_top);\n\n\t\t/* If property already exists, overwrites silently.\n\t\t * Property is writable, but not deletable (not configurable\n\t\t * in terms of property attributes).\n\t\t */\n\t\tduk_push_tval(thr, (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + regbase_byteoff + sizeof(duk_tval) * regnum));\n\t\tDUK_DDD(DUK_DDDPRINT(\"closing identifier %!O -> reg %ld, value %!T\",\n\t\t                     (duk_heaphdr *) key,\n\t\t                     (long) regnum,\n\t\t                     (duk_tval *) duk_get_tval(thr, -1)));\n\t\tduk_hobject_define_property_internal(thr, env, key, DUK_PROPDESC_FLAGS_WE);\n\t}\n\n\t/* NULL atomically to avoid inconsistent state + side effects. */\n\tDUK_HOBJECT_DECREF_NORZ(thr, ((duk_hdecenv *) env)->thread);\n\tDUK_HOBJECT_DECREF_NORZ(thr, ((duk_hdecenv *) env)->varmap);\n\t((duk_hdecenv *) env)->thread = NULL;\n\t((duk_hdecenv *) env)->varmap = NULL;\n\n\tDUK_DDD(DUK_DDDPRINT(\"env after closing: %!O\", (duk_heaphdr *) env));\n}\n\n/*\n *  GETIDREF: a GetIdentifierReference-like helper.\n *\n *  Provides a parent traversing lookup and a single level lookup\n *  (for HasBinding).\n *\n *  Instead of returning the value, returns a bunch of values allowing\n *  the caller to read, write, or delete the binding.  Value pointers\n *  are duk_tval pointers which can be mutated directly as long as\n *  refcounts are properly updated.  Note that any operation which may\n *  reallocate valstacks or compact objects may invalidate the returned\n *  duk_tval (but not object) pointers, so caller must be very careful.\n *\n *  If starting environment record 'env' is given, 'act' is ignored.\n *  However, if 'env' is NULL, the caller may identify, in 'act', an\n *  activation which hasn't had its declarative environment initialized\n *  yet.  The activation registers are then looked up, and its parent\n *  traversed normally.\n *\n *  The 'out' structure values are only valid if the function returns\n *  success (non-zero).\n */\n\n/* lookup name from an open declarative record's registers */\nDUK_LOCAL\nduk_bool_t duk__getid_open_decl_env_regs(duk_hthread *thr,\n                                         duk_hstring *name,\n                                         duk_hdecenv *env,\n                                         duk__id_lookup_result *out) {\n\tduk_tval *tv;\n\tduk_size_t reg_rel;\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(name != NULL);\n\tDUK_ASSERT(env != NULL);\n\tDUK_ASSERT(out != NULL);\n\n\tDUK_ASSERT(DUK_HOBJECT_IS_DECENV((duk_hobject *) env));\n\tDUK_ASSERT_HDECENV_VALID(env);\n\n\tif (env->thread == NULL) {\n\t\t/* already closed */\n\t\treturn 0;\n\t}\n\tDUK_ASSERT(env->varmap != NULL);\n\n\ttv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, env->varmap, name);\n\tif (DUK_UNLIKELY(tv == NULL)) {\n\t\treturn 0;\n\t}\n\n\tDUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));\n\tDUK_ASSERT(DUK_TVAL_GET_NUMBER(tv) <= (duk_double_t) DUK_UINT32_MAX);  /* limits */\n#if defined(DUK_USE_FASTINT)\n\tDUK_ASSERT(DUK_TVAL_IS_FASTINT(tv));\n\treg_rel = (duk_size_t) DUK_TVAL_GET_FASTINT_U32(tv);\n#else\n\treg_rel = (duk_size_t) DUK_TVAL_GET_NUMBER(tv);\n#endif\n\tDUK_ASSERT_DISABLE(reg_rel >= 0);  /* unsigned */\n\n\ttv = (duk_tval *) (void *) ((duk_uint8_t *) env->thread->valstack + env->regbase_byteoff + sizeof(duk_tval) * reg_rel);\n\tDUK_ASSERT(tv >= env->thread->valstack && tv < env->thread->valstack_end);  /* XXX: more accurate? */\n\n\tout->value = tv;\n\tout->attrs = DUK_PROPDESC_FLAGS_W;  /* registers are mutable, non-deletable */\n\tout->env = (duk_hobject *) env;\n\tout->holder = NULL;\n\tout->has_this = 0;\n\treturn 1;\n}\n\n/* lookup name from current activation record's functions' registers */\nDUK_LOCAL\nduk_bool_t duk__getid_activation_regs(duk_hthread *thr,\n                                      duk_hstring *name,\n                                      duk_activation *act,\n                                      duk__id_lookup_result *out) {\n\tduk_tval *tv;\n\tduk_hobject *func;\n\tduk_hobject *varmap;\n\tduk_size_t reg_rel;\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(name != NULL);\n\tDUK_ASSERT(act != NULL);\n\tDUK_ASSERT(out != NULL);\n\n\tfunc = DUK_ACT_GET_FUNC(act);\n\tDUK_ASSERT(func != NULL);\n\tDUK_ASSERT(DUK_HOBJECT_HAS_NEWENV(func));\n\n\tif (!DUK_HOBJECT_IS_COMPFUNC(func)) {\n\t\treturn 0;\n\t}\n\n\t/* XXX: move varmap to duk_hcompfunc struct field. */\n\ttv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, func, DUK_HTHREAD_STRING_INT_VARMAP(thr));\n\tif (!tv) {\n\t\treturn 0;\n\t}\n\tDUK_ASSERT(DUK_TVAL_IS_OBJECT(tv));\n\tvarmap = DUK_TVAL_GET_OBJECT(tv);\n\tDUK_ASSERT(varmap != NULL);\n\n\ttv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, varmap, name);\n\tif (!tv) {\n\t\treturn 0;\n\t}\n\tDUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));\n\treg_rel = (duk_size_t) DUK_TVAL_GET_NUMBER(tv);\n\tDUK_ASSERT_DISABLE(reg_rel >= 0);\n\tDUK_ASSERT(reg_rel < ((duk_hcompfunc *) func)->nregs);\n\n\ttv = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + act->bottom_byteoff);\n\ttv += reg_rel;\n\n\tout->value = tv;\n\tout->attrs = DUK_PROPDESC_FLAGS_W;  /* registers are mutable, non-deletable */\n\tout->env = NULL;\n\tout->holder = NULL;\n\tout->has_this = 0;\n\treturn 1;\n}\n\nDUK_LOCAL\nduk_bool_t duk__get_identifier_reference(duk_hthread *thr,\n                                         duk_hobject *env,\n                                         duk_hstring *name,\n                                         duk_activation *act,\n                                         duk_bool_t parents,\n                                         duk__id_lookup_result *out) {\n\tduk_tval *tv;\n\tduk_uint_t sanity;\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(env != NULL || act != NULL);\n\tDUK_ASSERT(name != NULL);\n\tDUK_ASSERT(out != NULL);\n\n\tDUK_ASSERT(!env || DUK_HOBJECT_IS_ENV(env));\n\tDUK_ASSERT(!env || !DUK_HOBJECT_HAS_ARRAY_PART(env));\n\n\t/*\n\t *  Conceptually, we look for the identifier binding by starting from\n\t *  'env' and following to chain of environment records (represented\n\t *  by the prototype chain).\n\t *\n\t *  If 'env' is NULL, the current activation does not yet have an\n\t *  allocated declarative environment record; this should be treated\n\t *  exactly as if the environment record existed but had no bindings\n\t *  other than register bindings.\n\t *\n\t *  Note: we assume that with the DUK_HOBJECT_FLAG_NEWENV cleared\n\t *  the environment will always be initialized immediately; hence\n\t *  a NULL 'env' should only happen with the flag set.  This is the\n\t *  case for: (1) function calls, and (2) strict, direct eval calls.\n\t */\n\n\tif (env == NULL && act != NULL) {\n\t\tduk_hobject *func;\n\t\tduk_hcompfunc *f;\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"duk__get_identifier_reference: env is NULL, activation is non-NULL -> \"\n\t\t                     \"delayed env case, look up activation regs first\"));\n\n\t\t/*\n\t\t *  Try registers\n\t\t */\n\n\t\tif (duk__getid_activation_regs(thr, name, act, out)) {\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"duk__get_identifier_reference successful: \"\n\t\t\t                     \"name=%!O -> value=%!T, attrs=%ld, has_this=%ld, env=%!O, holder=%!O \"\n\t\t\t                     \"(found from register bindings when env=NULL)\",\n\t\t\t                     (duk_heaphdr *) name, (duk_tval *) out->value,\n\t\t\t                     (long) out->attrs, (long) out->has_this,\n\t\t\t                     (duk_heaphdr *) out->env, (duk_heaphdr *) out->holder));\n\t\t\treturn 1;\n\t\t}\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"not found in current activation regs\"));\n\n\t\t/*\n\t\t *  Not found in registers, proceed to the parent record.\n\t\t *  Here we need to determine what the parent would be,\n\t\t *  if 'env' was not NULL (i.e. same logic as when initializing\n\t\t *  the record).\n\t\t *\n\t\t *  Note that environment initialization is only deferred when\n\t\t *  DUK_HOBJECT_HAS_NEWENV is set, and this only happens for:\n\t\t *    - Function code\n\t\t *    - Strict eval code\n\t\t *\n\t\t *  We only need to check _Lexenv here; _Varenv exists only if it\n\t\t *  differs from _Lexenv (and thus _Lexenv will also be present).\n\t\t */\n\n\t\tif (!parents) {\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"duk__get_identifier_reference failed, no parent traversal \"\n\t\t\t                     \"(not found from register bindings when env=NULL)\"));\n\t\t\tgoto fail_not_found;\n\t\t}\n\n\t\tfunc = DUK_ACT_GET_FUNC(act);\n\t\tDUK_ASSERT(func != NULL);\n\t\tDUK_ASSERT(DUK_HOBJECT_HAS_NEWENV(func));\n\t\tf = (duk_hcompfunc *) func;\n\n\t\tenv = DUK_HCOMPFUNC_GET_LEXENV(thr->heap, f);\n\t\tif (!env) {\n\t\t\tenv = thr->builtins[DUK_BIDX_GLOBAL_ENV];\n\t\t}\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"continue lookup from env: %!iO\",\n\t\t                     (duk_heaphdr *) env));\n\t}\n\n\t/*\n\t *  Prototype walking starting from 'env'.\n\t *\n\t *  ('act' is not needed anywhere here.)\n\t */\n\n\tsanity = DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY;\n\twhile (env != NULL) {\n\t\tduk_small_uint_t cl;\n\t\tduk_uint_t attrs;\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"duk__get_identifier_reference, name=%!O, considering env=%p -> %!iO\",\n\t\t                     (duk_heaphdr *) name,\n\t\t                     (void *) env,\n\t\t                     (duk_heaphdr *) env));\n\n\t\tDUK_ASSERT(env != NULL);\n\t\tDUK_ASSERT(DUK_HOBJECT_IS_ENV(env));\n\t\tDUK_ASSERT(!DUK_HOBJECT_HAS_ARRAY_PART(env));\n\n\t\tcl = DUK_HOBJECT_GET_CLASS_NUMBER(env);\n\t\tDUK_ASSERT(cl == DUK_HOBJECT_CLASS_OBJENV || cl == DUK_HOBJECT_CLASS_DECENV);\n\t\tif (cl == DUK_HOBJECT_CLASS_DECENV) {\n\t\t\t/*\n\t\t\t *  Declarative environment record.\n\t\t\t *\n\t\t\t *  Identifiers can never be stored in ancestors and are\n\t\t\t *  always plain values, so we can use an internal helper\n\t\t\t *  and access the value directly with an duk_tval ptr.\n\t\t\t *\n\t\t\t *  A closed environment is only indicated by it missing\n\t\t\t *  the \"book-keeping\" properties required for accessing\n\t\t\t *  register-bound variables.\n\t\t\t */\n\n\t\t\tDUK_ASSERT_HDECENV_VALID((duk_hdecenv *) env);\n\t\t\tif (duk__getid_open_decl_env_regs(thr, name, (duk_hdecenv *) env, out)) {\n\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"duk__get_identifier_reference successful: \"\n\t\t\t\t                     \"name=%!O -> value=%!T, attrs=%ld, has_this=%ld, env=%!O, holder=%!O \"\n\t\t\t\t                     \"(declarative environment record, scope open, found in regs)\",\n\t\t\t\t                     (duk_heaphdr *) name, (duk_tval *) out->value,\n\t\t\t\t                     (long) out->attrs, (long) out->has_this,\n\t\t\t\t                     (duk_heaphdr *) out->env, (duk_heaphdr *) out->holder));\n\t\t\t\treturn 1;\n\t\t\t}\n\n\t\t\ttv = duk_hobject_find_existing_entry_tval_ptr_and_attrs(thr->heap, env, name, &attrs);\n\t\t\tif (tv) {\n\t\t\t\tout->value = tv;\n\t\t\t\tout->attrs = attrs;\n\t\t\t\tout->env = env;\n\t\t\t\tout->holder = env;\n\t\t\t\tout->has_this = 0;\n\n\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"duk__get_identifier_reference successful: \"\n\t\t\t\t                     \"name=%!O -> value=%!T, attrs=%ld, has_this=%ld, env=%!O, holder=%!O \"\n\t\t\t\t                     \"(declarative environment record, found in properties)\",\n\t\t\t\t                     (duk_heaphdr *) name, (duk_tval *) out->value,\n\t\t\t\t                     (long) out->attrs, (long) out->has_this,\n\t\t\t\t                     (duk_heaphdr *) out->env, (duk_heaphdr *) out->holder));\n\t\t\t\treturn 1;\n\t\t\t}\n\t\t} else {\n\t\t\t/*\n\t\t\t *  Object environment record.\n\t\t\t *\n\t\t\t *  Binding (target) object is an external, uncontrolled object.\n\t\t\t *  Identifier may be bound in an ancestor property, and may be\n\t\t\t *  an accessor.  Target can also be a Proxy which we must support\n\t\t\t *  here.\n\t\t\t */\n\n\t\t\t/* XXX: we could save space by using _Target OR _This.  If _Target, assume\n\t\t\t * this binding is undefined.  If _This, assumes this binding is _This, and\n\t\t\t * target is also _This.  One property would then be enough.\n\t\t\t */\n\n\t\t\tduk_hobject *target;\n\t\t\tduk_bool_t found;\n\n\t\t\tDUK_ASSERT(cl == DUK_HOBJECT_CLASS_OBJENV);\n\t\t\tDUK_ASSERT_HOBJENV_VALID((duk_hobjenv *) env);\n\n\t\t\ttarget = ((duk_hobjenv *) env)->target;\n\t\t\tDUK_ASSERT(target != NULL);\n\n\t\t\t/* Target may be a Proxy or property may be an accessor, so we must\n\t\t\t * use an actual, Proxy-aware hasprop check here.\n\t\t\t *\n\t\t\t * out->holder is NOT set to the actual duk_hobject where the\n\t\t\t * property is found, but rather the object binding target object.\n\t\t\t */\n\n#if defined(DUK_USE_ES6_PROXY)\n\t\t\tif (DUK_UNLIKELY(DUK_HOBJECT_IS_PROXY(target))) {\n\t\t\t\tduk_tval tv_name;\n\t\t\t\tduk_tval tv_target_tmp;\n\n\t\t\t\tDUK_ASSERT(name != NULL);\n\t\t\t\tDUK_TVAL_SET_STRING(&tv_name, name);\n\t\t\t\tDUK_TVAL_SET_OBJECT(&tv_target_tmp, target);\n\n\t\t\t\tfound = duk_hobject_hasprop(thr, &tv_target_tmp, &tv_name);\n\t\t\t} else\n#endif  /* DUK_USE_ES6_PROXY */\n\t\t\t{\n\t\t\t\t/* XXX: duk_hobject_hasprop() would be correct for\n\t\t\t\t * non-Proxy objects too, but it is about ~20-25%\n\t\t\t\t * slower at present so separate code paths for\n\t\t\t\t * Proxy and non-Proxy now.\n\t\t\t\t */\n\t\t\t\tfound = duk_hobject_hasprop_raw(thr, target, name);\n\t\t\t}\n\n\t\t\tif (found) {\n\t\t\t\tout->value = NULL;  /* can't get value, may be accessor */\n\t\t\t\tout->attrs = 0;     /* irrelevant when out->value == NULL */\n\t\t\t\tout->env = env;\n\t\t\t\tout->holder = target;\n\t\t\t\tout->has_this = ((duk_hobjenv *) env)->has_this;\n\n\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"duk__get_identifier_reference successful: \"\n\t\t\t\t                     \"name=%!O -> value=%!T, attrs=%ld, has_this=%ld, env=%!O, holder=%!O \"\n\t\t\t\t                     \"(object environment record)\",\n\t\t\t\t                     (duk_heaphdr *) name, (duk_tval *) out->value,\n\t\t\t\t                     (long) out->attrs, (long) out->has_this,\n\t\t\t\t                     (duk_heaphdr *) out->env, (duk_heaphdr *) out->holder));\n\t\t\t\treturn 1;\n\t\t\t}\n\t\t}\n\n\t\tif (!parents) {\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"duk__get_identifier_reference failed, no parent traversal \"\n\t\t\t                     \"(not found from first traversed env)\"));\n\t\t\tgoto fail_not_found;\n\t\t}\n\n                if (DUK_UNLIKELY(sanity-- == 0)) {\n                        DUK_ERROR_RANGE(thr, DUK_STR_PROTOTYPE_CHAIN_LIMIT);\n                }\n\t\tenv = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, env);\n\t}\n\n\t/*\n\t *  Not found (even in global object)\n\t */\n\n fail_not_found:\n\treturn 0;\n}\n\n/*\n *  HASVAR: check identifier binding from a given environment record\n *  without traversing its parents.\n *\n *  This primitive is not exposed to user code as such, but is used\n *  internally for e.g. declaration binding instantiation.\n *\n *  See E5 Sections:\n *    10.2.1.1.1 HasBinding(N)\n *    10.2.1.2.1 HasBinding(N)\n *\n *  Note: strictness has no bearing on this check.  Hence we don't take\n *  a 'strict' parameter.\n */\n\n#if 0  /*unused*/\nDUK_INTERNAL\nduk_bool_t duk_js_hasvar_envrec(duk_hthread *thr,\n                                duk_hobject *env,\n                                duk_hstring *name) {\n\tduk__id_lookup_result ref;\n\tduk_bool_t parents;\n\n\tDUK_DDD(DUK_DDDPRINT(\"hasvar: thr=%p, env=%p, name=%!O \"\n\t                     \"(env -> %!dO)\",\n\t                     (void *) thr, (void *) env, (duk_heaphdr *) name,\n\t                     (duk_heaphdr *) env));\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(env != NULL);\n\tDUK_ASSERT(name != NULL);\n\n        DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(env);\n        DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(name);\n\n\tDUK_ASSERT(DUK_HOBJECT_IS_ENV(env));\n\tDUK_ASSERT(!DUK_HOBJECT_HAS_ARRAY_PART(env));\n\n\t/* lookup results is ignored */\n\tparents = 0;\n\treturn duk__get_identifier_reference(thr, env, name, NULL, parents, &ref);\n}\n#endif\n\n/*\n *  GETVAR\n *\n *  See E5 Sections:\n *    11.1.2 Identifier Reference\n *    10.3.1 Identifier Resolution\n *    11.13.1 Simple Assignment  [example of where the Reference is GetValue'd]\n *    8.7.1 GetValue (V)\n *    8.12.1 [[GetOwnProperty]] (P)\n *    8.12.2 [[GetProperty]] (P)\n *    8.12.3 [[Get]] (P)\n *\n *  If 'throw' is true, always leaves two values on top of stack: [val this].\n *\n *  If 'throw' is false, returns 0 if identifier cannot be resolved, and the\n *  stack will be unaffected in this case.  If identifier is resolved, returns\n *  1 and leaves [val this] on top of stack.\n *\n *  Note: the 'strict' flag of a reference returned by GetIdentifierReference\n *  is ignored by GetValue.  Hence we don't take a 'strict' parameter.\n *\n *  The 'throw' flag is needed for implementing 'typeof' for an unreferenced\n *  identifier.  An unreference identifier in other contexts generates a\n *  ReferenceError.\n */\n\nDUK_LOCAL\nduk_bool_t duk__getvar_helper(duk_hthread *thr,\n                              duk_hobject *env,\n                              duk_activation *act,\n                              duk_hstring *name,\n                              duk_bool_t throw_flag) {\n\tduk__id_lookup_result ref;\n\tduk_tval tv_tmp_obj;\n\tduk_tval tv_tmp_key;\n\tduk_bool_t parents;\n\n\tDUK_DDD(DUK_DDDPRINT(\"getvar: thr=%p, env=%p, act=%p, name=%!O \"\n\t                     \"(env -> %!dO)\",\n\t                     (void *) thr, (void *) env, (void *) act,\n\t                     (duk_heaphdr *) name, (duk_heaphdr *) env));\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(name != NULL);\n\t/* env and act may be NULL */\n\n\tDUK_STATS_INC(thr->heap, stats_getvar_all);\n\n        DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(env);\n        DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(name);\n\n\tparents = 1;     /* follow parent chain */\n\tif (duk__get_identifier_reference(thr, env, name, act, parents, &ref)) {\n\t\tif (ref.value) {\n\t\t\tduk_push_tval(thr, ref.value);\n\t\t\tduk_push_undefined(thr);\n\t\t} else {\n\t\t\tDUK_ASSERT(ref.holder != NULL);\n\n\t\t\t/* ref.holder is safe across the getprop call (even\n\t\t\t * with side effects) because 'env' is reachable and\n\t\t\t * ref.holder is a direct heap pointer.\n\t\t\t */\n\n\t\t\tDUK_TVAL_SET_OBJECT(&tv_tmp_obj, ref.holder);\n\t\t\tDUK_TVAL_SET_STRING(&tv_tmp_key, name);\n\t\t\t(void) duk_hobject_getprop(thr, &tv_tmp_obj, &tv_tmp_key);  /* [value] */\n\n\t\t\tif (ref.has_this) {\n\t\t\t\tduk_push_hobject(thr, ref.holder);\n\t\t\t} else {\n\t\t\t\tduk_push_undefined(thr);\n\t\t\t}\n\n\t\t\t/* [value this] */\n\t\t}\n\n\t\treturn 1;\n\t} else {\n\t\tif (throw_flag) {\n\t\t\tDUK_ERROR_FMT1(thr, DUK_ERR_REFERENCE_ERROR,\n\t\t\t               \"identifier '%s' undefined\",\n\t\t\t               (const char *) DUK_HSTRING_GET_DATA(name));\n\t\t}\n\n\t\treturn 0;\n\t}\n}\n\nDUK_INTERNAL\nduk_bool_t duk_js_getvar_envrec(duk_hthread *thr,\n                                duk_hobject *env,\n                                duk_hstring *name,\n                                duk_bool_t throw_flag) {\n\treturn duk__getvar_helper(thr, env, NULL, name, throw_flag);\n}\n\nDUK_INTERNAL\nduk_bool_t duk_js_getvar_activation(duk_hthread *thr,\n                                    duk_activation *act,\n                                    duk_hstring *name,\n                                    duk_bool_t throw_flag) {\n\tDUK_ASSERT(act != NULL);\n\treturn duk__getvar_helper(thr, act->lex_env, act, name, throw_flag);\n}\n\n/*\n *  PUTVAR\n *\n *  See E5 Sections:\n *    11.1.2 Identifier Reference\n *    10.3.1 Identifier Resolution\n *    11.13.1 Simple Assignment  [example of where the Reference is PutValue'd]\n *    8.7.2 PutValue (V,W)  [see especially step 3.b, undefined -> automatic global in non-strict mode]\n *    8.12.4 [[CanPut]] (P)\n *    8.12.5 [[Put]] (P)\n *\n *  Note: may invalidate any valstack (or object) duk_tval pointers because\n *  putting a value may reallocate any object or any valstack.  Caller beware.\n */\n\nDUK_LOCAL\nvoid duk__putvar_helper(duk_hthread *thr,\n                        duk_hobject *env,\n                        duk_activation *act,\n                        duk_hstring *name,\n                        duk_tval *val,\n                        duk_bool_t strict) {\n\tduk__id_lookup_result ref;\n\tduk_tval tv_tmp_obj;\n\tduk_tval tv_tmp_key;\n\tduk_bool_t parents;\n\n\tDUK_STATS_INC(thr->heap, stats_putvar_all);\n\n\tDUK_DDD(DUK_DDDPRINT(\"putvar: thr=%p, env=%p, act=%p, name=%!O, val=%p, strict=%ld \"\n\t                     \"(env -> %!dO, val -> %!T)\",\n\t                     (void *) thr, (void *) env, (void *) act,\n\t                     (duk_heaphdr *) name, (void *) val, (long) strict,\n\t                     (duk_heaphdr *) env, (duk_tval *) val));\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(name != NULL);\n\tDUK_ASSERT(val != NULL);\n\t/* env and act may be NULL */\n\n        DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(env);\n        DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(name);\n\tDUK_ASSERT_REFCOUNT_NONZERO_TVAL(val);\n\n\t/*\n\t *  In strict mode E5 protects 'eval' and 'arguments' from being\n\t *  assigned to (or even declared anywhere).  Attempt to do so\n\t *  should result in a compile time SyntaxError.  See the internal\n\t *  design documentation for details.\n\t *\n\t *  Thus, we should never come here, run-time, for strict code,\n\t *  and name 'eval' or 'arguments'.\n\t */\n\n\tDUK_ASSERT(!strict ||\n\t           (name != DUK_HTHREAD_STRING_EVAL(thr) &&\n\t            name != DUK_HTHREAD_STRING_LC_ARGUMENTS(thr)));\n\n\t/*\n\t *  Lookup variable and update in-place if found.\n\t */\n\n\tparents = 1;     /* follow parent chain */\n\n\tif (duk__get_identifier_reference(thr, env, name, act, parents, &ref)) {\n\t\tif (ref.value && (ref.attrs & DUK_PROPDESC_FLAG_WRITABLE)) {\n\t\t\t/* Update duk_tval in-place if pointer provided and the\n\t\t\t * property is writable.  If the property is not writable\n\t\t\t * (immutable binding), use duk_hobject_putprop() which\n\t\t\t * will respect mutability.\n\t\t\t */\n\t\t\tduk_tval *tv_val;\n\n\t\t\ttv_val = ref.value;\n\t\t\tDUK_ASSERT(tv_val != NULL);\n\t\t\tDUK_TVAL_SET_TVAL_UPDREF(thr, tv_val, val);  /* side effects */\n\n\t\t\t/* ref.value invalidated here */\n\t\t} else {\n\t\t\tDUK_ASSERT(ref.holder != NULL);\n\n\t\t\tDUK_TVAL_SET_OBJECT(&tv_tmp_obj, ref.holder);\n\t\t\tDUK_TVAL_SET_STRING(&tv_tmp_key, name);\n\t\t\t(void) duk_hobject_putprop(thr, &tv_tmp_obj, &tv_tmp_key, val, strict);\n\n\t\t\t/* ref.value invalidated here */\n\t\t}\n\n\t\treturn;\n\t}\n\n\t/*\n\t *  Not found: write to global object (non-strict) or ReferenceError\n\t *  (strict); see E5 Section 8.7.2, step 3.\n\t */\n\n\tif (strict) {\n\t\tDUK_DDD(DUK_DDDPRINT(\"identifier binding not found, strict => reference error\"));\n\t\tDUK_ERROR_FMT1(thr, DUK_ERR_REFERENCE_ERROR,\n\t\t               \"identifier '%s' undefined\",\n\t\t               (const char *) DUK_HSTRING_GET_DATA(name));\n\t}\n\n\tDUK_DDD(DUK_DDDPRINT(\"identifier binding not found, not strict => set to global\"));\n\n\tDUK_TVAL_SET_OBJECT(&tv_tmp_obj, thr->builtins[DUK_BIDX_GLOBAL]);\n\tDUK_TVAL_SET_STRING(&tv_tmp_key, name);\n\t(void) duk_hobject_putprop(thr, &tv_tmp_obj, &tv_tmp_key, val, 0);  /* 0 = no throw */\n\n\t/* NB: 'val' may be invalidated here because put_value may realloc valstack,\n\t * caller beware.\n\t */\n}\n\nDUK_INTERNAL\nvoid duk_js_putvar_envrec(duk_hthread *thr,\n                          duk_hobject *env,\n                          duk_hstring *name,\n                          duk_tval *val,\n                          duk_bool_t strict) {\n\tduk__putvar_helper(thr, env, NULL, name, val, strict);\n}\n\nDUK_INTERNAL\nvoid duk_js_putvar_activation(duk_hthread *thr,\n                              duk_activation *act,\n                              duk_hstring *name,\n                              duk_tval *val,\n                              duk_bool_t strict) {\n\tDUK_ASSERT(act != NULL);\n\tduk__putvar_helper(thr, act->lex_env, act, name, val, strict);\n}\n\n/*\n *  DELVAR\n *\n *  See E5 Sections:\n *    11.4.1 The delete operator\n *    10.2.1.1.5 DeleteBinding (N)  [declarative environment record]\n *    10.2.1.2.5 DeleteBinding (N)  [object environment record]\n *\n *  Variable bindings established inside eval() are deletable (configurable),\n *  other bindings are not, including variables declared in global level.\n *  Registers are always non-deletable, and the deletion of other bindings\n *  is controlled by the configurable flag.\n *\n *  For strict mode code, the 'delete' operator should fail with a compile\n *  time SyntaxError if applied to identifiers.  Hence, no strict mode\n *  run-time deletion of identifiers should ever happen.  This function\n *  should never be called from strict mode code!\n */\n\nDUK_LOCAL\nduk_bool_t duk__delvar_helper(duk_hthread *thr,\n                              duk_hobject *env,\n                              duk_activation *act,\n                              duk_hstring *name) {\n\tduk__id_lookup_result ref;\n\tduk_bool_t parents;\n\n\tDUK_DDD(DUK_DDDPRINT(\"delvar: thr=%p, env=%p, act=%p, name=%!O \"\n\t                     \"(env -> %!dO)\",\n\t                     (void *) thr, (void *) env, (void *) act,\n\t                     (duk_heaphdr *) name, (duk_heaphdr *) env));\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(name != NULL);\n\t/* env and act may be NULL */\n\n        DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(name);\n\n\tparents = 1;     /* follow parent chain */\n\n\tif (duk__get_identifier_reference(thr, env, name, act, parents, &ref)) {\n\t\tif (ref.value && !(ref.attrs & DUK_PROPDESC_FLAG_CONFIGURABLE)) {\n\t\t\t/* Identifier found in registers (always non-deletable)\n\t\t\t * or declarative environment record and non-configurable.\n\t\t\t */\n\t\t\treturn 0;\n\t\t}\n\t\tDUK_ASSERT(ref.holder != NULL);\n\n\t\treturn duk_hobject_delprop_raw(thr, ref.holder, name, 0);\n\t}\n\n\t/*\n\t *  Not found (even in global object).\n\t *\n\t *  In non-strict mode this is a silent SUCCESS (!), see E5 Section 11.4.1,\n\t *  step 3.b.  In strict mode this case is a compile time SyntaxError so\n\t *  we should not come here.\n\t */\n\n\tDUK_DDD(DUK_DDDPRINT(\"identifier to be deleted not found: name=%!O \"\n\t                     \"(treated as silent success)\",\n\t                     (duk_heaphdr *) name));\n\treturn 1;\n}\n\n#if 0  /*unused*/\nDUK_INTERNAL\nduk_bool_t duk_js_delvar_envrec(duk_hthread *thr,\n                                duk_hobject *env,\n                                duk_hstring *name) {\n\treturn duk__delvar_helper(thr, env, NULL, name);\n}\n#endif\n\nDUK_INTERNAL\nduk_bool_t duk_js_delvar_activation(duk_hthread *thr,\n                                    duk_activation *act,\n                                    duk_hstring *name) {\n\tDUK_ASSERT(act != NULL);\n\treturn duk__delvar_helper(thr, act->lex_env, act, name);\n}\n\n/*\n *  DECLVAR\n *\n *  See E5 Sections:\n *    10.4.3 Entering Function Code\n *    10.5 Declaration Binding Instantion\n *    12.2 Variable Statement\n *    11.1.2 Identifier Reference\n *    10.3.1 Identifier Resolution\n *\n *  Variable declaration behavior is mainly discussed in Section 10.5,\n *  and is not discussed in the execution semantics (Sections 11-13).\n *\n *  Conceptually declarations happen when code (global, eval, function)\n *  is entered, before any user code is executed.  In practice, register-\n *  bound identifiers are 'declared' automatically (by virtue of being\n *  allocated to registers with the initial value 'undefined').  Other\n *  identifiers are declared in the function prologue with this primitive.\n *\n *  Since non-register bindings eventually back to an internal object's\n *  properties, the 'prop_flags' argument is used to specify binding\n *  type:\n *\n *    - Immutable binding: set DUK_PROPDESC_FLAG_WRITABLE to false\n *    - Non-deletable binding: set DUK_PROPDESC_FLAG_CONFIGURABLE to false\n *    - The flag DUK_PROPDESC_FLAG_ENUMERABLE should be set, although it\n *      doesn't really matter for internal objects\n *\n *  All bindings are non-deletable mutable bindings except:\n *\n *    - Declarations in eval code (mutable, deletable)\n *    - 'arguments' binding in strict function code (immutable)\n *    - Function name binding of a function expression (immutable)\n *\n *  Declarations may go to declarative environment records (always\n *  so for functions), but may also go to object environment records\n *  (e.g. global code).  The global object environment has special\n *  behavior when re-declaring a function (but not a variable); see\n *  E5.1 specification, Section 10.5, step 5.e.\n *\n *  Declarations always go to the 'top-most' environment record, i.e.\n *  we never check the record chain.  It's not an error even if a\n *  property (even an immutable or non-deletable one) of the same name\n *  already exists.\n *\n *  If a declared variable already exists, its value needs to be updated\n *  (if possible).  Returns 1 if a PUTVAR needs to be done by the caller;\n *  otherwise returns 0.\n */\n\nDUK_LOCAL\nduk_bool_t duk__declvar_helper(duk_hthread *thr,\n                               duk_hobject *env,\n                               duk_hstring *name,\n                               duk_tval *val,\n                               duk_small_uint_t prop_flags,\n                               duk_bool_t is_func_decl) {\n\tduk_hobject *holder;\n\tduk_bool_t parents;\n\tduk__id_lookup_result ref;\n\tduk_tval *tv;\n\n\tDUK_DDD(DUK_DDDPRINT(\"declvar: thr=%p, env=%p, name=%!O, val=%!T, prop_flags=0x%08lx, is_func_decl=%ld \"\n\t                     \"(env -> %!iO)\",\n\t                     (void *) thr, (void *) env, (duk_heaphdr *) name,\n\t                     (duk_tval *) val, (unsigned long) prop_flags,\n\t                     (unsigned int) is_func_decl, (duk_heaphdr *) env));\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(env != NULL);\n\tDUK_ASSERT(name != NULL);\n\tDUK_ASSERT(val != NULL);\n\n\t/* Note: in strict mode the compiler should reject explicit\n\t * declaration of 'eval' or 'arguments'.  However, internal\n\t * bytecode may declare 'arguments' in the function prologue.\n\t * We don't bother checking (or asserting) for these now.\n\t */\n\n\t/* Note: val is a stable duk_tval pointer.  The caller makes\n\t * a value copy into its stack frame, so 'tv_val' is not subject\n\t * to side effects here.\n\t */\n\n\t/*\n\t *  Check whether already declared.\n\t *\n\t *  We need to check whether the binding exists in the environment\n\t *  without walking its parents.  However, we still need to check\n\t *  register-bound identifiers and the prototype chain of an object\n\t *  environment target object.\n\t */\n\n\tparents = 0;  /* just check 'env' */\n\tif (duk__get_identifier_reference(thr, env, name, NULL, parents, &ref)) {\n\t\tduk_int_t e_idx;\n\t\tduk_int_t h_idx;\n\t\tduk_small_uint_t flags;\n\n\t\t/*\n\t\t *  Variable already declared, ignore re-declaration.\n\t\t *  The only exception is the updated behavior of E5.1 for\n\t\t *  global function declarations, E5.1 Section 10.5, step 5.e.\n\t\t *  This behavior does not apply to global variable declarations.\n\t\t */\n\n\t\tif (!(is_func_decl && env == thr->builtins[DUK_BIDX_GLOBAL_ENV])) {\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"re-declare a binding, ignoring\"));\n\t\t\treturn 1;  /* 1 -> needs a PUTVAR */\n\t\t}\n\n\t\t/*\n\t\t *  Special behavior in E5.1.\n\t\t *\n\t\t *  Note that even though parents == 0, the conflicting property\n\t\t *  may be an inherited property (currently our global object's\n\t\t *  prototype is Object.prototype).  Step 5.e first operates on\n\t\t *  the existing property (which is potentially in an ancestor)\n\t\t *  and then defines a new property in the global object (and\n\t\t *  never modifies the ancestor).\n\t\t *\n\t\t *  Also note that this logic would become even more complicated\n\t\t *  if the conflicting property might be a virtual one.  Object\n\t\t *  prototype has no virtual properties, though.\n\t\t *\n\t\t *  XXX: this is now very awkward, rework.\n\t\t */\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"re-declare a function binding in global object, \"\n\t\t                     \"updated E5.1 processing\"));\n\n\t\tDUK_ASSERT(ref.holder != NULL);\n\t\tholder = ref.holder;\n\n\t\t/* holder will be set to the target object, not the actual object\n\t\t * where the property was found (see duk__get_identifier_reference()).\n\t\t */\n\t\tDUK_ASSERT(DUK_HOBJECT_GET_CLASS_NUMBER(holder) == DUK_HOBJECT_CLASS_GLOBAL);\n\t\tDUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARRAY(holder));  /* global object doesn't have array part */\n\n\t\t/* XXX: use a helper for prototype traversal; no loop check here */\n\t\t/* must be found: was found earlier, and cannot be inherited */\n\t\tfor (;;) {\n\t\t\tDUK_ASSERT(holder != NULL);\n\t\t\tif (duk_hobject_find_existing_entry(thr->heap, holder, name, &e_idx, &h_idx)) {\n\t\t\t\tDUK_ASSERT(e_idx >= 0);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\t/* SCANBUILD: NULL pointer dereference, doesn't actually trigger,\n\t\t\t * asserted above.\n\t\t\t */\n\t\t\tholder = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, holder);\n\t\t}\n\t\tDUK_ASSERT(holder != NULL);\n\t\tDUK_ASSERT(e_idx >= 0);\n\t\t/* SCANBUILD: scan-build produces a NULL pointer dereference warning\n\t\t * below; it never actually triggers because holder is actually never\n\t\t * NULL.\n\t\t */\n\n\t\t/* ref.holder is global object, holder is the object with the\n\t\t * conflicting property.\n\t\t */\n\n\t\tflags = DUK_HOBJECT_E_GET_FLAGS(thr->heap, holder, e_idx);\n\t\tif (!(flags & DUK_PROPDESC_FLAG_CONFIGURABLE)) {\n\t\t\tif (flags & DUK_PROPDESC_FLAG_ACCESSOR) {\n\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"existing property is a non-configurable \"\n\t\t\t\t                     \"accessor -> reject\"));\n\t\t\t\tgoto fail_existing_attributes;\n\t\t\t}\n\t\t\tif (!((flags & DUK_PROPDESC_FLAG_WRITABLE) &&\n\t\t\t      (flags & DUK_PROPDESC_FLAG_ENUMERABLE))) {\n\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"existing property is a non-configurable \"\n\t\t\t\t                     \"plain property which is not writable and \"\n\t\t\t\t                     \"enumerable -> reject\"));\n\t\t\t\tgoto fail_existing_attributes;\n\t\t\t}\n\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"existing property is not configurable but \"\n\t\t\t                     \"is plain, enumerable, and writable -> \"\n\t\t\t                     \"allow redeclaration\"));\n\t\t}\n\n\t\tif (holder == ref.holder) {\n\t\t\t/* XXX: if duk_hobject_define_property_internal() was updated\n\t\t\t * to handle a pre-existing accessor property, this would be\n\t\t\t * a simple call (like for the ancestor case).\n\t\t\t */\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"redefine, offending property in global object itself\"));\n\n\t\t\tif (flags & DUK_PROPDESC_FLAG_ACCESSOR) {\n\t\t\t\tduk_hobject *tmp;\n\n\t\t\t\ttmp = DUK_HOBJECT_E_GET_VALUE_GETTER(thr->heap, holder, e_idx);\n\t\t\t\tDUK_HOBJECT_E_SET_VALUE_GETTER(thr->heap, holder, e_idx, NULL);\n\t\t\t\tDUK_HOBJECT_DECREF_ALLOWNULL(thr, tmp);\n\t\t\t\tDUK_UNREF(tmp);\n\t\t\t\ttmp = DUK_HOBJECT_E_GET_VALUE_SETTER(thr->heap, holder, e_idx);\n\t\t\t\tDUK_HOBJECT_E_SET_VALUE_SETTER(thr->heap, holder, e_idx, NULL);\n\t\t\t\tDUK_HOBJECT_DECREF_ALLOWNULL(thr, tmp);\n\t\t\t\tDUK_UNREF(tmp);\n\t\t\t} else {\n\t\t\t\ttv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, holder, e_idx);\n\t\t\t\tDUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv);\n\t\t\t}\n\n\t\t\t/* Here val would be potentially invalid if we didn't make\n\t\t\t * a value copy at the caller.\n\t\t\t */\n\n\t\t\ttv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, holder, e_idx);\n\t\t\tDUK_TVAL_SET_TVAL(tv, val);\n\t\t\tDUK_TVAL_INCREF(thr, tv);\n\t\t\tDUK_HOBJECT_E_SET_FLAGS(thr->heap, holder, e_idx, prop_flags);\n\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"updated global binding, final result: \"\n\t\t\t                     \"value -> %!T, prop_flags=0x%08lx\",\n\t\t\t                     (duk_tval *) DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, holder, e_idx),\n\t\t\t                     (unsigned long) prop_flags));\n\t\t} else {\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"redefine, offending property in ancestor\"));\n\n\t\t\tDUK_ASSERT(ref.holder == thr->builtins[DUK_BIDX_GLOBAL]);\n\t\t\tduk_push_tval(thr, val);\n\t\t\tduk_hobject_define_property_internal(thr, ref.holder, name, prop_flags);\n\t\t}\n\n\t\treturn 0;\n\t}\n\n\t/*\n\t *  Not found (in registers or record objects).  Declare\n\t *  to current variable environment.\n\t */\n\n\t/*\n\t *  Get holder object\n\t */\n\n\tif (DUK_HOBJECT_IS_DECENV(env)) {\n\t\tDUK_ASSERT_HDECENV_VALID((duk_hdecenv *) env);\n\t\tholder = env;\n\t} else {\n\t\tDUK_ASSERT_HOBJENV_VALID((duk_hobjenv *) env);\n\t\tholder = ((duk_hobjenv *) env)->target;\n\t\tDUK_ASSERT(holder != NULL);\n\t}\n\n\t/*\n\t *  Define new property\n\t *\n\t *  Note: this may fail if the holder is not extensible.\n\t */\n\n\t/* XXX: this is awkward as we use an internal method which doesn't handle\n\t * extensibility etc correctly.  Basically we'd want to do a [[DefineOwnProperty]]\n\t * or Object.defineProperty() here.\n\t */\n\n\tif (!DUK_HOBJECT_HAS_EXTENSIBLE(holder)) {\n\t\tgoto fail_not_extensible;\n\t}\n\n\tduk_push_hobject(thr, holder);\n\tduk_push_hstring(thr, name);\n\tduk_push_tval(thr, val);\n\tduk_xdef_prop(thr, -3, prop_flags);  /* [holder name val] -> [holder] */\n\tduk_pop_unsafe(thr);\n\n\treturn 0;\n\n fail_existing_attributes:\n fail_not_extensible:\n\tDUK_ERROR_TYPE(thr, \"declaration failed\");\n\treturn 0;\n}\n\nDUK_INTERNAL\nduk_bool_t duk_js_declvar_activation(duk_hthread *thr,\n                                     duk_activation *act,\n                                     duk_hstring *name,\n                                     duk_tval *val,\n                                     duk_small_uint_t prop_flags,\n                                     duk_bool_t is_func_decl) {\n\tduk_hobject *env;\n\tduk_tval tv_val_copy;\n\n\tDUK_ASSERT(act != NULL);\n\n\t/*\n\t *  Make a value copy of the input val.  This ensures that\n\t *  side effects cannot invalidate the pointer.\n\t */\n\n\tDUK_TVAL_SET_TVAL(&tv_val_copy, val);\n\tval = &tv_val_copy;\n\n\t/*\n\t *  Delayed env creation check\n\t */\n\n\tif (!act->var_env) {\n\t\tDUK_ASSERT(act->lex_env == NULL);\n\t\tduk_js_init_activation_environment_records_delayed(thr, act);\n\t\t/* 'act' is a stable pointer, so still OK. */\n\t}\n\tDUK_ASSERT(act->lex_env != NULL);\n\tDUK_ASSERT(act->var_env != NULL);\n\n\tenv = act->var_env;\n\tDUK_ASSERT(env != NULL);\n\tDUK_ASSERT(DUK_HOBJECT_IS_ENV(env));\n\n\treturn duk__declvar_helper(thr, env, name, val, prop_flags, is_func_decl);\n}\n#line 1 \"duk_lexer.c\"\n/*\n *  Lexer for source files, ToNumber() string conversions, RegExp expressions,\n *  and JSON.\n *\n *  Provides a stream of Ecmascript tokens from an UTF-8/CESU-8 buffer.  The\n *  caller can also rewind the token stream into a certain position which is\n *  needed by the compiler part for multi-pass scanning.  Tokens are\n *  represented as duk_token structures, and contain line number information.\n *  Token types are identified with DUK_TOK_* defines.\n *\n *  Characters are decoded into a fixed size lookup window consisting of\n *  decoded Unicode code points, with window positions past the end of the\n *  input filled with an invalid codepoint (-1).  The tokenizer can thus\n *  perform multiple character lookups efficiently and with few sanity\n *  checks (such as access outside the end of the input), which keeps the\n *  tokenization code small at the cost of performance.\n *\n *  Character data in tokens, such as identifier names and string literals,\n *  is encoded into CESU-8 format on-the-fly while parsing the token in\n *  question.  The string data is made reachable to garbage collection by\n *  placing the token-related values in value stack entries allocated for\n *  this purpose by the caller.  The characters exist in Unicode code point\n *  form only in the fixed size lookup window, which keeps character data\n *  expansion (of especially ASCII data) low.\n *\n *  Token parsing supports the full range of Unicode characters as described\n *  in the E5 specification.  Parsing has been optimized for ASCII characters\n *  because ordinary Ecmascript code consists almost entirely of ASCII\n *  characters.  Matching of complex Unicode codepoint sets (such as in the\n *  IdentifierStart and IdentifierPart productions) is optimized for size,\n *  and is done using a linear scan of a bit-packed list of ranges.  This is\n *  very slow, but should never be entered unless the source code actually\n *  contains Unicode characters.\n *\n *  Ecmascript tokenization is partially context sensitive.  First,\n *  additional future reserved words are recognized in strict mode (see E5\n *  Section 7.6.1.2).  Second, a forward slash character ('/') can be\n *  recognized either as starting a RegExp literal or as a division operator,\n *  depending on context.  The caller must provide necessary context flags\n *  when requesting a new token.\n *\n *  Future work:\n *\n *    * Make line number tracking optional, as it consumes space.\n *\n *    * Add a feature flag for disabling UTF-8 decoding of input, as most\n *      source code is ASCII.  Because of Unicode escapes written in ASCII,\n *      this does not allow Unicode support to be removed from e.g.\n *      duk_unicode_is_identifier_start() nor does it allow removal of CESU-8\n *      encoding of e.g. string literals.\n *\n *    * Add a feature flag for disabling Unicode compliance of e.g. identifier\n *      names.  This allows for a build more than a kilobyte smaller, because\n *      Unicode ranges needed by duk_unicode_is_identifier_start() and\n *      duk_unicode_is_identifier_part() can be dropped.  String literals\n *      should still be allowed to contain escaped Unicode, so this still does\n *      not allow removal of CESU-8 encoding of e.g. string literals.\n *\n *    * Character lookup tables for codepoints above BMP could be stripped.\n *\n *    * Strictly speaking, E5 specification requires that source code consists\n *      of 16-bit code units, and if not, must be conceptually converted to\n *      that format first.  The current lexer processes Unicode code points\n *      and allows characters outside the BMP.  These should be converted to\n *      surrogate pairs while reading the source characters into the window,\n *      not after tokens have been formed (as is done now).  However, the fix\n *      is not trivial because two characters are decoded from one codepoint.\n *\n *    * Optimize for speed as well as size.  Large if-else ladders are (at\n *      least potentially) slow.\n */\n\n/* #include duk_internal.h -> already included */\n\n/*\n *  Various defines and file specific helper macros\n */\n\n#define DUK__MAX_RE_DECESC_DIGITS     9\n#define DUK__MAX_RE_QUANT_DIGITS      9   /* Does not allow e.g. 2**31-1, but one more would allow overflows of u32. */\n\n/* whether to use macros or helper function depends on call count */\n#define DUK__ISDIGIT(x)          ((x) >= DUK_ASC_0 && (x) <= DUK_ASC_9)\n#define DUK__ISHEXDIGIT(x)       duk__is_hex_digit((x))\n#define DUK__ISOCTDIGIT(x)       ((x) >= DUK_ASC_0 && (x) <= DUK_ASC_7)\n#define DUK__ISDIGIT03(x)        ((x) >= DUK_ASC_0 && (x) <= DUK_ASC_3)\n#define DUK__ISDIGIT47(x)        ((x) >= DUK_ASC_4 && (x) <= DUK_ASC_7)\n\n/* lexer character window helpers */\n#define DUK__LOOKUP(lex_ctx,idx)            ((lex_ctx)->window[(idx)].codepoint)\n#define DUK__ADVANCECHARS(lex_ctx,count)    duk__advance_chars((lex_ctx), (count))\n#define DUK__ADVANCEBYTES(lex_ctx,count)    duk__advance_bytes((lex_ctx), (count))\n#define DUK__INITBUFFER(lex_ctx)            duk__initbuffer((lex_ctx))\n#define DUK__APPENDBUFFER(lex_ctx,x)        duk__appendbuffer((lex_ctx), (duk_codepoint_t) (x))\n#define DUK__APPENDBUFFER_ASCII(lex_ctx,x)  duk__appendbuffer_ascii((lex_ctx), (duk_codepoint_t) (x))\n\n/* lookup shorthands (note: assume context variable is named 'lex_ctx') */\n#define DUK__L0()  DUK__LOOKUP(lex_ctx, 0)\n#define DUK__L1()  DUK__LOOKUP(lex_ctx, 1)\n#define DUK__L2()  DUK__LOOKUP(lex_ctx, 2)\n#define DUK__L3()  DUK__LOOKUP(lex_ctx, 3)\n#define DUK__L4()  DUK__LOOKUP(lex_ctx, 4)\n#define DUK__L5()  DUK__LOOKUP(lex_ctx, 5)\n\n/* packed advance/token number macro used by multiple functions */\n#define DUK__ADVTOK(advbytes,tok)  ((((advbytes) * sizeof(duk_lexer_codepoint)) << 8) + (tok))\n\n/*\n *  Advance lookup window by N characters, filling in new characters as\n *  necessary.  After returning caller is guaranteed a character window of\n *  at least DUK_LEXER_WINDOW_SIZE characters.\n *\n *  The main function duk__advance_bytes() is called at least once per every\n *  token so it has a major lexer/compiler performance impact.  There are two\n *  variants for the main duk__advance_bytes() algorithm: a sliding window\n *  approach which is slightly faster at the cost of larger code footprint,\n *  and a simple copying one.\n *\n *  Decoding directly from the source string would be another lexing option.\n *  But the lookup window based approach has the advantage of hiding the\n *  source string and its encoding effectively which gives more flexibility\n *  going forward to e.g. support chunked streaming of source from flash.\n *\n *  Decodes UTF-8/CESU-8 leniently with support for code points from U+0000 to\n *  U+10FFFF, causing an error if the input is unparseable.  Leniency means:\n *\n *    * Unicode code point validation is intentionally not performed,\n *      except to check that the codepoint does not exceed 0x10ffff.\n *\n *    * In particular, surrogate pairs are allowed and not combined, which\n *      allows source files to represent all SourceCharacters with CESU-8.\n *      Broken surrogate pairs are allowed, as Ecmascript does not mandate\n *      their validation.\n *\n *    * Allow non-shortest UTF-8 encodings.\n *\n *  Leniency here causes few security concerns because all character data is\n *  decoded into Unicode codepoints before lexer processing, and is then\n *  re-encoded into CESU-8.  The source can be parsed as strict UTF-8 with\n *  a compiler option.  However, Ecmascript source characters include -all-\n *  16-bit unsigned integer codepoints, so leniency seems to be appropriate.\n *\n *  Note that codepoints above the BMP are not strictly SourceCharacters,\n *  but the lexer still accepts them as such.  Before ending up in a string\n *  or an identifier name, codepoints above BMP are converted into surrogate\n *  pairs and then CESU-8 encoded, resulting in 16-bit Unicode data as\n *  expected by Ecmascript.\n *\n *  An alternative approach to dealing with invalid or partial sequences\n *  would be to skip them and replace them with e.g. the Unicode replacement\n *  character U+FFFD.  This has limited utility because a replacement character\n *  will most likely cause a parse error, unless it occurs inside a string.\n *  Further, Ecmascript source is typically pure ASCII.\n *\n *  See:\n *\n *     http://en.wikipedia.org/wiki/UTF-8\n *     http://en.wikipedia.org/wiki/CESU-8\n *     http://tools.ietf.org/html/rfc3629\n *     http://en.wikipedia.org/wiki/UTF-8#Invalid_byte_sequences\n *\n *  Future work:\n *\n *    * Reject other invalid Unicode sequences (see Wikipedia entry for examples)\n *      in strict UTF-8 mode.\n *\n *    * Size optimize.  An attempt to use a 16-byte lookup table for the first\n *      byte resulted in a code increase though.\n *\n *    * Is checking against maximum 0x10ffff really useful?  4-byte encoding\n *      imposes a certain limit anyway.\n *\n *    * Support chunked streaming of source code.  Can be implemented either\n *      by streaming chunks of bytes or chunks of codepoints.\n */\n\n#if defined(DUK_USE_LEXER_SLIDING_WINDOW)\nDUK_LOCAL void duk__fill_lexer_buffer(duk_lexer_ctx *lex_ctx, duk_small_uint_t start_offset_bytes) {\n\tduk_lexer_codepoint *cp, *cp_end;\n\tduk_ucodepoint_t x;\n\tduk_small_uint_t contlen;\n\tconst duk_uint8_t *p, *p_end;\n#if defined(DUK_USE_STRICT_UTF8_SOURCE)\n\tduk_ucodepoint_t mincp;\n#endif\n\tduk_int_t input_line;\n\n\t/* Use temporaries and update lex_ctx only when finished. */\n\tinput_line = lex_ctx->input_line;\n\tp = lex_ctx->input + lex_ctx->input_offset;\n\tp_end = lex_ctx->input + lex_ctx->input_length;\n\n\tcp = (duk_lexer_codepoint *) (void *) ((duk_uint8_t *) lex_ctx->buffer + start_offset_bytes);\n\tcp_end = lex_ctx->buffer + DUK_LEXER_BUFFER_SIZE;\n\n\tfor (; cp != cp_end; cp++) {\n\t\tcp->offset = (duk_size_t) (p - lex_ctx->input);\n\t\tcp->line = input_line;\n\n\t\t/* XXX: potential issue with signed pointers, p_end < p. */\n\t\tif (DUK_UNLIKELY(p >= p_end)) {\n\t\t\t/* If input_offset were assigned a negative value, it would\n\t\t\t * result in a large positive value.  Most likely it would be\n\t\t\t * larger than input_length and be caught here.  In any case\n\t\t\t * no memory unsafe behavior would happen.\n\t\t\t */\n\t\t\tcp->codepoint = -1;\n\t\t\tcontinue;\n\t\t}\n\n\t\tx = (duk_ucodepoint_t) (*p++);\n\n\t\t/* Fast path. */\n\n\t\tif (DUK_LIKELY(x < 0x80UL)) {\n\t\t\tDUK_ASSERT(x != 0x2028UL && x != 0x2029UL);  /* not LS/PS */\n\t\t\tif (DUK_UNLIKELY(x <= 0x000dUL)) {\n\t\t\t\tif ((x == 0x000aUL) ||\n\t\t\t\t    ((x == 0x000dUL) && (p >= p_end || *p != 0x000aUL))) {\n\t\t\t\t\t/* lookup for 0x000a above assumes shortest encoding now */\n\n\t\t\t\t\t/* E5 Section 7.3, treat the following as newlines:\n\t\t\t\t\t *   LF\n\t\t\t\t\t *   CR [not followed by LF]\n\t\t\t\t\t *   LS\n\t\t\t\t\t *   PS\n\t\t\t\t\t *\n\t\t\t\t\t * For CR LF, CR is ignored if it is followed by LF, and the LF will bump\n\t\t\t\t\t * the line number.\n\t\t\t\t\t */\n\t\t\t\t\tinput_line++;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tcp->codepoint = (duk_codepoint_t) x;\n\t\t\tcontinue;\n\t\t}\n\n\t\t/* Slow path. */\n\n\t\tif (x < 0xc0UL) {\n\t\t\t/* 10xx xxxx -> invalid */\n\t\t\tgoto error_encoding;\n\t\t} else if (x < 0xe0UL) {\n\t\t\t/* 110x xxxx   10xx xxxx  */\n\t\t\tcontlen = 1;\n#if defined(DUK_USE_STRICT_UTF8_SOURCE)\n\t\t\tmincp = 0x80UL;\n#endif\n\t\t\tx = x & 0x1fUL;\n\t\t} else if (x < 0xf0UL) {\n\t\t\t/* 1110 xxxx   10xx xxxx   10xx xxxx */\n\t\t\tcontlen = 2;\n#if defined(DUK_USE_STRICT_UTF8_SOURCE)\n\t\t\tmincp = 0x800UL;\n#endif\n\t\t\tx = x & 0x0fUL;\n\t\t} else if (x < 0xf8UL) {\n\t\t\t/* 1111 0xxx   10xx xxxx   10xx xxxx   10xx xxxx */\n\t\t\tcontlen = 3;\n#if defined(DUK_USE_STRICT_UTF8_SOURCE)\n\t\t\tmincp = 0x10000UL;\n#endif\n\t\t\tx = x & 0x07UL;\n\t\t} else {\n\t\t\t/* no point in supporting encodings of 5 or more bytes */\n\t\t\tgoto error_encoding;\n\t\t}\n\n\t\tDUK_ASSERT(p_end >= p);\n\t\tif ((duk_size_t) contlen > (duk_size_t) (p_end - p)) {\n\t\t\tgoto error_clipped;\n\t\t}\n\n\t\twhile (contlen > 0) {\n\t\t\tduk_small_uint_t y;\n\t\t\ty = *p++;\n\t\t\tif ((y & 0xc0U) != 0x80U) {\n\t\t\t\t/* check that byte has the form 10xx xxxx */\n\t\t\t\tgoto error_encoding;\n\t\t\t}\n\t\t\tx = x << 6;\n\t\t\tx += y & 0x3fUL;\n\t\t\tcontlen--;\n\t\t}\n\n\t\t/* check final character validity */\n\n\t\tif (x > 0x10ffffUL) {\n\t\t\tgoto error_encoding;\n\t\t}\n#if defined(DUK_USE_STRICT_UTF8_SOURCE)\n\t\tif (x < mincp || (x >= 0xd800UL && x <= 0xdfffUL) || x == 0xfffeUL) {\n\t\t\tgoto error_encoding;\n\t\t}\n#endif\n\n\t\tDUK_ASSERT(x != 0x000aUL && x != 0x000dUL);\n\t\tif ((x == 0x2028UL) || (x == 0x2029UL)) {\n\t\t\tinput_line++;\n\t\t}\n\n\t\tcp->codepoint = (duk_codepoint_t) x;\n\t}\n\n\tlex_ctx->input_offset = (duk_size_t) (p - lex_ctx->input);\n\tlex_ctx->input_line = input_line;\n\treturn;\n\n error_clipped:   /* clipped codepoint */\n error_encoding:  /* invalid codepoint encoding or codepoint */\n\tlex_ctx->input_offset = (duk_size_t) (p - lex_ctx->input);\n\tlex_ctx->input_line = input_line;\n\n\tDUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_SOURCE_DECODE_FAILED);\n}\n\nDUK_LOCAL void duk__advance_bytes(duk_lexer_ctx *lex_ctx, duk_small_uint_t count_bytes) {\n\tduk_small_uint_t used_bytes, avail_bytes;\n\n\tDUK_ASSERT_DISABLE(count_bytes >= 0);  /* unsigned */\n\tDUK_ASSERT(count_bytes <= (duk_small_uint_t) (DUK_LEXER_WINDOW_SIZE * sizeof(duk_lexer_codepoint)));\n\tDUK_ASSERT(lex_ctx->window >= lex_ctx->buffer);\n\tDUK_ASSERT(lex_ctx->window < lex_ctx->buffer + DUK_LEXER_BUFFER_SIZE);\n\tDUK_ASSERT((duk_uint8_t *) lex_ctx->window + count_bytes <= (duk_uint8_t *) lex_ctx->buffer + DUK_LEXER_BUFFER_SIZE * sizeof(duk_lexer_codepoint));\n\n\t/* Zero 'count' is also allowed to make call sites easier.\n\t * Arithmetic in bytes generates better code in GCC.\n\t */\n\n\tlex_ctx->window = (duk_lexer_codepoint *) (void *) ((duk_uint8_t *) lex_ctx->window + count_bytes);  /* avoid multiply */\n\tused_bytes = (duk_small_uint_t) ((duk_uint8_t *) lex_ctx->window - (duk_uint8_t *) lex_ctx->buffer);\n\tavail_bytes = DUK_LEXER_BUFFER_SIZE * sizeof(duk_lexer_codepoint) - used_bytes;\n\tif (avail_bytes < (duk_small_uint_t) (DUK_LEXER_WINDOW_SIZE * sizeof(duk_lexer_codepoint))) {\n\t\t/* Not enough data to provide a full window, so \"scroll\" window to\n\t\t * start of buffer and fill up the rest.\n\t\t */\n\t\tDUK_MEMMOVE((void *) lex_ctx->buffer,\n\t\t            (const void *) lex_ctx->window,\n\t\t            (size_t) avail_bytes);\n\t\tlex_ctx->window = lex_ctx->buffer;\n\t\tduk__fill_lexer_buffer(lex_ctx, avail_bytes);\n\t}\n}\n\nDUK_LOCAL void duk__init_lexer_window(duk_lexer_ctx *lex_ctx) {\n\tlex_ctx->window = lex_ctx->buffer;\n\tduk__fill_lexer_buffer(lex_ctx, 0);\n}\n#else  /* DUK_USE_LEXER_SLIDING_WINDOW */\nDUK_LOCAL duk_codepoint_t duk__read_char(duk_lexer_ctx *lex_ctx) {\n\tduk_ucodepoint_t x;\n\tduk_small_uint_t len;\n\tduk_small_uint_t i;\n\tconst duk_uint8_t *p;\n#if defined(DUK_USE_STRICT_UTF8_SOURCE)\n\tduk_ucodepoint_t mincp;\n#endif\n\tduk_size_t input_offset;\n\n\tinput_offset = lex_ctx->input_offset;\n\tif (DUK_UNLIKELY(input_offset >= lex_ctx->input_length)) {\n\t\t/* If input_offset were assigned a negative value, it would\n\t\t * result in a large positive value.  Most likely it would be\n\t\t * larger than input_length and be caught here.  In any case\n\t\t * no memory unsafe behavior would happen.\n\t\t */\n\t\treturn -1;\n\t}\n\n\tp = lex_ctx->input + input_offset;\n\tx = (duk_ucodepoint_t) (*p);\n\n\tif (DUK_LIKELY(x < 0x80UL)) {\n\t\t/* 0xxx xxxx -> fast path */\n\n\t\t/* input offset tracking */\n\t\tlex_ctx->input_offset++;\n\n\t\tDUK_ASSERT(x != 0x2028UL && x != 0x2029UL);  /* not LS/PS */\n\t\tif (DUK_UNLIKELY(x <= 0x000dUL)) {\n\t\t\tif ((x == 0x000aUL) ||\n\t\t\t    ((x == 0x000dUL) && (lex_ctx->input_offset >= lex_ctx->input_length ||\n\t\t\t                         lex_ctx->input[lex_ctx->input_offset] != 0x000aUL))) {\n\t\t\t\t/* lookup for 0x000a above assumes shortest encoding now */\n\n\t\t\t\t/* E5 Section 7.3, treat the following as newlines:\n\t\t\t\t *   LF\n\t\t\t\t *   CR [not followed by LF]\n\t\t\t\t *   LS\n\t\t\t\t *   PS\n\t\t\t\t *\n\t\t\t\t * For CR LF, CR is ignored if it is followed by LF, and the LF will bump\n\t\t\t\t * the line number.\n\t\t\t\t */\n\t\t\t\tlex_ctx->input_line++;\n\t\t\t}\n\t\t}\n\n\t\treturn (duk_codepoint_t) x;\n\t}\n\n\t/* Slow path. */\n\n\tif (x < 0xc0UL) {\n\t\t/* 10xx xxxx -> invalid */\n\t\tgoto error_encoding;\n\t} else if (x < 0xe0UL) {\n\t\t/* 110x xxxx   10xx xxxx  */\n\t\tlen = 2;\n#if defined(DUK_USE_STRICT_UTF8_SOURCE)\n\t\tmincp = 0x80UL;\n#endif\n\t\tx = x & 0x1fUL;\n\t} else if (x < 0xf0UL) {\n\t\t/* 1110 xxxx   10xx xxxx   10xx xxxx */\n\t\tlen = 3;\n#if defined(DUK_USE_STRICT_UTF8_SOURCE)\n\t\tmincp = 0x800UL;\n#endif\n\t\tx = x & 0x0fUL;\n\t} else if (x < 0xf8UL) {\n\t\t/* 1111 0xxx   10xx xxxx   10xx xxxx   10xx xxxx */\n\t\tlen = 4;\n#if defined(DUK_USE_STRICT_UTF8_SOURCE)\n\t\tmincp = 0x10000UL;\n#endif\n\t\tx = x & 0x07UL;\n\t} else {\n\t\t/* no point in supporting encodings of 5 or more bytes */\n\t\tgoto error_encoding;\n\t}\n\n\tDUK_ASSERT(lex_ctx->input_length >= lex_ctx->input_offset);\n\tif ((duk_size_t) len > (duk_size_t) (lex_ctx->input_length - lex_ctx->input_offset)) {\n\t\tgoto error_clipped;\n\t}\n\n\tp++;\n\tfor (i = 1; i < len; i++) {\n\t\tduk_small_uint_t y;\n\t\ty = *p++;\n\t\tif ((y & 0xc0U) != 0x80U) {\n\t\t\t/* check that byte has the form 10xx xxxx */\n\t\t\tgoto error_encoding;\n\t\t}\n\t\tx = x << 6;\n\t\tx += y & 0x3fUL;\n\t}\n\n\t/* check final character validity */\n\n\tif (x > 0x10ffffUL) {\n\t\tgoto error_encoding;\n\t}\n#if defined(DUK_USE_STRICT_UTF8_SOURCE)\n\tif (x < mincp || (x >= 0xd800UL && x <= 0xdfffUL) || x == 0xfffeUL) {\n\t\tgoto error_encoding;\n\t}\n#endif\n\n\t/* input offset tracking */\n\tlex_ctx->input_offset += len;\n\n\t/* line tracking */\n\tDUK_ASSERT(x != 0x000aUL && x != 0x000dUL);\n\tif ((x == 0x2028UL) || (x == 0x2029UL)) {\n\t\tlex_ctx->input_line++;\n\t}\n\n\treturn (duk_codepoint_t) x;\n\n error_clipped:   /* clipped codepoint */\n error_encoding:  /* invalid codepoint encoding or codepoint */\n\tDUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_SOURCE_DECODE_FAILED);\n\treturn 0;\n}\n\nDUK_LOCAL void duk__advance_bytes(duk_lexer_ctx *lex_ctx, duk_small_uint_t count_bytes) {\n\tduk_small_uint_t keep_bytes;\n\tduk_lexer_codepoint *cp, *cp_end;\n\n\tDUK_ASSERT_DISABLE(count_bytes >= 0);  /* unsigned */\n\tDUK_ASSERT(count_bytes <= (duk_small_uint_t) (DUK_LEXER_WINDOW_SIZE * sizeof(duk_lexer_codepoint)));\n\n\t/* Zero 'count' is also allowed to make call sites easier. */\n\n\tkeep_bytes = DUK_LEXER_WINDOW_SIZE * sizeof(duk_lexer_codepoint) - count_bytes;\n\tDUK_MEMMOVE((void *) lex_ctx->window,\n\t            (const void *) ((duk_uint8_t *) lex_ctx->window + count_bytes),\n\t            (size_t) keep_bytes);\n\n\tcp = (duk_lexer_codepoint *) ((duk_uint8_t *) lex_ctx->window + keep_bytes);\n\tcp_end = lex_ctx->window + DUK_LEXER_WINDOW_SIZE;\n\tfor (; cp != cp_end; cp++) {\n\t\tcp->offset = lex_ctx->input_offset;\n\t\tcp->line = lex_ctx->input_line;\n\t\tcp->codepoint = duk__read_char(lex_ctx);\n\t}\n}\n\nDUK_LOCAL void duk__init_lexer_window(duk_lexer_ctx *lex_ctx) {\n\t/* Call with count == DUK_LEXER_WINDOW_SIZE to fill buffer initially. */\n\tduk__advance_bytes(lex_ctx, DUK_LEXER_WINDOW_SIZE * sizeof(duk_lexer_codepoint));  /* fill window */\n}\n#endif  /* DUK_USE_LEXER_SLIDING_WINDOW */\n\nDUK_LOCAL void duk__advance_chars(duk_lexer_ctx *lex_ctx, duk_small_uint_t count_chars) {\n\tduk__advance_bytes(lex_ctx, count_chars * sizeof(duk_lexer_codepoint));\n}\n\n/*\n *  (Re)initialize the temporary byte buffer.  May be called extra times\n *  with little impact.\n */\n\nDUK_LOCAL void duk__initbuffer(duk_lexer_ctx *lex_ctx) {\n\t/* Reuse buffer as is unless buffer has grown large. */\n\tif (DUK_HBUFFER_DYNAMIC_GET_SIZE(lex_ctx->buf) < DUK_LEXER_TEMP_BUF_LIMIT) {\n\t\t/* Keep current size */\n\t} else {\n\t\tduk_hbuffer_resize(lex_ctx->thr, lex_ctx->buf, DUK_LEXER_TEMP_BUF_LIMIT);\n\t}\n\n\tDUK_BW_INIT_WITHBUF(lex_ctx->thr, &lex_ctx->bw, lex_ctx->buf);\n}\n\n/*\n *  Append a Unicode codepoint to the temporary byte buffer.  Performs\n *  CESU-8 surrogate pair encoding for codepoints above the BMP.\n *  Existing surrogate pairs are allowed and also encoded into CESU-8.\n */\n\nDUK_LOCAL void duk__appendbuffer(duk_lexer_ctx *lex_ctx, duk_codepoint_t x) {\n\t/*\n\t *  Since character data is only generated by decoding the source or by\n\t *  the compiler itself, we rely on the input codepoints being correct\n\t *  and avoid a check here.\n\t *\n\t *  Character data can also come here through decoding of Unicode\n\t *  escapes (\"\\udead\\ubeef\") so all 16-but unsigned values can be\n\t *  present, even when the source file itself is strict UTF-8.\n\t */\n\tDUK_ASSERT(x >= 0 && x <= 0x10ffffL);\n\n\tDUK_BW_WRITE_ENSURE_CESU8(lex_ctx->thr, &lex_ctx->bw, (duk_ucodepoint_t) x);\n}\n\nDUK_LOCAL void duk__appendbuffer_ascii(duk_lexer_ctx *lex_ctx, duk_codepoint_t x) {\n\t/* ASCII characters can be emitted as a single byte without encoding\n\t * which matters for some fast paths.\n\t */\n\tDUK_ASSERT(x >= 0 && x <= 0x7f);\n\n\tDUK_BW_WRITE_ENSURE_U8(lex_ctx->thr, &lex_ctx->bw, (duk_uint8_t) x);\n}\n\n/*\n *  Intern the temporary byte buffer into a valstack slot\n *  (in practice, slot1 or slot2).\n */\n\nDUK_LOCAL duk_hstring *duk__internbuffer(duk_lexer_ctx *lex_ctx, duk_idx_t valstack_idx) {\n\tDUK_ASSERT(valstack_idx == lex_ctx->slot1_idx || valstack_idx == lex_ctx->slot2_idx);\n\n\tDUK_BW_PUSH_AS_STRING(lex_ctx->thr, &lex_ctx->bw);\n\tduk_replace(lex_ctx->thr, valstack_idx);\n\treturn duk_known_hstring(lex_ctx->thr, valstack_idx);\n}\n\n/*\n *  Init lexer context\n */\n\nDUK_INTERNAL void duk_lexer_initctx(duk_lexer_ctx *lex_ctx) {\n\tDUK_ASSERT(lex_ctx != NULL);\n\n\tDUK_MEMZERO(lex_ctx, sizeof(*lex_ctx));\n#if defined(DUK_USE_EXPLICIT_NULL_INIT)\n#if defined(DUK_USE_LEXER_SLIDING_WINDOW)\n\tlex_ctx->window = NULL;\n#endif\n\tlex_ctx->thr = NULL;\n\tlex_ctx->input = NULL;\n\tlex_ctx->buf = NULL;\n#endif\n}\n\n/*\n *  Set lexer input position and reinitialize lookup window.\n */\n\nDUK_INTERNAL void duk_lexer_getpoint(duk_lexer_ctx *lex_ctx, duk_lexer_point *pt) {\n\tpt->offset = lex_ctx->window[0].offset;\n\tpt->line = lex_ctx->window[0].line;\n}\n\nDUK_INTERNAL void duk_lexer_setpoint(duk_lexer_ctx *lex_ctx, duk_lexer_point *pt) {\n\tDUK_ASSERT_DISABLE(pt->offset >= 0);  /* unsigned */\n\tDUK_ASSERT(pt->line >= 1);\n\tlex_ctx->input_offset = pt->offset;\n\tlex_ctx->input_line = pt->line;\n\tduk__init_lexer_window(lex_ctx);\n}\n\n/*\n *  Lexing helpers\n */\n\n/* Numeric value of a hex digit (also covers octal and decimal digits) or\n * -1 if not a valid hex digit.\n */\nDUK_LOCAL duk_codepoint_t duk__hexval_validate(duk_codepoint_t x) {\n\tduk_small_int_t t;\n\n\t/* Here 'x' is a Unicode codepoint */\n\tif (DUK_LIKELY(x >= 0 && x <= 0xff)) {\n\t\tt = duk_hex_dectab[x];\n\t\tif (DUK_LIKELY(t >= 0)) {\n\t\t\treturn t;\n\t\t}\n\t}\n\n\treturn -1;\n}\n\n/* Just a wrapper for call sites where 'x' is known to be valid so\n * we assert for it before decoding.\n */\nDUK_LOCAL duk_codepoint_t duk__hexval(duk_codepoint_t x) {\n\tduk_codepoint_t ret;\n\n\tDUK_ASSERT((x >= DUK_ASC_0 && x <= DUK_ASC_9) ||\n\t           (x >= DUK_ASC_LC_A && x <= DUK_ASC_LC_F) ||\n\t           (x >= DUK_ASC_UC_A && x <= DUK_ASC_UC_F));\n\tret = duk__hexval_validate(x);\n\tDUK_ASSERT(ret >= 0 && ret <= 15);\n\treturn ret;\n}\n\n/* having this as a separate function provided a size benefit */\nDUK_LOCAL duk_bool_t duk__is_hex_digit(duk_codepoint_t x) {\n\tif (DUK_LIKELY(x >= 0 && x <= 0xff)) {\n\t\treturn (duk_hex_dectab[x] >= 0);\n\t}\n\treturn 0;\n}\n\n/* Parse a Unicode escape of the form \\xHH, \\uHHHH, or \\u{H+}.  Shared by\n * source and RegExp parsing.\n */\nDUK_LOCAL duk_codepoint_t duk__lexer_parse_escape(duk_lexer_ctx *lex_ctx, duk_bool_t allow_es6) {\n\tduk_small_int_t digits;  /* Initial value 2 or 4 for fixed length escapes, 0 for ES2015 \\u{H+}. */\n\tduk_codepoint_t escval;\n\tduk_codepoint_t x;\n\tduk_small_uint_t adv;\n\n\tDUK_ASSERT(DUK__L0() == DUK_ASC_BACKSLASH);  /* caller responsibilities */\n\tDUK_ASSERT(DUK__L1() == DUK_ASC_LC_X || DUK__L1() == DUK_ASC_LC_U);\n\tDUK_UNREF(allow_es6);\n\n\tadv = 2;\n\tdigits = 2;\n\tif (DUK__L1() == DUK_ASC_LC_U) {\n\t\tdigits = 4;\n#if defined(DUK_USE_ES6_UNICODE_ESCAPE)\n\t\tif (DUK__L2() == DUK_ASC_LCURLY && allow_es6) {\n\t\t\tdigits = 0;\n\t\t\tadv = 3;\n\t\t}\n#endif\n\t}\n\tDUK__ADVANCECHARS(lex_ctx, adv);\n\n\tescval = 0;\n\tfor (;;) {\n\t\t/* One of the escape forms: \\xHH, \\uHHHH, \\u{H+}.\n\t\t * The 'digits' variable tracks parsing state and is\n\t\t * initialized to:\n\t\t *\n\t\t *   \\xHH     2\n\t\t *   \\uHH     4\n\t\t *   \\u{H+}   0 first time, updated to -1 to indicate\n\t\t *            at least one digit has been parsed\n\t\t *\n\t\t * Octal parsing is handled separately because it can be\n\t\t * done with fixed lookahead and also has validation\n\t\t * rules which depend on the escape length (which is\n\t\t * variable).\n\t\t *\n\t\t * We don't need a specific check for x < 0 (end of\n\t\t * input) or duk_unicode_is_line_terminator(x)\n\t\t * because the 'dig' decode will fail and lead to a\n\t\t * SyntaxError.\n\t\t */\n\t\tduk_codepoint_t dig;\n\n\t\tx = DUK__L0();\n\t\tDUK__ADVANCECHARS(lex_ctx, 1);\n\n\t\tdig = duk__hexval_validate(x);\n\t\tif (digits > 0) {\n\t\t\tdigits--;\n\t\t\tif (dig < 0) {\n\t\t\t\tgoto fail_escape;\n\t\t\t}\n\t\t\tDUK_ASSERT(dig >= 0x00 && dig <= 0x0f);\n\t\t\tescval = (escval << 4) + dig;\n\t\t\tif (digits == 0) {\n\t\t\t\tDUK_ASSERT(escval >= 0 && escval <= 0xffffL);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t} else {\n#if defined(DUK_USE_ES6_UNICODE_ESCAPE)\n\t\t\tDUK_ASSERT(digits == 0 /* first time */ || digits == -1 /* others */);\n\t\t\tif (dig >= 0) {\n\t\t\t\tDUK_ASSERT(dig >= 0x00 && dig <= 0x0f);\n\t\t\t\tescval = (escval << 4) + dig;\n\t\t\t\tif (escval > 0x10ffffL) {\n\t\t\t\t\tgoto fail_escape;\n\t\t\t\t}\n\t\t\t} else if (x == DUK_ASC_RCURLY) {\n\t\t\t\tif (digits == 0) {\n\t\t\t\t\t/* Empty escape, \\u{}. */\n\t\t\t\t\tgoto fail_escape;\n\t\t\t\t}\n\t\t\t\tDUK_ASSERT(escval >= 0 && escval <= 0x10ffffL);\n\t\t\t\tbreak;\n\t\t\t} else {\n\t\t\t\tgoto fail_escape;\n\t\t\t}\n\t\t\tdigits = -1;  /* Indicate we have at least one digit. */\n#else  /* DUK_USE_ES6_UNICODE_ESCAPE */\n\t\t\tDUK_ASSERT(0);  /* Never happens if \\u{H+} support disabled. */\n#endif  /* DUK_USE_ES6_UNICODE_ESCAPE */\n\t\t}\n\t}\n\n\treturn escval;\n\n fail_escape:\n\tDUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_ESCAPE);\n}\n\n/* Parse legacy octal escape of the form \\N{1,3}, e.g. \\0, \\5, \\0377.  Maximum\n * allowed value is \\0377 (U+00FF), longest match is used.  Used for both string\n * RegExp octal escape parsing.  Window[0] must be the slash '\\' and the first\n * digit must already be validated to be in [0-9] by the caller.\n */\nDUK_LOCAL duk_codepoint_t duk__lexer_parse_legacy_octal(duk_lexer_ctx *lex_ctx, duk_small_uint_t *out_adv, duk_bool_t reject_annex_b) {\n\tduk_codepoint_t cp;\n\tduk_small_uint_t lookup_idx;\n\tduk_small_uint_t adv;\n\tduk_codepoint_t tmp;\n\n\tDUK_ASSERT(out_adv != NULL);\n\tDUK_ASSERT(DUK__LOOKUP(lex_ctx, 0) == DUK_ASC_BACKSLASH);\n\tDUK_ASSERT(DUK__LOOKUP(lex_ctx, 1) >= DUK_ASC_0 && DUK__LOOKUP(lex_ctx, 1) <= DUK_ASC_9);\n\n\tcp = 0;\n\ttmp = 0;\n\tfor (lookup_idx = 1; lookup_idx <= 3; lookup_idx++) {\n\t\tDUK_DDD(DUK_DDDPRINT(\"lookup_idx=%ld, cp=%ld\", (long) lookup_idx, (long) cp));\n\t\ttmp = DUK__LOOKUP(lex_ctx, lookup_idx);\n\t\tif (tmp < DUK_ASC_0 || tmp > DUK_ASC_7) {\n\t\t\t/* No more valid digits. */\n\t\t\tbreak;\n\t\t}\n\t\ttmp = (cp << 3) + (tmp - DUK_ASC_0);\n\t\tif (tmp > 0xff) {\n\t\t\t/* Three digit octal escapes above \\377 (= 0xff)\n\t\t\t * are not allowed.\n\t\t\t */\n\t\t\tbreak;\n\t\t}\n\t\tcp = tmp;\n\t}\n\tDUK_DDD(DUK_DDDPRINT(\"final lookup_idx=%ld, cp=%ld\", (long) lookup_idx, (long) cp));\n\n\tadv = lookup_idx;\n\tif (lookup_idx == 1) {\n\t\tDUK_DDD(DUK_DDDPRINT(\"\\\\8 or \\\\9 -> treat as literal, accept in strict mode too\"));\n\t\tDUK_ASSERT(tmp == DUK_ASC_8 || tmp == DUK_ASC_9);\n\t\tcp = tmp;\n\t\tadv++;  /* correction to above, eat offending character */\n\t} else if (lookup_idx == 2 && cp == 0) {\n\t\t/* Note: 'foo\\0bar' is OK in strict mode, but 'foo\\00bar' is not.\n\t\t * It won't be interpreted as 'foo\\u{0}0bar' but as a SyntaxError.\n\t\t */\n\t\tDUK_DDD(DUK_DDDPRINT(\"\\\\0 -> accept in strict mode too\"));\n\t} else {\n\t\t/* This clause also handles non-shortest zero, e.g. \\00. */\n\t\tif (reject_annex_b) {\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"non-zero octal literal %ld -> reject in strict-mode\", (long) cp));\n\t\t\tcp = -1;\n\t\t} else {\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"non-zero octal literal %ld -> accepted\", (long) cp));\n\t\t\tDUK_ASSERT(cp >= 0 && cp <= 0xff);\n\t\t}\n\t}\n\n\t*out_adv = adv;\n\n\tDUK_ASSERT((cp >= 0 && cp <= 0xff) || (cp == -1 && reject_annex_b));\n\treturn cp;\n}\n\n/* XXX: move strict mode to lex_ctx? */\nDUK_LOCAL void duk__lexer_parse_string_literal(duk_lexer_ctx *lex_ctx, duk_token *out_token, duk_small_int_t quote, duk_bool_t strict_mode) {\n\tduk_small_uint_t adv;\n\n\tfor (adv = 1 /* initial quote */ ;;) {\n\t\tduk_codepoint_t x;\n\n\t\tDUK__ADVANCECHARS(lex_ctx, adv);  /* eat opening quote on first loop */\n\t\tx = DUK__L0();\n\n\t\tadv = 1;\n\t\tif (x == quote) {\n\t\t\tDUK__ADVANCECHARS(lex_ctx, 1);  /* eat closing quote */\n\t\t\tbreak;\n\t\t} else if (x == '\\\\') {\n\t\t\t/* DUK__L0        -> '\\' char\n\t\t\t * DUK__L1 ... DUK__L5 -> more lookup\n\t\t\t */\n\t\t\tduk_small_int_t emitcp = -1;\n\n\t\t\tx = DUK__L1();\n\n\t\t\t/* How much to advance before next loop. */\n\t\t\tadv = 2;  /* note: long live range */\n\n\t\t\tswitch (x) {\n\t\t\tcase '\\'':\n\t\t\t\temitcp = 0x0027;\n\t\t\t\tbreak;\n\t\t\tcase '\"':\n\t\t\t\temitcp = 0x0022;\n\t\t\t\tbreak;\n\t\t\tcase '\\\\':\n\t\t\t\temitcp = 0x005c;\n\t\t\t\tbreak;\n\t\t\tcase 'b':\n\t\t\t\temitcp = 0x0008;\n\t\t\t\tbreak;\n\t\t\tcase 'f':\n\t\t\t\temitcp = 0x000c;\n\t\t\t\tbreak;\n\t\t\tcase 'n':\n\t\t\t\temitcp = 0x000a;\n\t\t\t\tbreak;\n\t\t\tcase 'r':\n\t\t\t\temitcp = 0x000d;\n\t\t\t\tbreak;\n\t\t\tcase 't':\n\t\t\t\temitcp = 0x0009;\n\t\t\t\tbreak;\n\t\t\tcase 'v':\n\t\t\t\temitcp = 0x000b;\n\t\t\t\tbreak;\n\t\t\tcase 'x':\n\t\t\tcase 'u': {\n\t\t\t\tduk_codepoint_t esc_cp;\n\t\t\t\tesc_cp = duk__lexer_parse_escape(lex_ctx, 1 /*allow_es6*/);\n\t\t\t\tDUK__APPENDBUFFER(lex_ctx, esc_cp);\n\t\t\t\tadv = 0;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tdefault: {\n\t\t\t\tif (duk_unicode_is_line_terminator(x)) {\n\t\t\t\t\t/* line continuation */\n\t\t\t\t\tif (x == 0x000d && DUK__L2() == 0x000a) {\n\t\t\t\t\t\t/* CR LF again a special case */\n\t\t\t\t\t\tadv = 3;  /* line terminator, CR, LF */\n\t\t\t\t\t}\n\t\t\t\t} else if (DUK__ISDIGIT(x)) {\n\t\t\t\t\t/*\n\t\t\t\t\t *  Octal escape or zero escape:\n\t\t\t\t\t *    \\0                                     (lookahead not OctalDigit)\n\t\t\t\t\t *    \\1 ... \\7                              (lookahead not OctalDigit)\n\t\t\t\t\t *    \\ZeroToThree OctalDigit                (lookahead not OctalDigit)\n\t\t\t\t\t *    \\FourToSeven OctalDigit                (no lookahead restrictions)\n\t\t\t\t\t *    \\ZeroToThree OctalDigit OctalDigit     (no lookahead restrictions)\n\t\t\t\t\t *\n\t\t\t\t\t *  Zero escape is part of the standard syntax.  Octal escapes are\n\t\t\t\t\t *  defined in E5 Section B.1.2, and are only allowed in non-strict mode.\n\t\t\t\t\t *  Any other productions starting with a decimal digit are invalid\n\t\t\t\t\t *  but are in practice treated like identity escapes.\n\t\t\t\t\t *\n\t\t\t\t\t *  Parse octal (up to 3 digits) from the lookup window.\n\t\t\t\t\t */\n\n\t\t\t\t\temitcp = duk__lexer_parse_legacy_octal(lex_ctx, &adv, strict_mode /*reject_annex_b*/);\n\t\t\t\t\tif (emitcp < 0) {\n\t\t\t\t\t\tgoto fail_escape;\n\t\t\t\t\t}\n\t\t\t\t} else if (x < 0) {\n\t\t\t\t\tgoto fail_unterminated;\n\t\t\t\t} else {\n\t\t\t\t\t/* escaped NonEscapeCharacter */\n\t\t\t\t\tDUK__APPENDBUFFER(lex_ctx, x);\n\t\t\t\t}\n\t\t\t}  /* end default clause */\n\t\t\t}  /* end switch */\n\n\t\t\t/* Shared handling for single codepoint escapes. */\n\t\t\tif (emitcp >= 0) {\n\t\t\t\tDUK__APPENDBUFFER(lex_ctx, emitcp);\n\t\t\t}\n\n\t\t\t/* Track number of escapes; count not really needed but directive\n\t\t\t * prologues need to detect whether there were any escapes or line\n\t\t\t * continuations or not.\n\t\t\t */\n\t\t\tout_token->num_escapes++;\n\t\t} else if (x >= 0x20 && x <= 0x7f) {\n\t\t\t/* Fast path for ASCII case, avoids line terminator\n\t\t\t * check and CESU-8 encoding.\n\t\t\t */\n\t\t\tDUK_ASSERT(x >= 0);\n\t\t\tDUK_ASSERT(!duk_unicode_is_line_terminator(x));\n\t\t\tDUK_ASSERT(x != quote);\n\t\t\tDUK_ASSERT(x != DUK_ASC_BACKSLASH);\n\t\t\tDUK__APPENDBUFFER_ASCII(lex_ctx, x);\n\t\t} else if (x < 0 || duk_unicode_is_line_terminator(x)) {\n\t\t\tgoto fail_unterminated;\n\t\t} else {\n\t\t\t/* Character which is part of the string but wasn't handled\n\t\t\t * by the fast path.\n\t\t\t */\n\t\t\tDUK__APPENDBUFFER(lex_ctx, x);\n\t\t}\n\t} /* string parse loop */\n\n\treturn;\n\n fail_escape:\n\tDUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_ESCAPE);\n\treturn;\n\n fail_unterminated:\n\tDUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_UNTERMINATED_STRING);\n\treturn;\n}\n\n/* Skip to end-of-line (or end-of-file), used for single line comments. */\nDUK_LOCAL void duk__lexer_skip_to_endofline(duk_lexer_ctx *lex_ctx) {\n\tfor (;;) {\n\t\tduk_codepoint_t x;\n\n\t\tx = DUK__L0();\n\t\tif (x < 0 || duk_unicode_is_line_terminator(x)) {\n\t\t\tbreak;\n\t\t}\n\t\tDUK__ADVANCECHARS(lex_ctx, 1);\n\t}\n}\n\n/*\n *  Parse Ecmascript source InputElementDiv or InputElementRegExp\n *  (E5 Section 7), skipping whitespace, comments, and line terminators.\n *\n *  Possible results are:\n *    (1) a token\n *    (2) a line terminator (skipped)\n *    (3) a comment (skipped)\n *    (4) EOF\n *\n *  White space is automatically skipped from the current position (but\n *  not after the input element).  If input has already ended, returns\n *  DUK_TOK_EOF indefinitely.  If a parse error occurs, uses an DUK_ERROR()\n *  macro call (and hence a longjmp through current heap longjmp context).\n *  Comments and line terminator tokens are automatically skipped.\n *\n *  The input element being matched is determined by regexp_mode; if set,\n *  parses a InputElementRegExp, otherwise a InputElementDiv.  The\n *  difference between these are handling of productions starting with a\n *  forward slash.\n *\n *  If strict_mode is set, recognizes additional future reserved words\n *  specific to strict mode, and refuses to parse octal literals.\n *\n *  The matching strategy below is to (currently) use a six character\n *  lookup window to quickly determine which production is the -longest-\n *  matching one, and then parse that.  The top-level if-else clauses\n *  match the first character, and the code blocks for each clause\n *  handle -all- alternatives for that first character.  Ecmascript\n *  specification uses the \"longest match wins\" semantics, so the order\n *  of the if-clauses matters.\n *\n *  Misc notes:\n *\n *    * Ecmascript numeric literals do not accept a sign character.\n *      Consequently e.g. \"-1.0\" is parsed as two tokens: a negative\n *      sign and a positive numeric literal.  The compiler performs\n *      the negation during compilation, so this has no adverse impact.\n *\n *    * There is no token for \"undefined\": it is just a value available\n *      from the global object (or simply established by doing a reference\n *      to an undefined value).\n *\n *    * Some contexts want Identifier tokens, which are IdentifierNames\n *      excluding reserved words, while some contexts want IdentifierNames\n *      directly.  In the latter case e.g. \"while\" is interpreted as an\n *      identifier name, not a DUK_TOK_WHILE token.  The solution here is\n *      to provide both token types: DUK_TOK_WHILE goes to 't' while\n *      DUK_TOK_IDENTIFIER goes to 't_nores', and 'slot1' always contains\n *      the identifier / keyword name.\n *\n *    * Directive prologue needs to identify string literals such as\n *      \"use strict\" and 'use strict', which are sensitive to line\n *      continuations and escape sequences.  For instance, \"use\\u0020strict\"\n *      is a valid directive but is distinct from \"use strict\".  The solution\n *      here is to decode escapes while tokenizing, but to keep track of the\n *      number of escapes.  Directive detection can then check that the\n *      number of escapes is zero.\n *\n *    * Multi-line comments with one or more internal LineTerminator are\n *      treated like a line terminator to comply with automatic semicolon\n *      insertion.\n */\n\nDUK_INTERNAL\nvoid duk_lexer_parse_js_input_element(duk_lexer_ctx *lex_ctx,\n                                      duk_token *out_token,\n                                      duk_bool_t strict_mode,\n                                      duk_bool_t regexp_mode) {\n\tduk_codepoint_t x;           /* temporary, must be signed and 32-bit to hold Unicode code points */\n\tduk_small_uint_t advtok = 0; /* (advance << 8) + token_type, updated at function end,\n\t                              * init is unnecessary but suppresses \"may be used uninitialized\" warnings.\n\t                              */\n\tduk_bool_t got_lineterm = 0;  /* got lineterm preceding non-whitespace, non-lineterm token */\n\n\tif (++lex_ctx->token_count >= lex_ctx->token_limit) {\n\t\tgoto fail_token_limit;\n\t}\n\n\tout_token->t = DUK_TOK_EOF;\n\tout_token->t_nores = DUK_TOK_INVALID;  /* marker: copy t if not changed */\n#if 0  /* not necessary to init, disabled for faster parsing */\n\tout_token->num = DUK_DOUBLE_NAN;\n\tout_token->str1 = NULL;\n\tout_token->str2 = NULL;\n#endif\n\tout_token->num_escapes = 0;\n\t/* out_token->lineterm set by caller */\n\n\t/* This would be nice, but parsing is faster without resetting the\n\t * value slots.  The only side effect is that references to temporary\n\t * string values may linger until lexing is finished; they're then\n\t * freed normally.\n\t */\n#if 0\n\tduk_to_undefined(lex_ctx->thr, lex_ctx->slot1_idx);\n\tduk_to_undefined(lex_ctx->thr, lex_ctx->slot2_idx);\n#endif\n\n\t/* 'advtok' indicates how much to advance and which token id to assign\n\t * at the end.  This shared functionality minimizes code size.  All\n\t * code paths are required to set 'advtok' to some value, so no default\n\t * init value is used.  Code paths calling DUK_ERROR() never return so\n\t * they don't need to set advtok.\n\t */\n\n\t/*\n\t *  Matching order:\n\t *\n\t *    Punctuator first chars, also covers comments, regexps\n\t *    LineTerminator\n\t *    Identifier or reserved word, also covers null/true/false literals\n\t *    NumericLiteral\n\t *    StringLiteral\n\t *    EOF\n\t *\n\t *  The order does not matter as long as the longest match is\n\t *  always correctly identified.  There are order dependencies\n\t *  in the clauses, so it's not trivial to convert to a switch.\n\t */\n\n restart_lineupdate:\n\tout_token->start_line = lex_ctx->window[0].line;\n\n restart:\n\tout_token->start_offset = lex_ctx->window[0].offset;\n\n\tx = DUK__L0();\n\n\tswitch (x) {\n\tcase DUK_ASC_SPACE:\n\tcase DUK_ASC_HT:  /* fast paths for space and tab */\n\t\tDUK__ADVANCECHARS(lex_ctx, 1);\n\t\tgoto restart;\n\tcase DUK_ASC_LF:  /* LF line terminator; CR LF and Unicode lineterms are handled in slow path */\n\t\tDUK__ADVANCECHARS(lex_ctx, 1);\n\t\tgot_lineterm = 1;\n\t\tgoto restart_lineupdate;\n#if defined(DUK_USE_SHEBANG_COMMENTS)\n\tcase DUK_ASC_HASH:  /* '#' */\n\t\tif (DUK__L1() == DUK_ASC_EXCLAMATION && lex_ctx->window[0].offset == 0 &&\n\t\t    (lex_ctx->flags & DUK_COMPILE_SHEBANG)) {\n\t\t\t/* \"Shebang\" comment ('#! ...') on first line. */\n\t\t\t/* DUK__ADVANCECHARS(lex_ctx, 2) would be correct here, but not necessary */\n\t\t\tduk__lexer_skip_to_endofline(lex_ctx);\n\t\t\tgoto restart;  /* line terminator will be handled on next round */\n\t\t}\n\t\tgoto fail_token;\n#endif  /* DUK_USE_SHEBANG_COMMENTS */\n\tcase DUK_ASC_SLASH:  /* '/' */\n\t\tif (DUK__L1() == DUK_ASC_SLASH) {\n\t\t\t/*\n\t\t\t *  E5 Section 7.4, allow SourceCharacter (which is any 16-bit\n\t\t\t *  code point).\n\t\t\t */\n\n\t\t\t/* DUK__ADVANCECHARS(lex_ctx, 2) would be correct here, but not necessary */\n\t\t\tduk__lexer_skip_to_endofline(lex_ctx);\n\t\t\tgoto restart;  /* line terminator will be handled on next round */\n\t\t} else if (DUK__L1() == DUK_ASC_STAR) {\n\t\t\t/*\n\t\t\t *  E5 Section 7.4.  If the multi-line comment contains a newline,\n\t\t\t *  it is treated like a single line terminator for automatic\n\t\t\t *  semicolon insertion.\n\t\t\t */\n\n\t\t\tduk_bool_t last_asterisk = 0;\n\t\t\tDUK__ADVANCECHARS(lex_ctx, 2);\n\t\t\tfor (;;) {\n\t\t\t\tx = DUK__L0();\n\t\t\t\tif (x < 0) {\n\t\t\t\t\tgoto fail_unterm_comment;\n\t\t\t\t}\n\t\t\t\tDUK__ADVANCECHARS(lex_ctx, 1);\n\t\t\t\tif (last_asterisk && x == DUK_ASC_SLASH) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tif (duk_unicode_is_line_terminator(x)) {\n\t\t\t\t\tgot_lineterm = 1;\n\t\t\t\t}\n\t\t\t\tlast_asterisk = (x == DUK_ASC_STAR);\n\t\t\t}\n\t\t\tgoto restart_lineupdate;\n\t\t} else if (regexp_mode) {\n#if defined(DUK_USE_REGEXP_SUPPORT)\n\t\t\t/*\n\t\t\t *  \"/\" followed by something in regexp mode.  See E5 Section 7.8.5.\n\t\t\t *\n\t\t\t *  RegExp parsing is a bit complex.  First, the regexp body is delimited\n\t\t\t *  by forward slashes, but the body may also contain forward slashes as\n\t\t\t *  part of an escape sequence or inside a character class (delimited by\n\t\t\t *  square brackets).  A mini state machine is used to implement these.\n\t\t\t *\n\t\t\t *  Further, an early (parse time) error must be thrown if the regexp\n\t\t\t *  would cause a run-time error when used in the expression new RegExp(...).\n\t\t\t *  Parsing here simply extracts the (candidate) regexp, and also accepts\n\t\t\t *  invalid regular expressions (which are delimited properly).  The caller\n\t\t\t *  (compiler) must perform final validation and regexp compilation.\n\t\t\t *\n\t\t\t *  RegExp first char may not be '/' (single line comment) or '*' (multi-\n\t\t\t *  line comment).  These have already been checked above, so there is no\n\t\t\t *  need below for special handling of the first regexp character as in\n\t\t\t *  the E5 productions.\n\t\t\t *\n\t\t\t *  About unicode escapes within regexp literals:\n\t\t\t *\n\t\t\t *      E5 Section 7.8.5 grammar does NOT accept \\uHHHH escapes.\n\t\t\t *      However, Section 6 states that regexps accept the escapes,\n\t\t\t *      see paragraph starting with \"In string literals...\".\n\t\t\t *      The regexp grammar, which sees the decoded regexp literal\n\t\t\t *      (after lexical parsing) DOES have a \\uHHHH unicode escape.\n\t\t\t *      So, for instance:\n\t\t\t *\n\t\t\t *          /\\u1234/\n\t\t\t *\n\t\t\t *      should first be parsed by the lexical grammar as:\n\t\t\t *\n\t\t\t *          '\\' 'u'      RegularExpressionBackslashSequence\n\t\t\t *          '1'          RegularExpressionNonTerminator\n\t\t\t *          '2'          RegularExpressionNonTerminator\n\t\t\t *          '3'          RegularExpressionNonTerminator\n\t\t\t *          '4'          RegularExpressionNonTerminator\n\t\t\t *\n\t\t\t *      and the escape itself is then parsed by the regexp engine.\n\t\t\t *      This is the current implementation.\n\t\t\t *\n\t\t\t *  Minor spec inconsistency:\n\t\t\t *\n\t\t\t *      E5 Section 7.8.5 RegularExpressionBackslashSequence is:\n\t\t\t *\n\t\t\t *         \\ RegularExpressionNonTerminator\n\t\t\t *\n\t\t\t *      while Section A.1 RegularExpressionBackslashSequence is:\n\t\t\t *\n\t\t\t *         \\ NonTerminator\n\t\t\t *\n\t\t\t *      The latter is not normative and a typo.\n\t\t\t *\n\t\t\t */\n\n\t\t\t/* first, parse regexp body roughly */\n\n\t\t\tduk_small_int_t state = 0;  /* 0=base, 1=esc, 2=class, 3=class+esc */\n\n\t\t\tDUK__INITBUFFER(lex_ctx);\n\t\t\tfor (;;) {\n\t\t\t\tDUK__ADVANCECHARS(lex_ctx, 1);  /* skip opening slash on first loop */\n\t\t\t\tx = DUK__L0();\n\t\t\t\tif (x < 0 || duk_unicode_is_line_terminator(x)) {\n\t\t\t\t\tgoto fail_unterm_regexp;\n\t\t\t\t}\n\t\t\t\tx = DUK__L0();  /* re-read to avoid spill / fetch */\n\t\t\t\tif (state == 0) {\n\t\t\t\t\tif (x == DUK_ASC_SLASH) {\n\t\t\t\t\t\tDUK__ADVANCECHARS(lex_ctx, 1);  /* eat closing slash */\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t} else if (x == DUK_ASC_BACKSLASH) {\n\t\t\t\t\t\tstate = 1;\n\t\t\t\t\t} else if (x == DUK_ASC_LBRACKET) {\n\t\t\t\t\t\tstate = 2;\n\t\t\t\t\t}\n\t\t\t\t} else if (state == 1) {\n\t\t\t\t\tstate = 0;\n\t\t\t\t} else if (state == 2) {\n\t\t\t\t\tif (x == DUK_ASC_RBRACKET) {\n\t\t\t\t\t\tstate = 0;\n\t\t\t\t\t} else if (x == DUK_ASC_BACKSLASH) {\n\t\t\t\t\t\tstate = 3;\n\t\t\t\t\t}\n\t\t\t\t} else { /* state == 3 */\n\t\t\t\t\tstate = 2;\n\t\t\t\t}\n\t\t\t\tDUK__APPENDBUFFER(lex_ctx, x);\n\t\t\t}\n\t\t\tout_token->str1 = duk__internbuffer(lex_ctx, lex_ctx->slot1_idx);\n\n\t\t\t/* second, parse flags */\n\n\t\t\tDUK__INITBUFFER(lex_ctx);\n\t\t\tfor (;;) {\n\t\t\t\tx = DUK__L0();\n\t\t\t\tif (!duk_unicode_is_identifier_part(x)) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tx = DUK__L0();  /* re-read to avoid spill / fetch */\n\t\t\t\tDUK__APPENDBUFFER(lex_ctx, x);\n\t\t\t\tDUK__ADVANCECHARS(lex_ctx, 1);\n\t\t\t}\n\t\t\tout_token->str2 = duk__internbuffer(lex_ctx, lex_ctx->slot2_idx);\n\n\t\t\tDUK__INITBUFFER(lex_ctx);  /* free some memory */\n\n\t\t\t/* validation of the regexp is caller's responsibility */\n\n\t\t\tadvtok = DUK__ADVTOK(0, DUK_TOK_REGEXP);\n#else  /* DUK_USE_REGEXP_SUPPORT */\n\t\t\tgoto fail_regexp_support;\n#endif  /* DUK_USE_REGEXP_SUPPORT */\n\t\t} else if (DUK__L1() == DUK_ASC_EQUALS) {\n\t\t\t/* \"/=\" and not in regexp mode */\n\t\t\tadvtok = DUK__ADVTOK(2, DUK_TOK_DIV_EQ);\n\t\t} else {\n\t\t\t/* \"/\" and not in regexp mode */\n\t\t\tadvtok = DUK__ADVTOK(1, DUK_TOK_DIV);\n\t\t}\n\t\tbreak;\n\tcase DUK_ASC_LCURLY:  /* '{' */\n\t\tadvtok = DUK__ADVTOK(1, DUK_TOK_LCURLY);\n\t\tbreak;\n\tcase DUK_ASC_RCURLY:  /* '}' */\n\t\tadvtok = DUK__ADVTOK(1, DUK_TOK_RCURLY);\n\t\tbreak;\n\tcase DUK_ASC_LPAREN:  /* '(' */\n\t\tadvtok = DUK__ADVTOK(1, DUK_TOK_LPAREN);\n\t\tbreak;\n\tcase DUK_ASC_RPAREN:  /* ')' */\n\t\tadvtok = DUK__ADVTOK(1, DUK_TOK_RPAREN);\n\t\tbreak;\n\tcase DUK_ASC_LBRACKET:  /* '[' */\n\t\tadvtok = DUK__ADVTOK(1, DUK_TOK_LBRACKET);\n\t\tbreak;\n\tcase DUK_ASC_RBRACKET:  /* ']' */\n\t\tadvtok = DUK__ADVTOK(1, DUK_TOK_RBRACKET);\n\t\tbreak;\n\tcase DUK_ASC_PERIOD:  /* '.' */\n\t\tif (DUK__ISDIGIT(DUK__L1())) {\n\t\t\t/* Period followed by a digit can only start DecimalLiteral\n\t\t\t * (handled in slow path).  We could jump straight into the\n\t\t\t * DecimalLiteral handling but should avoid goto to inside\n\t\t\t * a block.\n\t\t\t */\n\t\t\tgoto slow_path;\n\t\t}\n\t\tadvtok = DUK__ADVTOK(1, DUK_TOK_PERIOD);\n\t\tbreak;\n\tcase DUK_ASC_SEMICOLON:  /* ';' */\n\t\tadvtok = DUK__ADVTOK(1, DUK_TOK_SEMICOLON);\n\t\tbreak;\n\tcase DUK_ASC_COMMA:  /* ',' */\n\t\tadvtok = DUK__ADVTOK(1, DUK_TOK_COMMA);\n\t\tbreak;\n\tcase DUK_ASC_LANGLE:  /* '<' */\n#if defined(DUK_USE_HTML_COMMENTS)\n\t\tif (DUK__L1() == DUK_ASC_EXCLAMATION && DUK__L2() == DUK_ASC_MINUS && DUK__L3() == DUK_ASC_MINUS) {\n\t\t\t/*\n\t\t\t *  ES2015: B.1.3, handle \"<!--\" SingleLineHTMLOpenComment\n\t\t\t */\n\n\t\t\t/* DUK__ADVANCECHARS(lex_ctx, 4) would be correct here, but not necessary */\n\t\t\tduk__lexer_skip_to_endofline(lex_ctx);\n\t\t\tgoto restart;  /* line terminator will be handled on next round */\n\t\t}\n\t\telse\n#endif  /* DUK_USE_HTML_COMMENTS */\n\t\tif (DUK__L1() == DUK_ASC_LANGLE && DUK__L2() == DUK_ASC_EQUALS) {\n\t\t\tadvtok = DUK__ADVTOK(3, DUK_TOK_ALSHIFT_EQ);\n\t\t} else if (DUK__L1() == DUK_ASC_EQUALS) {\n\t\t\tadvtok = DUK__ADVTOK(2, DUK_TOK_LE);\n\t\t} else if (DUK__L1() == DUK_ASC_LANGLE) {\n\t\t\tadvtok = DUK__ADVTOK(2, DUK_TOK_ALSHIFT);\n\t\t} else {\n\t\t\tadvtok = DUK__ADVTOK(1, DUK_TOK_LT);\n\t\t}\n\t\tbreak;\n\tcase DUK_ASC_RANGLE:  /* '>' */\n\t\tif (DUK__L1() == DUK_ASC_RANGLE && DUK__L2() == DUK_ASC_RANGLE && DUK__L3() == DUK_ASC_EQUALS) {\n\t\t\tadvtok = DUK__ADVTOK(4, DUK_TOK_RSHIFT_EQ);\n\t\t} else if (DUK__L1() == DUK_ASC_RANGLE && DUK__L2() == DUK_ASC_RANGLE) {\n\t\t\tadvtok = DUK__ADVTOK(3, DUK_TOK_RSHIFT);\n\t\t} else if (DUK__L1() == DUK_ASC_RANGLE && DUK__L2() == DUK_ASC_EQUALS) {\n\t\t\tadvtok = DUK__ADVTOK(3, DUK_TOK_ARSHIFT_EQ);\n\t\t} else if (DUK__L1() == DUK_ASC_EQUALS) {\n\t\t\tadvtok = DUK__ADVTOK(2, DUK_TOK_GE);\n\t\t} else if (DUK__L1() == DUK_ASC_RANGLE) {\n\t\t\tadvtok = DUK__ADVTOK(2, DUK_TOK_ARSHIFT);\n\t\t} else {\n\t\t\tadvtok = DUK__ADVTOK(1, DUK_TOK_GT);\n\t\t}\n\t\tbreak;\n\tcase DUK_ASC_EQUALS:  /* '=' */\n\t\tif (DUK__L1() == DUK_ASC_EQUALS && DUK__L2() == DUK_ASC_EQUALS) {\n\t\t\tadvtok = DUK__ADVTOK(3, DUK_TOK_SEQ);\n\t\t} else if (DUK__L1() == DUK_ASC_EQUALS) {\n\t\t\tadvtok = DUK__ADVTOK(2, DUK_TOK_EQ);\n\t\t} else {\n\t\t\tadvtok = DUK__ADVTOK(1, DUK_TOK_EQUALSIGN);\n\t\t}\n\t\tbreak;\n\tcase DUK_ASC_EXCLAMATION:  /* '!' */\n\t\tif (DUK__L1() == DUK_ASC_EQUALS && DUK__L2() == DUK_ASC_EQUALS) {\n\t\t\tadvtok = DUK__ADVTOK(3, DUK_TOK_SNEQ);\n\t\t} else if (DUK__L1() == DUK_ASC_EQUALS) {\n\t\t\tadvtok = DUK__ADVTOK(2, DUK_TOK_NEQ);\n\t\t} else {\n\t\t\tadvtok = DUK__ADVTOK(1, DUK_TOK_LNOT);\n\t\t}\n\t\tbreak;\n\tcase DUK_ASC_PLUS:  /* '+' */\n\t\tif (DUK__L1() == DUK_ASC_PLUS) {\n\t\t\tadvtok = DUK__ADVTOK(2, DUK_TOK_INCREMENT);\n\t\t} else if (DUK__L1() == DUK_ASC_EQUALS) {\n\t\t\tadvtok = DUK__ADVTOK(2, DUK_TOK_ADD_EQ);\n\t\t} else {\n\t\t\tadvtok = DUK__ADVTOK(1, DUK_TOK_ADD);\n\t\t}\n\t\tbreak;\n\tcase DUK_ASC_MINUS:  /* '-' */\n#if defined(DUK_USE_HTML_COMMENTS)\n\t\tif (got_lineterm && DUK__L1() == DUK_ASC_MINUS && DUK__L2() == DUK_ASC_RANGLE) {\n\t\t\t/*\n\t\t\t *  ES2015: B.1.3, handle \"-->\" SingleLineHTMLCloseComment\n\t\t\t *  Only allowed:\n\t\t\t *  - on new line\n\t\t\t *  - preceded only by whitespace\n\t\t\t *  - preceded by end of multiline comment and optional whitespace\n\t\t\t *\n\t\t\t * Since whitespace generates no tokens, and multiline comments\n\t\t\t * are treated as a line ending, consulting `got_lineterm` is\n\t\t\t * sufficient to test for these three options.\n\t\t\t */\n\n\t\t\t/* DUK__ADVANCECHARS(lex_ctx, 3) would be correct here, but not necessary */\n\t\t\tduk__lexer_skip_to_endofline(lex_ctx);\n\t\t\tgoto restart;  /* line terminator will be handled on next round */\n\t\t} else\n#endif  /* DUK_USE_HTML_COMMENTS */\n\t\tif (DUK__L1() == DUK_ASC_MINUS) {\n\t\t\tadvtok = DUK__ADVTOK(2, DUK_TOK_DECREMENT);\n\t\t} else if (DUK__L1() == DUK_ASC_EQUALS) {\n\t\t\tadvtok = DUK__ADVTOK(2, DUK_TOK_SUB_EQ);\n\t\t} else {\n\t\t\tadvtok = DUK__ADVTOK(1, DUK_TOK_SUB);\n\t\t}\n\t\tbreak;\n\tcase DUK_ASC_STAR:  /* '*' */\n#if defined(DUK_USE_ES7_EXP_OPERATOR)\n\t\tif (DUK__L1() == DUK_ASC_STAR && DUK__L2() == DUK_ASC_EQUALS) {\n\t\t\tadvtok = DUK__ADVTOK(3, DUK_TOK_EXP_EQ);\n\t\t} else if (DUK__L1() == DUK_ASC_STAR) {\n\t\t\tadvtok = DUK__ADVTOK(2, DUK_TOK_EXP);\n\t\t} else\n#endif\n\t\tif (DUK__L1() == DUK_ASC_EQUALS) {\n\t\t\tadvtok = DUK__ADVTOK(2, DUK_TOK_MUL_EQ);\n\t\t} else {\n\t\t\tadvtok = DUK__ADVTOK(1, DUK_TOK_MUL);\n\t\t}\n\t\tbreak;\n\tcase DUK_ASC_PERCENT:  /* '%' */\n\t\tif (DUK__L1() == DUK_ASC_EQUALS) {\n\t\t\tadvtok = DUK__ADVTOK(2, DUK_TOK_MOD_EQ);\n\t\t} else {\n\t\t\tadvtok = DUK__ADVTOK(1, DUK_TOK_MOD);\n\t\t}\n\t\tbreak;\n\tcase DUK_ASC_AMP:  /* '&' */\n\t\tif (DUK__L1() == DUK_ASC_AMP) {\n\t\t\tadvtok = DUK__ADVTOK(2, DUK_TOK_LAND);\n\t\t} else if (DUK__L1() == DUK_ASC_EQUALS) {\n\t\t\tadvtok = DUK__ADVTOK(2, DUK_TOK_BAND_EQ);\n\t\t} else {\n\t\t\tadvtok = DUK__ADVTOK(1, DUK_TOK_BAND);\n\t\t}\n\t\tbreak;\n\tcase DUK_ASC_PIPE:  /* '|' */\n\t\tif (DUK__L1() == DUK_ASC_PIPE) {\n\t\t\tadvtok = DUK__ADVTOK(2, DUK_TOK_LOR);\n\t\t} else if (DUK__L1() == DUK_ASC_EQUALS) {\n\t\t\tadvtok = DUK__ADVTOK(2, DUK_TOK_BOR_EQ);\n\t\t} else {\n\t\t\tadvtok = DUK__ADVTOK(1, DUK_TOK_BOR);\n\t\t}\n\t\tbreak;\n\tcase DUK_ASC_CARET:  /* '^' */\n\t\tif (DUK__L1() == DUK_ASC_EQUALS) {\n\t\t\tadvtok = DUK__ADVTOK(2, DUK_TOK_BXOR_EQ);\n\t\t} else {\n\t\t\tadvtok = DUK__ADVTOK(1, DUK_TOK_BXOR);\n\t\t}\n\t\tbreak;\n\tcase DUK_ASC_TILDE:  /* '~' */\n\t\tadvtok = DUK__ADVTOK(1, DUK_TOK_BNOT);\n\t\tbreak;\n\tcase DUK_ASC_QUESTION:  /* '?' */\n\t\tadvtok = DUK__ADVTOK(1, DUK_TOK_QUESTION);\n\t\tbreak;\n\tcase DUK_ASC_COLON:  /* ':' */\n\t\tadvtok = DUK__ADVTOK(1, DUK_TOK_COLON);\n\t\tbreak;\n\tcase DUK_ASC_DOUBLEQUOTE:    /* '\"' */\n\tcase DUK_ASC_SINGLEQUOTE: {  /* '\\'' */\n\t\tDUK__INITBUFFER(lex_ctx);\n\t\tduk__lexer_parse_string_literal(lex_ctx, out_token, x /*quote*/, strict_mode);\n\t\tduk__internbuffer(lex_ctx, lex_ctx->slot1_idx);\n\t\tout_token->str1 = duk_known_hstring(lex_ctx->thr, lex_ctx->slot1_idx);\n\n\t\tDUK__INITBUFFER(lex_ctx);  /* free some memory */\n\n\t\tadvtok = DUK__ADVTOK(0, DUK_TOK_STRING);\n\t\tbreak;\n\t}\n\tdefault:\n\t\tgoto slow_path;\n\t}  /* switch */\n\n\tgoto skip_slow_path;\n\n slow_path:\n\tif (duk_unicode_is_line_terminator(x)) {\n\t\tif (x == 0x000d && DUK__L1() == 0x000a) {\n\t\t\t/*\n\t\t\t *  E5 Section 7.3: CR LF is detected as a single line terminator for\n\t\t\t *  line numbers.  Here we also detect it as a single line terminator\n\t\t\t *  token.\n\t\t\t */\n\t\t\tDUK__ADVANCECHARS(lex_ctx, 2);\n\t\t} else {\n\t\t\tDUK__ADVANCECHARS(lex_ctx, 1);\n\t\t}\n\t\tgot_lineterm = 1;\n\t\tgoto restart_lineupdate;\n\t} else if (duk_unicode_is_identifier_start(x) || x == DUK_ASC_BACKSLASH) {\n\t\t/*\n\t\t *  Parse an identifier and then check whether it is:\n\t\t *    - reserved word (keyword or other reserved word)\n\t\t *    - \"null\"  (NullLiteral)\n\t\t *    - \"true\"  (BooleanLiteral)\n\t\t *    - \"false\" (BooleanLiteral)\n\t\t *    - anything else => identifier\n\t\t *\n\t\t *  This does not follow the E5 productions cleanly, but is\n\t\t *  useful and compact.\n\t\t *\n\t\t *  Note that identifiers may contain Unicode escapes,\n\t\t *  see E5 Sections 6 and 7.6.  They must be decoded first,\n\t\t *  and the result checked against allowed characters.\n\t\t *  The above if-clause accepts an identifier start and an\n\t\t *  '\\' character -- no other token can begin with a '\\'.\n\t\t *\n\t\t *  Note that \"get\" and \"set\" are not reserved words in E5\n\t\t *  specification so they are recognized as plain identifiers\n\t\t *  (the tokens DUK_TOK_GET and DUK_TOK_SET are actually not\n\t\t *  used now).  The compiler needs to work around this.\n\t\t *\n\t\t *  Strictly speaking, following Ecmascript longest match\n\t\t *  specification, an invalid escape for the first character\n\t\t *  should cause a syntax error.  However, an invalid escape\n\t\t *  for IdentifierParts should just terminate the identifier\n\t\t *  early (longest match), and let the next tokenization\n\t\t *  fail.  For instance Rhino croaks with 'foo\\z' when\n\t\t *  parsing the identifier.  This has little practical impact.\n\t\t */\n\n\t\tduk_small_uint_t i, i_end;\n\t\tduk_bool_t first = 1;\n\t\tduk_hstring *str;\n\n\t\tDUK__INITBUFFER(lex_ctx);\n\t\tfor (;;) {\n\t\t\t/* re-lookup first char on first loop */\n\t\t\tif (DUK__L0() == DUK_ASC_BACKSLASH) {\n\t\t\t\tduk_codepoint_t esc_cp;\n\t\t\t\tif (DUK__L1() != DUK_ASC_LC_U) {\n\t\t\t\t\tgoto fail_escape;\n\t\t\t\t}\n\t\t\t\tesc_cp = duk__lexer_parse_escape(lex_ctx, 1 /*allow_es6*/);\n\t\t\t\tDUK__APPENDBUFFER(lex_ctx, esc_cp);\n\n\t\t\t\t/* IdentifierStart is stricter than IdentifierPart, so if the first\n\t\t\t\t * character is escaped, must have a stricter check here.\n\t\t\t\t */\n\t\t\t\tif (!(first ? duk_unicode_is_identifier_start(esc_cp) : duk_unicode_is_identifier_part(esc_cp))) {\n\t\t\t\t\tgoto fail_escape;\n\t\t\t\t}\n\n\t\t\t\t/* Track number of escapes: necessary for proper keyword\n\t\t\t\t * detection.\n\t\t\t\t */\n\t\t\t\tout_token->num_escapes++;\n\t\t\t} else {\n\t\t\t\t/* Note: first character is checked against this.  But because\n\t\t\t\t * IdentifierPart includes all IdentifierStart characters, and\n\t\t\t\t * the first character (if unescaped) has already been checked\n\t\t\t\t * in the if condition, this is OK.\n\t\t\t\t */\n\t\t\t\tif (!duk_unicode_is_identifier_part(DUK__L0())) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tDUK__APPENDBUFFER(lex_ctx, DUK__L0());\n\t\t\t\tDUK__ADVANCECHARS(lex_ctx, 1);\n\t\t\t}\n\t\t\tfirst = 0;\n\t\t}\n\n\t\tout_token->str1 = duk__internbuffer(lex_ctx, lex_ctx->slot1_idx);\n\t\tstr = out_token->str1;\n\t\tout_token->t_nores = DUK_TOK_IDENTIFIER;\n\n\t\tDUK__INITBUFFER(lex_ctx);  /* free some memory */\n\n\t\t/*\n\t\t *  Interned identifier is compared against reserved words, which are\n\t\t *  currently interned into the heap context.  See genbuiltins.py.\n\t\t *\n\t\t *  Note that an escape in the identifier disables recognition of\n\t\t *  keywords; e.g. \"\\u0069f = 1;\" is a valid statement (assigns to\n\t\t *  identifier named \"if\").  This is not necessarily compliant,\n\t\t *  see test-dec-escaped-char-in-keyword.js.\n\t\t *\n\t\t *  Note: \"get\" and \"set\" are awkward.  They are not officially\n\t\t *  ReservedWords (and indeed e.g. \"var set = 1;\" is valid), and\n\t\t *  must come out as DUK_TOK_IDENTIFIER.  The compiler needs to\n\t\t *  work around this a bit.\n\t\t */\n\n\t\t/* XXX: optimize by adding the token numbers directly into the\n\t\t * always interned duk_hstring objects (there should be enough\n\t\t * flag bits free for that)?\n\t\t */\n\n\t\ti_end = (strict_mode ? DUK_STRIDX_END_RESERVED : DUK_STRIDX_START_STRICT_RESERVED);\n\n\t\tadvtok = DUK__ADVTOK(0, DUK_TOK_IDENTIFIER);\n\t\tif (out_token->num_escapes == 0) {\n\t\t\tfor (i = DUK_STRIDX_START_RESERVED; i < i_end; i++) {\n\t\t\t\tDUK_ASSERT_DISABLE(i >= 0);  /* unsigned */\n\t\t\t\tDUK_ASSERT(i < DUK_HEAP_NUM_STRINGS);\n\t\t\t\tif (DUK_HTHREAD_GET_STRING(lex_ctx->thr, i) == str) {\n\t\t\t\t\tadvtok = DUK__ADVTOK(0, DUK_STRIDX_TO_TOK(i));\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} else if (DUK__ISDIGIT(x) || (x == DUK_ASC_PERIOD)) {\n\t\t/* Note: decimal number may start with a period, but must be followed by a digit */\n\n\t\t/*\n\t\t *  Pre-parsing for decimal, hex, octal (both legacy and ES2015),\n\t\t *  and binary literals, followed by an actual parser step\n\t\t *  provided by numconv.\n\t\t *\n\t\t *  Note: the leading sign character ('+' or '-') is -not- part of\n\t\t *  the production in E5 grammar, and that the a DecimalLiteral\n\t\t *  starting with a '0' must be followed by a non-digit.\n\t\t *\n\t\t *  XXX: the two step parsing process is quite awkward, it would\n\t\t *  be more straightforward to allow numconv to parse the longest\n\t\t *  valid prefix (it already does that, it only needs to indicate\n\t\t *  where the input ended).  However, the lexer decodes characters\n\t\t *  using a limited lookup window, so this is not a trivial change.\n\t\t */\n\n\t\t/* XXX: because of the final check below (that the literal is not\n\t\t * followed by a digit), this could maybe be simplified, if we bail\n\t\t * out early from a leading zero (and if there are no periods etc).\n\t\t * Maybe too complex.\n\t\t */\n\n\t\tduk_double_t val;\n\t\tduk_bool_t legacy_oct = 0;\n\t\tduk_small_int_t state;  /* 0=before period/exp,\n\t\t                         * 1=after period, before exp\n\t\t                         * 2=after exp, allow '+' or '-'\n\t\t                         * 3=after exp and exp sign\n\t\t                         */\n\t\tduk_small_uint_t s2n_flags;\n\t\tduk_codepoint_t y, z;\n\t\tduk_small_int_t s2n_radix = 10;\n\t\tduk_small_uint_t pre_adv = 0;\n\n\t\tDUK__INITBUFFER(lex_ctx);\n\t\ty = DUK__L1();\n\n\t\tif (x == DUK_ASC_0) {\n\t\t\tz = DUK_LOWERCASE_CHAR_ASCII(y);\n\n\t\t\tpre_adv = 2;  /* default for 0xNNN, 0oNNN, 0bNNN. */\n\t\t\tif (z == DUK_ASC_LC_X) {\n\t\t\t\ts2n_radix = 16;\n\t\t\t} else if (z == DUK_ASC_LC_O) {\n\t\t\t\ts2n_radix = 8;\n\t\t\t} else if (z == DUK_ASC_LC_B) {\n\t\t\t\ts2n_radix = 2;\n\t\t\t} else {\n\t\t\t\tpre_adv = 0;\n\t\t\t\tif (DUK__ISDIGIT(y)) {\n\t\t\t\t\tif (strict_mode) {\n\t\t\t\t\t\t/* Reject octal like \\07 but also octal-lookalike\n\t\t\t\t\t\t * decimal like \\08 in strict mode.\n\t\t\t\t\t\t */\n\t\t\t\t\t\tgoto fail_number_literal;\n\t\t\t\t\t} else {\n\t\t\t\t\t\t/* Legacy OctalIntegerLiteral or octal-lookalice\n\t\t\t\t\t\t * decimal.  Deciding between the two happens below\n\t\t\t\t\t\t * in digit scanning.\n\t\t\t\t\t\t */\n\t\t\t\t\t\tDUK__APPENDBUFFER(lex_ctx, x);\n\t\t\t\t\t\tpre_adv = 1;\n\t\t\t\t\t\tlegacy_oct = 1;\n\t\t\t\t\t\ts2n_radix = 8;  /* tentative unless conflicting digits found */\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tDUK__ADVANCECHARS(lex_ctx, pre_adv);\n\n\t\t/* XXX: we could parse integers here directly, and fall back\n\t\t * to numconv only when encountering a fractional expression\n\t\t * or when an octal literal turned out to be decimal (0778 etc).\n\t\t */\n\t\tstate = 0;\n\t\tfor (;;) {\n\t\t\tx = DUK__L0();  /* re-lookup curr char on first round */\n\t\t\tif (DUK__ISDIGIT(x)) {\n\t\t\t\t/* Note: intentionally allow leading zeroes here, as the\n\t\t\t\t * actual parser will check for them.\n\t\t\t\t */\n\t\t\t\tif (state == 0 && legacy_oct && (x == DUK_ASC_8 || x == DUK_ASC_9)) {\n\t\t\t\t\t/* Started out as an octal-lookalike\n\t\t\t\t\t * but interpreted as decimal, e.g.\n\t\t\t\t\t * '0779' -> 779.  This also means\n\t\t\t\t\t * that fractions are allowed, e.g.\n\t\t\t\t\t * '0779.123' is allowed but '0777.123'\n\t\t\t\t\t * is not!\n\t\t\t\t\t */\n\t\t\t\t\ts2n_radix = 10;\n\t\t\t\t}\n\t\t\t\tif (state == 2) {\n\t\t\t\t\tstate = 3;\n\t\t\t\t}\n\t\t\t} else if (s2n_radix == 16 && DUK__ISHEXDIGIT(x)) {\n\t\t\t\t/* Note: 'e' and 'E' are also accepted here. */\n\t\t\t\t;\n\t\t\t} else if (x == DUK_ASC_PERIOD) {\n\t\t\t\tif (state >= 1 || s2n_radix != 10) {\n\t\t\t\t\tbreak;\n\t\t\t\t} else {\n\t\t\t\t\tstate = 1;\n\t\t\t\t}\n\t\t\t} else if (x == DUK_ASC_LC_E || x == DUK_ASC_UC_E) {\n\t\t\t\tif (state >= 2 || s2n_radix != 10) {\n\t\t\t\t\tbreak;\n\t\t\t\t} else {\n\t\t\t\t\tstate = 2;\n\t\t\t\t}\n\t\t\t} else if (x == DUK_ASC_MINUS || x == DUK_ASC_PLUS) {\n\t\t\t\tif (state != 2) {\n\t\t\t\t\tbreak;\n\t\t\t\t} else {\n\t\t\t\t\tstate = 3;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tDUK__APPENDBUFFER(lex_ctx, x);\n\t\t\tDUK__ADVANCECHARS(lex_ctx, 1);\n\t\t}\n\n\t\t/* XXX: better coercion */\n\t\t(void) duk__internbuffer(lex_ctx, lex_ctx->slot1_idx);\n\n\t\tif (s2n_radix != 10) {\n\t\t\t/* For bases other than 10, integer only. */\n\t\t\ts2n_flags = DUK_S2N_FLAG_ALLOW_LEADING_ZERO;\n\t\t} else {\n\t\t\ts2n_flags = DUK_S2N_FLAG_ALLOW_EXP |\n\t\t\t            DUK_S2N_FLAG_ALLOW_FRAC |\n\t\t\t            DUK_S2N_FLAG_ALLOW_NAKED_FRAC |\n\t\t\t            DUK_S2N_FLAG_ALLOW_EMPTY_FRAC |\n\t\t\t            DUK_S2N_FLAG_ALLOW_LEADING_ZERO;\n\t\t}\n\n\t\tduk_dup(lex_ctx->thr, lex_ctx->slot1_idx);\n\t\tduk_numconv_parse(lex_ctx->thr, s2n_radix, s2n_flags);\n\t\tval = duk_to_number_m1(lex_ctx->thr);\n\t\tif (DUK_ISNAN(val)) {\n\t\t\tgoto fail_number_literal;\n\t\t}\n\t\tduk_replace(lex_ctx->thr, lex_ctx->slot1_idx);  /* could also just pop? */\n\n\t\tDUK__INITBUFFER(lex_ctx);  /* free some memory */\n\n\t\t/* Section 7.8.3 (note): NumericLiteral must be followed by something other than\n\t\t * IdentifierStart or DecimalDigit.\n\t\t */\n\n\t\tif (DUK__ISDIGIT(DUK__L0()) || duk_unicode_is_identifier_start(DUK__L0())) {\n\t\t\tgoto fail_number_literal;\n\t\t}\n\n\t\tout_token->num = val;\n\t\tadvtok = DUK__ADVTOK(0, DUK_TOK_NUMBER);\n\t} else if (duk_unicode_is_whitespace(DUK__LOOKUP(lex_ctx, 0))) {\n\t\tDUK__ADVANCECHARS(lex_ctx, 1);\n\t\tgoto restart;\n\t} else if (x < 0) {\n\t\tadvtok = DUK__ADVTOK(0, DUK_TOK_EOF);\n\t} else {\n\t\tgoto fail_token;\n\t}\n skip_slow_path:\n\n\t/*\n\t *  Shared exit path\n\t */\n\n\tDUK__ADVANCEBYTES(lex_ctx, advtok >> 8);\n\tout_token->t = advtok & 0xff;\n\tif (out_token->t_nores == DUK_TOK_INVALID) {\n\t\tout_token->t_nores = out_token->t;\n\t}\n\tout_token->lineterm = got_lineterm;\n\n\t/* Automatic semicolon insertion is allowed if a token is preceded\n\t * by line terminator(s), or terminates a statement list (right curly\n\t * or EOF).\n\t */\n\tif (got_lineterm || out_token->t == DUK_TOK_RCURLY || out_token->t == DUK_TOK_EOF) {\n\t\tout_token->allow_auto_semi = 1;\n\t} else {\n\t\tout_token->allow_auto_semi = 0;\n\t}\n\n\treturn;\n\n fail_token_limit:\n\tDUK_ERROR_RANGE(lex_ctx->thr, DUK_STR_TOKEN_LIMIT);\n\treturn;\n\n fail_token:\n\tDUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_TOKEN);\n\treturn;\n\n fail_number_literal:\n\tDUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_NUMBER_LITERAL);\n\treturn;\n\n fail_escape:\n\tDUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_ESCAPE);\n\treturn;\n\n fail_unterm_regexp:\n\tDUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_UNTERMINATED_REGEXP);\n\treturn;\n\n fail_unterm_comment:\n\tDUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_UNTERMINATED_COMMENT);\n\treturn;\n\n#if !defined(DUK_USE_REGEXP_SUPPORT)\n fail_regexp_support:\n\tDUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_REGEXP_SUPPORT_DISABLED);\n\treturn;\n#endif\n}\n\n#if defined(DUK_USE_REGEXP_SUPPORT)\n\n/*\n *  Parse a RegExp token.  The grammar is described in E5 Section 15.10.\n *  Terminal constructions (such as quantifiers) are parsed directly here.\n *\n *  0xffffffffU is used as a marker for \"infinity\" in quantifiers.  Further,\n *  DUK__MAX_RE_QUANT_DIGITS limits the maximum number of digits that\n *  will be accepted for a quantifier.\n */\n\nDUK_INTERNAL void duk_lexer_parse_re_token(duk_lexer_ctx *lex_ctx, duk_re_token *out_token) {\n\tduk_small_uint_t advtok = 0;  /* init is unnecessary but suppresses \"may be used uninitialized\" warnings */\n\tduk_codepoint_t x, y;\n\n\tif (++lex_ctx->token_count >= lex_ctx->token_limit) {\n\t\tgoto fail_token_limit;\n\t}\n\n\tDUK_MEMZERO(out_token, sizeof(*out_token));\n\n\tx = DUK__L0();\n\ty = DUK__L1();\n\n\tDUK_DDD(DUK_DDDPRINT(\"parsing regexp token, L0=%ld, L1=%ld\", (long) x, (long) y));\n\n\tswitch (x) {\n\tcase DUK_ASC_PIPE: {\n\t\tadvtok = DUK__ADVTOK(1, DUK_RETOK_DISJUNCTION);\n\t\tbreak;\n\t}\n\tcase DUK_ASC_CARET: {\n\t\tadvtok = DUK__ADVTOK(1, DUK_RETOK_ASSERT_START);\n\t\tbreak;\n\t}\n\tcase DUK_ASC_DOLLAR: {\n\t\tadvtok = DUK__ADVTOK(1, DUK_RETOK_ASSERT_END);\n\t\tbreak;\n\t}\n\tcase DUK_ASC_QUESTION: {\n\t\tout_token->qmin = 0;\n\t\tout_token->qmax = 1;\n\t\tif (y == DUK_ASC_QUESTION) {\n\t\t\tadvtok = DUK__ADVTOK(2, DUK_RETOK_QUANTIFIER);\n\t\t\tout_token->greedy = 0;\n\t\t} else {\n\t\t\tadvtok = DUK__ADVTOK(1, DUK_RETOK_QUANTIFIER);\n\t\t\tout_token->greedy = 1;\n\t\t}\n\t\tbreak;\n\t}\n\tcase DUK_ASC_STAR: {\n\t\tout_token->qmin = 0;\n\t\tout_token->qmax = DUK_RE_QUANTIFIER_INFINITE;\n\t\tif (y == DUK_ASC_QUESTION) {\n\t\t\tadvtok = DUK__ADVTOK(2, DUK_RETOK_QUANTIFIER);\n\t\t\tout_token->greedy = 0;\n\t\t} else {\n\t\t\tadvtok = DUK__ADVTOK(1, DUK_RETOK_QUANTIFIER);\n\t\t\tout_token->greedy = 1;\n\t\t}\n\t\tbreak;\n\t}\n\tcase DUK_ASC_PLUS: {\n\t\tout_token->qmin = 1;\n\t\tout_token->qmax = DUK_RE_QUANTIFIER_INFINITE;\n\t\tif (y == DUK_ASC_QUESTION) {\n\t\t\tadvtok = DUK__ADVTOK(2, DUK_RETOK_QUANTIFIER);\n\t\t\tout_token->greedy = 0;\n\t\t} else {\n\t\t\tadvtok = DUK__ADVTOK(1, DUK_RETOK_QUANTIFIER);\n\t\t\tout_token->greedy = 1;\n\t\t}\n\t\tbreak;\n\t}\n\tcase DUK_ASC_LCURLY: {\n\t\t/* Production allows 'DecimalDigits', including leading zeroes */\n\t\tduk_uint32_t val1 = 0;\n\t\tduk_uint32_t val2 = DUK_RE_QUANTIFIER_INFINITE;\n\t\tduk_small_int_t digits = 0;\n#if defined(DUK_USE_ES6_REGEXP_SYNTAX)\n\t\tduk_lexer_point lex_pt;\n#endif\n\n#if defined(DUK_USE_ES6_REGEXP_SYNTAX)\n\t\t/* Store lexer position, restoring if quantifier is invalid. */\n\t\tDUK_LEXER_GETPOINT(lex_ctx, &lex_pt);\n#endif\n\n\t\tfor (;;) {\n\t\t\tDUK__ADVANCECHARS(lex_ctx, 1);  /* eat '{' on entry */\n\t\t\tx = DUK__L0();\n\t\t\tif (DUK__ISDIGIT(x)) {\n\t\t\t\tdigits++;\n\t\t\t\tval1 = val1 * 10 + (duk_uint32_t) duk__hexval(x);\n\t\t\t} else if (x == DUK_ASC_COMMA) {\n\t\t\t\tif (digits > DUK__MAX_RE_QUANT_DIGITS) {\n\t\t\t\t\tgoto invalid_quantifier;\n\t\t\t\t}\n\t\t\t\tif (val2 != DUK_RE_QUANTIFIER_INFINITE) {\n\t\t\t\t\tgoto invalid_quantifier;\n\t\t\t\t}\n\t\t\t\tif (DUK__L1() == DUK_ASC_RCURLY) {\n\t\t\t\t\t/* form: { DecimalDigits , }, val1 = min count */\n\t\t\t\t\tif (digits == 0) {\n\t\t\t\t\t\tgoto invalid_quantifier;\n\t\t\t\t\t}\n\t\t\t\t\tout_token->qmin = val1;\n\t\t\t\t\tout_token->qmax = DUK_RE_QUANTIFIER_INFINITE;\n\t\t\t\t\tDUK__ADVANCECHARS(lex_ctx, 2);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tval2 = val1;\n\t\t\t\tval1 = 0;\n\t\t\t\tdigits = 0;  /* not strictly necessary because of lookahead '}' above */\n\t\t\t} else if (x == DUK_ASC_RCURLY) {\n\t\t\t\tif (digits > DUK__MAX_RE_QUANT_DIGITS) {\n\t\t\t\t\tgoto invalid_quantifier;\n\t\t\t\t}\n\t\t\t\tif (digits == 0) {\n\t\t\t\t\tgoto invalid_quantifier;\n\t\t\t\t}\n\t\t\t\tif (val2 != DUK_RE_QUANTIFIER_INFINITE) {\n\t\t\t\t\t/* val2 = min count, val1 = max count */\n\t\t\t\t\tout_token->qmin = val2;\n\t\t\t\t\tout_token->qmax = val1;\n\t\t\t\t} else {\n\t\t\t\t\t/* val1 = count */\n\t\t\t\t\tout_token->qmin = val1;\n\t\t\t\t\tout_token->qmax = val1;\n\t\t\t\t}\n\t\t\t\tDUK__ADVANCECHARS(lex_ctx, 1);\n\t\t\t\tbreak;\n\t\t\t} else {\n\t\t\t\tgoto invalid_quantifier;\n\t\t\t}\n\t\t}\n\t\tif (DUK__L0() == DUK_ASC_QUESTION) {\n\t\t\tout_token->greedy = 0;\n\t\t\tDUK__ADVANCECHARS(lex_ctx, 1);\n\t\t} else {\n\t\t\tout_token->greedy = 1;\n\t\t}\n\t\tadvtok = DUK__ADVTOK(0, DUK_RETOK_QUANTIFIER);\n\t\tbreak;\n invalid_quantifier:\n#if defined(DUK_USE_ES6_REGEXP_SYNTAX)\n\t\t/* Failed to match the quantifier, restore lexer and parse\n\t\t * opening brace as a literal.\n\t\t */\n\t\tDUK_LEXER_SETPOINT(lex_ctx, &lex_pt);\n\t\tadvtok = DUK__ADVTOK(1, DUK_RETOK_ATOM_CHAR);\n\t\tout_token->num = DUK_ASC_LCURLY;\n#else\n\t\tgoto fail_quantifier;\n#endif\n\t\tbreak;\n\t}\n\tcase DUK_ASC_PERIOD: {\n\t\tadvtok = DUK__ADVTOK(1, DUK_RETOK_ATOM_PERIOD);\n\t\tbreak;\n\t}\n\tcase DUK_ASC_BACKSLASH: {\n\t\t/* The E5.1 specification does not seem to allow IdentifierPart characters\n\t\t * to be used as identity escapes.  Unfortunately this includes '$', which\n\t\t * cannot be escaped as '\\$'; it needs to be escaped e.g. as '\\u0024'.\n\t\t * Many other implementations (including V8 and Rhino, for instance) do\n\t\t * accept '\\$' as a valid identity escape, which is quite pragmatic, and\n\t\t * ES2015 Annex B relaxes the rules to allow these (and other) real world forms.\n\t\t */\n\n\t\tadvtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_CHAR);  /* default: char escape (two chars) */\n\t\tif (y == DUK_ASC_LC_B) {\n\t\t\tadvtok = DUK__ADVTOK(2, DUK_RETOK_ASSERT_WORD_BOUNDARY);\n\t\t} else if (y == DUK_ASC_UC_B) {\n\t\t\tadvtok = DUK__ADVTOK(2, DUK_RETOK_ASSERT_NOT_WORD_BOUNDARY);\n\t\t} else if (y == DUK_ASC_LC_F) {\n\t\t\tout_token->num = 0x000c;\n\t\t} else if (y == DUK_ASC_LC_N) {\n\t\t\tout_token->num = 0x000a;\n\t\t} else if (y == DUK_ASC_LC_T) {\n\t\t\tout_token->num = 0x0009;\n\t\t} else if (y == DUK_ASC_LC_R) {\n\t\t\tout_token->num = 0x000d;\n\t\t} else if (y == DUK_ASC_LC_V) {\n\t\t\tout_token->num = 0x000b;\n\t\t} else if (y == DUK_ASC_LC_C) {\n\t\t\tx = DUK__L2();\n\t\t\tif ((x >= DUK_ASC_LC_A && x <= DUK_ASC_LC_Z) ||\n\t\t\t    (x >= DUK_ASC_UC_A && x <= DUK_ASC_UC_Z)) {\n\t\t\t\tout_token->num = (duk_uint32_t) (x % 32);\n\t\t\t\tadvtok = DUK__ADVTOK(3, DUK_RETOK_ATOM_CHAR);\n\t\t\t} else {\n\t\t\t\tgoto fail_escape;\n\t\t\t}\n\t\t} else if (y == DUK_ASC_LC_X || y == DUK_ASC_LC_U) {\n\t\t\t/* The token value is the Unicode codepoint without\n\t\t\t * it being decode into surrogate pair characters\n\t\t\t * here.  The \\u{H+} is only allowed in Unicode mode\n\t\t\t * which we don't support yet.\n\t\t\t */\n\t\t\tout_token->num = (duk_uint32_t) duk__lexer_parse_escape(lex_ctx, 0 /*allow_es6*/);\n\t\t\tadvtok = DUK__ADVTOK(0, DUK_RETOK_ATOM_CHAR);\n\t\t} else if (y == DUK_ASC_LC_D) {\n\t\t\tadvtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_DIGIT);\n\t\t} else if (y == DUK_ASC_UC_D) {\n\t\t\tadvtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_NOT_DIGIT);\n\t\t} else if (y == DUK_ASC_LC_S) {\n\t\t\tadvtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_WHITE);\n\t\t} else if (y == DUK_ASC_UC_S) {\n\t\t\tadvtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_NOT_WHITE);\n\t\t} else if (y == DUK_ASC_LC_W) {\n\t\t\tadvtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_WORD_CHAR);\n\t\t} else if (y == DUK_ASC_UC_W) {\n\t\t\tadvtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_NOT_WORD_CHAR);\n\t\t} else if (DUK__ISDIGIT(y)) {\n\t\t\t/* E5 Section 15.10.2.11 */\n\t\t\tif (y == DUK_ASC_0) {\n\t\t\t\tif (DUK__ISDIGIT(DUK__L2())) {\n\t\t\t\t\tgoto fail_escape;\n\t\t\t\t}\n\t\t\t\tout_token->num = 0x0000;\n\t\t\t\tadvtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_CHAR);\n\t\t\t} else {\n\t\t\t\t/* XXX: shared parsing? */\n\t\t\t\tduk_uint32_t val = 0;\n\t\t\t\tduk_small_int_t i;\n\t\t\t\tfor (i = 0; ; i++) {\n\t\t\t\t\tif (i >= DUK__MAX_RE_DECESC_DIGITS) {\n\t\t\t\t\t\tgoto fail_escape;\n\t\t\t\t\t}\n\t\t\t\t\tDUK__ADVANCECHARS(lex_ctx, 1);  /* eat backslash on entry */\n\t\t\t\t\tx = DUK__L0();\n\t\t\t\t\tif (!DUK__ISDIGIT(x)) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tval = val * 10 + (duk_uint32_t) duk__hexval(x);\n\t\t\t\t}\n\t\t\t\t/* DUK__L0() cannot be a digit, because the loop doesn't terminate if it is */\n\t\t\t\tadvtok = DUK__ADVTOK(0, DUK_RETOK_ATOM_BACKREFERENCE);\n\t\t\t\tout_token->num = val;\n\t\t\t}\n#if defined(DUK_USE_ES6_REGEXP_SYNTAX)\n\t\t} else if (y >= 0) {\n\t\t\t/* For ES2015 Annex B, accept any source character as identity\n\t\t\t * escape except 'c' which is used for control characters.\n\t\t\t * http://www.ecma-international.org/ecma-262/6.0/#sec-regular-expressions-patterns\n\t\t\t * Careful not to match end-of-buffer (<0) here.\n\t\t\t * This is not yet full ES2015 Annex B because cases above\n\t\t\t * (like hex escape) won't backtrack.\n\t\t\t */\n\t\t\tDUK_ASSERT(y != DUK_ASC_LC_C);  /* covered above */\n#else  /* DUK_USE_ES6_REGEXP_SYNTAX */\n\t\t} else if ((y >= 0 && !duk_unicode_is_identifier_part(y)) ||\n\t\t           y == DUK_UNICODE_CP_ZWNJ ||\n\t\t           y == DUK_UNICODE_CP_ZWJ) {\n\t\t\t/* For ES5.1 identity escapes are not allowed for identifier\n\t\t\t * parts.  This conflicts with a lot of real world code as this\n\t\t\t * doesn't e.g. allow escaping a dollar sign as /\\$/, see\n\t\t\t * test-regexp-identity-escape-dollar.js.\n\t\t\t */\n#endif  /* DUK_USE_ES6_REGEXP_SYNTAX */\n\t\t\tout_token->num = (duk_uint32_t) y;\n\t\t} else {\n\t\t\tgoto fail_escape;\n\t\t}\n\t\tbreak;\n\t}\n\tcase DUK_ASC_LPAREN: {\n\t\t/* XXX: naming is inconsistent: ATOM_END_GROUP ends an ASSERT_START_LOOKAHEAD */\n\n\t\tif (y == DUK_ASC_QUESTION) {\n\t\t\tif (DUK__L2() == DUK_ASC_EQUALS) {\n\t\t\t\t/* (?= */\n\t\t\t\tadvtok = DUK__ADVTOK(3, DUK_RETOK_ASSERT_START_POS_LOOKAHEAD);\n\t\t\t} else if (DUK__L2() == DUK_ASC_EXCLAMATION) {\n\t\t\t\t/* (?! */\n\t\t\t\tadvtok = DUK__ADVTOK(3, DUK_RETOK_ASSERT_START_NEG_LOOKAHEAD);\n\t\t\t} else if (DUK__L2() == DUK_ASC_COLON) {\n\t\t\t\t/* (?: */\n\t\t\t\tadvtok = DUK__ADVTOK(3, DUK_RETOK_ATOM_START_NONCAPTURE_GROUP);\n\t\t\t} else {\n\t\t\t\tgoto fail_group;\n\t\t\t}\n\t\t} else {\n\t\t\t/* ( */\n\t\t\tadvtok = DUK__ADVTOK(1, DUK_RETOK_ATOM_START_CAPTURE_GROUP);\n\t\t}\n\t\tbreak;\n\t}\n\tcase DUK_ASC_RPAREN: {\n\t\tadvtok = DUK__ADVTOK(1, DUK_RETOK_ATOM_END_GROUP);\n\t\tbreak;\n\t}\n\tcase DUK_ASC_LBRACKET: {\n\t\t/*\n\t\t *  To avoid creating a heavy intermediate value for the list of ranges,\n\t\t *  only the start token ('[' or '[^') is parsed here.  The regexp\n\t\t *  compiler parses the ranges itself.\n\t\t */\n\n\t\t/* XXX: with DUK_USE_ES6_REGEXP_SYNTAX we should allow left bracket\n\t\t * literal too, but it's not easy to parse without backtracking.\n\t\t */\n\n\t\tadvtok = DUK__ADVTOK(1, DUK_RETOK_ATOM_START_CHARCLASS);\n\t\tif (y == DUK_ASC_CARET) {\n\t\t\tadvtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_START_CHARCLASS_INVERTED);\n\t\t}\n\t\tbreak;\n\t}\n#if !defined(DUK_USE_ES6_REGEXP_SYNTAX)\n\tcase DUK_ASC_RCURLY:\n\tcase DUK_ASC_RBRACKET: {\n\t\t/* Although these could be parsed as PatternCharacters unambiguously (here),\n\t\t * E5 Section 15.10.1 grammar explicitly forbids these as PatternCharacters.\n\t\t */\n\t\tgoto fail_invalid_char;\n\t\tbreak;\n\t}\n#endif\n\tcase -1: {\n\t\t/* EOF */\n\t\tadvtok = DUK__ADVTOK(0, DUK_TOK_EOF);\n\t\tbreak;\n\t}\n\tdefault: {\n\t\t/* PatternCharacter, all excluded characters are matched by cases above */\n\t\tadvtok = DUK__ADVTOK(1, DUK_RETOK_ATOM_CHAR);\n\t\tout_token->num = (duk_uint32_t) x;\n\t\tbreak;\n\t}\n\t}\n\n\t/*\n\t *  Shared exit path\n\t */\n\n\tDUK__ADVANCEBYTES(lex_ctx, advtok >> 8);\n\tout_token->t = advtok & 0xff;\n\treturn;\n\n fail_token_limit:\n\tDUK_ERROR_RANGE(lex_ctx->thr, DUK_STR_TOKEN_LIMIT);\n\treturn;\n\n fail_escape:\n\tDUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_REGEXP_ESCAPE);\n\treturn;\n\n fail_group:\n\tDUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_REGEXP_GROUP);\n\treturn;\n\n#if !defined(DUK_USE_ES6_REGEXP_SYNTAX)\n fail_invalid_char:\n\tDUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_REGEXP_CHARACTER);\n\treturn;\n\n fail_quantifier:\n\tDUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_QUANTIFIER);\n\treturn;\n#endif\n}\n\n/*\n *  Special parser for character classes; calls callback for every\n *  range parsed and returns the number of ranges present.\n */\n\n/* XXX: this duplicates functionality in duk_regexp.c where a similar loop is\n * required anyway.  We could use that BUT we need to update the regexp compiler\n * 'nranges' too.  Work this out a bit more cleanly to save space.\n */\n\n/* XXX: the handling of character range detection is a bit convoluted.\n * Try to simplify and make smaller.\n */\n\n/* XXX: logic for handling character ranges is now incorrect, it will accept\n * e.g. [\\d-z] whereas it should croak from it?  SMJS accepts this too, though.\n *\n * Needs a read through and a lot of additional tests.\n */\n\nDUK_LOCAL\nvoid duk__emit_u16_direct_ranges(duk_lexer_ctx *lex_ctx,\n                                 duk_re_range_callback gen_range,\n                                 void *userdata,\n                                 const duk_uint16_t *ranges,\n                                 duk_small_int_t num) {\n\tconst duk_uint16_t *ranges_end;\n\n\tDUK_UNREF(lex_ctx);\n\n\tranges_end = ranges + num;\n\twhile (ranges < ranges_end) {\n\t\t/* mark range 'direct', bypass canonicalization (see Wiki) */\n\t\tgen_range(userdata, (duk_codepoint_t) ranges[0], (duk_codepoint_t) ranges[1], 1);\n\t\tranges += 2;\n\t}\n}\n\nDUK_INTERNAL void duk_lexer_parse_re_ranges(duk_lexer_ctx *lex_ctx, duk_re_range_callback gen_range, void *userdata) {\n\tduk_codepoint_t start = -1;\n\tduk_codepoint_t ch;\n\tduk_codepoint_t x;\n\tduk_bool_t dash = 0;\n\tduk_small_uint_t adv = 0;\n\n\tDUK_DD(DUK_DDPRINT(\"parsing regexp ranges\"));\n\n\tfor (;;) {\n\t\tDUK__ADVANCECHARS(lex_ctx, adv);\n\t\tadv = 1;\n\n\t\tx = DUK__L0();\n\n\t\tch = -1;  /* not strictly necessary, but avoids \"uninitialized variable\" warnings */\n\t\tDUK_UNREF(ch);\n\n\t\tif (x < 0) {\n\t\t\tgoto fail_unterm_charclass;\n\t\t} else if (x == DUK_ASC_RBRACKET) {\n\t\t\tif (start >= 0) {\n\t\t\t\tgen_range(userdata, start, start, 0);\n\t\t\t}\n\t\t\tDUK__ADVANCECHARS(lex_ctx, 1);  /* eat ']' before finishing */\n\t\t\tbreak;\n\t\t} else if (x == DUK_ASC_MINUS) {\n\t\t\tif (start >= 0 && !dash && DUK__L1() != DUK_ASC_RBRACKET) {\n\t\t\t\t/* '-' as a range indicator */\n\t\t\t\tdash = 1;\n\t\t\t\tcontinue;\n\t\t\t} else {\n\t\t\t\t/* '-' verbatim */\n\t\t\t\tch = x;\n\t\t\t}\n\t\t} else if (x == DUK_ASC_BACKSLASH) {\n\t\t\t/*\n\t\t\t *  The escapes are same as outside a character class, except that \\b has a\n\t\t\t *  different meaning, and \\B and backreferences are prohibited (see E5\n\t\t\t *  Section 15.10.2.19).  However, it's difficult to share code because we\n\t\t\t *  handle e.g. \"\\n\" very differently: here we generate a single character\n\t\t\t *  range for it.\n\t\t\t */\n\n\t\t\t/* XXX: ES2015 surrogate pair handling. */\n\n\t\t\tx = DUK__L1();\n\n\t\t\tadv = 2;\n\n\t\t\tif (x == DUK_ASC_LC_B) {\n\t\t\t\t/* Note: '\\b' in char class is different than outside (assertion),\n\t\t\t\t * '\\B' is not allowed and is caught by the duk_unicode_is_identifier_part()\n\t\t\t\t * check below.\n\t\t\t\t */\n\t\t\t\tch = 0x0008;\n\t\t\t} else if (x == DUK_ASC_LC_F) {\n\t\t\t\tch = 0x000c;\n\t\t\t} else if (x == DUK_ASC_LC_N) {\n\t\t\t\tch = 0x000a;\n\t\t\t} else if (x == DUK_ASC_LC_T) {\n\t\t\t\tch = 0x0009;\n\t\t\t} else if (x == DUK_ASC_LC_R) {\n\t\t\t\tch = 0x000d;\n\t\t\t} else if (x == DUK_ASC_LC_V) {\n\t\t\t\tch = 0x000b;\n\t\t\t} else if (x == DUK_ASC_LC_C) {\n\t\t\t\tx = DUK__L2();\n\t\t\t\tadv = 3;\n\t\t\t\tif ((x >= DUK_ASC_LC_A && x <= DUK_ASC_LC_Z) ||\n\t\t\t\t    (x >= DUK_ASC_UC_A && x <= DUK_ASC_UC_Z)) {\n\t\t\t\t\tch = (x % 32);\n\t\t\t\t} else {\n\t\t\t\t\tgoto fail_escape;\n\t\t\t\t}\n\t\t\t} else if (x == DUK_ASC_LC_X || x == DUK_ASC_LC_U) {\n\t\t\t\t/* The \\u{H+} form is only allowed in Unicode mode which\n\t\t\t\t * we don't support yet.\n\t\t\t\t */\n\t\t\t\tch = duk__lexer_parse_escape(lex_ctx, 0 /*allow_es6*/);\n\t\t\t\tadv = 0;\n\t\t\t} else if (x == DUK_ASC_LC_D) {\n\t\t\t\tduk__emit_u16_direct_ranges(lex_ctx,\n\t\t\t\t                            gen_range,\n\t\t\t\t                            userdata,\n\t\t\t\t                            duk_unicode_re_ranges_digit,\n\t\t\t\t                            sizeof(duk_unicode_re_ranges_digit) / sizeof(duk_uint16_t));\n\t\t\t\tch = -1;\n\t\t\t} else if (x == DUK_ASC_UC_D) {\n\t\t\t\tduk__emit_u16_direct_ranges(lex_ctx,\n\t\t\t\t                            gen_range,\n\t\t\t\t                            userdata,\n\t\t\t\t                            duk_unicode_re_ranges_not_digit,\n\t\t\t\t                            sizeof(duk_unicode_re_ranges_not_digit) / sizeof(duk_uint16_t));\n\t\t\t\tch = -1;\n\t\t\t} else if (x == DUK_ASC_LC_S) {\n\t\t\t\tduk__emit_u16_direct_ranges(lex_ctx,\n\t\t\t\t                            gen_range,\n\t\t\t\t                            userdata,\n\t\t\t\t                            duk_unicode_re_ranges_white,\n\t\t\t\t                            sizeof(duk_unicode_re_ranges_white) / sizeof(duk_uint16_t));\n\t\t\t\tch = -1;\n\t\t\t} else if (x == DUK_ASC_UC_S) {\n\t\t\t\tduk__emit_u16_direct_ranges(lex_ctx,\n\t\t\t\t                            gen_range,\n\t\t\t\t                            userdata,\n\t\t\t\t                            duk_unicode_re_ranges_not_white,\n\t\t\t\t                            sizeof(duk_unicode_re_ranges_not_white) / sizeof(duk_uint16_t));\n\t\t\t\tch = -1;\n\t\t\t} else if (x == DUK_ASC_LC_W) {\n\t\t\t\tduk__emit_u16_direct_ranges(lex_ctx,\n\t\t\t\t                            gen_range,\n\t\t\t\t                            userdata,\n\t\t\t\t                            duk_unicode_re_ranges_wordchar,\n\t\t\t\t                            sizeof(duk_unicode_re_ranges_wordchar) / sizeof(duk_uint16_t));\n\t\t\t\tch = -1;\n\t\t\t} else if (x == DUK_ASC_UC_W) {\n\t\t\t\tduk__emit_u16_direct_ranges(lex_ctx,\n\t\t\t\t                            gen_range,\n\t\t\t\t                            userdata,\n\t\t\t\t                            duk_unicode_re_ranges_not_wordchar,\n\t\t\t\t                            sizeof(duk_unicode_re_ranges_not_wordchar) / sizeof(duk_uint16_t));\n\t\t\t\tch = -1;\n\t\t\t} else if (DUK__ISDIGIT(x)) {\n\t\t\t\t/* DecimalEscape, only \\0 is allowed, no leading\n\t\t\t\t * zeroes are allowed.\n\t\t\t\t *\n\t\t\t\t * ES2015 Annex B also allows (maximal match) legacy\n\t\t\t\t * octal escapes up to \\377 and \\8 and \\9 are\n\t\t\t\t * accepted as literal '8' and '9', also in strict mode.\n\t\t\t\t */\n\n#if defined(DUK_USE_ES6_REGEXP_SYNTAX)\n\t\t\t\tch = duk__lexer_parse_legacy_octal(lex_ctx, &adv, 0 /*reject_annex_b*/);\n\t\t\t\tDUK_ASSERT(ch >= 0);  /* no rejections */\n#else\n\t\t\t\tif (x == DUK_ASC_0 && !DUK__ISDIGIT(DUK__L2())) {\n\t\t\t\t\tch = 0x0000;\n\t\t\t\t} else {\n\t\t\t\t\tgoto fail_escape;\n\t\t\t\t}\n#endif\n#if defined(DUK_USE_ES6_REGEXP_SYNTAX)\n\t\t\t} else if (x >= 0) {\n\t\t\t\t/* IdentityEscape: ES2015 Annex B allows almost all\n\t\t\t\t * source characters here.  Match anything except\n\t\t\t\t * EOF here.\n\t\t\t\t */\n\t\t\t\tch = x;\n#else  /* DUK_USE_ES6_REGEXP_SYNTAX */\n\t\t\t} else if (!duk_unicode_is_identifier_part(x)) {\n\t\t\t\t/* IdentityEscape: ES5.1 doesn't allow identity escape\n\t\t\t\t * for identifier part characters, which conflicts with\n\t\t\t\t * some real world code.  For example, it doesn't allow\n\t\t\t\t * /[\\$]/ which is awkward.\n\t\t\t\t */\n\t\t\t\tch = x;\n#endif  /* DUK_USE_ES6_REGEXP_SYNTAX */\n\t\t\t} else {\n\t\t\t\tgoto fail_escape;\n\t\t\t}\n\t\t} else {\n\t\t\t/* character represents itself */\n\t\t\tch = x;\n\t\t}\n\n\t\t/* ch is a literal character here or -1 if parsed entity was\n\t\t * an escape such as \"\\s\".\n\t\t */\n\n\t\tif (ch < 0) {\n\t\t\t/* multi-character sets not allowed as part of ranges, see\n\t\t\t * E5 Section 15.10.2.15, abstract operation CharacterRange.\n\t\t\t */\n\t\t\tif (start >= 0) {\n\t\t\t\tif (dash) {\n\t\t\t\t\tgoto fail_range;\n\t\t\t\t} else {\n\t\t\t\t\tgen_range(userdata, start, start, 0);\n\t\t\t\t\tstart = -1;\n\t\t\t\t\t/* dash is already 0 */\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tif (start >= 0) {\n\t\t\t\tif (dash) {\n\t\t\t\t\tif (start > ch) {\n\t\t\t\t\t\tgoto fail_range;\n\t\t\t\t\t}\n\t\t\t\t\tgen_range(userdata, start, ch, 0);\n\t\t\t\t\tstart = -1;\n\t\t\t\t\tdash = 0;\n\t\t\t\t} else {\n\t\t\t\t\tgen_range(userdata, start, start, 0);\n\t\t\t\t\tstart = ch;\n\t\t\t\t\t/* dash is already 0 */\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tstart = ch;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn;\n\n fail_escape:\n\tDUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_REGEXP_ESCAPE);\n\treturn;\n\n fail_range:\n\tDUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_RANGE);\n\treturn;\n\n fail_unterm_charclass:\n\tDUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_UNTERMINATED_CHARCLASS);\n\treturn;\n}\n\n#endif  /* DUK_USE_REGEXP_SUPPORT */\n\n/* automatic undefs */\n#undef DUK__ADVANCEBYTES\n#undef DUK__ADVANCECHARS\n#undef DUK__ADVTOK\n#undef DUK__APPENDBUFFER\n#undef DUK__APPENDBUFFER_ASCII\n#undef DUK__INITBUFFER\n#undef DUK__ISDIGIT\n#undef DUK__ISDIGIT03\n#undef DUK__ISDIGIT47\n#undef DUK__ISHEXDIGIT\n#undef DUK__ISOCTDIGIT\n#undef DUK__L0\n#undef DUK__L1\n#undef DUK__L2\n#undef DUK__L3\n#undef DUK__L4\n#undef DUK__L5\n#undef DUK__LOOKUP\n#undef DUK__MAX_RE_DECESC_DIGITS\n#undef DUK__MAX_RE_QUANT_DIGITS\n#line 1 \"duk_numconv.c\"\n/*\n *  Number-to-string and string-to-number conversions.\n *\n *  Slow path number-to-string and string-to-number conversion is based on\n *  a Dragon4 variant, with fast paths for small integers.  Big integer\n *  arithmetic is needed for guaranteeing that the conversion is correct\n *  and uses a minimum number of digits.  The big number arithmetic has a\n *  fixed maximum size and does not require dynamic allocations.\n *\n *  See: doc/number-conversion.rst.\n */\n\n/* #include duk_internal.h -> already included */\n\n#define DUK__IEEE_DOUBLE_EXP_BIAS  1023\n#define DUK__IEEE_DOUBLE_EXP_MIN   (-1022)   /* biased exp == 0 -> denormal, exp -1022 */\n\n#define DUK__DIGITCHAR(x)  duk_lc_digits[(x)]\n\n/*\n *  Tables generated with util/gennumdigits.py.\n *\n *  duk__str2num_digits_for_radix indicates, for each radix, how many input\n *  digits should be considered significant for string-to-number conversion.\n *  The input is also padded to this many digits to give the Dragon4\n *  conversion enough (apparent) precision to work with.\n *\n *  duk__str2num_exp_limits indicates, for each radix, the radix-specific\n *  minimum/maximum exponent values (for a Dragon4 integer mantissa)\n *  below and above which the number is guaranteed to underflow to zero\n *  or overflow to Infinity.  This allows parsing to keep bigint values\n *  bounded.\n */\n\nDUK_LOCAL const duk_uint8_t duk__str2num_digits_for_radix[] = {\n\t69, 44, 35, 30, 27, 25, 23, 22, 20, 20,    /* 2 to 11 */\n\t20, 19, 19, 18, 18, 17, 17, 17, 16, 16,    /* 12 to 21 */\n\t16, 16, 16, 15, 15, 15, 15, 15, 15, 14,    /* 22 to 31 */\n\t14, 14, 14, 14, 14                         /* 31 to 36 */\n};\n\ntypedef struct {\n\tduk_int16_t upper;\n\tduk_int16_t lower;\n} duk__exp_limits;\n\nDUK_LOCAL const duk__exp_limits duk__str2num_exp_limits[] = {\n\t{ 957, -1147 }, { 605, -725 },  { 479, -575 },  { 414, -496 },\n\t{ 372, -446 },  { 342, -411 },  { 321, -384 },  { 304, -364 },\n\t{ 291, -346 },  { 279, -334 },  { 268, -323 },  { 260, -312 },\n\t{ 252, -304 },  { 247, -296 },  { 240, -289 },  { 236, -283 },\n\t{ 231, -278 },  { 227, -273 },  { 223, -267 },  { 220, -263 },\n\t{ 216, -260 },  { 213, -256 },  { 210, -253 },  { 208, -249 },\n\t{ 205, -246 },  { 203, -244 },  { 201, -241 },  { 198, -239 },\n\t{ 196, -237 },  { 195, -234 },  { 193, -232 },  { 191, -230 },\n\t{ 190, -228 },  { 188, -226 },  { 187, -225 },\n};\n\n/*\n *  Limited functionality bigint implementation.\n *\n *  Restricted to non-negative numbers with less than 32 * DUK__BI_MAX_PARTS bits,\n *  with the caller responsible for ensuring this is never exceeded.  No memory\n *  allocation (except stack) is needed for bigint computation.  Operations\n *  have been tailored for number conversion needs.\n *\n *  Argument order is \"assignment order\", i.e. target first, then arguments:\n *  x <- y * z  -->  duk__bi_mul(x, y, z);\n */\n\n/* This upper value has been experimentally determined; debug build will check\n * bigint size with assertions.\n */\n#define DUK__BI_MAX_PARTS  37  /* 37x32 = 1184 bits */\n\n#if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)\n#define DUK__BI_PRINT(name,x)  duk__bi_print((name),(x))\n#else\n#define DUK__BI_PRINT(name,x)\n#endif\n\n/* Current size is about 152 bytes. */\ntypedef struct {\n\tduk_small_int_t n;\n\tduk_uint32_t v[DUK__BI_MAX_PARTS];  /* low to high */\n} duk__bigint;\n\n#if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)\nDUK_LOCAL void duk__bi_print(const char *name, duk__bigint *x) {\n\t/* Overestimate required size; debug code so not critical to be tight. */\n\tchar buf[DUK__BI_MAX_PARTS * 9 + 64];\n\tchar *p = buf;\n\tduk_small_int_t i;\n\n\t/* No NUL term checks in this debug code. */\n\tp += DUK_SPRINTF(p, \"%p n=%ld\", (void *) x, (long) x->n);\n\tif (x->n == 0) {\n\t\tp += DUK_SPRINTF(p, \" 0\");\n\t}\n\tfor (i = x->n - 1; i >= 0; i--) {\n\t\tp += DUK_SPRINTF(p, \" %08lx\", (unsigned long) x->v[i]);\n\t}\n\n\tDUK_DDD(DUK_DDDPRINT(\"%s: %s\", (const char *) name, (const char *) buf));\n}\n#endif\n\n#if defined(DUK_USE_ASSERTIONS)\nDUK_LOCAL duk_small_int_t duk__bi_is_valid(duk__bigint *x) {\n\treturn (duk_small_int_t)\n\t       ( ((x->n >= 0) && (x->n <= DUK__BI_MAX_PARTS)) /* is valid size */ &&\n\t         ((x->n == 0) || (x->v[x->n - 1] != 0)) /* is normalized */ );\n}\n#endif\n\nDUK_LOCAL void duk__bi_normalize(duk__bigint *x) {\n\tduk_small_int_t i;\n\n\tfor (i = x->n - 1; i >= 0; i--) {\n\t\tif (x->v[i] != 0) {\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t/* Note: if 'x' is zero, x->n becomes 0 here */\n\tx->n = i + 1;\n\tDUK_ASSERT(duk__bi_is_valid(x));\n}\n\n/* x <- y */\nDUK_LOCAL void duk__bi_copy(duk__bigint *x, duk__bigint *y) {\n\tduk_small_int_t n;\n\n\tn = y->n;\n\tx->n = n;\n\tif (n == 0) {\n\t\treturn;\n\t}\n\tDUK_MEMCPY((void *) x->v, (const void *) y->v, (size_t) (sizeof(duk_uint32_t) * (size_t) n));\n}\n\nDUK_LOCAL void duk__bi_set_small(duk__bigint *x, duk_uint32_t v) {\n\tif (v == 0U) {\n\t\tx->n = 0;\n\t} else {\n\t\tx->n = 1;\n\t\tx->v[0] = v;\n\t}\n\tDUK_ASSERT(duk__bi_is_valid(x));\n}\n\n/* Return value: <0  <=>  x < y\n *                0  <=>  x == y\n *               >0  <=>  x > y\n */\nDUK_LOCAL int duk__bi_compare(duk__bigint *x, duk__bigint *y) {\n\tduk_small_int_t i, nx, ny;\n\tduk_uint32_t tx, ty;\n\n\tDUK_ASSERT(duk__bi_is_valid(x));\n\tDUK_ASSERT(duk__bi_is_valid(y));\n\n\tnx = x->n;\n\tny = y->n;\n\tif (nx > ny) {\n\t\tgoto ret_gt;\n\t}\n\tif (nx < ny) {\n\t\tgoto ret_lt;\n\t}\n\tfor (i = nx - 1; i >= 0; i--) {\n\t\ttx = x->v[i];\n\t\tty = y->v[i];\n\n\t\tif (tx > ty) {\n\t\t\tgoto ret_gt;\n\t\t}\n\t\tif (tx < ty) {\n\t\t\tgoto ret_lt;\n\t\t}\n\t}\n\n\treturn 0;\n\n ret_gt:\n\treturn 1;\n\n ret_lt:\n\treturn -1;\n}\n\n/* x <- y + z */\n#if defined(DUK_USE_64BIT_OPS)\nDUK_LOCAL void duk__bi_add(duk__bigint *x, duk__bigint *y, duk__bigint *z) {\n\tduk_uint64_t tmp;\n\tduk_small_int_t i, ny, nz;\n\n\tDUK_ASSERT(duk__bi_is_valid(y));\n\tDUK_ASSERT(duk__bi_is_valid(z));\n\n\tif (z->n > y->n) {\n\t\tduk__bigint *t;\n\t\tt = y; y = z; z = t;\n\t}\n\tDUK_ASSERT(y->n >= z->n);\n\n\tny = y->n; nz = z->n;\n\ttmp = 0U;\n\tfor (i = 0; i < ny; i++) {\n\t\tDUK_ASSERT(i < DUK__BI_MAX_PARTS);\n\t\ttmp += y->v[i];\n\t\tif (i < nz) {\n\t\t\ttmp += z->v[i];\n\t\t}\n\t\tx->v[i] = (duk_uint32_t) (tmp & 0xffffffffUL);\n\t\ttmp = tmp >> 32;\n\t}\n\tif (tmp != 0U) {\n\t\tDUK_ASSERT(i < DUK__BI_MAX_PARTS);\n\t\tx->v[i++] = (duk_uint32_t) tmp;\n\t}\n\tx->n = i;\n\tDUK_ASSERT(x->n <= DUK__BI_MAX_PARTS);\n\n\t/* no need to normalize */\n\tDUK_ASSERT(duk__bi_is_valid(x));\n}\n#else  /* DUK_USE_64BIT_OPS */\nDUK_LOCAL void duk__bi_add(duk__bigint *x, duk__bigint *y, duk__bigint *z) {\n\tduk_uint32_t carry, tmp1, tmp2;\n\tduk_small_int_t i, ny, nz;\n\n\tDUK_ASSERT(duk__bi_is_valid(y));\n\tDUK_ASSERT(duk__bi_is_valid(z));\n\n\tif (z->n > y->n) {\n\t\tduk__bigint *t;\n\t\tt = y; y = z; z = t;\n\t}\n\tDUK_ASSERT(y->n >= z->n);\n\n\tny = y->n; nz = z->n;\n\tcarry = 0U;\n\tfor (i = 0; i < ny; i++) {\n\t\t/* Carry is detected based on wrapping which relies on exact 32-bit\n\t\t * types.\n\t\t */\n\t\tDUK_ASSERT(i < DUK__BI_MAX_PARTS);\n\t\ttmp1 = y->v[i];\n\t\ttmp2 = tmp1;\n\t\tif (i < nz) {\n\t\t\ttmp2 += z->v[i];\n\t\t}\n\n\t\t/* Careful with carry condition:\n\t\t *  - If carry not added: 0x12345678 + 0 + 0xffffffff = 0x12345677 (< 0x12345678)\n\t\t *  - If carry added:     0x12345678 + 1 + 0xffffffff = 0x12345678 (== 0x12345678)\n\t\t */\n\t\tif (carry) {\n\t\t\ttmp2++;\n\t\t\tcarry = (tmp2 <= tmp1 ? 1U : 0U);\n\t\t} else {\n\t\t\tcarry = (tmp2 < tmp1 ? 1U : 0U);\n\t\t}\n\n\t\tx->v[i] = tmp2;\n\t}\n\tif (carry) {\n\t\tDUK_ASSERT(i < DUK__BI_MAX_PARTS);\n\t\tDUK_ASSERT(carry == 1U);\n\t\tx->v[i++] = carry;\n\t}\n\tx->n = i;\n\tDUK_ASSERT(x->n <= DUK__BI_MAX_PARTS);\n\n\t/* no need to normalize */\n\tDUK_ASSERT(duk__bi_is_valid(x));\n}\n#endif  /* DUK_USE_64BIT_OPS */\n\n/* x <- y + z */\nDUK_LOCAL void duk__bi_add_small(duk__bigint *x, duk__bigint *y, duk_uint32_t z) {\n\tduk__bigint tmp;\n\n\tDUK_ASSERT(duk__bi_is_valid(y));\n\n\t/* XXX: this could be optimized; there is only one call site now though */\n\tduk__bi_set_small(&tmp, z);\n\tduk__bi_add(x, y, &tmp);\n\n\tDUK_ASSERT(duk__bi_is_valid(x));\n}\n\n#if 0  /* unused */\n/* x <- x + y, use t as temp */\nDUK_LOCAL void duk__bi_add_copy(duk__bigint *x, duk__bigint *y, duk__bigint *t) {\n\tduk__bi_add(t, x, y);\n\tduk__bi_copy(x, t);\n}\n#endif\n\n/* x <- y - z, require x >= y => z >= 0, i.e. y >= z */\n#if defined(DUK_USE_64BIT_OPS)\nDUK_LOCAL void duk__bi_sub(duk__bigint *x, duk__bigint *y, duk__bigint *z) {\n\tduk_small_int_t i, ny, nz;\n\tduk_uint32_t ty, tz;\n\tduk_int64_t tmp;\n\n\tDUK_ASSERT(duk__bi_is_valid(y));\n\tDUK_ASSERT(duk__bi_is_valid(z));\n\tDUK_ASSERT(duk__bi_compare(y, z) >= 0);\n\tDUK_ASSERT(y->n >= z->n);\n\n\tny = y->n; nz = z->n;\n\ttmp = 0;\n\tfor (i = 0; i < ny; i++) {\n\t\tty = y->v[i];\n\t\tif (i < nz) {\n\t\t\ttz = z->v[i];\n\t\t} else {\n\t\t\ttz = 0;\n\t\t}\n\t\ttmp = (duk_int64_t) ty - (duk_int64_t) tz + tmp;\n\t\tx->v[i] = (duk_uint32_t) ((duk_uint64_t) tmp & 0xffffffffUL);\n\t\ttmp = tmp >> 32;  /* 0 or -1 */\n\t}\n\tDUK_ASSERT(tmp == 0);\n\n\tx->n = i;\n\tduk__bi_normalize(x);  /* need to normalize, may even cancel to 0 */\n\tDUK_ASSERT(duk__bi_is_valid(x));\n}\n#else\nDUK_LOCAL void duk__bi_sub(duk__bigint *x, duk__bigint *y, duk__bigint *z) {\n\tduk_small_int_t i, ny, nz;\n\tduk_uint32_t tmp1, tmp2, borrow;\n\n\tDUK_ASSERT(duk__bi_is_valid(y));\n\tDUK_ASSERT(duk__bi_is_valid(z));\n\tDUK_ASSERT(duk__bi_compare(y, z) >= 0);\n\tDUK_ASSERT(y->n >= z->n);\n\n\tny = y->n; nz = z->n;\n\tborrow = 0U;\n\tfor (i = 0; i < ny; i++) {\n\t\t/* Borrow is detected based on wrapping which relies on exact 32-bit\n\t\t * types.\n\t\t */\n\t\ttmp1 = y->v[i];\n\t\ttmp2 = tmp1;\n\t\tif (i < nz) {\n\t\t\ttmp2 -= z->v[i];\n\t\t}\n\n\t\t/* Careful with borrow condition:\n\t\t *  - If borrow not subtracted: 0x12345678 - 0 - 0xffffffff = 0x12345679 (> 0x12345678)\n\t\t *  - If borrow subtracted:     0x12345678 - 1 - 0xffffffff = 0x12345678 (== 0x12345678)\n\t\t */\n\t\tif (borrow) {\n\t\t\ttmp2--;\n\t\t\tborrow = (tmp2 >= tmp1 ? 1U : 0U);\n\t\t} else {\n\t\t\tborrow = (tmp2 > tmp1 ? 1U : 0U);\n\t\t}\n\n\t\tx->v[i] = tmp2;\n\t}\n\tDUK_ASSERT(borrow == 0U);\n\n\tx->n = i;\n\tduk__bi_normalize(x);  /* need to normalize, may even cancel to 0 */\n\tDUK_ASSERT(duk__bi_is_valid(x));\n}\n#endif\n\n#if 0  /* unused */\n/* x <- y - z */\nDUK_LOCAL void duk__bi_sub_small(duk__bigint *x, duk__bigint *y, duk_uint32_t z) {\n\tduk__bigint tmp;\n\n\tDUK_ASSERT(duk__bi_is_valid(y));\n\n\t/* XXX: this could be optimized */\n\tduk__bi_set_small(&tmp, z);\n\tduk__bi_sub(x, y, &tmp);\n\n\tDUK_ASSERT(duk__bi_is_valid(x));\n}\n#endif\n\n/* x <- x - y, use t as temp */\nDUK_LOCAL void duk__bi_sub_copy(duk__bigint *x, duk__bigint *y, duk__bigint *t) {\n\tduk__bi_sub(t, x, y);\n\tduk__bi_copy(x, t);\n}\n\n/* x <- y * z */\nDUK_LOCAL void duk__bi_mul(duk__bigint *x, duk__bigint *y, duk__bigint *z) {\n\tduk_small_int_t i, j, nx, nz;\n\n\tDUK_ASSERT(duk__bi_is_valid(y));\n\tDUK_ASSERT(duk__bi_is_valid(z));\n\n\tnx = y->n + z->n;  /* max possible */\n\tDUK_ASSERT(nx <= DUK__BI_MAX_PARTS);\n\n\tif (nx == 0) {\n\t\t/* Both inputs are zero; cases where only one is zero can go\n\t\t * through main algorithm.\n\t\t */\n\t\tx->n = 0;\n\t\treturn;\n\t}\n\n\tDUK_MEMZERO((void *) x->v, (size_t) (sizeof(duk_uint32_t) * (size_t) nx));\n\tx->n = nx;\n\n\tnz = z->n;\n\tfor (i = 0; i < y->n; i++) {\n#if defined(DUK_USE_64BIT_OPS)\n\t\tduk_uint64_t tmp = 0U;\n\t\tfor (j = 0; j < nz; j++) {\n\t\t\ttmp += (duk_uint64_t) y->v[i] * (duk_uint64_t) z->v[j] + x->v[i+j];\n\t\t\tx->v[i+j] = (duk_uint32_t) (tmp & 0xffffffffUL);\n\t\t\ttmp = tmp >> 32;\n\t\t}\n\t\tif (tmp > 0) {\n\t\t\tDUK_ASSERT(i + j < nx);\n\t\t\tDUK_ASSERT(i + j < DUK__BI_MAX_PARTS);\n\t\t\tDUK_ASSERT(x->v[i+j] == 0U);\n\t\t\tx->v[i+j] = (duk_uint32_t) tmp;\n\t\t}\n#else\n\t\t/*\n\t\t *  Multiply + add + carry for 32-bit components using only 16x16->32\n\t\t *  multiplies and carry detection based on unsigned overflow.\n\t\t *\n\t\t *    1st mult, 32-bit: (A*2^16 + B)\n\t\t *    2nd mult, 32-bit: (C*2^16 + D)\n\t\t *    3rd add, 32-bit: E\n\t\t *    4th add, 32-bit: F\n\t\t *\n\t\t *      (AC*2^16 + B) * (C*2^16 + D) + E + F\n\t\t *    = AC*2^32 + AD*2^16 + BC*2^16 + BD + E + F\n\t\t *    = AC*2^32 + (AD + BC)*2^16 + (BD + E + F)\n\t\t *    = AC*2^32 + AD*2^16 + BC*2^16 + (BD + E + F)\n\t\t */\n\t\tduk_uint32_t a, b, c, d, e, f;\n\t\tduk_uint32_t r, s, t;\n\n\t\ta = y->v[i]; b = a & 0xffffUL; a = a >> 16;\n\n\t\tf = 0;\n\t\tfor (j = 0; j < nz; j++) {\n\t\t\tc = z->v[j]; d = c & 0xffffUL; c = c >> 16;\n\t\t\te = x->v[i+j];\n\n\t\t\t/* build result as: (r << 32) + s: start with (BD + E + F) */\n\t\t\tr = 0;\n\t\t\ts = b * d;\n\n\t\t\t/* add E */\n\t\t\tt = s + e;\n\t\t\tif (t < s) { r++; }  /* carry */\n\t\t\ts = t;\n\n\t\t\t/* add F */\n\t\t\tt = s + f;\n\t\t\tif (t < s) { r++; }  /* carry */\n\t\t\ts = t;\n\n\t\t\t/* add BC*2^16 */\n\t\t\tt = b * c;\n\t\t\tr += (t >> 16);\n\t\t\tt = s + ((t & 0xffffUL) << 16);\n\t\t\tif (t < s) { r++; }  /* carry */\n\t\t\ts = t;\n\n\t\t\t/* add AD*2^16 */\n\t\t\tt = a * d;\n\t\t\tr += (t >> 16);\n\t\t\tt = s + ((t & 0xffffUL) << 16);\n\t\t\tif (t < s) { r++; }  /* carry */\n\t\t\ts = t;\n\n\t\t\t/* add AC*2^32 */\n\t\t\tt = a * c;\n\t\t\tr += t;\n\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"ab=%08lx cd=%08lx ef=%08lx -> rs=%08lx %08lx\",\n\t\t\t                     (unsigned long) y->v[i], (unsigned long) z->v[j],\n\t\t\t                     (unsigned long) x->v[i+j], (unsigned long) r,\n\t\t\t                     (unsigned long) s));\n\n\t\t\tx->v[i+j] = s;\n\t\t\tf = r;\n\t\t}\n\t\tif (f > 0U) {\n\t\t\tDUK_ASSERT(i + j < nx);\n\t\t\tDUK_ASSERT(i + j < DUK__BI_MAX_PARTS);\n\t\t\tDUK_ASSERT(x->v[i+j] == 0U);\n\t\t\tx->v[i+j] = (duk_uint32_t) f;\n\t\t}\n#endif  /* DUK_USE_64BIT_OPS */\n\t}\n\n\tduk__bi_normalize(x);\n\tDUK_ASSERT(duk__bi_is_valid(x));\n}\n\n/* x <- y * z */\nDUK_LOCAL void duk__bi_mul_small(duk__bigint *x, duk__bigint *y, duk_uint32_t z) {\n\tduk__bigint tmp;\n\n\tDUK_ASSERT(duk__bi_is_valid(y));\n\n\t/* XXX: this could be optimized */\n\tduk__bi_set_small(&tmp, z);\n\tduk__bi_mul(x, y, &tmp);\n\n\tDUK_ASSERT(duk__bi_is_valid(x));\n}\n\n/* x <- x * y, use t as temp */\nDUK_LOCAL void duk__bi_mul_copy(duk__bigint *x, duk__bigint *y, duk__bigint *t) {\n\tduk__bi_mul(t, x, y);\n\tduk__bi_copy(x, t);\n}\n\n/* x <- x * y, use t as temp */\nDUK_LOCAL void duk__bi_mul_small_copy(duk__bigint *x, duk_uint32_t y, duk__bigint *t) {\n\tduk__bi_mul_small(t, x, y);\n\tduk__bi_copy(x, t);\n}\n\nDUK_LOCAL int duk__bi_is_even(duk__bigint *x) {\n\tDUK_ASSERT(duk__bi_is_valid(x));\n\treturn (x->n == 0) || ((x->v[0] & 0x01) == 0);\n}\n\nDUK_LOCAL int duk__bi_is_zero(duk__bigint *x) {\n\tDUK_ASSERT(duk__bi_is_valid(x));\n\treturn (x->n == 0);  /* this is the case for normalized numbers */\n}\n\n/* Bigint is 2^52.  Used to detect normalized IEEE double mantissa values\n * which are at the lowest edge (next floating point value downwards has\n * a different exponent).  The lowest mantissa has the form:\n *\n *     1000........000    (52 zeroes; only \"hidden bit\" is set)\n */\nDUK_LOCAL duk_small_int_t duk__bi_is_2to52(duk__bigint *x) {\n\tDUK_ASSERT(duk__bi_is_valid(x));\n\treturn (duk_small_int_t)\n\t        (x->n == 2) && (x->v[0] == 0U) && (x->v[1] == (1U << (52-32)));\n}\n\n/* x <- (1<<y) */\nDUK_LOCAL void duk__bi_twoexp(duk__bigint *x, duk_small_int_t y) {\n\tduk_small_int_t n, r;\n\n\tn = (y / 32) + 1;\n\tDUK_ASSERT(n > 0);\n\tr = y % 32;\n\tDUK_MEMZERO((void *) x->v, sizeof(duk_uint32_t) * (size_t) n);\n\tx->n = n;\n\tx->v[n - 1] = (((duk_uint32_t) 1) << r);\n}\n\n/* x <- b^y; use t1 and t2 as temps */\nDUK_LOCAL void duk__bi_exp_small(duk__bigint *x, duk_small_int_t b, duk_small_int_t y, duk__bigint *t1, duk__bigint *t2) {\n\t/* Fast path the binary case */\n\n\tDUK_ASSERT(x != t1 && x != t2 && t1 != t2);  /* distinct bignums, easy mistake to make */\n\tDUK_ASSERT(b >= 0);\n\tDUK_ASSERT(y >= 0);\n\n\tif (b == 2) {\n\t\tduk__bi_twoexp(x, y);\n\t\treturn;\n\t}\n\n\t/* http://en.wikipedia.org/wiki/Exponentiation_by_squaring */\n\n\tDUK_DDD(DUK_DDDPRINT(\"exp_small: b=%ld, y=%ld\", (long) b, (long) y));\n\n\tduk__bi_set_small(x, 1);\n\tduk__bi_set_small(t1, (duk_uint32_t) b);\n\tfor (;;) {\n\t\t/* Loop structure ensures that we don't compute t1^2 unnecessarily\n\t\t * on the final round, as that might create a bignum exceeding the\n\t\t * current DUK__BI_MAX_PARTS limit.\n\t\t */\n\t\tif (y & 0x01) {\n\t\t\tduk__bi_mul_copy(x, t1, t2);\n\t\t}\n\t\ty = y >> 1;\n\t\tif (y == 0) {\n\t\t\tbreak;\n\t\t}\n\t\tduk__bi_mul_copy(t1, t1, t2);\n\t}\n\n\tDUK__BI_PRINT(\"exp_small result\", x);\n}\n\n/*\n *  A Dragon4 number-to-string variant, based on:\n *\n *    Guy L. Steele Jr., Jon L. White: \"How to Print Floating-Point Numbers\n *    Accurately\"\n *\n *    Robert G. Burger, R. Kent Dybvig: \"Printing Floating-Point Numbers\n *    Quickly and Accurately\"\n *\n *  The current algorithm is based on Figure 1 of the Burger-Dybvig paper,\n *  i.e. the base implementation without logarithm estimation speedups\n *  (these would increase code footprint considerably).  Fixed-format output\n *  does not follow the suggestions in the paper; instead, we generate an\n *  extra digit and round-with-carry.\n *\n *  The same algorithm is used for number parsing (with b=10 and B=2)\n *  by generating one extra digit and doing rounding manually.\n *\n *  See doc/number-conversion.rst for limitations.\n */\n\n/* Maximum number of digits generated. */\n#define DUK__MAX_OUTPUT_DIGITS          1040  /* (Number.MAX_VALUE).toString(2).length == 1024, + slack */\n\n/* Maximum number of characters in formatted value. */\n#define DUK__MAX_FORMATTED_LENGTH       1040  /* (-Number.MAX_VALUE).toString(2).length == 1025, + slack */\n\n/* Number and (minimum) size of bigints in the nc_ctx structure. */\n#define DUK__NUMCONV_CTX_NUM_BIGINTS    7\n#define DUK__NUMCONV_CTX_BIGINTS_SIZE   (sizeof(duk__bigint) * DUK__NUMCONV_CTX_NUM_BIGINTS)\n\ntypedef struct {\n\t/* Currently about 7*152 = 1064 bytes.  The space for these\n\t * duk__bigints is used also as a temporary buffer for generating\n\t * the final string.  This is a bit awkard; a union would be\n\t * more correct.\n\t */\n\tduk__bigint f, r, s, mp, mm, t1, t2;\n\n\tduk_small_int_t is_s2n;        /* if 1, doing a string-to-number; else doing a number-to-string */\n\tduk_small_int_t is_fixed;      /* if 1, doing a fixed format output (not free format) */\n\tduk_small_int_t req_digits;    /* requested number of output digits; 0 = free-format */\n\tduk_small_int_t abs_pos;       /* digit position is absolute, not relative */\n\tduk_small_int_t e;             /* exponent for 'f' */\n\tduk_small_int_t b;             /* input radix */\n\tduk_small_int_t B;             /* output radix */\n\tduk_small_int_t k;             /* see algorithm */\n\tduk_small_int_t low_ok;        /* see algorithm */\n\tduk_small_int_t high_ok;       /* see algorithm */\n\tduk_small_int_t unequal_gaps;  /* m+ != m- (very rarely) */\n\n\t/* Buffer used for generated digits, values are in the range [0,B-1]. */\n\tduk_uint8_t digits[DUK__MAX_OUTPUT_DIGITS];\n\tduk_small_int_t count;  /* digit count */\n} duk__numconv_stringify_ctx;\n\n/* Note: computes with 'idx' in assertions, so caller beware.\n * 'idx' is preincremented, i.e. '1' on first call, because it\n * is more convenient for the caller.\n */\n#define DUK__DRAGON4_OUTPUT_PREINC(nc_ctx,preinc_idx,x)  do { \\\n\t\tDUK_ASSERT((preinc_idx) - 1 >= 0); \\\n\t\tDUK_ASSERT((preinc_idx) - 1 < DUK__MAX_OUTPUT_DIGITS); \\\n\t\t((nc_ctx)->digits[(preinc_idx) - 1]) = (duk_uint8_t) (x); \\\n\t} while (0)\n\nDUK_LOCAL duk_size_t duk__dragon4_format_uint32(duk_uint8_t *buf, duk_uint32_t x, duk_small_int_t radix) {\n\tduk_uint8_t *p;\n\tduk_size_t len;\n\tduk_small_int_t dig;\n\tduk_uint32_t t;\n\n\tDUK_ASSERT(radix >= 2 && radix <= 36);\n\n\t/* A 32-bit unsigned integer formats to at most 32 digits (the\n\t * worst case happens with radix == 2).  Output the digits backwards,\n\t * and use a memmove() to get them in the right place.\n\t */\n\n\tp = buf + 32;\n\tfor (;;) {\n\t\tt = x / (duk_uint32_t) radix;\n\t\tdig = (duk_small_int_t) (x - t * (duk_uint32_t) radix);\n\t\tx = t;\n\n\t\tDUK_ASSERT(dig >= 0 && dig < 36);\n\t\t*(--p) = DUK__DIGITCHAR(dig);\n\n\t\tif (x == 0) {\n\t\t\tbreak;\n\t\t}\n\t}\n\tlen = (duk_size_t) ((buf + 32) - p);\n\n\tDUK_MEMMOVE((void *) buf, (const void *) p, (size_t) len);\n\n\treturn len;\n}\n\nDUK_LOCAL void duk__dragon4_prepare(duk__numconv_stringify_ctx *nc_ctx) {\n\tduk_small_int_t lowest_mantissa;\n\n#if 1\n\t/* Assume IEEE round-to-even, so that shorter encoding can be used\n\t * when round-to-even would produce correct result.  By removing\n\t * this check (and having low_ok == high_ok == 0) the results would\n\t * still be accurate but in some cases longer than necessary.\n\t */\n\tif (duk__bi_is_even(&nc_ctx->f)) {\n\t\tDUK_DDD(DUK_DDDPRINT(\"f is even\"));\n\t\tnc_ctx->low_ok = 1;\n\t\tnc_ctx->high_ok = 1;\n\t} else {\n\t\tDUK_DDD(DUK_DDDPRINT(\"f is odd\"));\n\t\tnc_ctx->low_ok = 0;\n\t\tnc_ctx->high_ok = 0;\n\t}\n#else\n\t/* Note: not honoring round-to-even should work but now generates incorrect\n\t * results.  For instance, 1e23 serializes to \"a000...\", i.e. the first digit\n\t * equals the radix (10).  Scaling stops one step too early in this case.\n\t * Don't know why this is the case, but since this code path is unused, it\n\t * doesn't matter.\n\t */\n\tnc_ctx->low_ok = 0;\n\tnc_ctx->high_ok = 0;\n#endif\n\n\t/* For string-to-number, pretend we never have the lowest mantissa as there\n\t * is no natural \"precision\" for inputs.  Having lowest_mantissa == 0, we'll\n\t * fall into the base cases for both e >= 0 and e < 0.\n\t */\n\tif (nc_ctx->is_s2n) {\n\t\tlowest_mantissa = 0;\n\t} else {\n\t\tlowest_mantissa = duk__bi_is_2to52(&nc_ctx->f);\n\t}\n\n\tnc_ctx->unequal_gaps = 0;\n\tif (nc_ctx->e >= 0) {\n\t\t/* exponent non-negative (and thus not minimum exponent) */\n\n\t\tif (lowest_mantissa) {\n\t\t\t/* (>= e 0) AND (= f (expt b (- p 1)))\n\t\t\t *\n\t\t\t * be <- (expt b e) == b^e\n\t\t\t * be1 <- (* be b) == (expt b (+ e 1)) == b^(e+1)\n\t\t\t * r <- (* f be1 2) == 2 * f * b^(e+1)    [if b==2 -> f * b^(e+2)]\n\t\t\t * s <- (* b 2)                           [if b==2 -> 4]\n\t\t\t * m+ <- be1 == b^(e+1)\n\t\t\t * m- <- be == b^e\n\t\t\t * k <- 0\n\t\t\t * B <- B\n\t\t\t * low_ok <- round\n\t\t\t * high_ok <- round\n\t\t\t */\n\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"non-negative exponent (not smallest exponent); \"\n\t\t\t                     \"lowest mantissa value for this exponent -> \"\n\t\t\t                     \"unequal gaps\"));\n\n\t\t\tduk__bi_exp_small(&nc_ctx->mm, nc_ctx->b, nc_ctx->e, &nc_ctx->t1, &nc_ctx->t2);  /* mm <- b^e */\n\t\t\tduk__bi_mul_small(&nc_ctx->mp, &nc_ctx->mm, (duk_uint32_t) nc_ctx->b);           /* mp <- b^(e+1) */\n\t\t\tduk__bi_mul_small(&nc_ctx->t1, &nc_ctx->f, 2);\n\t\t\tduk__bi_mul(&nc_ctx->r, &nc_ctx->t1, &nc_ctx->mp);              /* r <- (2 * f) * b^(e+1) */\n\t\t\tduk__bi_set_small(&nc_ctx->s, (duk_uint32_t) (nc_ctx->b * 2));  /* s <- 2 * b */\n\t\t\tnc_ctx->unequal_gaps = 1;\n\t\t} else {\n\t\t\t/* (>= e 0) AND (not (= f (expt b (- p 1))))\n\t\t\t *\n\t\t\t * be <- (expt b e) == b^e\n\t\t\t * r <- (* f be 2) == 2 * f * b^e    [if b==2 -> f * b^(e+1)]\n\t\t\t * s <- 2\n\t\t\t * m+ <- be == b^e\n\t\t\t * m- <- be == b^e\n\t\t\t * k <- 0\n\t\t\t * B <- B\n\t\t\t * low_ok <- round\n\t\t\t * high_ok <- round\n\t\t\t */\n\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"non-negative exponent (not smallest exponent); \"\n\t\t\t                     \"not lowest mantissa for this exponent -> \"\n\t\t\t                     \"equal gaps\"));\n\n\t\t\tduk__bi_exp_small(&nc_ctx->mm, nc_ctx->b, nc_ctx->e, &nc_ctx->t1, &nc_ctx->t2);  /* mm <- b^e */\n\t\t\tduk__bi_copy(&nc_ctx->mp, &nc_ctx->mm);                /* mp <- b^e */\n\t\t\tduk__bi_mul_small(&nc_ctx->t1, &nc_ctx->f, 2);\n\t\t\tduk__bi_mul(&nc_ctx->r, &nc_ctx->t1, &nc_ctx->mp);     /* r <- (2 * f) * b^e */\n\t\t\tduk__bi_set_small(&nc_ctx->s, 2);                      /* s <- 2 */\n\t\t}\n\t} else {\n\t\t/* When doing string-to-number, lowest_mantissa is always 0 so\n\t\t * the exponent check, while incorrect, won't matter.\n\t\t */\n\t\tif (nc_ctx->e > DUK__IEEE_DOUBLE_EXP_MIN /*not minimum exponent*/ &&\n\t\t    lowest_mantissa /* lowest mantissa for this exponent*/) {\n\t\t\t/* r <- (* f b 2)                                [if b==2 -> (* f 4)]\n\t\t\t * s <- (* (expt b (- 1 e)) 2) == b^(1-e) * 2    [if b==2 -> b^(2-e)]\n\t\t\t * m+ <- b == 2\n\t\t\t * m- <- 1\n\t\t\t * k <- 0\n\t\t\t * B <- B\n\t\t\t * low_ok <- round\n\t\t\t * high_ok <- round\n\t\t\t */\n\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"negative exponent; not minimum exponent and \"\n\t\t\t                     \"lowest mantissa for this exponent -> \"\n\t\t\t                     \"unequal gaps\"));\n\n\t\t\tduk__bi_mul_small(&nc_ctx->r, &nc_ctx->f, (duk_uint32_t) (nc_ctx->b * 2));  /* r <- (2 * b) * f */\n\t\t\tduk__bi_exp_small(&nc_ctx->t1, nc_ctx->b, 1 - nc_ctx->e, &nc_ctx->s, &nc_ctx->t2);  /* NB: use 's' as temp on purpose */\n\t\t\tduk__bi_mul_small(&nc_ctx->s, &nc_ctx->t1, 2);             /* s <- b^(1-e) * 2 */\n\t\t\tduk__bi_set_small(&nc_ctx->mp, 2);\n\t\t\tduk__bi_set_small(&nc_ctx->mm, 1);\n\t\t\tnc_ctx->unequal_gaps = 1;\n\t\t} else {\n\t\t\t/* r <- (* f 2)\n\t\t\t * s <- (* (expt b (- e)) 2) == b^(-e) * 2    [if b==2 -> b^(1-e)]\n\t\t\t * m+ <- 1\n\t\t\t * m- <- 1\n\t\t\t * k <- 0\n\t\t\t * B <- B\n\t\t\t * low_ok <- round\n\t\t\t * high_ok <- round\n\t\t\t */\n\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"negative exponent; minimum exponent or not \"\n\t\t\t                     \"lowest mantissa for this exponent -> \"\n\t\t\t                     \"equal gaps\"));\n\n\t\t\tduk__bi_mul_small(&nc_ctx->r, &nc_ctx->f, 2);            /* r <- 2 * f */\n\t\t\tduk__bi_exp_small(&nc_ctx->t1, nc_ctx->b, -nc_ctx->e, &nc_ctx->s, &nc_ctx->t2);  /* NB: use 's' as temp on purpose */\n\t\t\tduk__bi_mul_small(&nc_ctx->s, &nc_ctx->t1, 2);           /* s <- b^(-e) * 2 */\n\t\t\tduk__bi_set_small(&nc_ctx->mp, 1);\n\t\t\tduk__bi_set_small(&nc_ctx->mm, 1);\n\t\t}\n\t}\n}\n\nDUK_LOCAL void duk__dragon4_scale(duk__numconv_stringify_ctx *nc_ctx) {\n\tduk_small_int_t k = 0;\n\n\t/* This is essentially the 'scale' algorithm, with recursion removed.\n\t * Note that 'k' is either correct immediately, or will move in one\n\t * direction in the loop.  There's no need to do the low/high checks\n\t * on every round (like the Scheme algorithm does).\n\t *\n\t * The scheme algorithm finds 'k' and updates 's' simultaneously,\n\t * while the logical algorithm finds 'k' with 's' having its initial\n\t * value, after which 's' is updated separately (see the Burger-Dybvig\n\t * paper, Section 3.1, steps 2 and 3).\n\t *\n\t * The case where m+ == m- (almost always) is optimized for, because\n\t * it reduces the bigint operations considerably and almost always\n\t * applies.  The scale loop only needs to work with m+, so this works.\n\t */\n\n\t/* XXX: this algorithm could be optimized quite a lot by using e.g.\n\t * a logarithm based estimator for 'k' and performing B^n multiplication\n\t * using a lookup table or using some bit-representation based exp\n\t * algorithm.  Currently we just loop, with significant performance\n\t * impact for very large and very small numbers.\n\t */\n\n\tDUK_DDD(DUK_DDDPRINT(\"scale: B=%ld, low_ok=%ld, high_ok=%ld\",\n\t                     (long) nc_ctx->B, (long) nc_ctx->low_ok, (long) nc_ctx->high_ok));\n\tDUK__BI_PRINT(\"r(init)\", &nc_ctx->r);\n\tDUK__BI_PRINT(\"s(init)\", &nc_ctx->s);\n\tDUK__BI_PRINT(\"mp(init)\", &nc_ctx->mp);\n\tDUK__BI_PRINT(\"mm(init)\", &nc_ctx->mm);\n\n\tfor (;;) {\n\t\tDUK_DDD(DUK_DDDPRINT(\"scale loop (inc k), k=%ld\", (long) k));\n\t\tDUK__BI_PRINT(\"r\", &nc_ctx->r);\n\t\tDUK__BI_PRINT(\"s\", &nc_ctx->s);\n\t\tDUK__BI_PRINT(\"m+\", &nc_ctx->mp);\n\t\tDUK__BI_PRINT(\"m-\", &nc_ctx->mm);\n\n\t\tduk__bi_add(&nc_ctx->t1, &nc_ctx->r, &nc_ctx->mp);  /* t1 = (+ r m+) */\n\t\tif (duk__bi_compare(&nc_ctx->t1, &nc_ctx->s) >= (nc_ctx->high_ok ? 0 : 1)) {\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"k is too low\"));\n\t\t\t/* r <- r\n\t\t\t * s <- (* s B)\n\t\t\t * m+ <- m+\n\t\t\t * m- <- m-\n\t\t\t * k <- (+ k 1)\n\t\t\t */\n\n\t\t\tduk__bi_mul_small_copy(&nc_ctx->s, (duk_uint32_t) nc_ctx->B, &nc_ctx->t1);\n\t\t\tk++;\n\t\t} else {\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t/* k > 0 -> k was too low, and cannot be too high */\n\tif (k > 0) {\n\t\tgoto skip_dec_k;\n\t}\n\n\tfor (;;) {\n\t\tDUK_DDD(DUK_DDDPRINT(\"scale loop (dec k), k=%ld\", (long) k));\n\t\tDUK__BI_PRINT(\"r\", &nc_ctx->r);\n\t\tDUK__BI_PRINT(\"s\", &nc_ctx->s);\n\t\tDUK__BI_PRINT(\"m+\", &nc_ctx->mp);\n\t\tDUK__BI_PRINT(\"m-\", &nc_ctx->mm);\n\n\t\tduk__bi_add(&nc_ctx->t1, &nc_ctx->r, &nc_ctx->mp);  /* t1 = (+ r m+) */\n\t\tduk__bi_mul_small(&nc_ctx->t2, &nc_ctx->t1, (duk_uint32_t) nc_ctx->B);   /* t2 = (* (+ r m+) B) */\n\t\tif (duk__bi_compare(&nc_ctx->t2, &nc_ctx->s) <= (nc_ctx->high_ok ? -1 : 0)) {\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"k is too high\"));\n\t\t\t/* r <- (* r B)\n\t\t\t * s <- s\n\t\t\t * m+ <- (* m+ B)\n\t\t\t * m- <- (* m- B)\n\t\t\t * k <- (- k 1)\n\t\t\t */\n\t\t\tduk__bi_mul_small_copy(&nc_ctx->r, (duk_uint32_t) nc_ctx->B, &nc_ctx->t1);\n\t\t\tduk__bi_mul_small_copy(&nc_ctx->mp, (duk_uint32_t) nc_ctx->B, &nc_ctx->t1);\n\t\t\tif (nc_ctx->unequal_gaps) {\n\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"m+ != m- -> need to update m- too\"));\n\t\t\t\tduk__bi_mul_small_copy(&nc_ctx->mm, (duk_uint32_t) nc_ctx->B, &nc_ctx->t1);\n\t\t\t}\n\t\t\tk--;\n\t\t} else {\n\t\t\tbreak;\n\t\t}\n\t}\n\n skip_dec_k:\n\n\tif (!nc_ctx->unequal_gaps) {\n\t\tDUK_DDD(DUK_DDDPRINT(\"equal gaps, copy m- from m+\"));\n\t\tduk__bi_copy(&nc_ctx->mm, &nc_ctx->mp);  /* mm <- mp */\n\t}\n\tnc_ctx->k = k;\n\n\tDUK_DDD(DUK_DDDPRINT(\"final k: %ld\", (long) k));\n\tDUK__BI_PRINT(\"r(final)\", &nc_ctx->r);\n\tDUK__BI_PRINT(\"s(final)\", &nc_ctx->s);\n\tDUK__BI_PRINT(\"mp(final)\", &nc_ctx->mp);\n\tDUK__BI_PRINT(\"mm(final)\", &nc_ctx->mm);\n}\n\nDUK_LOCAL void duk__dragon4_generate(duk__numconv_stringify_ctx *nc_ctx) {\n\tduk_small_int_t tc1, tc2;    /* terminating conditions */\n\tduk_small_int_t d;           /* current digit */\n\tduk_small_int_t count = 0;   /* digit count */\n\n\t/*\n\t *  Digit generation loop.\n\t *\n\t *  Different termination conditions:\n\t *\n\t *    1. Free format output.  Terminate when shortest accurate\n\t *       representation found.\n\t *\n\t *    2. Fixed format output, with specific number of digits.\n\t *       Ignore termination conditions, terminate when digits\n\t *       generated.  Caller requests an extra digit and rounds.\n\t *\n\t *    3. Fixed format output, with a specific absolute cut-off\n\t *       position (e.g. 10 digits after decimal point).  Note\n\t *       that we always generate at least one digit, even if\n\t *       the digit is below the cut-off point already.\n\t */\n\n\tfor (;;) {\n\t\tDUK_DDD(DUK_DDDPRINT(\"generate loop, count=%ld, k=%ld, B=%ld, low_ok=%ld, high_ok=%ld\",\n\t\t                     (long) count, (long) nc_ctx->k, (long) nc_ctx->B,\n\t\t                     (long) nc_ctx->low_ok, (long) nc_ctx->high_ok));\n\t\tDUK__BI_PRINT(\"r\", &nc_ctx->r);\n\t\tDUK__BI_PRINT(\"s\", &nc_ctx->s);\n\t\tDUK__BI_PRINT(\"m+\", &nc_ctx->mp);\n\t\tDUK__BI_PRINT(\"m-\", &nc_ctx->mm);\n\n\t\t/* (quotient-remainder (* r B) s) using a dummy subtraction loop */\n\t\tduk__bi_mul_small(&nc_ctx->t1, &nc_ctx->r, (duk_uint32_t) nc_ctx->B);       /* t1 <- (* r B) */\n\t\td = 0;\n\t\tfor (;;) {\n\t\t\tif (duk__bi_compare(&nc_ctx->t1, &nc_ctx->s) < 0) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tduk__bi_sub_copy(&nc_ctx->t1, &nc_ctx->s, &nc_ctx->t2);  /* t1 <- t1 - s */\n\t\t\td++;\n\t\t}\n\t\tduk__bi_copy(&nc_ctx->r, &nc_ctx->t1);  /* r <- (remainder (* r B) s) */\n\t\t                                        /* d <- (quotient (* r B) s)   (in range 0...B-1) */\n\t\tDUK_DDD(DUK_DDDPRINT(\"-> d(quot)=%ld\", (long) d));\n\t\tDUK__BI_PRINT(\"r(rem)\", &nc_ctx->r);\n\n\t\tduk__bi_mul_small_copy(&nc_ctx->mp, (duk_uint32_t) nc_ctx->B, &nc_ctx->t2); /* m+ <- (* m+ B) */\n\t\tduk__bi_mul_small_copy(&nc_ctx->mm, (duk_uint32_t) nc_ctx->B, &nc_ctx->t2); /* m- <- (* m- B) */\n\t\tDUK__BI_PRINT(\"mp(upd)\", &nc_ctx->mp);\n\t\tDUK__BI_PRINT(\"mm(upd)\", &nc_ctx->mm);\n\n\t\t/* Terminating conditions.  For fixed width output, we just ignore the\n\t\t * terminating conditions (and pretend that tc1 == tc2 == false).  The\n\t\t * the current shortcut for fixed-format output is to generate a few\n\t\t * extra digits and use rounding (with carry) to finish the output.\n\t\t */\n\n\t\tif (nc_ctx->is_fixed == 0) {\n\t\t\t/* free-form */\n\t\t\ttc1 = (duk__bi_compare(&nc_ctx->r, &nc_ctx->mm) <= (nc_ctx->low_ok ? 0 : -1));\n\n\t\t\tduk__bi_add(&nc_ctx->t1, &nc_ctx->r, &nc_ctx->mp);  /* t1 <- (+ r m+) */\n\t\t\ttc2 = (duk__bi_compare(&nc_ctx->t1, &nc_ctx->s) >= (nc_ctx->high_ok ? 0 : 1));\n\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"tc1=%ld, tc2=%ld\", (long) tc1, (long) tc2));\n\t\t} else {\n\t\t\t/* fixed-format */\n\t\t\ttc1 = 0;\n\t\t\ttc2 = 0;\n\t\t}\n\n\t\t/* Count is incremented before DUK__DRAGON4_OUTPUT_PREINC() call\n\t\t * on purpose, which is taken into account by the macro.\n\t\t */\n\t\tcount++;\n\n\t\tif (tc1) {\n\t\t\tif (tc2) {\n\t\t\t\t/* tc1 = true, tc2 = true */\n\t\t\t\tduk__bi_mul_small(&nc_ctx->t1, &nc_ctx->r, 2);\n\t\t\t\tif (duk__bi_compare(&nc_ctx->t1, &nc_ctx->s) < 0) {  /* (< (* r 2) s) */\n\t\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"tc1=true, tc2=true, 2r > s: output d --> %ld (k=%ld)\",\n\t\t\t\t\t                     (long) d, (long) nc_ctx->k));\n\t\t\t\t\tDUK__DRAGON4_OUTPUT_PREINC(nc_ctx, count, d);\n\t\t\t\t} else {\n\t\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"tc1=true, tc2=true, 2r <= s: output d+1 --> %ld (k=%ld)\",\n\t\t\t\t\t                     (long) (d + 1), (long) nc_ctx->k));\n\t\t\t\t\tDUK__DRAGON4_OUTPUT_PREINC(nc_ctx, count, d + 1);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t} else {\n\t\t\t\t/* tc1 = true, tc2 = false */\n\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"tc1=true, tc2=false: output d --> %ld (k=%ld)\",\n\t\t\t\t                     (long) d, (long) nc_ctx->k));\n\t\t\t\tDUK__DRAGON4_OUTPUT_PREINC(nc_ctx, count, d);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t} else {\n\t\t\tif (tc2) {\n\t\t\t\t/* tc1 = false, tc2 = true */\n\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"tc1=false, tc2=true: output d+1 --> %ld (k=%ld)\",\n\t\t\t\t                     (long) (d + 1), (long) nc_ctx->k));\n\t\t\t\tDUK__DRAGON4_OUTPUT_PREINC(nc_ctx, count, d + 1);\n\t\t\t\tbreak;\n\t\t\t} else {\n\t\t\t\t/* tc1 = false, tc2 = false */\n\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"tc1=false, tc2=false: output d --> %ld (k=%ld)\",\n\t\t\t\t                     (long) d, (long) nc_ctx->k));\n\t\t\t\tDUK__DRAGON4_OUTPUT_PREINC(nc_ctx, count, d);\n\n\t\t\t\t/* r <- r    (updated above: r <- (remainder (* r B) s)\n\t\t\t\t * s <- s\n\t\t\t\t * m+ <- m+  (updated above: m+ <- (* m+ B)\n\t\t\t\t * m- <- m-  (updated above: m- <- (* m- B)\n\t\t\t\t * B, low_ok, high_ok are fixed\n\t\t\t\t */\n\n\t\t\t\t/* fall through and continue for-loop */\n\t\t\t}\n\t\t}\n\n\t\t/* fixed-format termination conditions */\n\t\tif (nc_ctx->is_fixed) {\n\t\t\tif (nc_ctx->abs_pos) {\n\t\t\t\tint pos = nc_ctx->k - count + 1;  /* count is already incremented, take into account */\n\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"fixed format, absolute: abs pos=%ld, k=%ld, count=%ld, req=%ld\",\n\t\t\t\t                     (long) pos, (long) nc_ctx->k, (long) count, (long) nc_ctx->req_digits));\n\t\t\t\tif (pos <= nc_ctx->req_digits) {\n\t\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"digit position reached req_digits, end generate loop\"));\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"fixed format, relative: k=%ld, count=%ld, req=%ld\",\n\t\t\t\t                     (long) nc_ctx->k, (long) count, (long) nc_ctx->req_digits));\n\t\t\t\tif (count >= nc_ctx->req_digits) {\n\t\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"digit count reached req_digits, end generate loop\"));\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}  /* for */\n\n\tnc_ctx->count = count;\n\n\tDUK_DDD(DUK_DDDPRINT(\"generate finished\"));\n\n#if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)\n\t{\n\t\tduk_uint8_t buf[2048];\n\t\tduk_small_int_t i, t;\n\t\tDUK_MEMZERO(buf, sizeof(buf));\n\t\tfor (i = 0; i < nc_ctx->count; i++) {\n\t\t\tt = nc_ctx->digits[i];\n\t\t\tif (t < 0 || t > 36) {\n\t\t\t\tbuf[i] = (duk_uint8_t) '?';\n\t\t\t} else {\n\t\t\t\tbuf[i] = (duk_uint8_t) DUK__DIGITCHAR(t);\n\t\t\t}\n\t\t}\n\t\tDUK_DDD(DUK_DDDPRINT(\"-> generated digits; k=%ld, digits='%s'\",\n\t\t                     (long) nc_ctx->k, (const char *) buf));\n\t}\n#endif\n}\n\n/* Round up digits to a given position.  If position is out-of-bounds,\n * does nothing.  If carry propagates over the first digit, a '1' is\n * prepended to digits and 'k' will be updated.  Return value indicates\n * whether carry propagated over the first digit.\n *\n * Note that nc_ctx->count is NOT updated based on the rounding position\n * (it is updated only if carry overflows over the first digit and an\n * extra digit is prepended).\n */\nDUK_LOCAL duk_small_int_t duk__dragon4_fixed_format_round(duk__numconv_stringify_ctx *nc_ctx, duk_small_int_t round_idx) {\n\tduk_small_int_t t;\n\tduk_uint8_t *p;\n\tduk_uint8_t roundup_limit;\n\tduk_small_int_t ret = 0;\n\n\t/*\n\t *  round_idx points to the digit which is considered for rounding; the\n\t *  digit to its left is the final digit of the rounded value.  If round_idx\n\t *  is zero, rounding will be performed; the result will either be an empty\n\t *  rounded value or if carry happens a '1' digit is generated.\n\t */\n\n\tif (round_idx >= nc_ctx->count) {\n\t\tDUK_DDD(DUK_DDDPRINT(\"round_idx out of bounds (%ld >= %ld (count)) -> no rounding\",\n\t\t                     (long) round_idx, (long) nc_ctx->count));\n\t\treturn 0;\n\t} else if (round_idx < 0) {\n\t\tDUK_DDD(DUK_DDDPRINT(\"round_idx out of bounds (%ld < 0) -> no rounding\",\n\t\t                     (long) round_idx));\n\t\treturn 0;\n\t}\n\n\t/*\n\t *  Round-up limit.\n\t *\n\t *  For even values, divides evenly, e.g. 10 -> roundup_limit=5.\n\t *\n\t *  For odd values, rounds up, e.g. 3 -> roundup_limit=2.\n\t *  If radix is 3, 0/3 -> down, 1/3 -> down, 2/3 -> up.\n\t */\n\troundup_limit = (duk_uint8_t) ((nc_ctx->B + 1) / 2);\n\n\tp = &nc_ctx->digits[round_idx];\n\tif (*p >= roundup_limit) {\n\t\tDUK_DDD(DUK_DDDPRINT(\"fixed-format rounding carry required\"));\n\t\t/* carry */\n\t\tfor (;;) {\n\t\t\t*p = 0;\n\t\t\tif (p == &nc_ctx->digits[0]) {\n\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"carry propagated to first digit -> special case handling\"));\n\t\t\t\tDUK_MEMMOVE((void *) (&nc_ctx->digits[1]),\n\t\t\t\t            (const void *) (&nc_ctx->digits[0]),\n\t\t\t\t            (size_t) (sizeof(char) * (size_t) nc_ctx->count));\n\t\t\t\tnc_ctx->digits[0] = 1;  /* don't increase 'count' */\n\t\t\t\tnc_ctx->k++;  /* position of highest digit changed */\n\t\t\t\tnc_ctx->count++;  /* number of digits changed */\n\t\t\t\tret = 1;\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"fixed-format rounding carry: B=%ld, roundup_limit=%ld, p=%p, digits=%p\",\n\t\t\t                     (long) nc_ctx->B, (long) roundup_limit, (void *) p, (void *) nc_ctx->digits));\n\t\t\tp--;\n\t\t\tt = *p;\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"digit before carry: %ld\", (long) t));\n\t\t\tif (++t < nc_ctx->B) {\n\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"rounding carry terminated\"));\n\t\t\t\t*p = (duk_uint8_t) t;\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"wraps, carry to next digit\"));\n\t\t}\n\t}\n\n\treturn ret;\n}\n\n#define DUK__NO_EXP  (65536)  /* arbitrary marker, outside valid exp range */\n\nDUK_LOCAL void duk__dragon4_convert_and_push(duk__numconv_stringify_ctx *nc_ctx,\n                                             duk_hthread *thr,\n                                             duk_small_int_t radix,\n                                             duk_small_int_t digits,\n                                             duk_small_uint_t flags,\n                                             duk_small_int_t neg) {\n\tduk_small_int_t k;\n\tduk_small_int_t pos, pos_end;\n\tduk_small_int_t expt;\n\tduk_small_int_t dig;\n\tduk_uint8_t *q;\n\tduk_uint8_t *buf;\n\n\t/*\n\t *  The string conversion here incorporates all the necessary Ecmascript\n\t *  semantics without attempting to be generic.  nc_ctx->digits contains\n\t *  nc_ctx->count digits (>= 1), with the topmost digit's 'position'\n\t *  indicated by nc_ctx->k as follows:\n\t *\n\t *    digits=\"123\" count=3 k=0   -->   0.123\n\t *    digits=\"123\" count=3 k=1   -->   1.23\n\t *    digits=\"123\" count=3 k=5   -->   12300\n\t *    digits=\"123\" count=3 k=-1  -->   0.0123\n\t *\n\t *  Note that the identifier names used for format selection are different\n\t *  in Burger-Dybvig paper and Ecmascript specification (quite confusingly\n\t *  so, because e.g. 'k' has a totally different meaning in each).  See\n\t *  documentation for discussion.\n\t *\n\t *  Ecmascript doesn't specify any specific behavior for format selection\n\t *  (e.g. when to use exponent notation) for non-base-10 numbers.\n\t *\n\t *  The bigint space in the context is reused for string output, as there\n\t *  is more than enough space for that (>1kB at the moment), and we avoid\n\t *  allocating even more stack.\n\t */\n\n\tDUK_ASSERT(DUK__NUMCONV_CTX_BIGINTS_SIZE >= DUK__MAX_FORMATTED_LENGTH);\n\tDUK_ASSERT(nc_ctx->count >= 1);\n\n\tk = nc_ctx->k;\n\tbuf = (duk_uint8_t *) &nc_ctx->f;  /* XXX: union would be more correct */\n\tq = buf;\n\n\t/* Exponent handling: if exponent format is used, record exponent value and\n\t * fake k such that one leading digit is generated (e.g. digits=123 -> \"1.23\").\n\t *\n\t * toFixed() prevents exponent use; otherwise apply a set of criteria to\n\t * match the other API calls (toString(), toPrecision, etc).\n\t */\n\n\texpt = DUK__NO_EXP;\n\tif (!nc_ctx->abs_pos /* toFixed() */) {\n\t\tif ((flags & DUK_N2S_FLAG_FORCE_EXP) ||             /* exponential notation forced */\n\t\t    ((flags & DUK_N2S_FLAG_NO_ZERO_PAD) &&          /* fixed precision and zero padding would be required */\n\t             (k - digits >= 1)) ||                          /* (e.g. k=3, digits=2 -> \"12X\") */\n\t\t    ((k > 21 || k <= -6) && (radix == 10))) {       /* toString() conditions */\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"use exponential notation: k=%ld -> expt=%ld\",\n\t\t\t                     (long) k, (long) (k - 1)));\n\t\t\texpt = k - 1;  /* e.g. 12.3 -> digits=\"123\" k=2 -> 1.23e1 */\n\t\t\tk = 1;  /* generate mantissa with a single leading whole number digit */\n\t\t}\n\t}\n\n\tif (neg) {\n\t\t*q++ = '-';\n\t}\n\n\t/* Start position (inclusive) and end position (exclusive) */\n\tpos = (k >= 1 ? k : 1);\n\tif (nc_ctx->is_fixed) {\n\t\tif (nc_ctx->abs_pos) {\n\t\t\t/* toFixed() */\n\t\t\tpos_end = -digits;\n\t\t} else {\n\t\t\tpos_end = k - digits;\n\t\t}\n\t} else {\n\t\tpos_end = k - nc_ctx->count;\n\t}\n\tif (pos_end > 0) {\n\t\tpos_end = 0;\n\t}\n\n\tDUK_DDD(DUK_DDDPRINT(\"expt=%ld, k=%ld, count=%ld, pos=%ld, pos_end=%ld, is_fixed=%ld, \"\n\t                     \"digits=%ld, abs_pos=%ld\",\n\t                     (long) expt, (long) k, (long) nc_ctx->count, (long) pos, (long) pos_end,\n\t                     (long) nc_ctx->is_fixed, (long) digits, (long) nc_ctx->abs_pos));\n\n\t/* Digit generation */\n\twhile (pos > pos_end) {\n\t\tDUK_DDD(DUK_DDDPRINT(\"digit generation: pos=%ld, pos_end=%ld\",\n\t\t                     (long) pos, (long) pos_end));\n\t\tif (pos == 0) {\n\t\t\t*q++ = (duk_uint8_t) '.';\n\t\t}\n\t\tif (pos > k) {\n\t\t\t*q++ = (duk_uint8_t) '0';\n\t\t} else if (pos <= k - nc_ctx->count) {\n\t\t\t*q++ = (duk_uint8_t) '0';\n\t\t} else {\n\t\t\tdig = nc_ctx->digits[k - pos];\n\t\t\tDUK_ASSERT(dig >= 0 && dig < nc_ctx->B);\n\t\t\t*q++ = (duk_uint8_t) DUK__DIGITCHAR(dig);\n\t\t}\n\n\t\tpos--;\n\t}\n\tDUK_ASSERT(pos <= 1);\n\n\t/* Exponent */\n\tif (expt != DUK__NO_EXP) {\n\t\t/*\n\t\t *  Exponent notation for non-base-10 numbers isn't specified in Ecmascript\n\t\t *  specification, as it never explicitly turns up: non-decimal numbers can\n\t\t *  only be formatted with Number.prototype.toString([radix]) and for that,\n\t\t *  behavior is not explicitly specified.\n\t\t *\n\t\t *  Logical choices include formatting the exponent as decimal (e.g. binary\n\t\t *  100000 as 1e+5) or in current radix (e.g. binary 100000 as 1e+101).\n\t\t *  The Dragon4 algorithm (in the original paper) prints the exponent value\n\t\t *  in the target radix B.  However, for radix values 15 and above, the\n\t\t *  exponent separator 'e' is no longer easily parseable.  Consider, for\n\t\t *  instance, the number \"1.faecee+1c\".\n\t\t */\n\n\t\tduk_size_t len;\n\t\tchar expt_sign;\n\n\t\t*q++ = 'e';\n\t\tif (expt >= 0) {\n\t\t\texpt_sign = '+';\n\t\t} else {\n\t\t\texpt_sign = '-';\n\t\t\texpt = -expt;\n\t\t}\n\t\t*q++ = (duk_uint8_t) expt_sign;\n\t\tlen = duk__dragon4_format_uint32(q, (duk_uint32_t) expt, radix);\n\t\tq += len;\n\t}\n\n\tduk_push_lstring(thr, (const char *) buf, (size_t) (q - buf));\n}\n\n/*\n *  Conversion helpers\n */\n\nDUK_LOCAL void duk__dragon4_double_to_ctx(duk__numconv_stringify_ctx *nc_ctx, duk_double_t x) {\n\tduk_double_union u;\n\tduk_uint32_t tmp;\n\tduk_small_int_t expt;\n\n\t/*\n\t *    seeeeeee eeeeffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff\n\t *       A        B        C        D        E        F        G        H\n\t *\n\t *    s       sign bit\n\t *    eee...  exponent field\n\t *    fff...  fraction\n\t *\n\t *    ieee value = 1.ffff... * 2^(e - 1023)  (normal)\n\t *               = 0.ffff... * 2^(-1022)     (denormal)\n\t *\n\t *    algorithm v = f * b^e\n\t */\n\n\tDUK_DBLUNION_SET_DOUBLE(&u, x);\n\n\tnc_ctx->f.n = 2;\n\n\ttmp = DUK_DBLUNION_GET_LOW32(&u);\n\tnc_ctx->f.v[0] = tmp;\n\ttmp = DUK_DBLUNION_GET_HIGH32(&u);\n\tnc_ctx->f.v[1] = tmp & 0x000fffffUL;\n\texpt = (duk_small_int_t) ((tmp >> 20) & 0x07ffUL);\n\n\tif (expt == 0) {\n\t\t/* denormal */\n\t\texpt = DUK__IEEE_DOUBLE_EXP_MIN - 52;\n\t\tduk__bi_normalize(&nc_ctx->f);\n\t} else {\n\t\t/* normal: implicit leading 1-bit */\n\t\tnc_ctx->f.v[1] |= 0x00100000UL;\n\t\texpt = expt - DUK__IEEE_DOUBLE_EXP_BIAS - 52;\n\t\tDUK_ASSERT(duk__bi_is_valid(&nc_ctx->f));  /* true, because v[1] has at least one bit set */\n\t}\n\n\tDUK_ASSERT(duk__bi_is_valid(&nc_ctx->f));\n\n\tnc_ctx->e = expt;\n}\n\nDUK_LOCAL void duk__dragon4_ctx_to_double(duk__numconv_stringify_ctx *nc_ctx, duk_double_t *x) {\n\tduk_double_union u;\n\tduk_small_int_t expt;\n\tduk_small_int_t i;\n\tduk_small_int_t bitstart;\n\tduk_small_int_t bitround;\n\tduk_small_int_t bitidx;\n\tduk_small_int_t skip_round;\n\tduk_uint32_t t, v;\n\n\tDUK_ASSERT(nc_ctx->count == 53 + 1);\n\n\t/* Sometimes this assert is not true right now; it will be true after\n\t * rounding.  See: test-bug-numconv-mantissa-assert.js.\n\t */\n\tDUK_ASSERT_DISABLE(nc_ctx->digits[0] == 1);  /* zero handled by caller */\n\n\t/* Should not be required because the code below always sets both high\n\t * and low parts, but at least gcc-4.4.5 fails to deduce this correctly\n\t * (perhaps because the low part is set (seemingly) conditionally in a\n\t * loop), so this is here to avoid the bogus warning.\n\t */\n\tDUK_MEMZERO((void *) &u, sizeof(u));\n\n\t/*\n\t *  Figure out how generated digits match up with the mantissa,\n\t *  and then perform rounding.  If mantissa overflows, need to\n\t *  recompute the exponent (it is bumped and may overflow to\n\t *  infinity).\n\t *\n\t *  For normal numbers the leading '1' is hidden and ignored,\n\t *  and the last bit is used for rounding:\n\t *\n\t *                          rounding pt\n\t *       <--------52------->|\n\t *     1 x x x x ... x x x x|y  ==>  x x x x ... x x x x\n\t *\n\t *  For denormals, the leading '1' is included in the number,\n\t *  and the rounding point is different:\n\t *\n\t *                      rounding pt\n\t *     <--52 or less--->|\n\t *     1 x x x x ... x x|x x y  ==>  0 0 ... 1 x x ... x x\n\t *\n\t *  The largest denormals will have a mantissa beginning with\n\t *  a '1' (the explicit leading bit); smaller denormals will\n\t *  have leading zero bits.\n\t *\n\t *  If the exponent would become too high, the result becomes\n\t *  Infinity.  If the exponent is so small that the entire\n\t *  mantissa becomes zero, the result becomes zero.\n\t *\n\t *  Note: the Dragon4 'k' is off-by-one with respect to the IEEE\n\t *  exponent.  For instance, k==0 indicates that the leading '1'\n\t *  digit is at the first binary fraction position (0.1xxx...);\n\t *  the corresponding IEEE exponent would be -1.\n\t */\n\n\tskip_round = 0;\n\n recheck_exp:\n\n\texpt = nc_ctx->k - 1;   /* IEEE exp without bias */\n\tif (expt > 1023) {\n\t\t/* Infinity */\n\t\tbitstart = -255;  /* needed for inf: causes mantissa to become zero,\n\t\t                   * and rounding to be skipped.\n\t\t                   */\n\t\texpt = 2047;\n\t} else if (expt >= -1022) {\n\t\t/* normal */\n\t\tbitstart = 1;  /* skip leading digit */\n\t\texpt += DUK__IEEE_DOUBLE_EXP_BIAS;\n\t\tDUK_ASSERT(expt >= 1 && expt <= 2046);\n\t} else {\n\t\t/* denormal or zero */\n\t\tbitstart = 1023 + expt;  /* expt==-1023 -> bitstart=0 (leading 1);\n\t\t                          * expt==-1024 -> bitstart=-1 (one left of leading 1), etc\n\t\t                          */\n\t\texpt = 0;\n\t}\n\tbitround = bitstart + 52;\n\n\tDUK_DDD(DUK_DDDPRINT(\"ieee expt=%ld, bitstart=%ld, bitround=%ld\",\n\t                     (long) expt, (long) bitstart, (long) bitround));\n\n\tif (!skip_round) {\n\t\tif (duk__dragon4_fixed_format_round(nc_ctx, bitround)) {\n\t\t\t/* Corner case: see test-numconv-parse-mant-carry.js.  We could\n\t\t\t * just bump the exponent and update bitstart, but it's more robust\n\t\t\t * to recompute (but avoid rounding twice).\n\t\t\t */\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"rounding caused exponent to be bumped, recheck exponent\"));\n\t\t\tskip_round = 1;\n\t\t\tgoto recheck_exp;\n\t\t}\n\t}\n\n\t/*\n\t *  Create mantissa\n\t */\n\n\tt = 0;\n\tfor (i = 0; i < 52; i++) {\n\t\tbitidx = bitstart + 52 - 1 - i;\n\t\tif (bitidx >= nc_ctx->count) {\n\t\t\tv = 0;\n\t\t} else if (bitidx < 0) {\n\t\t\tv = 0;\n\t\t} else {\n\t\t\tv = nc_ctx->digits[bitidx];\n\t\t}\n\t\tDUK_ASSERT(v == 0 || v == 1);\n\t\tt += v << (i % 32);\n\t\tif (i == 31) {\n\t\t\t/* low 32 bits is complete */\n\t\t\tDUK_DBLUNION_SET_LOW32(&u, t);\n\t\t\tt = 0;\n\t\t}\n\t}\n\t/* t has high mantissa */\n\n\tDUK_DDD(DUK_DDDPRINT(\"mantissa is complete: %08lx %08lx\",\n\t                     (unsigned long) t,\n\t                     (unsigned long) DUK_DBLUNION_GET_LOW32(&u)));\n\n\tDUK_ASSERT(expt >= 0 && expt <= 0x7ffL);\n\tt += ((duk_uint32_t) expt) << 20;\n#if 0  /* caller handles sign change */\n\tif (negative) {\n\t\tt |= 0x80000000U;\n\t}\n#endif\n\tDUK_DBLUNION_SET_HIGH32(&u, t);\n\n\tDUK_DDD(DUK_DDDPRINT(\"number is complete: %08lx %08lx\",\n\t                     (unsigned long) DUK_DBLUNION_GET_HIGH32(&u),\n\t                     (unsigned long) DUK_DBLUNION_GET_LOW32(&u)));\n\n\t*x = DUK_DBLUNION_GET_DOUBLE(&u);\n}\n\n/*\n *  Exposed number-to-string API\n *\n *  Input: [ number ]\n *  Output: [ string ]\n */\n\nDUK_INTERNAL void duk_numconv_stringify(duk_hthread *thr, duk_small_int_t radix, duk_small_int_t digits, duk_small_uint_t flags) {\n\tduk_double_t x;\n\tduk_small_int_t c;\n\tduk_small_int_t neg;\n\tduk_uint32_t uval;\n\tduk__numconv_stringify_ctx nc_ctx_alloc;  /* large context; around 2kB now */\n\tduk__numconv_stringify_ctx *nc_ctx = &nc_ctx_alloc;\n\n\tx = (duk_double_t) duk_require_number(thr, -1);\n\tduk_pop(thr);\n\n\t/*\n\t *  Handle special cases (NaN, infinity, zero).\n\t */\n\n\tc = (duk_small_int_t) DUK_FPCLASSIFY(x);\n\tif (DUK_SIGNBIT((double) x)) {\n\t\tx = -x;\n\t\tneg = 1;\n\t} else {\n\t\tneg = 0;\n\t}\n\n\t/* NaN sign bit is platform specific with unpacked, un-normalized NaNs */\n\tDUK_ASSERT(c == DUK_FP_NAN || DUK_SIGNBIT((double) x) == 0);\n\n\tif (c == DUK_FP_NAN) {\n\t\tduk_push_hstring_stridx(thr, DUK_STRIDX_NAN);\n\t\treturn;\n\t} else if (c == DUK_FP_INFINITE) {\n\t\tif (neg) {\n\t\t\t/* -Infinity */\n\t\t\tduk_push_hstring_stridx(thr, DUK_STRIDX_MINUS_INFINITY);\n\t\t} else {\n\t\t\t/* Infinity */\n\t\t\tduk_push_hstring_stridx(thr, DUK_STRIDX_INFINITY);\n\t\t}\n\t\treturn;\n\t} else if (c == DUK_FP_ZERO) {\n\t\t/* We can't shortcut zero here if it goes through special formatting\n\t\t * (such as forced exponential notation).\n\t\t */\n\t\t;\n\t}\n\n\t/*\n\t *  Handle integers in 32-bit range (that is, [-(2**32-1),2**32-1])\n\t *  specially, as they're very likely for embedded programs.  This\n\t *  is now done for all radix values.  We must be careful not to use\n\t *  the fast path when special formatting (e.g. forced exponential)\n\t *  is in force.\n\t *\n\t *  XXX: could save space by supporting radix 10 only and using\n\t *  sprintf \"%lu\" for the fast path and for exponent formatting.\n\t */\n\n\tuval = (unsigned int) x;\n\tif (((double) uval) == x &&  /* integer number in range */\n\t    flags == 0) {            /* no special formatting */\n\t\t/* use bigint area as a temp */\n\t\tduk_uint8_t *buf = (duk_uint8_t *) (&nc_ctx->f);\n\t\tduk_uint8_t *p = buf;\n\n\t\tDUK_ASSERT(DUK__NUMCONV_CTX_BIGINTS_SIZE >= 32 + 1);  /* max size: radix=2 + sign */\n\t\tif (neg && uval != 0) {\n\t\t\t/* no negative sign for zero */\n\t\t\t*p++ = (duk_uint8_t) '-';\n\t\t}\n\t\tp += duk__dragon4_format_uint32(p, uval, radix);\n\t\tduk_push_lstring(thr, (const char *) buf, (duk_size_t) (p - buf));\n\t\treturn;\n\t}\n\n\t/*\n\t *  Dragon4 setup.\n\t *\n\t *  Convert double from IEEE representation for conversion;\n\t *  normal finite values have an implicit leading 1-bit.  The\n\t *  slow path algorithm doesn't handle zero, so zero is special\n\t *  cased here but still creates a valid nc_ctx, and goes\n\t *  through normal formatting in case special formatting has\n\t *  been requested (e.g. forced exponential format: 0 -> \"0e+0\").\n\t */\n\n\t/* Would be nice to bulk clear the allocation, but the context\n\t * is 1-2 kilobytes and nothing should rely on it being zeroed.\n\t */\n#if 0\n\tDUK_MEMZERO((void *) nc_ctx, sizeof(*nc_ctx));  /* slow init, do only for slow path cases */\n#endif\n\n\tnc_ctx->is_s2n = 0;\n\tnc_ctx->b = 2;\n\tnc_ctx->B = radix;\n\tnc_ctx->abs_pos = 0;\n\tif (flags & DUK_N2S_FLAG_FIXED_FORMAT) {\n\t\tnc_ctx->is_fixed = 1;\n\t\tif (flags & DUK_N2S_FLAG_FRACTION_DIGITS) {\n\t\t\t/* absolute req_digits; e.g. digits = 1 -> last digit is 0,\n\t\t\t * but add an extra digit for rounding.\n\t\t\t */\n\t\t\tnc_ctx->abs_pos = 1;\n\t\t\tnc_ctx->req_digits = (-digits + 1) - 1;\n\t\t} else {\n\t\t\tnc_ctx->req_digits = digits + 1;\n\t\t}\n\t} else {\n\t\tnc_ctx->is_fixed = 0;\n\t\tnc_ctx->req_digits = 0;\n\t}\n\n\tif (c == DUK_FP_ZERO) {\n\t\t/* Zero special case: fake requested number of zero digits; ensure\n\t\t * no sign bit is printed.  Relative and absolute fixed format\n\t\t * require separate handling.\n\t\t */\n\t\tduk_small_int_t count;\n\t\tif (nc_ctx->is_fixed) {\n\t\t\tif (nc_ctx->abs_pos) {\n\t\t\t\tcount = digits + 2;  /* lead zero + 'digits' fractions + 1 for rounding */\n\t\t\t} else {\n\t\t\t\tcount = digits + 1;  /* + 1 for rounding */\n\t\t\t}\n\t\t} else {\n\t\t\tcount = 1;\n\t\t}\n\t\tDUK_DDD(DUK_DDDPRINT(\"count=%ld\", (long) count));\n\t\tDUK_ASSERT(count >= 1);\n\t\tDUK_MEMZERO((void *) nc_ctx->digits, (size_t) count);\n\t\tnc_ctx->count = count;\n\t\tnc_ctx->k = 1;  /* 0.000... */\n\t\tneg = 0;\n\t\tgoto zero_skip;\n\t}\n\n\tduk__dragon4_double_to_ctx(nc_ctx, x);   /* -> sets 'f' and 'e' */\n\tDUK__BI_PRINT(\"f\", &nc_ctx->f);\n\tDUK_DDD(DUK_DDDPRINT(\"e=%ld\", (long) nc_ctx->e));\n\n\t/*\n\t *  Dragon4 slow path digit generation.\n\t */\n\n\tduk__dragon4_prepare(nc_ctx);  /* setup many variables in nc_ctx */\n\n\tDUK_DDD(DUK_DDDPRINT(\"after prepare:\"));\n\tDUK__BI_PRINT(\"r\", &nc_ctx->r);\n\tDUK__BI_PRINT(\"s\", &nc_ctx->s);\n\tDUK__BI_PRINT(\"mp\", &nc_ctx->mp);\n\tDUK__BI_PRINT(\"mm\", &nc_ctx->mm);\n\n\tduk__dragon4_scale(nc_ctx);\n\n\tDUK_DDD(DUK_DDDPRINT(\"after scale; k=%ld\", (long) nc_ctx->k));\n\tDUK__BI_PRINT(\"r\", &nc_ctx->r);\n\tDUK__BI_PRINT(\"s\", &nc_ctx->s);\n\tDUK__BI_PRINT(\"mp\", &nc_ctx->mp);\n\tDUK__BI_PRINT(\"mm\", &nc_ctx->mm);\n\n\tduk__dragon4_generate(nc_ctx);\n\n\t/*\n\t *  Convert and push final string.\n\t */\n\n zero_skip:\n\n\tif (flags & DUK_N2S_FLAG_FIXED_FORMAT) {\n\t\t/* Perform fixed-format rounding. */\n\t\tduk_small_int_t roundpos;\n\t\tif (flags & DUK_N2S_FLAG_FRACTION_DIGITS) {\n\t\t\t/* 'roundpos' is relative to nc_ctx->k and increases to the right\n\t\t\t * (opposite of how 'k' changes).\n\t\t\t */\n\t\t\troundpos = -digits;  /* absolute position for digit considered for rounding */\n\t\t\troundpos = nc_ctx->k - roundpos;\n\t\t} else {\n\t\t\troundpos = digits;\n\t\t}\n\t\tDUK_DDD(DUK_DDDPRINT(\"rounding: k=%ld, count=%ld, digits=%ld, roundpos=%ld\",\n\t\t                     (long) nc_ctx->k, (long) nc_ctx->count, (long) digits, (long) roundpos));\n\t\t(void) duk__dragon4_fixed_format_round(nc_ctx, roundpos);\n\n\t\t/* Note: 'count' is currently not adjusted by rounding (i.e. the\n\t\t * digits are not \"chopped off\".  That shouldn't matter because\n\t\t * the digit position (absolute or relative) is passed on to the\n\t\t * convert-and-push function.\n\t\t */\n\t}\n\n\tduk__dragon4_convert_and_push(nc_ctx, thr, radix, digits, flags, neg);\n}\n\n/*\n *  Exposed string-to-number API\n *\n *  Input: [ string ]\n *  Output: [ number ]\n *\n *  If number parsing fails, a NaN is pushed as the result.  If number parsing\n *  fails due to an internal error, an InternalError is thrown.\n */\n\nDUK_INTERNAL void duk_numconv_parse(duk_hthread *thr, duk_small_int_t radix, duk_small_uint_t flags) {\n\tduk__numconv_stringify_ctx nc_ctx_alloc;  /* large context; around 2kB now */\n\tduk__numconv_stringify_ctx *nc_ctx = &nc_ctx_alloc;\n\tduk_double_t res;\n\tduk_hstring *h_str;\n\tduk_small_int_t expt;\n\tduk_small_int_t expt_neg;\n\tduk_small_int_t expt_adj;\n\tduk_small_int_t neg;\n\tduk_small_int_t dig;\n\tduk_small_int_t dig_whole;\n\tduk_small_int_t dig_lzero;\n\tduk_small_int_t dig_frac;\n\tduk_small_int_t dig_expt;\n\tduk_small_int_t dig_prec;\n\tconst duk__exp_limits *explim;\n\tconst duk_uint8_t *p;\n\tduk_small_int_t ch;\n\n\tDUK_DDD(DUK_DDDPRINT(\"parse number: %!T, radix=%ld, flags=0x%08lx\",\n\t                     (duk_tval *) duk_get_tval(thr, -1),\n\t                     (long) radix, (unsigned long) flags));\n\n\tDUK_ASSERT(radix >= 2 && radix <= 36);\n\tDUK_ASSERT(radix - 2 < (duk_small_int_t) sizeof(duk__str2num_digits_for_radix));\n\n\t/*\n\t *  Preliminaries: trim, sign, Infinity check\n\t *\n\t *  We rely on the interned string having a NUL terminator, which will\n\t *  cause a parse failure wherever it is encountered.  As a result, we\n\t *  don't need separate pointer checks.\n\t *\n\t *  There is no special parsing for 'NaN' in the specification although\n\t *  'Infinity' (with an optional sign) is allowed in some contexts.\n\t *  Some contexts allow plus/minus sign, while others only allow the\n\t *  minus sign (like JSON.parse()).\n\t *\n\t *  Automatic hex number detection (leading '0x' or '0X') and octal\n\t *  number detection (leading '0' followed by at least one octal digit)\n\t *  is done here too.\n\t *\n\t *  Symbols are not explicitly rejected here (that's up to the caller).\n\t *  If a symbol were passed here, it should ultimately safely fail\n\t *  parsing due to a syntax error.\n\t */\n\n\tif (flags & DUK_S2N_FLAG_TRIM_WHITE) {\n\t\t/* Leading / trailing whitespace is sometimes accepted and\n\t\t * sometimes not.  After white space trimming, all valid input\n\t\t * characters are pure ASCII.\n\t\t */\n\t\tduk_trim(thr, -1);\n\t}\n\th_str = duk_require_hstring(thr, -1);\n\tDUK_ASSERT(h_str != NULL);\n\tp = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_str);\n\n\tneg = 0;\n\tch = *p;\n\tif (ch == (duk_small_int_t) '+') {\n\t\tif ((flags & DUK_S2N_FLAG_ALLOW_PLUS) == 0) {\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"parse failed: leading plus sign not allowed\"));\n\t\t\tgoto parse_fail;\n\t\t}\n\t\tp++;\n\t} else if (ch == (duk_small_int_t) '-') {\n\t\tif ((flags & DUK_S2N_FLAG_ALLOW_MINUS) == 0) {\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"parse failed: leading minus sign not allowed\"));\n\t\t\tgoto parse_fail;\n\t\t}\n\t\tp++;\n\t\tneg = 1;\n\t}\n\n\tif ((flags & DUK_S2N_FLAG_ALLOW_INF) && DUK_STRNCMP((const char *) p, \"Infinity\", 8) == 0) {\n\t\t/* Don't check for Infinity unless the context allows it.\n\t\t * 'Infinity' is a valid integer literal in e.g. base-36:\n\t\t *\n\t\t *   parseInt('Infinity', 36)\n\t\t *   1461559270678\n\t\t */\n\n\t\tif ((flags & DUK_S2N_FLAG_ALLOW_GARBAGE) == 0 && p[8] != DUK_ASC_NUL) {\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"parse failed: trailing garbage after matching 'Infinity' not allowed\"));\n\t\t\tgoto parse_fail;\n\t\t} else {\n\t\t\tres = DUK_DOUBLE_INFINITY;\n\t\t\tgoto negcheck_and_ret;\n\t\t}\n\t}\n\tch = *p;\n\tif (ch == (duk_small_int_t) '0') {\n\t\tduk_small_int_t detect_radix = 0;\n\t\tch = DUK_LOWERCASE_CHAR_ASCII(p[1]);  /* 'x' or 'X' -> 'x' */\n\t\tif ((flags & DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT) && ch == DUK_ASC_LC_X) {\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"detected 0x/0X hex prefix, changing radix and preventing fractions and exponent\"));\n\t\t\tdetect_radix = 16;\n#if 0\n\t\t} else if ((flags & DUK_S2N_FLAG_ALLOW_AUTO_LEGACY_OCT_INT) &&\n\t\t           (ch >= (duk_small_int_t) '0' && ch <= (duk_small_int_t) '9')) {\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"detected 0n oct prefix, changing radix and preventing fractions and exponent\"));\n\t\t\tdetect_radix = 8;\n\n\t\t\t/* NOTE: if this legacy octal case is added back, it has\n\t\t\t * different flags and 'p' advance so this needs to be\n\t\t\t * reworked.\n\t\t\t */\n\t\t\tflags |= DUK_S2N_FLAG_ALLOW_EMPTY_AS_ZERO;  /* interpret e.g. '09' as '0', not NaN */\n\t\t\tp += 1;\n#endif\n\t\t} else if ((flags & DUK_S2N_FLAG_ALLOW_AUTO_OCT_INT) && ch == DUK_ASC_LC_O) {\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"detected 0o oct prefix, changing radix and preventing fractions and exponent\"));\n\t\t\tdetect_radix = 8;\n\t\t} else if ((flags & DUK_S2N_FLAG_ALLOW_AUTO_BIN_INT) && ch == DUK_ASC_LC_B) {\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"detected 0b bin prefix, changing radix and preventing fractions and exponent\"));\n\t\t\tdetect_radix = 2;\n\t\t}\n\t\tif (detect_radix > 0) {\n\t\t\tradix = detect_radix;\n\t\t\t/* Clear empty as zero flag: interpret e.g. '0x' and '0xg' as a NaN (= parse error) */\n\t\t\tflags &= ~(DUK_S2N_FLAG_ALLOW_EXP | DUK_S2N_FLAG_ALLOW_EMPTY_FRAC |\n\t\t\t           DUK_S2N_FLAG_ALLOW_FRAC | DUK_S2N_FLAG_ALLOW_NAKED_FRAC |\n\t\t\t           DUK_S2N_FLAG_ALLOW_EMPTY_AS_ZERO);\n\t\t\tflags |= DUK_S2N_FLAG_ALLOW_LEADING_ZERO;  /* allow e.g. '0x0009' and '0b00010001' */\n\t\t\tp += 2;\n\t\t}\n\t}\n\n\t/*\n\t *  Scan number and setup for Dragon4.\n\t *\n\t *  The fast path case is detected during setup: an integer which\n\t *  can be converted without rounding, no net exponent.  The fast\n\t *  path could be implemented as a separate scan, but may not really\n\t *  be worth it: the multiplications for building 'f' are not\n\t *  expensive when 'f' is small.\n\t *\n\t *  The significand ('f') must contain enough bits of (apparent)\n\t *  accuracy, so that Dragon4 will generate enough binary output digits.\n\t *  For decimal numbers, this means generating a 20-digit significand,\n\t *  which should yield enough practical accuracy to parse IEEE doubles.\n\t *  In fact, the Ecmascript specification explicitly allows an\n\t *  implementation to treat digits beyond 20 as zeroes (and even\n\t *  to round the 20th digit upwards).  For non-decimal numbers, the\n\t *  appropriate number of digits has been precomputed for comparable\n\t *  accuracy.\n\t *\n\t *  Digit counts:\n\t *\n\t *    [ dig_lzero ]\n\t *      |\n\t *     .+-..---[ dig_prec ]----.\n\t *     |  ||                   |\n\t *     0000123.456789012345678901234567890e+123456\n\t *     |     | |                         |  |    |\n\t *     `--+--' `------[ dig_frac ]-------'  `-+--'\n\t *        |                                   |\n\t *    [ dig_whole ]                       [ dig_expt ]\n\t *\n\t *    dig_frac and dig_expt are -1 if not present\n\t *    dig_lzero is only computed for whole number part\n\t *\n\t *  Parsing state\n\t *\n\t *     Parsing whole part      dig_frac < 0 AND dig_expt < 0\n\t *     Parsing fraction part   dig_frac >= 0 AND dig_expt < 0\n\t *     Parsing exponent part   dig_expt >= 0   (dig_frac may be < 0 or >= 0)\n\t *\n\t *  Note: in case we hit an implementation limit (like exponent range),\n\t *  we should throw an error, NOT return NaN or Infinity.  Even with\n\t *  very large exponent (or significand) values the final result may be\n\t *  finite, so NaN/Infinity would be incorrect.\n\t */\n\n\tduk__bi_set_small(&nc_ctx->f, 0);\n\tdig_prec = 0;\n\tdig_lzero = 0;\n\tdig_whole = 0;\n\tdig_frac = -1;\n\tdig_expt = -1;\n\texpt = 0;\n\texpt_adj = 0;  /* essentially tracks digit position of lowest 'f' digit */\n\texpt_neg = 0;\n\tfor (;;) {\n\t\tch = *p++;\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"parse digits: p=%p, ch='%c' (%ld), expt=%ld, expt_adj=%ld, \"\n\t\t                     \"dig_whole=%ld, dig_frac=%ld, dig_expt=%ld, dig_lzero=%ld, dig_prec=%ld\",\n\t\t                     (const void *) p, (int) ((ch >= 0x20 && ch <= 0x7e) ? ch : '?'), (long) ch,\n\t\t                     (long) expt, (long) expt_adj, (long) dig_whole, (long) dig_frac,\n\t\t                     (long) dig_expt, (long) dig_lzero, (long) dig_prec));\n\t\tDUK__BI_PRINT(\"f\", &nc_ctx->f);\n\n\t\t/* Most common cases first. */\n\t\tif (ch >= (duk_small_int_t) '0' && ch <= (duk_small_int_t) '9') {\n\t\t\tdig = (duk_small_int_t) ch - '0' + 0;\n\t\t} else if (ch == (duk_small_int_t) '.') {\n\t\t\t/* A leading digit is not required in some cases, e.g. accept \".123\".\n\t\t\t * In other cases (JSON.parse()) a leading digit is required.  This\n\t\t\t * is checked for after the loop.\n\t\t\t */\n\t\t\tif (dig_frac >= 0 || dig_expt >= 0) {\n\t\t\t\tif (flags & DUK_S2N_FLAG_ALLOW_GARBAGE) {\n\t\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"garbage termination (invalid period)\"));\n\t\t\t\t\tbreak;\n\t\t\t\t} else {\n\t\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"parse failed: period not allowed\"));\n\t\t\t\t\tgoto parse_fail;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ((flags & DUK_S2N_FLAG_ALLOW_FRAC) == 0) {\n\t\t\t\t/* Some contexts don't allow fractions at all; this can't be a\n\t\t\t\t * post-check because the state ('f' and expt) would be incorrect.\n\t\t\t\t */\n\t\t\t\tif (flags & DUK_S2N_FLAG_ALLOW_GARBAGE) {\n\t\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"garbage termination (invalid first period)\"));\n\t\t\t\t\tbreak;\n\t\t\t\t} else {\n\t\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"parse failed: fraction part not allowed\"));\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"start fraction part\"));\n\t\t\tdig_frac = 0;\n\t\t\tcontinue;\n\t\t} else if (ch == (duk_small_int_t) 0) {\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"NUL termination\"));\n\t\t\tbreak;\n\t\t} else if ((flags & DUK_S2N_FLAG_ALLOW_EXP) &&\n\t\t           dig_expt < 0 && (ch == (duk_small_int_t) 'e' || ch == (duk_small_int_t) 'E')) {\n\t\t\t/* Note: we don't parse back exponent notation for anything else\n\t\t\t * than radix 10, so this is not an ambiguous check (e.g. hex\n\t\t\t * exponent values may have 'e' either as a significand digit\n\t\t\t * or as an exponent separator).\n\t\t\t *\n\t\t\t * If the exponent separator occurs twice, 'e' will be interpreted\n\t\t\t * as a digit (= 14) and will be rejected as an invalid decimal\n\t\t\t * digit.\n\t\t\t */\n\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"start exponent part\"));\n\n\t\t\t/* Exponent without a sign or with a +/- sign is accepted\n\t\t\t * by all call sites (even JSON.parse()).\n\t\t\t */\n\t\t\tch = *p;\n\t\t\tif (ch == (duk_small_int_t) '-') {\n\t\t\t\texpt_neg = 1;\n\t\t\t\tp++;\n\t\t\t} else if (ch == (duk_small_int_t) '+') {\n\t\t\t\tp++;\n\t\t\t}\n\t\t\tdig_expt = 0;\n\t\t\tcontinue;\n\t\t} else if (ch >= (duk_small_int_t) 'a' && ch <= (duk_small_int_t) 'z') {\n\t\t\tdig = (duk_small_int_t) (ch - (duk_small_int_t) 'a' + 0x0a);\n\t\t} else if (ch >= (duk_small_int_t) 'A' && ch <= (duk_small_int_t) 'Z') {\n\t\t\tdig = (duk_small_int_t) (ch - (duk_small_int_t) 'A' + 0x0a);\n\t\t} else {\n\t\t\tdig = 255;  /* triggers garbage digit check below */\n\t\t}\n\t\tDUK_ASSERT((dig >= 0 && dig <= 35) || dig == 255);\n\n\t\tif (dig >= radix) {\n\t\t\tif (flags & DUK_S2N_FLAG_ALLOW_GARBAGE) {\n\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"garbage termination\"));\n\t\t\t\tbreak;\n\t\t\t} else {\n\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"parse failed: trailing garbage or invalid digit\"));\n\t\t\t\tgoto parse_fail;\n\t\t\t}\n\t\t}\n\n\t\tif (dig_expt < 0) {\n\t\t\t/* whole or fraction digit */\n\n\t\t\tif (dig_prec < duk__str2num_digits_for_radix[radix - 2]) {\n\t\t\t\t/* significant from precision perspective */\n\n\t\t\t\tduk_small_int_t f_zero = duk__bi_is_zero(&nc_ctx->f);\n\t\t\t\tif (f_zero && dig == 0) {\n\t\t\t\t\t/* Leading zero is not counted towards precision digits; not\n\t\t\t\t\t * in the integer part, nor in the fraction part.\n\t\t\t\t\t */\n\t\t\t\t\tif (dig_frac < 0) {\n\t\t\t\t\t\tdig_lzero++;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t/* XXX: join these ops (multiply-accumulate), but only if\n\t\t\t\t\t * code footprint decreases.\n\t\t\t\t\t */\n\t\t\t\t\tduk__bi_mul_small(&nc_ctx->t1, &nc_ctx->f, (duk_uint32_t) radix);\n\t\t\t\t\tduk__bi_add_small(&nc_ctx->f, &nc_ctx->t1, (duk_uint32_t) dig);\n\t\t\t\t\tdig_prec++;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t/* Ignore digits beyond a radix-specific limit, but note them\n\t\t\t\t * in expt_adj.\n\t\t\t\t */\n\t\t\t\texpt_adj++;\n\t\t\t}\n\n\t\t\tif (dig_frac >= 0) {\n\t\t\t\tdig_frac++;\n\t\t\t\texpt_adj--;\n\t\t\t} else {\n\t\t\t\tdig_whole++;\n\t\t\t}\n\t\t} else {\n\t\t\t/* exponent digit */\n\n\t\t\texpt = expt * radix + dig;\n\t\t\tif (expt > DUK_S2N_MAX_EXPONENT) {\n\t\t\t\t/* impose a reasonable exponent limit, so that exp\n\t\t\t\t * doesn't need to get tracked using a bigint.\n\t\t\t\t */\n\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"parse failed: exponent too large\"));\n\t\t\t\tgoto parse_explimit_error;\n\t\t\t}\n\t\t\tdig_expt++;\n\t\t}\n\t}\n\n\t/* Leading zero. */\n\n\tif (dig_lzero > 0 && dig_whole > 1) {\n\t\tif ((flags & DUK_S2N_FLAG_ALLOW_LEADING_ZERO) == 0) {\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"parse failed: leading zeroes not allowed in integer part\"));\n\t\t\tgoto parse_fail;\n\t\t}\n\t}\n\n\t/* Validity checks for various fraction formats (\"0.1\", \".1\", \"1.\", \".\"). */\n\n\tif (dig_whole == 0) {\n\t\tif (dig_frac == 0) {\n\t\t\t/* \".\" is not accepted in any format */\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"parse failed: plain period without leading or trailing digits\"));\n\t\t\tgoto parse_fail;\n\t\t} else if (dig_frac > 0) {\n\t\t\t/* \".123\" */\n\t\t\tif ((flags & DUK_S2N_FLAG_ALLOW_NAKED_FRAC) == 0) {\n\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"parse failed: fraction part not allowed without \"\n\t\t\t\t                     \"leading integer digit(s)\"));\n\t\t\t\tgoto parse_fail;\n\t\t\t}\n\t\t} else {\n\t\t\t/* empty (\"\") is allowed in some formats (e.g. Number(''), as zero */\n\t\t\tif ((flags & DUK_S2N_FLAG_ALLOW_EMPTY_AS_ZERO) == 0) {\n\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"parse failed: empty string not allowed (as zero)\"));\n\t\t\t\tgoto parse_fail;\n\t\t\t}\n\t\t}\n\t} else {\n\t\tif (dig_frac == 0) {\n\t\t\t/* \"123.\" is allowed in some formats */\n\t\t\tif ((flags & DUK_S2N_FLAG_ALLOW_EMPTY_FRAC) == 0) {\n\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"parse failed: empty fractions\"));\n\t\t\t\tgoto parse_fail;\n\t\t\t}\n\t\t} else if (dig_frac > 0) {\n\t\t\t/* \"123.456\" */\n\t\t\t;\n\t\t} else {\n\t\t\t/* \"123\" */\n\t\t\t;\n\t\t}\n\t}\n\n\t/* Exponent without digits (e.g. \"1e\" or \"1e+\").  If trailing garbage is\n\t * allowed, ignore exponent part as garbage (= parse as \"1\", i.e. exp 0).\n\t */\n\n\tif (dig_expt == 0) {\n\t\tif ((flags & DUK_S2N_FLAG_ALLOW_GARBAGE) == 0) {\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"parse failed: empty exponent\"));\n\t\t\tgoto parse_fail;\n\t\t}\n\t\tDUK_ASSERT(expt == 0);\n\t}\n\n\tif (expt_neg) {\n\t\texpt = -expt;\n\t}\n\tDUK_DDD(DUK_DDDPRINT(\"expt=%ld, expt_adj=%ld, net exponent -> %ld\",\n\t                     (long) expt, (long) expt_adj, (long) (expt + expt_adj)));\n\texpt += expt_adj;\n\n\t/* Fast path check. */\n\n\tif (nc_ctx->f.n <= 1 &&   /* 32-bit value */\n\t    expt == 0    /* no net exponent */) {\n\t\t/* Fast path is triggered for no exponent and also for balanced exponent\n\t\t * and fraction parts, e.g. for \"1.23e2\" == \"123\".  Remember to respect\n\t\t * zero sign.\n\t\t */\n\n\t\t/* XXX: could accept numbers larger than 32 bits, e.g. up to 53 bits? */\n\t\tDUK_DDD(DUK_DDDPRINT(\"fast path number parse\"));\n\t\tif (nc_ctx->f.n == 1) {\n\t\t\tres = (double) nc_ctx->f.v[0];\n\t\t} else {\n\t\t\tres = 0.0;\n\t\t}\n\t\tgoto negcheck_and_ret;\n\t}\n\n\t/* Significand ('f') padding. */\n\n\twhile (dig_prec < duk__str2num_digits_for_radix[radix - 2]) {\n\t\t/* Pad significand with \"virtual\" zero digits so that Dragon4 will\n\t\t * have enough (apparent) precision to work with.\n\t\t */\n\t\tDUK_DDD(DUK_DDDPRINT(\"dig_prec=%ld, pad significand with zero\", (long) dig_prec));\n\t\tduk__bi_mul_small_copy(&nc_ctx->f, (duk_uint32_t) radix, &nc_ctx->t1);\n\t\tDUK__BI_PRINT(\"f\", &nc_ctx->f);\n\t\texpt--;\n\t\tdig_prec++;\n\t}\n\n\tDUK_DDD(DUK_DDDPRINT(\"final exponent: %ld\", (long) expt));\n\n\t/* Detect zero special case. */\n\n\tif (nc_ctx->f.n == 0) {\n\t\t/* This may happen even after the fast path check, if exponent is\n\t\t * not balanced (e.g. \"0e1\").  Remember to respect zero sign.\n\t\t */\n\t\tDUK_DDD(DUK_DDDPRINT(\"significand is zero\"));\n\t\tres = 0.0;\n\t\tgoto negcheck_and_ret;\n\t}\n\n\n\t/* Quick reject of too large or too small exponents.  This check\n\t * would be incorrect for zero (e.g. \"0e1000\" is zero, not Infinity)\n\t * so zero check must be above.\n\t */\n\n\texplim = &duk__str2num_exp_limits[radix - 2];\n\tif (expt > explim->upper) {\n\t\tDUK_DDD(DUK_DDDPRINT(\"exponent too large -> infinite\"));\n\t\tres = (duk_double_t) DUK_DOUBLE_INFINITY;\n\t\tgoto negcheck_and_ret;\n\t} else if (expt < explim->lower) {\n\t\tDUK_DDD(DUK_DDDPRINT(\"exponent too small -> zero\"));\n\t\tres = (duk_double_t) 0.0;\n\t\tgoto negcheck_and_ret;\n\t}\n\n\tnc_ctx->is_s2n = 1;\n\tnc_ctx->e = expt;\n\tnc_ctx->b = radix;\n\tnc_ctx->B = 2;\n\tnc_ctx->is_fixed = 1;\n\tnc_ctx->abs_pos = 0;\n\tnc_ctx->req_digits = 53 + 1;\n\n\tDUK__BI_PRINT(\"f\", &nc_ctx->f);\n\tDUK_DDD(DUK_DDDPRINT(\"e=%ld\", (long) nc_ctx->e));\n\n\t/*\n\t *  Dragon4 slow path (binary) digit generation.\n\t *  An extra digit is generated for rounding.\n\t */\n\n\tduk__dragon4_prepare(nc_ctx);  /* setup many variables in nc_ctx */\n\n\tDUK_DDD(DUK_DDDPRINT(\"after prepare:\"));\n\tDUK__BI_PRINT(\"r\", &nc_ctx->r);\n\tDUK__BI_PRINT(\"s\", &nc_ctx->s);\n\tDUK__BI_PRINT(\"mp\", &nc_ctx->mp);\n\tDUK__BI_PRINT(\"mm\", &nc_ctx->mm);\n\n\tduk__dragon4_scale(nc_ctx);\n\n\tDUK_DDD(DUK_DDDPRINT(\"after scale; k=%ld\", (long) nc_ctx->k));\n\tDUK__BI_PRINT(\"r\", &nc_ctx->r);\n\tDUK__BI_PRINT(\"s\", &nc_ctx->s);\n\tDUK__BI_PRINT(\"mp\", &nc_ctx->mp);\n\tDUK__BI_PRINT(\"mm\", &nc_ctx->mm);\n\n\tduk__dragon4_generate(nc_ctx);\n\n\tDUK_ASSERT(nc_ctx->count == 53 + 1);\n\n\t/*\n\t *  Convert binary digits into an IEEE double.  Need to handle\n\t *  denormals and rounding correctly.\n\t *\n\t *  Some call sites currently assume the result is always a\n\t *  non-fastint double.  If this is changed, check all call\n\t *  sites.\n\t */\n\n\tduk__dragon4_ctx_to_double(nc_ctx, &res);\n\tgoto negcheck_and_ret;\n\n negcheck_and_ret:\n\tif (neg) {\n\t\tres = -res;\n\t}\n\tduk_pop(thr);\n\tduk_push_number(thr, (double) res);\n\tDUK_DDD(DUK_DDDPRINT(\"result: %!T\", (duk_tval *) duk_get_tval(thr, -1)));\n\treturn;\n\n parse_fail:\n\tDUK_DDD(DUK_DDDPRINT(\"parse failed\"));\n\tduk_pop(thr);\n\tduk_push_nan(thr);\n\treturn;\n\n parse_explimit_error:\n\tDUK_DDD(DUK_DDDPRINT(\"parse failed, internal error, can't return a value\"));\n\tDUK_ERROR_RANGE(thr, \"exponent too large\");\n\treturn;\n}\n\n/* automatic undefs */\n#undef DUK__BI_MAX_PARTS\n#undef DUK__BI_PRINT\n#undef DUK__DIGITCHAR\n#undef DUK__DRAGON4_OUTPUT_PREINC\n#undef DUK__IEEE_DOUBLE_EXP_BIAS\n#undef DUK__IEEE_DOUBLE_EXP_MIN\n#undef DUK__MAX_FORMATTED_LENGTH\n#undef DUK__MAX_OUTPUT_DIGITS\n#undef DUK__NO_EXP\n#undef DUK__NUMCONV_CTX_BIGINTS_SIZE\n#undef DUK__NUMCONV_CTX_NUM_BIGINTS\n#line 1 \"duk_regexp_compiler.c\"\n/*\n *  Regexp compilation.\n *\n *  See doc/regexp.rst for a discussion of the compilation approach and\n *  current limitations.\n *\n *  Regexp bytecode assumes jumps can be expressed with signed 32-bit\n *  integers.  Consequently the bytecode size must not exceed 0x7fffffffL.\n *  The implementation casts duk_size_t (buffer size) to duk_(u)int32_t\n *  in many places.  Although this could be changed, the bytecode format\n *  limit would still prevent regexps exceeding the signed 32-bit limit\n *  from working.\n *\n *  XXX: The implementation does not prevent bytecode from exceeding the\n *  maximum supported size.  This could be done by limiting the maximum\n *  input string size (assuming an upper bound can be computed for number\n *  of bytecode bytes emitted per input byte) or checking buffer maximum\n *  size when emitting bytecode (slower).\n */\n\n/* #include duk_internal.h -> already included */\n\n#if defined(DUK_USE_REGEXP_SUPPORT)\n\n/*\n *  Helper macros\n */\n\n#define DUK__RE_INITIAL_BUFSIZE 64\n\n#define DUK__RE_BUFLEN(re_ctx) \\\n\tDUK_BW_GET_SIZE(re_ctx->thr, &re_ctx->bw)\n\n/*\n *  Disjunction struct: result of parsing a disjunction\n */\n\ntypedef struct {\n\t/* Number of characters that the atom matches (e.g. 3 for 'abc'),\n\t * -1 if atom is complex and number of matched characters either\n\t * varies or is not known.\n\t */\n\tduk_int32_t charlen;\n\n#if 0\n\t/* These are not needed to implement quantifier capture handling,\n\t * but might be needed at some point.\n\t */\n\n\t/* re_ctx->captures at start and end of atom parsing.\n\t * Since 'captures' indicates highest capture number emitted\n\t * so far in a DUK_REOP_SAVE, the captures numbers saved by\n\t * the atom are: ]start_captures,end_captures].\n\t */\n\tduk_uint32_t start_captures;\n\tduk_uint32_t end_captures;\n#endif\n} duk__re_disjunction_info;\n\n/*\n *  Encoding helpers\n *\n *  Some of the typing is bytecode based, e.g. slice sizes are unsigned 32-bit\n *  even though the buffer operations will use duk_size_t.\n */\n\n/* XXX: the insert helpers should ensure that the bytecode result is not\n * larger than expected (or at least assert for it).  Many things in the\n * bytecode, like skip offsets, won't work correctly if the bytecode is\n * larger than say 2G.\n */\n\nDUK_LOCAL duk_uint32_t duk__encode_i32(duk_int32_t x) {\n\tif (x < 0) {\n\t\treturn ((duk_uint32_t) (-x)) * 2 + 1;\n\t} else {\n\t\treturn ((duk_uint32_t) x) * 2;\n\t}\n}\n\n/* XXX: return type should probably be duk_size_t, or explicit checks are needed for\n * maximum size.\n */\nDUK_LOCAL duk_uint32_t duk__insert_u32(duk_re_compiler_ctx *re_ctx, duk_uint32_t offset, duk_uint32_t x) {\n\tduk_uint8_t buf[DUK_UNICODE_MAX_XUTF8_LENGTH];\n\tduk_small_int_t len;\n\n\tlen = duk_unicode_encode_xutf8((duk_ucodepoint_t) x, buf);\n\tDUK_ASSERT(len >= 0);\n\tDUK_BW_INSERT_ENSURE_BYTES(re_ctx->thr, &re_ctx->bw, offset, buf, (duk_size_t) len);\n\treturn (duk_uint32_t) len;\n}\n\nDUK_LOCAL void duk__append_u32(duk_re_compiler_ctx *re_ctx, duk_uint32_t x) {\n\tDUK_BW_WRITE_ENSURE_XUTF8(re_ctx->thr, &re_ctx->bw, x);\n}\n\nDUK_LOCAL void duk__append_7bit(duk_re_compiler_ctx *re_ctx, duk_uint32_t x) {\n#if defined(DUK_USE_PREFER_SIZE)\n\tduk__append_u32(re_ctx, x);\n#else\n\tDUK_ASSERT(x <= 0x7fU);\n\tDUK_BW_WRITE_ENSURE_U8(re_ctx->thr, &re_ctx->bw, (duk_uint8_t) x);\n#endif\n}\n\n#if 0\nDUK_LOCAL void duk__append_2bytes(duk_re_compiler_ctx *re_ctx, duk_uint8_t x, duk_uint8_t y) {\n\tDUK_BW_WRITE_ENSURE_U8_2(re_ctx->thr, &re_ctx->bw, x, y);\n}\n#endif\n\nDUK_LOCAL duk_uint32_t duk__insert_i32(duk_re_compiler_ctx *re_ctx, duk_uint32_t offset, duk_int32_t x) {\n\treturn duk__insert_u32(re_ctx, offset, duk__encode_i32(x));\n}\n\nDUK_LOCAL void duk__append_reop(duk_re_compiler_ctx *re_ctx, duk_uint32_t reop) {\n\tDUK_ASSERT(reop <= 0x7fU);\n\t(void) duk__append_7bit(re_ctx, reop);\n}\n\n#if 0  /* unused */\nDUK_LOCAL void duk__append_i32(duk_re_compiler_ctx *re_ctx, duk_int32_t x) {\n\tduk__append_u32(re_ctx, duk__encode_i32(x));\n}\n#endif\n\n/* special helper for emitting u16 lists (used for character ranges for built-in char classes) */\nDUK_LOCAL void duk__append_u16_list(duk_re_compiler_ctx *re_ctx, const duk_uint16_t *values, duk_uint32_t count) {\n\t/* Call sites don't need the result length so it's not accumulated. */\n\twhile (count-- > 0) {\n\t\tduk__append_u32(re_ctx, (duk_uint32_t) (*values++));\n\t}\n}\n\nDUK_LOCAL void duk__insert_slice(duk_re_compiler_ctx *re_ctx, duk_uint32_t offset, duk_uint32_t data_offset, duk_uint32_t data_length) {\n\tDUK_BW_INSERT_ENSURE_SLICE(re_ctx->thr, &re_ctx->bw, offset, data_offset, data_length);\n}\n\nDUK_LOCAL void duk__append_slice(duk_re_compiler_ctx *re_ctx, duk_uint32_t data_offset, duk_uint32_t data_length) {\n\tDUK_BW_WRITE_ENSURE_SLICE(re_ctx->thr, &re_ctx->bw, data_offset, data_length);\n}\n\nDUK_LOCAL void duk__remove_slice(duk_re_compiler_ctx *re_ctx, duk_uint32_t data_offset, duk_uint32_t data_length) {\n\tDUK_BW_REMOVE_ENSURE_SLICE(re_ctx->thr, &re_ctx->bw, data_offset, data_length);\n}\n\n/*\n *  Insert a jump offset at 'offset' to complete an instruction\n *  (the jump offset is always the last component of an instruction).\n *  The 'skip' argument must be computed relative to 'offset',\n *  -without- taking into account the skip field being inserted.\n *\n *       ... A B C ins X Y Z ...   (ins may be a JUMP, SPLIT1/SPLIT2, etc)\n *   =>  ... A B C ins SKIP X Y Z\n *\n *  Computing the final (adjusted) skip value, which is relative to the\n *  first byte of the next instruction, is a bit tricky because of the\n *  variable length UTF-8 encoding.  See doc/regexp.rst for discussion.\n */\nDUK_LOCAL duk_uint32_t duk__insert_jump_offset(duk_re_compiler_ctx *re_ctx, duk_uint32_t offset, duk_int32_t skip) {\n#if 0\n\t/* Iterative solution. */\n\tif (skip < 0) {\n\t\tduk_small_int_t len;\n\t\t/* two encoding attempts suffices */\n\t\tlen = duk_unicode_get_xutf8_length((duk_codepoint_t) duk__encode_i32(skip));\n\t\tlen = duk_unicode_get_xutf8_length((duk_codepoint_t) duk__encode_i32(skip - (duk_int32_t) len));\n\t\tDUK_ASSERT(duk_unicode_get_xutf8_length(duk__encode_i32(skip - (duk_int32_t) len)) == len);  /* no change */\n\t\tskip -= (duk_int32_t) len;\n\t}\n#endif\n\n#if defined(DUK_USE_PREFER_SIZE)\n\t/* Closed form solution, this produces smallest code.\n\t * See re_neg_jump_offset (closed2).\n\t */\n\tif (skip < 0) {\n\t\tskip--;\n\t\tif (skip < -0x3fL) {\n\t\t\tskip--;\n\t\t}\n\t\tif (skip < -0x3ffL) {\n\t\t\tskip--;\n\t\t}\n\t\tif (skip < -0x7fffL) {\n\t\t\tskip--;\n\t\t}\n\t\tif (skip < -0xfffffL) {\n\t\t\tskip--;\n\t\t}\n\t\tif (skip < -0x1ffffffL) {\n\t\t\tskip--;\n\t\t}\n\t\tif (skip < -0x3fffffffL) {\n\t\t\tskip--;\n\t\t}\n\t}\n#else  /* DUK_USE_PREFER_SIZE */\n\t/* Closed form solution, this produces fastest code.\n\t * See re_neg_jump_offset (closed1).\n\t */\n\tif (skip < 0) {\n\t\tif (skip >= -0x3eL) {\n\t\t\tskip -= 1;\n\t\t} else if (skip >= -0x3fdL) {\n\t\t\tskip -= 2;\n\t\t} else if (skip >= -0x7ffcL) {\n\t\t\tskip -= 3;\n\t\t} else if (skip >= -0xffffbL) {\n\t\t\tskip -= 4;\n\t\t} else if (skip >= -0x1fffffaL) {\n\t\t\tskip -= 5;\n\t\t} else if (skip >= -0x3ffffff9L) {\n\t\t\tskip -= 6;\n\t\t} else {\n\t\t\tskip -= 7;\n\t\t}\n\t}\n#endif  /* DUK_USE_PREFER_SIZE */\n\n\treturn duk__insert_i32(re_ctx, offset, skip);\n}\n\nDUK_LOCAL duk_uint32_t duk__append_jump_offset(duk_re_compiler_ctx *re_ctx, duk_int32_t skip) {\n\treturn (duk_uint32_t) duk__insert_jump_offset(re_ctx, (duk_uint32_t) DUK__RE_BUFLEN(re_ctx), skip);\n}\n\n/*\n *  duk_re_range_callback for generating character class ranges.\n *\n *  When ignoreCase is false, the range is simply emitted as is.  We don't,\n *  for instance, eliminate duplicates or overlapping ranges in a character\n *  class.\n *\n *  When ignoreCase is true but the 'direct' flag is set, the caller knows\n *  that the range canonicalizes to itself for case insensitive matching,\n *  so the range is emitted as is.  This is mainly useful for built-in ranges\n *  like \\W.\n *\n *  Otherwise, when ignoreCase is true, the range needs to be normalized\n *  through canonicalization.  Unfortunately a canonicalized version of a\n *  continuous range is not necessarily continuous (e.g. [x-{] is continuous\n *  but [X-{] is not).  As a result, a single input range may expand to a lot\n *  of output ranges.  The current algorithm creates the canonicalized ranges\n *  footprint efficiently at the cost of compile time execution time; see\n *  doc/regexp.rst for discussion, and some more details below.\n *\n *  Note that the ctx->nranges is a context-wide temporary value.  This is OK\n *  because there cannot be multiple character classes being parsed\n *  simultaneously.\n *\n *  More detail on canonicalization:\n *\n *  Conceptually, a range is canonicalized by scanning the entire range,\n *  normalizing each codepoint by converting it to uppercase, and generating\n *  a set of result ranges.\n *\n *  Ideally a minimal set of output ranges would be emitted by merging all\n *  possible ranges even if they're emitted out of sequence.  Because the\n *  input string is also case normalized during matching, some codepoints\n *  never occur at runtime; these \"don't care\" codepoints can be included or\n *  excluded from ranges when merging/optimizing ranges.\n *\n *  The current algorithm does not do optimal range merging.  Rather, output\n *  codepoints are generated in sequence, and when the output codepoints are\n *  continuous (CP, CP+1, CP+2, ...), they are merged locally into as large a\n *  range as possible.  A small canonicalization bitmap is used to reduce\n *  actual codepoint canonicalizations which are quite slow at present.  The\n *  bitmap provides a \"codepoint block is continuous with respect to\n *  canonicalization\" for N-codepoint blocks.  This allows blocks to be\n *  skipped quickly.\n *\n *  There are a number of shortcomings and future work here:\n *\n *    - Individual codepoint normalizations are slow because they involve\n *      walking bit-packed rules without a lookup index.\n *\n *    - The conceptual algorithm needs to canonicalize every codepoint in the\n *      input range to figure out the output range(s).  Even with the small\n *      canonicalization bitmap the algorithm runs quite slowly for worst case\n *      inputs.  There are many data structure alternatives to improve this.\n *\n *    - While the current algorithm generates maximal output ranges when the\n *      output codepoints are emitted linearly, output ranges are not sorted or\n *      merged otherwise.  In the worst case a lot of ranges are emitted when\n *      most of the ranges could be merged.  In this process one could take\n *      advantage of \"don't care\" codepoints, which are never matched against at\n *      runtime due to canonicalization of input codepoints before comparison,\n *      to merge otherwise discontinuous output ranges.\n *\n *    - The runtime data structure is just a linear list of ranges to match\n *      against.  This can be quite slow if there are a lot of output ranges.\n *      There are various ways to make matching against the ranges faster,\n *      e.g. sorting the ranges and using a binary search; skip lists; tree\n *      based representations; full or approximate codepoint bitmaps, etc.\n *\n *    - Only BMP is supported, codepoints above BMP are assumed to canonicalize\n *      to themselves.  For now this is one place where we don't want to\n *      support chars outside the BMP, because the exhaustive search would be\n *      massively larger.  It would be possible to support non-BMP with a\n *      different algorithm, or perhaps doing case normalization only at match\n *      time.\n */\n\nDUK_LOCAL void duk__regexp_emit_range(duk_re_compiler_ctx *re_ctx, duk_codepoint_t r1, duk_codepoint_t r2) {\n\tDUK_ASSERT(r2 >= r1);\n\tduk__append_u32(re_ctx, (duk_uint32_t) r1);\n\tduk__append_u32(re_ctx, (duk_uint32_t) r2);\n\tre_ctx->nranges++;\n}\n\n#if defined(DUK_USE_REGEXP_CANON_BITMAP)\n/* Find next canonicalization discontinuity (conservative estimate) starting\n * from 'start', not exceeding 'end'.  If continuity is fine up to 'end'\n * inclusive, returns end.  Minimum possible return value is start.\n */\nDUK_LOCAL duk_codepoint_t duk__re_canon_next_discontinuity(duk_codepoint_t start, duk_codepoint_t end) {\n\tduk_uint_t start_blk;\n\tduk_uint_t end_blk;\n\tduk_uint_t blk;\n\tduk_uint_t offset;\n\tduk_uint8_t mask;\n\n\t/* Inclusive block range. */\n\tDUK_ASSERT(start >= 0);\n\tDUK_ASSERT(end >= 0);\n\tDUK_ASSERT(end >= start);\n\tstart_blk = (duk_uint_t) (start >> DUK_CANON_BITMAP_BLKSHIFT);\n\tend_blk = (duk_uint_t) (end >> DUK_CANON_BITMAP_BLKSHIFT);\n\n\tfor (blk = start_blk; blk <= end_blk; blk++) {\n\t\toffset = blk >> 3;\n\t\tmask = 1U << (blk & 0x07);\n\t\tif (offset >= sizeof(duk_unicode_re_canon_bitmap)) {\n\t\t\t/* Reached non-BMP range which is assumed continuous. */\n\t\t\treturn end;\n\t\t}\n\t\tDUK_ASSERT(offset < sizeof(duk_unicode_re_canon_bitmap));\n\t\tif ((duk_unicode_re_canon_bitmap[offset] & mask) == 0) {\n\t\t\t/* Block is discontinuous, continuity is guaranteed\n\t\t\t * only up to end of previous block (+1 for exclusive\n\t\t\t * return value => start of current block).  Start\n\t\t\t * block requires special handling.\n\t\t\t */\n\t\t\tif (blk > start_blk) {\n\t\t\t\treturn (duk_codepoint_t) (blk << DUK_CANON_BITMAP_BLKSHIFT);\n\t\t\t} else {\n\t\t\t\treturn start;\n\t\t\t}\n\t\t}\n\t}\n\tDUK_ASSERT(blk == end_blk + 1);  /* Reached end block which is continuous. */\n\treturn end;\n}\n#else  /* DUK_USE_REGEXP_CANON_BITMAP */\nDUK_LOCAL duk_codepoint_t duk__re_canon_next_discontinuity(duk_codepoint_t start, duk_codepoint_t end) {\n\tDUK_ASSERT(start >= 0);\n\tDUK_ASSERT(end >= 0);\n\tDUK_ASSERT(end >= start);\n\tif (start >= 0x10000) {\n\t\t/* Even without the bitmap, treat non-BMP as continuous. */\n\t\treturn end;\n\t}\n\treturn start;\n}\n#endif  /* DUK_USE_REGEXP_CANON_BITMAP */\n\nDUK_LOCAL void duk__regexp_generate_ranges(void *userdata, duk_codepoint_t r1, duk_codepoint_t r2, duk_bool_t direct) {\n\tduk_re_compiler_ctx *re_ctx = (duk_re_compiler_ctx *) userdata;\n\tduk_codepoint_t r_start;\n\tduk_codepoint_t r_end;\n\tduk_codepoint_t i;\n\tduk_codepoint_t t;\n\tduk_codepoint_t r_disc;\n\n\tDUK_DD(DUK_DDPRINT(\"duk__regexp_generate_ranges(): re_ctx=%p, range=[%ld,%ld] direct=%ld\",\n\t                   (void *) re_ctx, (long) r1, (long) r2, (long) direct));\n\n\tDUK_ASSERT(r2 >= r1);  /* SyntaxError for out of order range. */\n\n\tif (direct || (re_ctx->re_flags & DUK_RE_FLAG_IGNORE_CASE) == 0) {\n\t\tDUK_DD(DUK_DDPRINT(\"direct or not case sensitive, emit range: [%ld,%ld]\", (long) r1, (long) r2));\n\t\tduk__regexp_emit_range(re_ctx, r1, r2);\n\t\treturn;\n\t}\n\n\tDUK_DD(DUK_DDPRINT(\"case sensitive, process range: [%ld,%ld]\", (long) r1, (long) r2));\n\n\tr_start = duk_unicode_re_canonicalize_char(re_ctx->thr, r1);\n\tr_end = r_start;\n\n\tfor (i = r1 + 1; i <= r2;) {\n\t\t/* Input codepoint space processed up to i-1, and\n\t\t * current range in r_{start,end} is up-to-date\n\t\t * (inclusive) and may either break or continue.\n\t\t */\n\t\tr_disc = duk__re_canon_next_discontinuity(i, r2);\n\t\tDUK_ASSERT(r_disc >= i);\n\t\tDUK_ASSERT(r_disc <= r2);\n\n\t\tr_end += r_disc - i;  /* May be zero. */\n\t\tt = duk_unicode_re_canonicalize_char(re_ctx->thr, r_disc);\n\t\tif (t == r_end + 1) {\n\t\t\t/* Not actually a discontinuity, continue range\n\t\t\t * to r_disc and recheck.\n\t\t\t */\n\t\t\tr_end = t;\n\t\t} else {\n\t\t\tduk__regexp_emit_range(re_ctx, r_start, r_end);\n\t\t\tr_start = t;\n\t\t\tr_end = t;\n\t\t}\n\t\ti = r_disc + 1;  /* Guarantees progress. */\n\t}\n\tduk__regexp_emit_range(re_ctx, r_start, r_end);\n\n#if 0  /* Exhaustive search, very slow. */\n\tr_start = duk_unicode_re_canonicalize_char(re_ctx->thr, r1);\n\tr_end = r_start;\n\tfor (i = r1 + 1; i <= r2; i++) {\n\t\tt = duk_unicode_re_canonicalize_char(re_ctx->thr, i);\n\t\tif (t == r_end + 1) {\n\t\t\tr_end = t;\n\t\t} else {\n\t\t\tDUK_DD(DUK_DDPRINT(\"canonicalized, emit range: [%ld,%ld]\", (long) r_start, (long) r_end));\n\t\t\tduk__append_u32(re_ctx, (duk_uint32_t) r_start);\n\t\t\tduk__append_u32(re_ctx, (duk_uint32_t) r_end);\n\t\t\tre_ctx->nranges++;\n\t\t\tr_start = t;\n\t\t\tr_end = t;\n\t\t}\n\t}\n\tDUK_DD(DUK_DDPRINT(\"canonicalized, emit range: [%ld,%ld]\", (long) r_start, (long) r_end));\n\tduk__append_u32(re_ctx, (duk_uint32_t) r_start);\n\tduk__append_u32(re_ctx, (duk_uint32_t) r_end);\n\tre_ctx->nranges++;\n#endif\n}\n\n/*\n *  Parse regexp Disjunction.  Most of regexp compilation happens here.\n *\n *  Handles Disjunction, Alternative, and Term productions directly without\n *  recursion.  The only constructs requiring recursion are positive/negative\n *  lookaheads, capturing parentheses, and non-capturing parentheses.\n *\n *  The function determines whether the entire disjunction is a 'simple atom'\n *  (see doc/regexp.rst discussion on 'simple quantifiers') and if so,\n *  returns the atom character length which is needed by the caller to keep\n *  track of its own atom character length.  A disjunction with more than one\n *  alternative is never considered a simple atom (although in some cases\n *  that might be the case).\n *\n *  Return value: simple atom character length or < 0 if not a simple atom.\n *  Appends the bytecode for the disjunction matcher to the end of the temp\n *  buffer.\n *\n *  Regexp top level structure is:\n *\n *    Disjunction = Term*\n *                | Term* | Disjunction\n *\n *    Term = Assertion\n *         | Atom\n *         | Atom Quantifier\n *\n *  An empty Term sequence is a valid disjunction alternative (e.g. /|||c||/).\n *\n *  Notes:\n *\n *    * Tracking of the 'simple-ness' of the current atom vs. the entire\n *      disjunction are separate matters.  For instance, the disjunction\n *      may be complex, but individual atoms may be simple.  Furthermore,\n *      simple quantifiers are used whenever possible, even if the\n *      disjunction as a whole is complex.\n *\n *    * The estimate of whether an atom is simple is conservative now,\n *      and it would be possible to expand it.  For instance, captures\n *      cause the disjunction to be marked complex, even though captures\n *      -can- be handled by simple quantifiers with some minor modifications.\n *\n *    * Disjunction 'tainting' as 'complex' is handled at the end of the\n *      main for loop collectively for atoms.  Assertions, quantifiers,\n *      and '|' tokens need to taint the result manually if necessary.\n *      Assertions cannot add to result char length, only atoms (and\n *      quantifiers) can; currently quantifiers will taint the result\n *      as complex though.\n */\n\nDUK_LOCAL const duk_uint16_t * const duk__re_range_lookup1[3] = {\n\tduk_unicode_re_ranges_digit,\n\tduk_unicode_re_ranges_white,\n\tduk_unicode_re_ranges_wordchar\n};\nDUK_LOCAL const duk_uint8_t duk__re_range_lookup2[3] = {\n\tsizeof(duk_unicode_re_ranges_digit) / (2 * sizeof(duk_uint16_t)),\n\tsizeof(duk_unicode_re_ranges_white) / (2 * sizeof(duk_uint16_t)),\n\tsizeof(duk_unicode_re_ranges_wordchar) / (2 * sizeof(duk_uint16_t))\n};\n\nDUK_LOCAL void duk__append_range_atom_matcher(duk_re_compiler_ctx *re_ctx, duk_small_uint_t re_op, const duk_uint16_t *ranges, duk_small_uint_t count) {\n#if 0\n\tDUK_ASSERT(re_op <= 0x7fUL);\n\tDUK_ASSERT(count <= 0x7fUL);\n\tduk__append_2bytes(re_ctx, (duk_uint8_t) re_op, (duk_uint8_t) count);\n#endif\n\tduk__append_reop(re_ctx, re_op);\n\tduk__append_7bit(re_ctx, count);\n\tduk__append_u16_list(re_ctx, ranges, count * 2);\n}\n\nDUK_LOCAL void duk__parse_disjunction(duk_re_compiler_ctx *re_ctx, duk_bool_t expect_eof, duk__re_disjunction_info *out_atom_info) {\n\tduk_int32_t atom_start_offset = -1;                   /* negative -> no atom matched on previous round */\n\tduk_int32_t atom_char_length = 0;                     /* negative -> complex atom */\n\tduk_uint32_t atom_start_captures = re_ctx->captures;  /* value of re_ctx->captures at start of atom */\n\tduk_int32_t unpatched_disjunction_split = -1;\n\tduk_int32_t unpatched_disjunction_jump = -1;\n\tduk_uint32_t entry_offset = (duk_uint32_t) DUK__RE_BUFLEN(re_ctx);\n\tduk_int32_t res_charlen = 0;  /* -1 if disjunction is complex, char length if simple */\n\tduk__re_disjunction_info tmp_disj;\n\n\tDUK_ASSERT(out_atom_info != NULL);\n\n\tif (re_ctx->recursion_depth >= re_ctx->recursion_limit) {\n\t\tDUK_ERROR_RANGE(re_ctx->thr, DUK_STR_REGEXP_COMPILER_RECURSION_LIMIT);\n\t}\n\tre_ctx->recursion_depth++;\n\n#if 0\n\tout_atom_info->start_captures = re_ctx->captures;\n#endif\n\n\tfor (;;) {\n\t\t/* atom_char_length, atom_start_offset, atom_start_offset reflect the\n\t\t * atom matched on the previous loop.  If a quantifier is encountered\n\t\t * on this loop, these are needed to handle the quantifier correctly.\n\t\t * new_atom_char_length etc are for the atom parsed on this round;\n\t\t * they're written to atom_char_length etc at the end of the round.\n\t\t */\n\t\tduk_int32_t new_atom_char_length;   /* char length of the atom parsed in this loop */\n\t\tduk_int32_t new_atom_start_offset;  /* bytecode start offset of the atom parsed in this loop\n\t\t                                     * (allows quantifiers to copy the atom bytecode)\n\t\t                                     */\n\t\tduk_uint32_t new_atom_start_captures;  /* re_ctx->captures at the start of the atom parsed in this loop */\n\n\t\tduk_lexer_parse_re_token(&re_ctx->lex, &re_ctx->curr_token);\n\n\t\tDUK_DD(DUK_DDPRINT(\"re token: %ld (num=%ld, char=%c)\",\n\t\t                   (long) re_ctx->curr_token.t,\n\t\t                   (long) re_ctx->curr_token.num,\n\t\t                   (re_ctx->curr_token.num >= 0x20 && re_ctx->curr_token.num <= 0x7e) ?\n\t\t                   (int) re_ctx->curr_token.num : (int) '?'));\n\n\t\t/* set by atom case clauses */\n\t\tnew_atom_start_offset = -1;\n\t\tnew_atom_char_length = -1;\n\t\tnew_atom_start_captures = re_ctx->captures;\n\n\t\tswitch (re_ctx->curr_token.t) {\n\t\tcase DUK_RETOK_DISJUNCTION: {\n\t\t\t/*\n\t\t\t *  The handling here is a bit tricky.  If a previous '|' has been processed,\n\t\t\t *  we have a pending split1 and a pending jump (for a previous match).  These\n\t\t\t *  need to be back-patched carefully.  See docs for a detailed example.\n\t\t\t */\n\n\t\t\t/* patch pending jump and split */\n\t\t\tif (unpatched_disjunction_jump >= 0) {\n\t\t\t\tduk_uint32_t offset;\n\n\t\t\t\tDUK_ASSERT(unpatched_disjunction_split >= 0);\n\t\t\t\toffset = (duk_uint32_t) unpatched_disjunction_jump;\n\t\t\t\toffset += duk__insert_jump_offset(re_ctx,\n\t\t\t\t                                  offset,\n\t\t\t\t                                  (duk_int32_t) (DUK__RE_BUFLEN(re_ctx) - offset));\n\t\t\t\t/* offset is now target of the pending split (right after jump) */\n\t\t\t\tduk__insert_jump_offset(re_ctx,\n\t\t\t\t                        (duk_uint32_t) unpatched_disjunction_split,\n\t\t\t\t                        (duk_int32_t) offset - unpatched_disjunction_split);\n\t\t\t}\n\n\t\t\t/* add a new pending split to the beginning of the entire disjunction */\n\t\t\t(void) duk__insert_u32(re_ctx,\n\t\t\t                       entry_offset,\n\t\t\t                       DUK_REOP_SPLIT1);   /* prefer direct execution */\n\t\t\tunpatched_disjunction_split = (duk_int32_t) (entry_offset + 1);   /* +1 for opcode */\n\n\t\t\t/* add a new pending match jump for latest finished alternative */\n\t\t\tduk__append_reop(re_ctx, DUK_REOP_JUMP);\n\t\t\tunpatched_disjunction_jump = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);\n\n\t\t\t/* 'taint' result as complex */\n\t\t\tres_charlen = -1;\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_RETOK_QUANTIFIER: {\n\t\t\tif (atom_start_offset < 0) {\n\t\t\t\tDUK_ERROR_SYNTAX(re_ctx->thr, DUK_STR_INVALID_QUANTIFIER_NO_ATOM);\n\t\t\t}\n\t\t\tif (re_ctx->curr_token.qmin > re_ctx->curr_token.qmax) {\n\t\t\t\tDUK_ERROR_SYNTAX(re_ctx->thr, DUK_STR_INVALID_QUANTIFIER_VALUES);\n\t\t\t}\n\t\t\tif (atom_char_length >= 0) {\n\t\t\t\t/*\n\t\t\t\t *  Simple atom\n\t\t\t\t *\n\t\t\t\t *  If atom_char_length is zero, we'll have unbounded execution time for e.g.\n\t\t\t\t *  /()*x/.exec('x').  We can't just skip the match because it might have some\n\t\t\t\t *  side effects (for instance, if we allowed captures in simple atoms, the\n\t\t\t\t *  capture needs to happen).  The simple solution below is to force the\n\t\t\t\t *  quantifier to match at most once, since the additional matches have no effect.\n\t\t\t\t *\n\t\t\t\t *  With a simple atom there can be no capture groups, so no captures need\n\t\t\t\t *  to be reset.\n\t\t\t\t */\n\t\t\t\tduk_int32_t atom_code_length;\n\t\t\t\tduk_uint32_t offset;\n\t\t\t\tduk_uint32_t qmin, qmax;\n\n\t\t\t\tqmin = re_ctx->curr_token.qmin;\n\t\t\t\tqmax = re_ctx->curr_token.qmax;\n\t\t\t\tif (atom_char_length == 0) {\n\t\t\t\t\t/* qmin and qmax will be 0 or 1 */\n\t\t\t\t\tif (qmin > 1) {\n\t\t\t\t\t\tqmin = 1;\n\t\t\t\t\t}\n\t\t\t\t\tif (qmax > 1) {\n\t\t\t\t\t\tqmax = 1;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tduk__append_reop(re_ctx, DUK_REOP_MATCH);   /* complete 'sub atom' */\n\t\t\t\tatom_code_length = (duk_int32_t) (DUK__RE_BUFLEN(re_ctx) - (duk_size_t) atom_start_offset);\n\n\t\t\t\toffset = (duk_uint32_t) atom_start_offset;\n\t\t\t\tif (re_ctx->curr_token.greedy) {\n\t\t\t\t\toffset += duk__insert_u32(re_ctx, offset, DUK_REOP_SQGREEDY);\n\t\t\t\t\toffset += duk__insert_u32(re_ctx, offset, qmin);\n\t\t\t\t\toffset += duk__insert_u32(re_ctx, offset, qmax);\n\t\t\t\t\toffset += duk__insert_u32(re_ctx, offset, (duk_uint32_t) atom_char_length);\n\t\t\t\t\toffset += duk__insert_jump_offset(re_ctx, offset, atom_code_length);\n\t\t\t\t} else {\n\t\t\t\t\toffset += duk__insert_u32(re_ctx, offset, DUK_REOP_SQMINIMAL);\n\t\t\t\t\toffset += duk__insert_u32(re_ctx, offset, qmin);\n\t\t\t\t\toffset += duk__insert_u32(re_ctx, offset, qmax);\n\t\t\t\t\toffset += duk__insert_jump_offset(re_ctx, offset, atom_code_length);\n\t\t\t\t}\n\t\t\t\tDUK_UNREF(offset);  /* silence scan-build warning */\n\t\t\t} else {\n\t\t\t\t/*\n\t\t\t\t *  Complex atom\n\t\t\t\t *\n\t\t\t\t *  The original code is used as a template, and removed at the end\n\t\t\t\t *  (this differs from the handling of simple quantifiers).\n\t\t\t\t *\n\t\t\t\t *  NOTE: there is no current solution for empty atoms in complex\n\t\t\t\t *  quantifiers.  This would need some sort of a 'progress' instruction.\n\t\t\t\t *\n\t\t\t\t *  XXX: impose limit on maximum result size, i.e. atom_code_len * atom_copies?\n\t\t\t\t */\n\t\t\t\tduk_int32_t atom_code_length;\n\t\t\t\tduk_uint32_t atom_copies;\n\t\t\t\tduk_uint32_t tmp_qmin, tmp_qmax;\n\n\t\t\t\t/* pre-check how many atom copies we're willing to make (atom_copies not needed below) */\n\t\t\t\tatom_copies = (re_ctx->curr_token.qmax == DUK_RE_QUANTIFIER_INFINITE) ?\n\t\t\t\t              re_ctx->curr_token.qmin : re_ctx->curr_token.qmax;\n\t\t\t\tif (atom_copies > DUK_RE_MAX_ATOM_COPIES) {\n\t\t\t\t\tDUK_ERROR_RANGE(re_ctx->thr, DUK_STR_QUANTIFIER_TOO_MANY_COPIES);\n\t\t\t\t}\n\n\t\t\t\t/* wipe the capture range made by the atom (if any) */\n\t\t\t\tDUK_ASSERT(atom_start_captures <= re_ctx->captures);\n\t\t\t\tif (atom_start_captures != re_ctx->captures) {\n\t\t\t\t\tDUK_ASSERT(atom_start_captures < re_ctx->captures);\n\t\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"must wipe ]atom_start_captures,re_ctx->captures]: ]%ld,%ld]\",\n\t\t\t\t\t                     (long) atom_start_captures, (long) re_ctx->captures));\n\n\t\t\t\t\t/* insert (DUK_REOP_WIPERANGE, start, count) in reverse order so the order ends up right */\n\t\t\t\t\tduk__insert_u32(re_ctx, (duk_uint32_t) atom_start_offset, (re_ctx->captures - atom_start_captures) * 2U);\n\t\t\t\t\tduk__insert_u32(re_ctx, (duk_uint32_t) atom_start_offset, (atom_start_captures + 1) * 2);\n\t\t\t\t\tduk__insert_u32(re_ctx, (duk_uint32_t) atom_start_offset, DUK_REOP_WIPERANGE);\n\t\t\t\t} else {\n\t\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"no need to wipe captures: atom_start_captures == re_ctx->captures == %ld\",\n\t\t\t\t\t                     (long) atom_start_captures));\n\t\t\t\t}\n\n\t\t\t\tatom_code_length = (duk_int32_t) DUK__RE_BUFLEN(re_ctx) - atom_start_offset;\n\n\t\t\t\t/* insert the required matches (qmin) by copying the atom */\n\t\t\t\ttmp_qmin = re_ctx->curr_token.qmin;\n\t\t\t\ttmp_qmax = re_ctx->curr_token.qmax;\n\t\t\t\twhile (tmp_qmin > 0) {\n\t\t\t\t\tduk__append_slice(re_ctx, (duk_uint32_t) atom_start_offset, (duk_uint32_t) atom_code_length);\n\t\t\t\t\ttmp_qmin--;\n\t\t\t\t\tif (tmp_qmax != DUK_RE_QUANTIFIER_INFINITE) {\n\t\t\t\t\t\ttmp_qmax--;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tDUK_ASSERT(tmp_qmin == 0);\n\n\t\t\t\t/* insert code for matching the remainder - infinite or finite */\n\t\t\t\tif (tmp_qmax == DUK_RE_QUANTIFIER_INFINITE) {\n\t\t\t\t\t/* reuse last emitted atom for remaining 'infinite' quantifier */\n\n\t\t\t\t\tif (re_ctx->curr_token.qmin == 0) {\n\t\t\t\t\t\t/* Special case: original qmin was zero so there is nothing\n\t\t\t\t\t\t * to repeat.  Emit an atom copy but jump over it here.\n\t\t\t\t\t\t */\n\t\t\t\t\t\tduk__append_reop(re_ctx, DUK_REOP_JUMP);\n\t\t\t\t\t\tduk__append_jump_offset(re_ctx, atom_code_length);\n\t\t\t\t\t\tduk__append_slice(re_ctx, (duk_uint32_t) atom_start_offset, (duk_uint32_t) atom_code_length);\n\t\t\t\t\t}\n\t\t\t\t\tif (re_ctx->curr_token.greedy) {\n\t\t\t\t\t\tduk__append_reop(re_ctx, DUK_REOP_SPLIT2);   /* prefer jump */\n\t\t\t\t\t} else {\n\t\t\t\t\t\tduk__append_reop(re_ctx, DUK_REOP_SPLIT1);   /* prefer direct */\n\t\t\t\t\t}\n\t\t\t\t\tduk__append_jump_offset(re_ctx, -atom_code_length - 1);  /* -1 for opcode */\n\t\t\t\t} else {\n\t\t\t\t\t/*\n\t\t\t\t\t *  The remaining matches are emitted as sequence of SPLITs and atom\n\t\t\t\t\t *  copies; the SPLITs skip the remaining copies and match the sequel.\n\t\t\t\t\t *  This sequence needs to be emitted starting from the last copy\n\t\t\t\t\t *  because the SPLITs are variable length due to the variable length\n\t\t\t\t\t *  skip offset.  This causes a lot of memory copying now.\n\t\t\t\t\t *\n\t\t\t\t\t *  Example structure (greedy, match maximum # atoms):\n\t\t\t\t\t *\n\t\t\t\t\t *      SPLIT1 LSEQ\n\t\t\t\t\t *      (atom)\n\t\t\t\t\t *      SPLIT1 LSEQ    ; <- the byte length of this instruction is needed\n\t\t\t\t\t *      (atom)         ; to encode the above SPLIT1 correctly\n\t\t\t\t\t *      ...\n\t\t\t\t\t *   LSEQ:\n\t\t\t\t\t */\n\t\t\t\t\tduk_uint32_t offset = (duk_uint32_t) DUK__RE_BUFLEN(re_ctx);\n\t\t\t\t\twhile (tmp_qmax > 0) {\n\t\t\t\t\t\tduk__insert_slice(re_ctx, offset, (duk_uint32_t) atom_start_offset, (duk_uint32_t) atom_code_length);\n\t\t\t\t\t\tif (re_ctx->curr_token.greedy) {\n\t\t\t\t\t\t\tduk__insert_u32(re_ctx, offset, DUK_REOP_SPLIT1);   /* prefer direct */\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tduk__insert_u32(re_ctx, offset, DUK_REOP_SPLIT2);   /* prefer jump */\n\t\t\t\t\t\t}\n\t\t\t\t\t\tduk__insert_jump_offset(re_ctx,\n\t\t\t\t\t\t                        offset + 1,   /* +1 for opcode */\n\t\t\t\t\t\t                        (duk_int32_t) (DUK__RE_BUFLEN(re_ctx) - (offset + 1)));\n\t\t\t\t\t\ttmp_qmax--;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t/* remove the original 'template' atom */\n\t\t\t\tduk__remove_slice(re_ctx, (duk_uint32_t) atom_start_offset, (duk_uint32_t) atom_code_length);\n\t\t\t}\n\n\t\t\t/* 'taint' result as complex */\n\t\t\tres_charlen = -1;\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_RETOK_ASSERT_START: {\n\t\t\tduk__append_reop(re_ctx, DUK_REOP_ASSERT_START);\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_RETOK_ASSERT_END: {\n\t\t\tduk__append_reop(re_ctx, DUK_REOP_ASSERT_END);\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_RETOK_ASSERT_WORD_BOUNDARY: {\n\t\t\tduk__append_reop(re_ctx, DUK_REOP_ASSERT_WORD_BOUNDARY);\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_RETOK_ASSERT_NOT_WORD_BOUNDARY: {\n\t\t\tduk__append_reop(re_ctx, DUK_REOP_ASSERT_NOT_WORD_BOUNDARY);\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_RETOK_ASSERT_START_POS_LOOKAHEAD:\n\t\tcase DUK_RETOK_ASSERT_START_NEG_LOOKAHEAD: {\n\t\t\tduk_uint32_t offset;\n\t\t\tduk_uint32_t opcode = (re_ctx->curr_token.t == DUK_RETOK_ASSERT_START_POS_LOOKAHEAD) ?\n\t\t\t                      DUK_REOP_LOOKPOS : DUK_REOP_LOOKNEG;\n\n\t\t\toffset = (duk_uint32_t) DUK__RE_BUFLEN(re_ctx);\n\t\t\tduk__parse_disjunction(re_ctx, 0, &tmp_disj);\n\t\t\tduk__append_reop(re_ctx, DUK_REOP_MATCH);\n\n\t\t\t(void) duk__insert_u32(re_ctx, offset, opcode);\n\t\t\t(void) duk__insert_jump_offset(re_ctx,\n\t\t\t                               offset + 1,   /* +1 for opcode */\n\t\t\t                               (duk_int32_t) (DUK__RE_BUFLEN(re_ctx) - (offset + 1)));\n\n\t\t\t/* 'taint' result as complex -- this is conservative,\n\t\t\t * as lookaheads do not backtrack.\n\t\t\t */\n\t\t\tres_charlen = -1;\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_RETOK_ATOM_PERIOD: {\n\t\t\tnew_atom_char_length = 1;\n\t\t\tnew_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);\n\t\t\tduk__append_reop(re_ctx, DUK_REOP_PERIOD);\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_RETOK_ATOM_CHAR: {\n\t\t\t/* Note: successive characters could be joined into string matches\n\t\t\t * but this is not trivial (consider e.g. '/xyz+/); see docs for\n\t\t\t * more discussion.\n\t\t\t *\n\t\t\t * No support for \\u{H+} yet.  While only BMP Unicode escapes are\n\t\t\t * supported for RegExps at present, 'ch' may still be a non-BMP\n\t\t\t * codepoint if it is decoded straight from source text UTF-8.\n\t\t\t * There's no non-BMP support yet so this is handled simply by\n\t\t\t * matching the non-BMP character (which is custom behavior).\n\t\t\t */\n\t\t\tduk_uint32_t ch;\n\n\t\t\tnew_atom_char_length = 1;\n\t\t\tnew_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);\n\t\t\tduk__append_reop(re_ctx, DUK_REOP_CHAR);\n\t\t\tch = re_ctx->curr_token.num;\n\t\t\tif (re_ctx->re_flags & DUK_RE_FLAG_IGNORE_CASE) {\n\t\t\t\tch = (duk_uint32_t) duk_unicode_re_canonicalize_char(re_ctx->thr, (duk_codepoint_t) ch);\n\t\t\t}\n\t\t\tduk__append_u32(re_ctx, ch);\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_RETOK_ATOM_DIGIT:\n\t\tcase DUK_RETOK_ATOM_NOT_DIGIT:\n\t\tcase DUK_RETOK_ATOM_WHITE:\n\t\tcase DUK_RETOK_ATOM_NOT_WHITE:\n\t\tcase DUK_RETOK_ATOM_WORD_CHAR:\n\t\tcase DUK_RETOK_ATOM_NOT_WORD_CHAR: {\n\t\t\tduk_small_uint_t re_op;\n\t\t\tduk_small_uint_t idx;\n\n\t\t\tnew_atom_char_length = 1;\n\t\t\tnew_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);\n\n\t\t\tDUK_ASSERT((DUK_RETOK_ATOM_DIGIT & 0x01) != 0);\n\t\t\tDUK_ASSERT((DUK_RETOK_ATOM_WHITE & 0x01) != 0);\n\t\t\tDUK_ASSERT((DUK_RETOK_ATOM_WORD_CHAR & 0x01) != 0);\n\t\t\tDUK_ASSERT((DUK_RETOK_ATOM_NOT_DIGIT & 0x01) == 0);\n\t\t\tDUK_ASSERT((DUK_RETOK_ATOM_NOT_WHITE & 0x01) == 0);\n\t\t\tDUK_ASSERT((DUK_RETOK_ATOM_NOT_WORD_CHAR & 0x01) == 0);\n\t\t\tre_op = (re_ctx->curr_token.t & 0x01) ? DUK_REOP_RANGES : DUK_REOP_INVRANGES;\n\n\t\t\tDUK_ASSERT(DUK_RETOK_ATOM_WHITE == DUK_RETOK_ATOM_DIGIT + 2);\n\t\t\tDUK_ASSERT(DUK_RETOK_ATOM_WORD_CHAR == DUK_RETOK_ATOM_DIGIT + 4);\n\t\t\tidx = (duk_small_uint_t) ((re_ctx->curr_token.t - DUK_RETOK_ATOM_DIGIT) >> 1U);\n\t\t\tDUK_ASSERT(idx <= 2U);  /* Assume continuous token numbers; also checks negative underflow. */\n\n\t\t\tduk__append_range_atom_matcher(re_ctx, re_op, duk__re_range_lookup1[idx], duk__re_range_lookup2[idx]);\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_RETOK_ATOM_BACKREFERENCE: {\n\t\t\tduk_uint32_t backref = (duk_uint32_t) re_ctx->curr_token.num;\n\t\t\tif (backref > re_ctx->highest_backref) {\n\t\t\t\tre_ctx->highest_backref = backref;\n\t\t\t}\n\t\t\tnew_atom_char_length = -1;   /* mark as complex */\n\t\t\tnew_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);\n\t\t\tduk__append_reop(re_ctx, DUK_REOP_BACKREFERENCE);\n\t\t\tduk__append_u32(re_ctx, backref);\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_RETOK_ATOM_START_CAPTURE_GROUP: {\n\t\t\tduk_uint32_t cap;\n\n\t\t\tnew_atom_char_length = -1;   /* mark as complex (capture handling) */\n\t\t\tnew_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);\n\t\t\tcap = ++re_ctx->captures;\n\t\t\tduk__append_reop(re_ctx, DUK_REOP_SAVE);\n\t\t\tduk__append_u32(re_ctx, cap * 2);\n\t\t\tduk__parse_disjunction(re_ctx, 0, &tmp_disj);  /* retval (sub-atom char length) unused, tainted as complex above */\n\t\t\tduk__append_reop(re_ctx, DUK_REOP_SAVE);\n\t\t\tduk__append_u32(re_ctx, cap * 2 + 1);\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_RETOK_ATOM_START_NONCAPTURE_GROUP: {\n\t\t\tnew_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);\n\t\t\tduk__parse_disjunction(re_ctx, 0, &tmp_disj);\n\t\t\tnew_atom_char_length = tmp_disj.charlen;\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_RETOK_ATOM_START_CHARCLASS:\n\t\tcase DUK_RETOK_ATOM_START_CHARCLASS_INVERTED: {\n\t\t\t/*\n\t\t\t *  Range parsing is done with a special lexer function which calls\n\t\t\t *  us for every range parsed.  This is different from how rest of\n\t\t\t *  the parsing works, but avoids a heavy, arbitrary size intermediate\n\t\t\t *  value type to hold the ranges.\n\t\t\t *\n\t\t\t *  Another complication is the handling of character ranges when\n\t\t\t *  case insensitive matching is used (see docs for discussion).\n\t\t\t *  The range handler callback given to the lexer takes care of this\n\t\t\t *  as well.\n\t\t\t *\n\t\t\t *  Note that duplicate ranges are not eliminated when parsing character\n\t\t\t *  classes, so that canonicalization of\n\t\t\t *\n\t\t\t *    [0-9a-fA-Fx-{]\n\t\t\t *\n\t\t\t *  creates the result (note the duplicate ranges):\n\t\t\t *\n\t\t\t *    [0-9A-FA-FX-Z{-{]\n\t\t\t *\n\t\t\t *  where [x-{] is split as a result of canonicalization.  The duplicate\n\t\t\t *  ranges are not a semantics issue: they work correctly.\n\t\t\t */\n\n\t\t\tduk_uint32_t offset;\n\n\t\t\tDUK_DD(DUK_DDPRINT(\"character class\"));\n\n\t\t\t/* insert ranges instruction, range count patched in later */\n\t\t\tnew_atom_char_length = 1;\n\t\t\tnew_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);\n\t\t\tduk__append_reop(re_ctx,\n\t\t\t                 (re_ctx->curr_token.t == DUK_RETOK_ATOM_START_CHARCLASS) ?\n\t\t\t                 DUK_REOP_RANGES : DUK_REOP_INVRANGES);\n\t\t\toffset = (duk_uint32_t) DUK__RE_BUFLEN(re_ctx);    /* patch in range count later */\n\n\t\t\t/* parse ranges until character class ends */\n\t\t\tre_ctx->nranges = 0;    /* note: ctx-wide temporary */\n\t\t\tduk_lexer_parse_re_ranges(&re_ctx->lex, duk__regexp_generate_ranges, (void *) re_ctx);\n\n\t\t\t/* insert range count */\n\t\t\tduk__insert_u32(re_ctx, offset, re_ctx->nranges);\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_RETOK_ATOM_END_GROUP: {\n\t\t\tif (expect_eof) {\n\t\t\t\tDUK_ERROR_SYNTAX(re_ctx->thr, DUK_STR_UNEXPECTED_CLOSING_PAREN);\n\t\t\t}\n\t\t\tgoto done;\n\t\t}\n\t\tcase DUK_RETOK_EOF: {\n\t\t\tif (!expect_eof) {\n\t\t\t\tDUK_ERROR_SYNTAX(re_ctx->thr, DUK_STR_UNEXPECTED_END_OF_PATTERN);\n\t\t\t}\n\t\t\tgoto done;\n\t\t}\n\t\tdefault: {\n\t\t\tDUK_ERROR_SYNTAX(re_ctx->thr, DUK_STR_UNEXPECTED_REGEXP_TOKEN);\n\t\t}\n\t\t}\n\n\t\t/* a complex (new) atom taints the result */\n\t\tif (new_atom_start_offset >= 0) {\n\t\t\tif (new_atom_char_length < 0) {\n\t\t\t\tres_charlen = -1;\n\t\t\t} else if (res_charlen >= 0) {\n\t\t\t\t/* only advance if not tainted */\n\t\t\t\tres_charlen += new_atom_char_length;\n\t\t\t}\n\t\t}\n\n\t\t/* record previous atom info in case next token is a quantifier */\n\t\tatom_start_offset = new_atom_start_offset;\n\t\tatom_char_length = new_atom_char_length;\n\t\tatom_start_captures = new_atom_start_captures;\n\t}\n\n done:\n\n\t/* finish up pending jump and split for last alternative */\n\tif (unpatched_disjunction_jump >= 0) {\n\t\tduk_uint32_t offset;\n\n\t\tDUK_ASSERT(unpatched_disjunction_split >= 0);\n\t\toffset = (duk_uint32_t) unpatched_disjunction_jump;\n\t\toffset += duk__insert_jump_offset(re_ctx,\n\t\t                                  offset,\n\t\t                                  (duk_int32_t) (DUK__RE_BUFLEN(re_ctx) - offset));\n\t\t/* offset is now target of the pending split (right after jump) */\n\t\tduk__insert_jump_offset(re_ctx,\n\t\t                        (duk_uint32_t) unpatched_disjunction_split,\n\t\t                        (duk_int32_t) offset - unpatched_disjunction_split);\n\t}\n\n#if 0\n\tout_atom_info->end_captures = re_ctx->captures;\n#endif\n\tout_atom_info->charlen = res_charlen;\n\tDUK_DDD(DUK_DDDPRINT(\"parse disjunction finished: charlen=%ld\",\n\t                     (long) out_atom_info->charlen));\n\n\tre_ctx->recursion_depth--;\n}\n\n/*\n *  Flags parsing (see E5 Section 15.10.4.1).\n */\n\nDUK_LOCAL duk_uint32_t duk__parse_regexp_flags(duk_hthread *thr, duk_hstring *h) {\n\tconst duk_uint8_t *p;\n\tconst duk_uint8_t *p_end;\n\tduk_uint32_t flags = 0;\n\n\tp = DUK_HSTRING_GET_DATA(h);\n\tp_end = p + DUK_HSTRING_GET_BYTELEN(h);\n\n\t/* Note: can be safely scanned as bytes (undecoded) */\n\n\twhile (p < p_end) {\n\t\tduk_uint8_t c = *p++;\n\t\tswitch (c) {\n\t\tcase (duk_uint8_t) 'g': {\n\t\t\tif (flags & DUK_RE_FLAG_GLOBAL) {\n\t\t\t\tgoto flags_error;\n\t\t\t}\n\t\t\tflags |= DUK_RE_FLAG_GLOBAL;\n\t\t\tbreak;\n\t\t}\n\t\tcase (duk_uint8_t) 'i': {\n\t\t\tif (flags & DUK_RE_FLAG_IGNORE_CASE) {\n\t\t\t\tgoto flags_error;\n\t\t\t}\n\t\t\tflags |= DUK_RE_FLAG_IGNORE_CASE;\n\t\t\tbreak;\n\t\t}\n\t\tcase (duk_uint8_t) 'm': {\n\t\t\tif (flags & DUK_RE_FLAG_MULTILINE) {\n\t\t\t\tgoto flags_error;\n\t\t\t}\n\t\t\tflags |= DUK_RE_FLAG_MULTILINE;\n\t\t\tbreak;\n\t\t}\n\t\tdefault: {\n\t\t\tgoto flags_error;\n\t\t}\n\t\t}\n\t}\n\n\treturn flags;\n\n flags_error:\n\tDUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_REGEXP_FLAGS);\n\treturn 0;  /* never here */\n}\n\n/*\n *  Create escaped RegExp source (E5 Section 15.10.3).\n *\n *  The current approach is to special case the empty RegExp\n *  ('' -> '(?:)') and otherwise replace unescaped '/' characters\n *  with '\\/' regardless of where they occur in the regexp.\n *\n *  Note that normalization does not seem to be necessary for\n *  RegExp literals (e.g. '/foo/') because to be acceptable as\n *  a RegExp literal, the text between forward slashes must\n *  already match the escaping requirements (e.g. must not contain\n *  unescaped forward slashes or be empty).  Escaping IS needed\n *  for expressions like 'new Regexp(\"...\", \"\")' however.\n *  Currently, we re-escape in either case.\n *\n *  Also note that we process the source here in UTF-8 encoded\n *  form.  This is correct, because any non-ASCII characters are\n *  passed through without change.\n */\n\nDUK_LOCAL void duk__create_escaped_source(duk_hthread *thr, int idx_pattern) {\n\tduk_hstring *h;\n\tconst duk_uint8_t *p;\n\tduk_bufwriter_ctx bw_alloc;\n\tduk_bufwriter_ctx *bw;\n\tduk_uint8_t *q;\n\tduk_size_t i, n;\n\tduk_uint_fast8_t c_prev, c;\n\n\th = duk_known_hstring(thr, idx_pattern);\n\tp = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h);\n\tn = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h);\n\n\tif (n == 0) {\n\t\tduk_push_string(thr, \"(?:)\");\n\t\treturn;\n\t}\n\n\tbw = &bw_alloc;\n\tDUK_BW_INIT_PUSHBUF(thr, bw, n);\n\tq = DUK_BW_GET_PTR(thr, bw);\n\n\tc_prev = (duk_uint_fast8_t) 0;\n\n\tfor (i = 0; i < n; i++) {\n\t\tc = p[i];\n\n\t\tq = DUK_BW_ENSURE_RAW(thr, bw, 2, q);\n\n\t\tif (c == (duk_uint_fast8_t) '/' && c_prev != (duk_uint_fast8_t) '\\\\') {\n\t\t\t/* Unescaped '/' ANYWHERE in the regexp (in disjunction,\n\t\t\t * inside a character class, ...) => same escape works.\n\t\t\t */\n\t\t\t*q++ = DUK_ASC_BACKSLASH;\n\t\t}\n\t\t*q++ = (duk_uint8_t) c;\n\n\t\tc_prev = c;\n\t}\n\n\tDUK_BW_SETPTR_AND_COMPACT(thr, bw, q);\n\t(void) duk_buffer_to_string(thr, -1);  /* Safe if input is safe. */\n\n\t/* [ ... escaped_source ] */\n}\n\n/*\n *  Exposed regexp compilation primitive.\n *\n *  Sets up a regexp compilation context, and calls duk__parse_disjunction() to do the\n *  actual parsing.  Handles generation of the compiled regexp header and the\n *  \"boilerplate\" capture of the matching substring (save 0 and 1).  Also does some\n *  global level regexp checks after recursive compilation has finished.\n *\n *  An escaped version of the regexp source, suitable for use as a RegExp instance\n *  'source' property (see E5 Section 15.10.3), is also left on the stack.\n *\n *  Input stack:  [ pattern flags ]\n *  Output stack: [ bytecode escaped_source ]  (both as strings)\n */\n\nDUK_INTERNAL void duk_regexp_compile(duk_hthread *thr) {\n\tduk_re_compiler_ctx re_ctx;\n\tduk_lexer_point lex_point;\n\tduk_hstring *h_pattern;\n\tduk_hstring *h_flags;\n\tduk__re_disjunction_info ign_disj;\n\n\tDUK_ASSERT(thr != NULL);\n\n\t/*\n\t *  Args validation\n\t */\n\n\t/* TypeError if fails */\n\th_pattern = duk_require_hstring_notsymbol(thr, -2);\n\th_flags = duk_require_hstring_notsymbol(thr, -1);\n\n\t/*\n\t *  Create normalized 'source' property (E5 Section 15.10.3).\n\t */\n\n\t/* [ ... pattern flags ] */\n\n\tduk__create_escaped_source(thr, -2);\n\n\t/* [ ... pattern flags escaped_source ] */\n\n\t/*\n\t *  Init compilation context\n\t */\n\n\t/* [ ... pattern flags escaped_source buffer ] */\n\n\tDUK_MEMZERO(&re_ctx, sizeof(re_ctx));\n\tDUK_LEXER_INITCTX(&re_ctx.lex);  /* duplicate zeroing, expect for (possible) NULL inits */\n\tre_ctx.thr = thr;\n\tre_ctx.lex.thr = thr;\n\tre_ctx.lex.input = DUK_HSTRING_GET_DATA(h_pattern);\n\tre_ctx.lex.input_length = DUK_HSTRING_GET_BYTELEN(h_pattern);\n\tre_ctx.lex.token_limit = DUK_RE_COMPILE_TOKEN_LIMIT;\n\tre_ctx.recursion_limit = DUK_USE_REGEXP_COMPILER_RECLIMIT;\n\tre_ctx.re_flags = duk__parse_regexp_flags(thr, h_flags);\n\n\tDUK_BW_INIT_PUSHBUF(thr, &re_ctx.bw, DUK__RE_INITIAL_BUFSIZE);\n\n\tDUK_DD(DUK_DDPRINT(\"regexp compiler ctx initialized, flags=0x%08lx, recursion_limit=%ld\",\n\t                   (unsigned long) re_ctx.re_flags, (long) re_ctx.recursion_limit));\n\n\t/*\n\t *  Init lexer\n\t */\n\n\tlex_point.offset = 0;  /* expensive init, just want to fill window */\n\tlex_point.line = 1;\n\tDUK_LEXER_SETPOINT(&re_ctx.lex, &lex_point);\n\n\t/*\n\t *  Compilation\n\t */\n\n\tDUK_DD(DUK_DDPRINT(\"starting regexp compilation\"));\n\n\tduk__append_reop(&re_ctx, DUK_REOP_SAVE);\n\tduk__append_7bit(&re_ctx, 0);\n\tduk__parse_disjunction(&re_ctx, 1 /*expect_eof*/, &ign_disj);\n\tduk__append_reop(&re_ctx, DUK_REOP_SAVE);\n\tduk__append_7bit(&re_ctx, 1);\n\tduk__append_reop(&re_ctx, DUK_REOP_MATCH);\n\n\t/*\n\t *  Check for invalid backreferences; note that it is NOT an error\n\t *  to back-reference a capture group which has not yet been introduced\n\t *  in the pattern (as in /\\1(foo)/); in fact, the backreference will\n\t *  always match!  It IS an error to back-reference a capture group\n\t *  which will never be introduced in the pattern.  Thus, we can check\n\t *  for such references only after parsing is complete.\n\t */\n\n\tif (re_ctx.highest_backref > re_ctx.captures) {\n\t\tDUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_BACKREFS);\n\t}\n\n\t/*\n\t *  Emit compiled regexp header: flags, ncaptures\n\t *  (insertion order inverted on purpose)\n\t */\n\n\tduk__insert_u32(&re_ctx, 0, (re_ctx.captures + 1) * 2);\n\tduk__insert_u32(&re_ctx, 0, re_ctx.re_flags);\n\n\t/* [ ... pattern flags escaped_source buffer ] */\n\n\tDUK_BW_COMPACT(thr, &re_ctx.bw);\n\t(void) duk_buffer_to_string(thr, -1);  /* Safe because flags is at most 7 bit. */\n\n\t/* [ ... pattern flags escaped_source bytecode ] */\n\n\t/*\n\t *  Finalize stack\n\t */\n\n\tduk_remove(thr, -4);     /* -> [ ... flags escaped_source bytecode ] */\n\tduk_remove(thr, -3);     /* -> [ ... escaped_source bytecode ] */\n\n\tDUK_DD(DUK_DDPRINT(\"regexp compilation successful, bytecode: %!T, escaped source: %!T\",\n\t                   (duk_tval *) duk_get_tval(thr, -1), (duk_tval *) duk_get_tval(thr, -2)));\n}\n\n/*\n *  Create a RegExp instance (E5 Section 15.10.7).\n *\n *  Note: the output stack left by duk_regexp_compile() is directly compatible\n *  with the input here.\n *\n *  Input stack:  [ escaped_source bytecode ]  (both as strings)\n *  Output stack: [ RegExp ]\n */\n\nDUK_INTERNAL void duk_regexp_create_instance(duk_hthread *thr) {\n\tduk_hobject *h;\n\n\t/* [ ... escaped_source bytecode ] */\n\n\tduk_push_object(thr);\n\th = duk_known_hobject(thr, -1);\n\tduk_insert(thr, -3);\n\n\t/* [ ... regexp_object escaped_source bytecode ] */\n\n\tDUK_HOBJECT_SET_CLASS_NUMBER(h, DUK_HOBJECT_CLASS_REGEXP);\n\tDUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, h, thr->builtins[DUK_BIDX_REGEXP_PROTOTYPE]);\n\n\tduk_xdef_prop_stridx_short(thr, -3, DUK_STRIDX_INT_BYTECODE, DUK_PROPDESC_FLAGS_NONE);\n\n\t/* [ ... regexp_object escaped_source ] */\n\n\t/* In ES2015 .source, and the .global, .multiline, etc flags are\n\t * inherited getters.  Store the escaped source as an internal\n\t * property for the getter.\n\t */\n\n\tduk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_SOURCE, DUK_PROPDESC_FLAGS_NONE);\n\n\t/* [ ... regexp_object ] */\n\n\tduk_push_int(thr, 0);\n\tduk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_LAST_INDEX, DUK_PROPDESC_FLAGS_W);\n\n\t/* [ ... regexp_object ] */\n}\n\n#else  /* DUK_USE_REGEXP_SUPPORT */\n\n/* regexp support disabled */\n\n#endif  /* DUK_USE_REGEXP_SUPPORT */\n\n/* automatic undefs */\n#undef DUK__RE_BUFLEN\n#undef DUK__RE_INITIAL_BUFSIZE\n#line 1 \"duk_regexp_executor.c\"\n/*\n *  Regexp executor.\n *\n *  Safety: the Ecmascript executor should prevent user from reading and\n *  replacing regexp bytecode.  Even so, the executor must validate all\n *  memory accesses etc.  When an invalid access is detected (e.g. a 'save'\n *  opcode to invalid, unallocated index) it should fail with an internal\n *  error but not cause a segmentation fault.\n *\n *  Notes:\n *\n *    - Backtrack counts are limited to unsigned 32 bits but should\n *      technically be duk_size_t for strings longer than 4G chars.\n *      This also requires a regexp bytecode change.\n */\n\n/* #include duk_internal.h -> already included */\n\n#if defined(DUK_USE_REGEXP_SUPPORT)\n\n/*\n *  Helpers for UTF-8 handling\n *\n *  For bytecode readers the duk_uint32_t and duk_int32_t types are correct\n *  because they're used for more than just codepoints.\n */\n\nDUK_LOCAL duk_uint32_t duk__bc_get_u32(duk_re_matcher_ctx *re_ctx, const duk_uint8_t **pc) {\n\treturn (duk_uint32_t) duk_unicode_decode_xutf8_checked(re_ctx->thr, pc, re_ctx->bytecode, re_ctx->bytecode_end);\n}\n\nDUK_LOCAL duk_int32_t duk__bc_get_i32(duk_re_matcher_ctx *re_ctx, const duk_uint8_t **pc) {\n\tduk_uint32_t t;\n\n\t/* signed integer encoding needed to work with UTF-8 */\n\tt = (duk_uint32_t) duk_unicode_decode_xutf8_checked(re_ctx->thr, pc, re_ctx->bytecode, re_ctx->bytecode_end);\n\tif (t & 1) {\n\t\treturn -((duk_int32_t) (t >> 1));\n\t} else {\n\t\treturn (duk_int32_t) (t >> 1);\n\t}\n}\n\nDUK_LOCAL const duk_uint8_t *duk__utf8_backtrack(duk_hthread *thr, const duk_uint8_t **ptr, const duk_uint8_t *ptr_start, const duk_uint8_t *ptr_end, duk_uint_fast32_t count) {\n\tconst duk_uint8_t *p;\n\n\t/* Note: allow backtracking from p == ptr_end */\n\tp = *ptr;\n\tif (p < ptr_start || p > ptr_end) {\n\t\tgoto fail;\n\t}\n\n\twhile (count > 0) {\n\t\tfor (;;) {\n\t\t\tp--;\n\t\t\tif (p < ptr_start) {\n\t\t\t\tgoto fail;\n\t\t\t}\n\t\t\tif ((*p & 0xc0) != 0x80) {\n\t\t\t\t/* utf-8 continuation bytes have the form 10xx xxxx */\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tcount--;\n\t}\n\t*ptr = p;\n\treturn p;\n\n fail:\n\tDUK_ERROR_INTERNAL(thr);\n\treturn NULL;  /* never here */\n}\n\nDUK_LOCAL const duk_uint8_t *duk__utf8_advance(duk_hthread *thr, const duk_uint8_t **ptr, const duk_uint8_t *ptr_start, const duk_uint8_t *ptr_end, duk_uint_fast32_t count) {\n\tconst duk_uint8_t *p;\n\n\tp = *ptr;\n\tif (p < ptr_start || p >= ptr_end) {\n\t\tgoto fail;\n\t}\n\n\twhile (count > 0) {\n\t\tfor (;;) {\n\t\t\tp++;\n\n\t\t\t/* Note: if encoding ends by hitting end of input, we don't check that\n\t\t\t * the encoding is valid, we just assume it is.\n\t\t\t */\n\t\t\tif (p >= ptr_end || ((*p & 0xc0) != 0x80)) {\n\t\t\t\t/* utf-8 continuation bytes have the form 10xx xxxx */\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tcount--;\n\t}\n\n\t*ptr = p;\n\treturn p;\n\n fail:\n\tDUK_ERROR_INTERNAL(thr);\n\treturn NULL;  /* never here */\n}\n\n/*\n *  Helpers for dealing with the input string\n */\n\n/* Get a (possibly canonicalized) input character from current sp.  The input\n * itself is never modified, and captures always record non-canonicalized\n * characters even in case-insensitive matching.  Return <0 if out of input.\n */\nDUK_LOCAL duk_codepoint_t duk__inp_get_cp(duk_re_matcher_ctx *re_ctx, const duk_uint8_t **sp) {\n\tduk_codepoint_t res;\n\n\tif (*sp >= re_ctx->input_end) {\n\t\treturn -1;\n\t}\n\tres = (duk_codepoint_t) duk_unicode_decode_xutf8_checked(re_ctx->thr, sp, re_ctx->input, re_ctx->input_end);\n\tif (re_ctx->re_flags & DUK_RE_FLAG_IGNORE_CASE) {\n\t\tres = duk_unicode_re_canonicalize_char(re_ctx->thr, res);\n\t}\n\treturn res;\n}\n\nDUK_LOCAL const duk_uint8_t *duk__inp_backtrack(duk_re_matcher_ctx *re_ctx, const duk_uint8_t **sp, duk_uint_fast32_t count) {\n\treturn duk__utf8_backtrack(re_ctx->thr, sp, re_ctx->input, re_ctx->input_end, count);\n}\n\n/* Backtrack utf-8 input and return a (possibly canonicalized) input character. */\nDUK_LOCAL duk_codepoint_t duk__inp_get_prev_cp(duk_re_matcher_ctx *re_ctx, const duk_uint8_t *sp) {\n\t/* note: caller 'sp' is intentionally not updated here */\n\t(void) duk__inp_backtrack(re_ctx, &sp, (duk_uint_fast32_t) 1);\n\treturn duk__inp_get_cp(re_ctx, &sp);\n}\n\n/*\n *  Regexp recursive matching function.\n *\n *  Returns 'sp' on successful match (points to character after last matched one),\n *  NULL otherwise.\n *\n *  The C recursion depth limit check is only performed in this function, this\n *  suffices because the function is present in all true recursion required by\n *  regexp execution.\n */\n\nDUK_LOCAL const duk_uint8_t *duk__match_regexp(duk_re_matcher_ctx *re_ctx, const duk_uint8_t *pc, const duk_uint8_t *sp) {\n\tif (re_ctx->recursion_depth >= re_ctx->recursion_limit) {\n\t\tDUK_ERROR_RANGE(re_ctx->thr, DUK_STR_REGEXP_EXECUTOR_RECURSION_LIMIT);\n\t}\n\tre_ctx->recursion_depth++;\n\n\tfor (;;) {\n\t\tduk_small_int_t op;\n\n\t\tif (re_ctx->steps_count >= re_ctx->steps_limit) {\n\t\t\tDUK_ERROR_RANGE(re_ctx->thr, DUK_STR_REGEXP_EXECUTOR_STEP_LIMIT);\n\t\t}\n\t\tre_ctx->steps_count++;\n\n\t\t/* Opcodes are at most 7 bits now so they encode to one byte.  If this\n\t\t * were not the case or 'pc' is invalid here (due to a bug etc) we'll\n\t\t * still fail safely through the switch default case.\n\t\t */\n\t\tDUK_ASSERT(pc[0] <= 0x7fU);\n#if 0\n\t\top = (duk_small_int_t) duk__bc_get_u32(re_ctx, &pc);\n#endif\n\t\top = *pc++;\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"match: rec=%ld, steps=%ld, pc (after op)=%ld, sp=%ld, op=%ld\",\n\t\t                     (long) re_ctx->recursion_depth,\n\t\t                     (long) re_ctx->steps_count,\n\t\t                     (long) (pc - re_ctx->bytecode),\n\t\t                     (long) (sp - re_ctx->input),\n\t\t                     (long) op));\n\n\t\tswitch (op) {\n\t\tcase DUK_REOP_MATCH: {\n\t\t\tgoto match;\n\t\t}\n\t\tcase DUK_REOP_CHAR: {\n\t\t\t/*\n\t\t\t *  Byte-based matching would be possible for case-sensitive\n\t\t\t *  matching but not for case-insensitive matching.  So, we\n\t\t\t *  match by decoding the input and bytecode character normally.\n\t\t\t *\n\t\t\t *  Bytecode characters are assumed to be already canonicalized.\n\t\t\t *  Input characters are canonicalized automatically by\n\t\t\t *  duk__inp_get_cp() if necessary.\n\t\t\t *\n\t\t\t *  There is no opcode for matching multiple characters.  The\n\t\t\t *  regexp compiler has trouble joining strings efficiently\n\t\t\t *  during compilation.  See doc/regexp.rst for more discussion.\n\t\t\t */\n\t\t\tduk_codepoint_t c1, c2;\n\n\t\t\tc1 = (duk_codepoint_t) duk__bc_get_u32(re_ctx, &pc);\n\t\t\tDUK_ASSERT(!(re_ctx->re_flags & DUK_RE_FLAG_IGNORE_CASE) ||\n\t\t\t           c1 == duk_unicode_re_canonicalize_char(re_ctx->thr, c1));  /* canonicalized by compiler */\n\t\t\tc2 = duk__inp_get_cp(re_ctx, &sp);\n\t\t\t/* No need to check for c2 < 0 (end of input): because c1 >= 0, it\n\t\t\t * will fail the match below automatically and cause goto fail.\n\t\t\t */\n#if 0\n\t\t\tif (c2 < 0) {\n\t\t\t\tgoto fail;\n\t\t\t}\n#endif\n\t\t\tDUK_ASSERT(c1 >= 0);\n\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"char match, c1=%ld, c2=%ld\", (long) c1, (long) c2));\n\t\t\tif (c1 != c2) {\n\t\t\t\tgoto fail;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_REOP_PERIOD: {\n\t\t\tduk_codepoint_t c;\n\n\t\t\tc = duk__inp_get_cp(re_ctx, &sp);\n\t\t\tif (c < 0 || duk_unicode_is_line_terminator(c)) {\n\t\t\t\t/* E5 Sections 15.10.2.8, 7.3 */\n\t\t\t\tgoto fail;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_REOP_RANGES:\n\t\tcase DUK_REOP_INVRANGES: {\n\t\t\tduk_uint32_t n;\n\t\t\tduk_codepoint_t c;\n\t\t\tduk_small_int_t match;\n\n\t\t\tn = duk__bc_get_u32(re_ctx, &pc);\n\t\t\tc = duk__inp_get_cp(re_ctx, &sp);\n\t\t\tif (c < 0) {\n\t\t\t\tgoto fail;\n\t\t\t}\n\n\t\t\tmatch = 0;\n\t\t\twhile (n) {\n\t\t\t\tduk_codepoint_t r1, r2;\n\t\t\t\tr1 = (duk_codepoint_t) duk__bc_get_u32(re_ctx, &pc);\n\t\t\t\tr2 = (duk_codepoint_t) duk__bc_get_u32(re_ctx, &pc);\n\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"matching ranges/invranges, n=%ld, r1=%ld, r2=%ld, c=%ld\",\n\t\t\t\t                     (long) n, (long) r1, (long) r2, (long) c));\n\t\t\t\tif (c >= r1 && c <= r2) {\n\t\t\t\t\t/* Note: don't bail out early, we must read all the ranges from\n\t\t\t\t\t * bytecode.  Another option is to skip them efficiently after\n\t\t\t\t\t * breaking out of here.  Prefer smallest code.\n\t\t\t\t\t */\n\t\t\t\t\tmatch = 1;\n\t\t\t\t}\n\t\t\t\tn--;\n\t\t\t}\n\n\t\t\tif (op == DUK_REOP_RANGES) {\n\t\t\t\tif (!match) {\n\t\t\t\t\tgoto fail;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tDUK_ASSERT(op == DUK_REOP_INVRANGES);\n\t\t\t\tif (match) {\n\t\t\t\t\tgoto fail;\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_REOP_ASSERT_START: {\n\t\t\tduk_codepoint_t c;\n\n\t\t\tif (sp <= re_ctx->input) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (!(re_ctx->re_flags & DUK_RE_FLAG_MULTILINE)) {\n\t\t\t\tgoto fail;\n\t\t\t}\n\t\t\tc = duk__inp_get_prev_cp(re_ctx, sp);\n\t\t\tif (duk_unicode_is_line_terminator(c)) {\n\t\t\t\t/* E5 Sections 15.10.2.8, 7.3 */\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tgoto fail;\n\t\t}\n\t\tcase DUK_REOP_ASSERT_END: {\n\t\t\tduk_codepoint_t c;\n\t\t\tconst duk_uint8_t *tmp_sp;\n\n\t\t\ttmp_sp = sp;\n\t\t\tc = duk__inp_get_cp(re_ctx, &tmp_sp);\n\t\t\tif (c < 0) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (!(re_ctx->re_flags & DUK_RE_FLAG_MULTILINE)) {\n\t\t\t\tgoto fail;\n\t\t\t}\n\t\t\tif (duk_unicode_is_line_terminator(c)) {\n\t\t\t\t/* E5 Sections 15.10.2.8, 7.3 */\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tgoto fail;\n\t\t}\n\t\tcase DUK_REOP_ASSERT_WORD_BOUNDARY:\n\t\tcase DUK_REOP_ASSERT_NOT_WORD_BOUNDARY: {\n\t\t\t/*\n\t\t\t *  E5 Section 15.10.2.6.  The previous and current character\n\t\t\t *  should -not- be canonicalized as they are now.  However,\n\t\t\t *  canonicalization does not affect the result of IsWordChar()\n\t\t\t *  (which depends on Unicode characters never canonicalizing\n\t\t\t *  into ASCII characters) so this does not matter.\n\t\t\t */\n\t\t\tduk_small_int_t w1, w2;\n\n\t\t\tif (sp <= re_ctx->input) {\n\t\t\t\tw1 = 0;  /* not a wordchar */\n\t\t\t} else {\n\t\t\t\tduk_codepoint_t c;\n\t\t\t\tc = duk__inp_get_prev_cp(re_ctx, sp);\n\t\t\t\tw1 = duk_unicode_re_is_wordchar(c);\n\t\t\t}\n\t\t\tif (sp >= re_ctx->input_end) {\n\t\t\t\tw2 = 0;  /* not a wordchar */\n\t\t\t} else {\n\t\t\t\tconst duk_uint8_t *tmp_sp = sp;  /* dummy so sp won't get updated */\n\t\t\t\tduk_codepoint_t c;\n\t\t\t\tc = duk__inp_get_cp(re_ctx, &tmp_sp);\n\t\t\t\tw2 = duk_unicode_re_is_wordchar(c);\n\t\t\t}\n\n\t\t\tif (op == DUK_REOP_ASSERT_WORD_BOUNDARY) {\n\t\t\t\tif (w1 == w2) {\n\t\t\t\t\tgoto fail;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tDUK_ASSERT(op == DUK_REOP_ASSERT_NOT_WORD_BOUNDARY);\n\t\t\t\tif (w1 != w2) {\n\t\t\t\t\tgoto fail;\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_REOP_JUMP: {\n\t\t\tduk_int32_t skip;\n\n\t\t\tskip = duk__bc_get_i32(re_ctx, &pc);\n\t\t\tpc += skip;\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_REOP_SPLIT1: {\n\t\t\t/* split1: prefer direct execution (no jump) */\n\t\t\tconst duk_uint8_t *sub_sp;\n\t\t\tduk_int32_t skip;\n\n\t\t\tskip = duk__bc_get_i32(re_ctx, &pc);\n\t\t\tsub_sp = duk__match_regexp(re_ctx, pc, sp);\n\t\t\tif (sub_sp) {\n\t\t\t\tsp = sub_sp;\n\t\t\t\tgoto match;\n\t\t\t}\n\t\t\tpc += skip;\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_REOP_SPLIT2: {\n\t\t\t/* split2: prefer jump execution (not direct) */\n\t\t\tconst duk_uint8_t *sub_sp;\n\t\t\tduk_int32_t skip;\n\n\t\t\tskip = duk__bc_get_i32(re_ctx, &pc);\n\t\t\tsub_sp = duk__match_regexp(re_ctx, pc + skip, sp);\n\t\t\tif (sub_sp) {\n\t\t\t\tsp = sub_sp;\n\t\t\t\tgoto match;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tcase DUK_REOP_SQMINIMAL: {\n\t\t\tduk_uint32_t q, qmin, qmax;\n\t\t\tduk_int32_t skip;\n\t\t\tconst duk_uint8_t *sub_sp;\n\n\t\t\tqmin = duk__bc_get_u32(re_ctx, &pc);\n\t\t\tqmax = duk__bc_get_u32(re_ctx, &pc);\n\t\t\tskip = duk__bc_get_i32(re_ctx, &pc);\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"minimal quantifier, qmin=%lu, qmax=%lu, skip=%ld\",\n\t\t\t                     (unsigned long) qmin, (unsigned long) qmax, (long) skip));\n\n\t\t\tq = 0;\n\t\t\twhile (q <= qmax) {\n\t\t\t\tif (q >= qmin) {\n\t\t\t\t\tsub_sp = duk__match_regexp(re_ctx, pc + skip, sp);\n\t\t\t\t\tif (sub_sp) {\n\t\t\t\t\t\tsp = sub_sp;\n\t\t\t\t\t\tgoto match;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tsub_sp = duk__match_regexp(re_ctx, pc, sp);\n\t\t\t\tif (!sub_sp) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tsp = sub_sp;\n\t\t\t\tq++;\n\t\t\t}\n\t\t\tgoto fail;\n\t\t}\n\t\tcase DUK_REOP_SQGREEDY: {\n\t\t\tduk_uint32_t q, qmin, qmax, atomlen;\n\t\t\tduk_int32_t skip;\n\t\t\tconst duk_uint8_t *sub_sp;\n\n\t\t\tqmin = duk__bc_get_u32(re_ctx, &pc);\n\t\t\tqmax = duk__bc_get_u32(re_ctx, &pc);\n\t\t\tatomlen = duk__bc_get_u32(re_ctx, &pc);\n\t\t\tskip = duk__bc_get_i32(re_ctx, &pc);\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"greedy quantifier, qmin=%lu, qmax=%lu, atomlen=%lu, skip=%ld\",\n\t\t\t                     (unsigned long) qmin, (unsigned long) qmax, (unsigned long) atomlen, (long) skip));\n\n\t\t\tq = 0;\n\t\t\twhile (q < qmax) {\n\t\t\t\tsub_sp = duk__match_regexp(re_ctx, pc, sp);\n\t\t\t\tif (!sub_sp) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tsp = sub_sp;\n\t\t\t\tq++;\n\t\t\t}\n\t\t\twhile (q >= qmin) {\n\t\t\t\tsub_sp = duk__match_regexp(re_ctx, pc + skip, sp);\n\t\t\t\tif (sub_sp) {\n\t\t\t\t\tsp = sub_sp;\n\t\t\t\t\tgoto match;\n\t\t\t\t}\n\t\t\t\tif (q == qmin) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\t/* Note: if atom were to contain e.g. captures, we would need to\n\t\t\t\t * re-match the atom to get correct captures.  Simply quantifiers\n\t\t\t\t * do not allow captures in their atom now, so this is not an issue.\n\t\t\t\t */\n\n\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"greedy quantifier, backtrack %ld characters (atomlen)\",\n\t\t\t\t                     (long) atomlen));\n\t\t\t\tsp = duk__inp_backtrack(re_ctx, &sp, (duk_uint_fast32_t) atomlen);\n\t\t\t\tq--;\n\t\t\t}\n\t\t\tgoto fail;\n\t\t}\n\t\tcase DUK_REOP_SAVE: {\n\t\t\tduk_uint32_t idx;\n\t\t\tconst duk_uint8_t *old;\n\t\t\tconst duk_uint8_t *sub_sp;\n\n\t\t\tidx = duk__bc_get_u32(re_ctx, &pc);\n\t\t\tif (idx >= re_ctx->nsaved) {\n\t\t\t\t/* idx is unsigned, < 0 check is not necessary */\n\t\t\t\tDUK_D(DUK_DPRINT(\"internal error, regexp save index insane: idx=%ld\", (long) idx));\n\t\t\t\tgoto internal_error;\n\t\t\t}\n\t\t\told = re_ctx->saved[idx];\n\t\t\tre_ctx->saved[idx] = sp;\n\t\t\tsub_sp = duk__match_regexp(re_ctx, pc, sp);\n\t\t\tif (sub_sp) {\n\t\t\t\tsp = sub_sp;\n\t\t\t\tgoto match;\n\t\t\t}\n\t\t\tre_ctx->saved[idx] = old;\n\t\t\tgoto fail;\n\t\t}\n\t\tcase DUK_REOP_WIPERANGE: {\n\t\t\t/* Wipe capture range and save old values for backtracking.\n\t\t\t *\n\t\t\t * XXX: this typically happens with a relatively small idx_count.\n\t\t\t * It might be useful to handle cases where the count is small\n\t\t\t * (say <= 8) by saving the values in stack instead.  This would\n\t\t\t * reduce memory churn and improve performance, at the cost of a\n\t\t\t * slightly higher code footprint.\n\t\t\t */\n\t\t\tduk_uint32_t idx_start, idx_count;\n#if defined(DUK_USE_EXPLICIT_NULL_INIT)\n\t\t\tduk_uint32_t idx_end, idx;\n#endif\n\t\t\tduk_uint8_t **range_save;\n\t\t\tconst duk_uint8_t *sub_sp;\n\n\t\t\tidx_start = duk__bc_get_u32(re_ctx, &pc);\n\t\t\tidx_count = duk__bc_get_u32(re_ctx, &pc);\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"wipe saved range: start=%ld, count=%ld -> [%ld,%ld] (captures [%ld,%ld])\",\n\t\t\t                     (long) idx_start, (long) idx_count,\n\t\t\t                     (long) idx_start, (long) (idx_start + idx_count - 1),\n\t\t\t                     (long) (idx_start / 2), (long) ((idx_start + idx_count - 1) / 2)));\n\t\t\tif (idx_start + idx_count > re_ctx->nsaved || idx_count == 0) {\n\t\t\t\t/* idx is unsigned, < 0 check is not necessary */\n\t\t\t\tDUK_D(DUK_DPRINT(\"internal error, regexp wipe indices insane: idx_start=%ld, idx_count=%ld\",\n\t\t\t\t                 (long) idx_start, (long) idx_count));\n\t\t\t\tgoto internal_error;\n\t\t\t}\n\t\t\tDUK_ASSERT(idx_count > 0);\n\n\t\t\tduk_require_stack(re_ctx->thr, 1);\n\t\t\trange_save = (duk_uint8_t **) duk_push_fixed_buffer_nozero(re_ctx->thr,\n\t\t\t                                                           sizeof(duk_uint8_t *) * idx_count);\n\t\t\tDUK_ASSERT(range_save != NULL);\n\t\t\tDUK_MEMCPY(range_save, re_ctx->saved + idx_start, sizeof(duk_uint8_t *) * idx_count);\n#if defined(DUK_USE_EXPLICIT_NULL_INIT)\n\t\t\tidx_end = idx_start + idx_count;\n\t\t\tfor (idx = idx_start; idx < idx_end; idx++) {\n\t\t\t\tre_ctx->saved[idx] = NULL;\n\t\t\t}\n#else\n\t\t\tDUK_MEMZERO((void *) (re_ctx->saved + idx_start), sizeof(duk_uint8_t *) * idx_count);\n#endif\n\n\t\t\tsub_sp = duk__match_regexp(re_ctx, pc, sp);\n\t\t\tif (sub_sp) {\n\t\t\t\t/* match: keep wiped/resaved values */\n\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"match: keep wiped/resaved values [%ld,%ld] (captures [%ld,%ld])\",\n\t\t\t\t                     (long) idx_start, (long) (idx_start + idx_count - 1),\n\t\t\t                             (long) (idx_start / 2), (long) ((idx_start + idx_count - 1) / 2)));\n\t\t\t\tduk_pop_unsafe(re_ctx->thr);\n\t\t\t\tsp = sub_sp;\n\t\t\t\tgoto match;\n\t\t\t}\n\n\t\t\t/* fail: restore saves */\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"fail: restore wiped/resaved values [%ld,%ld] (captures [%ld,%ld])\",\n\t\t\t                     (long) idx_start, (long) (idx_start + idx_count - 1),\n\t\t\t                     (long) (idx_start / 2), (long) ((idx_start + idx_count - 1) / 2)));\n\t\t\tDUK_MEMCPY((void *) (re_ctx->saved + idx_start),\n\t\t\t           (const void *) range_save,\n\t\t\t           sizeof(duk_uint8_t *) * idx_count);\n\t\t\tduk_pop_unsafe(re_ctx->thr);\n\t\t\tgoto fail;\n\t\t}\n\t\tcase DUK_REOP_LOOKPOS:\n\t\tcase DUK_REOP_LOOKNEG: {\n\t\t\t/*\n\t\t\t *  Needs a save of multiple saved[] entries depending on what range\n\t\t\t *  may be overwritten.  Because the regexp parser does no such analysis,\n\t\t\t *  we currently save the entire saved array here.  Lookaheads are thus\n\t\t\t *  a bit expensive.  Note that the saved array is not needed for just\n\t\t\t *  the lookahead sub-match, but for the matching of the entire sequel.\n\t\t\t *\n\t\t\t *  The temporary save buffer is pushed on to the valstack to handle\n\t\t\t *  errors correctly.  Each lookahead causes a C recursion and pushes\n\t\t\t *  more stuff on the value stack.  If the C recursion limit is less\n\t\t\t *  than the value stack slack, there is no need to check the stack.\n\t\t\t *  We do so regardless, just in case.\n\t\t\t */\n\n\t\t\tduk_int32_t skip;\n\t\t\tduk_uint8_t **full_save;\n\t\t\tconst duk_uint8_t *sub_sp;\n\n\t\t\tDUK_ASSERT(re_ctx->nsaved > 0);\n\n\t\t\tduk_require_stack(re_ctx->thr, 1);\n\t\t\tfull_save = (duk_uint8_t **) duk_push_fixed_buffer_nozero(re_ctx->thr,\n\t\t\t                                                          sizeof(duk_uint8_t *) * re_ctx->nsaved);\n\t\t\tDUK_ASSERT(full_save != NULL);\n\t\t\tDUK_MEMCPY(full_save, re_ctx->saved, sizeof(duk_uint8_t *) * re_ctx->nsaved);\n\n\t\t\tskip = duk__bc_get_i32(re_ctx, &pc);\n\t\t\tsub_sp = duk__match_regexp(re_ctx, pc, sp);\n\t\t\tif (op == DUK_REOP_LOOKPOS) {\n\t\t\t\tif (!sub_sp) {\n\t\t\t\t\tgoto lookahead_fail;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (sub_sp) {\n\t\t\t\t\tgoto lookahead_fail;\n\t\t\t\t}\n\t\t\t}\n\t\t\tsub_sp = duk__match_regexp(re_ctx, pc + skip, sp);\n\t\t\tif (sub_sp) {\n\t\t\t\t/* match: keep saves */\n\t\t\t\tduk_pop_unsafe(re_ctx->thr);\n\t\t\t\tsp = sub_sp;\n\t\t\t\tgoto match;\n\t\t\t}\n\n\t\t\t/* fall through */\n\n\t\t lookahead_fail:\n\t\t\t/* fail: restore saves */\n\t\t\tDUK_MEMCPY((void *) re_ctx->saved,\n\t\t\t           (const void *) full_save,\n\t\t\t           sizeof(duk_uint8_t *) * re_ctx->nsaved);\n\t\t\tduk_pop_unsafe(re_ctx->thr);\n\t\t\tgoto fail;\n\t\t}\n\t\tcase DUK_REOP_BACKREFERENCE: {\n\t\t\t/*\n\t\t\t *  Byte matching for back-references would be OK in case-\n\t\t\t *  sensitive matching.  In case-insensitive matching we need\n\t\t\t *  to canonicalize characters, so back-reference matching needs\n\t\t\t *  to be done with codepoints instead.  So, we just decode\n\t\t\t *  everything normally here, too.\n\t\t\t *\n\t\t\t *  Note: back-reference index which is 0 or higher than\n\t\t\t *  NCapturingParens (= number of capturing parens in the\n\t\t\t *  -entire- regexp) is a compile time error.  However, a\n\t\t\t *  backreference referring to a valid capture which has\n\t\t\t *  not matched anything always succeeds!  See E5 Section\n\t\t\t *  15.10.2.9, step 5, sub-step 3.\n\t\t\t */\n\t\t\tduk_uint32_t idx;\n\t\t\tconst duk_uint8_t *p;\n\n\t\t\tidx = duk__bc_get_u32(re_ctx, &pc);\n\t\t\tidx = idx << 1;  /* backref n -> saved indices [n*2, n*2+1] */\n\t\t\tif (idx < 2 || idx + 1 >= re_ctx->nsaved) {\n\t\t\t\t/* regexp compiler should catch these */\n\t\t\t\tDUK_D(DUK_DPRINT(\"internal error, backreference index insane\"));\n\t\t\t\tgoto internal_error;\n\t\t\t}\n\t\t\tif (!re_ctx->saved[idx] || !re_ctx->saved[idx+1]) {\n\t\t\t\t/* capture is 'undefined', always matches! */\n\t\t\t\tDUK_DDD(DUK_DDDPRINT(\"backreference: saved[%ld,%ld] not complete, always match\",\n\t\t\t\t                     (long) idx, (long) (idx + 1)));\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"backreference: match saved[%ld,%ld]\", (long) idx, (long) (idx + 1)));\n\n\t\t\tp = re_ctx->saved[idx];\n\t\t\twhile (p < re_ctx->saved[idx+1]) {\n\t\t\t\tduk_codepoint_t c1, c2;\n\n\t\t\t\t/* Note: not necessary to check p against re_ctx->input_end:\n\t\t\t\t * the memory access is checked by duk__inp_get_cp(), while\n\t\t\t\t * valid compiled regexps cannot write a saved[] entry\n\t\t\t\t * which points to outside the string.\n\t\t\t\t */\n\t\t\t\tc1 = duk__inp_get_cp(re_ctx, &p);\n\t\t\t\tDUK_ASSERT(c1 >= 0);\n\t\t\t\tc2 = duk__inp_get_cp(re_ctx, &sp);\n\t\t\t\t/* No need for an explicit c2 < 0 check: because c1 >= 0,\n\t\t\t\t * the comparison will always fail if c2 < 0.\n\t\t\t\t */\n#if 0\n\t\t\t\tif (c2 < 0) {\n\t\t\t\t\tgoto fail;\n\t\t\t\t}\n#endif\n\t\t\t\tif (c1 != c2) {\n\t\t\t\t\tgoto fail;\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tdefault: {\n\t\t\tDUK_D(DUK_DPRINT(\"internal error, regexp opcode error: %ld\", (long) op));\n\t\t\tgoto internal_error;\n\t\t}\n\t\t}\n\t}\n\n match:\n\tre_ctx->recursion_depth--;\n\treturn sp;\n\n fail:\n\tre_ctx->recursion_depth--;\n\treturn NULL;\n\n internal_error:\n\tDUK_ERROR_INTERNAL(re_ctx->thr);\n\treturn NULL;  /* never here */\n}\n\n/*\n *  Exposed matcher function which provides the semantics of RegExp.prototype.exec().\n *\n *  RegExp.prototype.test() has the same semantics as exec() but does not return the\n *  result object (which contains the matching string and capture groups).  Currently\n *  there is no separate test() helper, so a temporary result object is created and\n *  discarded if test() is needed.  This is intentional, to save code space.\n *\n *  Input stack:  [ ... re_obj input ]\n *  Output stack: [ ... result ]\n */\n\nDUK_LOCAL void duk__regexp_match_helper(duk_hthread *thr, duk_small_int_t force_global) {\n\tduk_re_matcher_ctx re_ctx;\n\tduk_hobject *h_regexp;\n\tduk_hstring *h_bytecode;\n\tduk_hstring *h_input;\n\tduk_uint8_t *p_buf;\n\tconst duk_uint8_t *pc;\n\tconst duk_uint8_t *sp;\n\tduk_small_int_t match = 0;\n\tduk_small_int_t global;\n\tduk_uint_fast32_t i;\n\tdouble d;\n\tduk_uint32_t char_offset;\n\n\tDUK_ASSERT(thr != NULL);\n\n\tDUK_DD(DUK_DDPRINT(\"regexp match: regexp=%!T, input=%!T\",\n\t                   (duk_tval *) duk_get_tval(thr, -2),\n\t                   (duk_tval *) duk_get_tval(thr, -1)));\n\n\t/*\n\t *  Regexp instance check, bytecode check, input coercion.\n\t *\n\t *  See E5 Section 15.10.6.\n\t */\n\n\t/* TypeError if wrong; class check, see E5 Section 15.10.6 */\n\th_regexp = duk_require_hobject_with_class(thr, -2, DUK_HOBJECT_CLASS_REGEXP);\n\tDUK_ASSERT(h_regexp != NULL);\n\tDUK_ASSERT(DUK_HOBJECT_GET_CLASS_NUMBER(h_regexp) == DUK_HOBJECT_CLASS_REGEXP);\n\tDUK_UNREF(h_regexp);\n\n\th_input = duk_to_hstring(thr, -1);\n\tDUK_ASSERT(h_input != NULL);\n\n\tduk_get_prop_stridx_short(thr, -2, DUK_STRIDX_INT_BYTECODE);  /* [ ... re_obj input ] -> [ ... re_obj input bc ] */\n\th_bytecode = duk_require_hstring(thr, -1);  /* no regexp instance should exist without a non-configurable bytecode property */\n\tDUK_ASSERT(h_bytecode != NULL);\n\n\t/*\n\t *  Basic context initialization.\n\t *\n\t *  Some init values are read from the bytecode header\n\t *  whose format is (UTF-8 codepoints):\n\t *\n\t *    uint   flags\n\t *    uint   nsaved (even, 2n+2 where n = num captures)\n\t */\n\n\t/* [ ... re_obj input bc ] */\n\n\tDUK_MEMZERO(&re_ctx, sizeof(re_ctx));\n\n\tre_ctx.thr = thr;\n\tre_ctx.input = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input);\n\tre_ctx.input_end = re_ctx.input + DUK_HSTRING_GET_BYTELEN(h_input);\n\tre_ctx.bytecode = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_bytecode);\n\tre_ctx.bytecode_end = re_ctx.bytecode + DUK_HSTRING_GET_BYTELEN(h_bytecode);\n\tre_ctx.saved = NULL;\n\tre_ctx.recursion_limit = DUK_USE_REGEXP_EXECUTOR_RECLIMIT;\n\tre_ctx.steps_limit = DUK_RE_EXECUTE_STEPS_LIMIT;\n\n\t/* read header */\n\tpc = re_ctx.bytecode;\n\tre_ctx.re_flags = duk__bc_get_u32(&re_ctx, &pc);\n\tre_ctx.nsaved = duk__bc_get_u32(&re_ctx, &pc);\n\tre_ctx.bytecode = pc;\n\n\tDUK_ASSERT(DUK_RE_FLAG_GLOBAL < 0x10000UL);  /* must fit into duk_small_int_t */\n\tglobal = (duk_small_int_t) (force_global | (duk_small_int_t) (re_ctx.re_flags & DUK_RE_FLAG_GLOBAL));\n\n\tDUK_ASSERT(re_ctx.nsaved >= 2);\n\tDUK_ASSERT((re_ctx.nsaved % 2) == 0);\n\n\tp_buf = (duk_uint8_t *) duk_push_fixed_buffer(thr, sizeof(duk_uint8_t *) * re_ctx.nsaved);  /* rely on zeroing */\n\tDUK_UNREF(p_buf);\n\tre_ctx.saved = (const duk_uint8_t **) duk_get_buffer(thr, -1, NULL);\n\tDUK_ASSERT(re_ctx.saved != NULL);\n\n\t/* [ ... re_obj input bc saved_buf ] */\n\n#if defined(DUK_USE_EXPLICIT_NULL_INIT)\n\tfor (i = 0; i < re_ctx.nsaved; i++) {\n\t\tre_ctx.saved[i] = (duk_uint8_t *) NULL;\n\t}\n#elif defined(DUK_USE_ZERO_BUFFER_DATA)\n\t/* buffer is automatically zeroed */\n#else\n\tDUK_MEMZERO((void *) p_buf, sizeof(duk_uint8_t *) * re_ctx.nsaved);\n#endif\n\n\tDUK_DDD(DUK_DDDPRINT(\"regexp ctx initialized, flags=0x%08lx, nsaved=%ld, recursion_limit=%ld, steps_limit=%ld\",\n\t                     (unsigned long) re_ctx.re_flags, (long) re_ctx.nsaved, (long) re_ctx.recursion_limit,\n\t                     (long) re_ctx.steps_limit));\n\n\t/*\n\t *  Get starting character offset for match, and initialize 'sp' based on it.\n\t *\n\t *  Note: lastIndex is non-configurable so it must be present (we check the\n\t *  internal class of the object above, so we know it is).  User code can set\n\t *  its value to an arbitrary (garbage) value though; E5 requires that lastIndex\n\t *  be coerced to a number before using.  The code below works even if the\n\t *  property is missing: the value will then be coerced to zero.\n\t *\n\t *  Note: lastIndex may be outside Uint32 range even after ToInteger() coercion.\n\t *  For instance, ToInteger(+Infinity) = +Infinity.  We track the match offset\n\t *  as an integer, but pre-check it to be inside the 32-bit range before the loop.\n\t *  If not, the check in E5 Section 15.10.6.2, step 9.a applies.\n\t */\n\n\t/* XXX: lastIndex handling produces a lot of asm */\n\n\t/* [ ... re_obj input bc saved_buf ] */\n\n\tduk_get_prop_stridx_short(thr, -4, DUK_STRIDX_LAST_INDEX);  /* -> [ ... re_obj input bc saved_buf lastIndex ] */\n\t(void) duk_to_int(thr, -1);  /* ToInteger(lastIndex) */\n\td = duk_get_number(thr, -1);  /* integer, but may be +/- Infinite, +/- zero (not NaN, though) */\n\tduk_pop_nodecref_unsafe(thr);\n\n\tif (global) {\n\t\tif (d < 0.0 || d > (double) DUK_HSTRING_GET_CHARLEN(h_input)) {\n\t\t\t/* match fail */\n\t\t\tchar_offset = 0;   /* not really necessary */\n\t\t\tDUK_ASSERT(match == 0);\n\t\t\tgoto match_over;\n\t\t}\n\t\tchar_offset = (duk_uint32_t) d;\n\t} else {\n\t\t/* lastIndex must be ignored for non-global regexps, but get the\n\t\t * value for (theoretical) side effects.  No side effects can\n\t\t * really occur, because lastIndex is a normal property and is\n\t\t * always non-configurable for RegExp instances.\n\t\t */\n\t\tchar_offset = (duk_uint32_t) 0;\n\t}\n\n\tDUK_ASSERT(char_offset <= DUK_HSTRING_GET_CHARLEN(h_input));\n\tsp = re_ctx.input + duk_heap_strcache_offset_char2byte(thr, h_input, char_offset);\n\n\t/*\n\t *  Match loop.\n\t *\n\t *  Try matching at different offsets until match found or input exhausted.\n\t */\n\n\t/* [ ... re_obj input bc saved_buf ] */\n\n\tDUK_ASSERT(match == 0);\n\n\tfor (;;) {\n\t\t/* char offset in [0, h_input->clen] (both ends inclusive), checked before entry */\n\t\tDUK_ASSERT_DISABLE(char_offset >= 0);\n\t\tDUK_ASSERT(char_offset <= DUK_HSTRING_GET_CHARLEN(h_input));\n\n\t\t/* Note: re_ctx.steps is intentionally not reset, it applies to the entire unanchored match */\n\t\tDUK_ASSERT(re_ctx.recursion_depth == 0);\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"attempt match at char offset %ld; %p [%p,%p]\",\n\t\t                     (long) char_offset, (const void *) sp,\n\t\t                     (const void *) re_ctx.input, (const void *) re_ctx.input_end));\n\n\t\t/*\n\t\t *  Note:\n\t\t *\n\t\t *    - duk__match_regexp() is required not to longjmp() in ordinary \"non-match\"\n\t\t *      conditions; a longjmp() will terminate the entire matching process.\n\t\t *\n\t\t *    - Clearing saved[] is not necessary because backtracking does it\n\t\t *\n\t\t *    - Backtracking also rewinds re_ctx.recursion back to zero, unless an\n\t\t *      internal/limit error occurs (which causes a longjmp())\n\t\t *\n\t\t *    - If we supported anchored matches, we would break out here\n\t\t *      unconditionally; however, Ecmascript regexps don't have anchored\n\t\t *      matches.  It might make sense to implement a fast bail-out if\n\t\t *      the regexp begins with '^' and sp is not 0: currently we'll just\n\t\t *      run through the entire input string, trivially failing the match\n\t\t *      at every non-zero offset.\n\t\t */\n\n\t\tif (duk__match_regexp(&re_ctx, re_ctx.bytecode, sp) != NULL) {\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"match at offset %ld\", (long) char_offset));\n\t\t\tmatch = 1;\n\t\t\tbreak;\n\t\t}\n\n\t\t/* advance by one character (code point) and one char_offset */\n\t\tchar_offset++;\n\t\tif (char_offset > DUK_HSTRING_GET_CHARLEN(h_input)) {\n\t\t\t/*\n\t\t\t *  Note:\n\t\t\t *\n\t\t\t *    - Intentionally attempt (empty) match at char_offset == k_input->clen\n\t\t\t *\n\t\t\t *    - Negative char_offsets have been eliminated and char_offset is duk_uint32_t\n\t\t\t *      -> no need or use for a negative check\n\t\t\t */\n\n\t\t\tDUK_DDD(DUK_DDDPRINT(\"no match after trying all sp offsets\"));\n\t\t\tbreak;\n\t\t}\n\n\t\t/* avoid calling at end of input, will DUK_ERROR (above check suffices to avoid this) */\n\t\t(void) duk__utf8_advance(thr, &sp, re_ctx.input, re_ctx.input_end, (duk_uint_fast32_t) 1);\n\t}\n\n match_over:\n\n\t/*\n\t *  Matching complete, create result array or return a 'null'.  Update lastIndex\n\t *  if necessary.  See E5 Section 15.10.6.2.\n\t *\n\t *  Because lastIndex is a character (not byte) offset, we need the character\n\t *  length of the match which we conveniently get as a side effect of interning\n\t *  the matching substring (0th index of result array).\n\t *\n\t *  saved[0]         start pointer (~ byte offset) of current match\n\t *  saved[1]         end pointer (~ byte offset) of current match (exclusive)\n\t *  char_offset      start character offset of current match (-> .index of result)\n\t *  char_end_offset  end character offset (computed below)\n\t */\n\n\t/* [ ... re_obj input bc saved_buf ] */\n\n\tif (match) {\n#if defined(DUK_USE_ASSERTIONS)\n\t\tduk_hobject *h_res;\n#endif\n\t\tduk_uint32_t char_end_offset = 0;\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"regexp matches at char_offset %ld\", (long) char_offset));\n\n\t\tDUK_ASSERT(re_ctx.nsaved >= 2);        /* must have start and end */\n\t\tDUK_ASSERT((re_ctx.nsaved % 2) == 0);  /* and even number */\n\n\t\t/* XXX: Array size is known before and (2 * re_ctx.nsaved) but not taken\n\t\t * advantage of now.  The array is not compacted either, as regexp match\n\t\t * objects are usually short lived.\n\t\t */\n\n\t\tduk_push_array(thr);\n\n#if defined(DUK_USE_ASSERTIONS)\n\t\th_res = duk_require_hobject(thr, -1);\n\t\tDUK_ASSERT(DUK_HOBJECT_HAS_EXTENSIBLE(h_res));\n\t\tDUK_ASSERT(DUK_HOBJECT_HAS_EXOTIC_ARRAY(h_res));\n\t\tDUK_ASSERT(DUK_HOBJECT_GET_CLASS_NUMBER(h_res) == DUK_HOBJECT_CLASS_ARRAY);\n#endif\n\n\t\t/* [ ... re_obj input bc saved_buf res_obj ] */\n\n\t\tduk_push_u32(thr, char_offset);\n\t\tduk_xdef_prop_stridx_short_wec(thr, -2, DUK_STRIDX_INDEX);\n\n\t\tduk_dup_m4(thr);\n\t\tduk_xdef_prop_stridx_short_wec(thr, -2, DUK_STRIDX_INPUT);\n\n\t\tfor (i = 0; i < re_ctx.nsaved; i += 2) {\n\t\t\t/* Captures which are undefined have NULL pointers and are returned\n\t\t\t * as 'undefined'.  The same is done when saved[] pointers are insane\n\t\t\t * (this should, of course, never happen in practice).\n\t\t\t */\n\t\t\tif (re_ctx.saved[i] && re_ctx.saved[i + 1] && re_ctx.saved[i + 1] >= re_ctx.saved[i]) {\n\t\t\t\tduk_push_lstring(thr,\n\t\t\t\t                 (const char *) re_ctx.saved[i],\n\t\t\t\t                 (duk_size_t) (re_ctx.saved[i+1] - re_ctx.saved[i]));\n\t\t\t\tif (i == 0) {\n\t\t\t\t\t/* Assumes that saved[0] and saved[1] are always\n\t\t\t\t\t * set by regexp bytecode (if not, char_end_offset\n\t\t\t\t\t * will be zero).  Also assumes clen reflects the\n\t\t\t\t\t * correct char length.\n\t\t\t\t\t */\n\t\t\t\t\tchar_end_offset = char_offset + (duk_uint32_t) duk_get_length(thr, -1);  /* add charlen */\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tduk_push_undefined(thr);\n\t\t\t}\n\n\t\t\t/* [ ... re_obj input bc saved_buf res_obj val ] */\n\t\t\tduk_put_prop_index(thr, -2, (duk_uarridx_t) (i / 2));\n\t\t}\n\n\t\t/* [ ... re_obj input bc saved_buf res_obj ] */\n\n\t\t/* NB: 'length' property is automatically updated by the array setup loop */\n\n\t\tif (global) {\n\t\t\t/* global regexp: lastIndex updated on match */\n\t\t\tduk_push_u32(thr, char_end_offset);\n\t\t\tduk_put_prop_stridx_short(thr, -6, DUK_STRIDX_LAST_INDEX);\n\t\t} else {\n\t\t\t/* non-global regexp: lastIndex never updated on match */\n\t\t\t;\n\t\t}\n\t} else {\n\t\t/*\n\t\t *  No match, E5 Section 15.10.6.2, step 9.a.i - 9.a.ii apply, regardless\n\t\t *  of 'global' flag of the RegExp.  In particular, if lastIndex is invalid\n\t\t *  initially, it is reset to zero.\n\t\t */\n\n\t\tDUK_DDD(DUK_DDDPRINT(\"regexp does not match\"));\n\n\t\tduk_push_null(thr);\n\n\t\t/* [ ... re_obj input bc saved_buf res_obj ] */\n\n\t\tduk_push_int(thr, 0);\n\t\tduk_put_prop_stridx_short(thr, -6, DUK_STRIDX_LAST_INDEX);\n\t}\n\n\t/* [ ... re_obj input bc saved_buf res_obj ] */\n\n\tduk_insert(thr, -5);\n\n\t/* [ ... res_obj re_obj input bc saved_buf ] */\n\n\tduk_pop_n_unsafe(thr, 4);\n\n\t/* [ ... res_obj ] */\n\n\t/* XXX: these last tricks are unnecessary if the function is made\n\t * a genuine native function.\n\t */\n}\n\nDUK_INTERNAL void duk_regexp_match(duk_hthread *thr) {\n\tduk__regexp_match_helper(thr, 0 /*force_global*/);\n}\n\n/* This variant is needed by String.prototype.split(); it needs to perform\n * global-style matching on a cloned RegExp which is potentially non-global.\n */\nDUK_INTERNAL void duk_regexp_match_force_global(duk_hthread *thr) {\n\tduk__regexp_match_helper(thr, 1 /*force_global*/);\n}\n\n#else  /* DUK_USE_REGEXP_SUPPORT */\n\n/* regexp support disabled */\n\n#endif  /* DUK_USE_REGEXP_SUPPORT */\n#line 1 \"duk_selftest.c\"\n/*\n *  Self tests to ensure execution environment is sane.  Intended to catch\n *  compiler/platform problems which cannot be detected at compile time.\n */\n\n/* #include duk_internal.h -> already included */\n\n#if defined(DUK_USE_SELF_TESTS)\n\n/*\n *  Unions and structs for self tests\n */\n\ntypedef union {\n\tdouble d;\n\tduk_uint8_t x[8];\n} duk__test_double_union;\n\n/* Self test failed.  Expects a local variable 'error_count' to exist. */\n#define DUK__FAILED(msg)  do { \\\n\t\tDUK_D(DUK_DPRINT(\"self test failed: \" #msg \" at \" DUK_FILE_MACRO \":\" DUK_MACRO_STRINGIFY(DUK_LINE_MACRO))); \\\n\t\terror_count++; \\\n\t} while (0)\n\n#define DUK__DBLUNION_CMP_TRUE(a,b)  do { \\\n\t\tif (DUK_MEMCMP((const void *) (a), (const void *) (b), sizeof(duk__test_double_union)) != 0) { \\\n\t\t\tDUK__FAILED(\"double union compares false (expected true)\"); \\\n\t\t} \\\n\t} while (0)\n\n#define DUK__DBLUNION_CMP_FALSE(a,b)  do { \\\n\t\tif (DUK_MEMCMP((const void *) (a), (const void *) (b), sizeof(duk__test_double_union)) == 0) { \\\n\t\t\tDUK__FAILED(\"double union compares true (expected false)\"); \\\n\t\t} \\\n\t} while (0)\n\ntypedef union {\n\tduk_uint32_t i;\n\tduk_uint8_t x[8];\n} duk__test_u32_union;\n\n#if defined(DUK_USE_INTEGER_LE)\n#define DUK__U32_INIT(u, a, b, c, d) do { \\\n\t\t(u)->x[0] = (d); (u)->x[1] = (c); (u)->x[2] = (b); (u)->x[3] = (a); \\\n\t} while (0)\n#elif defined(DUK_USE_INTEGER_ME)\n#error integer mixed endian not supported now\n#elif defined(DUK_USE_INTEGER_BE)\n#define DUK__U32_INIT(u, a, b, c, d) do { \\\n\t\t(u)->x[0] = (a); (u)->x[1] = (b); (u)->x[2] = (c); (u)->x[3] = (d); \\\n\t} while (0)\n#else\n#error unknown integer endianness\n#endif\n\n#if defined(DUK_USE_DOUBLE_LE)\n#define DUK__DOUBLE_INIT(u, a, b, c, d, e, f, g, h) do { \\\n\t\t(u)->x[0] = (h); (u)->x[1] = (g); (u)->x[2] = (f); (u)->x[3] = (e); \\\n\t\t(u)->x[4] = (d); (u)->x[5] = (c); (u)->x[6] = (b); (u)->x[7] = (a); \\\n\t} while (0)\n#define DUK__DOUBLE_COMPARE(u, a, b, c, d, e, f, g, h) \\\n\t((u)->x[0] == (h) && (u)->x[1] == (g) && (u)->x[2] == (f) && (u)->x[3] == (e) && \\\n\t (u)->x[4] == (d) && (u)->x[5] == (c) && (u)->x[6] == (b) && (u)->x[7] == (a))\n#elif defined(DUK_USE_DOUBLE_ME)\n#define DUK__DOUBLE_INIT(u, a, b, c, d, e, f, g, h) do { \\\n\t\t(u)->x[0] = (d); (u)->x[1] = (c); (u)->x[2] = (b); (u)->x[3] = (a); \\\n\t\t(u)->x[4] = (h); (u)->x[5] = (g); (u)->x[6] = (f); (u)->x[7] = (e); \\\n\t} while (0)\n#define DUK__DOUBLE_COMPARE(u, a, b, c, d, e, f, g, h) \\\n\t((u)->x[0] == (d) && (u)->x[1] == (c) && (u)->x[2] == (b) && (u)->x[3] == (a) && \\\n\t (u)->x[4] == (h) && (u)->x[5] == (g) && (u)->x[6] == (f) && (u)->x[7] == (e))\n#elif defined(DUK_USE_DOUBLE_BE)\n#define DUK__DOUBLE_INIT(u, a, b, c, d, e, f, g, h) do { \\\n\t\t(u)->x[0] = (a); (u)->x[1] = (b); (u)->x[2] = (c); (u)->x[3] = (d); \\\n\t\t(u)->x[4] = (e); (u)->x[5] = (f); (u)->x[6] = (g); (u)->x[7] = (h); \\\n\t} while (0)\n#define DUK__DOUBLE_COMPARE(u, a, b, c, d, e, f, g, h) \\\n\t((u)->x[0] == (a) && (u)->x[1] == (b) && (u)->x[2] == (c) && (u)->x[3] == (d) && \\\n\t (u)->x[4] == (e) && (u)->x[5] == (f) && (u)->x[6] == (g) && (u)->x[7] == (h))\n#else\n#error unknown double endianness\n#endif\n\n/*\n *  Various sanity checks for typing\n */\n\nDUK_LOCAL duk_uint_t duk__selftest_types(void) {\n\tduk_uint_t error_count = 0;\n\n\tif (!(sizeof(duk_int8_t) == 1 &&\n\t      sizeof(duk_uint8_t) == 1 &&\n\t      sizeof(duk_int16_t) == 2 &&\n\t      sizeof(duk_uint16_t) == 2 &&\n\t      sizeof(duk_int32_t) == 4 &&\n\t      sizeof(duk_uint32_t) == 4)) {\n\t\tDUK__FAILED(\"duk_(u)int{8,16,32}_t size\");\n\t}\n#if defined(DUK_USE_64BIT_OPS)\n\tif (!(sizeof(duk_int64_t) == 8 &&\n\t      sizeof(duk_uint64_t) == 8)) {\n\t\tDUK__FAILED(\"duk_(u)int64_t size\");\n\t}\n#endif\n\n\tif (!(sizeof(duk_size_t) >= sizeof(duk_uint_t))) {\n\t\t/* Some internal code now assumes that all duk_uint_t values\n\t\t * can be expressed with a duk_size_t.\n\t\t */\n\t\tDUK__FAILED(\"duk_size_t is smaller than duk_uint_t\");\n\t}\n\tif (!(sizeof(duk_int_t) >= 4)) {\n\t\tDUK__FAILED(\"duk_int_t is not 32 bits\");\n\t}\n\n\treturn error_count;\n}\n\n/*\n *  Packed tval sanity\n */\n\nDUK_LOCAL duk_uint_t duk__selftest_packed_tval(void) {\n\tduk_uint_t error_count = 0;\n\n#if defined(DUK_USE_PACKED_TVAL)\n\tif (sizeof(void *) > 4) {\n\t\tDUK__FAILED(\"packed duk_tval in use but sizeof(void *) > 4\");\n\t}\n#endif\n\n\treturn error_count;\n}\n\n/*\n *  Two's complement arithmetic.\n */\n\nDUK_LOCAL duk_uint_t duk__selftest_twos_complement(void) {\n\tduk_uint_t error_count = 0;\n\tvolatile int test;\n\ttest = -1;\n\n\t/* Note that byte order doesn't affect this test: all bytes in\n\t * 'test' will be 0xFF for two's complement.\n\t */\n\tif (((volatile duk_uint8_t *) &test)[0] != (duk_uint8_t) 0xff) {\n\t\tDUK__FAILED(\"two's complement arithmetic\");\n\t}\n\n\treturn error_count;\n}\n\n/*\n *  Byte order.  Important to self check, because on some exotic platforms\n *  there is no actual detection but rather assumption based on platform\n *  defines.\n */\n\nDUK_LOCAL duk_uint_t duk__selftest_byte_order(void) {\n\tduk_uint_t error_count = 0;\n\tduk__test_u32_union u1;\n\tduk__test_double_union u2;\n\n\t/*\n\t *  >>> struct.pack('>d', 102030405060).encode('hex')\n\t *  '4237c17c6dc40000'\n\t */\n\n\tDUK__U32_INIT(&u1, 0xde, 0xad, 0xbe, 0xef);\n\tDUK__DOUBLE_INIT(&u2, 0x42, 0x37, 0xc1, 0x7c, 0x6d, 0xc4, 0x00, 0x00);\n\n\tif (u1.i != (duk_uint32_t) 0xdeadbeefUL) {\n\t\tDUK__FAILED(\"duk_uint32_t byte order\");\n\t}\n\n\tif (u2.d != (double) 102030405060.0) {\n\t\tDUK__FAILED(\"double byte order\");\n\t}\n\n\treturn error_count;\n}\n\n/*\n *  DUK_BSWAP macros\n */\n\nDUK_LOCAL duk_uint_t duk__selftest_bswap_macros(void) {\n\tduk_uint_t error_count = 0;\n\tduk_uint32_t x32;\n\tduk_uint16_t x16;\n\tduk_double_union du;\n\tduk_double_t du_diff;\n\n\tx16 = 0xbeefUL;\n\tx16 = DUK_BSWAP16(x16);\n\tif (x16 != (duk_uint16_t) 0xefbeUL) {\n\t\tDUK__FAILED(\"DUK_BSWAP16\");\n\t}\n\n\tx32 = 0xdeadbeefUL;\n\tx32 = DUK_BSWAP32(x32);\n\tif (x32 != (duk_uint32_t) 0xefbeaddeUL) {\n\t\tDUK__FAILED(\"DUK_BSWAP32\");\n\t}\n\n\t/* >>> struct.unpack('>d', '4000112233445566'.decode('hex'))\n\t * (2.008366013071895,)\n\t */\n\n\tdu.uc[0] = 0x40; du.uc[1] = 0x00; du.uc[2] = 0x11; du.uc[3] = 0x22;\n\tdu.uc[4] = 0x33; du.uc[5] = 0x44; du.uc[6] = 0x55; du.uc[7] = 0x66;\n\tDUK_DBLUNION_DOUBLE_NTOH(&du);\n\tdu_diff = du.d - 2.008366013071895;\n#if 0\n\tDUK_D(DUK_DPRINT(\"du_diff: %lg\\n\", (double) du_diff));\n#endif\n\tif (du_diff > 1e-15) {\n\t\t/* Allow very small lenience because some compilers won't parse\n\t\t * exact IEEE double constants (happened in matrix testing with\n\t\t * Linux gcc-4.8 -m32 at least).\n\t\t */\n#if 0\n\t\tDUK_D(DUK_DPRINT(\"Result of DUK_DBLUNION_DOUBLE_NTOH: %02x %02x %02x %02x %02x %02x %02x %02x\\n\",\n\t\t            (unsigned int) du.uc[0], (unsigned int) du.uc[1],\n\t\t            (unsigned int) du.uc[2], (unsigned int) du.uc[3],\n\t\t            (unsigned int) du.uc[4], (unsigned int) du.uc[5],\n\t\t            (unsigned int) du.uc[6], (unsigned int) du.uc[7]));\n#endif\n\t\tDUK__FAILED(\"DUK_DBLUNION_DOUBLE_NTOH\");\n\t}\n\n\treturn error_count;\n}\n\n/*\n *  Basic double / byte union memory layout.\n */\n\nDUK_LOCAL duk_uint_t duk__selftest_double_union_size(void) {\n\tduk_uint_t error_count = 0;\n\n\tif (sizeof(duk__test_double_union) != 8) {\n\t\tDUK__FAILED(\"invalid union size\");\n\t}\n\n\treturn error_count;\n}\n\n/*\n *  Union aliasing, see misc/clang_aliasing.c.\n */\n\nDUK_LOCAL duk_uint_t duk__selftest_double_aliasing(void) {\n\t/* This testcase fails when Emscripten-generated code runs on Firefox.\n\t * It's not an issue because the failure should only affect packed\n\t * duk_tval representation, which is not used with Emscripten.\n\t */\n#if defined(DUK_USE_PACKED_TVAL)\n\tduk_uint_t error_count = 0;\n\tduk__test_double_union a, b;\n\n\t/* Test signaling NaN and alias assignment in all endianness combinations.\n\t */\n\n\t/* little endian */\n\ta.x[0] = 0x11; a.x[1] = 0x22; a.x[2] = 0x33; a.x[3] = 0x44;\n\ta.x[4] = 0x00; a.x[5] = 0x00; a.x[6] = 0xf1; a.x[7] = 0xff;\n\tb = a;\n\tDUK__DBLUNION_CMP_TRUE(&a, &b);\n\n\t/* big endian */\n\ta.x[0] = 0xff; a.x[1] = 0xf1; a.x[2] = 0x00; a.x[3] = 0x00;\n\ta.x[4] = 0x44; a.x[5] = 0x33; a.x[6] = 0x22; a.x[7] = 0x11;\n\tb = a;\n\tDUK__DBLUNION_CMP_TRUE(&a, &b);\n\n\t/* mixed endian */\n\ta.x[0] = 0x00; a.x[1] = 0x00; a.x[2] = 0xf1; a.x[3] = 0xff;\n\ta.x[4] = 0x11; a.x[5] = 0x22; a.x[6] = 0x33; a.x[7] = 0x44;\n\tb = a;\n\tDUK__DBLUNION_CMP_TRUE(&a, &b);\n\n\treturn error_count;\n#else\n\tDUK_D(DUK_DPRINT(\"skip double aliasing self test when duk_tval is not packed\"));\n\treturn 0;\n#endif\n}\n\n/*\n *  Zero sign, see misc/tcc_zerosign2.c.\n */\n\nDUK_LOCAL duk_uint_t duk__selftest_double_zero_sign(void) {\n\tduk_uint_t error_count = 0;\n\tduk__test_double_union a, b;\n\n\ta.d = 0.0;\n\tb.d = -a.d;\n\tDUK__DBLUNION_CMP_FALSE(&a, &b);\n\n\treturn error_count;\n}\n\n/*\n *  Rounding mode: Duktape assumes round-to-nearest, check that this is true.\n *  If we had C99 fenv.h we could check that fegetround() == FE_TONEAREST,\n *  but we don't want to rely on that header; and even if we did, it's good\n *  to ensure the rounding actually works.\n */\n\nDUK_LOCAL duk_uint_t duk__selftest_double_rounding(void) {\n\tduk_uint_t error_count = 0;\n\tduk__test_double_union a, b, c;\n\n#if 0\n\t/* Include <fenv.h> and test manually; these trigger failures: */\n\tfesetround(FE_UPWARD);\n\tfesetround(FE_DOWNWARD);\n\tfesetround(FE_TOWARDZERO);\n\n\t/* This is the default and passes. */\n\tfesetround(FE_TONEAREST);\n#endif\n\n\t/* Rounding tests check that none of the other modes (round to\n\t * +Inf, round to -Inf, round to zero) can be active:\n\t * http://www.gnu.org/software/libc/manual/html_node/Rounding.html\n\t */\n\n\t/* 1.0 + 2^(-53): result is midway between 1.0 and 1.0 + ulp.\n\t * Round to nearest: 1.0\n\t * Round to +Inf:    1.0 + ulp\n\t * Round to -Inf:    1.0\n\t * Round to zero:    1.0\n\t * => Correct result eliminates round to +Inf.\n\t */\n\tDUK__DOUBLE_INIT(&a, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);\n\tDUK__DOUBLE_INIT(&b, 0x3c, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);\n\tDUK_MEMSET((void *) &c, 0, sizeof(c));\n\tc.d = a.d + b.d;\n\tif (!DUK__DOUBLE_COMPARE(&c, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00)) {\n\t\tDUK_D(DUK_DPRINT(\"broken result (native endiannesss): %02x %02x %02x %02x %02x %02x %02x %02x\",\n\t\t                 (unsigned int) c.x[0], (unsigned int) c.x[1],\n\t\t                 (unsigned int) c.x[2], (unsigned int) c.x[3],\n\t\t                 (unsigned int) c.x[4], (unsigned int) c.x[5],\n\t\t                 (unsigned int) c.x[6], (unsigned int) c.x[7]));\n\t\tDUK__FAILED(\"invalid result from 1.0 + 0.5ulp\");\n\t}\n\n\t/* (1.0 + ulp) + 2^(-53): result is midway between 1.0 + ulp and 1.0 + 2*ulp.\n\t * Round to nearest: 1.0 + 2*ulp (round to even mantissa)\n\t * Round to +Inf:    1.0 + 2*ulp\n\t * Round to -Inf:    1.0 + ulp\n\t * Round to zero:    1.0 + ulp\n\t * => Correct result eliminates round to -Inf and round to zero.\n\t */\n\tDUK__DOUBLE_INIT(&a, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01);\n\tDUK__DOUBLE_INIT(&b, 0x3c, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);\n\tDUK_MEMSET((void *) &c, 0, sizeof(c));\n\tc.d = a.d + b.d;\n\tif (!DUK__DOUBLE_COMPARE(&c, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02)) {\n\t\tDUK_D(DUK_DPRINT(\"broken result (native endiannesss): %02x %02x %02x %02x %02x %02x %02x %02x\",\n\t\t                 (unsigned int) c.x[0], (unsigned int) c.x[1],\n\t\t                 (unsigned int) c.x[2], (unsigned int) c.x[3],\n\t\t                 (unsigned int) c.x[4], (unsigned int) c.x[5],\n\t\t                 (unsigned int) c.x[6], (unsigned int) c.x[7]));\n\t\tDUK__FAILED(\"invalid result from (1.0 + ulp) + 0.5ulp\");\n\t}\n\n\t/* Could do negative number testing too, but the tests above should\n\t * differentiate between IEEE 754 rounding modes.\n\t */\n\treturn error_count;\n}\n\n/*\n *  fmod(): often a portability issue in embedded or bare platform targets.\n *  Check for at least minimally correct behavior.  Unlike some other math\n *  functions (like cos()) Duktape relies on fmod() internally too.\n */\n\nDUK_LOCAL duk_uint_t duk__selftest_fmod(void) {\n\tduk_uint_t error_count = 0;\n\tduk__test_double_union u1, u2;\n\tvolatile duk_double_t t1, t2, t3;\n\n\t/* fmod() with integer argument and exponent 2^32 is used by e.g.\n\t * ToUint32() and some Duktape internals.\n\t */\n\tu1.d = DUK_FMOD(10.0, 4294967296.0);\n\tu2.d = 10.0;\n\tDUK__DBLUNION_CMP_TRUE(&u1, &u2);\n\n\tu1.d = DUK_FMOD(4294967306.0, 4294967296.0);\n\tu2.d = 10.0;\n\tDUK__DBLUNION_CMP_TRUE(&u1, &u2);\n\n\tu1.d = DUK_FMOD(73014444042.0, 4294967296.0);\n\tu2.d = 10.0;\n\tDUK__DBLUNION_CMP_TRUE(&u1, &u2);\n\n\t/* 52-bit integer split into two parts:\n\t * >>> 0x1fedcba9876543\n\t * 8987183256397123\n\t * >>> float(0x1fedcba9876543) / float(2**53)\n\t * 0.9977777777777778\n\t */\n\tu1.d = DUK_FMOD(8987183256397123.0, 4294967296.0);\n\tu2.d = (duk_double_t) 0xa9876543UL;\n\tDUK__DBLUNION_CMP_TRUE(&u1, &u2);\n\tt1 = 8987183256397123.0;\n\tt2 = 4294967296.0;\n\tt3 = t1 / t2;\n\tu1.d = DUK_FLOOR(t3);\n\tu2.d = (duk_double_t) 0x1fedcbUL;\n\tDUK__DBLUNION_CMP_TRUE(&u1, &u2);\n\n\t/* C99 behavior is for fmod() result sign to mathc argument sign. */\n\tu1.d = DUK_FMOD(-10.0, 4294967296.0);\n\tu2.d = -10.0;\n\tDUK__DBLUNION_CMP_TRUE(&u1, &u2);\n\n\tu1.d = DUK_FMOD(-4294967306.0, 4294967296.0);\n\tu2.d = -10.0;\n\tDUK__DBLUNION_CMP_TRUE(&u1, &u2);\n\n\tu1.d = DUK_FMOD(-73014444042.0, 4294967296.0);\n\tu2.d = -10.0;\n\tDUK__DBLUNION_CMP_TRUE(&u1, &u2);\n\n\treturn error_count;\n}\n\n/*\n *  Struct size/alignment if platform requires it\n *\n *  There are some compiler specific struct padding pragmas etc in use, this\n *  selftest ensures they're correctly detected and used.\n */\n\nDUK_LOCAL duk_uint_t duk__selftest_struct_align(void) {\n\tduk_uint_t error_count = 0;\n\n#if (DUK_USE_ALIGN_BY == 4)\n\tif ((sizeof(duk_hbuffer_fixed) % 4) != 0) {\n\t\tDUK__FAILED(\"sizeof(duk_hbuffer_fixed) not aligned to 4\");\n\t}\n#elif (DUK_USE_ALIGN_BY == 8)\n\tif ((sizeof(duk_hbuffer_fixed) % 8) != 0) {\n\t\tDUK__FAILED(\"sizeof(duk_hbuffer_fixed) not aligned to 8\");\n\t}\n#elif (DUK_USE_ALIGN_BY == 1)\n\t/* no check */\n#else\n#error invalid DUK_USE_ALIGN_BY\n#endif\n\treturn error_count;\n}\n\n/*\n *  64-bit arithmetic\n *\n *  There are some platforms/compilers where 64-bit types are available\n *  but don't work correctly.  Test for known cases.\n */\n\nDUK_LOCAL duk_uint_t duk__selftest_64bit_arithmetic(void) {\n\tduk_uint_t error_count = 0;\n#if defined(DUK_USE_64BIT_OPS)\n\tvolatile duk_int64_t i;\n\tvolatile duk_double_t d;\n\n\t/* Catch a double-to-int64 cast issue encountered in practice. */\n\td = 2147483648.0;\n\ti = (duk_int64_t) d;\n\tif (i != DUK_I64_CONSTANT(0x80000000)) {\n\t\tDUK__FAILED(\"casting 2147483648.0 to duk_int64_t failed\");\n\t}\n#else\n\t/* nop */\n#endif\n\treturn error_count;\n}\n\n/*\n *  Casting\n */\n\nDUK_LOCAL duk_uint_t duk__selftest_cast_double_to_small_uint(void) {\n\t/*\n\t *  https://github.com/svaarala/duktape/issues/127#issuecomment-77863473\n\t */\n\n\tduk_uint_t error_count = 0;\n\n\tduk_double_t d1, d2;\n\tduk_small_uint_t u;\n\n\tduk_double_t d1v, d2v;\n\tduk_small_uint_t uv;\n\n\t/* Test without volatiles */\n\n\td1 = 1.0;\n\tu = (duk_small_uint_t) d1;\n\td2 = (duk_double_t) u;\n\n\tif (!(d1 == 1.0 && u == 1 && d2 == 1.0 && d1 == d2)) {\n\t\tDUK__FAILED(\"double to duk_small_uint_t cast failed\");\n\t}\n\n\t/* Same test with volatiles */\n\n\td1v = 1.0;\n\tuv = (duk_small_uint_t) d1v;\n\td2v = (duk_double_t) uv;\n\n\tif (!(d1v == 1.0 && uv == 1 && d2v == 1.0 && d1v == d2v)) {\n\t\tDUK__FAILED(\"double to duk_small_uint_t cast failed\");\n\t}\n\n\treturn error_count;\n}\n\nDUK_LOCAL duk_uint_t duk__selftest_cast_double_to_uint32(void) {\n\t/*\n\t *  This test fails on an exotic ARM target; double-to-uint\n\t *  cast is incorrectly clamped to -signed- int highest value.\n\t *\n\t *  https://github.com/svaarala/duktape/issues/336\n\t */\n\n\tduk_uint_t error_count = 0;\n\tduk_double_t dv;\n\tduk_uint32_t uv;\n\n\tdv = 3735928559.0;  /* 0xdeadbeef in decimal */\n\tuv = (duk_uint32_t) dv;\n\n\tif (uv != 0xdeadbeefUL) {\n\t\tDUK__FAILED(\"double to duk_uint32_t cast failed\");\n\t}\n\n\treturn error_count;\n}\n\n/*\n *  Minimal test of user supplied allocation functions\n *\n *    - Basic alloc + realloc + free cycle\n *\n *    - Realloc to significantly larger size to (hopefully) trigger a\n *      relocation and check that relocation copying works\n */\n\nDUK_LOCAL duk_uint_t duk__selftest_alloc_funcs(duk_alloc_function alloc_func,\n                                               duk_realloc_function realloc_func,\n                                               duk_free_function free_func,\n                                               void *udata) {\n\tduk_uint_t error_count = 0;\n\tvoid *ptr;\n\tvoid *new_ptr;\n\tduk_small_int_t i, j;\n\tunsigned char x;\n\n\tif (alloc_func == NULL || realloc_func == NULL || free_func == NULL) {\n\t\treturn 0;\n\t}\n\n\tfor (i = 1; i <= 256; i++) {\n\t\tptr = alloc_func(udata, (duk_size_t) i);\n\t\tif (ptr == NULL) {\n\t\t\tDUK_D(DUK_DPRINT(\"alloc failed, ignore\"));\n\t\t\tcontinue;  /* alloc failed, ignore */\n\t\t}\n\t\tfor (j = 0; j < i; j++) {\n\t\t\t((unsigned char *) ptr)[j] = (unsigned char) (0x80 + j);\n\t\t}\n\t\tnew_ptr = realloc_func(udata, ptr, 1024);\n\t\tif (new_ptr == NULL) {\n\t\t\tDUK_D(DUK_DPRINT(\"realloc failed, ignore\"));\n\t\t\tfree_func(udata, ptr);\n\t\t\tcontinue;  /* realloc failed, ignore */\n\t\t}\n\t\tptr = new_ptr;\n\t\tfor (j = 0; j < i; j++) {\n\t\t\tx = ((unsigned char *) ptr)[j];\n\t\t\tif (x != (unsigned char) (0x80 + j)) {\n\t\t\t\tDUK_D(DUK_DPRINT(\"byte at index %ld doesn't match after realloc: %02lx\",\n\t\t\t\t                 (long) j, (unsigned long) x));\n\t\t\t\tDUK__FAILED(\"byte compare after realloc\");\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tfree_func(udata, ptr);\n\t}\n\n\treturn error_count;\n}\n\n/*\n *  Self test main\n */\n\nDUK_INTERNAL duk_uint_t duk_selftest_run_tests(duk_alloc_function alloc_func,\n                                               duk_realloc_function realloc_func,\n                                               duk_free_function free_func,\n                                               void *udata) {\n\tduk_uint_t error_count = 0;\n\n\tDUK_D(DUK_DPRINT(\"self test starting\"));\n\n\terror_count += duk__selftest_types();\n\terror_count += duk__selftest_packed_tval();\n\terror_count += duk__selftest_twos_complement();\n\terror_count += duk__selftest_byte_order();\n\terror_count += duk__selftest_bswap_macros();\n\terror_count += duk__selftest_double_union_size();\n\terror_count += duk__selftest_double_aliasing();\n\terror_count += duk__selftest_double_zero_sign();\n\terror_count += duk__selftest_double_rounding();\n\terror_count += duk__selftest_fmod();\n\terror_count += duk__selftest_struct_align();\n\terror_count += duk__selftest_64bit_arithmetic();\n\terror_count += duk__selftest_cast_double_to_small_uint();\n\terror_count += duk__selftest_cast_double_to_uint32();\n\terror_count += duk__selftest_alloc_funcs(alloc_func, realloc_func, free_func, udata);\n\n\tDUK_D(DUK_DPRINT(\"self test complete, total error count: %ld\", (long) error_count));\n\n\treturn error_count;\n}\n\n#endif  /* DUK_USE_SELF_TESTS */\n\n/* automatic undefs */\n#undef DUK__DBLUNION_CMP_FALSE\n#undef DUK__DBLUNION_CMP_TRUE\n#undef DUK__DOUBLE_COMPARE\n#undef DUK__DOUBLE_INIT\n#undef DUK__FAILED\n#undef DUK__U32_INIT\n/* #include duk_internal.h -> already included */\n#line 2 \"duk_tval.c\"\n\n#if defined(DUK_USE_FASTINT)\n\n/*\n *  Manually optimized double-to-fastint downgrade check.\n *\n *  This check has a large impact on performance, especially for fastint\n *  slow paths, so must be changed carefully.  The code should probably be\n *  optimized for the case where the result does not fit into a fastint,\n *  to minimize the penalty for \"slow path code\" dealing with fractions etc.\n *\n *  At least on one tested soft float ARM platform double-to-int64 coercion\n *  is very slow (and sometimes produces incorrect results, see self tests).\n *  This algorithm combines a fastint compatibility check and extracting the\n *  integer value from an IEEE double for setting the tagged fastint.  For\n *  other platforms a more naive approach might be better.\n *\n *  See doc/fastint.rst for details.\n */\n\nDUK_INTERNAL DUK_ALWAYS_INLINE void duk_tval_set_number_chkfast_fast(duk_tval *tv, duk_double_t x) {\n\tduk_double_union du;\n\tduk_int64_t i;\n\tduk_small_int_t expt;\n\tduk_small_int_t shift;\n\n\t/* XXX: optimize for packed duk_tval directly? */\n\n\tdu.d = x;\n\ti = (duk_int64_t) DUK_DBLUNION_GET_INT64(&du);\n\texpt = (duk_small_int_t) ((i >> 52) & 0x07ff);\n\tshift = expt - 1023;\n\n\tif (shift >= 0 && shift <= 46) {  /* exponents 1023 to 1069 */\n\t\tduk_int64_t t;\n\n\t\tif (((DUK_I64_CONSTANT(0x000fffffffffffff) >> shift) & i) == 0) {\n\t\t\tt = i | DUK_I64_CONSTANT(0x0010000000000000);  /* implicit leading one */\n\t\t\tt = t & DUK_I64_CONSTANT(0x001fffffffffffff);\n\t\t\tt = t >> (52 - shift);\n\t\t\tif (i < 0) {\n\t\t\t\tt = -t;\n\t\t\t}\n\t\t\tDUK_TVAL_SET_FASTINT(tv, t);\n\t\t\treturn;\n\t\t}\n\t} else if (shift == -1023) {  /* exponent 0 */\n\t\tif (i >= 0 && (i & DUK_I64_CONSTANT(0x000fffffffffffff)) == 0) {\n\t\t\t/* Note: reject negative zero. */\n\t\t\tDUK_TVAL_SET_FASTINT(tv, (duk_int64_t) 0);\n\t\t\treturn;\n\t\t}\n\t} else if (shift == 47) {  /* exponent 1070 */\n\t\tif (i < 0 && (i & DUK_I64_CONSTANT(0x000fffffffffffff)) == 0) {\n\t\t\tDUK_TVAL_SET_FASTINT(tv, (duk_int64_t) DUK_FASTINT_MIN);\n\t\t\treturn;\n\t\t}\n\t}\n\n\tDUK_TVAL_SET_DOUBLE(tv, x);\n\treturn;\n}\n\nDUK_INTERNAL DUK_NOINLINE void duk_tval_set_number_chkfast_slow(duk_tval *tv, duk_double_t x) {\n\tduk_tval_set_number_chkfast_fast(tv, x);\n}\n\n/*\n *  Manually optimized number-to-double conversion\n */\n\n#if defined(DUK_USE_FASTINT) && defined(DUK_USE_PACKED_TVAL)\nDUK_INTERNAL DUK_ALWAYS_INLINE duk_double_t duk_tval_get_number_packed(duk_tval *tv) {\n\tduk_double_union du;\n\tduk_uint64_t t;\n\n\tt = (duk_uint64_t) DUK_DBLUNION_GET_UINT64(tv);\n\tif ((t >> 48) != DUK_TAG_FASTINT) {\n\t\treturn tv->d;\n\t} else if (t & DUK_U64_CONSTANT(0x0000800000000000)) {\n\t\tt = (duk_uint64_t) (-((duk_int64_t) t));  /* avoid unary minus on unsigned */\n\t\tt = t & DUK_U64_CONSTANT(0x0000ffffffffffff);  /* negative */\n\t\tt |= DUK_U64_CONSTANT(0xc330000000000000);\n\t\tDUK_DBLUNION_SET_UINT64(&du, t);\n\t\treturn du.d + 4503599627370496.0;  /* 1 << 52 */\n\t} else if (t != 0) {\n\t\tt &= DUK_U64_CONSTANT(0x0000ffffffffffff);  /* positive */\n\t\tt |= DUK_U64_CONSTANT(0x4330000000000000);\n\t\tDUK_DBLUNION_SET_UINT64(&du, t);\n\t\treturn du.d - 4503599627370496.0;  /* 1 << 52 */\n\t} else {\n\t\treturn 0.0;  /* zero */\n\t}\n}\n#endif  /* DUK_USE_FASTINT && DUK_USE_PACKED_TVAL */\n\n#if 0  /* unused */\n#if defined(DUK_USE_FASTINT) && !defined(DUK_USE_PACKED_TVAL)\nDUK_INTERNAL DUK_ALWAYS_INLINE duk_double_t duk_tval_get_number_unpacked(duk_tval *tv) {\n\tduk_double_union du;\n\tduk_uint64_t t;\n\n\tDUK_ASSERT(tv->t == DUK_TAG_NUMBER || tv->t == DUK_TAG_FASTINT);\n\n\tif (tv->t == DUK_TAG_FASTINT) {\n\t\tif (tv->v.fi >= 0) {\n\t\t\tt = DUK_U64_CONSTANT(0x4330000000000000) | (duk_uint64_t) tv->v.fi;\n\t\t\tDUK_DBLUNION_SET_UINT64(&du, t);\n\t\t\treturn du.d - 4503599627370496.0;  /* 1 << 52 */\n\t\t} else {\n\t\t\tt = DUK_U64_CONSTANT(0xc330000000000000) | (duk_uint64_t) (-tv->v.fi);\n\t\t\tDUK_DBLUNION_SET_UINT64(&du, t);\n\t\t\treturn du.d + 4503599627370496.0;  /* 1 << 52 */\n\t\t}\n\t} else {\n\t\treturn tv->v.d;\n\t}\n}\n#endif  /* DUK_USE_FASTINT && DUK_USE_PACKED_TVAL */\n#endif  /* 0 */\n\n#if defined(DUK_USE_FASTINT) && !defined(DUK_USE_PACKED_TVAL)\nDUK_INTERNAL DUK_ALWAYS_INLINE duk_double_t duk_tval_get_number_unpacked_fastint(duk_tval *tv) {\n\tduk_double_union du;\n\tduk_uint64_t t;\n\n\tDUK_ASSERT(tv->t == DUK_TAG_FASTINT);\n\n\tif (tv->v.fi >= 0) {\n\t\tt = DUK_U64_CONSTANT(0x4330000000000000) | (duk_uint64_t) tv->v.fi;\n\t\tDUK_DBLUNION_SET_UINT64(&du, t);\n\t\treturn du.d - 4503599627370496.0;  /* 1 << 52 */\n\t} else {\n\t\tt = DUK_U64_CONSTANT(0xc330000000000000) | (duk_uint64_t) (-tv->v.fi);\n\t\tDUK_DBLUNION_SET_UINT64(&du, t);\n\t\treturn du.d + 4503599627370496.0;  /* 1 << 52 */\n\t}\n}\n#endif  /* DUK_USE_FASTINT && DUK_USE_PACKED_TVAL */\n\n#endif  /* DUK_USE_FASTINT */\n#line 1 \"duk_unicode_tables.c\"\n/*\n *  Unicode support tables automatically generated during build.\n */\n\n/* #include duk_internal.h -> already included */\n\n/*\n *  Unicode tables containing ranges of Unicode characters in a\n *  packed format.  These tables are used to match non-ASCII\n *  characters of complex productions by resorting to a linear\n *  range-by-range comparison.  This is very slow, but is expected\n *  to be very rare in practical Ecmascript source code, and thus\n *  compactness is most important.\n *\n *  The tables are matched using uni_range_match() and the format\n *  is described in tools/extract_chars.py.\n */\n\n#if defined(DUK_USE_SOURCE_NONBMP)\n/* IdentifierStart production with ASCII excluded */\n/* duk_unicode_ids_noa[] */\n/*\n *  Automatically generated by extract_chars.py, do not edit!\n */\n\nconst duk_uint8_t duk_unicode_ids_noa[1036] = {\n249,176,176,80,111,7,47,15,47,254,11,197,191,0,72,2,15,115,66,19,50,7,2,34,\n2,240,66,244,50,247,185,249,98,241,99,8,241,127,58,240,182,47,31,241,191,\n21,18,245,50,15,1,24,27,35,15,2,2,240,239,15,244,156,15,10,241,26,21,6,240,\n101,10,4,15,9,240,159,57,240,82,127,56,242,100,15,4,8,159,1,240,5,115,19,\n240,98,98,4,52,15,2,14,18,47,0,31,5,85,19,240,98,98,18,18,31,17,50,15,5,47,\n2,130,34,240,98,98,18,68,15,4,15,1,31,9,12,115,19,240,98,98,18,68,15,16,18,\n47,1,15,3,2,84,34,52,18,2,20,20,36,191,8,15,38,114,34,240,114,240,4,15,12,\n38,31,16,5,114,34,240,114,146,68,15,18,2,31,1,31,4,114,34,241,147,15,2,6,\n41,47,10,86,240,36,240,130,130,3,111,44,242,2,29,111,44,18,3,18,3,7,50,98,\n34,2,3,18,50,26,3,66,15,7,63,18,15,49,114,241,79,13,79,101,241,191,6,15,2,\n85,52,4,24,37,205,15,3,241,98,6,3,241,178,255,224,63,35,54,32,35,63,25,35,\n63,17,35,54,32,35,62,47,41,35,63,51,241,127,0,240,47,70,53,79,254,21,227,\n240,18,240,166,243,180,168,194,63,0,240,47,0,240,47,0,194,47,1,242,79,21,5,\n15,53,244,137,67,241,34,6,243,107,240,255,35,240,227,76,241,197,240,175,40,\n240,122,242,95,68,15,79,241,255,3,111,41,240,238,27,241,207,12,241,79,27,\n43,241,67,143,82,50,52,26,251,15,50,255,224,8,53,63,22,53,55,32,32,32,47,\n15,63,37,38,32,66,38,67,53,92,98,38,246,96,224,240,44,245,112,80,57,32,68,\n112,32,32,35,42,51,100,80,240,63,25,255,233,107,241,242,241,242,247,87,52,\n29,241,98,6,3,242,136,15,2,240,122,98,98,98,98,98,98,98,111,66,15,254,12,\n146,240,184,132,52,95,70,114,47,74,35,111,25,79,78,240,63,11,242,127,0,255,\n224,244,255,240,0,138,143,60,255,240,4,12,143,28,255,227,127,243,95,30,63,\n253,79,0,177,240,111,31,240,47,15,63,64,241,152,63,87,63,20,39,243,26,34,\n35,47,7,240,255,36,240,15,34,243,5,64,32,223,12,191,7,240,191,13,143,31,\n240,224,240,36,41,180,47,25,240,146,39,240,111,7,64,79,34,32,65,52,48,32,\n240,162,58,130,213,53,53,166,38,47,27,41,191,99,240,255,255,0,26,150,223,7,\n95,33,255,240,0,255,143,254,6,3,245,175,24,109,70,2,146,194,66,2,18,18,245,\n207,19,255,224,93,240,79,48,63,38,241,171,246,100,47,119,241,111,10,127,10,\n207,73,69,53,53,50,241,91,47,10,47,3,33,46,61,241,79,107,243,127,37,255,\n223,13,79,33,242,31,16,240,47,11,111,22,191,14,63,20,87,36,241,207,142,240,\n79,20,95,20,95,24,159,36,248,239,254,2,154,240,107,127,138,83,2,241,194,20,\n3,240,123,240,122,240,255,51,240,50,27,240,107,240,175,56,242,135,31,50,15,\n1,50,34,240,191,30,240,212,240,223,21,114,240,207,13,242,107,240,107,240,\n62,240,47,96,243,159,41,242,62,242,63,254,32,79,37,243,223,29,241,47,9,240,\n207,20,241,191,19,64,223,32,240,3,240,112,32,241,95,2,47,9,244,102,32,35,\n46,41,143,31,241,135,49,63,6,38,33,36,64,240,64,212,249,15,37,240,67,242,\n127,32,240,97,32,250,175,31,241,179,241,111,32,240,96,242,223,27,244,127,\n10,255,224,122,243,15,17,15,254,11,79,41,255,152,47,21,240,48,242,63,14,\n255,226,100,255,226,140,245,143,95,240,63,180,255,233,176,255,227,33,255,\n238,197,255,225,57,255,240,1,10,223,254,18,184,240,255,99,240,239,4,242,15,\n2,63,17,240,86,240,63,254,38,79,53,192,243,76,243,32,241,31,255,0,6,223,\n240,95,254,30,95,255,0,20,1,31,254,175,47,91,108,72,137,255,240,0,101,175,\n69,47,55,33,48,49,51,43,32,38,47,49,35,55,38,47,12,35,36,32,70,47,254,4,99,\n240,146,240,146,240,242,240,146,240,242,240,146,240,242,240,146,240,242,\n240,146,127,254,242,143,181,242,223,52,255,227,176,50,240,178,18,3,2,146,\n50,2,7,5,2,2,2,34,18,3,2,2,2,2,2,18,3,50,98,50,50,2,146,240,22,34,66,240,\n31,255,0,0,56,255,240,9,92,159,27,255,239,39,207,206,63,255,0,5,116,255,\n240,1,133,47,254,17,0,\n};\n#else\n/* IdentifierStart production with ASCII and non-BMP excluded */\n/* duk_unicode_ids_noabmp[] */\n/*\n *  Automatically generated by extract_chars.py, do not edit!\n */\n\nconst duk_uint8_t duk_unicode_ids_noabmp[625] = {\n249,176,176,80,111,7,47,15,47,254,11,197,191,0,72,2,15,115,66,19,50,7,2,34,\n2,240,66,244,50,247,185,249,98,241,99,8,241,127,58,240,182,47,31,241,191,\n21,18,245,50,15,1,24,27,35,15,2,2,240,239,15,244,156,15,10,241,26,21,6,240,\n101,10,4,15,9,240,159,57,240,82,127,56,242,100,15,4,8,159,1,240,5,115,19,\n240,98,98,4,52,15,2,14,18,47,0,31,5,85,19,240,98,98,18,18,31,17,50,15,5,47,\n2,130,34,240,98,98,18,68,15,4,15,1,31,9,12,115,19,240,98,98,18,68,15,16,18,\n47,1,15,3,2,84,34,52,18,2,20,20,36,191,8,15,38,114,34,240,114,240,4,15,12,\n38,31,16,5,114,34,240,114,146,68,15,18,2,31,1,31,4,114,34,241,147,15,2,6,\n41,47,10,86,240,36,240,130,130,3,111,44,242,2,29,111,44,18,3,18,3,7,50,98,\n34,2,3,18,50,26,3,66,15,7,63,18,15,49,114,241,79,13,79,101,241,191,6,15,2,\n85,52,4,24,37,205,15,3,241,98,6,3,241,178,255,224,63,35,54,32,35,63,25,35,\n63,17,35,54,32,35,62,47,41,35,63,51,241,127,0,240,47,70,53,79,254,21,227,\n240,18,240,166,243,180,168,194,63,0,240,47,0,240,47,0,194,47,1,242,79,21,5,\n15,53,244,137,67,241,34,6,243,107,240,255,35,240,227,76,241,197,240,175,40,\n240,122,242,95,68,15,79,241,255,3,111,41,240,238,27,241,207,12,241,79,27,\n43,241,67,143,82,50,52,26,251,15,50,255,224,8,53,63,22,53,55,32,32,32,47,\n15,63,37,38,32,66,38,67,53,92,98,38,246,96,224,240,44,245,112,80,57,32,68,\n112,32,32,35,42,51,100,80,240,63,25,255,233,107,241,242,241,242,247,87,52,\n29,241,98,6,3,242,136,15,2,240,122,98,98,98,98,98,98,98,111,66,15,254,12,\n146,240,184,132,52,95,70,114,47,74,35,111,25,79,78,240,63,11,242,127,0,255,\n224,244,255,240,0,138,143,60,255,240,4,12,143,28,255,227,127,243,95,30,63,\n253,79,0,177,240,111,31,240,47,15,63,64,241,152,63,87,63,20,39,243,26,34,\n35,47,7,240,255,36,240,15,34,243,5,64,32,223,12,191,7,240,191,13,143,31,\n240,224,240,36,41,180,47,25,240,146,39,240,111,7,64,79,34,32,65,52,48,32,\n240,162,58,130,213,53,53,166,38,47,27,41,191,99,240,255,255,0,26,150,223,7,\n95,33,255,240,0,255,143,254,6,3,245,175,24,109,70,2,146,194,66,2,18,18,245,\n207,19,255,224,93,240,79,48,63,38,241,171,246,100,47,119,241,111,10,127,10,\n207,73,69,53,53,50,0,\n};\n#endif\n\n#if defined(DUK_USE_SOURCE_NONBMP)\n/* IdentifierStart production with Letter and ASCII excluded */\n/* duk_unicode_ids_m_let_noa[] */\n/*\n *  Automatically generated by extract_chars.py, do not edit!\n */\n\nconst duk_uint8_t duk_unicode_ids_m_let_noa[42] = {\n255,240,0,94,18,255,233,99,241,51,63,254,215,32,240,184,240,2,255,240,6,89,\n249,255,240,4,148,79,37,255,224,192,9,15,120,79,255,0,15,30,245,240,\n};\n#else\n/* IdentifierStart production with Letter, ASCII, and non-BMP excluded */\n/* duk_unicode_ids_m_let_noabmp[] */\n/*\n *  Automatically generated by extract_chars.py, do not edit!\n */\n\nconst duk_uint8_t duk_unicode_ids_m_let_noabmp[24] = {\n255,240,0,94,18,255,233,99,241,51,63,254,215,32,240,184,240,2,255,240,6,89,\n249,0,\n};\n#endif\n\n#if defined(DUK_USE_SOURCE_NONBMP)\n/* IdentifierPart production with IdentifierStart and ASCII excluded */\n/* duk_unicode_idp_m_ids_noa[] */\n/*\n *  Automatically generated by extract_chars.py, do not edit!\n */\n\nconst duk_uint8_t duk_unicode_idp_m_ids_noa[530] = {\n255,225,243,246,15,254,0,116,255,191,29,32,33,33,32,243,170,242,47,15,112,\n245,118,53,49,35,57,240,144,241,15,11,244,218,240,25,241,56,241,67,40,34,\n36,241,210,246,173,47,17,242,130,47,2,38,177,57,240,50,242,160,38,49,50,\n160,177,57,240,50,242,160,36,81,50,64,240,107,64,194,242,160,39,34,34,240,\n97,57,240,50,242,160,38,49,50,145,177,57,240,64,242,212,66,35,160,240,9,\n240,35,242,198,34,35,129,193,57,240,50,242,160,38,34,35,129,193,57,240,50,\n242,198,34,35,160,177,57,240,65,243,128,85,32,39,121,49,242,240,54,215,41,\n244,144,53,33,197,57,243,1,121,192,32,32,81,242,63,4,33,106,47,20,160,245,\n111,4,41,211,82,34,54,67,235,46,255,225,179,47,254,42,98,240,242,240,241,\n241,1,243,47,16,160,57,241,50,57,245,209,241,64,246,139,91,185,247,41,242,\n244,242,185,47,13,58,121,240,141,243,68,242,31,1,201,240,56,210,241,12,57,\n241,237,242,47,4,153,121,246,130,47,5,80,82,65,251,143,38,100,255,225,0,31,\n35,31,5,15,109,197,4,191,254,175,34,247,240,245,47,16,255,225,30,95,91,31,\n255,0,100,121,159,55,5,159,18,31,66,31,254,0,64,64,80,240,148,244,161,242,\n79,2,185,127,2,240,9,240,231,240,188,241,227,242,29,240,25,192,185,242,29,\n208,145,57,241,50,242,64,34,49,97,32,241,180,97,253,231,33,57,255,240,3,\n225,128,255,225,213,240,15,2,240,4,31,10,47,178,159,23,15,254,27,16,253,64,\n248,116,255,224,25,159,254,68,178,33,99,241,162,80,249,113,255,228,13,47,\n39,239,17,159,1,63,31,175,39,151,47,22,210,159,37,13,47,34,218,36,159,68,\n183,15,146,182,151,63,42,2,99,19,42,11,19,100,79,178,240,42,159,72,240,77,\n159,199,99,143,13,31,68,240,31,1,159,67,201,159,69,229,159,254,9,169,255,\n226,57,114,127,2,159,42,240,98,223,255,0,60,157,159,120,79,45,111,11,159,\n254,46,191,30,240,35,255,240,3,191,225,255,240,0,59,164,69,151,54,241,3,\n248,98,255,228,125,242,47,254,15,79,39,95,34,144,240,0,240,132,46,255,228,\n68,98,240,19,98,18,79,254,121,150,245,246,105,255,240,192,105,175,224,0,\n};\n#else\n/* IdentifierPart production with IdentifierStart, ASCII, and non-BMP excluded */\n/* duk_unicode_idp_m_ids_noabmp[] */\n/*\n *  Automatically generated by extract_chars.py, do not edit!\n */\n\nconst duk_uint8_t duk_unicode_idp_m_ids_noabmp[357] = {\n255,225,243,246,15,254,0,116,255,191,29,32,33,33,32,243,170,242,47,15,112,\n245,118,53,49,35,57,240,144,241,15,11,244,218,240,25,241,56,241,67,40,34,\n36,241,210,246,173,47,17,242,130,47,2,38,177,57,240,50,242,160,38,49,50,\n160,177,57,240,50,242,160,36,81,50,64,240,107,64,194,242,160,39,34,34,240,\n97,57,240,50,242,160,38,49,50,145,177,57,240,64,242,212,66,35,160,240,9,\n240,35,242,198,34,35,129,193,57,240,50,242,160,38,34,35,129,193,57,240,50,\n242,198,34,35,160,177,57,240,65,243,128,85,32,39,121,49,242,240,54,215,41,\n244,144,53,33,197,57,243,1,121,192,32,32,81,242,63,4,33,106,47,20,160,245,\n111,4,41,211,82,34,54,67,235,46,255,225,179,47,254,42,98,240,242,240,241,\n241,1,243,47,16,160,57,241,50,57,245,209,241,64,246,139,91,185,247,41,242,\n244,242,185,47,13,58,121,240,141,243,68,242,31,1,201,240,56,210,241,12,57,\n241,237,242,47,4,153,121,246,130,47,5,80,82,65,251,143,38,100,255,225,0,31,\n35,31,5,15,109,197,4,191,254,175,34,247,240,245,47,16,255,225,30,95,91,31,\n255,0,100,121,159,55,5,159,18,31,66,31,254,0,64,64,80,240,148,244,161,242,\n79,2,185,127,2,240,9,240,231,240,188,241,227,242,29,240,25,192,185,242,29,\n208,145,57,241,50,242,64,34,49,97,32,241,180,97,253,231,33,57,255,240,3,\n225,128,255,225,213,240,15,2,240,4,31,10,47,178,159,23,0,\n};\n#endif\n\n/*\n *  Case conversion tables generated using tools/extract_caseconv.py.\n */\n\n/* duk_unicode_caseconv_uc[] */\n/* duk_unicode_caseconv_lc[] */\n\n/*\n *  Automatically generated by extract_caseconv.py, do not edit!\n */\n\nconst duk_uint8_t duk_unicode_caseconv_uc[1386] = {\n144,3,128,3,0,184,7,192,6,192,112,35,242,199,224,64,74,192,49,32,128,162,\n128,108,65,1,189,129,254,131,3,173,3,136,6,7,98,7,34,68,15,12,14,140,72,30,\n104,28,112,32,67,0,65,4,0,138,0,128,4,1,88,65,76,83,9,252,9,248,6,28,131,4,\n33,4,62,0,62,16,32,124,64,124,96,48,249,0,249,64,129,243,1,243,129,3,232,3,\n233,1,135,216,7,218,4,15,184,15,221,2,31,114,31,200,8,62,236,63,180,8,125,\n224,127,224,16,251,208,255,80,33,247,193,255,160,67,246,3,247,0,135,244,7,\n246,1,15,240,15,244,2,33,112,33,96,32,73,160,73,108,104,176,192,176,1,121,\n104,0,133,2,106,183,1,58,10,31,232,63,228,38,162,1,1,1,0,48,2,102,2,100,12,\n4,232,4,228,64,10,88,10,81,112,23,160,23,144,96,48,96,48,64,128,104,64,104,\n1,128,218,0,217,130,1,206,1,205,16,3,190,3,188,36,7,228,7,224,160,17,24,17,\n16,144,36,112,36,96,160,110,32,110,0,128,246,64,246,6,2,48,130,48,17,4,139,\n4,138,54,9,132,9,130,28,19,68,19,65,128,240,8,240,4,177,234,17,234,6,3,234,\n35,235,33,11,26,11,25,193,150,64,150,64,50,44,236,44,235,5,76,131,76,128,\n94,154,6,154,0,117,57,29,57,16,122,115,58,115,35,244,239,84,239,32,169,223,\n233,223,130,211,200,211,200,2,167,151,167,150,21,79,107,79,104,8,112,26,\n208,26,192,64,56,160,56,128,192,113,128,113,1,128,249,0,248,130,2,128,1,\n166,4,7,240,7,238,8,177,204,177,200,16,96,49,0,48,224,128,110,64,110,1,1,\n51,83,213,2,0,48,35,192,35,176,64,77,32,50,192,139,73,196,49,193,127,48,2,\n212,14,112,3,252,5,224,4,196,1,36,5,252,1,76,6,0,9,12,6,72,6,68,6,84,7,216,\n6,100,6,96,6,104,8,244,6,120,8,128,6,160,6,156,6,252,7,220,7,116,6,56,7,\n204,7,196,9,64,177,188,9,68,177,180,9,72,177,192,9,76,6,4,9,80,6,24,9,100,\n6,60,9,108,6,64,9,114,158,172,9,128,6,76,9,134,158,176,9,140,6,80,9,150,\n158,52,9,160,6,92,9,172,177,136,9,178,158,180,9,196,177,184,9,200,6,116,9,\n212,6,124,9,244,177,144,10,30,158,196,10,32,6,184,10,36,9,16,10,48,9,20,10,\n72,6,220,10,118,158,200,10,122,158,192,13,20,14,100,13,220,13,216,14,176,\n14,24,15,8,14,140,15,48,14,48,15,64,14,72,15,68,14,96,15,84,14,152,15,88,\n14,128,15,92,15,60,15,192,14,104,15,196,14,132,15,200,15,228,15,204,13,252,\n15,212,14,84,19,60,19,0,114,0,16,72,114,4,16,80,114,8,16,120,114,20,16,136,\n114,24,16,168,114,28,17,136,114,34,153,40,117,230,157,244,117,244,177,140,\n122,108,121,128,126,248,14,100,127,148,127,176,133,56,132,200,134,16,134,\n12,177,132,177,128,177,148,8,232,177,152,8,248,179,204,179,202,158,50,158,\n46,173,78,158,207,48,6,252,0,166,0,166,2,147,1,94,0,39,0,248,64,9,64,97,\n128,114,24,28,200,24,64,24,8,29,134,7,74,6,16,6,2,11,15,2,154,130,169,15,\n75,64,9,0,102,35,210,240,2,160,24,64,244,196,0,174,6,20,61,51,0,44,129,133,\n15,77,64,8,32,87,195,234,16,29,40,24,152,250,150,7,74,6,38,6,0,62,169,129,\n210,129,137,129,128,143,171,96,116,160,98,96,104,67,240,16,248,64,28,200,\n252,12,62,18,7,50,63,5,15,133,1,204,143,193,195,225,96,115,35,240,144,248,\n96,28,200,252,44,62,26,7,50,63,13,15,135,1,204,143,195,195,225,224,115,35,\n241,16,248,64,28,200,252,76,62,18,7,50,63,21,15,133,1,204,143,197,195,225,\n96,115,35,241,144,248,96,28,200,252,108,62,26,7,50,63,29,15,135,1,204,143,\n199,195,225,224,115,35,242,16,249,64,28,200,252,140,62,82,7,50,63,37,15,\n149,1,204,143,201,195,229,96,115,35,242,144,249,96,28,200,252,172,62,90,7,\n50,63,45,15,151,1,204,143,203,195,229,224,115,35,243,16,249,64,28,200,252,\n204,62,82,7,50,63,53,15,149,1,204,143,205,195,229,96,115,35,243,144,249,96,\n28,200,252,236,62,90,7,50,63,61,15,151,1,204,143,207,195,229,224,115,35,\n244,16,251,64,28,200,253,12,62,210,7,50,63,69,15,181,1,204,143,209,195,237,\n96,115,35,244,144,251,96,28,200,253,44,62,218,7,50,63,77,15,183,1,204,143,\n211,195,237,224,115,35,245,16,251,64,28,200,253,76,62,210,7,50,63,85,15,\n181,1,204,143,213,195,237,96,115,35,245,144,251,96,28,200,253,108,62,218,7,\n50,63,93,15,183,1,204,143,215,195,237,224,115,35,246,80,253,208,28,200,253,\n156,7,34,7,50,63,105,1,195,1,204,143,219,64,114,32,104,67,246,248,28,136,\n26,16,28,200,253,228,7,34,7,50,63,133,15,229,1,204,143,225,192,114,224,115,\n35,248,144,28,72,28,200,254,52,7,46,6,132,63,143,129,203,129,161,1,204,143,\n230,64,114,224,115,35,250,88,28,200,24,64,24,0,254,158,7,50,6,16,6,2,63,\n173,1,204,129,161,15,235,224,115,32,97,0,104,67,252,88,29,40,24,64,24,0,\n255,30,7,74,6,16,6,2,63,201,1,208,129,137,143,243,64,116,160,104,67,252,\n248,29,40,24,64,26,16,255,148,63,244,7,50,63,231,1,212,129,204,143,250,64,\n113,224,115,35,254,208,29,72,26,16,255,190,7,82,6,132,7,50,63,249,1,212,\n129,204,253,128,64,8,192,8,223,96,48,2,48,2,79,216,20,0,140,0,153,246,7,\n128,35,0,35,0,36,253,130,96,8,192,8,192,9,159,96,176,2,152,2,167,216,52,0,\n166,0,169,246,39,2,162,2,163,125,138,64,168,128,166,191,98,176,42,32,41,\n223,216,180,10,156,10,141,246,47,2,162,2,158,128,\n};\nconst duk_uint8_t duk_unicode_caseconv_lc[680] = {\n152,3,0,3,128,184,6,192,7,192,112,24,144,37,96,64,54,32,81,64,128,226,0,\n235,65,129,199,1,230,130,3,145,3,177,34,7,70,7,134,36,15,244,13,236,24,32,\n0,34,129,0,65,0,67,4,0,166,32,172,41,132,40,11,64,19,9,208,85,184,80,19,\n240,19,248,12,62,16,62,0,32,124,96,124,64,48,249,64,249,0,129,243,129,243,\n1,3,233,3,232,1,135,218,7,216,4,15,196,15,192,8,31,152,31,144,16,63,80,63,\n64,32,126,224,126,192,16,253,208,251,128,33,252,129,247,32,131,251,3,250,0,\n135,246,135,221,129,15,244,15,240,2,31,234,31,122,4,63,240,62,240,8,127,\n232,125,240,17,11,1,11,129,2,75,98,77,3,69,128,5,134,11,203,31,128,143,193,\n127,144,255,160,154,140,4,0,4,4,192,9,144,9,152,48,19,144,19,161,0,41,64,\n41,101,192,94,64,94,129,128,193,0,193,130,1,160,1,161,6,3,102,3,104,8,7,44,\n7,48,72,14,240,14,248,144,31,32,31,48,64,63,0,63,37,0,136,128,136,196,129,\n35,1,35,133,3,112,3,113,4,7,176,7,178,48,17,128,17,132,136,36,80,36,89,176,\n76,16,76,32,224,154,0,154,44,7,128,7,128,101,143,80,15,80,176,31,89,31,81,\n8,88,206,88,208,12,178,0,178,5,145,103,89,103,96,42,100,10,100,18,244,208,\n20,208,35,169,200,169,200,195,211,153,83,153,159,167,121,167,122,5,78,253,\n78,254,22,158,66,158,68,21,60,181,60,184,170,123,74,123,80,67,0,211,1,64,2,\n1,172,1,173,4,3,136,3,140,12,7,20,7,24,16,31,184,31,192,34,199,34,199,48,\n65,128,195,128,196,2,1,184,1,185,5,79,84,4,204,8,0,192,101,128,154,65,1,29,\n129,30,2,16,199,45,39,5,251,240,23,128,15,240,24,16,37,48,24,96,37,64,24,\n224,29,208,24,240,37,144,25,0,37,176,25,16,25,32,25,48,38,0,25,64,38,48,25,\n112,38,128,25,128,25,144,25,208,39,32,25,240,39,80,26,112,26,128,26,224,40,\n128,27,112,41,32,31,16,31,48,31,96,25,80,31,112,27,240,34,0,25,224,35,162,\n198,80,35,208,25,160,35,226,198,96,36,48,24,0,36,64,40,144,36,80,40,192,55,\n96,55,112,55,240,63,48,56,96,58,192,56,192,60,192,60,240,61,112,63,64,59,\n128,63,144,63,32,76,0,76,241,233,224,13,241,251,193,251,49,252,193,252,49,\n254,193,254,81,255,193,255,50,18,96,60,146,18,160,6,178,18,176,14,82,19,34,\n20,226,24,50,24,66,198,2,198,18,198,32,38,178,198,49,215,210,198,64,39,210,\n198,208,37,18,198,224,39,18,198,240,37,2,199,0,37,34,207,34,207,58,119,209,\n215,154,120,186,120,202,120,208,38,90,122,176,37,202,122,192,38,26,122,208,\n38,202,123,0,41,234,123,16,40,122,123,32,41,218,123,58,181,48,32,38,16,3,\n72,24,56,\n};\n\n#if defined(DUK_USE_REGEXP_CANON_WORKAROUND)\n/*\n *  Automatically generated by extract_caseconv.py, do not edit!\n */\n\nconst duk_uint16_t duk_unicode_re_canon_lookup[65536] = {\n0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,\n28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,\n53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,\n78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,65,66,67,68,69,70,\n71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,123,124,125,\n126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,\n144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,\n162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,\n180,924,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,\n198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,\n216,217,218,219,220,221,222,223,192,193,194,195,196,197,198,199,200,201,\n202,203,204,205,206,207,208,209,210,211,212,213,214,247,216,217,218,219,\n220,221,222,376,256,256,258,258,260,260,262,262,264,264,266,266,268,268,\n270,270,272,272,274,274,276,276,278,278,280,280,282,282,284,284,286,286,\n288,288,290,290,292,292,294,294,296,296,298,298,300,300,302,302,304,305,\n306,306,308,308,310,310,312,313,313,315,315,317,317,319,319,321,321,323,\n323,325,325,327,327,329,330,330,332,332,334,334,336,336,338,338,340,340,\n342,342,344,344,346,346,348,348,350,350,352,352,354,354,356,356,358,358,\n360,360,362,362,364,364,366,366,368,368,370,370,372,372,374,374,376,377,\n377,379,379,381,381,383,579,385,386,386,388,388,390,391,391,393,394,395,\n395,397,398,399,400,401,401,403,404,502,406,407,408,408,573,411,412,413,\n544,415,416,416,418,418,420,420,422,423,423,425,426,427,428,428,430,431,\n431,433,434,435,435,437,437,439,440,440,442,443,444,444,446,503,448,449,\n450,451,452,452,452,455,455,455,458,458,458,461,461,463,463,465,465,467,\n467,469,469,471,471,473,473,475,475,398,478,478,480,480,482,482,484,484,\n486,486,488,488,490,490,492,492,494,494,496,497,497,497,500,500,502,503,\n504,504,506,506,508,508,510,510,512,512,514,514,516,516,518,518,520,520,\n522,522,524,524,526,526,528,528,530,530,532,532,534,534,536,536,538,538,\n540,540,542,542,544,545,546,546,548,548,550,550,552,552,554,554,556,556,\n558,558,560,560,562,562,564,565,566,567,568,569,570,571,571,573,574,11390,\n11391,577,577,579,580,581,582,582,584,584,586,586,588,588,590,590,11375,\n11373,11376,385,390,597,393,394,600,399,602,400,42923L,605,606,607,403,\n42924L,610,404,612,42893L,42922L,615,407,406,42926L,11362,42925L,621,622,\n412,624,11374,413,627,628,415,630,631,632,633,634,635,636,11364,638,639,\n422,641,642,425,644,645,646,42929L,430,580,433,434,581,653,654,655,656,657,\n439,659,660,661,662,663,664,665,666,667,668,42930L,42928L,671,672,673,674,\n675,676,677,678,679,680,681,682,683,684,685,686,687,688,689,690,691,692,\n693,694,695,696,697,698,699,700,701,702,703,704,705,706,707,708,709,710,\n711,712,713,714,715,716,717,718,719,720,721,722,723,724,725,726,727,728,\n729,730,731,732,733,734,735,736,737,738,739,740,741,742,743,744,745,746,\n747,748,749,750,751,752,753,754,755,756,757,758,759,760,761,762,763,764,\n765,766,767,768,769,770,771,772,773,774,775,776,777,778,779,780,781,782,\n783,784,785,786,787,788,789,790,791,792,793,794,795,796,797,798,799,800,\n801,802,803,804,805,806,807,808,809,810,811,812,813,814,815,816,817,818,\n819,820,821,822,823,824,825,826,827,828,829,830,831,832,833,834,835,836,\n921,838,839,840,841,842,843,844,845,846,847,848,849,850,851,852,853,854,\n855,856,857,858,859,860,861,862,863,864,865,866,867,868,869,870,871,872,\n873,874,875,876,877,878,879,880,880,882,882,884,885,886,886,888,889,890,\n1021,1022,1023,894,895,896,897,898,899,900,901,902,903,904,905,906,907,908,\n909,910,911,912,913,914,915,916,917,918,919,920,921,922,923,924,925,926,\n927,928,929,930,931,932,933,934,935,936,937,938,939,902,904,905,906,944,\n913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,931,\n931,932,933,934,935,936,937,938,939,908,910,911,975,914,920,978,979,980,\n934,928,975,984,984,986,986,988,988,990,990,992,992,994,994,996,996,998,\n998,1000,1000,1002,1002,1004,1004,1006,1006,922,929,1017,895,1012,917,1014,\n1015,1015,1017,1018,1018,1020,1021,1022,1023,1024,1025,1026,1027,1028,1029,\n1030,1031,1032,1033,1034,1035,1036,1037,1038,1039,1040,1041,1042,1043,1044,\n1045,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,\n1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,1040,1041,1042,\n1043,1044,1045,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,\n1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,1024,\n1025,1026,1027,1028,1029,1030,1031,1032,1033,1034,1035,1036,1037,1038,1039,\n1120,1120,1122,1122,1124,1124,1126,1126,1128,1128,1130,1130,1132,1132,1134,\n1134,1136,1136,1138,1138,1140,1140,1142,1142,1144,1144,1146,1146,1148,1148,\n1150,1150,1152,1152,1154,1155,1156,1157,1158,1159,1160,1161,1162,1162,1164,\n1164,1166,1166,1168,1168,1170,1170,1172,1172,1174,1174,1176,1176,1178,1178,\n1180,1180,1182,1182,1184,1184,1186,1186,1188,1188,1190,1190,1192,1192,1194,\n1194,1196,1196,1198,1198,1200,1200,1202,1202,1204,1204,1206,1206,1208,1208,\n1210,1210,1212,1212,1214,1214,1216,1217,1217,1219,1219,1221,1221,1223,1223,\n1225,1225,1227,1227,1229,1229,1216,1232,1232,1234,1234,1236,1236,1238,1238,\n1240,1240,1242,1242,1244,1244,1246,1246,1248,1248,1250,1250,1252,1252,1254,\n1254,1256,1256,1258,1258,1260,1260,1262,1262,1264,1264,1266,1266,1268,1268,\n1270,1270,1272,1272,1274,1274,1276,1276,1278,1278,1280,1280,1282,1282,1284,\n1284,1286,1286,1288,1288,1290,1290,1292,1292,1294,1294,1296,1296,1298,1298,\n1300,1300,1302,1302,1304,1304,1306,1306,1308,1308,1310,1310,1312,1312,1314,\n1314,1316,1316,1318,1318,1320,1320,1322,1322,1324,1324,1326,1326,1328,1329,\n1330,1331,1332,1333,1334,1335,1336,1337,1338,1339,1340,1341,1342,1343,1344,\n1345,1346,1347,1348,1349,1350,1351,1352,1353,1354,1355,1356,1357,1358,1359,\n1360,1361,1362,1363,1364,1365,1366,1367,1368,1369,1370,1371,1372,1373,1374,\n1375,1376,1329,1330,1331,1332,1333,1334,1335,1336,1337,1338,1339,1340,1341,\n1342,1343,1344,1345,1346,1347,1348,1349,1350,1351,1352,1353,1354,1355,1356,\n1357,1358,1359,1360,1361,1362,1363,1364,1365,1366,1415,1416,1417,1418,1419,\n1420,1421,1422,1423,1424,1425,1426,1427,1428,1429,1430,1431,1432,1433,1434,\n1435,1436,1437,1438,1439,1440,1441,1442,1443,1444,1445,1446,1447,1448,1449,\n1450,1451,1452,1453,1454,1455,1456,1457,1458,1459,1460,1461,1462,1463,1464,\n1465,1466,1467,1468,1469,1470,1471,1472,1473,1474,1475,1476,1477,1478,1479,\n1480,1481,1482,1483,1484,1485,1486,1487,1488,1489,1490,1491,1492,1493,1494,\n1495,1496,1497,1498,1499,1500,1501,1502,1503,1504,1505,1506,1507,1508,1509,\n1510,1511,1512,1513,1514,1515,1516,1517,1518,1519,1520,1521,1522,1523,1524,\n1525,1526,1527,1528,1529,1530,1531,1532,1533,1534,1535,1536,1537,1538,1539,\n1540,1541,1542,1543,1544,1545,1546,1547,1548,1549,1550,1551,1552,1553,1554,\n1555,1556,1557,1558,1559,1560,1561,1562,1563,1564,1565,1566,1567,1568,1569,\n1570,1571,1572,1573,1574,1575,1576,1577,1578,1579,1580,1581,1582,1583,1584,\n1585,1586,1587,1588,1589,1590,1591,1592,1593,1594,1595,1596,1597,1598,1599,\n1600,1601,1602,1603,1604,1605,1606,1607,1608,1609,1610,1611,1612,1613,1614,\n1615,1616,1617,1618,1619,1620,1621,1622,1623,1624,1625,1626,1627,1628,1629,\n1630,1631,1632,1633,1634,1635,1636,1637,1638,1639,1640,1641,1642,1643,1644,\n1645,1646,1647,1648,1649,1650,1651,1652,1653,1654,1655,1656,1657,1658,1659,\n1660,1661,1662,1663,1664,1665,1666,1667,1668,1669,1670,1671,1672,1673,1674,\n1675,1676,1677,1678,1679,1680,1681,1682,1683,1684,1685,1686,1687,1688,1689,\n1690,1691,1692,1693,1694,1695,1696,1697,1698,1699,1700,1701,1702,1703,1704,\n1705,1706,1707,1708,1709,1710,1711,1712,1713,1714,1715,1716,1717,1718,1719,\n1720,1721,1722,1723,1724,1725,1726,1727,1728,1729,1730,1731,1732,1733,1734,\n1735,1736,1737,1738,1739,1740,1741,1742,1743,1744,1745,1746,1747,1748,1749,\n1750,1751,1752,1753,1754,1755,1756,1757,1758,1759,1760,1761,1762,1763,1764,\n1765,1766,1767,1768,1769,1770,1771,1772,1773,1774,1775,1776,1777,1778,1779,\n1780,1781,1782,1783,1784,1785,1786,1787,1788,1789,1790,1791,1792,1793,1794,\n1795,1796,1797,1798,1799,1800,1801,1802,1803,1804,1805,1806,1807,1808,1809,\n1810,1811,1812,1813,1814,1815,1816,1817,1818,1819,1820,1821,1822,1823,1824,\n1825,1826,1827,1828,1829,1830,1831,1832,1833,1834,1835,1836,1837,1838,1839,\n1840,1841,1842,1843,1844,1845,1846,1847,1848,1849,1850,1851,1852,1853,1854,\n1855,1856,1857,1858,1859,1860,1861,1862,1863,1864,1865,1866,1867,1868,1869,\n1870,1871,1872,1873,1874,1875,1876,1877,1878,1879,1880,1881,1882,1883,1884,\n1885,1886,1887,1888,1889,1890,1891,1892,1893,1894,1895,1896,1897,1898,1899,\n1900,1901,1902,1903,1904,1905,1906,1907,1908,1909,1910,1911,1912,1913,1914,\n1915,1916,1917,1918,1919,1920,1921,1922,1923,1924,1925,1926,1927,1928,1929,\n1930,1931,1932,1933,1934,1935,1936,1937,1938,1939,1940,1941,1942,1943,1944,\n1945,1946,1947,1948,1949,1950,1951,1952,1953,1954,1955,1956,1957,1958,1959,\n1960,1961,1962,1963,1964,1965,1966,1967,1968,1969,1970,1971,1972,1973,1974,\n1975,1976,1977,1978,1979,1980,1981,1982,1983,1984,1985,1986,1987,1988,1989,\n1990,1991,1992,1993,1994,1995,1996,1997,1998,1999,2000,2001,2002,2003,2004,\n2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019,\n2020,2021,2022,2023,2024,2025,2026,2027,2028,2029,2030,2031,2032,2033,2034,\n2035,2036,2037,2038,2039,2040,2041,2042,2043,2044,2045,2046,2047,2048,2049,\n2050,2051,2052,2053,2054,2055,2056,2057,2058,2059,2060,2061,2062,2063,2064,\n2065,2066,2067,2068,2069,2070,2071,2072,2073,2074,2075,2076,2077,2078,2079,\n2080,2081,2082,2083,2084,2085,2086,2087,2088,2089,2090,2091,2092,2093,2094,\n2095,2096,2097,2098,2099,2100,2101,2102,2103,2104,2105,2106,2107,2108,2109,\n2110,2111,2112,2113,2114,2115,2116,2117,2118,2119,2120,2121,2122,2123,2124,\n2125,2126,2127,2128,2129,2130,2131,2132,2133,2134,2135,2136,2137,2138,2139,\n2140,2141,2142,2143,2144,2145,2146,2147,2148,2149,2150,2151,2152,2153,2154,\n2155,2156,2157,2158,2159,2160,2161,2162,2163,2164,2165,2166,2167,2168,2169,\n2170,2171,2172,2173,2174,2175,2176,2177,2178,2179,2180,2181,2182,2183,2184,\n2185,2186,2187,2188,2189,2190,2191,2192,2193,2194,2195,2196,2197,2198,2199,\n2200,2201,2202,2203,2204,2205,2206,2207,2208,2209,2210,2211,2212,2213,2214,\n2215,2216,2217,2218,2219,2220,2221,2222,2223,2224,2225,2226,2227,2228,2229,\n2230,2231,2232,2233,2234,2235,2236,2237,2238,2239,2240,2241,2242,2243,2244,\n2245,2246,2247,2248,2249,2250,2251,2252,2253,2254,2255,2256,2257,2258,2259,\n2260,2261,2262,2263,2264,2265,2266,2267,2268,2269,2270,2271,2272,2273,2274,\n2275,2276,2277,2278,2279,2280,2281,2282,2283,2284,2285,2286,2287,2288,2289,\n2290,2291,2292,2293,2294,2295,2296,2297,2298,2299,2300,2301,2302,2303,2304,\n2305,2306,2307,2308,2309,2310,2311,2312,2313,2314,2315,2316,2317,2318,2319,\n2320,2321,2322,2323,2324,2325,2326,2327,2328,2329,2330,2331,2332,2333,2334,\n2335,2336,2337,2338,2339,2340,2341,2342,2343,2344,2345,2346,2347,2348,2349,\n2350,2351,2352,2353,2354,2355,2356,2357,2358,2359,2360,2361,2362,2363,2364,\n2365,2366,2367,2368,2369,2370,2371,2372,2373,2374,2375,2376,2377,2378,2379,\n2380,2381,2382,2383,2384,2385,2386,2387,2388,2389,2390,2391,2392,2393,2394,\n2395,2396,2397,2398,2399,2400,2401,2402,2403,2404,2405,2406,2407,2408,2409,\n2410,2411,2412,2413,2414,2415,2416,2417,2418,2419,2420,2421,2422,2423,2424,\n2425,2426,2427,2428,2429,2430,2431,2432,2433,2434,2435,2436,2437,2438,2439,\n2440,2441,2442,2443,2444,2445,2446,2447,2448,2449,2450,2451,2452,2453,2454,\n2455,2456,2457,2458,2459,2460,2461,2462,2463,2464,2465,2466,2467,2468,2469,\n2470,2471,2472,2473,2474,2475,2476,2477,2478,2479,2480,2481,2482,2483,2484,\n2485,2486,2487,2488,2489,2490,2491,2492,2493,2494,2495,2496,2497,2498,2499,\n2500,2501,2502,2503,2504,2505,2506,2507,2508,2509,2510,2511,2512,2513,2514,\n2515,2516,2517,2518,2519,2520,2521,2522,2523,2524,2525,2526,2527,2528,2529,\n2530,2531,2532,2533,2534,2535,2536,2537,2538,2539,2540,2541,2542,2543,2544,\n2545,2546,2547,2548,2549,2550,2551,2552,2553,2554,2555,2556,2557,2558,2559,\n2560,2561,2562,2563,2564,2565,2566,2567,2568,2569,2570,2571,2572,2573,2574,\n2575,2576,2577,2578,2579,2580,2581,2582,2583,2584,2585,2586,2587,2588,2589,\n2590,2591,2592,2593,2594,2595,2596,2597,2598,2599,2600,2601,2602,2603,2604,\n2605,2606,2607,2608,2609,2610,2611,2612,2613,2614,2615,2616,2617,2618,2619,\n2620,2621,2622,2623,2624,2625,2626,2627,2628,2629,2630,2631,2632,2633,2634,\n2635,2636,2637,2638,2639,2640,2641,2642,2643,2644,2645,2646,2647,2648,2649,\n2650,2651,2652,2653,2654,2655,2656,2657,2658,2659,2660,2661,2662,2663,2664,\n2665,2666,2667,2668,2669,2670,2671,2672,2673,2674,2675,2676,2677,2678,2679,\n2680,2681,2682,2683,2684,2685,2686,2687,2688,2689,2690,2691,2692,2693,2694,\n2695,2696,2697,2698,2699,2700,2701,2702,2703,2704,2705,2706,2707,2708,2709,\n2710,2711,2712,2713,2714,2715,2716,2717,2718,2719,2720,2721,2722,2723,2724,\n2725,2726,2727,2728,2729,2730,2731,2732,2733,2734,2735,2736,2737,2738,2739,\n2740,2741,2742,2743,2744,2745,2746,2747,2748,2749,2750,2751,2752,2753,2754,\n2755,2756,2757,2758,2759,2760,2761,2762,2763,2764,2765,2766,2767,2768,2769,\n2770,2771,2772,2773,2774,2775,2776,2777,2778,2779,2780,2781,2782,2783,2784,\n2785,2786,2787,2788,2789,2790,2791,2792,2793,2794,2795,2796,2797,2798,2799,\n2800,2801,2802,2803,2804,2805,2806,2807,2808,2809,2810,2811,2812,2813,2814,\n2815,2816,2817,2818,2819,2820,2821,2822,2823,2824,2825,2826,2827,2828,2829,\n2830,2831,2832,2833,2834,2835,2836,2837,2838,2839,2840,2841,2842,2843,2844,\n2845,2846,2847,2848,2849,2850,2851,2852,2853,2854,2855,2856,2857,2858,2859,\n2860,2861,2862,2863,2864,2865,2866,2867,2868,2869,2870,2871,2872,2873,2874,\n2875,2876,2877,2878,2879,2880,2881,2882,2883,2884,2885,2886,2887,2888,2889,\n2890,2891,2892,2893,2894,2895,2896,2897,2898,2899,2900,2901,2902,2903,2904,\n2905,2906,2907,2908,2909,2910,2911,2912,2913,2914,2915,2916,2917,2918,2919,\n2920,2921,2922,2923,2924,2925,2926,2927,2928,2929,2930,2931,2932,2933,2934,\n2935,2936,2937,2938,2939,2940,2941,2942,2943,2944,2945,2946,2947,2948,2949,\n2950,2951,2952,2953,2954,2955,2956,2957,2958,2959,2960,2961,2962,2963,2964,\n2965,2966,2967,2968,2969,2970,2971,2972,2973,2974,2975,2976,2977,2978,2979,\n2980,2981,2982,2983,2984,2985,2986,2987,2988,2989,2990,2991,2992,2993,2994,\n2995,2996,2997,2998,2999,3000,3001,3002,3003,3004,3005,3006,3007,3008,3009,\n3010,3011,3012,3013,3014,3015,3016,3017,3018,3019,3020,3021,3022,3023,3024,\n3025,3026,3027,3028,3029,3030,3031,3032,3033,3034,3035,3036,3037,3038,3039,\n3040,3041,3042,3043,3044,3045,3046,3047,3048,3049,3050,3051,3052,3053,3054,\n3055,3056,3057,3058,3059,3060,3061,3062,3063,3064,3065,3066,3067,3068,3069,\n3070,3071,3072,3073,3074,3075,3076,3077,3078,3079,3080,3081,3082,3083,3084,\n3085,3086,3087,3088,3089,3090,3091,3092,3093,3094,3095,3096,3097,3098,3099,\n3100,3101,3102,3103,3104,3105,3106,3107,3108,3109,3110,3111,3112,3113,3114,\n3115,3116,3117,3118,3119,3120,3121,3122,3123,3124,3125,3126,3127,3128,3129,\n3130,3131,3132,3133,3134,3135,3136,3137,3138,3139,3140,3141,3142,3143,3144,\n3145,3146,3147,3148,3149,3150,3151,3152,3153,3154,3155,3156,3157,3158,3159,\n3160,3161,3162,3163,3164,3165,3166,3167,3168,3169,3170,3171,3172,3173,3174,\n3175,3176,3177,3178,3179,3180,3181,3182,3183,3184,3185,3186,3187,3188,3189,\n3190,3191,3192,3193,3194,3195,3196,3197,3198,3199,3200,3201,3202,3203,3204,\n3205,3206,3207,3208,3209,3210,3211,3212,3213,3214,3215,3216,3217,3218,3219,\n3220,3221,3222,3223,3224,3225,3226,3227,3228,3229,3230,3231,3232,3233,3234,\n3235,3236,3237,3238,3239,3240,3241,3242,3243,3244,3245,3246,3247,3248,3249,\n3250,3251,3252,3253,3254,3255,3256,3257,3258,3259,3260,3261,3262,3263,3264,\n3265,3266,3267,3268,3269,3270,3271,3272,3273,3274,3275,3276,3277,3278,3279,\n3280,3281,3282,3283,3284,3285,3286,3287,3288,3289,3290,3291,3292,3293,3294,\n3295,3296,3297,3298,3299,3300,3301,3302,3303,3304,3305,3306,3307,3308,3309,\n3310,3311,3312,3313,3314,3315,3316,3317,3318,3319,3320,3321,3322,3323,3324,\n3325,3326,3327,3328,3329,3330,3331,3332,3333,3334,3335,3336,3337,3338,3339,\n3340,3341,3342,3343,3344,3345,3346,3347,3348,3349,3350,3351,3352,3353,3354,\n3355,3356,3357,3358,3359,3360,3361,3362,3363,3364,3365,3366,3367,3368,3369,\n3370,3371,3372,3373,3374,3375,3376,3377,3378,3379,3380,3381,3382,3383,3384,\n3385,3386,3387,3388,3389,3390,3391,3392,3393,3394,3395,3396,3397,3398,3399,\n3400,3401,3402,3403,3404,3405,3406,3407,3408,3409,3410,3411,3412,3413,3414,\n3415,3416,3417,3418,3419,3420,3421,3422,3423,3424,3425,3426,3427,3428,3429,\n3430,3431,3432,3433,3434,3435,3436,3437,3438,3439,3440,3441,3442,3443,3444,\n3445,3446,3447,3448,3449,3450,3451,3452,3453,3454,3455,3456,3457,3458,3459,\n3460,3461,3462,3463,3464,3465,3466,3467,3468,3469,3470,3471,3472,3473,3474,\n3475,3476,3477,3478,3479,3480,3481,3482,3483,3484,3485,3486,3487,3488,3489,\n3490,3491,3492,3493,3494,3495,3496,3497,3498,3499,3500,3501,3502,3503,3504,\n3505,3506,3507,3508,3509,3510,3511,3512,3513,3514,3515,3516,3517,3518,3519,\n3520,3521,3522,3523,3524,3525,3526,3527,3528,3529,3530,3531,3532,3533,3534,\n3535,3536,3537,3538,3539,3540,3541,3542,3543,3544,3545,3546,3547,3548,3549,\n3550,3551,3552,3553,3554,3555,3556,3557,3558,3559,3560,3561,3562,3563,3564,\n3565,3566,3567,3568,3569,3570,3571,3572,3573,3574,3575,3576,3577,3578,3579,\n3580,3581,3582,3583,3584,3585,3586,3587,3588,3589,3590,3591,3592,3593,3594,\n3595,3596,3597,3598,3599,3600,3601,3602,3603,3604,3605,3606,3607,3608,3609,\n3610,3611,3612,3613,3614,3615,3616,3617,3618,3619,3620,3621,3622,3623,3624,\n3625,3626,3627,3628,3629,3630,3631,3632,3633,3634,3635,3636,3637,3638,3639,\n3640,3641,3642,3643,3644,3645,3646,3647,3648,3649,3650,3651,3652,3653,3654,\n3655,3656,3657,3658,3659,3660,3661,3662,3663,3664,3665,3666,3667,3668,3669,\n3670,3671,3672,3673,3674,3675,3676,3677,3678,3679,3680,3681,3682,3683,3684,\n3685,3686,3687,3688,3689,3690,3691,3692,3693,3694,3695,3696,3697,3698,3699,\n3700,3701,3702,3703,3704,3705,3706,3707,3708,3709,3710,3711,3712,3713,3714,\n3715,3716,3717,3718,3719,3720,3721,3722,3723,3724,3725,3726,3727,3728,3729,\n3730,3731,3732,3733,3734,3735,3736,3737,3738,3739,3740,3741,3742,3743,3744,\n3745,3746,3747,3748,3749,3750,3751,3752,3753,3754,3755,3756,3757,3758,3759,\n3760,3761,3762,3763,3764,3765,3766,3767,3768,3769,3770,3771,3772,3773,3774,\n3775,3776,3777,3778,3779,3780,3781,3782,3783,3784,3785,3786,3787,3788,3789,\n3790,3791,3792,3793,3794,3795,3796,3797,3798,3799,3800,3801,3802,3803,3804,\n3805,3806,3807,3808,3809,3810,3811,3812,3813,3814,3815,3816,3817,3818,3819,\n3820,3821,3822,3823,3824,3825,3826,3827,3828,3829,3830,3831,3832,3833,3834,\n3835,3836,3837,3838,3839,3840,3841,3842,3843,3844,3845,3846,3847,3848,3849,\n3850,3851,3852,3853,3854,3855,3856,3857,3858,3859,3860,3861,3862,3863,3864,\n3865,3866,3867,3868,3869,3870,3871,3872,3873,3874,3875,3876,3877,3878,3879,\n3880,3881,3882,3883,3884,3885,3886,3887,3888,3889,3890,3891,3892,3893,3894,\n3895,3896,3897,3898,3899,3900,3901,3902,3903,3904,3905,3906,3907,3908,3909,\n3910,3911,3912,3913,3914,3915,3916,3917,3918,3919,3920,3921,3922,3923,3924,\n3925,3926,3927,3928,3929,3930,3931,3932,3933,3934,3935,3936,3937,3938,3939,\n3940,3941,3942,3943,3944,3945,3946,3947,3948,3949,3950,3951,3952,3953,3954,\n3955,3956,3957,3958,3959,3960,3961,3962,3963,3964,3965,3966,3967,3968,3969,\n3970,3971,3972,3973,3974,3975,3976,3977,3978,3979,3980,3981,3982,3983,3984,\n3985,3986,3987,3988,3989,3990,3991,3992,3993,3994,3995,3996,3997,3998,3999,\n4000,4001,4002,4003,4004,4005,4006,4007,4008,4009,4010,4011,4012,4013,4014,\n4015,4016,4017,4018,4019,4020,4021,4022,4023,4024,4025,4026,4027,4028,4029,\n4030,4031,4032,4033,4034,4035,4036,4037,4038,4039,4040,4041,4042,4043,4044,\n4045,4046,4047,4048,4049,4050,4051,4052,4053,4054,4055,4056,4057,4058,4059,\n4060,4061,4062,4063,4064,4065,4066,4067,4068,4069,4070,4071,4072,4073,4074,\n4075,4076,4077,4078,4079,4080,4081,4082,4083,4084,4085,4086,4087,4088,4089,\n4090,4091,4092,4093,4094,4095,4096,4097,4098,4099,4100,4101,4102,4103,4104,\n4105,4106,4107,4108,4109,4110,4111,4112,4113,4114,4115,4116,4117,4118,4119,\n4120,4121,4122,4123,4124,4125,4126,4127,4128,4129,4130,4131,4132,4133,4134,\n4135,4136,4137,4138,4139,4140,4141,4142,4143,4144,4145,4146,4147,4148,4149,\n4150,4151,4152,4153,4154,4155,4156,4157,4158,4159,4160,4161,4162,4163,4164,\n4165,4166,4167,4168,4169,4170,4171,4172,4173,4174,4175,4176,4177,4178,4179,\n4180,4181,4182,4183,4184,4185,4186,4187,4188,4189,4190,4191,4192,4193,4194,\n4195,4196,4197,4198,4199,4200,4201,4202,4203,4204,4205,4206,4207,4208,4209,\n4210,4211,4212,4213,4214,4215,4216,4217,4218,4219,4220,4221,4222,4223,4224,\n4225,4226,4227,4228,4229,4230,4231,4232,4233,4234,4235,4236,4237,4238,4239,\n4240,4241,4242,4243,4244,4245,4246,4247,4248,4249,4250,4251,4252,4253,4254,\n4255,4256,4257,4258,4259,4260,4261,4262,4263,4264,4265,4266,4267,4268,4269,\n4270,4271,4272,4273,4274,4275,4276,4277,4278,4279,4280,4281,4282,4283,4284,\n4285,4286,4287,4288,4289,4290,4291,4292,4293,4294,4295,4296,4297,4298,4299,\n4300,4301,4302,4303,4304,4305,4306,4307,4308,4309,4310,4311,4312,4313,4314,\n4315,4316,4317,4318,4319,4320,4321,4322,4323,4324,4325,4326,4327,4328,4329,\n4330,4331,4332,4333,4334,4335,4336,4337,4338,4339,4340,4341,4342,4343,4344,\n4345,4346,4347,4348,4349,4350,4351,4352,4353,4354,4355,4356,4357,4358,4359,\n4360,4361,4362,4363,4364,4365,4366,4367,4368,4369,4370,4371,4372,4373,4374,\n4375,4376,4377,4378,4379,4380,4381,4382,4383,4384,4385,4386,4387,4388,4389,\n4390,4391,4392,4393,4394,4395,4396,4397,4398,4399,4400,4401,4402,4403,4404,\n4405,4406,4407,4408,4409,4410,4411,4412,4413,4414,4415,4416,4417,4418,4419,\n4420,4421,4422,4423,4424,4425,4426,4427,4428,4429,4430,4431,4432,4433,4434,\n4435,4436,4437,4438,4439,4440,4441,4442,4443,4444,4445,4446,4447,4448,4449,\n4450,4451,4452,4453,4454,4455,4456,4457,4458,4459,4460,4461,4462,4463,4464,\n4465,4466,4467,4468,4469,4470,4471,4472,4473,4474,4475,4476,4477,4478,4479,\n4480,4481,4482,4483,4484,4485,4486,4487,4488,4489,4490,4491,4492,4493,4494,\n4495,4496,4497,4498,4499,4500,4501,4502,4503,4504,4505,4506,4507,4508,4509,\n4510,4511,4512,4513,4514,4515,4516,4517,4518,4519,4520,4521,4522,4523,4524,\n4525,4526,4527,4528,4529,4530,4531,4532,4533,4534,4535,4536,4537,4538,4539,\n4540,4541,4542,4543,4544,4545,4546,4547,4548,4549,4550,4551,4552,4553,4554,\n4555,4556,4557,4558,4559,4560,4561,4562,4563,4564,4565,4566,4567,4568,4569,\n4570,4571,4572,4573,4574,4575,4576,4577,4578,4579,4580,4581,4582,4583,4584,\n4585,4586,4587,4588,4589,4590,4591,4592,4593,4594,4595,4596,4597,4598,4599,\n4600,4601,4602,4603,4604,4605,4606,4607,4608,4609,4610,4611,4612,4613,4614,\n4615,4616,4617,4618,4619,4620,4621,4622,4623,4624,4625,4626,4627,4628,4629,\n4630,4631,4632,4633,4634,4635,4636,4637,4638,4639,4640,4641,4642,4643,4644,\n4645,4646,4647,4648,4649,4650,4651,4652,4653,4654,4655,4656,4657,4658,4659,\n4660,4661,4662,4663,4664,4665,4666,4667,4668,4669,4670,4671,4672,4673,4674,\n4675,4676,4677,4678,4679,4680,4681,4682,4683,4684,4685,4686,4687,4688,4689,\n4690,4691,4692,4693,4694,4695,4696,4697,4698,4699,4700,4701,4702,4703,4704,\n4705,4706,4707,4708,4709,4710,4711,4712,4713,4714,4715,4716,4717,4718,4719,\n4720,4721,4722,4723,4724,4725,4726,4727,4728,4729,4730,4731,4732,4733,4734,\n4735,4736,4737,4738,4739,4740,4741,4742,4743,4744,4745,4746,4747,4748,4749,\n4750,4751,4752,4753,4754,4755,4756,4757,4758,4759,4760,4761,4762,4763,4764,\n4765,4766,4767,4768,4769,4770,4771,4772,4773,4774,4775,4776,4777,4778,4779,\n4780,4781,4782,4783,4784,4785,4786,4787,4788,4789,4790,4791,4792,4793,4794,\n4795,4796,4797,4798,4799,4800,4801,4802,4803,4804,4805,4806,4807,4808,4809,\n4810,4811,4812,4813,4814,4815,4816,4817,4818,4819,4820,4821,4822,4823,4824,\n4825,4826,4827,4828,4829,4830,4831,4832,4833,4834,4835,4836,4837,4838,4839,\n4840,4841,4842,4843,4844,4845,4846,4847,4848,4849,4850,4851,4852,4853,4854,\n4855,4856,4857,4858,4859,4860,4861,4862,4863,4864,4865,4866,4867,4868,4869,\n4870,4871,4872,4873,4874,4875,4876,4877,4878,4879,4880,4881,4882,4883,4884,\n4885,4886,4887,4888,4889,4890,4891,4892,4893,4894,4895,4896,4897,4898,4899,\n4900,4901,4902,4903,4904,4905,4906,4907,4908,4909,4910,4911,4912,4913,4914,\n4915,4916,4917,4918,4919,4920,4921,4922,4923,4924,4925,4926,4927,4928,4929,\n4930,4931,4932,4933,4934,4935,4936,4937,4938,4939,4940,4941,4942,4943,4944,\n4945,4946,4947,4948,4949,4950,4951,4952,4953,4954,4955,4956,4957,4958,4959,\n4960,4961,4962,4963,4964,4965,4966,4967,4968,4969,4970,4971,4972,4973,4974,\n4975,4976,4977,4978,4979,4980,4981,4982,4983,4984,4985,4986,4987,4988,4989,\n4990,4991,4992,4993,4994,4995,4996,4997,4998,4999,5000,5001,5002,5003,5004,\n5005,5006,5007,5008,5009,5010,5011,5012,5013,5014,5015,5016,5017,5018,5019,\n5020,5021,5022,5023,5024,5025,5026,5027,5028,5029,5030,5031,5032,5033,5034,\n5035,5036,5037,5038,5039,5040,5041,5042,5043,5044,5045,5046,5047,5048,5049,\n5050,5051,5052,5053,5054,5055,5056,5057,5058,5059,5060,5061,5062,5063,5064,\n5065,5066,5067,5068,5069,5070,5071,5072,5073,5074,5075,5076,5077,5078,5079,\n5080,5081,5082,5083,5084,5085,5086,5087,5088,5089,5090,5091,5092,5093,5094,\n5095,5096,5097,5098,5099,5100,5101,5102,5103,5104,5105,5106,5107,5108,5109,\n5110,5111,5104,5105,5106,5107,5108,5109,5118,5119,5120,5121,5122,5123,5124,\n5125,5126,5127,5128,5129,5130,5131,5132,5133,5134,5135,5136,5137,5138,5139,\n5140,5141,5142,5143,5144,5145,5146,5147,5148,5149,5150,5151,5152,5153,5154,\n5155,5156,5157,5158,5159,5160,5161,5162,5163,5164,5165,5166,5167,5168,5169,\n5170,5171,5172,5173,5174,5175,5176,5177,5178,5179,5180,5181,5182,5183,5184,\n5185,5186,5187,5188,5189,5190,5191,5192,5193,5194,5195,5196,5197,5198,5199,\n5200,5201,5202,5203,5204,5205,5206,5207,5208,5209,5210,5211,5212,5213,5214,\n5215,5216,5217,5218,5219,5220,5221,5222,5223,5224,5225,5226,5227,5228,5229,\n5230,5231,5232,5233,5234,5235,5236,5237,5238,5239,5240,5241,5242,5243,5244,\n5245,5246,5247,5248,5249,5250,5251,5252,5253,5254,5255,5256,5257,5258,5259,\n5260,5261,5262,5263,5264,5265,5266,5267,5268,5269,5270,5271,5272,5273,5274,\n5275,5276,5277,5278,5279,5280,5281,5282,5283,5284,5285,5286,5287,5288,5289,\n5290,5291,5292,5293,5294,5295,5296,5297,5298,5299,5300,5301,5302,5303,5304,\n5305,5306,5307,5308,5309,5310,5311,5312,5313,5314,5315,5316,5317,5318,5319,\n5320,5321,5322,5323,5324,5325,5326,5327,5328,5329,5330,5331,5332,5333,5334,\n5335,5336,5337,5338,5339,5340,5341,5342,5343,5344,5345,5346,5347,5348,5349,\n5350,5351,5352,5353,5354,5355,5356,5357,5358,5359,5360,5361,5362,5363,5364,\n5365,5366,5367,5368,5369,5370,5371,5372,5373,5374,5375,5376,5377,5378,5379,\n5380,5381,5382,5383,5384,5385,5386,5387,5388,5389,5390,5391,5392,5393,5394,\n5395,5396,5397,5398,5399,5400,5401,5402,5403,5404,5405,5406,5407,5408,5409,\n5410,5411,5412,5413,5414,5415,5416,5417,5418,5419,5420,5421,5422,5423,5424,\n5425,5426,5427,5428,5429,5430,5431,5432,5433,5434,5435,5436,5437,5438,5439,\n5440,5441,5442,5443,5444,5445,5446,5447,5448,5449,5450,5451,5452,5453,5454,\n5455,5456,5457,5458,5459,5460,5461,5462,5463,5464,5465,5466,5467,5468,5469,\n5470,5471,5472,5473,5474,5475,5476,5477,5478,5479,5480,5481,5482,5483,5484,\n5485,5486,5487,5488,5489,5490,5491,5492,5493,5494,5495,5496,5497,5498,5499,\n5500,5501,5502,5503,5504,5505,5506,5507,5508,5509,5510,5511,5512,5513,5514,\n5515,5516,5517,5518,5519,5520,5521,5522,5523,5524,5525,5526,5527,5528,5529,\n5530,5531,5532,5533,5534,5535,5536,5537,5538,5539,5540,5541,5542,5543,5544,\n5545,5546,5547,5548,5549,5550,5551,5552,5553,5554,5555,5556,5557,5558,5559,\n5560,5561,5562,5563,5564,5565,5566,5567,5568,5569,5570,5571,5572,5573,5574,\n5575,5576,5577,5578,5579,5580,5581,5582,5583,5584,5585,5586,5587,5588,5589,\n5590,5591,5592,5593,5594,5595,5596,5597,5598,5599,5600,5601,5602,5603,5604,\n5605,5606,5607,5608,5609,5610,5611,5612,5613,5614,5615,5616,5617,5618,5619,\n5620,5621,5622,5623,5624,5625,5626,5627,5628,5629,5630,5631,5632,5633,5634,\n5635,5636,5637,5638,5639,5640,5641,5642,5643,5644,5645,5646,5647,5648,5649,\n5650,5651,5652,5653,5654,5655,5656,5657,5658,5659,5660,5661,5662,5663,5664,\n5665,5666,5667,5668,5669,5670,5671,5672,5673,5674,5675,5676,5677,5678,5679,\n5680,5681,5682,5683,5684,5685,5686,5687,5688,5689,5690,5691,5692,5693,5694,\n5695,5696,5697,5698,5699,5700,5701,5702,5703,5704,5705,5706,5707,5708,5709,\n5710,5711,5712,5713,5714,5715,5716,5717,5718,5719,5720,5721,5722,5723,5724,\n5725,5726,5727,5728,5729,5730,5731,5732,5733,5734,5735,5736,5737,5738,5739,\n5740,5741,5742,5743,5744,5745,5746,5747,5748,5749,5750,5751,5752,5753,5754,\n5755,5756,5757,5758,5759,5760,5761,5762,5763,5764,5765,5766,5767,5768,5769,\n5770,5771,5772,5773,5774,5775,5776,5777,5778,5779,5780,5781,5782,5783,5784,\n5785,5786,5787,5788,5789,5790,5791,5792,5793,5794,5795,5796,5797,5798,5799,\n5800,5801,5802,5803,5804,5805,5806,5807,5808,5809,5810,5811,5812,5813,5814,\n5815,5816,5817,5818,5819,5820,5821,5822,5823,5824,5825,5826,5827,5828,5829,\n5830,5831,5832,5833,5834,5835,5836,5837,5838,5839,5840,5841,5842,5843,5844,\n5845,5846,5847,5848,5849,5850,5851,5852,5853,5854,5855,5856,5857,5858,5859,\n5860,5861,5862,5863,5864,5865,5866,5867,5868,5869,5870,5871,5872,5873,5874,\n5875,5876,5877,5878,5879,5880,5881,5882,5883,5884,5885,5886,5887,5888,5889,\n5890,5891,5892,5893,5894,5895,5896,5897,5898,5899,5900,5901,5902,5903,5904,\n5905,5906,5907,5908,5909,5910,5911,5912,5913,5914,5915,5916,5917,5918,5919,\n5920,5921,5922,5923,5924,5925,5926,5927,5928,5929,5930,5931,5932,5933,5934,\n5935,5936,5937,5938,5939,5940,5941,5942,5943,5944,5945,5946,5947,5948,5949,\n5950,5951,5952,5953,5954,5955,5956,5957,5958,5959,5960,5961,5962,5963,5964,\n5965,5966,5967,5968,5969,5970,5971,5972,5973,5974,5975,5976,5977,5978,5979,\n5980,5981,5982,5983,5984,5985,5986,5987,5988,5989,5990,5991,5992,5993,5994,\n5995,5996,5997,5998,5999,6000,6001,6002,6003,6004,6005,6006,6007,6008,6009,\n6010,6011,6012,6013,6014,6015,6016,6017,6018,6019,6020,6021,6022,6023,6024,\n6025,6026,6027,6028,6029,6030,6031,6032,6033,6034,6035,6036,6037,6038,6039,\n6040,6041,6042,6043,6044,6045,6046,6047,6048,6049,6050,6051,6052,6053,6054,\n6055,6056,6057,6058,6059,6060,6061,6062,6063,6064,6065,6066,6067,6068,6069,\n6070,6071,6072,6073,6074,6075,6076,6077,6078,6079,6080,6081,6082,6083,6084,\n6085,6086,6087,6088,6089,6090,6091,6092,6093,6094,6095,6096,6097,6098,6099,\n6100,6101,6102,6103,6104,6105,6106,6107,6108,6109,6110,6111,6112,6113,6114,\n6115,6116,6117,6118,6119,6120,6121,6122,6123,6124,6125,6126,6127,6128,6129,\n6130,6131,6132,6133,6134,6135,6136,6137,6138,6139,6140,6141,6142,6143,6144,\n6145,6146,6147,6148,6149,6150,6151,6152,6153,6154,6155,6156,6157,6158,6159,\n6160,6161,6162,6163,6164,6165,6166,6167,6168,6169,6170,6171,6172,6173,6174,\n6175,6176,6177,6178,6179,6180,6181,6182,6183,6184,6185,6186,6187,6188,6189,\n6190,6191,6192,6193,6194,6195,6196,6197,6198,6199,6200,6201,6202,6203,6204,\n6205,6206,6207,6208,6209,6210,6211,6212,6213,6214,6215,6216,6217,6218,6219,\n6220,6221,6222,6223,6224,6225,6226,6227,6228,6229,6230,6231,6232,6233,6234,\n6235,6236,6237,6238,6239,6240,6241,6242,6243,6244,6245,6246,6247,6248,6249,\n6250,6251,6252,6253,6254,6255,6256,6257,6258,6259,6260,6261,6262,6263,6264,\n6265,6266,6267,6268,6269,6270,6271,6272,6273,6274,6275,6276,6277,6278,6279,\n6280,6281,6282,6283,6284,6285,6286,6287,6288,6289,6290,6291,6292,6293,6294,\n6295,6296,6297,6298,6299,6300,6301,6302,6303,6304,6305,6306,6307,6308,6309,\n6310,6311,6312,6313,6314,6315,6316,6317,6318,6319,6320,6321,6322,6323,6324,\n6325,6326,6327,6328,6329,6330,6331,6332,6333,6334,6335,6336,6337,6338,6339,\n6340,6341,6342,6343,6344,6345,6346,6347,6348,6349,6350,6351,6352,6353,6354,\n6355,6356,6357,6358,6359,6360,6361,6362,6363,6364,6365,6366,6367,6368,6369,\n6370,6371,6372,6373,6374,6375,6376,6377,6378,6379,6380,6381,6382,6383,6384,\n6385,6386,6387,6388,6389,6390,6391,6392,6393,6394,6395,6396,6397,6398,6399,\n6400,6401,6402,6403,6404,6405,6406,6407,6408,6409,6410,6411,6412,6413,6414,\n6415,6416,6417,6418,6419,6420,6421,6422,6423,6424,6425,6426,6427,6428,6429,\n6430,6431,6432,6433,6434,6435,6436,6437,6438,6439,6440,6441,6442,6443,6444,\n6445,6446,6447,6448,6449,6450,6451,6452,6453,6454,6455,6456,6457,6458,6459,\n6460,6461,6462,6463,6464,6465,6466,6467,6468,6469,6470,6471,6472,6473,6474,\n6475,6476,6477,6478,6479,6480,6481,6482,6483,6484,6485,6486,6487,6488,6489,\n6490,6491,6492,6493,6494,6495,6496,6497,6498,6499,6500,6501,6502,6503,6504,\n6505,6506,6507,6508,6509,6510,6511,6512,6513,6514,6515,6516,6517,6518,6519,\n6520,6521,6522,6523,6524,6525,6526,6527,6528,6529,6530,6531,6532,6533,6534,\n6535,6536,6537,6538,6539,6540,6541,6542,6543,6544,6545,6546,6547,6548,6549,\n6550,6551,6552,6553,6554,6555,6556,6557,6558,6559,6560,6561,6562,6563,6564,\n6565,6566,6567,6568,6569,6570,6571,6572,6573,6574,6575,6576,6577,6578,6579,\n6580,6581,6582,6583,6584,6585,6586,6587,6588,6589,6590,6591,6592,6593,6594,\n6595,6596,6597,6598,6599,6600,6601,6602,6603,6604,6605,6606,6607,6608,6609,\n6610,6611,6612,6613,6614,6615,6616,6617,6618,6619,6620,6621,6622,6623,6624,\n6625,6626,6627,6628,6629,6630,6631,6632,6633,6634,6635,6636,6637,6638,6639,\n6640,6641,6642,6643,6644,6645,6646,6647,6648,6649,6650,6651,6652,6653,6654,\n6655,6656,6657,6658,6659,6660,6661,6662,6663,6664,6665,6666,6667,6668,6669,\n6670,6671,6672,6673,6674,6675,6676,6677,6678,6679,6680,6681,6682,6683,6684,\n6685,6686,6687,6688,6689,6690,6691,6692,6693,6694,6695,6696,6697,6698,6699,\n6700,6701,6702,6703,6704,6705,6706,6707,6708,6709,6710,6711,6712,6713,6714,\n6715,6716,6717,6718,6719,6720,6721,6722,6723,6724,6725,6726,6727,6728,6729,\n6730,6731,6732,6733,6734,6735,6736,6737,6738,6739,6740,6741,6742,6743,6744,\n6745,6746,6747,6748,6749,6750,6751,6752,6753,6754,6755,6756,6757,6758,6759,\n6760,6761,6762,6763,6764,6765,6766,6767,6768,6769,6770,6771,6772,6773,6774,\n6775,6776,6777,6778,6779,6780,6781,6782,6783,6784,6785,6786,6787,6788,6789,\n6790,6791,6792,6793,6794,6795,6796,6797,6798,6799,6800,6801,6802,6803,6804,\n6805,6806,6807,6808,6809,6810,6811,6812,6813,6814,6815,6816,6817,6818,6819,\n6820,6821,6822,6823,6824,6825,6826,6827,6828,6829,6830,6831,6832,6833,6834,\n6835,6836,6837,6838,6839,6840,6841,6842,6843,6844,6845,6846,6847,6848,6849,\n6850,6851,6852,6853,6854,6855,6856,6857,6858,6859,6860,6861,6862,6863,6864,\n6865,6866,6867,6868,6869,6870,6871,6872,6873,6874,6875,6876,6877,6878,6879,\n6880,6881,6882,6883,6884,6885,6886,6887,6888,6889,6890,6891,6892,6893,6894,\n6895,6896,6897,6898,6899,6900,6901,6902,6903,6904,6905,6906,6907,6908,6909,\n6910,6911,6912,6913,6914,6915,6916,6917,6918,6919,6920,6921,6922,6923,6924,\n6925,6926,6927,6928,6929,6930,6931,6932,6933,6934,6935,6936,6937,6938,6939,\n6940,6941,6942,6943,6944,6945,6946,6947,6948,6949,6950,6951,6952,6953,6954,\n6955,6956,6957,6958,6959,6960,6961,6962,6963,6964,6965,6966,6967,6968,6969,\n6970,6971,6972,6973,6974,6975,6976,6977,6978,6979,6980,6981,6982,6983,6984,\n6985,6986,6987,6988,6989,6990,6991,6992,6993,6994,6995,6996,6997,6998,6999,\n7000,7001,7002,7003,7004,7005,7006,7007,7008,7009,7010,7011,7012,7013,7014,\n7015,7016,7017,7018,7019,7020,7021,7022,7023,7024,7025,7026,7027,7028,7029,\n7030,7031,7032,7033,7034,7035,7036,7037,7038,7039,7040,7041,7042,7043,7044,\n7045,7046,7047,7048,7049,7050,7051,7052,7053,7054,7055,7056,7057,7058,7059,\n7060,7061,7062,7063,7064,7065,7066,7067,7068,7069,7070,7071,7072,7073,7074,\n7075,7076,7077,7078,7079,7080,7081,7082,7083,7084,7085,7086,7087,7088,7089,\n7090,7091,7092,7093,7094,7095,7096,7097,7098,7099,7100,7101,7102,7103,7104,\n7105,7106,7107,7108,7109,7110,7111,7112,7113,7114,7115,7116,7117,7118,7119,\n7120,7121,7122,7123,7124,7125,7126,7127,7128,7129,7130,7131,7132,7133,7134,\n7135,7136,7137,7138,7139,7140,7141,7142,7143,7144,7145,7146,7147,7148,7149,\n7150,7151,7152,7153,7154,7155,7156,7157,7158,7159,7160,7161,7162,7163,7164,\n7165,7166,7167,7168,7169,7170,7171,7172,7173,7174,7175,7176,7177,7178,7179,\n7180,7181,7182,7183,7184,7185,7186,7187,7188,7189,7190,7191,7192,7193,7194,\n7195,7196,7197,7198,7199,7200,7201,7202,7203,7204,7205,7206,7207,7208,7209,\n7210,7211,7212,7213,7214,7215,7216,7217,7218,7219,7220,7221,7222,7223,7224,\n7225,7226,7227,7228,7229,7230,7231,7232,7233,7234,7235,7236,7237,7238,7239,\n7240,7241,7242,7243,7244,7245,7246,7247,7248,7249,7250,7251,7252,7253,7254,\n7255,7256,7257,7258,7259,7260,7261,7262,7263,7264,7265,7266,7267,7268,7269,\n7270,7271,7272,7273,7274,7275,7276,7277,7278,7279,7280,7281,7282,7283,7284,\n7285,7286,7287,7288,7289,7290,7291,7292,7293,7294,7295,1042,1044,1054,1057,\n1058,1058,1066,1122,42570L,7305,7306,7307,7308,7309,7310,7311,7312,7313,\n7314,7315,7316,7317,7318,7319,7320,7321,7322,7323,7324,7325,7326,7327,7328,\n7329,7330,7331,7332,7333,7334,7335,7336,7337,7338,7339,7340,7341,7342,7343,\n7344,7345,7346,7347,7348,7349,7350,7351,7352,7353,7354,7355,7356,7357,7358,\n7359,7360,7361,7362,7363,7364,7365,7366,7367,7368,7369,7370,7371,7372,7373,\n7374,7375,7376,7377,7378,7379,7380,7381,7382,7383,7384,7385,7386,7387,7388,\n7389,7390,7391,7392,7393,7394,7395,7396,7397,7398,7399,7400,7401,7402,7403,\n7404,7405,7406,7407,7408,7409,7410,7411,7412,7413,7414,7415,7416,7417,7418,\n7419,7420,7421,7422,7423,7424,7425,7426,7427,7428,7429,7430,7431,7432,7433,\n7434,7435,7436,7437,7438,7439,7440,7441,7442,7443,7444,7445,7446,7447,7448,\n7449,7450,7451,7452,7453,7454,7455,7456,7457,7458,7459,7460,7461,7462,7463,\n7464,7465,7466,7467,7468,7469,7470,7471,7472,7473,7474,7475,7476,7477,7478,\n7479,7480,7481,7482,7483,7484,7485,7486,7487,7488,7489,7490,7491,7492,7493,\n7494,7495,7496,7497,7498,7499,7500,7501,7502,7503,7504,7505,7506,7507,7508,\n7509,7510,7511,7512,7513,7514,7515,7516,7517,7518,7519,7520,7521,7522,7523,\n7524,7525,7526,7527,7528,7529,7530,7531,7532,7533,7534,7535,7536,7537,7538,\n7539,7540,7541,7542,7543,7544,42877L,7546,7547,7548,11363,7550,7551,7552,\n7553,7554,7555,7556,7557,7558,7559,7560,7561,7562,7563,7564,7565,7566,7567,\n7568,7569,7570,7571,7572,7573,7574,7575,7576,7577,7578,7579,7580,7581,7582,\n7583,7584,7585,7586,7587,7588,7589,7590,7591,7592,7593,7594,7595,7596,7597,\n7598,7599,7600,7601,7602,7603,7604,7605,7606,7607,7608,7609,7610,7611,7612,\n7613,7614,7615,7616,7617,7618,7619,7620,7621,7622,7623,7624,7625,7626,7627,\n7628,7629,7630,7631,7632,7633,7634,7635,7636,7637,7638,7639,7640,7641,7642,\n7643,7644,7645,7646,7647,7648,7649,7650,7651,7652,7653,7654,7655,7656,7657,\n7658,7659,7660,7661,7662,7663,7664,7665,7666,7667,7668,7669,7670,7671,7672,\n7673,7674,7675,7676,7677,7678,7679,7680,7680,7682,7682,7684,7684,7686,7686,\n7688,7688,7690,7690,7692,7692,7694,7694,7696,7696,7698,7698,7700,7700,7702,\n7702,7704,7704,7706,7706,7708,7708,7710,7710,7712,7712,7714,7714,7716,7716,\n7718,7718,7720,7720,7722,7722,7724,7724,7726,7726,7728,7728,7730,7730,7732,\n7732,7734,7734,7736,7736,7738,7738,7740,7740,7742,7742,7744,7744,7746,7746,\n7748,7748,7750,7750,7752,7752,7754,7754,7756,7756,7758,7758,7760,7760,7762,\n7762,7764,7764,7766,7766,7768,7768,7770,7770,7772,7772,7774,7774,7776,7776,\n7778,7778,7780,7780,7782,7782,7784,7784,7786,7786,7788,7788,7790,7790,7792,\n7792,7794,7794,7796,7796,7798,7798,7800,7800,7802,7802,7804,7804,7806,7806,\n7808,7808,7810,7810,7812,7812,7814,7814,7816,7816,7818,7818,7820,7820,7822,\n7822,7824,7824,7826,7826,7828,7828,7830,7831,7832,7833,7834,7776,7836,7837,\n7838,7839,7840,7840,7842,7842,7844,7844,7846,7846,7848,7848,7850,7850,7852,\n7852,7854,7854,7856,7856,7858,7858,7860,7860,7862,7862,7864,7864,7866,7866,\n7868,7868,7870,7870,7872,7872,7874,7874,7876,7876,7878,7878,7880,7880,7882,\n7882,7884,7884,7886,7886,7888,7888,7890,7890,7892,7892,7894,7894,7896,7896,\n7898,7898,7900,7900,7902,7902,7904,7904,7906,7906,7908,7908,7910,7910,7912,\n7912,7914,7914,7916,7916,7918,7918,7920,7920,7922,7922,7924,7924,7926,7926,\n7928,7928,7930,7930,7932,7932,7934,7934,7944,7945,7946,7947,7948,7949,7950,\n7951,7944,7945,7946,7947,7948,7949,7950,7951,7960,7961,7962,7963,7964,7965,\n7958,7959,7960,7961,7962,7963,7964,7965,7966,7967,7976,7977,7978,7979,7980,\n7981,7982,7983,7976,7977,7978,7979,7980,7981,7982,7983,7992,7993,7994,7995,\n7996,7997,7998,7999,7992,7993,7994,7995,7996,7997,7998,7999,8008,8009,8010,\n8011,8012,8013,8006,8007,8008,8009,8010,8011,8012,8013,8014,8015,8016,8025,\n8018,8027,8020,8029,8022,8031,8024,8025,8026,8027,8028,8029,8030,8031,8040,\n8041,8042,8043,8044,8045,8046,8047,8040,8041,8042,8043,8044,8045,8046,8047,\n8122,8123,8136,8137,8138,8139,8154,8155,8184,8185,8170,8171,8186,8187,8062,\n8063,8064,8065,8066,8067,8068,8069,8070,8071,8072,8073,8074,8075,8076,8077,\n8078,8079,8080,8081,8082,8083,8084,8085,8086,8087,8088,8089,8090,8091,8092,\n8093,8094,8095,8096,8097,8098,8099,8100,8101,8102,8103,8104,8105,8106,8107,\n8108,8109,8110,8111,8120,8121,8114,8115,8116,8117,8118,8119,8120,8121,8122,\n8123,8124,8125,921,8127,8128,8129,8130,8131,8132,8133,8134,8135,8136,8137,\n8138,8139,8140,8141,8142,8143,8152,8153,8146,8147,8148,8149,8150,8151,8152,\n8153,8154,8155,8156,8157,8158,8159,8168,8169,8162,8163,8164,8172,8166,8167,\n8168,8169,8170,8171,8172,8173,8174,8175,8176,8177,8178,8179,8180,8181,8182,\n8183,8184,8185,8186,8187,8188,8189,8190,8191,8192,8193,8194,8195,8196,8197,\n8198,8199,8200,8201,8202,8203,8204,8205,8206,8207,8208,8209,8210,8211,8212,\n8213,8214,8215,8216,8217,8218,8219,8220,8221,8222,8223,8224,8225,8226,8227,\n8228,8229,8230,8231,8232,8233,8234,8235,8236,8237,8238,8239,8240,8241,8242,\n8243,8244,8245,8246,8247,8248,8249,8250,8251,8252,8253,8254,8255,8256,8257,\n8258,8259,8260,8261,8262,8263,8264,8265,8266,8267,8268,8269,8270,8271,8272,\n8273,8274,8275,8276,8277,8278,8279,8280,8281,8282,8283,8284,8285,8286,8287,\n8288,8289,8290,8291,8292,8293,8294,8295,8296,8297,8298,8299,8300,8301,8302,\n8303,8304,8305,8306,8307,8308,8309,8310,8311,8312,8313,8314,8315,8316,8317,\n8318,8319,8320,8321,8322,8323,8324,8325,8326,8327,8328,8329,8330,8331,8332,\n8333,8334,8335,8336,8337,8338,8339,8340,8341,8342,8343,8344,8345,8346,8347,\n8348,8349,8350,8351,8352,8353,8354,8355,8356,8357,8358,8359,8360,8361,8362,\n8363,8364,8365,8366,8367,8368,8369,8370,8371,8372,8373,8374,8375,8376,8377,\n8378,8379,8380,8381,8382,8383,8384,8385,8386,8387,8388,8389,8390,8391,8392,\n8393,8394,8395,8396,8397,8398,8399,8400,8401,8402,8403,8404,8405,8406,8407,\n8408,8409,8410,8411,8412,8413,8414,8415,8416,8417,8418,8419,8420,8421,8422,\n8423,8424,8425,8426,8427,8428,8429,8430,8431,8432,8433,8434,8435,8436,8437,\n8438,8439,8440,8441,8442,8443,8444,8445,8446,8447,8448,8449,8450,8451,8452,\n8453,8454,8455,8456,8457,8458,8459,8460,8461,8462,8463,8464,8465,8466,8467,\n8468,8469,8470,8471,8472,8473,8474,8475,8476,8477,8478,8479,8480,8481,8482,\n8483,8484,8485,8486,8487,8488,8489,8490,8491,8492,8493,8494,8495,8496,8497,\n8498,8499,8500,8501,8502,8503,8504,8505,8506,8507,8508,8509,8510,8511,8512,\n8513,8514,8515,8516,8517,8518,8519,8520,8521,8522,8523,8524,8525,8498,8527,\n8528,8529,8530,8531,8532,8533,8534,8535,8536,8537,8538,8539,8540,8541,8542,\n8543,8544,8545,8546,8547,8548,8549,8550,8551,8552,8553,8554,8555,8556,8557,\n8558,8559,8544,8545,8546,8547,8548,8549,8550,8551,8552,8553,8554,8555,8556,\n8557,8558,8559,8576,8577,8578,8579,8579,8581,8582,8583,8584,8585,8586,8587,\n8588,8589,8590,8591,8592,8593,8594,8595,8596,8597,8598,8599,8600,8601,8602,\n8603,8604,8605,8606,8607,8608,8609,8610,8611,8612,8613,8614,8615,8616,8617,\n8618,8619,8620,8621,8622,8623,8624,8625,8626,8627,8628,8629,8630,8631,8632,\n8633,8634,8635,8636,8637,8638,8639,8640,8641,8642,8643,8644,8645,8646,8647,\n8648,8649,8650,8651,8652,8653,8654,8655,8656,8657,8658,8659,8660,8661,8662,\n8663,8664,8665,8666,8667,8668,8669,8670,8671,8672,8673,8674,8675,8676,8677,\n8678,8679,8680,8681,8682,8683,8684,8685,8686,8687,8688,8689,8690,8691,8692,\n8693,8694,8695,8696,8697,8698,8699,8700,8701,8702,8703,8704,8705,8706,8707,\n8708,8709,8710,8711,8712,8713,8714,8715,8716,8717,8718,8719,8720,8721,8722,\n8723,8724,8725,8726,8727,8728,8729,8730,8731,8732,8733,8734,8735,8736,8737,\n8738,8739,8740,8741,8742,8743,8744,8745,8746,8747,8748,8749,8750,8751,8752,\n8753,8754,8755,8756,8757,8758,8759,8760,8761,8762,8763,8764,8765,8766,8767,\n8768,8769,8770,8771,8772,8773,8774,8775,8776,8777,8778,8779,8780,8781,8782,\n8783,8784,8785,8786,8787,8788,8789,8790,8791,8792,8793,8794,8795,8796,8797,\n8798,8799,8800,8801,8802,8803,8804,8805,8806,8807,8808,8809,8810,8811,8812,\n8813,8814,8815,8816,8817,8818,8819,8820,8821,8822,8823,8824,8825,8826,8827,\n8828,8829,8830,8831,8832,8833,8834,8835,8836,8837,8838,8839,8840,8841,8842,\n8843,8844,8845,8846,8847,8848,8849,8850,8851,8852,8853,8854,8855,8856,8857,\n8858,8859,8860,8861,8862,8863,8864,8865,8866,8867,8868,8869,8870,8871,8872,\n8873,8874,8875,8876,8877,8878,8879,8880,8881,8882,8883,8884,8885,8886,8887,\n8888,8889,8890,8891,8892,8893,8894,8895,8896,8897,8898,8899,8900,8901,8902,\n8903,8904,8905,8906,8907,8908,8909,8910,8911,8912,8913,8914,8915,8916,8917,\n8918,8919,8920,8921,8922,8923,8924,8925,8926,8927,8928,8929,8930,8931,8932,\n8933,8934,8935,8936,8937,8938,8939,8940,8941,8942,8943,8944,8945,8946,8947,\n8948,8949,8950,8951,8952,8953,8954,8955,8956,8957,8958,8959,8960,8961,8962,\n8963,8964,8965,8966,8967,8968,8969,8970,8971,8972,8973,8974,8975,8976,8977,\n8978,8979,8980,8981,8982,8983,8984,8985,8986,8987,8988,8989,8990,8991,8992,\n8993,8994,8995,8996,8997,8998,8999,9000,9001,9002,9003,9004,9005,9006,9007,\n9008,9009,9010,9011,9012,9013,9014,9015,9016,9017,9018,9019,9020,9021,9022,\n9023,9024,9025,9026,9027,9028,9029,9030,9031,9032,9033,9034,9035,9036,9037,\n9038,9039,9040,9041,9042,9043,9044,9045,9046,9047,9048,9049,9050,9051,9052,\n9053,9054,9055,9056,9057,9058,9059,9060,9061,9062,9063,9064,9065,9066,9067,\n9068,9069,9070,9071,9072,9073,9074,9075,9076,9077,9078,9079,9080,9081,9082,\n9083,9084,9085,9086,9087,9088,9089,9090,9091,9092,9093,9094,9095,9096,9097,\n9098,9099,9100,9101,9102,9103,9104,9105,9106,9107,9108,9109,9110,9111,9112,\n9113,9114,9115,9116,9117,9118,9119,9120,9121,9122,9123,9124,9125,9126,9127,\n9128,9129,9130,9131,9132,9133,9134,9135,9136,9137,9138,9139,9140,9141,9142,\n9143,9144,9145,9146,9147,9148,9149,9150,9151,9152,9153,9154,9155,9156,9157,\n9158,9159,9160,9161,9162,9163,9164,9165,9166,9167,9168,9169,9170,9171,9172,\n9173,9174,9175,9176,9177,9178,9179,9180,9181,9182,9183,9184,9185,9186,9187,\n9188,9189,9190,9191,9192,9193,9194,9195,9196,9197,9198,9199,9200,9201,9202,\n9203,9204,9205,9206,9207,9208,9209,9210,9211,9212,9213,9214,9215,9216,9217,\n9218,9219,9220,9221,9222,9223,9224,9225,9226,9227,9228,9229,9230,9231,9232,\n9233,9234,9235,9236,9237,9238,9239,9240,9241,9242,9243,9244,9245,9246,9247,\n9248,9249,9250,9251,9252,9253,9254,9255,9256,9257,9258,9259,9260,9261,9262,\n9263,9264,9265,9266,9267,9268,9269,9270,9271,9272,9273,9274,9275,9276,9277,\n9278,9279,9280,9281,9282,9283,9284,9285,9286,9287,9288,9289,9290,9291,9292,\n9293,9294,9295,9296,9297,9298,9299,9300,9301,9302,9303,9304,9305,9306,9307,\n9308,9309,9310,9311,9312,9313,9314,9315,9316,9317,9318,9319,9320,9321,9322,\n9323,9324,9325,9326,9327,9328,9329,9330,9331,9332,9333,9334,9335,9336,9337,\n9338,9339,9340,9341,9342,9343,9344,9345,9346,9347,9348,9349,9350,9351,9352,\n9353,9354,9355,9356,9357,9358,9359,9360,9361,9362,9363,9364,9365,9366,9367,\n9368,9369,9370,9371,9372,9373,9374,9375,9376,9377,9378,9379,9380,9381,9382,\n9383,9384,9385,9386,9387,9388,9389,9390,9391,9392,9393,9394,9395,9396,9397,\n9398,9399,9400,9401,9402,9403,9404,9405,9406,9407,9408,9409,9410,9411,9412,\n9413,9414,9415,9416,9417,9418,9419,9420,9421,9422,9423,9398,9399,9400,9401,\n9402,9403,9404,9405,9406,9407,9408,9409,9410,9411,9412,9413,9414,9415,9416,\n9417,9418,9419,9420,9421,9422,9423,9450,9451,9452,9453,9454,9455,9456,9457,\n9458,9459,9460,9461,9462,9463,9464,9465,9466,9467,9468,9469,9470,9471,9472,\n9473,9474,9475,9476,9477,9478,9479,9480,9481,9482,9483,9484,9485,9486,9487,\n9488,9489,9490,9491,9492,9493,9494,9495,9496,9497,9498,9499,9500,9501,9502,\n9503,9504,9505,9506,9507,9508,9509,9510,9511,9512,9513,9514,9515,9516,9517,\n9518,9519,9520,9521,9522,9523,9524,9525,9526,9527,9528,9529,9530,9531,9532,\n9533,9534,9535,9536,9537,9538,9539,9540,9541,9542,9543,9544,9545,9546,9547,\n9548,9549,9550,9551,9552,9553,9554,9555,9556,9557,9558,9559,9560,9561,9562,\n9563,9564,9565,9566,9567,9568,9569,9570,9571,9572,9573,9574,9575,9576,9577,\n9578,9579,9580,9581,9582,9583,9584,9585,9586,9587,9588,9589,9590,9591,9592,\n9593,9594,9595,9596,9597,9598,9599,9600,9601,9602,9603,9604,9605,9606,9607,\n9608,9609,9610,9611,9612,9613,9614,9615,9616,9617,9618,9619,9620,9621,9622,\n9623,9624,9625,9626,9627,9628,9629,9630,9631,9632,9633,9634,9635,9636,9637,\n9638,9639,9640,9641,9642,9643,9644,9645,9646,9647,9648,9649,9650,9651,9652,\n9653,9654,9655,9656,9657,9658,9659,9660,9661,9662,9663,9664,9665,9666,9667,\n9668,9669,9670,9671,9672,9673,9674,9675,9676,9677,9678,9679,9680,9681,9682,\n9683,9684,9685,9686,9687,9688,9689,9690,9691,9692,9693,9694,9695,9696,9697,\n9698,9699,9700,9701,9702,9703,9704,9705,9706,9707,9708,9709,9710,9711,9712,\n9713,9714,9715,9716,9717,9718,9719,9720,9721,9722,9723,9724,9725,9726,9727,\n9728,9729,9730,9731,9732,9733,9734,9735,9736,9737,9738,9739,9740,9741,9742,\n9743,9744,9745,9746,9747,9748,9749,9750,9751,9752,9753,9754,9755,9756,9757,\n9758,9759,9760,9761,9762,9763,9764,9765,9766,9767,9768,9769,9770,9771,9772,\n9773,9774,9775,9776,9777,9778,9779,9780,9781,9782,9783,9784,9785,9786,9787,\n9788,9789,9790,9791,9792,9793,9794,9795,9796,9797,9798,9799,9800,9801,9802,\n9803,9804,9805,9806,9807,9808,9809,9810,9811,9812,9813,9814,9815,9816,9817,\n9818,9819,9820,9821,9822,9823,9824,9825,9826,9827,9828,9829,9830,9831,9832,\n9833,9834,9835,9836,9837,9838,9839,9840,9841,9842,9843,9844,9845,9846,9847,\n9848,9849,9850,9851,9852,9853,9854,9855,9856,9857,9858,9859,9860,9861,9862,\n9863,9864,9865,9866,9867,9868,9869,9870,9871,9872,9873,9874,9875,9876,9877,\n9878,9879,9880,9881,9882,9883,9884,9885,9886,9887,9888,9889,9890,9891,9892,\n9893,9894,9895,9896,9897,9898,9899,9900,9901,9902,9903,9904,9905,9906,9907,\n9908,9909,9910,9911,9912,9913,9914,9915,9916,9917,9918,9919,9920,9921,9922,\n9923,9924,9925,9926,9927,9928,9929,9930,9931,9932,9933,9934,9935,9936,9937,\n9938,9939,9940,9941,9942,9943,9944,9945,9946,9947,9948,9949,9950,9951,9952,\n9953,9954,9955,9956,9957,9958,9959,9960,9961,9962,9963,9964,9965,9966,9967,\n9968,9969,9970,9971,9972,9973,9974,9975,9976,9977,9978,9979,9980,9981,9982,\n9983,9984,9985,9986,9987,9988,9989,9990,9991,9992,9993,9994,9995,9996,9997,\n9998,9999,10000,10001,10002,10003,10004,10005,10006,10007,10008,10009,\n10010,10011,10012,10013,10014,10015,10016,10017,10018,10019,10020,10021,\n10022,10023,10024,10025,10026,10027,10028,10029,10030,10031,10032,10033,\n10034,10035,10036,10037,10038,10039,10040,10041,10042,10043,10044,10045,\n10046,10047,10048,10049,10050,10051,10052,10053,10054,10055,10056,10057,\n10058,10059,10060,10061,10062,10063,10064,10065,10066,10067,10068,10069,\n10070,10071,10072,10073,10074,10075,10076,10077,10078,10079,10080,10081,\n10082,10083,10084,10085,10086,10087,10088,10089,10090,10091,10092,10093,\n10094,10095,10096,10097,10098,10099,10100,10101,10102,10103,10104,10105,\n10106,10107,10108,10109,10110,10111,10112,10113,10114,10115,10116,10117,\n10118,10119,10120,10121,10122,10123,10124,10125,10126,10127,10128,10129,\n10130,10131,10132,10133,10134,10135,10136,10137,10138,10139,10140,10141,\n10142,10143,10144,10145,10146,10147,10148,10149,10150,10151,10152,10153,\n10154,10155,10156,10157,10158,10159,10160,10161,10162,10163,10164,10165,\n10166,10167,10168,10169,10170,10171,10172,10173,10174,10175,10176,10177,\n10178,10179,10180,10181,10182,10183,10184,10185,10186,10187,10188,10189,\n10190,10191,10192,10193,10194,10195,10196,10197,10198,10199,10200,10201,\n10202,10203,10204,10205,10206,10207,10208,10209,10210,10211,10212,10213,\n10214,10215,10216,10217,10218,10219,10220,10221,10222,10223,10224,10225,\n10226,10227,10228,10229,10230,10231,10232,10233,10234,10235,10236,10237,\n10238,10239,10240,10241,10242,10243,10244,10245,10246,10247,10248,10249,\n10250,10251,10252,10253,10254,10255,10256,10257,10258,10259,10260,10261,\n10262,10263,10264,10265,10266,10267,10268,10269,10270,10271,10272,10273,\n10274,10275,10276,10277,10278,10279,10280,10281,10282,10283,10284,10285,\n10286,10287,10288,10289,10290,10291,10292,10293,10294,10295,10296,10297,\n10298,10299,10300,10301,10302,10303,10304,10305,10306,10307,10308,10309,\n10310,10311,10312,10313,10314,10315,10316,10317,10318,10319,10320,10321,\n10322,10323,10324,10325,10326,10327,10328,10329,10330,10331,10332,10333,\n10334,10335,10336,10337,10338,10339,10340,10341,10342,10343,10344,10345,\n10346,10347,10348,10349,10350,10351,10352,10353,10354,10355,10356,10357,\n10358,10359,10360,10361,10362,10363,10364,10365,10366,10367,10368,10369,\n10370,10371,10372,10373,10374,10375,10376,10377,10378,10379,10380,10381,\n10382,10383,10384,10385,10386,10387,10388,10389,10390,10391,10392,10393,\n10394,10395,10396,10397,10398,10399,10400,10401,10402,10403,10404,10405,\n10406,10407,10408,10409,10410,10411,10412,10413,10414,10415,10416,10417,\n10418,10419,10420,10421,10422,10423,10424,10425,10426,10427,10428,10429,\n10430,10431,10432,10433,10434,10435,10436,10437,10438,10439,10440,10441,\n10442,10443,10444,10445,10446,10447,10448,10449,10450,10451,10452,10453,\n10454,10455,10456,10457,10458,10459,10460,10461,10462,10463,10464,10465,\n10466,10467,10468,10469,10470,10471,10472,10473,10474,10475,10476,10477,\n10478,10479,10480,10481,10482,10483,10484,10485,10486,10487,10488,10489,\n10490,10491,10492,10493,10494,10495,10496,10497,10498,10499,10500,10501,\n10502,10503,10504,10505,10506,10507,10508,10509,10510,10511,10512,10513,\n10514,10515,10516,10517,10518,10519,10520,10521,10522,10523,10524,10525,\n10526,10527,10528,10529,10530,10531,10532,10533,10534,10535,10536,10537,\n10538,10539,10540,10541,10542,10543,10544,10545,10546,10547,10548,10549,\n10550,10551,10552,10553,10554,10555,10556,10557,10558,10559,10560,10561,\n10562,10563,10564,10565,10566,10567,10568,10569,10570,10571,10572,10573,\n10574,10575,10576,10577,10578,10579,10580,10581,10582,10583,10584,10585,\n10586,10587,10588,10589,10590,10591,10592,10593,10594,10595,10596,10597,\n10598,10599,10600,10601,10602,10603,10604,10605,10606,10607,10608,10609,\n10610,10611,10612,10613,10614,10615,10616,10617,10618,10619,10620,10621,\n10622,10623,10624,10625,10626,10627,10628,10629,10630,10631,10632,10633,\n10634,10635,10636,10637,10638,10639,10640,10641,10642,10643,10644,10645,\n10646,10647,10648,10649,10650,10651,10652,10653,10654,10655,10656,10657,\n10658,10659,10660,10661,10662,10663,10664,10665,10666,10667,10668,10669,\n10670,10671,10672,10673,10674,10675,10676,10677,10678,10679,10680,10681,\n10682,10683,10684,10685,10686,10687,10688,10689,10690,10691,10692,10693,\n10694,10695,10696,10697,10698,10699,10700,10701,10702,10703,10704,10705,\n10706,10707,10708,10709,10710,10711,10712,10713,10714,10715,10716,10717,\n10718,10719,10720,10721,10722,10723,10724,10725,10726,10727,10728,10729,\n10730,10731,10732,10733,10734,10735,10736,10737,10738,10739,10740,10741,\n10742,10743,10744,10745,10746,10747,10748,10749,10750,10751,10752,10753,\n10754,10755,10756,10757,10758,10759,10760,10761,10762,10763,10764,10765,\n10766,10767,10768,10769,10770,10771,10772,10773,10774,10775,10776,10777,\n10778,10779,10780,10781,10782,10783,10784,10785,10786,10787,10788,10789,\n10790,10791,10792,10793,10794,10795,10796,10797,10798,10799,10800,10801,\n10802,10803,10804,10805,10806,10807,10808,10809,10810,10811,10812,10813,\n10814,10815,10816,10817,10818,10819,10820,10821,10822,10823,10824,10825,\n10826,10827,10828,10829,10830,10831,10832,10833,10834,10835,10836,10837,\n10838,10839,10840,10841,10842,10843,10844,10845,10846,10847,10848,10849,\n10850,10851,10852,10853,10854,10855,10856,10857,10858,10859,10860,10861,\n10862,10863,10864,10865,10866,10867,10868,10869,10870,10871,10872,10873,\n10874,10875,10876,10877,10878,10879,10880,10881,10882,10883,10884,10885,\n10886,10887,10888,10889,10890,10891,10892,10893,10894,10895,10896,10897,\n10898,10899,10900,10901,10902,10903,10904,10905,10906,10907,10908,10909,\n10910,10911,10912,10913,10914,10915,10916,10917,10918,10919,10920,10921,\n10922,10923,10924,10925,10926,10927,10928,10929,10930,10931,10932,10933,\n10934,10935,10936,10937,10938,10939,10940,10941,10942,10943,10944,10945,\n10946,10947,10948,10949,10950,10951,10952,10953,10954,10955,10956,10957,\n10958,10959,10960,10961,10962,10963,10964,10965,10966,10967,10968,10969,\n10970,10971,10972,10973,10974,10975,10976,10977,10978,10979,10980,10981,\n10982,10983,10984,10985,10986,10987,10988,10989,10990,10991,10992,10993,\n10994,10995,10996,10997,10998,10999,11000,11001,11002,11003,11004,11005,\n11006,11007,11008,11009,11010,11011,11012,11013,11014,11015,11016,11017,\n11018,11019,11020,11021,11022,11023,11024,11025,11026,11027,11028,11029,\n11030,11031,11032,11033,11034,11035,11036,11037,11038,11039,11040,11041,\n11042,11043,11044,11045,11046,11047,11048,11049,11050,11051,11052,11053,\n11054,11055,11056,11057,11058,11059,11060,11061,11062,11063,11064,11065,\n11066,11067,11068,11069,11070,11071,11072,11073,11074,11075,11076,11077,\n11078,11079,11080,11081,11082,11083,11084,11085,11086,11087,11088,11089,\n11090,11091,11092,11093,11094,11095,11096,11097,11098,11099,11100,11101,\n11102,11103,11104,11105,11106,11107,11108,11109,11110,11111,11112,11113,\n11114,11115,11116,11117,11118,11119,11120,11121,11122,11123,11124,11125,\n11126,11127,11128,11129,11130,11131,11132,11133,11134,11135,11136,11137,\n11138,11139,11140,11141,11142,11143,11144,11145,11146,11147,11148,11149,\n11150,11151,11152,11153,11154,11155,11156,11157,11158,11159,11160,11161,\n11162,11163,11164,11165,11166,11167,11168,11169,11170,11171,11172,11173,\n11174,11175,11176,11177,11178,11179,11180,11181,11182,11183,11184,11185,\n11186,11187,11188,11189,11190,11191,11192,11193,11194,11195,11196,11197,\n11198,11199,11200,11201,11202,11203,11204,11205,11206,11207,11208,11209,\n11210,11211,11212,11213,11214,11215,11216,11217,11218,11219,11220,11221,\n11222,11223,11224,11225,11226,11227,11228,11229,11230,11231,11232,11233,\n11234,11235,11236,11237,11238,11239,11240,11241,11242,11243,11244,11245,\n11246,11247,11248,11249,11250,11251,11252,11253,11254,11255,11256,11257,\n11258,11259,11260,11261,11262,11263,11264,11265,11266,11267,11268,11269,\n11270,11271,11272,11273,11274,11275,11276,11277,11278,11279,11280,11281,\n11282,11283,11284,11285,11286,11287,11288,11289,11290,11291,11292,11293,\n11294,11295,11296,11297,11298,11299,11300,11301,11302,11303,11304,11305,\n11306,11307,11308,11309,11310,11311,11264,11265,11266,11267,11268,11269,\n11270,11271,11272,11273,11274,11275,11276,11277,11278,11279,11280,11281,\n11282,11283,11284,11285,11286,11287,11288,11289,11290,11291,11292,11293,\n11294,11295,11296,11297,11298,11299,11300,11301,11302,11303,11304,11305,\n11306,11307,11308,11309,11310,11359,11360,11360,11362,11363,11364,570,574,\n11367,11367,11369,11369,11371,11371,11373,11374,11375,11376,11377,11378,\n11378,11380,11381,11381,11383,11384,11385,11386,11387,11388,11389,11390,\n11391,11392,11392,11394,11394,11396,11396,11398,11398,11400,11400,11402,\n11402,11404,11404,11406,11406,11408,11408,11410,11410,11412,11412,11414,\n11414,11416,11416,11418,11418,11420,11420,11422,11422,11424,11424,11426,\n11426,11428,11428,11430,11430,11432,11432,11434,11434,11436,11436,11438,\n11438,11440,11440,11442,11442,11444,11444,11446,11446,11448,11448,11450,\n11450,11452,11452,11454,11454,11456,11456,11458,11458,11460,11460,11462,\n11462,11464,11464,11466,11466,11468,11468,11470,11470,11472,11472,11474,\n11474,11476,11476,11478,11478,11480,11480,11482,11482,11484,11484,11486,\n11486,11488,11488,11490,11490,11492,11493,11494,11495,11496,11497,11498,\n11499,11499,11501,11501,11503,11504,11505,11506,11506,11508,11509,11510,\n11511,11512,11513,11514,11515,11516,11517,11518,11519,4256,4257,4258,4259,\n4260,4261,4262,4263,4264,4265,4266,4267,4268,4269,4270,4271,4272,4273,4274,\n4275,4276,4277,4278,4279,4280,4281,4282,4283,4284,4285,4286,4287,4288,4289,\n4290,4291,4292,4293,11558,4295,11560,11561,11562,11563,11564,4301,11566,\n11567,11568,11569,11570,11571,11572,11573,11574,11575,11576,11577,11578,\n11579,11580,11581,11582,11583,11584,11585,11586,11587,11588,11589,11590,\n11591,11592,11593,11594,11595,11596,11597,11598,11599,11600,11601,11602,\n11603,11604,11605,11606,11607,11608,11609,11610,11611,11612,11613,11614,\n11615,11616,11617,11618,11619,11620,11621,11622,11623,11624,11625,11626,\n11627,11628,11629,11630,11631,11632,11633,11634,11635,11636,11637,11638,\n11639,11640,11641,11642,11643,11644,11645,11646,11647,11648,11649,11650,\n11651,11652,11653,11654,11655,11656,11657,11658,11659,11660,11661,11662,\n11663,11664,11665,11666,11667,11668,11669,11670,11671,11672,11673,11674,\n11675,11676,11677,11678,11679,11680,11681,11682,11683,11684,11685,11686,\n11687,11688,11689,11690,11691,11692,11693,11694,11695,11696,11697,11698,\n11699,11700,11701,11702,11703,11704,11705,11706,11707,11708,11709,11710,\n11711,11712,11713,11714,11715,11716,11717,11718,11719,11720,11721,11722,\n11723,11724,11725,11726,11727,11728,11729,11730,11731,11732,11733,11734,\n11735,11736,11737,11738,11739,11740,11741,11742,11743,11744,11745,11746,\n11747,11748,11749,11750,11751,11752,11753,11754,11755,11756,11757,11758,\n11759,11760,11761,11762,11763,11764,11765,11766,11767,11768,11769,11770,\n11771,11772,11773,11774,11775,11776,11777,11778,11779,11780,11781,11782,\n11783,11784,11785,11786,11787,11788,11789,11790,11791,11792,11793,11794,\n11795,11796,11797,11798,11799,11800,11801,11802,11803,11804,11805,11806,\n11807,11808,11809,11810,11811,11812,11813,11814,11815,11816,11817,11818,\n11819,11820,11821,11822,11823,11824,11825,11826,11827,11828,11829,11830,\n11831,11832,11833,11834,11835,11836,11837,11838,11839,11840,11841,11842,\n11843,11844,11845,11846,11847,11848,11849,11850,11851,11852,11853,11854,\n11855,11856,11857,11858,11859,11860,11861,11862,11863,11864,11865,11866,\n11867,11868,11869,11870,11871,11872,11873,11874,11875,11876,11877,11878,\n11879,11880,11881,11882,11883,11884,11885,11886,11887,11888,11889,11890,\n11891,11892,11893,11894,11895,11896,11897,11898,11899,11900,11901,11902,\n11903,11904,11905,11906,11907,11908,11909,11910,11911,11912,11913,11914,\n11915,11916,11917,11918,11919,11920,11921,11922,11923,11924,11925,11926,\n11927,11928,11929,11930,11931,11932,11933,11934,11935,11936,11937,11938,\n11939,11940,11941,11942,11943,11944,11945,11946,11947,11948,11949,11950,\n11951,11952,11953,11954,11955,11956,11957,11958,11959,11960,11961,11962,\n11963,11964,11965,11966,11967,11968,11969,11970,11971,11972,11973,11974,\n11975,11976,11977,11978,11979,11980,11981,11982,11983,11984,11985,11986,\n11987,11988,11989,11990,11991,11992,11993,11994,11995,11996,11997,11998,\n11999,12000,12001,12002,12003,12004,12005,12006,12007,12008,12009,12010,\n12011,12012,12013,12014,12015,12016,12017,12018,12019,12020,12021,12022,\n12023,12024,12025,12026,12027,12028,12029,12030,12031,12032,12033,12034,\n12035,12036,12037,12038,12039,12040,12041,12042,12043,12044,12045,12046,\n12047,12048,12049,12050,12051,12052,12053,12054,12055,12056,12057,12058,\n12059,12060,12061,12062,12063,12064,12065,12066,12067,12068,12069,12070,\n12071,12072,12073,12074,12075,12076,12077,12078,12079,12080,12081,12082,\n12083,12084,12085,12086,12087,12088,12089,12090,12091,12092,12093,12094,\n12095,12096,12097,12098,12099,12100,12101,12102,12103,12104,12105,12106,\n12107,12108,12109,12110,12111,12112,12113,12114,12115,12116,12117,12118,\n12119,12120,12121,12122,12123,12124,12125,12126,12127,12128,12129,12130,\n12131,12132,12133,12134,12135,12136,12137,12138,12139,12140,12141,12142,\n12143,12144,12145,12146,12147,12148,12149,12150,12151,12152,12153,12154,\n12155,12156,12157,12158,12159,12160,12161,12162,12163,12164,12165,12166,\n12167,12168,12169,12170,12171,12172,12173,12174,12175,12176,12177,12178,\n12179,12180,12181,12182,12183,12184,12185,12186,12187,12188,12189,12190,\n12191,12192,12193,12194,12195,12196,12197,12198,12199,12200,12201,12202,\n12203,12204,12205,12206,12207,12208,12209,12210,12211,12212,12213,12214,\n12215,12216,12217,12218,12219,12220,12221,12222,12223,12224,12225,12226,\n12227,12228,12229,12230,12231,12232,12233,12234,12235,12236,12237,12238,\n12239,12240,12241,12242,12243,12244,12245,12246,12247,12248,12249,12250,\n12251,12252,12253,12254,12255,12256,12257,12258,12259,12260,12261,12262,\n12263,12264,12265,12266,12267,12268,12269,12270,12271,12272,12273,12274,\n12275,12276,12277,12278,12279,12280,12281,12282,12283,12284,12285,12286,\n12287,12288,12289,12290,12291,12292,12293,12294,12295,12296,12297,12298,\n12299,12300,12301,12302,12303,12304,12305,12306,12307,12308,12309,12310,\n12311,12312,12313,12314,12315,12316,12317,12318,12319,12320,12321,12322,\n12323,12324,12325,12326,12327,12328,12329,12330,12331,12332,12333,12334,\n12335,12336,12337,12338,12339,12340,12341,12342,12343,12344,12345,12346,\n12347,12348,12349,12350,12351,12352,12353,12354,12355,12356,12357,12358,\n12359,12360,12361,12362,12363,12364,12365,12366,12367,12368,12369,12370,\n12371,12372,12373,12374,12375,12376,12377,12378,12379,12380,12381,12382,\n12383,12384,12385,12386,12387,12388,12389,12390,12391,12392,12393,12394,\n12395,12396,12397,12398,12399,12400,12401,12402,12403,12404,12405,12406,\n12407,12408,12409,12410,12411,12412,12413,12414,12415,12416,12417,12418,\n12419,12420,12421,12422,12423,12424,12425,12426,12427,12428,12429,12430,\n12431,12432,12433,12434,12435,12436,12437,12438,12439,12440,12441,12442,\n12443,12444,12445,12446,12447,12448,12449,12450,12451,12452,12453,12454,\n12455,12456,12457,12458,12459,12460,12461,12462,12463,12464,12465,12466,\n12467,12468,12469,12470,12471,12472,12473,12474,12475,12476,12477,12478,\n12479,12480,12481,12482,12483,12484,12485,12486,12487,12488,12489,12490,\n12491,12492,12493,12494,12495,12496,12497,12498,12499,12500,12501,12502,\n12503,12504,12505,12506,12507,12508,12509,12510,12511,12512,12513,12514,\n12515,12516,12517,12518,12519,12520,12521,12522,12523,12524,12525,12526,\n12527,12528,12529,12530,12531,12532,12533,12534,12535,12536,12537,12538,\n12539,12540,12541,12542,12543,12544,12545,12546,12547,12548,12549,12550,\n12551,12552,12553,12554,12555,12556,12557,12558,12559,12560,12561,12562,\n12563,12564,12565,12566,12567,12568,12569,12570,12571,12572,12573,12574,\n12575,12576,12577,12578,12579,12580,12581,12582,12583,12584,12585,12586,\n12587,12588,12589,12590,12591,12592,12593,12594,12595,12596,12597,12598,\n12599,12600,12601,12602,12603,12604,12605,12606,12607,12608,12609,12610,\n12611,12612,12613,12614,12615,12616,12617,12618,12619,12620,12621,12622,\n12623,12624,12625,12626,12627,12628,12629,12630,12631,12632,12633,12634,\n12635,12636,12637,12638,12639,12640,12641,12642,12643,12644,12645,12646,\n12647,12648,12649,12650,12651,12652,12653,12654,12655,12656,12657,12658,\n12659,12660,12661,12662,12663,12664,12665,12666,12667,12668,12669,12670,\n12671,12672,12673,12674,12675,12676,12677,12678,12679,12680,12681,12682,\n12683,12684,12685,12686,12687,12688,12689,12690,12691,12692,12693,12694,\n12695,12696,12697,12698,12699,12700,12701,12702,12703,12704,12705,12706,\n12707,12708,12709,12710,12711,12712,12713,12714,12715,12716,12717,12718,\n12719,12720,12721,12722,12723,12724,12725,12726,12727,12728,12729,12730,\n12731,12732,12733,12734,12735,12736,12737,12738,12739,12740,12741,12742,\n12743,12744,12745,12746,12747,12748,12749,12750,12751,12752,12753,12754,\n12755,12756,12757,12758,12759,12760,12761,12762,12763,12764,12765,12766,\n12767,12768,12769,12770,12771,12772,12773,12774,12775,12776,12777,12778,\n12779,12780,12781,12782,12783,12784,12785,12786,12787,12788,12789,12790,\n12791,12792,12793,12794,12795,12796,12797,12798,12799,12800,12801,12802,\n12803,12804,12805,12806,12807,12808,12809,12810,12811,12812,12813,12814,\n12815,12816,12817,12818,12819,12820,12821,12822,12823,12824,12825,12826,\n12827,12828,12829,12830,12831,12832,12833,12834,12835,12836,12837,12838,\n12839,12840,12841,12842,12843,12844,12845,12846,12847,12848,12849,12850,\n12851,12852,12853,12854,12855,12856,12857,12858,12859,12860,12861,12862,\n12863,12864,12865,12866,12867,12868,12869,12870,12871,12872,12873,12874,\n12875,12876,12877,12878,12879,12880,12881,12882,12883,12884,12885,12886,\n12887,12888,12889,12890,12891,12892,12893,12894,12895,12896,12897,12898,\n12899,12900,12901,12902,12903,12904,12905,12906,12907,12908,12909,12910,\n12911,12912,12913,12914,12915,12916,12917,12918,12919,12920,12921,12922,\n12923,12924,12925,12926,12927,12928,12929,12930,12931,12932,12933,12934,\n12935,12936,12937,12938,12939,12940,12941,12942,12943,12944,12945,12946,\n12947,12948,12949,12950,12951,12952,12953,12954,12955,12956,12957,12958,\n12959,12960,12961,12962,12963,12964,12965,12966,12967,12968,12969,12970,\n12971,12972,12973,12974,12975,12976,12977,12978,12979,12980,12981,12982,\n12983,12984,12985,12986,12987,12988,12989,12990,12991,12992,12993,12994,\n12995,12996,12997,12998,12999,13000,13001,13002,13003,13004,13005,13006,\n13007,13008,13009,13010,13011,13012,13013,13014,13015,13016,13017,13018,\n13019,13020,13021,13022,13023,13024,13025,13026,13027,13028,13029,13030,\n13031,13032,13033,13034,13035,13036,13037,13038,13039,13040,13041,13042,\n13043,13044,13045,13046,13047,13048,13049,13050,13051,13052,13053,13054,\n13055,13056,13057,13058,13059,13060,13061,13062,13063,13064,13065,13066,\n13067,13068,13069,13070,13071,13072,13073,13074,13075,13076,13077,13078,\n13079,13080,13081,13082,13083,13084,13085,13086,13087,13088,13089,13090,\n13091,13092,13093,13094,13095,13096,13097,13098,13099,13100,13101,13102,\n13103,13104,13105,13106,13107,13108,13109,13110,13111,13112,13113,13114,\n13115,13116,13117,13118,13119,13120,13121,13122,13123,13124,13125,13126,\n13127,13128,13129,13130,13131,13132,13133,13134,13135,13136,13137,13138,\n13139,13140,13141,13142,13143,13144,13145,13146,13147,13148,13149,13150,\n13151,13152,13153,13154,13155,13156,13157,13158,13159,13160,13161,13162,\n13163,13164,13165,13166,13167,13168,13169,13170,13171,13172,13173,13174,\n13175,13176,13177,13178,13179,13180,13181,13182,13183,13184,13185,13186,\n13187,13188,13189,13190,13191,13192,13193,13194,13195,13196,13197,13198,\n13199,13200,13201,13202,13203,13204,13205,13206,13207,13208,13209,13210,\n13211,13212,13213,13214,13215,13216,13217,13218,13219,13220,13221,13222,\n13223,13224,13225,13226,13227,13228,13229,13230,13231,13232,13233,13234,\n13235,13236,13237,13238,13239,13240,13241,13242,13243,13244,13245,13246,\n13247,13248,13249,13250,13251,13252,13253,13254,13255,13256,13257,13258,\n13259,13260,13261,13262,13263,13264,13265,13266,13267,13268,13269,13270,\n13271,13272,13273,13274,13275,13276,13277,13278,13279,13280,13281,13282,\n13283,13284,13285,13286,13287,13288,13289,13290,13291,13292,13293,13294,\n13295,13296,13297,13298,13299,13300,13301,13302,13303,13304,13305,13306,\n13307,13308,13309,13310,13311,13312,13313,13314,13315,13316,13317,13318,\n13319,13320,13321,13322,13323,13324,13325,13326,13327,13328,13329,13330,\n13331,13332,13333,13334,13335,13336,13337,13338,13339,13340,13341,13342,\n13343,13344,13345,13346,13347,13348,13349,13350,13351,13352,13353,13354,\n13355,13356,13357,13358,13359,13360,13361,13362,13363,13364,13365,13366,\n13367,13368,13369,13370,13371,13372,13373,13374,13375,13376,13377,13378,\n13379,13380,13381,13382,13383,13384,13385,13386,13387,13388,13389,13390,\n13391,13392,13393,13394,13395,13396,13397,13398,13399,13400,13401,13402,\n13403,13404,13405,13406,13407,13408,13409,13410,13411,13412,13413,13414,\n13415,13416,13417,13418,13419,13420,13421,13422,13423,13424,13425,13426,\n13427,13428,13429,13430,13431,13432,13433,13434,13435,13436,13437,13438,\n13439,13440,13441,13442,13443,13444,13445,13446,13447,13448,13449,13450,\n13451,13452,13453,13454,13455,13456,13457,13458,13459,13460,13461,13462,\n13463,13464,13465,13466,13467,13468,13469,13470,13471,13472,13473,13474,\n13475,13476,13477,13478,13479,13480,13481,13482,13483,13484,13485,13486,\n13487,13488,13489,13490,13491,13492,13493,13494,13495,13496,13497,13498,\n13499,13500,13501,13502,13503,13504,13505,13506,13507,13508,13509,13510,\n13511,13512,13513,13514,13515,13516,13517,13518,13519,13520,13521,13522,\n13523,13524,13525,13526,13527,13528,13529,13530,13531,13532,13533,13534,\n13535,13536,13537,13538,13539,13540,13541,13542,13543,13544,13545,13546,\n13547,13548,13549,13550,13551,13552,13553,13554,13555,13556,13557,13558,\n13559,13560,13561,13562,13563,13564,13565,13566,13567,13568,13569,13570,\n13571,13572,13573,13574,13575,13576,13577,13578,13579,13580,13581,13582,\n13583,13584,13585,13586,13587,13588,13589,13590,13591,13592,13593,13594,\n13595,13596,13597,13598,13599,13600,13601,13602,13603,13604,13605,13606,\n13607,13608,13609,13610,13611,13612,13613,13614,13615,13616,13617,13618,\n13619,13620,13621,13622,13623,13624,13625,13626,13627,13628,13629,13630,\n13631,13632,13633,13634,13635,13636,13637,13638,13639,13640,13641,13642,\n13643,13644,13645,13646,13647,13648,13649,13650,13651,13652,13653,13654,\n13655,13656,13657,13658,13659,13660,13661,13662,13663,13664,13665,13666,\n13667,13668,13669,13670,13671,13672,13673,13674,13675,13676,13677,13678,\n13679,13680,13681,13682,13683,13684,13685,13686,13687,13688,13689,13690,\n13691,13692,13693,13694,13695,13696,13697,13698,13699,13700,13701,13702,\n13703,13704,13705,13706,13707,13708,13709,13710,13711,13712,13713,13714,\n13715,13716,13717,13718,13719,13720,13721,13722,13723,13724,13725,13726,\n13727,13728,13729,13730,13731,13732,13733,13734,13735,13736,13737,13738,\n13739,13740,13741,13742,13743,13744,13745,13746,13747,13748,13749,13750,\n13751,13752,13753,13754,13755,13756,13757,13758,13759,13760,13761,13762,\n13763,13764,13765,13766,13767,13768,13769,13770,13771,13772,13773,13774,\n13775,13776,13777,13778,13779,13780,13781,13782,13783,13784,13785,13786,\n13787,13788,13789,13790,13791,13792,13793,13794,13795,13796,13797,13798,\n13799,13800,13801,13802,13803,13804,13805,13806,13807,13808,13809,13810,\n13811,13812,13813,13814,13815,13816,13817,13818,13819,13820,13821,13822,\n13823,13824,13825,13826,13827,13828,13829,13830,13831,13832,13833,13834,\n13835,13836,13837,13838,13839,13840,13841,13842,13843,13844,13845,13846,\n13847,13848,13849,13850,13851,13852,13853,13854,13855,13856,13857,13858,\n13859,13860,13861,13862,13863,13864,13865,13866,13867,13868,13869,13870,\n13871,13872,13873,13874,13875,13876,13877,13878,13879,13880,13881,13882,\n13883,13884,13885,13886,13887,13888,13889,13890,13891,13892,13893,13894,\n13895,13896,13897,13898,13899,13900,13901,13902,13903,13904,13905,13906,\n13907,13908,13909,13910,13911,13912,13913,13914,13915,13916,13917,13918,\n13919,13920,13921,13922,13923,13924,13925,13926,13927,13928,13929,13930,\n13931,13932,13933,13934,13935,13936,13937,13938,13939,13940,13941,13942,\n13943,13944,13945,13946,13947,13948,13949,13950,13951,13952,13953,13954,\n13955,13956,13957,13958,13959,13960,13961,13962,13963,13964,13965,13966,\n13967,13968,13969,13970,13971,13972,13973,13974,13975,13976,13977,13978,\n13979,13980,13981,13982,13983,13984,13985,13986,13987,13988,13989,13990,\n13991,13992,13993,13994,13995,13996,13997,13998,13999,14000,14001,14002,\n14003,14004,14005,14006,14007,14008,14009,14010,14011,14012,14013,14014,\n14015,14016,14017,14018,14019,14020,14021,14022,14023,14024,14025,14026,\n14027,14028,14029,14030,14031,14032,14033,14034,14035,14036,14037,14038,\n14039,14040,14041,14042,14043,14044,14045,14046,14047,14048,14049,14050,\n14051,14052,14053,14054,14055,14056,14057,14058,14059,14060,14061,14062,\n14063,14064,14065,14066,14067,14068,14069,14070,14071,14072,14073,14074,\n14075,14076,14077,14078,14079,14080,14081,14082,14083,14084,14085,14086,\n14087,14088,14089,14090,14091,14092,14093,14094,14095,14096,14097,14098,\n14099,14100,14101,14102,14103,14104,14105,14106,14107,14108,14109,14110,\n14111,14112,14113,14114,14115,14116,14117,14118,14119,14120,14121,14122,\n14123,14124,14125,14126,14127,14128,14129,14130,14131,14132,14133,14134,\n14135,14136,14137,14138,14139,14140,14141,14142,14143,14144,14145,14146,\n14147,14148,14149,14150,14151,14152,14153,14154,14155,14156,14157,14158,\n14159,14160,14161,14162,14163,14164,14165,14166,14167,14168,14169,14170,\n14171,14172,14173,14174,14175,14176,14177,14178,14179,14180,14181,14182,\n14183,14184,14185,14186,14187,14188,14189,14190,14191,14192,14193,14194,\n14195,14196,14197,14198,14199,14200,14201,14202,14203,14204,14205,14206,\n14207,14208,14209,14210,14211,14212,14213,14214,14215,14216,14217,14218,\n14219,14220,14221,14222,14223,14224,14225,14226,14227,14228,14229,14230,\n14231,14232,14233,14234,14235,14236,14237,14238,14239,14240,14241,14242,\n14243,14244,14245,14246,14247,14248,14249,14250,14251,14252,14253,14254,\n14255,14256,14257,14258,14259,14260,14261,14262,14263,14264,14265,14266,\n14267,14268,14269,14270,14271,14272,14273,14274,14275,14276,14277,14278,\n14279,14280,14281,14282,14283,14284,14285,14286,14287,14288,14289,14290,\n14291,14292,14293,14294,14295,14296,14297,14298,14299,14300,14301,14302,\n14303,14304,14305,14306,14307,14308,14309,14310,14311,14312,14313,14314,\n14315,14316,14317,14318,14319,14320,14321,14322,14323,14324,14325,14326,\n14327,14328,14329,14330,14331,14332,14333,14334,14335,14336,14337,14338,\n14339,14340,14341,14342,14343,14344,14345,14346,14347,14348,14349,14350,\n14351,14352,14353,14354,14355,14356,14357,14358,14359,14360,14361,14362,\n14363,14364,14365,14366,14367,14368,14369,14370,14371,14372,14373,14374,\n14375,14376,14377,14378,14379,14380,14381,14382,14383,14384,14385,14386,\n14387,14388,14389,14390,14391,14392,14393,14394,14395,14396,14397,14398,\n14399,14400,14401,14402,14403,14404,14405,14406,14407,14408,14409,14410,\n14411,14412,14413,14414,14415,14416,14417,14418,14419,14420,14421,14422,\n14423,14424,14425,14426,14427,14428,14429,14430,14431,14432,14433,14434,\n14435,14436,14437,14438,14439,14440,14441,14442,14443,14444,14445,14446,\n14447,14448,14449,14450,14451,14452,14453,14454,14455,14456,14457,14458,\n14459,14460,14461,14462,14463,14464,14465,14466,14467,14468,14469,14470,\n14471,14472,14473,14474,14475,14476,14477,14478,14479,14480,14481,14482,\n14483,14484,14485,14486,14487,14488,14489,14490,14491,14492,14493,14494,\n14495,14496,14497,14498,14499,14500,14501,14502,14503,14504,14505,14506,\n14507,14508,14509,14510,14511,14512,14513,14514,14515,14516,14517,14518,\n14519,14520,14521,14522,14523,14524,14525,14526,14527,14528,14529,14530,\n14531,14532,14533,14534,14535,14536,14537,14538,14539,14540,14541,14542,\n14543,14544,14545,14546,14547,14548,14549,14550,14551,14552,14553,14554,\n14555,14556,14557,14558,14559,14560,14561,14562,14563,14564,14565,14566,\n14567,14568,14569,14570,14571,14572,14573,14574,14575,14576,14577,14578,\n14579,14580,14581,14582,14583,14584,14585,14586,14587,14588,14589,14590,\n14591,14592,14593,14594,14595,14596,14597,14598,14599,14600,14601,14602,\n14603,14604,14605,14606,14607,14608,14609,14610,14611,14612,14613,14614,\n14615,14616,14617,14618,14619,14620,14621,14622,14623,14624,14625,14626,\n14627,14628,14629,14630,14631,14632,14633,14634,14635,14636,14637,14638,\n14639,14640,14641,14642,14643,14644,14645,14646,14647,14648,14649,14650,\n14651,14652,14653,14654,14655,14656,14657,14658,14659,14660,14661,14662,\n14663,14664,14665,14666,14667,14668,14669,14670,14671,14672,14673,14674,\n14675,14676,14677,14678,14679,14680,14681,14682,14683,14684,14685,14686,\n14687,14688,14689,14690,14691,14692,14693,14694,14695,14696,14697,14698,\n14699,14700,14701,14702,14703,14704,14705,14706,14707,14708,14709,14710,\n14711,14712,14713,14714,14715,14716,14717,14718,14719,14720,14721,14722,\n14723,14724,14725,14726,14727,14728,14729,14730,14731,14732,14733,14734,\n14735,14736,14737,14738,14739,14740,14741,14742,14743,14744,14745,14746,\n14747,14748,14749,14750,14751,14752,14753,14754,14755,14756,14757,14758,\n14759,14760,14761,14762,14763,14764,14765,14766,14767,14768,14769,14770,\n14771,14772,14773,14774,14775,14776,14777,14778,14779,14780,14781,14782,\n14783,14784,14785,14786,14787,14788,14789,14790,14791,14792,14793,14794,\n14795,14796,14797,14798,14799,14800,14801,14802,14803,14804,14805,14806,\n14807,14808,14809,14810,14811,14812,14813,14814,14815,14816,14817,14818,\n14819,14820,14821,14822,14823,14824,14825,14826,14827,14828,14829,14830,\n14831,14832,14833,14834,14835,14836,14837,14838,14839,14840,14841,14842,\n14843,14844,14845,14846,14847,14848,14849,14850,14851,14852,14853,14854,\n14855,14856,14857,14858,14859,14860,14861,14862,14863,14864,14865,14866,\n14867,14868,14869,14870,14871,14872,14873,14874,14875,14876,14877,14878,\n14879,14880,14881,14882,14883,14884,14885,14886,14887,14888,14889,14890,\n14891,14892,14893,14894,14895,14896,14897,14898,14899,14900,14901,14902,\n14903,14904,14905,14906,14907,14908,14909,14910,14911,14912,14913,14914,\n14915,14916,14917,14918,14919,14920,14921,14922,14923,14924,14925,14926,\n14927,14928,14929,14930,14931,14932,14933,14934,14935,14936,14937,14938,\n14939,14940,14941,14942,14943,14944,14945,14946,14947,14948,14949,14950,\n14951,14952,14953,14954,14955,14956,14957,14958,14959,14960,14961,14962,\n14963,14964,14965,14966,14967,14968,14969,14970,14971,14972,14973,14974,\n14975,14976,14977,14978,14979,14980,14981,14982,14983,14984,14985,14986,\n14987,14988,14989,14990,14991,14992,14993,14994,14995,14996,14997,14998,\n14999,15000,15001,15002,15003,15004,15005,15006,15007,15008,15009,15010,\n15011,15012,15013,15014,15015,15016,15017,15018,15019,15020,15021,15022,\n15023,15024,15025,15026,15027,15028,15029,15030,15031,15032,15033,15034,\n15035,15036,15037,15038,15039,15040,15041,15042,15043,15044,15045,15046,\n15047,15048,15049,15050,15051,15052,15053,15054,15055,15056,15057,15058,\n15059,15060,15061,15062,15063,15064,15065,15066,15067,15068,15069,15070,\n15071,15072,15073,15074,15075,15076,15077,15078,15079,15080,15081,15082,\n15083,15084,15085,15086,15087,15088,15089,15090,15091,15092,15093,15094,\n15095,15096,15097,15098,15099,15100,15101,15102,15103,15104,15105,15106,\n15107,15108,15109,15110,15111,15112,15113,15114,15115,15116,15117,15118,\n15119,15120,15121,15122,15123,15124,15125,15126,15127,15128,15129,15130,\n15131,15132,15133,15134,15135,15136,15137,15138,15139,15140,15141,15142,\n15143,15144,15145,15146,15147,15148,15149,15150,15151,15152,15153,15154,\n15155,15156,15157,15158,15159,15160,15161,15162,15163,15164,15165,15166,\n15167,15168,15169,15170,15171,15172,15173,15174,15175,15176,15177,15178,\n15179,15180,15181,15182,15183,15184,15185,15186,15187,15188,15189,15190,\n15191,15192,15193,15194,15195,15196,15197,15198,15199,15200,15201,15202,\n15203,15204,15205,15206,15207,15208,15209,15210,15211,15212,15213,15214,\n15215,15216,15217,15218,15219,15220,15221,15222,15223,15224,15225,15226,\n15227,15228,15229,15230,15231,15232,15233,15234,15235,15236,15237,15238,\n15239,15240,15241,15242,15243,15244,15245,15246,15247,15248,15249,15250,\n15251,15252,15253,15254,15255,15256,15257,15258,15259,15260,15261,15262,\n15263,15264,15265,15266,15267,15268,15269,15270,15271,15272,15273,15274,\n15275,15276,15277,15278,15279,15280,15281,15282,15283,15284,15285,15286,\n15287,15288,15289,15290,15291,15292,15293,15294,15295,15296,15297,15298,\n15299,15300,15301,15302,15303,15304,15305,15306,15307,15308,15309,15310,\n15311,15312,15313,15314,15315,15316,15317,15318,15319,15320,15321,15322,\n15323,15324,15325,15326,15327,15328,15329,15330,15331,15332,15333,15334,\n15335,15336,15337,15338,15339,15340,15341,15342,15343,15344,15345,15346,\n15347,15348,15349,15350,15351,15352,15353,15354,15355,15356,15357,15358,\n15359,15360,15361,15362,15363,15364,15365,15366,15367,15368,15369,15370,\n15371,15372,15373,15374,15375,15376,15377,15378,15379,15380,15381,15382,\n15383,15384,15385,15386,15387,15388,15389,15390,15391,15392,15393,15394,\n15395,15396,15397,15398,15399,15400,15401,15402,15403,15404,15405,15406,\n15407,15408,15409,15410,15411,15412,15413,15414,15415,15416,15417,15418,\n15419,15420,15421,15422,15423,15424,15425,15426,15427,15428,15429,15430,\n15431,15432,15433,15434,15435,15436,15437,15438,15439,15440,15441,15442,\n15443,15444,15445,15446,15447,15448,15449,15450,15451,15452,15453,15454,\n15455,15456,15457,15458,15459,15460,15461,15462,15463,15464,15465,15466,\n15467,15468,15469,15470,15471,15472,15473,15474,15475,15476,15477,15478,\n15479,15480,15481,15482,15483,15484,15485,15486,15487,15488,15489,15490,\n15491,15492,15493,15494,15495,15496,15497,15498,15499,15500,15501,15502,\n15503,15504,15505,15506,15507,15508,15509,15510,15511,15512,15513,15514,\n15515,15516,15517,15518,15519,15520,15521,15522,15523,15524,15525,15526,\n15527,15528,15529,15530,15531,15532,15533,15534,15535,15536,15537,15538,\n15539,15540,15541,15542,15543,15544,15545,15546,15547,15548,15549,15550,\n15551,15552,15553,15554,15555,15556,15557,15558,15559,15560,15561,15562,\n15563,15564,15565,15566,15567,15568,15569,15570,15571,15572,15573,15574,\n15575,15576,15577,15578,15579,15580,15581,15582,15583,15584,15585,15586,\n15587,15588,15589,15590,15591,15592,15593,15594,15595,15596,15597,15598,\n15599,15600,15601,15602,15603,15604,15605,15606,15607,15608,15609,15610,\n15611,15612,15613,15614,15615,15616,15617,15618,15619,15620,15621,15622,\n15623,15624,15625,15626,15627,15628,15629,15630,15631,15632,15633,15634,\n15635,15636,15637,15638,15639,15640,15641,15642,15643,15644,15645,15646,\n15647,15648,15649,15650,15651,15652,15653,15654,15655,15656,15657,15658,\n15659,15660,15661,15662,15663,15664,15665,15666,15667,15668,15669,15670,\n15671,15672,15673,15674,15675,15676,15677,15678,15679,15680,15681,15682,\n15683,15684,15685,15686,15687,15688,15689,15690,15691,15692,15693,15694,\n15695,15696,15697,15698,15699,15700,15701,15702,15703,15704,15705,15706,\n15707,15708,15709,15710,15711,15712,15713,15714,15715,15716,15717,15718,\n15719,15720,15721,15722,15723,15724,15725,15726,15727,15728,15729,15730,\n15731,15732,15733,15734,15735,15736,15737,15738,15739,15740,15741,15742,\n15743,15744,15745,15746,15747,15748,15749,15750,15751,15752,15753,15754,\n15755,15756,15757,15758,15759,15760,15761,15762,15763,15764,15765,15766,\n15767,15768,15769,15770,15771,15772,15773,15774,15775,15776,15777,15778,\n15779,15780,15781,15782,15783,15784,15785,15786,15787,15788,15789,15790,\n15791,15792,15793,15794,15795,15796,15797,15798,15799,15800,15801,15802,\n15803,15804,15805,15806,15807,15808,15809,15810,15811,15812,15813,15814,\n15815,15816,15817,15818,15819,15820,15821,15822,15823,15824,15825,15826,\n15827,15828,15829,15830,15831,15832,15833,15834,15835,15836,15837,15838,\n15839,15840,15841,15842,15843,15844,15845,15846,15847,15848,15849,15850,\n15851,15852,15853,15854,15855,15856,15857,15858,15859,15860,15861,15862,\n15863,15864,15865,15866,15867,15868,15869,15870,15871,15872,15873,15874,\n15875,15876,15877,15878,15879,15880,15881,15882,15883,15884,15885,15886,\n15887,15888,15889,15890,15891,15892,15893,15894,15895,15896,15897,15898,\n15899,15900,15901,15902,15903,15904,15905,15906,15907,15908,15909,15910,\n15911,15912,15913,15914,15915,15916,15917,15918,15919,15920,15921,15922,\n15923,15924,15925,15926,15927,15928,15929,15930,15931,15932,15933,15934,\n15935,15936,15937,15938,15939,15940,15941,15942,15943,15944,15945,15946,\n15947,15948,15949,15950,15951,15952,15953,15954,15955,15956,15957,15958,\n15959,15960,15961,15962,15963,15964,15965,15966,15967,15968,15969,15970,\n15971,15972,15973,15974,15975,15976,15977,15978,15979,15980,15981,15982,\n15983,15984,15985,15986,15987,15988,15989,15990,15991,15992,15993,15994,\n15995,15996,15997,15998,15999,16000,16001,16002,16003,16004,16005,16006,\n16007,16008,16009,16010,16011,16012,16013,16014,16015,16016,16017,16018,\n16019,16020,16021,16022,16023,16024,16025,16026,16027,16028,16029,16030,\n16031,16032,16033,16034,16035,16036,16037,16038,16039,16040,16041,16042,\n16043,16044,16045,16046,16047,16048,16049,16050,16051,16052,16053,16054,\n16055,16056,16057,16058,16059,16060,16061,16062,16063,16064,16065,16066,\n16067,16068,16069,16070,16071,16072,16073,16074,16075,16076,16077,16078,\n16079,16080,16081,16082,16083,16084,16085,16086,16087,16088,16089,16090,\n16091,16092,16093,16094,16095,16096,16097,16098,16099,16100,16101,16102,\n16103,16104,16105,16106,16107,16108,16109,16110,16111,16112,16113,16114,\n16115,16116,16117,16118,16119,16120,16121,16122,16123,16124,16125,16126,\n16127,16128,16129,16130,16131,16132,16133,16134,16135,16136,16137,16138,\n16139,16140,16141,16142,16143,16144,16145,16146,16147,16148,16149,16150,\n16151,16152,16153,16154,16155,16156,16157,16158,16159,16160,16161,16162,\n16163,16164,16165,16166,16167,16168,16169,16170,16171,16172,16173,16174,\n16175,16176,16177,16178,16179,16180,16181,16182,16183,16184,16185,16186,\n16187,16188,16189,16190,16191,16192,16193,16194,16195,16196,16197,16198,\n16199,16200,16201,16202,16203,16204,16205,16206,16207,16208,16209,16210,\n16211,16212,16213,16214,16215,16216,16217,16218,16219,16220,16221,16222,\n16223,16224,16225,16226,16227,16228,16229,16230,16231,16232,16233,16234,\n16235,16236,16237,16238,16239,16240,16241,16242,16243,16244,16245,16246,\n16247,16248,16249,16250,16251,16252,16253,16254,16255,16256,16257,16258,\n16259,16260,16261,16262,16263,16264,16265,16266,16267,16268,16269,16270,\n16271,16272,16273,16274,16275,16276,16277,16278,16279,16280,16281,16282,\n16283,16284,16285,16286,16287,16288,16289,16290,16291,16292,16293,16294,\n16295,16296,16297,16298,16299,16300,16301,16302,16303,16304,16305,16306,\n16307,16308,16309,16310,16311,16312,16313,16314,16315,16316,16317,16318,\n16319,16320,16321,16322,16323,16324,16325,16326,16327,16328,16329,16330,\n16331,16332,16333,16334,16335,16336,16337,16338,16339,16340,16341,16342,\n16343,16344,16345,16346,16347,16348,16349,16350,16351,16352,16353,16354,\n16355,16356,16357,16358,16359,16360,16361,16362,16363,16364,16365,16366,\n16367,16368,16369,16370,16371,16372,16373,16374,16375,16376,16377,16378,\n16379,16380,16381,16382,16383,16384,16385,16386,16387,16388,16389,16390,\n16391,16392,16393,16394,16395,16396,16397,16398,16399,16400,16401,16402,\n16403,16404,16405,16406,16407,16408,16409,16410,16411,16412,16413,16414,\n16415,16416,16417,16418,16419,16420,16421,16422,16423,16424,16425,16426,\n16427,16428,16429,16430,16431,16432,16433,16434,16435,16436,16437,16438,\n16439,16440,16441,16442,16443,16444,16445,16446,16447,16448,16449,16450,\n16451,16452,16453,16454,16455,16456,16457,16458,16459,16460,16461,16462,\n16463,16464,16465,16466,16467,16468,16469,16470,16471,16472,16473,16474,\n16475,16476,16477,16478,16479,16480,16481,16482,16483,16484,16485,16486,\n16487,16488,16489,16490,16491,16492,16493,16494,16495,16496,16497,16498,\n16499,16500,16501,16502,16503,16504,16505,16506,16507,16508,16509,16510,\n16511,16512,16513,16514,16515,16516,16517,16518,16519,16520,16521,16522,\n16523,16524,16525,16526,16527,16528,16529,16530,16531,16532,16533,16534,\n16535,16536,16537,16538,16539,16540,16541,16542,16543,16544,16545,16546,\n16547,16548,16549,16550,16551,16552,16553,16554,16555,16556,16557,16558,\n16559,16560,16561,16562,16563,16564,16565,16566,16567,16568,16569,16570,\n16571,16572,16573,16574,16575,16576,16577,16578,16579,16580,16581,16582,\n16583,16584,16585,16586,16587,16588,16589,16590,16591,16592,16593,16594,\n16595,16596,16597,16598,16599,16600,16601,16602,16603,16604,16605,16606,\n16607,16608,16609,16610,16611,16612,16613,16614,16615,16616,16617,16618,\n16619,16620,16621,16622,16623,16624,16625,16626,16627,16628,16629,16630,\n16631,16632,16633,16634,16635,16636,16637,16638,16639,16640,16641,16642,\n16643,16644,16645,16646,16647,16648,16649,16650,16651,16652,16653,16654,\n16655,16656,16657,16658,16659,16660,16661,16662,16663,16664,16665,16666,\n16667,16668,16669,16670,16671,16672,16673,16674,16675,16676,16677,16678,\n16679,16680,16681,16682,16683,16684,16685,16686,16687,16688,16689,16690,\n16691,16692,16693,16694,16695,16696,16697,16698,16699,16700,16701,16702,\n16703,16704,16705,16706,16707,16708,16709,16710,16711,16712,16713,16714,\n16715,16716,16717,16718,16719,16720,16721,16722,16723,16724,16725,16726,\n16727,16728,16729,16730,16731,16732,16733,16734,16735,16736,16737,16738,\n16739,16740,16741,16742,16743,16744,16745,16746,16747,16748,16749,16750,\n16751,16752,16753,16754,16755,16756,16757,16758,16759,16760,16761,16762,\n16763,16764,16765,16766,16767,16768,16769,16770,16771,16772,16773,16774,\n16775,16776,16777,16778,16779,16780,16781,16782,16783,16784,16785,16786,\n16787,16788,16789,16790,16791,16792,16793,16794,16795,16796,16797,16798,\n16799,16800,16801,16802,16803,16804,16805,16806,16807,16808,16809,16810,\n16811,16812,16813,16814,16815,16816,16817,16818,16819,16820,16821,16822,\n16823,16824,16825,16826,16827,16828,16829,16830,16831,16832,16833,16834,\n16835,16836,16837,16838,16839,16840,16841,16842,16843,16844,16845,16846,\n16847,16848,16849,16850,16851,16852,16853,16854,16855,16856,16857,16858,\n16859,16860,16861,16862,16863,16864,16865,16866,16867,16868,16869,16870,\n16871,16872,16873,16874,16875,16876,16877,16878,16879,16880,16881,16882,\n16883,16884,16885,16886,16887,16888,16889,16890,16891,16892,16893,16894,\n16895,16896,16897,16898,16899,16900,16901,16902,16903,16904,16905,16906,\n16907,16908,16909,16910,16911,16912,16913,16914,16915,16916,16917,16918,\n16919,16920,16921,16922,16923,16924,16925,16926,16927,16928,16929,16930,\n16931,16932,16933,16934,16935,16936,16937,16938,16939,16940,16941,16942,\n16943,16944,16945,16946,16947,16948,16949,16950,16951,16952,16953,16954,\n16955,16956,16957,16958,16959,16960,16961,16962,16963,16964,16965,16966,\n16967,16968,16969,16970,16971,16972,16973,16974,16975,16976,16977,16978,\n16979,16980,16981,16982,16983,16984,16985,16986,16987,16988,16989,16990,\n16991,16992,16993,16994,16995,16996,16997,16998,16999,17000,17001,17002,\n17003,17004,17005,17006,17007,17008,17009,17010,17011,17012,17013,17014,\n17015,17016,17017,17018,17019,17020,17021,17022,17023,17024,17025,17026,\n17027,17028,17029,17030,17031,17032,17033,17034,17035,17036,17037,17038,\n17039,17040,17041,17042,17043,17044,17045,17046,17047,17048,17049,17050,\n17051,17052,17053,17054,17055,17056,17057,17058,17059,17060,17061,17062,\n17063,17064,17065,17066,17067,17068,17069,17070,17071,17072,17073,17074,\n17075,17076,17077,17078,17079,17080,17081,17082,17083,17084,17085,17086,\n17087,17088,17089,17090,17091,17092,17093,17094,17095,17096,17097,17098,\n17099,17100,17101,17102,17103,17104,17105,17106,17107,17108,17109,17110,\n17111,17112,17113,17114,17115,17116,17117,17118,17119,17120,17121,17122,\n17123,17124,17125,17126,17127,17128,17129,17130,17131,17132,17133,17134,\n17135,17136,17137,17138,17139,17140,17141,17142,17143,17144,17145,17146,\n17147,17148,17149,17150,17151,17152,17153,17154,17155,17156,17157,17158,\n17159,17160,17161,17162,17163,17164,17165,17166,17167,17168,17169,17170,\n17171,17172,17173,17174,17175,17176,17177,17178,17179,17180,17181,17182,\n17183,17184,17185,17186,17187,17188,17189,17190,17191,17192,17193,17194,\n17195,17196,17197,17198,17199,17200,17201,17202,17203,17204,17205,17206,\n17207,17208,17209,17210,17211,17212,17213,17214,17215,17216,17217,17218,\n17219,17220,17221,17222,17223,17224,17225,17226,17227,17228,17229,17230,\n17231,17232,17233,17234,17235,17236,17237,17238,17239,17240,17241,17242,\n17243,17244,17245,17246,17247,17248,17249,17250,17251,17252,17253,17254,\n17255,17256,17257,17258,17259,17260,17261,17262,17263,17264,17265,17266,\n17267,17268,17269,17270,17271,17272,17273,17274,17275,17276,17277,17278,\n17279,17280,17281,17282,17283,17284,17285,17286,17287,17288,17289,17290,\n17291,17292,17293,17294,17295,17296,17297,17298,17299,17300,17301,17302,\n17303,17304,17305,17306,17307,17308,17309,17310,17311,17312,17313,17314,\n17315,17316,17317,17318,17319,17320,17321,17322,17323,17324,17325,17326,\n17327,17328,17329,17330,17331,17332,17333,17334,17335,17336,17337,17338,\n17339,17340,17341,17342,17343,17344,17345,17346,17347,17348,17349,17350,\n17351,17352,17353,17354,17355,17356,17357,17358,17359,17360,17361,17362,\n17363,17364,17365,17366,17367,17368,17369,17370,17371,17372,17373,17374,\n17375,17376,17377,17378,17379,17380,17381,17382,17383,17384,17385,17386,\n17387,17388,17389,17390,17391,17392,17393,17394,17395,17396,17397,17398,\n17399,17400,17401,17402,17403,17404,17405,17406,17407,17408,17409,17410,\n17411,17412,17413,17414,17415,17416,17417,17418,17419,17420,17421,17422,\n17423,17424,17425,17426,17427,17428,17429,17430,17431,17432,17433,17434,\n17435,17436,17437,17438,17439,17440,17441,17442,17443,17444,17445,17446,\n17447,17448,17449,17450,17451,17452,17453,17454,17455,17456,17457,17458,\n17459,17460,17461,17462,17463,17464,17465,17466,17467,17468,17469,17470,\n17471,17472,17473,17474,17475,17476,17477,17478,17479,17480,17481,17482,\n17483,17484,17485,17486,17487,17488,17489,17490,17491,17492,17493,17494,\n17495,17496,17497,17498,17499,17500,17501,17502,17503,17504,17505,17506,\n17507,17508,17509,17510,17511,17512,17513,17514,17515,17516,17517,17518,\n17519,17520,17521,17522,17523,17524,17525,17526,17527,17528,17529,17530,\n17531,17532,17533,17534,17535,17536,17537,17538,17539,17540,17541,17542,\n17543,17544,17545,17546,17547,17548,17549,17550,17551,17552,17553,17554,\n17555,17556,17557,17558,17559,17560,17561,17562,17563,17564,17565,17566,\n17567,17568,17569,17570,17571,17572,17573,17574,17575,17576,17577,17578,\n17579,17580,17581,17582,17583,17584,17585,17586,17587,17588,17589,17590,\n17591,17592,17593,17594,17595,17596,17597,17598,17599,17600,17601,17602,\n17603,17604,17605,17606,17607,17608,17609,17610,17611,17612,17613,17614,\n17615,17616,17617,17618,17619,17620,17621,17622,17623,17624,17625,17626,\n17627,17628,17629,17630,17631,17632,17633,17634,17635,17636,17637,17638,\n17639,17640,17641,17642,17643,17644,17645,17646,17647,17648,17649,17650,\n17651,17652,17653,17654,17655,17656,17657,17658,17659,17660,17661,17662,\n17663,17664,17665,17666,17667,17668,17669,17670,17671,17672,17673,17674,\n17675,17676,17677,17678,17679,17680,17681,17682,17683,17684,17685,17686,\n17687,17688,17689,17690,17691,17692,17693,17694,17695,17696,17697,17698,\n17699,17700,17701,17702,17703,17704,17705,17706,17707,17708,17709,17710,\n17711,17712,17713,17714,17715,17716,17717,17718,17719,17720,17721,17722,\n17723,17724,17725,17726,17727,17728,17729,17730,17731,17732,17733,17734,\n17735,17736,17737,17738,17739,17740,17741,17742,17743,17744,17745,17746,\n17747,17748,17749,17750,17751,17752,17753,17754,17755,17756,17757,17758,\n17759,17760,17761,17762,17763,17764,17765,17766,17767,17768,17769,17770,\n17771,17772,17773,17774,17775,17776,17777,17778,17779,17780,17781,17782,\n17783,17784,17785,17786,17787,17788,17789,17790,17791,17792,17793,17794,\n17795,17796,17797,17798,17799,17800,17801,17802,17803,17804,17805,17806,\n17807,17808,17809,17810,17811,17812,17813,17814,17815,17816,17817,17818,\n17819,17820,17821,17822,17823,17824,17825,17826,17827,17828,17829,17830,\n17831,17832,17833,17834,17835,17836,17837,17838,17839,17840,17841,17842,\n17843,17844,17845,17846,17847,17848,17849,17850,17851,17852,17853,17854,\n17855,17856,17857,17858,17859,17860,17861,17862,17863,17864,17865,17866,\n17867,17868,17869,17870,17871,17872,17873,17874,17875,17876,17877,17878,\n17879,17880,17881,17882,17883,17884,17885,17886,17887,17888,17889,17890,\n17891,17892,17893,17894,17895,17896,17897,17898,17899,17900,17901,17902,\n17903,17904,17905,17906,17907,17908,17909,17910,17911,17912,17913,17914,\n17915,17916,17917,17918,17919,17920,17921,17922,17923,17924,17925,17926,\n17927,17928,17929,17930,17931,17932,17933,17934,17935,17936,17937,17938,\n17939,17940,17941,17942,17943,17944,17945,17946,17947,17948,17949,17950,\n17951,17952,17953,17954,17955,17956,17957,17958,17959,17960,17961,17962,\n17963,17964,17965,17966,17967,17968,17969,17970,17971,17972,17973,17974,\n17975,17976,17977,17978,17979,17980,17981,17982,17983,17984,17985,17986,\n17987,17988,17989,17990,17991,17992,17993,17994,17995,17996,17997,17998,\n17999,18000,18001,18002,18003,18004,18005,18006,18007,18008,18009,18010,\n18011,18012,18013,18014,18015,18016,18017,18018,18019,18020,18021,18022,\n18023,18024,18025,18026,18027,18028,18029,18030,18031,18032,18033,18034,\n18035,18036,18037,18038,18039,18040,18041,18042,18043,18044,18045,18046,\n18047,18048,18049,18050,18051,18052,18053,18054,18055,18056,18057,18058,\n18059,18060,18061,18062,18063,18064,18065,18066,18067,18068,18069,18070,\n18071,18072,18073,18074,18075,18076,18077,18078,18079,18080,18081,18082,\n18083,18084,18085,18086,18087,18088,18089,18090,18091,18092,18093,18094,\n18095,18096,18097,18098,18099,18100,18101,18102,18103,18104,18105,18106,\n18107,18108,18109,18110,18111,18112,18113,18114,18115,18116,18117,18118,\n18119,18120,18121,18122,18123,18124,18125,18126,18127,18128,18129,18130,\n18131,18132,18133,18134,18135,18136,18137,18138,18139,18140,18141,18142,\n18143,18144,18145,18146,18147,18148,18149,18150,18151,18152,18153,18154,\n18155,18156,18157,18158,18159,18160,18161,18162,18163,18164,18165,18166,\n18167,18168,18169,18170,18171,18172,18173,18174,18175,18176,18177,18178,\n18179,18180,18181,18182,18183,18184,18185,18186,18187,18188,18189,18190,\n18191,18192,18193,18194,18195,18196,18197,18198,18199,18200,18201,18202,\n18203,18204,18205,18206,18207,18208,18209,18210,18211,18212,18213,18214,\n18215,18216,18217,18218,18219,18220,18221,18222,18223,18224,18225,18226,\n18227,18228,18229,18230,18231,18232,18233,18234,18235,18236,18237,18238,\n18239,18240,18241,18242,18243,18244,18245,18246,18247,18248,18249,18250,\n18251,18252,18253,18254,18255,18256,18257,18258,18259,18260,18261,18262,\n18263,18264,18265,18266,18267,18268,18269,18270,18271,18272,18273,18274,\n18275,18276,18277,18278,18279,18280,18281,18282,18283,18284,18285,18286,\n18287,18288,18289,18290,18291,18292,18293,18294,18295,18296,18297,18298,\n18299,18300,18301,18302,18303,18304,18305,18306,18307,18308,18309,18310,\n18311,18312,18313,18314,18315,18316,18317,18318,18319,18320,18321,18322,\n18323,18324,18325,18326,18327,18328,18329,18330,18331,18332,18333,18334,\n18335,18336,18337,18338,18339,18340,18341,18342,18343,18344,18345,18346,\n18347,18348,18349,18350,18351,18352,18353,18354,18355,18356,18357,18358,\n18359,18360,18361,18362,18363,18364,18365,18366,18367,18368,18369,18370,\n18371,18372,18373,18374,18375,18376,18377,18378,18379,18380,18381,18382,\n18383,18384,18385,18386,18387,18388,18389,18390,18391,18392,18393,18394,\n18395,18396,18397,18398,18399,18400,18401,18402,18403,18404,18405,18406,\n18407,18408,18409,18410,18411,18412,18413,18414,18415,18416,18417,18418,\n18419,18420,18421,18422,18423,18424,18425,18426,18427,18428,18429,18430,\n18431,18432,18433,18434,18435,18436,18437,18438,18439,18440,18441,18442,\n18443,18444,18445,18446,18447,18448,18449,18450,18451,18452,18453,18454,\n18455,18456,18457,18458,18459,18460,18461,18462,18463,18464,18465,18466,\n18467,18468,18469,18470,18471,18472,18473,18474,18475,18476,18477,18478,\n18479,18480,18481,18482,18483,18484,18485,18486,18487,18488,18489,18490,\n18491,18492,18493,18494,18495,18496,18497,18498,18499,18500,18501,18502,\n18503,18504,18505,18506,18507,18508,18509,18510,18511,18512,18513,18514,\n18515,18516,18517,18518,18519,18520,18521,18522,18523,18524,18525,18526,\n18527,18528,18529,18530,18531,18532,18533,18534,18535,18536,18537,18538,\n18539,18540,18541,18542,18543,18544,18545,18546,18547,18548,18549,18550,\n18551,18552,18553,18554,18555,18556,18557,18558,18559,18560,18561,18562,\n18563,18564,18565,18566,18567,18568,18569,18570,18571,18572,18573,18574,\n18575,18576,18577,18578,18579,18580,18581,18582,18583,18584,18585,18586,\n18587,18588,18589,18590,18591,18592,18593,18594,18595,18596,18597,18598,\n18599,18600,18601,18602,18603,18604,18605,18606,18607,18608,18609,18610,\n18611,18612,18613,18614,18615,18616,18617,18618,18619,18620,18621,18622,\n18623,18624,18625,18626,18627,18628,18629,18630,18631,18632,18633,18634,\n18635,18636,18637,18638,18639,18640,18641,18642,18643,18644,18645,18646,\n18647,18648,18649,18650,18651,18652,18653,18654,18655,18656,18657,18658,\n18659,18660,18661,18662,18663,18664,18665,18666,18667,18668,18669,18670,\n18671,18672,18673,18674,18675,18676,18677,18678,18679,18680,18681,18682,\n18683,18684,18685,18686,18687,18688,18689,18690,18691,18692,18693,18694,\n18695,18696,18697,18698,18699,18700,18701,18702,18703,18704,18705,18706,\n18707,18708,18709,18710,18711,18712,18713,18714,18715,18716,18717,18718,\n18719,18720,18721,18722,18723,18724,18725,18726,18727,18728,18729,18730,\n18731,18732,18733,18734,18735,18736,18737,18738,18739,18740,18741,18742,\n18743,18744,18745,18746,18747,18748,18749,18750,18751,18752,18753,18754,\n18755,18756,18757,18758,18759,18760,18761,18762,18763,18764,18765,18766,\n18767,18768,18769,18770,18771,18772,18773,18774,18775,18776,18777,18778,\n18779,18780,18781,18782,18783,18784,18785,18786,18787,18788,18789,18790,\n18791,18792,18793,18794,18795,18796,18797,18798,18799,18800,18801,18802,\n18803,18804,18805,18806,18807,18808,18809,18810,18811,18812,18813,18814,\n18815,18816,18817,18818,18819,18820,18821,18822,18823,18824,18825,18826,\n18827,18828,18829,18830,18831,18832,18833,18834,18835,18836,18837,18838,\n18839,18840,18841,18842,18843,18844,18845,18846,18847,18848,18849,18850,\n18851,18852,18853,18854,18855,18856,18857,18858,18859,18860,18861,18862,\n18863,18864,18865,18866,18867,18868,18869,18870,18871,18872,18873,18874,\n18875,18876,18877,18878,18879,18880,18881,18882,18883,18884,18885,18886,\n18887,18888,18889,18890,18891,18892,18893,18894,18895,18896,18897,18898,\n18899,18900,18901,18902,18903,18904,18905,18906,18907,18908,18909,18910,\n18911,18912,18913,18914,18915,18916,18917,18918,18919,18920,18921,18922,\n18923,18924,18925,18926,18927,18928,18929,18930,18931,18932,18933,18934,\n18935,18936,18937,18938,18939,18940,18941,18942,18943,18944,18945,18946,\n18947,18948,18949,18950,18951,18952,18953,18954,18955,18956,18957,18958,\n18959,18960,18961,18962,18963,18964,18965,18966,18967,18968,18969,18970,\n18971,18972,18973,18974,18975,18976,18977,18978,18979,18980,18981,18982,\n18983,18984,18985,18986,18987,18988,18989,18990,18991,18992,18993,18994,\n18995,18996,18997,18998,18999,19000,19001,19002,19003,19004,19005,19006,\n19007,19008,19009,19010,19011,19012,19013,19014,19015,19016,19017,19018,\n19019,19020,19021,19022,19023,19024,19025,19026,19027,19028,19029,19030,\n19031,19032,19033,19034,19035,19036,19037,19038,19039,19040,19041,19042,\n19043,19044,19045,19046,19047,19048,19049,19050,19051,19052,19053,19054,\n19055,19056,19057,19058,19059,19060,19061,19062,19063,19064,19065,19066,\n19067,19068,19069,19070,19071,19072,19073,19074,19075,19076,19077,19078,\n19079,19080,19081,19082,19083,19084,19085,19086,19087,19088,19089,19090,\n19091,19092,19093,19094,19095,19096,19097,19098,19099,19100,19101,19102,\n19103,19104,19105,19106,19107,19108,19109,19110,19111,19112,19113,19114,\n19115,19116,19117,19118,19119,19120,19121,19122,19123,19124,19125,19126,\n19127,19128,19129,19130,19131,19132,19133,19134,19135,19136,19137,19138,\n19139,19140,19141,19142,19143,19144,19145,19146,19147,19148,19149,19150,\n19151,19152,19153,19154,19155,19156,19157,19158,19159,19160,19161,19162,\n19163,19164,19165,19166,19167,19168,19169,19170,19171,19172,19173,19174,\n19175,19176,19177,19178,19179,19180,19181,19182,19183,19184,19185,19186,\n19187,19188,19189,19190,19191,19192,19193,19194,19195,19196,19197,19198,\n19199,19200,19201,19202,19203,19204,19205,19206,19207,19208,19209,19210,\n19211,19212,19213,19214,19215,19216,19217,19218,19219,19220,19221,19222,\n19223,19224,19225,19226,19227,19228,19229,19230,19231,19232,19233,19234,\n19235,19236,19237,19238,19239,19240,19241,19242,19243,19244,19245,19246,\n19247,19248,19249,19250,19251,19252,19253,19254,19255,19256,19257,19258,\n19259,19260,19261,19262,19263,19264,19265,19266,19267,19268,19269,19270,\n19271,19272,19273,19274,19275,19276,19277,19278,19279,19280,19281,19282,\n19283,19284,19285,19286,19287,19288,19289,19290,19291,19292,19293,19294,\n19295,19296,19297,19298,19299,19300,19301,19302,19303,19304,19305,19306,\n19307,19308,19309,19310,19311,19312,19313,19314,19315,19316,19317,19318,\n19319,19320,19321,19322,19323,19324,19325,19326,19327,19328,19329,19330,\n19331,19332,19333,19334,19335,19336,19337,19338,19339,19340,19341,19342,\n19343,19344,19345,19346,19347,19348,19349,19350,19351,19352,19353,19354,\n19355,19356,19357,19358,19359,19360,19361,19362,19363,19364,19365,19366,\n19367,19368,19369,19370,19371,19372,19373,19374,19375,19376,19377,19378,\n19379,19380,19381,19382,19383,19384,19385,19386,19387,19388,19389,19390,\n19391,19392,19393,19394,19395,19396,19397,19398,19399,19400,19401,19402,\n19403,19404,19405,19406,19407,19408,19409,19410,19411,19412,19413,19414,\n19415,19416,19417,19418,19419,19420,19421,19422,19423,19424,19425,19426,\n19427,19428,19429,19430,19431,19432,19433,19434,19435,19436,19437,19438,\n19439,19440,19441,19442,19443,19444,19445,19446,19447,19448,19449,19450,\n19451,19452,19453,19454,19455,19456,19457,19458,19459,19460,19461,19462,\n19463,19464,19465,19466,19467,19468,19469,19470,19471,19472,19473,19474,\n19475,19476,19477,19478,19479,19480,19481,19482,19483,19484,19485,19486,\n19487,19488,19489,19490,19491,19492,19493,19494,19495,19496,19497,19498,\n19499,19500,19501,19502,19503,19504,19505,19506,19507,19508,19509,19510,\n19511,19512,19513,19514,19515,19516,19517,19518,19519,19520,19521,19522,\n19523,19524,19525,19526,19527,19528,19529,19530,19531,19532,19533,19534,\n19535,19536,19537,19538,19539,19540,19541,19542,19543,19544,19545,19546,\n19547,19548,19549,19550,19551,19552,19553,19554,19555,19556,19557,19558,\n19559,19560,19561,19562,19563,19564,19565,19566,19567,19568,19569,19570,\n19571,19572,19573,19574,19575,19576,19577,19578,19579,19580,19581,19582,\n19583,19584,19585,19586,19587,19588,19589,19590,19591,19592,19593,19594,\n19595,19596,19597,19598,19599,19600,19601,19602,19603,19604,19605,19606,\n19607,19608,19609,19610,19611,19612,19613,19614,19615,19616,19617,19618,\n19619,19620,19621,19622,19623,19624,19625,19626,19627,19628,19629,19630,\n19631,19632,19633,19634,19635,19636,19637,19638,19639,19640,19641,19642,\n19643,19644,19645,19646,19647,19648,19649,19650,19651,19652,19653,19654,\n19655,19656,19657,19658,19659,19660,19661,19662,19663,19664,19665,19666,\n19667,19668,19669,19670,19671,19672,19673,19674,19675,19676,19677,19678,\n19679,19680,19681,19682,19683,19684,19685,19686,19687,19688,19689,19690,\n19691,19692,19693,19694,19695,19696,19697,19698,19699,19700,19701,19702,\n19703,19704,19705,19706,19707,19708,19709,19710,19711,19712,19713,19714,\n19715,19716,19717,19718,19719,19720,19721,19722,19723,19724,19725,19726,\n19727,19728,19729,19730,19731,19732,19733,19734,19735,19736,19737,19738,\n19739,19740,19741,19742,19743,19744,19745,19746,19747,19748,19749,19750,\n19751,19752,19753,19754,19755,19756,19757,19758,19759,19760,19761,19762,\n19763,19764,19765,19766,19767,19768,19769,19770,19771,19772,19773,19774,\n19775,19776,19777,19778,19779,19780,19781,19782,19783,19784,19785,19786,\n19787,19788,19789,19790,19791,19792,19793,19794,19795,19796,19797,19798,\n19799,19800,19801,19802,19803,19804,19805,19806,19807,19808,19809,19810,\n19811,19812,19813,19814,19815,19816,19817,19818,19819,19820,19821,19822,\n19823,19824,19825,19826,19827,19828,19829,19830,19831,19832,19833,19834,\n19835,19836,19837,19838,19839,19840,19841,19842,19843,19844,19845,19846,\n19847,19848,19849,19850,19851,19852,19853,19854,19855,19856,19857,19858,\n19859,19860,19861,19862,19863,19864,19865,19866,19867,19868,19869,19870,\n19871,19872,19873,19874,19875,19876,19877,19878,19879,19880,19881,19882,\n19883,19884,19885,19886,19887,19888,19889,19890,19891,19892,19893,19894,\n19895,19896,19897,19898,19899,19900,19901,19902,19903,19904,19905,19906,\n19907,19908,19909,19910,19911,19912,19913,19914,19915,19916,19917,19918,\n19919,19920,19921,19922,19923,19924,19925,19926,19927,19928,19929,19930,\n19931,19932,19933,19934,19935,19936,19937,19938,19939,19940,19941,19942,\n19943,19944,19945,19946,19947,19948,19949,19950,19951,19952,19953,19954,\n19955,19956,19957,19958,19959,19960,19961,19962,19963,19964,19965,19966,\n19967,19968,19969,19970,19971,19972,19973,19974,19975,19976,19977,19978,\n19979,19980,19981,19982,19983,19984,19985,19986,19987,19988,19989,19990,\n19991,19992,19993,19994,19995,19996,19997,19998,19999,20000,20001,20002,\n20003,20004,20005,20006,20007,20008,20009,20010,20011,20012,20013,20014,\n20015,20016,20017,20018,20019,20020,20021,20022,20023,20024,20025,20026,\n20027,20028,20029,20030,20031,20032,20033,20034,20035,20036,20037,20038,\n20039,20040,20041,20042,20043,20044,20045,20046,20047,20048,20049,20050,\n20051,20052,20053,20054,20055,20056,20057,20058,20059,20060,20061,20062,\n20063,20064,20065,20066,20067,20068,20069,20070,20071,20072,20073,20074,\n20075,20076,20077,20078,20079,20080,20081,20082,20083,20084,20085,20086,\n20087,20088,20089,20090,20091,20092,20093,20094,20095,20096,20097,20098,\n20099,20100,20101,20102,20103,20104,20105,20106,20107,20108,20109,20110,\n20111,20112,20113,20114,20115,20116,20117,20118,20119,20120,20121,20122,\n20123,20124,20125,20126,20127,20128,20129,20130,20131,20132,20133,20134,\n20135,20136,20137,20138,20139,20140,20141,20142,20143,20144,20145,20146,\n20147,20148,20149,20150,20151,20152,20153,20154,20155,20156,20157,20158,\n20159,20160,20161,20162,20163,20164,20165,20166,20167,20168,20169,20170,\n20171,20172,20173,20174,20175,20176,20177,20178,20179,20180,20181,20182,\n20183,20184,20185,20186,20187,20188,20189,20190,20191,20192,20193,20194,\n20195,20196,20197,20198,20199,20200,20201,20202,20203,20204,20205,20206,\n20207,20208,20209,20210,20211,20212,20213,20214,20215,20216,20217,20218,\n20219,20220,20221,20222,20223,20224,20225,20226,20227,20228,20229,20230,\n20231,20232,20233,20234,20235,20236,20237,20238,20239,20240,20241,20242,\n20243,20244,20245,20246,20247,20248,20249,20250,20251,20252,20253,20254,\n20255,20256,20257,20258,20259,20260,20261,20262,20263,20264,20265,20266,\n20267,20268,20269,20270,20271,20272,20273,20274,20275,20276,20277,20278,\n20279,20280,20281,20282,20283,20284,20285,20286,20287,20288,20289,20290,\n20291,20292,20293,20294,20295,20296,20297,20298,20299,20300,20301,20302,\n20303,20304,20305,20306,20307,20308,20309,20310,20311,20312,20313,20314,\n20315,20316,20317,20318,20319,20320,20321,20322,20323,20324,20325,20326,\n20327,20328,20329,20330,20331,20332,20333,20334,20335,20336,20337,20338,\n20339,20340,20341,20342,20343,20344,20345,20346,20347,20348,20349,20350,\n20351,20352,20353,20354,20355,20356,20357,20358,20359,20360,20361,20362,\n20363,20364,20365,20366,20367,20368,20369,20370,20371,20372,20373,20374,\n20375,20376,20377,20378,20379,20380,20381,20382,20383,20384,20385,20386,\n20387,20388,20389,20390,20391,20392,20393,20394,20395,20396,20397,20398,\n20399,20400,20401,20402,20403,20404,20405,20406,20407,20408,20409,20410,\n20411,20412,20413,20414,20415,20416,20417,20418,20419,20420,20421,20422,\n20423,20424,20425,20426,20427,20428,20429,20430,20431,20432,20433,20434,\n20435,20436,20437,20438,20439,20440,20441,20442,20443,20444,20445,20446,\n20447,20448,20449,20450,20451,20452,20453,20454,20455,20456,20457,20458,\n20459,20460,20461,20462,20463,20464,20465,20466,20467,20468,20469,20470,\n20471,20472,20473,20474,20475,20476,20477,20478,20479,20480,20481,20482,\n20483,20484,20485,20486,20487,20488,20489,20490,20491,20492,20493,20494,\n20495,20496,20497,20498,20499,20500,20501,20502,20503,20504,20505,20506,\n20507,20508,20509,20510,20511,20512,20513,20514,20515,20516,20517,20518,\n20519,20520,20521,20522,20523,20524,20525,20526,20527,20528,20529,20530,\n20531,20532,20533,20534,20535,20536,20537,20538,20539,20540,20541,20542,\n20543,20544,20545,20546,20547,20548,20549,20550,20551,20552,20553,20554,\n20555,20556,20557,20558,20559,20560,20561,20562,20563,20564,20565,20566,\n20567,20568,20569,20570,20571,20572,20573,20574,20575,20576,20577,20578,\n20579,20580,20581,20582,20583,20584,20585,20586,20587,20588,20589,20590,\n20591,20592,20593,20594,20595,20596,20597,20598,20599,20600,20601,20602,\n20603,20604,20605,20606,20607,20608,20609,20610,20611,20612,20613,20614,\n20615,20616,20617,20618,20619,20620,20621,20622,20623,20624,20625,20626,\n20627,20628,20629,20630,20631,20632,20633,20634,20635,20636,20637,20638,\n20639,20640,20641,20642,20643,20644,20645,20646,20647,20648,20649,20650,\n20651,20652,20653,20654,20655,20656,20657,20658,20659,20660,20661,20662,\n20663,20664,20665,20666,20667,20668,20669,20670,20671,20672,20673,20674,\n20675,20676,20677,20678,20679,20680,20681,20682,20683,20684,20685,20686,\n20687,20688,20689,20690,20691,20692,20693,20694,20695,20696,20697,20698,\n20699,20700,20701,20702,20703,20704,20705,20706,20707,20708,20709,20710,\n20711,20712,20713,20714,20715,20716,20717,20718,20719,20720,20721,20722,\n20723,20724,20725,20726,20727,20728,20729,20730,20731,20732,20733,20734,\n20735,20736,20737,20738,20739,20740,20741,20742,20743,20744,20745,20746,\n20747,20748,20749,20750,20751,20752,20753,20754,20755,20756,20757,20758,\n20759,20760,20761,20762,20763,20764,20765,20766,20767,20768,20769,20770,\n20771,20772,20773,20774,20775,20776,20777,20778,20779,20780,20781,20782,\n20783,20784,20785,20786,20787,20788,20789,20790,20791,20792,20793,20794,\n20795,20796,20797,20798,20799,20800,20801,20802,20803,20804,20805,20806,\n20807,20808,20809,20810,20811,20812,20813,20814,20815,20816,20817,20818,\n20819,20820,20821,20822,20823,20824,20825,20826,20827,20828,20829,20830,\n20831,20832,20833,20834,20835,20836,20837,20838,20839,20840,20841,20842,\n20843,20844,20845,20846,20847,20848,20849,20850,20851,20852,20853,20854,\n20855,20856,20857,20858,20859,20860,20861,20862,20863,20864,20865,20866,\n20867,20868,20869,20870,20871,20872,20873,20874,20875,20876,20877,20878,\n20879,20880,20881,20882,20883,20884,20885,20886,20887,20888,20889,20890,\n20891,20892,20893,20894,20895,20896,20897,20898,20899,20900,20901,20902,\n20903,20904,20905,20906,20907,20908,20909,20910,20911,20912,20913,20914,\n20915,20916,20917,20918,20919,20920,20921,20922,20923,20924,20925,20926,\n20927,20928,20929,20930,20931,20932,20933,20934,20935,20936,20937,20938,\n20939,20940,20941,20942,20943,20944,20945,20946,20947,20948,20949,20950,\n20951,20952,20953,20954,20955,20956,20957,20958,20959,20960,20961,20962,\n20963,20964,20965,20966,20967,20968,20969,20970,20971,20972,20973,20974,\n20975,20976,20977,20978,20979,20980,20981,20982,20983,20984,20985,20986,\n20987,20988,20989,20990,20991,20992,20993,20994,20995,20996,20997,20998,\n20999,21000,21001,21002,21003,21004,21005,21006,21007,21008,21009,21010,\n21011,21012,21013,21014,21015,21016,21017,21018,21019,21020,21021,21022,\n21023,21024,21025,21026,21027,21028,21029,21030,21031,21032,21033,21034,\n21035,21036,21037,21038,21039,21040,21041,21042,21043,21044,21045,21046,\n21047,21048,21049,21050,21051,21052,21053,21054,21055,21056,21057,21058,\n21059,21060,21061,21062,21063,21064,21065,21066,21067,21068,21069,21070,\n21071,21072,21073,21074,21075,21076,21077,21078,21079,21080,21081,21082,\n21083,21084,21085,21086,21087,21088,21089,21090,21091,21092,21093,21094,\n21095,21096,21097,21098,21099,21100,21101,21102,21103,21104,21105,21106,\n21107,21108,21109,21110,21111,21112,21113,21114,21115,21116,21117,21118,\n21119,21120,21121,21122,21123,21124,21125,21126,21127,21128,21129,21130,\n21131,21132,21133,21134,21135,21136,21137,21138,21139,21140,21141,21142,\n21143,21144,21145,21146,21147,21148,21149,21150,21151,21152,21153,21154,\n21155,21156,21157,21158,21159,21160,21161,21162,21163,21164,21165,21166,\n21167,21168,21169,21170,21171,21172,21173,21174,21175,21176,21177,21178,\n21179,21180,21181,21182,21183,21184,21185,21186,21187,21188,21189,21190,\n21191,21192,21193,21194,21195,21196,21197,21198,21199,21200,21201,21202,\n21203,21204,21205,21206,21207,21208,21209,21210,21211,21212,21213,21214,\n21215,21216,21217,21218,21219,21220,21221,21222,21223,21224,21225,21226,\n21227,21228,21229,21230,21231,21232,21233,21234,21235,21236,21237,21238,\n21239,21240,21241,21242,21243,21244,21245,21246,21247,21248,21249,21250,\n21251,21252,21253,21254,21255,21256,21257,21258,21259,21260,21261,21262,\n21263,21264,21265,21266,21267,21268,21269,21270,21271,21272,21273,21274,\n21275,21276,21277,21278,21279,21280,21281,21282,21283,21284,21285,21286,\n21287,21288,21289,21290,21291,21292,21293,21294,21295,21296,21297,21298,\n21299,21300,21301,21302,21303,21304,21305,21306,21307,21308,21309,21310,\n21311,21312,21313,21314,21315,21316,21317,21318,21319,21320,21321,21322,\n21323,21324,21325,21326,21327,21328,21329,21330,21331,21332,21333,21334,\n21335,21336,21337,21338,21339,21340,21341,21342,21343,21344,21345,21346,\n21347,21348,21349,21350,21351,21352,21353,21354,21355,21356,21357,21358,\n21359,21360,21361,21362,21363,21364,21365,21366,21367,21368,21369,21370,\n21371,21372,21373,21374,21375,21376,21377,21378,21379,21380,21381,21382,\n21383,21384,21385,21386,21387,21388,21389,21390,21391,21392,21393,21394,\n21395,21396,21397,21398,21399,21400,21401,21402,21403,21404,21405,21406,\n21407,21408,21409,21410,21411,21412,21413,21414,21415,21416,21417,21418,\n21419,21420,21421,21422,21423,21424,21425,21426,21427,21428,21429,21430,\n21431,21432,21433,21434,21435,21436,21437,21438,21439,21440,21441,21442,\n21443,21444,21445,21446,21447,21448,21449,21450,21451,21452,21453,21454,\n21455,21456,21457,21458,21459,21460,21461,21462,21463,21464,21465,21466,\n21467,21468,21469,21470,21471,21472,21473,21474,21475,21476,21477,21478,\n21479,21480,21481,21482,21483,21484,21485,21486,21487,21488,21489,21490,\n21491,21492,21493,21494,21495,21496,21497,21498,21499,21500,21501,21502,\n21503,21504,21505,21506,21507,21508,21509,21510,21511,21512,21513,21514,\n21515,21516,21517,21518,21519,21520,21521,21522,21523,21524,21525,21526,\n21527,21528,21529,21530,21531,21532,21533,21534,21535,21536,21537,21538,\n21539,21540,21541,21542,21543,21544,21545,21546,21547,21548,21549,21550,\n21551,21552,21553,21554,21555,21556,21557,21558,21559,21560,21561,21562,\n21563,21564,21565,21566,21567,21568,21569,21570,21571,21572,21573,21574,\n21575,21576,21577,21578,21579,21580,21581,21582,21583,21584,21585,21586,\n21587,21588,21589,21590,21591,21592,21593,21594,21595,21596,21597,21598,\n21599,21600,21601,21602,21603,21604,21605,21606,21607,21608,21609,21610,\n21611,21612,21613,21614,21615,21616,21617,21618,21619,21620,21621,21622,\n21623,21624,21625,21626,21627,21628,21629,21630,21631,21632,21633,21634,\n21635,21636,21637,21638,21639,21640,21641,21642,21643,21644,21645,21646,\n21647,21648,21649,21650,21651,21652,21653,21654,21655,21656,21657,21658,\n21659,21660,21661,21662,21663,21664,21665,21666,21667,21668,21669,21670,\n21671,21672,21673,21674,21675,21676,21677,21678,21679,21680,21681,21682,\n21683,21684,21685,21686,21687,21688,21689,21690,21691,21692,21693,21694,\n21695,21696,21697,21698,21699,21700,21701,21702,21703,21704,21705,21706,\n21707,21708,21709,21710,21711,21712,21713,21714,21715,21716,21717,21718,\n21719,21720,21721,21722,21723,21724,21725,21726,21727,21728,21729,21730,\n21731,21732,21733,21734,21735,21736,21737,21738,21739,21740,21741,21742,\n21743,21744,21745,21746,21747,21748,21749,21750,21751,21752,21753,21754,\n21755,21756,21757,21758,21759,21760,21761,21762,21763,21764,21765,21766,\n21767,21768,21769,21770,21771,21772,21773,21774,21775,21776,21777,21778,\n21779,21780,21781,21782,21783,21784,21785,21786,21787,21788,21789,21790,\n21791,21792,21793,21794,21795,21796,21797,21798,21799,21800,21801,21802,\n21803,21804,21805,21806,21807,21808,21809,21810,21811,21812,21813,21814,\n21815,21816,21817,21818,21819,21820,21821,21822,21823,21824,21825,21826,\n21827,21828,21829,21830,21831,21832,21833,21834,21835,21836,21837,21838,\n21839,21840,21841,21842,21843,21844,21845,21846,21847,21848,21849,21850,\n21851,21852,21853,21854,21855,21856,21857,21858,21859,21860,21861,21862,\n21863,21864,21865,21866,21867,21868,21869,21870,21871,21872,21873,21874,\n21875,21876,21877,21878,21879,21880,21881,21882,21883,21884,21885,21886,\n21887,21888,21889,21890,21891,21892,21893,21894,21895,21896,21897,21898,\n21899,21900,21901,21902,21903,21904,21905,21906,21907,21908,21909,21910,\n21911,21912,21913,21914,21915,21916,21917,21918,21919,21920,21921,21922,\n21923,21924,21925,21926,21927,21928,21929,21930,21931,21932,21933,21934,\n21935,21936,21937,21938,21939,21940,21941,21942,21943,21944,21945,21946,\n21947,21948,21949,21950,21951,21952,21953,21954,21955,21956,21957,21958,\n21959,21960,21961,21962,21963,21964,21965,21966,21967,21968,21969,21970,\n21971,21972,21973,21974,21975,21976,21977,21978,21979,21980,21981,21982,\n21983,21984,21985,21986,21987,21988,21989,21990,21991,21992,21993,21994,\n21995,21996,21997,21998,21999,22000,22001,22002,22003,22004,22005,22006,\n22007,22008,22009,22010,22011,22012,22013,22014,22015,22016,22017,22018,\n22019,22020,22021,22022,22023,22024,22025,22026,22027,22028,22029,22030,\n22031,22032,22033,22034,22035,22036,22037,22038,22039,22040,22041,22042,\n22043,22044,22045,22046,22047,22048,22049,22050,22051,22052,22053,22054,\n22055,22056,22057,22058,22059,22060,22061,22062,22063,22064,22065,22066,\n22067,22068,22069,22070,22071,22072,22073,22074,22075,22076,22077,22078,\n22079,22080,22081,22082,22083,22084,22085,22086,22087,22088,22089,22090,\n22091,22092,22093,22094,22095,22096,22097,22098,22099,22100,22101,22102,\n22103,22104,22105,22106,22107,22108,22109,22110,22111,22112,22113,22114,\n22115,22116,22117,22118,22119,22120,22121,22122,22123,22124,22125,22126,\n22127,22128,22129,22130,22131,22132,22133,22134,22135,22136,22137,22138,\n22139,22140,22141,22142,22143,22144,22145,22146,22147,22148,22149,22150,\n22151,22152,22153,22154,22155,22156,22157,22158,22159,22160,22161,22162,\n22163,22164,22165,22166,22167,22168,22169,22170,22171,22172,22173,22174,\n22175,22176,22177,22178,22179,22180,22181,22182,22183,22184,22185,22186,\n22187,22188,22189,22190,22191,22192,22193,22194,22195,22196,22197,22198,\n22199,22200,22201,22202,22203,22204,22205,22206,22207,22208,22209,22210,\n22211,22212,22213,22214,22215,22216,22217,22218,22219,22220,22221,22222,\n22223,22224,22225,22226,22227,22228,22229,22230,22231,22232,22233,22234,\n22235,22236,22237,22238,22239,22240,22241,22242,22243,22244,22245,22246,\n22247,22248,22249,22250,22251,22252,22253,22254,22255,22256,22257,22258,\n22259,22260,22261,22262,22263,22264,22265,22266,22267,22268,22269,22270,\n22271,22272,22273,22274,22275,22276,22277,22278,22279,22280,22281,22282,\n22283,22284,22285,22286,22287,22288,22289,22290,22291,22292,22293,22294,\n22295,22296,22297,22298,22299,22300,22301,22302,22303,22304,22305,22306,\n22307,22308,22309,22310,22311,22312,22313,22314,22315,22316,22317,22318,\n22319,22320,22321,22322,22323,22324,22325,22326,22327,22328,22329,22330,\n22331,22332,22333,22334,22335,22336,22337,22338,22339,22340,22341,22342,\n22343,22344,22345,22346,22347,22348,22349,22350,22351,22352,22353,22354,\n22355,22356,22357,22358,22359,22360,22361,22362,22363,22364,22365,22366,\n22367,22368,22369,22370,22371,22372,22373,22374,22375,22376,22377,22378,\n22379,22380,22381,22382,22383,22384,22385,22386,22387,22388,22389,22390,\n22391,22392,22393,22394,22395,22396,22397,22398,22399,22400,22401,22402,\n22403,22404,22405,22406,22407,22408,22409,22410,22411,22412,22413,22414,\n22415,22416,22417,22418,22419,22420,22421,22422,22423,22424,22425,22426,\n22427,22428,22429,22430,22431,22432,22433,22434,22435,22436,22437,22438,\n22439,22440,22441,22442,22443,22444,22445,22446,22447,22448,22449,22450,\n22451,22452,22453,22454,22455,22456,22457,22458,22459,22460,22461,22462,\n22463,22464,22465,22466,22467,22468,22469,22470,22471,22472,22473,22474,\n22475,22476,22477,22478,22479,22480,22481,22482,22483,22484,22485,22486,\n22487,22488,22489,22490,22491,22492,22493,22494,22495,22496,22497,22498,\n22499,22500,22501,22502,22503,22504,22505,22506,22507,22508,22509,22510,\n22511,22512,22513,22514,22515,22516,22517,22518,22519,22520,22521,22522,\n22523,22524,22525,22526,22527,22528,22529,22530,22531,22532,22533,22534,\n22535,22536,22537,22538,22539,22540,22541,22542,22543,22544,22545,22546,\n22547,22548,22549,22550,22551,22552,22553,22554,22555,22556,22557,22558,\n22559,22560,22561,22562,22563,22564,22565,22566,22567,22568,22569,22570,\n22571,22572,22573,22574,22575,22576,22577,22578,22579,22580,22581,22582,\n22583,22584,22585,22586,22587,22588,22589,22590,22591,22592,22593,22594,\n22595,22596,22597,22598,22599,22600,22601,22602,22603,22604,22605,22606,\n22607,22608,22609,22610,22611,22612,22613,22614,22615,22616,22617,22618,\n22619,22620,22621,22622,22623,22624,22625,22626,22627,22628,22629,22630,\n22631,22632,22633,22634,22635,22636,22637,22638,22639,22640,22641,22642,\n22643,22644,22645,22646,22647,22648,22649,22650,22651,22652,22653,22654,\n22655,22656,22657,22658,22659,22660,22661,22662,22663,22664,22665,22666,\n22667,22668,22669,22670,22671,22672,22673,22674,22675,22676,22677,22678,\n22679,22680,22681,22682,22683,22684,22685,22686,22687,22688,22689,22690,\n22691,22692,22693,22694,22695,22696,22697,22698,22699,22700,22701,22702,\n22703,22704,22705,22706,22707,22708,22709,22710,22711,22712,22713,22714,\n22715,22716,22717,22718,22719,22720,22721,22722,22723,22724,22725,22726,\n22727,22728,22729,22730,22731,22732,22733,22734,22735,22736,22737,22738,\n22739,22740,22741,22742,22743,22744,22745,22746,22747,22748,22749,22750,\n22751,22752,22753,22754,22755,22756,22757,22758,22759,22760,22761,22762,\n22763,22764,22765,22766,22767,22768,22769,22770,22771,22772,22773,22774,\n22775,22776,22777,22778,22779,22780,22781,22782,22783,22784,22785,22786,\n22787,22788,22789,22790,22791,22792,22793,22794,22795,22796,22797,22798,\n22799,22800,22801,22802,22803,22804,22805,22806,22807,22808,22809,22810,\n22811,22812,22813,22814,22815,22816,22817,22818,22819,22820,22821,22822,\n22823,22824,22825,22826,22827,22828,22829,22830,22831,22832,22833,22834,\n22835,22836,22837,22838,22839,22840,22841,22842,22843,22844,22845,22846,\n22847,22848,22849,22850,22851,22852,22853,22854,22855,22856,22857,22858,\n22859,22860,22861,22862,22863,22864,22865,22866,22867,22868,22869,22870,\n22871,22872,22873,22874,22875,22876,22877,22878,22879,22880,22881,22882,\n22883,22884,22885,22886,22887,22888,22889,22890,22891,22892,22893,22894,\n22895,22896,22897,22898,22899,22900,22901,22902,22903,22904,22905,22906,\n22907,22908,22909,22910,22911,22912,22913,22914,22915,22916,22917,22918,\n22919,22920,22921,22922,22923,22924,22925,22926,22927,22928,22929,22930,\n22931,22932,22933,22934,22935,22936,22937,22938,22939,22940,22941,22942,\n22943,22944,22945,22946,22947,22948,22949,22950,22951,22952,22953,22954,\n22955,22956,22957,22958,22959,22960,22961,22962,22963,22964,22965,22966,\n22967,22968,22969,22970,22971,22972,22973,22974,22975,22976,22977,22978,\n22979,22980,22981,22982,22983,22984,22985,22986,22987,22988,22989,22990,\n22991,22992,22993,22994,22995,22996,22997,22998,22999,23000,23001,23002,\n23003,23004,23005,23006,23007,23008,23009,23010,23011,23012,23013,23014,\n23015,23016,23017,23018,23019,23020,23021,23022,23023,23024,23025,23026,\n23027,23028,23029,23030,23031,23032,23033,23034,23035,23036,23037,23038,\n23039,23040,23041,23042,23043,23044,23045,23046,23047,23048,23049,23050,\n23051,23052,23053,23054,23055,23056,23057,23058,23059,23060,23061,23062,\n23063,23064,23065,23066,23067,23068,23069,23070,23071,23072,23073,23074,\n23075,23076,23077,23078,23079,23080,23081,23082,23083,23084,23085,23086,\n23087,23088,23089,23090,23091,23092,23093,23094,23095,23096,23097,23098,\n23099,23100,23101,23102,23103,23104,23105,23106,23107,23108,23109,23110,\n23111,23112,23113,23114,23115,23116,23117,23118,23119,23120,23121,23122,\n23123,23124,23125,23126,23127,23128,23129,23130,23131,23132,23133,23134,\n23135,23136,23137,23138,23139,23140,23141,23142,23143,23144,23145,23146,\n23147,23148,23149,23150,23151,23152,23153,23154,23155,23156,23157,23158,\n23159,23160,23161,23162,23163,23164,23165,23166,23167,23168,23169,23170,\n23171,23172,23173,23174,23175,23176,23177,23178,23179,23180,23181,23182,\n23183,23184,23185,23186,23187,23188,23189,23190,23191,23192,23193,23194,\n23195,23196,23197,23198,23199,23200,23201,23202,23203,23204,23205,23206,\n23207,23208,23209,23210,23211,23212,23213,23214,23215,23216,23217,23218,\n23219,23220,23221,23222,23223,23224,23225,23226,23227,23228,23229,23230,\n23231,23232,23233,23234,23235,23236,23237,23238,23239,23240,23241,23242,\n23243,23244,23245,23246,23247,23248,23249,23250,23251,23252,23253,23254,\n23255,23256,23257,23258,23259,23260,23261,23262,23263,23264,23265,23266,\n23267,23268,23269,23270,23271,23272,23273,23274,23275,23276,23277,23278,\n23279,23280,23281,23282,23283,23284,23285,23286,23287,23288,23289,23290,\n23291,23292,23293,23294,23295,23296,23297,23298,23299,23300,23301,23302,\n23303,23304,23305,23306,23307,23308,23309,23310,23311,23312,23313,23314,\n23315,23316,23317,23318,23319,23320,23321,23322,23323,23324,23325,23326,\n23327,23328,23329,23330,23331,23332,23333,23334,23335,23336,23337,23338,\n23339,23340,23341,23342,23343,23344,23345,23346,23347,23348,23349,23350,\n23351,23352,23353,23354,23355,23356,23357,23358,23359,23360,23361,23362,\n23363,23364,23365,23366,23367,23368,23369,23370,23371,23372,23373,23374,\n23375,23376,23377,23378,23379,23380,23381,23382,23383,23384,23385,23386,\n23387,23388,23389,23390,23391,23392,23393,23394,23395,23396,23397,23398,\n23399,23400,23401,23402,23403,23404,23405,23406,23407,23408,23409,23410,\n23411,23412,23413,23414,23415,23416,23417,23418,23419,23420,23421,23422,\n23423,23424,23425,23426,23427,23428,23429,23430,23431,23432,23433,23434,\n23435,23436,23437,23438,23439,23440,23441,23442,23443,23444,23445,23446,\n23447,23448,23449,23450,23451,23452,23453,23454,23455,23456,23457,23458,\n23459,23460,23461,23462,23463,23464,23465,23466,23467,23468,23469,23470,\n23471,23472,23473,23474,23475,23476,23477,23478,23479,23480,23481,23482,\n23483,23484,23485,23486,23487,23488,23489,23490,23491,23492,23493,23494,\n23495,23496,23497,23498,23499,23500,23501,23502,23503,23504,23505,23506,\n23507,23508,23509,23510,23511,23512,23513,23514,23515,23516,23517,23518,\n23519,23520,23521,23522,23523,23524,23525,23526,23527,23528,23529,23530,\n23531,23532,23533,23534,23535,23536,23537,23538,23539,23540,23541,23542,\n23543,23544,23545,23546,23547,23548,23549,23550,23551,23552,23553,23554,\n23555,23556,23557,23558,23559,23560,23561,23562,23563,23564,23565,23566,\n23567,23568,23569,23570,23571,23572,23573,23574,23575,23576,23577,23578,\n23579,23580,23581,23582,23583,23584,23585,23586,23587,23588,23589,23590,\n23591,23592,23593,23594,23595,23596,23597,23598,23599,23600,23601,23602,\n23603,23604,23605,23606,23607,23608,23609,23610,23611,23612,23613,23614,\n23615,23616,23617,23618,23619,23620,23621,23622,23623,23624,23625,23626,\n23627,23628,23629,23630,23631,23632,23633,23634,23635,23636,23637,23638,\n23639,23640,23641,23642,23643,23644,23645,23646,23647,23648,23649,23650,\n23651,23652,23653,23654,23655,23656,23657,23658,23659,23660,23661,23662,\n23663,23664,23665,23666,23667,23668,23669,23670,23671,23672,23673,23674,\n23675,23676,23677,23678,23679,23680,23681,23682,23683,23684,23685,23686,\n23687,23688,23689,23690,23691,23692,23693,23694,23695,23696,23697,23698,\n23699,23700,23701,23702,23703,23704,23705,23706,23707,23708,23709,23710,\n23711,23712,23713,23714,23715,23716,23717,23718,23719,23720,23721,23722,\n23723,23724,23725,23726,23727,23728,23729,23730,23731,23732,23733,23734,\n23735,23736,23737,23738,23739,23740,23741,23742,23743,23744,23745,23746,\n23747,23748,23749,23750,23751,23752,23753,23754,23755,23756,23757,23758,\n23759,23760,23761,23762,23763,23764,23765,23766,23767,23768,23769,23770,\n23771,23772,23773,23774,23775,23776,23777,23778,23779,23780,23781,23782,\n23783,23784,23785,23786,23787,23788,23789,23790,23791,23792,23793,23794,\n23795,23796,23797,23798,23799,23800,23801,23802,23803,23804,23805,23806,\n23807,23808,23809,23810,23811,23812,23813,23814,23815,23816,23817,23818,\n23819,23820,23821,23822,23823,23824,23825,23826,23827,23828,23829,23830,\n23831,23832,23833,23834,23835,23836,23837,23838,23839,23840,23841,23842,\n23843,23844,23845,23846,23847,23848,23849,23850,23851,23852,23853,23854,\n23855,23856,23857,23858,23859,23860,23861,23862,23863,23864,23865,23866,\n23867,23868,23869,23870,23871,23872,23873,23874,23875,23876,23877,23878,\n23879,23880,23881,23882,23883,23884,23885,23886,23887,23888,23889,23890,\n23891,23892,23893,23894,23895,23896,23897,23898,23899,23900,23901,23902,\n23903,23904,23905,23906,23907,23908,23909,23910,23911,23912,23913,23914,\n23915,23916,23917,23918,23919,23920,23921,23922,23923,23924,23925,23926,\n23927,23928,23929,23930,23931,23932,23933,23934,23935,23936,23937,23938,\n23939,23940,23941,23942,23943,23944,23945,23946,23947,23948,23949,23950,\n23951,23952,23953,23954,23955,23956,23957,23958,23959,23960,23961,23962,\n23963,23964,23965,23966,23967,23968,23969,23970,23971,23972,23973,23974,\n23975,23976,23977,23978,23979,23980,23981,23982,23983,23984,23985,23986,\n23987,23988,23989,23990,23991,23992,23993,23994,23995,23996,23997,23998,\n23999,24000,24001,24002,24003,24004,24005,24006,24007,24008,24009,24010,\n24011,24012,24013,24014,24015,24016,24017,24018,24019,24020,24021,24022,\n24023,24024,24025,24026,24027,24028,24029,24030,24031,24032,24033,24034,\n24035,24036,24037,24038,24039,24040,24041,24042,24043,24044,24045,24046,\n24047,24048,24049,24050,24051,24052,24053,24054,24055,24056,24057,24058,\n24059,24060,24061,24062,24063,24064,24065,24066,24067,24068,24069,24070,\n24071,24072,24073,24074,24075,24076,24077,24078,24079,24080,24081,24082,\n24083,24084,24085,24086,24087,24088,24089,24090,24091,24092,24093,24094,\n24095,24096,24097,24098,24099,24100,24101,24102,24103,24104,24105,24106,\n24107,24108,24109,24110,24111,24112,24113,24114,24115,24116,24117,24118,\n24119,24120,24121,24122,24123,24124,24125,24126,24127,24128,24129,24130,\n24131,24132,24133,24134,24135,24136,24137,24138,24139,24140,24141,24142,\n24143,24144,24145,24146,24147,24148,24149,24150,24151,24152,24153,24154,\n24155,24156,24157,24158,24159,24160,24161,24162,24163,24164,24165,24166,\n24167,24168,24169,24170,24171,24172,24173,24174,24175,24176,24177,24178,\n24179,24180,24181,24182,24183,24184,24185,24186,24187,24188,24189,24190,\n24191,24192,24193,24194,24195,24196,24197,24198,24199,24200,24201,24202,\n24203,24204,24205,24206,24207,24208,24209,24210,24211,24212,24213,24214,\n24215,24216,24217,24218,24219,24220,24221,24222,24223,24224,24225,24226,\n24227,24228,24229,24230,24231,24232,24233,24234,24235,24236,24237,24238,\n24239,24240,24241,24242,24243,24244,24245,24246,24247,24248,24249,24250,\n24251,24252,24253,24254,24255,24256,24257,24258,24259,24260,24261,24262,\n24263,24264,24265,24266,24267,24268,24269,24270,24271,24272,24273,24274,\n24275,24276,24277,24278,24279,24280,24281,24282,24283,24284,24285,24286,\n24287,24288,24289,24290,24291,24292,24293,24294,24295,24296,24297,24298,\n24299,24300,24301,24302,24303,24304,24305,24306,24307,24308,24309,24310,\n24311,24312,24313,24314,24315,24316,24317,24318,24319,24320,24321,24322,\n24323,24324,24325,24326,24327,24328,24329,24330,24331,24332,24333,24334,\n24335,24336,24337,24338,24339,24340,24341,24342,24343,24344,24345,24346,\n24347,24348,24349,24350,24351,24352,24353,24354,24355,24356,24357,24358,\n24359,24360,24361,24362,24363,24364,24365,24366,24367,24368,24369,24370,\n24371,24372,24373,24374,24375,24376,24377,24378,24379,24380,24381,24382,\n24383,24384,24385,24386,24387,24388,24389,24390,24391,24392,24393,24394,\n24395,24396,24397,24398,24399,24400,24401,24402,24403,24404,24405,24406,\n24407,24408,24409,24410,24411,24412,24413,24414,24415,24416,24417,24418,\n24419,24420,24421,24422,24423,24424,24425,24426,24427,24428,24429,24430,\n24431,24432,24433,24434,24435,24436,24437,24438,24439,24440,24441,24442,\n24443,24444,24445,24446,24447,24448,24449,24450,24451,24452,24453,24454,\n24455,24456,24457,24458,24459,24460,24461,24462,24463,24464,24465,24466,\n24467,24468,24469,24470,24471,24472,24473,24474,24475,24476,24477,24478,\n24479,24480,24481,24482,24483,24484,24485,24486,24487,24488,24489,24490,\n24491,24492,24493,24494,24495,24496,24497,24498,24499,24500,24501,24502,\n24503,24504,24505,24506,24507,24508,24509,24510,24511,24512,24513,24514,\n24515,24516,24517,24518,24519,24520,24521,24522,24523,24524,24525,24526,\n24527,24528,24529,24530,24531,24532,24533,24534,24535,24536,24537,24538,\n24539,24540,24541,24542,24543,24544,24545,24546,24547,24548,24549,24550,\n24551,24552,24553,24554,24555,24556,24557,24558,24559,24560,24561,24562,\n24563,24564,24565,24566,24567,24568,24569,24570,24571,24572,24573,24574,\n24575,24576,24577,24578,24579,24580,24581,24582,24583,24584,24585,24586,\n24587,24588,24589,24590,24591,24592,24593,24594,24595,24596,24597,24598,\n24599,24600,24601,24602,24603,24604,24605,24606,24607,24608,24609,24610,\n24611,24612,24613,24614,24615,24616,24617,24618,24619,24620,24621,24622,\n24623,24624,24625,24626,24627,24628,24629,24630,24631,24632,24633,24634,\n24635,24636,24637,24638,24639,24640,24641,24642,24643,24644,24645,24646,\n24647,24648,24649,24650,24651,24652,24653,24654,24655,24656,24657,24658,\n24659,24660,24661,24662,24663,24664,24665,24666,24667,24668,24669,24670,\n24671,24672,24673,24674,24675,24676,24677,24678,24679,24680,24681,24682,\n24683,24684,24685,24686,24687,24688,24689,24690,24691,24692,24693,24694,\n24695,24696,24697,24698,24699,24700,24701,24702,24703,24704,24705,24706,\n24707,24708,24709,24710,24711,24712,24713,24714,24715,24716,24717,24718,\n24719,24720,24721,24722,24723,24724,24725,24726,24727,24728,24729,24730,\n24731,24732,24733,24734,24735,24736,24737,24738,24739,24740,24741,24742,\n24743,24744,24745,24746,24747,24748,24749,24750,24751,24752,24753,24754,\n24755,24756,24757,24758,24759,24760,24761,24762,24763,24764,24765,24766,\n24767,24768,24769,24770,24771,24772,24773,24774,24775,24776,24777,24778,\n24779,24780,24781,24782,24783,24784,24785,24786,24787,24788,24789,24790,\n24791,24792,24793,24794,24795,24796,24797,24798,24799,24800,24801,24802,\n24803,24804,24805,24806,24807,24808,24809,24810,24811,24812,24813,24814,\n24815,24816,24817,24818,24819,24820,24821,24822,24823,24824,24825,24826,\n24827,24828,24829,24830,24831,24832,24833,24834,24835,24836,24837,24838,\n24839,24840,24841,24842,24843,24844,24845,24846,24847,24848,24849,24850,\n24851,24852,24853,24854,24855,24856,24857,24858,24859,24860,24861,24862,\n24863,24864,24865,24866,24867,24868,24869,24870,24871,24872,24873,24874,\n24875,24876,24877,24878,24879,24880,24881,24882,24883,24884,24885,24886,\n24887,24888,24889,24890,24891,24892,24893,24894,24895,24896,24897,24898,\n24899,24900,24901,24902,24903,24904,24905,24906,24907,24908,24909,24910,\n24911,24912,24913,24914,24915,24916,24917,24918,24919,24920,24921,24922,\n24923,24924,24925,24926,24927,24928,24929,24930,24931,24932,24933,24934,\n24935,24936,24937,24938,24939,24940,24941,24942,24943,24944,24945,24946,\n24947,24948,24949,24950,24951,24952,24953,24954,24955,24956,24957,24958,\n24959,24960,24961,24962,24963,24964,24965,24966,24967,24968,24969,24970,\n24971,24972,24973,24974,24975,24976,24977,24978,24979,24980,24981,24982,\n24983,24984,24985,24986,24987,24988,24989,24990,24991,24992,24993,24994,\n24995,24996,24997,24998,24999,25000,25001,25002,25003,25004,25005,25006,\n25007,25008,25009,25010,25011,25012,25013,25014,25015,25016,25017,25018,\n25019,25020,25021,25022,25023,25024,25025,25026,25027,25028,25029,25030,\n25031,25032,25033,25034,25035,25036,25037,25038,25039,25040,25041,25042,\n25043,25044,25045,25046,25047,25048,25049,25050,25051,25052,25053,25054,\n25055,25056,25057,25058,25059,25060,25061,25062,25063,25064,25065,25066,\n25067,25068,25069,25070,25071,25072,25073,25074,25075,25076,25077,25078,\n25079,25080,25081,25082,25083,25084,25085,25086,25087,25088,25089,25090,\n25091,25092,25093,25094,25095,25096,25097,25098,25099,25100,25101,25102,\n25103,25104,25105,25106,25107,25108,25109,25110,25111,25112,25113,25114,\n25115,25116,25117,25118,25119,25120,25121,25122,25123,25124,25125,25126,\n25127,25128,25129,25130,25131,25132,25133,25134,25135,25136,25137,25138,\n25139,25140,25141,25142,25143,25144,25145,25146,25147,25148,25149,25150,\n25151,25152,25153,25154,25155,25156,25157,25158,25159,25160,25161,25162,\n25163,25164,25165,25166,25167,25168,25169,25170,25171,25172,25173,25174,\n25175,25176,25177,25178,25179,25180,25181,25182,25183,25184,25185,25186,\n25187,25188,25189,25190,25191,25192,25193,25194,25195,25196,25197,25198,\n25199,25200,25201,25202,25203,25204,25205,25206,25207,25208,25209,25210,\n25211,25212,25213,25214,25215,25216,25217,25218,25219,25220,25221,25222,\n25223,25224,25225,25226,25227,25228,25229,25230,25231,25232,25233,25234,\n25235,25236,25237,25238,25239,25240,25241,25242,25243,25244,25245,25246,\n25247,25248,25249,25250,25251,25252,25253,25254,25255,25256,25257,25258,\n25259,25260,25261,25262,25263,25264,25265,25266,25267,25268,25269,25270,\n25271,25272,25273,25274,25275,25276,25277,25278,25279,25280,25281,25282,\n25283,25284,25285,25286,25287,25288,25289,25290,25291,25292,25293,25294,\n25295,25296,25297,25298,25299,25300,25301,25302,25303,25304,25305,25306,\n25307,25308,25309,25310,25311,25312,25313,25314,25315,25316,25317,25318,\n25319,25320,25321,25322,25323,25324,25325,25326,25327,25328,25329,25330,\n25331,25332,25333,25334,25335,25336,25337,25338,25339,25340,25341,25342,\n25343,25344,25345,25346,25347,25348,25349,25350,25351,25352,25353,25354,\n25355,25356,25357,25358,25359,25360,25361,25362,25363,25364,25365,25366,\n25367,25368,25369,25370,25371,25372,25373,25374,25375,25376,25377,25378,\n25379,25380,25381,25382,25383,25384,25385,25386,25387,25388,25389,25390,\n25391,25392,25393,25394,25395,25396,25397,25398,25399,25400,25401,25402,\n25403,25404,25405,25406,25407,25408,25409,25410,25411,25412,25413,25414,\n25415,25416,25417,25418,25419,25420,25421,25422,25423,25424,25425,25426,\n25427,25428,25429,25430,25431,25432,25433,25434,25435,25436,25437,25438,\n25439,25440,25441,25442,25443,25444,25445,25446,25447,25448,25449,25450,\n25451,25452,25453,25454,25455,25456,25457,25458,25459,25460,25461,25462,\n25463,25464,25465,25466,25467,25468,25469,25470,25471,25472,25473,25474,\n25475,25476,25477,25478,25479,25480,25481,25482,25483,25484,25485,25486,\n25487,25488,25489,25490,25491,25492,25493,25494,25495,25496,25497,25498,\n25499,25500,25501,25502,25503,25504,25505,25506,25507,25508,25509,25510,\n25511,25512,25513,25514,25515,25516,25517,25518,25519,25520,25521,25522,\n25523,25524,25525,25526,25527,25528,25529,25530,25531,25532,25533,25534,\n25535,25536,25537,25538,25539,25540,25541,25542,25543,25544,25545,25546,\n25547,25548,25549,25550,25551,25552,25553,25554,25555,25556,25557,25558,\n25559,25560,25561,25562,25563,25564,25565,25566,25567,25568,25569,25570,\n25571,25572,25573,25574,25575,25576,25577,25578,25579,25580,25581,25582,\n25583,25584,25585,25586,25587,25588,25589,25590,25591,25592,25593,25594,\n25595,25596,25597,25598,25599,25600,25601,25602,25603,25604,25605,25606,\n25607,25608,25609,25610,25611,25612,25613,25614,25615,25616,25617,25618,\n25619,25620,25621,25622,25623,25624,25625,25626,25627,25628,25629,25630,\n25631,25632,25633,25634,25635,25636,25637,25638,25639,25640,25641,25642,\n25643,25644,25645,25646,25647,25648,25649,25650,25651,25652,25653,25654,\n25655,25656,25657,25658,25659,25660,25661,25662,25663,25664,25665,25666,\n25667,25668,25669,25670,25671,25672,25673,25674,25675,25676,25677,25678,\n25679,25680,25681,25682,25683,25684,25685,25686,25687,25688,25689,25690,\n25691,25692,25693,25694,25695,25696,25697,25698,25699,25700,25701,25702,\n25703,25704,25705,25706,25707,25708,25709,25710,25711,25712,25713,25714,\n25715,25716,25717,25718,25719,25720,25721,25722,25723,25724,25725,25726,\n25727,25728,25729,25730,25731,25732,25733,25734,25735,25736,25737,25738,\n25739,25740,25741,25742,25743,25744,25745,25746,25747,25748,25749,25750,\n25751,25752,25753,25754,25755,25756,25757,25758,25759,25760,25761,25762,\n25763,25764,25765,25766,25767,25768,25769,25770,25771,25772,25773,25774,\n25775,25776,25777,25778,25779,25780,25781,25782,25783,25784,25785,25786,\n25787,25788,25789,25790,25791,25792,25793,25794,25795,25796,25797,25798,\n25799,25800,25801,25802,25803,25804,25805,25806,25807,25808,25809,25810,\n25811,25812,25813,25814,25815,25816,25817,25818,25819,25820,25821,25822,\n25823,25824,25825,25826,25827,25828,25829,25830,25831,25832,25833,25834,\n25835,25836,25837,25838,25839,25840,25841,25842,25843,25844,25845,25846,\n25847,25848,25849,25850,25851,25852,25853,25854,25855,25856,25857,25858,\n25859,25860,25861,25862,25863,25864,25865,25866,25867,25868,25869,25870,\n25871,25872,25873,25874,25875,25876,25877,25878,25879,25880,25881,25882,\n25883,25884,25885,25886,25887,25888,25889,25890,25891,25892,25893,25894,\n25895,25896,25897,25898,25899,25900,25901,25902,25903,25904,25905,25906,\n25907,25908,25909,25910,25911,25912,25913,25914,25915,25916,25917,25918,\n25919,25920,25921,25922,25923,25924,25925,25926,25927,25928,25929,25930,\n25931,25932,25933,25934,25935,25936,25937,25938,25939,25940,25941,25942,\n25943,25944,25945,25946,25947,25948,25949,25950,25951,25952,25953,25954,\n25955,25956,25957,25958,25959,25960,25961,25962,25963,25964,25965,25966,\n25967,25968,25969,25970,25971,25972,25973,25974,25975,25976,25977,25978,\n25979,25980,25981,25982,25983,25984,25985,25986,25987,25988,25989,25990,\n25991,25992,25993,25994,25995,25996,25997,25998,25999,26000,26001,26002,\n26003,26004,26005,26006,26007,26008,26009,26010,26011,26012,26013,26014,\n26015,26016,26017,26018,26019,26020,26021,26022,26023,26024,26025,26026,\n26027,26028,26029,26030,26031,26032,26033,26034,26035,26036,26037,26038,\n26039,26040,26041,26042,26043,26044,26045,26046,26047,26048,26049,26050,\n26051,26052,26053,26054,26055,26056,26057,26058,26059,26060,26061,26062,\n26063,26064,26065,26066,26067,26068,26069,26070,26071,26072,26073,26074,\n26075,26076,26077,26078,26079,26080,26081,26082,26083,26084,26085,26086,\n26087,26088,26089,26090,26091,26092,26093,26094,26095,26096,26097,26098,\n26099,26100,26101,26102,26103,26104,26105,26106,26107,26108,26109,26110,\n26111,26112,26113,26114,26115,26116,26117,26118,26119,26120,26121,26122,\n26123,26124,26125,26126,26127,26128,26129,26130,26131,26132,26133,26134,\n26135,26136,26137,26138,26139,26140,26141,26142,26143,26144,26145,26146,\n26147,26148,26149,26150,26151,26152,26153,26154,26155,26156,26157,26158,\n26159,26160,26161,26162,26163,26164,26165,26166,26167,26168,26169,26170,\n26171,26172,26173,26174,26175,26176,26177,26178,26179,26180,26181,26182,\n26183,26184,26185,26186,26187,26188,26189,26190,26191,26192,26193,26194,\n26195,26196,26197,26198,26199,26200,26201,26202,26203,26204,26205,26206,\n26207,26208,26209,26210,26211,26212,26213,26214,26215,26216,26217,26218,\n26219,26220,26221,26222,26223,26224,26225,26226,26227,26228,26229,26230,\n26231,26232,26233,26234,26235,26236,26237,26238,26239,26240,26241,26242,\n26243,26244,26245,26246,26247,26248,26249,26250,26251,26252,26253,26254,\n26255,26256,26257,26258,26259,26260,26261,26262,26263,26264,26265,26266,\n26267,26268,26269,26270,26271,26272,26273,26274,26275,26276,26277,26278,\n26279,26280,26281,26282,26283,26284,26285,26286,26287,26288,26289,26290,\n26291,26292,26293,26294,26295,26296,26297,26298,26299,26300,26301,26302,\n26303,26304,26305,26306,26307,26308,26309,26310,26311,26312,26313,26314,\n26315,26316,26317,26318,26319,26320,26321,26322,26323,26324,26325,26326,\n26327,26328,26329,26330,26331,26332,26333,26334,26335,26336,26337,26338,\n26339,26340,26341,26342,26343,26344,26345,26346,26347,26348,26349,26350,\n26351,26352,26353,26354,26355,26356,26357,26358,26359,26360,26361,26362,\n26363,26364,26365,26366,26367,26368,26369,26370,26371,26372,26373,26374,\n26375,26376,26377,26378,26379,26380,26381,26382,26383,26384,26385,26386,\n26387,26388,26389,26390,26391,26392,26393,26394,26395,26396,26397,26398,\n26399,26400,26401,26402,26403,26404,26405,26406,26407,26408,26409,26410,\n26411,26412,26413,26414,26415,26416,26417,26418,26419,26420,26421,26422,\n26423,26424,26425,26426,26427,26428,26429,26430,26431,26432,26433,26434,\n26435,26436,26437,26438,26439,26440,26441,26442,26443,26444,26445,26446,\n26447,26448,26449,26450,26451,26452,26453,26454,26455,26456,26457,26458,\n26459,26460,26461,26462,26463,26464,26465,26466,26467,26468,26469,26470,\n26471,26472,26473,26474,26475,26476,26477,26478,26479,26480,26481,26482,\n26483,26484,26485,26486,26487,26488,26489,26490,26491,26492,26493,26494,\n26495,26496,26497,26498,26499,26500,26501,26502,26503,26504,26505,26506,\n26507,26508,26509,26510,26511,26512,26513,26514,26515,26516,26517,26518,\n26519,26520,26521,26522,26523,26524,26525,26526,26527,26528,26529,26530,\n26531,26532,26533,26534,26535,26536,26537,26538,26539,26540,26541,26542,\n26543,26544,26545,26546,26547,26548,26549,26550,26551,26552,26553,26554,\n26555,26556,26557,26558,26559,26560,26561,26562,26563,26564,26565,26566,\n26567,26568,26569,26570,26571,26572,26573,26574,26575,26576,26577,26578,\n26579,26580,26581,26582,26583,26584,26585,26586,26587,26588,26589,26590,\n26591,26592,26593,26594,26595,26596,26597,26598,26599,26600,26601,26602,\n26603,26604,26605,26606,26607,26608,26609,26610,26611,26612,26613,26614,\n26615,26616,26617,26618,26619,26620,26621,26622,26623,26624,26625,26626,\n26627,26628,26629,26630,26631,26632,26633,26634,26635,26636,26637,26638,\n26639,26640,26641,26642,26643,26644,26645,26646,26647,26648,26649,26650,\n26651,26652,26653,26654,26655,26656,26657,26658,26659,26660,26661,26662,\n26663,26664,26665,26666,26667,26668,26669,26670,26671,26672,26673,26674,\n26675,26676,26677,26678,26679,26680,26681,26682,26683,26684,26685,26686,\n26687,26688,26689,26690,26691,26692,26693,26694,26695,26696,26697,26698,\n26699,26700,26701,26702,26703,26704,26705,26706,26707,26708,26709,26710,\n26711,26712,26713,26714,26715,26716,26717,26718,26719,26720,26721,26722,\n26723,26724,26725,26726,26727,26728,26729,26730,26731,26732,26733,26734,\n26735,26736,26737,26738,26739,26740,26741,26742,26743,26744,26745,26746,\n26747,26748,26749,26750,26751,26752,26753,26754,26755,26756,26757,26758,\n26759,26760,26761,26762,26763,26764,26765,26766,26767,26768,26769,26770,\n26771,26772,26773,26774,26775,26776,26777,26778,26779,26780,26781,26782,\n26783,26784,26785,26786,26787,26788,26789,26790,26791,26792,26793,26794,\n26795,26796,26797,26798,26799,26800,26801,26802,26803,26804,26805,26806,\n26807,26808,26809,26810,26811,26812,26813,26814,26815,26816,26817,26818,\n26819,26820,26821,26822,26823,26824,26825,26826,26827,26828,26829,26830,\n26831,26832,26833,26834,26835,26836,26837,26838,26839,26840,26841,26842,\n26843,26844,26845,26846,26847,26848,26849,26850,26851,26852,26853,26854,\n26855,26856,26857,26858,26859,26860,26861,26862,26863,26864,26865,26866,\n26867,26868,26869,26870,26871,26872,26873,26874,26875,26876,26877,26878,\n26879,26880,26881,26882,26883,26884,26885,26886,26887,26888,26889,26890,\n26891,26892,26893,26894,26895,26896,26897,26898,26899,26900,26901,26902,\n26903,26904,26905,26906,26907,26908,26909,26910,26911,26912,26913,26914,\n26915,26916,26917,26918,26919,26920,26921,26922,26923,26924,26925,26926,\n26927,26928,26929,26930,26931,26932,26933,26934,26935,26936,26937,26938,\n26939,26940,26941,26942,26943,26944,26945,26946,26947,26948,26949,26950,\n26951,26952,26953,26954,26955,26956,26957,26958,26959,26960,26961,26962,\n26963,26964,26965,26966,26967,26968,26969,26970,26971,26972,26973,26974,\n26975,26976,26977,26978,26979,26980,26981,26982,26983,26984,26985,26986,\n26987,26988,26989,26990,26991,26992,26993,26994,26995,26996,26997,26998,\n26999,27000,27001,27002,27003,27004,27005,27006,27007,27008,27009,27010,\n27011,27012,27013,27014,27015,27016,27017,27018,27019,27020,27021,27022,\n27023,27024,27025,27026,27027,27028,27029,27030,27031,27032,27033,27034,\n27035,27036,27037,27038,27039,27040,27041,27042,27043,27044,27045,27046,\n27047,27048,27049,27050,27051,27052,27053,27054,27055,27056,27057,27058,\n27059,27060,27061,27062,27063,27064,27065,27066,27067,27068,27069,27070,\n27071,27072,27073,27074,27075,27076,27077,27078,27079,27080,27081,27082,\n27083,27084,27085,27086,27087,27088,27089,27090,27091,27092,27093,27094,\n27095,27096,27097,27098,27099,27100,27101,27102,27103,27104,27105,27106,\n27107,27108,27109,27110,27111,27112,27113,27114,27115,27116,27117,27118,\n27119,27120,27121,27122,27123,27124,27125,27126,27127,27128,27129,27130,\n27131,27132,27133,27134,27135,27136,27137,27138,27139,27140,27141,27142,\n27143,27144,27145,27146,27147,27148,27149,27150,27151,27152,27153,27154,\n27155,27156,27157,27158,27159,27160,27161,27162,27163,27164,27165,27166,\n27167,27168,27169,27170,27171,27172,27173,27174,27175,27176,27177,27178,\n27179,27180,27181,27182,27183,27184,27185,27186,27187,27188,27189,27190,\n27191,27192,27193,27194,27195,27196,27197,27198,27199,27200,27201,27202,\n27203,27204,27205,27206,27207,27208,27209,27210,27211,27212,27213,27214,\n27215,27216,27217,27218,27219,27220,27221,27222,27223,27224,27225,27226,\n27227,27228,27229,27230,27231,27232,27233,27234,27235,27236,27237,27238,\n27239,27240,27241,27242,27243,27244,27245,27246,27247,27248,27249,27250,\n27251,27252,27253,27254,27255,27256,27257,27258,27259,27260,27261,27262,\n27263,27264,27265,27266,27267,27268,27269,27270,27271,27272,27273,27274,\n27275,27276,27277,27278,27279,27280,27281,27282,27283,27284,27285,27286,\n27287,27288,27289,27290,27291,27292,27293,27294,27295,27296,27297,27298,\n27299,27300,27301,27302,27303,27304,27305,27306,27307,27308,27309,27310,\n27311,27312,27313,27314,27315,27316,27317,27318,27319,27320,27321,27322,\n27323,27324,27325,27326,27327,27328,27329,27330,27331,27332,27333,27334,\n27335,27336,27337,27338,27339,27340,27341,27342,27343,27344,27345,27346,\n27347,27348,27349,27350,27351,27352,27353,27354,27355,27356,27357,27358,\n27359,27360,27361,27362,27363,27364,27365,27366,27367,27368,27369,27370,\n27371,27372,27373,27374,27375,27376,27377,27378,27379,27380,27381,27382,\n27383,27384,27385,27386,27387,27388,27389,27390,27391,27392,27393,27394,\n27395,27396,27397,27398,27399,27400,27401,27402,27403,27404,27405,27406,\n27407,27408,27409,27410,27411,27412,27413,27414,27415,27416,27417,27418,\n27419,27420,27421,27422,27423,27424,27425,27426,27427,27428,27429,27430,\n27431,27432,27433,27434,27435,27436,27437,27438,27439,27440,27441,27442,\n27443,27444,27445,27446,27447,27448,27449,27450,27451,27452,27453,27454,\n27455,27456,27457,27458,27459,27460,27461,27462,27463,27464,27465,27466,\n27467,27468,27469,27470,27471,27472,27473,27474,27475,27476,27477,27478,\n27479,27480,27481,27482,27483,27484,27485,27486,27487,27488,27489,27490,\n27491,27492,27493,27494,27495,27496,27497,27498,27499,27500,27501,27502,\n27503,27504,27505,27506,27507,27508,27509,27510,27511,27512,27513,27514,\n27515,27516,27517,27518,27519,27520,27521,27522,27523,27524,27525,27526,\n27527,27528,27529,27530,27531,27532,27533,27534,27535,27536,27537,27538,\n27539,27540,27541,27542,27543,27544,27545,27546,27547,27548,27549,27550,\n27551,27552,27553,27554,27555,27556,27557,27558,27559,27560,27561,27562,\n27563,27564,27565,27566,27567,27568,27569,27570,27571,27572,27573,27574,\n27575,27576,27577,27578,27579,27580,27581,27582,27583,27584,27585,27586,\n27587,27588,27589,27590,27591,27592,27593,27594,27595,27596,27597,27598,\n27599,27600,27601,27602,27603,27604,27605,27606,27607,27608,27609,27610,\n27611,27612,27613,27614,27615,27616,27617,27618,27619,27620,27621,27622,\n27623,27624,27625,27626,27627,27628,27629,27630,27631,27632,27633,27634,\n27635,27636,27637,27638,27639,27640,27641,27642,27643,27644,27645,27646,\n27647,27648,27649,27650,27651,27652,27653,27654,27655,27656,27657,27658,\n27659,27660,27661,27662,27663,27664,27665,27666,27667,27668,27669,27670,\n27671,27672,27673,27674,27675,27676,27677,27678,27679,27680,27681,27682,\n27683,27684,27685,27686,27687,27688,27689,27690,27691,27692,27693,27694,\n27695,27696,27697,27698,27699,27700,27701,27702,27703,27704,27705,27706,\n27707,27708,27709,27710,27711,27712,27713,27714,27715,27716,27717,27718,\n27719,27720,27721,27722,27723,27724,27725,27726,27727,27728,27729,27730,\n27731,27732,27733,27734,27735,27736,27737,27738,27739,27740,27741,27742,\n27743,27744,27745,27746,27747,27748,27749,27750,27751,27752,27753,27754,\n27755,27756,27757,27758,27759,27760,27761,27762,27763,27764,27765,27766,\n27767,27768,27769,27770,27771,27772,27773,27774,27775,27776,27777,27778,\n27779,27780,27781,27782,27783,27784,27785,27786,27787,27788,27789,27790,\n27791,27792,27793,27794,27795,27796,27797,27798,27799,27800,27801,27802,\n27803,27804,27805,27806,27807,27808,27809,27810,27811,27812,27813,27814,\n27815,27816,27817,27818,27819,27820,27821,27822,27823,27824,27825,27826,\n27827,27828,27829,27830,27831,27832,27833,27834,27835,27836,27837,27838,\n27839,27840,27841,27842,27843,27844,27845,27846,27847,27848,27849,27850,\n27851,27852,27853,27854,27855,27856,27857,27858,27859,27860,27861,27862,\n27863,27864,27865,27866,27867,27868,27869,27870,27871,27872,27873,27874,\n27875,27876,27877,27878,27879,27880,27881,27882,27883,27884,27885,27886,\n27887,27888,27889,27890,27891,27892,27893,27894,27895,27896,27897,27898,\n27899,27900,27901,27902,27903,27904,27905,27906,27907,27908,27909,27910,\n27911,27912,27913,27914,27915,27916,27917,27918,27919,27920,27921,27922,\n27923,27924,27925,27926,27927,27928,27929,27930,27931,27932,27933,27934,\n27935,27936,27937,27938,27939,27940,27941,27942,27943,27944,27945,27946,\n27947,27948,27949,27950,27951,27952,27953,27954,27955,27956,27957,27958,\n27959,27960,27961,27962,27963,27964,27965,27966,27967,27968,27969,27970,\n27971,27972,27973,27974,27975,27976,27977,27978,27979,27980,27981,27982,\n27983,27984,27985,27986,27987,27988,27989,27990,27991,27992,27993,27994,\n27995,27996,27997,27998,27999,28000,28001,28002,28003,28004,28005,28006,\n28007,28008,28009,28010,28011,28012,28013,28014,28015,28016,28017,28018,\n28019,28020,28021,28022,28023,28024,28025,28026,28027,28028,28029,28030,\n28031,28032,28033,28034,28035,28036,28037,28038,28039,28040,28041,28042,\n28043,28044,28045,28046,28047,28048,28049,28050,28051,28052,28053,28054,\n28055,28056,28057,28058,28059,28060,28061,28062,28063,28064,28065,28066,\n28067,28068,28069,28070,28071,28072,28073,28074,28075,28076,28077,28078,\n28079,28080,28081,28082,28083,28084,28085,28086,28087,28088,28089,28090,\n28091,28092,28093,28094,28095,28096,28097,28098,28099,28100,28101,28102,\n28103,28104,28105,28106,28107,28108,28109,28110,28111,28112,28113,28114,\n28115,28116,28117,28118,28119,28120,28121,28122,28123,28124,28125,28126,\n28127,28128,28129,28130,28131,28132,28133,28134,28135,28136,28137,28138,\n28139,28140,28141,28142,28143,28144,28145,28146,28147,28148,28149,28150,\n28151,28152,28153,28154,28155,28156,28157,28158,28159,28160,28161,28162,\n28163,28164,28165,28166,28167,28168,28169,28170,28171,28172,28173,28174,\n28175,28176,28177,28178,28179,28180,28181,28182,28183,28184,28185,28186,\n28187,28188,28189,28190,28191,28192,28193,28194,28195,28196,28197,28198,\n28199,28200,28201,28202,28203,28204,28205,28206,28207,28208,28209,28210,\n28211,28212,28213,28214,28215,28216,28217,28218,28219,28220,28221,28222,\n28223,28224,28225,28226,28227,28228,28229,28230,28231,28232,28233,28234,\n28235,28236,28237,28238,28239,28240,28241,28242,28243,28244,28245,28246,\n28247,28248,28249,28250,28251,28252,28253,28254,28255,28256,28257,28258,\n28259,28260,28261,28262,28263,28264,28265,28266,28267,28268,28269,28270,\n28271,28272,28273,28274,28275,28276,28277,28278,28279,28280,28281,28282,\n28283,28284,28285,28286,28287,28288,28289,28290,28291,28292,28293,28294,\n28295,28296,28297,28298,28299,28300,28301,28302,28303,28304,28305,28306,\n28307,28308,28309,28310,28311,28312,28313,28314,28315,28316,28317,28318,\n28319,28320,28321,28322,28323,28324,28325,28326,28327,28328,28329,28330,\n28331,28332,28333,28334,28335,28336,28337,28338,28339,28340,28341,28342,\n28343,28344,28345,28346,28347,28348,28349,28350,28351,28352,28353,28354,\n28355,28356,28357,28358,28359,28360,28361,28362,28363,28364,28365,28366,\n28367,28368,28369,28370,28371,28372,28373,28374,28375,28376,28377,28378,\n28379,28380,28381,28382,28383,28384,28385,28386,28387,28388,28389,28390,\n28391,28392,28393,28394,28395,28396,28397,28398,28399,28400,28401,28402,\n28403,28404,28405,28406,28407,28408,28409,28410,28411,28412,28413,28414,\n28415,28416,28417,28418,28419,28420,28421,28422,28423,28424,28425,28426,\n28427,28428,28429,28430,28431,28432,28433,28434,28435,28436,28437,28438,\n28439,28440,28441,28442,28443,28444,28445,28446,28447,28448,28449,28450,\n28451,28452,28453,28454,28455,28456,28457,28458,28459,28460,28461,28462,\n28463,28464,28465,28466,28467,28468,28469,28470,28471,28472,28473,28474,\n28475,28476,28477,28478,28479,28480,28481,28482,28483,28484,28485,28486,\n28487,28488,28489,28490,28491,28492,28493,28494,28495,28496,28497,28498,\n28499,28500,28501,28502,28503,28504,28505,28506,28507,28508,28509,28510,\n28511,28512,28513,28514,28515,28516,28517,28518,28519,28520,28521,28522,\n28523,28524,28525,28526,28527,28528,28529,28530,28531,28532,28533,28534,\n28535,28536,28537,28538,28539,28540,28541,28542,28543,28544,28545,28546,\n28547,28548,28549,28550,28551,28552,28553,28554,28555,28556,28557,28558,\n28559,28560,28561,28562,28563,28564,28565,28566,28567,28568,28569,28570,\n28571,28572,28573,28574,28575,28576,28577,28578,28579,28580,28581,28582,\n28583,28584,28585,28586,28587,28588,28589,28590,28591,28592,28593,28594,\n28595,28596,28597,28598,28599,28600,28601,28602,28603,28604,28605,28606,\n28607,28608,28609,28610,28611,28612,28613,28614,28615,28616,28617,28618,\n28619,28620,28621,28622,28623,28624,28625,28626,28627,28628,28629,28630,\n28631,28632,28633,28634,28635,28636,28637,28638,28639,28640,28641,28642,\n28643,28644,28645,28646,28647,28648,28649,28650,28651,28652,28653,28654,\n28655,28656,28657,28658,28659,28660,28661,28662,28663,28664,28665,28666,\n28667,28668,28669,28670,28671,28672,28673,28674,28675,28676,28677,28678,\n28679,28680,28681,28682,28683,28684,28685,28686,28687,28688,28689,28690,\n28691,28692,28693,28694,28695,28696,28697,28698,28699,28700,28701,28702,\n28703,28704,28705,28706,28707,28708,28709,28710,28711,28712,28713,28714,\n28715,28716,28717,28718,28719,28720,28721,28722,28723,28724,28725,28726,\n28727,28728,28729,28730,28731,28732,28733,28734,28735,28736,28737,28738,\n28739,28740,28741,28742,28743,28744,28745,28746,28747,28748,28749,28750,\n28751,28752,28753,28754,28755,28756,28757,28758,28759,28760,28761,28762,\n28763,28764,28765,28766,28767,28768,28769,28770,28771,28772,28773,28774,\n28775,28776,28777,28778,28779,28780,28781,28782,28783,28784,28785,28786,\n28787,28788,28789,28790,28791,28792,28793,28794,28795,28796,28797,28798,\n28799,28800,28801,28802,28803,28804,28805,28806,28807,28808,28809,28810,\n28811,28812,28813,28814,28815,28816,28817,28818,28819,28820,28821,28822,\n28823,28824,28825,28826,28827,28828,28829,28830,28831,28832,28833,28834,\n28835,28836,28837,28838,28839,28840,28841,28842,28843,28844,28845,28846,\n28847,28848,28849,28850,28851,28852,28853,28854,28855,28856,28857,28858,\n28859,28860,28861,28862,28863,28864,28865,28866,28867,28868,28869,28870,\n28871,28872,28873,28874,28875,28876,28877,28878,28879,28880,28881,28882,\n28883,28884,28885,28886,28887,28888,28889,28890,28891,28892,28893,28894,\n28895,28896,28897,28898,28899,28900,28901,28902,28903,28904,28905,28906,\n28907,28908,28909,28910,28911,28912,28913,28914,28915,28916,28917,28918,\n28919,28920,28921,28922,28923,28924,28925,28926,28927,28928,28929,28930,\n28931,28932,28933,28934,28935,28936,28937,28938,28939,28940,28941,28942,\n28943,28944,28945,28946,28947,28948,28949,28950,28951,28952,28953,28954,\n28955,28956,28957,28958,28959,28960,28961,28962,28963,28964,28965,28966,\n28967,28968,28969,28970,28971,28972,28973,28974,28975,28976,28977,28978,\n28979,28980,28981,28982,28983,28984,28985,28986,28987,28988,28989,28990,\n28991,28992,28993,28994,28995,28996,28997,28998,28999,29000,29001,29002,\n29003,29004,29005,29006,29007,29008,29009,29010,29011,29012,29013,29014,\n29015,29016,29017,29018,29019,29020,29021,29022,29023,29024,29025,29026,\n29027,29028,29029,29030,29031,29032,29033,29034,29035,29036,29037,29038,\n29039,29040,29041,29042,29043,29044,29045,29046,29047,29048,29049,29050,\n29051,29052,29053,29054,29055,29056,29057,29058,29059,29060,29061,29062,\n29063,29064,29065,29066,29067,29068,29069,29070,29071,29072,29073,29074,\n29075,29076,29077,29078,29079,29080,29081,29082,29083,29084,29085,29086,\n29087,29088,29089,29090,29091,29092,29093,29094,29095,29096,29097,29098,\n29099,29100,29101,29102,29103,29104,29105,29106,29107,29108,29109,29110,\n29111,29112,29113,29114,29115,29116,29117,29118,29119,29120,29121,29122,\n29123,29124,29125,29126,29127,29128,29129,29130,29131,29132,29133,29134,\n29135,29136,29137,29138,29139,29140,29141,29142,29143,29144,29145,29146,\n29147,29148,29149,29150,29151,29152,29153,29154,29155,29156,29157,29158,\n29159,29160,29161,29162,29163,29164,29165,29166,29167,29168,29169,29170,\n29171,29172,29173,29174,29175,29176,29177,29178,29179,29180,29181,29182,\n29183,29184,29185,29186,29187,29188,29189,29190,29191,29192,29193,29194,\n29195,29196,29197,29198,29199,29200,29201,29202,29203,29204,29205,29206,\n29207,29208,29209,29210,29211,29212,29213,29214,29215,29216,29217,29218,\n29219,29220,29221,29222,29223,29224,29225,29226,29227,29228,29229,29230,\n29231,29232,29233,29234,29235,29236,29237,29238,29239,29240,29241,29242,\n29243,29244,29245,29246,29247,29248,29249,29250,29251,29252,29253,29254,\n29255,29256,29257,29258,29259,29260,29261,29262,29263,29264,29265,29266,\n29267,29268,29269,29270,29271,29272,29273,29274,29275,29276,29277,29278,\n29279,29280,29281,29282,29283,29284,29285,29286,29287,29288,29289,29290,\n29291,29292,29293,29294,29295,29296,29297,29298,29299,29300,29301,29302,\n29303,29304,29305,29306,29307,29308,29309,29310,29311,29312,29313,29314,\n29315,29316,29317,29318,29319,29320,29321,29322,29323,29324,29325,29326,\n29327,29328,29329,29330,29331,29332,29333,29334,29335,29336,29337,29338,\n29339,29340,29341,29342,29343,29344,29345,29346,29347,29348,29349,29350,\n29351,29352,29353,29354,29355,29356,29357,29358,29359,29360,29361,29362,\n29363,29364,29365,29366,29367,29368,29369,29370,29371,29372,29373,29374,\n29375,29376,29377,29378,29379,29380,29381,29382,29383,29384,29385,29386,\n29387,29388,29389,29390,29391,29392,29393,29394,29395,29396,29397,29398,\n29399,29400,29401,29402,29403,29404,29405,29406,29407,29408,29409,29410,\n29411,29412,29413,29414,29415,29416,29417,29418,29419,29420,29421,29422,\n29423,29424,29425,29426,29427,29428,29429,29430,29431,29432,29433,29434,\n29435,29436,29437,29438,29439,29440,29441,29442,29443,29444,29445,29446,\n29447,29448,29449,29450,29451,29452,29453,29454,29455,29456,29457,29458,\n29459,29460,29461,29462,29463,29464,29465,29466,29467,29468,29469,29470,\n29471,29472,29473,29474,29475,29476,29477,29478,29479,29480,29481,29482,\n29483,29484,29485,29486,29487,29488,29489,29490,29491,29492,29493,29494,\n29495,29496,29497,29498,29499,29500,29501,29502,29503,29504,29505,29506,\n29507,29508,29509,29510,29511,29512,29513,29514,29515,29516,29517,29518,\n29519,29520,29521,29522,29523,29524,29525,29526,29527,29528,29529,29530,\n29531,29532,29533,29534,29535,29536,29537,29538,29539,29540,29541,29542,\n29543,29544,29545,29546,29547,29548,29549,29550,29551,29552,29553,29554,\n29555,29556,29557,29558,29559,29560,29561,29562,29563,29564,29565,29566,\n29567,29568,29569,29570,29571,29572,29573,29574,29575,29576,29577,29578,\n29579,29580,29581,29582,29583,29584,29585,29586,29587,29588,29589,29590,\n29591,29592,29593,29594,29595,29596,29597,29598,29599,29600,29601,29602,\n29603,29604,29605,29606,29607,29608,29609,29610,29611,29612,29613,29614,\n29615,29616,29617,29618,29619,29620,29621,29622,29623,29624,29625,29626,\n29627,29628,29629,29630,29631,29632,29633,29634,29635,29636,29637,29638,\n29639,29640,29641,29642,29643,29644,29645,29646,29647,29648,29649,29650,\n29651,29652,29653,29654,29655,29656,29657,29658,29659,29660,29661,29662,\n29663,29664,29665,29666,29667,29668,29669,29670,29671,29672,29673,29674,\n29675,29676,29677,29678,29679,29680,29681,29682,29683,29684,29685,29686,\n29687,29688,29689,29690,29691,29692,29693,29694,29695,29696,29697,29698,\n29699,29700,29701,29702,29703,29704,29705,29706,29707,29708,29709,29710,\n29711,29712,29713,29714,29715,29716,29717,29718,29719,29720,29721,29722,\n29723,29724,29725,29726,29727,29728,29729,29730,29731,29732,29733,29734,\n29735,29736,29737,29738,29739,29740,29741,29742,29743,29744,29745,29746,\n29747,29748,29749,29750,29751,29752,29753,29754,29755,29756,29757,29758,\n29759,29760,29761,29762,29763,29764,29765,29766,29767,29768,29769,29770,\n29771,29772,29773,29774,29775,29776,29777,29778,29779,29780,29781,29782,\n29783,29784,29785,29786,29787,29788,29789,29790,29791,29792,29793,29794,\n29795,29796,29797,29798,29799,29800,29801,29802,29803,29804,29805,29806,\n29807,29808,29809,29810,29811,29812,29813,29814,29815,29816,29817,29818,\n29819,29820,29821,29822,29823,29824,29825,29826,29827,29828,29829,29830,\n29831,29832,29833,29834,29835,29836,29837,29838,29839,29840,29841,29842,\n29843,29844,29845,29846,29847,29848,29849,29850,29851,29852,29853,29854,\n29855,29856,29857,29858,29859,29860,29861,29862,29863,29864,29865,29866,\n29867,29868,29869,29870,29871,29872,29873,29874,29875,29876,29877,29878,\n29879,29880,29881,29882,29883,29884,29885,29886,29887,29888,29889,29890,\n29891,29892,29893,29894,29895,29896,29897,29898,29899,29900,29901,29902,\n29903,29904,29905,29906,29907,29908,29909,29910,29911,29912,29913,29914,\n29915,29916,29917,29918,29919,29920,29921,29922,29923,29924,29925,29926,\n29927,29928,29929,29930,29931,29932,29933,29934,29935,29936,29937,29938,\n29939,29940,29941,29942,29943,29944,29945,29946,29947,29948,29949,29950,\n29951,29952,29953,29954,29955,29956,29957,29958,29959,29960,29961,29962,\n29963,29964,29965,29966,29967,29968,29969,29970,29971,29972,29973,29974,\n29975,29976,29977,29978,29979,29980,29981,29982,29983,29984,29985,29986,\n29987,29988,29989,29990,29991,29992,29993,29994,29995,29996,29997,29998,\n29999,30000,30001,30002,30003,30004,30005,30006,30007,30008,30009,30010,\n30011,30012,30013,30014,30015,30016,30017,30018,30019,30020,30021,30022,\n30023,30024,30025,30026,30027,30028,30029,30030,30031,30032,30033,30034,\n30035,30036,30037,30038,30039,30040,30041,30042,30043,30044,30045,30046,\n30047,30048,30049,30050,30051,30052,30053,30054,30055,30056,30057,30058,\n30059,30060,30061,30062,30063,30064,30065,30066,30067,30068,30069,30070,\n30071,30072,30073,30074,30075,30076,30077,30078,30079,30080,30081,30082,\n30083,30084,30085,30086,30087,30088,30089,30090,30091,30092,30093,30094,\n30095,30096,30097,30098,30099,30100,30101,30102,30103,30104,30105,30106,\n30107,30108,30109,30110,30111,30112,30113,30114,30115,30116,30117,30118,\n30119,30120,30121,30122,30123,30124,30125,30126,30127,30128,30129,30130,\n30131,30132,30133,30134,30135,30136,30137,30138,30139,30140,30141,30142,\n30143,30144,30145,30146,30147,30148,30149,30150,30151,30152,30153,30154,\n30155,30156,30157,30158,30159,30160,30161,30162,30163,30164,30165,30166,\n30167,30168,30169,30170,30171,30172,30173,30174,30175,30176,30177,30178,\n30179,30180,30181,30182,30183,30184,30185,30186,30187,30188,30189,30190,\n30191,30192,30193,30194,30195,30196,30197,30198,30199,30200,30201,30202,\n30203,30204,30205,30206,30207,30208,30209,30210,30211,30212,30213,30214,\n30215,30216,30217,30218,30219,30220,30221,30222,30223,30224,30225,30226,\n30227,30228,30229,30230,30231,30232,30233,30234,30235,30236,30237,30238,\n30239,30240,30241,30242,30243,30244,30245,30246,30247,30248,30249,30250,\n30251,30252,30253,30254,30255,30256,30257,30258,30259,30260,30261,30262,\n30263,30264,30265,30266,30267,30268,30269,30270,30271,30272,30273,30274,\n30275,30276,30277,30278,30279,30280,30281,30282,30283,30284,30285,30286,\n30287,30288,30289,30290,30291,30292,30293,30294,30295,30296,30297,30298,\n30299,30300,30301,30302,30303,30304,30305,30306,30307,30308,30309,30310,\n30311,30312,30313,30314,30315,30316,30317,30318,30319,30320,30321,30322,\n30323,30324,30325,30326,30327,30328,30329,30330,30331,30332,30333,30334,\n30335,30336,30337,30338,30339,30340,30341,30342,30343,30344,30345,30346,\n30347,30348,30349,30350,30351,30352,30353,30354,30355,30356,30357,30358,\n30359,30360,30361,30362,30363,30364,30365,30366,30367,30368,30369,30370,\n30371,30372,30373,30374,30375,30376,30377,30378,30379,30380,30381,30382,\n30383,30384,30385,30386,30387,30388,30389,30390,30391,30392,30393,30394,\n30395,30396,30397,30398,30399,30400,30401,30402,30403,30404,30405,30406,\n30407,30408,30409,30410,30411,30412,30413,30414,30415,30416,30417,30418,\n30419,30420,30421,30422,30423,30424,30425,30426,30427,30428,30429,30430,\n30431,30432,30433,30434,30435,30436,30437,30438,30439,30440,30441,30442,\n30443,30444,30445,30446,30447,30448,30449,30450,30451,30452,30453,30454,\n30455,30456,30457,30458,30459,30460,30461,30462,30463,30464,30465,30466,\n30467,30468,30469,30470,30471,30472,30473,30474,30475,30476,30477,30478,\n30479,30480,30481,30482,30483,30484,30485,30486,30487,30488,30489,30490,\n30491,30492,30493,30494,30495,30496,30497,30498,30499,30500,30501,30502,\n30503,30504,30505,30506,30507,30508,30509,30510,30511,30512,30513,30514,\n30515,30516,30517,30518,30519,30520,30521,30522,30523,30524,30525,30526,\n30527,30528,30529,30530,30531,30532,30533,30534,30535,30536,30537,30538,\n30539,30540,30541,30542,30543,30544,30545,30546,30547,30548,30549,30550,\n30551,30552,30553,30554,30555,30556,30557,30558,30559,30560,30561,30562,\n30563,30564,30565,30566,30567,30568,30569,30570,30571,30572,30573,30574,\n30575,30576,30577,30578,30579,30580,30581,30582,30583,30584,30585,30586,\n30587,30588,30589,30590,30591,30592,30593,30594,30595,30596,30597,30598,\n30599,30600,30601,30602,30603,30604,30605,30606,30607,30608,30609,30610,\n30611,30612,30613,30614,30615,30616,30617,30618,30619,30620,30621,30622,\n30623,30624,30625,30626,30627,30628,30629,30630,30631,30632,30633,30634,\n30635,30636,30637,30638,30639,30640,30641,30642,30643,30644,30645,30646,\n30647,30648,30649,30650,30651,30652,30653,30654,30655,30656,30657,30658,\n30659,30660,30661,30662,30663,30664,30665,30666,30667,30668,30669,30670,\n30671,30672,30673,30674,30675,30676,30677,30678,30679,30680,30681,30682,\n30683,30684,30685,30686,30687,30688,30689,30690,30691,30692,30693,30694,\n30695,30696,30697,30698,30699,30700,30701,30702,30703,30704,30705,30706,\n30707,30708,30709,30710,30711,30712,30713,30714,30715,30716,30717,30718,\n30719,30720,30721,30722,30723,30724,30725,30726,30727,30728,30729,30730,\n30731,30732,30733,30734,30735,30736,30737,30738,30739,30740,30741,30742,\n30743,30744,30745,30746,30747,30748,30749,30750,30751,30752,30753,30754,\n30755,30756,30757,30758,30759,30760,30761,30762,30763,30764,30765,30766,\n30767,30768,30769,30770,30771,30772,30773,30774,30775,30776,30777,30778,\n30779,30780,30781,30782,30783,30784,30785,30786,30787,30788,30789,30790,\n30791,30792,30793,30794,30795,30796,30797,30798,30799,30800,30801,30802,\n30803,30804,30805,30806,30807,30808,30809,30810,30811,30812,30813,30814,\n30815,30816,30817,30818,30819,30820,30821,30822,30823,30824,30825,30826,\n30827,30828,30829,30830,30831,30832,30833,30834,30835,30836,30837,30838,\n30839,30840,30841,30842,30843,30844,30845,30846,30847,30848,30849,30850,\n30851,30852,30853,30854,30855,30856,30857,30858,30859,30860,30861,30862,\n30863,30864,30865,30866,30867,30868,30869,30870,30871,30872,30873,30874,\n30875,30876,30877,30878,30879,30880,30881,30882,30883,30884,30885,30886,\n30887,30888,30889,30890,30891,30892,30893,30894,30895,30896,30897,30898,\n30899,30900,30901,30902,30903,30904,30905,30906,30907,30908,30909,30910,\n30911,30912,30913,30914,30915,30916,30917,30918,30919,30920,30921,30922,\n30923,30924,30925,30926,30927,30928,30929,30930,30931,30932,30933,30934,\n30935,30936,30937,30938,30939,30940,30941,30942,30943,30944,30945,30946,\n30947,30948,30949,30950,30951,30952,30953,30954,30955,30956,30957,30958,\n30959,30960,30961,30962,30963,30964,30965,30966,30967,30968,30969,30970,\n30971,30972,30973,30974,30975,30976,30977,30978,30979,30980,30981,30982,\n30983,30984,30985,30986,30987,30988,30989,30990,30991,30992,30993,30994,\n30995,30996,30997,30998,30999,31000,31001,31002,31003,31004,31005,31006,\n31007,31008,31009,31010,31011,31012,31013,31014,31015,31016,31017,31018,\n31019,31020,31021,31022,31023,31024,31025,31026,31027,31028,31029,31030,\n31031,31032,31033,31034,31035,31036,31037,31038,31039,31040,31041,31042,\n31043,31044,31045,31046,31047,31048,31049,31050,31051,31052,31053,31054,\n31055,31056,31057,31058,31059,31060,31061,31062,31063,31064,31065,31066,\n31067,31068,31069,31070,31071,31072,31073,31074,31075,31076,31077,31078,\n31079,31080,31081,31082,31083,31084,31085,31086,31087,31088,31089,31090,\n31091,31092,31093,31094,31095,31096,31097,31098,31099,31100,31101,31102,\n31103,31104,31105,31106,31107,31108,31109,31110,31111,31112,31113,31114,\n31115,31116,31117,31118,31119,31120,31121,31122,31123,31124,31125,31126,\n31127,31128,31129,31130,31131,31132,31133,31134,31135,31136,31137,31138,\n31139,31140,31141,31142,31143,31144,31145,31146,31147,31148,31149,31150,\n31151,31152,31153,31154,31155,31156,31157,31158,31159,31160,31161,31162,\n31163,31164,31165,31166,31167,31168,31169,31170,31171,31172,31173,31174,\n31175,31176,31177,31178,31179,31180,31181,31182,31183,31184,31185,31186,\n31187,31188,31189,31190,31191,31192,31193,31194,31195,31196,31197,31198,\n31199,31200,31201,31202,31203,31204,31205,31206,31207,31208,31209,31210,\n31211,31212,31213,31214,31215,31216,31217,31218,31219,31220,31221,31222,\n31223,31224,31225,31226,31227,31228,31229,31230,31231,31232,31233,31234,\n31235,31236,31237,31238,31239,31240,31241,31242,31243,31244,31245,31246,\n31247,31248,31249,31250,31251,31252,31253,31254,31255,31256,31257,31258,\n31259,31260,31261,31262,31263,31264,31265,31266,31267,31268,31269,31270,\n31271,31272,31273,31274,31275,31276,31277,31278,31279,31280,31281,31282,\n31283,31284,31285,31286,31287,31288,31289,31290,31291,31292,31293,31294,\n31295,31296,31297,31298,31299,31300,31301,31302,31303,31304,31305,31306,\n31307,31308,31309,31310,31311,31312,31313,31314,31315,31316,31317,31318,\n31319,31320,31321,31322,31323,31324,31325,31326,31327,31328,31329,31330,\n31331,31332,31333,31334,31335,31336,31337,31338,31339,31340,31341,31342,\n31343,31344,31345,31346,31347,31348,31349,31350,31351,31352,31353,31354,\n31355,31356,31357,31358,31359,31360,31361,31362,31363,31364,31365,31366,\n31367,31368,31369,31370,31371,31372,31373,31374,31375,31376,31377,31378,\n31379,31380,31381,31382,31383,31384,31385,31386,31387,31388,31389,31390,\n31391,31392,31393,31394,31395,31396,31397,31398,31399,31400,31401,31402,\n31403,31404,31405,31406,31407,31408,31409,31410,31411,31412,31413,31414,\n31415,31416,31417,31418,31419,31420,31421,31422,31423,31424,31425,31426,\n31427,31428,31429,31430,31431,31432,31433,31434,31435,31436,31437,31438,\n31439,31440,31441,31442,31443,31444,31445,31446,31447,31448,31449,31450,\n31451,31452,31453,31454,31455,31456,31457,31458,31459,31460,31461,31462,\n31463,31464,31465,31466,31467,31468,31469,31470,31471,31472,31473,31474,\n31475,31476,31477,31478,31479,31480,31481,31482,31483,31484,31485,31486,\n31487,31488,31489,31490,31491,31492,31493,31494,31495,31496,31497,31498,\n31499,31500,31501,31502,31503,31504,31505,31506,31507,31508,31509,31510,\n31511,31512,31513,31514,31515,31516,31517,31518,31519,31520,31521,31522,\n31523,31524,31525,31526,31527,31528,31529,31530,31531,31532,31533,31534,\n31535,31536,31537,31538,31539,31540,31541,31542,31543,31544,31545,31546,\n31547,31548,31549,31550,31551,31552,31553,31554,31555,31556,31557,31558,\n31559,31560,31561,31562,31563,31564,31565,31566,31567,31568,31569,31570,\n31571,31572,31573,31574,31575,31576,31577,31578,31579,31580,31581,31582,\n31583,31584,31585,31586,31587,31588,31589,31590,31591,31592,31593,31594,\n31595,31596,31597,31598,31599,31600,31601,31602,31603,31604,31605,31606,\n31607,31608,31609,31610,31611,31612,31613,31614,31615,31616,31617,31618,\n31619,31620,31621,31622,31623,31624,31625,31626,31627,31628,31629,31630,\n31631,31632,31633,31634,31635,31636,31637,31638,31639,31640,31641,31642,\n31643,31644,31645,31646,31647,31648,31649,31650,31651,31652,31653,31654,\n31655,31656,31657,31658,31659,31660,31661,31662,31663,31664,31665,31666,\n31667,31668,31669,31670,31671,31672,31673,31674,31675,31676,31677,31678,\n31679,31680,31681,31682,31683,31684,31685,31686,31687,31688,31689,31690,\n31691,31692,31693,31694,31695,31696,31697,31698,31699,31700,31701,31702,\n31703,31704,31705,31706,31707,31708,31709,31710,31711,31712,31713,31714,\n31715,31716,31717,31718,31719,31720,31721,31722,31723,31724,31725,31726,\n31727,31728,31729,31730,31731,31732,31733,31734,31735,31736,31737,31738,\n31739,31740,31741,31742,31743,31744,31745,31746,31747,31748,31749,31750,\n31751,31752,31753,31754,31755,31756,31757,31758,31759,31760,31761,31762,\n31763,31764,31765,31766,31767,31768,31769,31770,31771,31772,31773,31774,\n31775,31776,31777,31778,31779,31780,31781,31782,31783,31784,31785,31786,\n31787,31788,31789,31790,31791,31792,31793,31794,31795,31796,31797,31798,\n31799,31800,31801,31802,31803,31804,31805,31806,31807,31808,31809,31810,\n31811,31812,31813,31814,31815,31816,31817,31818,31819,31820,31821,31822,\n31823,31824,31825,31826,31827,31828,31829,31830,31831,31832,31833,31834,\n31835,31836,31837,31838,31839,31840,31841,31842,31843,31844,31845,31846,\n31847,31848,31849,31850,31851,31852,31853,31854,31855,31856,31857,31858,\n31859,31860,31861,31862,31863,31864,31865,31866,31867,31868,31869,31870,\n31871,31872,31873,31874,31875,31876,31877,31878,31879,31880,31881,31882,\n31883,31884,31885,31886,31887,31888,31889,31890,31891,31892,31893,31894,\n31895,31896,31897,31898,31899,31900,31901,31902,31903,31904,31905,31906,\n31907,31908,31909,31910,31911,31912,31913,31914,31915,31916,31917,31918,\n31919,31920,31921,31922,31923,31924,31925,31926,31927,31928,31929,31930,\n31931,31932,31933,31934,31935,31936,31937,31938,31939,31940,31941,31942,\n31943,31944,31945,31946,31947,31948,31949,31950,31951,31952,31953,31954,\n31955,31956,31957,31958,31959,31960,31961,31962,31963,31964,31965,31966,\n31967,31968,31969,31970,31971,31972,31973,31974,31975,31976,31977,31978,\n31979,31980,31981,31982,31983,31984,31985,31986,31987,31988,31989,31990,\n31991,31992,31993,31994,31995,31996,31997,31998,31999,32000,32001,32002,\n32003,32004,32005,32006,32007,32008,32009,32010,32011,32012,32013,32014,\n32015,32016,32017,32018,32019,32020,32021,32022,32023,32024,32025,32026,\n32027,32028,32029,32030,32031,32032,32033,32034,32035,32036,32037,32038,\n32039,32040,32041,32042,32043,32044,32045,32046,32047,32048,32049,32050,\n32051,32052,32053,32054,32055,32056,32057,32058,32059,32060,32061,32062,\n32063,32064,32065,32066,32067,32068,32069,32070,32071,32072,32073,32074,\n32075,32076,32077,32078,32079,32080,32081,32082,32083,32084,32085,32086,\n32087,32088,32089,32090,32091,32092,32093,32094,32095,32096,32097,32098,\n32099,32100,32101,32102,32103,32104,32105,32106,32107,32108,32109,32110,\n32111,32112,32113,32114,32115,32116,32117,32118,32119,32120,32121,32122,\n32123,32124,32125,32126,32127,32128,32129,32130,32131,32132,32133,32134,\n32135,32136,32137,32138,32139,32140,32141,32142,32143,32144,32145,32146,\n32147,32148,32149,32150,32151,32152,32153,32154,32155,32156,32157,32158,\n32159,32160,32161,32162,32163,32164,32165,32166,32167,32168,32169,32170,\n32171,32172,32173,32174,32175,32176,32177,32178,32179,32180,32181,32182,\n32183,32184,32185,32186,32187,32188,32189,32190,32191,32192,32193,32194,\n32195,32196,32197,32198,32199,32200,32201,32202,32203,32204,32205,32206,\n32207,32208,32209,32210,32211,32212,32213,32214,32215,32216,32217,32218,\n32219,32220,32221,32222,32223,32224,32225,32226,32227,32228,32229,32230,\n32231,32232,32233,32234,32235,32236,32237,32238,32239,32240,32241,32242,\n32243,32244,32245,32246,32247,32248,32249,32250,32251,32252,32253,32254,\n32255,32256,32257,32258,32259,32260,32261,32262,32263,32264,32265,32266,\n32267,32268,32269,32270,32271,32272,32273,32274,32275,32276,32277,32278,\n32279,32280,32281,32282,32283,32284,32285,32286,32287,32288,32289,32290,\n32291,32292,32293,32294,32295,32296,32297,32298,32299,32300,32301,32302,\n32303,32304,32305,32306,32307,32308,32309,32310,32311,32312,32313,32314,\n32315,32316,32317,32318,32319,32320,32321,32322,32323,32324,32325,32326,\n32327,32328,32329,32330,32331,32332,32333,32334,32335,32336,32337,32338,\n32339,32340,32341,32342,32343,32344,32345,32346,32347,32348,32349,32350,\n32351,32352,32353,32354,32355,32356,32357,32358,32359,32360,32361,32362,\n32363,32364,32365,32366,32367,32368,32369,32370,32371,32372,32373,32374,\n32375,32376,32377,32378,32379,32380,32381,32382,32383,32384,32385,32386,\n32387,32388,32389,32390,32391,32392,32393,32394,32395,32396,32397,32398,\n32399,32400,32401,32402,32403,32404,32405,32406,32407,32408,32409,32410,\n32411,32412,32413,32414,32415,32416,32417,32418,32419,32420,32421,32422,\n32423,32424,32425,32426,32427,32428,32429,32430,32431,32432,32433,32434,\n32435,32436,32437,32438,32439,32440,32441,32442,32443,32444,32445,32446,\n32447,32448,32449,32450,32451,32452,32453,32454,32455,32456,32457,32458,\n32459,32460,32461,32462,32463,32464,32465,32466,32467,32468,32469,32470,\n32471,32472,32473,32474,32475,32476,32477,32478,32479,32480,32481,32482,\n32483,32484,32485,32486,32487,32488,32489,32490,32491,32492,32493,32494,\n32495,32496,32497,32498,32499,32500,32501,32502,32503,32504,32505,32506,\n32507,32508,32509,32510,32511,32512,32513,32514,32515,32516,32517,32518,\n32519,32520,32521,32522,32523,32524,32525,32526,32527,32528,32529,32530,\n32531,32532,32533,32534,32535,32536,32537,32538,32539,32540,32541,32542,\n32543,32544,32545,32546,32547,32548,32549,32550,32551,32552,32553,32554,\n32555,32556,32557,32558,32559,32560,32561,32562,32563,32564,32565,32566,\n32567,32568,32569,32570,32571,32572,32573,32574,32575,32576,32577,32578,\n32579,32580,32581,32582,32583,32584,32585,32586,32587,32588,32589,32590,\n32591,32592,32593,32594,32595,32596,32597,32598,32599,32600,32601,32602,\n32603,32604,32605,32606,32607,32608,32609,32610,32611,32612,32613,32614,\n32615,32616,32617,32618,32619,32620,32621,32622,32623,32624,32625,32626,\n32627,32628,32629,32630,32631,32632,32633,32634,32635,32636,32637,32638,\n32639,32640,32641,32642,32643,32644,32645,32646,32647,32648,32649,32650,\n32651,32652,32653,32654,32655,32656,32657,32658,32659,32660,32661,32662,\n32663,32664,32665,32666,32667,32668,32669,32670,32671,32672,32673,32674,\n32675,32676,32677,32678,32679,32680,32681,32682,32683,32684,32685,32686,\n32687,32688,32689,32690,32691,32692,32693,32694,32695,32696,32697,32698,\n32699,32700,32701,32702,32703,32704,32705,32706,32707,32708,32709,32710,\n32711,32712,32713,32714,32715,32716,32717,32718,32719,32720,32721,32722,\n32723,32724,32725,32726,32727,32728,32729,32730,32731,32732,32733,32734,\n32735,32736,32737,32738,32739,32740,32741,32742,32743,32744,32745,32746,\n32747,32748,32749,32750,32751,32752,32753,32754,32755,32756,32757,32758,\n32759,32760,32761,32762,32763,32764,32765,32766,32767,32768L,32769L,32770L,\n32771L,32772L,32773L,32774L,32775L,32776L,32777L,32778L,32779L,32780L,\n32781L,32782L,32783L,32784L,32785L,32786L,32787L,32788L,32789L,32790L,\n32791L,32792L,32793L,32794L,32795L,32796L,32797L,32798L,32799L,32800L,\n32801L,32802L,32803L,32804L,32805L,32806L,32807L,32808L,32809L,32810L,\n32811L,32812L,32813L,32814L,32815L,32816L,32817L,32818L,32819L,32820L,\n32821L,32822L,32823L,32824L,32825L,32826L,32827L,32828L,32829L,32830L,\n32831L,32832L,32833L,32834L,32835L,32836L,32837L,32838L,32839L,32840L,\n32841L,32842L,32843L,32844L,32845L,32846L,32847L,32848L,32849L,32850L,\n32851L,32852L,32853L,32854L,32855L,32856L,32857L,32858L,32859L,32860L,\n32861L,32862L,32863L,32864L,32865L,32866L,32867L,32868L,32869L,32870L,\n32871L,32872L,32873L,32874L,32875L,32876L,32877L,32878L,32879L,32880L,\n32881L,32882L,32883L,32884L,32885L,32886L,32887L,32888L,32889L,32890L,\n32891L,32892L,32893L,32894L,32895L,32896L,32897L,32898L,32899L,32900L,\n32901L,32902L,32903L,32904L,32905L,32906L,32907L,32908L,32909L,32910L,\n32911L,32912L,32913L,32914L,32915L,32916L,32917L,32918L,32919L,32920L,\n32921L,32922L,32923L,32924L,32925L,32926L,32927L,32928L,32929L,32930L,\n32931L,32932L,32933L,32934L,32935L,32936L,32937L,32938L,32939L,32940L,\n32941L,32942L,32943L,32944L,32945L,32946L,32947L,32948L,32949L,32950L,\n32951L,32952L,32953L,32954L,32955L,32956L,32957L,32958L,32959L,32960L,\n32961L,32962L,32963L,32964L,32965L,32966L,32967L,32968L,32969L,32970L,\n32971L,32972L,32973L,32974L,32975L,32976L,32977L,32978L,32979L,32980L,\n32981L,32982L,32983L,32984L,32985L,32986L,32987L,32988L,32989L,32990L,\n32991L,32992L,32993L,32994L,32995L,32996L,32997L,32998L,32999L,33000L,\n33001L,33002L,33003L,33004L,33005L,33006L,33007L,33008L,33009L,33010L,\n33011L,33012L,33013L,33014L,33015L,33016L,33017L,33018L,33019L,33020L,\n33021L,33022L,33023L,33024L,33025L,33026L,33027L,33028L,33029L,33030L,\n33031L,33032L,33033L,33034L,33035L,33036L,33037L,33038L,33039L,33040L,\n33041L,33042L,33043L,33044L,33045L,33046L,33047L,33048L,33049L,33050L,\n33051L,33052L,33053L,33054L,33055L,33056L,33057L,33058L,33059L,33060L,\n33061L,33062L,33063L,33064L,33065L,33066L,33067L,33068L,33069L,33070L,\n33071L,33072L,33073L,33074L,33075L,33076L,33077L,33078L,33079L,33080L,\n33081L,33082L,33083L,33084L,33085L,33086L,33087L,33088L,33089L,33090L,\n33091L,33092L,33093L,33094L,33095L,33096L,33097L,33098L,33099L,33100L,\n33101L,33102L,33103L,33104L,33105L,33106L,33107L,33108L,33109L,33110L,\n33111L,33112L,33113L,33114L,33115L,33116L,33117L,33118L,33119L,33120L,\n33121L,33122L,33123L,33124L,33125L,33126L,33127L,33128L,33129L,33130L,\n33131L,33132L,33133L,33134L,33135L,33136L,33137L,33138L,33139L,33140L,\n33141L,33142L,33143L,33144L,33145L,33146L,33147L,33148L,33149L,33150L,\n33151L,33152L,33153L,33154L,33155L,33156L,33157L,33158L,33159L,33160L,\n33161L,33162L,33163L,33164L,33165L,33166L,33167L,33168L,33169L,33170L,\n33171L,33172L,33173L,33174L,33175L,33176L,33177L,33178L,33179L,33180L,\n33181L,33182L,33183L,33184L,33185L,33186L,33187L,33188L,33189L,33190L,\n33191L,33192L,33193L,33194L,33195L,33196L,33197L,33198L,33199L,33200L,\n33201L,33202L,33203L,33204L,33205L,33206L,33207L,33208L,33209L,33210L,\n33211L,33212L,33213L,33214L,33215L,33216L,33217L,33218L,33219L,33220L,\n33221L,33222L,33223L,33224L,33225L,33226L,33227L,33228L,33229L,33230L,\n33231L,33232L,33233L,33234L,33235L,33236L,33237L,33238L,33239L,33240L,\n33241L,33242L,33243L,33244L,33245L,33246L,33247L,33248L,33249L,33250L,\n33251L,33252L,33253L,33254L,33255L,33256L,33257L,33258L,33259L,33260L,\n33261L,33262L,33263L,33264L,33265L,33266L,33267L,33268L,33269L,33270L,\n33271L,33272L,33273L,33274L,33275L,33276L,33277L,33278L,33279L,33280L,\n33281L,33282L,33283L,33284L,33285L,33286L,33287L,33288L,33289L,33290L,\n33291L,33292L,33293L,33294L,33295L,33296L,33297L,33298L,33299L,33300L,\n33301L,33302L,33303L,33304L,33305L,33306L,33307L,33308L,33309L,33310L,\n33311L,33312L,33313L,33314L,33315L,33316L,33317L,33318L,33319L,33320L,\n33321L,33322L,33323L,33324L,33325L,33326L,33327L,33328L,33329L,33330L,\n33331L,33332L,33333L,33334L,33335L,33336L,33337L,33338L,33339L,33340L,\n33341L,33342L,33343L,33344L,33345L,33346L,33347L,33348L,33349L,33350L,\n33351L,33352L,33353L,33354L,33355L,33356L,33357L,33358L,33359L,33360L,\n33361L,33362L,33363L,33364L,33365L,33366L,33367L,33368L,33369L,33370L,\n33371L,33372L,33373L,33374L,33375L,33376L,33377L,33378L,33379L,33380L,\n33381L,33382L,33383L,33384L,33385L,33386L,33387L,33388L,33389L,33390L,\n33391L,33392L,33393L,33394L,33395L,33396L,33397L,33398L,33399L,33400L,\n33401L,33402L,33403L,33404L,33405L,33406L,33407L,33408L,33409L,33410L,\n33411L,33412L,33413L,33414L,33415L,33416L,33417L,33418L,33419L,33420L,\n33421L,33422L,33423L,33424L,33425L,33426L,33427L,33428L,33429L,33430L,\n33431L,33432L,33433L,33434L,33435L,33436L,33437L,33438L,33439L,33440L,\n33441L,33442L,33443L,33444L,33445L,33446L,33447L,33448L,33449L,33450L,\n33451L,33452L,33453L,33454L,33455L,33456L,33457L,33458L,33459L,33460L,\n33461L,33462L,33463L,33464L,33465L,33466L,33467L,33468L,33469L,33470L,\n33471L,33472L,33473L,33474L,33475L,33476L,33477L,33478L,33479L,33480L,\n33481L,33482L,33483L,33484L,33485L,33486L,33487L,33488L,33489L,33490L,\n33491L,33492L,33493L,33494L,33495L,33496L,33497L,33498L,33499L,33500L,\n33501L,33502L,33503L,33504L,33505L,33506L,33507L,33508L,33509L,33510L,\n33511L,33512L,33513L,33514L,33515L,33516L,33517L,33518L,33519L,33520L,\n33521L,33522L,33523L,33524L,33525L,33526L,33527L,33528L,33529L,33530L,\n33531L,33532L,33533L,33534L,33535L,33536L,33537L,33538L,33539L,33540L,\n33541L,33542L,33543L,33544L,33545L,33546L,33547L,33548L,33549L,33550L,\n33551L,33552L,33553L,33554L,33555L,33556L,33557L,33558L,33559L,33560L,\n33561L,33562L,33563L,33564L,33565L,33566L,33567L,33568L,33569L,33570L,\n33571L,33572L,33573L,33574L,33575L,33576L,33577L,33578L,33579L,33580L,\n33581L,33582L,33583L,33584L,33585L,33586L,33587L,33588L,33589L,33590L,\n33591L,33592L,33593L,33594L,33595L,33596L,33597L,33598L,33599L,33600L,\n33601L,33602L,33603L,33604L,33605L,33606L,33607L,33608L,33609L,33610L,\n33611L,33612L,33613L,33614L,33615L,33616L,33617L,33618L,33619L,33620L,\n33621L,33622L,33623L,33624L,33625L,33626L,33627L,33628L,33629L,33630L,\n33631L,33632L,33633L,33634L,33635L,33636L,33637L,33638L,33639L,33640L,\n33641L,33642L,33643L,33644L,33645L,33646L,33647L,33648L,33649L,33650L,\n33651L,33652L,33653L,33654L,33655L,33656L,33657L,33658L,33659L,33660L,\n33661L,33662L,33663L,33664L,33665L,33666L,33667L,33668L,33669L,33670L,\n33671L,33672L,33673L,33674L,33675L,33676L,33677L,33678L,33679L,33680L,\n33681L,33682L,33683L,33684L,33685L,33686L,33687L,33688L,33689L,33690L,\n33691L,33692L,33693L,33694L,33695L,33696L,33697L,33698L,33699L,33700L,\n33701L,33702L,33703L,33704L,33705L,33706L,33707L,33708L,33709L,33710L,\n33711L,33712L,33713L,33714L,33715L,33716L,33717L,33718L,33719L,33720L,\n33721L,33722L,33723L,33724L,33725L,33726L,33727L,33728L,33729L,33730L,\n33731L,33732L,33733L,33734L,33735L,33736L,33737L,33738L,33739L,33740L,\n33741L,33742L,33743L,33744L,33745L,33746L,33747L,33748L,33749L,33750L,\n33751L,33752L,33753L,33754L,33755L,33756L,33757L,33758L,33759L,33760L,\n33761L,33762L,33763L,33764L,33765L,33766L,33767L,33768L,33769L,33770L,\n33771L,33772L,33773L,33774L,33775L,33776L,33777L,33778L,33779L,33780L,\n33781L,33782L,33783L,33784L,33785L,33786L,33787L,33788L,33789L,33790L,\n33791L,33792L,33793L,33794L,33795L,33796L,33797L,33798L,33799L,33800L,\n33801L,33802L,33803L,33804L,33805L,33806L,33807L,33808L,33809L,33810L,\n33811L,33812L,33813L,33814L,33815L,33816L,33817L,33818L,33819L,33820L,\n33821L,33822L,33823L,33824L,33825L,33826L,33827L,33828L,33829L,33830L,\n33831L,33832L,33833L,33834L,33835L,33836L,33837L,33838L,33839L,33840L,\n33841L,33842L,33843L,33844L,33845L,33846L,33847L,33848L,33849L,33850L,\n33851L,33852L,33853L,33854L,33855L,33856L,33857L,33858L,33859L,33860L,\n33861L,33862L,33863L,33864L,33865L,33866L,33867L,33868L,33869L,33870L,\n33871L,33872L,33873L,33874L,33875L,33876L,33877L,33878L,33879L,33880L,\n33881L,33882L,33883L,33884L,33885L,33886L,33887L,33888L,33889L,33890L,\n33891L,33892L,33893L,33894L,33895L,33896L,33897L,33898L,33899L,33900L,\n33901L,33902L,33903L,33904L,33905L,33906L,33907L,33908L,33909L,33910L,\n33911L,33912L,33913L,33914L,33915L,33916L,33917L,33918L,33919L,33920L,\n33921L,33922L,33923L,33924L,33925L,33926L,33927L,33928L,33929L,33930L,\n33931L,33932L,33933L,33934L,33935L,33936L,33937L,33938L,33939L,33940L,\n33941L,33942L,33943L,33944L,33945L,33946L,33947L,33948L,33949L,33950L,\n33951L,33952L,33953L,33954L,33955L,33956L,33957L,33958L,33959L,33960L,\n33961L,33962L,33963L,33964L,33965L,33966L,33967L,33968L,33969L,33970L,\n33971L,33972L,33973L,33974L,33975L,33976L,33977L,33978L,33979L,33980L,\n33981L,33982L,33983L,33984L,33985L,33986L,33987L,33988L,33989L,33990L,\n33991L,33992L,33993L,33994L,33995L,33996L,33997L,33998L,33999L,34000L,\n34001L,34002L,34003L,34004L,34005L,34006L,34007L,34008L,34009L,34010L,\n34011L,34012L,34013L,34014L,34015L,34016L,34017L,34018L,34019L,34020L,\n34021L,34022L,34023L,34024L,34025L,34026L,34027L,34028L,34029L,34030L,\n34031L,34032L,34033L,34034L,34035L,34036L,34037L,34038L,34039L,34040L,\n34041L,34042L,34043L,34044L,34045L,34046L,34047L,34048L,34049L,34050L,\n34051L,34052L,34053L,34054L,34055L,34056L,34057L,34058L,34059L,34060L,\n34061L,34062L,34063L,34064L,34065L,34066L,34067L,34068L,34069L,34070L,\n34071L,34072L,34073L,34074L,34075L,34076L,34077L,34078L,34079L,34080L,\n34081L,34082L,34083L,34084L,34085L,34086L,34087L,34088L,34089L,34090L,\n34091L,34092L,34093L,34094L,34095L,34096L,34097L,34098L,34099L,34100L,\n34101L,34102L,34103L,34104L,34105L,34106L,34107L,34108L,34109L,34110L,\n34111L,34112L,34113L,34114L,34115L,34116L,34117L,34118L,34119L,34120L,\n34121L,34122L,34123L,34124L,34125L,34126L,34127L,34128L,34129L,34130L,\n34131L,34132L,34133L,34134L,34135L,34136L,34137L,34138L,34139L,34140L,\n34141L,34142L,34143L,34144L,34145L,34146L,34147L,34148L,34149L,34150L,\n34151L,34152L,34153L,34154L,34155L,34156L,34157L,34158L,34159L,34160L,\n34161L,34162L,34163L,34164L,34165L,34166L,34167L,34168L,34169L,34170L,\n34171L,34172L,34173L,34174L,34175L,34176L,34177L,34178L,34179L,34180L,\n34181L,34182L,34183L,34184L,34185L,34186L,34187L,34188L,34189L,34190L,\n34191L,34192L,34193L,34194L,34195L,34196L,34197L,34198L,34199L,34200L,\n34201L,34202L,34203L,34204L,34205L,34206L,34207L,34208L,34209L,34210L,\n34211L,34212L,34213L,34214L,34215L,34216L,34217L,34218L,34219L,34220L,\n34221L,34222L,34223L,34224L,34225L,34226L,34227L,34228L,34229L,34230L,\n34231L,34232L,34233L,34234L,34235L,34236L,34237L,34238L,34239L,34240L,\n34241L,34242L,34243L,34244L,34245L,34246L,34247L,34248L,34249L,34250L,\n34251L,34252L,34253L,34254L,34255L,34256L,34257L,34258L,34259L,34260L,\n34261L,34262L,34263L,34264L,34265L,34266L,34267L,34268L,34269L,34270L,\n34271L,34272L,34273L,34274L,34275L,34276L,34277L,34278L,34279L,34280L,\n34281L,34282L,34283L,34284L,34285L,34286L,34287L,34288L,34289L,34290L,\n34291L,34292L,34293L,34294L,34295L,34296L,34297L,34298L,34299L,34300L,\n34301L,34302L,34303L,34304L,34305L,34306L,34307L,34308L,34309L,34310L,\n34311L,34312L,34313L,34314L,34315L,34316L,34317L,34318L,34319L,34320L,\n34321L,34322L,34323L,34324L,34325L,34326L,34327L,34328L,34329L,34330L,\n34331L,34332L,34333L,34334L,34335L,34336L,34337L,34338L,34339L,34340L,\n34341L,34342L,34343L,34344L,34345L,34346L,34347L,34348L,34349L,34350L,\n34351L,34352L,34353L,34354L,34355L,34356L,34357L,34358L,34359L,34360L,\n34361L,34362L,34363L,34364L,34365L,34366L,34367L,34368L,34369L,34370L,\n34371L,34372L,34373L,34374L,34375L,34376L,34377L,34378L,34379L,34380L,\n34381L,34382L,34383L,34384L,34385L,34386L,34387L,34388L,34389L,34390L,\n34391L,34392L,34393L,34394L,34395L,34396L,34397L,34398L,34399L,34400L,\n34401L,34402L,34403L,34404L,34405L,34406L,34407L,34408L,34409L,34410L,\n34411L,34412L,34413L,34414L,34415L,34416L,34417L,34418L,34419L,34420L,\n34421L,34422L,34423L,34424L,34425L,34426L,34427L,34428L,34429L,34430L,\n34431L,34432L,34433L,34434L,34435L,34436L,34437L,34438L,34439L,34440L,\n34441L,34442L,34443L,34444L,34445L,34446L,34447L,34448L,34449L,34450L,\n34451L,34452L,34453L,34454L,34455L,34456L,34457L,34458L,34459L,34460L,\n34461L,34462L,34463L,34464L,34465L,34466L,34467L,34468L,34469L,34470L,\n34471L,34472L,34473L,34474L,34475L,34476L,34477L,34478L,34479L,34480L,\n34481L,34482L,34483L,34484L,34485L,34486L,34487L,34488L,34489L,34490L,\n34491L,34492L,34493L,34494L,34495L,34496L,34497L,34498L,34499L,34500L,\n34501L,34502L,34503L,34504L,34505L,34506L,34507L,34508L,34509L,34510L,\n34511L,34512L,34513L,34514L,34515L,34516L,34517L,34518L,34519L,34520L,\n34521L,34522L,34523L,34524L,34525L,34526L,34527L,34528L,34529L,34530L,\n34531L,34532L,34533L,34534L,34535L,34536L,34537L,34538L,34539L,34540L,\n34541L,34542L,34543L,34544L,34545L,34546L,34547L,34548L,34549L,34550L,\n34551L,34552L,34553L,34554L,34555L,34556L,34557L,34558L,34559L,34560L,\n34561L,34562L,34563L,34564L,34565L,34566L,34567L,34568L,34569L,34570L,\n34571L,34572L,34573L,34574L,34575L,34576L,34577L,34578L,34579L,34580L,\n34581L,34582L,34583L,34584L,34585L,34586L,34587L,34588L,34589L,34590L,\n34591L,34592L,34593L,34594L,34595L,34596L,34597L,34598L,34599L,34600L,\n34601L,34602L,34603L,34604L,34605L,34606L,34607L,34608L,34609L,34610L,\n34611L,34612L,34613L,34614L,34615L,34616L,34617L,34618L,34619L,34620L,\n34621L,34622L,34623L,34624L,34625L,34626L,34627L,34628L,34629L,34630L,\n34631L,34632L,34633L,34634L,34635L,34636L,34637L,34638L,34639L,34640L,\n34641L,34642L,34643L,34644L,34645L,34646L,34647L,34648L,34649L,34650L,\n34651L,34652L,34653L,34654L,34655L,34656L,34657L,34658L,34659L,34660L,\n34661L,34662L,34663L,34664L,34665L,34666L,34667L,34668L,34669L,34670L,\n34671L,34672L,34673L,34674L,34675L,34676L,34677L,34678L,34679L,34680L,\n34681L,34682L,34683L,34684L,34685L,34686L,34687L,34688L,34689L,34690L,\n34691L,34692L,34693L,34694L,34695L,34696L,34697L,34698L,34699L,34700L,\n34701L,34702L,34703L,34704L,34705L,34706L,34707L,34708L,34709L,34710L,\n34711L,34712L,34713L,34714L,34715L,34716L,34717L,34718L,34719L,34720L,\n34721L,34722L,34723L,34724L,34725L,34726L,34727L,34728L,34729L,34730L,\n34731L,34732L,34733L,34734L,34735L,34736L,34737L,34738L,34739L,34740L,\n34741L,34742L,34743L,34744L,34745L,34746L,34747L,34748L,34749L,34750L,\n34751L,34752L,34753L,34754L,34755L,34756L,34757L,34758L,34759L,34760L,\n34761L,34762L,34763L,34764L,34765L,34766L,34767L,34768L,34769L,34770L,\n34771L,34772L,34773L,34774L,34775L,34776L,34777L,34778L,34779L,34780L,\n34781L,34782L,34783L,34784L,34785L,34786L,34787L,34788L,34789L,34790L,\n34791L,34792L,34793L,34794L,34795L,34796L,34797L,34798L,34799L,34800L,\n34801L,34802L,34803L,34804L,34805L,34806L,34807L,34808L,34809L,34810L,\n34811L,34812L,34813L,34814L,34815L,34816L,34817L,34818L,34819L,34820L,\n34821L,34822L,34823L,34824L,34825L,34826L,34827L,34828L,34829L,34830L,\n34831L,34832L,34833L,34834L,34835L,34836L,34837L,34838L,34839L,34840L,\n34841L,34842L,34843L,34844L,34845L,34846L,34847L,34848L,34849L,34850L,\n34851L,34852L,34853L,34854L,34855L,34856L,34857L,34858L,34859L,34860L,\n34861L,34862L,34863L,34864L,34865L,34866L,34867L,34868L,34869L,34870L,\n34871L,34872L,34873L,34874L,34875L,34876L,34877L,34878L,34879L,34880L,\n34881L,34882L,34883L,34884L,34885L,34886L,34887L,34888L,34889L,34890L,\n34891L,34892L,34893L,34894L,34895L,34896L,34897L,34898L,34899L,34900L,\n34901L,34902L,34903L,34904L,34905L,34906L,34907L,34908L,34909L,34910L,\n34911L,34912L,34913L,34914L,34915L,34916L,34917L,34918L,34919L,34920L,\n34921L,34922L,34923L,34924L,34925L,34926L,34927L,34928L,34929L,34930L,\n34931L,34932L,34933L,34934L,34935L,34936L,34937L,34938L,34939L,34940L,\n34941L,34942L,34943L,34944L,34945L,34946L,34947L,34948L,34949L,34950L,\n34951L,34952L,34953L,34954L,34955L,34956L,34957L,34958L,34959L,34960L,\n34961L,34962L,34963L,34964L,34965L,34966L,34967L,34968L,34969L,34970L,\n34971L,34972L,34973L,34974L,34975L,34976L,34977L,34978L,34979L,34980L,\n34981L,34982L,34983L,34984L,34985L,34986L,34987L,34988L,34989L,34990L,\n34991L,34992L,34993L,34994L,34995L,34996L,34997L,34998L,34999L,35000L,\n35001L,35002L,35003L,35004L,35005L,35006L,35007L,35008L,35009L,35010L,\n35011L,35012L,35013L,35014L,35015L,35016L,35017L,35018L,35019L,35020L,\n35021L,35022L,35023L,35024L,35025L,35026L,35027L,35028L,35029L,35030L,\n35031L,35032L,35033L,35034L,35035L,35036L,35037L,35038L,35039L,35040L,\n35041L,35042L,35043L,35044L,35045L,35046L,35047L,35048L,35049L,35050L,\n35051L,35052L,35053L,35054L,35055L,35056L,35057L,35058L,35059L,35060L,\n35061L,35062L,35063L,35064L,35065L,35066L,35067L,35068L,35069L,35070L,\n35071L,35072L,35073L,35074L,35075L,35076L,35077L,35078L,35079L,35080L,\n35081L,35082L,35083L,35084L,35085L,35086L,35087L,35088L,35089L,35090L,\n35091L,35092L,35093L,35094L,35095L,35096L,35097L,35098L,35099L,35100L,\n35101L,35102L,35103L,35104L,35105L,35106L,35107L,35108L,35109L,35110L,\n35111L,35112L,35113L,35114L,35115L,35116L,35117L,35118L,35119L,35120L,\n35121L,35122L,35123L,35124L,35125L,35126L,35127L,35128L,35129L,35130L,\n35131L,35132L,35133L,35134L,35135L,35136L,35137L,35138L,35139L,35140L,\n35141L,35142L,35143L,35144L,35145L,35146L,35147L,35148L,35149L,35150L,\n35151L,35152L,35153L,35154L,35155L,35156L,35157L,35158L,35159L,35160L,\n35161L,35162L,35163L,35164L,35165L,35166L,35167L,35168L,35169L,35170L,\n35171L,35172L,35173L,35174L,35175L,35176L,35177L,35178L,35179L,35180L,\n35181L,35182L,35183L,35184L,35185L,35186L,35187L,35188L,35189L,35190L,\n35191L,35192L,35193L,35194L,35195L,35196L,35197L,35198L,35199L,35200L,\n35201L,35202L,35203L,35204L,35205L,35206L,35207L,35208L,35209L,35210L,\n35211L,35212L,35213L,35214L,35215L,35216L,35217L,35218L,35219L,35220L,\n35221L,35222L,35223L,35224L,35225L,35226L,35227L,35228L,35229L,35230L,\n35231L,35232L,35233L,35234L,35235L,35236L,35237L,35238L,35239L,35240L,\n35241L,35242L,35243L,35244L,35245L,35246L,35247L,35248L,35249L,35250L,\n35251L,35252L,35253L,35254L,35255L,35256L,35257L,35258L,35259L,35260L,\n35261L,35262L,35263L,35264L,35265L,35266L,35267L,35268L,35269L,35270L,\n35271L,35272L,35273L,35274L,35275L,35276L,35277L,35278L,35279L,35280L,\n35281L,35282L,35283L,35284L,35285L,35286L,35287L,35288L,35289L,35290L,\n35291L,35292L,35293L,35294L,35295L,35296L,35297L,35298L,35299L,35300L,\n35301L,35302L,35303L,35304L,35305L,35306L,35307L,35308L,35309L,35310L,\n35311L,35312L,35313L,35314L,35315L,35316L,35317L,35318L,35319L,35320L,\n35321L,35322L,35323L,35324L,35325L,35326L,35327L,35328L,35329L,35330L,\n35331L,35332L,35333L,35334L,35335L,35336L,35337L,35338L,35339L,35340L,\n35341L,35342L,35343L,35344L,35345L,35346L,35347L,35348L,35349L,35350L,\n35351L,35352L,35353L,35354L,35355L,35356L,35357L,35358L,35359L,35360L,\n35361L,35362L,35363L,35364L,35365L,35366L,35367L,35368L,35369L,35370L,\n35371L,35372L,35373L,35374L,35375L,35376L,35377L,35378L,35379L,35380L,\n35381L,35382L,35383L,35384L,35385L,35386L,35387L,35388L,35389L,35390L,\n35391L,35392L,35393L,35394L,35395L,35396L,35397L,35398L,35399L,35400L,\n35401L,35402L,35403L,35404L,35405L,35406L,35407L,35408L,35409L,35410L,\n35411L,35412L,35413L,35414L,35415L,35416L,35417L,35418L,35419L,35420L,\n35421L,35422L,35423L,35424L,35425L,35426L,35427L,35428L,35429L,35430L,\n35431L,35432L,35433L,35434L,35435L,35436L,35437L,35438L,35439L,35440L,\n35441L,35442L,35443L,35444L,35445L,35446L,35447L,35448L,35449L,35450L,\n35451L,35452L,35453L,35454L,35455L,35456L,35457L,35458L,35459L,35460L,\n35461L,35462L,35463L,35464L,35465L,35466L,35467L,35468L,35469L,35470L,\n35471L,35472L,35473L,35474L,35475L,35476L,35477L,35478L,35479L,35480L,\n35481L,35482L,35483L,35484L,35485L,35486L,35487L,35488L,35489L,35490L,\n35491L,35492L,35493L,35494L,35495L,35496L,35497L,35498L,35499L,35500L,\n35501L,35502L,35503L,35504L,35505L,35506L,35507L,35508L,35509L,35510L,\n35511L,35512L,35513L,35514L,35515L,35516L,35517L,35518L,35519L,35520L,\n35521L,35522L,35523L,35524L,35525L,35526L,35527L,35528L,35529L,35530L,\n35531L,35532L,35533L,35534L,35535L,35536L,35537L,35538L,35539L,35540L,\n35541L,35542L,35543L,35544L,35545L,35546L,35547L,35548L,35549L,35550L,\n35551L,35552L,35553L,35554L,35555L,35556L,35557L,35558L,35559L,35560L,\n35561L,35562L,35563L,35564L,35565L,35566L,35567L,35568L,35569L,35570L,\n35571L,35572L,35573L,35574L,35575L,35576L,35577L,35578L,35579L,35580L,\n35581L,35582L,35583L,35584L,35585L,35586L,35587L,35588L,35589L,35590L,\n35591L,35592L,35593L,35594L,35595L,35596L,35597L,35598L,35599L,35600L,\n35601L,35602L,35603L,35604L,35605L,35606L,35607L,35608L,35609L,35610L,\n35611L,35612L,35613L,35614L,35615L,35616L,35617L,35618L,35619L,35620L,\n35621L,35622L,35623L,35624L,35625L,35626L,35627L,35628L,35629L,35630L,\n35631L,35632L,35633L,35634L,35635L,35636L,35637L,35638L,35639L,35640L,\n35641L,35642L,35643L,35644L,35645L,35646L,35647L,35648L,35649L,35650L,\n35651L,35652L,35653L,35654L,35655L,35656L,35657L,35658L,35659L,35660L,\n35661L,35662L,35663L,35664L,35665L,35666L,35667L,35668L,35669L,35670L,\n35671L,35672L,35673L,35674L,35675L,35676L,35677L,35678L,35679L,35680L,\n35681L,35682L,35683L,35684L,35685L,35686L,35687L,35688L,35689L,35690L,\n35691L,35692L,35693L,35694L,35695L,35696L,35697L,35698L,35699L,35700L,\n35701L,35702L,35703L,35704L,35705L,35706L,35707L,35708L,35709L,35710L,\n35711L,35712L,35713L,35714L,35715L,35716L,35717L,35718L,35719L,35720L,\n35721L,35722L,35723L,35724L,35725L,35726L,35727L,35728L,35729L,35730L,\n35731L,35732L,35733L,35734L,35735L,35736L,35737L,35738L,35739L,35740L,\n35741L,35742L,35743L,35744L,35745L,35746L,35747L,35748L,35749L,35750L,\n35751L,35752L,35753L,35754L,35755L,35756L,35757L,35758L,35759L,35760L,\n35761L,35762L,35763L,35764L,35765L,35766L,35767L,35768L,35769L,35770L,\n35771L,35772L,35773L,35774L,35775L,35776L,35777L,35778L,35779L,35780L,\n35781L,35782L,35783L,35784L,35785L,35786L,35787L,35788L,35789L,35790L,\n35791L,35792L,35793L,35794L,35795L,35796L,35797L,35798L,35799L,35800L,\n35801L,35802L,35803L,35804L,35805L,35806L,35807L,35808L,35809L,35810L,\n35811L,35812L,35813L,35814L,35815L,35816L,35817L,35818L,35819L,35820L,\n35821L,35822L,35823L,35824L,35825L,35826L,35827L,35828L,35829L,35830L,\n35831L,35832L,35833L,35834L,35835L,35836L,35837L,35838L,35839L,35840L,\n35841L,35842L,35843L,35844L,35845L,35846L,35847L,35848L,35849L,35850L,\n35851L,35852L,35853L,35854L,35855L,35856L,35857L,35858L,35859L,35860L,\n35861L,35862L,35863L,35864L,35865L,35866L,35867L,35868L,35869L,35870L,\n35871L,35872L,35873L,35874L,35875L,35876L,35877L,35878L,35879L,35880L,\n35881L,35882L,35883L,35884L,35885L,35886L,35887L,35888L,35889L,35890L,\n35891L,35892L,35893L,35894L,35895L,35896L,35897L,35898L,35899L,35900L,\n35901L,35902L,35903L,35904L,35905L,35906L,35907L,35908L,35909L,35910L,\n35911L,35912L,35913L,35914L,35915L,35916L,35917L,35918L,35919L,35920L,\n35921L,35922L,35923L,35924L,35925L,35926L,35927L,35928L,35929L,35930L,\n35931L,35932L,35933L,35934L,35935L,35936L,35937L,35938L,35939L,35940L,\n35941L,35942L,35943L,35944L,35945L,35946L,35947L,35948L,35949L,35950L,\n35951L,35952L,35953L,35954L,35955L,35956L,35957L,35958L,35959L,35960L,\n35961L,35962L,35963L,35964L,35965L,35966L,35967L,35968L,35969L,35970L,\n35971L,35972L,35973L,35974L,35975L,35976L,35977L,35978L,35979L,35980L,\n35981L,35982L,35983L,35984L,35985L,35986L,35987L,35988L,35989L,35990L,\n35991L,35992L,35993L,35994L,35995L,35996L,35997L,35998L,35999L,36000L,\n36001L,36002L,36003L,36004L,36005L,36006L,36007L,36008L,36009L,36010L,\n36011L,36012L,36013L,36014L,36015L,36016L,36017L,36018L,36019L,36020L,\n36021L,36022L,36023L,36024L,36025L,36026L,36027L,36028L,36029L,36030L,\n36031L,36032L,36033L,36034L,36035L,36036L,36037L,36038L,36039L,36040L,\n36041L,36042L,36043L,36044L,36045L,36046L,36047L,36048L,36049L,36050L,\n36051L,36052L,36053L,36054L,36055L,36056L,36057L,36058L,36059L,36060L,\n36061L,36062L,36063L,36064L,36065L,36066L,36067L,36068L,36069L,36070L,\n36071L,36072L,36073L,36074L,36075L,36076L,36077L,36078L,36079L,36080L,\n36081L,36082L,36083L,36084L,36085L,36086L,36087L,36088L,36089L,36090L,\n36091L,36092L,36093L,36094L,36095L,36096L,36097L,36098L,36099L,36100L,\n36101L,36102L,36103L,36104L,36105L,36106L,36107L,36108L,36109L,36110L,\n36111L,36112L,36113L,36114L,36115L,36116L,36117L,36118L,36119L,36120L,\n36121L,36122L,36123L,36124L,36125L,36126L,36127L,36128L,36129L,36130L,\n36131L,36132L,36133L,36134L,36135L,36136L,36137L,36138L,36139L,36140L,\n36141L,36142L,36143L,36144L,36145L,36146L,36147L,36148L,36149L,36150L,\n36151L,36152L,36153L,36154L,36155L,36156L,36157L,36158L,36159L,36160L,\n36161L,36162L,36163L,36164L,36165L,36166L,36167L,36168L,36169L,36170L,\n36171L,36172L,36173L,36174L,36175L,36176L,36177L,36178L,36179L,36180L,\n36181L,36182L,36183L,36184L,36185L,36186L,36187L,36188L,36189L,36190L,\n36191L,36192L,36193L,36194L,36195L,36196L,36197L,36198L,36199L,36200L,\n36201L,36202L,36203L,36204L,36205L,36206L,36207L,36208L,36209L,36210L,\n36211L,36212L,36213L,36214L,36215L,36216L,36217L,36218L,36219L,36220L,\n36221L,36222L,36223L,36224L,36225L,36226L,36227L,36228L,36229L,36230L,\n36231L,36232L,36233L,36234L,36235L,36236L,36237L,36238L,36239L,36240L,\n36241L,36242L,36243L,36244L,36245L,36246L,36247L,36248L,36249L,36250L,\n36251L,36252L,36253L,36254L,36255L,36256L,36257L,36258L,36259L,36260L,\n36261L,36262L,36263L,36264L,36265L,36266L,36267L,36268L,36269L,36270L,\n36271L,36272L,36273L,36274L,36275L,36276L,36277L,36278L,36279L,36280L,\n36281L,36282L,36283L,36284L,36285L,36286L,36287L,36288L,36289L,36290L,\n36291L,36292L,36293L,36294L,36295L,36296L,36297L,36298L,36299L,36300L,\n36301L,36302L,36303L,36304L,36305L,36306L,36307L,36308L,36309L,36310L,\n36311L,36312L,36313L,36314L,36315L,36316L,36317L,36318L,36319L,36320L,\n36321L,36322L,36323L,36324L,36325L,36326L,36327L,36328L,36329L,36330L,\n36331L,36332L,36333L,36334L,36335L,36336L,36337L,36338L,36339L,36340L,\n36341L,36342L,36343L,36344L,36345L,36346L,36347L,36348L,36349L,36350L,\n36351L,36352L,36353L,36354L,36355L,36356L,36357L,36358L,36359L,36360L,\n36361L,36362L,36363L,36364L,36365L,36366L,36367L,36368L,36369L,36370L,\n36371L,36372L,36373L,36374L,36375L,36376L,36377L,36378L,36379L,36380L,\n36381L,36382L,36383L,36384L,36385L,36386L,36387L,36388L,36389L,36390L,\n36391L,36392L,36393L,36394L,36395L,36396L,36397L,36398L,36399L,36400L,\n36401L,36402L,36403L,36404L,36405L,36406L,36407L,36408L,36409L,36410L,\n36411L,36412L,36413L,36414L,36415L,36416L,36417L,36418L,36419L,36420L,\n36421L,36422L,36423L,36424L,36425L,36426L,36427L,36428L,36429L,36430L,\n36431L,36432L,36433L,36434L,36435L,36436L,36437L,36438L,36439L,36440L,\n36441L,36442L,36443L,36444L,36445L,36446L,36447L,36448L,36449L,36450L,\n36451L,36452L,36453L,36454L,36455L,36456L,36457L,36458L,36459L,36460L,\n36461L,36462L,36463L,36464L,36465L,36466L,36467L,36468L,36469L,36470L,\n36471L,36472L,36473L,36474L,36475L,36476L,36477L,36478L,36479L,36480L,\n36481L,36482L,36483L,36484L,36485L,36486L,36487L,36488L,36489L,36490L,\n36491L,36492L,36493L,36494L,36495L,36496L,36497L,36498L,36499L,36500L,\n36501L,36502L,36503L,36504L,36505L,36506L,36507L,36508L,36509L,36510L,\n36511L,36512L,36513L,36514L,36515L,36516L,36517L,36518L,36519L,36520L,\n36521L,36522L,36523L,36524L,36525L,36526L,36527L,36528L,36529L,36530L,\n36531L,36532L,36533L,36534L,36535L,36536L,36537L,36538L,36539L,36540L,\n36541L,36542L,36543L,36544L,36545L,36546L,36547L,36548L,36549L,36550L,\n36551L,36552L,36553L,36554L,36555L,36556L,36557L,36558L,36559L,36560L,\n36561L,36562L,36563L,36564L,36565L,36566L,36567L,36568L,36569L,36570L,\n36571L,36572L,36573L,36574L,36575L,36576L,36577L,36578L,36579L,36580L,\n36581L,36582L,36583L,36584L,36585L,36586L,36587L,36588L,36589L,36590L,\n36591L,36592L,36593L,36594L,36595L,36596L,36597L,36598L,36599L,36600L,\n36601L,36602L,36603L,36604L,36605L,36606L,36607L,36608L,36609L,36610L,\n36611L,36612L,36613L,36614L,36615L,36616L,36617L,36618L,36619L,36620L,\n36621L,36622L,36623L,36624L,36625L,36626L,36627L,36628L,36629L,36630L,\n36631L,36632L,36633L,36634L,36635L,36636L,36637L,36638L,36639L,36640L,\n36641L,36642L,36643L,36644L,36645L,36646L,36647L,36648L,36649L,36650L,\n36651L,36652L,36653L,36654L,36655L,36656L,36657L,36658L,36659L,36660L,\n36661L,36662L,36663L,36664L,36665L,36666L,36667L,36668L,36669L,36670L,\n36671L,36672L,36673L,36674L,36675L,36676L,36677L,36678L,36679L,36680L,\n36681L,36682L,36683L,36684L,36685L,36686L,36687L,36688L,36689L,36690L,\n36691L,36692L,36693L,36694L,36695L,36696L,36697L,36698L,36699L,36700L,\n36701L,36702L,36703L,36704L,36705L,36706L,36707L,36708L,36709L,36710L,\n36711L,36712L,36713L,36714L,36715L,36716L,36717L,36718L,36719L,36720L,\n36721L,36722L,36723L,36724L,36725L,36726L,36727L,36728L,36729L,36730L,\n36731L,36732L,36733L,36734L,36735L,36736L,36737L,36738L,36739L,36740L,\n36741L,36742L,36743L,36744L,36745L,36746L,36747L,36748L,36749L,36750L,\n36751L,36752L,36753L,36754L,36755L,36756L,36757L,36758L,36759L,36760L,\n36761L,36762L,36763L,36764L,36765L,36766L,36767L,36768L,36769L,36770L,\n36771L,36772L,36773L,36774L,36775L,36776L,36777L,36778L,36779L,36780L,\n36781L,36782L,36783L,36784L,36785L,36786L,36787L,36788L,36789L,36790L,\n36791L,36792L,36793L,36794L,36795L,36796L,36797L,36798L,36799L,36800L,\n36801L,36802L,36803L,36804L,36805L,36806L,36807L,36808L,36809L,36810L,\n36811L,36812L,36813L,36814L,36815L,36816L,36817L,36818L,36819L,36820L,\n36821L,36822L,36823L,36824L,36825L,36826L,36827L,36828L,36829L,36830L,\n36831L,36832L,36833L,36834L,36835L,36836L,36837L,36838L,36839L,36840L,\n36841L,36842L,36843L,36844L,36845L,36846L,36847L,36848L,36849L,36850L,\n36851L,36852L,36853L,36854L,36855L,36856L,36857L,36858L,36859L,36860L,\n36861L,36862L,36863L,36864L,36865L,36866L,36867L,36868L,36869L,36870L,\n36871L,36872L,36873L,36874L,36875L,36876L,36877L,36878L,36879L,36880L,\n36881L,36882L,36883L,36884L,36885L,36886L,36887L,36888L,36889L,36890L,\n36891L,36892L,36893L,36894L,36895L,36896L,36897L,36898L,36899L,36900L,\n36901L,36902L,36903L,36904L,36905L,36906L,36907L,36908L,36909L,36910L,\n36911L,36912L,36913L,36914L,36915L,36916L,36917L,36918L,36919L,36920L,\n36921L,36922L,36923L,36924L,36925L,36926L,36927L,36928L,36929L,36930L,\n36931L,36932L,36933L,36934L,36935L,36936L,36937L,36938L,36939L,36940L,\n36941L,36942L,36943L,36944L,36945L,36946L,36947L,36948L,36949L,36950L,\n36951L,36952L,36953L,36954L,36955L,36956L,36957L,36958L,36959L,36960L,\n36961L,36962L,36963L,36964L,36965L,36966L,36967L,36968L,36969L,36970L,\n36971L,36972L,36973L,36974L,36975L,36976L,36977L,36978L,36979L,36980L,\n36981L,36982L,36983L,36984L,36985L,36986L,36987L,36988L,36989L,36990L,\n36991L,36992L,36993L,36994L,36995L,36996L,36997L,36998L,36999L,37000L,\n37001L,37002L,37003L,37004L,37005L,37006L,37007L,37008L,37009L,37010L,\n37011L,37012L,37013L,37014L,37015L,37016L,37017L,37018L,37019L,37020L,\n37021L,37022L,37023L,37024L,37025L,37026L,37027L,37028L,37029L,37030L,\n37031L,37032L,37033L,37034L,37035L,37036L,37037L,37038L,37039L,37040L,\n37041L,37042L,37043L,37044L,37045L,37046L,37047L,37048L,37049L,37050L,\n37051L,37052L,37053L,37054L,37055L,37056L,37057L,37058L,37059L,37060L,\n37061L,37062L,37063L,37064L,37065L,37066L,37067L,37068L,37069L,37070L,\n37071L,37072L,37073L,37074L,37075L,37076L,37077L,37078L,37079L,37080L,\n37081L,37082L,37083L,37084L,37085L,37086L,37087L,37088L,37089L,37090L,\n37091L,37092L,37093L,37094L,37095L,37096L,37097L,37098L,37099L,37100L,\n37101L,37102L,37103L,37104L,37105L,37106L,37107L,37108L,37109L,37110L,\n37111L,37112L,37113L,37114L,37115L,37116L,37117L,37118L,37119L,37120L,\n37121L,37122L,37123L,37124L,37125L,37126L,37127L,37128L,37129L,37130L,\n37131L,37132L,37133L,37134L,37135L,37136L,37137L,37138L,37139L,37140L,\n37141L,37142L,37143L,37144L,37145L,37146L,37147L,37148L,37149L,37150L,\n37151L,37152L,37153L,37154L,37155L,37156L,37157L,37158L,37159L,37160L,\n37161L,37162L,37163L,37164L,37165L,37166L,37167L,37168L,37169L,37170L,\n37171L,37172L,37173L,37174L,37175L,37176L,37177L,37178L,37179L,37180L,\n37181L,37182L,37183L,37184L,37185L,37186L,37187L,37188L,37189L,37190L,\n37191L,37192L,37193L,37194L,37195L,37196L,37197L,37198L,37199L,37200L,\n37201L,37202L,37203L,37204L,37205L,37206L,37207L,37208L,37209L,37210L,\n37211L,37212L,37213L,37214L,37215L,37216L,37217L,37218L,37219L,37220L,\n37221L,37222L,37223L,37224L,37225L,37226L,37227L,37228L,37229L,37230L,\n37231L,37232L,37233L,37234L,37235L,37236L,37237L,37238L,37239L,37240L,\n37241L,37242L,37243L,37244L,37245L,37246L,37247L,37248L,37249L,37250L,\n37251L,37252L,37253L,37254L,37255L,37256L,37257L,37258L,37259L,37260L,\n37261L,37262L,37263L,37264L,37265L,37266L,37267L,37268L,37269L,37270L,\n37271L,37272L,37273L,37274L,37275L,37276L,37277L,37278L,37279L,37280L,\n37281L,37282L,37283L,37284L,37285L,37286L,37287L,37288L,37289L,37290L,\n37291L,37292L,37293L,37294L,37295L,37296L,37297L,37298L,37299L,37300L,\n37301L,37302L,37303L,37304L,37305L,37306L,37307L,37308L,37309L,37310L,\n37311L,37312L,37313L,37314L,37315L,37316L,37317L,37318L,37319L,37320L,\n37321L,37322L,37323L,37324L,37325L,37326L,37327L,37328L,37329L,37330L,\n37331L,37332L,37333L,37334L,37335L,37336L,37337L,37338L,37339L,37340L,\n37341L,37342L,37343L,37344L,37345L,37346L,37347L,37348L,37349L,37350L,\n37351L,37352L,37353L,37354L,37355L,37356L,37357L,37358L,37359L,37360L,\n37361L,37362L,37363L,37364L,37365L,37366L,37367L,37368L,37369L,37370L,\n37371L,37372L,37373L,37374L,37375L,37376L,37377L,37378L,37379L,37380L,\n37381L,37382L,37383L,37384L,37385L,37386L,37387L,37388L,37389L,37390L,\n37391L,37392L,37393L,37394L,37395L,37396L,37397L,37398L,37399L,37400L,\n37401L,37402L,37403L,37404L,37405L,37406L,37407L,37408L,37409L,37410L,\n37411L,37412L,37413L,37414L,37415L,37416L,37417L,37418L,37419L,37420L,\n37421L,37422L,37423L,37424L,37425L,37426L,37427L,37428L,37429L,37430L,\n37431L,37432L,37433L,37434L,37435L,37436L,37437L,37438L,37439L,37440L,\n37441L,37442L,37443L,37444L,37445L,37446L,37447L,37448L,37449L,37450L,\n37451L,37452L,37453L,37454L,37455L,37456L,37457L,37458L,37459L,37460L,\n37461L,37462L,37463L,37464L,37465L,37466L,37467L,37468L,37469L,37470L,\n37471L,37472L,37473L,37474L,37475L,37476L,37477L,37478L,37479L,37480L,\n37481L,37482L,37483L,37484L,37485L,37486L,37487L,37488L,37489L,37490L,\n37491L,37492L,37493L,37494L,37495L,37496L,37497L,37498L,37499L,37500L,\n37501L,37502L,37503L,37504L,37505L,37506L,37507L,37508L,37509L,37510L,\n37511L,37512L,37513L,37514L,37515L,37516L,37517L,37518L,37519L,37520L,\n37521L,37522L,37523L,37524L,37525L,37526L,37527L,37528L,37529L,37530L,\n37531L,37532L,37533L,37534L,37535L,37536L,37537L,37538L,37539L,37540L,\n37541L,37542L,37543L,37544L,37545L,37546L,37547L,37548L,37549L,37550L,\n37551L,37552L,37553L,37554L,37555L,37556L,37557L,37558L,37559L,37560L,\n37561L,37562L,37563L,37564L,37565L,37566L,37567L,37568L,37569L,37570L,\n37571L,37572L,37573L,37574L,37575L,37576L,37577L,37578L,37579L,37580L,\n37581L,37582L,37583L,37584L,37585L,37586L,37587L,37588L,37589L,37590L,\n37591L,37592L,37593L,37594L,37595L,37596L,37597L,37598L,37599L,37600L,\n37601L,37602L,37603L,37604L,37605L,37606L,37607L,37608L,37609L,37610L,\n37611L,37612L,37613L,37614L,37615L,37616L,37617L,37618L,37619L,37620L,\n37621L,37622L,37623L,37624L,37625L,37626L,37627L,37628L,37629L,37630L,\n37631L,37632L,37633L,37634L,37635L,37636L,37637L,37638L,37639L,37640L,\n37641L,37642L,37643L,37644L,37645L,37646L,37647L,37648L,37649L,37650L,\n37651L,37652L,37653L,37654L,37655L,37656L,37657L,37658L,37659L,37660L,\n37661L,37662L,37663L,37664L,37665L,37666L,37667L,37668L,37669L,37670L,\n37671L,37672L,37673L,37674L,37675L,37676L,37677L,37678L,37679L,37680L,\n37681L,37682L,37683L,37684L,37685L,37686L,37687L,37688L,37689L,37690L,\n37691L,37692L,37693L,37694L,37695L,37696L,37697L,37698L,37699L,37700L,\n37701L,37702L,37703L,37704L,37705L,37706L,37707L,37708L,37709L,37710L,\n37711L,37712L,37713L,37714L,37715L,37716L,37717L,37718L,37719L,37720L,\n37721L,37722L,37723L,37724L,37725L,37726L,37727L,37728L,37729L,37730L,\n37731L,37732L,37733L,37734L,37735L,37736L,37737L,37738L,37739L,37740L,\n37741L,37742L,37743L,37744L,37745L,37746L,37747L,37748L,37749L,37750L,\n37751L,37752L,37753L,37754L,37755L,37756L,37757L,37758L,37759L,37760L,\n37761L,37762L,37763L,37764L,37765L,37766L,37767L,37768L,37769L,37770L,\n37771L,37772L,37773L,37774L,37775L,37776L,37777L,37778L,37779L,37780L,\n37781L,37782L,37783L,37784L,37785L,37786L,37787L,37788L,37789L,37790L,\n37791L,37792L,37793L,37794L,37795L,37796L,37797L,37798L,37799L,37800L,\n37801L,37802L,37803L,37804L,37805L,37806L,37807L,37808L,37809L,37810L,\n37811L,37812L,37813L,37814L,37815L,37816L,37817L,37818L,37819L,37820L,\n37821L,37822L,37823L,37824L,37825L,37826L,37827L,37828L,37829L,37830L,\n37831L,37832L,37833L,37834L,37835L,37836L,37837L,37838L,37839L,37840L,\n37841L,37842L,37843L,37844L,37845L,37846L,37847L,37848L,37849L,37850L,\n37851L,37852L,37853L,37854L,37855L,37856L,37857L,37858L,37859L,37860L,\n37861L,37862L,37863L,37864L,37865L,37866L,37867L,37868L,37869L,37870L,\n37871L,37872L,37873L,37874L,37875L,37876L,37877L,37878L,37879L,37880L,\n37881L,37882L,37883L,37884L,37885L,37886L,37887L,37888L,37889L,37890L,\n37891L,37892L,37893L,37894L,37895L,37896L,37897L,37898L,37899L,37900L,\n37901L,37902L,37903L,37904L,37905L,37906L,37907L,37908L,37909L,37910L,\n37911L,37912L,37913L,37914L,37915L,37916L,37917L,37918L,37919L,37920L,\n37921L,37922L,37923L,37924L,37925L,37926L,37927L,37928L,37929L,37930L,\n37931L,37932L,37933L,37934L,37935L,37936L,37937L,37938L,37939L,37940L,\n37941L,37942L,37943L,37944L,37945L,37946L,37947L,37948L,37949L,37950L,\n37951L,37952L,37953L,37954L,37955L,37956L,37957L,37958L,37959L,37960L,\n37961L,37962L,37963L,37964L,37965L,37966L,37967L,37968L,37969L,37970L,\n37971L,37972L,37973L,37974L,37975L,37976L,37977L,37978L,37979L,37980L,\n37981L,37982L,37983L,37984L,37985L,37986L,37987L,37988L,37989L,37990L,\n37991L,37992L,37993L,37994L,37995L,37996L,37997L,37998L,37999L,38000L,\n38001L,38002L,38003L,38004L,38005L,38006L,38007L,38008L,38009L,38010L,\n38011L,38012L,38013L,38014L,38015L,38016L,38017L,38018L,38019L,38020L,\n38021L,38022L,38023L,38024L,38025L,38026L,38027L,38028L,38029L,38030L,\n38031L,38032L,38033L,38034L,38035L,38036L,38037L,38038L,38039L,38040L,\n38041L,38042L,38043L,38044L,38045L,38046L,38047L,38048L,38049L,38050L,\n38051L,38052L,38053L,38054L,38055L,38056L,38057L,38058L,38059L,38060L,\n38061L,38062L,38063L,38064L,38065L,38066L,38067L,38068L,38069L,38070L,\n38071L,38072L,38073L,38074L,38075L,38076L,38077L,38078L,38079L,38080L,\n38081L,38082L,38083L,38084L,38085L,38086L,38087L,38088L,38089L,38090L,\n38091L,38092L,38093L,38094L,38095L,38096L,38097L,38098L,38099L,38100L,\n38101L,38102L,38103L,38104L,38105L,38106L,38107L,38108L,38109L,38110L,\n38111L,38112L,38113L,38114L,38115L,38116L,38117L,38118L,38119L,38120L,\n38121L,38122L,38123L,38124L,38125L,38126L,38127L,38128L,38129L,38130L,\n38131L,38132L,38133L,38134L,38135L,38136L,38137L,38138L,38139L,38140L,\n38141L,38142L,38143L,38144L,38145L,38146L,38147L,38148L,38149L,38150L,\n38151L,38152L,38153L,38154L,38155L,38156L,38157L,38158L,38159L,38160L,\n38161L,38162L,38163L,38164L,38165L,38166L,38167L,38168L,38169L,38170L,\n38171L,38172L,38173L,38174L,38175L,38176L,38177L,38178L,38179L,38180L,\n38181L,38182L,38183L,38184L,38185L,38186L,38187L,38188L,38189L,38190L,\n38191L,38192L,38193L,38194L,38195L,38196L,38197L,38198L,38199L,38200L,\n38201L,38202L,38203L,38204L,38205L,38206L,38207L,38208L,38209L,38210L,\n38211L,38212L,38213L,38214L,38215L,38216L,38217L,38218L,38219L,38220L,\n38221L,38222L,38223L,38224L,38225L,38226L,38227L,38228L,38229L,38230L,\n38231L,38232L,38233L,38234L,38235L,38236L,38237L,38238L,38239L,38240L,\n38241L,38242L,38243L,38244L,38245L,38246L,38247L,38248L,38249L,38250L,\n38251L,38252L,38253L,38254L,38255L,38256L,38257L,38258L,38259L,38260L,\n38261L,38262L,38263L,38264L,38265L,38266L,38267L,38268L,38269L,38270L,\n38271L,38272L,38273L,38274L,38275L,38276L,38277L,38278L,38279L,38280L,\n38281L,38282L,38283L,38284L,38285L,38286L,38287L,38288L,38289L,38290L,\n38291L,38292L,38293L,38294L,38295L,38296L,38297L,38298L,38299L,38300L,\n38301L,38302L,38303L,38304L,38305L,38306L,38307L,38308L,38309L,38310L,\n38311L,38312L,38313L,38314L,38315L,38316L,38317L,38318L,38319L,38320L,\n38321L,38322L,38323L,38324L,38325L,38326L,38327L,38328L,38329L,38330L,\n38331L,38332L,38333L,38334L,38335L,38336L,38337L,38338L,38339L,38340L,\n38341L,38342L,38343L,38344L,38345L,38346L,38347L,38348L,38349L,38350L,\n38351L,38352L,38353L,38354L,38355L,38356L,38357L,38358L,38359L,38360L,\n38361L,38362L,38363L,38364L,38365L,38366L,38367L,38368L,38369L,38370L,\n38371L,38372L,38373L,38374L,38375L,38376L,38377L,38378L,38379L,38380L,\n38381L,38382L,38383L,38384L,38385L,38386L,38387L,38388L,38389L,38390L,\n38391L,38392L,38393L,38394L,38395L,38396L,38397L,38398L,38399L,38400L,\n38401L,38402L,38403L,38404L,38405L,38406L,38407L,38408L,38409L,38410L,\n38411L,38412L,38413L,38414L,38415L,38416L,38417L,38418L,38419L,38420L,\n38421L,38422L,38423L,38424L,38425L,38426L,38427L,38428L,38429L,38430L,\n38431L,38432L,38433L,38434L,38435L,38436L,38437L,38438L,38439L,38440L,\n38441L,38442L,38443L,38444L,38445L,38446L,38447L,38448L,38449L,38450L,\n38451L,38452L,38453L,38454L,38455L,38456L,38457L,38458L,38459L,38460L,\n38461L,38462L,38463L,38464L,38465L,38466L,38467L,38468L,38469L,38470L,\n38471L,38472L,38473L,38474L,38475L,38476L,38477L,38478L,38479L,38480L,\n38481L,38482L,38483L,38484L,38485L,38486L,38487L,38488L,38489L,38490L,\n38491L,38492L,38493L,38494L,38495L,38496L,38497L,38498L,38499L,38500L,\n38501L,38502L,38503L,38504L,38505L,38506L,38507L,38508L,38509L,38510L,\n38511L,38512L,38513L,38514L,38515L,38516L,38517L,38518L,38519L,38520L,\n38521L,38522L,38523L,38524L,38525L,38526L,38527L,38528L,38529L,38530L,\n38531L,38532L,38533L,38534L,38535L,38536L,38537L,38538L,38539L,38540L,\n38541L,38542L,38543L,38544L,38545L,38546L,38547L,38548L,38549L,38550L,\n38551L,38552L,38553L,38554L,38555L,38556L,38557L,38558L,38559L,38560L,\n38561L,38562L,38563L,38564L,38565L,38566L,38567L,38568L,38569L,38570L,\n38571L,38572L,38573L,38574L,38575L,38576L,38577L,38578L,38579L,38580L,\n38581L,38582L,38583L,38584L,38585L,38586L,38587L,38588L,38589L,38590L,\n38591L,38592L,38593L,38594L,38595L,38596L,38597L,38598L,38599L,38600L,\n38601L,38602L,38603L,38604L,38605L,38606L,38607L,38608L,38609L,38610L,\n38611L,38612L,38613L,38614L,38615L,38616L,38617L,38618L,38619L,38620L,\n38621L,38622L,38623L,38624L,38625L,38626L,38627L,38628L,38629L,38630L,\n38631L,38632L,38633L,38634L,38635L,38636L,38637L,38638L,38639L,38640L,\n38641L,38642L,38643L,38644L,38645L,38646L,38647L,38648L,38649L,38650L,\n38651L,38652L,38653L,38654L,38655L,38656L,38657L,38658L,38659L,38660L,\n38661L,38662L,38663L,38664L,38665L,38666L,38667L,38668L,38669L,38670L,\n38671L,38672L,38673L,38674L,38675L,38676L,38677L,38678L,38679L,38680L,\n38681L,38682L,38683L,38684L,38685L,38686L,38687L,38688L,38689L,38690L,\n38691L,38692L,38693L,38694L,38695L,38696L,38697L,38698L,38699L,38700L,\n38701L,38702L,38703L,38704L,38705L,38706L,38707L,38708L,38709L,38710L,\n38711L,38712L,38713L,38714L,38715L,38716L,38717L,38718L,38719L,38720L,\n38721L,38722L,38723L,38724L,38725L,38726L,38727L,38728L,38729L,38730L,\n38731L,38732L,38733L,38734L,38735L,38736L,38737L,38738L,38739L,38740L,\n38741L,38742L,38743L,38744L,38745L,38746L,38747L,38748L,38749L,38750L,\n38751L,38752L,38753L,38754L,38755L,38756L,38757L,38758L,38759L,38760L,\n38761L,38762L,38763L,38764L,38765L,38766L,38767L,38768L,38769L,38770L,\n38771L,38772L,38773L,38774L,38775L,38776L,38777L,38778L,38779L,38780L,\n38781L,38782L,38783L,38784L,38785L,38786L,38787L,38788L,38789L,38790L,\n38791L,38792L,38793L,38794L,38795L,38796L,38797L,38798L,38799L,38800L,\n38801L,38802L,38803L,38804L,38805L,38806L,38807L,38808L,38809L,38810L,\n38811L,38812L,38813L,38814L,38815L,38816L,38817L,38818L,38819L,38820L,\n38821L,38822L,38823L,38824L,38825L,38826L,38827L,38828L,38829L,38830L,\n38831L,38832L,38833L,38834L,38835L,38836L,38837L,38838L,38839L,38840L,\n38841L,38842L,38843L,38844L,38845L,38846L,38847L,38848L,38849L,38850L,\n38851L,38852L,38853L,38854L,38855L,38856L,38857L,38858L,38859L,38860L,\n38861L,38862L,38863L,38864L,38865L,38866L,38867L,38868L,38869L,38870L,\n38871L,38872L,38873L,38874L,38875L,38876L,38877L,38878L,38879L,38880L,\n38881L,38882L,38883L,38884L,38885L,38886L,38887L,38888L,38889L,38890L,\n38891L,38892L,38893L,38894L,38895L,38896L,38897L,38898L,38899L,38900L,\n38901L,38902L,38903L,38904L,38905L,38906L,38907L,38908L,38909L,38910L,\n38911L,38912L,38913L,38914L,38915L,38916L,38917L,38918L,38919L,38920L,\n38921L,38922L,38923L,38924L,38925L,38926L,38927L,38928L,38929L,38930L,\n38931L,38932L,38933L,38934L,38935L,38936L,38937L,38938L,38939L,38940L,\n38941L,38942L,38943L,38944L,38945L,38946L,38947L,38948L,38949L,38950L,\n38951L,38952L,38953L,38954L,38955L,38956L,38957L,38958L,38959L,38960L,\n38961L,38962L,38963L,38964L,38965L,38966L,38967L,38968L,38969L,38970L,\n38971L,38972L,38973L,38974L,38975L,38976L,38977L,38978L,38979L,38980L,\n38981L,38982L,38983L,38984L,38985L,38986L,38987L,38988L,38989L,38990L,\n38991L,38992L,38993L,38994L,38995L,38996L,38997L,38998L,38999L,39000L,\n39001L,39002L,39003L,39004L,39005L,39006L,39007L,39008L,39009L,39010L,\n39011L,39012L,39013L,39014L,39015L,39016L,39017L,39018L,39019L,39020L,\n39021L,39022L,39023L,39024L,39025L,39026L,39027L,39028L,39029L,39030L,\n39031L,39032L,39033L,39034L,39035L,39036L,39037L,39038L,39039L,39040L,\n39041L,39042L,39043L,39044L,39045L,39046L,39047L,39048L,39049L,39050L,\n39051L,39052L,39053L,39054L,39055L,39056L,39057L,39058L,39059L,39060L,\n39061L,39062L,39063L,39064L,39065L,39066L,39067L,39068L,39069L,39070L,\n39071L,39072L,39073L,39074L,39075L,39076L,39077L,39078L,39079L,39080L,\n39081L,39082L,39083L,39084L,39085L,39086L,39087L,39088L,39089L,39090L,\n39091L,39092L,39093L,39094L,39095L,39096L,39097L,39098L,39099L,39100L,\n39101L,39102L,39103L,39104L,39105L,39106L,39107L,39108L,39109L,39110L,\n39111L,39112L,39113L,39114L,39115L,39116L,39117L,39118L,39119L,39120L,\n39121L,39122L,39123L,39124L,39125L,39126L,39127L,39128L,39129L,39130L,\n39131L,39132L,39133L,39134L,39135L,39136L,39137L,39138L,39139L,39140L,\n39141L,39142L,39143L,39144L,39145L,39146L,39147L,39148L,39149L,39150L,\n39151L,39152L,39153L,39154L,39155L,39156L,39157L,39158L,39159L,39160L,\n39161L,39162L,39163L,39164L,39165L,39166L,39167L,39168L,39169L,39170L,\n39171L,39172L,39173L,39174L,39175L,39176L,39177L,39178L,39179L,39180L,\n39181L,39182L,39183L,39184L,39185L,39186L,39187L,39188L,39189L,39190L,\n39191L,39192L,39193L,39194L,39195L,39196L,39197L,39198L,39199L,39200L,\n39201L,39202L,39203L,39204L,39205L,39206L,39207L,39208L,39209L,39210L,\n39211L,39212L,39213L,39214L,39215L,39216L,39217L,39218L,39219L,39220L,\n39221L,39222L,39223L,39224L,39225L,39226L,39227L,39228L,39229L,39230L,\n39231L,39232L,39233L,39234L,39235L,39236L,39237L,39238L,39239L,39240L,\n39241L,39242L,39243L,39244L,39245L,39246L,39247L,39248L,39249L,39250L,\n39251L,39252L,39253L,39254L,39255L,39256L,39257L,39258L,39259L,39260L,\n39261L,39262L,39263L,39264L,39265L,39266L,39267L,39268L,39269L,39270L,\n39271L,39272L,39273L,39274L,39275L,39276L,39277L,39278L,39279L,39280L,\n39281L,39282L,39283L,39284L,39285L,39286L,39287L,39288L,39289L,39290L,\n39291L,39292L,39293L,39294L,39295L,39296L,39297L,39298L,39299L,39300L,\n39301L,39302L,39303L,39304L,39305L,39306L,39307L,39308L,39309L,39310L,\n39311L,39312L,39313L,39314L,39315L,39316L,39317L,39318L,39319L,39320L,\n39321L,39322L,39323L,39324L,39325L,39326L,39327L,39328L,39329L,39330L,\n39331L,39332L,39333L,39334L,39335L,39336L,39337L,39338L,39339L,39340L,\n39341L,39342L,39343L,39344L,39345L,39346L,39347L,39348L,39349L,39350L,\n39351L,39352L,39353L,39354L,39355L,39356L,39357L,39358L,39359L,39360L,\n39361L,39362L,39363L,39364L,39365L,39366L,39367L,39368L,39369L,39370L,\n39371L,39372L,39373L,39374L,39375L,39376L,39377L,39378L,39379L,39380L,\n39381L,39382L,39383L,39384L,39385L,39386L,39387L,39388L,39389L,39390L,\n39391L,39392L,39393L,39394L,39395L,39396L,39397L,39398L,39399L,39400L,\n39401L,39402L,39403L,39404L,39405L,39406L,39407L,39408L,39409L,39410L,\n39411L,39412L,39413L,39414L,39415L,39416L,39417L,39418L,39419L,39420L,\n39421L,39422L,39423L,39424L,39425L,39426L,39427L,39428L,39429L,39430L,\n39431L,39432L,39433L,39434L,39435L,39436L,39437L,39438L,39439L,39440L,\n39441L,39442L,39443L,39444L,39445L,39446L,39447L,39448L,39449L,39450L,\n39451L,39452L,39453L,39454L,39455L,39456L,39457L,39458L,39459L,39460L,\n39461L,39462L,39463L,39464L,39465L,39466L,39467L,39468L,39469L,39470L,\n39471L,39472L,39473L,39474L,39475L,39476L,39477L,39478L,39479L,39480L,\n39481L,39482L,39483L,39484L,39485L,39486L,39487L,39488L,39489L,39490L,\n39491L,39492L,39493L,39494L,39495L,39496L,39497L,39498L,39499L,39500L,\n39501L,39502L,39503L,39504L,39505L,39506L,39507L,39508L,39509L,39510L,\n39511L,39512L,39513L,39514L,39515L,39516L,39517L,39518L,39519L,39520L,\n39521L,39522L,39523L,39524L,39525L,39526L,39527L,39528L,39529L,39530L,\n39531L,39532L,39533L,39534L,39535L,39536L,39537L,39538L,39539L,39540L,\n39541L,39542L,39543L,39544L,39545L,39546L,39547L,39548L,39549L,39550L,\n39551L,39552L,39553L,39554L,39555L,39556L,39557L,39558L,39559L,39560L,\n39561L,39562L,39563L,39564L,39565L,39566L,39567L,39568L,39569L,39570L,\n39571L,39572L,39573L,39574L,39575L,39576L,39577L,39578L,39579L,39580L,\n39581L,39582L,39583L,39584L,39585L,39586L,39587L,39588L,39589L,39590L,\n39591L,39592L,39593L,39594L,39595L,39596L,39597L,39598L,39599L,39600L,\n39601L,39602L,39603L,39604L,39605L,39606L,39607L,39608L,39609L,39610L,\n39611L,39612L,39613L,39614L,39615L,39616L,39617L,39618L,39619L,39620L,\n39621L,39622L,39623L,39624L,39625L,39626L,39627L,39628L,39629L,39630L,\n39631L,39632L,39633L,39634L,39635L,39636L,39637L,39638L,39639L,39640L,\n39641L,39642L,39643L,39644L,39645L,39646L,39647L,39648L,39649L,39650L,\n39651L,39652L,39653L,39654L,39655L,39656L,39657L,39658L,39659L,39660L,\n39661L,39662L,39663L,39664L,39665L,39666L,39667L,39668L,39669L,39670L,\n39671L,39672L,39673L,39674L,39675L,39676L,39677L,39678L,39679L,39680L,\n39681L,39682L,39683L,39684L,39685L,39686L,39687L,39688L,39689L,39690L,\n39691L,39692L,39693L,39694L,39695L,39696L,39697L,39698L,39699L,39700L,\n39701L,39702L,39703L,39704L,39705L,39706L,39707L,39708L,39709L,39710L,\n39711L,39712L,39713L,39714L,39715L,39716L,39717L,39718L,39719L,39720L,\n39721L,39722L,39723L,39724L,39725L,39726L,39727L,39728L,39729L,39730L,\n39731L,39732L,39733L,39734L,39735L,39736L,39737L,39738L,39739L,39740L,\n39741L,39742L,39743L,39744L,39745L,39746L,39747L,39748L,39749L,39750L,\n39751L,39752L,39753L,39754L,39755L,39756L,39757L,39758L,39759L,39760L,\n39761L,39762L,39763L,39764L,39765L,39766L,39767L,39768L,39769L,39770L,\n39771L,39772L,39773L,39774L,39775L,39776L,39777L,39778L,39779L,39780L,\n39781L,39782L,39783L,39784L,39785L,39786L,39787L,39788L,39789L,39790L,\n39791L,39792L,39793L,39794L,39795L,39796L,39797L,39798L,39799L,39800L,\n39801L,39802L,39803L,39804L,39805L,39806L,39807L,39808L,39809L,39810L,\n39811L,39812L,39813L,39814L,39815L,39816L,39817L,39818L,39819L,39820L,\n39821L,39822L,39823L,39824L,39825L,39826L,39827L,39828L,39829L,39830L,\n39831L,39832L,39833L,39834L,39835L,39836L,39837L,39838L,39839L,39840L,\n39841L,39842L,39843L,39844L,39845L,39846L,39847L,39848L,39849L,39850L,\n39851L,39852L,39853L,39854L,39855L,39856L,39857L,39858L,39859L,39860L,\n39861L,39862L,39863L,39864L,39865L,39866L,39867L,39868L,39869L,39870L,\n39871L,39872L,39873L,39874L,39875L,39876L,39877L,39878L,39879L,39880L,\n39881L,39882L,39883L,39884L,39885L,39886L,39887L,39888L,39889L,39890L,\n39891L,39892L,39893L,39894L,39895L,39896L,39897L,39898L,39899L,39900L,\n39901L,39902L,39903L,39904L,39905L,39906L,39907L,39908L,39909L,39910L,\n39911L,39912L,39913L,39914L,39915L,39916L,39917L,39918L,39919L,39920L,\n39921L,39922L,39923L,39924L,39925L,39926L,39927L,39928L,39929L,39930L,\n39931L,39932L,39933L,39934L,39935L,39936L,39937L,39938L,39939L,39940L,\n39941L,39942L,39943L,39944L,39945L,39946L,39947L,39948L,39949L,39950L,\n39951L,39952L,39953L,39954L,39955L,39956L,39957L,39958L,39959L,39960L,\n39961L,39962L,39963L,39964L,39965L,39966L,39967L,39968L,39969L,39970L,\n39971L,39972L,39973L,39974L,39975L,39976L,39977L,39978L,39979L,39980L,\n39981L,39982L,39983L,39984L,39985L,39986L,39987L,39988L,39989L,39990L,\n39991L,39992L,39993L,39994L,39995L,39996L,39997L,39998L,39999L,40000L,\n40001L,40002L,40003L,40004L,40005L,40006L,40007L,40008L,40009L,40010L,\n40011L,40012L,40013L,40014L,40015L,40016L,40017L,40018L,40019L,40020L,\n40021L,40022L,40023L,40024L,40025L,40026L,40027L,40028L,40029L,40030L,\n40031L,40032L,40033L,40034L,40035L,40036L,40037L,40038L,40039L,40040L,\n40041L,40042L,40043L,40044L,40045L,40046L,40047L,40048L,40049L,40050L,\n40051L,40052L,40053L,40054L,40055L,40056L,40057L,40058L,40059L,40060L,\n40061L,40062L,40063L,40064L,40065L,40066L,40067L,40068L,40069L,40070L,\n40071L,40072L,40073L,40074L,40075L,40076L,40077L,40078L,40079L,40080L,\n40081L,40082L,40083L,40084L,40085L,40086L,40087L,40088L,40089L,40090L,\n40091L,40092L,40093L,40094L,40095L,40096L,40097L,40098L,40099L,40100L,\n40101L,40102L,40103L,40104L,40105L,40106L,40107L,40108L,40109L,40110L,\n40111L,40112L,40113L,40114L,40115L,40116L,40117L,40118L,40119L,40120L,\n40121L,40122L,40123L,40124L,40125L,40126L,40127L,40128L,40129L,40130L,\n40131L,40132L,40133L,40134L,40135L,40136L,40137L,40138L,40139L,40140L,\n40141L,40142L,40143L,40144L,40145L,40146L,40147L,40148L,40149L,40150L,\n40151L,40152L,40153L,40154L,40155L,40156L,40157L,40158L,40159L,40160L,\n40161L,40162L,40163L,40164L,40165L,40166L,40167L,40168L,40169L,40170L,\n40171L,40172L,40173L,40174L,40175L,40176L,40177L,40178L,40179L,40180L,\n40181L,40182L,40183L,40184L,40185L,40186L,40187L,40188L,40189L,40190L,\n40191L,40192L,40193L,40194L,40195L,40196L,40197L,40198L,40199L,40200L,\n40201L,40202L,40203L,40204L,40205L,40206L,40207L,40208L,40209L,40210L,\n40211L,40212L,40213L,40214L,40215L,40216L,40217L,40218L,40219L,40220L,\n40221L,40222L,40223L,40224L,40225L,40226L,40227L,40228L,40229L,40230L,\n40231L,40232L,40233L,40234L,40235L,40236L,40237L,40238L,40239L,40240L,\n40241L,40242L,40243L,40244L,40245L,40246L,40247L,40248L,40249L,40250L,\n40251L,40252L,40253L,40254L,40255L,40256L,40257L,40258L,40259L,40260L,\n40261L,40262L,40263L,40264L,40265L,40266L,40267L,40268L,40269L,40270L,\n40271L,40272L,40273L,40274L,40275L,40276L,40277L,40278L,40279L,40280L,\n40281L,40282L,40283L,40284L,40285L,40286L,40287L,40288L,40289L,40290L,\n40291L,40292L,40293L,40294L,40295L,40296L,40297L,40298L,40299L,40300L,\n40301L,40302L,40303L,40304L,40305L,40306L,40307L,40308L,40309L,40310L,\n40311L,40312L,40313L,40314L,40315L,40316L,40317L,40318L,40319L,40320L,\n40321L,40322L,40323L,40324L,40325L,40326L,40327L,40328L,40329L,40330L,\n40331L,40332L,40333L,40334L,40335L,40336L,40337L,40338L,40339L,40340L,\n40341L,40342L,40343L,40344L,40345L,40346L,40347L,40348L,40349L,40350L,\n40351L,40352L,40353L,40354L,40355L,40356L,40357L,40358L,40359L,40360L,\n40361L,40362L,40363L,40364L,40365L,40366L,40367L,40368L,40369L,40370L,\n40371L,40372L,40373L,40374L,40375L,40376L,40377L,40378L,40379L,40380L,\n40381L,40382L,40383L,40384L,40385L,40386L,40387L,40388L,40389L,40390L,\n40391L,40392L,40393L,40394L,40395L,40396L,40397L,40398L,40399L,40400L,\n40401L,40402L,40403L,40404L,40405L,40406L,40407L,40408L,40409L,40410L,\n40411L,40412L,40413L,40414L,40415L,40416L,40417L,40418L,40419L,40420L,\n40421L,40422L,40423L,40424L,40425L,40426L,40427L,40428L,40429L,40430L,\n40431L,40432L,40433L,40434L,40435L,40436L,40437L,40438L,40439L,40440L,\n40441L,40442L,40443L,40444L,40445L,40446L,40447L,40448L,40449L,40450L,\n40451L,40452L,40453L,40454L,40455L,40456L,40457L,40458L,40459L,40460L,\n40461L,40462L,40463L,40464L,40465L,40466L,40467L,40468L,40469L,40470L,\n40471L,40472L,40473L,40474L,40475L,40476L,40477L,40478L,40479L,40480L,\n40481L,40482L,40483L,40484L,40485L,40486L,40487L,40488L,40489L,40490L,\n40491L,40492L,40493L,40494L,40495L,40496L,40497L,40498L,40499L,40500L,\n40501L,40502L,40503L,40504L,40505L,40506L,40507L,40508L,40509L,40510L,\n40511L,40512L,40513L,40514L,40515L,40516L,40517L,40518L,40519L,40520L,\n40521L,40522L,40523L,40524L,40525L,40526L,40527L,40528L,40529L,40530L,\n40531L,40532L,40533L,40534L,40535L,40536L,40537L,40538L,40539L,40540L,\n40541L,40542L,40543L,40544L,40545L,40546L,40547L,40548L,40549L,40550L,\n40551L,40552L,40553L,40554L,40555L,40556L,40557L,40558L,40559L,40560L,\n40561L,40562L,40563L,40564L,40565L,40566L,40567L,40568L,40569L,40570L,\n40571L,40572L,40573L,40574L,40575L,40576L,40577L,40578L,40579L,40580L,\n40581L,40582L,40583L,40584L,40585L,40586L,40587L,40588L,40589L,40590L,\n40591L,40592L,40593L,40594L,40595L,40596L,40597L,40598L,40599L,40600L,\n40601L,40602L,40603L,40604L,40605L,40606L,40607L,40608L,40609L,40610L,\n40611L,40612L,40613L,40614L,40615L,40616L,40617L,40618L,40619L,40620L,\n40621L,40622L,40623L,40624L,40625L,40626L,40627L,40628L,40629L,40630L,\n40631L,40632L,40633L,40634L,40635L,40636L,40637L,40638L,40639L,40640L,\n40641L,40642L,40643L,40644L,40645L,40646L,40647L,40648L,40649L,40650L,\n40651L,40652L,40653L,40654L,40655L,40656L,40657L,40658L,40659L,40660L,\n40661L,40662L,40663L,40664L,40665L,40666L,40667L,40668L,40669L,40670L,\n40671L,40672L,40673L,40674L,40675L,40676L,40677L,40678L,40679L,40680L,\n40681L,40682L,40683L,40684L,40685L,40686L,40687L,40688L,40689L,40690L,\n40691L,40692L,40693L,40694L,40695L,40696L,40697L,40698L,40699L,40700L,\n40701L,40702L,40703L,40704L,40705L,40706L,40707L,40708L,40709L,40710L,\n40711L,40712L,40713L,40714L,40715L,40716L,40717L,40718L,40719L,40720L,\n40721L,40722L,40723L,40724L,40725L,40726L,40727L,40728L,40729L,40730L,\n40731L,40732L,40733L,40734L,40735L,40736L,40737L,40738L,40739L,40740L,\n40741L,40742L,40743L,40744L,40745L,40746L,40747L,40748L,40749L,40750L,\n40751L,40752L,40753L,40754L,40755L,40756L,40757L,40758L,40759L,40760L,\n40761L,40762L,40763L,40764L,40765L,40766L,40767L,40768L,40769L,40770L,\n40771L,40772L,40773L,40774L,40775L,40776L,40777L,40778L,40779L,40780L,\n40781L,40782L,40783L,40784L,40785L,40786L,40787L,40788L,40789L,40790L,\n40791L,40792L,40793L,40794L,40795L,40796L,40797L,40798L,40799L,40800L,\n40801L,40802L,40803L,40804L,40805L,40806L,40807L,40808L,40809L,40810L,\n40811L,40812L,40813L,40814L,40815L,40816L,40817L,40818L,40819L,40820L,\n40821L,40822L,40823L,40824L,40825L,40826L,40827L,40828L,40829L,40830L,\n40831L,40832L,40833L,40834L,40835L,40836L,40837L,40838L,40839L,40840L,\n40841L,40842L,40843L,40844L,40845L,40846L,40847L,40848L,40849L,40850L,\n40851L,40852L,40853L,40854L,40855L,40856L,40857L,40858L,40859L,40860L,\n40861L,40862L,40863L,40864L,40865L,40866L,40867L,40868L,40869L,40870L,\n40871L,40872L,40873L,40874L,40875L,40876L,40877L,40878L,40879L,40880L,\n40881L,40882L,40883L,40884L,40885L,40886L,40887L,40888L,40889L,40890L,\n40891L,40892L,40893L,40894L,40895L,40896L,40897L,40898L,40899L,40900L,\n40901L,40902L,40903L,40904L,40905L,40906L,40907L,40908L,40909L,40910L,\n40911L,40912L,40913L,40914L,40915L,40916L,40917L,40918L,40919L,40920L,\n40921L,40922L,40923L,40924L,40925L,40926L,40927L,40928L,40929L,40930L,\n40931L,40932L,40933L,40934L,40935L,40936L,40937L,40938L,40939L,40940L,\n40941L,40942L,40943L,40944L,40945L,40946L,40947L,40948L,40949L,40950L,\n40951L,40952L,40953L,40954L,40955L,40956L,40957L,40958L,40959L,40960L,\n40961L,40962L,40963L,40964L,40965L,40966L,40967L,40968L,40969L,40970L,\n40971L,40972L,40973L,40974L,40975L,40976L,40977L,40978L,40979L,40980L,\n40981L,40982L,40983L,40984L,40985L,40986L,40987L,40988L,40989L,40990L,\n40991L,40992L,40993L,40994L,40995L,40996L,40997L,40998L,40999L,41000L,\n41001L,41002L,41003L,41004L,41005L,41006L,41007L,41008L,41009L,41010L,\n41011L,41012L,41013L,41014L,41015L,41016L,41017L,41018L,41019L,41020L,\n41021L,41022L,41023L,41024L,41025L,41026L,41027L,41028L,41029L,41030L,\n41031L,41032L,41033L,41034L,41035L,41036L,41037L,41038L,41039L,41040L,\n41041L,41042L,41043L,41044L,41045L,41046L,41047L,41048L,41049L,41050L,\n41051L,41052L,41053L,41054L,41055L,41056L,41057L,41058L,41059L,41060L,\n41061L,41062L,41063L,41064L,41065L,41066L,41067L,41068L,41069L,41070L,\n41071L,41072L,41073L,41074L,41075L,41076L,41077L,41078L,41079L,41080L,\n41081L,41082L,41083L,41084L,41085L,41086L,41087L,41088L,41089L,41090L,\n41091L,41092L,41093L,41094L,41095L,41096L,41097L,41098L,41099L,41100L,\n41101L,41102L,41103L,41104L,41105L,41106L,41107L,41108L,41109L,41110L,\n41111L,41112L,41113L,41114L,41115L,41116L,41117L,41118L,41119L,41120L,\n41121L,41122L,41123L,41124L,41125L,41126L,41127L,41128L,41129L,41130L,\n41131L,41132L,41133L,41134L,41135L,41136L,41137L,41138L,41139L,41140L,\n41141L,41142L,41143L,41144L,41145L,41146L,41147L,41148L,41149L,41150L,\n41151L,41152L,41153L,41154L,41155L,41156L,41157L,41158L,41159L,41160L,\n41161L,41162L,41163L,41164L,41165L,41166L,41167L,41168L,41169L,41170L,\n41171L,41172L,41173L,41174L,41175L,41176L,41177L,41178L,41179L,41180L,\n41181L,41182L,41183L,41184L,41185L,41186L,41187L,41188L,41189L,41190L,\n41191L,41192L,41193L,41194L,41195L,41196L,41197L,41198L,41199L,41200L,\n41201L,41202L,41203L,41204L,41205L,41206L,41207L,41208L,41209L,41210L,\n41211L,41212L,41213L,41214L,41215L,41216L,41217L,41218L,41219L,41220L,\n41221L,41222L,41223L,41224L,41225L,41226L,41227L,41228L,41229L,41230L,\n41231L,41232L,41233L,41234L,41235L,41236L,41237L,41238L,41239L,41240L,\n41241L,41242L,41243L,41244L,41245L,41246L,41247L,41248L,41249L,41250L,\n41251L,41252L,41253L,41254L,41255L,41256L,41257L,41258L,41259L,41260L,\n41261L,41262L,41263L,41264L,41265L,41266L,41267L,41268L,41269L,41270L,\n41271L,41272L,41273L,41274L,41275L,41276L,41277L,41278L,41279L,41280L,\n41281L,41282L,41283L,41284L,41285L,41286L,41287L,41288L,41289L,41290L,\n41291L,41292L,41293L,41294L,41295L,41296L,41297L,41298L,41299L,41300L,\n41301L,41302L,41303L,41304L,41305L,41306L,41307L,41308L,41309L,41310L,\n41311L,41312L,41313L,41314L,41315L,41316L,41317L,41318L,41319L,41320L,\n41321L,41322L,41323L,41324L,41325L,41326L,41327L,41328L,41329L,41330L,\n41331L,41332L,41333L,41334L,41335L,41336L,41337L,41338L,41339L,41340L,\n41341L,41342L,41343L,41344L,41345L,41346L,41347L,41348L,41349L,41350L,\n41351L,41352L,41353L,41354L,41355L,41356L,41357L,41358L,41359L,41360L,\n41361L,41362L,41363L,41364L,41365L,41366L,41367L,41368L,41369L,41370L,\n41371L,41372L,41373L,41374L,41375L,41376L,41377L,41378L,41379L,41380L,\n41381L,41382L,41383L,41384L,41385L,41386L,41387L,41388L,41389L,41390L,\n41391L,41392L,41393L,41394L,41395L,41396L,41397L,41398L,41399L,41400L,\n41401L,41402L,41403L,41404L,41405L,41406L,41407L,41408L,41409L,41410L,\n41411L,41412L,41413L,41414L,41415L,41416L,41417L,41418L,41419L,41420L,\n41421L,41422L,41423L,41424L,41425L,41426L,41427L,41428L,41429L,41430L,\n41431L,41432L,41433L,41434L,41435L,41436L,41437L,41438L,41439L,41440L,\n41441L,41442L,41443L,41444L,41445L,41446L,41447L,41448L,41449L,41450L,\n41451L,41452L,41453L,41454L,41455L,41456L,41457L,41458L,41459L,41460L,\n41461L,41462L,41463L,41464L,41465L,41466L,41467L,41468L,41469L,41470L,\n41471L,41472L,41473L,41474L,41475L,41476L,41477L,41478L,41479L,41480L,\n41481L,41482L,41483L,41484L,41485L,41486L,41487L,41488L,41489L,41490L,\n41491L,41492L,41493L,41494L,41495L,41496L,41497L,41498L,41499L,41500L,\n41501L,41502L,41503L,41504L,41505L,41506L,41507L,41508L,41509L,41510L,\n41511L,41512L,41513L,41514L,41515L,41516L,41517L,41518L,41519L,41520L,\n41521L,41522L,41523L,41524L,41525L,41526L,41527L,41528L,41529L,41530L,\n41531L,41532L,41533L,41534L,41535L,41536L,41537L,41538L,41539L,41540L,\n41541L,41542L,41543L,41544L,41545L,41546L,41547L,41548L,41549L,41550L,\n41551L,41552L,41553L,41554L,41555L,41556L,41557L,41558L,41559L,41560L,\n41561L,41562L,41563L,41564L,41565L,41566L,41567L,41568L,41569L,41570L,\n41571L,41572L,41573L,41574L,41575L,41576L,41577L,41578L,41579L,41580L,\n41581L,41582L,41583L,41584L,41585L,41586L,41587L,41588L,41589L,41590L,\n41591L,41592L,41593L,41594L,41595L,41596L,41597L,41598L,41599L,41600L,\n41601L,41602L,41603L,41604L,41605L,41606L,41607L,41608L,41609L,41610L,\n41611L,41612L,41613L,41614L,41615L,41616L,41617L,41618L,41619L,41620L,\n41621L,41622L,41623L,41624L,41625L,41626L,41627L,41628L,41629L,41630L,\n41631L,41632L,41633L,41634L,41635L,41636L,41637L,41638L,41639L,41640L,\n41641L,41642L,41643L,41644L,41645L,41646L,41647L,41648L,41649L,41650L,\n41651L,41652L,41653L,41654L,41655L,41656L,41657L,41658L,41659L,41660L,\n41661L,41662L,41663L,41664L,41665L,41666L,41667L,41668L,41669L,41670L,\n41671L,41672L,41673L,41674L,41675L,41676L,41677L,41678L,41679L,41680L,\n41681L,41682L,41683L,41684L,41685L,41686L,41687L,41688L,41689L,41690L,\n41691L,41692L,41693L,41694L,41695L,41696L,41697L,41698L,41699L,41700L,\n41701L,41702L,41703L,41704L,41705L,41706L,41707L,41708L,41709L,41710L,\n41711L,41712L,41713L,41714L,41715L,41716L,41717L,41718L,41719L,41720L,\n41721L,41722L,41723L,41724L,41725L,41726L,41727L,41728L,41729L,41730L,\n41731L,41732L,41733L,41734L,41735L,41736L,41737L,41738L,41739L,41740L,\n41741L,41742L,41743L,41744L,41745L,41746L,41747L,41748L,41749L,41750L,\n41751L,41752L,41753L,41754L,41755L,41756L,41757L,41758L,41759L,41760L,\n41761L,41762L,41763L,41764L,41765L,41766L,41767L,41768L,41769L,41770L,\n41771L,41772L,41773L,41774L,41775L,41776L,41777L,41778L,41779L,41780L,\n41781L,41782L,41783L,41784L,41785L,41786L,41787L,41788L,41789L,41790L,\n41791L,41792L,41793L,41794L,41795L,41796L,41797L,41798L,41799L,41800L,\n41801L,41802L,41803L,41804L,41805L,41806L,41807L,41808L,41809L,41810L,\n41811L,41812L,41813L,41814L,41815L,41816L,41817L,41818L,41819L,41820L,\n41821L,41822L,41823L,41824L,41825L,41826L,41827L,41828L,41829L,41830L,\n41831L,41832L,41833L,41834L,41835L,41836L,41837L,41838L,41839L,41840L,\n41841L,41842L,41843L,41844L,41845L,41846L,41847L,41848L,41849L,41850L,\n41851L,41852L,41853L,41854L,41855L,41856L,41857L,41858L,41859L,41860L,\n41861L,41862L,41863L,41864L,41865L,41866L,41867L,41868L,41869L,41870L,\n41871L,41872L,41873L,41874L,41875L,41876L,41877L,41878L,41879L,41880L,\n41881L,41882L,41883L,41884L,41885L,41886L,41887L,41888L,41889L,41890L,\n41891L,41892L,41893L,41894L,41895L,41896L,41897L,41898L,41899L,41900L,\n41901L,41902L,41903L,41904L,41905L,41906L,41907L,41908L,41909L,41910L,\n41911L,41912L,41913L,41914L,41915L,41916L,41917L,41918L,41919L,41920L,\n41921L,41922L,41923L,41924L,41925L,41926L,41927L,41928L,41929L,41930L,\n41931L,41932L,41933L,41934L,41935L,41936L,41937L,41938L,41939L,41940L,\n41941L,41942L,41943L,41944L,41945L,41946L,41947L,41948L,41949L,41950L,\n41951L,41952L,41953L,41954L,41955L,41956L,41957L,41958L,41959L,41960L,\n41961L,41962L,41963L,41964L,41965L,41966L,41967L,41968L,41969L,41970L,\n41971L,41972L,41973L,41974L,41975L,41976L,41977L,41978L,41979L,41980L,\n41981L,41982L,41983L,41984L,41985L,41986L,41987L,41988L,41989L,41990L,\n41991L,41992L,41993L,41994L,41995L,41996L,41997L,41998L,41999L,42000L,\n42001L,42002L,42003L,42004L,42005L,42006L,42007L,42008L,42009L,42010L,\n42011L,42012L,42013L,42014L,42015L,42016L,42017L,42018L,42019L,42020L,\n42021L,42022L,42023L,42024L,42025L,42026L,42027L,42028L,42029L,42030L,\n42031L,42032L,42033L,42034L,42035L,42036L,42037L,42038L,42039L,42040L,\n42041L,42042L,42043L,42044L,42045L,42046L,42047L,42048L,42049L,42050L,\n42051L,42052L,42053L,42054L,42055L,42056L,42057L,42058L,42059L,42060L,\n42061L,42062L,42063L,42064L,42065L,42066L,42067L,42068L,42069L,42070L,\n42071L,42072L,42073L,42074L,42075L,42076L,42077L,42078L,42079L,42080L,\n42081L,42082L,42083L,42084L,42085L,42086L,42087L,42088L,42089L,42090L,\n42091L,42092L,42093L,42094L,42095L,42096L,42097L,42098L,42099L,42100L,\n42101L,42102L,42103L,42104L,42105L,42106L,42107L,42108L,42109L,42110L,\n42111L,42112L,42113L,42114L,42115L,42116L,42117L,42118L,42119L,42120L,\n42121L,42122L,42123L,42124L,42125L,42126L,42127L,42128L,42129L,42130L,\n42131L,42132L,42133L,42134L,42135L,42136L,42137L,42138L,42139L,42140L,\n42141L,42142L,42143L,42144L,42145L,42146L,42147L,42148L,42149L,42150L,\n42151L,42152L,42153L,42154L,42155L,42156L,42157L,42158L,42159L,42160L,\n42161L,42162L,42163L,42164L,42165L,42166L,42167L,42168L,42169L,42170L,\n42171L,42172L,42173L,42174L,42175L,42176L,42177L,42178L,42179L,42180L,\n42181L,42182L,42183L,42184L,42185L,42186L,42187L,42188L,42189L,42190L,\n42191L,42192L,42193L,42194L,42195L,42196L,42197L,42198L,42199L,42200L,\n42201L,42202L,42203L,42204L,42205L,42206L,42207L,42208L,42209L,42210L,\n42211L,42212L,42213L,42214L,42215L,42216L,42217L,42218L,42219L,42220L,\n42221L,42222L,42223L,42224L,42225L,42226L,42227L,42228L,42229L,42230L,\n42231L,42232L,42233L,42234L,42235L,42236L,42237L,42238L,42239L,42240L,\n42241L,42242L,42243L,42244L,42245L,42246L,42247L,42248L,42249L,42250L,\n42251L,42252L,42253L,42254L,42255L,42256L,42257L,42258L,42259L,42260L,\n42261L,42262L,42263L,42264L,42265L,42266L,42267L,42268L,42269L,42270L,\n42271L,42272L,42273L,42274L,42275L,42276L,42277L,42278L,42279L,42280L,\n42281L,42282L,42283L,42284L,42285L,42286L,42287L,42288L,42289L,42290L,\n42291L,42292L,42293L,42294L,42295L,42296L,42297L,42298L,42299L,42300L,\n42301L,42302L,42303L,42304L,42305L,42306L,42307L,42308L,42309L,42310L,\n42311L,42312L,42313L,42314L,42315L,42316L,42317L,42318L,42319L,42320L,\n42321L,42322L,42323L,42324L,42325L,42326L,42327L,42328L,42329L,42330L,\n42331L,42332L,42333L,42334L,42335L,42336L,42337L,42338L,42339L,42340L,\n42341L,42342L,42343L,42344L,42345L,42346L,42347L,42348L,42349L,42350L,\n42351L,42352L,42353L,42354L,42355L,42356L,42357L,42358L,42359L,42360L,\n42361L,42362L,42363L,42364L,42365L,42366L,42367L,42368L,42369L,42370L,\n42371L,42372L,42373L,42374L,42375L,42376L,42377L,42378L,42379L,42380L,\n42381L,42382L,42383L,42384L,42385L,42386L,42387L,42388L,42389L,42390L,\n42391L,42392L,42393L,42394L,42395L,42396L,42397L,42398L,42399L,42400L,\n42401L,42402L,42403L,42404L,42405L,42406L,42407L,42408L,42409L,42410L,\n42411L,42412L,42413L,42414L,42415L,42416L,42417L,42418L,42419L,42420L,\n42421L,42422L,42423L,42424L,42425L,42426L,42427L,42428L,42429L,42430L,\n42431L,42432L,42433L,42434L,42435L,42436L,42437L,42438L,42439L,42440L,\n42441L,42442L,42443L,42444L,42445L,42446L,42447L,42448L,42449L,42450L,\n42451L,42452L,42453L,42454L,42455L,42456L,42457L,42458L,42459L,42460L,\n42461L,42462L,42463L,42464L,42465L,42466L,42467L,42468L,42469L,42470L,\n42471L,42472L,42473L,42474L,42475L,42476L,42477L,42478L,42479L,42480L,\n42481L,42482L,42483L,42484L,42485L,42486L,42487L,42488L,42489L,42490L,\n42491L,42492L,42493L,42494L,42495L,42496L,42497L,42498L,42499L,42500L,\n42501L,42502L,42503L,42504L,42505L,42506L,42507L,42508L,42509L,42510L,\n42511L,42512L,42513L,42514L,42515L,42516L,42517L,42518L,42519L,42520L,\n42521L,42522L,42523L,42524L,42525L,42526L,42527L,42528L,42529L,42530L,\n42531L,42532L,42533L,42534L,42535L,42536L,42537L,42538L,42539L,42540L,\n42541L,42542L,42543L,42544L,42545L,42546L,42547L,42548L,42549L,42550L,\n42551L,42552L,42553L,42554L,42555L,42556L,42557L,42558L,42559L,42560L,\n42560L,42562L,42562L,42564L,42564L,42566L,42566L,42568L,42568L,42570L,\n42570L,42572L,42572L,42574L,42574L,42576L,42576L,42578L,42578L,42580L,\n42580L,42582L,42582L,42584L,42584L,42586L,42586L,42588L,42588L,42590L,\n42590L,42592L,42592L,42594L,42594L,42596L,42596L,42598L,42598L,42600L,\n42600L,42602L,42602L,42604L,42604L,42606L,42607L,42608L,42609L,42610L,\n42611L,42612L,42613L,42614L,42615L,42616L,42617L,42618L,42619L,42620L,\n42621L,42622L,42623L,42624L,42624L,42626L,42626L,42628L,42628L,42630L,\n42630L,42632L,42632L,42634L,42634L,42636L,42636L,42638L,42638L,42640L,\n42640L,42642L,42642L,42644L,42644L,42646L,42646L,42648L,42648L,42650L,\n42650L,42652L,42653L,42654L,42655L,42656L,42657L,42658L,42659L,42660L,\n42661L,42662L,42663L,42664L,42665L,42666L,42667L,42668L,42669L,42670L,\n42671L,42672L,42673L,42674L,42675L,42676L,42677L,42678L,42679L,42680L,\n42681L,42682L,42683L,42684L,42685L,42686L,42687L,42688L,42689L,42690L,\n42691L,42692L,42693L,42694L,42695L,42696L,42697L,42698L,42699L,42700L,\n42701L,42702L,42703L,42704L,42705L,42706L,42707L,42708L,42709L,42710L,\n42711L,42712L,42713L,42714L,42715L,42716L,42717L,42718L,42719L,42720L,\n42721L,42722L,42723L,42724L,42725L,42726L,42727L,42728L,42729L,42730L,\n42731L,42732L,42733L,42734L,42735L,42736L,42737L,42738L,42739L,42740L,\n42741L,42742L,42743L,42744L,42745L,42746L,42747L,42748L,42749L,42750L,\n42751L,42752L,42753L,42754L,42755L,42756L,42757L,42758L,42759L,42760L,\n42761L,42762L,42763L,42764L,42765L,42766L,42767L,42768L,42769L,42770L,\n42771L,42772L,42773L,42774L,42775L,42776L,42777L,42778L,42779L,42780L,\n42781L,42782L,42783L,42784L,42785L,42786L,42786L,42788L,42788L,42790L,\n42790L,42792L,42792L,42794L,42794L,42796L,42796L,42798L,42798L,42800L,\n42801L,42802L,42802L,42804L,42804L,42806L,42806L,42808L,42808L,42810L,\n42810L,42812L,42812L,42814L,42814L,42816L,42816L,42818L,42818L,42820L,\n42820L,42822L,42822L,42824L,42824L,42826L,42826L,42828L,42828L,42830L,\n42830L,42832L,42832L,42834L,42834L,42836L,42836L,42838L,42838L,42840L,\n42840L,42842L,42842L,42844L,42844L,42846L,42846L,42848L,42848L,42850L,\n42850L,42852L,42852L,42854L,42854L,42856L,42856L,42858L,42858L,42860L,\n42860L,42862L,42862L,42864L,42865L,42866L,42867L,42868L,42869L,42870L,\n42871L,42872L,42873L,42873L,42875L,42875L,42877L,42878L,42878L,42880L,\n42880L,42882L,42882L,42884L,42884L,42886L,42886L,42888L,42889L,42890L,\n42891L,42891L,42893L,42894L,42895L,42896L,42896L,42898L,42898L,42900L,\n42901L,42902L,42902L,42904L,42904L,42906L,42906L,42908L,42908L,42910L,\n42910L,42912L,42912L,42914L,42914L,42916L,42916L,42918L,42918L,42920L,\n42920L,42922L,42923L,42924L,42925L,42926L,42927L,42928L,42929L,42930L,\n42931L,42932L,42932L,42934L,42934L,42936L,42937L,42938L,42939L,42940L,\n42941L,42942L,42943L,42944L,42945L,42946L,42947L,42948L,42949L,42950L,\n42951L,42952L,42953L,42954L,42955L,42956L,42957L,42958L,42959L,42960L,\n42961L,42962L,42963L,42964L,42965L,42966L,42967L,42968L,42969L,42970L,\n42971L,42972L,42973L,42974L,42975L,42976L,42977L,42978L,42979L,42980L,\n42981L,42982L,42983L,42984L,42985L,42986L,42987L,42988L,42989L,42990L,\n42991L,42992L,42993L,42994L,42995L,42996L,42997L,42998L,42999L,43000L,\n43001L,43002L,43003L,43004L,43005L,43006L,43007L,43008L,43009L,43010L,\n43011L,43012L,43013L,43014L,43015L,43016L,43017L,43018L,43019L,43020L,\n43021L,43022L,43023L,43024L,43025L,43026L,43027L,43028L,43029L,43030L,\n43031L,43032L,43033L,43034L,43035L,43036L,43037L,43038L,43039L,43040L,\n43041L,43042L,43043L,43044L,43045L,43046L,43047L,43048L,43049L,43050L,\n43051L,43052L,43053L,43054L,43055L,43056L,43057L,43058L,43059L,43060L,\n43061L,43062L,43063L,43064L,43065L,43066L,43067L,43068L,43069L,43070L,\n43071L,43072L,43073L,43074L,43075L,43076L,43077L,43078L,43079L,43080L,\n43081L,43082L,43083L,43084L,43085L,43086L,43087L,43088L,43089L,43090L,\n43091L,43092L,43093L,43094L,43095L,43096L,43097L,43098L,43099L,43100L,\n43101L,43102L,43103L,43104L,43105L,43106L,43107L,43108L,43109L,43110L,\n43111L,43112L,43113L,43114L,43115L,43116L,43117L,43118L,43119L,43120L,\n43121L,43122L,43123L,43124L,43125L,43126L,43127L,43128L,43129L,43130L,\n43131L,43132L,43133L,43134L,43135L,43136L,43137L,43138L,43139L,43140L,\n43141L,43142L,43143L,43144L,43145L,43146L,43147L,43148L,43149L,43150L,\n43151L,43152L,43153L,43154L,43155L,43156L,43157L,43158L,43159L,43160L,\n43161L,43162L,43163L,43164L,43165L,43166L,43167L,43168L,43169L,43170L,\n43171L,43172L,43173L,43174L,43175L,43176L,43177L,43178L,43179L,43180L,\n43181L,43182L,43183L,43184L,43185L,43186L,43187L,43188L,43189L,43190L,\n43191L,43192L,43193L,43194L,43195L,43196L,43197L,43198L,43199L,43200L,\n43201L,43202L,43203L,43204L,43205L,43206L,43207L,43208L,43209L,43210L,\n43211L,43212L,43213L,43214L,43215L,43216L,43217L,43218L,43219L,43220L,\n43221L,43222L,43223L,43224L,43225L,43226L,43227L,43228L,43229L,43230L,\n43231L,43232L,43233L,43234L,43235L,43236L,43237L,43238L,43239L,43240L,\n43241L,43242L,43243L,43244L,43245L,43246L,43247L,43248L,43249L,43250L,\n43251L,43252L,43253L,43254L,43255L,43256L,43257L,43258L,43259L,43260L,\n43261L,43262L,43263L,43264L,43265L,43266L,43267L,43268L,43269L,43270L,\n43271L,43272L,43273L,43274L,43275L,43276L,43277L,43278L,43279L,43280L,\n43281L,43282L,43283L,43284L,43285L,43286L,43287L,43288L,43289L,43290L,\n43291L,43292L,43293L,43294L,43295L,43296L,43297L,43298L,43299L,43300L,\n43301L,43302L,43303L,43304L,43305L,43306L,43307L,43308L,43309L,43310L,\n43311L,43312L,43313L,43314L,43315L,43316L,43317L,43318L,43319L,43320L,\n43321L,43322L,43323L,43324L,43325L,43326L,43327L,43328L,43329L,43330L,\n43331L,43332L,43333L,43334L,43335L,43336L,43337L,43338L,43339L,43340L,\n43341L,43342L,43343L,43344L,43345L,43346L,43347L,43348L,43349L,43350L,\n43351L,43352L,43353L,43354L,43355L,43356L,43357L,43358L,43359L,43360L,\n43361L,43362L,43363L,43364L,43365L,43366L,43367L,43368L,43369L,43370L,\n43371L,43372L,43373L,43374L,43375L,43376L,43377L,43378L,43379L,43380L,\n43381L,43382L,43383L,43384L,43385L,43386L,43387L,43388L,43389L,43390L,\n43391L,43392L,43393L,43394L,43395L,43396L,43397L,43398L,43399L,43400L,\n43401L,43402L,43403L,43404L,43405L,43406L,43407L,43408L,43409L,43410L,\n43411L,43412L,43413L,43414L,43415L,43416L,43417L,43418L,43419L,43420L,\n43421L,43422L,43423L,43424L,43425L,43426L,43427L,43428L,43429L,43430L,\n43431L,43432L,43433L,43434L,43435L,43436L,43437L,43438L,43439L,43440L,\n43441L,43442L,43443L,43444L,43445L,43446L,43447L,43448L,43449L,43450L,\n43451L,43452L,43453L,43454L,43455L,43456L,43457L,43458L,43459L,43460L,\n43461L,43462L,43463L,43464L,43465L,43466L,43467L,43468L,43469L,43470L,\n43471L,43472L,43473L,43474L,43475L,43476L,43477L,43478L,43479L,43480L,\n43481L,43482L,43483L,43484L,43485L,43486L,43487L,43488L,43489L,43490L,\n43491L,43492L,43493L,43494L,43495L,43496L,43497L,43498L,43499L,43500L,\n43501L,43502L,43503L,43504L,43505L,43506L,43507L,43508L,43509L,43510L,\n43511L,43512L,43513L,43514L,43515L,43516L,43517L,43518L,43519L,43520L,\n43521L,43522L,43523L,43524L,43525L,43526L,43527L,43528L,43529L,43530L,\n43531L,43532L,43533L,43534L,43535L,43536L,43537L,43538L,43539L,43540L,\n43541L,43542L,43543L,43544L,43545L,43546L,43547L,43548L,43549L,43550L,\n43551L,43552L,43553L,43554L,43555L,43556L,43557L,43558L,43559L,43560L,\n43561L,43562L,43563L,43564L,43565L,43566L,43567L,43568L,43569L,43570L,\n43571L,43572L,43573L,43574L,43575L,43576L,43577L,43578L,43579L,43580L,\n43581L,43582L,43583L,43584L,43585L,43586L,43587L,43588L,43589L,43590L,\n43591L,43592L,43593L,43594L,43595L,43596L,43597L,43598L,43599L,43600L,\n43601L,43602L,43603L,43604L,43605L,43606L,43607L,43608L,43609L,43610L,\n43611L,43612L,43613L,43614L,43615L,43616L,43617L,43618L,43619L,43620L,\n43621L,43622L,43623L,43624L,43625L,43626L,43627L,43628L,43629L,43630L,\n43631L,43632L,43633L,43634L,43635L,43636L,43637L,43638L,43639L,43640L,\n43641L,43642L,43643L,43644L,43645L,43646L,43647L,43648L,43649L,43650L,\n43651L,43652L,43653L,43654L,43655L,43656L,43657L,43658L,43659L,43660L,\n43661L,43662L,43663L,43664L,43665L,43666L,43667L,43668L,43669L,43670L,\n43671L,43672L,43673L,43674L,43675L,43676L,43677L,43678L,43679L,43680L,\n43681L,43682L,43683L,43684L,43685L,43686L,43687L,43688L,43689L,43690L,\n43691L,43692L,43693L,43694L,43695L,43696L,43697L,43698L,43699L,43700L,\n43701L,43702L,43703L,43704L,43705L,43706L,43707L,43708L,43709L,43710L,\n43711L,43712L,43713L,43714L,43715L,43716L,43717L,43718L,43719L,43720L,\n43721L,43722L,43723L,43724L,43725L,43726L,43727L,43728L,43729L,43730L,\n43731L,43732L,43733L,43734L,43735L,43736L,43737L,43738L,43739L,43740L,\n43741L,43742L,43743L,43744L,43745L,43746L,43747L,43748L,43749L,43750L,\n43751L,43752L,43753L,43754L,43755L,43756L,43757L,43758L,43759L,43760L,\n43761L,43762L,43763L,43764L,43765L,43766L,43767L,43768L,43769L,43770L,\n43771L,43772L,43773L,43774L,43775L,43776L,43777L,43778L,43779L,43780L,\n43781L,43782L,43783L,43784L,43785L,43786L,43787L,43788L,43789L,43790L,\n43791L,43792L,43793L,43794L,43795L,43796L,43797L,43798L,43799L,43800L,\n43801L,43802L,43803L,43804L,43805L,43806L,43807L,43808L,43809L,43810L,\n43811L,43812L,43813L,43814L,43815L,43816L,43817L,43818L,43819L,43820L,\n43821L,43822L,43823L,43824L,43825L,43826L,43827L,43828L,43829L,43830L,\n43831L,43832L,43833L,43834L,43835L,43836L,43837L,43838L,43839L,43840L,\n43841L,43842L,43843L,43844L,43845L,43846L,43847L,43848L,43849L,43850L,\n43851L,43852L,43853L,43854L,43855L,43856L,43857L,43858L,42931L,43860L,\n43861L,43862L,43863L,43864L,43865L,43866L,43867L,43868L,43869L,43870L,\n43871L,43872L,43873L,43874L,43875L,43876L,43877L,43878L,43879L,43880L,\n43881L,43882L,43883L,43884L,43885L,43886L,43887L,5024,5025,5026,5027,5028,\n5029,5030,5031,5032,5033,5034,5035,5036,5037,5038,5039,5040,5041,5042,5043,\n5044,5045,5046,5047,5048,5049,5050,5051,5052,5053,5054,5055,5056,5057,5058,\n5059,5060,5061,5062,5063,5064,5065,5066,5067,5068,5069,5070,5071,5072,5073,\n5074,5075,5076,5077,5078,5079,5080,5081,5082,5083,5084,5085,5086,5087,5088,\n5089,5090,5091,5092,5093,5094,5095,5096,5097,5098,5099,5100,5101,5102,5103,\n43968L,43969L,43970L,43971L,43972L,43973L,43974L,43975L,43976L,43977L,\n43978L,43979L,43980L,43981L,43982L,43983L,43984L,43985L,43986L,43987L,\n43988L,43989L,43990L,43991L,43992L,43993L,43994L,43995L,43996L,43997L,\n43998L,43999L,44000L,44001L,44002L,44003L,44004L,44005L,44006L,44007L,\n44008L,44009L,44010L,44011L,44012L,44013L,44014L,44015L,44016L,44017L,\n44018L,44019L,44020L,44021L,44022L,44023L,44024L,44025L,44026L,44027L,\n44028L,44029L,44030L,44031L,44032L,44033L,44034L,44035L,44036L,44037L,\n44038L,44039L,44040L,44041L,44042L,44043L,44044L,44045L,44046L,44047L,\n44048L,44049L,44050L,44051L,44052L,44053L,44054L,44055L,44056L,44057L,\n44058L,44059L,44060L,44061L,44062L,44063L,44064L,44065L,44066L,44067L,\n44068L,44069L,44070L,44071L,44072L,44073L,44074L,44075L,44076L,44077L,\n44078L,44079L,44080L,44081L,44082L,44083L,44084L,44085L,44086L,44087L,\n44088L,44089L,44090L,44091L,44092L,44093L,44094L,44095L,44096L,44097L,\n44098L,44099L,44100L,44101L,44102L,44103L,44104L,44105L,44106L,44107L,\n44108L,44109L,44110L,44111L,44112L,44113L,44114L,44115L,44116L,44117L,\n44118L,44119L,44120L,44121L,44122L,44123L,44124L,44125L,44126L,44127L,\n44128L,44129L,44130L,44131L,44132L,44133L,44134L,44135L,44136L,44137L,\n44138L,44139L,44140L,44141L,44142L,44143L,44144L,44145L,44146L,44147L,\n44148L,44149L,44150L,44151L,44152L,44153L,44154L,44155L,44156L,44157L,\n44158L,44159L,44160L,44161L,44162L,44163L,44164L,44165L,44166L,44167L,\n44168L,44169L,44170L,44171L,44172L,44173L,44174L,44175L,44176L,44177L,\n44178L,44179L,44180L,44181L,44182L,44183L,44184L,44185L,44186L,44187L,\n44188L,44189L,44190L,44191L,44192L,44193L,44194L,44195L,44196L,44197L,\n44198L,44199L,44200L,44201L,44202L,44203L,44204L,44205L,44206L,44207L,\n44208L,44209L,44210L,44211L,44212L,44213L,44214L,44215L,44216L,44217L,\n44218L,44219L,44220L,44221L,44222L,44223L,44224L,44225L,44226L,44227L,\n44228L,44229L,44230L,44231L,44232L,44233L,44234L,44235L,44236L,44237L,\n44238L,44239L,44240L,44241L,44242L,44243L,44244L,44245L,44246L,44247L,\n44248L,44249L,44250L,44251L,44252L,44253L,44254L,44255L,44256L,44257L,\n44258L,44259L,44260L,44261L,44262L,44263L,44264L,44265L,44266L,44267L,\n44268L,44269L,44270L,44271L,44272L,44273L,44274L,44275L,44276L,44277L,\n44278L,44279L,44280L,44281L,44282L,44283L,44284L,44285L,44286L,44287L,\n44288L,44289L,44290L,44291L,44292L,44293L,44294L,44295L,44296L,44297L,\n44298L,44299L,44300L,44301L,44302L,44303L,44304L,44305L,44306L,44307L,\n44308L,44309L,44310L,44311L,44312L,44313L,44314L,44315L,44316L,44317L,\n44318L,44319L,44320L,44321L,44322L,44323L,44324L,44325L,44326L,44327L,\n44328L,44329L,44330L,44331L,44332L,44333L,44334L,44335L,44336L,44337L,\n44338L,44339L,44340L,44341L,44342L,44343L,44344L,44345L,44346L,44347L,\n44348L,44349L,44350L,44351L,44352L,44353L,44354L,44355L,44356L,44357L,\n44358L,44359L,44360L,44361L,44362L,44363L,44364L,44365L,44366L,44367L,\n44368L,44369L,44370L,44371L,44372L,44373L,44374L,44375L,44376L,44377L,\n44378L,44379L,44380L,44381L,44382L,44383L,44384L,44385L,44386L,44387L,\n44388L,44389L,44390L,44391L,44392L,44393L,44394L,44395L,44396L,44397L,\n44398L,44399L,44400L,44401L,44402L,44403L,44404L,44405L,44406L,44407L,\n44408L,44409L,44410L,44411L,44412L,44413L,44414L,44415L,44416L,44417L,\n44418L,44419L,44420L,44421L,44422L,44423L,44424L,44425L,44426L,44427L,\n44428L,44429L,44430L,44431L,44432L,44433L,44434L,44435L,44436L,44437L,\n44438L,44439L,44440L,44441L,44442L,44443L,44444L,44445L,44446L,44447L,\n44448L,44449L,44450L,44451L,44452L,44453L,44454L,44455L,44456L,44457L,\n44458L,44459L,44460L,44461L,44462L,44463L,44464L,44465L,44466L,44467L,\n44468L,44469L,44470L,44471L,44472L,44473L,44474L,44475L,44476L,44477L,\n44478L,44479L,44480L,44481L,44482L,44483L,44484L,44485L,44486L,44487L,\n44488L,44489L,44490L,44491L,44492L,44493L,44494L,44495L,44496L,44497L,\n44498L,44499L,44500L,44501L,44502L,44503L,44504L,44505L,44506L,44507L,\n44508L,44509L,44510L,44511L,44512L,44513L,44514L,44515L,44516L,44517L,\n44518L,44519L,44520L,44521L,44522L,44523L,44524L,44525L,44526L,44527L,\n44528L,44529L,44530L,44531L,44532L,44533L,44534L,44535L,44536L,44537L,\n44538L,44539L,44540L,44541L,44542L,44543L,44544L,44545L,44546L,44547L,\n44548L,44549L,44550L,44551L,44552L,44553L,44554L,44555L,44556L,44557L,\n44558L,44559L,44560L,44561L,44562L,44563L,44564L,44565L,44566L,44567L,\n44568L,44569L,44570L,44571L,44572L,44573L,44574L,44575L,44576L,44577L,\n44578L,44579L,44580L,44581L,44582L,44583L,44584L,44585L,44586L,44587L,\n44588L,44589L,44590L,44591L,44592L,44593L,44594L,44595L,44596L,44597L,\n44598L,44599L,44600L,44601L,44602L,44603L,44604L,44605L,44606L,44607L,\n44608L,44609L,44610L,44611L,44612L,44613L,44614L,44615L,44616L,44617L,\n44618L,44619L,44620L,44621L,44622L,44623L,44624L,44625L,44626L,44627L,\n44628L,44629L,44630L,44631L,44632L,44633L,44634L,44635L,44636L,44637L,\n44638L,44639L,44640L,44641L,44642L,44643L,44644L,44645L,44646L,44647L,\n44648L,44649L,44650L,44651L,44652L,44653L,44654L,44655L,44656L,44657L,\n44658L,44659L,44660L,44661L,44662L,44663L,44664L,44665L,44666L,44667L,\n44668L,44669L,44670L,44671L,44672L,44673L,44674L,44675L,44676L,44677L,\n44678L,44679L,44680L,44681L,44682L,44683L,44684L,44685L,44686L,44687L,\n44688L,44689L,44690L,44691L,44692L,44693L,44694L,44695L,44696L,44697L,\n44698L,44699L,44700L,44701L,44702L,44703L,44704L,44705L,44706L,44707L,\n44708L,44709L,44710L,44711L,44712L,44713L,44714L,44715L,44716L,44717L,\n44718L,44719L,44720L,44721L,44722L,44723L,44724L,44725L,44726L,44727L,\n44728L,44729L,44730L,44731L,44732L,44733L,44734L,44735L,44736L,44737L,\n44738L,44739L,44740L,44741L,44742L,44743L,44744L,44745L,44746L,44747L,\n44748L,44749L,44750L,44751L,44752L,44753L,44754L,44755L,44756L,44757L,\n44758L,44759L,44760L,44761L,44762L,44763L,44764L,44765L,44766L,44767L,\n44768L,44769L,44770L,44771L,44772L,44773L,44774L,44775L,44776L,44777L,\n44778L,44779L,44780L,44781L,44782L,44783L,44784L,44785L,44786L,44787L,\n44788L,44789L,44790L,44791L,44792L,44793L,44794L,44795L,44796L,44797L,\n44798L,44799L,44800L,44801L,44802L,44803L,44804L,44805L,44806L,44807L,\n44808L,44809L,44810L,44811L,44812L,44813L,44814L,44815L,44816L,44817L,\n44818L,44819L,44820L,44821L,44822L,44823L,44824L,44825L,44826L,44827L,\n44828L,44829L,44830L,44831L,44832L,44833L,44834L,44835L,44836L,44837L,\n44838L,44839L,44840L,44841L,44842L,44843L,44844L,44845L,44846L,44847L,\n44848L,44849L,44850L,44851L,44852L,44853L,44854L,44855L,44856L,44857L,\n44858L,44859L,44860L,44861L,44862L,44863L,44864L,44865L,44866L,44867L,\n44868L,44869L,44870L,44871L,44872L,44873L,44874L,44875L,44876L,44877L,\n44878L,44879L,44880L,44881L,44882L,44883L,44884L,44885L,44886L,44887L,\n44888L,44889L,44890L,44891L,44892L,44893L,44894L,44895L,44896L,44897L,\n44898L,44899L,44900L,44901L,44902L,44903L,44904L,44905L,44906L,44907L,\n44908L,44909L,44910L,44911L,44912L,44913L,44914L,44915L,44916L,44917L,\n44918L,44919L,44920L,44921L,44922L,44923L,44924L,44925L,44926L,44927L,\n44928L,44929L,44930L,44931L,44932L,44933L,44934L,44935L,44936L,44937L,\n44938L,44939L,44940L,44941L,44942L,44943L,44944L,44945L,44946L,44947L,\n44948L,44949L,44950L,44951L,44952L,44953L,44954L,44955L,44956L,44957L,\n44958L,44959L,44960L,44961L,44962L,44963L,44964L,44965L,44966L,44967L,\n44968L,44969L,44970L,44971L,44972L,44973L,44974L,44975L,44976L,44977L,\n44978L,44979L,44980L,44981L,44982L,44983L,44984L,44985L,44986L,44987L,\n44988L,44989L,44990L,44991L,44992L,44993L,44994L,44995L,44996L,44997L,\n44998L,44999L,45000L,45001L,45002L,45003L,45004L,45005L,45006L,45007L,\n45008L,45009L,45010L,45011L,45012L,45013L,45014L,45015L,45016L,45017L,\n45018L,45019L,45020L,45021L,45022L,45023L,45024L,45025L,45026L,45027L,\n45028L,45029L,45030L,45031L,45032L,45033L,45034L,45035L,45036L,45037L,\n45038L,45039L,45040L,45041L,45042L,45043L,45044L,45045L,45046L,45047L,\n45048L,45049L,45050L,45051L,45052L,45053L,45054L,45055L,45056L,45057L,\n45058L,45059L,45060L,45061L,45062L,45063L,45064L,45065L,45066L,45067L,\n45068L,45069L,45070L,45071L,45072L,45073L,45074L,45075L,45076L,45077L,\n45078L,45079L,45080L,45081L,45082L,45083L,45084L,45085L,45086L,45087L,\n45088L,45089L,45090L,45091L,45092L,45093L,45094L,45095L,45096L,45097L,\n45098L,45099L,45100L,45101L,45102L,45103L,45104L,45105L,45106L,45107L,\n45108L,45109L,45110L,45111L,45112L,45113L,45114L,45115L,45116L,45117L,\n45118L,45119L,45120L,45121L,45122L,45123L,45124L,45125L,45126L,45127L,\n45128L,45129L,45130L,45131L,45132L,45133L,45134L,45135L,45136L,45137L,\n45138L,45139L,45140L,45141L,45142L,45143L,45144L,45145L,45146L,45147L,\n45148L,45149L,45150L,45151L,45152L,45153L,45154L,45155L,45156L,45157L,\n45158L,45159L,45160L,45161L,45162L,45163L,45164L,45165L,45166L,45167L,\n45168L,45169L,45170L,45171L,45172L,45173L,45174L,45175L,45176L,45177L,\n45178L,45179L,45180L,45181L,45182L,45183L,45184L,45185L,45186L,45187L,\n45188L,45189L,45190L,45191L,45192L,45193L,45194L,45195L,45196L,45197L,\n45198L,45199L,45200L,45201L,45202L,45203L,45204L,45205L,45206L,45207L,\n45208L,45209L,45210L,45211L,45212L,45213L,45214L,45215L,45216L,45217L,\n45218L,45219L,45220L,45221L,45222L,45223L,45224L,45225L,45226L,45227L,\n45228L,45229L,45230L,45231L,45232L,45233L,45234L,45235L,45236L,45237L,\n45238L,45239L,45240L,45241L,45242L,45243L,45244L,45245L,45246L,45247L,\n45248L,45249L,45250L,45251L,45252L,45253L,45254L,45255L,45256L,45257L,\n45258L,45259L,45260L,45261L,45262L,45263L,45264L,45265L,45266L,45267L,\n45268L,45269L,45270L,45271L,45272L,45273L,45274L,45275L,45276L,45277L,\n45278L,45279L,45280L,45281L,45282L,45283L,45284L,45285L,45286L,45287L,\n45288L,45289L,45290L,45291L,45292L,45293L,45294L,45295L,45296L,45297L,\n45298L,45299L,45300L,45301L,45302L,45303L,45304L,45305L,45306L,45307L,\n45308L,45309L,45310L,45311L,45312L,45313L,45314L,45315L,45316L,45317L,\n45318L,45319L,45320L,45321L,45322L,45323L,45324L,45325L,45326L,45327L,\n45328L,45329L,45330L,45331L,45332L,45333L,45334L,45335L,45336L,45337L,\n45338L,45339L,45340L,45341L,45342L,45343L,45344L,45345L,45346L,45347L,\n45348L,45349L,45350L,45351L,45352L,45353L,45354L,45355L,45356L,45357L,\n45358L,45359L,45360L,45361L,45362L,45363L,45364L,45365L,45366L,45367L,\n45368L,45369L,45370L,45371L,45372L,45373L,45374L,45375L,45376L,45377L,\n45378L,45379L,45380L,45381L,45382L,45383L,45384L,45385L,45386L,45387L,\n45388L,45389L,45390L,45391L,45392L,45393L,45394L,45395L,45396L,45397L,\n45398L,45399L,45400L,45401L,45402L,45403L,45404L,45405L,45406L,45407L,\n45408L,45409L,45410L,45411L,45412L,45413L,45414L,45415L,45416L,45417L,\n45418L,45419L,45420L,45421L,45422L,45423L,45424L,45425L,45426L,45427L,\n45428L,45429L,45430L,45431L,45432L,45433L,45434L,45435L,45436L,45437L,\n45438L,45439L,45440L,45441L,45442L,45443L,45444L,45445L,45446L,45447L,\n45448L,45449L,45450L,45451L,45452L,45453L,45454L,45455L,45456L,45457L,\n45458L,45459L,45460L,45461L,45462L,45463L,45464L,45465L,45466L,45467L,\n45468L,45469L,45470L,45471L,45472L,45473L,45474L,45475L,45476L,45477L,\n45478L,45479L,45480L,45481L,45482L,45483L,45484L,45485L,45486L,45487L,\n45488L,45489L,45490L,45491L,45492L,45493L,45494L,45495L,45496L,45497L,\n45498L,45499L,45500L,45501L,45502L,45503L,45504L,45505L,45506L,45507L,\n45508L,45509L,45510L,45511L,45512L,45513L,45514L,45515L,45516L,45517L,\n45518L,45519L,45520L,45521L,45522L,45523L,45524L,45525L,45526L,45527L,\n45528L,45529L,45530L,45531L,45532L,45533L,45534L,45535L,45536L,45537L,\n45538L,45539L,45540L,45541L,45542L,45543L,45544L,45545L,45546L,45547L,\n45548L,45549L,45550L,45551L,45552L,45553L,45554L,45555L,45556L,45557L,\n45558L,45559L,45560L,45561L,45562L,45563L,45564L,45565L,45566L,45567L,\n45568L,45569L,45570L,45571L,45572L,45573L,45574L,45575L,45576L,45577L,\n45578L,45579L,45580L,45581L,45582L,45583L,45584L,45585L,45586L,45587L,\n45588L,45589L,45590L,45591L,45592L,45593L,45594L,45595L,45596L,45597L,\n45598L,45599L,45600L,45601L,45602L,45603L,45604L,45605L,45606L,45607L,\n45608L,45609L,45610L,45611L,45612L,45613L,45614L,45615L,45616L,45617L,\n45618L,45619L,45620L,45621L,45622L,45623L,45624L,45625L,45626L,45627L,\n45628L,45629L,45630L,45631L,45632L,45633L,45634L,45635L,45636L,45637L,\n45638L,45639L,45640L,45641L,45642L,45643L,45644L,45645L,45646L,45647L,\n45648L,45649L,45650L,45651L,45652L,45653L,45654L,45655L,45656L,45657L,\n45658L,45659L,45660L,45661L,45662L,45663L,45664L,45665L,45666L,45667L,\n45668L,45669L,45670L,45671L,45672L,45673L,45674L,45675L,45676L,45677L,\n45678L,45679L,45680L,45681L,45682L,45683L,45684L,45685L,45686L,45687L,\n45688L,45689L,45690L,45691L,45692L,45693L,45694L,45695L,45696L,45697L,\n45698L,45699L,45700L,45701L,45702L,45703L,45704L,45705L,45706L,45707L,\n45708L,45709L,45710L,45711L,45712L,45713L,45714L,45715L,45716L,45717L,\n45718L,45719L,45720L,45721L,45722L,45723L,45724L,45725L,45726L,45727L,\n45728L,45729L,45730L,45731L,45732L,45733L,45734L,45735L,45736L,45737L,\n45738L,45739L,45740L,45741L,45742L,45743L,45744L,45745L,45746L,45747L,\n45748L,45749L,45750L,45751L,45752L,45753L,45754L,45755L,45756L,45757L,\n45758L,45759L,45760L,45761L,45762L,45763L,45764L,45765L,45766L,45767L,\n45768L,45769L,45770L,45771L,45772L,45773L,45774L,45775L,45776L,45777L,\n45778L,45779L,45780L,45781L,45782L,45783L,45784L,45785L,45786L,45787L,\n45788L,45789L,45790L,45791L,45792L,45793L,45794L,45795L,45796L,45797L,\n45798L,45799L,45800L,45801L,45802L,45803L,45804L,45805L,45806L,45807L,\n45808L,45809L,45810L,45811L,45812L,45813L,45814L,45815L,45816L,45817L,\n45818L,45819L,45820L,45821L,45822L,45823L,45824L,45825L,45826L,45827L,\n45828L,45829L,45830L,45831L,45832L,45833L,45834L,45835L,45836L,45837L,\n45838L,45839L,45840L,45841L,45842L,45843L,45844L,45845L,45846L,45847L,\n45848L,45849L,45850L,45851L,45852L,45853L,45854L,45855L,45856L,45857L,\n45858L,45859L,45860L,45861L,45862L,45863L,45864L,45865L,45866L,45867L,\n45868L,45869L,45870L,45871L,45872L,45873L,45874L,45875L,45876L,45877L,\n45878L,45879L,45880L,45881L,45882L,45883L,45884L,45885L,45886L,45887L,\n45888L,45889L,45890L,45891L,45892L,45893L,45894L,45895L,45896L,45897L,\n45898L,45899L,45900L,45901L,45902L,45903L,45904L,45905L,45906L,45907L,\n45908L,45909L,45910L,45911L,45912L,45913L,45914L,45915L,45916L,45917L,\n45918L,45919L,45920L,45921L,45922L,45923L,45924L,45925L,45926L,45927L,\n45928L,45929L,45930L,45931L,45932L,45933L,45934L,45935L,45936L,45937L,\n45938L,45939L,45940L,45941L,45942L,45943L,45944L,45945L,45946L,45947L,\n45948L,45949L,45950L,45951L,45952L,45953L,45954L,45955L,45956L,45957L,\n45958L,45959L,45960L,45961L,45962L,45963L,45964L,45965L,45966L,45967L,\n45968L,45969L,45970L,45971L,45972L,45973L,45974L,45975L,45976L,45977L,\n45978L,45979L,45980L,45981L,45982L,45983L,45984L,45985L,45986L,45987L,\n45988L,45989L,45990L,45991L,45992L,45993L,45994L,45995L,45996L,45997L,\n45998L,45999L,46000L,46001L,46002L,46003L,46004L,46005L,46006L,46007L,\n46008L,46009L,46010L,46011L,46012L,46013L,46014L,46015L,46016L,46017L,\n46018L,46019L,46020L,46021L,46022L,46023L,46024L,46025L,46026L,46027L,\n46028L,46029L,46030L,46031L,46032L,46033L,46034L,46035L,46036L,46037L,\n46038L,46039L,46040L,46041L,46042L,46043L,46044L,46045L,46046L,46047L,\n46048L,46049L,46050L,46051L,46052L,46053L,46054L,46055L,46056L,46057L,\n46058L,46059L,46060L,46061L,46062L,46063L,46064L,46065L,46066L,46067L,\n46068L,46069L,46070L,46071L,46072L,46073L,46074L,46075L,46076L,46077L,\n46078L,46079L,46080L,46081L,46082L,46083L,46084L,46085L,46086L,46087L,\n46088L,46089L,46090L,46091L,46092L,46093L,46094L,46095L,46096L,46097L,\n46098L,46099L,46100L,46101L,46102L,46103L,46104L,46105L,46106L,46107L,\n46108L,46109L,46110L,46111L,46112L,46113L,46114L,46115L,46116L,46117L,\n46118L,46119L,46120L,46121L,46122L,46123L,46124L,46125L,46126L,46127L,\n46128L,46129L,46130L,46131L,46132L,46133L,46134L,46135L,46136L,46137L,\n46138L,46139L,46140L,46141L,46142L,46143L,46144L,46145L,46146L,46147L,\n46148L,46149L,46150L,46151L,46152L,46153L,46154L,46155L,46156L,46157L,\n46158L,46159L,46160L,46161L,46162L,46163L,46164L,46165L,46166L,46167L,\n46168L,46169L,46170L,46171L,46172L,46173L,46174L,46175L,46176L,46177L,\n46178L,46179L,46180L,46181L,46182L,46183L,46184L,46185L,46186L,46187L,\n46188L,46189L,46190L,46191L,46192L,46193L,46194L,46195L,46196L,46197L,\n46198L,46199L,46200L,46201L,46202L,46203L,46204L,46205L,46206L,46207L,\n46208L,46209L,46210L,46211L,46212L,46213L,46214L,46215L,46216L,46217L,\n46218L,46219L,46220L,46221L,46222L,46223L,46224L,46225L,46226L,46227L,\n46228L,46229L,46230L,46231L,46232L,46233L,46234L,46235L,46236L,46237L,\n46238L,46239L,46240L,46241L,46242L,46243L,46244L,46245L,46246L,46247L,\n46248L,46249L,46250L,46251L,46252L,46253L,46254L,46255L,46256L,46257L,\n46258L,46259L,46260L,46261L,46262L,46263L,46264L,46265L,46266L,46267L,\n46268L,46269L,46270L,46271L,46272L,46273L,46274L,46275L,46276L,46277L,\n46278L,46279L,46280L,46281L,46282L,46283L,46284L,46285L,46286L,46287L,\n46288L,46289L,46290L,46291L,46292L,46293L,46294L,46295L,46296L,46297L,\n46298L,46299L,46300L,46301L,46302L,46303L,46304L,46305L,46306L,46307L,\n46308L,46309L,46310L,46311L,46312L,46313L,46314L,46315L,46316L,46317L,\n46318L,46319L,46320L,46321L,46322L,46323L,46324L,46325L,46326L,46327L,\n46328L,46329L,46330L,46331L,46332L,46333L,46334L,46335L,46336L,46337L,\n46338L,46339L,46340L,46341L,46342L,46343L,46344L,46345L,46346L,46347L,\n46348L,46349L,46350L,46351L,46352L,46353L,46354L,46355L,46356L,46357L,\n46358L,46359L,46360L,46361L,46362L,46363L,46364L,46365L,46366L,46367L,\n46368L,46369L,46370L,46371L,46372L,46373L,46374L,46375L,46376L,46377L,\n46378L,46379L,46380L,46381L,46382L,46383L,46384L,46385L,46386L,46387L,\n46388L,46389L,46390L,46391L,46392L,46393L,46394L,46395L,46396L,46397L,\n46398L,46399L,46400L,46401L,46402L,46403L,46404L,46405L,46406L,46407L,\n46408L,46409L,46410L,46411L,46412L,46413L,46414L,46415L,46416L,46417L,\n46418L,46419L,46420L,46421L,46422L,46423L,46424L,46425L,46426L,46427L,\n46428L,46429L,46430L,46431L,46432L,46433L,46434L,46435L,46436L,46437L,\n46438L,46439L,46440L,46441L,46442L,46443L,46444L,46445L,46446L,46447L,\n46448L,46449L,46450L,46451L,46452L,46453L,46454L,46455L,46456L,46457L,\n46458L,46459L,46460L,46461L,46462L,46463L,46464L,46465L,46466L,46467L,\n46468L,46469L,46470L,46471L,46472L,46473L,46474L,46475L,46476L,46477L,\n46478L,46479L,46480L,46481L,46482L,46483L,46484L,46485L,46486L,46487L,\n46488L,46489L,46490L,46491L,46492L,46493L,46494L,46495L,46496L,46497L,\n46498L,46499L,46500L,46501L,46502L,46503L,46504L,46505L,46506L,46507L,\n46508L,46509L,46510L,46511L,46512L,46513L,46514L,46515L,46516L,46517L,\n46518L,46519L,46520L,46521L,46522L,46523L,46524L,46525L,46526L,46527L,\n46528L,46529L,46530L,46531L,46532L,46533L,46534L,46535L,46536L,46537L,\n46538L,46539L,46540L,46541L,46542L,46543L,46544L,46545L,46546L,46547L,\n46548L,46549L,46550L,46551L,46552L,46553L,46554L,46555L,46556L,46557L,\n46558L,46559L,46560L,46561L,46562L,46563L,46564L,46565L,46566L,46567L,\n46568L,46569L,46570L,46571L,46572L,46573L,46574L,46575L,46576L,46577L,\n46578L,46579L,46580L,46581L,46582L,46583L,46584L,46585L,46586L,46587L,\n46588L,46589L,46590L,46591L,46592L,46593L,46594L,46595L,46596L,46597L,\n46598L,46599L,46600L,46601L,46602L,46603L,46604L,46605L,46606L,46607L,\n46608L,46609L,46610L,46611L,46612L,46613L,46614L,46615L,46616L,46617L,\n46618L,46619L,46620L,46621L,46622L,46623L,46624L,46625L,46626L,46627L,\n46628L,46629L,46630L,46631L,46632L,46633L,46634L,46635L,46636L,46637L,\n46638L,46639L,46640L,46641L,46642L,46643L,46644L,46645L,46646L,46647L,\n46648L,46649L,46650L,46651L,46652L,46653L,46654L,46655L,46656L,46657L,\n46658L,46659L,46660L,46661L,46662L,46663L,46664L,46665L,46666L,46667L,\n46668L,46669L,46670L,46671L,46672L,46673L,46674L,46675L,46676L,46677L,\n46678L,46679L,46680L,46681L,46682L,46683L,46684L,46685L,46686L,46687L,\n46688L,46689L,46690L,46691L,46692L,46693L,46694L,46695L,46696L,46697L,\n46698L,46699L,46700L,46701L,46702L,46703L,46704L,46705L,46706L,46707L,\n46708L,46709L,46710L,46711L,46712L,46713L,46714L,46715L,46716L,46717L,\n46718L,46719L,46720L,46721L,46722L,46723L,46724L,46725L,46726L,46727L,\n46728L,46729L,46730L,46731L,46732L,46733L,46734L,46735L,46736L,46737L,\n46738L,46739L,46740L,46741L,46742L,46743L,46744L,46745L,46746L,46747L,\n46748L,46749L,46750L,46751L,46752L,46753L,46754L,46755L,46756L,46757L,\n46758L,46759L,46760L,46761L,46762L,46763L,46764L,46765L,46766L,46767L,\n46768L,46769L,46770L,46771L,46772L,46773L,46774L,46775L,46776L,46777L,\n46778L,46779L,46780L,46781L,46782L,46783L,46784L,46785L,46786L,46787L,\n46788L,46789L,46790L,46791L,46792L,46793L,46794L,46795L,46796L,46797L,\n46798L,46799L,46800L,46801L,46802L,46803L,46804L,46805L,46806L,46807L,\n46808L,46809L,46810L,46811L,46812L,46813L,46814L,46815L,46816L,46817L,\n46818L,46819L,46820L,46821L,46822L,46823L,46824L,46825L,46826L,46827L,\n46828L,46829L,46830L,46831L,46832L,46833L,46834L,46835L,46836L,46837L,\n46838L,46839L,46840L,46841L,46842L,46843L,46844L,46845L,46846L,46847L,\n46848L,46849L,46850L,46851L,46852L,46853L,46854L,46855L,46856L,46857L,\n46858L,46859L,46860L,46861L,46862L,46863L,46864L,46865L,46866L,46867L,\n46868L,46869L,46870L,46871L,46872L,46873L,46874L,46875L,46876L,46877L,\n46878L,46879L,46880L,46881L,46882L,46883L,46884L,46885L,46886L,46887L,\n46888L,46889L,46890L,46891L,46892L,46893L,46894L,46895L,46896L,46897L,\n46898L,46899L,46900L,46901L,46902L,46903L,46904L,46905L,46906L,46907L,\n46908L,46909L,46910L,46911L,46912L,46913L,46914L,46915L,46916L,46917L,\n46918L,46919L,46920L,46921L,46922L,46923L,46924L,46925L,46926L,46927L,\n46928L,46929L,46930L,46931L,46932L,46933L,46934L,46935L,46936L,46937L,\n46938L,46939L,46940L,46941L,46942L,46943L,46944L,46945L,46946L,46947L,\n46948L,46949L,46950L,46951L,46952L,46953L,46954L,46955L,46956L,46957L,\n46958L,46959L,46960L,46961L,46962L,46963L,46964L,46965L,46966L,46967L,\n46968L,46969L,46970L,46971L,46972L,46973L,46974L,46975L,46976L,46977L,\n46978L,46979L,46980L,46981L,46982L,46983L,46984L,46985L,46986L,46987L,\n46988L,46989L,46990L,46991L,46992L,46993L,46994L,46995L,46996L,46997L,\n46998L,46999L,47000L,47001L,47002L,47003L,47004L,47005L,47006L,47007L,\n47008L,47009L,47010L,47011L,47012L,47013L,47014L,47015L,47016L,47017L,\n47018L,47019L,47020L,47021L,47022L,47023L,47024L,47025L,47026L,47027L,\n47028L,47029L,47030L,47031L,47032L,47033L,47034L,47035L,47036L,47037L,\n47038L,47039L,47040L,47041L,47042L,47043L,47044L,47045L,47046L,47047L,\n47048L,47049L,47050L,47051L,47052L,47053L,47054L,47055L,47056L,47057L,\n47058L,47059L,47060L,47061L,47062L,47063L,47064L,47065L,47066L,47067L,\n47068L,47069L,47070L,47071L,47072L,47073L,47074L,47075L,47076L,47077L,\n47078L,47079L,47080L,47081L,47082L,47083L,47084L,47085L,47086L,47087L,\n47088L,47089L,47090L,47091L,47092L,47093L,47094L,47095L,47096L,47097L,\n47098L,47099L,47100L,47101L,47102L,47103L,47104L,47105L,47106L,47107L,\n47108L,47109L,47110L,47111L,47112L,47113L,47114L,47115L,47116L,47117L,\n47118L,47119L,47120L,47121L,47122L,47123L,47124L,47125L,47126L,47127L,\n47128L,47129L,47130L,47131L,47132L,47133L,47134L,47135L,47136L,47137L,\n47138L,47139L,47140L,47141L,47142L,47143L,47144L,47145L,47146L,47147L,\n47148L,47149L,47150L,47151L,47152L,47153L,47154L,47155L,47156L,47157L,\n47158L,47159L,47160L,47161L,47162L,47163L,47164L,47165L,47166L,47167L,\n47168L,47169L,47170L,47171L,47172L,47173L,47174L,47175L,47176L,47177L,\n47178L,47179L,47180L,47181L,47182L,47183L,47184L,47185L,47186L,47187L,\n47188L,47189L,47190L,47191L,47192L,47193L,47194L,47195L,47196L,47197L,\n47198L,47199L,47200L,47201L,47202L,47203L,47204L,47205L,47206L,47207L,\n47208L,47209L,47210L,47211L,47212L,47213L,47214L,47215L,47216L,47217L,\n47218L,47219L,47220L,47221L,47222L,47223L,47224L,47225L,47226L,47227L,\n47228L,47229L,47230L,47231L,47232L,47233L,47234L,47235L,47236L,47237L,\n47238L,47239L,47240L,47241L,47242L,47243L,47244L,47245L,47246L,47247L,\n47248L,47249L,47250L,47251L,47252L,47253L,47254L,47255L,47256L,47257L,\n47258L,47259L,47260L,47261L,47262L,47263L,47264L,47265L,47266L,47267L,\n47268L,47269L,47270L,47271L,47272L,47273L,47274L,47275L,47276L,47277L,\n47278L,47279L,47280L,47281L,47282L,47283L,47284L,47285L,47286L,47287L,\n47288L,47289L,47290L,47291L,47292L,47293L,47294L,47295L,47296L,47297L,\n47298L,47299L,47300L,47301L,47302L,47303L,47304L,47305L,47306L,47307L,\n47308L,47309L,47310L,47311L,47312L,47313L,47314L,47315L,47316L,47317L,\n47318L,47319L,47320L,47321L,47322L,47323L,47324L,47325L,47326L,47327L,\n47328L,47329L,47330L,47331L,47332L,47333L,47334L,47335L,47336L,47337L,\n47338L,47339L,47340L,47341L,47342L,47343L,47344L,47345L,47346L,47347L,\n47348L,47349L,47350L,47351L,47352L,47353L,47354L,47355L,47356L,47357L,\n47358L,47359L,47360L,47361L,47362L,47363L,47364L,47365L,47366L,47367L,\n47368L,47369L,47370L,47371L,47372L,47373L,47374L,47375L,47376L,47377L,\n47378L,47379L,47380L,47381L,47382L,47383L,47384L,47385L,47386L,47387L,\n47388L,47389L,47390L,47391L,47392L,47393L,47394L,47395L,47396L,47397L,\n47398L,47399L,47400L,47401L,47402L,47403L,47404L,47405L,47406L,47407L,\n47408L,47409L,47410L,47411L,47412L,47413L,47414L,47415L,47416L,47417L,\n47418L,47419L,47420L,47421L,47422L,47423L,47424L,47425L,47426L,47427L,\n47428L,47429L,47430L,47431L,47432L,47433L,47434L,47435L,47436L,47437L,\n47438L,47439L,47440L,47441L,47442L,47443L,47444L,47445L,47446L,47447L,\n47448L,47449L,47450L,47451L,47452L,47453L,47454L,47455L,47456L,47457L,\n47458L,47459L,47460L,47461L,47462L,47463L,47464L,47465L,47466L,47467L,\n47468L,47469L,47470L,47471L,47472L,47473L,47474L,47475L,47476L,47477L,\n47478L,47479L,47480L,47481L,47482L,47483L,47484L,47485L,47486L,47487L,\n47488L,47489L,47490L,47491L,47492L,47493L,47494L,47495L,47496L,47497L,\n47498L,47499L,47500L,47501L,47502L,47503L,47504L,47505L,47506L,47507L,\n47508L,47509L,47510L,47511L,47512L,47513L,47514L,47515L,47516L,47517L,\n47518L,47519L,47520L,47521L,47522L,47523L,47524L,47525L,47526L,47527L,\n47528L,47529L,47530L,47531L,47532L,47533L,47534L,47535L,47536L,47537L,\n47538L,47539L,47540L,47541L,47542L,47543L,47544L,47545L,47546L,47547L,\n47548L,47549L,47550L,47551L,47552L,47553L,47554L,47555L,47556L,47557L,\n47558L,47559L,47560L,47561L,47562L,47563L,47564L,47565L,47566L,47567L,\n47568L,47569L,47570L,47571L,47572L,47573L,47574L,47575L,47576L,47577L,\n47578L,47579L,47580L,47581L,47582L,47583L,47584L,47585L,47586L,47587L,\n47588L,47589L,47590L,47591L,47592L,47593L,47594L,47595L,47596L,47597L,\n47598L,47599L,47600L,47601L,47602L,47603L,47604L,47605L,47606L,47607L,\n47608L,47609L,47610L,47611L,47612L,47613L,47614L,47615L,47616L,47617L,\n47618L,47619L,47620L,47621L,47622L,47623L,47624L,47625L,47626L,47627L,\n47628L,47629L,47630L,47631L,47632L,47633L,47634L,47635L,47636L,47637L,\n47638L,47639L,47640L,47641L,47642L,47643L,47644L,47645L,47646L,47647L,\n47648L,47649L,47650L,47651L,47652L,47653L,47654L,47655L,47656L,47657L,\n47658L,47659L,47660L,47661L,47662L,47663L,47664L,47665L,47666L,47667L,\n47668L,47669L,47670L,47671L,47672L,47673L,47674L,47675L,47676L,47677L,\n47678L,47679L,47680L,47681L,47682L,47683L,47684L,47685L,47686L,47687L,\n47688L,47689L,47690L,47691L,47692L,47693L,47694L,47695L,47696L,47697L,\n47698L,47699L,47700L,47701L,47702L,47703L,47704L,47705L,47706L,47707L,\n47708L,47709L,47710L,47711L,47712L,47713L,47714L,47715L,47716L,47717L,\n47718L,47719L,47720L,47721L,47722L,47723L,47724L,47725L,47726L,47727L,\n47728L,47729L,47730L,47731L,47732L,47733L,47734L,47735L,47736L,47737L,\n47738L,47739L,47740L,47741L,47742L,47743L,47744L,47745L,47746L,47747L,\n47748L,47749L,47750L,47751L,47752L,47753L,47754L,47755L,47756L,47757L,\n47758L,47759L,47760L,47761L,47762L,47763L,47764L,47765L,47766L,47767L,\n47768L,47769L,47770L,47771L,47772L,47773L,47774L,47775L,47776L,47777L,\n47778L,47779L,47780L,47781L,47782L,47783L,47784L,47785L,47786L,47787L,\n47788L,47789L,47790L,47791L,47792L,47793L,47794L,47795L,47796L,47797L,\n47798L,47799L,47800L,47801L,47802L,47803L,47804L,47805L,47806L,47807L,\n47808L,47809L,47810L,47811L,47812L,47813L,47814L,47815L,47816L,47817L,\n47818L,47819L,47820L,47821L,47822L,47823L,47824L,47825L,47826L,47827L,\n47828L,47829L,47830L,47831L,47832L,47833L,47834L,47835L,47836L,47837L,\n47838L,47839L,47840L,47841L,47842L,47843L,47844L,47845L,47846L,47847L,\n47848L,47849L,47850L,47851L,47852L,47853L,47854L,47855L,47856L,47857L,\n47858L,47859L,47860L,47861L,47862L,47863L,47864L,47865L,47866L,47867L,\n47868L,47869L,47870L,47871L,47872L,47873L,47874L,47875L,47876L,47877L,\n47878L,47879L,47880L,47881L,47882L,47883L,47884L,47885L,47886L,47887L,\n47888L,47889L,47890L,47891L,47892L,47893L,47894L,47895L,47896L,47897L,\n47898L,47899L,47900L,47901L,47902L,47903L,47904L,47905L,47906L,47907L,\n47908L,47909L,47910L,47911L,47912L,47913L,47914L,47915L,47916L,47917L,\n47918L,47919L,47920L,47921L,47922L,47923L,47924L,47925L,47926L,47927L,\n47928L,47929L,47930L,47931L,47932L,47933L,47934L,47935L,47936L,47937L,\n47938L,47939L,47940L,47941L,47942L,47943L,47944L,47945L,47946L,47947L,\n47948L,47949L,47950L,47951L,47952L,47953L,47954L,47955L,47956L,47957L,\n47958L,47959L,47960L,47961L,47962L,47963L,47964L,47965L,47966L,47967L,\n47968L,47969L,47970L,47971L,47972L,47973L,47974L,47975L,47976L,47977L,\n47978L,47979L,47980L,47981L,47982L,47983L,47984L,47985L,47986L,47987L,\n47988L,47989L,47990L,47991L,47992L,47993L,47994L,47995L,47996L,47997L,\n47998L,47999L,48000L,48001L,48002L,48003L,48004L,48005L,48006L,48007L,\n48008L,48009L,48010L,48011L,48012L,48013L,48014L,48015L,48016L,48017L,\n48018L,48019L,48020L,48021L,48022L,48023L,48024L,48025L,48026L,48027L,\n48028L,48029L,48030L,48031L,48032L,48033L,48034L,48035L,48036L,48037L,\n48038L,48039L,48040L,48041L,48042L,48043L,48044L,48045L,48046L,48047L,\n48048L,48049L,48050L,48051L,48052L,48053L,48054L,48055L,48056L,48057L,\n48058L,48059L,48060L,48061L,48062L,48063L,48064L,48065L,48066L,48067L,\n48068L,48069L,48070L,48071L,48072L,48073L,48074L,48075L,48076L,48077L,\n48078L,48079L,48080L,48081L,48082L,48083L,48084L,48085L,48086L,48087L,\n48088L,48089L,48090L,48091L,48092L,48093L,48094L,48095L,48096L,48097L,\n48098L,48099L,48100L,48101L,48102L,48103L,48104L,48105L,48106L,48107L,\n48108L,48109L,48110L,48111L,48112L,48113L,48114L,48115L,48116L,48117L,\n48118L,48119L,48120L,48121L,48122L,48123L,48124L,48125L,48126L,48127L,\n48128L,48129L,48130L,48131L,48132L,48133L,48134L,48135L,48136L,48137L,\n48138L,48139L,48140L,48141L,48142L,48143L,48144L,48145L,48146L,48147L,\n48148L,48149L,48150L,48151L,48152L,48153L,48154L,48155L,48156L,48157L,\n48158L,48159L,48160L,48161L,48162L,48163L,48164L,48165L,48166L,48167L,\n48168L,48169L,48170L,48171L,48172L,48173L,48174L,48175L,48176L,48177L,\n48178L,48179L,48180L,48181L,48182L,48183L,48184L,48185L,48186L,48187L,\n48188L,48189L,48190L,48191L,48192L,48193L,48194L,48195L,48196L,48197L,\n48198L,48199L,48200L,48201L,48202L,48203L,48204L,48205L,48206L,48207L,\n48208L,48209L,48210L,48211L,48212L,48213L,48214L,48215L,48216L,48217L,\n48218L,48219L,48220L,48221L,48222L,48223L,48224L,48225L,48226L,48227L,\n48228L,48229L,48230L,48231L,48232L,48233L,48234L,48235L,48236L,48237L,\n48238L,48239L,48240L,48241L,48242L,48243L,48244L,48245L,48246L,48247L,\n48248L,48249L,48250L,48251L,48252L,48253L,48254L,48255L,48256L,48257L,\n48258L,48259L,48260L,48261L,48262L,48263L,48264L,48265L,48266L,48267L,\n48268L,48269L,48270L,48271L,48272L,48273L,48274L,48275L,48276L,48277L,\n48278L,48279L,48280L,48281L,48282L,48283L,48284L,48285L,48286L,48287L,\n48288L,48289L,48290L,48291L,48292L,48293L,48294L,48295L,48296L,48297L,\n48298L,48299L,48300L,48301L,48302L,48303L,48304L,48305L,48306L,48307L,\n48308L,48309L,48310L,48311L,48312L,48313L,48314L,48315L,48316L,48317L,\n48318L,48319L,48320L,48321L,48322L,48323L,48324L,48325L,48326L,48327L,\n48328L,48329L,48330L,48331L,48332L,48333L,48334L,48335L,48336L,48337L,\n48338L,48339L,48340L,48341L,48342L,48343L,48344L,48345L,48346L,48347L,\n48348L,48349L,48350L,48351L,48352L,48353L,48354L,48355L,48356L,48357L,\n48358L,48359L,48360L,48361L,48362L,48363L,48364L,48365L,48366L,48367L,\n48368L,48369L,48370L,48371L,48372L,48373L,48374L,48375L,48376L,48377L,\n48378L,48379L,48380L,48381L,48382L,48383L,48384L,48385L,48386L,48387L,\n48388L,48389L,48390L,48391L,48392L,48393L,48394L,48395L,48396L,48397L,\n48398L,48399L,48400L,48401L,48402L,48403L,48404L,48405L,48406L,48407L,\n48408L,48409L,48410L,48411L,48412L,48413L,48414L,48415L,48416L,48417L,\n48418L,48419L,48420L,48421L,48422L,48423L,48424L,48425L,48426L,48427L,\n48428L,48429L,48430L,48431L,48432L,48433L,48434L,48435L,48436L,48437L,\n48438L,48439L,48440L,48441L,48442L,48443L,48444L,48445L,48446L,48447L,\n48448L,48449L,48450L,48451L,48452L,48453L,48454L,48455L,48456L,48457L,\n48458L,48459L,48460L,48461L,48462L,48463L,48464L,48465L,48466L,48467L,\n48468L,48469L,48470L,48471L,48472L,48473L,48474L,48475L,48476L,48477L,\n48478L,48479L,48480L,48481L,48482L,48483L,48484L,48485L,48486L,48487L,\n48488L,48489L,48490L,48491L,48492L,48493L,48494L,48495L,48496L,48497L,\n48498L,48499L,48500L,48501L,48502L,48503L,48504L,48505L,48506L,48507L,\n48508L,48509L,48510L,48511L,48512L,48513L,48514L,48515L,48516L,48517L,\n48518L,48519L,48520L,48521L,48522L,48523L,48524L,48525L,48526L,48527L,\n48528L,48529L,48530L,48531L,48532L,48533L,48534L,48535L,48536L,48537L,\n48538L,48539L,48540L,48541L,48542L,48543L,48544L,48545L,48546L,48547L,\n48548L,48549L,48550L,48551L,48552L,48553L,48554L,48555L,48556L,48557L,\n48558L,48559L,48560L,48561L,48562L,48563L,48564L,48565L,48566L,48567L,\n48568L,48569L,48570L,48571L,48572L,48573L,48574L,48575L,48576L,48577L,\n48578L,48579L,48580L,48581L,48582L,48583L,48584L,48585L,48586L,48587L,\n48588L,48589L,48590L,48591L,48592L,48593L,48594L,48595L,48596L,48597L,\n48598L,48599L,48600L,48601L,48602L,48603L,48604L,48605L,48606L,48607L,\n48608L,48609L,48610L,48611L,48612L,48613L,48614L,48615L,48616L,48617L,\n48618L,48619L,48620L,48621L,48622L,48623L,48624L,48625L,48626L,48627L,\n48628L,48629L,48630L,48631L,48632L,48633L,48634L,48635L,48636L,48637L,\n48638L,48639L,48640L,48641L,48642L,48643L,48644L,48645L,48646L,48647L,\n48648L,48649L,48650L,48651L,48652L,48653L,48654L,48655L,48656L,48657L,\n48658L,48659L,48660L,48661L,48662L,48663L,48664L,48665L,48666L,48667L,\n48668L,48669L,48670L,48671L,48672L,48673L,48674L,48675L,48676L,48677L,\n48678L,48679L,48680L,48681L,48682L,48683L,48684L,48685L,48686L,48687L,\n48688L,48689L,48690L,48691L,48692L,48693L,48694L,48695L,48696L,48697L,\n48698L,48699L,48700L,48701L,48702L,48703L,48704L,48705L,48706L,48707L,\n48708L,48709L,48710L,48711L,48712L,48713L,48714L,48715L,48716L,48717L,\n48718L,48719L,48720L,48721L,48722L,48723L,48724L,48725L,48726L,48727L,\n48728L,48729L,48730L,48731L,48732L,48733L,48734L,48735L,48736L,48737L,\n48738L,48739L,48740L,48741L,48742L,48743L,48744L,48745L,48746L,48747L,\n48748L,48749L,48750L,48751L,48752L,48753L,48754L,48755L,48756L,48757L,\n48758L,48759L,48760L,48761L,48762L,48763L,48764L,48765L,48766L,48767L,\n48768L,48769L,48770L,48771L,48772L,48773L,48774L,48775L,48776L,48777L,\n48778L,48779L,48780L,48781L,48782L,48783L,48784L,48785L,48786L,48787L,\n48788L,48789L,48790L,48791L,48792L,48793L,48794L,48795L,48796L,48797L,\n48798L,48799L,48800L,48801L,48802L,48803L,48804L,48805L,48806L,48807L,\n48808L,48809L,48810L,48811L,48812L,48813L,48814L,48815L,48816L,48817L,\n48818L,48819L,48820L,48821L,48822L,48823L,48824L,48825L,48826L,48827L,\n48828L,48829L,48830L,48831L,48832L,48833L,48834L,48835L,48836L,48837L,\n48838L,48839L,48840L,48841L,48842L,48843L,48844L,48845L,48846L,48847L,\n48848L,48849L,48850L,48851L,48852L,48853L,48854L,48855L,48856L,48857L,\n48858L,48859L,48860L,48861L,48862L,48863L,48864L,48865L,48866L,48867L,\n48868L,48869L,48870L,48871L,48872L,48873L,48874L,48875L,48876L,48877L,\n48878L,48879L,48880L,48881L,48882L,48883L,48884L,48885L,48886L,48887L,\n48888L,48889L,48890L,48891L,48892L,48893L,48894L,48895L,48896L,48897L,\n48898L,48899L,48900L,48901L,48902L,48903L,48904L,48905L,48906L,48907L,\n48908L,48909L,48910L,48911L,48912L,48913L,48914L,48915L,48916L,48917L,\n48918L,48919L,48920L,48921L,48922L,48923L,48924L,48925L,48926L,48927L,\n48928L,48929L,48930L,48931L,48932L,48933L,48934L,48935L,48936L,48937L,\n48938L,48939L,48940L,48941L,48942L,48943L,48944L,48945L,48946L,48947L,\n48948L,48949L,48950L,48951L,48952L,48953L,48954L,48955L,48956L,48957L,\n48958L,48959L,48960L,48961L,48962L,48963L,48964L,48965L,48966L,48967L,\n48968L,48969L,48970L,48971L,48972L,48973L,48974L,48975L,48976L,48977L,\n48978L,48979L,48980L,48981L,48982L,48983L,48984L,48985L,48986L,48987L,\n48988L,48989L,48990L,48991L,48992L,48993L,48994L,48995L,48996L,48997L,\n48998L,48999L,49000L,49001L,49002L,49003L,49004L,49005L,49006L,49007L,\n49008L,49009L,49010L,49011L,49012L,49013L,49014L,49015L,49016L,49017L,\n49018L,49019L,49020L,49021L,49022L,49023L,49024L,49025L,49026L,49027L,\n49028L,49029L,49030L,49031L,49032L,49033L,49034L,49035L,49036L,49037L,\n49038L,49039L,49040L,49041L,49042L,49043L,49044L,49045L,49046L,49047L,\n49048L,49049L,49050L,49051L,49052L,49053L,49054L,49055L,49056L,49057L,\n49058L,49059L,49060L,49061L,49062L,49063L,49064L,49065L,49066L,49067L,\n49068L,49069L,49070L,49071L,49072L,49073L,49074L,49075L,49076L,49077L,\n49078L,49079L,49080L,49081L,49082L,49083L,49084L,49085L,49086L,49087L,\n49088L,49089L,49090L,49091L,49092L,49093L,49094L,49095L,49096L,49097L,\n49098L,49099L,49100L,49101L,49102L,49103L,49104L,49105L,49106L,49107L,\n49108L,49109L,49110L,49111L,49112L,49113L,49114L,49115L,49116L,49117L,\n49118L,49119L,49120L,49121L,49122L,49123L,49124L,49125L,49126L,49127L,\n49128L,49129L,49130L,49131L,49132L,49133L,49134L,49135L,49136L,49137L,\n49138L,49139L,49140L,49141L,49142L,49143L,49144L,49145L,49146L,49147L,\n49148L,49149L,49150L,49151L,49152L,49153L,49154L,49155L,49156L,49157L,\n49158L,49159L,49160L,49161L,49162L,49163L,49164L,49165L,49166L,49167L,\n49168L,49169L,49170L,49171L,49172L,49173L,49174L,49175L,49176L,49177L,\n49178L,49179L,49180L,49181L,49182L,49183L,49184L,49185L,49186L,49187L,\n49188L,49189L,49190L,49191L,49192L,49193L,49194L,49195L,49196L,49197L,\n49198L,49199L,49200L,49201L,49202L,49203L,49204L,49205L,49206L,49207L,\n49208L,49209L,49210L,49211L,49212L,49213L,49214L,49215L,49216L,49217L,\n49218L,49219L,49220L,49221L,49222L,49223L,49224L,49225L,49226L,49227L,\n49228L,49229L,49230L,49231L,49232L,49233L,49234L,49235L,49236L,49237L,\n49238L,49239L,49240L,49241L,49242L,49243L,49244L,49245L,49246L,49247L,\n49248L,49249L,49250L,49251L,49252L,49253L,49254L,49255L,49256L,49257L,\n49258L,49259L,49260L,49261L,49262L,49263L,49264L,49265L,49266L,49267L,\n49268L,49269L,49270L,49271L,49272L,49273L,49274L,49275L,49276L,49277L,\n49278L,49279L,49280L,49281L,49282L,49283L,49284L,49285L,49286L,49287L,\n49288L,49289L,49290L,49291L,49292L,49293L,49294L,49295L,49296L,49297L,\n49298L,49299L,49300L,49301L,49302L,49303L,49304L,49305L,49306L,49307L,\n49308L,49309L,49310L,49311L,49312L,49313L,49314L,49315L,49316L,49317L,\n49318L,49319L,49320L,49321L,49322L,49323L,49324L,49325L,49326L,49327L,\n49328L,49329L,49330L,49331L,49332L,49333L,49334L,49335L,49336L,49337L,\n49338L,49339L,49340L,49341L,49342L,49343L,49344L,49345L,49346L,49347L,\n49348L,49349L,49350L,49351L,49352L,49353L,49354L,49355L,49356L,49357L,\n49358L,49359L,49360L,49361L,49362L,49363L,49364L,49365L,49366L,49367L,\n49368L,49369L,49370L,49371L,49372L,49373L,49374L,49375L,49376L,49377L,\n49378L,49379L,49380L,49381L,49382L,49383L,49384L,49385L,49386L,49387L,\n49388L,49389L,49390L,49391L,49392L,49393L,49394L,49395L,49396L,49397L,\n49398L,49399L,49400L,49401L,49402L,49403L,49404L,49405L,49406L,49407L,\n49408L,49409L,49410L,49411L,49412L,49413L,49414L,49415L,49416L,49417L,\n49418L,49419L,49420L,49421L,49422L,49423L,49424L,49425L,49426L,49427L,\n49428L,49429L,49430L,49431L,49432L,49433L,49434L,49435L,49436L,49437L,\n49438L,49439L,49440L,49441L,49442L,49443L,49444L,49445L,49446L,49447L,\n49448L,49449L,49450L,49451L,49452L,49453L,49454L,49455L,49456L,49457L,\n49458L,49459L,49460L,49461L,49462L,49463L,49464L,49465L,49466L,49467L,\n49468L,49469L,49470L,49471L,49472L,49473L,49474L,49475L,49476L,49477L,\n49478L,49479L,49480L,49481L,49482L,49483L,49484L,49485L,49486L,49487L,\n49488L,49489L,49490L,49491L,49492L,49493L,49494L,49495L,49496L,49497L,\n49498L,49499L,49500L,49501L,49502L,49503L,49504L,49505L,49506L,49507L,\n49508L,49509L,49510L,49511L,49512L,49513L,49514L,49515L,49516L,49517L,\n49518L,49519L,49520L,49521L,49522L,49523L,49524L,49525L,49526L,49527L,\n49528L,49529L,49530L,49531L,49532L,49533L,49534L,49535L,49536L,49537L,\n49538L,49539L,49540L,49541L,49542L,49543L,49544L,49545L,49546L,49547L,\n49548L,49549L,49550L,49551L,49552L,49553L,49554L,49555L,49556L,49557L,\n49558L,49559L,49560L,49561L,49562L,49563L,49564L,49565L,49566L,49567L,\n49568L,49569L,49570L,49571L,49572L,49573L,49574L,49575L,49576L,49577L,\n49578L,49579L,49580L,49581L,49582L,49583L,49584L,49585L,49586L,49587L,\n49588L,49589L,49590L,49591L,49592L,49593L,49594L,49595L,49596L,49597L,\n49598L,49599L,49600L,49601L,49602L,49603L,49604L,49605L,49606L,49607L,\n49608L,49609L,49610L,49611L,49612L,49613L,49614L,49615L,49616L,49617L,\n49618L,49619L,49620L,49621L,49622L,49623L,49624L,49625L,49626L,49627L,\n49628L,49629L,49630L,49631L,49632L,49633L,49634L,49635L,49636L,49637L,\n49638L,49639L,49640L,49641L,49642L,49643L,49644L,49645L,49646L,49647L,\n49648L,49649L,49650L,49651L,49652L,49653L,49654L,49655L,49656L,49657L,\n49658L,49659L,49660L,49661L,49662L,49663L,49664L,49665L,49666L,49667L,\n49668L,49669L,49670L,49671L,49672L,49673L,49674L,49675L,49676L,49677L,\n49678L,49679L,49680L,49681L,49682L,49683L,49684L,49685L,49686L,49687L,\n49688L,49689L,49690L,49691L,49692L,49693L,49694L,49695L,49696L,49697L,\n49698L,49699L,49700L,49701L,49702L,49703L,49704L,49705L,49706L,49707L,\n49708L,49709L,49710L,49711L,49712L,49713L,49714L,49715L,49716L,49717L,\n49718L,49719L,49720L,49721L,49722L,49723L,49724L,49725L,49726L,49727L,\n49728L,49729L,49730L,49731L,49732L,49733L,49734L,49735L,49736L,49737L,\n49738L,49739L,49740L,49741L,49742L,49743L,49744L,49745L,49746L,49747L,\n49748L,49749L,49750L,49751L,49752L,49753L,49754L,49755L,49756L,49757L,\n49758L,49759L,49760L,49761L,49762L,49763L,49764L,49765L,49766L,49767L,\n49768L,49769L,49770L,49771L,49772L,49773L,49774L,49775L,49776L,49777L,\n49778L,49779L,49780L,49781L,49782L,49783L,49784L,49785L,49786L,49787L,\n49788L,49789L,49790L,49791L,49792L,49793L,49794L,49795L,49796L,49797L,\n49798L,49799L,49800L,49801L,49802L,49803L,49804L,49805L,49806L,49807L,\n49808L,49809L,49810L,49811L,49812L,49813L,49814L,49815L,49816L,49817L,\n49818L,49819L,49820L,49821L,49822L,49823L,49824L,49825L,49826L,49827L,\n49828L,49829L,49830L,49831L,49832L,49833L,49834L,49835L,49836L,49837L,\n49838L,49839L,49840L,49841L,49842L,49843L,49844L,49845L,49846L,49847L,\n49848L,49849L,49850L,49851L,49852L,49853L,49854L,49855L,49856L,49857L,\n49858L,49859L,49860L,49861L,49862L,49863L,49864L,49865L,49866L,49867L,\n49868L,49869L,49870L,49871L,49872L,49873L,49874L,49875L,49876L,49877L,\n49878L,49879L,49880L,49881L,49882L,49883L,49884L,49885L,49886L,49887L,\n49888L,49889L,49890L,49891L,49892L,49893L,49894L,49895L,49896L,49897L,\n49898L,49899L,49900L,49901L,49902L,49903L,49904L,49905L,49906L,49907L,\n49908L,49909L,49910L,49911L,49912L,49913L,49914L,49915L,49916L,49917L,\n49918L,49919L,49920L,49921L,49922L,49923L,49924L,49925L,49926L,49927L,\n49928L,49929L,49930L,49931L,49932L,49933L,49934L,49935L,49936L,49937L,\n49938L,49939L,49940L,49941L,49942L,49943L,49944L,49945L,49946L,49947L,\n49948L,49949L,49950L,49951L,49952L,49953L,49954L,49955L,49956L,49957L,\n49958L,49959L,49960L,49961L,49962L,49963L,49964L,49965L,49966L,49967L,\n49968L,49969L,49970L,49971L,49972L,49973L,49974L,49975L,49976L,49977L,\n49978L,49979L,49980L,49981L,49982L,49983L,49984L,49985L,49986L,49987L,\n49988L,49989L,49990L,49991L,49992L,49993L,49994L,49995L,49996L,49997L,\n49998L,49999L,50000L,50001L,50002L,50003L,50004L,50005L,50006L,50007L,\n50008L,50009L,50010L,50011L,50012L,50013L,50014L,50015L,50016L,50017L,\n50018L,50019L,50020L,50021L,50022L,50023L,50024L,50025L,50026L,50027L,\n50028L,50029L,50030L,50031L,50032L,50033L,50034L,50035L,50036L,50037L,\n50038L,50039L,50040L,50041L,50042L,50043L,50044L,50045L,50046L,50047L,\n50048L,50049L,50050L,50051L,50052L,50053L,50054L,50055L,50056L,50057L,\n50058L,50059L,50060L,50061L,50062L,50063L,50064L,50065L,50066L,50067L,\n50068L,50069L,50070L,50071L,50072L,50073L,50074L,50075L,50076L,50077L,\n50078L,50079L,50080L,50081L,50082L,50083L,50084L,50085L,50086L,50087L,\n50088L,50089L,50090L,50091L,50092L,50093L,50094L,50095L,50096L,50097L,\n50098L,50099L,50100L,50101L,50102L,50103L,50104L,50105L,50106L,50107L,\n50108L,50109L,50110L,50111L,50112L,50113L,50114L,50115L,50116L,50117L,\n50118L,50119L,50120L,50121L,50122L,50123L,50124L,50125L,50126L,50127L,\n50128L,50129L,50130L,50131L,50132L,50133L,50134L,50135L,50136L,50137L,\n50138L,50139L,50140L,50141L,50142L,50143L,50144L,50145L,50146L,50147L,\n50148L,50149L,50150L,50151L,50152L,50153L,50154L,50155L,50156L,50157L,\n50158L,50159L,50160L,50161L,50162L,50163L,50164L,50165L,50166L,50167L,\n50168L,50169L,50170L,50171L,50172L,50173L,50174L,50175L,50176L,50177L,\n50178L,50179L,50180L,50181L,50182L,50183L,50184L,50185L,50186L,50187L,\n50188L,50189L,50190L,50191L,50192L,50193L,50194L,50195L,50196L,50197L,\n50198L,50199L,50200L,50201L,50202L,50203L,50204L,50205L,50206L,50207L,\n50208L,50209L,50210L,50211L,50212L,50213L,50214L,50215L,50216L,50217L,\n50218L,50219L,50220L,50221L,50222L,50223L,50224L,50225L,50226L,50227L,\n50228L,50229L,50230L,50231L,50232L,50233L,50234L,50235L,50236L,50237L,\n50238L,50239L,50240L,50241L,50242L,50243L,50244L,50245L,50246L,50247L,\n50248L,50249L,50250L,50251L,50252L,50253L,50254L,50255L,50256L,50257L,\n50258L,50259L,50260L,50261L,50262L,50263L,50264L,50265L,50266L,50267L,\n50268L,50269L,50270L,50271L,50272L,50273L,50274L,50275L,50276L,50277L,\n50278L,50279L,50280L,50281L,50282L,50283L,50284L,50285L,50286L,50287L,\n50288L,50289L,50290L,50291L,50292L,50293L,50294L,50295L,50296L,50297L,\n50298L,50299L,50300L,50301L,50302L,50303L,50304L,50305L,50306L,50307L,\n50308L,50309L,50310L,50311L,50312L,50313L,50314L,50315L,50316L,50317L,\n50318L,50319L,50320L,50321L,50322L,50323L,50324L,50325L,50326L,50327L,\n50328L,50329L,50330L,50331L,50332L,50333L,50334L,50335L,50336L,50337L,\n50338L,50339L,50340L,50341L,50342L,50343L,50344L,50345L,50346L,50347L,\n50348L,50349L,50350L,50351L,50352L,50353L,50354L,50355L,50356L,50357L,\n50358L,50359L,50360L,50361L,50362L,50363L,50364L,50365L,50366L,50367L,\n50368L,50369L,50370L,50371L,50372L,50373L,50374L,50375L,50376L,50377L,\n50378L,50379L,50380L,50381L,50382L,50383L,50384L,50385L,50386L,50387L,\n50388L,50389L,50390L,50391L,50392L,50393L,50394L,50395L,50396L,50397L,\n50398L,50399L,50400L,50401L,50402L,50403L,50404L,50405L,50406L,50407L,\n50408L,50409L,50410L,50411L,50412L,50413L,50414L,50415L,50416L,50417L,\n50418L,50419L,50420L,50421L,50422L,50423L,50424L,50425L,50426L,50427L,\n50428L,50429L,50430L,50431L,50432L,50433L,50434L,50435L,50436L,50437L,\n50438L,50439L,50440L,50441L,50442L,50443L,50444L,50445L,50446L,50447L,\n50448L,50449L,50450L,50451L,50452L,50453L,50454L,50455L,50456L,50457L,\n50458L,50459L,50460L,50461L,50462L,50463L,50464L,50465L,50466L,50467L,\n50468L,50469L,50470L,50471L,50472L,50473L,50474L,50475L,50476L,50477L,\n50478L,50479L,50480L,50481L,50482L,50483L,50484L,50485L,50486L,50487L,\n50488L,50489L,50490L,50491L,50492L,50493L,50494L,50495L,50496L,50497L,\n50498L,50499L,50500L,50501L,50502L,50503L,50504L,50505L,50506L,50507L,\n50508L,50509L,50510L,50511L,50512L,50513L,50514L,50515L,50516L,50517L,\n50518L,50519L,50520L,50521L,50522L,50523L,50524L,50525L,50526L,50527L,\n50528L,50529L,50530L,50531L,50532L,50533L,50534L,50535L,50536L,50537L,\n50538L,50539L,50540L,50541L,50542L,50543L,50544L,50545L,50546L,50547L,\n50548L,50549L,50550L,50551L,50552L,50553L,50554L,50555L,50556L,50557L,\n50558L,50559L,50560L,50561L,50562L,50563L,50564L,50565L,50566L,50567L,\n50568L,50569L,50570L,50571L,50572L,50573L,50574L,50575L,50576L,50577L,\n50578L,50579L,50580L,50581L,50582L,50583L,50584L,50585L,50586L,50587L,\n50588L,50589L,50590L,50591L,50592L,50593L,50594L,50595L,50596L,50597L,\n50598L,50599L,50600L,50601L,50602L,50603L,50604L,50605L,50606L,50607L,\n50608L,50609L,50610L,50611L,50612L,50613L,50614L,50615L,50616L,50617L,\n50618L,50619L,50620L,50621L,50622L,50623L,50624L,50625L,50626L,50627L,\n50628L,50629L,50630L,50631L,50632L,50633L,50634L,50635L,50636L,50637L,\n50638L,50639L,50640L,50641L,50642L,50643L,50644L,50645L,50646L,50647L,\n50648L,50649L,50650L,50651L,50652L,50653L,50654L,50655L,50656L,50657L,\n50658L,50659L,50660L,50661L,50662L,50663L,50664L,50665L,50666L,50667L,\n50668L,50669L,50670L,50671L,50672L,50673L,50674L,50675L,50676L,50677L,\n50678L,50679L,50680L,50681L,50682L,50683L,50684L,50685L,50686L,50687L,\n50688L,50689L,50690L,50691L,50692L,50693L,50694L,50695L,50696L,50697L,\n50698L,50699L,50700L,50701L,50702L,50703L,50704L,50705L,50706L,50707L,\n50708L,50709L,50710L,50711L,50712L,50713L,50714L,50715L,50716L,50717L,\n50718L,50719L,50720L,50721L,50722L,50723L,50724L,50725L,50726L,50727L,\n50728L,50729L,50730L,50731L,50732L,50733L,50734L,50735L,50736L,50737L,\n50738L,50739L,50740L,50741L,50742L,50743L,50744L,50745L,50746L,50747L,\n50748L,50749L,50750L,50751L,50752L,50753L,50754L,50755L,50756L,50757L,\n50758L,50759L,50760L,50761L,50762L,50763L,50764L,50765L,50766L,50767L,\n50768L,50769L,50770L,50771L,50772L,50773L,50774L,50775L,50776L,50777L,\n50778L,50779L,50780L,50781L,50782L,50783L,50784L,50785L,50786L,50787L,\n50788L,50789L,50790L,50791L,50792L,50793L,50794L,50795L,50796L,50797L,\n50798L,50799L,50800L,50801L,50802L,50803L,50804L,50805L,50806L,50807L,\n50808L,50809L,50810L,50811L,50812L,50813L,50814L,50815L,50816L,50817L,\n50818L,50819L,50820L,50821L,50822L,50823L,50824L,50825L,50826L,50827L,\n50828L,50829L,50830L,50831L,50832L,50833L,50834L,50835L,50836L,50837L,\n50838L,50839L,50840L,50841L,50842L,50843L,50844L,50845L,50846L,50847L,\n50848L,50849L,50850L,50851L,50852L,50853L,50854L,50855L,50856L,50857L,\n50858L,50859L,50860L,50861L,50862L,50863L,50864L,50865L,50866L,50867L,\n50868L,50869L,50870L,50871L,50872L,50873L,50874L,50875L,50876L,50877L,\n50878L,50879L,50880L,50881L,50882L,50883L,50884L,50885L,50886L,50887L,\n50888L,50889L,50890L,50891L,50892L,50893L,50894L,50895L,50896L,50897L,\n50898L,50899L,50900L,50901L,50902L,50903L,50904L,50905L,50906L,50907L,\n50908L,50909L,50910L,50911L,50912L,50913L,50914L,50915L,50916L,50917L,\n50918L,50919L,50920L,50921L,50922L,50923L,50924L,50925L,50926L,50927L,\n50928L,50929L,50930L,50931L,50932L,50933L,50934L,50935L,50936L,50937L,\n50938L,50939L,50940L,50941L,50942L,50943L,50944L,50945L,50946L,50947L,\n50948L,50949L,50950L,50951L,50952L,50953L,50954L,50955L,50956L,50957L,\n50958L,50959L,50960L,50961L,50962L,50963L,50964L,50965L,50966L,50967L,\n50968L,50969L,50970L,50971L,50972L,50973L,50974L,50975L,50976L,50977L,\n50978L,50979L,50980L,50981L,50982L,50983L,50984L,50985L,50986L,50987L,\n50988L,50989L,50990L,50991L,50992L,50993L,50994L,50995L,50996L,50997L,\n50998L,50999L,51000L,51001L,51002L,51003L,51004L,51005L,51006L,51007L,\n51008L,51009L,51010L,51011L,51012L,51013L,51014L,51015L,51016L,51017L,\n51018L,51019L,51020L,51021L,51022L,51023L,51024L,51025L,51026L,51027L,\n51028L,51029L,51030L,51031L,51032L,51033L,51034L,51035L,51036L,51037L,\n51038L,51039L,51040L,51041L,51042L,51043L,51044L,51045L,51046L,51047L,\n51048L,51049L,51050L,51051L,51052L,51053L,51054L,51055L,51056L,51057L,\n51058L,51059L,51060L,51061L,51062L,51063L,51064L,51065L,51066L,51067L,\n51068L,51069L,51070L,51071L,51072L,51073L,51074L,51075L,51076L,51077L,\n51078L,51079L,51080L,51081L,51082L,51083L,51084L,51085L,51086L,51087L,\n51088L,51089L,51090L,51091L,51092L,51093L,51094L,51095L,51096L,51097L,\n51098L,51099L,51100L,51101L,51102L,51103L,51104L,51105L,51106L,51107L,\n51108L,51109L,51110L,51111L,51112L,51113L,51114L,51115L,51116L,51117L,\n51118L,51119L,51120L,51121L,51122L,51123L,51124L,51125L,51126L,51127L,\n51128L,51129L,51130L,51131L,51132L,51133L,51134L,51135L,51136L,51137L,\n51138L,51139L,51140L,51141L,51142L,51143L,51144L,51145L,51146L,51147L,\n51148L,51149L,51150L,51151L,51152L,51153L,51154L,51155L,51156L,51157L,\n51158L,51159L,51160L,51161L,51162L,51163L,51164L,51165L,51166L,51167L,\n51168L,51169L,51170L,51171L,51172L,51173L,51174L,51175L,51176L,51177L,\n51178L,51179L,51180L,51181L,51182L,51183L,51184L,51185L,51186L,51187L,\n51188L,51189L,51190L,51191L,51192L,51193L,51194L,51195L,51196L,51197L,\n51198L,51199L,51200L,51201L,51202L,51203L,51204L,51205L,51206L,51207L,\n51208L,51209L,51210L,51211L,51212L,51213L,51214L,51215L,51216L,51217L,\n51218L,51219L,51220L,51221L,51222L,51223L,51224L,51225L,51226L,51227L,\n51228L,51229L,51230L,51231L,51232L,51233L,51234L,51235L,51236L,51237L,\n51238L,51239L,51240L,51241L,51242L,51243L,51244L,51245L,51246L,51247L,\n51248L,51249L,51250L,51251L,51252L,51253L,51254L,51255L,51256L,51257L,\n51258L,51259L,51260L,51261L,51262L,51263L,51264L,51265L,51266L,51267L,\n51268L,51269L,51270L,51271L,51272L,51273L,51274L,51275L,51276L,51277L,\n51278L,51279L,51280L,51281L,51282L,51283L,51284L,51285L,51286L,51287L,\n51288L,51289L,51290L,51291L,51292L,51293L,51294L,51295L,51296L,51297L,\n51298L,51299L,51300L,51301L,51302L,51303L,51304L,51305L,51306L,51307L,\n51308L,51309L,51310L,51311L,51312L,51313L,51314L,51315L,51316L,51317L,\n51318L,51319L,51320L,51321L,51322L,51323L,51324L,51325L,51326L,51327L,\n51328L,51329L,51330L,51331L,51332L,51333L,51334L,51335L,51336L,51337L,\n51338L,51339L,51340L,51341L,51342L,51343L,51344L,51345L,51346L,51347L,\n51348L,51349L,51350L,51351L,51352L,51353L,51354L,51355L,51356L,51357L,\n51358L,51359L,51360L,51361L,51362L,51363L,51364L,51365L,51366L,51367L,\n51368L,51369L,51370L,51371L,51372L,51373L,51374L,51375L,51376L,51377L,\n51378L,51379L,51380L,51381L,51382L,51383L,51384L,51385L,51386L,51387L,\n51388L,51389L,51390L,51391L,51392L,51393L,51394L,51395L,51396L,51397L,\n51398L,51399L,51400L,51401L,51402L,51403L,51404L,51405L,51406L,51407L,\n51408L,51409L,51410L,51411L,51412L,51413L,51414L,51415L,51416L,51417L,\n51418L,51419L,51420L,51421L,51422L,51423L,51424L,51425L,51426L,51427L,\n51428L,51429L,51430L,51431L,51432L,51433L,51434L,51435L,51436L,51437L,\n51438L,51439L,51440L,51441L,51442L,51443L,51444L,51445L,51446L,51447L,\n51448L,51449L,51450L,51451L,51452L,51453L,51454L,51455L,51456L,51457L,\n51458L,51459L,51460L,51461L,51462L,51463L,51464L,51465L,51466L,51467L,\n51468L,51469L,51470L,51471L,51472L,51473L,51474L,51475L,51476L,51477L,\n51478L,51479L,51480L,51481L,51482L,51483L,51484L,51485L,51486L,51487L,\n51488L,51489L,51490L,51491L,51492L,51493L,51494L,51495L,51496L,51497L,\n51498L,51499L,51500L,51501L,51502L,51503L,51504L,51505L,51506L,51507L,\n51508L,51509L,51510L,51511L,51512L,51513L,51514L,51515L,51516L,51517L,\n51518L,51519L,51520L,51521L,51522L,51523L,51524L,51525L,51526L,51527L,\n51528L,51529L,51530L,51531L,51532L,51533L,51534L,51535L,51536L,51537L,\n51538L,51539L,51540L,51541L,51542L,51543L,51544L,51545L,51546L,51547L,\n51548L,51549L,51550L,51551L,51552L,51553L,51554L,51555L,51556L,51557L,\n51558L,51559L,51560L,51561L,51562L,51563L,51564L,51565L,51566L,51567L,\n51568L,51569L,51570L,51571L,51572L,51573L,51574L,51575L,51576L,51577L,\n51578L,51579L,51580L,51581L,51582L,51583L,51584L,51585L,51586L,51587L,\n51588L,51589L,51590L,51591L,51592L,51593L,51594L,51595L,51596L,51597L,\n51598L,51599L,51600L,51601L,51602L,51603L,51604L,51605L,51606L,51607L,\n51608L,51609L,51610L,51611L,51612L,51613L,51614L,51615L,51616L,51617L,\n51618L,51619L,51620L,51621L,51622L,51623L,51624L,51625L,51626L,51627L,\n51628L,51629L,51630L,51631L,51632L,51633L,51634L,51635L,51636L,51637L,\n51638L,51639L,51640L,51641L,51642L,51643L,51644L,51645L,51646L,51647L,\n51648L,51649L,51650L,51651L,51652L,51653L,51654L,51655L,51656L,51657L,\n51658L,51659L,51660L,51661L,51662L,51663L,51664L,51665L,51666L,51667L,\n51668L,51669L,51670L,51671L,51672L,51673L,51674L,51675L,51676L,51677L,\n51678L,51679L,51680L,51681L,51682L,51683L,51684L,51685L,51686L,51687L,\n51688L,51689L,51690L,51691L,51692L,51693L,51694L,51695L,51696L,51697L,\n51698L,51699L,51700L,51701L,51702L,51703L,51704L,51705L,51706L,51707L,\n51708L,51709L,51710L,51711L,51712L,51713L,51714L,51715L,51716L,51717L,\n51718L,51719L,51720L,51721L,51722L,51723L,51724L,51725L,51726L,51727L,\n51728L,51729L,51730L,51731L,51732L,51733L,51734L,51735L,51736L,51737L,\n51738L,51739L,51740L,51741L,51742L,51743L,51744L,51745L,51746L,51747L,\n51748L,51749L,51750L,51751L,51752L,51753L,51754L,51755L,51756L,51757L,\n51758L,51759L,51760L,51761L,51762L,51763L,51764L,51765L,51766L,51767L,\n51768L,51769L,51770L,51771L,51772L,51773L,51774L,51775L,51776L,51777L,\n51778L,51779L,51780L,51781L,51782L,51783L,51784L,51785L,51786L,51787L,\n51788L,51789L,51790L,51791L,51792L,51793L,51794L,51795L,51796L,51797L,\n51798L,51799L,51800L,51801L,51802L,51803L,51804L,51805L,51806L,51807L,\n51808L,51809L,51810L,51811L,51812L,51813L,51814L,51815L,51816L,51817L,\n51818L,51819L,51820L,51821L,51822L,51823L,51824L,51825L,51826L,51827L,\n51828L,51829L,51830L,51831L,51832L,51833L,51834L,51835L,51836L,51837L,\n51838L,51839L,51840L,51841L,51842L,51843L,51844L,51845L,51846L,51847L,\n51848L,51849L,51850L,51851L,51852L,51853L,51854L,51855L,51856L,51857L,\n51858L,51859L,51860L,51861L,51862L,51863L,51864L,51865L,51866L,51867L,\n51868L,51869L,51870L,51871L,51872L,51873L,51874L,51875L,51876L,51877L,\n51878L,51879L,51880L,51881L,51882L,51883L,51884L,51885L,51886L,51887L,\n51888L,51889L,51890L,51891L,51892L,51893L,51894L,51895L,51896L,51897L,\n51898L,51899L,51900L,51901L,51902L,51903L,51904L,51905L,51906L,51907L,\n51908L,51909L,51910L,51911L,51912L,51913L,51914L,51915L,51916L,51917L,\n51918L,51919L,51920L,51921L,51922L,51923L,51924L,51925L,51926L,51927L,\n51928L,51929L,51930L,51931L,51932L,51933L,51934L,51935L,51936L,51937L,\n51938L,51939L,51940L,51941L,51942L,51943L,51944L,51945L,51946L,51947L,\n51948L,51949L,51950L,51951L,51952L,51953L,51954L,51955L,51956L,51957L,\n51958L,51959L,51960L,51961L,51962L,51963L,51964L,51965L,51966L,51967L,\n51968L,51969L,51970L,51971L,51972L,51973L,51974L,51975L,51976L,51977L,\n51978L,51979L,51980L,51981L,51982L,51983L,51984L,51985L,51986L,51987L,\n51988L,51989L,51990L,51991L,51992L,51993L,51994L,51995L,51996L,51997L,\n51998L,51999L,52000L,52001L,52002L,52003L,52004L,52005L,52006L,52007L,\n52008L,52009L,52010L,52011L,52012L,52013L,52014L,52015L,52016L,52017L,\n52018L,52019L,52020L,52021L,52022L,52023L,52024L,52025L,52026L,52027L,\n52028L,52029L,52030L,52031L,52032L,52033L,52034L,52035L,52036L,52037L,\n52038L,52039L,52040L,52041L,52042L,52043L,52044L,52045L,52046L,52047L,\n52048L,52049L,52050L,52051L,52052L,52053L,52054L,52055L,52056L,52057L,\n52058L,52059L,52060L,52061L,52062L,52063L,52064L,52065L,52066L,52067L,\n52068L,52069L,52070L,52071L,52072L,52073L,52074L,52075L,52076L,52077L,\n52078L,52079L,52080L,52081L,52082L,52083L,52084L,52085L,52086L,52087L,\n52088L,52089L,52090L,52091L,52092L,52093L,52094L,52095L,52096L,52097L,\n52098L,52099L,52100L,52101L,52102L,52103L,52104L,52105L,52106L,52107L,\n52108L,52109L,52110L,52111L,52112L,52113L,52114L,52115L,52116L,52117L,\n52118L,52119L,52120L,52121L,52122L,52123L,52124L,52125L,52126L,52127L,\n52128L,52129L,52130L,52131L,52132L,52133L,52134L,52135L,52136L,52137L,\n52138L,52139L,52140L,52141L,52142L,52143L,52144L,52145L,52146L,52147L,\n52148L,52149L,52150L,52151L,52152L,52153L,52154L,52155L,52156L,52157L,\n52158L,52159L,52160L,52161L,52162L,52163L,52164L,52165L,52166L,52167L,\n52168L,52169L,52170L,52171L,52172L,52173L,52174L,52175L,52176L,52177L,\n52178L,52179L,52180L,52181L,52182L,52183L,52184L,52185L,52186L,52187L,\n52188L,52189L,52190L,52191L,52192L,52193L,52194L,52195L,52196L,52197L,\n52198L,52199L,52200L,52201L,52202L,52203L,52204L,52205L,52206L,52207L,\n52208L,52209L,52210L,52211L,52212L,52213L,52214L,52215L,52216L,52217L,\n52218L,52219L,52220L,52221L,52222L,52223L,52224L,52225L,52226L,52227L,\n52228L,52229L,52230L,52231L,52232L,52233L,52234L,52235L,52236L,52237L,\n52238L,52239L,52240L,52241L,52242L,52243L,52244L,52245L,52246L,52247L,\n52248L,52249L,52250L,52251L,52252L,52253L,52254L,52255L,52256L,52257L,\n52258L,52259L,52260L,52261L,52262L,52263L,52264L,52265L,52266L,52267L,\n52268L,52269L,52270L,52271L,52272L,52273L,52274L,52275L,52276L,52277L,\n52278L,52279L,52280L,52281L,52282L,52283L,52284L,52285L,52286L,52287L,\n52288L,52289L,52290L,52291L,52292L,52293L,52294L,52295L,52296L,52297L,\n52298L,52299L,52300L,52301L,52302L,52303L,52304L,52305L,52306L,52307L,\n52308L,52309L,52310L,52311L,52312L,52313L,52314L,52315L,52316L,52317L,\n52318L,52319L,52320L,52321L,52322L,52323L,52324L,52325L,52326L,52327L,\n52328L,52329L,52330L,52331L,52332L,52333L,52334L,52335L,52336L,52337L,\n52338L,52339L,52340L,52341L,52342L,52343L,52344L,52345L,52346L,52347L,\n52348L,52349L,52350L,52351L,52352L,52353L,52354L,52355L,52356L,52357L,\n52358L,52359L,52360L,52361L,52362L,52363L,52364L,52365L,52366L,52367L,\n52368L,52369L,52370L,52371L,52372L,52373L,52374L,52375L,52376L,52377L,\n52378L,52379L,52380L,52381L,52382L,52383L,52384L,52385L,52386L,52387L,\n52388L,52389L,52390L,52391L,52392L,52393L,52394L,52395L,52396L,52397L,\n52398L,52399L,52400L,52401L,52402L,52403L,52404L,52405L,52406L,52407L,\n52408L,52409L,52410L,52411L,52412L,52413L,52414L,52415L,52416L,52417L,\n52418L,52419L,52420L,52421L,52422L,52423L,52424L,52425L,52426L,52427L,\n52428L,52429L,52430L,52431L,52432L,52433L,52434L,52435L,52436L,52437L,\n52438L,52439L,52440L,52441L,52442L,52443L,52444L,52445L,52446L,52447L,\n52448L,52449L,52450L,52451L,52452L,52453L,52454L,52455L,52456L,52457L,\n52458L,52459L,52460L,52461L,52462L,52463L,52464L,52465L,52466L,52467L,\n52468L,52469L,52470L,52471L,52472L,52473L,52474L,52475L,52476L,52477L,\n52478L,52479L,52480L,52481L,52482L,52483L,52484L,52485L,52486L,52487L,\n52488L,52489L,52490L,52491L,52492L,52493L,52494L,52495L,52496L,52497L,\n52498L,52499L,52500L,52501L,52502L,52503L,52504L,52505L,52506L,52507L,\n52508L,52509L,52510L,52511L,52512L,52513L,52514L,52515L,52516L,52517L,\n52518L,52519L,52520L,52521L,52522L,52523L,52524L,52525L,52526L,52527L,\n52528L,52529L,52530L,52531L,52532L,52533L,52534L,52535L,52536L,52537L,\n52538L,52539L,52540L,52541L,52542L,52543L,52544L,52545L,52546L,52547L,\n52548L,52549L,52550L,52551L,52552L,52553L,52554L,52555L,52556L,52557L,\n52558L,52559L,52560L,52561L,52562L,52563L,52564L,52565L,52566L,52567L,\n52568L,52569L,52570L,52571L,52572L,52573L,52574L,52575L,52576L,52577L,\n52578L,52579L,52580L,52581L,52582L,52583L,52584L,52585L,52586L,52587L,\n52588L,52589L,52590L,52591L,52592L,52593L,52594L,52595L,52596L,52597L,\n52598L,52599L,52600L,52601L,52602L,52603L,52604L,52605L,52606L,52607L,\n52608L,52609L,52610L,52611L,52612L,52613L,52614L,52615L,52616L,52617L,\n52618L,52619L,52620L,52621L,52622L,52623L,52624L,52625L,52626L,52627L,\n52628L,52629L,52630L,52631L,52632L,52633L,52634L,52635L,52636L,52637L,\n52638L,52639L,52640L,52641L,52642L,52643L,52644L,52645L,52646L,52647L,\n52648L,52649L,52650L,52651L,52652L,52653L,52654L,52655L,52656L,52657L,\n52658L,52659L,52660L,52661L,52662L,52663L,52664L,52665L,52666L,52667L,\n52668L,52669L,52670L,52671L,52672L,52673L,52674L,52675L,52676L,52677L,\n52678L,52679L,52680L,52681L,52682L,52683L,52684L,52685L,52686L,52687L,\n52688L,52689L,52690L,52691L,52692L,52693L,52694L,52695L,52696L,52697L,\n52698L,52699L,52700L,52701L,52702L,52703L,52704L,52705L,52706L,52707L,\n52708L,52709L,52710L,52711L,52712L,52713L,52714L,52715L,52716L,52717L,\n52718L,52719L,52720L,52721L,52722L,52723L,52724L,52725L,52726L,52727L,\n52728L,52729L,52730L,52731L,52732L,52733L,52734L,52735L,52736L,52737L,\n52738L,52739L,52740L,52741L,52742L,52743L,52744L,52745L,52746L,52747L,\n52748L,52749L,52750L,52751L,52752L,52753L,52754L,52755L,52756L,52757L,\n52758L,52759L,52760L,52761L,52762L,52763L,52764L,52765L,52766L,52767L,\n52768L,52769L,52770L,52771L,52772L,52773L,52774L,52775L,52776L,52777L,\n52778L,52779L,52780L,52781L,52782L,52783L,52784L,52785L,52786L,52787L,\n52788L,52789L,52790L,52791L,52792L,52793L,52794L,52795L,52796L,52797L,\n52798L,52799L,52800L,52801L,52802L,52803L,52804L,52805L,52806L,52807L,\n52808L,52809L,52810L,52811L,52812L,52813L,52814L,52815L,52816L,52817L,\n52818L,52819L,52820L,52821L,52822L,52823L,52824L,52825L,52826L,52827L,\n52828L,52829L,52830L,52831L,52832L,52833L,52834L,52835L,52836L,52837L,\n52838L,52839L,52840L,52841L,52842L,52843L,52844L,52845L,52846L,52847L,\n52848L,52849L,52850L,52851L,52852L,52853L,52854L,52855L,52856L,52857L,\n52858L,52859L,52860L,52861L,52862L,52863L,52864L,52865L,52866L,52867L,\n52868L,52869L,52870L,52871L,52872L,52873L,52874L,52875L,52876L,52877L,\n52878L,52879L,52880L,52881L,52882L,52883L,52884L,52885L,52886L,52887L,\n52888L,52889L,52890L,52891L,52892L,52893L,52894L,52895L,52896L,52897L,\n52898L,52899L,52900L,52901L,52902L,52903L,52904L,52905L,52906L,52907L,\n52908L,52909L,52910L,52911L,52912L,52913L,52914L,52915L,52916L,52917L,\n52918L,52919L,52920L,52921L,52922L,52923L,52924L,52925L,52926L,52927L,\n52928L,52929L,52930L,52931L,52932L,52933L,52934L,52935L,52936L,52937L,\n52938L,52939L,52940L,52941L,52942L,52943L,52944L,52945L,52946L,52947L,\n52948L,52949L,52950L,52951L,52952L,52953L,52954L,52955L,52956L,52957L,\n52958L,52959L,52960L,52961L,52962L,52963L,52964L,52965L,52966L,52967L,\n52968L,52969L,52970L,52971L,52972L,52973L,52974L,52975L,52976L,52977L,\n52978L,52979L,52980L,52981L,52982L,52983L,52984L,52985L,52986L,52987L,\n52988L,52989L,52990L,52991L,52992L,52993L,52994L,52995L,52996L,52997L,\n52998L,52999L,53000L,53001L,53002L,53003L,53004L,53005L,53006L,53007L,\n53008L,53009L,53010L,53011L,53012L,53013L,53014L,53015L,53016L,53017L,\n53018L,53019L,53020L,53021L,53022L,53023L,53024L,53025L,53026L,53027L,\n53028L,53029L,53030L,53031L,53032L,53033L,53034L,53035L,53036L,53037L,\n53038L,53039L,53040L,53041L,53042L,53043L,53044L,53045L,53046L,53047L,\n53048L,53049L,53050L,53051L,53052L,53053L,53054L,53055L,53056L,53057L,\n53058L,53059L,53060L,53061L,53062L,53063L,53064L,53065L,53066L,53067L,\n53068L,53069L,53070L,53071L,53072L,53073L,53074L,53075L,53076L,53077L,\n53078L,53079L,53080L,53081L,53082L,53083L,53084L,53085L,53086L,53087L,\n53088L,53089L,53090L,53091L,53092L,53093L,53094L,53095L,53096L,53097L,\n53098L,53099L,53100L,53101L,53102L,53103L,53104L,53105L,53106L,53107L,\n53108L,53109L,53110L,53111L,53112L,53113L,53114L,53115L,53116L,53117L,\n53118L,53119L,53120L,53121L,53122L,53123L,53124L,53125L,53126L,53127L,\n53128L,53129L,53130L,53131L,53132L,53133L,53134L,53135L,53136L,53137L,\n53138L,53139L,53140L,53141L,53142L,53143L,53144L,53145L,53146L,53147L,\n53148L,53149L,53150L,53151L,53152L,53153L,53154L,53155L,53156L,53157L,\n53158L,53159L,53160L,53161L,53162L,53163L,53164L,53165L,53166L,53167L,\n53168L,53169L,53170L,53171L,53172L,53173L,53174L,53175L,53176L,53177L,\n53178L,53179L,53180L,53181L,53182L,53183L,53184L,53185L,53186L,53187L,\n53188L,53189L,53190L,53191L,53192L,53193L,53194L,53195L,53196L,53197L,\n53198L,53199L,53200L,53201L,53202L,53203L,53204L,53205L,53206L,53207L,\n53208L,53209L,53210L,53211L,53212L,53213L,53214L,53215L,53216L,53217L,\n53218L,53219L,53220L,53221L,53222L,53223L,53224L,53225L,53226L,53227L,\n53228L,53229L,53230L,53231L,53232L,53233L,53234L,53235L,53236L,53237L,\n53238L,53239L,53240L,53241L,53242L,53243L,53244L,53245L,53246L,53247L,\n53248L,53249L,53250L,53251L,53252L,53253L,53254L,53255L,53256L,53257L,\n53258L,53259L,53260L,53261L,53262L,53263L,53264L,53265L,53266L,53267L,\n53268L,53269L,53270L,53271L,53272L,53273L,53274L,53275L,53276L,53277L,\n53278L,53279L,53280L,53281L,53282L,53283L,53284L,53285L,53286L,53287L,\n53288L,53289L,53290L,53291L,53292L,53293L,53294L,53295L,53296L,53297L,\n53298L,53299L,53300L,53301L,53302L,53303L,53304L,53305L,53306L,53307L,\n53308L,53309L,53310L,53311L,53312L,53313L,53314L,53315L,53316L,53317L,\n53318L,53319L,53320L,53321L,53322L,53323L,53324L,53325L,53326L,53327L,\n53328L,53329L,53330L,53331L,53332L,53333L,53334L,53335L,53336L,53337L,\n53338L,53339L,53340L,53341L,53342L,53343L,53344L,53345L,53346L,53347L,\n53348L,53349L,53350L,53351L,53352L,53353L,53354L,53355L,53356L,53357L,\n53358L,53359L,53360L,53361L,53362L,53363L,53364L,53365L,53366L,53367L,\n53368L,53369L,53370L,53371L,53372L,53373L,53374L,53375L,53376L,53377L,\n53378L,53379L,53380L,53381L,53382L,53383L,53384L,53385L,53386L,53387L,\n53388L,53389L,53390L,53391L,53392L,53393L,53394L,53395L,53396L,53397L,\n53398L,53399L,53400L,53401L,53402L,53403L,53404L,53405L,53406L,53407L,\n53408L,53409L,53410L,53411L,53412L,53413L,53414L,53415L,53416L,53417L,\n53418L,53419L,53420L,53421L,53422L,53423L,53424L,53425L,53426L,53427L,\n53428L,53429L,53430L,53431L,53432L,53433L,53434L,53435L,53436L,53437L,\n53438L,53439L,53440L,53441L,53442L,53443L,53444L,53445L,53446L,53447L,\n53448L,53449L,53450L,53451L,53452L,53453L,53454L,53455L,53456L,53457L,\n53458L,53459L,53460L,53461L,53462L,53463L,53464L,53465L,53466L,53467L,\n53468L,53469L,53470L,53471L,53472L,53473L,53474L,53475L,53476L,53477L,\n53478L,53479L,53480L,53481L,53482L,53483L,53484L,53485L,53486L,53487L,\n53488L,53489L,53490L,53491L,53492L,53493L,53494L,53495L,53496L,53497L,\n53498L,53499L,53500L,53501L,53502L,53503L,53504L,53505L,53506L,53507L,\n53508L,53509L,53510L,53511L,53512L,53513L,53514L,53515L,53516L,53517L,\n53518L,53519L,53520L,53521L,53522L,53523L,53524L,53525L,53526L,53527L,\n53528L,53529L,53530L,53531L,53532L,53533L,53534L,53535L,53536L,53537L,\n53538L,53539L,53540L,53541L,53542L,53543L,53544L,53545L,53546L,53547L,\n53548L,53549L,53550L,53551L,53552L,53553L,53554L,53555L,53556L,53557L,\n53558L,53559L,53560L,53561L,53562L,53563L,53564L,53565L,53566L,53567L,\n53568L,53569L,53570L,53571L,53572L,53573L,53574L,53575L,53576L,53577L,\n53578L,53579L,53580L,53581L,53582L,53583L,53584L,53585L,53586L,53587L,\n53588L,53589L,53590L,53591L,53592L,53593L,53594L,53595L,53596L,53597L,\n53598L,53599L,53600L,53601L,53602L,53603L,53604L,53605L,53606L,53607L,\n53608L,53609L,53610L,53611L,53612L,53613L,53614L,53615L,53616L,53617L,\n53618L,53619L,53620L,53621L,53622L,53623L,53624L,53625L,53626L,53627L,\n53628L,53629L,53630L,53631L,53632L,53633L,53634L,53635L,53636L,53637L,\n53638L,53639L,53640L,53641L,53642L,53643L,53644L,53645L,53646L,53647L,\n53648L,53649L,53650L,53651L,53652L,53653L,53654L,53655L,53656L,53657L,\n53658L,53659L,53660L,53661L,53662L,53663L,53664L,53665L,53666L,53667L,\n53668L,53669L,53670L,53671L,53672L,53673L,53674L,53675L,53676L,53677L,\n53678L,53679L,53680L,53681L,53682L,53683L,53684L,53685L,53686L,53687L,\n53688L,53689L,53690L,53691L,53692L,53693L,53694L,53695L,53696L,53697L,\n53698L,53699L,53700L,53701L,53702L,53703L,53704L,53705L,53706L,53707L,\n53708L,53709L,53710L,53711L,53712L,53713L,53714L,53715L,53716L,53717L,\n53718L,53719L,53720L,53721L,53722L,53723L,53724L,53725L,53726L,53727L,\n53728L,53729L,53730L,53731L,53732L,53733L,53734L,53735L,53736L,53737L,\n53738L,53739L,53740L,53741L,53742L,53743L,53744L,53745L,53746L,53747L,\n53748L,53749L,53750L,53751L,53752L,53753L,53754L,53755L,53756L,53757L,\n53758L,53759L,53760L,53761L,53762L,53763L,53764L,53765L,53766L,53767L,\n53768L,53769L,53770L,53771L,53772L,53773L,53774L,53775L,53776L,53777L,\n53778L,53779L,53780L,53781L,53782L,53783L,53784L,53785L,53786L,53787L,\n53788L,53789L,53790L,53791L,53792L,53793L,53794L,53795L,53796L,53797L,\n53798L,53799L,53800L,53801L,53802L,53803L,53804L,53805L,53806L,53807L,\n53808L,53809L,53810L,53811L,53812L,53813L,53814L,53815L,53816L,53817L,\n53818L,53819L,53820L,53821L,53822L,53823L,53824L,53825L,53826L,53827L,\n53828L,53829L,53830L,53831L,53832L,53833L,53834L,53835L,53836L,53837L,\n53838L,53839L,53840L,53841L,53842L,53843L,53844L,53845L,53846L,53847L,\n53848L,53849L,53850L,53851L,53852L,53853L,53854L,53855L,53856L,53857L,\n53858L,53859L,53860L,53861L,53862L,53863L,53864L,53865L,53866L,53867L,\n53868L,53869L,53870L,53871L,53872L,53873L,53874L,53875L,53876L,53877L,\n53878L,53879L,53880L,53881L,53882L,53883L,53884L,53885L,53886L,53887L,\n53888L,53889L,53890L,53891L,53892L,53893L,53894L,53895L,53896L,53897L,\n53898L,53899L,53900L,53901L,53902L,53903L,53904L,53905L,53906L,53907L,\n53908L,53909L,53910L,53911L,53912L,53913L,53914L,53915L,53916L,53917L,\n53918L,53919L,53920L,53921L,53922L,53923L,53924L,53925L,53926L,53927L,\n53928L,53929L,53930L,53931L,53932L,53933L,53934L,53935L,53936L,53937L,\n53938L,53939L,53940L,53941L,53942L,53943L,53944L,53945L,53946L,53947L,\n53948L,53949L,53950L,53951L,53952L,53953L,53954L,53955L,53956L,53957L,\n53958L,53959L,53960L,53961L,53962L,53963L,53964L,53965L,53966L,53967L,\n53968L,53969L,53970L,53971L,53972L,53973L,53974L,53975L,53976L,53977L,\n53978L,53979L,53980L,53981L,53982L,53983L,53984L,53985L,53986L,53987L,\n53988L,53989L,53990L,53991L,53992L,53993L,53994L,53995L,53996L,53997L,\n53998L,53999L,54000L,54001L,54002L,54003L,54004L,54005L,54006L,54007L,\n54008L,54009L,54010L,54011L,54012L,54013L,54014L,54015L,54016L,54017L,\n54018L,54019L,54020L,54021L,54022L,54023L,54024L,54025L,54026L,54027L,\n54028L,54029L,54030L,54031L,54032L,54033L,54034L,54035L,54036L,54037L,\n54038L,54039L,54040L,54041L,54042L,54043L,54044L,54045L,54046L,54047L,\n54048L,54049L,54050L,54051L,54052L,54053L,54054L,54055L,54056L,54057L,\n54058L,54059L,54060L,54061L,54062L,54063L,54064L,54065L,54066L,54067L,\n54068L,54069L,54070L,54071L,54072L,54073L,54074L,54075L,54076L,54077L,\n54078L,54079L,54080L,54081L,54082L,54083L,54084L,54085L,54086L,54087L,\n54088L,54089L,54090L,54091L,54092L,54093L,54094L,54095L,54096L,54097L,\n54098L,54099L,54100L,54101L,54102L,54103L,54104L,54105L,54106L,54107L,\n54108L,54109L,54110L,54111L,54112L,54113L,54114L,54115L,54116L,54117L,\n54118L,54119L,54120L,54121L,54122L,54123L,54124L,54125L,54126L,54127L,\n54128L,54129L,54130L,54131L,54132L,54133L,54134L,54135L,54136L,54137L,\n54138L,54139L,54140L,54141L,54142L,54143L,54144L,54145L,54146L,54147L,\n54148L,54149L,54150L,54151L,54152L,54153L,54154L,54155L,54156L,54157L,\n54158L,54159L,54160L,54161L,54162L,54163L,54164L,54165L,54166L,54167L,\n54168L,54169L,54170L,54171L,54172L,54173L,54174L,54175L,54176L,54177L,\n54178L,54179L,54180L,54181L,54182L,54183L,54184L,54185L,54186L,54187L,\n54188L,54189L,54190L,54191L,54192L,54193L,54194L,54195L,54196L,54197L,\n54198L,54199L,54200L,54201L,54202L,54203L,54204L,54205L,54206L,54207L,\n54208L,54209L,54210L,54211L,54212L,54213L,54214L,54215L,54216L,54217L,\n54218L,54219L,54220L,54221L,54222L,54223L,54224L,54225L,54226L,54227L,\n54228L,54229L,54230L,54231L,54232L,54233L,54234L,54235L,54236L,54237L,\n54238L,54239L,54240L,54241L,54242L,54243L,54244L,54245L,54246L,54247L,\n54248L,54249L,54250L,54251L,54252L,54253L,54254L,54255L,54256L,54257L,\n54258L,54259L,54260L,54261L,54262L,54263L,54264L,54265L,54266L,54267L,\n54268L,54269L,54270L,54271L,54272L,54273L,54274L,54275L,54276L,54277L,\n54278L,54279L,54280L,54281L,54282L,54283L,54284L,54285L,54286L,54287L,\n54288L,54289L,54290L,54291L,54292L,54293L,54294L,54295L,54296L,54297L,\n54298L,54299L,54300L,54301L,54302L,54303L,54304L,54305L,54306L,54307L,\n54308L,54309L,54310L,54311L,54312L,54313L,54314L,54315L,54316L,54317L,\n54318L,54319L,54320L,54321L,54322L,54323L,54324L,54325L,54326L,54327L,\n54328L,54329L,54330L,54331L,54332L,54333L,54334L,54335L,54336L,54337L,\n54338L,54339L,54340L,54341L,54342L,54343L,54344L,54345L,54346L,54347L,\n54348L,54349L,54350L,54351L,54352L,54353L,54354L,54355L,54356L,54357L,\n54358L,54359L,54360L,54361L,54362L,54363L,54364L,54365L,54366L,54367L,\n54368L,54369L,54370L,54371L,54372L,54373L,54374L,54375L,54376L,54377L,\n54378L,54379L,54380L,54381L,54382L,54383L,54384L,54385L,54386L,54387L,\n54388L,54389L,54390L,54391L,54392L,54393L,54394L,54395L,54396L,54397L,\n54398L,54399L,54400L,54401L,54402L,54403L,54404L,54405L,54406L,54407L,\n54408L,54409L,54410L,54411L,54412L,54413L,54414L,54415L,54416L,54417L,\n54418L,54419L,54420L,54421L,54422L,54423L,54424L,54425L,54426L,54427L,\n54428L,54429L,54430L,54431L,54432L,54433L,54434L,54435L,54436L,54437L,\n54438L,54439L,54440L,54441L,54442L,54443L,54444L,54445L,54446L,54447L,\n54448L,54449L,54450L,54451L,54452L,54453L,54454L,54455L,54456L,54457L,\n54458L,54459L,54460L,54461L,54462L,54463L,54464L,54465L,54466L,54467L,\n54468L,54469L,54470L,54471L,54472L,54473L,54474L,54475L,54476L,54477L,\n54478L,54479L,54480L,54481L,54482L,54483L,54484L,54485L,54486L,54487L,\n54488L,54489L,54490L,54491L,54492L,54493L,54494L,54495L,54496L,54497L,\n54498L,54499L,54500L,54501L,54502L,54503L,54504L,54505L,54506L,54507L,\n54508L,54509L,54510L,54511L,54512L,54513L,54514L,54515L,54516L,54517L,\n54518L,54519L,54520L,54521L,54522L,54523L,54524L,54525L,54526L,54527L,\n54528L,54529L,54530L,54531L,54532L,54533L,54534L,54535L,54536L,54537L,\n54538L,54539L,54540L,54541L,54542L,54543L,54544L,54545L,54546L,54547L,\n54548L,54549L,54550L,54551L,54552L,54553L,54554L,54555L,54556L,54557L,\n54558L,54559L,54560L,54561L,54562L,54563L,54564L,54565L,54566L,54567L,\n54568L,54569L,54570L,54571L,54572L,54573L,54574L,54575L,54576L,54577L,\n54578L,54579L,54580L,54581L,54582L,54583L,54584L,54585L,54586L,54587L,\n54588L,54589L,54590L,54591L,54592L,54593L,54594L,54595L,54596L,54597L,\n54598L,54599L,54600L,54601L,54602L,54603L,54604L,54605L,54606L,54607L,\n54608L,54609L,54610L,54611L,54612L,54613L,54614L,54615L,54616L,54617L,\n54618L,54619L,54620L,54621L,54622L,54623L,54624L,54625L,54626L,54627L,\n54628L,54629L,54630L,54631L,54632L,54633L,54634L,54635L,54636L,54637L,\n54638L,54639L,54640L,54641L,54642L,54643L,54644L,54645L,54646L,54647L,\n54648L,54649L,54650L,54651L,54652L,54653L,54654L,54655L,54656L,54657L,\n54658L,54659L,54660L,54661L,54662L,54663L,54664L,54665L,54666L,54667L,\n54668L,54669L,54670L,54671L,54672L,54673L,54674L,54675L,54676L,54677L,\n54678L,54679L,54680L,54681L,54682L,54683L,54684L,54685L,54686L,54687L,\n54688L,54689L,54690L,54691L,54692L,54693L,54694L,54695L,54696L,54697L,\n54698L,54699L,54700L,54701L,54702L,54703L,54704L,54705L,54706L,54707L,\n54708L,54709L,54710L,54711L,54712L,54713L,54714L,54715L,54716L,54717L,\n54718L,54719L,54720L,54721L,54722L,54723L,54724L,54725L,54726L,54727L,\n54728L,54729L,54730L,54731L,54732L,54733L,54734L,54735L,54736L,54737L,\n54738L,54739L,54740L,54741L,54742L,54743L,54744L,54745L,54746L,54747L,\n54748L,54749L,54750L,54751L,54752L,54753L,54754L,54755L,54756L,54757L,\n54758L,54759L,54760L,54761L,54762L,54763L,54764L,54765L,54766L,54767L,\n54768L,54769L,54770L,54771L,54772L,54773L,54774L,54775L,54776L,54777L,\n54778L,54779L,54780L,54781L,54782L,54783L,54784L,54785L,54786L,54787L,\n54788L,54789L,54790L,54791L,54792L,54793L,54794L,54795L,54796L,54797L,\n54798L,54799L,54800L,54801L,54802L,54803L,54804L,54805L,54806L,54807L,\n54808L,54809L,54810L,54811L,54812L,54813L,54814L,54815L,54816L,54817L,\n54818L,54819L,54820L,54821L,54822L,54823L,54824L,54825L,54826L,54827L,\n54828L,54829L,54830L,54831L,54832L,54833L,54834L,54835L,54836L,54837L,\n54838L,54839L,54840L,54841L,54842L,54843L,54844L,54845L,54846L,54847L,\n54848L,54849L,54850L,54851L,54852L,54853L,54854L,54855L,54856L,54857L,\n54858L,54859L,54860L,54861L,54862L,54863L,54864L,54865L,54866L,54867L,\n54868L,54869L,54870L,54871L,54872L,54873L,54874L,54875L,54876L,54877L,\n54878L,54879L,54880L,54881L,54882L,54883L,54884L,54885L,54886L,54887L,\n54888L,54889L,54890L,54891L,54892L,54893L,54894L,54895L,54896L,54897L,\n54898L,54899L,54900L,54901L,54902L,54903L,54904L,54905L,54906L,54907L,\n54908L,54909L,54910L,54911L,54912L,54913L,54914L,54915L,54916L,54917L,\n54918L,54919L,54920L,54921L,54922L,54923L,54924L,54925L,54926L,54927L,\n54928L,54929L,54930L,54931L,54932L,54933L,54934L,54935L,54936L,54937L,\n54938L,54939L,54940L,54941L,54942L,54943L,54944L,54945L,54946L,54947L,\n54948L,54949L,54950L,54951L,54952L,54953L,54954L,54955L,54956L,54957L,\n54958L,54959L,54960L,54961L,54962L,54963L,54964L,54965L,54966L,54967L,\n54968L,54969L,54970L,54971L,54972L,54973L,54974L,54975L,54976L,54977L,\n54978L,54979L,54980L,54981L,54982L,54983L,54984L,54985L,54986L,54987L,\n54988L,54989L,54990L,54991L,54992L,54993L,54994L,54995L,54996L,54997L,\n54998L,54999L,55000L,55001L,55002L,55003L,55004L,55005L,55006L,55007L,\n55008L,55009L,55010L,55011L,55012L,55013L,55014L,55015L,55016L,55017L,\n55018L,55019L,55020L,55021L,55022L,55023L,55024L,55025L,55026L,55027L,\n55028L,55029L,55030L,55031L,55032L,55033L,55034L,55035L,55036L,55037L,\n55038L,55039L,55040L,55041L,55042L,55043L,55044L,55045L,55046L,55047L,\n55048L,55049L,55050L,55051L,55052L,55053L,55054L,55055L,55056L,55057L,\n55058L,55059L,55060L,55061L,55062L,55063L,55064L,55065L,55066L,55067L,\n55068L,55069L,55070L,55071L,55072L,55073L,55074L,55075L,55076L,55077L,\n55078L,55079L,55080L,55081L,55082L,55083L,55084L,55085L,55086L,55087L,\n55088L,55089L,55090L,55091L,55092L,55093L,55094L,55095L,55096L,55097L,\n55098L,55099L,55100L,55101L,55102L,55103L,55104L,55105L,55106L,55107L,\n55108L,55109L,55110L,55111L,55112L,55113L,55114L,55115L,55116L,55117L,\n55118L,55119L,55120L,55121L,55122L,55123L,55124L,55125L,55126L,55127L,\n55128L,55129L,55130L,55131L,55132L,55133L,55134L,55135L,55136L,55137L,\n55138L,55139L,55140L,55141L,55142L,55143L,55144L,55145L,55146L,55147L,\n55148L,55149L,55150L,55151L,55152L,55153L,55154L,55155L,55156L,55157L,\n55158L,55159L,55160L,55161L,55162L,55163L,55164L,55165L,55166L,55167L,\n55168L,55169L,55170L,55171L,55172L,55173L,55174L,55175L,55176L,55177L,\n55178L,55179L,55180L,55181L,55182L,55183L,55184L,55185L,55186L,55187L,\n55188L,55189L,55190L,55191L,55192L,55193L,55194L,55195L,55196L,55197L,\n55198L,55199L,55200L,55201L,55202L,55203L,55204L,55205L,55206L,55207L,\n55208L,55209L,55210L,55211L,55212L,55213L,55214L,55215L,55216L,55217L,\n55218L,55219L,55220L,55221L,55222L,55223L,55224L,55225L,55226L,55227L,\n55228L,55229L,55230L,55231L,55232L,55233L,55234L,55235L,55236L,55237L,\n55238L,55239L,55240L,55241L,55242L,55243L,55244L,55245L,55246L,55247L,\n55248L,55249L,55250L,55251L,55252L,55253L,55254L,55255L,55256L,55257L,\n55258L,55259L,55260L,55261L,55262L,55263L,55264L,55265L,55266L,55267L,\n55268L,55269L,55270L,55271L,55272L,55273L,55274L,55275L,55276L,55277L,\n55278L,55279L,55280L,55281L,55282L,55283L,55284L,55285L,55286L,55287L,\n55288L,55289L,55290L,55291L,55292L,55293L,55294L,55295L,55296L,55297L,\n55298L,55299L,55300L,55301L,55302L,55303L,55304L,55305L,55306L,55307L,\n55308L,55309L,55310L,55311L,55312L,55313L,55314L,55315L,55316L,55317L,\n55318L,55319L,55320L,55321L,55322L,55323L,55324L,55325L,55326L,55327L,\n55328L,55329L,55330L,55331L,55332L,55333L,55334L,55335L,55336L,55337L,\n55338L,55339L,55340L,55341L,55342L,55343L,55344L,55345L,55346L,55347L,\n55348L,55349L,55350L,55351L,55352L,55353L,55354L,55355L,55356L,55357L,\n55358L,55359L,55360L,55361L,55362L,55363L,55364L,55365L,55366L,55367L,\n55368L,55369L,55370L,55371L,55372L,55373L,55374L,55375L,55376L,55377L,\n55378L,55379L,55380L,55381L,55382L,55383L,55384L,55385L,55386L,55387L,\n55388L,55389L,55390L,55391L,55392L,55393L,55394L,55395L,55396L,55397L,\n55398L,55399L,55400L,55401L,55402L,55403L,55404L,55405L,55406L,55407L,\n55408L,55409L,55410L,55411L,55412L,55413L,55414L,55415L,55416L,55417L,\n55418L,55419L,55420L,55421L,55422L,55423L,55424L,55425L,55426L,55427L,\n55428L,55429L,55430L,55431L,55432L,55433L,55434L,55435L,55436L,55437L,\n55438L,55439L,55440L,55441L,55442L,55443L,55444L,55445L,55446L,55447L,\n55448L,55449L,55450L,55451L,55452L,55453L,55454L,55455L,55456L,55457L,\n55458L,55459L,55460L,55461L,55462L,55463L,55464L,55465L,55466L,55467L,\n55468L,55469L,55470L,55471L,55472L,55473L,55474L,55475L,55476L,55477L,\n55478L,55479L,55480L,55481L,55482L,55483L,55484L,55485L,55486L,55487L,\n55488L,55489L,55490L,55491L,55492L,55493L,55494L,55495L,55496L,55497L,\n55498L,55499L,55500L,55501L,55502L,55503L,55504L,55505L,55506L,55507L,\n55508L,55509L,55510L,55511L,55512L,55513L,55514L,55515L,55516L,55517L,\n55518L,55519L,55520L,55521L,55522L,55523L,55524L,55525L,55526L,55527L,\n55528L,55529L,55530L,55531L,55532L,55533L,55534L,55535L,55536L,55537L,\n55538L,55539L,55540L,55541L,55542L,55543L,55544L,55545L,55546L,55547L,\n55548L,55549L,55550L,55551L,55552L,55553L,55554L,55555L,55556L,55557L,\n55558L,55559L,55560L,55561L,55562L,55563L,55564L,55565L,55566L,55567L,\n55568L,55569L,55570L,55571L,55572L,55573L,55574L,55575L,55576L,55577L,\n55578L,55579L,55580L,55581L,55582L,55583L,55584L,55585L,55586L,55587L,\n55588L,55589L,55590L,55591L,55592L,55593L,55594L,55595L,55596L,55597L,\n55598L,55599L,55600L,55601L,55602L,55603L,55604L,55605L,55606L,55607L,\n55608L,55609L,55610L,55611L,55612L,55613L,55614L,55615L,55616L,55617L,\n55618L,55619L,55620L,55621L,55622L,55623L,55624L,55625L,55626L,55627L,\n55628L,55629L,55630L,55631L,55632L,55633L,55634L,55635L,55636L,55637L,\n55638L,55639L,55640L,55641L,55642L,55643L,55644L,55645L,55646L,55647L,\n55648L,55649L,55650L,55651L,55652L,55653L,55654L,55655L,55656L,55657L,\n55658L,55659L,55660L,55661L,55662L,55663L,55664L,55665L,55666L,55667L,\n55668L,55669L,55670L,55671L,55672L,55673L,55674L,55675L,55676L,55677L,\n55678L,55679L,55680L,55681L,55682L,55683L,55684L,55685L,55686L,55687L,\n55688L,55689L,55690L,55691L,55692L,55693L,55694L,55695L,55696L,55697L,\n55698L,55699L,55700L,55701L,55702L,55703L,55704L,55705L,55706L,55707L,\n55708L,55709L,55710L,55711L,55712L,55713L,55714L,55715L,55716L,55717L,\n55718L,55719L,55720L,55721L,55722L,55723L,55724L,55725L,55726L,55727L,\n55728L,55729L,55730L,55731L,55732L,55733L,55734L,55735L,55736L,55737L,\n55738L,55739L,55740L,55741L,55742L,55743L,55744L,55745L,55746L,55747L,\n55748L,55749L,55750L,55751L,55752L,55753L,55754L,55755L,55756L,55757L,\n55758L,55759L,55760L,55761L,55762L,55763L,55764L,55765L,55766L,55767L,\n55768L,55769L,55770L,55771L,55772L,55773L,55774L,55775L,55776L,55777L,\n55778L,55779L,55780L,55781L,55782L,55783L,55784L,55785L,55786L,55787L,\n55788L,55789L,55790L,55791L,55792L,55793L,55794L,55795L,55796L,55797L,\n55798L,55799L,55800L,55801L,55802L,55803L,55804L,55805L,55806L,55807L,\n55808L,55809L,55810L,55811L,55812L,55813L,55814L,55815L,55816L,55817L,\n55818L,55819L,55820L,55821L,55822L,55823L,55824L,55825L,55826L,55827L,\n55828L,55829L,55830L,55831L,55832L,55833L,55834L,55835L,55836L,55837L,\n55838L,55839L,55840L,55841L,55842L,55843L,55844L,55845L,55846L,55847L,\n55848L,55849L,55850L,55851L,55852L,55853L,55854L,55855L,55856L,55857L,\n55858L,55859L,55860L,55861L,55862L,55863L,55864L,55865L,55866L,55867L,\n55868L,55869L,55870L,55871L,55872L,55873L,55874L,55875L,55876L,55877L,\n55878L,55879L,55880L,55881L,55882L,55883L,55884L,55885L,55886L,55887L,\n55888L,55889L,55890L,55891L,55892L,55893L,55894L,55895L,55896L,55897L,\n55898L,55899L,55900L,55901L,55902L,55903L,55904L,55905L,55906L,55907L,\n55908L,55909L,55910L,55911L,55912L,55913L,55914L,55915L,55916L,55917L,\n55918L,55919L,55920L,55921L,55922L,55923L,55924L,55925L,55926L,55927L,\n55928L,55929L,55930L,55931L,55932L,55933L,55934L,55935L,55936L,55937L,\n55938L,55939L,55940L,55941L,55942L,55943L,55944L,55945L,55946L,55947L,\n55948L,55949L,55950L,55951L,55952L,55953L,55954L,55955L,55956L,55957L,\n55958L,55959L,55960L,55961L,55962L,55963L,55964L,55965L,55966L,55967L,\n55968L,55969L,55970L,55971L,55972L,55973L,55974L,55975L,55976L,55977L,\n55978L,55979L,55980L,55981L,55982L,55983L,55984L,55985L,55986L,55987L,\n55988L,55989L,55990L,55991L,55992L,55993L,55994L,55995L,55996L,55997L,\n55998L,55999L,56000L,56001L,56002L,56003L,56004L,56005L,56006L,56007L,\n56008L,56009L,56010L,56011L,56012L,56013L,56014L,56015L,56016L,56017L,\n56018L,56019L,56020L,56021L,56022L,56023L,56024L,56025L,56026L,56027L,\n56028L,56029L,56030L,56031L,56032L,56033L,56034L,56035L,56036L,56037L,\n56038L,56039L,56040L,56041L,56042L,56043L,56044L,56045L,56046L,56047L,\n56048L,56049L,56050L,56051L,56052L,56053L,56054L,56055L,56056L,56057L,\n56058L,56059L,56060L,56061L,56062L,56063L,56064L,56065L,56066L,56067L,\n56068L,56069L,56070L,56071L,56072L,56073L,56074L,56075L,56076L,56077L,\n56078L,56079L,56080L,56081L,56082L,56083L,56084L,56085L,56086L,56087L,\n56088L,56089L,56090L,56091L,56092L,56093L,56094L,56095L,56096L,56097L,\n56098L,56099L,56100L,56101L,56102L,56103L,56104L,56105L,56106L,56107L,\n56108L,56109L,56110L,56111L,56112L,56113L,56114L,56115L,56116L,56117L,\n56118L,56119L,56120L,56121L,56122L,56123L,56124L,56125L,56126L,56127L,\n56128L,56129L,56130L,56131L,56132L,56133L,56134L,56135L,56136L,56137L,\n56138L,56139L,56140L,56141L,56142L,56143L,56144L,56145L,56146L,56147L,\n56148L,56149L,56150L,56151L,56152L,56153L,56154L,56155L,56156L,56157L,\n56158L,56159L,56160L,56161L,56162L,56163L,56164L,56165L,56166L,56167L,\n56168L,56169L,56170L,56171L,56172L,56173L,56174L,56175L,56176L,56177L,\n56178L,56179L,56180L,56181L,56182L,56183L,56184L,56185L,56186L,56187L,\n56188L,56189L,56190L,56191L,56192L,56193L,56194L,56195L,56196L,56197L,\n56198L,56199L,56200L,56201L,56202L,56203L,56204L,56205L,56206L,56207L,\n56208L,56209L,56210L,56211L,56212L,56213L,56214L,56215L,56216L,56217L,\n56218L,56219L,56220L,56221L,56222L,56223L,56224L,56225L,56226L,56227L,\n56228L,56229L,56230L,56231L,56232L,56233L,56234L,56235L,56236L,56237L,\n56238L,56239L,56240L,56241L,56242L,56243L,56244L,56245L,56246L,56247L,\n56248L,56249L,56250L,56251L,56252L,56253L,56254L,56255L,56256L,56257L,\n56258L,56259L,56260L,56261L,56262L,56263L,56264L,56265L,56266L,56267L,\n56268L,56269L,56270L,56271L,56272L,56273L,56274L,56275L,56276L,56277L,\n56278L,56279L,56280L,56281L,56282L,56283L,56284L,56285L,56286L,56287L,\n56288L,56289L,56290L,56291L,56292L,56293L,56294L,56295L,56296L,56297L,\n56298L,56299L,56300L,56301L,56302L,56303L,56304L,56305L,56306L,56307L,\n56308L,56309L,56310L,56311L,56312L,56313L,56314L,56315L,56316L,56317L,\n56318L,56319L,56320L,56321L,56322L,56323L,56324L,56325L,56326L,56327L,\n56328L,56329L,56330L,56331L,56332L,56333L,56334L,56335L,56336L,56337L,\n56338L,56339L,56340L,56341L,56342L,56343L,56344L,56345L,56346L,56347L,\n56348L,56349L,56350L,56351L,56352L,56353L,56354L,56355L,56356L,56357L,\n56358L,56359L,56360L,56361L,56362L,56363L,56364L,56365L,56366L,56367L,\n56368L,56369L,56370L,56371L,56372L,56373L,56374L,56375L,56376L,56377L,\n56378L,56379L,56380L,56381L,56382L,56383L,56384L,56385L,56386L,56387L,\n56388L,56389L,56390L,56391L,56392L,56393L,56394L,56395L,56396L,56397L,\n56398L,56399L,56400L,56401L,56402L,56403L,56404L,56405L,56406L,56407L,\n56408L,56409L,56410L,56411L,56412L,56413L,56414L,56415L,56416L,56417L,\n56418L,56419L,56420L,56421L,56422L,56423L,56424L,56425L,56426L,56427L,\n56428L,56429L,56430L,56431L,56432L,56433L,56434L,56435L,56436L,56437L,\n56438L,56439L,56440L,56441L,56442L,56443L,56444L,56445L,56446L,56447L,\n56448L,56449L,56450L,56451L,56452L,56453L,56454L,56455L,56456L,56457L,\n56458L,56459L,56460L,56461L,56462L,56463L,56464L,56465L,56466L,56467L,\n56468L,56469L,56470L,56471L,56472L,56473L,56474L,56475L,56476L,56477L,\n56478L,56479L,56480L,56481L,56482L,56483L,56484L,56485L,56486L,56487L,\n56488L,56489L,56490L,56491L,56492L,56493L,56494L,56495L,56496L,56497L,\n56498L,56499L,56500L,56501L,56502L,56503L,56504L,56505L,56506L,56507L,\n56508L,56509L,56510L,56511L,56512L,56513L,56514L,56515L,56516L,56517L,\n56518L,56519L,56520L,56521L,56522L,56523L,56524L,56525L,56526L,56527L,\n56528L,56529L,56530L,56531L,56532L,56533L,56534L,56535L,56536L,56537L,\n56538L,56539L,56540L,56541L,56542L,56543L,56544L,56545L,56546L,56547L,\n56548L,56549L,56550L,56551L,56552L,56553L,56554L,56555L,56556L,56557L,\n56558L,56559L,56560L,56561L,56562L,56563L,56564L,56565L,56566L,56567L,\n56568L,56569L,56570L,56571L,56572L,56573L,56574L,56575L,56576L,56577L,\n56578L,56579L,56580L,56581L,56582L,56583L,56584L,56585L,56586L,56587L,\n56588L,56589L,56590L,56591L,56592L,56593L,56594L,56595L,56596L,56597L,\n56598L,56599L,56600L,56601L,56602L,56603L,56604L,56605L,56606L,56607L,\n56608L,56609L,56610L,56611L,56612L,56613L,56614L,56615L,56616L,56617L,\n56618L,56619L,56620L,56621L,56622L,56623L,56624L,56625L,56626L,56627L,\n56628L,56629L,56630L,56631L,56632L,56633L,56634L,56635L,56636L,56637L,\n56638L,56639L,56640L,56641L,56642L,56643L,56644L,56645L,56646L,56647L,\n56648L,56649L,56650L,56651L,56652L,56653L,56654L,56655L,56656L,56657L,\n56658L,56659L,56660L,56661L,56662L,56663L,56664L,56665L,56666L,56667L,\n56668L,56669L,56670L,56671L,56672L,56673L,56674L,56675L,56676L,56677L,\n56678L,56679L,56680L,56681L,56682L,56683L,56684L,56685L,56686L,56687L,\n56688L,56689L,56690L,56691L,56692L,56693L,56694L,56695L,56696L,56697L,\n56698L,56699L,56700L,56701L,56702L,56703L,56704L,56705L,56706L,56707L,\n56708L,56709L,56710L,56711L,56712L,56713L,56714L,56715L,56716L,56717L,\n56718L,56719L,56720L,56721L,56722L,56723L,56724L,56725L,56726L,56727L,\n56728L,56729L,56730L,56731L,56732L,56733L,56734L,56735L,56736L,56737L,\n56738L,56739L,56740L,56741L,56742L,56743L,56744L,56745L,56746L,56747L,\n56748L,56749L,56750L,56751L,56752L,56753L,56754L,56755L,56756L,56757L,\n56758L,56759L,56760L,56761L,56762L,56763L,56764L,56765L,56766L,56767L,\n56768L,56769L,56770L,56771L,56772L,56773L,56774L,56775L,56776L,56777L,\n56778L,56779L,56780L,56781L,56782L,56783L,56784L,56785L,56786L,56787L,\n56788L,56789L,56790L,56791L,56792L,56793L,56794L,56795L,56796L,56797L,\n56798L,56799L,56800L,56801L,56802L,56803L,56804L,56805L,56806L,56807L,\n56808L,56809L,56810L,56811L,56812L,56813L,56814L,56815L,56816L,56817L,\n56818L,56819L,56820L,56821L,56822L,56823L,56824L,56825L,56826L,56827L,\n56828L,56829L,56830L,56831L,56832L,56833L,56834L,56835L,56836L,56837L,\n56838L,56839L,56840L,56841L,56842L,56843L,56844L,56845L,56846L,56847L,\n56848L,56849L,56850L,56851L,56852L,56853L,56854L,56855L,56856L,56857L,\n56858L,56859L,56860L,56861L,56862L,56863L,56864L,56865L,56866L,56867L,\n56868L,56869L,56870L,56871L,56872L,56873L,56874L,56875L,56876L,56877L,\n56878L,56879L,56880L,56881L,56882L,56883L,56884L,56885L,56886L,56887L,\n56888L,56889L,56890L,56891L,56892L,56893L,56894L,56895L,56896L,56897L,\n56898L,56899L,56900L,56901L,56902L,56903L,56904L,56905L,56906L,56907L,\n56908L,56909L,56910L,56911L,56912L,56913L,56914L,56915L,56916L,56917L,\n56918L,56919L,56920L,56921L,56922L,56923L,56924L,56925L,56926L,56927L,\n56928L,56929L,56930L,56931L,56932L,56933L,56934L,56935L,56936L,56937L,\n56938L,56939L,56940L,56941L,56942L,56943L,56944L,56945L,56946L,56947L,\n56948L,56949L,56950L,56951L,56952L,56953L,56954L,56955L,56956L,56957L,\n56958L,56959L,56960L,56961L,56962L,56963L,56964L,56965L,56966L,56967L,\n56968L,56969L,56970L,56971L,56972L,56973L,56974L,56975L,56976L,56977L,\n56978L,56979L,56980L,56981L,56982L,56983L,56984L,56985L,56986L,56987L,\n56988L,56989L,56990L,56991L,56992L,56993L,56994L,56995L,56996L,56997L,\n56998L,56999L,57000L,57001L,57002L,57003L,57004L,57005L,57006L,57007L,\n57008L,57009L,57010L,57011L,57012L,57013L,57014L,57015L,57016L,57017L,\n57018L,57019L,57020L,57021L,57022L,57023L,57024L,57025L,57026L,57027L,\n57028L,57029L,57030L,57031L,57032L,57033L,57034L,57035L,57036L,57037L,\n57038L,57039L,57040L,57041L,57042L,57043L,57044L,57045L,57046L,57047L,\n57048L,57049L,57050L,57051L,57052L,57053L,57054L,57055L,57056L,57057L,\n57058L,57059L,57060L,57061L,57062L,57063L,57064L,57065L,57066L,57067L,\n57068L,57069L,57070L,57071L,57072L,57073L,57074L,57075L,57076L,57077L,\n57078L,57079L,57080L,57081L,57082L,57083L,57084L,57085L,57086L,57087L,\n57088L,57089L,57090L,57091L,57092L,57093L,57094L,57095L,57096L,57097L,\n57098L,57099L,57100L,57101L,57102L,57103L,57104L,57105L,57106L,57107L,\n57108L,57109L,57110L,57111L,57112L,57113L,57114L,57115L,57116L,57117L,\n57118L,57119L,57120L,57121L,57122L,57123L,57124L,57125L,57126L,57127L,\n57128L,57129L,57130L,57131L,57132L,57133L,57134L,57135L,57136L,57137L,\n57138L,57139L,57140L,57141L,57142L,57143L,57144L,57145L,57146L,57147L,\n57148L,57149L,57150L,57151L,57152L,57153L,57154L,57155L,57156L,57157L,\n57158L,57159L,57160L,57161L,57162L,57163L,57164L,57165L,57166L,57167L,\n57168L,57169L,57170L,57171L,57172L,57173L,57174L,57175L,57176L,57177L,\n57178L,57179L,57180L,57181L,57182L,57183L,57184L,57185L,57186L,57187L,\n57188L,57189L,57190L,57191L,57192L,57193L,57194L,57195L,57196L,57197L,\n57198L,57199L,57200L,57201L,57202L,57203L,57204L,57205L,57206L,57207L,\n57208L,57209L,57210L,57211L,57212L,57213L,57214L,57215L,57216L,57217L,\n57218L,57219L,57220L,57221L,57222L,57223L,57224L,57225L,57226L,57227L,\n57228L,57229L,57230L,57231L,57232L,57233L,57234L,57235L,57236L,57237L,\n57238L,57239L,57240L,57241L,57242L,57243L,57244L,57245L,57246L,57247L,\n57248L,57249L,57250L,57251L,57252L,57253L,57254L,57255L,57256L,57257L,\n57258L,57259L,57260L,57261L,57262L,57263L,57264L,57265L,57266L,57267L,\n57268L,57269L,57270L,57271L,57272L,57273L,57274L,57275L,57276L,57277L,\n57278L,57279L,57280L,57281L,57282L,57283L,57284L,57285L,57286L,57287L,\n57288L,57289L,57290L,57291L,57292L,57293L,57294L,57295L,57296L,57297L,\n57298L,57299L,57300L,57301L,57302L,57303L,57304L,57305L,57306L,57307L,\n57308L,57309L,57310L,57311L,57312L,57313L,57314L,57315L,57316L,57317L,\n57318L,57319L,57320L,57321L,57322L,57323L,57324L,57325L,57326L,57327L,\n57328L,57329L,57330L,57331L,57332L,57333L,57334L,57335L,57336L,57337L,\n57338L,57339L,57340L,57341L,57342L,57343L,57344L,57345L,57346L,57347L,\n57348L,57349L,57350L,57351L,57352L,57353L,57354L,57355L,57356L,57357L,\n57358L,57359L,57360L,57361L,57362L,57363L,57364L,57365L,57366L,57367L,\n57368L,57369L,57370L,57371L,57372L,57373L,57374L,57375L,57376L,57377L,\n57378L,57379L,57380L,57381L,57382L,57383L,57384L,57385L,57386L,57387L,\n57388L,57389L,57390L,57391L,57392L,57393L,57394L,57395L,57396L,57397L,\n57398L,57399L,57400L,57401L,57402L,57403L,57404L,57405L,57406L,57407L,\n57408L,57409L,57410L,57411L,57412L,57413L,57414L,57415L,57416L,57417L,\n57418L,57419L,57420L,57421L,57422L,57423L,57424L,57425L,57426L,57427L,\n57428L,57429L,57430L,57431L,57432L,57433L,57434L,57435L,57436L,57437L,\n57438L,57439L,57440L,57441L,57442L,57443L,57444L,57445L,57446L,57447L,\n57448L,57449L,57450L,57451L,57452L,57453L,57454L,57455L,57456L,57457L,\n57458L,57459L,57460L,57461L,57462L,57463L,57464L,57465L,57466L,57467L,\n57468L,57469L,57470L,57471L,57472L,57473L,57474L,57475L,57476L,57477L,\n57478L,57479L,57480L,57481L,57482L,57483L,57484L,57485L,57486L,57487L,\n57488L,57489L,57490L,57491L,57492L,57493L,57494L,57495L,57496L,57497L,\n57498L,57499L,57500L,57501L,57502L,57503L,57504L,57505L,57506L,57507L,\n57508L,57509L,57510L,57511L,57512L,57513L,57514L,57515L,57516L,57517L,\n57518L,57519L,57520L,57521L,57522L,57523L,57524L,57525L,57526L,57527L,\n57528L,57529L,57530L,57531L,57532L,57533L,57534L,57535L,57536L,57537L,\n57538L,57539L,57540L,57541L,57542L,57543L,57544L,57545L,57546L,57547L,\n57548L,57549L,57550L,57551L,57552L,57553L,57554L,57555L,57556L,57557L,\n57558L,57559L,57560L,57561L,57562L,57563L,57564L,57565L,57566L,57567L,\n57568L,57569L,57570L,57571L,57572L,57573L,57574L,57575L,57576L,57577L,\n57578L,57579L,57580L,57581L,57582L,57583L,57584L,57585L,57586L,57587L,\n57588L,57589L,57590L,57591L,57592L,57593L,57594L,57595L,57596L,57597L,\n57598L,57599L,57600L,57601L,57602L,57603L,57604L,57605L,57606L,57607L,\n57608L,57609L,57610L,57611L,57612L,57613L,57614L,57615L,57616L,57617L,\n57618L,57619L,57620L,57621L,57622L,57623L,57624L,57625L,57626L,57627L,\n57628L,57629L,57630L,57631L,57632L,57633L,57634L,57635L,57636L,57637L,\n57638L,57639L,57640L,57641L,57642L,57643L,57644L,57645L,57646L,57647L,\n57648L,57649L,57650L,57651L,57652L,57653L,57654L,57655L,57656L,57657L,\n57658L,57659L,57660L,57661L,57662L,57663L,57664L,57665L,57666L,57667L,\n57668L,57669L,57670L,57671L,57672L,57673L,57674L,57675L,57676L,57677L,\n57678L,57679L,57680L,57681L,57682L,57683L,57684L,57685L,57686L,57687L,\n57688L,57689L,57690L,57691L,57692L,57693L,57694L,57695L,57696L,57697L,\n57698L,57699L,57700L,57701L,57702L,57703L,57704L,57705L,57706L,57707L,\n57708L,57709L,57710L,57711L,57712L,57713L,57714L,57715L,57716L,57717L,\n57718L,57719L,57720L,57721L,57722L,57723L,57724L,57725L,57726L,57727L,\n57728L,57729L,57730L,57731L,57732L,57733L,57734L,57735L,57736L,57737L,\n57738L,57739L,57740L,57741L,57742L,57743L,57744L,57745L,57746L,57747L,\n57748L,57749L,57750L,57751L,57752L,57753L,57754L,57755L,57756L,57757L,\n57758L,57759L,57760L,57761L,57762L,57763L,57764L,57765L,57766L,57767L,\n57768L,57769L,57770L,57771L,57772L,57773L,57774L,57775L,57776L,57777L,\n57778L,57779L,57780L,57781L,57782L,57783L,57784L,57785L,57786L,57787L,\n57788L,57789L,57790L,57791L,57792L,57793L,57794L,57795L,57796L,57797L,\n57798L,57799L,57800L,57801L,57802L,57803L,57804L,57805L,57806L,57807L,\n57808L,57809L,57810L,57811L,57812L,57813L,57814L,57815L,57816L,57817L,\n57818L,57819L,57820L,57821L,57822L,57823L,57824L,57825L,57826L,57827L,\n57828L,57829L,57830L,57831L,57832L,57833L,57834L,57835L,57836L,57837L,\n57838L,57839L,57840L,57841L,57842L,57843L,57844L,57845L,57846L,57847L,\n57848L,57849L,57850L,57851L,57852L,57853L,57854L,57855L,57856L,57857L,\n57858L,57859L,57860L,57861L,57862L,57863L,57864L,57865L,57866L,57867L,\n57868L,57869L,57870L,57871L,57872L,57873L,57874L,57875L,57876L,57877L,\n57878L,57879L,57880L,57881L,57882L,57883L,57884L,57885L,57886L,57887L,\n57888L,57889L,57890L,57891L,57892L,57893L,57894L,57895L,57896L,57897L,\n57898L,57899L,57900L,57901L,57902L,57903L,57904L,57905L,57906L,57907L,\n57908L,57909L,57910L,57911L,57912L,57913L,57914L,57915L,57916L,57917L,\n57918L,57919L,57920L,57921L,57922L,57923L,57924L,57925L,57926L,57927L,\n57928L,57929L,57930L,57931L,57932L,57933L,57934L,57935L,57936L,57937L,\n57938L,57939L,57940L,57941L,57942L,57943L,57944L,57945L,57946L,57947L,\n57948L,57949L,57950L,57951L,57952L,57953L,57954L,57955L,57956L,57957L,\n57958L,57959L,57960L,57961L,57962L,57963L,57964L,57965L,57966L,57967L,\n57968L,57969L,57970L,57971L,57972L,57973L,57974L,57975L,57976L,57977L,\n57978L,57979L,57980L,57981L,57982L,57983L,57984L,57985L,57986L,57987L,\n57988L,57989L,57990L,57991L,57992L,57993L,57994L,57995L,57996L,57997L,\n57998L,57999L,58000L,58001L,58002L,58003L,58004L,58005L,58006L,58007L,\n58008L,58009L,58010L,58011L,58012L,58013L,58014L,58015L,58016L,58017L,\n58018L,58019L,58020L,58021L,58022L,58023L,58024L,58025L,58026L,58027L,\n58028L,58029L,58030L,58031L,58032L,58033L,58034L,58035L,58036L,58037L,\n58038L,58039L,58040L,58041L,58042L,58043L,58044L,58045L,58046L,58047L,\n58048L,58049L,58050L,58051L,58052L,58053L,58054L,58055L,58056L,58057L,\n58058L,58059L,58060L,58061L,58062L,58063L,58064L,58065L,58066L,58067L,\n58068L,58069L,58070L,58071L,58072L,58073L,58074L,58075L,58076L,58077L,\n58078L,58079L,58080L,58081L,58082L,58083L,58084L,58085L,58086L,58087L,\n58088L,58089L,58090L,58091L,58092L,58093L,58094L,58095L,58096L,58097L,\n58098L,58099L,58100L,58101L,58102L,58103L,58104L,58105L,58106L,58107L,\n58108L,58109L,58110L,58111L,58112L,58113L,58114L,58115L,58116L,58117L,\n58118L,58119L,58120L,58121L,58122L,58123L,58124L,58125L,58126L,58127L,\n58128L,58129L,58130L,58131L,58132L,58133L,58134L,58135L,58136L,58137L,\n58138L,58139L,58140L,58141L,58142L,58143L,58144L,58145L,58146L,58147L,\n58148L,58149L,58150L,58151L,58152L,58153L,58154L,58155L,58156L,58157L,\n58158L,58159L,58160L,58161L,58162L,58163L,58164L,58165L,58166L,58167L,\n58168L,58169L,58170L,58171L,58172L,58173L,58174L,58175L,58176L,58177L,\n58178L,58179L,58180L,58181L,58182L,58183L,58184L,58185L,58186L,58187L,\n58188L,58189L,58190L,58191L,58192L,58193L,58194L,58195L,58196L,58197L,\n58198L,58199L,58200L,58201L,58202L,58203L,58204L,58205L,58206L,58207L,\n58208L,58209L,58210L,58211L,58212L,58213L,58214L,58215L,58216L,58217L,\n58218L,58219L,58220L,58221L,58222L,58223L,58224L,58225L,58226L,58227L,\n58228L,58229L,58230L,58231L,58232L,58233L,58234L,58235L,58236L,58237L,\n58238L,58239L,58240L,58241L,58242L,58243L,58244L,58245L,58246L,58247L,\n58248L,58249L,58250L,58251L,58252L,58253L,58254L,58255L,58256L,58257L,\n58258L,58259L,58260L,58261L,58262L,58263L,58264L,58265L,58266L,58267L,\n58268L,58269L,58270L,58271L,58272L,58273L,58274L,58275L,58276L,58277L,\n58278L,58279L,58280L,58281L,58282L,58283L,58284L,58285L,58286L,58287L,\n58288L,58289L,58290L,58291L,58292L,58293L,58294L,58295L,58296L,58297L,\n58298L,58299L,58300L,58301L,58302L,58303L,58304L,58305L,58306L,58307L,\n58308L,58309L,58310L,58311L,58312L,58313L,58314L,58315L,58316L,58317L,\n58318L,58319L,58320L,58321L,58322L,58323L,58324L,58325L,58326L,58327L,\n58328L,58329L,58330L,58331L,58332L,58333L,58334L,58335L,58336L,58337L,\n58338L,58339L,58340L,58341L,58342L,58343L,58344L,58345L,58346L,58347L,\n58348L,58349L,58350L,58351L,58352L,58353L,58354L,58355L,58356L,58357L,\n58358L,58359L,58360L,58361L,58362L,58363L,58364L,58365L,58366L,58367L,\n58368L,58369L,58370L,58371L,58372L,58373L,58374L,58375L,58376L,58377L,\n58378L,58379L,58380L,58381L,58382L,58383L,58384L,58385L,58386L,58387L,\n58388L,58389L,58390L,58391L,58392L,58393L,58394L,58395L,58396L,58397L,\n58398L,58399L,58400L,58401L,58402L,58403L,58404L,58405L,58406L,58407L,\n58408L,58409L,58410L,58411L,58412L,58413L,58414L,58415L,58416L,58417L,\n58418L,58419L,58420L,58421L,58422L,58423L,58424L,58425L,58426L,58427L,\n58428L,58429L,58430L,58431L,58432L,58433L,58434L,58435L,58436L,58437L,\n58438L,58439L,58440L,58441L,58442L,58443L,58444L,58445L,58446L,58447L,\n58448L,58449L,58450L,58451L,58452L,58453L,58454L,58455L,58456L,58457L,\n58458L,58459L,58460L,58461L,58462L,58463L,58464L,58465L,58466L,58467L,\n58468L,58469L,58470L,58471L,58472L,58473L,58474L,58475L,58476L,58477L,\n58478L,58479L,58480L,58481L,58482L,58483L,58484L,58485L,58486L,58487L,\n58488L,58489L,58490L,58491L,58492L,58493L,58494L,58495L,58496L,58497L,\n58498L,58499L,58500L,58501L,58502L,58503L,58504L,58505L,58506L,58507L,\n58508L,58509L,58510L,58511L,58512L,58513L,58514L,58515L,58516L,58517L,\n58518L,58519L,58520L,58521L,58522L,58523L,58524L,58525L,58526L,58527L,\n58528L,58529L,58530L,58531L,58532L,58533L,58534L,58535L,58536L,58537L,\n58538L,58539L,58540L,58541L,58542L,58543L,58544L,58545L,58546L,58547L,\n58548L,58549L,58550L,58551L,58552L,58553L,58554L,58555L,58556L,58557L,\n58558L,58559L,58560L,58561L,58562L,58563L,58564L,58565L,58566L,58567L,\n58568L,58569L,58570L,58571L,58572L,58573L,58574L,58575L,58576L,58577L,\n58578L,58579L,58580L,58581L,58582L,58583L,58584L,58585L,58586L,58587L,\n58588L,58589L,58590L,58591L,58592L,58593L,58594L,58595L,58596L,58597L,\n58598L,58599L,58600L,58601L,58602L,58603L,58604L,58605L,58606L,58607L,\n58608L,58609L,58610L,58611L,58612L,58613L,58614L,58615L,58616L,58617L,\n58618L,58619L,58620L,58621L,58622L,58623L,58624L,58625L,58626L,58627L,\n58628L,58629L,58630L,58631L,58632L,58633L,58634L,58635L,58636L,58637L,\n58638L,58639L,58640L,58641L,58642L,58643L,58644L,58645L,58646L,58647L,\n58648L,58649L,58650L,58651L,58652L,58653L,58654L,58655L,58656L,58657L,\n58658L,58659L,58660L,58661L,58662L,58663L,58664L,58665L,58666L,58667L,\n58668L,58669L,58670L,58671L,58672L,58673L,58674L,58675L,58676L,58677L,\n58678L,58679L,58680L,58681L,58682L,58683L,58684L,58685L,58686L,58687L,\n58688L,58689L,58690L,58691L,58692L,58693L,58694L,58695L,58696L,58697L,\n58698L,58699L,58700L,58701L,58702L,58703L,58704L,58705L,58706L,58707L,\n58708L,58709L,58710L,58711L,58712L,58713L,58714L,58715L,58716L,58717L,\n58718L,58719L,58720L,58721L,58722L,58723L,58724L,58725L,58726L,58727L,\n58728L,58729L,58730L,58731L,58732L,58733L,58734L,58735L,58736L,58737L,\n58738L,58739L,58740L,58741L,58742L,58743L,58744L,58745L,58746L,58747L,\n58748L,58749L,58750L,58751L,58752L,58753L,58754L,58755L,58756L,58757L,\n58758L,58759L,58760L,58761L,58762L,58763L,58764L,58765L,58766L,58767L,\n58768L,58769L,58770L,58771L,58772L,58773L,58774L,58775L,58776L,58777L,\n58778L,58779L,58780L,58781L,58782L,58783L,58784L,58785L,58786L,58787L,\n58788L,58789L,58790L,58791L,58792L,58793L,58794L,58795L,58796L,58797L,\n58798L,58799L,58800L,58801L,58802L,58803L,58804L,58805L,58806L,58807L,\n58808L,58809L,58810L,58811L,58812L,58813L,58814L,58815L,58816L,58817L,\n58818L,58819L,58820L,58821L,58822L,58823L,58824L,58825L,58826L,58827L,\n58828L,58829L,58830L,58831L,58832L,58833L,58834L,58835L,58836L,58837L,\n58838L,58839L,58840L,58841L,58842L,58843L,58844L,58845L,58846L,58847L,\n58848L,58849L,58850L,58851L,58852L,58853L,58854L,58855L,58856L,58857L,\n58858L,58859L,58860L,58861L,58862L,58863L,58864L,58865L,58866L,58867L,\n58868L,58869L,58870L,58871L,58872L,58873L,58874L,58875L,58876L,58877L,\n58878L,58879L,58880L,58881L,58882L,58883L,58884L,58885L,58886L,58887L,\n58888L,58889L,58890L,58891L,58892L,58893L,58894L,58895L,58896L,58897L,\n58898L,58899L,58900L,58901L,58902L,58903L,58904L,58905L,58906L,58907L,\n58908L,58909L,58910L,58911L,58912L,58913L,58914L,58915L,58916L,58917L,\n58918L,58919L,58920L,58921L,58922L,58923L,58924L,58925L,58926L,58927L,\n58928L,58929L,58930L,58931L,58932L,58933L,58934L,58935L,58936L,58937L,\n58938L,58939L,58940L,58941L,58942L,58943L,58944L,58945L,58946L,58947L,\n58948L,58949L,58950L,58951L,58952L,58953L,58954L,58955L,58956L,58957L,\n58958L,58959L,58960L,58961L,58962L,58963L,58964L,58965L,58966L,58967L,\n58968L,58969L,58970L,58971L,58972L,58973L,58974L,58975L,58976L,58977L,\n58978L,58979L,58980L,58981L,58982L,58983L,58984L,58985L,58986L,58987L,\n58988L,58989L,58990L,58991L,58992L,58993L,58994L,58995L,58996L,58997L,\n58998L,58999L,59000L,59001L,59002L,59003L,59004L,59005L,59006L,59007L,\n59008L,59009L,59010L,59011L,59012L,59013L,59014L,59015L,59016L,59017L,\n59018L,59019L,59020L,59021L,59022L,59023L,59024L,59025L,59026L,59027L,\n59028L,59029L,59030L,59031L,59032L,59033L,59034L,59035L,59036L,59037L,\n59038L,59039L,59040L,59041L,59042L,59043L,59044L,59045L,59046L,59047L,\n59048L,59049L,59050L,59051L,59052L,59053L,59054L,59055L,59056L,59057L,\n59058L,59059L,59060L,59061L,59062L,59063L,59064L,59065L,59066L,59067L,\n59068L,59069L,59070L,59071L,59072L,59073L,59074L,59075L,59076L,59077L,\n59078L,59079L,59080L,59081L,59082L,59083L,59084L,59085L,59086L,59087L,\n59088L,59089L,59090L,59091L,59092L,59093L,59094L,59095L,59096L,59097L,\n59098L,59099L,59100L,59101L,59102L,59103L,59104L,59105L,59106L,59107L,\n59108L,59109L,59110L,59111L,59112L,59113L,59114L,59115L,59116L,59117L,\n59118L,59119L,59120L,59121L,59122L,59123L,59124L,59125L,59126L,59127L,\n59128L,59129L,59130L,59131L,59132L,59133L,59134L,59135L,59136L,59137L,\n59138L,59139L,59140L,59141L,59142L,59143L,59144L,59145L,59146L,59147L,\n59148L,59149L,59150L,59151L,59152L,59153L,59154L,59155L,59156L,59157L,\n59158L,59159L,59160L,59161L,59162L,59163L,59164L,59165L,59166L,59167L,\n59168L,59169L,59170L,59171L,59172L,59173L,59174L,59175L,59176L,59177L,\n59178L,59179L,59180L,59181L,59182L,59183L,59184L,59185L,59186L,59187L,\n59188L,59189L,59190L,59191L,59192L,59193L,59194L,59195L,59196L,59197L,\n59198L,59199L,59200L,59201L,59202L,59203L,59204L,59205L,59206L,59207L,\n59208L,59209L,59210L,59211L,59212L,59213L,59214L,59215L,59216L,59217L,\n59218L,59219L,59220L,59221L,59222L,59223L,59224L,59225L,59226L,59227L,\n59228L,59229L,59230L,59231L,59232L,59233L,59234L,59235L,59236L,59237L,\n59238L,59239L,59240L,59241L,59242L,59243L,59244L,59245L,59246L,59247L,\n59248L,59249L,59250L,59251L,59252L,59253L,59254L,59255L,59256L,59257L,\n59258L,59259L,59260L,59261L,59262L,59263L,59264L,59265L,59266L,59267L,\n59268L,59269L,59270L,59271L,59272L,59273L,59274L,59275L,59276L,59277L,\n59278L,59279L,59280L,59281L,59282L,59283L,59284L,59285L,59286L,59287L,\n59288L,59289L,59290L,59291L,59292L,59293L,59294L,59295L,59296L,59297L,\n59298L,59299L,59300L,59301L,59302L,59303L,59304L,59305L,59306L,59307L,\n59308L,59309L,59310L,59311L,59312L,59313L,59314L,59315L,59316L,59317L,\n59318L,59319L,59320L,59321L,59322L,59323L,59324L,59325L,59326L,59327L,\n59328L,59329L,59330L,59331L,59332L,59333L,59334L,59335L,59336L,59337L,\n59338L,59339L,59340L,59341L,59342L,59343L,59344L,59345L,59346L,59347L,\n59348L,59349L,59350L,59351L,59352L,59353L,59354L,59355L,59356L,59357L,\n59358L,59359L,59360L,59361L,59362L,59363L,59364L,59365L,59366L,59367L,\n59368L,59369L,59370L,59371L,59372L,59373L,59374L,59375L,59376L,59377L,\n59378L,59379L,59380L,59381L,59382L,59383L,59384L,59385L,59386L,59387L,\n59388L,59389L,59390L,59391L,59392L,59393L,59394L,59395L,59396L,59397L,\n59398L,59399L,59400L,59401L,59402L,59403L,59404L,59405L,59406L,59407L,\n59408L,59409L,59410L,59411L,59412L,59413L,59414L,59415L,59416L,59417L,\n59418L,59419L,59420L,59421L,59422L,59423L,59424L,59425L,59426L,59427L,\n59428L,59429L,59430L,59431L,59432L,59433L,59434L,59435L,59436L,59437L,\n59438L,59439L,59440L,59441L,59442L,59443L,59444L,59445L,59446L,59447L,\n59448L,59449L,59450L,59451L,59452L,59453L,59454L,59455L,59456L,59457L,\n59458L,59459L,59460L,59461L,59462L,59463L,59464L,59465L,59466L,59467L,\n59468L,59469L,59470L,59471L,59472L,59473L,59474L,59475L,59476L,59477L,\n59478L,59479L,59480L,59481L,59482L,59483L,59484L,59485L,59486L,59487L,\n59488L,59489L,59490L,59491L,59492L,59493L,59494L,59495L,59496L,59497L,\n59498L,59499L,59500L,59501L,59502L,59503L,59504L,59505L,59506L,59507L,\n59508L,59509L,59510L,59511L,59512L,59513L,59514L,59515L,59516L,59517L,\n59518L,59519L,59520L,59521L,59522L,59523L,59524L,59525L,59526L,59527L,\n59528L,59529L,59530L,59531L,59532L,59533L,59534L,59535L,59536L,59537L,\n59538L,59539L,59540L,59541L,59542L,59543L,59544L,59545L,59546L,59547L,\n59548L,59549L,59550L,59551L,59552L,59553L,59554L,59555L,59556L,59557L,\n59558L,59559L,59560L,59561L,59562L,59563L,59564L,59565L,59566L,59567L,\n59568L,59569L,59570L,59571L,59572L,59573L,59574L,59575L,59576L,59577L,\n59578L,59579L,59580L,59581L,59582L,59583L,59584L,59585L,59586L,59587L,\n59588L,59589L,59590L,59591L,59592L,59593L,59594L,59595L,59596L,59597L,\n59598L,59599L,59600L,59601L,59602L,59603L,59604L,59605L,59606L,59607L,\n59608L,59609L,59610L,59611L,59612L,59613L,59614L,59615L,59616L,59617L,\n59618L,59619L,59620L,59621L,59622L,59623L,59624L,59625L,59626L,59627L,\n59628L,59629L,59630L,59631L,59632L,59633L,59634L,59635L,59636L,59637L,\n59638L,59639L,59640L,59641L,59642L,59643L,59644L,59645L,59646L,59647L,\n59648L,59649L,59650L,59651L,59652L,59653L,59654L,59655L,59656L,59657L,\n59658L,59659L,59660L,59661L,59662L,59663L,59664L,59665L,59666L,59667L,\n59668L,59669L,59670L,59671L,59672L,59673L,59674L,59675L,59676L,59677L,\n59678L,59679L,59680L,59681L,59682L,59683L,59684L,59685L,59686L,59687L,\n59688L,59689L,59690L,59691L,59692L,59693L,59694L,59695L,59696L,59697L,\n59698L,59699L,59700L,59701L,59702L,59703L,59704L,59705L,59706L,59707L,\n59708L,59709L,59710L,59711L,59712L,59713L,59714L,59715L,59716L,59717L,\n59718L,59719L,59720L,59721L,59722L,59723L,59724L,59725L,59726L,59727L,\n59728L,59729L,59730L,59731L,59732L,59733L,59734L,59735L,59736L,59737L,\n59738L,59739L,59740L,59741L,59742L,59743L,59744L,59745L,59746L,59747L,\n59748L,59749L,59750L,59751L,59752L,59753L,59754L,59755L,59756L,59757L,\n59758L,59759L,59760L,59761L,59762L,59763L,59764L,59765L,59766L,59767L,\n59768L,59769L,59770L,59771L,59772L,59773L,59774L,59775L,59776L,59777L,\n59778L,59779L,59780L,59781L,59782L,59783L,59784L,59785L,59786L,59787L,\n59788L,59789L,59790L,59791L,59792L,59793L,59794L,59795L,59796L,59797L,\n59798L,59799L,59800L,59801L,59802L,59803L,59804L,59805L,59806L,59807L,\n59808L,59809L,59810L,59811L,59812L,59813L,59814L,59815L,59816L,59817L,\n59818L,59819L,59820L,59821L,59822L,59823L,59824L,59825L,59826L,59827L,\n59828L,59829L,59830L,59831L,59832L,59833L,59834L,59835L,59836L,59837L,\n59838L,59839L,59840L,59841L,59842L,59843L,59844L,59845L,59846L,59847L,\n59848L,59849L,59850L,59851L,59852L,59853L,59854L,59855L,59856L,59857L,\n59858L,59859L,59860L,59861L,59862L,59863L,59864L,59865L,59866L,59867L,\n59868L,59869L,59870L,59871L,59872L,59873L,59874L,59875L,59876L,59877L,\n59878L,59879L,59880L,59881L,59882L,59883L,59884L,59885L,59886L,59887L,\n59888L,59889L,59890L,59891L,59892L,59893L,59894L,59895L,59896L,59897L,\n59898L,59899L,59900L,59901L,59902L,59903L,59904L,59905L,59906L,59907L,\n59908L,59909L,59910L,59911L,59912L,59913L,59914L,59915L,59916L,59917L,\n59918L,59919L,59920L,59921L,59922L,59923L,59924L,59925L,59926L,59927L,\n59928L,59929L,59930L,59931L,59932L,59933L,59934L,59935L,59936L,59937L,\n59938L,59939L,59940L,59941L,59942L,59943L,59944L,59945L,59946L,59947L,\n59948L,59949L,59950L,59951L,59952L,59953L,59954L,59955L,59956L,59957L,\n59958L,59959L,59960L,59961L,59962L,59963L,59964L,59965L,59966L,59967L,\n59968L,59969L,59970L,59971L,59972L,59973L,59974L,59975L,59976L,59977L,\n59978L,59979L,59980L,59981L,59982L,59983L,59984L,59985L,59986L,59987L,\n59988L,59989L,59990L,59991L,59992L,59993L,59994L,59995L,59996L,59997L,\n59998L,59999L,60000L,60001L,60002L,60003L,60004L,60005L,60006L,60007L,\n60008L,60009L,60010L,60011L,60012L,60013L,60014L,60015L,60016L,60017L,\n60018L,60019L,60020L,60021L,60022L,60023L,60024L,60025L,60026L,60027L,\n60028L,60029L,60030L,60031L,60032L,60033L,60034L,60035L,60036L,60037L,\n60038L,60039L,60040L,60041L,60042L,60043L,60044L,60045L,60046L,60047L,\n60048L,60049L,60050L,60051L,60052L,60053L,60054L,60055L,60056L,60057L,\n60058L,60059L,60060L,60061L,60062L,60063L,60064L,60065L,60066L,60067L,\n60068L,60069L,60070L,60071L,60072L,60073L,60074L,60075L,60076L,60077L,\n60078L,60079L,60080L,60081L,60082L,60083L,60084L,60085L,60086L,60087L,\n60088L,60089L,60090L,60091L,60092L,60093L,60094L,60095L,60096L,60097L,\n60098L,60099L,60100L,60101L,60102L,60103L,60104L,60105L,60106L,60107L,\n60108L,60109L,60110L,60111L,60112L,60113L,60114L,60115L,60116L,60117L,\n60118L,60119L,60120L,60121L,60122L,60123L,60124L,60125L,60126L,60127L,\n60128L,60129L,60130L,60131L,60132L,60133L,60134L,60135L,60136L,60137L,\n60138L,60139L,60140L,60141L,60142L,60143L,60144L,60145L,60146L,60147L,\n60148L,60149L,60150L,60151L,60152L,60153L,60154L,60155L,60156L,60157L,\n60158L,60159L,60160L,60161L,60162L,60163L,60164L,60165L,60166L,60167L,\n60168L,60169L,60170L,60171L,60172L,60173L,60174L,60175L,60176L,60177L,\n60178L,60179L,60180L,60181L,60182L,60183L,60184L,60185L,60186L,60187L,\n60188L,60189L,60190L,60191L,60192L,60193L,60194L,60195L,60196L,60197L,\n60198L,60199L,60200L,60201L,60202L,60203L,60204L,60205L,60206L,60207L,\n60208L,60209L,60210L,60211L,60212L,60213L,60214L,60215L,60216L,60217L,\n60218L,60219L,60220L,60221L,60222L,60223L,60224L,60225L,60226L,60227L,\n60228L,60229L,60230L,60231L,60232L,60233L,60234L,60235L,60236L,60237L,\n60238L,60239L,60240L,60241L,60242L,60243L,60244L,60245L,60246L,60247L,\n60248L,60249L,60250L,60251L,60252L,60253L,60254L,60255L,60256L,60257L,\n60258L,60259L,60260L,60261L,60262L,60263L,60264L,60265L,60266L,60267L,\n60268L,60269L,60270L,60271L,60272L,60273L,60274L,60275L,60276L,60277L,\n60278L,60279L,60280L,60281L,60282L,60283L,60284L,60285L,60286L,60287L,\n60288L,60289L,60290L,60291L,60292L,60293L,60294L,60295L,60296L,60297L,\n60298L,60299L,60300L,60301L,60302L,60303L,60304L,60305L,60306L,60307L,\n60308L,60309L,60310L,60311L,60312L,60313L,60314L,60315L,60316L,60317L,\n60318L,60319L,60320L,60321L,60322L,60323L,60324L,60325L,60326L,60327L,\n60328L,60329L,60330L,60331L,60332L,60333L,60334L,60335L,60336L,60337L,\n60338L,60339L,60340L,60341L,60342L,60343L,60344L,60345L,60346L,60347L,\n60348L,60349L,60350L,60351L,60352L,60353L,60354L,60355L,60356L,60357L,\n60358L,60359L,60360L,60361L,60362L,60363L,60364L,60365L,60366L,60367L,\n60368L,60369L,60370L,60371L,60372L,60373L,60374L,60375L,60376L,60377L,\n60378L,60379L,60380L,60381L,60382L,60383L,60384L,60385L,60386L,60387L,\n60388L,60389L,60390L,60391L,60392L,60393L,60394L,60395L,60396L,60397L,\n60398L,60399L,60400L,60401L,60402L,60403L,60404L,60405L,60406L,60407L,\n60408L,60409L,60410L,60411L,60412L,60413L,60414L,60415L,60416L,60417L,\n60418L,60419L,60420L,60421L,60422L,60423L,60424L,60425L,60426L,60427L,\n60428L,60429L,60430L,60431L,60432L,60433L,60434L,60435L,60436L,60437L,\n60438L,60439L,60440L,60441L,60442L,60443L,60444L,60445L,60446L,60447L,\n60448L,60449L,60450L,60451L,60452L,60453L,60454L,60455L,60456L,60457L,\n60458L,60459L,60460L,60461L,60462L,60463L,60464L,60465L,60466L,60467L,\n60468L,60469L,60470L,60471L,60472L,60473L,60474L,60475L,60476L,60477L,\n60478L,60479L,60480L,60481L,60482L,60483L,60484L,60485L,60486L,60487L,\n60488L,60489L,60490L,60491L,60492L,60493L,60494L,60495L,60496L,60497L,\n60498L,60499L,60500L,60501L,60502L,60503L,60504L,60505L,60506L,60507L,\n60508L,60509L,60510L,60511L,60512L,60513L,60514L,60515L,60516L,60517L,\n60518L,60519L,60520L,60521L,60522L,60523L,60524L,60525L,60526L,60527L,\n60528L,60529L,60530L,60531L,60532L,60533L,60534L,60535L,60536L,60537L,\n60538L,60539L,60540L,60541L,60542L,60543L,60544L,60545L,60546L,60547L,\n60548L,60549L,60550L,60551L,60552L,60553L,60554L,60555L,60556L,60557L,\n60558L,60559L,60560L,60561L,60562L,60563L,60564L,60565L,60566L,60567L,\n60568L,60569L,60570L,60571L,60572L,60573L,60574L,60575L,60576L,60577L,\n60578L,60579L,60580L,60581L,60582L,60583L,60584L,60585L,60586L,60587L,\n60588L,60589L,60590L,60591L,60592L,60593L,60594L,60595L,60596L,60597L,\n60598L,60599L,60600L,60601L,60602L,60603L,60604L,60605L,60606L,60607L,\n60608L,60609L,60610L,60611L,60612L,60613L,60614L,60615L,60616L,60617L,\n60618L,60619L,60620L,60621L,60622L,60623L,60624L,60625L,60626L,60627L,\n60628L,60629L,60630L,60631L,60632L,60633L,60634L,60635L,60636L,60637L,\n60638L,60639L,60640L,60641L,60642L,60643L,60644L,60645L,60646L,60647L,\n60648L,60649L,60650L,60651L,60652L,60653L,60654L,60655L,60656L,60657L,\n60658L,60659L,60660L,60661L,60662L,60663L,60664L,60665L,60666L,60667L,\n60668L,60669L,60670L,60671L,60672L,60673L,60674L,60675L,60676L,60677L,\n60678L,60679L,60680L,60681L,60682L,60683L,60684L,60685L,60686L,60687L,\n60688L,60689L,60690L,60691L,60692L,60693L,60694L,60695L,60696L,60697L,\n60698L,60699L,60700L,60701L,60702L,60703L,60704L,60705L,60706L,60707L,\n60708L,60709L,60710L,60711L,60712L,60713L,60714L,60715L,60716L,60717L,\n60718L,60719L,60720L,60721L,60722L,60723L,60724L,60725L,60726L,60727L,\n60728L,60729L,60730L,60731L,60732L,60733L,60734L,60735L,60736L,60737L,\n60738L,60739L,60740L,60741L,60742L,60743L,60744L,60745L,60746L,60747L,\n60748L,60749L,60750L,60751L,60752L,60753L,60754L,60755L,60756L,60757L,\n60758L,60759L,60760L,60761L,60762L,60763L,60764L,60765L,60766L,60767L,\n60768L,60769L,60770L,60771L,60772L,60773L,60774L,60775L,60776L,60777L,\n60778L,60779L,60780L,60781L,60782L,60783L,60784L,60785L,60786L,60787L,\n60788L,60789L,60790L,60791L,60792L,60793L,60794L,60795L,60796L,60797L,\n60798L,60799L,60800L,60801L,60802L,60803L,60804L,60805L,60806L,60807L,\n60808L,60809L,60810L,60811L,60812L,60813L,60814L,60815L,60816L,60817L,\n60818L,60819L,60820L,60821L,60822L,60823L,60824L,60825L,60826L,60827L,\n60828L,60829L,60830L,60831L,60832L,60833L,60834L,60835L,60836L,60837L,\n60838L,60839L,60840L,60841L,60842L,60843L,60844L,60845L,60846L,60847L,\n60848L,60849L,60850L,60851L,60852L,60853L,60854L,60855L,60856L,60857L,\n60858L,60859L,60860L,60861L,60862L,60863L,60864L,60865L,60866L,60867L,\n60868L,60869L,60870L,60871L,60872L,60873L,60874L,60875L,60876L,60877L,\n60878L,60879L,60880L,60881L,60882L,60883L,60884L,60885L,60886L,60887L,\n60888L,60889L,60890L,60891L,60892L,60893L,60894L,60895L,60896L,60897L,\n60898L,60899L,60900L,60901L,60902L,60903L,60904L,60905L,60906L,60907L,\n60908L,60909L,60910L,60911L,60912L,60913L,60914L,60915L,60916L,60917L,\n60918L,60919L,60920L,60921L,60922L,60923L,60924L,60925L,60926L,60927L,\n60928L,60929L,60930L,60931L,60932L,60933L,60934L,60935L,60936L,60937L,\n60938L,60939L,60940L,60941L,60942L,60943L,60944L,60945L,60946L,60947L,\n60948L,60949L,60950L,60951L,60952L,60953L,60954L,60955L,60956L,60957L,\n60958L,60959L,60960L,60961L,60962L,60963L,60964L,60965L,60966L,60967L,\n60968L,60969L,60970L,60971L,60972L,60973L,60974L,60975L,60976L,60977L,\n60978L,60979L,60980L,60981L,60982L,60983L,60984L,60985L,60986L,60987L,\n60988L,60989L,60990L,60991L,60992L,60993L,60994L,60995L,60996L,60997L,\n60998L,60999L,61000L,61001L,61002L,61003L,61004L,61005L,61006L,61007L,\n61008L,61009L,61010L,61011L,61012L,61013L,61014L,61015L,61016L,61017L,\n61018L,61019L,61020L,61021L,61022L,61023L,61024L,61025L,61026L,61027L,\n61028L,61029L,61030L,61031L,61032L,61033L,61034L,61035L,61036L,61037L,\n61038L,61039L,61040L,61041L,61042L,61043L,61044L,61045L,61046L,61047L,\n61048L,61049L,61050L,61051L,61052L,61053L,61054L,61055L,61056L,61057L,\n61058L,61059L,61060L,61061L,61062L,61063L,61064L,61065L,61066L,61067L,\n61068L,61069L,61070L,61071L,61072L,61073L,61074L,61075L,61076L,61077L,\n61078L,61079L,61080L,61081L,61082L,61083L,61084L,61085L,61086L,61087L,\n61088L,61089L,61090L,61091L,61092L,61093L,61094L,61095L,61096L,61097L,\n61098L,61099L,61100L,61101L,61102L,61103L,61104L,61105L,61106L,61107L,\n61108L,61109L,61110L,61111L,61112L,61113L,61114L,61115L,61116L,61117L,\n61118L,61119L,61120L,61121L,61122L,61123L,61124L,61125L,61126L,61127L,\n61128L,61129L,61130L,61131L,61132L,61133L,61134L,61135L,61136L,61137L,\n61138L,61139L,61140L,61141L,61142L,61143L,61144L,61145L,61146L,61147L,\n61148L,61149L,61150L,61151L,61152L,61153L,61154L,61155L,61156L,61157L,\n61158L,61159L,61160L,61161L,61162L,61163L,61164L,61165L,61166L,61167L,\n61168L,61169L,61170L,61171L,61172L,61173L,61174L,61175L,61176L,61177L,\n61178L,61179L,61180L,61181L,61182L,61183L,61184L,61185L,61186L,61187L,\n61188L,61189L,61190L,61191L,61192L,61193L,61194L,61195L,61196L,61197L,\n61198L,61199L,61200L,61201L,61202L,61203L,61204L,61205L,61206L,61207L,\n61208L,61209L,61210L,61211L,61212L,61213L,61214L,61215L,61216L,61217L,\n61218L,61219L,61220L,61221L,61222L,61223L,61224L,61225L,61226L,61227L,\n61228L,61229L,61230L,61231L,61232L,61233L,61234L,61235L,61236L,61237L,\n61238L,61239L,61240L,61241L,61242L,61243L,61244L,61245L,61246L,61247L,\n61248L,61249L,61250L,61251L,61252L,61253L,61254L,61255L,61256L,61257L,\n61258L,61259L,61260L,61261L,61262L,61263L,61264L,61265L,61266L,61267L,\n61268L,61269L,61270L,61271L,61272L,61273L,61274L,61275L,61276L,61277L,\n61278L,61279L,61280L,61281L,61282L,61283L,61284L,61285L,61286L,61287L,\n61288L,61289L,61290L,61291L,61292L,61293L,61294L,61295L,61296L,61297L,\n61298L,61299L,61300L,61301L,61302L,61303L,61304L,61305L,61306L,61307L,\n61308L,61309L,61310L,61311L,61312L,61313L,61314L,61315L,61316L,61317L,\n61318L,61319L,61320L,61321L,61322L,61323L,61324L,61325L,61326L,61327L,\n61328L,61329L,61330L,61331L,61332L,61333L,61334L,61335L,61336L,61337L,\n61338L,61339L,61340L,61341L,61342L,61343L,61344L,61345L,61346L,61347L,\n61348L,61349L,61350L,61351L,61352L,61353L,61354L,61355L,61356L,61357L,\n61358L,61359L,61360L,61361L,61362L,61363L,61364L,61365L,61366L,61367L,\n61368L,61369L,61370L,61371L,61372L,61373L,61374L,61375L,61376L,61377L,\n61378L,61379L,61380L,61381L,61382L,61383L,61384L,61385L,61386L,61387L,\n61388L,61389L,61390L,61391L,61392L,61393L,61394L,61395L,61396L,61397L,\n61398L,61399L,61400L,61401L,61402L,61403L,61404L,61405L,61406L,61407L,\n61408L,61409L,61410L,61411L,61412L,61413L,61414L,61415L,61416L,61417L,\n61418L,61419L,61420L,61421L,61422L,61423L,61424L,61425L,61426L,61427L,\n61428L,61429L,61430L,61431L,61432L,61433L,61434L,61435L,61436L,61437L,\n61438L,61439L,61440L,61441L,61442L,61443L,61444L,61445L,61446L,61447L,\n61448L,61449L,61450L,61451L,61452L,61453L,61454L,61455L,61456L,61457L,\n61458L,61459L,61460L,61461L,61462L,61463L,61464L,61465L,61466L,61467L,\n61468L,61469L,61470L,61471L,61472L,61473L,61474L,61475L,61476L,61477L,\n61478L,61479L,61480L,61481L,61482L,61483L,61484L,61485L,61486L,61487L,\n61488L,61489L,61490L,61491L,61492L,61493L,61494L,61495L,61496L,61497L,\n61498L,61499L,61500L,61501L,61502L,61503L,61504L,61505L,61506L,61507L,\n61508L,61509L,61510L,61511L,61512L,61513L,61514L,61515L,61516L,61517L,\n61518L,61519L,61520L,61521L,61522L,61523L,61524L,61525L,61526L,61527L,\n61528L,61529L,61530L,61531L,61532L,61533L,61534L,61535L,61536L,61537L,\n61538L,61539L,61540L,61541L,61542L,61543L,61544L,61545L,61546L,61547L,\n61548L,61549L,61550L,61551L,61552L,61553L,61554L,61555L,61556L,61557L,\n61558L,61559L,61560L,61561L,61562L,61563L,61564L,61565L,61566L,61567L,\n61568L,61569L,61570L,61571L,61572L,61573L,61574L,61575L,61576L,61577L,\n61578L,61579L,61580L,61581L,61582L,61583L,61584L,61585L,61586L,61587L,\n61588L,61589L,61590L,61591L,61592L,61593L,61594L,61595L,61596L,61597L,\n61598L,61599L,61600L,61601L,61602L,61603L,61604L,61605L,61606L,61607L,\n61608L,61609L,61610L,61611L,61612L,61613L,61614L,61615L,61616L,61617L,\n61618L,61619L,61620L,61621L,61622L,61623L,61624L,61625L,61626L,61627L,\n61628L,61629L,61630L,61631L,61632L,61633L,61634L,61635L,61636L,61637L,\n61638L,61639L,61640L,61641L,61642L,61643L,61644L,61645L,61646L,61647L,\n61648L,61649L,61650L,61651L,61652L,61653L,61654L,61655L,61656L,61657L,\n61658L,61659L,61660L,61661L,61662L,61663L,61664L,61665L,61666L,61667L,\n61668L,61669L,61670L,61671L,61672L,61673L,61674L,61675L,61676L,61677L,\n61678L,61679L,61680L,61681L,61682L,61683L,61684L,61685L,61686L,61687L,\n61688L,61689L,61690L,61691L,61692L,61693L,61694L,61695L,61696L,61697L,\n61698L,61699L,61700L,61701L,61702L,61703L,61704L,61705L,61706L,61707L,\n61708L,61709L,61710L,61711L,61712L,61713L,61714L,61715L,61716L,61717L,\n61718L,61719L,61720L,61721L,61722L,61723L,61724L,61725L,61726L,61727L,\n61728L,61729L,61730L,61731L,61732L,61733L,61734L,61735L,61736L,61737L,\n61738L,61739L,61740L,61741L,61742L,61743L,61744L,61745L,61746L,61747L,\n61748L,61749L,61750L,61751L,61752L,61753L,61754L,61755L,61756L,61757L,\n61758L,61759L,61760L,61761L,61762L,61763L,61764L,61765L,61766L,61767L,\n61768L,61769L,61770L,61771L,61772L,61773L,61774L,61775L,61776L,61777L,\n61778L,61779L,61780L,61781L,61782L,61783L,61784L,61785L,61786L,61787L,\n61788L,61789L,61790L,61791L,61792L,61793L,61794L,61795L,61796L,61797L,\n61798L,61799L,61800L,61801L,61802L,61803L,61804L,61805L,61806L,61807L,\n61808L,61809L,61810L,61811L,61812L,61813L,61814L,61815L,61816L,61817L,\n61818L,61819L,61820L,61821L,61822L,61823L,61824L,61825L,61826L,61827L,\n61828L,61829L,61830L,61831L,61832L,61833L,61834L,61835L,61836L,61837L,\n61838L,61839L,61840L,61841L,61842L,61843L,61844L,61845L,61846L,61847L,\n61848L,61849L,61850L,61851L,61852L,61853L,61854L,61855L,61856L,61857L,\n61858L,61859L,61860L,61861L,61862L,61863L,61864L,61865L,61866L,61867L,\n61868L,61869L,61870L,61871L,61872L,61873L,61874L,61875L,61876L,61877L,\n61878L,61879L,61880L,61881L,61882L,61883L,61884L,61885L,61886L,61887L,\n61888L,61889L,61890L,61891L,61892L,61893L,61894L,61895L,61896L,61897L,\n61898L,61899L,61900L,61901L,61902L,61903L,61904L,61905L,61906L,61907L,\n61908L,61909L,61910L,61911L,61912L,61913L,61914L,61915L,61916L,61917L,\n61918L,61919L,61920L,61921L,61922L,61923L,61924L,61925L,61926L,61927L,\n61928L,61929L,61930L,61931L,61932L,61933L,61934L,61935L,61936L,61937L,\n61938L,61939L,61940L,61941L,61942L,61943L,61944L,61945L,61946L,61947L,\n61948L,61949L,61950L,61951L,61952L,61953L,61954L,61955L,61956L,61957L,\n61958L,61959L,61960L,61961L,61962L,61963L,61964L,61965L,61966L,61967L,\n61968L,61969L,61970L,61971L,61972L,61973L,61974L,61975L,61976L,61977L,\n61978L,61979L,61980L,61981L,61982L,61983L,61984L,61985L,61986L,61987L,\n61988L,61989L,61990L,61991L,61992L,61993L,61994L,61995L,61996L,61997L,\n61998L,61999L,62000L,62001L,62002L,62003L,62004L,62005L,62006L,62007L,\n62008L,62009L,62010L,62011L,62012L,62013L,62014L,62015L,62016L,62017L,\n62018L,62019L,62020L,62021L,62022L,62023L,62024L,62025L,62026L,62027L,\n62028L,62029L,62030L,62031L,62032L,62033L,62034L,62035L,62036L,62037L,\n62038L,62039L,62040L,62041L,62042L,62043L,62044L,62045L,62046L,62047L,\n62048L,62049L,62050L,62051L,62052L,62053L,62054L,62055L,62056L,62057L,\n62058L,62059L,62060L,62061L,62062L,62063L,62064L,62065L,62066L,62067L,\n62068L,62069L,62070L,62071L,62072L,62073L,62074L,62075L,62076L,62077L,\n62078L,62079L,62080L,62081L,62082L,62083L,62084L,62085L,62086L,62087L,\n62088L,62089L,62090L,62091L,62092L,62093L,62094L,62095L,62096L,62097L,\n62098L,62099L,62100L,62101L,62102L,62103L,62104L,62105L,62106L,62107L,\n62108L,62109L,62110L,62111L,62112L,62113L,62114L,62115L,62116L,62117L,\n62118L,62119L,62120L,62121L,62122L,62123L,62124L,62125L,62126L,62127L,\n62128L,62129L,62130L,62131L,62132L,62133L,62134L,62135L,62136L,62137L,\n62138L,62139L,62140L,62141L,62142L,62143L,62144L,62145L,62146L,62147L,\n62148L,62149L,62150L,62151L,62152L,62153L,62154L,62155L,62156L,62157L,\n62158L,62159L,62160L,62161L,62162L,62163L,62164L,62165L,62166L,62167L,\n62168L,62169L,62170L,62171L,62172L,62173L,62174L,62175L,62176L,62177L,\n62178L,62179L,62180L,62181L,62182L,62183L,62184L,62185L,62186L,62187L,\n62188L,62189L,62190L,62191L,62192L,62193L,62194L,62195L,62196L,62197L,\n62198L,62199L,62200L,62201L,62202L,62203L,62204L,62205L,62206L,62207L,\n62208L,62209L,62210L,62211L,62212L,62213L,62214L,62215L,62216L,62217L,\n62218L,62219L,62220L,62221L,62222L,62223L,62224L,62225L,62226L,62227L,\n62228L,62229L,62230L,62231L,62232L,62233L,62234L,62235L,62236L,62237L,\n62238L,62239L,62240L,62241L,62242L,62243L,62244L,62245L,62246L,62247L,\n62248L,62249L,62250L,62251L,62252L,62253L,62254L,62255L,62256L,62257L,\n62258L,62259L,62260L,62261L,62262L,62263L,62264L,62265L,62266L,62267L,\n62268L,62269L,62270L,62271L,62272L,62273L,62274L,62275L,62276L,62277L,\n62278L,62279L,62280L,62281L,62282L,62283L,62284L,62285L,62286L,62287L,\n62288L,62289L,62290L,62291L,62292L,62293L,62294L,62295L,62296L,62297L,\n62298L,62299L,62300L,62301L,62302L,62303L,62304L,62305L,62306L,62307L,\n62308L,62309L,62310L,62311L,62312L,62313L,62314L,62315L,62316L,62317L,\n62318L,62319L,62320L,62321L,62322L,62323L,62324L,62325L,62326L,62327L,\n62328L,62329L,62330L,62331L,62332L,62333L,62334L,62335L,62336L,62337L,\n62338L,62339L,62340L,62341L,62342L,62343L,62344L,62345L,62346L,62347L,\n62348L,62349L,62350L,62351L,62352L,62353L,62354L,62355L,62356L,62357L,\n62358L,62359L,62360L,62361L,62362L,62363L,62364L,62365L,62366L,62367L,\n62368L,62369L,62370L,62371L,62372L,62373L,62374L,62375L,62376L,62377L,\n62378L,62379L,62380L,62381L,62382L,62383L,62384L,62385L,62386L,62387L,\n62388L,62389L,62390L,62391L,62392L,62393L,62394L,62395L,62396L,62397L,\n62398L,62399L,62400L,62401L,62402L,62403L,62404L,62405L,62406L,62407L,\n62408L,62409L,62410L,62411L,62412L,62413L,62414L,62415L,62416L,62417L,\n62418L,62419L,62420L,62421L,62422L,62423L,62424L,62425L,62426L,62427L,\n62428L,62429L,62430L,62431L,62432L,62433L,62434L,62435L,62436L,62437L,\n62438L,62439L,62440L,62441L,62442L,62443L,62444L,62445L,62446L,62447L,\n62448L,62449L,62450L,62451L,62452L,62453L,62454L,62455L,62456L,62457L,\n62458L,62459L,62460L,62461L,62462L,62463L,62464L,62465L,62466L,62467L,\n62468L,62469L,62470L,62471L,62472L,62473L,62474L,62475L,62476L,62477L,\n62478L,62479L,62480L,62481L,62482L,62483L,62484L,62485L,62486L,62487L,\n62488L,62489L,62490L,62491L,62492L,62493L,62494L,62495L,62496L,62497L,\n62498L,62499L,62500L,62501L,62502L,62503L,62504L,62505L,62506L,62507L,\n62508L,62509L,62510L,62511L,62512L,62513L,62514L,62515L,62516L,62517L,\n62518L,62519L,62520L,62521L,62522L,62523L,62524L,62525L,62526L,62527L,\n62528L,62529L,62530L,62531L,62532L,62533L,62534L,62535L,62536L,62537L,\n62538L,62539L,62540L,62541L,62542L,62543L,62544L,62545L,62546L,62547L,\n62548L,62549L,62550L,62551L,62552L,62553L,62554L,62555L,62556L,62557L,\n62558L,62559L,62560L,62561L,62562L,62563L,62564L,62565L,62566L,62567L,\n62568L,62569L,62570L,62571L,62572L,62573L,62574L,62575L,62576L,62577L,\n62578L,62579L,62580L,62581L,62582L,62583L,62584L,62585L,62586L,62587L,\n62588L,62589L,62590L,62591L,62592L,62593L,62594L,62595L,62596L,62597L,\n62598L,62599L,62600L,62601L,62602L,62603L,62604L,62605L,62606L,62607L,\n62608L,62609L,62610L,62611L,62612L,62613L,62614L,62615L,62616L,62617L,\n62618L,62619L,62620L,62621L,62622L,62623L,62624L,62625L,62626L,62627L,\n62628L,62629L,62630L,62631L,62632L,62633L,62634L,62635L,62636L,62637L,\n62638L,62639L,62640L,62641L,62642L,62643L,62644L,62645L,62646L,62647L,\n62648L,62649L,62650L,62651L,62652L,62653L,62654L,62655L,62656L,62657L,\n62658L,62659L,62660L,62661L,62662L,62663L,62664L,62665L,62666L,62667L,\n62668L,62669L,62670L,62671L,62672L,62673L,62674L,62675L,62676L,62677L,\n62678L,62679L,62680L,62681L,62682L,62683L,62684L,62685L,62686L,62687L,\n62688L,62689L,62690L,62691L,62692L,62693L,62694L,62695L,62696L,62697L,\n62698L,62699L,62700L,62701L,62702L,62703L,62704L,62705L,62706L,62707L,\n62708L,62709L,62710L,62711L,62712L,62713L,62714L,62715L,62716L,62717L,\n62718L,62719L,62720L,62721L,62722L,62723L,62724L,62725L,62726L,62727L,\n62728L,62729L,62730L,62731L,62732L,62733L,62734L,62735L,62736L,62737L,\n62738L,62739L,62740L,62741L,62742L,62743L,62744L,62745L,62746L,62747L,\n62748L,62749L,62750L,62751L,62752L,62753L,62754L,62755L,62756L,62757L,\n62758L,62759L,62760L,62761L,62762L,62763L,62764L,62765L,62766L,62767L,\n62768L,62769L,62770L,62771L,62772L,62773L,62774L,62775L,62776L,62777L,\n62778L,62779L,62780L,62781L,62782L,62783L,62784L,62785L,62786L,62787L,\n62788L,62789L,62790L,62791L,62792L,62793L,62794L,62795L,62796L,62797L,\n62798L,62799L,62800L,62801L,62802L,62803L,62804L,62805L,62806L,62807L,\n62808L,62809L,62810L,62811L,62812L,62813L,62814L,62815L,62816L,62817L,\n62818L,62819L,62820L,62821L,62822L,62823L,62824L,62825L,62826L,62827L,\n62828L,62829L,62830L,62831L,62832L,62833L,62834L,62835L,62836L,62837L,\n62838L,62839L,62840L,62841L,62842L,62843L,62844L,62845L,62846L,62847L,\n62848L,62849L,62850L,62851L,62852L,62853L,62854L,62855L,62856L,62857L,\n62858L,62859L,62860L,62861L,62862L,62863L,62864L,62865L,62866L,62867L,\n62868L,62869L,62870L,62871L,62872L,62873L,62874L,62875L,62876L,62877L,\n62878L,62879L,62880L,62881L,62882L,62883L,62884L,62885L,62886L,62887L,\n62888L,62889L,62890L,62891L,62892L,62893L,62894L,62895L,62896L,62897L,\n62898L,62899L,62900L,62901L,62902L,62903L,62904L,62905L,62906L,62907L,\n62908L,62909L,62910L,62911L,62912L,62913L,62914L,62915L,62916L,62917L,\n62918L,62919L,62920L,62921L,62922L,62923L,62924L,62925L,62926L,62927L,\n62928L,62929L,62930L,62931L,62932L,62933L,62934L,62935L,62936L,62937L,\n62938L,62939L,62940L,62941L,62942L,62943L,62944L,62945L,62946L,62947L,\n62948L,62949L,62950L,62951L,62952L,62953L,62954L,62955L,62956L,62957L,\n62958L,62959L,62960L,62961L,62962L,62963L,62964L,62965L,62966L,62967L,\n62968L,62969L,62970L,62971L,62972L,62973L,62974L,62975L,62976L,62977L,\n62978L,62979L,62980L,62981L,62982L,62983L,62984L,62985L,62986L,62987L,\n62988L,62989L,62990L,62991L,62992L,62993L,62994L,62995L,62996L,62997L,\n62998L,62999L,63000L,63001L,63002L,63003L,63004L,63005L,63006L,63007L,\n63008L,63009L,63010L,63011L,63012L,63013L,63014L,63015L,63016L,63017L,\n63018L,63019L,63020L,63021L,63022L,63023L,63024L,63025L,63026L,63027L,\n63028L,63029L,63030L,63031L,63032L,63033L,63034L,63035L,63036L,63037L,\n63038L,63039L,63040L,63041L,63042L,63043L,63044L,63045L,63046L,63047L,\n63048L,63049L,63050L,63051L,63052L,63053L,63054L,63055L,63056L,63057L,\n63058L,63059L,63060L,63061L,63062L,63063L,63064L,63065L,63066L,63067L,\n63068L,63069L,63070L,63071L,63072L,63073L,63074L,63075L,63076L,63077L,\n63078L,63079L,63080L,63081L,63082L,63083L,63084L,63085L,63086L,63087L,\n63088L,63089L,63090L,63091L,63092L,63093L,63094L,63095L,63096L,63097L,\n63098L,63099L,63100L,63101L,63102L,63103L,63104L,63105L,63106L,63107L,\n63108L,63109L,63110L,63111L,63112L,63113L,63114L,63115L,63116L,63117L,\n63118L,63119L,63120L,63121L,63122L,63123L,63124L,63125L,63126L,63127L,\n63128L,63129L,63130L,63131L,63132L,63133L,63134L,63135L,63136L,63137L,\n63138L,63139L,63140L,63141L,63142L,63143L,63144L,63145L,63146L,63147L,\n63148L,63149L,63150L,63151L,63152L,63153L,63154L,63155L,63156L,63157L,\n63158L,63159L,63160L,63161L,63162L,63163L,63164L,63165L,63166L,63167L,\n63168L,63169L,63170L,63171L,63172L,63173L,63174L,63175L,63176L,63177L,\n63178L,63179L,63180L,63181L,63182L,63183L,63184L,63185L,63186L,63187L,\n63188L,63189L,63190L,63191L,63192L,63193L,63194L,63195L,63196L,63197L,\n63198L,63199L,63200L,63201L,63202L,63203L,63204L,63205L,63206L,63207L,\n63208L,63209L,63210L,63211L,63212L,63213L,63214L,63215L,63216L,63217L,\n63218L,63219L,63220L,63221L,63222L,63223L,63224L,63225L,63226L,63227L,\n63228L,63229L,63230L,63231L,63232L,63233L,63234L,63235L,63236L,63237L,\n63238L,63239L,63240L,63241L,63242L,63243L,63244L,63245L,63246L,63247L,\n63248L,63249L,63250L,63251L,63252L,63253L,63254L,63255L,63256L,63257L,\n63258L,63259L,63260L,63261L,63262L,63263L,63264L,63265L,63266L,63267L,\n63268L,63269L,63270L,63271L,63272L,63273L,63274L,63275L,63276L,63277L,\n63278L,63279L,63280L,63281L,63282L,63283L,63284L,63285L,63286L,63287L,\n63288L,63289L,63290L,63291L,63292L,63293L,63294L,63295L,63296L,63297L,\n63298L,63299L,63300L,63301L,63302L,63303L,63304L,63305L,63306L,63307L,\n63308L,63309L,63310L,63311L,63312L,63313L,63314L,63315L,63316L,63317L,\n63318L,63319L,63320L,63321L,63322L,63323L,63324L,63325L,63326L,63327L,\n63328L,63329L,63330L,63331L,63332L,63333L,63334L,63335L,63336L,63337L,\n63338L,63339L,63340L,63341L,63342L,63343L,63344L,63345L,63346L,63347L,\n63348L,63349L,63350L,63351L,63352L,63353L,63354L,63355L,63356L,63357L,\n63358L,63359L,63360L,63361L,63362L,63363L,63364L,63365L,63366L,63367L,\n63368L,63369L,63370L,63371L,63372L,63373L,63374L,63375L,63376L,63377L,\n63378L,63379L,63380L,63381L,63382L,63383L,63384L,63385L,63386L,63387L,\n63388L,63389L,63390L,63391L,63392L,63393L,63394L,63395L,63396L,63397L,\n63398L,63399L,63400L,63401L,63402L,63403L,63404L,63405L,63406L,63407L,\n63408L,63409L,63410L,63411L,63412L,63413L,63414L,63415L,63416L,63417L,\n63418L,63419L,63420L,63421L,63422L,63423L,63424L,63425L,63426L,63427L,\n63428L,63429L,63430L,63431L,63432L,63433L,63434L,63435L,63436L,63437L,\n63438L,63439L,63440L,63441L,63442L,63443L,63444L,63445L,63446L,63447L,\n63448L,63449L,63450L,63451L,63452L,63453L,63454L,63455L,63456L,63457L,\n63458L,63459L,63460L,63461L,63462L,63463L,63464L,63465L,63466L,63467L,\n63468L,63469L,63470L,63471L,63472L,63473L,63474L,63475L,63476L,63477L,\n63478L,63479L,63480L,63481L,63482L,63483L,63484L,63485L,63486L,63487L,\n63488L,63489L,63490L,63491L,63492L,63493L,63494L,63495L,63496L,63497L,\n63498L,63499L,63500L,63501L,63502L,63503L,63504L,63505L,63506L,63507L,\n63508L,63509L,63510L,63511L,63512L,63513L,63514L,63515L,63516L,63517L,\n63518L,63519L,63520L,63521L,63522L,63523L,63524L,63525L,63526L,63527L,\n63528L,63529L,63530L,63531L,63532L,63533L,63534L,63535L,63536L,63537L,\n63538L,63539L,63540L,63541L,63542L,63543L,63544L,63545L,63546L,63547L,\n63548L,63549L,63550L,63551L,63552L,63553L,63554L,63555L,63556L,63557L,\n63558L,63559L,63560L,63561L,63562L,63563L,63564L,63565L,63566L,63567L,\n63568L,63569L,63570L,63571L,63572L,63573L,63574L,63575L,63576L,63577L,\n63578L,63579L,63580L,63581L,63582L,63583L,63584L,63585L,63586L,63587L,\n63588L,63589L,63590L,63591L,63592L,63593L,63594L,63595L,63596L,63597L,\n63598L,63599L,63600L,63601L,63602L,63603L,63604L,63605L,63606L,63607L,\n63608L,63609L,63610L,63611L,63612L,63613L,63614L,63615L,63616L,63617L,\n63618L,63619L,63620L,63621L,63622L,63623L,63624L,63625L,63626L,63627L,\n63628L,63629L,63630L,63631L,63632L,63633L,63634L,63635L,63636L,63637L,\n63638L,63639L,63640L,63641L,63642L,63643L,63644L,63645L,63646L,63647L,\n63648L,63649L,63650L,63651L,63652L,63653L,63654L,63655L,63656L,63657L,\n63658L,63659L,63660L,63661L,63662L,63663L,63664L,63665L,63666L,63667L,\n63668L,63669L,63670L,63671L,63672L,63673L,63674L,63675L,63676L,63677L,\n63678L,63679L,63680L,63681L,63682L,63683L,63684L,63685L,63686L,63687L,\n63688L,63689L,63690L,63691L,63692L,63693L,63694L,63695L,63696L,63697L,\n63698L,63699L,63700L,63701L,63702L,63703L,63704L,63705L,63706L,63707L,\n63708L,63709L,63710L,63711L,63712L,63713L,63714L,63715L,63716L,63717L,\n63718L,63719L,63720L,63721L,63722L,63723L,63724L,63725L,63726L,63727L,\n63728L,63729L,63730L,63731L,63732L,63733L,63734L,63735L,63736L,63737L,\n63738L,63739L,63740L,63741L,63742L,63743L,63744L,63745L,63746L,63747L,\n63748L,63749L,63750L,63751L,63752L,63753L,63754L,63755L,63756L,63757L,\n63758L,63759L,63760L,63761L,63762L,63763L,63764L,63765L,63766L,63767L,\n63768L,63769L,63770L,63771L,63772L,63773L,63774L,63775L,63776L,63777L,\n63778L,63779L,63780L,63781L,63782L,63783L,63784L,63785L,63786L,63787L,\n63788L,63789L,63790L,63791L,63792L,63793L,63794L,63795L,63796L,63797L,\n63798L,63799L,63800L,63801L,63802L,63803L,63804L,63805L,63806L,63807L,\n63808L,63809L,63810L,63811L,63812L,63813L,63814L,63815L,63816L,63817L,\n63818L,63819L,63820L,63821L,63822L,63823L,63824L,63825L,63826L,63827L,\n63828L,63829L,63830L,63831L,63832L,63833L,63834L,63835L,63836L,63837L,\n63838L,63839L,63840L,63841L,63842L,63843L,63844L,63845L,63846L,63847L,\n63848L,63849L,63850L,63851L,63852L,63853L,63854L,63855L,63856L,63857L,\n63858L,63859L,63860L,63861L,63862L,63863L,63864L,63865L,63866L,63867L,\n63868L,63869L,63870L,63871L,63872L,63873L,63874L,63875L,63876L,63877L,\n63878L,63879L,63880L,63881L,63882L,63883L,63884L,63885L,63886L,63887L,\n63888L,63889L,63890L,63891L,63892L,63893L,63894L,63895L,63896L,63897L,\n63898L,63899L,63900L,63901L,63902L,63903L,63904L,63905L,63906L,63907L,\n63908L,63909L,63910L,63911L,63912L,63913L,63914L,63915L,63916L,63917L,\n63918L,63919L,63920L,63921L,63922L,63923L,63924L,63925L,63926L,63927L,\n63928L,63929L,63930L,63931L,63932L,63933L,63934L,63935L,63936L,63937L,\n63938L,63939L,63940L,63941L,63942L,63943L,63944L,63945L,63946L,63947L,\n63948L,63949L,63950L,63951L,63952L,63953L,63954L,63955L,63956L,63957L,\n63958L,63959L,63960L,63961L,63962L,63963L,63964L,63965L,63966L,63967L,\n63968L,63969L,63970L,63971L,63972L,63973L,63974L,63975L,63976L,63977L,\n63978L,63979L,63980L,63981L,63982L,63983L,63984L,63985L,63986L,63987L,\n63988L,63989L,63990L,63991L,63992L,63993L,63994L,63995L,63996L,63997L,\n63998L,63999L,64000L,64001L,64002L,64003L,64004L,64005L,64006L,64007L,\n64008L,64009L,64010L,64011L,64012L,64013L,64014L,64015L,64016L,64017L,\n64018L,64019L,64020L,64021L,64022L,64023L,64024L,64025L,64026L,64027L,\n64028L,64029L,64030L,64031L,64032L,64033L,64034L,64035L,64036L,64037L,\n64038L,64039L,64040L,64041L,64042L,64043L,64044L,64045L,64046L,64047L,\n64048L,64049L,64050L,64051L,64052L,64053L,64054L,64055L,64056L,64057L,\n64058L,64059L,64060L,64061L,64062L,64063L,64064L,64065L,64066L,64067L,\n64068L,64069L,64070L,64071L,64072L,64073L,64074L,64075L,64076L,64077L,\n64078L,64079L,64080L,64081L,64082L,64083L,64084L,64085L,64086L,64087L,\n64088L,64089L,64090L,64091L,64092L,64093L,64094L,64095L,64096L,64097L,\n64098L,64099L,64100L,64101L,64102L,64103L,64104L,64105L,64106L,64107L,\n64108L,64109L,64110L,64111L,64112L,64113L,64114L,64115L,64116L,64117L,\n64118L,64119L,64120L,64121L,64122L,64123L,64124L,64125L,64126L,64127L,\n64128L,64129L,64130L,64131L,64132L,64133L,64134L,64135L,64136L,64137L,\n64138L,64139L,64140L,64141L,64142L,64143L,64144L,64145L,64146L,64147L,\n64148L,64149L,64150L,64151L,64152L,64153L,64154L,64155L,64156L,64157L,\n64158L,64159L,64160L,64161L,64162L,64163L,64164L,64165L,64166L,64167L,\n64168L,64169L,64170L,64171L,64172L,64173L,64174L,64175L,64176L,64177L,\n64178L,64179L,64180L,64181L,64182L,64183L,64184L,64185L,64186L,64187L,\n64188L,64189L,64190L,64191L,64192L,64193L,64194L,64195L,64196L,64197L,\n64198L,64199L,64200L,64201L,64202L,64203L,64204L,64205L,64206L,64207L,\n64208L,64209L,64210L,64211L,64212L,64213L,64214L,64215L,64216L,64217L,\n64218L,64219L,64220L,64221L,64222L,64223L,64224L,64225L,64226L,64227L,\n64228L,64229L,64230L,64231L,64232L,64233L,64234L,64235L,64236L,64237L,\n64238L,64239L,64240L,64241L,64242L,64243L,64244L,64245L,64246L,64247L,\n64248L,64249L,64250L,64251L,64252L,64253L,64254L,64255L,64256L,64257L,\n64258L,64259L,64260L,64261L,64262L,64263L,64264L,64265L,64266L,64267L,\n64268L,64269L,64270L,64271L,64272L,64273L,64274L,64275L,64276L,64277L,\n64278L,64279L,64280L,64281L,64282L,64283L,64284L,64285L,64286L,64287L,\n64288L,64289L,64290L,64291L,64292L,64293L,64294L,64295L,64296L,64297L,\n64298L,64299L,64300L,64301L,64302L,64303L,64304L,64305L,64306L,64307L,\n64308L,64309L,64310L,64311L,64312L,64313L,64314L,64315L,64316L,64317L,\n64318L,64319L,64320L,64321L,64322L,64323L,64324L,64325L,64326L,64327L,\n64328L,64329L,64330L,64331L,64332L,64333L,64334L,64335L,64336L,64337L,\n64338L,64339L,64340L,64341L,64342L,64343L,64344L,64345L,64346L,64347L,\n64348L,64349L,64350L,64351L,64352L,64353L,64354L,64355L,64356L,64357L,\n64358L,64359L,64360L,64361L,64362L,64363L,64364L,64365L,64366L,64367L,\n64368L,64369L,64370L,64371L,64372L,64373L,64374L,64375L,64376L,64377L,\n64378L,64379L,64380L,64381L,64382L,64383L,64384L,64385L,64386L,64387L,\n64388L,64389L,64390L,64391L,64392L,64393L,64394L,64395L,64396L,64397L,\n64398L,64399L,64400L,64401L,64402L,64403L,64404L,64405L,64406L,64407L,\n64408L,64409L,64410L,64411L,64412L,64413L,64414L,64415L,64416L,64417L,\n64418L,64419L,64420L,64421L,64422L,64423L,64424L,64425L,64426L,64427L,\n64428L,64429L,64430L,64431L,64432L,64433L,64434L,64435L,64436L,64437L,\n64438L,64439L,64440L,64441L,64442L,64443L,64444L,64445L,64446L,64447L,\n64448L,64449L,64450L,64451L,64452L,64453L,64454L,64455L,64456L,64457L,\n64458L,64459L,64460L,64461L,64462L,64463L,64464L,64465L,64466L,64467L,\n64468L,64469L,64470L,64471L,64472L,64473L,64474L,64475L,64476L,64477L,\n64478L,64479L,64480L,64481L,64482L,64483L,64484L,64485L,64486L,64487L,\n64488L,64489L,64490L,64491L,64492L,64493L,64494L,64495L,64496L,64497L,\n64498L,64499L,64500L,64501L,64502L,64503L,64504L,64505L,64506L,64507L,\n64508L,64509L,64510L,64511L,64512L,64513L,64514L,64515L,64516L,64517L,\n64518L,64519L,64520L,64521L,64522L,64523L,64524L,64525L,64526L,64527L,\n64528L,64529L,64530L,64531L,64532L,64533L,64534L,64535L,64536L,64537L,\n64538L,64539L,64540L,64541L,64542L,64543L,64544L,64545L,64546L,64547L,\n64548L,64549L,64550L,64551L,64552L,64553L,64554L,64555L,64556L,64557L,\n64558L,64559L,64560L,64561L,64562L,64563L,64564L,64565L,64566L,64567L,\n64568L,64569L,64570L,64571L,64572L,64573L,64574L,64575L,64576L,64577L,\n64578L,64579L,64580L,64581L,64582L,64583L,64584L,64585L,64586L,64587L,\n64588L,64589L,64590L,64591L,64592L,64593L,64594L,64595L,64596L,64597L,\n64598L,64599L,64600L,64601L,64602L,64603L,64604L,64605L,64606L,64607L,\n64608L,64609L,64610L,64611L,64612L,64613L,64614L,64615L,64616L,64617L,\n64618L,64619L,64620L,64621L,64622L,64623L,64624L,64625L,64626L,64627L,\n64628L,64629L,64630L,64631L,64632L,64633L,64634L,64635L,64636L,64637L,\n64638L,64639L,64640L,64641L,64642L,64643L,64644L,64645L,64646L,64647L,\n64648L,64649L,64650L,64651L,64652L,64653L,64654L,64655L,64656L,64657L,\n64658L,64659L,64660L,64661L,64662L,64663L,64664L,64665L,64666L,64667L,\n64668L,64669L,64670L,64671L,64672L,64673L,64674L,64675L,64676L,64677L,\n64678L,64679L,64680L,64681L,64682L,64683L,64684L,64685L,64686L,64687L,\n64688L,64689L,64690L,64691L,64692L,64693L,64694L,64695L,64696L,64697L,\n64698L,64699L,64700L,64701L,64702L,64703L,64704L,64705L,64706L,64707L,\n64708L,64709L,64710L,64711L,64712L,64713L,64714L,64715L,64716L,64717L,\n64718L,64719L,64720L,64721L,64722L,64723L,64724L,64725L,64726L,64727L,\n64728L,64729L,64730L,64731L,64732L,64733L,64734L,64735L,64736L,64737L,\n64738L,64739L,64740L,64741L,64742L,64743L,64744L,64745L,64746L,64747L,\n64748L,64749L,64750L,64751L,64752L,64753L,64754L,64755L,64756L,64757L,\n64758L,64759L,64760L,64761L,64762L,64763L,64764L,64765L,64766L,64767L,\n64768L,64769L,64770L,64771L,64772L,64773L,64774L,64775L,64776L,64777L,\n64778L,64779L,64780L,64781L,64782L,64783L,64784L,64785L,64786L,64787L,\n64788L,64789L,64790L,64791L,64792L,64793L,64794L,64795L,64796L,64797L,\n64798L,64799L,64800L,64801L,64802L,64803L,64804L,64805L,64806L,64807L,\n64808L,64809L,64810L,64811L,64812L,64813L,64814L,64815L,64816L,64817L,\n64818L,64819L,64820L,64821L,64822L,64823L,64824L,64825L,64826L,64827L,\n64828L,64829L,64830L,64831L,64832L,64833L,64834L,64835L,64836L,64837L,\n64838L,64839L,64840L,64841L,64842L,64843L,64844L,64845L,64846L,64847L,\n64848L,64849L,64850L,64851L,64852L,64853L,64854L,64855L,64856L,64857L,\n64858L,64859L,64860L,64861L,64862L,64863L,64864L,64865L,64866L,64867L,\n64868L,64869L,64870L,64871L,64872L,64873L,64874L,64875L,64876L,64877L,\n64878L,64879L,64880L,64881L,64882L,64883L,64884L,64885L,64886L,64887L,\n64888L,64889L,64890L,64891L,64892L,64893L,64894L,64895L,64896L,64897L,\n64898L,64899L,64900L,64901L,64902L,64903L,64904L,64905L,64906L,64907L,\n64908L,64909L,64910L,64911L,64912L,64913L,64914L,64915L,64916L,64917L,\n64918L,64919L,64920L,64921L,64922L,64923L,64924L,64925L,64926L,64927L,\n64928L,64929L,64930L,64931L,64932L,64933L,64934L,64935L,64936L,64937L,\n64938L,64939L,64940L,64941L,64942L,64943L,64944L,64945L,64946L,64947L,\n64948L,64949L,64950L,64951L,64952L,64953L,64954L,64955L,64956L,64957L,\n64958L,64959L,64960L,64961L,64962L,64963L,64964L,64965L,64966L,64967L,\n64968L,64969L,64970L,64971L,64972L,64973L,64974L,64975L,64976L,64977L,\n64978L,64979L,64980L,64981L,64982L,64983L,64984L,64985L,64986L,64987L,\n64988L,64989L,64990L,64991L,64992L,64993L,64994L,64995L,64996L,64997L,\n64998L,64999L,65000L,65001L,65002L,65003L,65004L,65005L,65006L,65007L,\n65008L,65009L,65010L,65011L,65012L,65013L,65014L,65015L,65016L,65017L,\n65018L,65019L,65020L,65021L,65022L,65023L,65024L,65025L,65026L,65027L,\n65028L,65029L,65030L,65031L,65032L,65033L,65034L,65035L,65036L,65037L,\n65038L,65039L,65040L,65041L,65042L,65043L,65044L,65045L,65046L,65047L,\n65048L,65049L,65050L,65051L,65052L,65053L,65054L,65055L,65056L,65057L,\n65058L,65059L,65060L,65061L,65062L,65063L,65064L,65065L,65066L,65067L,\n65068L,65069L,65070L,65071L,65072L,65073L,65074L,65075L,65076L,65077L,\n65078L,65079L,65080L,65081L,65082L,65083L,65084L,65085L,65086L,65087L,\n65088L,65089L,65090L,65091L,65092L,65093L,65094L,65095L,65096L,65097L,\n65098L,65099L,65100L,65101L,65102L,65103L,65104L,65105L,65106L,65107L,\n65108L,65109L,65110L,65111L,65112L,65113L,65114L,65115L,65116L,65117L,\n65118L,65119L,65120L,65121L,65122L,65123L,65124L,65125L,65126L,65127L,\n65128L,65129L,65130L,65131L,65132L,65133L,65134L,65135L,65136L,65137L,\n65138L,65139L,65140L,65141L,65142L,65143L,65144L,65145L,65146L,65147L,\n65148L,65149L,65150L,65151L,65152L,65153L,65154L,65155L,65156L,65157L,\n65158L,65159L,65160L,65161L,65162L,65163L,65164L,65165L,65166L,65167L,\n65168L,65169L,65170L,65171L,65172L,65173L,65174L,65175L,65176L,65177L,\n65178L,65179L,65180L,65181L,65182L,65183L,65184L,65185L,65186L,65187L,\n65188L,65189L,65190L,65191L,65192L,65193L,65194L,65195L,65196L,65197L,\n65198L,65199L,65200L,65201L,65202L,65203L,65204L,65205L,65206L,65207L,\n65208L,65209L,65210L,65211L,65212L,65213L,65214L,65215L,65216L,65217L,\n65218L,65219L,65220L,65221L,65222L,65223L,65224L,65225L,65226L,65227L,\n65228L,65229L,65230L,65231L,65232L,65233L,65234L,65235L,65236L,65237L,\n65238L,65239L,65240L,65241L,65242L,65243L,65244L,65245L,65246L,65247L,\n65248L,65249L,65250L,65251L,65252L,65253L,65254L,65255L,65256L,65257L,\n65258L,65259L,65260L,65261L,65262L,65263L,65264L,65265L,65266L,65267L,\n65268L,65269L,65270L,65271L,65272L,65273L,65274L,65275L,65276L,65277L,\n65278L,65279L,65280L,65281L,65282L,65283L,65284L,65285L,65286L,65287L,\n65288L,65289L,65290L,65291L,65292L,65293L,65294L,65295L,65296L,65297L,\n65298L,65299L,65300L,65301L,65302L,65303L,65304L,65305L,65306L,65307L,\n65308L,65309L,65310L,65311L,65312L,65313L,65314L,65315L,65316L,65317L,\n65318L,65319L,65320L,65321L,65322L,65323L,65324L,65325L,65326L,65327L,\n65328L,65329L,65330L,65331L,65332L,65333L,65334L,65335L,65336L,65337L,\n65338L,65339L,65340L,65341L,65342L,65343L,65344L,65313L,65314L,65315L,\n65316L,65317L,65318L,65319L,65320L,65321L,65322L,65323L,65324L,65325L,\n65326L,65327L,65328L,65329L,65330L,65331L,65332L,65333L,65334L,65335L,\n65336L,65337L,65338L,65371L,65372L,65373L,65374L,65375L,65376L,65377L,\n65378L,65379L,65380L,65381L,65382L,65383L,65384L,65385L,65386L,65387L,\n65388L,65389L,65390L,65391L,65392L,65393L,65394L,65395L,65396L,65397L,\n65398L,65399L,65400L,65401L,65402L,65403L,65404L,65405L,65406L,65407L,\n65408L,65409L,65410L,65411L,65412L,65413L,65414L,65415L,65416L,65417L,\n65418L,65419L,65420L,65421L,65422L,65423L,65424L,65425L,65426L,65427L,\n65428L,65429L,65430L,65431L,65432L,65433L,65434L,65435L,65436L,65437L,\n65438L,65439L,65440L,65441L,65442L,65443L,65444L,65445L,65446L,65447L,\n65448L,65449L,65450L,65451L,65452L,65453L,65454L,65455L,65456L,65457L,\n65458L,65459L,65460L,65461L,65462L,65463L,65464L,65465L,65466L,65467L,\n65468L,65469L,65470L,65471L,65472L,65473L,65474L,65475L,65476L,65477L,\n65478L,65479L,65480L,65481L,65482L,65483L,65484L,65485L,65486L,65487L,\n65488L,65489L,65490L,65491L,65492L,65493L,65494L,65495L,65496L,65497L,\n65498L,65499L,65500L,65501L,65502L,65503L,65504L,65505L,65506L,65507L,\n65508L,65509L,65510L,65511L,65512L,65513L,65514L,65515L,65516L,65517L,\n65518L,65519L,65520L,65521L,65522L,65523L,65524L,65525L,65526L,65527L,\n65528L,65529L,65530L,65531L,65532L,65533L,65534L,65535L,\n};\n#endif\n\n#if defined(DUK_USE_REGEXP_CANON_BITMAP)\n/*\n *  Automatically generated by extract_caseconv.py, do not edit!\n */\n\nconst duk_uint8_t duk_unicode_re_canon_bitmap[256] = {\n23,0,224,19,1,228,255,255,255,255,255,255,255,255,255,255,255,255,255,127,\n255,255,255,255,255,255,255,255,231,247,0,16,255,227,255,255,63,255,255,\n255,255,255,255,255,1,252,255,255,255,255,255,255,255,255,255,255,255,255,\n255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,\n255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,\n255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,\n255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,\n255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,\n255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,\n227,193,255,255,255,147,255,255,255,255,255,255,255,255,255,255,255,255,\n255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,\n255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,\n255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,\n255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,251,\n};\n#endif\n#line 1 \"duk_util_bitdecoder.c\"\n/*\n *  Bitstream decoder.\n */\n\n/* #include duk_internal.h -> already included */\n\n/* Decode 'bits' bits from the input stream (bits must be 1...24).\n * When reading past bitstream end, zeroes are shifted in.  The result\n * is signed to match duk_bd_decode_flagged.\n */\nDUK_INTERNAL duk_uint32_t duk_bd_decode(duk_bitdecoder_ctx *ctx, duk_small_int_t bits) {\n\tduk_small_int_t shift;\n\tduk_uint32_t mask;\n\tduk_uint32_t tmp;\n\n\t/* Note: cannot read more than 24 bits without possibly shifting top bits out.\n\t * Fixable, but adds complexity.\n\t */\n\tDUK_ASSERT(bits >= 1 && bits <= 24);\n\n\twhile (ctx->currbits < bits) {\n#if 0\n\t\tDUK_DDD(DUK_DDDPRINT(\"decode_bits: shift more data (bits=%ld, currbits=%ld)\",\n\t\t                     (long) bits, (long) ctx->currbits));\n#endif\n\t\tctx->currval <<= 8;\n\t\tif (ctx->offset < ctx->length) {\n\t\t\t/* If ctx->offset >= ctx->length, we \"shift zeroes in\"\n\t\t\t * instead of croaking.\n\t\t\t */\n\t\t\tctx->currval |= ctx->data[ctx->offset++];\n\t\t}\n\t\tctx->currbits += 8;\n\t}\n#if 0\n\tDUK_DDD(DUK_DDDPRINT(\"decode_bits: bits=%ld, currbits=%ld, currval=0x%08lx\",\n\t                     (long) bits, (long) ctx->currbits, (unsigned long) ctx->currval));\n#endif\n\n\t/* Extract 'top' bits of currval; note that the extracted bits do not need\n\t * to be cleared, we just ignore them on next round.\n\t */\n\tshift = ctx->currbits - bits;\n\tmask = (((duk_uint32_t) 1U) << bits) - 1U;\n\ttmp = (ctx->currval >> shift) & mask;\n\tctx->currbits = shift;  /* remaining */\n\n#if 0\n\tDUK_DDD(DUK_DDDPRINT(\"decode_bits: %ld bits -> 0x%08lx (%ld), currbits=%ld, currval=0x%08lx\",\n\t                     (long) bits, (unsigned long) tmp, (long) tmp, (long) ctx->currbits, (unsigned long) ctx->currval));\n#endif\n\n\treturn tmp;\n}\n\nDUK_INTERNAL duk_small_uint_t duk_bd_decode_flag(duk_bitdecoder_ctx *ctx) {\n\treturn (duk_small_uint_t) duk_bd_decode(ctx, 1);\n}\n\n/* Decode a one-bit flag, and if set, decode a value of 'bits', otherwise return\n * default value.\n */\nDUK_INTERNAL duk_uint32_t duk_bd_decode_flagged(duk_bitdecoder_ctx *ctx, duk_small_int_t bits, duk_uint32_t def_value) {\n\tif (duk_bd_decode_flag(ctx)) {\n\t\treturn duk_bd_decode(ctx, bits);\n\t} else {\n\t\treturn def_value;\n\t}\n}\n\n/* Signed variant, allows negative marker value. */\nDUK_INTERNAL duk_int32_t duk_bd_decode_flagged_signed(duk_bitdecoder_ctx *ctx, duk_small_int_t bits, duk_int32_t def_value) {\n\treturn (duk_int32_t) duk_bd_decode_flagged(ctx, bits, (duk_uint32_t) def_value);\n}\n\n/* Shared varint encoding.  Match dukutil.py BitEncode.varuint(). */\nDUK_INTERNAL duk_uint32_t duk_bd_decode_varuint(duk_bitdecoder_ctx *ctx) {\n\tduk_small_uint_t t;\n\n\t/* The bit encoding choices here are based on manual testing against\n\t * the actual varuints generated by genbuiltins.py.\n\t */\n\tswitch (duk_bd_decode(ctx, 2)) {\n\tcase 0:\n\t\treturn 0;  /* [0,0] */\n\tcase 1:\n\t\treturn duk_bd_decode(ctx, 2) + 1;  /* [1,4] */\n\tcase 2:\n\t\treturn duk_bd_decode(ctx, 5) + 5;  /* [5,36] */\n\tdefault:\n\t\tt = duk_bd_decode(ctx, 7);\n\t\tif (t == 0) {\n\t\t\treturn duk_bd_decode(ctx, 20);\n\t\t}\n\t\treturn (t - 1) + 37;  /* [37,163] */\n\t}\n}\n\n/* Decode a bit packed string from a custom format used by genbuiltins.py.\n * This function is here because it's used for both heap and thread inits.\n * Caller must supply the output buffer whose size is NOT checked!\n */\n\n#define DUK__BITPACK_LETTER_LIMIT  26\n#define DUK__BITPACK_LOOKUP1       26\n#define DUK__BITPACK_LOOKUP2       27\n#define DUK__BITPACK_SWITCH1       28\n#define DUK__BITPACK_SWITCH        29\n#define DUK__BITPACK_UNUSED1       30\n#define DUK__BITPACK_EIGHTBIT      31\n\nDUK_LOCAL const duk_uint8_t duk__bitpacked_lookup[16] = {\n\tDUK_ASC_0, DUK_ASC_1, DUK_ASC_2, DUK_ASC_3,\n\tDUK_ASC_4, DUK_ASC_5, DUK_ASC_6, DUK_ASC_7,\n\tDUK_ASC_8, DUK_ASC_9, DUK_ASC_UNDERSCORE, DUK_ASC_SPACE,\n\t0x82, 0x80, DUK_ASC_DOUBLEQUOTE, DUK_ASC_LCURLY\n};\n\nDUK_INTERNAL duk_small_uint_t duk_bd_decode_bitpacked_string(duk_bitdecoder_ctx *bd, duk_uint8_t *out) {\n\tduk_small_uint_t len;\n\tduk_small_uint_t mode;\n\tduk_small_uint_t t;\n\tduk_small_uint_t i;\n\n\tlen = duk_bd_decode(bd, 5);\n\tif (len == 31) {\n\t\tlen = duk_bd_decode(bd, 8);  /* Support up to 256 bytes; rare. */\n\t}\n\n\tmode = 32;  /* 0 = uppercase, 32 = lowercase (= 'a' - 'A') */\n\tfor (i = 0; i < len; i++) {\n\t\tt = duk_bd_decode(bd, 5);\n\t\tif (t < DUK__BITPACK_LETTER_LIMIT) {\n\t\t\tt = t + DUK_ASC_UC_A + mode;\n\t\t} else if (t == DUK__BITPACK_LOOKUP1) {\n\t\t\tt = duk__bitpacked_lookup[duk_bd_decode(bd, 3)];\n\t\t} else if (t == DUK__BITPACK_LOOKUP2) {\n\t\t\tt = duk__bitpacked_lookup[8 + duk_bd_decode(bd, 3)];\n\t\t} else if (t == DUK__BITPACK_SWITCH1) {\n\t\t\tt = duk_bd_decode(bd, 5);\n\t\t\tDUK_ASSERT_DISABLE(t >= 0);  /* unsigned */\n\t\t\tDUK_ASSERT(t <= 25);\n\t\t\tt = t + DUK_ASC_UC_A + (mode ^ 32);\n\t\t} else if (t == DUK__BITPACK_SWITCH) {\n\t\t\tmode = mode ^ 32;\n\t\t\tt = duk_bd_decode(bd, 5);\n\t\t\tDUK_ASSERT_DISABLE(t >= 0);\n\t\t\tDUK_ASSERT(t <= 25);\n\t\t\tt = t + DUK_ASC_UC_A + mode;\n\t\t} else if (t == DUK__BITPACK_EIGHTBIT) {\n\t\t\tt = duk_bd_decode(bd, 8);\n\t\t}\n\t\tout[i] = (duk_uint8_t) t;\n\t}\n\n\treturn len;\n}\n\n/* automatic undefs */\n#undef DUK__BITPACK_EIGHTBIT\n#undef DUK__BITPACK_LETTER_LIMIT\n#undef DUK__BITPACK_LOOKUP1\n#undef DUK__BITPACK_LOOKUP2\n#undef DUK__BITPACK_SWITCH\n#undef DUK__BITPACK_SWITCH1\n#undef DUK__BITPACK_UNUSED1\n#line 1 \"duk_util_bitencoder.c\"\n/*\n *  Bitstream encoder.\n */\n\n/* #include duk_internal.h -> already included */\n\nDUK_INTERNAL void duk_be_encode(duk_bitencoder_ctx *ctx, duk_uint32_t data, duk_small_int_t bits) {\n\tduk_uint8_t tmp;\n\n\tDUK_ASSERT(ctx != NULL);\n\tDUK_ASSERT(ctx->currbits < 8);\n\n\t/* This limitation would be fixable but adds unnecessary complexity. */\n\tDUK_ASSERT(bits >= 1 && bits <= 24);\n\n\tctx->currval = (ctx->currval << bits) | data;\n\tctx->currbits += bits;\n\n\twhile (ctx->currbits >= 8) {\n\t\tif (ctx->offset < ctx->length) {\n\t\t\ttmp = (duk_uint8_t) ((ctx->currval >> (ctx->currbits - 8)) & 0xff);\n\t\t\tctx->data[ctx->offset++] = tmp;\n\t\t} else {\n\t\t\t/* If buffer has been exhausted, truncate bitstream */\n\t\t\tctx->truncated = 1;\n\t\t}\n\n\t\tctx->currbits -= 8;\n\t}\n}\n\nDUK_INTERNAL void duk_be_finish(duk_bitencoder_ctx *ctx) {\n\tduk_small_int_t npad;\n\n\tDUK_ASSERT(ctx != NULL);\n\tDUK_ASSERT(ctx->currbits < 8);\n\n\tnpad = (duk_small_int_t) (8 - ctx->currbits);\n\tif (npad > 0) {\n\t\tduk_be_encode(ctx, 0, npad);\n\t}\n\tDUK_ASSERT(ctx->currbits == 0);\n}\n#line 1 \"duk_util_bufwriter.c\"\n/*\n *  Fast buffer writer with slack management.\n */\n\n/* #include duk_internal.h -> already included */\n\n/*\n *  Macro support functions (use only macros in calling code)\n */\n\nDUK_LOCAL void duk__bw_update_ptrs(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, duk_size_t curr_offset, duk_size_t new_length) {\n\tduk_uint8_t *p;\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(bw_ctx != NULL);\n\tDUK_UNREF(thr);\n\n\tp = (duk_uint8_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, bw_ctx->buf);\n\tDUK_ASSERT(p != NULL || (DUK_HBUFFER_DYNAMIC_GET_SIZE(bw_ctx->buf) == 0 && curr_offset == 0 && new_length == 0));\n\tbw_ctx->p = p + curr_offset;\n\tbw_ctx->p_base = p;\n\tbw_ctx->p_limit = p + new_length;\n}\n\nDUK_INTERNAL void duk_bw_init(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, duk_hbuffer_dynamic *h_buf) {\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(bw_ctx != NULL);\n\tDUK_ASSERT(h_buf != NULL);\n\n\tbw_ctx->buf = h_buf;\n\tduk__bw_update_ptrs(thr, bw_ctx, 0, DUK_HBUFFER_DYNAMIC_GET_SIZE(h_buf));\n}\n\nDUK_INTERNAL void duk_bw_init_pushbuf(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, duk_size_t buf_size) {\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(bw_ctx != NULL);\n\n\t(void) duk_push_dynamic_buffer(thr, buf_size);\n\tbw_ctx->buf = (duk_hbuffer_dynamic *) duk_known_hbuffer(thr, -1);\n\tduk__bw_update_ptrs(thr, bw_ctx, 0, buf_size);\n}\n\n/* Resize target buffer for requested size.  Called by the macro only when the\n * fast path test (= there is space) fails.\n */\nDUK_INTERNAL duk_uint8_t *duk_bw_resize(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, duk_size_t sz) {\n\tduk_size_t curr_off;\n\tduk_size_t add_sz;\n\tduk_size_t new_sz;\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(bw_ctx != NULL);\n\n\t/* We could do this operation without caller updating bw_ctx->ptr,\n\t * but by writing it back here we can share code better.\n\t */\n\n\tcurr_off = (duk_size_t) (bw_ctx->p - bw_ctx->p_base);\n\tadd_sz = (curr_off >> DUK_BW_SLACK_SHIFT) + DUK_BW_SLACK_ADD;\n\tnew_sz = curr_off + sz + add_sz;\n\tif (DUK_UNLIKELY(new_sz < curr_off)) {\n\t\t/* overflow */\n\t\tDUK_ERROR_RANGE(thr, DUK_STR_BUFFER_TOO_LONG);\n\t\treturn NULL;  /* not reachable */\n\t}\n#if 0  /* for manual torture testing: tight allocation, useful with valgrind */\n\tnew_sz = curr_off + sz;\n#endif\n\n\t/* This is important to ensure dynamic buffer data pointer is not\n\t * NULL (which is possible if buffer size is zero), which in turn\n\t * causes portability issues with e.g. memmove() and memcpy().\n\t */\n\tDUK_ASSERT(new_sz >= 1);\n\n\tDUK_DD(DUK_DDPRINT(\"resize bufferwriter from %ld to %ld (add_sz=%ld)\", (long) curr_off, (long) new_sz, (long) add_sz));\n\n\tduk_hbuffer_resize(thr, bw_ctx->buf, new_sz);\n\tduk__bw_update_ptrs(thr, bw_ctx, curr_off, new_sz);\n\treturn bw_ctx->p;\n}\n\n/* Make buffer compact, matching current written size. */\nDUK_INTERNAL void duk_bw_compact(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx) {\n\tduk_size_t len;\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(bw_ctx != NULL);\n\tDUK_UNREF(thr);\n\n\tlen = (duk_size_t) (bw_ctx->p - bw_ctx->p_base);\n\tduk_hbuffer_resize(thr, bw_ctx->buf, len);\n\tduk__bw_update_ptrs(thr, bw_ctx, len, len);\n}\n\nDUK_INTERNAL void duk_bw_write_raw_slice(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t src_off, duk_size_t len) {\n\tduk_uint8_t *p_base;\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(bw != NULL);\n\tDUK_ASSERT(src_off <= DUK_BW_GET_SIZE(thr, bw));\n\tDUK_ASSERT(len <= DUK_BW_GET_SIZE(thr, bw));\n\tDUK_ASSERT(src_off + len <= DUK_BW_GET_SIZE(thr, bw));\n\tDUK_UNREF(thr);\n\n\tp_base = bw->p_base;\n\tDUK_MEMCPY((void *) bw->p,\n\t           (const void *) (p_base + src_off),\n\t           (size_t) len);\n\tbw->p += len;\n}\n\nDUK_INTERNAL void duk_bw_write_ensure_slice(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t src_off, duk_size_t len) {\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(bw != NULL);\n\tDUK_ASSERT(src_off <= DUK_BW_GET_SIZE(thr, bw));\n\tDUK_ASSERT(len <= DUK_BW_GET_SIZE(thr, bw));\n\tDUK_ASSERT(src_off + len <= DUK_BW_GET_SIZE(thr, bw));\n\n\tDUK_BW_ENSURE(thr, bw, len);\n\tduk_bw_write_raw_slice(thr, bw, src_off, len);\n}\n\nDUK_INTERNAL void duk_bw_insert_raw_bytes(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t dst_off, const duk_uint8_t *buf, duk_size_t len) {\n\tduk_uint8_t *p_base;\n\tduk_size_t buf_sz, move_sz;\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(bw != NULL);\n\tDUK_ASSERT(dst_off <= DUK_BW_GET_SIZE(thr, bw));\n\tDUK_ASSERT(buf != NULL);\n\tDUK_UNREF(thr);\n\n\tp_base = bw->p_base;\n\tbuf_sz = (duk_size_t) (bw->p - p_base);  /* constrained by maximum buffer size */\n\tmove_sz = buf_sz - dst_off;\n\n\tDUK_ASSERT(p_base != NULL);  /* buffer size is >= 1 */\n\tDUK_MEMMOVE((void *) (p_base + dst_off + len),\n\t            (const void *) (p_base + dst_off),\n\t            (size_t) move_sz);\n\tDUK_MEMCPY((void *) (p_base + dst_off),\n\t           (const void *) buf,\n\t           (size_t) len);\n\tbw->p += len;\n}\n\nDUK_INTERNAL void duk_bw_insert_ensure_bytes(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t dst_off, const duk_uint8_t *buf, duk_size_t len) {\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(bw != NULL);\n\tDUK_ASSERT(dst_off <= DUK_BW_GET_SIZE(thr, bw));\n\tDUK_ASSERT(buf != NULL);\n\n\tDUK_BW_ENSURE(thr, bw, len);\n\tduk_bw_insert_raw_bytes(thr, bw, dst_off, buf, len);\n}\n\nDUK_INTERNAL void duk_bw_insert_raw_slice(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t dst_off, duk_size_t src_off, duk_size_t len) {\n\tduk_uint8_t *p_base;\n\tduk_size_t buf_sz, move_sz;\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(bw != NULL);\n\tDUK_ASSERT(dst_off <= DUK_BW_GET_SIZE(thr, bw));\n\tDUK_ASSERT(src_off <= DUK_BW_GET_SIZE(thr, bw));\n\tDUK_ASSERT(len <= DUK_BW_GET_SIZE(thr, bw));\n\tDUK_ASSERT(src_off + len <= DUK_BW_GET_SIZE(thr, bw));\n\tDUK_UNREF(thr);\n\n\tp_base = bw->p_base;\n\n\t/* Don't support \"straddled\" source now. */\n\tDUK_ASSERT(dst_off <= src_off || dst_off >= src_off + len);\n\n\tif (dst_off <= src_off) {\n\t\t/* Target is before source.  Source offset is expressed as\n\t\t * a \"before change\" offset.  Account for the memmove.\n\t\t */\n\t\tsrc_off += len;\n\t}\n\n\tbuf_sz = (duk_size_t) (bw->p - p_base);\n\tmove_sz = buf_sz - dst_off;\n\n\tDUK_ASSERT(p_base != NULL);  /* buffer size is >= 1 */\n\tDUK_MEMMOVE((void *) (p_base + dst_off + len),\n\t            (const void *) (p_base + dst_off),\n\t            (size_t) move_sz);\n\tDUK_MEMCPY((void *) (p_base + dst_off),\n\t           (const void *) (p_base + src_off),\n\t           (size_t) len);\n\tbw->p += len;\n}\n\nDUK_INTERNAL void duk_bw_insert_ensure_slice(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t dst_off, duk_size_t src_off, duk_size_t len) {\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(bw != NULL);\n\tDUK_ASSERT(dst_off <= DUK_BW_GET_SIZE(thr, bw));\n\tDUK_ASSERT(src_off <= DUK_BW_GET_SIZE(thr, bw));\n\tDUK_ASSERT(len <= DUK_BW_GET_SIZE(thr, bw));\n\tDUK_ASSERT(src_off + len <= DUK_BW_GET_SIZE(thr, bw));\n\n\t/* Don't support \"straddled\" source now. */\n\tDUK_ASSERT(dst_off <= src_off || dst_off >= src_off + len);\n\n\tDUK_BW_ENSURE(thr, bw, len);\n\tduk_bw_insert_raw_slice(thr, bw, dst_off, src_off, len);\n}\n\nDUK_INTERNAL duk_uint8_t *duk_bw_insert_raw_area(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t off, duk_size_t len) {\n\tduk_uint8_t *p_base, *p_dst, *p_src;\n\tduk_size_t buf_sz, move_sz;\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(bw != NULL);\n\tDUK_ASSERT(off <= DUK_BW_GET_SIZE(thr, bw));\n\tDUK_UNREF(thr);\n\n\tp_base = bw->p_base;\n\tbuf_sz = (duk_size_t) (bw->p - p_base);\n\tmove_sz = buf_sz - off;\n\tp_dst = p_base + off + len;\n\tp_src = p_base + off;\n\tDUK_MEMMOVE((void *) p_dst, (const void *) p_src, (size_t) move_sz);\n\treturn p_src;  /* point to start of 'reserved area' */\n}\n\nDUK_INTERNAL duk_uint8_t *duk_bw_insert_ensure_area(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t off, duk_size_t len) {\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(bw != NULL);\n\tDUK_ASSERT(off <= DUK_BW_GET_SIZE(thr, bw));\n\n\tDUK_BW_ENSURE(thr, bw, len);\n\treturn duk_bw_insert_raw_area(thr, bw, off, len);\n}\n\nDUK_INTERNAL void duk_bw_remove_raw_slice(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t off, duk_size_t len) {\n\tduk_size_t move_sz;\n\n\tduk_uint8_t *p_base;\n\tduk_uint8_t *p_src;\n\tduk_uint8_t *p_dst;\n\n\tDUK_ASSERT(thr != NULL);\n\tDUK_ASSERT(bw != NULL);\n\tDUK_ASSERT(off <= DUK_BW_GET_SIZE(thr, bw));\n\tDUK_ASSERT(len <= DUK_BW_GET_SIZE(thr, bw));\n\tDUK_ASSERT(off + len <= DUK_BW_GET_SIZE(thr, bw));\n\tDUK_UNREF(thr);\n\n\tp_base = bw->p_base;\n\tp_dst = p_base + off;\n\tp_src = p_dst + len;\n\tmove_sz = (duk_size_t) (bw->p - p_src);\n\tDUK_MEMMOVE((void *) p_dst,\n\t            (const void *) p_src,\n\t            (size_t) move_sz);\n\tbw->p -= len;\n}\n\n/*\n *  Macro support functions for reading/writing raw data.\n *\n *  These are done using mempcy to ensure they're valid even for unaligned\n *  reads/writes on platforms where alignment counts.  On x86 at least gcc\n *  is able to compile these into a bswap+mov.  \"Always inline\" is used to\n *  ensure these macros compile to minimal code.\n *\n *  Not really bufwriter related, but currently used together.\n */\n\nDUK_INTERNAL DUK_ALWAYS_INLINE duk_uint16_t duk_raw_read_u16_be(duk_uint8_t **p) {\n\tunion {\n\t\tduk_uint8_t b[2];\n\t\tduk_uint16_t x;\n\t} u;\n\n\tDUK_MEMCPY((void *) u.b, (const void *) (*p), (size_t) 2);\n\tu.x = DUK_NTOH16(u.x);\n\t*p += 2;\n\treturn u.x;\n}\n\nDUK_INTERNAL DUK_ALWAYS_INLINE duk_uint32_t duk_raw_read_u32_be(duk_uint8_t **p) {\n\tunion {\n\t\tduk_uint8_t b[4];\n\t\tduk_uint32_t x;\n\t} u;\n\n\tDUK_MEMCPY((void *) u.b, (const void *) (*p), (size_t) 4);\n\tu.x = DUK_NTOH32(u.x);\n\t*p += 4;\n\treturn u.x;\n}\n\nDUK_INTERNAL DUK_ALWAYS_INLINE duk_double_t duk_raw_read_double_be(duk_uint8_t **p) {\n\tduk_double_union du;\n\tunion {\n\t\tduk_uint8_t b[4];\n\t\tduk_uint32_t x;\n\t} u;\n\n\tDUK_MEMCPY((void *) u.b, (const void *) (*p), (size_t) 4);\n\tu.x = DUK_NTOH32(u.x);\n\tdu.ui[DUK_DBL_IDX_UI0] = u.x;\n\tDUK_MEMCPY((void *) u.b, (const void *) (*p + 4), (size_t) 4);\n\tu.x = DUK_NTOH32(u.x);\n\tdu.ui[DUK_DBL_IDX_UI1] = u.x;\n\t*p += 8;\n\n\treturn du.d;\n}\n\nDUK_INTERNAL DUK_ALWAYS_INLINE void duk_raw_write_u16_be(duk_uint8_t **p, duk_uint16_t val) {\n\tunion {\n\t\tduk_uint8_t b[2];\n\t\tduk_uint16_t x;\n\t} u;\n\n\tu.x = DUK_HTON16(val);\n\tDUK_MEMCPY((void *) (*p), (const void *) u.b, (size_t) 2);\n\t*p += 2;\n}\n\nDUK_INTERNAL DUK_ALWAYS_INLINE void duk_raw_write_u32_be(duk_uint8_t **p, duk_uint32_t val) {\n\tunion {\n\t\tduk_uint8_t b[4];\n\t\tduk_uint32_t x;\n\t} u;\n\n\tu.x = DUK_HTON32(val);\n\tDUK_MEMCPY((void *) (*p), (const void *) u.b, (size_t) 4);\n\t*p += 4;\n}\n\nDUK_INTERNAL DUK_ALWAYS_INLINE void duk_raw_write_double_be(duk_uint8_t **p, duk_double_t val) {\n\tduk_double_union du;\n\tunion {\n\t\tduk_uint8_t b[4];\n\t\tduk_uint32_t x;\n\t} u;\n\n\tdu.d = val;\n\tu.x = du.ui[DUK_DBL_IDX_UI0];\n\tu.x = DUK_HTON32(u.x);\n\tDUK_MEMCPY((void *) (*p), (const void *) u.b, (size_t) 4);\n\tu.x = du.ui[DUK_DBL_IDX_UI1];\n\tu.x = DUK_HTON32(u.x);\n\tDUK_MEMCPY((void *) (*p + 4), (const void *) u.b, (size_t) 4);\n\t*p += 8;\n}\n#line 1 \"duk_util_hashbytes.c\"\n/*\n *  Hash function duk_util_hashbytes().\n *\n *  Currently, 32-bit MurmurHash2.\n *\n *  Don't rely on specific hash values; hash function may be endianness\n *  dependent, for instance.\n */\n\n/* #include duk_internal.h -> already included */\n\n#if defined(DUK_USE_STRHASH_DENSE)\n/* 'magic' constants for Murmurhash2 */\n#define DUK__MAGIC_M  ((duk_uint32_t) 0x5bd1e995UL)\n#define DUK__MAGIC_R  24\n\nDUK_INTERNAL duk_uint32_t duk_util_hashbytes(const duk_uint8_t *data, duk_size_t len, duk_uint32_t seed) {\n\tduk_uint32_t h = seed ^ ((duk_uint32_t) len);\n\n\twhile (len >= 4) {\n\t\t/* Portability workaround is required for platforms without\n\t\t * unaligned access.  The replacement code emulates little\n\t\t * endian access even on big endian architectures, which is\n\t\t * OK as long as it is consistent for a build.\n\t\t */\n#if defined(DUK_USE_HASHBYTES_UNALIGNED_U32_ACCESS)\n\t\tduk_uint32_t k = *((const duk_uint32_t *) (const void *) data);\n#else\n\t\tduk_uint32_t k = ((duk_uint32_t) data[0]) |\n\t\t                 (((duk_uint32_t) data[1]) << 8) |\n\t\t                 (((duk_uint32_t) data[2]) << 16) |\n\t\t                 (((duk_uint32_t) data[3]) << 24);\n#endif\n\n\t\tk *= DUK__MAGIC_M;\n\t\tk ^= k >> DUK__MAGIC_R;\n\t\tk *= DUK__MAGIC_M;\n\t\th *= DUK__MAGIC_M;\n\t\th ^= k;\n\t\tdata += 4;\n\t\tlen -= 4;\n\t}\n\n\tswitch (len) {\n\tcase 3: h ^= data[2] << 16;\n\tcase 2: h ^= data[1] << 8;\n\tcase 1: h ^= data[0];\n\t        h *= DUK__MAGIC_M;\n        }\n\n\th ^= h >> 13;\n\th *= DUK__MAGIC_M;\n\th ^= h >> 15;\n\n\treturn h;\n}\n#endif  /* DUK_USE_STRHASH_DENSE */\n\n/* automatic undefs */\n#undef DUK__MAGIC_M\n#undef DUK__MAGIC_R\n#line 1 \"duk_util_tinyrandom.c\"\n/*\n *  A tiny random number generator used for Math.random() and other internals.\n *\n *  Default algorithm is xoroshiro128+: http://xoroshiro.di.unimi.it/xoroshiro128plus.c\n *  with SplitMix64 seed preparation: http://xorshift.di.unimi.it/splitmix64.c.\n *\n *  Low memory targets and targets without 64-bit types use a slightly smaller\n *  (but slower) algorithm by Adi Shamir:\n *  http://www.woodmann.com/forum/archive/index.php/t-3100.html.\n *\n */\n\n/* #include duk_internal.h -> already included */\n\n#if !defined(DUK_USE_GET_RANDOM_DOUBLE)\n\n#if defined(DUK_USE_PREFER_SIZE) || !defined(DUK_USE_64BIT_OPS)\n#define DUK__RANDOM_SHAMIR3OP\n#else\n#define DUK__RANDOM_XOROSHIRO128PLUS\n#endif\n\n#if defined(DUK__RANDOM_SHAMIR3OP)\n#define DUK__UPDATE_RND(rnd) do { \\\n\t\t(rnd) += ((rnd) * (rnd)) | 0x05UL; \\\n\t\t(rnd) = ((rnd) & 0xffffffffUL);       /* if duk_uint32_t is exactly 32 bits, this is a NOP */ \\\n\t} while (0)\n\n#define DUK__RND_BIT(rnd)  ((rnd) >> 31)  /* only use the highest bit */\n\nDUK_INTERNAL void duk_util_tinyrandom_prepare_seed(duk_hthread *thr) {\n\tDUK_UNREF(thr);  /* Nothing now. */\n}\n\nDUK_INTERNAL duk_double_t duk_util_tinyrandom_get_double(duk_hthread *thr) {\n\tduk_double_t t;\n\tduk_small_int_t n;\n\tduk_uint32_t rnd;\n\n\trnd = thr->heap->rnd_state;\n\n\tn = 53;  /* enough to cover the whole mantissa */\n\tt = 0.0;\n\n\tdo {\n\t\tDUK__UPDATE_RND(rnd);\n\t\tt += DUK__RND_BIT(rnd);\n\t\tt /= 2.0;\n\t} while (--n);\n\n\tthr->heap->rnd_state = rnd;\n\n\tDUK_ASSERT(t >= (duk_double_t) 0.0);\n\tDUK_ASSERT(t < (duk_double_t) 1.0);\n\n\treturn t;\n}\n#endif  /* DUK__RANDOM_SHAMIR3OP */\n\n#if defined(DUK__RANDOM_XOROSHIRO128PLUS)\nDUK_LOCAL DUK_ALWAYS_INLINE duk_uint64_t duk__rnd_splitmix64(duk_uint64_t *x) {\n\tduk_uint64_t z;\n\tz = (*x += DUK_U64_CONSTANT(0x9E3779B97F4A7C15));\n\tz = (z ^ (z >> 30U)) * DUK_U64_CONSTANT(0xBF58476D1CE4E5B9);\n\tz = (z ^ (z >> 27U)) * DUK_U64_CONSTANT(0x94D049BB133111EB);\n\treturn z ^ (z >> 31U);\n}\n\nDUK_LOCAL DUK_ALWAYS_INLINE duk_uint64_t duk__rnd_rotl(const duk_uint64_t x, duk_small_uint_t k) {\n\treturn (x << k) | (x >> (64U - k));\n}\n\nDUK_LOCAL DUK_ALWAYS_INLINE duk_uint64_t duk__xoroshiro128plus(duk_uint64_t *s) {\n\tduk_uint64_t s0;\n\tduk_uint64_t s1;\n\tduk_uint64_t res;\n\n\ts0 = s[0];\n\ts1 = s[1];\n\tres = s0 + s1;\n\ts1 ^= s0;\n\ts[0] = duk__rnd_rotl(s0, 55) ^ s1 ^ (s1 << 14U);\n\ts[1] = duk__rnd_rotl(s1, 36);\n\n\treturn res;\n}\n\nDUK_INTERNAL void duk_util_tinyrandom_prepare_seed(duk_hthread *thr) {\n\tduk_small_uint_t i;\n\tduk_uint64_t x;\n\n\t/* Mix both halves of the initial seed with SplitMix64.  The intent\n\t * is to ensure that very similar raw seeds (which is usually the case\n\t * because current seed is Date.now()) result in different xoroshiro128+\n\t * seeds.\n\t */\n\tx = thr->heap->rnd_state[0];  /* Only [0] is used as input here. */\n\tfor (i = 0; i < 64; i++) {\n\t\tthr->heap->rnd_state[i & 0x01] = duk__rnd_splitmix64(&x);  /* Keep last 2 values. */\n\t}\n}\n\nDUK_INTERNAL duk_double_t duk_util_tinyrandom_get_double(duk_hthread *thr) {\n\tduk_uint64_t v;\n\tduk_double_union du;\n\n\t/* For big and little endian the integer and IEEE double byte order\n\t * is the same so a direct assignment works.  For mixed endian the\n\t * 32-bit parts must be swapped.\n\t */\n\tv = (DUK_U64_CONSTANT(0x3ff) << 52U) | (duk__xoroshiro128plus((duk_uint64_t *) thr->heap->rnd_state) >> 12U);\n\tdu.ull[0] = v;\n#if defined(DUK_USE_DOUBLE_ME)\n\tdo {\n\t\tduk_uint32_t tmp;\n\t\ttmp = du.ui[0];\n\t\tdu.ui[0] = du.ui[1];\n\t\tdu.ui[1] = tmp;\n\t} while (0);\n#endif\n\treturn du.d - 1.0;\n}\n#endif  /* DUK__RANDOM_XOROSHIRO128PLUS */\n\n#endif  /* !DUK_USE_GET_RANDOM_DOUBLE */\n\n/* automatic undefs */\n#undef DUK__RANDOM_SHAMIR3OP\n#undef DUK__RANDOM_XOROSHIRO128PLUS\n#undef DUK__RND_BIT\n#undef DUK__UPDATE_RND\n"
  },
  {
    "path": "src/engine/script/duktape-2.2.0/duktape.h",
    "content": "/*\n *  Duktape public API for Duktape 2.2.0.\n *\n *  See the API reference for documentation on call semantics.  The exposed,\n *  supported API is between the \"BEGIN PUBLIC API\" and \"END PUBLIC API\"\n *  comments.  Other parts of the header are Duktape internal and related to\n *  e.g. platform/compiler/feature detection.\n *\n *  Git commit a459cf3c9bd1779fc01b435d69302b742675a08f (v2.2.0).\n *  Git branch master.\n *\n *  See Duktape AUTHORS.rst and LICENSE.txt for copyright and\n *  licensing information.\n */\n\n/* LICENSE.txt */\n/*\n *  ===============\n *  Duktape license\n *  ===============\n *  \n *  (http://opensource.org/licenses/MIT)\n *  \n *  Copyright (c) 2013-2017 by Duktape authors (see AUTHORS.rst)\n *  \n *  Permission is hereby granted, free of charge, to any person obtaining a copy\n *  of this software and associated documentation files (the \"Software\"), to deal\n *  in the Software without restriction, including without limitation the rights\n *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n *  copies of the Software, and to permit persons to whom the Software is\n *  furnished to do so, subject to the following conditions:\n *  \n *  The above copyright notice and this permission notice shall be included in\n *  all copies or substantial portions of the Software.\n *  \n *  THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n *  THE SOFTWARE.\n */\n\n/* AUTHORS.rst */\n/*\n *  ===============\n *  Duktape authors\n *  ===============\n *  \n *  Copyright\n *  =========\n *  \n *  Duktape copyrights are held by its authors.  Each author has a copyright\n *  to their contribution, and agrees to irrevocably license the contribution\n *  under the Duktape ``LICENSE.txt``.\n *  \n *  Authors\n *  =======\n *  \n *  Please include an e-mail address, a link to your GitHub profile, or something\n *  similar to allow your contribution to be identified accurately.\n *  \n *  The following people have contributed code, website contents, or Wiki contents,\n *  and agreed to irrevocably license their contributions under the Duktape\n *  ``LICENSE.txt`` (in order of appearance):\n *  \n *  * Sami Vaarala <sami.vaarala@iki.fi>\n *  * Niki Dobrev\n *  * Andreas \\u00d6man <andreas@lonelycoder.com>\n *  * L\\u00e1szl\\u00f3 Lang\\u00f3 <llango.u-szeged@partner.samsung.com>\n *  * Legimet <legimet.calc@gmail.com>\n *  * Karl Skomski <karl@skomski.com>\n *  * Bruce Pascoe <fatcerberus1@gmail.com>\n *  * Ren\\u00e9 Hollander <rene@rene8888.at>\n *  * Julien Hamaide (https://github.com/crazyjul)\n *  * Sebastian G\\u00f6tte (https://github.com/jaseg)\n *  * Tomasz Magulski (https://github.com/magul)\n *  * \\D. Bohdan (https://github.com/dbohdan)\n *  * Ond\\u0159ej Jirman (https://github.com/megous)\n *  * Sa\\u00fal Ibarra Corretg\\u00e9 <saghul@gmail.com>\n *  * Jeremy HU <huxingyi@msn.com>\n *  * Ole Andr\\u00e9 Vadla Ravn\\u00e5s (https://github.com/oleavr)\n *  * Harold Brenes (https://github.com/harold-b)\n *  * Oliver Crow (https://github.com/ocrow)\n *  * Jakub Ch\\u0142api\\u0144ski (https://github.com/jchlapinski)\n *  * Brett Vickers (https://github.com/beevik)\n *  * Dominik Okwieka (https://github.com/okitec)\n *  * Remko Tron\\u00e7on (https://el-tramo.be)\n *  * Romero Malaquias (rbsm@ic.ufal.br)\n *  * Michael Drake <michael.drake@codethink.co.uk>\n *  * Steven Don (https://github.com/shdon)\n *  * Simon Stone (https://github.com/sstone1)\n *  * \\J. McC. (https://github.com/jmhmccr)\n *  \n *  Other contributions\n *  ===================\n *  \n *  The following people have contributed something other than code (e.g. reported\n *  bugs, provided ideas, etc; roughly in order of appearance):\n *  \n *  * Greg Burns\n *  * Anthony Rabine\n *  * Carlos Costa\n *  * Aur\\u00e9lien Bouilland\n *  * Preet Desai (Pris Matic)\n *  * judofyr (http://www.reddit.com/user/judofyr)\n *  * Jason Woofenden\n *  * Micha\\u0142 Przyby\\u015b\n *  * Anthony Howe\n *  * Conrad Pankoff\n *  * Jim Schimpf\n *  * Rajaran Gaunker (https://github.com/zimbabao)\n *  * Andreas \\u00d6man\n *  * Doug Sanden\n *  * Josh Engebretson (https://github.com/JoshEngebretson)\n *  * Remo Eichenberger (https://github.com/remoe)\n *  * Mamod Mehyar (https://github.com/mamod)\n *  * David Demelier (https://github.com/markand)\n *  * Tim Caswell (https://github.com/creationix)\n *  * Mitchell Blank Jr (https://github.com/mitchblank)\n *  * https://github.com/yushli\n *  * Seo Sanghyeon (https://github.com/sanxiyn)\n *  * Han ChoongWoo (https://github.com/tunz)\n *  * Joshua Peek (https://github.com/josh)\n *  * Bruce E. Pascoe (https://github.com/fatcerberus)\n *  * https://github.com/Kelledin\n *  * https://github.com/sstruchtrup\n *  * Michael Drake (https://github.com/tlsa)\n *  * https://github.com/chris-y\n *  * Laurent Zubiaur (https://github.com/lzubiaur)\n *  * Neil Kolban (https://github.com/nkolban)\n *  \n *  If you are accidentally missing from this list, send me an e-mail\n *  (``sami.vaarala@iki.fi``) and I'll fix the omission.\n */\n\n#if !defined(DUKTAPE_H_INCLUDED)\n#define DUKTAPE_H_INCLUDED\n\n#define DUK_SINGLE_FILE\n\n/*\n *  BEGIN PUBLIC API\n */\n\n/*\n *  Version and Git commit identification\n */\n\n/* Duktape version, (major * 10000) + (minor * 100) + patch.  Allows C code\n * to #if (DUK_VERSION >= NNN) against Duktape API version.  The same value\n * is also available to Ecmascript code in Duktape.version.  Unofficial\n * development snapshots have 99 for patch level (e.g. 0.10.99 would be a\n * development version after 0.10.0 but before the next official release).\n */\n#define DUK_VERSION                       20200L\n\n/* Git commit, describe, and branch for Duktape build.  Useful for\n * non-official snapshot builds so that application code can easily log\n * which Duktape snapshot was used.  Not available in the Ecmascript\n * environment.\n */\n#define DUK_GIT_COMMIT                    \"a459cf3c9bd1779fc01b435d69302b742675a08f\"\n#define DUK_GIT_DESCRIBE                  \"v2.2.0\"\n#define DUK_GIT_BRANCH                    \"master\"\n\n/* External duk_config.h provides platform/compiler/OS dependent\n * typedefs and macros, and DUK_USE_xxx config options so that\n * the rest of Duktape doesn't need to do any feature detection.\n * DUK_VERSION is defined before including so that configuration\n * snippets can react to it.\n */\n#include \"duk_config.h\"\n\n/*\n *  Avoid C++ name mangling\n */\n\n#if defined(__cplusplus)\nextern \"C\" {\n#endif\n\n/*\n *  Some defines forwarded from feature detection\n */\n\n#undef DUK_API_VARIADIC_MACROS\n#if defined(DUK_USE_VARIADIC_MACROS)\n#define DUK_API_VARIADIC_MACROS\n#endif\n\n#define DUK_API_NORETURN(decl) DUK_NORETURN(decl)\n\n/*\n *  Public API specific typedefs\n *\n *  Many types are wrapped by Duktape for portability to rare platforms\n *  where e.g. 'int' is a 16-bit type.  See practical typing discussion\n *  in Duktape web documentation.\n */\n\nstruct duk_thread_state;\nstruct duk_memory_functions;\nstruct duk_function_list_entry;\nstruct duk_number_list_entry;\nstruct duk_time_components;\n\n/* duk_context is now defined in duk_config.h because it may also be\n * referenced there by prototypes.\n */\ntypedef struct duk_thread_state duk_thread_state;\ntypedef struct duk_memory_functions duk_memory_functions;\ntypedef struct duk_function_list_entry duk_function_list_entry;\ntypedef struct duk_number_list_entry duk_number_list_entry;\ntypedef struct duk_time_components duk_time_components;\n\ntypedef duk_ret_t (*duk_c_function)(duk_context *ctx);\ntypedef void *(*duk_alloc_function) (void *udata, duk_size_t size);\ntypedef void *(*duk_realloc_function) (void *udata, void *ptr, duk_size_t size);\ntypedef void (*duk_free_function) (void *udata, void *ptr);\ntypedef void (*duk_fatal_function) (void *udata, const char *msg);\ntypedef void (*duk_decode_char_function) (void *udata, duk_codepoint_t codepoint);\ntypedef duk_codepoint_t (*duk_map_char_function) (void *udata, duk_codepoint_t codepoint);\ntypedef duk_ret_t (*duk_safe_call_function) (duk_context *ctx, void *udata);\ntypedef duk_size_t (*duk_debug_read_function) (void *udata, char *buffer, duk_size_t length);\ntypedef duk_size_t (*duk_debug_write_function) (void *udata, const char *buffer, duk_size_t length);\ntypedef duk_size_t (*duk_debug_peek_function) (void *udata);\ntypedef void (*duk_debug_read_flush_function) (void *udata);\ntypedef void (*duk_debug_write_flush_function) (void *udata);\ntypedef duk_idx_t (*duk_debug_request_function) (duk_context *ctx, void *udata, duk_idx_t nvalues);\ntypedef void (*duk_debug_detached_function) (duk_context *ctx, void *udata);\n\nstruct duk_thread_state {\n\t/* XXX: Enough space to hold internal suspend/resume structure.\n\t * This is rather awkward and to be fixed when the internal\n\t * structure is visible for the public API header.\n\t */\n\tchar data[128];\n};\n\nstruct duk_memory_functions {\n\tduk_alloc_function alloc_func;\n\tduk_realloc_function realloc_func;\n\tduk_free_function free_func;\n\tvoid *udata;\n};\n\nstruct duk_function_list_entry {\n\tconst char *key;\n\tduk_c_function value;\n\tduk_idx_t nargs;\n};\n\nstruct duk_number_list_entry {\n\tconst char *key;\n\tduk_double_t value;\n};\n\nstruct duk_time_components {\n\tduk_double_t year;          /* year, e.g. 2016, Ecmascript year range */\n\tduk_double_t month;         /* month: 1-12 */\n\tduk_double_t day;           /* day: 1-31 */\n\tduk_double_t hours;         /* hour: 0-59 */\n\tduk_double_t minutes;       /* minute: 0-59 */\n\tduk_double_t seconds;       /* second: 0-59 (in POSIX time no leap second) */\n\tduk_double_t milliseconds;  /* may contain sub-millisecond fractions */\n\tduk_double_t weekday;       /* weekday: 0-6, 0=Sunday, 1=Monday, ..., 6=Saturday */\n};\n\n/*\n *  Constants\n */\n\n/* Duktape debug protocol version used by this build. */\n#define DUK_DEBUG_PROTOCOL_VERSION        2\n\n/* Used to represent invalid index; if caller uses this without checking,\n * this index will map to a non-existent stack entry.  Also used in some\n * API calls as a marker to denote \"no value\".\n */\n#define DUK_INVALID_INDEX                 DUK_IDX_MIN\n\n/* Indicates that a native function does not have a fixed number of args,\n * and the argument stack should not be capped/extended at all.\n */\n#define DUK_VARARGS                       ((duk_int_t) (-1))\n\n/* Number of value stack entries (in addition to actual call arguments)\n * guaranteed to be allocated on entry to a Duktape/C function.\n */\n#define DUK_API_ENTRY_STACK               64U\n\n/* Value types, used by e.g. duk_get_type() */\n#define DUK_TYPE_MIN                      0U\n#define DUK_TYPE_NONE                     0U    /* no value, e.g. invalid index */\n#define DUK_TYPE_UNDEFINED                1U    /* Ecmascript undefined */\n#define DUK_TYPE_NULL                     2U    /* Ecmascript null */\n#define DUK_TYPE_BOOLEAN                  3U    /* Ecmascript boolean: 0 or 1 */\n#define DUK_TYPE_NUMBER                   4U    /* Ecmascript number: double */\n#define DUK_TYPE_STRING                   5U    /* Ecmascript string: CESU-8 / extended UTF-8 encoded */\n#define DUK_TYPE_OBJECT                   6U    /* Ecmascript object: includes objects, arrays, functions, threads */\n#define DUK_TYPE_BUFFER                   7U    /* fixed or dynamic, garbage collected byte buffer */\n#define DUK_TYPE_POINTER                  8U    /* raw void pointer */\n#define DUK_TYPE_LIGHTFUNC                9U    /* lightweight function pointer */\n#define DUK_TYPE_MAX                      9U\n\n/* Value mask types, used by e.g. duk_get_type_mask() */\n#define DUK_TYPE_MASK_NONE                (1U << DUK_TYPE_NONE)\n#define DUK_TYPE_MASK_UNDEFINED           (1U << DUK_TYPE_UNDEFINED)\n#define DUK_TYPE_MASK_NULL                (1U << DUK_TYPE_NULL)\n#define DUK_TYPE_MASK_BOOLEAN             (1U << DUK_TYPE_BOOLEAN)\n#define DUK_TYPE_MASK_NUMBER              (1U << DUK_TYPE_NUMBER)\n#define DUK_TYPE_MASK_STRING              (1U << DUK_TYPE_STRING)\n#define DUK_TYPE_MASK_OBJECT              (1U << DUK_TYPE_OBJECT)\n#define DUK_TYPE_MASK_BUFFER              (1U << DUK_TYPE_BUFFER)\n#define DUK_TYPE_MASK_POINTER             (1U << DUK_TYPE_POINTER)\n#define DUK_TYPE_MASK_LIGHTFUNC           (1U << DUK_TYPE_LIGHTFUNC)\n#define DUK_TYPE_MASK_THROW               (1U << 10)  /* internal flag value: throw if mask doesn't match */\n#define DUK_TYPE_MASK_PROMOTE             (1U << 11)  /* internal flag value: promote to object if mask matches */\n\n/* Coercion hints */\n#define DUK_HINT_NONE                     0    /* prefer number, unless input is a Date, in which\n                                                * case prefer string (E5 Section 8.12.8)\n                                                */\n#define DUK_HINT_STRING                   1    /* prefer string */\n#define DUK_HINT_NUMBER                   2    /* prefer number */\n\n/* Enumeration flags for duk_enum() */\n#define DUK_ENUM_INCLUDE_NONENUMERABLE    (1U << 0)    /* enumerate non-numerable properties in addition to enumerable */\n#define DUK_ENUM_INCLUDE_HIDDEN           (1U << 1)    /* enumerate hidden symbols too (in Duktape 1.x called internal properties) */\n#define DUK_ENUM_INCLUDE_SYMBOLS          (1U << 2)    /* enumerate symbols */\n#define DUK_ENUM_EXCLUDE_STRINGS          (1U << 3)    /* exclude strings */\n#define DUK_ENUM_OWN_PROPERTIES_ONLY      (1U << 4)    /* don't walk prototype chain, only check own properties */\n#define DUK_ENUM_ARRAY_INDICES_ONLY       (1U << 5)    /* only enumerate array indices */\n/* XXX: misleading name */\n#define DUK_ENUM_SORT_ARRAY_INDICES       (1U << 6)    /* sort array indices (applied to full enumeration result, including inherited array indices); XXX: misleading name */\n#define DUK_ENUM_NO_PROXY_BEHAVIOR        (1U << 7)    /* enumerate a proxy object itself without invoking proxy behavior */\n\n/* Compilation flags for duk_compile() and duk_eval() */\n/* DUK_COMPILE_xxx bits 0-2 are reserved for an internal 'nargs' argument.\n */\n#define DUK_COMPILE_EVAL                  (1U << 3)    /* compile eval code (instead of global code) */\n#define DUK_COMPILE_FUNCTION              (1U << 4)    /* compile function code (instead of global code) */\n#define DUK_COMPILE_STRICT                (1U << 5)    /* use strict (outer) context for global, eval, or function code */\n#define DUK_COMPILE_SHEBANG               (1U << 6)    /* allow shebang ('#! ...') comment on first line of source */\n#define DUK_COMPILE_SAFE                  (1U << 7)    /* (internal) catch compilation errors */\n#define DUK_COMPILE_NORESULT              (1U << 8)    /* (internal) omit eval result */\n#define DUK_COMPILE_NOSOURCE              (1U << 9)    /* (internal) no source string on stack */\n#define DUK_COMPILE_STRLEN                (1U << 10)   /* (internal) take strlen() of src_buffer (avoids double evaluation in macro) */\n#define DUK_COMPILE_NOFILENAME            (1U << 11)   /* (internal) no filename on stack */\n#define DUK_COMPILE_FUNCEXPR              (1U << 12)   /* (internal) source is a function expression (used for Function constructor) */\n\n/* Flags for duk_def_prop() and its variants; base flags + a lot of convenience shorthands */\n#define DUK_DEFPROP_WRITABLE              (1U << 0)    /* set writable (effective if DUK_DEFPROP_HAVE_WRITABLE set) */\n#define DUK_DEFPROP_ENUMERABLE            (1U << 1)    /* set enumerable (effective if DUK_DEFPROP_HAVE_ENUMERABLE set) */\n#define DUK_DEFPROP_CONFIGURABLE          (1U << 2)    /* set configurable (effective if DUK_DEFPROP_HAVE_CONFIGURABLE set) */\n#define DUK_DEFPROP_HAVE_WRITABLE         (1U << 3)    /* set/clear writable */\n#define DUK_DEFPROP_HAVE_ENUMERABLE       (1U << 4)    /* set/clear enumerable */\n#define DUK_DEFPROP_HAVE_CONFIGURABLE     (1U << 5)    /* set/clear configurable */\n#define DUK_DEFPROP_HAVE_VALUE            (1U << 6)    /* set value (given on value stack) */\n#define DUK_DEFPROP_HAVE_GETTER           (1U << 7)    /* set getter (given on value stack) */\n#define DUK_DEFPROP_HAVE_SETTER           (1U << 8)    /* set setter (given on value stack) */\n#define DUK_DEFPROP_FORCE                 (1U << 9)    /* force change if possible, may still fail for e.g. virtual properties */\n#define DUK_DEFPROP_SET_WRITABLE          (DUK_DEFPROP_HAVE_WRITABLE | DUK_DEFPROP_WRITABLE)\n#define DUK_DEFPROP_CLEAR_WRITABLE        DUK_DEFPROP_HAVE_WRITABLE\n#define DUK_DEFPROP_SET_ENUMERABLE        (DUK_DEFPROP_HAVE_ENUMERABLE | DUK_DEFPROP_ENUMERABLE)\n#define DUK_DEFPROP_CLEAR_ENUMERABLE      DUK_DEFPROP_HAVE_ENUMERABLE\n#define DUK_DEFPROP_SET_CONFIGURABLE      (DUK_DEFPROP_HAVE_CONFIGURABLE | DUK_DEFPROP_CONFIGURABLE)\n#define DUK_DEFPROP_CLEAR_CONFIGURABLE    DUK_DEFPROP_HAVE_CONFIGURABLE\n#define DUK_DEFPROP_W                     DUK_DEFPROP_WRITABLE\n#define DUK_DEFPROP_E                     DUK_DEFPROP_ENUMERABLE\n#define DUK_DEFPROP_C                     DUK_DEFPROP_CONFIGURABLE\n#define DUK_DEFPROP_WE                    (DUK_DEFPROP_WRITABLE | DUK_DEFPROP_ENUMERABLE)\n#define DUK_DEFPROP_WC                    (DUK_DEFPROP_WRITABLE | DUK_DEFPROP_CONFIGURABLE)\n#define DUK_DEFPROP_WEC                   (DUK_DEFPROP_WRITABLE | DUK_DEFPROP_ENUMERABLE | DUK_DEFPROP_CONFIGURABLE)\n#define DUK_DEFPROP_HAVE_W                DUK_DEFPROP_HAVE_WRITABLE\n#define DUK_DEFPROP_HAVE_E                DUK_DEFPROP_HAVE_ENUMERABLE\n#define DUK_DEFPROP_HAVE_C                DUK_DEFPROP_HAVE_CONFIGURABLE\n#define DUK_DEFPROP_HAVE_WE               (DUK_DEFPROP_HAVE_WRITABLE | DUK_DEFPROP_HAVE_ENUMERABLE)\n#define DUK_DEFPROP_HAVE_WC               (DUK_DEFPROP_HAVE_WRITABLE | DUK_DEFPROP_HAVE_CONFIGURABLE)\n#define DUK_DEFPROP_HAVE_WEC              (DUK_DEFPROP_HAVE_WRITABLE | DUK_DEFPROP_HAVE_ENUMERABLE | DUK_DEFPROP_HAVE_CONFIGURABLE)\n#define DUK_DEFPROP_SET_W                 DUK_DEFPROP_SET_WRITABLE\n#define DUK_DEFPROP_SET_E                 DUK_DEFPROP_SET_ENUMERABLE\n#define DUK_DEFPROP_SET_C                 DUK_DEFPROP_SET_CONFIGURABLE\n#define DUK_DEFPROP_SET_WE                (DUK_DEFPROP_SET_WRITABLE | DUK_DEFPROP_SET_ENUMERABLE)\n#define DUK_DEFPROP_SET_WC                (DUK_DEFPROP_SET_WRITABLE | DUK_DEFPROP_SET_CONFIGURABLE)\n#define DUK_DEFPROP_SET_WEC               (DUK_DEFPROP_SET_WRITABLE | DUK_DEFPROP_SET_ENUMERABLE | DUK_DEFPROP_SET_CONFIGURABLE)\n#define DUK_DEFPROP_CLEAR_W               DUK_DEFPROP_CLEAR_WRITABLE\n#define DUK_DEFPROP_CLEAR_E               DUK_DEFPROP_CLEAR_ENUMERABLE\n#define DUK_DEFPROP_CLEAR_C               DUK_DEFPROP_CLEAR_CONFIGURABLE\n#define DUK_DEFPROP_CLEAR_WE              (DUK_DEFPROP_CLEAR_WRITABLE | DUK_DEFPROP_CLEAR_ENUMERABLE)\n#define DUK_DEFPROP_CLEAR_WC              (DUK_DEFPROP_CLEAR_WRITABLE | DUK_DEFPROP_CLEAR_CONFIGURABLE)\n#define DUK_DEFPROP_CLEAR_WEC             (DUK_DEFPROP_CLEAR_WRITABLE | DUK_DEFPROP_CLEAR_ENUMERABLE | DUK_DEFPROP_CLEAR_CONFIGURABLE)\n#define DUK_DEFPROP_ATTR_W                (DUK_DEFPROP_HAVE_WEC | DUK_DEFPROP_W)\n#define DUK_DEFPROP_ATTR_E                (DUK_DEFPROP_HAVE_WEC | DUK_DEFPROP_E)\n#define DUK_DEFPROP_ATTR_C                (DUK_DEFPROP_HAVE_WEC | DUK_DEFPROP_C)\n#define DUK_DEFPROP_ATTR_WE               (DUK_DEFPROP_HAVE_WEC | DUK_DEFPROP_WE)\n#define DUK_DEFPROP_ATTR_WC               (DUK_DEFPROP_HAVE_WEC | DUK_DEFPROP_WC)\n#define DUK_DEFPROP_ATTR_WEC              (DUK_DEFPROP_HAVE_WEC | DUK_DEFPROP_WEC)\n\n/* Flags for duk_push_thread_raw() */\n#define DUK_THREAD_NEW_GLOBAL_ENV         (1U << 0)    /* create a new global environment */\n\n/* Flags for duk_gc() */\n#define DUK_GC_COMPACT                    (1U << 0)    /* compact heap objects */\n\n/* Error codes (must be 8 bits at most, see duk_error.h) */\n#define DUK_ERR_NONE                      0    /* no error (e.g. from duk_get_error_code()) */\n#define DUK_ERR_ERROR                     1    /* Error */\n#define DUK_ERR_EVAL_ERROR                2    /* EvalError */\n#define DUK_ERR_RANGE_ERROR               3    /* RangeError */\n#define DUK_ERR_REFERENCE_ERROR           4    /* ReferenceError */\n#define DUK_ERR_SYNTAX_ERROR              5    /* SyntaxError */\n#define DUK_ERR_TYPE_ERROR                6    /* TypeError */\n#define DUK_ERR_URI_ERROR                 7    /* URIError */\n\n/* Return codes for C functions (shortcut for throwing an error) */\n#define DUK_RET_ERROR                     (-DUK_ERR_ERROR)\n#define DUK_RET_EVAL_ERROR                (-DUK_ERR_EVAL_ERROR)\n#define DUK_RET_RANGE_ERROR               (-DUK_ERR_RANGE_ERROR)\n#define DUK_RET_REFERENCE_ERROR           (-DUK_ERR_REFERENCE_ERROR)\n#define DUK_RET_SYNTAX_ERROR              (-DUK_ERR_SYNTAX_ERROR)\n#define DUK_RET_TYPE_ERROR                (-DUK_ERR_TYPE_ERROR)\n#define DUK_RET_URI_ERROR                 (-DUK_ERR_URI_ERROR)\n\n/* Return codes for protected calls (duk_safe_call(), duk_pcall()) */\n#define DUK_EXEC_SUCCESS                  0\n#define DUK_EXEC_ERROR                    1\n\n/* Debug levels for DUK_USE_DEBUG_WRITE(). */\n#define DUK_LEVEL_DEBUG                   0\n#define DUK_LEVEL_DDEBUG                  1\n#define DUK_LEVEL_DDDEBUG                 2\n\n/*\n *  Macros to create Symbols as C statically constructed strings.\n *\n *  Call e.g. as DUK_HIDDEN_SYMBOL(\"myProperty\") <=> (\"\\xFF\" \"myProperty\").\n *  Local symbols have a unique suffix, caller should take care to avoid\n *  conflicting with the Duktape internal representation by e.g. prepending\n *  a '!' character: DUK_LOCAL_SYMBOL(\"myLocal\", \"!123\").\n *\n *  Note that these can only be used for string constants, not dynamically\n *  created strings.\n */\n\n#define DUK_HIDDEN_SYMBOL(x)     (\"\\xFF\" x)\n#define DUK_GLOBAL_SYMBOL(x)     (\"\\x80\" x)\n#define DUK_LOCAL_SYMBOL(x,uniq) (\"\\x81\" x \"\\xff\" uniq)\n#define DUK_WELLKNOWN_SYMBOL(x)  (\"\\x81\" x \"\\xff\")\n\n/*\n *  If no variadic macros, __FILE__ and __LINE__ are passed through globals\n *  which is ugly and not thread safe.\n */\n\n#if !defined(DUK_API_VARIADIC_MACROS)\nDUK_EXTERNAL_DECL const char *duk_api_global_filename;\nDUK_EXTERNAL_DECL duk_int_t duk_api_global_line;\n#endif\n\n/*\n *  Context management\n */\n\nDUK_EXTERNAL_DECL\nduk_context *duk_create_heap(duk_alloc_function alloc_func,\n                             duk_realloc_function realloc_func,\n                             duk_free_function free_func,\n                             void *heap_udata,\n                             duk_fatal_function fatal_handler);\nDUK_EXTERNAL_DECL void duk_destroy_heap(duk_context *ctx);\n\nDUK_EXTERNAL_DECL void duk_suspend(duk_context *ctx, duk_thread_state *state);\nDUK_EXTERNAL_DECL void duk_resume(duk_context *ctx, const duk_thread_state *state);\n\n#define duk_create_heap_default() \\\n\tduk_create_heap(NULL, NULL, NULL, NULL, NULL)\n\n/*\n *  Memory management\n *\n *  Raw functions have no side effects (cannot trigger GC).\n */\n\nDUK_EXTERNAL_DECL void *duk_alloc_raw(duk_context *ctx, duk_size_t size);\nDUK_EXTERNAL_DECL void duk_free_raw(duk_context *ctx, void *ptr);\nDUK_EXTERNAL_DECL void *duk_realloc_raw(duk_context *ctx, void *ptr, duk_size_t size);\nDUK_EXTERNAL_DECL void *duk_alloc(duk_context *ctx, duk_size_t size);\nDUK_EXTERNAL_DECL void duk_free(duk_context *ctx, void *ptr);\nDUK_EXTERNAL_DECL void *duk_realloc(duk_context *ctx, void *ptr, duk_size_t size);\nDUK_EXTERNAL_DECL void duk_get_memory_functions(duk_context *ctx, duk_memory_functions *out_funcs);\nDUK_EXTERNAL_DECL void duk_gc(duk_context *ctx, duk_uint_t flags);\n\n/*\n *  Error handling\n */\n\nDUK_API_NORETURN(DUK_EXTERNAL_DECL void duk_throw_raw(duk_context *ctx));\n#define duk_throw(ctx) \\\n\t(duk_throw_raw((ctx)), (duk_ret_t) 0)\nDUK_API_NORETURN(DUK_EXTERNAL_DECL void duk_fatal_raw(duk_context *ctx, const char *err_msg));\n#define duk_fatal(ctx,err_msg) \\\n\t(duk_fatal_raw((ctx), (err_msg)), (duk_ret_t) 0)\nDUK_API_NORETURN(DUK_EXTERNAL_DECL void duk_error_raw(duk_context *ctx, duk_errcode_t err_code, const char *filename, duk_int_t line, const char *fmt, ...));\n\n#if defined(DUK_API_VARIADIC_MACROS)\n#define duk_error(ctx,err_code,...)  \\\n\t(duk_error_raw((ctx), (duk_errcode_t) (err_code), (const char *) (DUK_FILE_MACRO), (duk_int_t) (DUK_LINE_MACRO), __VA_ARGS__), (duk_ret_t) 0)\n#define duk_generic_error(ctx,...)  \\\n\t(duk_error_raw((ctx), (duk_errcode_t) DUK_ERR_ERROR, (const char *) (DUK_FILE_MACRO), (duk_int_t) (DUK_LINE_MACRO), __VA_ARGS__), (duk_ret_t) 0)\n#define duk_eval_error(ctx,...)  \\\n\t(duk_error_raw((ctx), (duk_errcode_t) DUK_ERR_EVAL_ERROR, (const char *) (DUK_FILE_MACRO), (duk_int_t) (DUK_LINE_MACRO), __VA_ARGS__), (duk_ret_t) 0)\n#define duk_range_error(ctx,...)  \\\n\t(duk_error_raw((ctx), (duk_errcode_t) DUK_ERR_RANGE_ERROR, (const char *) (DUK_FILE_MACRO), (duk_int_t) (DUK_LINE_MACRO), __VA_ARGS__), (duk_ret_t) 0)\n#define duk_reference_error(ctx,...)  \\\n\t(duk_error_raw((ctx), (duk_errcode_t) DUK_ERR_REFERENCE_ERROR, (const char *) (DUK_FILE_MACRO), (duk_int_t) (DUK_LINE_MACRO), __VA_ARGS__), (duk_ret_t) 0)\n#define duk_syntax_error(ctx,...)  \\\n\t(duk_error_raw((ctx), (duk_errcode_t) DUK_ERR_SYNTAX_ERROR, (const char *) (DUK_FILE_MACRO), (duk_int_t) (DUK_LINE_MACRO), __VA_ARGS__), (duk_ret_t) 0)\n#define duk_type_error(ctx,...)  \\\n\t(duk_error_raw((ctx), (duk_errcode_t) DUK_ERR_TYPE_ERROR, (const char *) (DUK_FILE_MACRO), (duk_int_t) (DUK_LINE_MACRO), __VA_ARGS__), (duk_ret_t) 0)\n#define duk_uri_error(ctx,...)  \\\n\t(duk_error_raw((ctx), (duk_errcode_t) DUK_ERR_URI_ERROR, (const char *) (DUK_FILE_MACRO), (duk_int_t) (DUK_LINE_MACRO), __VA_ARGS__), (duk_ret_t) 0)\n#else  /* DUK_API_VARIADIC_MACROS */\n/* For legacy compilers without variadic macros a macro hack is used to allow\n * variable arguments.  While the macro allows \"return duk_error(...)\", it\n * will fail with e.g. \"(void) duk_error(...)\".  The calls are noreturn but\n * with a return value to allow the \"return duk_error(...)\" idiom.  This may\n * cause some compiler warnings, but without noreturn the generated code is\n * often worse.  The same approach as with variadic macros (using\n * \"(duk_error(...), 0)\") won't work due to the macro hack structure.\n */\nDUK_API_NORETURN(DUK_EXTERNAL_DECL duk_ret_t duk_error_stash(duk_context *ctx, duk_errcode_t err_code, const char *fmt, ...));\nDUK_API_NORETURN(DUK_EXTERNAL_DECL duk_ret_t duk_generic_error_stash(duk_context *ctx, const char *fmt, ...));\nDUK_API_NORETURN(DUK_EXTERNAL_DECL duk_ret_t duk_eval_error_stash(duk_context *ctx, const char *fmt, ...));\nDUK_API_NORETURN(DUK_EXTERNAL_DECL duk_ret_t duk_range_error_stash(duk_context *ctx, const char *fmt, ...));\nDUK_API_NORETURN(DUK_EXTERNAL_DECL duk_ret_t duk_reference_error_stash(duk_context *ctx, const char *fmt, ...));\nDUK_API_NORETURN(DUK_EXTERNAL_DECL duk_ret_t duk_syntax_error_stash(duk_context *ctx, const char *fmt, ...));\nDUK_API_NORETURN(DUK_EXTERNAL_DECL duk_ret_t duk_type_error_stash(duk_context *ctx, const char *fmt, ...));\nDUK_API_NORETURN(DUK_EXTERNAL_DECL duk_ret_t duk_uri_error_stash(duk_context *ctx, const char *fmt, ...));\n#define duk_error  \\\n\t(duk_api_global_filename = (const char *) (DUK_FILE_MACRO), \\\n\t duk_api_global_line = (duk_int_t) (DUK_LINE_MACRO), \\\n\t duk_error_stash)  /* last value is func pointer, arguments follow in parens */\n#define duk_generic_error  \\\n\t(duk_api_global_filename = (const char *) (DUK_FILE_MACRO), \\\n\t duk_api_global_line = (duk_int_t) (DUK_LINE_MACRO), \\\n\t duk_generic_error_stash)\n#define duk_eval_error  \\\n\t(duk_api_global_filename = (const char *) (DUK_FILE_MACRO), \\\n\t duk_api_global_line = (duk_int_t) (DUK_LINE_MACRO), \\\n\t duk_eval_error_stash)\n#define duk_range_error  \\\n\t(duk_api_global_filename = (const char *) (DUK_FILE_MACRO), \\\n\t duk_api_global_line = (duk_int_t) (DUK_LINE_MACRO), \\\n\t duk_range_error_stash)\n#define duk_reference_error  \\\n\t(duk_api_global_filename = (const char *) (DUK_FILE_MACRO), \\\n\t duk_api_global_line = (duk_int_t) (DUK_LINE_MACRO), \\\n\t duk_reference_error_stash)\n#define duk_syntax_error  \\\n\t(duk_api_global_filename = (const char *) (DUK_FILE_MACRO), \\\n\t duk_api_global_line = (duk_int_t) (DUK_LINE_MACRO), \\\n\t duk_syntax_error_stash)\n#define duk_type_error  \\\n\t(duk_api_global_filename = (const char *) (DUK_FILE_MACRO), \\\n\t duk_api_global_line = (duk_int_t) (DUK_LINE_MACRO), \\\n\t duk_type_error_stash)\n#define duk_uri_error  \\\n\t(duk_api_global_filename = (const char *) (DUK_FILE_MACRO), \\\n\t duk_api_global_line = (duk_int_t) (DUK_LINE_MACRO), \\\n\t duk_uri_error_stash)\n#endif  /* DUK_API_VARIADIC_MACROS */\n\nDUK_API_NORETURN(DUK_EXTERNAL_DECL void duk_error_va_raw(duk_context *ctx, duk_errcode_t err_code, const char *filename, duk_int_t line, const char *fmt, va_list ap));\n\n#define duk_error_va(ctx,err_code,fmt,ap)  \\\n\t(duk_error_va_raw((ctx), (duk_errcode_t) (err_code), (const char *) (DUK_FILE_MACRO), (duk_int_t) (DUK_LINE_MACRO), (fmt), (ap)), (duk_ret_t) 0)\n#define duk_generic_error_va(ctx,fmt,ap)  \\\n\t(duk_error_va_raw((ctx), (duk_errcode_t) DUK_ERR_ERROR, (const char *) (DUK_FILE_MACRO), (duk_int_t) (DUK_LINE_MACRO), (fmt), (ap)), (duk_ret_t) 0)\n#define duk_eval_error_va(ctx,fmt,ap)  \\\n\t(duk_error_va_raw((ctx), (duk_errcode_t) DUK_ERR_EVAL_ERROR, (const char *) (DUK_FILE_MACRO), (duk_int_t) (DUK_LINE_MACRO), (fmt), (ap)), (duk_ret_t) 0)\n#define duk_range_error_va(ctx,fmt,ap)  \\\n\t(duk_error_va_raw((ctx), (duk_errcode_t) DUK_ERR_RANGE_ERROR, (const char *) (DUK_FILE_MACRO), (duk_int_t) (DUK_LINE_MACRO), (fmt), (ap)), (duk_ret_t) 0)\n#define duk_reference_error_va(ctx,fmt,ap)  \\\n\t(duk_error_va_raw((ctx), (duk_errcode_t) DUK_ERR_REFERENCE_ERROR, (const char *) (DUK_FILE_MACRO), (duk_int_t) (DUK_LINE_MACRO), (fmt), (ap)), (duk_ret_t) 0)\n#define duk_syntax_error_va(ctx,fmt,ap)  \\\n\t(duk_error_va_raw((ctx), (duk_errcode_t) DUK_ERR_SYNTAX_ERROR, (const char *) (DUK_FILE_MACRO), (duk_int_t) (DUK_LINE_MACRO), (fmt), (ap)), (duk_ret_t) 0)\n#define duk_type_error_va(ctx,fmt,ap)  \\\n\t(duk_error_va_raw((ctx), (duk_errcode_t) DUK_ERR_TYPE_ERROR, (const char *) (DUK_FILE_MACRO), (duk_int_t) (DUK_LINE_MACRO), (fmt), (ap)), (duk_ret_t) 0)\n#define duk_uri_error_va(ctx,fmt,ap)  \\\n\t(duk_error_va_raw((ctx), (duk_errcode_t) DUK_ERR_URI_ERROR, (const char *) (DUK_FILE_MACRO), (duk_int_t) (DUK_LINE_MACRO), (fmt), (ap)), (duk_ret_t) 0)\n\n/*\n *  Other state related functions\n */\n\nDUK_EXTERNAL_DECL duk_bool_t duk_is_strict_call(duk_context *ctx);\nDUK_EXTERNAL_DECL duk_bool_t duk_is_constructor_call(duk_context *ctx);\n\n/*\n *  Stack management\n */\n\nDUK_EXTERNAL_DECL duk_idx_t duk_normalize_index(duk_context *ctx, duk_idx_t idx);\nDUK_EXTERNAL_DECL duk_idx_t duk_require_normalize_index(duk_context *ctx, duk_idx_t idx);\nDUK_EXTERNAL_DECL duk_bool_t duk_is_valid_index(duk_context *ctx, duk_idx_t idx);\nDUK_EXTERNAL_DECL void duk_require_valid_index(duk_context *ctx, duk_idx_t idx);\n\nDUK_EXTERNAL_DECL duk_idx_t duk_get_top(duk_context *ctx);\nDUK_EXTERNAL_DECL void duk_set_top(duk_context *ctx, duk_idx_t idx);\nDUK_EXTERNAL_DECL duk_idx_t duk_get_top_index(duk_context *ctx);\nDUK_EXTERNAL_DECL duk_idx_t duk_require_top_index(duk_context *ctx);\n\n/* Although extra/top could be an unsigned type here, using a signed type\n * makes the API more robust to calling code calculation errors or corner\n * cases (where caller might occasionally come up with negative values).\n * Negative values are treated as zero, which is better than casting them\n * to a large unsigned number.  (This principle is used elsewhere in the\n * API too.)\n */\nDUK_EXTERNAL_DECL duk_bool_t duk_check_stack(duk_context *ctx, duk_idx_t extra);\nDUK_EXTERNAL_DECL void duk_require_stack(duk_context *ctx, duk_idx_t extra);\nDUK_EXTERNAL_DECL duk_bool_t duk_check_stack_top(duk_context *ctx, duk_idx_t top);\nDUK_EXTERNAL_DECL void duk_require_stack_top(duk_context *ctx, duk_idx_t top);\n\n/*\n *  Stack manipulation (other than push/pop)\n */\n\nDUK_EXTERNAL_DECL void duk_swap(duk_context *ctx, duk_idx_t idx1, duk_idx_t idx2);\nDUK_EXTERNAL_DECL void duk_swap_top(duk_context *ctx, duk_idx_t idx);\nDUK_EXTERNAL_DECL void duk_dup(duk_context *ctx, duk_idx_t from_idx);\nDUK_EXTERNAL_DECL void duk_dup_top(duk_context *ctx);\nDUK_EXTERNAL_DECL void duk_insert(duk_context *ctx, duk_idx_t to_idx);\nDUK_EXTERNAL_DECL void duk_replace(duk_context *ctx, duk_idx_t to_idx);\nDUK_EXTERNAL_DECL void duk_copy(duk_context *ctx, duk_idx_t from_idx, duk_idx_t to_idx);\nDUK_EXTERNAL_DECL void duk_remove(duk_context *ctx, duk_idx_t idx);\nDUK_EXTERNAL_DECL void duk_xcopymove_raw(duk_context *to_ctx, duk_context *from_ctx, duk_idx_t count, duk_bool_t is_copy);\n\n#define duk_xmove_top(to_ctx,from_ctx,count) \\\n\tduk_xcopymove_raw((to_ctx), (from_ctx), (count), 0 /*is_copy*/)\n#define duk_xcopy_top(to_ctx,from_ctx,count) \\\n\tduk_xcopymove_raw((to_ctx), (from_ctx), (count), 1 /*is_copy*/)\n\n/*\n *  Push operations\n *\n *  Push functions return the absolute (relative to bottom of frame)\n *  position of the pushed value for convenience.\n *\n *  Note: duk_dup() is technically a push.\n */\n\nDUK_EXTERNAL_DECL void duk_push_undefined(duk_context *ctx);\nDUK_EXTERNAL_DECL void duk_push_null(duk_context *ctx);\nDUK_EXTERNAL_DECL void duk_push_boolean(duk_context *ctx, duk_bool_t val);\nDUK_EXTERNAL_DECL void duk_push_true(duk_context *ctx);\nDUK_EXTERNAL_DECL void duk_push_false(duk_context *ctx);\nDUK_EXTERNAL_DECL void duk_push_number(duk_context *ctx, duk_double_t val);\nDUK_EXTERNAL_DECL void duk_push_nan(duk_context *ctx);\nDUK_EXTERNAL_DECL void duk_push_int(duk_context *ctx, duk_int_t val);\nDUK_EXTERNAL_DECL void duk_push_uint(duk_context *ctx, duk_uint_t val);\nDUK_EXTERNAL_DECL const char *duk_push_string(duk_context *ctx, const char *str);\nDUK_EXTERNAL_DECL const char *duk_push_lstring(duk_context *ctx, const char *str, duk_size_t len);\nDUK_EXTERNAL_DECL void duk_push_pointer(duk_context *ctx, void *p);\nDUK_EXTERNAL_DECL const char *duk_push_sprintf(duk_context *ctx, const char *fmt, ...);\nDUK_EXTERNAL_DECL const char *duk_push_vsprintf(duk_context *ctx, const char *fmt, va_list ap);\n\nDUK_EXTERNAL_DECL void duk_push_this(duk_context *ctx);\nDUK_EXTERNAL_DECL void duk_push_current_function(duk_context *ctx);\nDUK_EXTERNAL_DECL void duk_push_current_thread(duk_context *ctx);\nDUK_EXTERNAL_DECL void duk_push_global_object(duk_context *ctx);\nDUK_EXTERNAL_DECL void duk_push_heap_stash(duk_context *ctx);\nDUK_EXTERNAL_DECL void duk_push_global_stash(duk_context *ctx);\nDUK_EXTERNAL_DECL void duk_push_thread_stash(duk_context *ctx, duk_context *target_ctx);\n\nDUK_EXTERNAL_DECL duk_idx_t duk_push_object(duk_context *ctx);\nDUK_EXTERNAL_DECL duk_idx_t duk_push_bare_object(duk_context *ctx);\nDUK_EXTERNAL_DECL duk_idx_t duk_push_array(duk_context *ctx);\nDUK_EXTERNAL_DECL duk_idx_t duk_push_c_function(duk_context *ctx, duk_c_function func, duk_idx_t nargs);\nDUK_EXTERNAL_DECL duk_idx_t duk_push_c_lightfunc(duk_context *ctx, duk_c_function func, duk_idx_t nargs, duk_idx_t length, duk_int_t magic);\nDUK_EXTERNAL_DECL duk_idx_t duk_push_thread_raw(duk_context *ctx, duk_uint_t flags);\nDUK_EXTERNAL_DECL duk_idx_t duk_push_proxy(duk_context *ctx, duk_uint_t proxy_flags);\n\n#define duk_push_thread(ctx) \\\n\tduk_push_thread_raw((ctx), 0 /*flags*/)\n\n#define duk_push_thread_new_globalenv(ctx) \\\n\tduk_push_thread_raw((ctx), DUK_THREAD_NEW_GLOBAL_ENV /*flags*/)\n\nDUK_EXTERNAL_DECL duk_idx_t duk_push_error_object_raw(duk_context *ctx, duk_errcode_t err_code, const char *filename, duk_int_t line, const char *fmt, ...);\n\n#if defined(DUK_API_VARIADIC_MACROS)\n#define duk_push_error_object(ctx,err_code,...)  \\\n\tduk_push_error_object_raw((ctx), (err_code), (const char *) (DUK_FILE_MACRO), (duk_int_t) (DUK_LINE_MACRO), __VA_ARGS__)\n#else\nDUK_EXTERNAL_DECL duk_idx_t duk_push_error_object_stash(duk_context *ctx, duk_errcode_t err_code, const char *fmt, ...);\n/* Note: parentheses are required so that the comma expression works in assignments. */\n#define duk_push_error_object  \\\n\t(duk_api_global_filename = (const char *) (DUK_FILE_MACRO), \\\n\t duk_api_global_line = (duk_int_t) (DUK_LINE_MACRO), \\\n\t duk_push_error_object_stash)  /* last value is func pointer, arguments follow in parens */\n#endif\n\nDUK_EXTERNAL_DECL duk_idx_t duk_push_error_object_va_raw(duk_context *ctx, duk_errcode_t err_code, const char *filename, duk_int_t line, const char *fmt, va_list ap);\n#define duk_push_error_object_va(ctx,err_code,fmt,ap)  \\\n\tduk_push_error_object_va_raw((ctx), (err_code), (const char *) (DUK_FILE_MACRO), (duk_int_t) (DUK_LINE_MACRO), (fmt), (ap))\n\n#define DUK_BUF_FLAG_DYNAMIC   (1 << 0)    /* internal flag: dynamic buffer */\n#define DUK_BUF_FLAG_EXTERNAL  (1 << 1)    /* internal flag: external buffer */\n#define DUK_BUF_FLAG_NOZERO    (1 << 2)    /* internal flag: don't zero allocated buffer */\n\nDUK_EXTERNAL_DECL void *duk_push_buffer_raw(duk_context *ctx, duk_size_t size, duk_small_uint_t flags);\n\n#define duk_push_buffer(ctx,size,dynamic) \\\n\tduk_push_buffer_raw((ctx), (size), (dynamic) ? DUK_BUF_FLAG_DYNAMIC : 0)\n#define duk_push_fixed_buffer(ctx,size) \\\n\tduk_push_buffer_raw((ctx), (size), 0 /*flags*/)\n#define duk_push_dynamic_buffer(ctx,size) \\\n\tduk_push_buffer_raw((ctx), (size), DUK_BUF_FLAG_DYNAMIC /*flags*/)\n#define duk_push_external_buffer(ctx) \\\n\t((void) duk_push_buffer_raw((ctx), 0, DUK_BUF_FLAG_DYNAMIC | DUK_BUF_FLAG_EXTERNAL))\n\n#define DUK_BUFOBJ_ARRAYBUFFER         0\n#define DUK_BUFOBJ_NODEJS_BUFFER       1\n#define DUK_BUFOBJ_DATAVIEW            2\n#define DUK_BUFOBJ_INT8ARRAY           3\n#define DUK_BUFOBJ_UINT8ARRAY          4\n#define DUK_BUFOBJ_UINT8CLAMPEDARRAY   5\n#define DUK_BUFOBJ_INT16ARRAY          6\n#define DUK_BUFOBJ_UINT16ARRAY         7\n#define DUK_BUFOBJ_INT32ARRAY          8\n#define DUK_BUFOBJ_UINT32ARRAY         9\n#define DUK_BUFOBJ_FLOAT32ARRAY        10\n#define DUK_BUFOBJ_FLOAT64ARRAY        11\n\nDUK_EXTERNAL_DECL void duk_push_buffer_object(duk_context *ctx, duk_idx_t idx_buffer, duk_size_t byte_offset, duk_size_t byte_length, duk_uint_t flags);\n\nDUK_EXTERNAL_DECL duk_idx_t duk_push_heapptr(duk_context *ctx, void *ptr);\n\n/*\n *  Pop operations\n */\n\nDUK_EXTERNAL_DECL void duk_pop(duk_context *ctx);\nDUK_EXTERNAL_DECL void duk_pop_n(duk_context *ctx, duk_idx_t count);\nDUK_EXTERNAL_DECL void duk_pop_2(duk_context *ctx);\nDUK_EXTERNAL_DECL void duk_pop_3(duk_context *ctx);\n\n/*\n *  Type checks\n *\n *  duk_is_none(), which would indicate whether index it outside of stack,\n *  is not needed; duk_is_valid_index() gives the same information.\n */\n\nDUK_EXTERNAL_DECL duk_int_t duk_get_type(duk_context *ctx, duk_idx_t idx);\nDUK_EXTERNAL_DECL duk_bool_t duk_check_type(duk_context *ctx, duk_idx_t idx, duk_int_t type);\nDUK_EXTERNAL_DECL duk_uint_t duk_get_type_mask(duk_context *ctx, duk_idx_t idx);\nDUK_EXTERNAL_DECL duk_bool_t duk_check_type_mask(duk_context *ctx, duk_idx_t idx, duk_uint_t mask);\n\nDUK_EXTERNAL_DECL duk_bool_t duk_is_undefined(duk_context *ctx, duk_idx_t idx);\nDUK_EXTERNAL_DECL duk_bool_t duk_is_null(duk_context *ctx, duk_idx_t idx);\n#define duk_is_null_or_undefined(ctx, idx) \\\n\t((duk_get_type_mask((ctx), (idx)) & (DUK_TYPE_MASK_NULL | DUK_TYPE_MASK_UNDEFINED)) ? 1 : 0)\n\nDUK_EXTERNAL_DECL duk_bool_t duk_is_boolean(duk_context *ctx, duk_idx_t idx);\nDUK_EXTERNAL_DECL duk_bool_t duk_is_number(duk_context *ctx, duk_idx_t idx);\nDUK_EXTERNAL_DECL duk_bool_t duk_is_nan(duk_context *ctx, duk_idx_t idx);\nDUK_EXTERNAL_DECL duk_bool_t duk_is_string(duk_context *ctx, duk_idx_t idx);\nDUK_EXTERNAL_DECL duk_bool_t duk_is_object(duk_context *ctx, duk_idx_t idx);\nDUK_EXTERNAL_DECL duk_bool_t duk_is_buffer(duk_context *ctx, duk_idx_t idx);\nDUK_EXTERNAL_DECL duk_bool_t duk_is_buffer_data(duk_context *ctx, duk_idx_t idx);\nDUK_EXTERNAL_DECL duk_bool_t duk_is_pointer(duk_context *ctx, duk_idx_t idx);\nDUK_EXTERNAL_DECL duk_bool_t duk_is_lightfunc(duk_context *ctx, duk_idx_t idx);\n\nDUK_EXTERNAL_DECL duk_bool_t duk_is_symbol(duk_context *ctx, duk_idx_t idx);\nDUK_EXTERNAL_DECL duk_bool_t duk_is_array(duk_context *ctx, duk_idx_t idx);\nDUK_EXTERNAL_DECL duk_bool_t duk_is_function(duk_context *ctx, duk_idx_t idx);\nDUK_EXTERNAL_DECL duk_bool_t duk_is_c_function(duk_context *ctx, duk_idx_t idx);\nDUK_EXTERNAL_DECL duk_bool_t duk_is_ecmascript_function(duk_context *ctx, duk_idx_t idx);\nDUK_EXTERNAL_DECL duk_bool_t duk_is_bound_function(duk_context *ctx, duk_idx_t idx);\nDUK_EXTERNAL_DECL duk_bool_t duk_is_thread(duk_context *ctx, duk_idx_t idx);\n\n#define duk_is_callable(ctx,idx) \\\n\tduk_is_function((ctx), (idx))\nDUK_EXTERNAL_DECL duk_bool_t duk_is_constructable(duk_context *ctx, duk_idx_t idx);\n\nDUK_EXTERNAL_DECL duk_bool_t duk_is_dynamic_buffer(duk_context *ctx, duk_idx_t idx);\nDUK_EXTERNAL_DECL duk_bool_t duk_is_fixed_buffer(duk_context *ctx, duk_idx_t idx);\nDUK_EXTERNAL_DECL duk_bool_t duk_is_external_buffer(duk_context *ctx, duk_idx_t idx);\n\n/* Buffers and lightfuncs are not considered primitive because they mimic\n * objects and e.g. duk_to_primitive() will coerce them instead of returning\n * them as is.  Symbols are represented as strings internally.\n */\n#define duk_is_primitive(ctx,idx) \\\n\tduk_check_type_mask((ctx), (idx), DUK_TYPE_MASK_UNDEFINED | \\\n\t                                  DUK_TYPE_MASK_NULL | \\\n\t                                  DUK_TYPE_MASK_BOOLEAN | \\\n\t                                  DUK_TYPE_MASK_NUMBER | \\\n\t                                  DUK_TYPE_MASK_STRING | \\\n\t                                  DUK_TYPE_MASK_POINTER)\n\n/* Symbols are object coercible, covered by DUK_TYPE_MASK_STRING. */\n#define duk_is_object_coercible(ctx,idx) \\\n\tduk_check_type_mask((ctx), (idx), DUK_TYPE_MASK_BOOLEAN | \\\n\t                                  DUK_TYPE_MASK_NUMBER | \\\n\t                                  DUK_TYPE_MASK_STRING | \\\n\t                                  DUK_TYPE_MASK_OBJECT | \\\n\t                                  DUK_TYPE_MASK_BUFFER | \\\n\t                                  DUK_TYPE_MASK_POINTER | \\\n\t                                  DUK_TYPE_MASK_LIGHTFUNC)\n\nDUK_EXTERNAL_DECL duk_errcode_t duk_get_error_code(duk_context *ctx, duk_idx_t idx);\n#define duk_is_error(ctx,idx) \\\n\t(duk_get_error_code((ctx), (idx)) != 0)\n#define duk_is_eval_error(ctx,idx) \\\n\t(duk_get_error_code((ctx), (idx)) == DUK_ERR_EVAL_ERROR)\n#define duk_is_range_error(ctx,idx) \\\n\t(duk_get_error_code((ctx), (idx)) == DUK_ERR_RANGE_ERROR)\n#define duk_is_reference_error(ctx,idx) \\\n\t(duk_get_error_code((ctx), (idx)) == DUK_ERR_REFERENCE_ERROR)\n#define duk_is_syntax_error(ctx,idx) \\\n\t(duk_get_error_code((ctx), (idx)) == DUK_ERR_SYNTAX_ERROR)\n#define duk_is_type_error(ctx,idx) \\\n\t(duk_get_error_code((ctx), (idx)) == DUK_ERR_TYPE_ERROR)\n#define duk_is_uri_error(ctx,idx) \\\n\t(duk_get_error_code((ctx), (idx)) == DUK_ERR_URI_ERROR)\n\n/*\n *  Get operations: no coercion, returns default value for invalid\n *  indices and invalid value types.\n *\n *  duk_get_undefined() and duk_get_null() would be pointless and\n *  are not included.\n */\n\nDUK_EXTERNAL_DECL duk_bool_t duk_get_boolean(duk_context *ctx, duk_idx_t idx);\nDUK_EXTERNAL_DECL duk_double_t duk_get_number(duk_context *ctx, duk_idx_t idx);\nDUK_EXTERNAL_DECL duk_int_t duk_get_int(duk_context *ctx, duk_idx_t idx);\nDUK_EXTERNAL_DECL duk_uint_t duk_get_uint(duk_context *ctx, duk_idx_t idx);\nDUK_EXTERNAL_DECL const char *duk_get_string(duk_context *ctx, duk_idx_t idx);\nDUK_EXTERNAL_DECL const char *duk_get_lstring(duk_context *ctx, duk_idx_t idx, duk_size_t *out_len);\nDUK_EXTERNAL_DECL void *duk_get_buffer(duk_context *ctx, duk_idx_t idx, duk_size_t *out_size);\nDUK_EXTERNAL_DECL void *duk_get_buffer_data(duk_context *ctx, duk_idx_t idx, duk_size_t *out_size);\nDUK_EXTERNAL_DECL void *duk_get_pointer(duk_context *ctx, duk_idx_t idx);\nDUK_EXTERNAL_DECL duk_c_function duk_get_c_function(duk_context *ctx, duk_idx_t idx);\nDUK_EXTERNAL_DECL duk_context *duk_get_context(duk_context *ctx, duk_idx_t idx);\nDUK_EXTERNAL_DECL void *duk_get_heapptr(duk_context *ctx, duk_idx_t idx);\n\n/*\n *  Get-with-explicit default operations: like get operations but with an\n *  explicit default value.\n */\n\nDUK_EXTERNAL_DECL duk_bool_t duk_get_boolean_default(duk_context *ctx, duk_idx_t idx, duk_bool_t def_value);\nDUK_EXTERNAL_DECL duk_double_t duk_get_number_default(duk_context *ctx, duk_idx_t idx, duk_double_t def_value);\nDUK_EXTERNAL_DECL duk_int_t duk_get_int_default(duk_context *ctx, duk_idx_t idx, duk_int_t def_value);\nDUK_EXTERNAL_DECL duk_uint_t duk_get_uint_default(duk_context *ctx, duk_idx_t idx, duk_uint_t def_value);\nDUK_EXTERNAL_DECL const char *duk_get_string_default(duk_context *ctx, duk_idx_t idx, const char *def_value);\nDUK_EXTERNAL_DECL const char *duk_get_lstring_default(duk_context *ctx, duk_idx_t idx, duk_size_t *out_len, const char *def_ptr, duk_size_t def_len);\nDUK_EXTERNAL_DECL void *duk_get_buffer_default(duk_context *ctx, duk_idx_t idx, duk_size_t *out_size, void *def_ptr, duk_size_t def_len);\nDUK_EXTERNAL_DECL void *duk_get_buffer_data_default(duk_context *ctx, duk_idx_t idx, duk_size_t *out_size, void *def_ptr, duk_size_t def_len);\nDUK_EXTERNAL_DECL void *duk_get_pointer_default(duk_context *ctx, duk_idx_t idx, void *def_value);\nDUK_EXTERNAL_DECL duk_c_function duk_get_c_function_default(duk_context *ctx, duk_idx_t idx, duk_c_function def_value);\nDUK_EXTERNAL_DECL duk_context *duk_get_context_default(duk_context *ctx, duk_idx_t idx, duk_context *def_value);\nDUK_EXTERNAL_DECL void *duk_get_heapptr_default(duk_context *ctx, duk_idx_t idx, void *def_value);\n\n/*\n *  Opt operations: like require operations but with an explicit default value\n *  when value is undefined or index is invalid, null and non-matching types\n *  cause a TypeError.\n */\n\nDUK_EXTERNAL_DECL duk_bool_t duk_opt_boolean(duk_context *ctx, duk_idx_t idx, duk_bool_t def_value);\nDUK_EXTERNAL_DECL duk_double_t duk_opt_number(duk_context *ctx, duk_idx_t idx, duk_double_t def_value);\nDUK_EXTERNAL_DECL duk_int_t duk_opt_int(duk_context *ctx, duk_idx_t idx, duk_int_t def_value);\nDUK_EXTERNAL_DECL duk_uint_t duk_opt_uint(duk_context *ctx, duk_idx_t idx, duk_uint_t def_value);\nDUK_EXTERNAL_DECL const char *duk_opt_string(duk_context *ctx, duk_idx_t idx, const char *def_ptr);\nDUK_EXTERNAL_DECL const char *duk_opt_lstring(duk_context *ctx, duk_idx_t idx, duk_size_t *out_len, const char *def_ptr, duk_size_t def_len);\nDUK_EXTERNAL_DECL void *duk_opt_buffer(duk_context *ctx, duk_idx_t idx, duk_size_t *out_size, void *def_ptr, duk_size_t def_size);\nDUK_EXTERNAL_DECL void *duk_opt_buffer_data(duk_context *ctx, duk_idx_t idx, duk_size_t *out_size, void *def_ptr, duk_size_t def_size);\nDUK_EXTERNAL_DECL void *duk_opt_pointer(duk_context *ctx, duk_idx_t idx, void *def_value);\nDUK_EXTERNAL_DECL duk_c_function duk_opt_c_function(duk_context *ctx, duk_idx_t idx, duk_c_function def_value);\nDUK_EXTERNAL_DECL duk_context *duk_opt_context(duk_context *ctx, duk_idx_t idx, duk_context *def_value);\nDUK_EXTERNAL_DECL void *duk_opt_heapptr(duk_context *ctx, duk_idx_t idx, void *def_value);\n\n/*\n *  Require operations: no coercion, throw error if index or type\n *  is incorrect.  No defaulting.\n */\n\n#define duk_require_type_mask(ctx,idx,mask) \\\n\t((void) duk_check_type_mask((ctx), (idx), (mask) | DUK_TYPE_MASK_THROW))\n\nDUK_EXTERNAL_DECL void duk_require_undefined(duk_context *ctx, duk_idx_t idx);\nDUK_EXTERNAL_DECL void duk_require_null(duk_context *ctx, duk_idx_t idx);\nDUK_EXTERNAL_DECL duk_bool_t duk_require_boolean(duk_context *ctx, duk_idx_t idx);\nDUK_EXTERNAL_DECL duk_double_t duk_require_number(duk_context *ctx, duk_idx_t idx);\nDUK_EXTERNAL_DECL duk_int_t duk_require_int(duk_context *ctx, duk_idx_t idx);\nDUK_EXTERNAL_DECL duk_uint_t duk_require_uint(duk_context *ctx, duk_idx_t idx);\nDUK_EXTERNAL_DECL const char *duk_require_string(duk_context *ctx, duk_idx_t idx);\nDUK_EXTERNAL_DECL const char *duk_require_lstring(duk_context *ctx, duk_idx_t idx, duk_size_t *out_len);\nDUK_EXTERNAL_DECL void duk_require_object(duk_context *ctx, duk_idx_t idx);\nDUK_EXTERNAL_DECL void *duk_require_buffer(duk_context *ctx, duk_idx_t idx, duk_size_t *out_size);\nDUK_EXTERNAL_DECL void *duk_require_buffer_data(duk_context *ctx, duk_idx_t idx, duk_size_t *out_size);\nDUK_EXTERNAL_DECL void *duk_require_pointer(duk_context *ctx, duk_idx_t idx);\nDUK_EXTERNAL_DECL duk_c_function duk_require_c_function(duk_context *ctx, duk_idx_t idx);\nDUK_EXTERNAL_DECL duk_context *duk_require_context(duk_context *ctx, duk_idx_t idx);\nDUK_EXTERNAL_DECL void duk_require_function(duk_context *ctx, duk_idx_t idx);\n#define duk_require_callable(ctx,idx) \\\n\tduk_require_function((ctx), (idx))\nDUK_EXTERNAL_DECL void *duk_require_heapptr(duk_context *ctx, duk_idx_t idx);\n\n/* Symbols are object coercible and covered by DUK_TYPE_MASK_STRING. */\n#define duk_require_object_coercible(ctx,idx) \\\n\t((void) duk_check_type_mask((ctx), (idx), DUK_TYPE_MASK_BOOLEAN | \\\n\t                                            DUK_TYPE_MASK_NUMBER | \\\n\t                                            DUK_TYPE_MASK_STRING | \\\n\t                                            DUK_TYPE_MASK_OBJECT | \\\n\t                                            DUK_TYPE_MASK_BUFFER | \\\n\t                                            DUK_TYPE_MASK_POINTER | \\\n\t                                            DUK_TYPE_MASK_LIGHTFUNC | \\\n\t                                            DUK_TYPE_MASK_THROW))\n\n/*\n *  Coercion operations: in-place coercion, return coerced value where\n *  applicable.  If index is invalid, throw error.  Some coercions may\n *  throw an expected error (e.g. from a toString() or valueOf() call)\n *  or an internal error (e.g. from out of memory).\n */\n\nDUK_EXTERNAL_DECL void duk_to_undefined(duk_context *ctx, duk_idx_t idx);\nDUK_EXTERNAL_DECL void duk_to_null(duk_context *ctx, duk_idx_t idx);\nDUK_EXTERNAL_DECL duk_bool_t duk_to_boolean(duk_context *ctx, duk_idx_t idx);\nDUK_EXTERNAL_DECL duk_double_t duk_to_number(duk_context *ctx, duk_idx_t idx);\nDUK_EXTERNAL_DECL duk_int_t duk_to_int(duk_context *ctx, duk_idx_t idx);\nDUK_EXTERNAL_DECL duk_uint_t duk_to_uint(duk_context *ctx, duk_idx_t idx);\nDUK_EXTERNAL_DECL duk_int32_t duk_to_int32(duk_context *ctx, duk_idx_t idx);\nDUK_EXTERNAL_DECL duk_uint32_t duk_to_uint32(duk_context *ctx, duk_idx_t idx);\nDUK_EXTERNAL_DECL duk_uint16_t duk_to_uint16(duk_context *ctx, duk_idx_t idx);\nDUK_EXTERNAL_DECL const char *duk_to_string(duk_context *ctx, duk_idx_t idx);\nDUK_EXTERNAL_DECL const char *duk_to_lstring(duk_context *ctx, duk_idx_t idx, duk_size_t *out_len);\nDUK_EXTERNAL_DECL void *duk_to_buffer_raw(duk_context *ctx, duk_idx_t idx, duk_size_t *out_size, duk_uint_t flags);\nDUK_EXTERNAL_DECL void *duk_to_pointer(duk_context *ctx, duk_idx_t idx);\nDUK_EXTERNAL_DECL void duk_to_object(duk_context *ctx, duk_idx_t idx);\nDUK_EXTERNAL_DECL void duk_to_primitive(duk_context *ctx, duk_idx_t idx, duk_int_t hint);\n\n#define DUK_BUF_MODE_FIXED      0   /* internal: request fixed buffer result */\n#define DUK_BUF_MODE_DYNAMIC    1   /* internal: request dynamic buffer result */\n#define DUK_BUF_MODE_DONTCARE   2   /* internal: don't care about fixed/dynamic nature */\n\n#define duk_to_buffer(ctx,idx,out_size) \\\n\tduk_to_buffer_raw((ctx), (idx), (out_size), DUK_BUF_MODE_DONTCARE)\n#define duk_to_fixed_buffer(ctx,idx,out_size) \\\n\tduk_to_buffer_raw((ctx), (idx), (out_size), DUK_BUF_MODE_FIXED)\n#define duk_to_dynamic_buffer(ctx,idx,out_size) \\\n\tduk_to_buffer_raw((ctx), (idx), (out_size), DUK_BUF_MODE_DYNAMIC)\n\n/* safe variants of a few coercion operations */\nDUK_EXTERNAL_DECL const char *duk_safe_to_lstring(duk_context *ctx, duk_idx_t idx, duk_size_t *out_len);\n#define duk_safe_to_string(ctx,idx) \\\n\tduk_safe_to_lstring((ctx), (idx), NULL)\n\n/*\n *  Value length\n */\n\nDUK_EXTERNAL_DECL duk_size_t duk_get_length(duk_context *ctx, duk_idx_t idx);\nDUK_EXTERNAL_DECL void duk_set_length(duk_context *ctx, duk_idx_t idx, duk_size_t len);\n#if 0\n/* duk_require_length()? */\n/* duk_opt_length()? */\n#endif\n\n/*\n *  Misc conversion\n */\n\nDUK_EXTERNAL_DECL const char *duk_base64_encode(duk_context *ctx, duk_idx_t idx);\nDUK_EXTERNAL_DECL void duk_base64_decode(duk_context *ctx, duk_idx_t idx);\nDUK_EXTERNAL_DECL const char *duk_hex_encode(duk_context *ctx, duk_idx_t idx);\nDUK_EXTERNAL_DECL void duk_hex_decode(duk_context *ctx, duk_idx_t idx);\nDUK_EXTERNAL_DECL const char *duk_json_encode(duk_context *ctx, duk_idx_t idx);\nDUK_EXTERNAL_DECL void duk_json_decode(duk_context *ctx, duk_idx_t idx);\n\nDUK_EXTERNAL_DECL const char *duk_buffer_to_string(duk_context *ctx, duk_idx_t idx);\n\n/*\n *  Buffer\n */\n\nDUK_EXTERNAL_DECL void *duk_resize_buffer(duk_context *ctx, duk_idx_t idx, duk_size_t new_size);\nDUK_EXTERNAL_DECL void *duk_steal_buffer(duk_context *ctx, duk_idx_t idx, duk_size_t *out_size);\nDUK_EXTERNAL_DECL void duk_config_buffer(duk_context *ctx, duk_idx_t idx, void *ptr, duk_size_t len);\n\n/*\n *  Property access\n *\n *  The basic function assumes key is on stack.  The _string variant takes\n *  a C string as a property name, while the _index variant takes an array\n *  index as a property name (e.g. 123 is equivalent to the key \"123\").\n */\n\nDUK_EXTERNAL_DECL duk_bool_t duk_get_prop(duk_context *ctx, duk_idx_t obj_idx);\nDUK_EXTERNAL_DECL duk_bool_t duk_get_prop_string(duk_context *ctx, duk_idx_t obj_idx, const char *key);\nDUK_EXTERNAL_DECL duk_bool_t duk_get_prop_lstring(duk_context *ctx, duk_idx_t obj_idx, const char *key, duk_size_t key_len);\nDUK_EXTERNAL_DECL duk_bool_t duk_get_prop_index(duk_context *ctx, duk_idx_t obj_idx, duk_uarridx_t arr_idx);\nDUK_EXTERNAL_DECL duk_bool_t duk_get_prop_heapptr(duk_context *ctx, duk_idx_t obj_idx, void *ptr);\nDUK_EXTERNAL_DECL duk_bool_t duk_put_prop(duk_context *ctx, duk_idx_t obj_idx);\nDUK_EXTERNAL_DECL duk_bool_t duk_put_prop_string(duk_context *ctx, duk_idx_t obj_idx, const char *key);\nDUK_EXTERNAL_DECL duk_bool_t duk_put_prop_lstring(duk_context *ctx, duk_idx_t obj_idx, const char *key, duk_size_t key_len);\nDUK_EXTERNAL_DECL duk_bool_t duk_put_prop_index(duk_context *ctx, duk_idx_t obj_idx, duk_uarridx_t arr_idx);\nDUK_EXTERNAL_DECL duk_bool_t duk_put_prop_heapptr(duk_context *ctx, duk_idx_t obj_idx, void *ptr);\nDUK_EXTERNAL_DECL duk_bool_t duk_del_prop(duk_context *ctx, duk_idx_t obj_idx);\nDUK_EXTERNAL_DECL duk_bool_t duk_del_prop_string(duk_context *ctx, duk_idx_t obj_idx, const char *key);\nDUK_EXTERNAL_DECL duk_bool_t duk_del_prop_lstring(duk_context *ctx, duk_idx_t obj_idx, const char *key, duk_size_t key_len);\nDUK_EXTERNAL_DECL duk_bool_t duk_del_prop_index(duk_context *ctx, duk_idx_t obj_idx, duk_uarridx_t arr_idx);\nDUK_EXTERNAL_DECL duk_bool_t duk_del_prop_heapptr(duk_context *ctx, duk_idx_t obj_idx, void *ptr);\nDUK_EXTERNAL_DECL duk_bool_t duk_has_prop(duk_context *ctx, duk_idx_t obj_idx);\nDUK_EXTERNAL_DECL duk_bool_t duk_has_prop_string(duk_context *ctx, duk_idx_t obj_idx, const char *key);\nDUK_EXTERNAL_DECL duk_bool_t duk_has_prop_lstring(duk_context *ctx, duk_idx_t obj_idx, const char *key, duk_size_t key_len);\nDUK_EXTERNAL_DECL duk_bool_t duk_has_prop_index(duk_context *ctx, duk_idx_t obj_idx, duk_uarridx_t arr_idx);\nDUK_EXTERNAL_DECL duk_bool_t duk_has_prop_heapptr(duk_context *ctx, duk_idx_t obj_idx, void *ptr);\n\nDUK_EXTERNAL_DECL void duk_get_prop_desc(duk_context *ctx, duk_idx_t obj_idx, duk_uint_t flags);\nDUK_EXTERNAL_DECL void duk_def_prop(duk_context *ctx, duk_idx_t obj_idx, duk_uint_t flags);\n\nDUK_EXTERNAL_DECL duk_bool_t duk_get_global_string(duk_context *ctx, const char *key);\nDUK_EXTERNAL_DECL duk_bool_t duk_get_global_lstring(duk_context *ctx, const char *key, duk_size_t key_len);\nDUK_EXTERNAL_DECL duk_bool_t duk_put_global_string(duk_context *ctx, const char *key);\nDUK_EXTERNAL_DECL duk_bool_t duk_put_global_lstring(duk_context *ctx, const char *key, duk_size_t key_len);\n\n/*\n *  Inspection\n */\n\nDUK_EXTERNAL_DECL void duk_inspect_value(duk_context *ctx, duk_idx_t idx);\nDUK_EXTERNAL_DECL void duk_inspect_callstack_entry(duk_context *ctx, duk_int_t level);\n\n/*\n *  Object prototype\n */\n\nDUK_EXTERNAL_DECL void duk_get_prototype(duk_context *ctx, duk_idx_t idx);\nDUK_EXTERNAL_DECL void duk_set_prototype(duk_context *ctx, duk_idx_t idx);\n\n/*\n *  Object finalizer\n */\n\nDUK_EXTERNAL_DECL void duk_get_finalizer(duk_context *ctx, duk_idx_t idx);\nDUK_EXTERNAL_DECL void duk_set_finalizer(duk_context *ctx, duk_idx_t idx);\n\n/*\n *  Global object\n */\n\nDUK_EXTERNAL_DECL void duk_set_global_object(duk_context *ctx);\n\n/*\n *  Duktape/C function magic value\n */\n\nDUK_EXTERNAL_DECL duk_int_t duk_get_magic(duk_context *ctx, duk_idx_t idx);\nDUK_EXTERNAL_DECL void duk_set_magic(duk_context *ctx, duk_idx_t idx, duk_int_t magic);\nDUK_EXTERNAL_DECL duk_int_t duk_get_current_magic(duk_context *ctx);\n\n/*\n *  Module helpers: put multiple function or constant properties\n */\n\nDUK_EXTERNAL_DECL void duk_put_function_list(duk_context *ctx, duk_idx_t obj_idx, const duk_function_list_entry *funcs);\nDUK_EXTERNAL_DECL void duk_put_number_list(duk_context *ctx, duk_idx_t obj_idx, const duk_number_list_entry *numbers);\n\n/*\n *  Object operations\n */\n\nDUK_EXTERNAL_DECL void duk_compact(duk_context *ctx, duk_idx_t obj_idx);\nDUK_EXTERNAL_DECL void duk_enum(duk_context *ctx, duk_idx_t obj_idx, duk_uint_t enum_flags);\nDUK_EXTERNAL_DECL duk_bool_t duk_next(duk_context *ctx, duk_idx_t enum_idx, duk_bool_t get_value);\nDUK_EXTERNAL_DECL void duk_seal(duk_context *ctx, duk_idx_t obj_idx);\nDUK_EXTERNAL_DECL void duk_freeze(duk_context *ctx, duk_idx_t obj_idx);\n\n/*\n *  String manipulation\n */\n\nDUK_EXTERNAL_DECL void duk_concat(duk_context *ctx, duk_idx_t count);\nDUK_EXTERNAL_DECL void duk_join(duk_context *ctx, duk_idx_t count);\nDUK_EXTERNAL_DECL void duk_decode_string(duk_context *ctx, duk_idx_t idx, duk_decode_char_function callback, void *udata);\nDUK_EXTERNAL_DECL void duk_map_string(duk_context *ctx, duk_idx_t idx, duk_map_char_function callback, void *udata);\nDUK_EXTERNAL_DECL void duk_substring(duk_context *ctx, duk_idx_t idx, duk_size_t start_char_offset, duk_size_t end_char_offset);\nDUK_EXTERNAL_DECL void duk_trim(duk_context *ctx, duk_idx_t idx);\nDUK_EXTERNAL_DECL duk_codepoint_t duk_char_code_at(duk_context *ctx, duk_idx_t idx, duk_size_t char_offset);\n\n/*\n *  Ecmascript operators\n */\n\nDUK_EXTERNAL_DECL duk_bool_t duk_equals(duk_context *ctx, duk_idx_t idx1, duk_idx_t idx2);\nDUK_EXTERNAL_DECL duk_bool_t duk_strict_equals(duk_context *ctx, duk_idx_t idx1, duk_idx_t idx2);\nDUK_EXTERNAL_DECL duk_bool_t duk_samevalue(duk_context *ctx, duk_idx_t idx1, duk_idx_t idx2);\nDUK_EXTERNAL_DECL duk_bool_t duk_instanceof(duk_context *ctx, duk_idx_t idx1, duk_idx_t idx2);\n\n/*\n *  Function (method) calls\n */\n\nDUK_EXTERNAL_DECL void duk_call(duk_context *ctx, duk_idx_t nargs);\nDUK_EXTERNAL_DECL void duk_call_method(duk_context *ctx, duk_idx_t nargs);\nDUK_EXTERNAL_DECL void duk_call_prop(duk_context *ctx, duk_idx_t obj_idx, duk_idx_t nargs);\nDUK_EXTERNAL_DECL duk_int_t duk_pcall(duk_context *ctx, duk_idx_t nargs);\nDUK_EXTERNAL_DECL duk_int_t duk_pcall_method(duk_context *ctx, duk_idx_t nargs);\nDUK_EXTERNAL_DECL duk_int_t duk_pcall_prop(duk_context *ctx, duk_idx_t obj_idx, duk_idx_t nargs);\nDUK_EXTERNAL_DECL void duk_new(duk_context *ctx, duk_idx_t nargs);\nDUK_EXTERNAL_DECL duk_int_t duk_pnew(duk_context *ctx, duk_idx_t nargs);\nDUK_EXTERNAL_DECL duk_int_t duk_safe_call(duk_context *ctx, duk_safe_call_function func, void *udata, duk_idx_t nargs, duk_idx_t nrets);\n\n/*\n *  Thread management\n */\n\n/* There are currently no native functions to yield/resume, due to the internal\n * limitations on coroutine handling.  These will be added later.\n */\n\n/*\n *  Compilation and evaluation\n */\n\nDUK_EXTERNAL_DECL duk_int_t duk_eval_raw(duk_context *ctx, const char *src_buffer, duk_size_t src_length, duk_uint_t flags);\nDUK_EXTERNAL_DECL duk_int_t duk_compile_raw(duk_context *ctx, const char *src_buffer, duk_size_t src_length, duk_uint_t flags);\n\n/* plain */\n#define duk_eval(ctx)  \\\n\t((void) duk_eval_raw((ctx), NULL, 0, 1 /*args*/ | DUK_COMPILE_EVAL | DUK_COMPILE_NOFILENAME))\n\n#define duk_eval_noresult(ctx)  \\\n\t((void) duk_eval_raw((ctx), NULL, 0, 1 /*args*/ | DUK_COMPILE_EVAL | DUK_COMPILE_NORESULT | DUK_COMPILE_NOFILENAME))\n\n#define duk_peval(ctx)  \\\n\t(duk_eval_raw((ctx), NULL, 0, 1 /*args*/ | DUK_COMPILE_EVAL | DUK_COMPILE_SAFE | DUK_COMPILE_NOFILENAME))\n\n#define duk_peval_noresult(ctx)  \\\n\t(duk_eval_raw((ctx), NULL, 0, 1 /*args*/ | DUK_COMPILE_EVAL | DUK_COMPILE_SAFE | DUK_COMPILE_NORESULT | DUK_COMPILE_NOFILENAME))\n\n#define duk_compile(ctx,flags)  \\\n\t((void) duk_compile_raw((ctx), NULL, 0, 2 /*args*/ | (flags)))\n\n#define duk_pcompile(ctx,flags)  \\\n\t(duk_compile_raw((ctx), NULL, 0, 2 /*args*/ | (flags) | DUK_COMPILE_SAFE))\n\n/* string */\n#define duk_eval_string(ctx,src)  \\\n\t((void) duk_eval_raw((ctx), (src), 0, 0 /*args*/ | DUK_COMPILE_EVAL | DUK_COMPILE_NOSOURCE | DUK_COMPILE_STRLEN | DUK_COMPILE_NOFILENAME))\n\n#define duk_eval_string_noresult(ctx,src)  \\\n\t((void) duk_eval_raw((ctx), (src), 0, 0 /*args*/ | DUK_COMPILE_EVAL | DUK_COMPILE_NOSOURCE | DUK_COMPILE_STRLEN | DUK_COMPILE_NORESULT | DUK_COMPILE_NOFILENAME))\n\n#define duk_peval_string(ctx,src)  \\\n\t(duk_eval_raw((ctx), (src), 0, 0 /*args*/ | DUK_COMPILE_EVAL | DUK_COMPILE_SAFE | DUK_COMPILE_NOSOURCE | DUK_COMPILE_STRLEN | DUK_COMPILE_NOFILENAME))\n\n#define duk_peval_string_noresult(ctx,src)  \\\n\t(duk_eval_raw((ctx), (src), 0, 0 /*args*/ | DUK_COMPILE_EVAL | DUK_COMPILE_SAFE | DUK_COMPILE_NOSOURCE | DUK_COMPILE_STRLEN | DUK_COMPILE_NORESULT | DUK_COMPILE_NOFILENAME))\n\n#define duk_compile_string(ctx,flags,src)  \\\n\t((void) duk_compile_raw((ctx), (src), 0, 0 /*args*/ | (flags) | DUK_COMPILE_NOSOURCE | DUK_COMPILE_STRLEN | DUK_COMPILE_NOFILENAME))\n\n#define duk_compile_string_filename(ctx,flags,src)  \\\n\t((void) duk_compile_raw((ctx), (src), 0, 1 /*args*/ | (flags) | DUK_COMPILE_NOSOURCE | DUK_COMPILE_STRLEN))\n\n#define duk_pcompile_string(ctx,flags,src)  \\\n\t(duk_compile_raw((ctx), (src), 0, 0 /*args*/ | (flags) | DUK_COMPILE_SAFE | DUK_COMPILE_NOSOURCE | DUK_COMPILE_STRLEN | DUK_COMPILE_NOFILENAME))\n\n#define duk_pcompile_string_filename(ctx,flags,src)  \\\n\t(duk_compile_raw((ctx), (src), 0, 1 /*args*/ | (flags) | DUK_COMPILE_SAFE | DUK_COMPILE_NOSOURCE | DUK_COMPILE_STRLEN))\n\n/* lstring */\n#define duk_eval_lstring(ctx,buf,len)  \\\n\t((void) duk_eval_raw((ctx), buf, len, 0 /*args*/ | DUK_COMPILE_EVAL | DUK_COMPILE_NOSOURCE | DUK_COMPILE_NOFILENAME))\n\n#define duk_eval_lstring_noresult(ctx,buf,len)  \\\n\t((void) duk_eval_raw((ctx), buf, len, 0 /*args*/ | DUK_COMPILE_EVAL | DUK_COMPILE_NOSOURCE | DUK_COMPILE_NORESULT | DUK_COMPILE_NOFILENAME))\n\n#define duk_peval_lstring(ctx,buf,len)  \\\n\t(duk_eval_raw((ctx), buf, len, 0 /*args*/ | DUK_COMPILE_EVAL | DUK_COMPILE_NOSOURCE | DUK_COMPILE_SAFE | DUK_COMPILE_NOFILENAME))\n\n#define duk_peval_lstring_noresult(ctx,buf,len)  \\\n\t(duk_eval_raw((ctx), buf, len, 0 /*args*/ | DUK_COMPILE_EVAL | DUK_COMPILE_SAFE | DUK_COMPILE_NOSOURCE | DUK_COMPILE_NORESULT | DUK_COMPILE_NOFILENAME))\n\n#define duk_compile_lstring(ctx,flags,buf,len)  \\\n\t((void) duk_compile_raw((ctx), buf, len, 0 /*args*/ | (flags) | DUK_COMPILE_NOSOURCE | DUK_COMPILE_NOFILENAME))\n\n#define duk_compile_lstring_filename(ctx,flags,buf,len)  \\\n\t((void) duk_compile_raw((ctx), buf, len, 1 /*args*/ | (flags) | DUK_COMPILE_NOSOURCE))\n\n#define duk_pcompile_lstring(ctx,flags,buf,len)  \\\n\t(duk_compile_raw((ctx), buf, len, 0 /*args*/ | (flags) | DUK_COMPILE_SAFE | DUK_COMPILE_NOSOURCE | DUK_COMPILE_NOFILENAME))\n\n#define duk_pcompile_lstring_filename(ctx,flags,buf,len)  \\\n\t(duk_compile_raw((ctx), buf, len, 1 /*args*/ | (flags) | DUK_COMPILE_SAFE | DUK_COMPILE_NOSOURCE))\n\n/*\n *  Bytecode load/dump\n */\n\nDUK_EXTERNAL_DECL void duk_dump_function(duk_context *ctx);\nDUK_EXTERNAL_DECL void duk_load_function(duk_context *ctx);\n\n/*\n *  Debugging\n */\n\nDUK_EXTERNAL_DECL void duk_push_context_dump(duk_context *ctx);\n\n/*\n *  Debugger (debug protocol)\n */\n\nDUK_EXTERNAL_DECL void duk_debugger_attach(duk_context *ctx,\n                                           duk_debug_read_function read_cb,\n                                           duk_debug_write_function write_cb,\n                                           duk_debug_peek_function peek_cb,\n                                           duk_debug_read_flush_function read_flush_cb,\n                                           duk_debug_write_flush_function write_flush_cb,\n                                           duk_debug_request_function request_cb,\n                                           duk_debug_detached_function detached_cb,\n                                           void *udata);\nDUK_EXTERNAL_DECL void duk_debugger_detach(duk_context *ctx);\nDUK_EXTERNAL_DECL void duk_debugger_cooperate(duk_context *ctx);\nDUK_EXTERNAL_DECL duk_bool_t duk_debugger_notify(duk_context *ctx, duk_idx_t nvalues);\nDUK_EXTERNAL_DECL void duk_debugger_pause(duk_context *ctx);\n\n/*\n *  Time handling\n */\n\nDUK_EXTERNAL_DECL duk_double_t duk_get_now(duk_context *ctx);\nDUK_EXTERNAL_DECL void duk_time_to_components(duk_context *ctx, duk_double_t timeval, duk_time_components *comp);\nDUK_EXTERNAL_DECL duk_double_t duk_components_to_time(duk_context *ctx, duk_time_components *comp);\n\n/*\n *  Date provider related constants\n *\n *  NOTE: These are \"semi public\" - you should only use these if you write\n *  your own platform specific Date provider, see doc/datetime.rst.\n */\n\n/* Millisecond count constants. */\n#define DUK_DATE_MSEC_SECOND          1000L\n#define DUK_DATE_MSEC_MINUTE          (60L * 1000L)\n#define DUK_DATE_MSEC_HOUR            (60L * 60L * 1000L)\n#define DUK_DATE_MSEC_DAY             (24L * 60L * 60L * 1000L)\n\n/* Ecmascript date range is 100 million days from Epoch:\n * > 100e6 * 24 * 60 * 60 * 1000  // 100M days in millisecs\n * 8640000000000000\n * (= 8.64e15)\n */\n#define DUK_DATE_MSEC_100M_DAYS         (8.64e15)\n#define DUK_DATE_MSEC_100M_DAYS_LEEWAY  (8.64e15 + 24 * 3600e3)\n\n/* Ecmascript year range:\n * > new Date(100e6 * 24 * 3600e3).toISOString()\n * '+275760-09-13T00:00:00.000Z'\n * > new Date(-100e6 * 24 * 3600e3).toISOString()\n * '-271821-04-20T00:00:00.000Z'\n */\n#define DUK_DATE_MIN_ECMA_YEAR     (-271821L)\n#define DUK_DATE_MAX_ECMA_YEAR     275760L\n\n/* Part indices for internal breakdowns.  Part order from DUK_DATE_IDX_YEAR\n * to DUK_DATE_IDX_MILLISECOND matches argument ordering of Ecmascript API\n * calls (like Date constructor call).  Some functions in duk_bi_date.c\n * depend on the specific ordering, so change with care.  16 bits are not\n * enough for all parts (year, specifically).\n *\n * Must be in-sync with genbuiltins.py.\n */\n#define DUK_DATE_IDX_YEAR           0  /* year */\n#define DUK_DATE_IDX_MONTH          1  /* month: 0 to 11 */\n#define DUK_DATE_IDX_DAY            2  /* day within month: 0 to 30 */\n#define DUK_DATE_IDX_HOUR           3\n#define DUK_DATE_IDX_MINUTE         4\n#define DUK_DATE_IDX_SECOND         5\n#define DUK_DATE_IDX_MILLISECOND    6\n#define DUK_DATE_IDX_WEEKDAY        7  /* weekday: 0 to 6, 0=sunday, 1=monday, etc */\n#define DUK_DATE_IDX_NUM_PARTS      8\n\n/* Internal API call flags, used for various functions in duk_bi_date.c.\n * Certain flags are used by only certain functions, but since the flags\n * don't overlap, a single flags value can be passed around to multiple\n * functions.\n *\n * The unused top bits of the flags field are also used to pass values\n * to helpers (duk__get_part_helper() and duk__set_part_helper()).\n *\n * Must be in-sync with genbuiltins.py.\n */\n\n/* NOTE: when writing a Date provider you only need a few specific\n * flags from here, the rest are internal.  Avoid using anything you\n * don't need.\n */\n\n#define DUK_DATE_FLAG_NAN_TO_ZERO          (1 << 0)  /* timeval breakdown: internal time value NaN -> zero */\n#define DUK_DATE_FLAG_NAN_TO_RANGE_ERROR   (1 << 1)  /* timeval breakdown: internal time value NaN -> RangeError (toISOString) */\n#define DUK_DATE_FLAG_ONEBASED             (1 << 2)  /* timeval breakdown: convert month and day-of-month parts to one-based (default is zero-based) */\n#define DUK_DATE_FLAG_EQUIVYEAR            (1 << 3)  /* timeval breakdown: replace year with equivalent year in the [1971,2037] range for DST calculations */\n#define DUK_DATE_FLAG_LOCALTIME            (1 << 4)  /* convert time value to local time */\n#define DUK_DATE_FLAG_SUB1900              (1 << 5)  /* getter: subtract 1900 from year when getting year part */\n#define DUK_DATE_FLAG_TOSTRING_DATE        (1 << 6)  /* include date part in string conversion result */\n#define DUK_DATE_FLAG_TOSTRING_TIME        (1 << 7)  /* include time part in string conversion result */\n#define DUK_DATE_FLAG_TOSTRING_LOCALE      (1 << 8)  /* use locale specific formatting if available */\n#define DUK_DATE_FLAG_TIMESETTER           (1 << 9)  /* setter: call is a time setter (affects hour, min, sec, ms); otherwise date setter (affects year, month, day-in-month) */\n#define DUK_DATE_FLAG_YEAR_FIXUP           (1 << 10) /* setter: perform 2-digit year fixup (00...99 -> 1900...1999) */\n#define DUK_DATE_FLAG_SEP_T                (1 << 11) /* string conversion: use 'T' instead of ' ' as a separator */\n#define DUK_DATE_FLAG_VALUE_SHIFT          12        /* additional values begin at bit 12 */\n\n/*\n *  ROM pointer compression\n */\n\n/* Support array for ROM pointer compression.  Only declared when ROM\n * pointer compression is active.\n */\n#if defined(DUK_USE_ROM_OBJECTS) && defined(DUK_USE_HEAPPTR16)\nDUK_EXTERNAL_DECL const void * const duk_rom_compressed_pointers[];\n#endif\n\n/*\n *  C++ name mangling\n */\n\n#if defined(__cplusplus)\n/* end 'extern \"C\"' wrapper */\n}\n#endif\n\n/*\n *  END PUBLIC API\n */\n\n#endif  /* DUKTAPE_H_INCLUDED */\n"
  },
  {
    "path": "src/extractor/CMakeLists.txt",
    "content": "#[[\nThis is free and unencumbered software released into the public domain.\n\nAnyone is free to copy, modify, publish, use, compile, sell, or\ndistribute this software, either in source code form or as a compiled\nbinary, for any purpose, commercial or non-commercial, and by any\nmeans.\n\nIn jurisdictions that recognize copyright laws, the author or authors\nof this software dedicate any and all copyright interest in the\nsoftware to the public domain. We make this dedication for the benefit\nof the public at large and to the detriment of our heirs and\nsuccessors. We intend this dedication to be an overt act of\nrelinquishment in perpetuity of all present and future rights to this\nsoftware under copyright law.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR\nOTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,\nARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\nOTHER DEALINGS IN THE SOFTWARE.\n\nFor more information, please refer to <http://unlicense.org>\n]]\n\nproject(extractor)\n\nadd_executable(extractor\n        extractor.c extractor.h\n        fac.c fac.h\n        pc_copy_paths.h\n        pc_music_paths.h\n        pc_package_paths.h\n        version.c\n        )\n\ntarget_include_directories(extractor PUBLIC . ${CMAKE_SYSTEM_INCLUDE_PATH})\ntarget_link_libraries(extractor plcore plgraphics)"
  },
  {
    "path": "src/extractor/extractor.c",
    "content": "/* OpenHoW\n * Copyright (C) 2017-2020 TalonBrave.info and Others (see CONTRIBUTORS)\n * Copyright (C) 2017 Daniel Collins <solemnwarning@solemnwarning.net>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include \"extractor.h\"\n#include \"fac.h\"\n\nstatic char g_input_path[ PL_SYSTEM_MAX_PATH ] = { '\\0' };\nstatic char g_output_path[ PL_SYSTEM_MAX_PATH ];\n\n//#define PARANOID_DATA\n//#define EXPORT_NORMALS\n#define CONVERT_TIMS\n\n/************************************************************/\n/* Data Conversion */\n\nstatic void ConvertImageToPng( const char *path ) {\n#if defined( CONVERT_TIMS )\n\t// figure out if the file already exists before\n\t// we even start trying to convert this thing\n\tchar out_path[ PL_SYSTEM_MAX_PATH ];\n\tPlStripExtension( out_path, sizeof( out_path ), path );\n\tstrcat( out_path, \".png\" );\n\tif ( PlFileExists( out_path ) ) {\n\t\tPlDeleteFile( path );\n\t\treturn;\n\t}\n\n\tPLImage *image = PlLoadImage( path );\n\tif ( image == NULL ) {\n\t\tWarning( \"Failed to load image, \\\"%s\\\" (%s)!\\n\", path, PlGetError() );\n\t\treturn;\n\t}\n\n\tconst char *ext = PlGetFileExtension( path );\n\tif ( ext != NULL && ext[ 0 ] != '\\0' && strcmp( ext, \"tim\" ) == 0 ) {\n\t\t// ensure that it's a format we're able to convert from\n\t\tif ( image->format == PL_IMAGEFORMAT_RGB5A1 ) {\n\t\t\tif ( PlConvertPixelFormat( image, PL_IMAGEFORMAT_RGBA8 ) ) {\n\t\t\t\tPlReplaceImageColour( image, PLColour( 255, 0, 255, 255 ), PLColour( 0, 0, 0, 0 ) );\n\t\t\t\tif ( !PlWriteImage( image, out_path ) ) {\n\t\t\t\t\tWarning( \"Failed to write PNG, \\\"%s\\\" (%s)!\\n\", out_path, PlGetError() );\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tWarning( \"Failed to convert \\\"%s\\\", %s, aborting!\\n\", path, PlGetError() );\n\t\t\t}\n\t\t} else {\n\t\t\tWarning( \"Unexpected pixel format in \\\"%s\\\", aborting!\\n\", path );\n\t\t}\n\t}\n\n\tif ( PlFileExists( out_path ) ) {\n\t\tPlDeleteFile( path );\n\t}\n\n\tPlDestroyImage( image );\n#endif\n}\n\ntypedef struct ModelConversionData {\n\tconst char *mad;\n\tconst char *mtd;\n\tconst char *out;\n} ModelConversionData;\nstatic ModelConversionData pc_conversion_data[] = {\n        { \"/Maps/BAY.MAD\", \"/Maps/bay.mtd\", \"mods/how/chars/scenery/\" },\n        { \"/Maps/ICE.MAD\", \"/Maps/ice.mtd\", \"mods/how/chars/scenery/\" },\n        { \"/Maps/BOOM.MAD\", \"/Maps/boom.mtd\", \"mods/how/chars/scenery/\" },\n        { \"/Maps/BUTE.MAD\", \"/Maps/bute.mtd\", \"mods/how/chars/scenery/\" },\n        { \"/Maps/CAMP.MAD\", \"/Maps/camp.mtd\", \"mods/how/chars/scenery/\" },\n        { \"/Maps/DEMO.MAD\", \"/Maps/demo.mtd\", \"mods/how/chars/scenery/\" },\n        { \"/Maps/DEVI.MAD\", \"/Maps/devi.mtd\", \"mods/how/chars/scenery/\" },\n        { \"/Maps/DVAL.MAD\", \"/Maps/dval.mtd\", \"mods/how/chars/scenery/\" },\n        { \"/Maps/EASY.MAD\", \"/Maps/easy.mtd\", \"mods/how/chars/scenery/\" },\n        { \"/Maps/ESTU.MAD\", \"/Maps/estu.mtd\", \"mods/how/chars/scenery/\" },\n        { \"/Maps/FOOT.MAD\", \"/Maps/foot.mtd\", \"mods/how/chars/scenery/\" },\n        { \"/Maps/GUNS.MAD\", \"/Maps/guns.mtd\", \"mods/how/chars/scenery/\" },\n        { \"/Maps/HELL2.MAD\", \"/Maps/hell2.mtd\", \"mods/how/chars/scenery/\" },\n        { \"/Maps/HELL3.MAD\", \"/Maps/hell3.mtd\", \"mods/how/chars/scenery/\" },\n        { \"/Maps/HILLBASE.MAD\", \"/Maps/hillbase.mtd\", \"mods/how/chars/scenery/\" },\n        { \"/Maps/ICEFLOW.MAD\", \"/Maps/iceflow.mtd\", \"mods/how/chars/scenery/\" },\n        { \"/Maps/ICE.MAD\", \"/Maps/ice.mtd\", \"mods/how/chars/scenery/\" },\n        { \"/Maps/ZULUS.MAD\", \"/Maps/zulus.mtd\", \"mods/how/chars/scenery/\" },\n\n        { \"/Chars/WEAPONS.MAD\", \"/Chars/WEAPONS.MTD\", \"mods/how/chars/weapons/\" },\n        { \"/Chars/PROPOINT.MAD\", \"/Chars/propoint.mtd\", \"mods/how/chars/propoint/\" },\n        { \"/Chars/TOP.MAD\", \"/Chars/TOP.MTD\", \"mods/how/chars/top/\" },\n        { \"/Chars/SIGHT.MAD\", \"/Chars/SIGHT.MTD\", \"mods/how/chars/sight/\" },\n\n        { \"/Chars/british.mad\", \"/Chars/british.mtd\", \"mods/how/chars/pigs/\" }, /* pig models */\n\n        { \"/Chars/SKYDOME.MAD\", \"/Chars/SKYDOME.MTD\", \"mods/how/skys/\" },\n};\n\nstatic void ConvertModelData( void ) {\n\tfor ( unsigned long i = 0; i < PL_ARRAY_ELEMENTS( pc_conversion_data ); ++i ) {\n\t\tchar path[ PL_SYSTEM_MAX_PATH ];\n\t\tsnprintf( path, sizeof( path ), \"%s%s\", g_input_path, pc_conversion_data[ i ].mad );\n\t\tPLPackage *package = PlLoadPackage( path );\n\t\tif ( package == NULL ) {\n\t\t\tError( \"Failed to load MAD package, \\\"%s\\\" (%s)!\\n\", path, PlGetError() );\n\t\t}\n\n\t\t/* Write the files out to the destination. I'm lazy and we'll delete it once we're done anyway. */\n\t\tchar model_paths[ package->table_size ][ PL_SYSTEM_MAX_PATH ];\n\t\tunsigned int num_models = 0;\n\t\tfor ( unsigned int j = 0; j < package->table_size; ++j ) {\n\t\t\tchar out[ PL_SYSTEM_MAX_PATH ];\n\t\t\tsnprintf( out, sizeof( out ), \"%s/%s%s\", g_output_path, pc_conversion_data[ i ].out, pl_strtolower( package->table[ j ].fileName ) );\n\n\t\t\tchar dir[ PL_SYSTEM_MAX_PATH ];\n\t\t\tconst char *filename = PlGetFileName( out );\n\t\t\tstrncpy( dir, out, strlen( out ) - strlen( filename ) );\n\t\t\tdir[ strlen( out ) - strlen( filename ) ] = '\\0';\n\t\t\tif ( PlCreatePath( dir ) ) {\n\t\t\t\tPLFile *fp = PlLoadPackageFile( package, package->table[ j ].fileName );\n\t\t\t\tif ( !PlWriteFile( out, PlGetFileData( fp ), package->table[ j ].fileSize ) ) {\n\t\t\t\t\tError( \"Failed to write model, \\\"%s\\\" (%s)!\\n\", out, PlGetError() );\n\t\t\t\t}\n\t\t\t\tPlCloseFile( fp );\n\t\t\t} else {\n\t\t\t\tError( \"Failed to create output directory, \\\"%s\\\" (%s)!\\n\", dir, PlGetError() );\n\t\t\t}\n\n\t\t\t// skydome is a special case\n\t\t\tif ( pl_strcasecmp( filename, \"skydomeu.fac\" ) == 0 || pl_strcasecmp( filename, \"skydome.fac\" ) == 0 ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst char *ext = PlGetFileExtension( package->table[ j ].fileName );\n\t\t\tif ( pl_strcasecmp( ext, \"fac\" ) == 0 ) {\n\t\t\t\tPlStripExtension( model_paths[ num_models++ ], PL_SYSTEM_MAX_PATH - 1, out );\n\t\t\t}\n\t\t}\n\n\t\tPlDestroyPackage( package );\n\n\t\t/* Now we need to load each fac, fetch each index for each texture and figure out\n\t\t * the true name for that texture by comparing against the mtd. */\n\n\t\tsnprintf( path, sizeof( path ), \"%s%s\", g_input_path, pc_conversion_data[ i ].mtd );\n\t\tpackage = PlLoadPackage( path );\n\t\tif ( package == NULL ) {\n\t\t\tError( \"Failed to load MTD package, \\\"%s\\\" (%s)!\\n\", pc_conversion_data[ i ].mtd, PlGetError() );\n\t\t}\n\n\t\t/* pigs are a special case... */\n\t\tif ( strcmp( pc_conversion_data[ i ].mad, \"/Chars/british.mad\" ) != 0 ) {\n\t\t\t// write all the textures out\n\t\t\tfor ( unsigned int j = 0; j < package->table_size; ++j ) {\n\t\t\t\tchar out[ PL_SYSTEM_MAX_PATH ];\n\t\t\t\tsnprintf( out, sizeof( out ), \"%s/%s%s\", g_output_path, pc_conversion_data[ i ].out, pl_strtolower( package->table[ j ].fileName ) );\n\n\t\t\t\tchar dir[ PL_SYSTEM_MAX_PATH ];\n\t\t\t\tconst char *filename = PlGetFileName( out );\n\t\t\t\tstrncpy( dir, out, strlen( out ) - strlen( filename ) );\n\t\t\t\tdir[ strlen( out ) - strlen( filename ) ] = '\\0';\n\n#if defined( PARANOID_DATA )// paranoid check, doesn't happen...\n\t\t\t\tif ( plFileExists( out ) ) {\n\t\t\t\t\tLogInfo( \"The file \\\"%s\\\" already exists, comparing...\\n\", out );\n\n\t\t\t\t\tsize_t size = plGetLocalFileSize( out );\n\t\t\t\t\tFILE *fp = fopen( out, \"rb\" );\n\t\t\t\t\tchar *data = u_alloc( size, 1, true );\n\t\t\t\t\tfread( data, 1, size, fp );\n\t\t\t\t\tfclose( fp );\n\n\t\t\t\t\tuint32_t crc_a;\n\t\t\t\t\tpl_crc32( package->table[ j ].file.data, package->table[ j ].fileSize, &crc_a );\n\t\t\t\t\tuint32_t crc_b;\n\t\t\t\t\tpl_crc32( data, size, &crc_b );\n\t\t\t\t\tif ( crc_a != crc_b ) {\n\t\t\t\t\t\tLogWarn( \"Files are different, renaming second file!\\n\" );\n\t\t\t\t\t\twhile ( plFileExists( out ) ) {\n\t\t\t\t\t\t\tstrcat( out, \"_\" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n#endif\n\n\t\t\t\tif ( PlCreatePath( dir ) ) {\n\t\t\t\t\tPLFile *fp = PlLoadPackageFile( package, package->table[ j ].fileName );\n\t\t\t\t\tif ( !PlWriteFile( out, PlGetFileData( fp ), package->table[ j ].fileSize ) ) {\n\t\t\t\t\t\tError( \"Failed to write model, \\\"%s\\\" (%s)!\\n\", out, PlGetError() );\n\t\t\t\t\t}\n\t\t\t\t\tPlCloseFile( fp );\n\t\t\t\t} else {\n\t\t\t\t\tError( \"Failed to create output directory, \\\"%s\\\" (%s)!\\n\", dir, PlGetError() );\n\t\t\t\t}\n\n\t\t\t\tConvertImageToPng( out );\n\t\t\t}\n\t\t}\n\n\t\t/* and now we go through again, converting everything as we do so */\n\t\tfor ( unsigned int j = 0; j < num_models; ++j ) {\n\t\t\tchar fac_path[ PL_SYSTEM_MAX_PATH ];\n\t\t\tsnprintf( fac_path, PL_SYSTEM_MAX_PATH, \"%s.fac\", model_paths[ j ] );\n\t\t\tif ( !PlFileExists( fac_path ) ) {\n\t\t\t\tError( \"Failed to find FAC file, \\\"%s\\\"!\\n\", fac_path );\n\t\t\t}\n\n\t\t\t// we'll resize this later...\n\t\t\tFacTextureIndex *table = calloc( package->table_size, sizeof( FacTextureIndex ) );\n\t\t\tif ( table == NULL ) {\n\t\t\t\tWarning( \"Failed to allocate texture table!\\n\" );\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tunsigned int table_size = 0;\n\n\t\t\tFacHandle *fac = Fac_LoadFile( fac_path );\n\t\t\tif ( fac == NULL ) {\n\t\t\t\tWarning( \"Failed to load FAC \\\"%s\\\"!\\n\", fac_path );\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tfor ( unsigned int k = 0; k < fac->num_triangles; ++k ) {\n\t\t\t\tuint32_t texture_index = fac->triangles[ k ].texture_index;\n\t\t\t\tif ( texture_index >= package->table_size ) {\n\t\t\t\t\tError( \"Out of bounds texture index, \\\"%s\\\"!\\n\", fac_path );\n\t\t\t\t}\n\n\t\t\t\t// attempt to add it to the table\n\t\t\t\tchar texture_name[ 16 ];\n\t\t\t\tstrncpy( texture_name, package->table[ texture_index ].fileName, strlen( package->table[ texture_index ].fileName ) - 4 );\n\t\t\t\ttexture_name[ strlen( package->table[ texture_index ].fileName ) - 4 ] = '\\0';\n\t\t\t\tpl_strtolower( texture_name );\n\t\t\t\tunsigned int l;\n\t\t\t\tfor ( l = 0; l < package->table_size; ++l ) {\n\t\t\t\t\tif ( table[ l ].name[ 0 ] == '\\0' ) {\n\t\t\t\t\t\tstrncpy( table[ l ].name, texture_name, sizeof( table[ l ].name ) );\n\t\t\t\t\t\ttable_size++;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t} else if ( strncmp( table[ l ].name, texture_name, sizeof( table[ l ].name ) ) == 0 ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( table_size > package->table_size ) {\n\t\t\t\t\tError( \"Invalid table size, %d > %d!\\n\", table_size, package->table_size );\n\t\t\t\t}\n\n\t\t\t\t// replace the original id so it matches with the index in our table\n\t\t\t\tfac->triangles[ k ].texture_index = l;\n\t\t\t}\n\n\t\t\tfac->texture_table = calloc( table_size, sizeof( FacTextureIndex ) );\n\t\t\tif ( fac->texture_table == NULL ) {\n\t\t\t\tError( \"Failed to allocate texture table for output!\\n\" );\n\t\t\t}\n\n\t\t\tfac->texture_table_size = table_size;\n\t\t\tmemcpy( fac->texture_table, table, sizeof( FacTextureIndex ) * table_size );\n\t\t\tfree( table );\n\n\t\t\t// write out the fac and replace it (we'll append the table to the end)\n\t\t\tsnprintf( fac_path, PL_SYSTEM_MAX_PATH, \"%s.fac\", model_paths[ j ] );\n\t\t\tFac_WriteFile( fac, fac_path );\n\t\t}\n\t}\n}\n\n/////////////////////////////////////////////////////////////\n/* Extraction process for initial setup */\n\nstatic void ExtractPtgPackage( const char *input_path, const char *output_path ) {\n\tif ( !PlCreatePath( output_path ) ) {\n\t\tError( \"Failed to create path, \\\"%s\\\" (%s)!\\n\", output_path, PlGetError() );\n\t}\n\n\tFILE *file = fopen( input_path, \"rb\" );\n\tif ( file == NULL ) {\n\t\tError( \"Failed to load PTG package, \\\"%s\\\"!\\n\", input_path );\n\t}\n\n\tuint32_t num_textures = 0;\n\tif ( fread( &num_textures, sizeof( uint32_t ), 1, file ) != 1 ) {\n\t\tError( \"Invalid PTG file, failed to get number of textures!\\n\" );\n\t}\n\n\tsize_t tim_size = ( PlGetLocalFileSize( input_path ) - sizeof( num_textures ) ) / num_textures;\n\tfor ( unsigned int i = 0; i < num_textures; ++i ) {\n\t\tuint8_t tim[ tim_size ];\n\t\tif ( fread( tim, tim_size, 1, file ) != 1 ) {\n\t\t\tPrint( \"Failed to read Tim, \\\"%d\\\"!\\n\", i );\n\t\t\tcontinue;\n\t\t}\n\n\t\tchar out_path[ PL_SYSTEM_MAX_PATH ] = { '\\0' };\n\t\tsprintf( out_path, \"%s%d.tim\", output_path, i );\n\t\tif ( !PlWriteFile( out_path, tim, tim_size ) ) {\n\t\t\tWarning( \"Failed to write file, \\\"%s\\\" (%s)!\\n\", out_path, PlGetError() );\n\t\t}\n\n\t\tConvertImageToPng( out_path );\n\t}\n\n\tfclose( file );\n}\n\nstatic void ExtractMadPackage( const char *input_path, const char *output_path ) {\n\tif ( !PlCreatePath( output_path ) ) {\n\t\tError( \"Failed to create output directory,  \\\"%s\\\"!\\nPL: %s\\n\", output_path, PlGetError() );\n\t}\n\n\tPLPackage *package = PlLoadPackage( input_path );\n\tif ( package == NULL ) {\n\t\tError( \"Failed to load %s, aborting!\\nPL: %s\\n\", input_path, PlGetError() );\n\t}\n\n\tfor ( unsigned int i = 0; i < package->table_size; i++ ) {\n\t\tchar out[ PL_SYSTEM_MAX_PATH ];\n\t\tsnprintf( out, sizeof( out ) - 1, \"%s%s\", output_path, pl_strtolower( package->table[ i ].fileName ) );\n\t\tPLFile *fp = PlLoadPackageFile( package, package->table[ i ].fileName );\n\t\tif ( !PlWriteFile( out, PlGetFileData( fp ), package->table[ i ].fileSize ) ) {\n\t\t\tError( \"Failed to write file, \\\"%s\\\" (%s)!\\n\", out, PlGetError() );\n\t\t}\n\t\tPlCloseFile( fp );\n\n\t\tconst char *ext = PlGetFileExtension( out );\n\t\tif ( strcmp( ext, \"tim\" ) == 0 ) {\n\t\t\tConvertImageToPng( out );\n\t\t}\n\t}\n\n\tPlDestroyPackage( package );\n}\n\n/************************************************************/\n/* Texture Merger */\n\ntypedef struct TextureMerge {\n\tconst char *output;\n\tunsigned int num_textures;\n\tunsigned int width, height;\n\tstruct {\n\t\tconst char *path;\n\t\tunsigned int x, y;\n\t} targets[ 10 ];\n} TextureMerge;\nstatic TextureMerge texture_targets[] = {\n        { \"/mods/how/frontend/dash/ang.png\", 5, 152, 121, { { \"/mods/how/frontend/dash/ang1.png\", 0, 0 }, { \"/mods/how/frontend/dash/ang2.png\", 64, 22 }, { \"/mods/how/frontend/dash/ang3.png\", 0, 64 }, { \"/mods/how/frontend/dash/ang4.png\", 64, 64 }, { \"/mods/how/frontend/dash/ang5.png\", 128, 31 } } },\n\n        { \"/mods/how/frontend/dash/clock.png\", 4, 128, 96, { { \"/mods/how/frontend/dash/clock01.png\", 0, 0 }, { \"/mods/how/frontend/dash/clock02.png\", 64, 0 }, { \"/mods/how/frontend/dash/clock03.png\", 0, 28 }, { \"/mods/how/frontend/dash/clock04.png\", 64, 28 } } },\n\n        { \"/mods/how/frontend/dash/timer.png\", 10, 256, 32, { { \"/mods/how/frontend/dash/timer0.png\", 0, 0 }, { \"/mods/how/frontend/dash/timer1.png\", 24, 0 }, { \"/mods/how/frontend/dash/timer2.png\", 48, 0 }, { \"/mods/how/frontend/dash/timer3.png\", 72, 0 }, { \"/mods/how/frontend/dash/timer4.png\", 96, 0 }, { \"/mods/how/frontend/dash/timer5.png\", 120, 0 }, { \"/mods/how/frontend/dash/timer6.png\", 144, 0 }, { \"/mods/how/frontend/dash/timer7.png\", 168, 0 }, { \"/mods/how/frontend/dash/timer8.png\", 192, 0 }, { \"/mods/how/frontend/dash/timer9.png\", 216, 0 } } },\n\n        { \"/mods/how/frontend/dash/pause.png\", 8, 48, 48, { { \"/mods/how/frontend/dash/pause1.png\", 0, 0 }, { \"/mods/how/frontend/dash/pause2.png\", 16, 0 }, { \"/mods/how/frontend/dash/pause3.png\", 32, 0 }, { \"/mods/how/frontend/dash/pause4.png\", 0, 16 }, { \"/mods/how/frontend/dash/pause5.png\", 32, 16 }, { \"/mods/how/frontend/dash/pause6.png\", 0, 32 }, { \"/mods/how/frontend/dash/pause7.png\", 16, 32 }, { \"/mods/how/frontend/dash/pause8.png\", 32, 32 } } } };\n\nstatic void MergeTextureTargets( void ) {\n\tunsigned int num_texture_targets = PL_ARRAY_ELEMENTS( texture_targets );\n\tPrint( \"Merging %d texture targets...\\n\", num_texture_targets );\n\tfor ( unsigned int i = 0; i < num_texture_targets; ++i ) {\n\t\tTextureMerge *merge = &texture_targets[ i ];\n\t\tPrint( \"Generating %s\\n\", merge->output );\n\t\tPLImage *output = PlCreateImage( NULL, merge->width, merge->height, PL_COLOURFORMAT_RGBA, PL_IMAGEFORMAT_RGBA8 );\n\t\tif ( output == NULL ) {\n\t\t\tWarning( \"Failed to generate texture target (%s)!\\n\", PlGetError() );\n\t\t\tcontinue;\n\t\t}\n\n\t\tfor ( unsigned int j = 0; j < merge->num_textures; ++j ) {\n\t\t\tconst char *path = merge->targets[ j ].path;\n\t\t\tPLImage *image = PlLoadImage( path );\n\t\t\tif ( image == NULL ) {\n\t\t\t\tWarning( \"Failed to find image, \\\"%s\\\", for merge!\\n\", merge->targets[ j ].path );\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tPrint( \"Writing %s into %s\\n\", merge->targets[ j ].path, merge->output );\n\n\t\t\tuint8_t\n\t\t\t        *pos = output->data[ 0 ] + ( ( merge->targets[ j ].y * output->width ) + merge->targets[ j ].x ) * 4;\n\t\t\tuint8_t *src = image->data[ 0 ];\n\t\t\tfor ( unsigned int y = 0; y < image->height; ++y ) {\n\t\t\t\tmemcpy( pos, src, ( image->width * 4 ) );\n\t\t\t\tsrc += image->width * 4;\n\t\t\t\tpos += output->width * 4;\n\t\t\t}\n\n\t\t\tPlDestroyImage( image );\n\t\t\tPlDeleteFile( path );\n\t\t}\n\n\t\tPrint( \"Writing %s\\n\", merge->output );\n\t\tPlWriteImage( output, merge->output );\n\t\tPlDestroyImage( output );\n\t}\n}\n\n/************************************************************/\n\ntypedef struct IOPath {\n\tconst char *input, *output;\n} IOPath;\n\nstatic IOPath pc_music_paths[] = {\n#include \"pc_music_paths.h\"\n};\n\nstatic IOPath pc_copy_paths[] = {\n#include \"pc_copy_paths.h\"\n};\n\nstatic IOPath pc_package_paths[] = {\n#include \"pc_package_paths.h\"\n};\n\nstatic void ProcessPackagePaths( const char *in, const char *out, const IOPath *paths, unsigned int length ) {\n\tfor ( unsigned int i = 0; i < length; ++i ) {\n\t\tchar output_path[ PL_SYSTEM_MAX_PATH ];\n\t\tsnprintf( output_path, sizeof( output_path ), \"%s%s\", out, paths[ i ].output );\n\t\tif ( !PlCreatePath( output_path ) ) {\n\t\t\tWarning( \"%s\\n\", PlGetError() );\n\t\t\tcontinue;\n\t\t}\n\n\t\tchar input_path[ PL_SYSTEM_MAX_PATH ];\n\t\tsnprintf( input_path, sizeof( input_path ), \"%s%s\", in, paths[ i ].input );\n\t\tPrint( \"Copying %s to %s\\n\", input_path, output_path );\n\t\tconst char *ext = PlGetFileExtension( input_path );\n\t\tif ( pl_strncasecmp( ext, \"PTG\", 3 ) == 0 ) {\n\t\t\tExtractPtgPackage( input_path, output_path );\n\t\t} else {\n\t\t\tExtractMadPackage( input_path, output_path );\n\t\t}\n\t}\n}\n\nstatic void ProcessCopyPaths( const char *in, const char *out, const IOPath *paths, unsigned int length ) {\n\tfor ( unsigned int i = 0; i < length; ++i ) {\n\t\tchar output_path[ PL_SYSTEM_MAX_PATH ];\n\t\tsnprintf( output_path, sizeof( output_path ), \"%s%s\", out, paths[ i ].output );\n\n\t\t// Fudge the path if it's one of the audio tracks\n\t\tchar *p = strstr( output_path, \"sku1/\" );\n\t\tif ( p != NULL ) {\n\t\t\tstrncpy( p, region_idents[ version_info.region ], 3 );\n\t\t\tmemmove( p + 3, p + 4, strlen( p + 4 ) + 1 );\n\t\t}\n\n\t\tif ( !PlCreatePath( output_path ) ) {\n\t\t\tError( \"Failed to create path, \\\"%s\\\" (%s)!\\n\", output_path, PlGetError() );\n\t\t}\n\n\t\tstrncat( output_path, PlGetFileName( paths[ i ].input ), sizeof( output_path ) - strlen( output_path ) - 1 );\n\t\tpl_strtolower( output_path );\n\n\t\tchar input_path[ PL_SYSTEM_MAX_PATH ];\n\t\tsnprintf( input_path, sizeof( input_path ), \"%s%s\", in, paths[ i ].input );\n\t\tPrint( \"Copying %s to %s\\n\", input_path, output_path );\n\t\tPlCopyFile( input_path, output_path );\n\t}\n}\n\nunsigned int MSG_LVL_PRINT;\nunsigned int MSG_LVL_WARN;\nunsigned int MSG_LVL_ERR;\n\nint main( int argc, char **argv ) {\n\tif ( argc == 1 ) {\n\t\tprintf( \"Invalid number of arguments ...\\n\"\n\t\t        \"  extractor <game_path> -<out_path>\\n\" );\n\t\treturn EXIT_SUCCESS;\n\t}\n\n\tPlInitialize( argc, argv );\n\n\tPlRegisterStandardPackageLoaders();\n\tPlRegisterStandardImageLoaders( PL_IMAGE_FILEFORMAT_TIM | PL_IMAGE_FILEFORMAT_BMP | PL_IMAGE_FILEFORMAT_PNG );\n\n\tchar app_dir[ PL_SYSTEM_MAX_PATH ];\n\tPlGetApplicationDataDirectory( \"OpenHoW\", app_dir, PL_SYSTEM_MAX_PATH );\n\tif ( !PlCreatePath( app_dir ) ) {\n\t\tWarning( \"Unable to create %s: %s\\nSettings will not be saved.\", app_dir, PlGetError() );\n\t}\n\n\tchar log_path[ PL_SYSTEM_MAX_PATH ];\n\tsnprintf( log_path, PL_SYSTEM_MAX_PATH, \"%s/extractor\", app_dir );\n\tPlSetupLogOutput( log_path );\n\n\tMSG_LVL_PRINT = PlAddLogLevel( \"print\", PL_COLOUR_GREEN, true );\n\tMSG_LVL_WARN = PlAddLogLevel( \"warning\", PL_COLOUR_YELLOW, true );\n\tMSG_LVL_ERR = PlAddLogLevel( \"error\", PL_COLOUR_RED, true );\n\n\t/* now deal with any arguments */\n\n#if 0\n\tif(getcwd(output_path, sizeof(output_path) - 1) == NULL) {\n\t\tstrcpy(output_path, \"./\");\n\t}\n#else\n\tstrcpy( g_output_path, \"./\" );\n#endif\n\n\tfor ( int i = 1; i < argc; ++i ) {\n\t\tif ( argv[ i ][ 0 ] == '-' ) {\n\t\t\tstrncpy( g_output_path, argv[ i ] + 1, sizeof( g_output_path ) );\n\t\t} else {\n\t\t\tstrncpy( g_input_path, argv[ i ], sizeof( g_input_path ) );\n\t\t}\n\t}\n\n\tif ( *g_input_path == '\\0' ) {\n\t\tError( \"Empty game path, aborting!\\n\" );\n\t}\n\n\tPrint( \"\\n\"\n\t       \"output path: %s\\n\"\n\t       \"input path:  %s\\n\",\n\t       g_output_path, g_input_path );\n\n\t/* ensure it's a valid version - original CD version requires\n\t * us to extract audio from the CD while GOG and Steam versions\n\t * provide OGG audio.\n\t *\n\t * PSX is a totally different story, with it's own fun adventure. */\n\tCheckGameVersion( g_input_path );\n\tif ( version_info.region == REGION_UNKNOWN || version_info.platform == PLATFORM_UNKNOWN ) {\n\t\tError( \"Unknown game version, aborting!\\n\" );\n\t} else if ( version_info.platform == PLATFORM_PSX ) {\n\t\tError( \"Unsupported platform!\\n\" );\n\t}\n\n\tif ( version_info.platform == PLATFORM_PC || version_info.platform == PLATFORM_PC_DIGITAL ) {\n\t\tProcessPackagePaths( g_input_path, g_output_path, pc_package_paths, PL_ARRAY_ELEMENTS( pc_package_paths ) );\n\t\tProcessCopyPaths( g_input_path, g_output_path, pc_copy_paths, PL_ARRAY_ELEMENTS( pc_copy_paths ) );\n\n\t\tif ( version_info.platform == PLATFORM_PC_DIGITAL ) {\n\t\t\t// They've done us the honors for the digital version\n\t\t\tProcessCopyPaths( g_input_path, g_output_path, pc_music_paths, PL_ARRAY_ELEMENTS( pc_music_paths ) );\n\t\t} else {\n\t\t\t// todo: rip the disc...\n\t\t}\n\t}\n\n\tMergeTextureTargets();\n\n\tConvertModelData();\n\n\tPrint( \"Complete!\\n\" );\n\treturn EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "src/extractor/extractor.h",
    "content": "/* OpenHoW\n * Copyright (C) 2017-2020 TalonBrave.info and Others (see CONTRIBUTORS)\n * Copyright (C) 2017 Daniel Collins <solemnwarning@solemnwarning.net>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#pragma once\n\n#include <plcore/pl_package.h>\n#include <plcore/pl_image.h>\n#include <plcore/pl_console.h>\n\nextern unsigned int MSG_LVL_PRINT;\nextern unsigned int MSG_LVL_WARN;\nextern unsigned int MSG_LVL_ERR;\n\n#define Print( ... )    PlLogMessage( MSG_LVL_PRINT, __VA_ARGS__ )\n#define Warning( ... )  PlLogMessage( MSG_LVL_WARN, __VA_ARGS__ )\n#define Error( ... )    PlLogMessage( MSG_LVL_ERR, __VA_ARGS__ ); exit( EXIT_FAILURE )\n\ntypedef enum ERegion {\n\tREGION_UNKNOWN = -1,\n\n\tREGION_ENG,\n\tREGION_FRE,\n\tREGION_GER,\n\tREGION_ITA,\n\tREGION_RUS,\n\tREGION_SPA,\n\n\tMAX_REGIONS\n} ERegion;\nextern const char *region_idents[MAX_REGIONS];\n\ntypedef enum EPlatform {\n\tPLATFORM_UNKNOWN = -1,\n\tPLATFORM_PSX,               /* PSX version */\n\tPLATFORM_PC,                /* PC version */\n\tPLATFORM_PC_DIGITAL,        /* PC/Digital version */\n} EPlatform;\n\ntypedef struct VersionInfo {\n\tERegion region;\n\tEPlatform platform;\n} VersionInfo;\nextern VersionInfo version_info;\n\nvoid CheckGameVersion( const char *path );\n"
  },
  {
    "path": "src/extractor/fac.c",
    "content": "/* OpenHoW\n * Copyright (C) 2017-2020 TalonBrave.info and Others (see CONTRIBUTORS)\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include \"extractor.h\"\n#include \"fac.h\"\n\n/************************************************************/\n/* Fac Triangle/Quad Faces Format */\n\ntypedef struct FacQuad {\n\tint8_t uv_coords[8];\n\tuint16_t vertex_indices[4];\n\tuint16_t normal_indices[4];\n\tuint32_t texture_index;\n\tuint16_t unknown[4];\n} FacQuad;\n\nstatic FacQuad *Fac_LoadQuads( PLFile *filePtr, unsigned int numQuads ) {\n\tbool status = false;\n\tFacQuad *quads = ( FacQuad * ) calloc( numQuads, sizeof( FacQuad ) );\n\tif ( quads == NULL ) {\n\t\tWarning( \"Failed to allocate quads array!\\n\" );\n\t\treturn NULL;\n\t}\n\n\tfor ( unsigned int i = 0; i < numQuads; ++i ) {\n\t\tfor ( unsigned int j = 0; j < 8; ++j ) {\n\t\t\tquads[ i ].uv_coords[ j ] = PlReadInt8( filePtr, &status );\n\t\t}\n\t\tfor ( unsigned int j = 0; j < 4; ++j ) {\n\t\t\tquads[ i ].vertex_indices[ j ] = PlReadInt16( filePtr, false, &status );\n\t\t}\n\t\tfor ( unsigned int j = 0; j < 4; ++j ) {\n\t\t\tquads[ i ].normal_indices[ j ] = PlReadInt16( filePtr, false, &status );\n\t\t}\n\t\tquads[ i ].texture_index = PlReadInt32( filePtr, false, &status );\n\t\tfor ( unsigned int j = 0; j < 4; ++j ) {\n\t\t\tquads[ i ].unknown[ j ] = PlReadInt16( filePtr, false, &status );\n\t\t}\n\t}\n\n\tif ( !status ) {\n\t\tfree( quads );\n\t\treturn NULL;\n\t}\n\n\treturn quads;\n}\n\nstatic FacTriangle *Fac_LoadTriangles( PLFile *filePtr, unsigned int numTriangles ) {\n\tbool status = false;\n\tFacTriangle *triangles = ( FacTriangle * ) calloc( numTriangles, sizeof( FacTriangle ) );\n\tif ( triangles == NULL ) {\n\t\tWarning( \"Failed to allocate triangle array!\\n\" );\n\t\treturn NULL;\n\t}\n\n\tfor ( unsigned int i = 0; i < numTriangles; ++i ) {\n\t\tfor ( unsigned int j = 0; j < 6; ++j ) {\n\t\t\ttriangles[ i ].uv_coords[ j ] = PlReadInt8( filePtr, &status );\n\t\t}\n\t\tfor ( unsigned int j = 0; j < 3; ++j ) {\n\t\t\ttriangles[ i ].vertex_indices[ j ] = PlReadInt16( filePtr, false, &status );\n\t\t}\n\t\tfor ( unsigned int j = 0; j < 3; ++j ) {\n\t\t\ttriangles[ i ].normal_indices[ j ] = PlReadInt16( filePtr, false, &status );\n\t\t}\n\t\ttriangles[ i ].unknown0 = PlReadInt16( filePtr, false, &status );\n\t\ttriangles[ i ].texture_index = PlReadInt32( filePtr, false, &status );\n\t\tfor ( unsigned int j = 0; j < 4; ++j ) {\n\t\t\ttriangles[ i ].unknown1[ j ] = PlReadInt16( filePtr, false, &status );\n\t\t}\n\t}\n\n\tif ( !status ) {\n\t\tfree( triangles );\n\t\treturn NULL;\n\t}\n\n\treturn triangles;\n}\n\nFacHandle *Fac_LoadFile( const char *path ) {\n\tPLFile *filePtr = PlOpenFile( path, false );\n\tif ( filePtr == NULL ) {\n\t\tWarning( \"Failed to load Fac \\\"%s\\\", aborting!\\nPL: %s\\n\", path, PlGetError() );\n\t\treturn NULL;\n\t}\n\n\t//LogDebug( \"Opened Fac \\\"%s\\\"...\\n\", plGetFilePath( filePtr ) );\n\n\t/* 16 bytes of unknown data, just skip it for now */\n\tif ( !PlFileSeek( filePtr, 16, PL_SEEK_CUR ) ) {\n\t\tPlCloseFile( filePtr );\n\n\t\tWarning( \"Failed to find data in Fac \\\"%s\\\"!\\nPL: %s\\n\", path, PlGetError() );\n\t\treturn NULL;\n\t}\n\n\tbool status;\n\tuint32_t numTriangles = PlReadInt32( filePtr, false, &status );\n\tFacTriangle *triangles = Fac_LoadTriangles( filePtr, numTriangles );\n\tif ( triangles == NULL && numTriangles > 0 ) {\n\t\tWarning( \"Failed to read in triangles, \\\"%s\\\"!\\nPL: %s\\n\", path, PlGetError() );\n\t\tPlCloseFile( filePtr );\n\t\treturn NULL;\n\t}\n\n\tuint32_t numQuads = PlReadInt32( filePtr, false, &status );\n\tFacQuad *quads = Fac_LoadQuads( filePtr, numQuads );\n\tif ( quads == NULL && numQuads > 0 ) {\n\t\tWarning( \"Failed to read in quads, \\\"%s\\\"!\\nPL: %s\\n\", path, PlGetError() );\n\t\tfree( triangles );\n\t\tPlCloseFile( filePtr );\n\t\treturn NULL;\n\t}\n\n\tif ( numQuads == 0 && numTriangles == 0 ) {\n\t\tWarning( \"Fac \\\"%s\\\" contains no quads or triangles!\\n\", path );\n\t}\n\n\t// check for textures table\n\tuint8_t num_textures = PlReadInt8( filePtr, &status );\n\tFacTextureIndex *texture_table = NULL;\n\tif ( num_textures > 0 ) {\n\t\ttexture_table = ( FacTextureIndex * ) calloc( num_textures, sizeof( FacTextureIndex ) );\n\t\tif ( texture_table == NULL ) {\n\t\t\tError( \"Failed to allocate texture table for \\\"%s\\\"!\\n\", path );\n\t\t}\n\t\tfor ( unsigned int i = 0; i < num_textures; ++i ) {\n\t\t\tPlReadFile( filePtr, texture_table[ i ].name, 1, sizeof( texture_table[ i ].name ) );\n\t\t}\n\t}\n\n\tPlCloseFile( filePtr );\n\n\tFacHandle *handle = ( FacHandle * ) calloc( 1, sizeof( FacHandle ) );\n\tif ( handle == NULL ) {\n\t\tError( \"Failed to allocate Fac handle for \\\"%s\\\"!\\n\", path );\n\t}\n\thandle->num_triangles = numTriangles + ( numQuads * 2 );\n\thandle->triangles = ( FacTriangle * ) calloc( handle->num_triangles, sizeof( FacTriangle ) );\n\tif ( handle->triangles == NULL ) {\n\t\tError( \"Failed to allocate triangle array for \\\"%s\\\"!\\n\", path );\n\t}\n\n\tfor ( unsigned int i = 0; i < numTriangles; ++i ) {\n\t\thandle->triangles[ i ].texture_index = triangles[ i ].texture_index;\n\t\tfor ( unsigned int j = 0, u = 0; j < 3; j++, u += 2 ) {\n\t\t\thandle->triangles[ i ].vertex_indices[ j ] = triangles[ i ].vertex_indices[ j ];\n\t\t\thandle->triangles[ i ].normal_indices[ j ] = triangles[ i ].normal_indices[ j ];\n\t\t\thandle->triangles[ i ].uv_coords[ u ] = triangles[ i ].uv_coords[ u ];\n\t\t\thandle->triangles[ i ].uv_coords[ u + 1 ] = triangles[ i ].uv_coords[ u + 1 ];\n\t\t}\n\t}\n\n\tfor ( unsigned int i = 0, tri = numTriangles; i < numQuads; ++i ) {\n\t\tint quad_to_tri[2][3] = {\n\t\t\t\t{ 0, 1, 2 },\n\t\t\t\t{ 2, 3, 0 },\n\t\t};\n\n\t\tfor ( int q = 0; q < 2; ++q, ++tri ) {\n\t\t\tint *q2t = quad_to_tri[ q ];\n\n\t\t\thandle->triangles[ tri ].texture_index = quads[ i ].texture_index;\n\t\t\tfor ( unsigned int j = 0; j < 3; j++ ) {\n\t\t\t\thandle->triangles[ tri ].vertex_indices[ j ] = quads[ i ].vertex_indices[ q2t[ j ] ];\n\t\t\t\thandle->triangles[ tri ].normal_indices[ j ] = quads[ i ].normal_indices[ q2t[ j ] ];\n\t\t\t\t// todo\n\t\t\t\thandle->triangles[ tri ].uv_coords[ j * 2 ] = quads[ i ].uv_coords[ q2t[ j ] * 2 ];\n\t\t\t\thandle->triangles[ tri ].uv_coords[ j * 2 + 1 ] = quads[ i ].uv_coords[ q2t[ j ] * 2 + 1 ];\n\t\t\t}\n\t\t}\n\t}\n\n\tif ( texture_table != NULL ) {\n\t\thandle->texture_table = texture_table;\n\t\thandle->texture_table_size = num_textures;\n\t}\n\n\treturn handle;\n}\n\nvoid Fac_WriteFile( FacHandle *handle, const char *path ) {\n\tFILE *fp = fopen( path, \"wb\" );\n\tif ( fp == NULL ) {\n\t\tWarning( \"Failed to open, \\\"%s\\\"!\\n\", path );\n\t\treturn;\n\t}\n\n\t// 16 bytes of unknown data, just skip it for now\n\tchar empty[16];\n\tmemset( empty, 0, sizeof( empty ) );\n\tfwrite( empty, sizeof( empty ), 1, fp );\n\n\t// write out the triangle data\n\tfwrite( &handle->num_triangles, sizeof( uint32_t ), 1, fp );\n\tstruct __attribute__((packed)) {\n\t\tint8_t uv_coords[6];\n\t\tuint16_t vertex_indices[3];\n\t\tuint16_t normal_indices[3];\n\t\tuint16_t unknown0;\n\t\tuint32_t texture_index;\n\t\tuint16_t unknown1[4];\n\t} triangles[handle->num_triangles];\n\tmemset( triangles, 0, sizeof( *triangles ) * handle->num_triangles );\n\tfor ( unsigned int i = 0; i < handle->num_triangles; ++i ) {\n\t\ttriangles[ i ].texture_index = handle->triangles[ i ].texture_index;\n\t\tfor ( unsigned int j = 0; j < 3; ++j ) {\n\t\t\ttriangles[ i ].vertex_indices[ j ] = handle->triangles[ i ].vertex_indices[ j ];\n\t\t\ttriangles[ i ].normal_indices[ j ] = handle->triangles[ i ].normal_indices[ j ];\n\t\t}\n\t\tfor ( unsigned int j = 0; j < 6; ++j ) {\n\t\t\ttriangles[ i ].uv_coords[ j ] = handle->triangles[ i ].uv_coords[ j ];\n\t\t}\n\t}\n\tfwrite( triangles, sizeof( *triangles ), handle->num_triangles, fp );\n\n\t// we won't write any quads, so just mark it as 0\n\tuint32_t quads = 0;\n\tfwrite( &quads, sizeof( uint32_t ), 1, fp );\n\n\t// now write the string table\n\tif ( handle->texture_table_size > 0 ) {\n\t\tfwrite( &handle->texture_table_size, sizeof( uint8_t ), 1, fp );\n\t\tfor ( unsigned int i = 0; i < handle->texture_table_size; ++i ) {\n\t\t\tfwrite( handle->texture_table[ i ].name, 1, 16, fp );\n\t\t}\n\t}\n\n\t// Done!\n\tfclose( fp );\n}\n\nvoid Fac_DestroyHandle( FacHandle *handle ) {\n\tif ( handle == NULL ) {\n\t\treturn;\n\t}\n\n\tfree( handle->triangles );\n\tfree( handle->texture_table );\n\tfree( handle );\n}\n"
  },
  {
    "path": "src/extractor/fac.h",
    "content": "/* OpenHoW\n * Copyright (C) 2017-2020 TalonBrave.info and Others (see CONTRIBUTORS)\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#pragma once\n\nPL_EXTERN_C\n\ntypedef struct FacTriangle {\n\tint8_t uv_coords[6];\n\tuint16_t vertex_indices[3];\n\tuint16_t normal_indices[3];\n\tuint16_t unknown0;\n\tuint32_t texture_index;\n\tuint16_t unknown1[4];\n} FacTriangle;\n\ntypedef struct FacTextureIndex {\n\tchar name[16];\n} FacTextureIndex;\n\ntypedef struct FacHandle {\n\tFacTriangle *triangles;\n\tunsigned int num_triangles;\n\n\tstruct FacTextureIndex *texture_table;\n\tunsigned int texture_table_size;\n} FacHandle;\n\nFacHandle *Fac_LoadFile( const char *path );\nvoid Fac_WriteFile( FacHandle *handle, const char *path );\nvoid Fac_DestroyHandle( FacHandle *handle );\n\nPL_EXTERN_C_END\n"
  },
  {
    "path": "src/extractor/pc_copy_paths.h",
    "content": "/* OpenHoW\n * Copyright (C) 2017-2020 TalonBrave.info and Others (see CONTRIBUTORS)\n * Copyright (C) 2017 Daniel Collins <solemnwarning@solemnwarning.net>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n{\n\"/FEText/BIG.tab\", \"/mods/how/frontend/text/\"},\n{\n\"/FEText/BigChars.tab\", \"/mods/how/frontend/text/\"},\n{\n\"/FEText/chars3.tab\", \"/mods/how/frontend/text/\"},\n{\n\"/FEText/CHARS2.tab\", \"/mods/how/frontend/text/\"},\n{\n\"/FEText/GameChars.tab\", \"/mods/how/frontend/text/\"},\n{\n\"/FEText/SMALL.tab\", \"/mods/how/frontend/text/\"},\n{\n\"/FEText/BIG.BMP\", \"/mods/how/frontend/text/\"},\n{\n\"/FEText/BigChars.BMP\", \"/mods/how/frontend/text/\"},\n{\n\"/FEText/chars2D.bmp\", \"/mods/how/frontend/text/\"},\n{\n\"/FEText/chars2L.bmp\", \"/mods/how/frontend/text/\"},\n{\n\"/FEText/Chars2.bmp\", \"/mods/how/frontend/text/\"},\n{\n\"/FEText/CHARS3.BMP\", \"/mods/how/frontend/text/\"},\n{\n\"/FEText/GameChars.bmp\", \"/mods/how/frontend/text/\"},\n{\n\"/FEText/SMALL.BMP\", \"/mods/how/frontend/text/\"},\n\n{\n\"/Language/Tims/Pigbkpc1.BMP\", \"/mods/how/frontend/\"},\n\n{\n\"/Language/Tims/loadmult.bmp\", \"/mods/how/frontend/briefing/\"},\n{\n\"/Language/Tims/Briefing/Level0.bmp\", \"/mods/how/frontend/briefing/\"},\n{\n\"/Language/Tims/Briefing/Level1.bmp\", \"/mods/how/frontend/briefing/\"},\n{\n\"/Language/Tims/Briefing/Level1n0.bmp\", \"/mods/how/frontend/briefing/\"},\n{\n\"/Language/Tims/Briefing/Level1n1.bmp\", \"/mods/how/frontend/briefing/\"},\n{\n\"/Language/Tims/Briefing/Level1n2.bmp\", \"/mods/how/frontend/briefing/\"},\n{\n\"/Language/Tims/Briefing/Level1n3.bmp\", \"/mods/how/frontend/briefing/\"},\n{\n\"/Language/Tims/Briefing/Level1n4.bmp\", \"/mods/how/frontend/briefing/\"},\n{\n\"/Language/Tims/Briefing/Level1n5.bmp\", \"/mods/how/frontend/briefing/\"},\n{\n\"/Language/Tims/Briefing/Level2.bmp\", \"/mods/how/frontend/briefing/\"},\n{\n\"/Language/Tims/Briefing/Level3.bmp\", \"/mods/how/frontend/briefing/\"},\n{\n\"/Language/Tims/Briefing/level4.bmp\", \"/mods/how/frontend/briefing/\"},\n{\n\"/Language/Tims/Briefing/Level5.bmp\", \"/mods/how/frontend/briefing/\"},\n{\n\"/Language/Tims/Briefing/level6.bmp\", \"/mods/how/frontend/briefing/\"},\n{\n\"/Language/Tims/Briefing/level7.bmp\", \"/mods/how/frontend/briefing/\"},\n{\n\"/Language/Tims/Briefing/level8.bmp\", \"/mods/how/frontend/briefing/\"},\n{\n\"/Language/Tims/Briefing/level9.bmp\", \"/mods/how/frontend/briefing/\"},\n{\n\"/Language/Tims/Briefing/level10.bmp\", \"/mods/how/frontend/briefing/\"},\n{\n\"/Language/Tims/Briefing/level11.bmp\", \"/mods/how/frontend/briefing/\"},\n{\n\"/Language/Tims/Briefing/level12.bmp\", \"/mods/how/frontend/briefing/\"},\n{\n\"/Language/Tims/Briefing/level13.bmp\", \"/mods/how/frontend/briefing/\"},\n{\n\"/Language/Tims/Briefing/level14.bmp\", \"/mods/how/frontend/briefing/\"},\n{\n\"/Language/Tims/Briefing/level15.bmp\", \"/mods/how/frontend/briefing/\"},\n{\n\"/Language/Tims/Briefing/level16.bmp\", \"/mods/how/frontend/briefing/\"},\n{\n\"/Language/Tims/Briefing/level17.bmp\", \"/mods/how/frontend/briefing/\"},\n{\n\"/Language/Tims/Briefing/level18.bmp\", \"/mods/how/frontend/briefing/\"},\n{\n\"/Language/Tims/Briefing/level19.bmp\", \"/mods/how/frontend/briefing/\"},\n{\n\"/Language/Tims/Briefing/level20.bmp\", \"/mods/how/frontend/briefing/\"},\n{\n\"/Language/Tims/Briefing/level21.bmp\", \"/mods/how/frontend/briefing/\"},\n{\n\"/Language/Tims/Briefing/level22.bmp\", \"/mods/how/frontend/briefing/\"},\n{\n\"/Language/Tims/Briefing/level23.bmp\", \"/mods/how/frontend/briefing/\"},\n{\n\"/Language/Tims/Briefing/level24.bmp\", \"/mods/how/frontend/briefing/\"},\n{\n\"/Language/Tims/Briefing/level25.bmp\", \"/mods/how/frontend/briefing/\"},\n\n{\n\"/Language/Tims/Title/ANY.bmp\", \"/mods/how/frontend/title/\"},\n{\n\"/Language/Tims/Title/Bruno1.bmp\", \"/mods/how/frontend/title/\"},\n{\n\"/Language/Tims/Title/KEY.bmp\", \"/mods/how/frontend/title/\"},\n{\n\"/Language/Tims/Title/PRESS.bmp\", \"/mods/how/frontend/title/\"},\n{\n\"/Language/Tims/Title/title.bmp\", \"/mods/how/frontend/title/\"},\n{\n\"/Language/Tims/Title/titlemon.bmp\", \"/mods/how/frontend/title/\"},\n\n//{\"/Language/Tims/Briefing/loadbar.bmp\", \"/mods/how/frontend/\"},  // we're not using this\n//{\"/Language/Tims/Debrief/deathm1.bmp\", \"/mods/how/frontend/debrief/\"},\n//{\"/Language/Tims/Debrief/deathm2.bmp\", \"/mods/how/frontend/debrief/\"},\n{\n\"/Language/Tims/Debrief/Facepc1.bmp\", \"/mods/how/frontend/debrief/\"},\n{\n\"/Language/Tims/Debrief/Facepc2.bmp\", \"/mods/how/frontend/debrief/\"},\n{\n\"/Language/Tims/Debrief/Facepc3.bmp\", \"/mods/how/frontend/debrief/\"},\n{\n\"/Language/Tims/Debrief/Facepc4.bmp\", \"/mods/how/frontend/debrief/\"},\n{\n\"/Language/Tims/Debrief/Facepc5.bmp\", \"/mods/how/frontend/debrief/\"},\n{\n\"/Language/Tims/Debrief/Facepc6.bmp\", \"/mods/how/frontend/debrief/\"},\n{\n\"/Language/Tims/Debrief/Facepc7.bmp\", \"/mods/how/frontend/debrief/\"},\n{\n\"/Language/Tims/Debrief/Facepc8.bmp\", \"/mods/how/frontend/debrief/\"},\n{\n\"/Language/Tims/Debrief/Facepc9.bmp\", \"/mods/how/frontend/debrief/\"},\n{\n\"/Language/Tims/Debrief/facepcw1.bmp\", \"/mods/how/frontend/debrief/\"},\n{\n\"/Language/Tims/Debrief/facepcw2.bmp\", \"/mods/how/frontend/debrief/\"},\n{\n\"/Language/Tims/Debrief/facepcw3.bmp\", \"/mods/how/frontend/debrief/\"},\n{\n\"/Language/Tims/Debrief/facepcw4.bmp\", \"/mods/how/frontend/debrief/\"},\n{\n\"/Language/Tims/Debrief/facepcw5.bmp\", \"/mods/how/frontend/debrief/\"},\n{\n\"/Language/Tims/Debrief/facepcw6.bmp\", \"/mods/how/frontend/debrief/\"},\n{\n\"/Language/Tims/Debrief/facepcw7.bmp\", \"/mods/how/frontend/debrief/\"},\n{\n\"/Language/Tims/Debrief/facepcw8.bmp\", \"/mods/how/frontend/debrief/\"},\n{\n\"/Language/Tims/Debrief/facepcw9.bmp\", \"/mods/how/frontend/debrief/\"},\n//{\"/Language/Tims/Debrief/Hgren.BMP\", \"/mods/how/frontend/debrief/\"},\n//{\"/Language/Tims/Debrief/Hpara.BMP\", \"/mods/how/frontend/debrief/\"},\n{\n\"/Language/Tims/Debrief/pcCmmndo.bmp\", \"/mods/how/frontend/debrief/\"},\n{\n\"/Language/Tims/Debrief/pcEngine.bmp\", \"/mods/how/frontend/debrief/\"},\n{\n\"/Language/Tims/Debrief/pcGrenad.BMP\", \"/mods/how/frontend/debrief/\"},\n{\n\"/Language/Tims/Debrief/pcHeavy.bmp\", \"/mods/how/frontend/debrief/\"},\n{\n\"/Language/Tims/Debrief/pcLegend.bmp\", \"/mods/how/frontend/debrief/\"},\n{\n\"/Language/Tims/Debrief/pcMedic.bmp\", \"/mods/how/frontend/debrief/\"},\n{\n\"/Language/Tims/Debrief/pcParatr.bmp\", \"/mods/how/frontend/debrief/\"},\n{\n\"/Language/Tims/Debrief/pcPip1.bmp\", \"/mods/how/frontend/debrief/\"},\n{\n\"/Language/Tims/Debrief/pcPip2.bmp\", \"/mods/how/frontend/debrief/\"},\n{\n\"/Language/Tims/Debrief/pcSniper.bmp\", \"/mods/how/frontend/debrief/\"},\n{\n\"/Language/Tims/Debrief/r_i_p.bmp\", \"/mods/how/frontend/debrief/\"},\n{\n\"/Language/Tims/Debrief/unifeng.bmp\", \"/mods/how/frontend/debrief/\"},\n{\n\"/Language/Tims/Debrief/uniffren.bmp\", \"/mods/how/frontend/debrief/\"},\n{\n\"/Language/Tims/Debrief/unifgerm.bmp\", \"/mods/how/frontend/debrief/\"},\n{\n\"/Language/Tims/Debrief/unifjap.bmp\", \"/mods/how/frontend/debrief/\"},\n{\n\"/Language/Tims/Debrief/uniflard.bmp\", \"/mods/how/frontend/debrief/\"},\n{\n\"/Language/Tims/Debrief/unifruss.bmp\", \"/mods/how/frontend/debrief/\"},\n{\n\"/Language/Tims/Debrief/unifusa.bmp\", \"/mods/how/frontend/debrief/\"},\n\n{\n\"/Language/Tims/Papers/American.bmp\", \"/mods/how/frontend/papers/\"},\n{\n\"/Language/Tims/Papers/British.bmp\", \"/mods/how/frontend/papers/\"},\n{\n\"/Language/Tims/Papers/French.bmp\", \"/mods/how/frontend/papers/\"},\n{\n\"/Language/Tims/Papers/German.bmp\", \"/mods/how/frontend/papers/\"},\n{\n\"/Language/Tims/Papers/Japan.bmp\", \"/mods/how/frontend/papers/\"},\n{\n\"/Language/Tims/Papers/Russian.bmp\", \"/mods/how/frontend/papers/\"},\n{\n\"/Language/Tims/Papers/teamlard.bmp\", \"/mods/how/frontend/papers/\"},\n\n{\n\"/Language/Streams/FMV 01.bik\", \"/mods/how/streams/\"},\n{\n\"/Language/Streams/FMV 02.bik\", \"/mods/how/streams/\"},\n{\n\"/Language/Streams/FMV 03.bik\", \"/mods/how/streams/\"},\n{\n\"/Language/Streams/FMV 04.bik\", \"/mods/how/streams/\"},\n{\n\"/Language/Streams/FMV 05.bik\", \"/mods/how/streams/\"},\n{\n\"/Language/Streams/FMV 06.bik\", \"/mods/how/streams/\"},\n{\n\"/Language/Streams/FMV 07.bik\", \"/mods/how/streams/\"},\n{\n\"/Language/Streams/FMV 08.bik\", \"/mods/how/streams/\"},\n{\n\"/Language/Streams/FMV 09.bik\", \"/mods/how/streams/\"},\n{\n\"/Language/Streams/InfoLogo.bik\", \"/mods/how/streams/\"},\n{\n\"/Language/Streams/Sheff.bik\", \"/mods/how/streams/\"},\n\n/* misc */\n{\n\"/Language/Tims/Mine.tim\", \"/mods/how/textures/\"},\n{\n\"/Language/Tims/wat01.TIM\", \"/mods/how/textures/\"},\n{\n\"/Language/Tims/wat02.tim\", \"/mods/how/textures/\"},\n\n/* maps */\n{\n\"/Maps/BAY.PMG\", \"/mods/how/maps/bay/\"},\n{\n\"/Maps/ICE.PMG\", \"/mods/how/maps/ice/\"},\n{\n\"/Maps/BOOM.PMG\", \"/mods/how/maps/boom/\"},\n{\n\"/Maps/BUTE.PMG\", \"/mods/how/maps/bute/\"},\n{\n\"/Maps/CAMP.PMG\", \"/mods/how/maps/camp/\"},\n{\n\"/Maps/DEMO.PMG\", \"/mods/how/maps/demo/\"},\n{\n\"/Maps/DEVI.PMG\", \"/mods/how/maps/devi/\"},\n{\n\"/Maps/DVAL.PMG\", \"/mods/how/maps/dval/\"},\n{\n\"/Maps/EASY.PMG\", \"/mods/how/maps/easy/\"},\n{\n\"/Maps/ESTU.PMG\", \"/mods/how/maps/estu/\"},\n{\n\"/Maps/FOOT.PMG\", \"/mods/how/maps/foot/\"},\n{\n\"/Maps/GUNS.PMG\", \"/mods/how/maps/guns/\"},\n{\n\"/Maps/KEEP.PMG\", \"/mods/how/maps/keep/\"},\n{\n\"/Maps/LAKE.PMG\", \"/mods/how/maps/lake/\"},\n{\n\"/Maps/MAZE.PMG\", \"/mods/how/maps/maze/\"},\n{\n\"/Maps/ROAD.PMG\", \"/mods/how/maps/road/\"},\n{\n\"/Maps/TWIN.PMG\", \"/mods/how/maps/twin/\"},\n{\n\"/Maps/ARCHI.PMG\", \"/mods/how/maps/archi/\"},\n{\n\"/Maps/BHILL.PMG\", \"/mods/how/maps/bhill/\"},\n{\n\"/Maps/CMASS.PMG\", \"/mods/how/maps/cmass/\"},\n{\n\"/Maps/DBOWL.PMG\", \"/mods/how/maps/dbowl/\"},\n{\n\"/Maps/DEMO2.PMG\", \"/mods/how/maps/demo2/\"},\n{\n\"/Maps/DVAL2.PMG\", \"/mods/how/maps/dval2/\"},\n{\n\"/Maps/EYRIE.PMG\", \"/mods/how/maps/eyrie/\"},\n{\n\"/Maps/FINAL.PMG\", \"/mods/how/maps/final/\"},\n{\n\"/Maps/HELL2.PMG\", \"/mods/how/maps/hell2/\"},\n{\n\"/Maps/HELL3.PMG\", \"/mods/how/maps/hell3/\"},\n{\n\"/Maps/MEDIX.PMG\", \"/mods/how/maps/medix/\"},\n{\n\"/Maps/MLAKE.PMG\", \"/mods/how/maps/mlake/\"},\n{\n\"/Maps/OASIS.PMG\", \"/mods/how/maps/oasis/\"},\n{\n\"/Maps/PLAY1.PMG\", \"/mods/how/maps/play1/\"},\n{\n\"/Maps/PLAY2.PMG\", \"/mods/how/maps/play2/\"},\n{\n\"/Maps/RIDGE.PMG\", \"/mods/how/maps/ridge/\"},\n{\n\"/Maps/SNAKE.PMG\", \"/mods/how/maps/snake/\"},\n{\n\"/Maps/ZULUS.PMG\", \"/mods/how/maps/zulus/\"},\n{\n\"/Maps/ARTGUN.PMG\", \"/mods/how/maps/artgun/\"},\n{\n\"/Maps/BRIDGE.PMG\", \"/mods/how/maps/bridge/\"},\n{\n\"/Maps/DESVAL.PMG\", \"/mods/how/maps/desval/\"},\n{\n\"/Maps/FJORDS.PMG\", \"/mods/how/maps/fjords/\"},\n{\n\"/Maps/GENMUD.PMG\", \"/mods/how/maps/genmud/\"},\n{\n\"/Maps/ISLAND.PMG\", \"/mods/how/maps/island/\"},\n{\n\"/Maps/LUNAR1.PMG\", \"/mods/how/maps/lunar1/\"},\n{\n\"/Maps/MASHED.PMG\", \"/mods/how/maps/mashed/\"},\n{\n\"/Maps/ONEWAY.PMG\", \"/mods/how/maps/oneway/\"},\n{\n\"/Maps/RUMBLE.PMG\", \"/mods/how/maps/rumble/\"},\n{\n\"/Maps/SEPIA1.PMG\", \"/mods/how/maps/sepia1/\"},\n{\n\"/Maps/SNIPER.PMG\", \"/mods/how/maps/sniper/\"},\n{\n\"/Maps/TRENCH.PMG\", \"/mods/how/maps/trench/\"},\n{\n\"/Maps/CREEPY2.PMG\", \"/mods/how/maps/creepy2/\"},\n{\n\"/Maps/EMPLACE.PMG\", \"/mods/how/maps/emplace/\"},\n{\n\"/Maps/GENLAVA.PMG\", \"/mods/how/maps/genlava/\"},\n{\n\"/Maps/GENSNOW.PMG\", \"/mods/how/maps/gensnow/\"},\n{\n\"/Maps/ICEFLOW.PMG\", \"/mods/how/maps/iceflow/\"},\n{\n\"/Maps/LECPROD.PMG\", \"/mods/how/maps/lecprod/\"},\n{\n\"/Maps/SUPLINE.PMG\", \"/mods/how/maps/supline/\"},\n{\n\"/Maps/GENBRACK.PMG\", \"/mods/how/maps/genbrack/\"},\n{\n\"/Maps/GENCHALK.PMG\", \"/mods/how/maps/genchalk/\"},\n{\n\"/Maps/GENDESRT.PMG\", \"/mods/how/maps/gendesrt/\"},\n{\n\"/Maps/HILLBASE.PMG\", \"/mods/how/maps/hillbase/\"},\n{\n\"/Maps/LIBERATE.PMG\", \"/mods/how/maps/liberate/\"},\n{\n\"/Maps/TESTER.PMG\", \"/mods/how/maps/tester/\"},\n#if 0\n{\"/Maps/BAY.PTG\", \"/mods/how/maps/bay/\"},\n{\"/Maps/ICE.PTG\", \"/mods/how/maps/ice/\"},\n{\"/Maps/BOOM.PTG\", \"/mods/how/maps/boom/\"},\n{\"/Maps/BUTE.PTG\", \"/mods/how/maps/bute/\"},\n{\"/Maps/CAMP.PTG\", \"/mods/how/maps/camp/\"},\n{\"/Maps/DEMO.PTG\", \"/mods/how/maps/demo/\"},\n{\"/Maps/DEVI.PTG\", \"/mods/how/maps/devi/\"},\n{\"/Maps/DVAL.PTG\", \"/mods/how/maps/dval/\"},\n{\"/Maps/EASY.PTG\", \"/mods/how/maps/easy/\"},\n{\"/Maps/ESTU.PTG\", \"/mods/how/maps/estu/\"},\n{\"/Maps/FOOT.PTG\", \"/mods/how/maps/foot/\"},\n{\"/Maps/GUNS.PTG\", \"/mods/how/maps/guns/\"},\n{\"/Maps/KEEP.PTG\", \"/mods/how/maps/keep/\"},\n{\"/Maps/LAKE.PTG\", \"/mods/how/maps/lake/\"},\n{\"/Maps/MAZE.PTG\", \"/mods/how/maps/maze/\"},\n{\"/Maps/ROAD.PTG\", \"/mods/how/maps/road/\"},\n{\"/Maps/TWIN.PTG\", \"/mods/how/maps/twin/\"},\n{\"/Maps/ARCHI.PTG\", \"/mods/how/maps/archi/\"},\n{\"/Maps/BHILL.PTG\", \"/mods/how/maps/bhill/\"},\n{\"/Maps/CMASS.PTG\", \"/mods/how/maps/cmass/\"},\n{\"/Maps/DBOWL.PTG\", \"/mods/how/maps/dbowl/\"},\n{\"/Maps/DEMO2.PTG\", \"/mods/how/maps/demo2/\"},\n{\"/Maps/DVAL2.PTG\", \"/mods/how/maps/dval2/\"},\n{\"/Maps/EYRIE.PTG\", \"/mods/how/maps/eyrie/\"},\n{\"/Maps/FINAL.PTG\", \"/mods/how/maps/final/\"},\n{\"/Maps/HELL2.PTG\", \"/mods/how/maps/hell2/\"},\n{\"/Maps/HELL3.PTG\", \"/mods/how/maps/hell3/\"},\n{\"/Maps/MEDIX.PTG\", \"/mods/how/maps/medix/\"},\n{\"/Maps/MLAKE.PTG\", \"/mods/how/maps/mlake/\"},\n{\"/Maps/OASIS.PTG\", \"/mods/how/maps/oasis/\"},\n{\"/Maps/PLAY1.PTG\", \"/mods/how/maps/play1/\"},\n{\"/Maps/PLAY2.PTG\", \"/mods/how/maps/play2/\"},\n{\"/Maps/RIDGE.PTG\", \"/mods/how/maps/ridge/\"},\n{\"/Maps/SNAKE.PTG\", \"/mods/how/maps/snake/\"},\n{\"/Maps/ZULUS.PTG\", \"/mods/how/maps/zulus/\"},\n{\"/Maps/ARTGUN.PTG\", \"/mods/how/maps/artgun/\"},\n{\"/Maps/BRIDGE.PTG\", \"/mods/how/maps/bridge/\"},\n{\"/Maps/DESVAL.PTG\", \"/mods/how/maps/desval/\"},\n{\"/Maps/FJORDS.PTG\", \"/mods/how/maps/fjords/\"},\n{\"/Maps/GENMUD.PTG\", \"/mods/how/maps/genmud/\"},\n{\"/Maps/ISLAND.PTG\", \"/mods/how/maps/island/\"},\n{\"/Maps/LUNAR1.PTG\", \"/mods/how/maps/lunar1/\"},\n{\"/Maps/MASHED.PTG\", \"/mods/how/maps/mashed/\"},\n{\"/Maps/ONEWAY.PTG\", \"/mods/how/maps/oneway/\"},\n{\"/Maps/RUMBLE.PTG\", \"/mods/how/maps/rumble/\"},\n{\"/Maps/SEPIA1.PTG\", \"/mods/how/maps/sepia1/\"},\n{\"/Maps/SNIPER.PTG\", \"/mods/how/maps/sniper/\"},\n{\"/Maps/TRENCH.PTG\", \"/mods/how/maps/trench/\"},\n{\"/Maps/CREEPY2.PTG\", \"/mods/how/maps/creepy2/\"},\n{\"/Maps/EMPLACE.PTG\", \"/mods/how/maps/emplace/\"},\n{\"/Maps/GENLAVA.PTG\", \"/mods/how/maps/genlava/\"},\n{\"/Maps/GENSNOW.PTG\", \"/mods/how/maps/gensnow/\"},\n{\"/Maps/ICEFLOW.PTG\", \"/mods/how/maps/iceflow/\"},\n{\"/Maps/LECPROD.PTG\", \"/mods/how/maps/lecprod/\"},\n{\"/Maps/SUPLINE.PTG\", \"/mods/how/maps/supline/\"},\n{\"/Maps/genbrack.ptg\", \"/mods/how/maps/genbrack/\"},\n{\"/Maps/GENCHALK.PTG\", \"/mods/how/maps/genchalk/\"},\n{\"/Maps/GENDESRT.PTG\", \"/mods/how/maps/gendesrt/\"},\n{\"/Maps/HILLBASE.PTG\", \"/mods/how/maps/hillbase/\"},\n{\"/Maps/LIBERATE.PTG\", \"/mods/how/maps/liberate/\"},\n{\"/Maps/TESTER.PTG\", \"/mods/how/maps/tester/\"},\n#endif\n{\n\"/Maps/BAY.POG\", \"/mods/how/maps/bay/\"},\n{\n\"/Maps/ICE.POG\", \"/mods/how/maps/ice/\"},\n{\n\"/Maps/BOOM.POG\", \"/mods/how/maps/boom/\"},\n{\n\"/Maps/BUTE.POG\", \"/mods/how/maps/bute/\"},\n{\n\"/Maps/CAMP.POG\", \"/mods/how/maps/camp/\"},\n{\n\"/Maps/DEMO.POG\", \"/mods/how/maps/demo/\"},\n{\n\"/Maps/DEVI.POG\", \"/mods/how/maps/devi/\"},\n{\n\"/Maps/DVAL.POG\", \"/mods/how/maps/dval/\"},\n{\n\"/Maps/EASY.POG\", \"/mods/how/maps/easy/\"},\n{\n\"/Maps/ESTU.POG\", \"/mods/how/maps/estu/\"},\n{\n\"/Maps/FOOT.POG\", \"/mods/how/maps/foot/\"},\n{\n\"/Maps/GUNS.POG\", \"/mods/how/maps/guns/\"},\n{\n\"/Maps/KEEP.POG\", \"/mods/how/maps/keep/\"},\n{\n\"/Maps/LAKE.POG\", \"/mods/how/maps/lake/\"},\n{\n\"/Maps/MAZE.POG\", \"/mods/how/maps/maze/\"},\n{\n\"/Maps/ROAD.POG\", \"/mods/how/maps/road/\"},\n{\n\"/Maps/TWIN.POG\", \"/mods/how/maps/twin/\"},\n{\n\"/Maps/ARCHI.POG\", \"/mods/how/maps/archi/\"},\n{\n\"/Maps/BHILL.POG\", \"/mods/how/maps/bhill/\"},\n{\n\"/Maps/CMASS.POG\", \"/mods/how/maps/cmass/\"},\n{\n\"/Maps/DBOWL.POG\", \"/mods/how/maps/dbowl/\"},\n{\n\"/Maps/DEMO2.POG\", \"/mods/how/maps/demo2/\"},\n{\n\"/Maps/DVAL2.POG\", \"/mods/how/maps/dval2/\"},\n{\n\"/Maps/EYRIE.POG\", \"/mods/how/maps/eyrie/\"},\n{\n\"/Maps/FINAL.POG\", \"/mods/how/maps/final/\"},\n{\n\"/Maps/HELL2.POG\", \"/mods/how/maps/hell2/\"},\n{\n\"/Maps/HELL3.POG\", \"/mods/how/maps/hell3/\"},\n{\n\"/Maps/MEDIX.POG\", \"/mods/how/maps/medix/\"},\n{\n\"/Maps/MLAKE.POG\", \"/mods/how/maps/mlake/\"},\n{\n\"/Maps/OASIS.POG\", \"/mods/how/maps/oasis/\"},\n{\n\"/Maps/PLAY1.POG\", \"/mods/how/maps/play1/\"},\n{\n\"/Maps/PLAY2.POG\", \"/mods/how/maps/play2/\"},\n{\n\"/Maps/RIDGE.POG\", \"/mods/how/maps/ridge/\"},\n{\n\"/Maps/SNAKE.POG\", \"/mods/how/maps/snake/\"},\n{\n\"/Maps/ZULUS.POG\", \"/mods/how/maps/zulus/\"},\n{\n\"/Maps/ARTGUN.POG\", \"/mods/how/maps/artgun/\"},\n{\n\"/Maps/BRIDGE.POG\", \"/mods/how/maps/bridge/\"},\n{\n\"/Maps/DESVAL.POG\", \"/mods/how/maps/desval/\"},\n{\n\"/Maps/FJORDS.POG\", \"/mods/how/maps/fjords/\"},\n{\n\"/Maps/GENMUD.POG\", \"/mods/how/maps/genmud/\"},\n{\n\"/Maps/ISLAND.POG\", \"/mods/how/maps/island/\"},\n{\n\"/Maps/LUNAR1.POG\", \"/mods/how/maps/lunar1/\"},\n{\n\"/Maps/MASHED.POG\", \"/mods/how/maps/mashed/\"},\n{\n\"/Maps/ONEWAY.POG\", \"/mods/how/maps/oneway/\"},\n{\n\"/Maps/RUMBLE.POG\", \"/mods/how/maps/rumble/\"},\n{\n\"/Maps/SEPIA1.POG\", \"/mods/how/maps/sepia1/\"},\n{\n\"/Maps/SNIPER.POG\", \"/mods/how/maps/sniper/\"},\n{\n\"/Maps/TRENCH.POG\", \"/mods/how/maps/trench/\"},\n{\n\"/Maps/CREEPY2.POG\", \"/mods/how/maps/creepy2/\"},\n{\n\"/Maps/EMPLACE.POG\", \"/mods/how/maps/emplace/\"},\n{\n\"/Maps/GENLAVA.POG\", \"/mods/how/maps/genlava/\"},\n{\n\"/Maps/GENSNOW.POG\", \"/mods/how/maps/gensnow/\"},\n{\n\"/Maps/ICEFLOW.POG\", \"/mods/how/maps/iceflow/\"},\n{\n\"/Maps/LECPROD.POG\", \"/mods/how/maps/lecprod/\"},\n{\n\"/Maps/SUPLINE.POG\", \"/mods/how/maps/supline/\"},\n{\n\"/Maps/GENBRACK.POG\", \"/mods/how/maps/genbrack/\"},\n{\n\"/Maps/GENCHALK.POG\", \"/mods/how/maps/genchalk/\"},\n{\n\"/Maps/GENDESRT.POG\", \"/mods/how/maps/gendesrt/\"},\n{\n\"/Maps/HILLBASE.POG\", \"/mods/how/maps/hillbase/\"},\n{\n\"/Maps/LIBERATE.POG\", \"/mods/how/maps/liberate/\"},\n{\n\"/Maps/TESTER.POG\", \"/mods/how/maps/tester/\"},\n\n/* chars */\n{\n\"/Chars/pig.HIR\", \"/mods/how/chars/\"},\n{\n\"/Chars/mcap.mad\", \"/mods/how/chars/\"},\n\n/* audio */\n{\n\"/Audio/AMB_1D.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/AMB_1N.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/AMB_2D.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/AMB_2N.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/BATT_L1.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/BATT_L2.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/BATT_L3.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/BATT_S1.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/BATT_S2.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/BATT_S3.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/BG_GAS.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/BG_PLANE.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/EN_BIP.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/EN_TANK.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/E_1.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/E_1000P.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/FT_GRASS.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/FT_ICE.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/FT_LAVA.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/FT_METAL.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/FT_MUD.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/FT_QUAG.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/FT_ROCK.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/FT_SAND.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/FT_SNOW.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/FT_STONE.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/FT_SWIM.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/FT_WATER.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/FT_WOOD.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/I_BUILD.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/I_BULIT1.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/I_METAL.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/I_PICKUP.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/I_SPLASH.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/I_STAB.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/I_SWMISS.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/I_SWORD.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/L_ARTIL.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/L_BAZOO.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/L_FLAME.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/L_HVYMG.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/L_MGUN.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/L_MINETR.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/L_MORT.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/L_PISTOL.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/L_RIFLE.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/L_ROC.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/L_SHOTG.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/P_BOUNCE.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/P_BREAT1.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/P_BREAT2.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/P_BRRR.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/P_BRUSH.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/P_BURP.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/P_BUSH.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/P_CHUTE.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/P_CHUTE1.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/P_CLAP.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/P_COUGH1.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/P_COWER1.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/P_COWER2.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/P_COWER3.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/P_DROWN.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/P_EXERT.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/P_FART1.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/P_FART2.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/P_FART3.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/P_FLAP1.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/P_HAND1.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/P_HEAL.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/P_HEAL1.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/P_HMMM.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/P_ITCH.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/P_LAND1.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/P_LAUGH1.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/P_LAUGH2.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/P_LAUGH3.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/P_MAD1.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/P_MAD2.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/P_MOAN.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/P_MUTTER.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/P_OWW.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/P_PANT.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/P_PUNCH.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/P_SICK.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/P_SIGH.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/P_SLIP.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/P_SNEEZE.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/P_SNIFF.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/P_SNORT1.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/P_SNORT2.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/P_SQUEA1.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/P_SQUEA2.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/P_WHIST1.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/P_WHISTL.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/P_WHOHO.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/P_WHOOPE.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/S_CLOCK.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/S_OPEN.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/S_SELECT.wav\", \"/mods/how/audio/\"},\n{\n\"/Audio/S_UNHOLS.wav\", \"/mods/how/audio/\"},\n\n{\n\"/Speech/Sku1/Pig01/01JA0105.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01EN0403.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01AM0204.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01AM0504.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01JA0404.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01AM0301.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01fr0503.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01ge0105.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01ge0405.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01JA0506.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01JA0504.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01fr0504.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01fr0506.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01fr0203.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01EN0204.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01AM0306.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01ge0501.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01AM0201.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01EN0206.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01EN0402.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01RU0301.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01ge0203.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01AM0101.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01ge0205.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01AM0505.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01fr0405.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01AM0405.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01fr0104.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01JA0102.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01ge0504.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01JA0106.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01fr0406.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01ge0201.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01ge0402.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01RU0406.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01RU0203.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01fr0301.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01ge0305.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01EN0503.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01ge0401.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01RU0306.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01JA0303.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01AM0406.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01EN0101.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01AM0402.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01JA0205.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01JA0104.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01EN0203.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01JA0304.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01AM0205.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01AM0403.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01RU0105.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01RU0106.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01fr0305.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01fr0403.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01ge0202.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01AM0104.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01AM0501.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01RU0302.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01fr0204.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01JA0201.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01RU0202.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01EN0302.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01RU0402.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01AM0106.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01RU0505.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01AM0305.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01ge0106.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01RU0501.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01AM0302.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01ge0506.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01RU0506.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01fr0105.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01EN0105.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01fr0306.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01RU0206.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01JA0206.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01JA0306.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01EN0103.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01JA0302.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01ge0404.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01fr0401.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01EN0303.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01RU0405.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01JA0203.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01ge0101.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01RU0305.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01ge0301.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01ge0502.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01ge0302.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01RU0103.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01JA0401.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01fr0404.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01EN0304.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01fr0206.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01JA0405.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01RU0205.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01EN0205.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01RU0401.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01fr0106.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01fr0501.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01fr0202.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01fr0205.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01ge0403.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01EN0201.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01RU0503.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01EN0504.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01AM0206.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01JA0503.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01ge0503.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01EN0301.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01fr0101.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01RU0104.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01RU0304.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01fr0502.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01JA0402.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01RU0102.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01ge0103.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01JA0305.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01AM0103.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01AM0506.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01JA0502.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01AM0303.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01AM0404.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01RU0502.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01JA0103.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01RU0101.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01ge0102.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01AM0401.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01fr0402.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01JA0403.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01JA0101.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01fr0304.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01EN0501.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01fr0505.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01EN0104.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01fr0201.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01AM0203.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01fr0302.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01EN0401.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01AM0304.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01RU0404.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01fr0103.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01EN0202.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01JA0301.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01EN0404.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01ge0204.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01EN0306.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01ge0304.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01ge0303.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01EN0506.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01ge0505.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01ge0206.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01EN0406.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01JA0202.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01RU0303.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01AM0202.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01EN0106.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01EN0305.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01RU0204.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01JA0505.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01JA0204.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01EN0505.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01EN0102.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01RU0403.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01AM0502.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01EN0502.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01ge0104.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01ge0406.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01RU0504.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01AM0503.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01JA0406.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01EN0405.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01ge0306.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01JA0501.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01AM0102.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01AM0105.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01fr0303.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01fr0102.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig01/01RU0201.wav\", \"/mods/how/speech/sku1/pig01/\" },\n{\n\"/Speech/Sku1/Pig03/03JA0101.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03GE0501.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03GE0103.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03JA0202.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03AM0506.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03GE0205.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03AM0402.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03AM0301.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03EN0201.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03JA0204.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03FR0501.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03FR0405.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03FR0306.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03GE0206.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03EN0306.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03FR0106.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03EN0504.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03JA0403.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03AM0305.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03FR0206.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03JA0303.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03RU0305.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03EN0301.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03GE0305.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03RU0402.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03AM0106.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03GE0105.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03RU0206.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03RU0506.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03GE0406.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03GE0502.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03EN0101.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03RU0505.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03JA0306.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03AM0202.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03GE0403.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03RU0104.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03GE0404.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03FR0403.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03RU0504.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03AM0206.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03AM0401.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03AM0502.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03JA0106.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03AM0505.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03GE0204.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03GE0503.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03AM0501.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03JA0102.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03RU0101.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03JA0405.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03EN0205.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03AM0204.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03FR0503.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03AM0102.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03FR0401.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03AM0203.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03AM0403.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03JA0203.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03FR0406.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03FR0402.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03AM0406.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03EN0305.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03EN0405.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03RU0303.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03JA0201.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03FR0102.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03JA0305.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03RU0403.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03GE0201.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03FR0303.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03AM0205.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03EN0203.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03AM0302.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03EN0403.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03JA0302.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03EN0401.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03GE0106.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03EN0502.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03FR0201.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03GE0505.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03RU0304.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03AM0104.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03FR0202.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03JA0304.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03AM0306.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03AM0405.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03FR0101.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03JA0104.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03JA0504.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03FR0302.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03RU0301.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03RU0306.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03RU0406.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03RU0401.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03EN0503.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03EN0202.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03JA0103.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03GE0102.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03EN0505.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03RU0204.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03RU0106.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03GE0401.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03RU0501.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03EN0103.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03EN0104.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03FR0205.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03FR0105.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03GE0302.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03EN0501.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03GE0504.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03AM0504.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03JA0503.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03AM0201.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03EN0106.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03EN0402.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03FR0301.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03RU0405.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03FR0505.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03AM0101.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03JA0501.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03JA0404.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03JA0406.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03EN0304.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03EN0204.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03GE0306.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03FR0305.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03AM0304.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03GE0202.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03JA0506.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03EN0302.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03RU0202.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03GE0303.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03RU0205.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03FR0506.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03RU0503.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03FR0103.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03EN0105.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03EN0506.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03RU0203.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03RU0502.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03RU0201.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03EN0303.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03GE0104.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03FR0404.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03AM0404.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03EN0404.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03AM0303.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03EN0406.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03RU0102.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03AM0503.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03JA0301.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03FR0204.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03AM0105.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03GE0304.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03JA0401.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03JA0206.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03JA0402.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03GE0405.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03JA0105.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03RU0302.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03FR0502.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03EN0102.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03JA0205.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03RU0105.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03RU0103.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03GE0101.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03GE0402.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03GE0506.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03RU0404.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03FR0504.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03FR0104.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03AM0103.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03FR0203.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03GE0203.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03GE0301.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03JA0505.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03FR0304.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03EN0206.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig03/03JA0502.wav\", \"/mods/how/speech/sku1/pig03/\" },\n{\n\"/Speech/Sku1/Pig08/08AM0302.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08RU0305.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08EN0401.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08JA0303.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08AM0504.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08FR0301.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08GE0303.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08GE0206.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08JA0401.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08JA0104.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08GE0202.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08AM0505.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08EN0306.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08EN0403.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08RU0206.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08JA0203.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08FR0401.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08JA0201.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08RU0501.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08RU0506.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08RU0503.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08AM0303.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08RU0505.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08FR0505.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08AM0105.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08GE0404.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08FR0503.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08JA0204.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08AM0101.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08AM0104.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08EN0301.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08FR0105.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08AM0503.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08JA0503.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08EN0206.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08FR0101.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08AM0404.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08RU0502.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08JA0404.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08RU0105.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08RU0102.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08EN0201.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08GE0302.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08EN0203.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08JA0505.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08EN0506.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08EN0402.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08RU0205.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08AM0405.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08GE0402.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08EN0405.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08JA0205.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08EN0406.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08GE0401.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08AM0501.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08GE0301.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08AM0306.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08AM0402.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08EN0304.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08EN0104.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08RU0101.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08GE0204.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08AM0102.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08EN0504.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08FR0203.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08RU0504.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08JA0504.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08GE0101.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08JA0304.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08FR0406.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08AM0406.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08JA0306.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08FR0305.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08RU0203.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08AM0106.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08RU0301.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08FR0501.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08GE0201.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08RU0404.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08FR0104.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08JA0405.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08GE0205.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08RU0302.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08EN0302.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08EN0106.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08FR0302.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08AM0506.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08FR0504.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08FR0403.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08RU0402.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08EN0105.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08EN0205.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08AM0301.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08RU0403.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08EN0103.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08GE0106.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08GE0405.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08GE0203.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08FR0405.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08FR0404.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08FR0304.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08JA0202.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08FR0103.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08FR0506.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08EN0305.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08JA0106.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08ge0305.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08RU0104.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08GE0104.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08EN0503.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08JA0103.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08JA0406.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08RU0406.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08EN0505.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08RU0401.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08FR0106.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08AM0202.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08FR0402.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08JA0206.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08RU0103.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08FR0102.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08RU0106.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08JA0102.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08AM0201.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08AM0206.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08EN0101.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08GE0403.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08EN0404.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08JA0403.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08EN0102.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08JA0506.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08JA0101.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08JA0105.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08AM0304.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08RU0405.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08EN0204.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08RU0204.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08ge0306.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08JA0305.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08AM0203.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08JA0402.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08EN0303.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08GE0502.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08GE0406.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08JA0302.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08AM0305.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08FR0306.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08EN0501.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08GE0501.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08GE0505.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08FR0205.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08GE0504.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08FR0303.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08RU0304.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08AM0204.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08JA0501.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08FR0201.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08EN0502.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08RU0202.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08FR0502.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08EN0202.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08FR0204.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08FR0206.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08GE0102.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08GE0304.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08GE0506.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08AM0403.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08GE0103.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08JA0301.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08RU0306.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08AM0205.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08AM0401.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08RU0201.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08AM0103.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08JA0502.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08GE0503.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08AM0502.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08RU0303.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08FR0202.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig08/08GE0105.wav\", \"/mods/how/speech/sku1/pig08/\" },\n{\n\"/Speech/Sku1/Pig05/05RU0203.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05ge0506.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05AM0304.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05JA0105.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05FR0302.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05EN0405.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05FR0304.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05ge0205.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05EN0306.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05FR0201.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05ge0201.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05ge0303.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05EN0501.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05RU0503.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05FR0203.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05RU0204.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05RU0201.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05AM0302.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05AM0203.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05EN0305.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05RU0305.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05EN0503.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05FR0106.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05ge0105.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05JA0505.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05EN0402.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05AM0201.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05EN0201.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05RU0402.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05EN0202.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05AM0403.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05RU0304.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05AM0103.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05FR0101.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05JA0206.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05AM0102.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05RU0504.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05RU0206.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05JA0406.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05JA0404.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05EN0204.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05RU0405.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05ge0306.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05JA0103.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05JA0203.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05JA0106.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05AM0204.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05AM0503.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05EN0406.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05RU0501.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05FR0105.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05ge0203.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05JA0205.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05ge0405.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05AM0504.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05EN0505.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05FR0503.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05JA0201.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05AM0502.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05ge0503.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05JA0104.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05JA0305.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05RU0102.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05RU0502.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05EN0506.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05JA0501.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05EN0302.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05AM0505.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05ge0406.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05RU0104.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05FR0505.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05RU0403.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05EN0104.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05RU0401.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05AM0401.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05JA0402.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05AM0402.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05RU0205.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05FR0305.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05ge0504.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05AM0501.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05ge0102.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05AM0206.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05AM0305.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05EN0106.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05JA0403.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05EN0203.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05AM0406.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05RU0103.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05AM0301.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05ge0302.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05ge0104.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05FR0406.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05JA0304.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05RU0404.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05RU0302.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05JA0202.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05AM0106.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05RU0505.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05FR0301.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05FR0502.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05JA0503.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05FR0202.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05ge0402.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05EN0502.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05FR0204.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05RU0105.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05FR0103.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05ge0404.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05JA0302.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05JA0204.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05EN0101.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05RU0106.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05ge0204.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05EN0206.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05EN0105.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05RU0306.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05EN0301.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05AM0105.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05JA0502.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05JA0306.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05FR0402.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05FR0104.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05FR0405.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05JA0405.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05ge0304.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05RU0101.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05RU0301.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05ge0202.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05FR0404.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05ge0103.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05AM0202.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05FR0306.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05ge0301.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05ge0305.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05AM0405.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05AM0104.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05EN0404.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05EN0401.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05AM0506.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05ge0401.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05EN0403.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05RU0202.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05ge0403.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05ge0505.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05FR0401.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05EN0304.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05JA0504.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05ge0501.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05FR0102.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05FR0506.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05EN0504.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05ge0106.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05JA0303.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05FR0205.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05EN0102.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05ge0206.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05AM0404.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05EN0103.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05AM0306.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05JA0506.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05JA0101.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05RU0303.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05AM0101.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05RU0506.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05AM0303.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05EN0303.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05ge0101.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05JA0401.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05FR0403.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05EN0205.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05ge0502.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05JA0102.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05JA0301.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05RU0406.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05FR0206.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05FR0501.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05AM0205.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05FR0303.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig05/05FR0504.wav\", \"/mods/how/speech/sku1/pig05/\" },\n{\n\"/Speech/Sku1/Pig02/02RU0504.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02GE0203.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02AM0105.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02GE0101.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02GE0502.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02AM0501.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02AM0302.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02FR0403.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02EN0404.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02EN0406.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02GE0504.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02EN0501.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02AM0401.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02AM0304.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02JA0204.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02fr0204.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02GE0404.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02EN0106.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02AM0404.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02AM0504.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02RU0203.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02GE0106.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02GE0405.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02JA0501.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02AM0202.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02JA0104.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02JA0404.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02AM0403.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02RU0202.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02JA0503.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02fr0302.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02JA0402.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02GE0501.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02EN0303.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02AM0205.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02RU0406.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02AM0402.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02JA0105.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02RU0305.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02JA0305.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02JA0405.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02RU0102.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02JA0302.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02AM0104.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02EN0102.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02AM0106.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02fr0301.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02EN0505.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02JA0406.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02AM0101.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02EN0506.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02fr0102.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02AM0103.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02GE0202.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02FR0501.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02fr0101.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02GE0105.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02GE0201.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02EN0203.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02AM0203.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02RU0302.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02JA0502.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02EN0401.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02RU0103.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02fr0105.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02JA0303.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02GE0303.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02AM0303.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02EN0101.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02FR0503.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02FR0504.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02RU0206.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02fr0106.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02EN0205.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02FR0502.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02fr0201.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02AM0503.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02fr0203.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02RU0503.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02EN0301.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02RU0101.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02AM0102.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02fr0304.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02AM0306.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02EN0403.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02GE0403.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02JA0505.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02JA0304.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02RU0205.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02EN0305.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02fr0103.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02EN0302.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02EN0405.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02GE0506.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02fr0202.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02EN0306.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02EN0201.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02JA0403.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02FR0506.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02JA0101.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02AM0305.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02fr0306.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02RU0404.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02JA0103.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02EN0402.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02JA0205.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02EN0206.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02GE0305.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02RU0405.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02GE0401.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02fr0205.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02EN0104.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02GE0505.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02AM0201.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02AM0505.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02RU0506.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02GE0304.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02AM0301.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02GE0206.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02RU0505.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02JA0206.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02FR0406.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02GE0302.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02AM0206.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02GE0306.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02GE0402.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02GE0406.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02GE0503.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02EN0204.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02FR0401.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02RU0501.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02EN0304.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02EN0502.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02EN0103.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02GE0301.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02JA0102.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02AM0506.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02RU0401.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02FR0505.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02FR0405.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02AM0405.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02GE0103.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02RU0104.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02JA0301.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02GE0205.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02FR0402.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02GE0104.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02RU0303.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02JA0201.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02JA0106.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02EN0202.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02fr0303.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02RU0402.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02JA0504.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02JA0203.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02fr0104.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02RU0106.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02JA0202.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02GE0204.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02RU0301.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02AM0502.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02RU0502.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02RU0403.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02EN0503.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02GE0102.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02RU0201.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02RU0304.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02JA0506.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02AM0204.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02FR0404.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02RU0105.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02EN0504.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02EN0105.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02JA0401.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02RU0306.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02fr0206.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02AM0406.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02fr0305.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02JA0306.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig02/02RU0204.wav\", \"/mods/how/speech/sku1/pig02/\" },\n{\n\"/Speech/Sku1/Pig04/04FR0502.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04EN0404.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04RU0501.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04FR0206.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04RU0306.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04FR0501.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04AM0305.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04RU0305.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04RU0101.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04GE0301.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04FR0103.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04RU0403.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04RU0203.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04GE0406.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04JA0204.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04AM0402.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04GE0306.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04FR0106.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04FR0202.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04AM0405.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04FR0505.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04RU0404.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04GE0203.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04GE0303.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04EN0506.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04JA0406.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04RU0401.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04GE0401.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04RU0102.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04RU0402.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04FR0506.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04EN0401.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04EN0405.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04RU0104.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04GE0304.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04EN0203.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04JA0202.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04AM0201.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04EN0305.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04AM0304.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04EN0301.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04EN0503.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04EN0104.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04JA0106.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04EN0501.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04FR0301.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04FR0303.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04GE0502.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04JA0205.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04EN0504.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04AM0406.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04EN0105.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04JA0102.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04RU0304.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04JA0401.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04AM0105.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04EN0101.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04JA0402.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04FR0403.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04JA0502.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04RU0205.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04AM0403.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04FR0205.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04GE0506.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04FR0105.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04JA0503.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04AM0106.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04JA0304.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04JA0203.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04AM0302.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04FR0102.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04RU0506.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04GE0302.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04EN0202.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04FR0503.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04AM0206.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04RU0106.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04FR0406.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04AM0301.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04EN0204.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04AM0202.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04EN0201.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04JA0104.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04AM0506.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04AM0503.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04GE0103.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04GE0404.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04EN0103.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04EN0505.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04GE0305.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04JA0504.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04AM0303.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04FR0203.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04GE0201.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04FR0404.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04FR0201.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04RU0503.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04JA0206.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04JA0306.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04AM0404.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04FR0305.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04GE0504.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04EN0502.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04JA0506.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04RU0201.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04EN0306.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04GE0202.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04FR0104.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04JA0101.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04JA0404.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04EN0206.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04AM0102.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04GE0106.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04GE0102.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04AM0205.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04GE0205.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04GE0405.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04RU0405.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04AM0401.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04EN0303.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04JA0403.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04RU0206.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04EN0205.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04GE0101.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04AM0203.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04EN0402.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04EN0406.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04AM0502.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04AM0103.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04AM0306.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04FR0504.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04AM0501.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04RU0302.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04RU0504.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04EN0102.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04JA0501.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04JA0303.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04GE0503.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04AM0504.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04RU0406.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04JA0302.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04FR0405.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04EN0403.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04GE0105.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04EN0304.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04RU0505.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04FR0302.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04RU0502.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04GE0505.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04RU0103.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04AM0101.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04GE0402.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04FR0402.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04FR0304.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04EN0106.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04JA0105.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04JA0103.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04AM0204.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04RU0105.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04JA0305.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04AM0104.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04RU0303.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04EN0302.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04RU0301.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04GE0204.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04FR0204.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04GE0501.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04JA0201.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04GE0403.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04RU0202.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04AM0505.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04GE0104.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04GE0206.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04FR0306.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04JA0301.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04JA0505.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04FR0401.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04JA0405.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04FR0101.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Pig04/04RU0204.wav\", \"/mods/how/speech/sku1/pig04/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN1403.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN0105.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN0208.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN2104.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN0207.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN2203.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN1606.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN0507.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN1402.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN1103.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN0106.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN2205.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN0504.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN0407.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN0505.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN2108.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN0903.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN1406.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN0904.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN0607.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN1301.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN1805.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN1308.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN0307.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN2206.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN1905.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN0708.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN2007.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN1706.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN1202.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN1902.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN0405.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN2003.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN1307.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN0701.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN1502.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN0502.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN0608.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN0102.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN1107.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN0408.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN1005.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN0503.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN0402.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN1608.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN0803.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN1701.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN0908.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN0305.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN1104.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN1404.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN1604.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN0805.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN0202.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN1906.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN0702.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN1106.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN1001.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN0906.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN0703.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN1302.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN2005.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN1102.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN0802.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN0806.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN0103.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN0902.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN2008.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN0304.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN0404.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN1508.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN1207.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN1903.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN1203.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN1708.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN1401.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN0308.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN1807.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN1801.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN1408.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN0104.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN1004.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN0204.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN1407.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN1908.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN1305.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN1808.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN1007.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN0101.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN0506.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN1605.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN0601.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN1008.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN1501.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN0807.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN2101.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN1607.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN2202.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN1901.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN0704.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN1804.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN2103.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN1105.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN0403.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN1205.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN1505.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN1306.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN0203.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN0302.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN0901.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN1802.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN0306.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN1002.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN1108.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN2204.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN1705.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN1601.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN1907.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN0301.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN1201.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN1506.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN0905.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN0201.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN1904.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN1003.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN0707.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN0603.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN0907.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN0108.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN1101.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN2004.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN2006.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN1507.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN1204.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN0706.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN2106.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN0406.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN2207.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN0604.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN2107.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN2105.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN0206.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN2102.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN1703.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN1006.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN0804.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN2201.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN1504.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN1702.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN1602.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN1208.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN1603.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN0508.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN1304.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN2002.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN0606.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN0808.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN0205.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN1704.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN1707.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN1803.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN1206.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN0401.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN1405.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN0501.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN0107.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN0602.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN1303.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN1503.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN0303.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN0705.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN2001.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN0801.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN1806.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Sarge/SGEN0605.wav\", \"/mods/how/speech/sku1/sarge/\" },\n{\n\"/Speech/Sku1/Train1/tr1_en13.wav\", \"/mods/how/speech/sku1/train1/\" },\n{\n\"/Speech/Sku1/Train1/tr1_en17.wav\", \"/mods/how/speech/sku1/train1/\" },\n{\n\"/Speech/Sku1/Train1/tr1_en06.wav\", \"/mods/how/speech/sku1/train1/\" },\n{\n\"/Speech/Sku1/Train1/tr1_en05.wav\", \"/mods/how/speech/sku1/train1/\" },\n{\n\"/Speech/Sku1/Train1/tr1_en25.wav\", \"/mods/how/speech/sku1/train1/\" },\n{\n\"/Speech/Sku1/Train1/tr1_en15.wav\", \"/mods/how/speech/sku1/train1/\" },\n{\n\"/Speech/Sku1/Train1/tr1_en11.wav\", \"/mods/how/speech/sku1/train1/\" },\n{\n\"/Speech/Sku1/Train1/tr1_en28.wav\", \"/mods/how/speech/sku1/train1/\" },\n{\n\"/Speech/Sku1/Train1/tr1_en09.wav\", \"/mods/how/speech/sku1/train1/\" },\n{\n\"/Speech/Sku1/Train1/tr1_en16.wav\", \"/mods/how/speech/sku1/train1/\" },\n{\n\"/Speech/Sku1/Train1/tr1_en08.wav\", \"/mods/how/speech/sku1/train1/\" },\n{\n\"/Speech/Sku1/Train1/tr1_en23.wav\", \"/mods/how/speech/sku1/train1/\" },\n{\n\"/Speech/Sku1/Train1/tr1_en10.wav\", \"/mods/how/speech/sku1/train1/\" },\n{\n\"/Speech/Sku1/Train1/tr1_en24.wav\", \"/mods/how/speech/sku1/train1/\" },\n{\n\"/Speech/Sku1/Train1/tr1_en12.wav\", \"/mods/how/speech/sku1/train1/\" },\n{\n\"/Speech/Sku1/Train1/tr1_en03.wav\", \"/mods/how/speech/sku1/train1/\" },\n{\n\"/Speech/Sku1/Train1/tr1_en22.wav\", \"/mods/how/speech/sku1/train1/\" },\n{\n\"/Speech/Sku1/Train1/tr1_en04.wav\", \"/mods/how/speech/sku1/train1/\" },\n{\n\"/Speech/Sku1/Train1/tr1_en07.wav\", \"/mods/how/speech/sku1/train1/\" },\n{\n\"/Speech/Sku1/Train1/tr1_en20.wav\", \"/mods/how/speech/sku1/train1/\" },\n{\n\"/Speech/Sku1/Train1/tr1_en27.wav\", \"/mods/how/speech/sku1/train1/\" },\n{\n\"/Speech/Sku1/Train1/tr1_en14.wav\", \"/mods/how/speech/sku1/train1/\" },\n{\n\"/Speech/Sku1/Train1/tr1_en19.wav\", \"/mods/how/speech/sku1/train1/\" },\n{\n\"/Speech/Sku1/Train1/tr1_en18.wav\", \"/mods/how/speech/sku1/train1/\" },\n{\n\"/Speech/Sku1/Train1/tr1_en26.wav\", \"/mods/how/speech/sku1/train1/\" },\n{\n\"/Speech/Sku1/Train1/tr1_en01.wav\", \"/mods/how/speech/sku1/train1/\" },\n{\n\"/Speech/Sku1/Train1/tr1_en21.wav\", \"/mods/how/speech/sku1/train1/\" },\n{\n\"/Speech/Sku1/Train1/tr1_en02.wav\", \"/mods/how/speech/sku1/train1/\" },\n{\n\"/Speech/Sku1/Pig09/09RU0301.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09AM0506.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09GE0403.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09JA0105.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09AM0103.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09JA0203.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09FR0203.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09GE0206.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09EN0306.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09AM0302.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09FR0101.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09GE0302.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09RU0404.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09FR0401.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09AM0402.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09JA0506.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09FR0406.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09JA0104.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09GE0305.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09AM0404.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09GE0104.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09EN0404.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09AM0303.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09RU0403.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09JA0101.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09GE0303.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09AM0104.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09EN0205.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09FR0206.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09RU0302.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09JA0403.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09FR0303.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09JA0502.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09JA0106.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09GE0105.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09GE0204.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09AM0502.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09GE0504.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09AM0105.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09RU0502.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09EN0303.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09FR0205.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09JA0302.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09EN0204.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09FR0105.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09AM0201.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09RU0104.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09AM0204.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09EN0401.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09RU0106.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09AM0505.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09JA0301.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09EN0305.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09GE0401.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09EN0402.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09JA0201.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09EN0502.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09JA0503.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09GE0103.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09EN0501.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09EN0506.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09EN0105.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09RU0405.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09JA0404.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09FR0305.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09EN0206.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09AM0504.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09GE0503.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09GE0502.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09RU0101.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09FR0503.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09AM0304.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09EN0202.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09FR0202.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09RU0501.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09EN0302.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09EN0504.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09GE0501.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09AM0101.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09JA0103.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09FR0504.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09GE0201.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09JA0401.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09FR0403.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09FR0402.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09RU0503.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09GE0301.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09RU0406.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09FR0102.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09AM0405.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09EN0106.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09EN0203.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09FR0106.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09EN0503.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09FR0104.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09JA0504.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09FR0405.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09JA0402.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09RU0102.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09FR0501.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09AM0106.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09EN0406.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09AM0206.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09GE0203.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09EN0505.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09EN0201.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09JA0405.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09EN0102.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09EN0301.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09JA0303.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09JA0102.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09AM0306.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09AM0305.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09GE0304.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09GE0506.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09GE0102.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09JA0205.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09AM0403.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09GE0101.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09FR0502.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09RU0206.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09EN0101.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09JA0505.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09FR0404.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09AM0401.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09GE0406.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09AM0301.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09FR0201.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09AM0501.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09RU0205.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09JA0406.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09RU0201.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09FR0506.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09RU0303.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09JA0306.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09GE0306.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09EN0103.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09JA0304.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09RU0504.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09RU0306.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09GE0405.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09GE0205.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09EN0304.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09FR0301.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09AM0102.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09JA0202.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09JA0204.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09RU0105.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09RU0304.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09FR0505.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09FR0302.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09RU0203.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09GE0404.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09GE0402.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09AM0406.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09GE0505.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09FR0103.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09EN0403.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09RU0505.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09GE0202.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09JA0501.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09RU0103.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09FR0306.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09RU0305.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09EN0405.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09AM0205.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09RU0506.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09JA0305.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09RU0202.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09RU0204.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09GE0106.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09JA0206.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09RU0402.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09RU0401.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09EN0104.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09FR0304.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09FR0204.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09AM0203.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09AM0503.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig09/09AM0202.wav\", \"/mods/how/speech/sku1/pig09/\" },\n{\n\"/Speech/Sku1/Pig07/07GE0301.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07FR0404.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07EN0403.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07AM0101.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07GE0305.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07RU0303.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07RU0503.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07AM0102.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07JA0202.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07FR0303.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07FR0202.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07EN0502.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07EN0504.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07RU0504.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07EN0301.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07RU0304.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07EN0406.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07RU0102.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07EN0506.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07RU0201.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07GE0306.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07EN0501.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07FR0206.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07FR0503.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07JA0301.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07RU0203.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07EN0304.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07AM0301.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07FR0402.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07GE0304.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07GE0201.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07RU0406.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07AM0204.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07FR0201.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07JA0103.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07GE0401.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07EN0303.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07AM0506.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07RU0106.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07FR0504.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07FR0401.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07RU0305.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07GE0202.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07JA0503.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07RU0302.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07RU0103.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07JA0405.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07FR0406.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07AM0502.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07JA0102.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07JA0406.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07EN0302.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07GE0104.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07EN0404.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07JA0204.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07AM0201.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07JA0506.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07FR0105.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07GE0404.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07JA0505.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07AM0304.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07JA0203.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07EN0405.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07AM0503.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07JA0205.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07GE0204.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07RU0104.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07JA0304.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07EN0101.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07RU0306.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07JA0401.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07AM0105.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07GE0505.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07AM0402.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07AM0306.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07EN0206.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07JA0306.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07RU0101.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07JA0402.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07GE0501.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07EN0201.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07FR0403.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07AM0305.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07RU0206.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07EN0104.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07EN0202.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07RU0402.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07JA0501.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07GE0402.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07FR0505.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07EN0102.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07FR0502.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07GE0504.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07RU0505.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07JA0206.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07EN0106.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07AM0104.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07EN0105.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07AM0202.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07EN0505.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07GE0106.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07EN0305.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07JA0106.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07GE0403.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07RU0205.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07JA0403.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07AM0401.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07EN0401.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07RU0105.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07GE0102.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07RU0401.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07FR0501.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07GE0206.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07FR0306.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07EN0203.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07FR0204.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07FR0103.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07EN0204.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07GE0502.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07JA0105.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07FR0106.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07GE0205.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07FR0104.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07EN0402.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07GE0405.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07RU0404.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07JA0305.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07AM0103.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07AM0206.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07FR0102.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07AM0406.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07EN0503.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07AM0404.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07GE0103.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07AM0505.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07GE0303.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07JA0201.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07RU0405.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07JA0404.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07GE0506.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07RU0301.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07GE0503.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07GE0101.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07AM0504.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07GE0406.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07FR0203.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07AM0501.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07EN0103.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07EN0306.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07AM0302.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07FR0405.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07FR0205.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07RU0202.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07RU0506.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07JA0504.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07FR0305.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07JA0101.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07AM0405.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07FR0301.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07GE0302.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07RU0502.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07AM0203.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07AM0303.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07FR0304.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07GE0203.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07RU0501.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07AM0205.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07FR0101.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07RU0204.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07RU0403.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07JA0302.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07FR0302.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07JA0104.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07JA0303.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07JA0502.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07AM0106.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07AM0403.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07FR0506.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07EN0205.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig07/07GE0105.wav\", \"/mods/how/speech/sku1/pig07/\" },\n{\n\"/Speech/Sku1/Pig06/06RU0106.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06RU0103.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06EN0303.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06EN0504.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06FR0306.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06GE0205.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06GE0104.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06RU0204.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06FR0104.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06RU0302.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06AM0506.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06GE0103.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06JA0303.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06EN0502.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06EN0402.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06RU0506.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06AM0203.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06GE0405.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06RU0105.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06EN0204.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06JA0202.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06GE0401.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06GE0304.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06EN0503.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06EN0305.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06FR0102.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06FR0506.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06JA0403.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06GE0402.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06GE0101.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06AM0104.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06RU0405.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06JA0104.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06RU0306.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06AM0303.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06GE0106.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06FR0404.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06JA0301.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06JA0101.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06GE0105.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06EN0205.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06GE0102.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06GE0404.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06EN0203.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06JA0102.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06AM0206.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06FR0103.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06GE0301.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06JA0306.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06AM0202.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06EN0206.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06JA0401.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06FR0101.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06RU0401.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06GE0502.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06EN0406.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06FR0203.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06AM0405.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06RU0101.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06EN0105.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06FR0504.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06AM0306.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06EN0201.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06RU0203.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06EN0306.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06AM0301.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06FR0505.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06FR0106.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06AM0406.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06GE0305.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06FR0105.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06GE0505.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06RU0304.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06EN0104.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06AM0105.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06EN0301.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06RU0303.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06JA0504.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06RU0104.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06AM0401.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06RU0102.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06JA0203.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06AM0302.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06FR0304.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06RU0301.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06EN0103.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06RU0404.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06RU0403.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06JA0206.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06FR0202.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06AM0205.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06RU0205.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06AM0402.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06AM0106.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06JA0502.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06JA0304.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06EN0405.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06FR0503.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06FR0201.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06RU0502.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06FR0501.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06EN0403.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06JA0503.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06EN0501.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06JA0106.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06JA0501.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06JA0404.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06GE0202.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06GE0506.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06RU0406.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06JA0505.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06EN0106.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06GE0204.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06GE0201.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06AM0503.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06GE0406.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06FR0206.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06AM0101.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06AM0103.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06GE0306.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06AM0502.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06GE0302.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06RU0305.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06AM0102.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06RU0503.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06JA0302.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06AM0504.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06GE0403.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06FR0403.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06FR0204.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06FR0405.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06RU0504.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06JA0105.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06FR0305.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06AM0305.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06EN0404.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06JA0405.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06FR0303.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06GE0503.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06JA0201.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06EN0304.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06RU0505.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06FR0502.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06RU0201.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06AM0404.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06EN0302.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06RU0202.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06EN0102.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06RU0501.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06AM0304.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06GE0203.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06EN0506.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06GE0303.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06EN0505.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06JA0205.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06JA0406.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06RU0402.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06FR0205.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06JA0402.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06FR0301.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06JA0305.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06AM0403.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06FR0302.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06FR0402.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06JA0204.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06GE0501.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06AM0501.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06EN0401.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06JA0506.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06EN0101.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06GE0206.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06AM0201.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06FR0406.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06EN0202.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06RU0206.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06AM0505.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06FR0401.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06JA0103.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06AM0204.wav\", \"/mods/how/speech/sku1/pig06/\" },\n{\n\"/Speech/Sku1/Pig06/06GE0504.wav\", \"/mods/how/speech/sku1/pig06/\" },\n\n{\n\"/FESounds/click1.wav\", \"/mods/how/audio/frontend/\"},\n{\n\"/FESounds/click2.wav\", \"/mods/how/audio/frontend/\"},\n{\n\"/FESounds/click3.wav\", \"/mods/how/audio/frontend/\"},\n{\n\"/FESounds/click4.wav\", \"/mods/how/audio/frontend/\"},\n{\n\"/FESounds/click5.wav\", \"/mods/how/audio/frontend/\"},\n"
  },
  {
    "path": "src/extractor/pc_music_paths.h",
    "content": "/* OpenHoW\n * Copyright (C) 2017-2020 TalonBrave.info and Others (see CONTRIBUTORS)\n * Copyright (C) 2017 Daniel Collins <solemnwarning@solemnwarning.net>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n{\n\"/MUSIC/Track02.ogg\", \"/mods/how/music/\"},\n{\n\"/MUSIC/Track03.ogg\", \"/mods/how/music/\"},\n{\n\"/MUSIC/Track04.ogg\", \"/mods/how/music/\"},\n{\n\"/MUSIC/Track05.ogg\", \"/mods/how/music/\"},\n{\n\"/MUSIC/Track06.ogg\", \"/mods/how/music/\"},\n{\n\"/MUSIC/Track07.ogg\", \"/mods/how/music/\"},\n{\n\"/MUSIC/Track08.ogg\", \"/mods/how/music/\"},\n{\n\"/MUSIC/Track09.ogg\", \"/mods/how/music/\"},\n{\n\"/MUSIC/Track10.ogg\", \"/mods/how/music/\"},\n{\n\"/MUSIC/Track11.ogg\", \"/mods/how/music/\"},\n{\n\"/MUSIC/Track12.ogg\", \"/mods/how/music/\"},\n{\n\"/MUSIC/Track13.ogg\", \"/mods/how/music/\"},\n{\n\"/MUSIC/Track14.ogg\", \"/mods/how/music/\"},\n{\n\"/MUSIC/Track15.ogg\", \"/mods/how/music/\"},\n{\n\"/MUSIC/Track16.ogg\", \"/mods/how/music/\"},\n{\n\"/MUSIC/Track17.ogg\", \"/mods/how/music/\"},\n{\n\"/MUSIC/Track18.ogg\", \"/mods/how/music/\"},\n{\n\"/MUSIC/Track19.ogg\", \"/mods/how/music/\"},\n{\n\"/MUSIC/Track20.ogg\", \"/mods/how/music/\"},\n{\n\"/MUSIC/Track21.ogg\", \"/mods/how/music/\"},\n{\n\"/MUSIC/Track22.ogg\", \"/mods/how/music/\"},\n{\n\"/MUSIC/Track23.ogg\", \"/mods/how/music/\"},\n{\n\"/MUSIC/Track24.ogg\", \"/mods/how/music/\"},\n{\n\"/MUSIC/Track25.ogg\", \"/mods/how/music/\"},\n{\n\"/MUSIC/Track26.ogg\", \"/mods/how/music/\"},\n{\n\"/MUSIC/Track27.ogg\", \"/mods/how/music/\"},\n{\n\"/MUSIC/Track28.ogg\", \"/mods/how/music/\"},\n{\n\"/MUSIC/Track29.ogg\", \"/mods/how/music/\"},\n{\n\"/MUSIC/Track30.ogg\", \"/mods/how/music/\"},\n{\n\"/MUSIC/Track31.ogg\", \"/mods/how/music/\"},\n{\n\"/MUSIC/Track32.ogg\", \"/mods/how/music/\"},\n"
  },
  {
    "path": "src/extractor/pc_package_paths.h",
    "content": "/* OpenHoW\n * Copyright (C) 2017-2020 TalonBrave.info and Others (see CONTRIBUTORS)\n * Copyright (C) 2017 Daniel Collins <solemnwarning@solemnwarning.net>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n/* pigs */\n{\"/Chars/FACES.MTD\", \"/mods/how/chars/pigs/faces/\"},  /* contains all the face textures       */\n{\"/Chars/AMERICAN.MTD\", \"/mods/how/chars/pigs/american/\"},\n{\"/Chars/british.mtd\", \"/mods/how/chars/pigs/british/\"},\n{\"/Chars/FRENCH.MTD\", \"/mods/how/chars/pigs/french/\"},\n{\"/Chars/GERMAN.MTD\", \"/mods/how/chars/pigs/german/\"},\n{\"/Chars/JAPANESE.MTD\", \"/mods/how/chars/pigs/japanese/\"},\n{\"/Chars/RUSSIAN.MTD\", \"/mods/how/chars/pigs/russian/\"},\n{\"/Chars/TEAMLARD.MTD\", \"/mods/how/chars/pigs/teamlard/\"},\n{\"/Chars/BRITHATS.MAD\", \"/mods/how/chars/pigs/hats/\"},\n{\"/Chars/FHATS.MAD\", \"/mods/how/chars/pigs/hats/\"},\n\n/* sky */\n{\n\"/Chars/TOY.MAD\", \"/mods/how/skys/toy/\"},\n{\n\"/Chars/SPACE.MAD\", \"/mods/how/skys/space/\"},\n{\n\"/Chars/SUNSET.MAD\", \"/mods/how/skys/sunset/\"},\n{\n\"/Chars/SUNRISE.MAD\", \"/mods/how/skys/sunrise/\"},\n{\n\"/Chars/SUNNY.MAD\", \"/mods/how/skys/sunny/\"},\n{\n\"/Chars/OMINOUS.MAD\", \"/mods/how/skys/ominous/\"},\n{\n\"/Chars/DESERT.MAD\", \"/mods/how/skys/desert/\"},\n{\n\"/Chars/COLDSKY.MAD\", \"/mods/how/skys/coldsky/\"},\n{\n\"/Chars/NIGHT1.MAD\", \"/mods/how/skys/night1/\"},\n\n/* frontend */\n{\n\"/FEBmps/FEBMP.MAD\", \"/mods/how/frontend/bitmaps/\"},\n{\n\"/Language/Tims/FEFXTIMS.MTD\", \"/mods/how/frontend/fx/\"},\n{\n\"/Language/Tims/EXPLTIMS.MAD\", \"/mods/how/frontend/expl/\"},\n{\n\"/Language/Tims/FACETIMS.MAD\", \"/mods/how/frontend/dash/\"},\n{\n\"/Language/Tims/FLAGTIMS.MAD\", \"/mods/how/frontend/dash/\"},\n{\n\"/Language/Tims/dashtims.mad\", \"/mods/how/frontend/dash/\"},\n{\n\"/Language/Tims/MAPICONS.MTD\", \"/mods/how/frontend/map/\"},\n{\n\"/Language/Tims/MENUTIMS.MAD\", \"/mods/how/frontend/dash/menu/\"},\n{\n\"/Language/Tims/TBOXTIMS.MAD\", \"/mods/how/frontend/dash/\"},\n\n#if 1\n{\n\"/Maps/BAY.PTG\", \"/mods/how/maps/bay/tiles/\"},\n{\n\"/Maps/ICE.PTG\", \"/mods/how/maps/ice/tiles/\"},\n{\n\"/Maps/BOOM.PTG\", \"/mods/how/maps/boom/tiles/\"},\n{\n\"/Maps/BUTE.PTG\", \"/mods/how/maps/bute/tiles/\"},\n{\n\"/Maps/CAMP.PTG\", \"/mods/how/maps/camp/tiles/\"},\n{\n\"/Maps/DEMO.PTG\", \"/mods/how/maps/demo/tiles/\"},\n{\n\"/Maps/DEVI.PTG\", \"/mods/how/maps/devi/tiles/\"},\n{\n\"/Maps/DVAL.PTG\", \"/mods/how/maps/dval/tiles/\"},\n{\n\"/Maps/EASY.PTG\", \"/mods/how/maps/easy/tiles/\"},\n{\n\"/Maps/ESTU.PTG\", \"/mods/how/maps/estu/tiles/\"},\n{\n\"/Maps/FOOT.PTG\", \"/mods/how/maps/foot/tiles/\"},\n{\n\"/Maps/GUNS.PTG\", \"/mods/how/maps/guns/tiles/\"},\n{\n\"/Maps/KEEP.PTG\", \"/mods/how/maps/keep/tiles/\"},\n{\n\"/Maps/LAKE.PTG\", \"/mods/how/maps/lake/tiles/\"},\n{\n\"/Maps/MAZE.PTG\", \"/mods/how/maps/maze/tiles/\"},\n{\n\"/Maps/ROAD.PTG\", \"/mods/how/maps/road/tiles/\"},\n{\n\"/Maps/TWIN.PTG\", \"/mods/how/maps/twin/tiles/\"},\n{\n\"/Maps/ARCHI.PTG\", \"/mods/how/maps/archi/tiles/\"},\n{\n\"/Maps/BHILL.PTG\", \"/mods/how/maps/bhill/tiles/\"},\n{\n\"/Maps/CMASS.PTG\", \"/mods/how/maps/cmass/tiles/\"},\n{\n\"/Maps/DBOWL.PTG\", \"/mods/how/maps/dbowl/tiles/\"},\n{\n\"/Maps/DEMO2.PTG\", \"/mods/how/maps/demo2/tiles/\"},\n{\n\"/Maps/DVAL2.PTG\", \"/mods/how/maps/dval2/tiles/\"},\n{\n\"/Maps/EYRIE.PTG\", \"/mods/how/maps/eyrie/tiles/\"},\n{\n\"/Maps/FINAL.PTG\", \"/mods/how/maps/final/tiles/\"},\n{\n\"/Maps/HELL2.PTG\", \"/mods/how/maps/hell2/tiles/\"},\n{\n\"/Maps/HELL3.PTG\", \"/mods/how/maps/hell3/tiles/\"},\n{\n\"/Maps/MEDIX.PTG\", \"/mods/how/maps/medix/tiles/\"},\n{\n\"/Maps/MLAKE.PTG\", \"/mods/how/maps/mlake/tiles/\"},\n{\n\"/Maps/OASIS.PTG\", \"/mods/how/maps/oasis/tiles/\"},\n{\n\"/Maps/PLAY1.PTG\", \"/mods/how/maps/play1/tiles/\"},\n{\n\"/Maps/PLAY2.PTG\", \"/mods/how/maps/play2/tiles/\"},\n{\n\"/Maps/RIDGE.PTG\", \"/mods/how/maps/ridge/tiles/\"},\n{\n\"/Maps/SNAKE.PTG\", \"/mods/how/maps/snake/tiles/\"},\n{\n\"/Maps/ZULUS.PTG\", \"/mods/how/maps/zulus/tiles/\"},\n{\n\"/Maps/ARTGUN.PTG\", \"/mods/how/maps/artgun/tiles/\"},\n{\n\"/Maps/BRIDGE.PTG\", \"/mods/how/maps/bridge/tiles/\"},\n{\n\"/Maps/DESVAL.PTG\", \"/mods/how/maps/desval/tiles/\"},\n{\n\"/Maps/FJORDS.PTG\", \"/mods/how/maps/fjords/tiles/\"},\n{\n\"/Maps/GENMUD.PTG\", \"/mods/how/maps/genmud/tiles/\"},\n{\n\"/Maps/ISLAND.PTG\", \"/mods/how/maps/island/tiles/\"},\n{\n\"/Maps/LUNAR1.PTG\", \"/mods/how/maps/lunar1/tiles/\"},\n{\n\"/Maps/MASHED.PTG\", \"/mods/how/maps/mashed/tiles/\"},\n{\n\"/Maps/ONEWAY.PTG\", \"/mods/how/maps/oneway/tiles/\"},\n{\n\"/Maps/RUMBLE.PTG\", \"/mods/how/maps/rumble/tiles/\"},\n{\n\"/Maps/SEPIA1.PTG\", \"/mods/how/maps/sepia1/tiles/\"},\n{\n\"/Maps/SNIPER.PTG\", \"/mods/how/maps/sniper/tiles/\"},\n{\n\"/Maps/TRENCH.PTG\", \"/mods/how/maps/trench/tiles/\"},\n{\n\"/Maps/CREEPY2.PTG\", \"/mods/how/maps/creepy2/tiles/\"},\n{\n\"/Maps/EMPLACE.PTG\", \"/mods/how/maps/emplace/tiles/\"},\n{\n\"/Maps/GENLAVA.PTG\", \"/mods/how/maps/genlava/tiles/\"},\n{\n\"/Maps/GENSNOW.PTG\", \"/mods/how/maps/gensnow/tiles/\"},\n{\n\"/Maps/ICEFLOW.PTG\", \"/mods/how/maps/iceflow/tiles/\"},\n{\n\"/Maps/LECPROD.PTG\", \"/mods/how/maps/lecprod/tiles/\"},\n{\n\"/Maps/SUPLINE.PTG\", \"/mods/how/maps/supline/tiles/\"},\n{\n\"/Maps/genbrack.ptg\", \"/mods/how/maps/genbrack/tiles/\"},\n{\n\"/Maps/GENCHALK.PTG\", \"/mods/how/maps/genchalk/tiles/\"},\n{\n\"/Maps/GENDESRT.PTG\", \"/mods/how/maps/gendesrt/tiles/\"},\n{\n\"/Maps/HILLBASE.PTG\", \"/mods/how/maps/hillbase/tiles/\"},\n{\n\"/Maps/LIBERATE.PTG\", \"/mods/how/maps/liberate/tiles/\"},\n{\n\"/Maps/TESTER.PTG\", \"/mods/how/maps/tester/tiles/\"},\n\n{\n\"/Skys/COLD/COLD1.PTG\", \"/mods/how/skys/cold1/\"},\n//{\"/Skys/DESERT/DESERT1.PTG\", \"/mods/how/skys/desert1/\"},\n#endif\n"
  },
  {
    "path": "src/extractor/version.c",
    "content": "/* OpenHoW\n * Copyright (C) 2017-2020 TalonBrave.info and Others (see CONTRIBUTORS)\n * Copyright (C) 2017 Daniel Collins <solemnwarning@solemnwarning.net>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include \"extractor.h\"\n\nconst char *region_idents[ MAX_REGIONS ] = {\n        \"eng\", \"fre\", \"ger\", \"ita\", \"rus\", \"spa\" };\n\nVersionInfo version_info = {\n        .platform = PLATFORM_UNKNOWN,\n        .region = REGION_UNKNOWN };\n\nvoid CheckGameVersion( const char *path ) {\n\tPrint( \"checking game version...\\n\" );\n\n\tchar fcheck[ PL_SYSTEM_MAX_PATH ];\n\tsnprintf( fcheck, sizeof( fcheck ), \"%s/system.cnf\", path );\n\tif ( PlFileExists( fcheck ) ) {\n\t\tPrint( \"Detected system.cnf, assuming PSX version\\n\" );\n\t\tversion_info.platform = PLATFORM_PSX;\n\n#if 0\n\t\t// NTSC-U:\n\t\t// - SLUS-01195  HOGS OF WAR                          [E]\n\t\t// PAL:\n\t\t// - SLES-01041  HOGS OF WAR                          [E]\n\t\t// - SLES-02769  HOGS OF WAR                          [I]\n\t\t// - SLES-02767  HOGS OF WAR [FRONTSCHWEINE]          [G]\n\t\t// - SLES-02766  HOGS OF WAR [LES COCHONS DE GUERRE]  [F]\n\t\t// - SLES-02768  HOGS OF WAR [MARRANOS EN GUERRA]     [S]\n\n\t\tsnprintf(fcheck, sizeof(fcheck), \"%s/SLUS_011.95\", path);\n\t\tif (plFileExists(fcheck)) {\n\t\t  //version_info.platform = PLATFORM_PSX_NTSC?;\n\t\t  version_info.region = REGION_ENG;\n\t\t}\n\n\t\tsnprintf(fcheck, sizeof(fcheck), \"%s/SLES_010.95\", path);\n\t\tif (plFileExists(fcheck)) {\n\t\t  //version_info.platform = PLATFORM_PSX_PAL?;\n\t\t  version_info.region = REGION_ENG;\n\t\t}\n\n\t\tsnprintf(fcheck, sizeof(fcheck), \"%s/SLES_027.66\", path);\n\t\tif (plFileExists(fcheck)) {\n\t\t  //version_info.platform = PLATFORM_PSX_PAL?;\n\t\t  version_info.region = REGION_FRE;\n\t\t}\n\n\t\tsnprintf(fcheck, sizeof(fcheck), \"%s/SLES_027.67\", path);\n\t\tif (plFileExists(fcheck)) {\n\t\t  //version_info.platform = PLATFORM_PSX_PAL?;\n\t\t  version_info.region = REGION_GER;\n\t\t}\n\n\t\tsnprintf(fcheck, sizeof(fcheck), \"%s/SLES_027.68\", path);\n\t\tif (plFileExists(fcheck)) {\n\t\t  //version_info.platform = PLATFORM_PSX_PAL?;\n\t\t  version_info.region = REGION_SPA;\n\t\t}\n\n\t\tsnprintf(fcheck, sizeof(fcheck), \"%s/SLES_027.69\", path);\n\t\tif (plFileExists(fcheck)) {\n\t\t  //version_info.platform = PLATFORM_PSX_PAL?;\n\t\t  version_info.region = REGION_ITA;\n\t\t}\n\n\t\tif (version_info.region == REGION_UNKNOWN) {\n\t\t  LogWarn(\"Failed to find any known PSX-EXE file, unable to determine region!\\n\");\n\t\t  return;\n\t\t}\n#else\n\t\t// Alternative approach reading the language.lng file.\n\t\t// Language ids:\n\t\t// 0 = ENG_GB\n\t\t// 1 = ENG_US\n\t\t// 2 = FRE (no proof)\n\t\t// 3 = GER\n\t\t// 4 = SPA (no proof)\n\t\t// 5 = ITA (no proof)\n\n\t\tPLFile *languageFile = PlOpenFile( path, false );\n\t\tif ( languageFile == NULL ) {\n\t\t\tWarning( \"Failed to load \\\"%s\\\", aborting (%s)!\\n\", path, PlGetError() );\n\t\t\treturn;\n\t\t}\n\n\t\tuint32_t languageId;\n\t\tif ( PlReadFile( languageFile, &languageId, sizeof( uint32_t ), 1 ) != 1 ) {\n\t\t\tWarning( \"Failed to get language code, \\\"%s\\\" (%s)!\\n\", path, PlGetError() );\n\t\t\treturn;\n\t\t}\n\n\t\tif ( languageId == 0 || languageId == 1 ) {\n\t\t\tversion_info.region = REGION_ENG;\n\t\t} else if ( languageId == 2 ) {\n\t\t\tversion_info.region = REGION_FRE;\n\t\t} else if ( languageId == 3 ) {\n\t\t\tversion_info.region = REGION_GER;\n\t\t} else if ( languageId == 4 ) {\n\t\t\tversion_info.region = REGION_SPA;\n\t\t} else if ( languageId == 5 ) {\n\t\t\tversion_info.region = REGION_ITA;\n\t\t} else {\n\t\t\tWarning( \"Language id (%d) is unknown, unable to determine region!\\n\", languageId );\n\t\t\treturn;\n\t\t}\n#endif\n\t}\n\n\tsnprintf( fcheck, sizeof( fcheck ), \"%s/Data/foxscale.d3d\", path );\n\tif ( !PlFileExists( fcheck ) ) {\n\t\tWarning( \"Failed to find foxscale.d3d, unable to determine platform!\\n\" );\n\t\treturn;\n\t}\n\n\tPrint( \"Detected Data/foxscale.d3d, assuming PC version\\n\" );\n\tversion_info.platform = PLATFORM_PC;\n\n\t/* todo: need better method to determine this */\n\t/* todo: use checksum, not filesize!!! */\n\tsnprintf( fcheck, sizeof( fcheck ), \"%s/Language/Text/fetext.bin\", path );\n\tunsigned int fetext_size = PlGetLocalFileSize( fcheck );\n\tsnprintf( fcheck, sizeof( fcheck ), \"%s/Language/Text/gtext.bin\", path );\n\tunsigned int gtext_size = PlGetLocalFileSize( fcheck );\n\tif ( fetext_size == 8997 && gtext_size == 4518 ) {\n\t\tversion_info.region = REGION_GER;\n\t} else if ( fetext_size == 8102 && gtext_size == 4112 ) {\n\t\tversion_info.region = REGION_ENG;\n\t} else if ( fetext_size == 8391 && gtext_size == 4513 ) {\n\t\tversion_info.region = REGION_RUS;\n\t}\n\n\tsnprintf( fcheck, sizeof( fcheck ), \"%s/MUSIC/Track02.ogg\", path );\n\tif ( PlFileExists( fcheck ) ) {\n\t\tPrint( \"Detected MUSIC/Track02.ogg, assuming GOG version\\n\" );\n\t\tversion_info.platform = PLATFORM_PC_DIGITAL;\n\t}\n\n\tPrint( \"platform=%d, region=%d\\n\", version_info.platform, version_info.region );\n}\n"
  },
  {
    "path": "src/tools/CMakeLists.txt",
    "content": "#[[\nThis is free and unencumbered software released into the public domain.\n\nAnyone is free to copy, modify, publish, use, compile, sell, or\ndistribute this software, either in source code form or as a compiled\nbinary, for any purpose, commercial or non-commercial, and by any\nmeans.\n\nIn jurisdictions that recognize copyright laws, the author or authors\nof this software dedicate any and all copyright interest in the\nsoftware to the public domain. We make this dedication for the benefit\nof the public at large and to the detriment of our heirs and\nsuccessors. We intend this dedication to be an overt act of\nrelinquishment in perpetuity of all present and future rights to this\nsoftware under copyright law.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR\nOTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,\nARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\nOTHER DEALINGS IN THE SOFTWARE.\n\nFor more information, please refer to <http://unlicense.org>\n]]\n\ncmake_minimum_required(VERSION 3.5.1)\n\n# Set all of our output directories.\nset(CMAKE_LIBRARY_OUTPUT_DIRECTORY \"${CMAKE_SOURCE_DIR}../../lib/\")\nset(CMAKE_ARCHIVE_OUTPUT_DIRECTORY \"${CMAKE_SOURCE_DIR}../../lib/\")\nset(CMAKE_RUNTIME_OUTPUT_DIRECTORY \"${CMAKE_SOURCE_DIR}../../../bin/\")\n\nset(CMAKE_CXX_STANDARD 11)\nset(CMAKE_C_STANDARD 11)\n\nset(CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS} -Wall\")\nset(CMAKE_C_FLAGS \"${CMAKE_C_FLAGS} -Wall -Wsign-compare\")\nif (\"${CMAKE_CXX_COMPILER_ID}\" STREQUAL \"GNU\") #GCC\n    set(CMAKE_C_FLAGS \"${CMAKE_C_FLAGS} -Wno-format-truncation -Wold-style-declaration\")\nendif()\n\nset(PL_USE_GRAPHICS OFF CACHE BOOL \"Graphics\")\nadd_subdirectory(../3rdparty/platform/platform ${CMAKE_SOURCE_DIR}../../lib/ EXCLUDE_FROM_ALL)\n\nadd_subdirectory(ptgtool)\nadd_subdirectory(img2pmg)\n"
  },
  {
    "path": "src/tools/img2pmg/CMakeLists.txt",
    "content": "#[[\nThis is free and unencumbered software released into the public domain.\n\nAnyone is free to copy, modify, publish, use, compile, sell, or\ndistribute this software, either in source code form or as a compiled\nbinary, for any purpose, commercial or non-commercial, and by any\nmeans.\n\nIn jurisdictions that recognize copyright laws, the author or authors\nof this software dedicate any and all copyright interest in the\nsoftware to the public domain. We make this dedication for the benefit\nof the public at large and to the detriment of our heirs and\nsuccessors. We intend this dedication to be an overt act of\nrelinquishment in perpetuity of all present and future rights to this\nsoftware under copyright law.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR\nOTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,\nARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\nOTHER DEALINGS IN THE SOFTWARE.\n\nFor more information, please refer to <http://unlicense.org>\n]]\n\nproject( Img2Pmg )\n\nadd_executable( Img2Pmg main.c )\n\ntarget_include_directories(Img2Pmg PRIVATE . ${CMAKE_SYSTEM_INCLUDE_PATH})\ntarget_link_libraries(Img2Pmg platform)"
  },
  {
    "path": "src/tools/img2pmg/main.c",
    "content": "/* OpenHoW\n * Copyright (C) 2020 Mark Sowden <markelswo@gmail.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include <PL/platform_filesystem.h>\n#include <PL/platform_image.h>\n#include <PL/platform_console.h>\n\n/**\n * Img2Pmg\n * This tool will convert any four channel image into a PMG file\n * for use with Hogs of War.\n *\n * R = Height\n * G = Texture\n * B = Surface\n * A = Shading\n */\n\n#define Print(...)  plLogMessage(0, __VA_ARGS__)\n#define Warning(...)  plLogMessage(1, __VA_ARGS__)\n#define Error(...)    plLogMessage(2, __VA_ARGS__); exit(EXIT_FAILURE)\n\n/* ripped from terrain.h */\n#define TERRAIN_CHUNK_ROW           16\n#define TERRAIN_CHUNKS              (TERRAIN_CHUNK_ROW * TERRAIN_CHUNK_ROW)\n#define TERRAIN_CHUNK_ROW_TILES     4\n#define TERRAIN_CHUNK_TILES         (TERRAIN_CHUNK_ROW_TILES * TERRAIN_CHUNK_ROW_TILES)\n#define TERRAIN_TILE_PIXEL_WIDTH    512\n#define TERRAIN_CHUNK_PIXEL_WIDTH   2048\n#define TERRAIN_ROW_TILES           (TERRAIN_CHUNK_ROW * TERRAIN_CHUNK_ROW_TILES)\n#define TERRAIN_PIXEL_WIDTH         (TERRAIN_TILE_PIXEL_WIDTH * TERRAIN_ROW_TILES)\n\ntypedef struct PmgTile {\n  unsigned int surface;\n  unsigned int behaviour;\n  unsigned int slip;\n  uint8_t texture;\n  unsigned int rotation;\n  float height[ 4 ];\n  uint8_t shading[ 4 ];\n} PmgTile;\n\ntypedef struct PmgChunk {\n  PmgTile tiles[ 16 ];\n} PmgChunk;\n\nstatic PmgChunk mapChunks[ TERRAIN_CHUNKS ];\n\nstatic const char *instructions =\n\t\"Img2Pmg.exe myimage.png 100 myterrain.pmg\";\n\nstatic void LoadHeightmap( const char *path, int multiplier ) {\n\tPLImage *image = plLoadImage( path );\n\tif ( image == NULL ) {\n\t\tError( \"Failed to load the specified heightmap, \\\"%s\\\"!\\nPL: %s\\n\", path, plGetError() );\n\t}\n\n\tstatic const unsigned int imageWidth = 65;\n\tif ( image->width < imageWidth || image->height < imageWidth ) {\n\t\tError( \"Invalid image size for heightmap, %dx%d vs 65x65!\\n\", image->width, image->height );\n\t}\n\n\tunsigned int channelLength = image->width * image->height;\n\n\t/* height */\n\tfloat *redChannel = malloc( sizeof( float ) * channelLength );\n\tuint8_t *pixel = image->data[ 0 ];\n\tfor ( unsigned int i = 0; i < channelLength; ++i ) {\n\t\tredChannel[ i ] = (float) ( *pixel * multiplier );\n\t\tpixel += 4;\n\t}\n\n\tuint8_t *greenChannel = malloc( sizeof( uint8_t ) * channelLength );\n\tpixel = image->data[ 0 ] + 1;\n\tfor ( unsigned int i = 0; i < channelLength; ++i ) {\n\t\tgreenChannel[ i ] = *pixel;\n\t\tpixel += 4;\n\t}\n\n\tuint8_t *alphaChannel = malloc( sizeof( uint8_t ) * channelLength );\n\tpixel = image->data[ 0 ] + 3;\n\tfor ( unsigned int i = 0; i < channelLength; ++i ) {\n\t\talphaChannel[ i ] = *pixel;\n\t\tpixel += 4;\n\t}\n\n\tplDestroyImage( image );\n\n\t/* copy pasta this, since I can't be bothered writing it out again */\n\tfor ( unsigned int chunk_y = 0; chunk_y < TERRAIN_CHUNK_ROW; ++chunk_y ) {\n\t\tfor ( unsigned int chunk_x = 0; chunk_x < TERRAIN_CHUNK_ROW; ++chunk_x ) {\n\t\t\tPmgChunk *current_chunk = &mapChunks[ chunk_x + chunk_y * TERRAIN_CHUNK_ROW ];\n\t\t\tfor ( unsigned int tile_y = 0; tile_y < TERRAIN_CHUNK_ROW_TILES; ++tile_y ) {\n\t\t\t\tfor ( unsigned int tile_x = 0; tile_x < TERRAIN_CHUNK_ROW_TILES; ++tile_x ) {\n\t\t\t\t\tPmgTile *current_tile = &current_chunk->tiles[ tile_x + tile_y * TERRAIN_CHUNK_ROW_TILES ];\n\t\t\t\t\tunsigned int aaa = ( chunk_y * 4 * 65 ) + ( chunk_x * 4 );\n\t\t\t\t\tcurrent_tile->height[ 0 ] = redChannel[ aaa + ( tile_y * imageWidth ) + tile_x ];\n\t\t\t\t\tcurrent_tile->height[ 1 ] = redChannel[ aaa + ( tile_y * imageWidth ) + tile_x + 1 ];\n\t\t\t\t\tcurrent_tile->height[ 2 ] = redChannel[ aaa + ( ( tile_y + 1 ) * imageWidth ) + tile_x ];\n\t\t\t\t\tcurrent_tile->height[ 3 ] = redChannel[ aaa + ( ( tile_y + 1 ) * imageWidth ) + tile_x + 1 ];\n\n\t\t\t\t\tcurrent_tile->texture = greenChannel[ aaa + ( tile_y * imageWidth ) + tile_x ];\n\n\t\t\t\t\t/* todo: perhaps use alpha channel? */\n\t\t\t\t\tcurrent_tile->shading[ 0 ] =\n\t\t\t\t\tcurrent_tile->shading[ 1 ] =\n\t\t\t\t\tcurrent_tile->shading[ 2 ] =\n\t\t\t\t\tcurrent_tile->shading[ 3 ] = 255; //alphaChannel[ aaa + ( tile_y * imageWidth ) + tile_x ];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tfree( redChannel );\n\tfree( greenChannel );\n\tfree( alphaChannel );\n}\n\nstatic void WritePmg( const char *path ) {\n\tFILE *filePtr = fopen( path, \"wb\" );\n\tif ( filePtr == NULL ) {\n\t\tError( \"Failed to open \\\"%s\\\" for writing!\\n\" );\n\t}\n\n\tfor ( unsigned int chunk_y = 0; chunk_y < TERRAIN_CHUNK_ROW; ++chunk_y ) {\n\t\tfor ( unsigned int chunk_x = 0; chunk_x < TERRAIN_CHUNK_ROW; ++chunk_x ) {\n\t\t\tPmgChunk *current_chunk = &mapChunks[ chunk_x + chunk_y * TERRAIN_CHUNK_ROW ];\n\n\t\t\tstruct __attribute__((packed)) {\n\t\t\t  /* offsets */\n\t\t\t  uint16_t x;\n\t\t\t  uint16_t y;\n\t\t\t  uint16_t z;\n\t\t\t  uint16_t unknown0;\n\t\t\t} chunk = {\n\t\t\t\t.x = 0,\n\t\t\t\t.y = 0,\n\t\t\t\t.z = 0,\n\t\t\t\t.unknown0 = 0,\n\t\t\t};\n\n\t\t\tfwrite( &chunk, sizeof( chunk ), 1, filePtr );\n\n\t\t\tstruct __attribute__((packed)) {\n\t\t\t  int16_t height;\n\t\t\t  uint16_t lighting;\n\t\t\t} vertices[25];\n\n\t\t\tfor ( unsigned int tile_y = 0; tile_y < TERRAIN_CHUNK_ROW_TILES; ++tile_y ) {\n\t\t\t\tfor ( unsigned int tile_x = 0; tile_x < TERRAIN_CHUNK_ROW_TILES; ++tile_x ) {\n\t\t\t\t\tPmgTile *current_tile = &current_chunk->tiles[ tile_x + tile_y * TERRAIN_CHUNK_ROW_TILES ];\n\n\t\t\t\t\tvertices[ ( tile_y * 5 ) + tile_x ].height = current_tile->height[ 0 ];\n\t\t\t\t\tvertices[ ( tile_y * 5 ) + tile_x + 1 ].height = current_tile->height[ 1 ];\n\t\t\t\t\tvertices[ ( ( tile_y + 1 ) * 5 ) + tile_x ].height = current_tile->height[ 2 ];\n\t\t\t\t\tvertices[ ( ( tile_y + 1 ) * 5 ) + tile_x + 1 ].height = current_tile->height[ 3 ];\n\t\t\t\t\tvertices[ ( tile_y * 5 ) + tile_x ].lighting = current_tile->shading[ 0 ];\n\t\t\t\t\tvertices[ ( tile_y * 5 ) + tile_x + 1 ].lighting = current_tile->shading[ 0 ];\n\t\t\t\t\tvertices[ ( ( tile_y + 1 ) * 5 ) + tile_x ].lighting = current_tile->shading[ 0 ];\n\t\t\t\t\tvertices[ ( ( tile_y + 1 ) * 5 ) + tile_x + 1 ].lighting = current_tile->shading[ 0 ];\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfwrite( vertices, sizeof( *vertices ), 25, filePtr );\n\n\t\t\tuint32_t unknown = 0;\n\t\t\tfwrite( &unknown, sizeof( int32_t ), 1, filePtr );\n\n\t\t\tfor ( unsigned int tile_y = 0; tile_y < TERRAIN_CHUNK_ROW_TILES; ++tile_y ) {\n\t\t\t\tfor ( unsigned int tile_x = 0; tile_x < TERRAIN_CHUNK_ROW_TILES; ++tile_x ) {\n\t\t\t\t\tPmgTile *current_tile = &current_chunk->tiles[ tile_x + tile_y * TERRAIN_CHUNK_ROW_TILES ];\n\n\t\t\t\t\tstruct __attribute__((packed)) {\n\t\t\t\t\t  int8_t unused0[6];\n\t\t\t\t\t  uint8_t type;\n\t\t\t\t\t  uint8_t slip;\n\t\t\t\t\t  int16_t unused1;\n\t\t\t\t\t  uint8_t rotation;\n\t\t\t\t\t  uint32_t texture;\n\t\t\t\t\t  uint8_t unused2;\n\t\t\t\t\t} tile = {\n\t\t\t\t\t\t.unused0 = { 0, 0, 0, 0, 0, 0 },\n\t\t\t\t\t\t.type = 0,\n\t\t\t\t\t\t.slip = 0,\n\t\t\t\t\t\t.unused1 = 0,\n\t\t\t\t\t\t.rotation = 0,\n\t\t\t\t\t\t.texture = current_tile->texture,\n\t\t\t\t\t\t.unused2 = 0\n\t\t\t\t\t};\n\n\t\t\t\t\tfwrite( &tile, sizeof( tile ), 1, filePtr );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tfclose( filePtr );\n}\n\nint main(int argc, char **argv) {\n\tplInitialize(argc, argv);\n\n\tplSetupLogOutput( \"Img2Pmg.txt\" );\n\n\tplSetupLogLevel(0, \"info\", PLColour(0, 255, 0, 255), true);\n\tplSetupLogLevel(1, \"warning\", PLColour(255, 255, 0, 255), true);\n\tplSetupLogLevel(2, \"error\", PLColour(255, 0, 0, 255), true);\n\n\tif(argc < 4) {\n\t\tprintf(\"Invalid number of arguments!\\n%s\\n\", instructions);\n\t\treturn EXIT_SUCCESS;\n\t}\n\n\tchar imgPath[PL_SYSTEM_MAX_PATH];\n\tstrncpy(imgPath, argv[ 1 ], sizeof(imgPath));\n\tPrint( \"Input: %s\\n\", imgPath);\n\tchar pmgPath[PL_SYSTEM_MAX_PATH];\n\tstrncpy(pmgPath, argv[ 3 ], sizeof(pmgPath));\n\tPrint( \"Output: %s\\n\", pmgPath);\n\n\tint multiplier = atoi( argv[ 2 ] );\n\n\tLoadHeightmap( imgPath, multiplier );\n\tWritePmg( pmgPath );\n\n\tPrint( \"Done!\\n\");\n\n\treturn EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "src/tools/ptgtool/CMakeLists.txt",
    "content": "#[[\nThis is free and unencumbered software released into the public domain.\n\nAnyone is free to copy, modify, publish, use, compile, sell, or\ndistribute this software, either in source code form or as a compiled\nbinary, for any purpose, commercial or non-commercial, and by any\nmeans.\n\nIn jurisdictions that recognize copyright laws, the author or authors\nof this software dedicate any and all copyright interest in the\nsoftware to the public domain. We make this dedication for the benefit\nof the public at large and to the detriment of our heirs and\nsuccessors. We intend this dedication to be an overt act of\nrelinquishment in perpetuity of all present and future rights to this\nsoftware under copyright law.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR\nOTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,\nARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\nOTHER DEALINGS IN THE SOFTWARE.\n\nFor more information, please refer to <http://unlicense.org>\n]]\n\nproject(ptgtool)\n\nadd_executable(ptgtool ptgtool.c)\n\ntarget_include_directories(ptgtool PRIVATE . ${CMAKE_SYSTEM_INCLUDE_PATH})\ntarget_link_libraries(ptgtool platform)"
  },
  {
    "path": "src/tools/ptgtool/ptgtool.c",
    "content": "/* OpenHoW\n * Copyright (C) 2019 Mark Sowden <markelswo@gmail.com>\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include <PL/platform_filesystem.h>\n#include <PL/platform_console.h>\n\n#include \"../../engine/engine.h\"\n\n#undef Print\n#undef Warning\n#undef Error\n#define Print(...)  plLogMessage(0, __VA_ARGS__)\n#define Warning(...)  plLogMessage(1, __VA_ARGS__)\n#define Error(...)    plLogMessage(2, __VA_ARGS__); exit(EXIT_FAILURE)\n\nstatic FILE *ptg_fp = NULL;\n\nstatic unsigned int num_textures = 0;\nstatic char dir_textures[256][PL_SYSTEM_MAX_PATH];\nstatic void PTG_CountDirectoryTextures(const char *path, void *userData) {\n    /* ensure consistency */\n    u_unused( userData );\n\n    size_t size = plGetLocalFileSize( path );\n    if(size == 0) {\n        Error(\"Invalid file size for \\\"%s\\\", aborting!\\n\", path);\n    }\n\n    static size_t use_size = 0;\n    if(use_size == 0) {\n        use_size = size;\n    }\n\n    if(size != use_size) {\n        Error(\"Invalid file size for \\\"%s\\\", expected %lu (%lu), aborting!\\n\", path, use_size, size);\n    }\n\n    /* now index it */\n\n    Print( \"(%d) %s\\n\", num_textures, path);\n    strncpy(dir_textures[num_textures++], path, PL_SYSTEM_MAX_PATH);\n}\n\nstatic int PTG_SortTextures(const void *a, const void *b) {\n    const char *filename = plGetFileName(a);\n    char str_num[4];\n    memset(str_num, 0, sizeof(str_num));\n    strncpy(str_num, filename, strlen(filename) - 4);\n    int a_num = atoi(str_num);\n    filename = plGetFileName(b);\n    memset(str_num, 0, sizeof(str_num));\n    strncpy(str_num, filename, strlen(filename) - 4);\n    int b_num = atoi(str_num);\n    //LogInfo(\"%s\\n%d\\n%s\\n%d\\n\", a, a_num, b, b_num);\n    return a_num - b_num;\n}\n\nstatic void PTG_Extract(const char *input_path, const char *output_path) {\n    if(input_path == NULL || input_path[0] == '\\0') {\n        Error(\"Encountered invalid path for PTG, aborting!\\n\");\n    }\n\n    char ptg_name[PL_SYSTEM_MAX_PATH] = {'\\0'};\n    plStripExtension(ptg_name, sizeof(ptg_name), plGetFileName(input_path));\n    pl_strtolower(ptg_name);\n\n    if(!plCreatePath(output_path)) {\n        Error(\"Failed to create path %s, aborting!\\n\", output_path);\n    }\n\n    FILE *file = fopen(input_path, \"rb\");\n    if(file == NULL) {\n        Error(\"Failed to load %s, aborting!\\n\", input_path);\n    }\n\n    uint32_t num_textures;\n    if(fread(&num_textures, sizeof(uint32_t), 1, file) != 1) {\n        Error(\"invalid PTG file, failed to get number of textures!\\n\");\n    }\n\n    char index_path[PL_SYSTEM_MAX_PATH];\n    snprintf(index_path, sizeof(index_path), \"%s/.index\", output_path);\n    FILE* index = fopen(index_path, \"w\");\n    if(index == NULL) {\n        Error(\"Failed to open index for writing at \\\"%s\\\", aborting!\\n\", index_path);\n    }\n\n    size_t tim_size = ( plGetLocalFileSize( input_path ) - sizeof( num_textures ) ) / num_textures;\n    for(unsigned int i = 0; i < num_textures; ++i) {\n        fprintf(index, \"%d\\n\", i);\n\n        uint8_t tim[tim_size];\n        if(fread(tim, tim_size, 1, file) != 1) {\n            Print( \"failed to read tim, aborting!\\n\");\n            goto ABORT_PTG;\n        }\n\n        char out_path[PL_SYSTEM_MAX_PATH] = {'\\0'};\n        sprintf(out_path, \"%s/%d.tim\", output_path, i);\n        FILE* out = fopen(out_path, \"wb\");\n        if(out == NULL) {\n            Print( \"failed to open %s for writing, aborting!\\n\", out_path);\n            goto ABORT_PTG;\n        }\n\n        //print(\" %s\\n\", out_path);\n        if(fwrite(tim, tim_size, 1, out) != 1) {\n            Print( \"Failed to write \\\"%s\\\", aborting!\\n\", out_path);\n        }\n\n        u_fclose(out);\n    }\n\n    ABORT_PTG:\n    u_fclose(index);\n    u_fclose(file);\n}\n\nstatic const char *instructions =\n        \"USAGE:\\n\"\n        \"   ptgtool extract \\\"pathtoptg\\\" \\\"outpath\\\"\\n\"\n        \"   ptgtool package \\\"pathtodir\\\" \\\"outpath\\\"\";\n\nint main(int argc, char **argv) {\n    plInitialize(argc, argv);\n\n    char app_dir[PL_SYSTEM_MAX_PATH];\n    plGetApplicationDataDirectory(ENGINE_APP_NAME, app_dir, PL_SYSTEM_MAX_PATH);\n\n    if(!plCreatePath(app_dir)) {\n        Warning( \"Unable to create %s: %s\\nSettings will not be saved.\", app_dir, plGetError());\n    }\n\n    char log_path[PL_SYSTEM_MAX_PATH];\n    snprintf(log_path, PL_SYSTEM_MAX_PATH, \"%s/ptgtool\", app_dir);\n    plSetupLogOutput(log_path);\n\n    Print( \"Log path: %s\\n\", log_path);\n\n    plSetupLogLevel(0, \"info\", PLColour(0, 255, 0, 255), true);\n    plSetupLogLevel(1, \"warning\", PLColour(255, 255, 0, 255), true);\n    plSetupLogLevel(2, \"error\", PLColour(255, 0, 0, 255), true);\n\n    if(argc < 2) {\n        printf(\"Invalid number of arguments!\\n%s\\n\", instructions);\n        return EXIT_SUCCESS;\n    }\n\n    char in_path[PL_SYSTEM_MAX_PATH] = {'\\0'};\n    char out_path[PL_SYSTEM_MAX_PATH] = {'\\0'};\n\n    enum {\n        MODE_NONE,\n        MODE_EXTRACT,\n        MODE_PACKAGE,\n    } mode = MODE_NONE;\n\n    const char *arg = NULL;\n    if((arg = plGetCommandLineArgumentValue(\"extract\")) != NULL) {\n        mode = MODE_EXTRACT;\n    } else if((arg = plGetCommandLineArgumentValue(\"package\")) != NULL) {\n        mode = MODE_PACKAGE;\n    } else {\n        Error(\"Invalid mode specified, aborting!\\n%s\\n\", instructions);\n    }\n\n    strncpy(in_path, arg, sizeof(in_path));\n    Print( \"Input: %s\\n\", in_path);\n    if(argc > 3 && (argv[3] != NULL && argv[3][0] != '\\0')) {\n        strncpy(out_path, argv[3], sizeof(out_path));\n        Print( \"Output: %s\\n\", out_path);\n    } else if(mode == MODE_PACKAGE) {\n        Error(\"Valid output path is required for packaging, aborting!\\n\");\n    }\n\n    if(mode == MODE_EXTRACT) {\n        if(out_path[0] == '\\0') {\n            const char *filename = plGetFileName(in_path);\n            if(filename == NULL) {\n                Error(\"Failed to get filename from \\\"%s\\\"!\\n\", in_path);\n            }\n\n            snprintf(out_path, sizeof(out_path), \"./%s/\", filename);\n        }\n\n        PTG_Extract(in_path, out_path);\n    } else {\n        ptg_fp = fopen(out_path, \"wb\");\n        if(ptg_fp == NULL) {\n            Error(\"Failed to open \\\"%s\\\" for writing, aborting!\\n\", out_path);\n        }\n\n        plScanDirectory(in_path, \"tim\", PTG_CountDirectoryTextures, false, NULL );\n\n        Print( \"Found %d textures for writing into \\\"%s\\\"...\\n\", num_textures, out_path);\n\n        fwrite(&num_textures, sizeof(uint32_t), 1, ptg_fp);\n        qsort(dir_textures[0], num_textures, PL_SYSTEM_MAX_PATH, PTG_SortTextures);\n        for(unsigned int i = 0; i < num_textures; ++i) {\n            Print( \"Writing \\\"%s\\\" (%d)\\n\", dir_textures[i], i);\n\t\t\tsize_t tim_size = plGetLocalFileSize( dir_textures[ i ] );\n\t\t\tuint8_t buf[tim_size];\n            FILE *tim_fp = fopen(dir_textures[i], \"rb\");\n            fread(buf, sizeof(uint8_t), tim_size, tim_fp);\n            fwrite(buf, sizeof(uint8_t), tim_size, ptg_fp);\n            fclose(tim_fp);\n        }\n        fclose(ptg_fp);\n    }\n\n    Print( \"Done!\\n\");\n\n    return EXIT_SUCCESS;\n}"
  }
]