Merge "Upgrade python/pycparser to release_v2.20" am: 2d9dbc9f30

Change-Id: I89e58ce156bae722cc2db9b389b53e2922e93923
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..91c326c
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,2 @@
+*.ppout linguist-vendored=true
+
diff --git a/.gitignore b/.gitignore
index 5ce5b00..afa1201 100644
--- a/.gitignore
+++ b/.gitignore
@@ -14,4 +14,4 @@
 .tox
 utils/z.c
 *.egg-info
-
+*.swp
diff --git a/.travis.yml b/.travis.yml
index 25c9df6..d71276e 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,7 +1,7 @@
 language: python
 python:
   - "2.7"
-  - "3.4"
-  - "3.5"
   - "3.6"
+  - "3.7"
+  - "3.8"
 script: python tests/all_tests.py
diff --git a/.vimrc b/.vimrc
new file mode 100644
index 0000000..d2627af
--- /dev/null
+++ b/.vimrc
@@ -0,0 +1,8 @@
+" Force indentation styles for this directory
+autocmd FileType python set shiftwidth=4
+autocmd FileType python set tabstop=4
+autocmd FileType python set softtabstop=4
+
+autocmd FileType c set shiftwidth=2
+autocmd FileType c set tabstop=2
+autocmd FileType c set softtabstop=2
diff --git a/CHANGES b/CHANGES
index 711c263..d94cf57 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,9 +1,26 @@
++ Version 2.20 (2020.03.04)
+
+  - #61: Fix slow backtracking when parsing strings.
+  - #99: Parser for FuncDecl incorrectly sets declname attribute on return type.
+  - #310: Fix crash when file starts with a semicolon.
+  - #313: Fix array type generation.
+  - #314: Fix failed parsing of unnamed function parameters with array dim
+    qualifiers.
+  - #315: Fix pointer type generation.
+  - #324: Fixes for u/l constant integer suffix.
+  - #346: Fix error transforming an empty switch.
+  - #350: Recognize integer multicharacter constants like 'ABCD'.
+  - #363: Fix incorrect AST when parsing offsetof.
+
 + Version 2.19 (2018.09.19)
 
   - PR #277: Fix parsing of floating point literals
   - PR #254: Add support for parsing empty structs
   - PR #240: Fix enum formatting in generated C code (also #216)
   - PR #222: Add support for #pragma in struct declarations
+  - There are reports that this release doesn't work with Python 2.6 (#281).
+    Please note that the minimal supported version is 2.7; the required versions
+    are listed in the README file.
 
 + Version 2.18 (2017.07.04)
 
@@ -149,11 +166,11 @@
 + Version 2.05 (2011.10.16)
 
   - Added support for the C99 ``_Bool`` type and ``stdbool.h`` header file
-  - Expanded ``examples/explore_ast.py`` with more details on working with the 
+  - Expanded ``examples/explore_ast.py`` with more details on working with the
     AST
   - Relaxed the rules on parsing unnamed struct members (helps parse ``windows.h``)
   - Bug fixes:
-  
+
     * Fixed spacing issue for some type declarations
     * Issue 47: display empty statements (lone ';') correctly after parsing
 
@@ -161,34 +178,34 @@
 
   - License changed from LGPL to BSD
   - Bug fixes:
-  
+
     * Issue 31: constraining the scope of typedef definitions
     * Issues 33, 35: fixes for the c-to-c.py example
-  
+
   - Added C99 integer types to fake headers
   - Added unit tests for the c-to-c.py example
 
 + Version 2.03 (2011.03.06)
 
   - Bug fixes:
-  
+
     * Issue 17: empty file-level declarations
     * Issue 18: empty statements and declarations in functions
     * Issue 19: anonymous structs & union fields
     * Issue 23: fix coordinates of Cast nodes
-  
+
   - New example added (``examples/c-to-c.py``) for translating ASTs generated
     by ``pycparser`` back into C code.
   - ``pycparser`` is now on PyPI (Python Package Index)
   - Created `FAQ <http://code.google.com/p/pycparser/wiki/FAQ>`_ on
-    the ``pycparser`` project page 
+    the ``pycparser`` project page
   - Removed support for Python 2.5. ``pycparser`` supports Python 2
     from 2.6 and on, and Python 3.
 
 + Version 2.02 (2010.12.10)
 
-  * The name of a ``NamedInitializer`` node was turned into a sequence of nodes 
-    instead of an attribute, to make it discoverable by the AST node visitor.  
+  * The name of a ``NamedInitializer`` node was turned into a sequence of nodes
+    instead of an attribute, to make it discoverable by the AST node visitor.
   * Documentation updates
 
 + Version 2.01 (04.12.2010)
@@ -218,7 +235,7 @@
 
 + Version 1.06 (2010.04.10)
 
-  * Bug fixes: 
+  * Bug fixes:
 
     + coord not propagated to FuncCall nodes
     + lexing of the ^= token (XOREQUALS)
@@ -246,7 +263,7 @@
 + Version 1.02 (2009.01.16)
 
   * Fixed problem of parsing struct/enum/union names that were named similarly
-    to previously defined ``typedef`` types. 
+    to previously defined ``typedef`` types.
 
 + Version 1.01 (2009.01.09)
 
diff --git a/METADATA b/METADATA
index e07b7a2..78bbe58 100644
--- a/METADATA
+++ b/METADATA
@@ -9,11 +9,11 @@
     type: GIT
     value: "https://github.com/eliben/pycparser"
   }
-  version: "release_v2.19"
+  version: "release_v2.20"
   license_type: NOTICE
   last_upgrade_date {
-    year: 2019
-    month: 5
-    day: 2
+    year: 2020
+    month: 3
+    day: 4
   }
 }
diff --git a/README.rst b/README.rst
index df9025c..ebf12f6 100644
--- a/README.rst
+++ b/README.rst
@@ -1,9 +1,15 @@
 ===============
-pycparser v2.19
+pycparser v2.20
 ===============
 
-:Author: `Eli Bendersky <https://eli.thegreenplace.net/>`_
 
+.. image:: https://travis-ci.org/eliben/pycparser.png?branch=master
+  :align: center
+  :target: https://travis-ci.org/eliben/pycparser
+
+.. image:: https://ci.appveyor.com/api/projects/status/wrup68o5y8nuk1i9?svg=true
+  :align: center
+  :target: https://ci.appveyor.com/project/eliben/pycparser/
 
 .. contents::
     :backlinks: none
@@ -161,6 +167,9 @@
 <https://eli.thegreenplace.net/2015/on-parsing-c-type-declarations-and-fake-headers>`_
 for more details.
 
+Note that the fake headers are not included in the ``pip`` package nor installed
+via ``setup.py`` (`#224 <https://github.com/eliben/pycparser/issues/224>`_).
+
 Basic usage
 -----------
 
@@ -240,18 +249,3 @@
 contributions.
 
 
-CI Status
-=========
-
-**pycparser** has automatic testing enabled through the convenient
-`Travis CI project <https://travis-ci.org>`_. Here is the latest build status:
-
-.. image:: https://travis-ci.org/eliben/pycparser.png?branch=master
-  :align: center
-  :target: https://travis-ci.org/eliben/pycparser
-
-AppVeyor also helps run tests on Windows:
-
-.. image:: https://ci.appveyor.com/api/projects/status/wrup68o5y8nuk1i9?svg=true
-  :align: center
-  :target: https://ci.appveyor.com/project/eliben/pycparser/
diff --git a/TODO.txt b/TODO.txt
index 3737893..d946d30 100644
--- a/TODO.txt
+++ b/TODO.txt
@@ -19,7 +19,7 @@
 `pip install <tarballname>`. See that pycparser is importable in the Python
 interpreter of this virtualenv; run pycparser tests from this virtualenv.
 
-After this it's OK to rerun `python3.6 setup.py sdist upload` to push to PyPI
+After this it's OK to rerun `python3.6 -m twine upload dist/*` to push to PyPI
 (older Pythons use a deprecated API for PyPI uploading).
 
 - Tag in git. When pushing to GitHub, git push --tags
diff --git a/appveyor.yml b/appveyor.yml
index 05c1c7e..900df8f 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -2,9 +2,9 @@
 
   matrix:
     - PYTHON: "C:\\Python27"
-    - PYTHON: "C:\\Python34"
     - PYTHON: "C:\\Python35"
     - PYTHON: "C:\\Python36"
+    - PYTHON: "C:\\Python37"
 
 build: off
 
diff --git a/examples/dump_ast.py b/examples/dump_ast.py
index 2cff874..63f5e2d 100644
--- a/examples/dump_ast.py
+++ b/examples/dump_ast.py
@@ -19,7 +19,9 @@
 if __name__ == "__main__":
     argparser = argparse.ArgumentParser('Dump AST')
     argparser.add_argument('filename', help='name of file to parse')
+    argparser.add_argument('--coord', help='show coordinates in the dump',
+                           action='store_true')
     args = argparser.parse_args()
 
     ast = parse_file(args.filename, use_cpp=False)
-    ast.show()
+    ast.show(showcoord=args.coord)
diff --git a/examples/func_calls.py b/examples/func_calls.py
index ec31fe5..97a7271 100644
--- a/examples/func_calls.py
+++ b/examples/func_calls.py
@@ -17,9 +17,7 @@
 from pycparser import c_parser, c_ast, parse_file
 
 
-# A visitor with some state information (the funcname it's
-# looking for)
-#
+# A visitor with some state information (the funcname it's looking for)
 class FuncCallVisitor(c_ast.NodeVisitor):
     def __init__(self, funcname):
         self.funcname = funcname
@@ -27,6 +25,9 @@
     def visit_FuncCall(self, node):
         if node.name.name == self.funcname:
             print('%s called at %s' % (self.funcname, node.name.coord))
+        # Visit args in case they contain more func calls.
+        if node.args:
+            self.visit(node.args)
 
 
 def show_func_calls(filename, funcname):
diff --git a/pycparser/__init__.py b/pycparser/__init__.py
index b67389f..6e86e9f 100644
--- a/pycparser/__init__.py
+++ b/pycparser/__init__.py
@@ -8,7 +8,7 @@
 # License: BSD
 #-----------------------------------------------------------------
 __all__ = ['c_lexer', 'c_parser', 'c_ast']
-__version__ = '2.19'
+__version__ = '2.20'
 
 import io
 from subprocess import check_output
diff --git a/pycparser/_build_tables.py b/pycparser/_build_tables.py
index 94a3891..958381a 100644
--- a/pycparser/_build_tables.py
+++ b/pycparser/_build_tables.py
@@ -10,13 +10,17 @@
 # License: BSD
 #-----------------------------------------------------------------
 
+# Insert '.' and '..' as first entries to the search path for modules.
+# Restricted environments like embeddable python do not include the
+# current working directory on startup.
+import sys
+sys.path[0:0] = ['.', '..']
+
 # Generate c_ast.py
 from _ast_gen import ASTCodeGenerator
 ast_gen = ASTCodeGenerator('_c_ast.cfg')
 ast_gen.generate(open('c_ast.py', 'w'))
 
-import sys
-sys.path[0:0] = ['.', '..']
 from pycparser import c_parser
 
 # Generates the tables
diff --git a/pycparser/ast_transforms.py b/pycparser/ast_transforms.py
index ba50966..0aeb88f 100644
--- a/pycparser/ast_transforms.py
+++ b/pycparser/ast_transforms.py
@@ -74,7 +74,8 @@
 
     # Goes over the children of the Compound below the Switch, adding them
     # either directly below new_compound or below the last Case as appropriate
-    for child in switch_node.stmt.block_items:
+    # (for `switch(cond) {}`, block_items would have been None)
+    for child in (switch_node.stmt.block_items or []):
         if isinstance(child, (c_ast.Case, c_ast.Default)):
             # If it's a Case/Default:
             # 1. Add it to the Compound and mark as "last case"
diff --git a/pycparser/c_generator.py b/pycparser/c_generator.py
index f789742..973d24a 100644
--- a/pycparser/c_generator.py
+++ b/pycparser/c_generator.py
@@ -119,7 +119,7 @@
         return s
 
     def visit_Cast(self, n):
-        s = '(' + self._generate_type(n.to_type) + ')'
+        s = '(' + self._generate_type(n.to_type, emit_declname=False) + ')'
         return s + ' ' + self._parenthesize_unless_simple(n.expr)
 
     def visit_ExprList(self, n):
@@ -291,6 +291,15 @@
     def visit_FuncDecl(self, n):
         return self._generate_type(n)
 
+    def visit_ArrayDecl(self, n):
+        return self._generate_type(n, emit_declname=False)
+
+    def visit_TypeDecl(self, n):
+        return self._generate_type(n, emit_declname=False)
+
+    def visit_PtrDecl(self, n):
+        return self._generate_type(n, emit_declname=False)
+
     def _generate_struct_union_enum(self, n, name):
         """ Generates code for structs, unions, and enums. name should be
             'struct', 'union', or 'enum'.
@@ -359,7 +368,7 @@
         s += self._generate_type(n.type)
         return s
 
-    def _generate_type(self, n, modifiers=[]):
+    def _generate_type(self, n, modifiers=[], emit_declname = True):
         """ Recursive generation from a type node. n is the type node.
             modifiers collects the PtrDecl, ArrayDecl and FuncDecl modifiers
             encountered on the way down to a TypeDecl, to allow proper
@@ -373,23 +382,29 @@
             if n.quals: s += ' '.join(n.quals) + ' '
             s += self.visit(n.type)
 
-            nstr = n.declname if n.declname else ''
+            nstr = n.declname if n.declname and emit_declname else ''
             # Resolve modifiers.
             # Wrap in parens to distinguish pointer to array and pointer to
             # function syntax.
             #
             for i, modifier in enumerate(modifiers):
                 if isinstance(modifier, c_ast.ArrayDecl):
-                    if (i != 0 and isinstance(modifiers[i - 1], c_ast.PtrDecl)):
-                        nstr = '(' + nstr + ')'
-                    nstr += '[' + self.visit(modifier.dim) + ']'
+                    if (i != 0 and
+                        isinstance(modifiers[i - 1], c_ast.PtrDecl)):
+                            nstr = '(' + nstr + ')'
+                    nstr += '['
+                    if modifier.dim_quals:
+                        nstr += ' '.join(modifier.dim_quals) + ' '
+                    nstr += self.visit(modifier.dim) + ']'
                 elif isinstance(modifier, c_ast.FuncDecl):
-                    if (i != 0 and isinstance(modifiers[i - 1], c_ast.PtrDecl)):
-                        nstr = '(' + nstr + ')'
+                    if (i != 0 and
+                        isinstance(modifiers[i - 1], c_ast.PtrDecl)):
+                            nstr = '(' + nstr + ')'
                     nstr += '(' + self.visit(modifier.args) + ')'
                 elif isinstance(modifier, c_ast.PtrDecl):
                     if modifier.quals:
-                        nstr = '* %s %s' % (' '.join(modifier.quals), nstr)
+                        nstr = '* %s%s' % (' '.join(modifier.quals),
+                                           ' ' + nstr if nstr else '')
                     else:
                         nstr = '*' + nstr
             if nstr: s += ' ' + nstr
@@ -397,11 +412,12 @@
         elif typ == c_ast.Decl:
             return self._generate_decl(n.type)
         elif typ == c_ast.Typename:
-            return self._generate_type(n.type)
+            return self._generate_type(n.type, emit_declname = emit_declname)
         elif typ == c_ast.IdentifierType:
             return ' '.join(n.names) + ' '
         elif typ in (c_ast.ArrayDecl, c_ast.PtrDecl, c_ast.FuncDecl):
-            return self._generate_type(n.type, modifiers + [n])
+            return self._generate_type(n.type, modifiers + [n],
+                                       emit_declname = emit_declname)
         else:
             return self.visit(n)
 
diff --git a/pycparser/c_lexer.py b/pycparser/c_lexer.py
index de8445e..045d24e 100644
--- a/pycparser/c_lexer.py
+++ b/pycparser/c_lexer.py
@@ -19,7 +19,7 @@
         tokens.
 
         The public attribute filename can be set to an initial
-        filaneme, but the lexer will update it upon #line
+        filename, but the lexer will update it upon #line
         directives.
     """
     def __init__(self, error_func, on_lbrace_func, on_rbrace_func,
@@ -130,7 +130,7 @@
         'TYPEID',
 
         # constants
-        'INT_CONST_DEC', 'INT_CONST_OCT', 'INT_CONST_HEX', 'INT_CONST_BIN',
+        'INT_CONST_DEC', 'INT_CONST_OCT', 'INT_CONST_HEX', 'INT_CONST_BIN', 'INT_CONST_CHAR',
         'FLOAT_CONST', 'HEX_FLOAT_CONST',
         'CHAR_CONST',
         'WCHAR_CONST',
@@ -205,23 +205,49 @@
     # parse all correct code, even if it means to sometimes parse incorrect
     # code.
     #
-    simple_escape = r"""([a-zA-Z._~!=&\^\-\\?'"])"""
-    decimal_escape = r"""(\d+)"""
-    hex_escape = r"""(x[0-9a-fA-F]+)"""
-    bad_escape = r"""([\\][^a-zA-Z._~^!=&\^\-\\?'"x0-7])"""
+    # The original regexes were taken verbatim from the C syntax definition,
+    # and were later modified to avoid worst-case exponential running time.
+    #
+    #   simple_escape = r"""([a-zA-Z._~!=&\^\-\\?'"])"""
+    #   decimal_escape = r"""(\d+)"""
+    #   hex_escape = r"""(x[0-9a-fA-F]+)"""
+    #   bad_escape = r"""([\\][^a-zA-Z._~^!=&\^\-\\?'"x0-7])"""
+    #
+    # The following modifications were made to avoid the ambiguity that allowed backtracking:
+    # (https://github.com/eliben/pycparser/issues/61)
+    #
+    # - \x was removed from simple_escape, unless it was not followed by a hex digit, to avoid ambiguity with hex_escape.
+    # - hex_escape allows one or more hex characters, but requires that the next character(if any) is not hex
+    # - decimal_escape allows one or more decimal characters, but requires that the next character(if any) is not a decimal
+    # - bad_escape does not allow any decimals (8-9), to avoid conflicting with the permissive decimal_escape.
+    #
+    # Without this change, python's `re` module would recursively try parsing each ambiguous escape sequence in multiple ways.
+    # e.g. `\123` could be parsed as `\1`+`23`, `\12`+`3`, and `\123`.
+
+    simple_escape = r"""([a-wyzA-Z._~!=&\^\-\\?'"]|x(?![0-9a-fA-F]))"""
+    decimal_escape = r"""(\d+)(?!\d)"""
+    hex_escape = r"""(x[0-9a-fA-F]+)(?![0-9a-fA-F])"""
+    bad_escape = r"""([\\][^a-zA-Z._~^!=&\^\-\\?'"x0-9])"""
 
     escape_sequence = r"""(\\("""+simple_escape+'|'+decimal_escape+'|'+hex_escape+'))'
+
+    # This complicated regex with lookahead might be slow for strings, so because all of the valid escapes (including \x) allowed
+    # 0 or more non-escaped characters after the first character, simple_escape+decimal_escape+hex_escape got simplified to
+
+    escape_sequence_start_in_string = r"""(\\[0-9a-zA-Z._~!=&\^\-\\?'"])"""
+
     cconst_char = r"""([^'\\\n]|"""+escape_sequence+')'
     char_const = "'"+cconst_char+"'"
     wchar_const = 'L'+char_const
+    multicharacter_constant = "'"+cconst_char+"{2,4}'"
     unmatched_quote = "('"+cconst_char+"*\\n)|('"+cconst_char+"*$)"
     bad_char_const = r"""('"""+cconst_char+"""[^'\n]+')|('')|('"""+bad_escape+r"""[^'\n]*')"""
 
     # string literals (K&R2: A.2.6)
-    string_char = r"""([^"\\\n]|"""+escape_sequence+')'
+    string_char = r"""([^"\\\n]|"""+escape_sequence_start_in_string+')'
     string_literal = '"'+string_char+'*"'
     wstring_literal = 'L'+string_literal
-    bad_string_literal = '"'+string_char+'*?'+bad_escape+string_char+'*"'
+    bad_string_literal = '"'+string_char+'*'+bad_escape+string_char+'*"'
 
     # floating constants (K&R2: A.2.5.3)
     exponent_part = r"""([eE][-+]?[0-9]+)"""
@@ -443,6 +469,10 @@
     # Must come before bad_char_const, to prevent it from
     # catching valid char constants as invalid
     #
+    @TOKEN(multicharacter_constant)
+    def t_INT_CONST_CHAR(self, t):
+        return t
+
     @TOKEN(char_const)
     def t_CHAR_CONST(self, t):
         return t
diff --git a/pycparser/c_parser.py b/pycparser/c_parser.py
index 0e6e755..744ede8 100644
--- a/pycparser/c_parser.py
+++ b/pycparser/c_parser.py
@@ -529,8 +529,7 @@
     def p_translation_unit_2(self, p):
         """ translation_unit    : translation_unit external_declaration
         """
-        if p[2] is not None:
-            p[1].extend(p[2])
+        p[1].extend(p[2])
         p[0] = p[1]
 
     # Declarations always come as lists (because they can be
@@ -557,7 +556,7 @@
     def p_external_declaration_4(self, p):
         """ external_declaration    : SEMI
         """
-        p[0] = None
+        p[0] = []
 
     def p_pp_directive(self, p):
         """ pp_directive  : PPHASH
@@ -1411,12 +1410,13 @@
         p[0] = self._type_modify_decl(decl=p[1], modifier=arr)
 
     def p_direct_abstract_declarator_3(self, p):
-        """ direct_abstract_declarator  : LBRACKET assignment_expression_opt RBRACKET
+        """ direct_abstract_declarator  : LBRACKET type_qualifier_list_opt assignment_expression_opt RBRACKET
         """
+        quals = (p[2] if len(p) > 4 else []) or []
         p[0] = c_ast.ArrayDecl(
             type=c_ast.TypeDecl(None, None, None),
-            dim=p[2],
-            dim_quals=[],
+            dim=p[3] if len(p) > 4 else p[2],
+            dim_quals=quals,
             coord=self._token_coord(p, 1))
 
     def p_direct_abstract_declarator_4(self, p):
@@ -1740,8 +1740,7 @@
         if len(p) == 2:
             p[0] = p[1]
         elif len(p) == 4:
-            field = c_ast.ID(p[3], self._token_coord(p, 3))
-            p[0] = c_ast.StructRef(p[1], p[2], field, p[1].coord)
+            p[0] = c_ast.StructRef(p[1], p[2], p[3], p[1].coord)
         elif len(p) == 5:
             p[0] = c_ast.ArrayRef(p[1], p[3], p[1].coord)
         else:
@@ -1766,9 +1765,23 @@
                         | INT_CONST_OCT
                         | INT_CONST_HEX
                         | INT_CONST_BIN
+                        | INT_CONST_CHAR
         """
+        uCount = 0
+        lCount = 0
+        for x in p[1][-3:]:
+            if x in ('l', 'L'):
+                lCount += 1
+            elif x in ('u', 'U'):
+                uCount += 1
+        t = ''
+        if uCount > 1:
+             raise ValueError('Constant cannot have more than one u/U suffix.')
+        elif lCount > 2:
+             raise ValueError('Constant cannot have more than two l/L suffix.')
+        prefix = 'unsigned ' * uCount + 'long ' * lCount
         p[0] = c_ast.Constant(
-            'int', p[1], self._token_coord(p, 1))
+            prefix + 'int', p[1], self._token_coord(p, 1))
 
     def p_constant_2(self, p):
         """ constant    : FLOAT_CONST
diff --git a/setup.py b/setup.py
index 62eddc2..6dce89c 100644
--- a/setup.py
+++ b/setup.py
@@ -43,7 +43,7 @@
         C compilers or analysis tools.
     """,
     license='BSD',
-    version='2.19',
+    version='2.20',
     author='Eli Bendersky',
     maintainer='Eli Bendersky',
     author_email='eliben@gmail.com',
diff --git a/tests/test_c_generator.py b/tests/test_c_generator.py
index 3727f91..dd19a11 100644
--- a/tests/test_c_generator.py
+++ b/tests/test_c_generator.py
@@ -1,11 +1,12 @@
+import os
+import platform
 import sys
-import textwrap
 import unittest
 
 # Run from the root dir
 sys.path.insert(0, '.')
 
-from pycparser import c_parser, c_generator, c_ast
+from pycparser import c_parser, c_generator, c_ast, parse_file
 
 _c_parser = c_parser.CParser(
                 lex_optimize=False,
@@ -332,6 +333,62 @@
             name='',
         )
 
+    def test_array_decl(self):
+        self._assert_ctoc_correct('int g(const int a[const 20]){}')
+        ast = parse_to_ast('const int a[const 20];')
+        generator = c_generator.CGenerator()
+        self.assertEqual(generator.visit(ast.ext[0].type),
+                         'const int [const 20]')
+        self.assertEqual(generator.visit(ast.ext[0].type.type),
+                         'const int')
+
+    def test_ptr_decl(self):
+        src = 'const int ** const  x;'
+        self._assert_ctoc_correct(src)
+        ast = parse_to_ast(src)
+        generator = c_generator.CGenerator()
+        self.assertEqual(generator.visit(ast.ext[0].type),
+                         'const int ** const')
+        self.assertEqual(generator.visit(ast.ext[0].type.type),
+                         'const int *')
+        self.assertEqual(generator.visit(ast.ext[0].type.type.type),
+                         'const int')
+
+
+class TestCasttoC(unittest.TestCase):
+    def _find_file(self, name):
+        test_dir = os.path.dirname(__file__)
+        name = os.path.join(test_dir, 'c_files', name)
+        assert os.path.exists(name)
+        return name
+
+    def test_to_type(self):
+        src = 'int *x;'
+        generator = c_generator.CGenerator()
+        test_fun = c_ast.FuncCall(c_ast.ID('test_fun'), c_ast.ExprList([]))
+
+        ast1 = parse_to_ast(src)
+        int_ptr_type = ast1.ext[0].type
+        int_type = int_ptr_type.type
+        self.assertEqual(generator.visit(c_ast.Cast(int_ptr_type, test_fun)),
+                         '(int *) test_fun()')
+        self.assertEqual(generator.visit(c_ast.Cast(int_type, test_fun)),
+                         '(int) test_fun()')
+
+    @unittest.skipUnless(platform.system() == 'Linux',
+                         'cpp only works on Linux')
+    def test_to_type_with_cpp(self):
+        generator = c_generator.CGenerator()
+        test_fun = c_ast.FuncCall(c_ast.ID('test_fun'), c_ast.ExprList([]))
+        memmgr_path = self._find_file('memmgr.h')
+
+        ast2 = parse_file(memmgr_path, use_cpp=True)
+        void_ptr_type = ast2.ext[-3].type.type
+        void_type = void_ptr_type.type
+        self.assertEqual(generator.visit(c_ast.Cast(void_ptr_type, test_fun)),
+                         '(void *) test_fun()')
+        self.assertEqual(generator.visit(c_ast.Cast(void_type, test_fun)),
+                         '(void) test_fun()')
 
 if __name__ == "__main__":
     unittest.main()
diff --git a/tests/test_c_lexer.py b/tests/test_c_lexer.py
index 11c7b26..d63d6fd 100644
--- a/tests/test_c_lexer.py
+++ b/tests/test_c_lexer.py
@@ -77,6 +77,10 @@
         self.assertTokensTypes('0xf7', ['INT_CONST_HEX'])
         self.assertTokensTypes('0b110', ['INT_CONST_BIN'])
         self.assertTokensTypes('0x01202AAbbf7Ul', ['INT_CONST_HEX'])
+        self.assertTokensTypes("'12'", ['INT_CONST_CHAR'])
+        self.assertTokensTypes("'123'", ['INT_CONST_CHAR'])
+        self.assertTokensTypes("'1AB4'", ['INT_CONST_CHAR'])
+        self.assertTokensTypes(r"'1A\n4'", ['INT_CONST_CHAR'])
 
         # no 0 before x, so ID catches it
         self.assertTokensTypes('xf7', ['ID'])
@@ -116,6 +120,7 @@
         self.assertTokensTypes(r"""'\t'""", ['CHAR_CONST'])
         self.assertTokensTypes(r"""'\''""", ['CHAR_CONST'])
         self.assertTokensTypes(r"""'\?'""", ['CHAR_CONST'])
+        self.assertTokensTypes(r"""'\0'""", ['CHAR_CONST'])
         self.assertTokensTypes(r"""'\012'""", ['CHAR_CONST'])
         self.assertTokensTypes(r"""'\x2f'""", ['CHAR_CONST'])
         self.assertTokensTypes(r"""'\x2f12'""", ['CHAR_CONST'])
@@ -149,6 +154,24 @@
         self.assertTokensTypes(
             '"\123\123\123\123\123\123\123\123\123\123\123\123\123\123\123\123"',
             ['STRING_LITERAL'])
+        # Note: a-zA-Z and '.-~^_!=&;,' are allowed as escape chars to support #line
+        # directives with Windows paths as filenames (..\..\dir\file)
+        self.assertTokensTypes(
+            r'"\x"',
+            ['STRING_LITERAL'])
+        self.assertTokensTypes(
+            r'"\a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z\A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z"',
+            ['STRING_LITERAL'])
+        self.assertTokensTypes(
+            r'"C:\x\fa\x1e\xited"',
+            ['STRING_LITERAL'])
+        # The lexer is permissive and allows decimal escapes (not just octal)
+        self.assertTokensTypes(
+            '"jx\9"',
+            ['STRING_LITERAL'])
+        self.assertTokensTypes(
+            '"fo\9999999"',
+            ['STRING_LITERAL'])
 
     def test_mess(self):
         self.assertTokensTypes(
@@ -428,14 +451,24 @@
     def test_char_constants(self):
         self.assertLexerError("'", ERR_UNMATCHED_QUOTE)
         self.assertLexerError("'b\n", ERR_UNMATCHED_QUOTE)
-
-        self.assertLexerError("'jx'", ERR_INVALID_CCONST)
+        self.assertLexerError("'\\xaa\n'", ERR_UNMATCHED_QUOTE)
+        
+        self.assertLexerError(r"'123\12a'", ERR_INVALID_CCONST)
+        self.assertLexerError(r"'123\xabg'", ERR_INVALID_CCONST)
+        self.assertLexerError("''", ERR_INVALID_CCONST)
+        self.assertLexerError("'abcjx'", ERR_INVALID_CCONST)
         self.assertLexerError(r"'\*'", ERR_INVALID_CCONST)
 
     def test_string_literals(self):
-        self.assertLexerError(r'"jx\9"', ERR_STRING_ESCAPE)
+        self.assertLexerError(r'"jx\`"', ERR_STRING_ESCAPE)
         self.assertLexerError(r'"hekllo\* on ix"', ERR_STRING_ESCAPE)
         self.assertLexerError(r'L"hekllo\* on ix"', ERR_STRING_ESCAPE)
+        # Should not suffer from slow backtracking
+        self.assertLexerError(r'"\123\123\123\123\123\123\123\123\123\123\123\123\123\123\123\123\123\123\123\`\123\123\123\123\123\123\123\123\123\123\123\123\123\123\123\123\123\123\123\123"', ERR_STRING_ESCAPE)
+        self.assertLexerError(r'"\xf1\x23\xf1\x23\xf1\x23\xf1\x23\xf1\x23\xf1\x23\xf1\x23\xf1\x23\xf1\x23\x23\`\xf1\x23\xf1\x23\xf1\x23\xf1\x23\xf1\x23\xf1\x23\xf1\x23\xf1\x23\xf1\x23\xf1\x23"', ERR_STRING_ESCAPE)
+        # Should not suffer from slow backtracking when there's no end quote
+        self.assertLexerError(r'"\123\123\123\123\123\123\123\123\123\123\123\123\123\123\123\`\123\123\123\123\123\123\123\123\123\123\123\123\123\123\123\123\123\123\12\123456', ERR_ILLEGAL_CHAR)
+        self.assertLexerError(r'"\x23\x23\x23\x23\x23\x23\x23\x23\x23\x23\x23\x23\x23\x23\x23\`\x23\x23\x23\x23\x23\x23\x23\x23\x23\x23\x23\x23\x23\x23\x23\x23\x23\x23\x2\x23456', ERR_ILLEGAL_CHAR)
 
     def test_preprocessor(self):
         self.assertLexerError('#line "ka"', ERR_FILENAME_BEFORE_LINE)
diff --git a/tests/test_c_parser.py b/tests/test_c_parser.py
index a48f1c6..b6ecdd5 100755
--- a/tests/test_c_parser.py
+++ b/tests/test_c_parser.py
@@ -136,6 +136,15 @@
             ['Decl', 'foo',
                 ['TypeDecl', ['IdentifierType', ['int']]]])
 
+    def test_initial_semi(self):
+        t = self.parse(';')
+        self.assertEqual(len(t.ext), 0)
+        t = self.parse(';int foo;')
+        self.assertEqual(len(t.ext), 1)
+        self.assertEqual(expand_decl(t.ext[0]),
+            ['Decl', 'foo',
+                ['TypeDecl', ['IdentifierType', ['int']]]])
+
     def test_coords(self):
         """ Tests the "coordinates" of parsed elements - file
             name, line and column numbers, with modification
@@ -413,6 +422,7 @@
                         ['TypeDecl', ['IdentifierType', ['int']]]]]])
 
     def test_func_decls_with_array_dim_qualifiers(self):
+        # named function parameter
         self.assertEqual(self.get_decl('int zz(int p[static 10]);'),
             ['Decl', 'zz',
                 ['FuncDecl',
@@ -443,6 +453,30 @@
                             ['TypeDecl', ['IdentifierType', ['int']]]]]]],
                     ['TypeDecl', ['IdentifierType', ['int']]]]])
 
+        # unnamed function parameter
+        self.assertEqual(self.get_decl('int zz(int [const 10]);'),
+            ['Decl', 'zz',
+                ['FuncDecl',
+                    [['Typename', ['ArrayDecl', '10', ['const'],
+                                       ['TypeDecl', ['IdentifierType', ['int']]]]]],
+                    ['TypeDecl', ['IdentifierType', ['int']]]]])
+
+        self.assertEqual(self.get_decl('int zz(int [restrict][5]);'),
+            ['Decl', 'zz',
+                ['FuncDecl',
+                    [['Typename', ['ArrayDecl', '', ['restrict'],
+                        ['ArrayDecl', '5', [],
+                            ['TypeDecl', ['IdentifierType', ['int']]]]]]],
+                    ['TypeDecl', ['IdentifierType', ['int']]]]])
+
+        self.assertEqual(self.get_decl('int zz(int [const restrict volatile 10][5]);'),
+            ['Decl', 'zz',
+                ['FuncDecl',
+                    [['Typename', ['ArrayDecl', '10', ['const', 'restrict', 'volatile'],
+                        ['ArrayDecl', '5', [],
+                            ['TypeDecl', ['IdentifierType', ['int']]]]]]],
+                    ['TypeDecl', ['IdentifierType', ['int']]]]])
+
     def test_qualifiers_storage_specifiers(self):
         def assert_qs(txt, index, quals, storage):
             d = self.parse(txt).ext[index]
@@ -495,6 +529,18 @@
                             ['IdentifierType', ['int']]]]]])
 
     def test_offsetof(self):
+        def expand_ref(n):
+            if isinstance(n, StructRef):
+                return ['StructRef', expand_ref(n.name), expand_ref(n.field)]
+            elif isinstance(n, ArrayRef):
+                return ['ArrayRef', expand_ref(n.name), expand_ref(n.subscript)]
+            elif isinstance(n, ID):
+                return ['ID', n.name]
+            elif isinstance(n, Constant):
+                return ['Constant', n.type, n.value]
+            else:
+                raise TypeError("Unexpected type " + n.__class__.__name__)
+
         e = """
             void foo() {
                 int a = offsetof(struct S, p);
@@ -512,8 +558,20 @@
         self.assertIsInstance(s1.args.exprs[1], ID)
         s3 = compound.block_items[2].init
         self.assertIsInstance(s3.args.exprs[1], StructRef)
+        self.assertEqual(expand_ref(s3.args.exprs[1]),
+            ['StructRef',
+                ['StructRef', ['ID', 'p'], ['ID', 'q']],
+                ['ID', 'r']])
         s4 = compound.block_items[3].init
         self.assertIsInstance(s4.args.exprs[1], ArrayRef)
+        self.assertEqual(expand_ref(s4.args.exprs[1]),
+            ['ArrayRef',
+                ['ArrayRef',
+                    ['StructRef',
+                        ['ArrayRef', ['ID', 'p'], ['Constant', 'int', '5']],
+                        ['ID', 'q']],
+                    ['Constant', 'int', '4']],
+                ['Constant', 'int', '5']])
 
     def test_compound_statement(self):
         e = """
@@ -828,6 +886,19 @@
                     ['Decl', 'd',
                         ['TypeDecl', ['IdentifierType', ['char']]]]]]]])
 
+    def test_struct_with_initial_semi(self):
+        s1 = """
+            struct {
+                ;int a;
+            } foo;
+        """
+        s1_ast = self.parse(s1)
+        self.assertEqual(expand_decl(s1_ast.ext[0]),
+            ['Decl', 'foo',
+                ['TypeDecl', ['Struct', None,
+                    [['Decl', 'a',
+                        ['TypeDecl', ['IdentifierType', ['int']]]]]]]])
+
     def test_anonymous_struct_union(self):
         s1 = """
             union
@@ -1240,6 +1311,22 @@
         self.assertEqual(self.get_decl_init(d55),
             ['Constant', 'float', '0xDE.38p0'])
 
+        d6 = 'int i = 1;'
+        self.assertEqual(self.get_decl_init(d6),
+            ['Constant', 'int', '1'])
+
+        d61 = 'long int li = 1l;'
+        self.assertEqual(self.get_decl_init(d61),
+            ['Constant', 'long int', '1l'])
+
+        d62 = 'unsigned int ui = 1u;'
+        self.assertEqual(self.get_decl_init(d62),
+            ['Constant', 'unsigned int', '1u'])
+
+        d63 = 'unsigned long long int ulli = 1LLU;'
+        self.assertEqual(self.get_decl_init(d63),
+            ['Constant', 'unsigned long long int', '1LLU'])
+
     def test_decl_named_inits(self):
         d1 = 'int a = {.k = 16};'
         self.assertEqual(self.get_decl_init(d1),
@@ -1407,6 +1494,10 @@
             void main() {
                 #pragma foo
                 for(;;) {}
+                #pragma baz
+                {
+                    int i = 0;
+                }
                 #pragma
             }
             struct s {
@@ -1423,12 +1514,16 @@
         self.assertEqual(s1_ast.ext[1].body.block_items[0].coord.line, 4)
 
         self.assertIsInstance(s1_ast.ext[1].body.block_items[2], Pragma)
-        self.assertEqual(s1_ast.ext[1].body.block_items[2].string, '')
+        self.assertEqual(s1_ast.ext[1].body.block_items[2].string, 'baz')
         self.assertEqual(s1_ast.ext[1].body.block_items[2].coord.line, 6)
 
+        self.assertIsInstance(s1_ast.ext[1].body.block_items[4], Pragma)
+        self.assertEqual(s1_ast.ext[1].body.block_items[4].string, '')
+        self.assertEqual(s1_ast.ext[1].body.block_items[4].coord.line, 10)
+
         self.assertIsInstance(s1_ast.ext[2].type.type.decls[0], Pragma)
         self.assertEqual(s1_ast.ext[2].type.type.decls[0].string, 'baz')
-        self.assertEqual(s1_ast.ext[2].type.type.decls[0].coord.line, 9)
+        self.assertEqual(s1_ast.ext[2].type.type.decls[0].coord.line, 13)
 
     def test_pragmacomp_or_statement(self):
         s1 = r'''
@@ -1475,8 +1570,10 @@
         self.assertIsInstance(s1_ast.ext[0].body.block_items[4].iftrue.block_items[1], Assignment)
         self.assertIsInstance(s1_ast.ext[0].body.block_items[5], Switch)
         self.assertIsInstance(s1_ast.ext[0].body.block_items[5].stmt.stmts[0], Compound)
-        self.assertIsInstance(s1_ast.ext[0].body.block_items[5].stmt.stmts[0].block_items[0], Pragma)
-        self.assertIsInstance(s1_ast.ext[0].body.block_items[5].stmt.stmts[0].block_items[1], Assignment)
+        self.assertIsInstance(s1_ast.ext[0].body.block_items[5].stmt.stmts[0].block_items[0],
+                              Pragma)
+        self.assertIsInstance(s1_ast.ext[0].body.block_items[5].stmt.stmts[0].block_items[1],
+                              Assignment)
 
 
 class TestCParser_whole_code(TestCParser_base):
@@ -1719,6 +1816,7 @@
         switch = ps1.ext[0].body.block_items[0]
 
         block = switch.stmt.block_items
+        self.assertEqual(len(block), 4)
         assert_case_node(block[0], '10')
         self.assertEqual(len(block[0].stmts), 3)
         assert_case_node(block[1], '20')
@@ -1746,6 +1844,7 @@
         switch = ps2.ext[0].body.block_items[0]
 
         block = switch.stmt.block_items
+        self.assertEqual(len(block), 5)
         assert_default_node(block[0])
         self.assertEqual(len(block[0].stmts), 2)
         assert_case_node(block[1], '10')
@@ -1757,6 +1856,18 @@
         assert_case_node(block[4], '40')
         self.assertEqual(len(block[4].stmts), 1)
 
+        s3 = r'''
+        int foo(void) {
+            switch (myvar) {
+            }
+            return 0;
+        }
+        '''
+        ps3 = self.parse(s3)
+        switch = ps3.ext[0].body.block_items[0]
+
+        self.assertEqual(switch.stmt.block_items, [])
+
     def test_for_statement(self):
         s2 = r'''
         void x(void)
diff --git a/utils/benchmark/README.rst b/utils/benchmark/README.rst
new file mode 100644
index 0000000..652b274
--- /dev/null
+++ b/utils/benchmark/README.rst
@@ -0,0 +1,22 @@
+Basic benchmarking of parsing speed with pycparser.
+
+The ``inputs`` directory contains preprocessed files taken from open source
+projects.
+
+``redis.c.pp`` taken from Redis. Generated with:
+
+.. sourcecode::
+
+   gcc -nostdinc -D'__attribute__(x)=' -E -Isrc/ -Ideps/hiredis -Ideps/linenoise -I$HOME/eli/pycparser/utils/fake_libc_include src/redis-cli.c
+
+``tccgen.c.pp`` taken from TCC. Generated with:
+
+.. sourcecode::
+
+   gcc -nostdinc -D'__attribute__(x)=' -E -I.  -I$HOME/eli/pycparser/utils/fake_libc_include tccgen.c
+
+``sqlite-btree.c.pp`` taken from SQLite. Generated with:
+
+.. sourcecode::
+
+   gcc -nostdinc -D'__attribute__(x)=' -E -I. -Isrc/ -I$HOME/eli/pycparser/utils/fake_libc_include src/btree.c
diff --git a/utils/benchmark/benchmark-parse.py b/utils/benchmark/benchmark-parse.py
new file mode 100644
index 0000000..003acda
--- /dev/null
+++ b/utils/benchmark/benchmark-parse.py
@@ -0,0 +1,58 @@
+#-----------------------------------------------------------------
+# Benchmarking utility for internal use.
+#
+# Use with Python 3.6+
+#
+# Eli Bendersky [https://eli.thegreenplace.net/]
+# License: BSD
+#-----------------------------------------------------------------
+import os
+import statistics
+import sys
+import time
+
+sys.path.extend(['.', '..'])
+
+from pycparser import c_parser, c_ast
+
+
+def measure_parse(text, n, progress_cb):
+    """Measure the parsing of text with pycparser.
+
+    text should represent a full file. n is the number of iterations to measure.
+    progress_cb will be called with the iteration number each time one is done.
+
+    Returns a list of elapsed times, one per iteration.
+    """
+    times = []
+    for i in range(n):
+        parser = c_parser.CParser()
+        t1 = time.time()
+        ast = parser.parse(text, '')
+        elapsed = time.time() - t1
+        assert isinstance(ast, c_ast.FileAST)
+        times.append(elapsed)
+        progress_cb(i)
+    return times
+
+
+def measure_file(filename, n):
+    progress_cb = lambda i: print('.', sep='', end='', flush=True)
+    with open(filename) as f:
+        print('%-25s' % os.path.basename(filename), end='', flush=True)
+        text = f.read()
+        times = measure_parse(text, n, progress_cb)
+    print('    Mean: %.3f  Stddev: %.3f' % (statistics.mean(times),
+                                            statistics.stdev(times)))
+
+
+NUM_RUNS = 5
+
+
+if __name__ == '__main__':
+    if len(sys.argv) < 2:
+        print("Usage: %s <dir with input files>")
+        sys.exit(1)
+    for filename in os.listdir(sys.argv[1]):
+        filename = os.path.join(sys.argv[1], filename)
+        measure_file(filename, NUM_RUNS)
diff --git a/utils/benchmark/inputs/redis.c.ppout b/utils/benchmark/inputs/redis.c.ppout
new file mode 100644
index 0000000..b1fa222
--- /dev/null
+++ b/utils/benchmark/inputs/redis.c.ppout
@@ -0,0 +1,4621 @@
+# 1 "src/redis-cli.c"
+# 1 "<built-in>"
+# 1 "<command-line>"
+# 1 "src/redis-cli.c"
+# 31 "src/redis-cli.c"
+# 1 "src/fmacros.h" 1
+# 32 "src/redis-cli.c" 2
+# 1 "src/version.h" 1
+# 33 "src/redis-cli.c" 2
+
+# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/stdio.h" 1
+# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/_fake_defines.h" 1
+# 2 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/stdio.h" 2
+# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/_fake_typedefs.h" 1
+
+
+
+typedef int size_t;
+typedef int __builtin_va_list;
+typedef int __gnuc_va_list;
+typedef int va_list;
+typedef int __int8_t;
+typedef int __uint8_t;
+typedef int __int16_t;
+typedef int __uint16_t;
+typedef int __int_least16_t;
+typedef int __uint_least16_t;
+typedef int __int32_t;
+typedef int __uint32_t;
+typedef int __int64_t;
+typedef int __uint64_t;
+typedef int __int_least32_t;
+typedef int __uint_least32_t;
+typedef int __s8;
+typedef int __u8;
+typedef int __s16;
+typedef int __u16;
+typedef int __s32;
+typedef int __u32;
+typedef int __s64;
+typedef int __u64;
+typedef int _LOCK_T;
+typedef int _LOCK_RECURSIVE_T;
+typedef int _off_t;
+typedef int __dev_t;
+typedef int __uid_t;
+typedef int __gid_t;
+typedef int _off64_t;
+typedef int _fpos_t;
+typedef int _ssize_t;
+typedef int wint_t;
+typedef int _mbstate_t;
+typedef int _flock_t;
+typedef int _iconv_t;
+typedef int __ULong;
+typedef int __FILE;
+typedef int ptrdiff_t;
+typedef int wchar_t;
+typedef int __off_t;
+typedef int __pid_t;
+typedef int __loff_t;
+typedef int u_char;
+typedef int u_short;
+typedef int u_int;
+typedef int u_long;
+typedef int ushort;
+typedef int uint;
+typedef int clock_t;
+typedef int time_t;
+typedef int daddr_t;
+typedef int caddr_t;
+typedef int ino_t;
+typedef int off_t;
+typedef int dev_t;
+typedef int uid_t;
+typedef int gid_t;
+typedef int pid_t;
+typedef int key_t;
+typedef int ssize_t;
+typedef int mode_t;
+typedef int nlink_t;
+typedef int fd_mask;
+typedef int _types_fd_set;
+typedef int clockid_t;
+typedef int timer_t;
+typedef int useconds_t;
+typedef int suseconds_t;
+typedef int FILE;
+typedef int fpos_t;
+typedef int cookie_read_function_t;
+typedef int cookie_write_function_t;
+typedef int cookie_seek_function_t;
+typedef int cookie_close_function_t;
+typedef int cookie_io_functions_t;
+typedef int div_t;
+typedef int ldiv_t;
+typedef int lldiv_t;
+typedef int sigset_t;
+typedef int __sigset_t;
+typedef int _sig_func_ptr;
+typedef int sig_atomic_t;
+typedef int __tzrule_type;
+typedef int __tzinfo_type;
+typedef int mbstate_t;
+typedef int sem_t;
+typedef int pthread_t;
+typedef int pthread_attr_t;
+typedef int pthread_mutex_t;
+typedef int pthread_mutexattr_t;
+typedef int pthread_cond_t;
+typedef int pthread_condattr_t;
+typedef int pthread_key_t;
+typedef int pthread_once_t;
+typedef int pthread_rwlock_t;
+typedef int pthread_rwlockattr_t;
+typedef int pthread_spinlock_t;
+typedef int pthread_barrier_t;
+typedef int pthread_barrierattr_t;
+typedef int jmp_buf;
+typedef int rlim_t;
+typedef int sa_family_t;
+typedef int sigjmp_buf;
+typedef int stack_t;
+typedef int siginfo_t;
+typedef int z_stream;
+
+
+typedef int int8_t;
+typedef int uint8_t;
+typedef int int16_t;
+typedef int uint16_t;
+typedef int int32_t;
+typedef int uint32_t;
+typedef int int64_t;
+typedef int uint64_t;
+
+
+typedef int int_least8_t;
+typedef int uint_least8_t;
+typedef int int_least16_t;
+typedef int uint_least16_t;
+typedef int int_least32_t;
+typedef int uint_least32_t;
+typedef int int_least64_t;
+typedef int uint_least64_t;
+
+
+typedef int int_fast8_t;
+typedef int uint_fast8_t;
+typedef int int_fast16_t;
+typedef int uint_fast16_t;
+typedef int int_fast32_t;
+typedef int uint_fast32_t;
+typedef int int_fast64_t;
+typedef int uint_fast64_t;
+
+
+typedef int intptr_t;
+typedef int uintptr_t;
+
+
+typedef int intmax_t;
+typedef int uintmax_t;
+
+
+typedef _Bool bool;
+
+
+typedef void* MirEGLNativeWindowType;
+typedef void* MirEGLNativeDisplayType;
+typedef struct MirConnection MirConnection;
+typedef struct MirSurface MirSurface;
+typedef struct MirSurfaceSpec MirSurfaceSpec;
+typedef struct MirScreencast MirScreencast;
+typedef struct MirPromptSession MirPromptSession;
+typedef struct MirBufferStream MirBufferStream;
+typedef struct MirPersistentId MirPersistentId;
+typedef struct MirBlob MirBlob;
+typedef struct MirDisplayConfig MirDisplayConfig;
+
+
+typedef struct xcb_connection_t xcb_connection_t;
+typedef uint32_t xcb_window_t;
+typedef uint32_t xcb_visualid_t;
+# 2 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/stdio.h" 2
+# 35 "src/redis-cli.c" 2
+# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/string.h" 1
+# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/_fake_defines.h" 1
+# 2 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/string.h" 2
+# 36 "src/redis-cli.c" 2
+# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/stdlib.h" 1
+# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/_fake_defines.h" 1
+# 2 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/stdlib.h" 2
+# 37 "src/redis-cli.c" 2
+# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/signal.h" 1
+# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/_fake_defines.h" 1
+# 2 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/signal.h" 2
+# 38 "src/redis-cli.c" 2
+# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/unistd.h" 1
+# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/_fake_defines.h" 1
+# 2 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/unistd.h" 2
+# 39 "src/redis-cli.c" 2
+# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/time.h" 1
+# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/_fake_defines.h" 1
+# 2 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/time.h" 2
+# 40 "src/redis-cli.c" 2
+# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/ctype.h" 1
+# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/_fake_defines.h" 1
+# 2 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/ctype.h" 2
+# 41 "src/redis-cli.c" 2
+# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/errno.h" 1
+# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/_fake_defines.h" 1
+# 2 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/errno.h" 2
+# 42 "src/redis-cli.c" 2
+# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/sys/stat.h" 1
+# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/_fake_defines.h" 1
+# 2 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/sys/stat.h" 2
+# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/_fake_typedefs.h" 1
+# 2 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/sys/stat.h" 2
+# 43 "src/redis-cli.c" 2
+# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/sys/time.h" 1
+# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/_fake_defines.h" 1
+# 2 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/sys/time.h" 2
+# 44 "src/redis-cli.c" 2
+# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/assert.h" 1
+# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/_fake_defines.h" 1
+# 2 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/assert.h" 2
+# 45 "src/redis-cli.c" 2
+# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/fcntl.h" 1
+# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/_fake_defines.h" 1
+# 2 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/fcntl.h" 2
+# 46 "src/redis-cli.c" 2
+# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/limits.h" 1
+# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/_fake_defines.h" 1
+# 2 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/limits.h" 2
+# 47 "src/redis-cli.c" 2
+# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/math.h" 1
+# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/_fake_defines.h" 1
+# 2 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/math.h" 2
+# 48 "src/redis-cli.c" 2
+
+# 1 "deps/hiredis/hiredis.h" 1
+# 36 "deps/hiredis/hiredis.h"
+# 1 "deps/hiredis/read.h" 1
+# 35 "deps/hiredis/read.h"
+# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/stdio.h" 1
+# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/_fake_defines.h" 1
+# 2 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/stdio.h" 2
+# 36 "deps/hiredis/read.h" 2
+# 63 "deps/hiredis/read.h"
+typedef struct redisReadTask {
+    int type;
+    int elements;
+    int idx;
+    void *obj;
+    struct redisReadTask *parent;
+    void *privdata;
+} redisReadTask;
+
+typedef struct redisReplyObjectFunctions {
+    void *(*createString)(const redisReadTask*, char*, size_t);
+    void *(*createArray)(const redisReadTask*, int);
+    void *(*createInteger)(const redisReadTask*, long long);
+    void *(*createNil)(const redisReadTask*);
+    void (*freeObject)(void*);
+} redisReplyObjectFunctions;
+
+typedef struct redisReader {
+    int err;
+    char errstr[128];
+
+    char *buf;
+    size_t pos;
+    size_t len;
+    size_t maxbuf;
+
+    redisReadTask rstack[9];
+    int ridx;
+    void *reply;
+
+    redisReplyObjectFunctions *fn;
+    void *privdata;
+} redisReader;
+
+
+redisReader *redisReaderCreateWithFunctions(redisReplyObjectFunctions *fn);
+void redisReaderFree(redisReader *r);
+int redisReaderFeed(redisReader *r, const char *buf, size_t len);
+int redisReaderGetReply(redisReader *r, void **reply);
+# 37 "deps/hiredis/hiredis.h" 2
+# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/stdarg.h" 1
+# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/_fake_defines.h" 1
+# 2 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/stdarg.h" 2
+# 38 "deps/hiredis/hiredis.h" 2
+# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/sys/time.h" 1
+# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/_fake_defines.h" 1
+# 2 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/sys/time.h" 2
+# 39 "deps/hiredis/hiredis.h" 2
+# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/stdint.h" 1
+# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/_fake_defines.h" 1
+# 2 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/stdint.h" 2
+# 40 "deps/hiredis/hiredis.h" 2
+# 1 "deps/hiredis/sds.h" 1
+# 38 "deps/hiredis/sds.h"
+# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/sys/types.h" 1
+# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/_fake_defines.h" 1
+# 2 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/sys/types.h" 2
+# 39 "deps/hiredis/sds.h" 2
+# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/stdarg.h" 1
+# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/_fake_defines.h" 1
+# 2 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/stdarg.h" 2
+# 40 "deps/hiredis/sds.h" 2
+# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/stdint.h" 1
+# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/_fake_defines.h" 1
+# 2 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/stdint.h" 2
+# 41 "deps/hiredis/sds.h" 2
+
+typedef char *sds;
+
+
+
+struct sdshdr5 {
+    unsigned char flags;
+    char buf[];
+};
+struct sdshdr8 {
+    uint8_t len;
+    uint8_t alloc;
+    unsigned char flags;
+    char buf[];
+};
+struct sdshdr16 {
+    uint16_t len;
+    uint16_t alloc;
+    unsigned char flags;
+    char buf[];
+};
+struct sdshdr32 {
+    uint32_t len;
+    uint32_t alloc;
+    unsigned char flags;
+    char buf[];
+};
+struct sdshdr64 {
+    uint64_t len;
+    uint64_t alloc;
+    unsigned char flags;
+    char buf[];
+};
+# 86 "deps/hiredis/sds.h"
+static inline size_t sdslen(const sds s) {
+    unsigned char flags = s[-1];
+    switch(flags&7) {
+        case 0:
+            return ((flags)>>3);
+        case 1:
+            return ((struct sdshdr8 *)((s)-(sizeof(struct sdshdr8))))->len;
+        case 2:
+            return ((struct sdshdr16 *)((s)-(sizeof(struct sdshdr16))))->len;
+        case 3:
+            return ((struct sdshdr32 *)((s)-(sizeof(struct sdshdr32))))->len;
+        case 4:
+            return ((struct sdshdr64 *)((s)-(sizeof(struct sdshdr64))))->len;
+    }
+    return 0;
+}
+
+static inline size_t sdsavail(const sds s) {
+    unsigned char flags = s[-1];
+    switch(flags&7) {
+        case 0: {
+            return 0;
+        }
+        case 1: {
+            struct sdshdr8 *sh = (struct sdshdr8 *)((s)-(sizeof(struct sdshdr8)));;
+            return sh->alloc - sh->len;
+        }
+        case 2: {
+            struct sdshdr16 *sh = (struct sdshdr16 *)((s)-(sizeof(struct sdshdr16)));;
+            return sh->alloc - sh->len;
+        }
+        case 3: {
+            struct sdshdr32 *sh = (struct sdshdr32 *)((s)-(sizeof(struct sdshdr32)));;
+            return sh->alloc - sh->len;
+        }
+        case 4: {
+            struct sdshdr64 *sh = (struct sdshdr64 *)((s)-(sizeof(struct sdshdr64)));;
+            return sh->alloc - sh->len;
+        }
+    }
+    return 0;
+}
+
+static inline void sdssetlen(sds s, size_t newlen) {
+    unsigned char flags = s[-1];
+    switch(flags&7) {
+        case 0:
+            {
+                unsigned char *fp = ((unsigned char*)s)-1;
+                *fp = 0 | (newlen << 3);
+            }
+            break;
+        case 1:
+            ((struct sdshdr8 *)((s)-(sizeof(struct sdshdr8))))->len = newlen;
+            break;
+        case 2:
+            ((struct sdshdr16 *)((s)-(sizeof(struct sdshdr16))))->len = newlen;
+            break;
+        case 3:
+            ((struct sdshdr32 *)((s)-(sizeof(struct sdshdr32))))->len = newlen;
+            break;
+        case 4:
+            ((struct sdshdr64 *)((s)-(sizeof(struct sdshdr64))))->len = newlen;
+            break;
+    }
+}
+
+static inline void sdsinclen(sds s, size_t inc) {
+    unsigned char flags = s[-1];
+    switch(flags&7) {
+        case 0:
+            {
+                unsigned char *fp = ((unsigned char*)s)-1;
+                unsigned char newlen = ((flags)>>3)+inc;
+                *fp = 0 | (newlen << 3);
+            }
+            break;
+        case 1:
+            ((struct sdshdr8 *)((s)-(sizeof(struct sdshdr8))))->len += inc;
+            break;
+        case 2:
+            ((struct sdshdr16 *)((s)-(sizeof(struct sdshdr16))))->len += inc;
+            break;
+        case 3:
+            ((struct sdshdr32 *)((s)-(sizeof(struct sdshdr32))))->len += inc;
+            break;
+        case 4:
+            ((struct sdshdr64 *)((s)-(sizeof(struct sdshdr64))))->len += inc;
+            break;
+    }
+}
+
+
+static inline size_t sdsalloc(const sds s) {
+    unsigned char flags = s[-1];
+    switch(flags&7) {
+        case 0:
+            return ((flags)>>3);
+        case 1:
+            return ((struct sdshdr8 *)((s)-(sizeof(struct sdshdr8))))->alloc;
+        case 2:
+            return ((struct sdshdr16 *)((s)-(sizeof(struct sdshdr16))))->alloc;
+        case 3:
+            return ((struct sdshdr32 *)((s)-(sizeof(struct sdshdr32))))->alloc;
+        case 4:
+            return ((struct sdshdr64 *)((s)-(sizeof(struct sdshdr64))))->alloc;
+    }
+    return 0;
+}
+
+static inline void sdssetalloc(sds s, size_t newlen) {
+    unsigned char flags = s[-1];
+    switch(flags&7) {
+        case 0:
+
+            break;
+        case 1:
+            ((struct sdshdr8 *)((s)-(sizeof(struct sdshdr8))))->alloc = newlen;
+            break;
+        case 2:
+            ((struct sdshdr16 *)((s)-(sizeof(struct sdshdr16))))->alloc = newlen;
+            break;
+        case 3:
+            ((struct sdshdr32 *)((s)-(sizeof(struct sdshdr32))))->alloc = newlen;
+            break;
+        case 4:
+            ((struct sdshdr64 *)((s)-(sizeof(struct sdshdr64))))->alloc = newlen;
+            break;
+    }
+}
+
+sds sdsnewlen(const void *init, size_t initlen);
+sds sdsnew(const char *init);
+sds sdsempty(void);
+sds sdsdup(const sds s);
+void sdsfree(sds s);
+sds sdsgrowzero(sds s, size_t len);
+sds sdscatlen(sds s, const void *t, size_t len);
+sds sdscat(sds s, const char *t);
+sds sdscatsds(sds s, const sds t);
+sds sdscpylen(sds s, const char *t, size_t len);
+sds sdscpy(sds s, const char *t);
+
+sds sdscatvprintf(sds s, const char *fmt, va_list ap);
+
+sds sdscatprintf(sds s, const char *fmt, ...)
+    ;
+
+
+
+
+sds sdscatfmt(sds s, char const *fmt, ...);
+sds sdstrim(sds s, const char *cset);
+void sdsrange(sds s, int start, int end);
+void sdsupdatelen(sds s);
+void sdsclear(sds s);
+int sdscmp(const sds s1, const sds s2);
+sds *sdssplitlen(const char *s, int len, const char *sep, int seplen, int *count);
+void sdsfreesplitres(sds *tokens, int count);
+void sdstolower(sds s);
+void sdstoupper(sds s);
+sds sdsfromlonglong(long long value);
+sds sdscatrepr(sds s, const char *p, size_t len);
+sds *sdssplitargs(const char *line, int *argc);
+sds sdsmapchars(sds s, const char *from, const char *to, size_t setlen);
+sds sdsjoin(char **argv, int argc, char *sep);
+sds sdsjoinsds(sds *argv, int argc, const char *sep, size_t seplen);
+
+
+sds sdsMakeRoomFor(sds s, size_t addlen);
+void sdsIncrLen(sds s, int incr);
+sds sdsRemoveFreeSpace(sds s);
+size_t sdsAllocSize(sds s);
+void *sdsAllocPtr(sds s);
+
+
+
+
+
+void *sds_malloc(size_t size);
+void *sds_realloc(void *ptr, size_t size);
+void sds_free(void *ptr);
+# 41 "deps/hiredis/hiredis.h" 2
+# 112 "deps/hiredis/hiredis.h"
+typedef struct redisReply {
+    int type;
+    long long integer;
+    size_t len;
+    char *str;
+    size_t elements;
+    struct redisReply **element;
+} redisReply;
+
+redisReader *redisReaderCreate(void);
+
+
+void freeReplyObject(void *reply);
+
+
+int redisvFormatCommand(char **target, const char *format, va_list ap);
+int redisFormatCommand(char **target, const char *format, ...);
+int redisFormatCommandArgv(char **target, int argc, const char **argv, const size_t *argvlen);
+int redisFormatSdsCommandArgv(sds *target, int argc, const char ** argv, const size_t *argvlen);
+void redisFreeCommand(char *cmd);
+void redisFreeSdsCommand(sds cmd);
+
+enum redisConnectionType {
+    REDIS_CONN_TCP,
+    REDIS_CONN_UNIX
+};
+
+
+typedef struct redisContext {
+    int err;
+    char errstr[128];
+    int fd;
+    int flags;
+    char *obuf;
+    redisReader *reader;
+
+    enum redisConnectionType connection_type;
+    struct timeval *timeout;
+
+    struct {
+        char *host;
+        char *source_addr;
+        int port;
+    } tcp;
+
+    struct {
+        char *path;
+    } unix_sock;
+
+} redisContext;
+
+redisContext *redisConnect(const char *ip, int port);
+redisContext *redisConnectWithTimeout(const char *ip, int port, const struct timeval tv);
+redisContext *redisConnectNonBlock(const char *ip, int port);
+redisContext *redisConnectBindNonBlock(const char *ip, int port,
+                                       const char *source_addr);
+redisContext *redisConnectBindNonBlockWithReuse(const char *ip, int port,
+                                                const char *source_addr);
+redisContext *redisConnectUnix(const char *path);
+redisContext *redisConnectUnixWithTimeout(const char *path, const struct timeval tv);
+redisContext *redisConnectUnixNonBlock(const char *path);
+redisContext *redisConnectFd(int fd);
+# 184 "deps/hiredis/hiredis.h"
+int redisReconnect(redisContext *c);
+
+int redisSetTimeout(redisContext *c, const struct timeval tv);
+int redisEnableKeepAlive(redisContext *c);
+void redisFree(redisContext *c);
+int redisFreeKeepFd(redisContext *c);
+int redisBufferRead(redisContext *c);
+int redisBufferWrite(redisContext *c, int *done);
+
+
+
+
+
+int redisGetReply(redisContext *c, void **reply);
+int redisGetReplyFromReader(redisContext *c, void **reply);
+
+
+
+int redisAppendFormattedCommand(redisContext *c, const char *cmd, size_t len);
+
+
+
+int redisvAppendCommand(redisContext *c, const char *format, va_list ap);
+int redisAppendCommand(redisContext *c, const char *format, ...);
+int redisAppendCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen);
+
+
+
+
+
+
+void *redisvCommand(redisContext *c, const char *format, va_list ap);
+void *redisCommand(redisContext *c, const char *format, ...);
+void *redisCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen);
+# 50 "src/redis-cli.c" 2
+# 1 "src/sds.h" 1
+# 51 "src/redis-cli.c" 2
+# 1 "src/zmalloc.h" 1
+# 75 "src/zmalloc.h"
+void *zmalloc(size_t size);
+void *zcalloc(size_t size);
+void *zrealloc(void *ptr, size_t size);
+void zfree(void *ptr);
+char *zstrdup(const char *s);
+size_t zmalloc_used_memory(void);
+void zmalloc_set_oom_handler(void (*oom_handler)(size_t));
+float zmalloc_get_fragmentation_ratio(size_t rss);
+size_t zmalloc_get_rss(void);
+size_t zmalloc_get_private_dirty(long pid);
+size_t zmalloc_get_smap_bytes_by_field(char *field, long pid);
+size_t zmalloc_get_memory_size(void);
+void zlibc_free(void *ptr);
+
+
+
+
+
+
+
+size_t zmalloc_size(void *ptr);
+# 52 "src/redis-cli.c" 2
+# 1 "deps/linenoise/linenoise.h" 1
+# 46 "deps/linenoise/linenoise.h"
+typedef struct linenoiseCompletions {
+  size_t len;
+  char **cvec;
+} linenoiseCompletions;
+
+typedef void(linenoiseCompletionCallback)(const char *, linenoiseCompletions *);
+typedef char*(linenoiseHintsCallback)(const char *, int *color, int *bold);
+typedef void(linenoiseFreeHintsCallback)(void *);
+void linenoiseSetCompletionCallback(linenoiseCompletionCallback *);
+void linenoiseSetHintsCallback(linenoiseHintsCallback *);
+void linenoiseSetFreeHintsCallback(linenoiseFreeHintsCallback *);
+void linenoiseAddCompletion(linenoiseCompletions *, const char *);
+
+char *linenoise(const char *prompt);
+void linenoiseFree(void *ptr);
+int linenoiseHistoryAdd(const char *line);
+int linenoiseHistorySetMaxLen(int len);
+int linenoiseHistorySave(const char *filename);
+int linenoiseHistoryLoad(const char *filename);
+void linenoiseClearScreen(void);
+void linenoiseSetMultiLine(int ml);
+void linenoisePrintKeyCodes(void);
+# 53 "src/redis-cli.c" 2
+# 1 "src/help.h" 1
+
+
+
+
+
+static char *commandGroups[] = {
+    "generic",
+    "string",
+    "list",
+    "set",
+    "sorted_set",
+    "hash",
+    "pubsub",
+    "transactions",
+    "connection",
+    "server",
+    "scripting",
+    "hyperloglog",
+    "cluster",
+    "geo"
+};
+
+struct commandHelp {
+  char *name;
+  char *params;
+  char *summary;
+  int group;
+  char *since;
+} commandHelp[] = {
+    { "APPEND",
+    "key value",
+    "Append a value to a key",
+    1,
+    "2.0.0" },
+    { "AUTH",
+    "password",
+    "Authenticate to the server",
+    8,
+    "1.0.0" },
+    { "BGREWRITEAOF",
+    "-",
+    "Asynchronously rewrite the append-only file",
+    9,
+    "1.0.0" },
+    { "BGSAVE",
+    "-",
+    "Asynchronously save the dataset to disk",
+    9,
+    "1.0.0" },
+    { "BITCOUNT",
+    "key [start end]",
+    "Count set bits in a string",
+    1,
+    "2.6.0" },
+    { "BITFIELD",
+    "key [GET type offset] [SET type offset value] [INCRBY type offset increment] [OVERFLOW WRAP|SAT|FAIL]",
+    "Perform arbitrary bitfield integer operations on strings",
+    1,
+    "3.2.0" },
+    { "BITOP",
+    "operation destkey key [key ...]",
+    "Perform bitwise operations between strings",
+    1,
+    "2.6.0" },
+    { "BITPOS",
+    "key bit [start] [end]",
+    "Find first bit set or clear in a string",
+    1,
+    "2.8.7" },
+    { "BLPOP",
+    "key [key ...] timeout",
+    "Remove and get the first element in a list, or block until one is available",
+    2,
+    "2.0.0" },
+    { "BRPOP",
+    "key [key ...] timeout",
+    "Remove and get the last element in a list, or block until one is available",
+    2,
+    "2.0.0" },
+    { "BRPOPLPUSH",
+    "source destination timeout",
+    "Pop a value from a list, push it to another list and return it; or block until one is available",
+    2,
+    "2.2.0" },
+    { "CLIENT GETNAME",
+    "-",
+    "Get the current connection name",
+    9,
+    "2.6.9" },
+    { "CLIENT KILL",
+    "[ip:port] [ID client-id] [TYPE normal|master|slave|pubsub] [ADDR ip:port] [SKIPME yes/no]",
+    "Kill the connection of a client",
+    9,
+    "2.4.0" },
+    { "CLIENT LIST",
+    "-",
+    "Get the list of client connections",
+    9,
+    "2.4.0" },
+    { "CLIENT PAUSE",
+    "timeout",
+    "Stop processing commands from clients for some time",
+    9,
+    "2.9.50" },
+    { "CLIENT REPLY",
+    "ON|OFF|SKIP",
+    "Instruct the server whether to reply to commands",
+    9,
+    "3.2" },
+    { "CLIENT SETNAME",
+    "connection-name",
+    "Set the current connection name",
+    9,
+    "2.6.9" },
+    { "CLUSTER ADDSLOTS",
+    "slot [slot ...]",
+    "Assign new hash slots to receiving node",
+    12,
+    "3.0.0" },
+    { "CLUSTER COUNT-FAILURE-REPORTS",
+    "node-id",
+    "Return the number of failure reports active for a given node",
+    12,
+    "3.0.0" },
+    { "CLUSTER COUNTKEYSINSLOT",
+    "slot",
+    "Return the number of local keys in the specified hash slot",
+    12,
+    "3.0.0" },
+    { "CLUSTER DELSLOTS",
+    "slot [slot ...]",
+    "Set hash slots as unbound in receiving node",
+    12,
+    "3.0.0" },
+    { "CLUSTER FAILOVER",
+    "[FORCE|TAKEOVER]",
+    "Forces a slave to perform a manual failover of its master.",
+    12,
+    "3.0.0" },
+    { "CLUSTER FORGET",
+    "node-id",
+    "Remove a node from the nodes table",
+    12,
+    "3.0.0" },
+    { "CLUSTER GETKEYSINSLOT",
+    "slot count",
+    "Return local key names in the specified hash slot",
+    12,
+    "3.0.0" },
+    { "CLUSTER INFO",
+    "-",
+    "Provides info about Redis Cluster node state",
+    12,
+    "3.0.0" },
+    { "CLUSTER KEYSLOT",
+    "key",
+    "Returns the hash slot of the specified key",
+    12,
+    "3.0.0" },
+    { "CLUSTER MEET",
+    "ip port",
+    "Force a node cluster to handshake with another node",
+    12,
+    "3.0.0" },
+    { "CLUSTER NODES",
+    "-",
+    "Get Cluster config for the node",
+    12,
+    "3.0.0" },
+    { "CLUSTER REPLICATE",
+    "node-id",
+    "Reconfigure a node as a slave of the specified master node",
+    12,
+    "3.0.0" },
+    { "CLUSTER RESET",
+    "[HARD|SOFT]",
+    "Reset a Redis Cluster node",
+    12,
+    "3.0.0" },
+    { "CLUSTER SAVECONFIG",
+    "-",
+    "Forces the node to save cluster state on disk",
+    12,
+    "3.0.0" },
+    { "CLUSTER SET-CONFIG-EPOCH",
+    "config-epoch",
+    "Set the configuration epoch in a new node",
+    12,
+    "3.0.0" },
+    { "CLUSTER SETSLOT",
+    "slot IMPORTING|MIGRATING|STABLE|NODE [node-id]",
+    "Bind a hash slot to a specific node",
+    12,
+    "3.0.0" },
+    { "CLUSTER SLAVES",
+    "node-id",
+    "List slave nodes of the specified master node",
+    12,
+    "3.0.0" },
+    { "CLUSTER SLOTS",
+    "-",
+    "Get array of Cluster slot to node mappings",
+    12,
+    "3.0.0" },
+    { "COMMAND",
+    "-",
+    "Get array of Redis command details",
+    9,
+    "2.8.13" },
+    { "COMMAND COUNT",
+    "-",
+    "Get total number of Redis commands",
+    9,
+    "2.8.13" },
+    { "COMMAND GETKEYS",
+    "-",
+    "Extract keys given a full Redis command",
+    9,
+    "2.8.13" },
+    { "COMMAND INFO",
+    "command-name [command-name ...]",
+    "Get array of specific Redis command details",
+    9,
+    "2.8.13" },
+    { "CONFIG GET",
+    "parameter",
+    "Get the value of a configuration parameter",
+    9,
+    "2.0.0" },
+    { "CONFIG RESETSTAT",
+    "-",
+    "Reset the stats returned by INFO",
+    9,
+    "2.0.0" },
+    { "CONFIG REWRITE",
+    "-",
+    "Rewrite the configuration file with the in memory configuration",
+    9,
+    "2.8.0" },
+    { "CONFIG SET",
+    "parameter value",
+    "Set a configuration parameter to the given value",
+    9,
+    "2.0.0" },
+    { "DBSIZE",
+    "-",
+    "Return the number of keys in the selected database",
+    9,
+    "1.0.0" },
+    { "DEBUG OBJECT",
+    "key",
+    "Get debugging information about a key",
+    9,
+    "1.0.0" },
+    { "DEBUG SEGFAULT",
+    "-",
+    "Make the server crash",
+    9,
+    "1.0.0" },
+    { "DECR",
+    "key",
+    "Decrement the integer value of a key by one",
+    1,
+    "1.0.0" },
+    { "DECRBY",
+    "key decrement",
+    "Decrement the integer value of a key by the given number",
+    1,
+    "1.0.0" },
+    { "DEL",
+    "key [key ...]",
+    "Delete a key",
+    0,
+    "1.0.0" },
+    { "DISCARD",
+    "-",
+    "Discard all commands issued after MULTI",
+    7,
+    "2.0.0" },
+    { "DUMP",
+    "key",
+    "Return a serialized version of the value stored at the specified key.",
+    0,
+    "2.6.0" },
+    { "ECHO",
+    "message",
+    "Echo the given string",
+    8,
+    "1.0.0" },
+    { "EVAL",
+    "script numkeys key [key ...] arg [arg ...]",
+    "Execute a Lua script server side",
+    10,
+    "2.6.0" },
+    { "EVALSHA",
+    "sha1 numkeys key [key ...] arg [arg ...]",
+    "Execute a Lua script server side",
+    10,
+    "2.6.0" },
+    { "EXEC",
+    "-",
+    "Execute all commands issued after MULTI",
+    7,
+    "1.2.0" },
+    { "EXISTS",
+    "key [key ...]",
+    "Determine if a key exists",
+    0,
+    "1.0.0" },
+    { "EXPIRE",
+    "key seconds",
+    "Set a key's time to live in seconds",
+    0,
+    "1.0.0" },
+    { "EXPIREAT",
+    "key timestamp",
+    "Set the expiration for a key as a UNIX timestamp",
+    0,
+    "1.2.0" },
+    { "FLUSHALL",
+    "-",
+    "Remove all keys from all databases",
+    9,
+    "1.0.0" },
+    { "FLUSHDB",
+    "-",
+    "Remove all keys from the current database",
+    9,
+    "1.0.0" },
+    { "GEOADD",
+    "key longitude latitude member [longitude latitude member ...]",
+    "Add one or more geospatial items in the geospatial index represented using a sorted set",
+    13,
+    "3.2.0" },
+    { "GEODIST",
+    "key member1 member2 [unit]",
+    "Returns the distance between two members of a geospatial index",
+    13,
+    "3.2.0" },
+    { "GEOHASH",
+    "key member [member ...]",
+    "Returns members of a geospatial index as standard geohash strings",
+    13,
+    "3.2.0" },
+    { "GEOPOS",
+    "key member [member ...]",
+    "Returns longitude and latitude of members of a geospatial index",
+    13,
+    "3.2.0" },
+    { "GEORADIUS",
+    "key longitude latitude radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count] [ASC|DESC] [STORE key] [STOREDIST key]",
+    "Query a sorted set representing a geospatial index to fetch members matching a given maximum distance from a point",
+    13,
+    "3.2.0" },
+    { "GEORADIUSBYMEMBER",
+    "key member radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count] [ASC|DESC] [STORE key] [STOREDIST key]",
+    "Query a sorted set representing a geospatial index to fetch members matching a given maximum distance from a member",
+    13,
+    "3.2.0" },
+    { "GET",
+    "key",
+    "Get the value of a key",
+    1,
+    "1.0.0" },
+    { "GETBIT",
+    "key offset",
+    "Returns the bit value at offset in the string value stored at key",
+    1,
+    "2.2.0" },
+    { "GETRANGE",
+    "key start end",
+    "Get a substring of the string stored at a key",
+    1,
+    "2.4.0" },
+    { "GETSET",
+    "key value",
+    "Set the string value of a key and return its old value",
+    1,
+    "1.0.0" },
+    { "HDEL",
+    "key field [field ...]",
+    "Delete one or more hash fields",
+    5,
+    "2.0.0" },
+    { "HEXISTS",
+    "key field",
+    "Determine if a hash field exists",
+    5,
+    "2.0.0" },
+    { "HGET",
+    "key field",
+    "Get the value of a hash field",
+    5,
+    "2.0.0" },
+    { "HGETALL",
+    "key",
+    "Get all the fields and values in a hash",
+    5,
+    "2.0.0" },
+    { "HINCRBY",
+    "key field increment",
+    "Increment the integer value of a hash field by the given number",
+    5,
+    "2.0.0" },
+    { "HINCRBYFLOAT",
+    "key field increment",
+    "Increment the float value of a hash field by the given amount",
+    5,
+    "2.6.0" },
+    { "HKEYS",
+    "key",
+    "Get all the fields in a hash",
+    5,
+    "2.0.0" },
+    { "HLEN",
+    "key",
+    "Get the number of fields in a hash",
+    5,
+    "2.0.0" },
+    { "HMGET",
+    "key field [field ...]",
+    "Get the values of all the given hash fields",
+    5,
+    "2.0.0" },
+    { "HMSET",
+    "key field value [field value ...]",
+    "Set multiple hash fields to multiple values",
+    5,
+    "2.0.0" },
+    { "HSCAN",
+    "key cursor [MATCH pattern] [COUNT count]",
+    "Incrementally iterate hash fields and associated values",
+    5,
+    "2.8.0" },
+    { "HSET",
+    "key field value",
+    "Set the string value of a hash field",
+    5,
+    "2.0.0" },
+    { "HSETNX",
+    "key field value",
+    "Set the value of a hash field, only if the field does not exist",
+    5,
+    "2.0.0" },
+    { "HSTRLEN",
+    "key field",
+    "Get the length of the value of a hash field",
+    5,
+    "3.2.0" },
+    { "HVALS",
+    "key",
+    "Get all the values in a hash",
+    5,
+    "2.0.0" },
+    { "INCR",
+    "key",
+    "Increment the integer value of a key by one",
+    1,
+    "1.0.0" },
+    { "INCRBY",
+    "key increment",
+    "Increment the integer value of a key by the given amount",
+    1,
+    "1.0.0" },
+    { "INCRBYFLOAT",
+    "key increment",
+    "Increment the float value of a key by the given amount",
+    1,
+    "2.6.0" },
+    { "INFO",
+    "[section]",
+    "Get information and statistics about the server",
+    9,
+    "1.0.0" },
+    { "KEYS",
+    "pattern",
+    "Find all keys matching the given pattern",
+    0,
+    "1.0.0" },
+    { "LASTSAVE",
+    "-",
+    "Get the UNIX time stamp of the last successful save to disk",
+    9,
+    "1.0.0" },
+    { "LINDEX",
+    "key index",
+    "Get an element from a list by its index",
+    2,
+    "1.0.0" },
+    { "LINSERT",
+    "key BEFORE|AFTER pivot value",
+    "Insert an element before or after another element in a list",
+    2,
+    "2.2.0" },
+    { "LLEN",
+    "key",
+    "Get the length of a list",
+    2,
+    "1.0.0" },
+    { "LPOP",
+    "key",
+    "Remove and get the first element in a list",
+    2,
+    "1.0.0" },
+    { "LPUSH",
+    "key value [value ...]",
+    "Prepend one or multiple values to a list",
+    2,
+    "1.0.0" },
+    { "LPUSHX",
+    "key value",
+    "Prepend a value to a list, only if the list exists",
+    2,
+    "2.2.0" },
+    { "LRANGE",
+    "key start stop",
+    "Get a range of elements from a list",
+    2,
+    "1.0.0" },
+    { "LREM",
+    "key count value",
+    "Remove elements from a list",
+    2,
+    "1.0.0" },
+    { "LSET",
+    "key index value",
+    "Set the value of an element in a list by its index",
+    2,
+    "1.0.0" },
+    { "LTRIM",
+    "key start stop",
+    "Trim a list to the specified range",
+    2,
+    "1.0.0" },
+    { "MGET",
+    "key [key ...]",
+    "Get the values of all the given keys",
+    1,
+    "1.0.0" },
+    { "MIGRATE",
+    "host port key|"" destination-db timeout [COPY] [REPLACE] [KEYS key]",
+    "Atomically transfer a key from a Redis instance to another one.",
+    0,
+    "2.6.0" },
+    { "MONITOR",
+    "-",
+    "Listen for all requests received by the server in real time",
+    9,
+    "1.0.0" },
+    { "MOVE",
+    "key db",
+    "Move a key to another database",
+    0,
+    "1.0.0" },
+    { "MSET",
+    "key value [key value ...]",
+    "Set multiple keys to multiple values",
+    1,
+    "1.0.1" },
+    { "MSETNX",
+    "key value [key value ...]",
+    "Set multiple keys to multiple values, only if none of the keys exist",
+    1,
+    "1.0.1" },
+    { "MULTI",
+    "-",
+    "Mark the start of a transaction block",
+    7,
+    "1.2.0" },
+    { "OBJECT",
+    "subcommand [arguments [arguments ...]]",
+    "Inspect the internals of Redis objects",
+    0,
+    "2.2.3" },
+    { "PERSIST",
+    "key",
+    "Remove the expiration from a key",
+    0,
+    "2.2.0" },
+    { "PEXPIRE",
+    "key milliseconds",
+    "Set a key's time to live in milliseconds",
+    0,
+    "2.6.0" },
+    { "PEXPIREAT",
+    "key milliseconds-timestamp",
+    "Set the expiration for a key as a UNIX timestamp specified in milliseconds",
+    0,
+    "2.6.0" },
+    { "PFADD",
+    "key element [element ...]",
+    "Adds the specified elements to the specified HyperLogLog.",
+    11,
+    "2.8.9" },
+    { "PFCOUNT",
+    "key [key ...]",
+    "Return the approximated cardinality of the set(s) observed by the HyperLogLog at key(s).",
+    11,
+    "2.8.9" },
+    { "PFMERGE",
+    "destkey sourcekey [sourcekey ...]",
+    "Merge N different HyperLogLogs into a single one.",
+    11,
+    "2.8.9" },
+    { "PING",
+    "[message]",
+    "Ping the server",
+    8,
+    "1.0.0" },
+    { "PSETEX",
+    "key milliseconds value",
+    "Set the value and expiration in milliseconds of a key",
+    1,
+    "2.6.0" },
+    { "PSUBSCRIBE",
+    "pattern [pattern ...]",
+    "Listen for messages published to channels matching the given patterns",
+    6,
+    "2.0.0" },
+    { "PTTL",
+    "key",
+    "Get the time to live for a key in milliseconds",
+    0,
+    "2.6.0" },
+    { "PUBLISH",
+    "channel message",
+    "Post a message to a channel",
+    6,
+    "2.0.0" },
+    { "PUBSUB",
+    "subcommand [argument [argument ...]]",
+    "Inspect the state of the Pub/Sub subsystem",
+    6,
+    "2.8.0" },
+    { "PUNSUBSCRIBE",
+    "[pattern [pattern ...]]",
+    "Stop listening for messages posted to channels matching the given patterns",
+    6,
+    "2.0.0" },
+    { "QUIT",
+    "-",
+    "Close the connection",
+    8,
+    "1.0.0" },
+    { "RANDOMKEY",
+    "-",
+    "Return a random key from the keyspace",
+    0,
+    "1.0.0" },
+    { "READONLY",
+    "-",
+    "Enables read queries for a connection to a cluster slave node",
+    12,
+    "3.0.0" },
+    { "READWRITE",
+    "-",
+    "Disables read queries for a connection to a cluster slave node",
+    12,
+    "3.0.0" },
+    { "RENAME",
+    "key newkey",
+    "Rename a key",
+    0,
+    "1.0.0" },
+    { "RENAMENX",
+    "key newkey",
+    "Rename a key, only if the new key does not exist",
+    0,
+    "1.0.0" },
+    { "RESTORE",
+    "key ttl serialized-value [REPLACE]",
+    "Create a key using the provided serialized value, previously obtained using DUMP.",
+    0,
+    "2.6.0" },
+    { "ROLE",
+    "-",
+    "Return the role of the instance in the context of replication",
+    9,
+    "2.8.12" },
+    { "RPOP",
+    "key",
+    "Remove and get the last element in a list",
+    2,
+    "1.0.0" },
+    { "RPOPLPUSH",
+    "source destination",
+    "Remove the last element in a list, prepend it to another list and return it",
+    2,
+    "1.2.0" },
+    { "RPUSH",
+    "key value [value ...]",
+    "Append one or multiple values to a list",
+    2,
+    "1.0.0" },
+    { "RPUSHX",
+    "key value",
+    "Append a value to a list, only if the list exists",
+    2,
+    "2.2.0" },
+    { "SADD",
+    "key member [member ...]",
+    "Add one or more members to a set",
+    3,
+    "1.0.0" },
+    { "SAVE",
+    "-",
+    "Synchronously save the dataset to disk",
+    9,
+    "1.0.0" },
+    { "SCAN",
+    "cursor [MATCH pattern] [COUNT count]",
+    "Incrementally iterate the keys space",
+    0,
+    "2.8.0" },
+    { "SCARD",
+    "key",
+    "Get the number of members in a set",
+    3,
+    "1.0.0" },
+    { "SCRIPT DEBUG",
+    "YES|SYNC|NO",
+    "Set the debug mode for executed scripts.",
+    10,
+    "3.2.0" },
+    { "SCRIPT EXISTS",
+    "script [script ...]",
+    "Check existence of scripts in the script cache.",
+    10,
+    "2.6.0" },
+    { "SCRIPT FLUSH",
+    "-",
+    "Remove all the scripts from the script cache.",
+    10,
+    "2.6.0" },
+    { "SCRIPT KILL",
+    "-",
+    "Kill the script currently in execution.",
+    10,
+    "2.6.0" },
+    { "SCRIPT LOAD",
+    "script",
+    "Load the specified Lua script into the script cache.",
+    10,
+    "2.6.0" },
+    { "SDIFF",
+    "key [key ...]",
+    "Subtract multiple sets",
+    3,
+    "1.0.0" },
+    { "SDIFFSTORE",
+    "destination key [key ...]",
+    "Subtract multiple sets and store the resulting set in a key",
+    3,
+    "1.0.0" },
+    { "SELECT",
+    "index",
+    "Change the selected database for the current connection",
+    8,
+    "1.0.0" },
+    { "SET",
+    "key value [EX seconds] [PX milliseconds] [NX|XX]",
+    "Set the string value of a key",
+    1,
+    "1.0.0" },
+    { "SETBIT",
+    "key offset value",
+    "Sets or clears the bit at offset in the string value stored at key",
+    1,
+    "2.2.0" },
+    { "SETEX",
+    "key seconds value",
+    "Set the value and expiration of a key",
+    1,
+    "2.0.0" },
+    { "SETNX",
+    "key value",
+    "Set the value of a key, only if the key does not exist",
+    1,
+    "1.0.0" },
+    { "SETRANGE",
+    "key offset value",
+    "Overwrite part of a string at key starting at the specified offset",
+    1,
+    "2.2.0" },
+    { "SHUTDOWN",
+    "[NOSAVE|SAVE]",
+    "Synchronously save the dataset to disk and then shut down the server",
+    9,
+    "1.0.0" },
+    { "SINTER",
+    "key [key ...]",
+    "Intersect multiple sets",
+    3,
+    "1.0.0" },
+    { "SINTERSTORE",
+    "destination key [key ...]",
+    "Intersect multiple sets and store the resulting set in a key",
+    3,
+    "1.0.0" },
+    { "SISMEMBER",
+    "key member",
+    "Determine if a given value is a member of a set",
+    3,
+    "1.0.0" },
+    { "SLAVEOF",
+    "host port",
+    "Make the server a slave of another instance, or promote it as master",
+    9,
+    "1.0.0" },
+    { "SLOWLOG",
+    "subcommand [argument]",
+    "Manages the Redis slow queries log",
+    9,
+    "2.2.12" },
+    { "SMEMBERS",
+    "key",
+    "Get all the members in a set",
+    3,
+    "1.0.0" },
+    { "SMOVE",
+    "source destination member",
+    "Move a member from one set to another",
+    3,
+    "1.0.0" },
+    { "SORT",
+    "key [BY pattern] [LIMIT offset count] [GET pattern [GET pattern ...]] [ASC|DESC] [ALPHA] [STORE destination]",
+    "Sort the elements in a list, set or sorted set",
+    0,
+    "1.0.0" },
+    { "SPOP",
+    "key [count]",
+    "Remove and return one or multiple random members from a set",
+    3,
+    "1.0.0" },
+    { "SRANDMEMBER",
+    "key [count]",
+    "Get one or multiple random members from a set",
+    3,
+    "1.0.0" },
+    { "SREM",
+    "key member [member ...]",
+    "Remove one or more members from a set",
+    3,
+    "1.0.0" },
+    { "SSCAN",
+    "key cursor [MATCH pattern] [COUNT count]",
+    "Incrementally iterate Set elements",
+    3,
+    "2.8.0" },
+    { "STRLEN",
+    "key",
+    "Get the length of the value stored in a key",
+    1,
+    "2.2.0" },
+    { "SUBSCRIBE",
+    "channel [channel ...]",
+    "Listen for messages published to the given channels",
+    6,
+    "2.0.0" },
+    { "SUNION",
+    "key [key ...]",
+    "Add multiple sets",
+    3,
+    "1.0.0" },
+    { "SUNIONSTORE",
+    "destination key [key ...]",
+    "Add multiple sets and store the resulting set in a key",
+    3,
+    "1.0.0" },
+    { "SYNC",
+    "-",
+    "Internal command used for replication",
+    9,
+    "1.0.0" },
+    { "TIME",
+    "-",
+    "Return the current server time",
+    9,
+    "2.6.0" },
+    { "TTL",
+    "key",
+    "Get the time to live for a key",
+    0,
+    "1.0.0" },
+    { "TYPE",
+    "key",
+    "Determine the type stored at key",
+    0,
+    "1.0.0" },
+    { "UNSUBSCRIBE",
+    "[channel [channel ...]]",
+    "Stop listening for messages posted to the given channels",
+    6,
+    "2.0.0" },
+    { "UNWATCH",
+    "-",
+    "Forget about all watched keys",
+    7,
+    "2.2.0" },
+    { "WAIT",
+    "numslaves timeout",
+    "Wait for the synchronous replication of all the write commands sent in the context of the current connection",
+    0,
+    "3.0.0" },
+    { "WATCH",
+    "key [key ...]",
+    "Watch the given keys to determine execution of the MULTI/EXEC block",
+    7,
+    "2.2.0" },
+    { "ZADD",
+    "key [NX|XX] [CH] [INCR] score member [score member ...]",
+    "Add one or more members to a sorted set, or update its score if it already exists",
+    4,
+    "1.2.0" },
+    { "ZCARD",
+    "key",
+    "Get the number of members in a sorted set",
+    4,
+    "1.2.0" },
+    { "ZCOUNT",
+    "key min max",
+    "Count the members in a sorted set with scores within the given values",
+    4,
+    "2.0.0" },
+    { "ZINCRBY",
+    "key increment member",
+    "Increment the score of a member in a sorted set",
+    4,
+    "1.2.0" },
+    { "ZINTERSTORE",
+    "destination numkeys key [key ...] [WEIGHTS weight] [AGGREGATE SUM|MIN|MAX]",
+    "Intersect multiple sorted sets and store the resulting sorted set in a new key",
+    4,
+    "2.0.0" },
+    { "ZLEXCOUNT",
+    "key min max",
+    "Count the number of members in a sorted set between a given lexicographical range",
+    4,
+    "2.8.9" },
+    { "ZRANGE",
+    "key start stop [WITHSCORES]",
+    "Return a range of members in a sorted set, by index",
+    4,
+    "1.2.0" },
+    { "ZRANGEBYLEX",
+    "key min max [LIMIT offset count]",
+    "Return a range of members in a sorted set, by lexicographical range",
+    4,
+    "2.8.9" },
+    { "ZRANGEBYSCORE",
+    "key min max [WITHSCORES] [LIMIT offset count]",
+    "Return a range of members in a sorted set, by score",
+    4,
+    "1.0.5" },
+    { "ZRANK",
+    "key member",
+    "Determine the index of a member in a sorted set",
+    4,
+    "2.0.0" },
+    { "ZREM",
+    "key member [member ...]",
+    "Remove one or more members from a sorted set",
+    4,
+    "1.2.0" },
+    { "ZREMRANGEBYLEX",
+    "key min max",
+    "Remove all members in a sorted set between the given lexicographical range",
+    4,
+    "2.8.9" },
+    { "ZREMRANGEBYRANK",
+    "key start stop",
+    "Remove all members in a sorted set within the given indexes",
+    4,
+    "2.0.0" },
+    { "ZREMRANGEBYSCORE",
+    "key min max",
+    "Remove all members in a sorted set within the given scores",
+    4,
+    "1.2.0" },
+    { "ZREVRANGE",
+    "key start stop [WITHSCORES]",
+    "Return a range of members in a sorted set, by index, with scores ordered from high to low",
+    4,
+    "1.2.0" },
+    { "ZREVRANGEBYLEX",
+    "key max min [LIMIT offset count]",
+    "Return a range of members in a sorted set, by lexicographical range, ordered from higher to lower strings.",
+    4,
+    "2.8.9" },
+    { "ZREVRANGEBYSCORE",
+    "key max min [WITHSCORES] [LIMIT offset count]",
+    "Return a range of members in a sorted set, by score, with scores ordered from high to low",
+    4,
+    "2.2.0" },
+    { "ZREVRANK",
+    "key member",
+    "Determine the index of a member in a sorted set, with scores ordered from high to low",
+    4,
+    "2.0.0" },
+    { "ZSCAN",
+    "key cursor [MATCH pattern] [COUNT count]",
+    "Incrementally iterate sorted sets elements and associated scores",
+    4,
+    "2.8.0" },
+    { "ZSCORE",
+    "key member",
+    "Get the score associated with the given member in a sorted set",
+    4,
+    "1.2.0" },
+    { "ZUNIONSTORE",
+    "destination numkeys key [key ...] [WEIGHTS weight] [AGGREGATE SUM|MIN|MAX]",
+    "Add multiple sorted sets and store the resulting sorted set in a new key",
+    4,
+    "2.0.0" }
+};
+# 54 "src/redis-cli.c" 2
+# 1 "src/anet.h" 1
+# 34 "src/anet.h"
+# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/sys/types.h" 1
+# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/_fake_defines.h" 1
+# 2 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/sys/types.h" 2
+# 35 "src/anet.h" 2
+# 52 "src/anet.h"
+int anetTcpConnect(char *err, char *addr, int port);
+int anetTcpNonBlockConnect(char *err, char *addr, int port);
+int anetTcpNonBlockBindConnect(char *err, char *addr, int port, char *source_addr);
+int anetTcpNonBlockBestEffortBindConnect(char *err, char *addr, int port, char *source_addr);
+int anetUnixConnect(char *err, char *path);
+int anetUnixNonBlockConnect(char *err, char *path);
+int anetRead(int fd, char *buf, int count);
+int anetResolve(char *err, char *host, char *ipbuf, size_t ipbuf_len);
+int anetResolveIP(char *err, char *host, char *ipbuf, size_t ipbuf_len);
+int anetTcpServer(char *err, int port, char *bindaddr, int backlog);
+int anetTcp6Server(char *err, int port, char *bindaddr, int backlog);
+int anetUnixServer(char *err, char *path, mode_t perm, int backlog);
+int anetTcpAccept(char *err, int serversock, char *ip, size_t ip_len, int *port);
+int anetUnixAccept(char *err, int serversock);
+int anetWrite(int fd, char *buf, int count);
+int anetNonBlock(char *err, int fd);
+int anetBlock(char *err, int fd);
+int anetEnableTcpNoDelay(char *err, int fd);
+int anetDisableTcpNoDelay(char *err, int fd);
+int anetTcpKeepAlive(char *err, int fd);
+int anetSendTimeout(char *err, int fd, long long ms);
+int anetPeerToString(int fd, char *ip, size_t ip_len, int *port);
+int anetKeepAlive(char *err, int fd, int interval);
+int anetSockName(int fd, char *ip, size_t ip_len, int *port);
+int anetFormatAddr(char *fmt, size_t fmt_len, char *ip, int port);
+int anetFormatPeer(int fd, char *fmt, size_t fmt_len);
+int anetFormatSock(int fd, char *fmt, size_t fmt_len);
+# 55 "src/redis-cli.c" 2
+# 1 "src/ae.h" 1
+# 36 "src/ae.h"
+# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/time.h" 1
+# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/_fake_defines.h" 1
+# 2 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/time.h" 2
+# 37 "src/ae.h" 2
+# 57 "src/ae.h"
+struct aeEventLoop;
+
+
+typedef void aeFileProc(struct aeEventLoop *eventLoop, int fd, void *clientData, int mask);
+typedef int aeTimeProc(struct aeEventLoop *eventLoop, long long id, void *clientData);
+typedef void aeEventFinalizerProc(struct aeEventLoop *eventLoop, void *clientData);
+typedef void aeBeforeSleepProc(struct aeEventLoop *eventLoop);
+
+
+typedef struct aeFileEvent {
+    int mask;
+    aeFileProc *rfileProc;
+    aeFileProc *wfileProc;
+    void *clientData;
+} aeFileEvent;
+
+
+typedef struct aeTimeEvent {
+    long long id;
+    long when_sec;
+    long when_ms;
+    aeTimeProc *timeProc;
+    aeEventFinalizerProc *finalizerProc;
+    void *clientData;
+    struct aeTimeEvent *next;
+} aeTimeEvent;
+
+
+typedef struct aeFiredEvent {
+    int fd;
+    int mask;
+} aeFiredEvent;
+
+
+typedef struct aeEventLoop {
+    int maxfd;
+    int setsize;
+    long long timeEventNextId;
+    time_t lastTime;
+    aeFileEvent *events;
+    aeFiredEvent *fired;
+    aeTimeEvent *timeEventHead;
+    int stop;
+    void *apidata;
+    aeBeforeSleepProc *beforesleep;
+    aeBeforeSleepProc *aftersleep;
+} aeEventLoop;
+
+
+aeEventLoop *aeCreateEventLoop(int setsize);
+void aeDeleteEventLoop(aeEventLoop *eventLoop);
+void aeStop(aeEventLoop *eventLoop);
+int aeCreateFileEvent(aeEventLoop *eventLoop, int fd, int mask,
+        aeFileProc *proc, void *clientData);
+void aeDeleteFileEvent(aeEventLoop *eventLoop, int fd, int mask);
+int aeGetFileEvents(aeEventLoop *eventLoop, int fd);
+long long aeCreateTimeEvent(aeEventLoop *eventLoop, long long milliseconds,
+        aeTimeProc *proc, void *clientData,
+        aeEventFinalizerProc *finalizerProc);
+int aeDeleteTimeEvent(aeEventLoop *eventLoop, long long id);
+int aeProcessEvents(aeEventLoop *eventLoop, int flags);
+int aeWait(int fd, int mask, long long milliseconds);
+void aeMain(aeEventLoop *eventLoop);
+char *aeGetApiName(void);
+void aeSetBeforeSleepProc(aeEventLoop *eventLoop, aeBeforeSleepProc *beforesleep);
+void aeSetAfterSleepProc(aeEventLoop *eventLoop, aeBeforeSleepProc *aftersleep);
+int aeGetSetSize(aeEventLoop *eventLoop);
+int aeResizeSetSize(aeEventLoop *eventLoop, int setsize);
+# 56 "src/redis-cli.c" 2
+# 70 "src/redis-cli.c"
+int spectrum_palette_color_size = 19;
+int spectrum_palette_color[] = {0,233,234,235,237,239,241,243,245,247,144,143,142,184,226,214,208,202,196};
+
+int spectrum_palette_mono_size = 13;
+int spectrum_palette_mono[] = {0,233,234,235,237,239,241,243,245,247,249,251,253};
+
+
+int *spectrum_palette;
+int spectrum_palette_size;
+
+static redisContext *context;
+static struct config {
+    char *hostip;
+    int hostport;
+    char *hostsocket;
+    long repeat;
+    long interval;
+    int dbnum;
+    int interactive;
+    int shutdown;
+    int monitor_mode;
+    int pubsub_mode;
+    int latency_mode;
+    int latency_dist_mode;
+    int latency_history;
+    int lru_test_mode;
+    long long lru_test_sample_size;
+    int cluster_mode;
+    int cluster_reissue_command;
+    int slave_mode;
+    int pipe_mode;
+    int pipe_timeout;
+    int getrdb_mode;
+    int stat_mode;
+    int scan_mode;
+    int intrinsic_latency_mode;
+    int intrinsic_latency_duration;
+    char *pattern;
+    char *rdb_filename;
+    int bigkeys;
+    int hotkeys;
+    int stdinarg;
+    char *auth;
+    int output;
+    sds mb_delim;
+    char prompt[128];
+    char *eval;
+    int eval_ldb;
+    int eval_ldb_sync;
+    int eval_ldb_end;
+    int enable_ldb_on_eval;
+    int last_cmd_type;
+} config;
+
+
+static struct pref {
+    int hints;
+} pref;
+
+static volatile sig_atomic_t force_cancel_loop = 0;
+static void usage(void);
+static void slaveMode(void);
+char *redisGitSHA1(void);
+char *redisGitDirty(void);
+static int cliConnect(int force);
+
+
+
+
+
+static long long ustime(void) {
+    struct timeval tv;
+    long long ust;
+
+    gettimeofday(&tv, 0);
+    ust = ((long long)tv.tv_sec)*1000000;
+    ust += tv.tv_usec;
+    return ust;
+}
+
+static long long mstime(void) {
+    return ustime()/1000;
+}
+
+static void cliRefreshPrompt(void) {
+    int len;
+
+    if (config.eval_ldb) return;
+    if (config.hostsocket != 0)
+        len = snprintf(config.prompt,sizeof(config.prompt),"redis %s",
+                       config.hostsocket);
+    else
+        len = anetFormatAddr(config.prompt, sizeof(config.prompt),
+                           config.hostip, config.hostport);
+
+    if (config.dbnum != 0)
+        len += snprintf(config.prompt+len,sizeof(config.prompt)-len,"[%d]",
+            config.dbnum);
+    snprintf(config.prompt+len,sizeof(config.prompt)-len,"> ");
+}
+# 179 "src/redis-cli.c"
+static sds getDotfilePath(char *envoverride, char *dotfilename) {
+    char *path = 0;
+    sds dotPath = 0;
+
+
+    path = getenv(envoverride);
+    if (path != 0 && *path != '\0') {
+        if (!strcmp("/dev/null", path)) {
+            return 0;
+        }
+
+
+        dotPath = sdsnew(path);
+    } else {
+        char *home = getenv("HOME");
+        if (home != 0 && *home != '\0') {
+
+            dotPath = sdscatprintf(sdsempty(), "%s/%s", home, dotfilename);
+        }
+    }
+    return dotPath;
+}
+
+
+
+
+
+
+static sds percentDecode(const char *pe, size_t len) {
+    const char *end = pe + len;
+    sds ret = sdsempty();
+    const char *curr = pe;
+
+    while (curr < end) {
+        if (*curr == '%') {
+            if ((end - curr) < 2) {
+                fprintf(stderr, "Incomplete URI encoding\n");
+                exit(1);
+            }
+
+            char h = tolower(*(++curr));
+            char l = tolower(*(++curr));
+            if (!(isdigit(h) || (h >= 'a' && h <= 'f')) || !(isdigit(l) || (l >= 'a' && l <= 'f'))) {
+                fprintf(stderr, "Illegal character in URI encoding\n");
+                exit(1);
+            }
+            char c = (((isdigit(h) ? h - '0' : h - 'a' + 10) << 4) + (isdigit(l) ? l - '0' : l - 'a' + 10));
+            ret = sdscatlen(ret, &c, 1);
+            curr++;
+        } else {
+            ret = sdscatlen(ret, curr++, 1);
+        }
+    }
+
+    return ret;
+}
+# 244 "src/redis-cli.c"
+static void parseRedisUri(const char *uri) {
+
+    const char *scheme = "redis://";
+    const char *curr = uri;
+    const char *end = uri + strlen(uri);
+    const char *userinfo, *username, *port, *host, *path;
+
+
+    if (strncasecmp(scheme, curr, strlen(scheme))) {
+        fprintf(stderr,"Invalid URI scheme\n");
+        exit(1);
+    }
+    curr += strlen(scheme);
+    if (curr == end) return;
+
+
+    if ((userinfo = strchr(curr,'@'))) {
+        if ((username = strchr(curr, ':')) && username < userinfo) {
+
+            curr = username + 1;
+        }
+
+        config.auth = percentDecode(curr, userinfo - curr);
+        curr = userinfo + 1;
+    }
+    if (curr == end) return;
+
+
+    path = strchr(curr, '/');
+    if (*curr != '/') {
+        host = path ? path - 1 : end;
+        if ((port = strchr(curr, ':'))) {
+            config.hostport = atoi(port + 1);
+            host = port - 1;
+        }
+        config.hostip = sdsnewlen(curr, host - curr + 1);
+    }
+    curr = path ? path + 1 : end;
+    if (curr == end) return;
+
+
+    config.dbnum = atoi(curr);
+}
+# 295 "src/redis-cli.c"
+typedef struct {
+    int type;
+    int argc;
+    sds *argv;
+    sds full;
+
+
+    struct commandHelp *org;
+} helpEntry;
+
+static helpEntry *helpEntries;
+static int helpEntriesLen;
+
+static sds cliVersion(void) {
+    sds version;
+    version = sdscatprintf(sdsempty(), "%s", "4.0.8");
+
+
+    if (strtoll(redisGitSHA1(),0,16)) {
+        version = sdscatprintf(version, " (git:%s", redisGitSHA1());
+        if (strtoll(redisGitDirty(),0,10))
+            version = sdscatprintf(version, "-dirty");
+        version = sdscat(version, ")");
+    }
+    return version;
+}
+
+static void cliInitHelp(void) {
+    int commandslen = sizeof(commandHelp)/sizeof(struct commandHelp);
+    int groupslen = sizeof(commandGroups)/sizeof(char*);
+    int i, len, pos = 0;
+    helpEntry tmp;
+
+    helpEntriesLen = len = commandslen+groupslen;
+    helpEntries = zmalloc(sizeof(helpEntry)*len);
+
+    for (i = 0; i < groupslen; i++) {
+        tmp.argc = 1;
+        tmp.argv = zmalloc(sizeof(sds));
+        tmp.argv[0] = sdscatprintf(sdsempty(),"@%s",commandGroups[i]);
+        tmp.full = tmp.argv[0];
+        tmp.type = 2;
+        tmp.org = 0;
+        helpEntries[pos++] = tmp;
+    }
+
+    for (i = 0; i < commandslen; i++) {
+        tmp.argv = sdssplitargs(commandHelp[i].name,&tmp.argc);
+        tmp.full = sdsnew(commandHelp[i].name);
+        tmp.type = 1;
+        tmp.org = &commandHelp[i];
+        helpEntries[pos++] = tmp;
+    }
+}
+
+
+
+
+
+
+static void cliIntegrateHelp(void) {
+    if (cliConnect(0) == -1) return;
+
+    redisReply *reply = redisCommand(context, "COMMAND");
+    if(reply == 0 || reply->type != 2) return;
+
+
+
+    for (size_t j = 0; j < reply->elements; j++) {
+        redisReply *entry = reply->element[j];
+        if (entry->type != 2 || entry->elements < 4 ||
+            entry->element[0]->type != 1 ||
+            entry->element[1]->type != 3 ||
+            entry->element[3]->type != 3) return;
+        char *cmdname = entry->element[0]->str;
+        int i;
+
+        for (i = 0; i < helpEntriesLen; i++) {
+            helpEntry *he = helpEntries+i;
+            if (!strcasecmp(he->argv[0],cmdname))
+                break;
+        }
+        if (i != helpEntriesLen) continue;
+
+        helpEntriesLen++;
+        helpEntries = zrealloc(helpEntries,sizeof(helpEntry)*helpEntriesLen);
+        helpEntry *new = helpEntries+(helpEntriesLen-1);
+
+        new->argc = 1;
+        new->argv = zmalloc(sizeof(sds));
+        new->argv[0] = sdsnew(cmdname);
+        new->full = new->argv[0];
+        new->type = 1;
+        sdstoupper(new->argv[0]);
+
+        struct commandHelp *ch = zmalloc(sizeof(*ch));
+        ch->name = new->argv[0];
+        ch->params = sdsempty();
+        int args = llabs(entry->element[1]->integer);
+        if (entry->element[3]->integer == 1) {
+            ch->params = sdscat(ch->params,"key ");
+            args--;
+        }
+        while(args--) ch->params = sdscat(ch->params,"arg ");
+        if (entry->element[1]->integer < 0)
+            ch->params = sdscat(ch->params,"...options...");
+        ch->summary = "Help not available";
+        ch->group = 0;
+        ch->since = "not known";
+        new->org = ch;
+    }
+    freeReplyObject(reply);
+}
+
+
+static void cliOutputCommandHelp(struct commandHelp *help, int group) {
+    printf("\r\n  \x1b[1m%s\x1b[0m \x1b[90m%s\x1b[0m\r\n", help->name, help->params);
+    printf("  \x1b[33msummary:\x1b[0m %s\r\n", help->summary);
+    printf("  \x1b[33msince:\x1b[0m %s\r\n", help->since);
+    if (group) {
+        printf("  \x1b[33mgroup:\x1b[0m %s\r\n", commandGroups[help->group]);
+    }
+}
+
+
+static void cliOutputGenericHelp(void) {
+    sds version = cliVersion();
+    printf(
+        "redis-cli %s\n"
+        "To get help about Redis commands type:\n"
+        "      \"help @<group>\" to get a list of commands in <group>\n"
+        "      \"help <command>\" for help on <command>\n"
+        "      \"help <tab>\" to get a list of possible help topics\n"
+        "      \"quit\" to exit\n"
+        "\n"
+        "To set redis-cli preferences:\n"
+        "      \":set hints\" enable online hints\n"
+        "      \":set nohints\" disable online hints\n"
+        "Set your preferences in ~/.redisclirc\n",
+        version
+    );
+    sdsfree(version);
+}
+
+
+static void cliOutputHelp(int argc, char **argv) {
+    int i, j, len;
+    int group = -1;
+    helpEntry *entry;
+    struct commandHelp *help;
+
+    if (argc == 0) {
+        cliOutputGenericHelp();
+        return;
+    } else if (argc > 0 && argv[0][0] == '@') {
+        len = sizeof(commandGroups)/sizeof(char*);
+        for (i = 0; i < len; i++) {
+            if (strcasecmp(argv[0]+1,commandGroups[i]) == 0) {
+                group = i;
+                break;
+            }
+        }
+    }
+
+    assert(argc > 0);
+    for (i = 0; i < helpEntriesLen; i++) {
+        entry = &helpEntries[i];
+        if (entry->type != 1) continue;
+
+        help = entry->org;
+        if (group == -1) {
+
+            if (argc == entry->argc) {
+                for (j = 0; j < argc; j++) {
+                    if (strcasecmp(argv[j],entry->argv[j]) != 0) break;
+                }
+                if (j == argc) {
+                    cliOutputCommandHelp(help,1);
+                }
+            }
+        } else {
+            if (group == help->group) {
+                cliOutputCommandHelp(help,0);
+            }
+        }
+    }
+    printf("\r\n");
+}
+
+
+static void completionCallback(const char *buf, linenoiseCompletions *lc) {
+    size_t startpos = 0;
+    int mask;
+    int i;
+    size_t matchlen;
+    sds tmp;
+
+    if (strncasecmp(buf,"help ",5) == 0) {
+        startpos = 5;
+        while (isspace(buf[startpos])) startpos++;
+        mask = 1 | 2;
+    } else {
+        mask = 1;
+    }
+
+    for (i = 0; i < helpEntriesLen; i++) {
+        if (!(helpEntries[i].type & mask)) continue;
+
+        matchlen = strlen(buf+startpos);
+        if (strncasecmp(buf+startpos,helpEntries[i].full,matchlen) == 0) {
+            tmp = sdsnewlen(buf,startpos);
+            tmp = sdscat(tmp,helpEntries[i].full);
+            linenoiseAddCompletion(lc,tmp);
+            sdsfree(tmp);
+        }
+    }
+}
+
+
+static char *hintsCallback(const char *buf, int *color, int *bold) {
+    if (!pref.hints) return 0;
+
+    int i, argc, buflen = strlen(buf);
+    sds *argv = sdssplitargs(buf,&argc);
+    int endspace = buflen && isspace(buf[buflen-1]);
+
+
+    if (argc == 0) {
+        sdsfreesplitres(argv,argc);
+        return 0;
+    }
+
+    for (i = 0; i < helpEntriesLen; i++) {
+        if (!(helpEntries[i].type & 1)) continue;
+
+        if (strcasecmp(argv[0],helpEntries[i].full) == 0)
+        {
+            *color = 90;
+            *bold = 0;
+            sds hint = sdsnew(helpEntries[i].org->params);
+
+
+
+            int toremove = argc-1;
+            while(toremove > 0 && sdslen(hint)) {
+                if (hint[0] == '[') break;
+                if (hint[0] == ' ') toremove--;
+                sdsrange(hint,1,-1);
+            }
+
+
+            if (!endspace) {
+                sds newhint = sdsnewlen(" ",1);
+                newhint = sdscatsds(newhint,hint);
+                sdsfree(hint);
+                hint = newhint;
+            }
+
+            sdsfreesplitres(argv,argc);
+            return hint;
+        }
+    }
+    sdsfreesplitres(argv,argc);
+    return 0;
+}
+
+static void freeHintsCallback(void *ptr) {
+    sdsfree(ptr);
+}
+
+
+
+
+
+
+static int cliAuth(void) {
+    redisReply *reply;
+    if (config.auth == 0) return 0;
+
+    reply = redisCommand(context,"AUTH %s",config.auth);
+    if (reply != 0) {
+        freeReplyObject(reply);
+        return 0;
+    }
+    return -1;
+}
+
+
+static int cliSelect(void) {
+    redisReply *reply;
+    if (config.dbnum == 0) return 0;
+
+    reply = redisCommand(context,"SELECT %d",config.dbnum);
+    if (reply != 0) {
+        int result = 0;
+        if (reply->type == 6) result = -1;
+        freeReplyObject(reply);
+        return result;
+    }
+    return -1;
+}
+
+
+
+static int cliConnect(int force) {
+    if (context == 0 || force) {
+        if (context != 0) {
+            redisFree(context);
+        }
+
+        if (config.hostsocket == 0) {
+            context = redisConnect(config.hostip,config.hostport);
+        } else {
+            context = redisConnectUnix(config.hostsocket);
+        }
+
+        if (context->err) {
+            fprintf(stderr,"Could not connect to Redis at ");
+            if (config.hostsocket == 0)
+                fprintf(stderr,"%s:%d: %s\n",config.hostip,config.hostport,context->errstr);
+            else
+                fprintf(stderr,"%s: %s\n",config.hostsocket,context->errstr);
+            redisFree(context);
+            context = 0;
+            return -1;
+        }
+
+
+
+
+
+        anetKeepAlive(0, context->fd, 15);
+
+
+        if (cliAuth() != 0)
+            return -1;
+        if (cliSelect() != 0)
+            return -1;
+    }
+    return 0;
+}
+
+static void cliPrintContextError(void) {
+    if (context == 0) return;
+    fprintf(stderr,"Error: %s\n",context->errstr);
+}
+
+static sds cliFormatReplyTTY(redisReply *r, char *prefix) {
+    sds out = sdsempty();
+    switch (r->type) {
+    case 6:
+        out = sdscatprintf(out,"(error) %s\n", r->str);
+    break;
+    case 5:
+        out = sdscat(out,r->str);
+        out = sdscat(out,"\n");
+    break;
+    case 3:
+        out = sdscatprintf(out,"(integer) %lld\n",r->integer);
+    break;
+    case 1:
+
+
+        out = sdscatrepr(out,r->str,r->len);
+        out = sdscat(out,"\n");
+    break;
+    case 4:
+        out = sdscat(out,"(nil)\n");
+    break;
+    case 2:
+        if (r->elements == 0) {
+            out = sdscat(out,"(empty list or set)\n");
+        } else {
+            unsigned int i, idxlen = 0;
+            char _prefixlen[16];
+            char _prefixfmt[16];
+            sds _prefix;
+            sds tmp;
+
+
+            i = r->elements;
+            do {
+                idxlen++;
+                i /= 10;
+            } while(i);
+
+
+            memset(_prefixlen,' ',idxlen+2);
+            _prefixlen[idxlen+2] = '\0';
+            _prefix = sdscat(sdsnew(prefix),_prefixlen);
+
+
+            snprintf(_prefixfmt,sizeof(_prefixfmt),"%%s%%%ud) ",idxlen);
+
+            for (i = 0; i < r->elements; i++) {
+
+
+                out = sdscatprintf(out,_prefixfmt,i == 0 ? "" : prefix,i+1);
+
+
+                tmp = cliFormatReplyTTY(r->element[i],_prefix);
+                out = sdscatlen(out,tmp,sdslen(tmp));
+                sdsfree(tmp);
+            }
+            sdsfree(_prefix);
+        }
+    break;
+    default:
+        fprintf(stderr,"Unknown reply type: %d\n", r->type);
+        exit(1);
+    }
+    return out;
+}
+
+int isColorTerm(void) {
+    char *t = getenv("TERM");
+    return t != 0 && strstr(t,"xterm") != 0;
+}
+
+
+
+sds sdscatcolor(sds o, char *s, size_t len, char *color) {
+    if (!isColorTerm()) return sdscatlen(o,s,len);
+
+    int bold = strstr(color,"bold") != 0;
+    int ccode = 37;
+    if (strstr(color,"red")) ccode = 31;
+    else if (strstr(color,"green")) ccode = 32;
+    else if (strstr(color,"yellow")) ccode = 33;
+    else if (strstr(color,"blue")) ccode = 34;
+    else if (strstr(color,"magenta")) ccode = 35;
+    else if (strstr(color,"cyan")) ccode = 36;
+    else if (strstr(color,"white")) ccode = 37;
+
+    o = sdscatfmt(o,"\033[%i;%i;49m",bold,ccode);
+    o = sdscatlen(o,s,len);
+    o = sdscat(o,"\033[0m");
+    return o;
+}
+
+
+
+sds sdsCatColorizedLdbReply(sds o, char *s, size_t len) {
+    char *color = "white";
+
+    if (strstr(s,"<debug>")) color = "bold";
+    if (strstr(s,"<redis>")) color = "green";
+    if (strstr(s,"<reply>")) color = "cyan";
+    if (strstr(s,"<error>")) color = "red";
+    if (strstr(s,"<hint>")) color = "bold";
+    if (strstr(s,"<value>") || strstr(s,"<retval>")) color = "magenta";
+    if (len > 4 && isdigit(s[3])) {
+        if (s[1] == '>') color = "yellow";
+        else if (s[2] == '#') color = "bold";
+    }
+    return sdscatcolor(o,s,len,color);
+}
+
+static sds cliFormatReplyRaw(redisReply *r) {
+    sds out = sdsempty(), tmp;
+    size_t i;
+
+    switch (r->type) {
+    case 4:
+
+        break;
+    case 6:
+        out = sdscatlen(out,r->str,r->len);
+        out = sdscatlen(out,"\n",1);
+        break;
+    case 5:
+    case 1:
+        if (r->type == 5 && config.eval_ldb) {
+
+
+
+
+
+            if (strstr(r->str,"<endsession>") == r->str) {
+                config.enable_ldb_on_eval = 0;
+                config.eval_ldb = 0;
+                config.eval_ldb_end = 1;
+                config.output = 0;
+                cliRefreshPrompt();
+            } else {
+                out = sdsCatColorizedLdbReply(out,r->str,r->len);
+            }
+        } else {
+            out = sdscatlen(out,r->str,r->len);
+        }
+        break;
+    case 3:
+        out = sdscatprintf(out,"%lld",r->integer);
+        break;
+    case 2:
+        for (i = 0; i < r->elements; i++) {
+            if (i > 0) out = sdscat(out,config.mb_delim);
+            tmp = cliFormatReplyRaw(r->element[i]);
+            out = sdscatlen(out,tmp,sdslen(tmp));
+            sdsfree(tmp);
+        }
+        break;
+    default:
+        fprintf(stderr,"Unknown reply type: %d\n", r->type);
+        exit(1);
+    }
+    return out;
+}
+
+static sds cliFormatReplyCSV(redisReply *r) {
+    unsigned int i;
+
+    sds out = sdsempty();
+    switch (r->type) {
+    case 6:
+        out = sdscat(out,"ERROR,");
+        out = sdscatrepr(out,r->str,strlen(r->str));
+    break;
+    case 5:
+        out = sdscatrepr(out,r->str,r->len);
+    break;
+    case 3:
+        out = sdscatprintf(out,"%lld",r->integer);
+    break;
+    case 1:
+        out = sdscatrepr(out,r->str,r->len);
+    break;
+    case 4:
+        out = sdscat(out,"NIL");
+    break;
+    case 2:
+        for (i = 0; i < r->elements; i++) {
+            sds tmp = cliFormatReplyCSV(r->element[i]);
+            out = sdscatlen(out,tmp,sdslen(tmp));
+            if (i != r->elements-1) out = sdscat(out,",");
+            sdsfree(tmp);
+        }
+    break;
+    default:
+        fprintf(stderr,"Unknown reply type: %d\n", r->type);
+        exit(1);
+    }
+    return out;
+}
+
+static int cliReadReply(int output_raw_strings) {
+    void *_reply;
+    redisReply *reply;
+    sds out = 0;
+    int output = 1;
+
+    if (redisGetReply(context,&_reply) != 0) {
+        if (config.shutdown) {
+            redisFree(context);
+            context = 0;
+            return 0;
+        }
+        if (config.interactive) {
+
+            if (context->err == 1 &&
+                (errno == ECONNRESET || errno == EPIPE))
+                return -1;
+            if (context->err == 3)
+                return -1;
+        }
+        cliPrintContextError();
+        exit(1);
+        return -1;
+    }
+
+    reply = (redisReply*)_reply;
+
+    config.last_cmd_type = reply->type;
+
+
+
+    if (config.cluster_mode && reply->type == 6 &&
+        (!strncmp(reply->str,"MOVED",5) || !strcmp(reply->str,"ASK")))
+    {
+        char *p = reply->str, *s;
+        int slot;
+
+        output = 0;
+
+
+
+
+
+        s = strchr(p,' ');
+        p = strchr(s+1,' ');
+        *p = '\0';
+        slot = atoi(s+1);
+        s = strrchr(p+1,':');
+        *s = '\0';
+        sdsfree(config.hostip);
+        config.hostip = sdsnew(p+1);
+        config.hostport = atoi(s+1);
+        if (config.interactive)
+            printf("-> Redirected to slot [%d] located at %s:%d\n",
+                slot, config.hostip, config.hostport);
+        config.cluster_reissue_command = 1;
+        cliRefreshPrompt();
+    }
+
+    if (output) {
+        if (output_raw_strings) {
+            out = cliFormatReplyRaw(reply);
+        } else {
+            if (config.output == 1) {
+                out = cliFormatReplyRaw(reply);
+                out = sdscat(out,"\n");
+            } else if (config.output == 0) {
+                out = cliFormatReplyTTY(reply,"");
+            } else if (config.output == 2) {
+                out = cliFormatReplyCSV(reply);
+                out = sdscat(out,"\n");
+            }
+        }
+        fwrite(out,sdslen(out),1,stdout);
+        sdsfree(out);
+    }
+    freeReplyObject(reply);
+    return 0;
+}
+
+static int cliSendCommand(int argc, char **argv, int repeat) {
+    char *command = argv[0];
+    size_t *argvlen;
+    int j, output_raw;
+
+    if (!config.eval_ldb &&
+        (!strcasecmp(command,"help") || !strcasecmp(command,"?"))) {
+        cliOutputHelp(--argc, ++argv);
+        return 0;
+    }
+
+    if (context == 0) return -1;
+
+    output_raw = 0;
+    if (!strcasecmp(command,"info") ||
+        (argc >= 2 && !strcasecmp(command,"debug") &&
+                       !strcasecmp(argv[1],"htstats")) ||
+        (argc >= 2 && !strcasecmp(command,"memory") &&
+                      (!strcasecmp(argv[1],"malloc-stats") ||
+                       !strcasecmp(argv[1],"doctor"))) ||
+        (argc == 2 && !strcasecmp(command,"cluster") &&
+                      (!strcasecmp(argv[1],"nodes") ||
+                       !strcasecmp(argv[1],"info"))) ||
+        (argc == 2 && !strcasecmp(command,"client") &&
+                       !strcasecmp(argv[1],"list")) ||
+        (argc == 3 && !strcasecmp(command,"latency") &&
+                       !strcasecmp(argv[1],"graph")) ||
+        (argc == 2 && !strcasecmp(command,"latency") &&
+                       !strcasecmp(argv[1],"doctor")))
+    {
+        output_raw = 1;
+    }
+
+    if (!strcasecmp(command,"shutdown")) config.shutdown = 1;
+    if (!strcasecmp(command,"monitor")) config.monitor_mode = 1;
+    if (!strcasecmp(command,"subscribe") ||
+        !strcasecmp(command,"psubscribe")) config.pubsub_mode = 1;
+    if (!strcasecmp(command,"sync") ||
+        !strcasecmp(command,"psync")) config.slave_mode = 1;
+
+
+
+    if (argc == 3 && !strcasecmp(argv[0],"script") &&
+                     !strcasecmp(argv[1],"debug"))
+    {
+        if (!strcasecmp(argv[2],"yes") || !strcasecmp(argv[2],"sync")) {
+            config.enable_ldb_on_eval = 1;
+        } else {
+            config.enable_ldb_on_eval = 0;
+        }
+    }
+
+
+    if (!strcasecmp(command,"eval") && config.enable_ldb_on_eval) {
+        config.eval_ldb = 1;
+        config.output = 1;
+    }
+
+
+    argvlen = zmalloc(argc*sizeof(size_t));
+    for (j = 0; j < argc; j++)
+        argvlen[j] = sdslen(argv[j]);
+
+    while(repeat--) {
+        redisAppendCommandArgv(context,argc,(const char**)argv,argvlen);
+        while (config.monitor_mode) {
+            if (cliReadReply(output_raw) != 0) exit(1);
+            fflush(stdout);
+        }
+
+        if (config.pubsub_mode) {
+            if (config.output != 1)
+                printf("Reading messages... (press Ctrl-C to quit)\n");
+            while (1) {
+                if (cliReadReply(output_raw) != 0) exit(1);
+            }
+        }
+
+        if (config.slave_mode) {
+            printf("Entering slave output mode...  (press Ctrl-C to quit)\n");
+            slaveMode();
+            config.slave_mode = 0;
+            zfree(argvlen);
+            return -1;
+        }
+
+        if (cliReadReply(output_raw) != 0) {
+            zfree(argvlen);
+            return -1;
+        } else {
+
+            if (!strcasecmp(command,"select") && argc == 2 && config.last_cmd_type != 6) {
+                config.dbnum = atoi(argv[1]);
+                cliRefreshPrompt();
+            } else if (!strcasecmp(command,"auth") && argc == 2) {
+                cliSelect();
+            }
+        }
+        if (config.interval) usleep(config.interval);
+        fflush(stdout);
+    }
+
+    zfree(argvlen);
+    return 0;
+}
+
+
+static redisReply *reconnectingRedisCommand(redisContext *c, const char *fmt, ...) {
+    redisReply *reply = 0;
+    int tries = 0;
+    va_list ap;
+
+    assert(!c->err);
+    while(reply == 0) {
+        while (c->err & (1 | 3)) {
+            printf("\r\x1b[0K");
+            printf("Reconnecting... %d\r", ++tries);
+            fflush(stdout);
+
+            redisFree(c);
+            c = redisConnect(config.hostip,config.hostport);
+            usleep(1000000);
+        }
+
+        __builtin_va_start((ap));
+        reply = redisvCommand(c,fmt,ap);
+        ;
+
+        if (c->err && !(c->err & (1 | 3))) {
+            fprintf(stderr, "Error: %s\n", c->errstr);
+            exit(1);
+        } else if (tries > 0) {
+            printf("\r\x1b[0K");
+        }
+    }
+
+    context = c;
+    return reply;
+}
+
+
+
+
+
+static int parseOptions(int argc, char **argv) {
+    int i;
+
+    for (i = 1; i < argc; i++) {
+        int lastarg = i==argc-1;
+
+        if (!strcmp(argv[i],"-h") && !lastarg) {
+            sdsfree(config.hostip);
+            config.hostip = sdsnew(argv[++i]);
+        } else if (!strcmp(argv[i],"-h") && lastarg) {
+            usage();
+        } else if (!strcmp(argv[i],"--help")) {
+            usage();
+        } else if (!strcmp(argv[i],"-x")) {
+            config.stdinarg = 1;
+        } else if (!strcmp(argv[i],"-p") && !lastarg) {
+            config.hostport = atoi(argv[++i]);
+        } else if (!strcmp(argv[i],"-s") && !lastarg) {
+            config.hostsocket = argv[++i];
+        } else if (!strcmp(argv[i],"-r") && !lastarg) {
+            config.repeat = strtoll(argv[++i],0,10);
+        } else if (!strcmp(argv[i],"-i") && !lastarg) {
+            double seconds = atof(argv[++i]);
+            config.interval = seconds*1000000;
+        } else if (!strcmp(argv[i],"-n") && !lastarg) {
+            config.dbnum = atoi(argv[++i]);
+        } else if (!strcmp(argv[i],"-a") && !lastarg) {
+            config.auth = argv[++i];
+        } else if (!strcmp(argv[i],"-u") && !lastarg) {
+            parseRedisUri(argv[++i]);
+        } else if (!strcmp(argv[i],"--raw")) {
+            config.output = 1;
+        } else if (!strcmp(argv[i],"--no-raw")) {
+            config.output = 0;
+        } else if (!strcmp(argv[i],"--csv")) {
+            config.output = 2;
+        } else if (!strcmp(argv[i],"--latency")) {
+            config.latency_mode = 1;
+        } else if (!strcmp(argv[i],"--latency-dist")) {
+            config.latency_dist_mode = 1;
+        } else if (!strcmp(argv[i],"--mono")) {
+            spectrum_palette = spectrum_palette_mono;
+            spectrum_palette_size = spectrum_palette_mono_size;
+        } else if (!strcmp(argv[i],"--latency-history")) {
+            config.latency_mode = 1;
+            config.latency_history = 1;
+        } else if (!strcmp(argv[i],"--lru-test") && !lastarg) {
+            config.lru_test_mode = 1;
+            config.lru_test_sample_size = strtoll(argv[++i],0,10);
+        } else if (!strcmp(argv[i],"--slave")) {
+            config.slave_mode = 1;
+        } else if (!strcmp(argv[i],"--stat")) {
+            config.stat_mode = 1;
+        } else if (!strcmp(argv[i],"--scan")) {
+            config.scan_mode = 1;
+        } else if (!strcmp(argv[i],"--pattern") && !lastarg) {
+            config.pattern = argv[++i];
+        } else if (!strcmp(argv[i],"--intrinsic-latency") && !lastarg) {
+            config.intrinsic_latency_mode = 1;
+            config.intrinsic_latency_duration = atoi(argv[++i]);
+        } else if (!strcmp(argv[i],"--rdb") && !lastarg) {
+            config.getrdb_mode = 1;
+            config.rdb_filename = argv[++i];
+        } else if (!strcmp(argv[i],"--pipe")) {
+            config.pipe_mode = 1;
+        } else if (!strcmp(argv[i],"--pipe-timeout") && !lastarg) {
+            config.pipe_timeout = atoi(argv[++i]);
+        } else if (!strcmp(argv[i],"--bigkeys")) {
+            config.bigkeys = 1;
+        } else if (!strcmp(argv[i],"--hotkeys")) {
+            config.hotkeys = 1;
+        } else if (!strcmp(argv[i],"--eval") && !lastarg) {
+            config.eval = argv[++i];
+        } else if (!strcmp(argv[i],"--ldb")) {
+            config.eval_ldb = 1;
+            config.output = 1;
+        } else if (!strcmp(argv[i],"--ldb-sync-mode")) {
+            config.eval_ldb = 1;
+            config.eval_ldb_sync = 1;
+            config.output = 1;
+        } else if (!strcmp(argv[i],"-c")) {
+            config.cluster_mode = 1;
+        } else if (!strcmp(argv[i],"-d") && !lastarg) {
+            sdsfree(config.mb_delim);
+            config.mb_delim = sdsnew(argv[++i]);
+        } else if (!strcmp(argv[i],"-v") || !strcmp(argv[i], "--version")) {
+            sds version = cliVersion();
+            printf("redis-cli %s\n", version);
+            sdsfree(version);
+            exit(0);
+        } else {
+            if (argv[i][0] == '-') {
+                fprintf(stderr,
+                    "Unrecognized option or bad number of args for: '%s'\n",
+                    argv[i]);
+                exit(1);
+            } else {
+
+                break;
+            }
+        }
+    }
+
+
+    if (config.eval_ldb && config.eval == 0) {
+        fprintf(stderr,"Options --ldb and --ldb-sync-mode require --eval.\n");
+        fprintf(stderr,"Try %s --help for more information.\n", argv[0]);
+        exit(1);
+    }
+    return i;
+}
+
+static sds readArgFromStdin(void) {
+    char buf[1024];
+    sds arg = sdsempty();
+
+    while(1) {
+        int nread = read(fileno(stdin),buf,1024);
+
+        if (nread == 0) break;
+        else if (nread == -1) {
+            perror("Reading from standard input");
+            exit(1);
+        }
+        arg = sdscatlen(arg,buf,nread);
+    }
+    return arg;
+}
+
+static void usage(void) {
+    sds version = cliVersion();
+    fprintf(stderr,
+"redis-cli %s\n"
+"\n"
+"Usage: redis-cli [OPTIONS] [cmd [arg [arg ...]]]\n"
+"  -h <hostname>      Server hostname (default: 127.0.0.1).\n"
+"  -p <port>          Server port (default: 6379).\n"
+"  -s <socket>        Server socket (overrides hostname and port).\n"
+"  -a <password>      Password to use when connecting to the server.\n"
+"  -u <uri>           Server URI.\n"
+"  -r <repeat>        Execute specified command N times.\n"
+"  -i <interval>      When -r is used, waits <interval> seconds per command.\n"
+"                     It is possible to specify sub-second times like -i 0.1.\n"
+"  -n <db>            Database number.\n"
+"  -x                 Read last argument from STDIN.\n"
+"  -d <delimiter>     Multi-bulk delimiter in for raw formatting (default: \\n).\n"
+"  -c                 Enable cluster mode (follow -ASK and -MOVED redirections).\n"
+"  --raw              Use raw formatting for replies (default when STDOUT is\n"
+"                     not a tty).\n"
+"  --no-raw           Force formatted output even when STDOUT is not a tty.\n"
+"  --csv              Output in CSV format.\n"
+"  --stat             Print rolling stats about server: mem, clients, ...\n"
+"  --latency          Enter a special mode continuously sampling latency.\n"
+"                     If you use this mode in an interactive session it runs\n"
+"                     forever displaying real-time stats. Otherwise if --raw or\n"
+"                     --csv is specified, or if you redirect the output to a non\n"
+"                     TTY, it samples the latency for 1 second (you can use\n"
+"                     -i to change the interval), then produces a single output\n"
+"                     and exits.\n"
+"  --latency-history  Like --latency but tracking latency changes over time.\n"
+"                     Default time interval is 15 sec. Change it using -i.\n"
+"  --latency-dist     Shows latency as a spectrum, requires xterm 256 colors.\n"
+"                     Default time interval is 1 sec. Change it using -i.\n"
+"  --lru-test <keys>  Simulate a cache workload with an 80-20 distribution.\n"
+"  --slave            Simulate a slave showing commands received from the master.\n"
+"  --rdb <filename>   Transfer an RDB dump from remote server to local file.\n"
+"  --pipe             Transfer raw Redis protocol from stdin to server.\n"
+"  --pipe-timeout <n> In --pipe mode, abort with error if after sending all data.\n"
+"                     no reply is received within <n> seconds.\n"
+"                     Default timeout: %d. Use 0 to wait forever.\n"
+"  --bigkeys          Sample Redis keys looking for big keys.\n"
+"  --hotkeys          Sample Redis keys looking for hot keys.\n"
+"                     only works when maxmemory-policy is *lfu.\n"
+"  --scan             List all keys using the SCAN command.\n"
+"  --pattern <pat>    Useful with --scan to specify a SCAN pattern.\n"
+"  --intrinsic-latency <sec> Run a test to measure intrinsic system latency.\n"
+"                     The test will run for the specified amount of seconds.\n"
+"  --eval <file>      Send an EVAL command using the Lua script at <file>.\n"
+"  --ldb              Used with --eval enable the Redis Lua debugger.\n"
+"  --ldb-sync-mode    Like --ldb but uses the synchronous Lua debugger, in\n"
+"                     this mode the server is blocked and script changes are\n"
+"                     are not rolled back from the server memory.\n"
+"  --help             Output this help and exit.\n"
+"  --version          Output version and exit.\n"
+"\n"
+"Examples:\n"
+"  cat /etc/passwd | redis-cli -x set mypasswd\n"
+"  redis-cli get mypasswd\n"
+"  redis-cli -r 100 lpush mylist x\n"
+"  redis-cli -r 100 -i 1 info | grep used_memory_human:\n"
+"  redis-cli --eval myscript.lua key1 key2 , arg1 arg2 arg3\n"
+"  redis-cli --scan --pattern '*:12345*'\n"
+"\n"
+"  (Note: when using --eval the comma separates KEYS[] from ARGV[] items)\n"
+"\n"
+"When no command is given, redis-cli starts in interactive mode.\n"
+"Type \"help\" in interactive mode for information on available commands\n"
+"and settings.\n"
+"\n",
+        version, 30);
+    sdsfree(version);
+    exit(1);
+}
+
+
+static char **convertToSds(int count, char** args) {
+  int j;
+  char **sds = zmalloc(sizeof(char*)*count);
+
+  for(j = 0; j < count; j++)
+    sds[j] = sdsnew(args[j]);
+
+  return sds;
+}
+
+static int issueCommandRepeat(int argc, char **argv, long repeat) {
+    while (1) {
+        config.cluster_reissue_command = 0;
+        if (cliSendCommand(argc,argv,repeat) != 0) {
+            cliConnect(1);
+
+
+
+            if (cliSendCommand(argc,argv,repeat) != 0) {
+                cliPrintContextError();
+                return -1;
+            }
+         }
+
+         if (config.cluster_mode && config.cluster_reissue_command) {
+            cliConnect(1);
+         } else {
+             break;
+        }
+    }
+    return 0;
+}
+
+static int issueCommand(int argc, char **argv) {
+    return issueCommandRepeat(argc, argv, config.repeat);
+}
+
+
+
+
+
+
+
+static sds *cliSplitArgs(char *line, int *argc) {
+    if (config.eval_ldb && (strstr(line,"eval ") == line ||
+                            strstr(line,"e ") == line))
+    {
+        sds *argv = sds_malloc(sizeof(sds)*2);
+        *argc = 2;
+        int len = strlen(line);
+        int elen = line[1] == ' ' ? 2 : 5;
+        argv[0] = sdsnewlen(line,elen-1);
+        argv[1] = sdsnewlen(line+elen,len-elen);
+        return argv;
+    } else {
+        return sdssplitargs(line,argc);
+    }
+}
+
+
+
+
+void cliSetPreferences(char **argv, int argc, int interactive) {
+    if (!strcasecmp(argv[0],":set") && argc >= 2) {
+        if (!strcasecmp(argv[1],"hints")) pref.hints = 1;
+        else if (!strcasecmp(argv[1],"nohints")) pref.hints = 0;
+        else {
+            printf("%sunknown redis-cli preference '%s'\n",
+                interactive ? "" : ".redisclirc: ",
+                argv[1]);
+        }
+    } else {
+        printf("%sunknown redis-cli internal command '%s'\n",
+            interactive ? "" : ".redisclirc: ",
+            argv[0]);
+    }
+}
+
+
+void cliLoadPreferences(void) {
+    sds rcfile = getDotfilePath("REDISCLI_RCFILE",".redisclirc");
+    if (rcfile == 0) return;
+    FILE *fp = fopen(rcfile,"r");
+    char buf[1024];
+
+    if (fp) {
+        while(fgets(buf,sizeof(buf),fp) != 0) {
+            sds *argv;
+            int argc;
+
+            argv = sdssplitargs(buf,&argc);
+            if (argc > 0) cliSetPreferences(argv,argc,0);
+            sdsfreesplitres(argv,argc);
+        }
+        fclose(fp);
+    }
+    sdsfree(rcfile);
+}
+
+static void repl(void) {
+    sds historyfile = 0;
+    int history = 0;
+    char *line;
+    int argc;
+    sds *argv;
+
+
+
+    cliInitHelp();
+    cliIntegrateHelp();
+
+    config.interactive = 1;
+    linenoiseSetMultiLine(1);
+    linenoiseSetCompletionCallback(completionCallback);
+    linenoiseSetHintsCallback(hintsCallback);
+    linenoiseSetFreeHintsCallback(freeHintsCallback);
+
+
+    if (isatty(fileno(stdin))) {
+        historyfile = getDotfilePath("REDISCLI_HISTFILE",".rediscli_history");
+
+        history = 1;
+        if (historyfile != 0) {
+            linenoiseHistoryLoad(historyfile);
+        }
+        cliLoadPreferences();
+    }
+
+    cliRefreshPrompt();
+    while((line = linenoise(context ? config.prompt : "not connected> ")) != 0) {
+        if (line[0] != '\0') {
+            argv = cliSplitArgs(line,&argc);
+            if (history) linenoiseHistoryAdd(line);
+            if (historyfile) linenoiseHistorySave(historyfile);
+
+            if (argv == 0) {
+                printf("Invalid argument(s)\n");
+                linenoiseFree(line);
+                continue;
+            } else if (argc > 0) {
+                if (strcasecmp(argv[0],"quit") == 0 ||
+                    strcasecmp(argv[0],"exit") == 0)
+                {
+                    exit(0);
+                } else if (argv[0][0] == ':') {
+                    cliSetPreferences(argv,argc,1);
+                    continue;
+                } else if (strcasecmp(argv[0],"restart") == 0) {
+                    if (config.eval) {
+                        config.eval_ldb = 1;
+                        config.output = 1;
+                        return;
+                    } else {
+                        printf("Use 'restart' only in Lua debugging mode.");
+                    }
+                } else if (argc == 3 && !strcasecmp(argv[0],"connect")) {
+                    sdsfree(config.hostip);
+                    config.hostip = sdsnew(argv[1]);
+                    config.hostport = atoi(argv[2]);
+                    cliRefreshPrompt();
+                    cliConnect(1);
+                } else if (argc == 1 && !strcasecmp(argv[0],"clear")) {
+                    linenoiseClearScreen();
+                } else {
+                    long long start_time = mstime(), elapsed;
+                    int repeat, skipargs = 0;
+                    char *endptr;
+
+                    repeat = strtol(argv[0], &endptr, 10);
+                    if (argc > 1 && *endptr == '\0' && repeat) {
+                        skipargs = 1;
+                    } else {
+                        repeat = 1;
+                    }
+
+                    issueCommandRepeat(argc-skipargs, argv+skipargs, repeat);
+
+
+
+                    if (config.eval_ldb_end) {
+                        config.eval_ldb_end = 0;
+                        cliReadReply(0);
+                        printf("\n(Lua debugging session ended%s)\n\n",
+                            config.eval_ldb_sync ? "" :
+                            " -- dataset changes rolled back");
+                    }
+
+                    elapsed = mstime()-start_time;
+                    if (elapsed >= 500 &&
+                        config.output == 0)
+                    {
+                        printf("(%.2fs)\n",(double)elapsed/1000);
+                    }
+                }
+            }
+
+            sdsfreesplitres(argv,argc);
+        }
+
+        linenoiseFree(line);
+    }
+    exit(0);
+}
+
+static int noninteractive(int argc, char **argv) {
+    int retval = 0;
+    if (config.stdinarg) {
+        argv = zrealloc(argv, (argc+1)*sizeof(char*));
+        argv[argc] = readArgFromStdin();
+        retval = issueCommand(argc+1, argv);
+    } else {
+        retval = issueCommand(argc, argv);
+    }
+    return retval;
+}
+
+
+
+
+
+static int evalMode(int argc, char **argv) {
+    sds script = 0;
+    FILE *fp;
+    char buf[1024];
+    size_t nread;
+    char **argv2;
+    int j, got_comma, keys;
+    int retval = 0;
+
+    while(1) {
+        if (config.eval_ldb) {
+            printf(
+            "Lua debugging session started, please use:\n"
+            "quit    -- End the session.\n"
+            "restart -- Restart the script in debug mode again.\n"
+            "help    -- Show Lua script debugging commands.\n\n"
+            );
+        }
+
+        sdsfree(script);
+        script = sdsempty();
+        got_comma = 0;
+        keys = 0;
+
+
+        fp = fopen(config.eval,"r");
+        if (!fp) {
+            fprintf(stderr,
+                "Can't open file '%s': %s\n", config.eval, strerror(errno));
+            exit(1);
+        }
+        while((nread = fread(buf,1,sizeof(buf),fp)) != 0) {
+            script = sdscatlen(script,buf,nread);
+        }
+        fclose(fp);
+
+
+        if (config.eval_ldb) {
+            redisReply *reply = redisCommand(context,
+                    config.eval_ldb_sync ?
+                    "SCRIPT DEBUG sync": "SCRIPT DEBUG yes");
+            if (reply) freeReplyObject(reply);
+        }
+
+
+        argv2 = zmalloc(sizeof(sds)*(argc+3));
+        argv2[0] = sdsnew("EVAL");
+        argv2[1] = script;
+        for (j = 0; j < argc; j++) {
+            if (!got_comma && argv[j][0] == ',' && argv[j][1] == 0) {
+                got_comma = 1;
+                continue;
+            }
+            argv2[j+3-got_comma] = sdsnew(argv[j]);
+            if (!got_comma) keys++;
+        }
+        argv2[2] = sdscatprintf(sdsempty(),"%d",keys);
+
+
+        int eval_ldb = config.eval_ldb;
+        retval = issueCommand(argc+3-got_comma, argv2);
+        if (eval_ldb) {
+            if (!config.eval_ldb) {
+
+
+
+                printf("Eval debugging session can't start:\n");
+                cliReadReply(0);
+                break;
+            } else {
+                strncpy(config.prompt,"lua debugger> ",sizeof(config.prompt));
+                repl();
+
+                cliConnect(1);
+                printf("\n");
+            }
+        } else {
+            break;
+        }
+    }
+    return retval;
+}
+
+
+
+
+
+static void latencyModePrint(long long min, long long max, double avg, long long count) {
+    if (config.output == 0) {
+        printf("min: %lld, max: %lld, avg: %.2f (%lld samples)",
+                min, max, avg, count);
+        fflush(stdout);
+    } else if (config.output == 2) {
+        printf("%lld,%lld,%.2f,%lld\n", min, max, avg, count);
+    } else if (config.output == 1) {
+        printf("%lld %lld %.2f %lld\n", min, max, avg, count);
+    }
+}
+
+
+
+static void latencyMode(void) {
+    redisReply *reply;
+    long long start, latency, min = 0, max = 0, tot = 0, count = 0;
+    long long history_interval =
+        config.interval ? config.interval/1000 :
+                          15000;
+    double avg;
+    long long history_start = mstime();
+
+
+
+    if (config.interval == 0) {
+        config.interval = 1000;
+    } else {
+        config.interval /= 1000;
+    }
+
+    if (!context) exit(1);
+    while(1) {
+        start = mstime();
+        reply = reconnectingRedisCommand(context,"PING");
+        if (reply == 0) {
+            fprintf(stderr,"\nI/O error\n");
+            exit(1);
+        }
+        latency = mstime()-start;
+        freeReplyObject(reply);
+        count++;
+        if (count == 1) {
+            min = max = tot = latency;
+            avg = (double) latency;
+        } else {
+            if (latency < min) min = latency;
+            if (latency > max) max = latency;
+            tot += latency;
+            avg = (double) tot/count;
+        }
+
+        if (config.output == 0) {
+            printf("\x1b[0G\x1b[2K");
+            latencyModePrint(min,max,avg,count);
+        } else {
+            if (config.latency_history) {
+                latencyModePrint(min,max,avg,count);
+            } else if (mstime()-history_start > config.interval) {
+                latencyModePrint(min,max,avg,count);
+                exit(0);
+            }
+        }
+
+        if (config.latency_history && mstime()-history_start > history_interval)
+        {
+            printf(" -- %.2f seconds range\n", (float)(mstime()-history_start)/1000);
+            history_start = mstime();
+            min = max = tot = count = 0;
+        }
+        usleep(10 * 1000);
+    }
+}
+# 1657 "src/redis-cli.c"
+struct distsamples {
+    long long max;
+    long long count;
+    int character;
+};
+# 1674 "src/redis-cli.c"
+void showLatencyDistSamples(struct distsamples *samples, long long tot) {
+    int j;
+
+
+
+
+
+
+    printf("\033[38;5;0m");
+    for (j = 0; ; j++) {
+        int coloridx =
+            ceil((float) samples[j].count / tot * (spectrum_palette_size-1));
+        int color = spectrum_palette[coloridx];
+        printf("\033[48;5;%dm%c", (int)color, samples[j].character);
+        samples[j].count = 0;
+        if (samples[j].max == 0) break;
+    }
+    printf("\033[0m\n");
+    fflush(stdout);
+}
+
+
+
+void showLatencyDistLegend(void) {
+    int j;
+
+    printf("---------------------------------------------\n");
+    printf(". - * #          .01 .125 .25 .5 milliseconds\n");
+    printf("1,2,3,...,9      from 1 to 9     milliseconds\n");
+    printf("A,B,C,D,E        10,20,30,40,50  milliseconds\n");
+    printf("F,G,H,I,J        .1,.2,.3,.4,.5       seconds\n");
+    printf("K,L,M,N,O,P,Q,?  1,2,4,8,16,30,60,>60 seconds\n");
+    printf("From 0 to 100%%: ");
+    for (j = 0; j < spectrum_palette_size; j++) {
+        printf("\033[48;5;%dm ", spectrum_palette[j]);
+    }
+    printf("\033[0m\n");
+    printf("---------------------------------------------\n");
+}
+
+static void latencyDistMode(void) {
+    redisReply *reply;
+    long long start, latency, count = 0;
+    long long history_interval =
+        config.interval ? config.interval/1000 :
+                          1000;
+    long long history_start = ustime();
+    int j, outputs = 0;
+
+    struct distsamples samples[] = {
+
+
+
+        {10,0,'.'},
+        {125,0,'-'},
+        {250,0,'*'},
+        {500,0,'#'},
+        {1000,0,'1'},
+        {2000,0,'2'},
+        {3000,0,'3'},
+        {4000,0,'4'},
+        {5000,0,'5'},
+        {6000,0,'6'},
+        {7000,0,'7'},
+        {8000,0,'8'},
+        {9000,0,'9'},
+        {10000,0,'A'},
+        {20000,0,'B'},
+        {30000,0,'C'},
+        {40000,0,'D'},
+        {50000,0,'E'},
+        {100000,0,'F'},
+        {200000,0,'G'},
+        {300000,0,'H'},
+        {400000,0,'I'},
+        {500000,0,'J'},
+        {1000000,0,'K'},
+        {2000000,0,'L'},
+        {4000000,0,'M'},
+        {8000000,0,'N'},
+        {16000000,0,'O'},
+        {30000000,0,'P'},
+        {60000000,0,'Q'},
+        {0,0,'?'},
+    };
+
+    if (!context) exit(1);
+    while(1) {
+        start = ustime();
+        reply = reconnectingRedisCommand(context,"PING");
+        if (reply == 0) {
+            fprintf(stderr,"\nI/O error\n");
+            exit(1);
+        }
+        latency = ustime()-start;
+        freeReplyObject(reply);
+        count++;
+
+
+        for (j = 0; ; j++) {
+            if (samples[j].max == 0 || latency <= samples[j].max) {
+                samples[j].count++;
+                break;
+            }
+        }
+
+
+        if (count && (ustime()-history_start)/1000 > history_interval) {
+            if ((outputs++ % 20) == 0)
+                showLatencyDistLegend();
+            showLatencyDistSamples(samples,count);
+            history_start = ustime();
+            count = 0;
+        }
+        usleep(10 * 1000);
+    }
+}
+
+
+
+
+
+
+
+unsigned long long sendSync(int fd) {
+
+
+
+
+    char buf[4096], *p;
+    ssize_t nread;
+
+
+    if (write(fd,"SYNC\r\n",6) != 6) {
+        fprintf(stderr,"Error writing to master\n");
+        exit(1);
+    }
+
+
+    p = buf;
+    while(1) {
+        nread = read(fd,p,1);
+        if (nread <= 0) {
+            fprintf(stderr,"Error reading bulk length while SYNCing\n");
+            exit(1);
+        }
+        if (*p == '\n' && p != buf) break;
+        if (*p != '\n') p++;
+    }
+    *p = '\0';
+    if (buf[0] == '-') {
+        printf("SYNC with master failed: %s\n", buf);
+        exit(1);
+    }
+    return strtoull(buf+1,0,10);
+}
+
+static void slaveMode(void) {
+    int fd = context->fd;
+    unsigned long long payload = sendSync(fd);
+    char buf[1024];
+    int original_output = config.output;
+
+    fprintf(stderr,"SYNC with master, discarding %llu "
+                   "bytes of bulk transfer...\n", payload);
+
+
+    while(payload) {
+        ssize_t nread;
+
+        nread = read(fd,buf,(payload > sizeof(buf)) ? sizeof(buf) : payload);
+        if (nread <= 0) {
+            fprintf(stderr,"Error reading RDB payload while SYNCing\n");
+            exit(1);
+        }
+        payload -= nread;
+    }
+    fprintf(stderr,"SYNC done. Logging commands from master.\n");
+
+
+    config.output = 2;
+    while (cliReadReply(0) == 0);
+    config.output = original_output;
+}
+
+
+
+
+
+
+
+static void getRDB(void) {
+    int s = context->fd;
+    int fd;
+    unsigned long long payload = sendSync(s);
+    char buf[4096];
+
+    fprintf(stderr,"SYNC sent to master, writing %llu bytes to '%s'\n",
+        payload, config.rdb_filename);
+
+
+    if (!strcmp(config.rdb_filename,"-")) {
+        fd = STDOUT_FILENO;
+    } else {
+        fd = open(config.rdb_filename, O_CREAT|O_WRONLY, 0644);
+        if (fd == -1) {
+            fprintf(stderr, "Error opening '%s': %s\n", config.rdb_filename,
+                strerror(errno));
+            exit(1);
+        }
+    }
+
+    while(payload) {
+        ssize_t nread, nwritten;
+
+        nread = read(s,buf,(payload > sizeof(buf)) ? sizeof(buf) : payload);
+        if (nread <= 0) {
+            fprintf(stderr,"I/O Error reading RDB payload from socket\n");
+            exit(1);
+        }
+        nwritten = write(fd, buf, nread);
+        if (nwritten != nread) {
+            fprintf(stderr,"Error writing data to file: %s\n",
+                strerror(errno));
+            exit(1);
+        }
+        payload -= nread;
+    }
+    close(s);
+    fsync(fd);
+    fprintf(stderr,"Transfer finished with success.\n");
+    exit(0);
+}
+
+
+
+
+
+
+static void pipeMode(void) {
+    int fd = context->fd;
+    long long errors = 0, replies = 0, obuf_len = 0, obuf_pos = 0;
+    char ibuf[1024*16], obuf[1024*16];
+    char aneterr[256];
+    redisReader *reader = redisReaderCreate();
+    redisReply *reply;
+    int eof = 0;
+    int done = 0;
+    char magic[20];
+    time_t last_read_time = time(0);
+
+    srand(time(0));
+
+
+    if (anetNonBlock(aneterr,fd) == -1) {
+        fprintf(stderr, "Can't set the socket in non blocking mode: %s\n",
+            aneterr);
+        exit(1);
+    }
+
+
+
+    while(!done) {
+        int mask = 1;
+
+        if (!eof || obuf_len != 0) mask |= 2;
+        mask = aeWait(fd,mask,1000);
+
+
+        if (mask & 1) {
+            ssize_t nread;
+
+
+            do {
+                nread = read(fd,ibuf,sizeof(ibuf));
+                if (nread == -1 && errno != EAGAIN && errno != EINTR) {
+                    fprintf(stderr, "Error reading from the server: %s\n",
+                        strerror(errno));
+                    exit(1);
+                }
+                if (nread > 0) {
+                    redisReaderFeed(reader,ibuf,nread);
+                    last_read_time = time(0);
+                }
+            } while(nread > 0);
+
+
+            do {
+                if (redisReaderGetReply(reader,(void**)&reply) == -1) {
+                    fprintf(stderr, "Error reading replies from server\n");
+                    exit(1);
+                }
+                if (reply) {
+                    if (reply->type == 6) {
+                        fprintf(stderr,"%s\n", reply->str);
+                        errors++;
+                    } else if (eof && reply->type == 1 &&
+                                      reply->len == 20) {
+
+
+
+                        if (memcmp(reply->str,magic,20) == 0) {
+                            printf("Last reply received from server.\n");
+                            done = 1;
+                            replies--;
+                        }
+                    }
+                    replies++;
+                    freeReplyObject(reply);
+                }
+            } while(reply);
+        }
+
+
+        if (mask & 2) {
+            ssize_t loop_nwritten = 0;
+
+            while(1) {
+
+                if (obuf_len != 0) {
+                    ssize_t nwritten = write(fd,obuf+obuf_pos,obuf_len);
+
+                    if (nwritten == -1) {
+                        if (errno != EAGAIN && errno != EINTR) {
+                            fprintf(stderr, "Error writing to the server: %s\n",
+                                strerror(errno));
+                            exit(1);
+                        } else {
+                            nwritten = 0;
+                        }
+                    }
+                    obuf_len -= nwritten;
+                    obuf_pos += nwritten;
+                    loop_nwritten += nwritten;
+                    if (obuf_len != 0) break;
+                }
+
+                if (obuf_len == 0 && !eof) {
+                    ssize_t nread = read(STDIN_FILENO,obuf,sizeof(obuf));
+
+                    if (nread == 0) {
+
+
+
+
+                        char echo[] =
+                        "\r\n*2\r\n$4\r\nECHO\r\n$20\r\n01234567890123456789\r\n";
+                        int j;
+
+                        eof = 1;
+
+
+
+                        for (j = 0; j < 20; j++)
+                            magic[j] = rand() & 0xff;
+                        memcpy(echo+21,magic,20);
+                        memcpy(obuf,echo,sizeof(echo)-1);
+                        obuf_len = sizeof(echo)-1;
+                        obuf_pos = 0;
+                        printf("All data transferred. Waiting for the last reply...\n");
+                    } else if (nread == -1) {
+                        fprintf(stderr, "Error reading from stdin: %s\n",
+                            strerror(errno));
+                        exit(1);
+                    } else {
+                        obuf_len = nread;
+                        obuf_pos = 0;
+                    }
+                }
+                if ((obuf_len == 0 && eof) ||
+                    loop_nwritten > (128*1024)) break;
+            }
+        }
+
+
+
+
+        if (eof && config.pipe_timeout > 0 &&
+            time(0)-last_read_time > config.pipe_timeout)
+        {
+            fprintf(stderr,"No replies for %d seconds: exiting.\n",
+                config.pipe_timeout);
+            errors++;
+            break;
+        }
+    }
+    redisReaderFree(reader);
+    printf("errors: %lld, replies: %lld\n", errors, replies);
+    if (errors)
+        exit(1);
+    else
+        exit(0);
+}
+# 2079 "src/redis-cli.c"
+static redisReply *sendScan(unsigned long long *it) {
+    redisReply *reply = redisCommand(context, "SCAN %llu", *it);
+
+
+    if(reply == 0) {
+        fprintf(stderr, "\nI/O error\n");
+        exit(1);
+    } else if(reply->type == 6) {
+        fprintf(stderr, "SCAN error: %s\n", reply->str);
+        exit(1);
+    } else if(reply->type != 2) {
+        fprintf(stderr, "Non ARRAY response from SCAN!\n");
+        exit(1);
+    } else if(reply->elements != 2) {
+        fprintf(stderr, "Invalid element count from SCAN!\n");
+        exit(1);
+    }
+
+
+    assert(reply->element[0]->type == 1);
+    assert(reply->element[1]->type == 2);
+
+
+    *it = strtoull(reply->element[0]->str, 0, 10);
+
+    return reply;
+}
+
+static int getDbSize(void) {
+    redisReply *reply;
+    int size;
+
+    reply = redisCommand(context, "DBSIZE");
+
+    if(reply == 0 || reply->type != 3) {
+        fprintf(stderr, "Couldn't determine DBSIZE!\n");
+        exit(1);
+    }
+
+
+    size = reply->integer;
+    freeReplyObject(reply);
+
+    return size;
+}
+
+static int toIntType(char *key, char *type) {
+    if(!strcmp(type, "string")) {
+        return 0;
+    } else if(!strcmp(type, "list")) {
+        return 1;
+    } else if(!strcmp(type, "set")) {
+        return 2;
+    } else if(!strcmp(type, "hash")) {
+        return 3;
+    } else if(!strcmp(type, "zset")) {
+        return 4;
+    } else if(!strcmp(type, "none")) {
+        return 5;
+    } else {
+        fprintf(stderr, "Unknown type '%s' for key '%s'\n", type, key);
+        exit(1);
+    }
+}
+
+static void getKeyTypes(redisReply *keys, int *types) {
+    redisReply *reply;
+    unsigned int i;
+
+
+    for(i=0;i<keys->elements;i++) {
+        redisAppendCommand(context, "TYPE %s", keys->element[i]->str);
+    }
+
+
+    for(i=0;i<keys->elements;i++) {
+        if(redisGetReply(context, (void**)&reply)!=0) {
+            fprintf(stderr, "Error getting type for key '%s' (%d: %s)\n",
+                keys->element[i]->str, context->err, context->errstr);
+            exit(1);
+        } else if(reply->type != 5) {
+            if(reply->type == 6) {
+                fprintf(stderr, "TYPE returned an error: %s\n", reply->str);
+            } else {
+                fprintf(stderr,
+                    "Invalid reply type (%d) for TYPE on key '%s'!\n",
+                    reply->type, keys->element[i]->str);
+            }
+            exit(1);
+        }
+
+        types[i] = toIntType(keys->element[i]->str, reply->str);
+        freeReplyObject(reply);
+    }
+}
+
+static void getKeySizes(redisReply *keys, int *types,
+                        unsigned long long *sizes)
+{
+    redisReply *reply;
+    char *sizecmds[] = {"STRLEN","LLEN","SCARD","HLEN","ZCARD"};
+    unsigned int i;
+
+
+    for(i=0;i<keys->elements;i++) {
+
+        if(types[i]==5)
+            continue;
+
+        redisAppendCommand(context, "%s %s", sizecmds[types[i]],
+            keys->element[i]->str);
+    }
+
+
+    for(i=0;i<keys->elements;i++) {
+
+        if(types[i] == 5) {
+            sizes[i] = 0;
+            continue;
+        }
+
+
+        if(redisGetReply(context, (void**)&reply)!=0) {
+            fprintf(stderr, "Error getting size for key '%s' (%d: %s)\n",
+                keys->element[i]->str, context->err, context->errstr);
+            exit(1);
+        } else if(reply->type != 3) {
+
+
+            fprintf(stderr,
+                "Warning:  %s on '%s' failed (may have changed type)\n",
+                 sizecmds[types[i]], keys->element[i]->str);
+            sizes[i] = 0;
+        } else {
+            sizes[i] = reply->integer;
+        }
+
+        freeReplyObject(reply);
+    }
+}
+
+static void findBigKeys(void) {
+    unsigned long long biggest[5] = {0}, counts[5] = {0}, totalsize[5] = {0};
+    unsigned long long sampled = 0, total_keys, totlen=0, *sizes=0, it=0;
+    sds maxkeys[5] = {0};
+    char *typename[] = {"string","list","set","hash","zset"};
+    char *typeunit[] = {"bytes","items","members","fields","members"};
+    redisReply *reply, *keys;
+    unsigned int arrsize=0, i;
+    int type, *types=0;
+    double pct;
+
+
+    total_keys = getDbSize();
+
+
+    printf("\n# Scanning the entire keyspace to find biggest keys as well as\n");
+    printf("# average sizes per key type.  You can use -i 0.1 to sleep 0.1 sec\n");
+    printf("# per 100 SCAN commands (not usually needed).\n\n");
+
+
+    for(i=0;i<5; i++) {
+        maxkeys[i] = sdsempty();
+        if(!maxkeys[i]) {
+            fprintf(stderr, "Failed to allocate memory for largest key names!\n");
+            exit(1);
+        }
+    }
+
+
+    do {
+
+        pct = 100 * (double)sampled/total_keys;
+
+
+        reply = sendScan(&it);
+        keys = reply->element[1];
+
+
+        if(keys->elements > arrsize) {
+            types = zrealloc(types, sizeof(int)*keys->elements);
+            sizes = zrealloc(sizes, sizeof(unsigned long long)*keys->elements);
+
+            if(!types || !sizes) {
+                fprintf(stderr, "Failed to allocate storage for keys!\n");
+                exit(1);
+            }
+
+            arrsize = keys->elements;
+        }
+
+
+        getKeyTypes(keys, types);
+        getKeySizes(keys, types, sizes);
+
+
+        for(i=0;i<keys->elements;i++) {
+            if((type = types[i]) == 5)
+                continue;
+
+            totalsize[type] += sizes[i];
+            counts[type]++;
+            totlen += keys->element[i]->len;
+            sampled++;
+
+            if(biggest[type]<sizes[i]) {
+                printf(
+                   "[%05.2f%%] Biggest %-6s found so far '%s' with %llu %s\n",
+                   pct, typename[type], keys->element[i]->str, sizes[i],
+                   typeunit[type]);
+
+
+                maxkeys[type] = sdscpy(maxkeys[type], keys->element[i]->str);
+                if(!maxkeys[type]) {
+                    fprintf(stderr, "Failed to allocate memory for key!\n");
+                    exit(1);
+                }
+
+
+                biggest[type] = sizes[i];
+            }
+
+
+            if(sampled % 1000000 == 0) {
+                printf("[%05.2f%%] Sampled %llu keys so far\n", pct, sampled);
+            }
+        }
+
+
+        if(sampled && (sampled %100) == 0 && config.interval) {
+            usleep(config.interval);
+        }
+
+        freeReplyObject(reply);
+    } while(it != 0);
+
+    if(types) zfree(types);
+    if(sizes) zfree(sizes);
+
+
+    printf("\n-------- summary -------\n\n");
+
+    printf("Sampled %llu keys in the keyspace!\n", sampled);
+    printf("Total key length in bytes is %llu (avg len %.2f)\n\n",
+       totlen, totlen ? (double)totlen/sampled : 0);
+
+
+    for(i=0;i<5;i++) {
+        if(sdslen(maxkeys[i])>0) {
+            printf("Biggest %6s found '%s' has %llu %s\n", typename[i], maxkeys[i],
+               biggest[i], typeunit[i]);
+        }
+    }
+
+    printf("\n");
+
+    for(i=0;i<5;i++) {
+        printf("%llu %ss with %llu %s (%05.2f%% of keys, avg size %.2f)\n",
+           counts[i], typename[i], totalsize[i], typeunit[i],
+           sampled ? 100 * (double)counts[i]/sampled : 0,
+           counts[i] ? (double)totalsize[i]/counts[i] : 0);
+    }
+
+
+    for(i=0;i<5;i++) {
+        sdsfree(maxkeys[i]);
+    }
+
+
+    exit(0);
+}
+
+static void getKeyFreqs(redisReply *keys, unsigned long long *freqs) {
+    redisReply *reply;
+    unsigned int i;
+
+
+    for(i=0;i<keys->elements;i++) {
+        redisAppendCommand(context, "OBJECT freq %s", keys->element[i]->str);
+    }
+
+
+    for(i=0;i<keys->elements;i++) {
+        if(redisGetReply(context, (void**)&reply)!=0) {
+            fprintf(stderr, "Error getting freq for key '%s' (%d: %s)\n",
+                keys->element[i]->str, context->err, context->errstr);
+            exit(1);
+        } else if(reply->type != 3) {
+            if(reply->type == 6) {
+                fprintf(stderr, "Error: %s\n", reply->str);
+                exit(1);
+            } else {
+                fprintf(stderr, "Warning: OBJECT freq on '%s' failed (may have been deleted)\n", keys->element[i]->str);
+                freqs[i] = 0;
+            }
+        } else {
+            freqs[i] = reply->integer;
+        }
+        freeReplyObject(reply);
+    }
+}
+
+
+static void findHotKeys(void) {
+    redisReply *keys, *reply;
+    unsigned long long counters[16] = {0};
+    sds hotkeys[16] = {0};
+    unsigned long long sampled = 0, total_keys, *freqs = 0, it = 0;
+    unsigned int arrsize = 0, i, k;
+    double pct;
+
+
+    total_keys = getDbSize();
+
+
+    printf("\n# Scanning the entire keyspace to find hot keys as well as\n");
+    printf("# average sizes per key type.  You can use -i 0.1 to sleep 0.1 sec\n");
+    printf("# per 100 SCAN commands (not usually needed).\n\n");
+
+
+    do {
+
+        pct = 100 * (double)sampled/total_keys;
+
+
+        reply = sendScan(&it);
+        keys = reply->element[1];
+
+
+        if(keys->elements > arrsize) {
+            freqs = zrealloc(freqs, sizeof(unsigned long long)*keys->elements);
+
+            if(!freqs) {
+                fprintf(stderr, "Failed to allocate storage for keys!\n");
+                exit(1);
+            }
+
+            arrsize = keys->elements;
+        }
+
+        getKeyFreqs(keys, freqs);
+
+
+        for(i=0;i<keys->elements;i++) {
+            sampled++;
+
+            if(sampled % 1000000 == 0) {
+                printf("[%05.2f%%] Sampled %llu keys so far\n", pct, sampled);
+            }
+
+
+            k = 0;
+            while (k < 16 && freqs[i] > counters[k]) k++;
+            if (k == 0) continue;
+            k--;
+            if (k == 0 || counters[k] == 0) {
+                sdsfree(hotkeys[k]);
+            } else {
+                sdsfree(hotkeys[0]);
+                memmove(counters,counters+1,sizeof(counters[0])*k);
+                memmove(hotkeys,hotkeys+1,sizeof(hotkeys[0])*k);
+            }
+            counters[k] = freqs[i];
+            hotkeys[k] = sdsnew(keys->element[i]->str);
+            printf(
+               "[%05.2f%%] Hot key '%s' found so far with counter %llu\n",
+               pct, keys->element[i]->str, freqs[i]);
+        }
+
+
+        if(sampled && (sampled %100) == 0 && config.interval) {
+            usleep(config.interval);
+        }
+
+        freeReplyObject(reply);
+    } while(it != 0);
+
+    if (freqs) zfree(freqs);
+
+
+    printf("\n-------- summary -------\n\n");
+
+    printf("Sampled %llu keys in the keyspace!\n", sampled);
+
+    for (i=1; i<= 16; i++) {
+        k = 16 - i;
+        if(counters[k]>0) {
+            printf("hot key found with counter: %llu\tkeyname: %s\n", counters[k], hotkeys[k]);
+            sdsfree(hotkeys[k]);
+        }
+    }
+
+    exit(0);
+}
+# 2481 "src/redis-cli.c"
+static char *getInfoField(char *info, char *field) {
+    char *p = strstr(info,field);
+    char *n1, *n2;
+    char *result;
+
+    if (!p) return 0;
+    p += strlen(field)+1;
+    n1 = strchr(p,'\r');
+    n2 = strchr(p,',');
+    if (n2 && n2 < n1) n1 = n2;
+    result = zmalloc(sizeof(char)*(n1-p)+1);
+    memcpy(result,p,(n1-p));
+    result[n1-p] = '\0';
+    return result;
+}
+
+
+
+static long getLongInfoField(char *info, char *field) {
+    char *value = getInfoField(info,field);
+    long l;
+
+    if (!value) return LONG_MIN;
+    l = strtol(value,0,10);
+    zfree(value);
+    return l;
+}
+
+
+
+void bytesToHuman(char *s, long long n) {
+    double d;
+
+    if (n < 0) {
+        *s = '-';
+        s++;
+        n = -n;
+    }
+    if (n < 1024) {
+
+        sprintf(s,"%lldB",n);
+        return;
+    } else if (n < (1024*1024)) {
+        d = (double)n/(1024);
+        sprintf(s,"%.2fK",d);
+    } else if (n < (1024LL*1024*1024)) {
+        d = (double)n/(1024*1024);
+        sprintf(s,"%.2fM",d);
+    } else if (n < (1024LL*1024*1024*1024)) {
+        d = (double)n/(1024LL*1024*1024);
+        sprintf(s,"%.2fG",d);
+    }
+}
+
+static void statMode(void) {
+    redisReply *reply;
+    long aux, requests = 0;
+    int i = 0;
+
+    while(1) {
+        char buf[64];
+        int j;
+
+        reply = reconnectingRedisCommand(context,"INFO");
+        if (reply->type == 6) {
+            printf("ERROR: %s\n", reply->str);
+            exit(1);
+        }
+
+        if ((i++ % 20) == 0) {
+            printf(
+"------- data ------ --------------------- load -------------------- - child -\n"
+"keys       mem      clients blocked requests            connections          \n");
+        }
+
+
+        aux = 0;
+        for (j = 0; j < 20; j++) {
+            long k;
+
+            sprintf(buf,"db%d:keys",j);
+            k = getLongInfoField(reply->str,buf);
+            if (k == LONG_MIN) continue;
+            aux += k;
+        }
+        sprintf(buf,"%ld",aux);
+        printf("%-11s",buf);
+
+
+        aux = getLongInfoField(reply->str,"used_memory");
+        bytesToHuman(buf,aux);
+        printf("%-8s",buf);
+
+
+        aux = getLongInfoField(reply->str,"connected_clients");
+        sprintf(buf,"%ld",aux);
+        printf(" %-8s",buf);
+
+
+        aux = getLongInfoField(reply->str,"blocked_clients");
+        sprintf(buf,"%ld",aux);
+        printf("%-8s",buf);
+
+
+        aux = getLongInfoField(reply->str,"total_commands_processed");
+        sprintf(buf,"%ld (+%ld)",aux,requests == 0 ? 0 : aux-requests);
+        printf("%-19s",buf);
+        requests = aux;
+
+
+        aux = getLongInfoField(reply->str,"total_connections_received");
+        sprintf(buf,"%ld",aux);
+        printf(" %-12s",buf);
+
+
+        aux = getLongInfoField(reply->str,"bgsave_in_progress");
+        aux |= getLongInfoField(reply->str,"aof_rewrite_in_progress") << 1;
+        aux |= getLongInfoField(reply->str,"loading") << 2;
+        switch(aux) {
+        case 0: break;
+        case 1:
+            printf("SAVE");
+            break;
+        case 2:
+            printf("AOF");
+            break;
+        case 3:
+            printf("SAVE+AOF");
+            break;
+        case 4:
+            printf("LOAD");
+            break;
+        }
+
+        printf("\n");
+        freeReplyObject(reply);
+        usleep(config.interval);
+    }
+}
+
+
+
+
+
+static void scanMode(void) {
+    redisReply *reply;
+    unsigned long long cur = 0;
+
+    do {
+        if (config.pattern)
+            reply = redisCommand(context,"SCAN %llu MATCH %s",
+                cur,config.pattern);
+        else
+            reply = redisCommand(context,"SCAN %llu",cur);
+        if (reply == 0) {
+            printf("I/O error\n");
+            exit(1);
+        } else if (reply->type == 6) {
+            printf("ERROR: %s\n", reply->str);
+            exit(1);
+        } else {
+            unsigned int j;
+
+            cur = strtoull(reply->element[0]->str,0,10);
+            for (j = 0; j < reply->element[1]->elements; j++)
+                printf("%s\n", reply->element[1]->element[j]->str);
+        }
+        freeReplyObject(reply);
+    } while(cur != 0);
+
+    exit(0);
+}
+# 2664 "src/redis-cli.c"
+long long powerLawRand(long long min, long long max, double alpha) {
+    double pl, r;
+
+    max += 1;
+    r = ((double)rand()) / 32767;
+    pl = pow(
+        ((pow(max,alpha+1) - pow(min,alpha+1))*r + pow(min,alpha+1)),
+        (1.0/(alpha+1)));
+    return (max-1-(long long)pl)+min;
+}
+
+
+
+void LRUTestGenKey(char *buf, size_t buflen) {
+    snprintf(buf, buflen, "lru:%lld",
+        powerLawRand(1, config.lru_test_sample_size, 6.2));
+}
+
+
+
+static void LRUTestMode(void) {
+    redisReply *reply;
+    char key[128];
+    long long start_cycle;
+    int j;
+
+    srand(time(0)^getpid());
+    while(1) {
+
+
+
+        start_cycle = mstime();
+        long long hits = 0, misses = 0;
+        while(mstime() - start_cycle < 1000) {
+
+            for (j = 0; j < 250; j++) {
+                char val[6];
+                val[5] = '\0';
+                for (int i = 0; i < 5; i++) val[i] = 'A'+rand()%('z'-'A');
+                LRUTestGenKey(key,sizeof(key));
+                redisAppendCommand(context, "SET %s %s",key,val);
+            }
+            for (j = 0; j < 250; j++)
+                redisGetReply(context, (void**)&reply);
+
+
+            for (j = 0; j < 250; j++) {
+                LRUTestGenKey(key,sizeof(key));
+                redisAppendCommand(context, "GET %s",key);
+            }
+            for (j = 0; j < 250; j++) {
+                if (redisGetReply(context, (void**)&reply) == 0) {
+                    switch(reply->type) {
+                        case 6:
+                            printf("%s\n", reply->str);
+                            break;
+                        case 4:
+                            misses++;
+                            break;
+                        default:
+                            hits++;
+                            break;
+                    }
+                }
+            }
+
+            if (context->err) {
+                fprintf(stderr,"I/O error during LRU test\n");
+                exit(1);
+            }
+        }
+
+        printf(
+            "%lld Gets/sec | Hits: %lld (%.2f%%) | Misses: %lld (%.2f%%)\n",
+            hits+misses,
+            hits, (double)hits/(hits+misses)*100,
+            misses, (double)misses/(hits+misses)*100);
+    }
+    exit(0);
+}
+# 2756 "src/redis-cli.c"
+unsigned long compute_something_fast(void) {
+    unsigned char s[256], i, j, t;
+    int count = 1000, k;
+    unsigned long output = 0;
+
+    for (k = 0; k < 256; k++) s[k] = k;
+
+    i = 0;
+    j = 0;
+    while(count--) {
+        i++;
+        j = j + s[i];
+        t = s[i];
+        s[i] = s[j];
+        s[j] = t;
+        output += s[(s[i]+s[j])&255];
+    }
+    return output;
+}
+
+static void intrinsicLatencyModeStop(int s) {
+    ((void) s);
+    force_cancel_loop = 1;
+}
+
+static void intrinsicLatencyMode(void) {
+    long long test_end, run_time, max_latency = 0, runs = 0;
+
+    run_time = config.intrinsic_latency_duration*1000000;
+    test_end = ustime() + run_time;
+    signal(SIGINT, intrinsicLatencyModeStop);
+
+    while(1) {
+        long long start, end, latency;
+
+        start = ustime();
+        compute_something_fast();
+        end = ustime();
+        latency = end-start;
+        runs++;
+        if (latency <= 0) continue;
+
+
+        if (latency > max_latency) {
+            max_latency = latency;
+            printf("Max latency so far: %lld microseconds.\n", max_latency);
+        }
+
+        double avg_us = (double)run_time/runs;
+        double avg_ns = avg_us * 1e3;
+        if (force_cancel_loop || end > test_end) {
+            printf("\n%lld total runs "
+                "(avg latency: "
+                "%.4f microseconds / %.2f nanoseconds per run).\n",
+                runs, avg_us, avg_ns);
+            printf("Worst run took %.0fx longer than the average latency.\n",
+                max_latency / avg_us);
+            exit(0);
+        }
+    }
+}
+
+
+
+
+
+int main(int argc, char **argv) {
+    int firstarg;
+
+    config.hostip = sdsnew("127.0.0.1");
+    config.hostport = 6379;
+    config.hostsocket = 0;
+    config.repeat = 1;
+    config.interval = 0;
+    config.dbnum = 0;
+    config.interactive = 0;
+    config.shutdown = 0;
+    config.monitor_mode = 0;
+    config.pubsub_mode = 0;
+    config.latency_mode = 0;
+    config.latency_dist_mode = 0;
+    config.latency_history = 0;
+    config.lru_test_mode = 0;
+    config.lru_test_sample_size = 0;
+    config.cluster_mode = 0;
+    config.slave_mode = 0;
+    config.getrdb_mode = 0;
+    config.stat_mode = 0;
+    config.scan_mode = 0;
+    config.intrinsic_latency_mode = 0;
+    config.pattern = 0;
+    config.rdb_filename = 0;
+    config.pipe_mode = 0;
+    config.pipe_timeout = 30;
+    config.bigkeys = 0;
+    config.hotkeys = 0;
+    config.stdinarg = 0;
+    config.auth = 0;
+    config.eval = 0;
+    config.eval_ldb = 0;
+    config.eval_ldb_end = 0;
+    config.eval_ldb_sync = 0;
+    config.enable_ldb_on_eval = 0;
+    config.last_cmd_type = -1;
+
+    pref.hints = 1;
+
+    spectrum_palette = spectrum_palette_color;
+    spectrum_palette_size = spectrum_palette_color_size;
+
+    if (!isatty(fileno(stdout)) && (getenv("FAKETTY") == 0))
+        config.output = 1;
+    else
+        config.output = 0;
+    config.mb_delim = sdsnew("\n");
+
+    firstarg = parseOptions(argc,argv);
+    argc -= firstarg;
+    argv += firstarg;
+
+
+    if (config.latency_mode) {
+        if (cliConnect(0) == -1) exit(1);
+        latencyMode();
+    }
+
+
+    if (config.latency_dist_mode) {
+        if (cliConnect(0) == -1) exit(1);
+        latencyDistMode();
+    }
+
+
+    if (config.slave_mode) {
+        if (cliConnect(0) == -1) exit(1);
+        slaveMode();
+    }
+
+
+    if (config.getrdb_mode) {
+        if (cliConnect(0) == -1) exit(1);
+        getRDB();
+    }
+
+
+    if (config.pipe_mode) {
+        if (cliConnect(0) == -1) exit(1);
+        pipeMode();
+    }
+
+
+    if (config.bigkeys) {
+        if (cliConnect(0) == -1) exit(1);
+        findBigKeys();
+    }
+
+
+    if (config.hotkeys) {
+        if (cliConnect(0) == -1) exit(1);
+        findHotKeys();
+    }
+
+
+    if (config.stat_mode) {
+        if (cliConnect(0) == -1) exit(1);
+        if (config.interval == 0) config.interval = 1000000;
+        statMode();
+    }
+
+
+    if (config.scan_mode) {
+        if (cliConnect(0) == -1) exit(1);
+        scanMode();
+    }
+
+
+    if (config.lru_test_mode) {
+        if (cliConnect(0) == -1) exit(1);
+        LRUTestMode();
+    }
+
+
+    if (config.intrinsic_latency_mode) intrinsicLatencyMode();
+
+
+    if (argc == 0 && !config.eval) {
+
+        signal(SIGPIPE, SIG_IGN);
+
+
+
+        cliConnect(0);
+        repl();
+    }
+
+
+    if (cliConnect(0) != 0) exit(1);
+    if (config.eval) {
+        return evalMode(argc,argv);
+    } else {
+        return noninteractive(argc,convertToSds(argc,argv));
+    }
+}
diff --git a/utils/benchmark/inputs/sqlite-btree.c.ppout b/utils/benchmark/inputs/sqlite-btree.c.ppout
new file mode 100644
index 0000000..e73a0fa
--- /dev/null
+++ b/utils/benchmark/inputs/sqlite-btree.c.ppout
@@ -0,0 +1,11397 @@
+# 1 "src/btree.c"
+# 1 "<built-in>"
+# 1 "<command-line>"
+# 1 "src/btree.c"
+# 16 "src/btree.c"
+# 1 "src/btreeInt.h" 1
+# 216 "src/btreeInt.h"
+# 1 "src/sqliteInt.h" 1
+# 59 "src/sqliteInt.h"
+# 1 "src/msvc.h" 1
+# 60 "src/sqliteInt.h" 2
+
+
+
+
+# 1 "src/vxworks.h" 1
+# 65 "src/sqliteInt.h" 2
+# 167 "src/sqliteInt.h"
+# 1 "./sqlite3.h" 1
+# 35 "./sqlite3.h"
+# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/stdarg.h" 1
+# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/_fake_defines.h" 1
+# 2 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/stdarg.h" 2
+# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/_fake_typedefs.h" 1
+
+
+
+typedef int size_t;
+typedef int __builtin_va_list;
+typedef int __gnuc_va_list;
+typedef int va_list;
+typedef int __int8_t;
+typedef int __uint8_t;
+typedef int __int16_t;
+typedef int __uint16_t;
+typedef int __int_least16_t;
+typedef int __uint_least16_t;
+typedef int __int32_t;
+typedef int __uint32_t;
+typedef int __int64_t;
+typedef int __uint64_t;
+typedef int __int_least32_t;
+typedef int __uint_least32_t;
+typedef int __s8;
+typedef int __u8;
+typedef int __s16;
+typedef int __u16;
+typedef int __s32;
+typedef int __u32;
+typedef int __s64;
+typedef int __u64;
+typedef int _LOCK_T;
+typedef int _LOCK_RECURSIVE_T;
+typedef int _off_t;
+typedef int __dev_t;
+typedef int __uid_t;
+typedef int __gid_t;
+typedef int _off64_t;
+typedef int _fpos_t;
+typedef int _ssize_t;
+typedef int wint_t;
+typedef int _mbstate_t;
+typedef int _flock_t;
+typedef int _iconv_t;
+typedef int __ULong;
+typedef int __FILE;
+typedef int ptrdiff_t;
+typedef int wchar_t;
+typedef int __off_t;
+typedef int __pid_t;
+typedef int __loff_t;
+typedef int u_char;
+typedef int u_short;
+typedef int u_int;
+typedef int u_long;
+typedef int ushort;
+typedef int uint;
+typedef int clock_t;
+typedef int time_t;
+typedef int daddr_t;
+typedef int caddr_t;
+typedef int ino_t;
+typedef int off_t;
+typedef int dev_t;
+typedef int uid_t;
+typedef int gid_t;
+typedef int pid_t;
+typedef int key_t;
+typedef int ssize_t;
+typedef int mode_t;
+typedef int nlink_t;
+typedef int fd_mask;
+typedef int _types_fd_set;
+typedef int clockid_t;
+typedef int timer_t;
+typedef int useconds_t;
+typedef int suseconds_t;
+typedef int FILE;
+typedef int fpos_t;
+typedef int cookie_read_function_t;
+typedef int cookie_write_function_t;
+typedef int cookie_seek_function_t;
+typedef int cookie_close_function_t;
+typedef int cookie_io_functions_t;
+typedef int div_t;
+typedef int ldiv_t;
+typedef int lldiv_t;
+typedef int sigset_t;
+typedef int __sigset_t;
+typedef int _sig_func_ptr;
+typedef int sig_atomic_t;
+typedef int __tzrule_type;
+typedef int __tzinfo_type;
+typedef int mbstate_t;
+typedef int sem_t;
+typedef int pthread_t;
+typedef int pthread_attr_t;
+typedef int pthread_mutex_t;
+typedef int pthread_mutexattr_t;
+typedef int pthread_cond_t;
+typedef int pthread_condattr_t;
+typedef int pthread_key_t;
+typedef int pthread_once_t;
+typedef int pthread_rwlock_t;
+typedef int pthread_rwlockattr_t;
+typedef int pthread_spinlock_t;
+typedef int pthread_barrier_t;
+typedef int pthread_barrierattr_t;
+typedef int jmp_buf;
+typedef int rlim_t;
+typedef int sa_family_t;
+typedef int sigjmp_buf;
+typedef int stack_t;
+typedef int siginfo_t;
+typedef int z_stream;
+
+
+typedef int int8_t;
+typedef int uint8_t;
+typedef int int16_t;
+typedef int uint16_t;
+typedef int int32_t;
+typedef int uint32_t;
+typedef int int64_t;
+typedef int uint64_t;
+
+
+typedef int int_least8_t;
+typedef int uint_least8_t;
+typedef int int_least16_t;
+typedef int uint_least16_t;
+typedef int int_least32_t;
+typedef int uint_least32_t;
+typedef int int_least64_t;
+typedef int uint_least64_t;
+
+
+typedef int int_fast8_t;
+typedef int uint_fast8_t;
+typedef int int_fast16_t;
+typedef int uint_fast16_t;
+typedef int int_fast32_t;
+typedef int uint_fast32_t;
+typedef int int_fast64_t;
+typedef int uint_fast64_t;
+
+
+typedef int intptr_t;
+typedef int uintptr_t;
+
+
+typedef int intmax_t;
+typedef int uintmax_t;
+
+
+typedef _Bool bool;
+
+
+typedef void* MirEGLNativeWindowType;
+typedef void* MirEGLNativeDisplayType;
+typedef struct MirConnection MirConnection;
+typedef struct MirSurface MirSurface;
+typedef struct MirSurfaceSpec MirSurfaceSpec;
+typedef struct MirScreencast MirScreencast;
+typedef struct MirPromptSession MirPromptSession;
+typedef struct MirBufferStream MirBufferStream;
+typedef struct MirPersistentId MirPersistentId;
+typedef struct MirBlob MirBlob;
+typedef struct MirDisplayConfig MirDisplayConfig;
+
+
+typedef struct xcb_connection_t xcb_connection_t;
+typedef uint32_t xcb_window_t;
+typedef uint32_t xcb_visualid_t;
+# 2 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/stdarg.h" 2
+# 36 "./sqlite3.h" 2
+# 162 "./sqlite3.h"
+ extern const char sqlite3_version[];
+ const char *sqlite3_libversion(void);
+ const char *sqlite3_sourceid(void);
+ int sqlite3_libversion_number(void);
+# 190 "./sqlite3.h"
+ int sqlite3_compileoption_used(const char *zOptName);
+ const char *sqlite3_compileoption_get(int N);
+# 233 "./sqlite3.h"
+ int sqlite3_threadsafe(void);
+# 249 "./sqlite3.h"
+typedef struct sqlite3 sqlite3;
+# 278 "./sqlite3.h"
+  typedef long long int sqlite_int64;
+  typedef unsigned long long int sqlite_uint64;
+
+typedef sqlite_int64 sqlite3_int64;
+typedef sqlite_uint64 sqlite3_uint64;
+# 334 "./sqlite3.h"
+ int sqlite3_close(sqlite3*);
+ int sqlite3_close_v2(sqlite3*);
+
+
+
+
+
+
+typedef int (*sqlite3_callback)(void*,int,char**, char**);
+# 406 "./sqlite3.h"
+ int sqlite3_exec(
+  sqlite3*,
+  const char *sql,
+  int (*callback)(void*,int,char**,char**),
+  void *,
+  char **errmsg
+);
+# 677 "./sqlite3.h"
+typedef struct sqlite3_file sqlite3_file;
+struct sqlite3_file {
+  const struct sqlite3_io_methods *pMethods;
+};
+# 776 "./sqlite3.h"
+typedef struct sqlite3_io_methods sqlite3_io_methods;
+struct sqlite3_io_methods {
+  int iVersion;
+  int (*xClose)(sqlite3_file*);
+  int (*xRead)(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
+  int (*xWrite)(sqlite3_file*, const void*, int iAmt, sqlite3_int64 iOfst);
+  int (*xTruncate)(sqlite3_file*, sqlite3_int64 size);
+  int (*xSync)(sqlite3_file*, int flags);
+  int (*xFileSize)(sqlite3_file*, sqlite3_int64 *pSize);
+  int (*xLock)(sqlite3_file*, int);
+  int (*xUnlock)(sqlite3_file*, int);
+  int (*xCheckReservedLock)(sqlite3_file*, int *pResOut);
+  int (*xFileControl)(sqlite3_file*, int op, void *pArg);
+  int (*xSectorSize)(sqlite3_file*);
+  int (*xDeviceCharacteristics)(sqlite3_file*);
+
+  int (*xShmMap)(sqlite3_file*, int iPg, int pgsz, int, void volatile**);
+  int (*xShmLock)(sqlite3_file*, int offset, int n, int flags);
+  void (*xShmBarrier)(sqlite3_file*);
+  int (*xShmUnmap)(sqlite3_file*, int deleteFlag);
+
+  int (*xFetch)(sqlite3_file*, sqlite3_int64 iOfst, int iAmt, void **pp);
+  int (*xUnfetch)(sqlite3_file*, sqlite3_int64 iOfst, void *p);
+
+
+};
+# 1164 "./sqlite3.h"
+typedef struct sqlite3_mutex sqlite3_mutex;
+# 1174 "./sqlite3.h"
+typedef struct sqlite3_api_routines sqlite3_api_routines;
+# 1345 "./sqlite3.h"
+typedef struct sqlite3_vfs sqlite3_vfs;
+typedef void (*sqlite3_syscall_ptr)(void);
+struct sqlite3_vfs {
+  int iVersion;
+  int szOsFile;
+  int mxPathname;
+  sqlite3_vfs *pNext;
+  const char *zName;
+  void *pAppData;
+  int (*xOpen)(sqlite3_vfs*, const char *zName, sqlite3_file*,
+               int flags, int *pOutFlags);
+  int (*xDelete)(sqlite3_vfs*, const char *zName, int syncDir);
+  int (*xAccess)(sqlite3_vfs*, const char *zName, int flags, int *pResOut);
+  int (*xFullPathname)(sqlite3_vfs*, const char *zName, int nOut, char *zOut);
+  void *(*xDlOpen)(sqlite3_vfs*, const char *zFilename);
+  void (*xDlError)(sqlite3_vfs*, int nByte, char *zErrMsg);
+  void (*(*xDlSym)(sqlite3_vfs*,void*, const char *zSymbol))(void);
+  void (*xDlClose)(sqlite3_vfs*, void*);
+  int (*xRandomness)(sqlite3_vfs*, int nByte, char *zOut);
+  int (*xSleep)(sqlite3_vfs*, int microseconds);
+  int (*xCurrentTime)(sqlite3_vfs*, double*);
+  int (*xGetLastError)(sqlite3_vfs*, int, char *);
+
+
+
+
+  int (*xCurrentTimeInt64)(sqlite3_vfs*, sqlite3_int64*);
+
+
+
+
+  int (*xSetSystemCall)(sqlite3_vfs*, const char *zName, sqlite3_syscall_ptr);
+  sqlite3_syscall_ptr (*xGetSystemCall)(sqlite3_vfs*, const char *zName);
+  const char *(*xNextSystemCall)(sqlite3_vfs*, const char *zName);
+
+
+
+
+
+};
+# 1523 "./sqlite3.h"
+ int sqlite3_initialize(void);
+ int sqlite3_shutdown(void);
+ int sqlite3_os_init(void);
+ int sqlite3_os_end(void);
+# 1559 "./sqlite3.h"
+ int sqlite3_config(int, ...);
+# 1578 "./sqlite3.h"
+ int sqlite3_db_config(sqlite3*, int op, ...);
+# 1643 "./sqlite3.h"
+typedef struct sqlite3_mem_methods sqlite3_mem_methods;
+struct sqlite3_mem_methods {
+  void *(*xMalloc)(int);
+  void (*xFree)(void*);
+  void *(*xRealloc)(void*,int);
+  int (*xSize)(void*);
+  int (*xRoundup)(int);
+  int (*xInit)(void*);
+  void (*xShutdown)(void*);
+  void *pAppData;
+};
+# 2278 "./sqlite3.h"
+ int sqlite3_extended_result_codes(sqlite3*, int onoff);
+# 2340 "./sqlite3.h"
+ sqlite3_int64 sqlite3_last_insert_rowid(sqlite3*);
+# 2350 "./sqlite3.h"
+ void sqlite3_set_last_insert_rowid(sqlite3*,sqlite3_int64);
+# 2408 "./sqlite3.h"
+ int sqlite3_changes(sqlite3*);
+# 2445 "./sqlite3.h"
+ int sqlite3_total_changes(sqlite3*);
+# 2482 "./sqlite3.h"
+ void sqlite3_interrupt(sqlite3*);
+# 2517 "./sqlite3.h"
+ int sqlite3_complete(const char *sql);
+ int sqlite3_complete16(const void *sql);
+# 2579 "./sqlite3.h"
+ int sqlite3_busy_handler(sqlite3*,int(*)(void*,int),void*);
+# 2602 "./sqlite3.h"
+ int sqlite3_busy_timeout(sqlite3*, int ms);
+# 2677 "./sqlite3.h"
+ int sqlite3_get_table(
+  sqlite3 *db,
+  const char *zSql,
+  char ***pazResult,
+  int *pnRow,
+  int *pnColumn,
+  char **pzErrmsg
+);
+ void sqlite3_free_table(char **result);
+# 2727 "./sqlite3.h"
+ char *sqlite3_mprintf(const char*,...);
+ char *sqlite3_vmprintf(const char*, va_list);
+ char *sqlite3_snprintf(int,char*,const char*, ...);
+ char *sqlite3_vsnprintf(int,char*,const char*, va_list);
+# 2820 "./sqlite3.h"
+ void *sqlite3_malloc(int);
+ void *sqlite3_malloc64(sqlite3_uint64);
+ void *sqlite3_realloc(void*, int);
+ void *sqlite3_realloc64(void*, sqlite3_uint64);
+ void sqlite3_free(void*);
+ sqlite3_uint64 sqlite3_msize(void*);
+# 2850 "./sqlite3.h"
+ sqlite3_int64 sqlite3_memory_used(void);
+ sqlite3_int64 sqlite3_memory_highwater(int resetFlag);
+# 2874 "./sqlite3.h"
+ void sqlite3_randomness(int N, void *P);
+# 2965 "./sqlite3.h"
+ int sqlite3_set_authorizer(
+  sqlite3*,
+  int (*xAuth)(void*,int,const char*,const char*,const char*,const char*),
+  void *pUserData
+);
+# 3073 "./sqlite3.h"
+ void *sqlite3_trace(sqlite3*,
+   void(*xTrace)(void*,const char*), void*);
+ void *sqlite3_profile(sqlite3*,
+   void(*xProfile)(void*,const char*,sqlite3_uint64), void*);
+# 3164 "./sqlite3.h"
+ int sqlite3_trace_v2(
+  sqlite3*,
+  unsigned uMask,
+  int(*xCallback)(unsigned,void*,void*,void*),
+  void *pCtx
+);
+# 3203 "./sqlite3.h"
+ void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
+# 3432 "./sqlite3.h"
+ int sqlite3_open(
+  const char *filename,
+  sqlite3 **ppDb
+);
+ int sqlite3_open16(
+  const void *filename,
+  sqlite3 **ppDb
+);
+ int sqlite3_open_v2(
+  const char *filename,
+  sqlite3 **ppDb,
+  int flags,
+  const char *zVfs
+);
+# 3488 "./sqlite3.h"
+ const char *sqlite3_uri_parameter(const char *zFilename, const char *zParam);
+ int sqlite3_uri_boolean(const char *zFile, const char *zParam, int bDefault);
+ sqlite3_int64 sqlite3_uri_int64(const char*, const char*, sqlite3_int64);
+# 3545 "./sqlite3.h"
+ int sqlite3_errcode(sqlite3 *db);
+ int sqlite3_extended_errcode(sqlite3 *db);
+ const char *sqlite3_errmsg(sqlite3*);
+ const void *sqlite3_errmsg16(sqlite3*);
+ const char *sqlite3_errstr(int);
+# 3575 "./sqlite3.h"
+typedef struct sqlite3_stmt sqlite3_stmt;
+# 3617 "./sqlite3.h"
+ int sqlite3_limit(sqlite3*, int id, int newVal);
+# 3827 "./sqlite3.h"
+ int sqlite3_prepare(
+  sqlite3 *db,
+  const char *zSql,
+  int nByte,
+  sqlite3_stmt **ppStmt,
+  const char **pzTail
+);
+ int sqlite3_prepare_v2(
+  sqlite3 *db,
+  const char *zSql,
+  int nByte,
+  sqlite3_stmt **ppStmt,
+  const char **pzTail
+);
+ int sqlite3_prepare_v3(
+  sqlite3 *db,
+  const char *zSql,
+  int nByte,
+  unsigned int prepFlags,
+  sqlite3_stmt **ppStmt,
+  const char **pzTail
+);
+ int sqlite3_prepare16(
+  sqlite3 *db,
+  const void *zSql,
+  int nByte,
+  sqlite3_stmt **ppStmt,
+  const void **pzTail
+);
+ int sqlite3_prepare16_v2(
+  sqlite3 *db,
+  const void *zSql,
+  int nByte,
+  sqlite3_stmt **ppStmt,
+  const void **pzTail
+);
+ int sqlite3_prepare16_v3(
+  sqlite3 *db,
+  const void *zSql,
+  int nByte,
+  unsigned int prepFlags,
+  sqlite3_stmt **ppStmt,
+  const void **pzTail
+);
+# 3910 "./sqlite3.h"
+ const char *sqlite3_sql(sqlite3_stmt *pStmt);
+ char *sqlite3_expanded_sql(sqlite3_stmt *pStmt);
+ const char *sqlite3_normalized_sql(sqlite3_stmt *pStmt);
+# 3948 "./sqlite3.h"
+ int sqlite3_stmt_readonly(sqlite3_stmt *pStmt);
+# 3960 "./sqlite3.h"
+ int sqlite3_stmt_isexplain(sqlite3_stmt *pStmt);
+# 3981 "./sqlite3.h"
+ int sqlite3_stmt_busy(sqlite3_stmt*);
+# 4023 "./sqlite3.h"
+typedef struct sqlite3_value sqlite3_value;
+# 4037 "./sqlite3.h"
+typedef struct sqlite3_context sqlite3_context;
+# 4157 "./sqlite3.h"
+ int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*));
+ int sqlite3_bind_blob64(sqlite3_stmt*, int, const void*, sqlite3_uint64,
+                        void(*)(void*));
+ int sqlite3_bind_double(sqlite3_stmt*, int, double);
+ int sqlite3_bind_int(sqlite3_stmt*, int, int);
+ int sqlite3_bind_int64(sqlite3_stmt*, int, sqlite3_int64);
+ int sqlite3_bind_null(sqlite3_stmt*, int);
+ int sqlite3_bind_text(sqlite3_stmt*,int,const char*,int,void(*)(void*));
+ int sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)(void*));
+ int sqlite3_bind_text64(sqlite3_stmt*, int, const char*, sqlite3_uint64,
+                         void(*)(void*), unsigned char encoding);
+ int sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*);
+ int sqlite3_bind_pointer(sqlite3_stmt*, int, void*, const char*,void(*)(void*));
+ int sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n);
+ int sqlite3_bind_zeroblob64(sqlite3_stmt*, int, sqlite3_uint64);
+# 4192 "./sqlite3.h"
+ int sqlite3_bind_parameter_count(sqlite3_stmt*);
+# 4220 "./sqlite3.h"
+ const char *sqlite3_bind_parameter_name(sqlite3_stmt*, int);
+# 4238 "./sqlite3.h"
+ int sqlite3_bind_parameter_index(sqlite3_stmt*, const char *zName);
+# 4248 "./sqlite3.h"
+ int sqlite3_clear_bindings(sqlite3_stmt*);
+# 4264 "./sqlite3.h"
+ int sqlite3_column_count(sqlite3_stmt *pStmt);
+# 4293 "./sqlite3.h"
+ const char *sqlite3_column_name(sqlite3_stmt*, int N);
+ const void *sqlite3_column_name16(sqlite3_stmt*, int N);
+# 4342 "./sqlite3.h"
+ const char *sqlite3_column_database_name(sqlite3_stmt*,int);
+ const void *sqlite3_column_database_name16(sqlite3_stmt*,int);
+ const char *sqlite3_column_table_name(sqlite3_stmt*,int);
+ const void *sqlite3_column_table_name16(sqlite3_stmt*,int);
+ const char *sqlite3_column_origin_name(sqlite3_stmt*,int);
+ const void *sqlite3_column_origin_name16(sqlite3_stmt*,int);
+# 4379 "./sqlite3.h"
+ const char *sqlite3_column_decltype(sqlite3_stmt*,int);
+ const void *sqlite3_column_decltype16(sqlite3_stmt*,int);
+# 4464 "./sqlite3.h"
+ int sqlite3_step(sqlite3_stmt*);
+# 4485 "./sqlite3.h"
+ int sqlite3_data_count(sqlite3_stmt *pStmt);
+# 4728 "./sqlite3.h"
+ const void *sqlite3_column_blob(sqlite3_stmt*, int iCol);
+ double sqlite3_column_double(sqlite3_stmt*, int iCol);
+ int sqlite3_column_int(sqlite3_stmt*, int iCol);
+ sqlite3_int64 sqlite3_column_int64(sqlite3_stmt*, int iCol);
+ const unsigned char *sqlite3_column_text(sqlite3_stmt*, int iCol);
+ const void *sqlite3_column_text16(sqlite3_stmt*, int iCol);
+ sqlite3_value *sqlite3_column_value(sqlite3_stmt*, int iCol);
+ int sqlite3_column_bytes(sqlite3_stmt*, int iCol);
+ int sqlite3_column_bytes16(sqlite3_stmt*, int iCol);
+ int sqlite3_column_type(sqlite3_stmt*, int iCol);
+# 4765 "./sqlite3.h"
+ int sqlite3_finalize(sqlite3_stmt *pStmt);
+# 4792 "./sqlite3.h"
+ int sqlite3_reset(sqlite3_stmt *pStmt);
+# 4904 "./sqlite3.h"
+ int sqlite3_create_function(
+  sqlite3 *db,
+  const char *zFunctionName,
+  int nArg,
+  int eTextRep,
+  void *pApp,
+  void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
+  void (*xStep)(sqlite3_context*,int,sqlite3_value**),
+  void (*xFinal)(sqlite3_context*)
+);
+ int sqlite3_create_function16(
+  sqlite3 *db,
+  const void *zFunctionName,
+  int nArg,
+  int eTextRep,
+  void *pApp,
+  void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
+  void (*xStep)(sqlite3_context*,int,sqlite3_value**),
+  void (*xFinal)(sqlite3_context*)
+);
+ int sqlite3_create_function_v2(
+  sqlite3 *db,
+  const char *zFunctionName,
+  int nArg,
+  int eTextRep,
+  void *pApp,
+  void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
+  void (*xStep)(sqlite3_context*,int,sqlite3_value**),
+  void (*xFinal)(sqlite3_context*),
+  void(*xDestroy)(void*)
+);
+ int sqlite3_create_window_function(
+  sqlite3 *db,
+  const char *zFunctionName,
+  int nArg,
+  int eTextRep,
+  void *pApp,
+  void (*xStep)(sqlite3_context*,int,sqlite3_value**),
+  void (*xFinal)(sqlite3_context*),
+  void (*xValue)(sqlite3_context*),
+  void (*xInverse)(sqlite3_context*,int,sqlite3_value**),
+  void(*xDestroy)(void*)
+);
+# 4982 "./sqlite3.h"
+ int sqlite3_aggregate_count(sqlite3_context*);
+ int sqlite3_expired(sqlite3_stmt*);
+ int sqlite3_transfer_bindings(sqlite3_stmt*, sqlite3_stmt*);
+ int sqlite3_global_recover(void);
+ void sqlite3_thread_cleanup(void);
+ int sqlite3_memory_alarm(void(*)(void*,sqlite3_int64,int),
+                      void*,sqlite3_int64);
+# 5119 "./sqlite3.h"
+ const void *sqlite3_value_blob(sqlite3_value*);
+ double sqlite3_value_double(sqlite3_value*);
+ int sqlite3_value_int(sqlite3_value*);
+ sqlite3_int64 sqlite3_value_int64(sqlite3_value*);
+ void *sqlite3_value_pointer(sqlite3_value*, const char*);
+ const unsigned char *sqlite3_value_text(sqlite3_value*);
+ const void *sqlite3_value_text16(sqlite3_value*);
+ const void *sqlite3_value_text16le(sqlite3_value*);
+ const void *sqlite3_value_text16be(sqlite3_value*);
+ int sqlite3_value_bytes(sqlite3_value*);
+ int sqlite3_value_bytes16(sqlite3_value*);
+ int sqlite3_value_type(sqlite3_value*);
+ int sqlite3_value_numeric_type(sqlite3_value*);
+ int sqlite3_value_nochange(sqlite3_value*);
+ int sqlite3_value_frombind(sqlite3_value*);
+# 5145 "./sqlite3.h"
+ unsigned int sqlite3_value_subtype(sqlite3_value*);
+# 5161 "./sqlite3.h"
+ sqlite3_value *sqlite3_value_dup(const sqlite3_value*);
+ void sqlite3_value_free(sqlite3_value*);
+# 5207 "./sqlite3.h"
+ void *sqlite3_aggregate_context(sqlite3_context*, int nBytes);
+# 5222 "./sqlite3.h"
+ void *sqlite3_user_data(sqlite3_context*);
+# 5234 "./sqlite3.h"
+ sqlite3 *sqlite3_context_db_handle(sqlite3_context*);
+# 5293 "./sqlite3.h"
+ void *sqlite3_get_auxdata(sqlite3_context*, int N);
+ void sqlite3_set_auxdata(sqlite3_context*, int N, void*, void (*)(void*));
+# 5311 "./sqlite3.h"
+typedef void (*sqlite3_destructor_type)(void*);
+# 5441 "./sqlite3.h"
+ void sqlite3_result_blob(sqlite3_context*, const void*, int, void(*)(void*));
+ void sqlite3_result_blob64(sqlite3_context*,const void*,
+                           sqlite3_uint64,void(*)(void*));
+ void sqlite3_result_double(sqlite3_context*, double);
+ void sqlite3_result_error(sqlite3_context*, const char*, int);
+ void sqlite3_result_error16(sqlite3_context*, const void*, int);
+ void sqlite3_result_error_toobig(sqlite3_context*);
+ void sqlite3_result_error_nomem(sqlite3_context*);
+ void sqlite3_result_error_code(sqlite3_context*, int);
+ void sqlite3_result_int(sqlite3_context*, int);
+ void sqlite3_result_int64(sqlite3_context*, sqlite3_int64);
+ void sqlite3_result_null(sqlite3_context*);
+ void sqlite3_result_text(sqlite3_context*, const char*, int, void(*)(void*));
+ void sqlite3_result_text64(sqlite3_context*, const char*,sqlite3_uint64,
+                           void(*)(void*), unsigned char encoding);
+ void sqlite3_result_text16(sqlite3_context*, const void*, int, void(*)(void*));
+ void sqlite3_result_text16le(sqlite3_context*, const void*, int,void(*)(void*));
+ void sqlite3_result_text16be(sqlite3_context*, const void*, int,void(*)(void*));
+ void sqlite3_result_value(sqlite3_context*, sqlite3_value*);
+ void sqlite3_result_pointer(sqlite3_context*, void*,const char*,void(*)(void*));
+ void sqlite3_result_zeroblob(sqlite3_context*, int n);
+ int sqlite3_result_zeroblob64(sqlite3_context*, sqlite3_uint64 n);
+# 5477 "./sqlite3.h"
+ void sqlite3_result_subtype(sqlite3_context*,unsigned int);
+# 5559 "./sqlite3.h"
+ int sqlite3_create_collation(
+  sqlite3*,
+  const char *zName,
+  int eTextRep,
+  void *pArg,
+  int(*xCompare)(void*,int,const void*,int,const void*)
+);
+ int sqlite3_create_collation_v2(
+  sqlite3*,
+  const char *zName,
+  int eTextRep,
+  void *pArg,
+  int(*xCompare)(void*,int,const void*,int,const void*),
+  void(*xDestroy)(void*)
+);
+ int sqlite3_create_collation16(
+  sqlite3*,
+  const void *zName,
+  int eTextRep,
+  void *pArg,
+  int(*xCompare)(void*,int,const void*,int,const void*)
+);
+# 5609 "./sqlite3.h"
+ int sqlite3_collation_needed(
+  sqlite3*,
+  void*,
+  void(*)(void*,sqlite3*,int eTextRep,const char*)
+);
+ int sqlite3_collation_needed16(
+  sqlite3*,
+  void*,
+  void(*)(void*,sqlite3*,int eTextRep,const void*)
+);
+# 5692 "./sqlite3.h"
+ int sqlite3_sleep(int);
+# 5750 "./sqlite3.h"
+ extern char *sqlite3_temp_directory;
+# 5787 "./sqlite3.h"
+ extern char *sqlite3_data_directory;
+# 5808 "./sqlite3.h"
+ int sqlite3_win32_set_directory(
+  unsigned long type,
+  void *zValue
+);
+ int sqlite3_win32_set_directory8(unsigned long type, const char *zValue);
+ int sqlite3_win32_set_directory16(unsigned long type, const void *zValue);
+# 5846 "./sqlite3.h"
+ int sqlite3_get_autocommit(sqlite3*);
+# 5859 "./sqlite3.h"
+ sqlite3 *sqlite3_db_handle(sqlite3_stmt*);
+# 5876 "./sqlite3.h"
+ const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName);
+# 5886 "./sqlite3.h"
+ int sqlite3_db_readonly(sqlite3 *db, const char *zDbName);
+# 5902 "./sqlite3.h"
+ sqlite3_stmt *sqlite3_next_stmt(sqlite3 *pDb, sqlite3_stmt *pStmt);
+# 5951 "./sqlite3.h"
+ void *sqlite3_commit_hook(sqlite3*, int(*)(void*), void*);
+ void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*);
+# 6003 "./sqlite3.h"
+ void *sqlite3_update_hook(
+  sqlite3*,
+  void(*)(void *,int ,char const *,char const *,sqlite3_int64),
+  void*
+);
+# 6044 "./sqlite3.h"
+ int sqlite3_enable_shared_cache(int);
+# 6060 "./sqlite3.h"
+ int sqlite3_release_memory(int);
+# 6074 "./sqlite3.h"
+ int sqlite3_db_release_memory(sqlite3*);
+# 6127 "./sqlite3.h"
+ sqlite3_int64 sqlite3_soft_heap_limit64(sqlite3_int64 N);
+# 6138 "./sqlite3.h"
+ void sqlite3_soft_heap_limit(int N);
+# 6210 "./sqlite3.h"
+ int sqlite3_table_column_metadata(
+  sqlite3 *db,
+  const char *zDbName,
+  const char *zTableName,
+  const char *zColumnName,
+  char const **pzDataType,
+  char const **pzCollSeq,
+  int *pNotNull,
+  int *pPrimaryKey,
+  int *pAutoinc
+);
+# 6266 "./sqlite3.h"
+ int sqlite3_load_extension(
+  sqlite3 *db,
+  const char *zFile,
+  const char *zProc,
+  char **pzErrMsg
+);
+# 6298 "./sqlite3.h"
+ int sqlite3_enable_load_extension(sqlite3 *db, int onoff);
+# 6336 "./sqlite3.h"
+ int sqlite3_auto_extension(void(*xEntryPoint)(void));
+# 6348 "./sqlite3.h"
+ int sqlite3_cancel_auto_extension(void(*xEntryPoint)(void));
+
+
+
+
+
+
+
+ void sqlite3_reset_auto_extension(void);
+# 6370 "./sqlite3.h"
+typedef struct sqlite3_vtab sqlite3_vtab;
+typedef struct sqlite3_index_info sqlite3_index_info;
+typedef struct sqlite3_vtab_cursor sqlite3_vtab_cursor;
+typedef struct sqlite3_module sqlite3_module;
+# 6391 "./sqlite3.h"
+struct sqlite3_module {
+  int iVersion;
+  int (*xCreate)(sqlite3*, void *pAux,
+               int argc, const char *const*argv,
+               sqlite3_vtab **ppVTab, char**);
+  int (*xConnect)(sqlite3*, void *pAux,
+               int argc, const char *const*argv,
+               sqlite3_vtab **ppVTab, char**);
+  int (*xBestIndex)(sqlite3_vtab *pVTab, sqlite3_index_info*);
+  int (*xDisconnect)(sqlite3_vtab *pVTab);
+  int (*xDestroy)(sqlite3_vtab *pVTab);
+  int (*xOpen)(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor);
+  int (*xClose)(sqlite3_vtab_cursor*);
+  int (*xFilter)(sqlite3_vtab_cursor*, int idxNum, const char *idxStr,
+                int argc, sqlite3_value **argv);
+  int (*xNext)(sqlite3_vtab_cursor*);
+  int (*xEof)(sqlite3_vtab_cursor*);
+  int (*xColumn)(sqlite3_vtab_cursor*, sqlite3_context*, int);
+  int (*xRowid)(sqlite3_vtab_cursor*, sqlite3_int64 *pRowid);
+  int (*xUpdate)(sqlite3_vtab *, int, sqlite3_value **, sqlite3_int64 *);
+  int (*xBegin)(sqlite3_vtab *pVTab);
+  int (*xSync)(sqlite3_vtab *pVTab);
+  int (*xCommit)(sqlite3_vtab *pVTab);
+  int (*xRollback)(sqlite3_vtab *pVTab);
+  int (*xFindFunction)(sqlite3_vtab *pVtab, int nArg, const char *zName,
+                       void (**pxFunc)(sqlite3_context*,int,sqlite3_value**),
+                       void **ppArg);
+  int (*xRename)(sqlite3_vtab *pVtab, const char *zNew);
+
+
+  int (*xSavepoint)(sqlite3_vtab *pVTab, int);
+  int (*xRelease)(sqlite3_vtab *pVTab, int);
+  int (*xRollbackTo)(sqlite3_vtab *pVTab, int);
+
+
+  int (*xShadowName)(const char*);
+};
+# 6525 "./sqlite3.h"
+struct sqlite3_index_info {
+
+  int nConstraint;
+  struct sqlite3_index_constraint {
+     int iColumn;
+     unsigned char op;
+     unsigned char usable;
+     int iTermOffset;
+  } *aConstraint;
+  int nOrderBy;
+  struct sqlite3_index_orderby {
+     int iColumn;
+     unsigned char desc;
+  } *aOrderBy;
+
+  struct sqlite3_index_constraint_usage {
+    int argvIndex;
+    unsigned char omit;
+  } *aConstraintUsage;
+  int idxNum;
+  char *idxStr;
+  int needToFreeIdxStr;
+  int orderByConsumed;
+  double estimatedCost;
+
+  sqlite3_int64 estimatedRows;
+
+  int idxFlags;
+
+  sqlite3_uint64 colUsed;
+};
+# 6616 "./sqlite3.h"
+ int sqlite3_create_module(
+  sqlite3 *db,
+  const char *zName,
+  const sqlite3_module *p,
+  void *pClientData
+);
+ int sqlite3_create_module_v2(
+  sqlite3 *db,
+  const char *zName,
+  const sqlite3_module *p,
+  void *pClientData,
+  void(*xDestroy)(void*)
+);
+# 6648 "./sqlite3.h"
+struct sqlite3_vtab {
+  const sqlite3_module *pModule;
+  int nRef;
+  char *zErrMsg;
+
+};
+# 6672 "./sqlite3.h"
+struct sqlite3_vtab_cursor {
+  sqlite3_vtab *pVtab;
+
+};
+# 6685 "./sqlite3.h"
+ int sqlite3_declare_vtab(sqlite3*, const char *zSQL);
+# 6704 "./sqlite3.h"
+ int sqlite3_overload_function(sqlite3*, const char *zFuncName, int nArg);
+# 6728 "./sqlite3.h"
+typedef struct sqlite3_blob sqlite3_blob;
+# 6813 "./sqlite3.h"
+ int sqlite3_blob_open(
+  sqlite3*,
+  const char *zDb,
+  const char *zTable,
+  const char *zColumn,
+  sqlite3_int64 iRow,
+  int flags,
+  sqlite3_blob **ppBlob
+);
+# 6846 "./sqlite3.h"
+ int sqlite3_blob_reopen(sqlite3_blob *, sqlite3_int64);
+# 6869 "./sqlite3.h"
+ int sqlite3_blob_close(sqlite3_blob *);
+# 6885 "./sqlite3.h"
+ int sqlite3_blob_bytes(sqlite3_blob *);
+# 6914 "./sqlite3.h"
+ int sqlite3_blob_read(sqlite3_blob *, void *Z, int N, int iOffset);
+# 6956 "./sqlite3.h"
+ int sqlite3_blob_write(sqlite3_blob *, const void *z, int n, int iOffset);
+# 6987 "./sqlite3.h"
+ sqlite3_vfs *sqlite3_vfs_find(const char *zVfsName);
+ int sqlite3_vfs_register(sqlite3_vfs*, int makeDflt);
+ int sqlite3_vfs_unregister(sqlite3_vfs*);
+# 7105 "./sqlite3.h"
+ sqlite3_mutex *sqlite3_mutex_alloc(int);
+ void sqlite3_mutex_free(sqlite3_mutex*);
+ void sqlite3_mutex_enter(sqlite3_mutex*);
+ int sqlite3_mutex_try(sqlite3_mutex*);
+ void sqlite3_mutex_leave(sqlite3_mutex*);
+# 7176 "./sqlite3.h"
+typedef struct sqlite3_mutex_methods sqlite3_mutex_methods;
+struct sqlite3_mutex_methods {
+  int (*xMutexInit)(void);
+  int (*xMutexEnd)(void);
+  sqlite3_mutex *(*xMutexAlloc)(int);
+  void (*xMutexFree)(sqlite3_mutex *);
+  void (*xMutexEnter)(sqlite3_mutex *);
+  int (*xMutexTry)(sqlite3_mutex *);
+  void (*xMutexLeave)(sqlite3_mutex *);
+  int (*xMutexHeld)(sqlite3_mutex *);
+  int (*xMutexNotheld)(sqlite3_mutex *);
+};
+# 7219 "./sqlite3.h"
+ int sqlite3_mutex_held(sqlite3_mutex*);
+ int sqlite3_mutex_notheld(sqlite3_mutex*);
+# 7260 "./sqlite3.h"
+ sqlite3_mutex *sqlite3_db_mutex(sqlite3*);
+# 7303 "./sqlite3.h"
+ int sqlite3_file_control(sqlite3*, const char *zDbName, int op, void*);
+# 7322 "./sqlite3.h"
+ int sqlite3_test_control(int op, ...);
+# 7410 "./sqlite3.h"
+ int sqlite3_keyword_count(void);
+ int sqlite3_keyword_name(int,const char**,int*);
+ int sqlite3_keyword_check(const char*,int);
+# 7430 "./sqlite3.h"
+typedef struct sqlite3_str sqlite3_str;
+# 7457 "./sqlite3.h"
+ sqlite3_str *sqlite3_str_new(sqlite3*);
+# 7472 "./sqlite3.h"
+ char *sqlite3_str_finish(sqlite3_str*);
+# 7506 "./sqlite3.h"
+ void sqlite3_str_appendf(sqlite3_str*, const char *zFormat, ...);
+ void sqlite3_str_vappendf(sqlite3_str*, const char *zFormat, va_list);
+ void sqlite3_str_append(sqlite3_str*, const char *zIn, int N);
+ void sqlite3_str_appendall(sqlite3_str*, const char *zIn);
+ void sqlite3_str_appendchar(sqlite3_str*, int N, char C);
+ void sqlite3_str_reset(sqlite3_str*);
+# 7542 "./sqlite3.h"
+ int sqlite3_str_errcode(sqlite3_str*);
+ int sqlite3_str_length(sqlite3_str*);
+ char *sqlite3_str_value(sqlite3_str*);
+# 7572 "./sqlite3.h"
+ int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag);
+ int sqlite3_status64(
+  int op,
+  sqlite3_int64 *pCurrent,
+  sqlite3_int64 *pHighwater,
+  int resetFlag
+);
+# 7682 "./sqlite3.h"
+ int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg);
+# 7835 "./sqlite3.h"
+ int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg);
+# 7911 "./sqlite3.h"
+typedef struct sqlite3_pcache sqlite3_pcache;
+# 7923 "./sqlite3.h"
+typedef struct sqlite3_pcache_page sqlite3_pcache_page;
+struct sqlite3_pcache_page {
+  void *pBuf;
+  void *pExtra;
+};
+# 8088 "./sqlite3.h"
+typedef struct sqlite3_pcache_methods2 sqlite3_pcache_methods2;
+struct sqlite3_pcache_methods2 {
+  int iVersion;
+  void *pArg;
+  int (*xInit)(void*);
+  void (*xShutdown)(void*);
+  sqlite3_pcache *(*xCreate)(int szPage, int szExtra, int bPurgeable);
+  void (*xCachesize)(sqlite3_pcache*, int nCachesize);
+  int (*xPagecount)(sqlite3_pcache*);
+  sqlite3_pcache_page *(*xFetch)(sqlite3_pcache*, unsigned key, int createFlag);
+  void (*xUnpin)(sqlite3_pcache*, sqlite3_pcache_page*, int discard);
+  void (*xRekey)(sqlite3_pcache*, sqlite3_pcache_page*,
+      unsigned oldKey, unsigned newKey);
+  void (*xTruncate)(sqlite3_pcache*, unsigned iLimit);
+  void (*xDestroy)(sqlite3_pcache*);
+  void (*xShrink)(sqlite3_pcache*);
+};
+
+
+
+
+
+
+typedef struct sqlite3_pcache_methods sqlite3_pcache_methods;
+struct sqlite3_pcache_methods {
+  void *pArg;
+  int (*xInit)(void*);
+  void (*xShutdown)(void*);
+  sqlite3_pcache *(*xCreate)(int szPage, int bPurgeable);
+  void (*xCachesize)(sqlite3_pcache*, int nCachesize);
+  int (*xPagecount)(sqlite3_pcache*);
+  void *(*xFetch)(sqlite3_pcache*, unsigned key, int createFlag);
+  void (*xUnpin)(sqlite3_pcache*, void*, int discard);
+  void (*xRekey)(sqlite3_pcache*, void*, unsigned oldKey, unsigned newKey);
+  void (*xTruncate)(sqlite3_pcache*, unsigned iLimit);
+  void (*xDestroy)(sqlite3_pcache*);
+};
+# 8137 "./sqlite3.h"
+typedef struct sqlite3_backup sqlite3_backup;
+# 8325 "./sqlite3.h"
+ sqlite3_backup *sqlite3_backup_init(
+  sqlite3 *pDest,
+  const char *zDestName,
+  sqlite3 *pSource,
+  const char *zSourceName
+);
+ int sqlite3_backup_step(sqlite3_backup *p, int nPage);
+ int sqlite3_backup_finish(sqlite3_backup *p);
+ int sqlite3_backup_remaining(sqlite3_backup *p);
+ int sqlite3_backup_pagecount(sqlite3_backup *p);
+# 8451 "./sqlite3.h"
+ int sqlite3_unlock_notify(
+  sqlite3 *pBlocked,
+  void (*xNotify)(void **apArg, int nArg),
+  void *pNotifyArg
+);
+# 8466 "./sqlite3.h"
+ int sqlite3_stricmp(const char *, const char *);
+ int sqlite3_strnicmp(const char *, const char *, int);
+# 8484 "./sqlite3.h"
+ int sqlite3_strglob(const char *zGlob, const char *zStr);
+# 8507 "./sqlite3.h"
+ int sqlite3_strlike(const char *zGlob, const char *zStr, unsigned int cEsc);
+# 8530 "./sqlite3.h"
+ void sqlite3_log(int iErrCode, const char *zFormat, ...);
+# 8566 "./sqlite3.h"
+ void *sqlite3_wal_hook(
+  sqlite3*,
+  int(*)(void *,sqlite3*,const char*,int),
+  void*
+);
+# 8601 "./sqlite3.h"
+ int sqlite3_wal_autocheckpoint(sqlite3 *db, int N);
+# 8623 "./sqlite3.h"
+ int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb);
+# 8717 "./sqlite3.h"
+ int sqlite3_wal_checkpoint_v2(
+  sqlite3 *db,
+  const char *zDb,
+  int eMode,
+  int *pnLog,
+  int *pnCkpt
+);
+# 8753 "./sqlite3.h"
+ int sqlite3_vtab_config(sqlite3*, int op, ...);
+# 8807 "./sqlite3.h"
+ int sqlite3_vtab_on_conflict(sqlite3 *);
+# 8826 "./sqlite3.h"
+ int sqlite3_vtab_nochange(sqlite3_context*);
+# 8841 "./sqlite3.h"
+ const char *sqlite3_vtab_collation(sqlite3_index_info*,int);
+# 8946 "./sqlite3.h"
+ int sqlite3_stmt_scanstatus(
+  sqlite3_stmt *pStmt,
+  int idx,
+  int iScanStatusOp,
+  void *pOut
+);
+# 8962 "./sqlite3.h"
+ void sqlite3_stmt_scanstatus_reset(sqlite3_stmt*);
+# 8994 "./sqlite3.h"
+ int sqlite3_db_cacheflush(sqlite3*);
+# 9108 "./sqlite3.h"
+ int sqlite3_system_errno(sqlite3*);
+# 9130 "./sqlite3.h"
+typedef struct sqlite3_snapshot {
+  unsigned char hidden[48];
+} sqlite3_snapshot;
+# 9177 "./sqlite3.h"
+ int sqlite3_snapshot_get(
+  sqlite3 *db,
+  const char *zSchema,
+  sqlite3_snapshot **ppSnapshot
+);
+# 9226 "./sqlite3.h"
+ int sqlite3_snapshot_open(
+  sqlite3 *db,
+  const char *zSchema,
+  sqlite3_snapshot *pSnapshot
+);
+# 9243 "./sqlite3.h"
+ void sqlite3_snapshot_free(sqlite3_snapshot*);
+# 9270 "./sqlite3.h"
+ int sqlite3_snapshot_cmp(
+  sqlite3_snapshot *p1,
+  sqlite3_snapshot *p2
+);
+# 9298 "./sqlite3.h"
+ int sqlite3_snapshot_recover(sqlite3 *db, const char *zDb);
+# 9336 "./sqlite3.h"
+ unsigned char *sqlite3_serialize(
+  sqlite3 *db,
+  const char *zSchema,
+  sqlite3_int64 *piSize,
+  unsigned int mFlags
+);
+# 9388 "./sqlite3.h"
+ int sqlite3_deserialize(
+  sqlite3 *db,
+  const char *zSchema,
+  unsigned char *pData,
+  sqlite3_int64 szDb,
+  sqlite3_int64 szBuf,
+  unsigned mFlags
+);
+# 9457 "./sqlite3.h"
+typedef struct sqlite3_rtree_geometry sqlite3_rtree_geometry;
+typedef struct sqlite3_rtree_query_info sqlite3_rtree_query_info;
+
+
+
+
+
+
+
+  typedef double sqlite3_rtree_dbl;
+# 9475 "./sqlite3.h"
+ int sqlite3_rtree_geometry_callback(
+  sqlite3 *db,
+  const char *zGeom,
+  int (*xGeom)(sqlite3_rtree_geometry*, int, sqlite3_rtree_dbl*,int*),
+  void *pContext
+);
+
+
+
+
+
+
+struct sqlite3_rtree_geometry {
+  void *pContext;
+  int nParam;
+  sqlite3_rtree_dbl *aParam;
+  void *pUser;
+  void (*xDelUser)(void *);
+};
+
+
+
+
+
+
+
+ int sqlite3_rtree_query_callback(
+  sqlite3 *db,
+  const char *zQueryFunc,
+  int (*xQueryFunc)(sqlite3_rtree_query_info*),
+  void *pContext,
+  void (*xDestructor)(void*)
+);
+# 9519 "./sqlite3.h"
+struct sqlite3_rtree_query_info {
+  void *pContext;
+  int nParam;
+  sqlite3_rtree_dbl *aParam;
+  void *pUser;
+  void (*xDelUser)(void*);
+  sqlite3_rtree_dbl *aCoord;
+  unsigned int *anQueue;
+  int nCoord;
+  int iLevel;
+  int mxLevel;
+  sqlite3_int64 iRowid;
+  sqlite3_rtree_dbl rParentScore;
+  int eParentWithin;
+  int eWithin;
+  sqlite3_rtree_dbl rScore;
+
+  sqlite3_value **apSqlParam;
+};
+# 11252 "./sqlite3.h"
+typedef struct Fts5ExtensionApi Fts5ExtensionApi;
+typedef struct Fts5Context Fts5Context;
+typedef struct Fts5PhraseIter Fts5PhraseIter;
+
+typedef void (*fts5_extension_function)(
+  const Fts5ExtensionApi *pApi,
+  Fts5Context *pFts,
+  sqlite3_context *pCtx,
+  int nVal,
+  sqlite3_value **apVal
+);
+
+struct Fts5PhraseIter {
+  const unsigned char *a;
+  const unsigned char *b;
+};
+# 11480 "./sqlite3.h"
+struct Fts5ExtensionApi {
+  int iVersion;
+
+  void *(*xUserData)(Fts5Context*);
+
+  int (*xColumnCount)(Fts5Context*);
+  int (*xRowCount)(Fts5Context*, sqlite3_int64 *pnRow);
+  int (*xColumnTotalSize)(Fts5Context*, int iCol, sqlite3_int64 *pnToken);
+
+  int (*xTokenize)(Fts5Context*,
+    const char *pText, int nText,
+    void *pCtx,
+    int (*xToken)(void*, int, const char*, int, int, int)
+  );
+
+  int (*xPhraseCount)(Fts5Context*);
+  int (*xPhraseSize)(Fts5Context*, int iPhrase);
+
+  int (*xInstCount)(Fts5Context*, int *pnInst);
+  int (*xInst)(Fts5Context*, int iIdx, int *piPhrase, int *piCol, int *piOff);
+
+  sqlite3_int64 (*xRowid)(Fts5Context*);
+  int (*xColumnText)(Fts5Context*, int iCol, const char **pz, int *pn);
+  int (*xColumnSize)(Fts5Context*, int iCol, int *pnToken);
+
+  int (*xQueryPhrase)(Fts5Context*, int iPhrase, void *pUserData,
+    int(*)(const Fts5ExtensionApi*,Fts5Context*,void*)
+  );
+  int (*xSetAuxdata)(Fts5Context*, void *pAux, void(*xDelete)(void*));
+  void *(*xGetAuxdata)(Fts5Context*, int bClear);
+
+  int (*xPhraseFirst)(Fts5Context*, int iPhrase, Fts5PhraseIter*, int*, int*);
+  void (*xPhraseNext)(Fts5Context*, Fts5PhraseIter*, int *piCol, int *piOff);
+
+  int (*xPhraseFirstColumn)(Fts5Context*, int iPhrase, Fts5PhraseIter*, int*);
+  void (*xPhraseNextColumn)(Fts5Context*, Fts5PhraseIter*, int *piCol);
+};
+# 11714 "./sqlite3.h"
+typedef struct Fts5Tokenizer Fts5Tokenizer;
+typedef struct fts5_tokenizer fts5_tokenizer;
+struct fts5_tokenizer {
+  int (*xCreate)(void*, const char **azArg, int nArg, Fts5Tokenizer **ppOut);
+  void (*xDelete)(Fts5Tokenizer*);
+  int (*xTokenize)(Fts5Tokenizer*,
+      void *pCtx,
+      int flags,
+      const char *pText, int nText,
+      int (*xToken)(
+        void *pCtx,
+        int tflags,
+        const char *pToken,
+        int nToken,
+        int iStart,
+        int iEnd
+      )
+  );
+};
+# 11751 "./sqlite3.h"
+typedef struct fts5_api fts5_api;
+struct fts5_api {
+  int iVersion;
+
+
+  int (*xCreateTokenizer)(
+    fts5_api *pApi,
+    const char *zName,
+    void *pContext,
+    fts5_tokenizer *pTokenizer,
+    void (*xDestroy)(void*)
+  );
+
+
+  int (*xFindTokenizer)(
+    fts5_api *pApi,
+    const char *zName,
+    void **ppContext,
+    fts5_tokenizer *pTokenizer
+  );
+
+
+  int (*xCreateFunction)(
+    fts5_api *pApi,
+    const char *zName,
+    void *pContext,
+    fts5_extension_function xFunction,
+    void (*xDestroy)(void*)
+  );
+};
+# 168 "src/sqliteInt.h" 2
+# 178 "src/sqliteInt.h"
+# 1 "src/sqliteLimit.h" 1
+# 179 "src/sqliteInt.h" 2
+# 529 "src/sqliteInt.h"
+# 1 "src/hash.h" 1
+# 19 "src/hash.h"
+typedef struct Hash Hash;
+typedef struct HashElem HashElem;
+# 43 "src/hash.h"
+struct Hash {
+  unsigned int htsize;
+  unsigned int count;
+  HashElem *first;
+  struct _ht {
+    unsigned int count;
+    HashElem *chain;
+  } *ht;
+};
+
+
+
+
+
+
+
+struct HashElem {
+  HashElem *next, *prev;
+  void *data;
+  const char *pKey;
+};
+
+
+
+
+void sqlite3HashInit(Hash*);
+void *sqlite3HashInsert(Hash*, const char *pKey, void *pData);
+void *sqlite3HashFind(const Hash*, const char *pKey);
+void sqlite3HashClear(Hash*);
+# 530 "src/sqliteInt.h" 2
+# 1 "./parse.h" 1
+# 531 "src/sqliteInt.h" 2
+# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/stdio.h" 1
+# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/_fake_defines.h" 1
+# 2 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/stdio.h" 2
+# 532 "src/sqliteInt.h" 2
+# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/stdlib.h" 1
+# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/_fake_defines.h" 1
+# 2 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/stdlib.h" 2
+# 533 "src/sqliteInt.h" 2
+# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/string.h" 1
+# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/_fake_defines.h" 1
+# 2 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/string.h" 2
+# 534 "src/sqliteInt.h" 2
+# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/assert.h" 1
+# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/_fake_defines.h" 1
+# 2 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/assert.h" 2
+# 535 "src/sqliteInt.h" 2
+# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/stddef.h" 1
+# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/_fake_defines.h" 1
+# 2 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/stddef.h" 2
+# 536 "src/sqliteInt.h" 2
+# 734 "src/sqliteInt.h"
+typedef sqlite_int64 i64;
+typedef sqlite_uint64 u64;
+typedef unsigned int u32;
+typedef unsigned short int u16;
+typedef short int i16;
+typedef unsigned char u8;
+typedef signed char i8;
+# 759 "src/sqliteInt.h"
+ typedef u32 tRowcnt;
+# 785 "src/sqliteInt.h"
+typedef short int LogEst;
+# 809 "src/sqliteInt.h"
+  typedef u64 uptr;
+# 971 "src/sqliteInt.h"
+typedef struct BusyHandler BusyHandler;
+struct BusyHandler {
+  int (*xBusyHandler)(void *,int);
+  void *pBusyArg;
+  int nBusy;
+  u8 bExtraFileArg;
+};
+# 1066 "src/sqliteInt.h"
+typedef struct AggInfo AggInfo;
+typedef struct AuthContext AuthContext;
+typedef struct AutoincInfo AutoincInfo;
+typedef struct Bitvec Bitvec;
+typedef struct CollSeq CollSeq;
+typedef struct Column Column;
+typedef struct Db Db;
+typedef struct Schema Schema;
+typedef struct Expr Expr;
+typedef struct ExprList ExprList;
+typedef struct FKey FKey;
+typedef struct FuncDestructor FuncDestructor;
+typedef struct FuncDef FuncDef;
+typedef struct FuncDefHash FuncDefHash;
+typedef struct IdList IdList;
+typedef struct Index Index;
+typedef struct IndexSample IndexSample;
+typedef struct KeyClass KeyClass;
+typedef struct KeyInfo KeyInfo;
+typedef struct Lookaside Lookaside;
+typedef struct LookasideSlot LookasideSlot;
+typedef struct Module Module;
+typedef struct NameContext NameContext;
+typedef struct Parse Parse;
+typedef struct PreUpdate PreUpdate;
+typedef struct PrintfArguments PrintfArguments;
+typedef struct RenameToken RenameToken;
+typedef struct RowSet RowSet;
+typedef struct Savepoint Savepoint;
+typedef struct Select Select;
+typedef struct SQLiteThread SQLiteThread;
+typedef struct SelectDest SelectDest;
+typedef struct SrcList SrcList;
+typedef struct sqlite3_str StrAccum;
+typedef struct Table Table;
+typedef struct TableLock TableLock;
+typedef struct Token Token;
+typedef struct TreeView TreeView;
+typedef struct Trigger Trigger;
+typedef struct TriggerPrg TriggerPrg;
+typedef struct TriggerStep TriggerStep;
+typedef struct UnpackedRecord UnpackedRecord;
+typedef struct Upsert Upsert;
+typedef struct VTable VTable;
+typedef struct VtabCtx VtabCtx;
+typedef struct Walker Walker;
+typedef struct WhereInfo WhereInfo;
+typedef struct Window Window;
+typedef struct With With;
+# 1127 "src/sqliteInt.h"
+  typedef u64 Bitmask;
+# 1148 "src/sqliteInt.h"
+typedef int VList;
+
+
+
+
+
+
+# 1 "src/btree.h" 1
+# 39 "src/btree.h"
+typedef struct Btree Btree;
+typedef struct BtCursor BtCursor;
+typedef struct BtShared BtShared;
+typedef struct BtreePayload BtreePayload;
+
+
+int sqlite3BtreeOpen(
+  sqlite3_vfs *pVfs,
+  const char *zFilename,
+  sqlite3 *db,
+  Btree **ppBtree,
+  int flags,
+  int vfsFlags
+);
+# 65 "src/btree.h"
+int sqlite3BtreeClose(Btree*);
+int sqlite3BtreeSetCacheSize(Btree*,int);
+int sqlite3BtreeSetSpillSize(Btree*,int);
+
+  int sqlite3BtreeSetMmapLimit(Btree*,sqlite3_int64);
+
+int sqlite3BtreeSetPagerFlags(Btree*,unsigned);
+int sqlite3BtreeSetPageSize(Btree *p, int nPagesize, int nReserve, int eFix);
+int sqlite3BtreeGetPageSize(Btree*);
+int sqlite3BtreeMaxPageCount(Btree*,int);
+u32 sqlite3BtreeLastPage(Btree*);
+int sqlite3BtreeSecureDelete(Btree*,int);
+int sqlite3BtreeGetOptimalReserve(Btree*);
+int sqlite3BtreeGetReserveNoMutex(Btree *p);
+int sqlite3BtreeSetAutoVacuum(Btree *, int);
+int sqlite3BtreeGetAutoVacuum(Btree *);
+int sqlite3BtreeBeginTrans(Btree*,int,int*);
+int sqlite3BtreeCommitPhaseOne(Btree*, const char *zMaster);
+int sqlite3BtreeCommitPhaseTwo(Btree*, int);
+int sqlite3BtreeCommit(Btree*);
+int sqlite3BtreeRollback(Btree*,int,int);
+int sqlite3BtreeBeginStmt(Btree*,int);
+int sqlite3BtreeCreateTable(Btree*, int*, int flags);
+int sqlite3BtreeIsInTrans(Btree*);
+int sqlite3BtreeIsInReadTrans(Btree*);
+int sqlite3BtreeIsInBackup(Btree*);
+void *sqlite3BtreeSchema(Btree *, int, void(*)(void *));
+int sqlite3BtreeSchemaLocked(Btree *pBtree);
+
+int sqlite3BtreeLockTable(Btree *pBtree, int iTab, u8 isWriteLock);
+
+int sqlite3BtreeSavepoint(Btree *, int, int);
+
+const char *sqlite3BtreeGetFilename(Btree *);
+const char *sqlite3BtreeGetJournalname(Btree *);
+int sqlite3BtreeCopyFile(Btree *, Btree *);
+
+int sqlite3BtreeIncrVacuum(Btree *);
+# 117 "src/btree.h"
+int sqlite3BtreeDropTable(Btree*, int, int*);
+int sqlite3BtreeClearTable(Btree*, int, int*);
+int sqlite3BtreeClearTableOfCursor(BtCursor*);
+int sqlite3BtreeTripAllCursors(Btree*, int, int);
+
+void sqlite3BtreeGetMeta(Btree *pBtree, int idx, u32 *pValue);
+int sqlite3BtreeUpdateMeta(Btree*, int idx, u32 value);
+
+int sqlite3BtreeNewDb(Btree *p);
+# 226 "src/btree.h"
+int sqlite3BtreeCursor(
+  Btree*,
+  int iTable,
+  int wrFlag,
+  struct KeyInfo*,
+  BtCursor *pCursor
+);
+BtCursor *sqlite3BtreeFakeValidCursor(void);
+int sqlite3BtreeCursorSize(void);
+void sqlite3BtreeCursorZero(BtCursor*);
+void sqlite3BtreeCursorHintFlags(BtCursor*, unsigned);
+
+
+
+
+int sqlite3BtreeCloseCursor(BtCursor*);
+int sqlite3BtreeMovetoUnpacked(
+  BtCursor*,
+  UnpackedRecord *pUnKey,
+  i64 intKey,
+  int bias,
+  int *pRes
+);
+int sqlite3BtreeCursorHasMoved(BtCursor*);
+int sqlite3BtreeCursorRestore(BtCursor*, int*);
+int sqlite3BtreeDelete(BtCursor*, u8 flags);
+# 291 "src/btree.h"
+struct BtreePayload {
+  const void *pKey;
+  sqlite3_int64 nKey;
+  const void *pData;
+  sqlite3_value *aMem;
+  u16 nMem;
+  int nData;
+  int nZero;
+};
+
+int sqlite3BtreeInsert(BtCursor*, const BtreePayload *pPayload,
+                       int flags, int seekResult);
+int sqlite3BtreeFirst(BtCursor*, int *pRes);
+int sqlite3BtreeLast(BtCursor*, int *pRes);
+int sqlite3BtreeNext(BtCursor*, int flags);
+int sqlite3BtreeEof(BtCursor*);
+int sqlite3BtreePrevious(BtCursor*, int flags);
+i64 sqlite3BtreeIntegerKey(BtCursor*);
+
+
+
+int sqlite3BtreePayload(BtCursor*, u32 offset, u32 amt, void*);
+const void *sqlite3BtreePayloadFetch(BtCursor*, u32 *pAmt);
+u32 sqlite3BtreePayloadSize(BtCursor*);
+sqlite3_int64 sqlite3BtreeMaxRecordSize(BtCursor*);
+
+char *sqlite3BtreeIntegrityCheck(Btree*, int *aRoot, int nRoot, int, int*);
+struct Pager *sqlite3BtreePager(Btree*);
+i64 sqlite3BtreeRowCountEst(BtCursor*);
+
+
+int sqlite3BtreePayloadChecked(BtCursor*, u32 offset, u32 amt, void*);
+int sqlite3BtreePutData(BtCursor*, u32 offset, u32 amt, void*);
+void sqlite3BtreeIncrblobCursor(BtCursor *);
+
+void sqlite3BtreeClearCursor(BtCursor *);
+int sqlite3BtreeSetVersion(Btree *pBt, int iVersion);
+int sqlite3BtreeCursorHasHint(BtCursor*, unsigned int mask);
+int sqlite3BtreeIsReadonly(Btree *pBt);
+int sqlite3HeaderSizeBtree(void);
+
+
+
+
+int sqlite3BtreeCursorIsValidNN(BtCursor*);
+
+
+int sqlite3BtreeCount(BtCursor *, i64 *);
+# 347 "src/btree.h"
+  int sqlite3BtreeCheckpoint(Btree*, int, int *, int *);
+# 356 "src/btree.h"
+  void sqlite3BtreeEnter(Btree*);
+  void sqlite3BtreeEnterAll(sqlite3*);
+  int sqlite3BtreeSharable(Btree*);
+  void sqlite3BtreeEnterCursor(BtCursor*);
+  int sqlite3BtreeConnectionCount(Btree*);
+# 370 "src/btree.h"
+  void sqlite3BtreeLeave(Btree*);
+  void sqlite3BtreeLeaveCursor(BtCursor*);
+  void sqlite3BtreeLeaveAll(sqlite3*);
+# 1156 "src/sqliteInt.h" 2
+# 1 "src/vdbe.h" 1
+# 20 "src/vdbe.h"
+# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/stdio.h" 1
+# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/_fake_defines.h" 1
+# 2 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/stdio.h" 2
+# 21 "src/vdbe.h" 2
+
+
+
+
+
+
+typedef struct Vdbe Vdbe;
+
+
+
+
+
+typedef struct sqlite3_value Mem;
+typedef struct SubProgram SubProgram;
+
+
+
+
+
+
+struct VdbeOp {
+  u8 opcode;
+  signed char p4type;
+  u16 p5;
+  int p1;
+  int p2;
+  int p3;
+  union p4union {
+    int i;
+    void *p;
+    char *z;
+    i64 *pI64;
+    double *pReal;
+    FuncDef *pFunc;
+    sqlite3_context *pCtx;
+    CollSeq *pColl;
+    Mem *pMem;
+    VTable *pVtab;
+    KeyInfo *pKeyInfo;
+    int *ai;
+    SubProgram *pProgram;
+    Table *pTab;
+
+
+
+    int (*xAdvance)(BtCursor *, int);
+  } p4;
+# 79 "src/vdbe.h"
+};
+typedef struct VdbeOp VdbeOp;
+
+
+
+
+
+struct SubProgram {
+  VdbeOp *aOp;
+  int nOp;
+  int nMem;
+  int nCsr;
+  u8 *aOnce;
+  void *token;
+  SubProgram *pNext;
+};
+
+
+
+
+
+struct VdbeOpList {
+  u8 opcode;
+  signed char p1;
+  signed char p2;
+  signed char p3;
+};
+typedef struct VdbeOpList VdbeOpList;
+# 169 "src/vdbe.h"
+# 1 "./opcodes.h" 1
+# 170 "src/vdbe.h" 2
+# 181 "src/vdbe.h"
+Vdbe *sqlite3VdbeCreate(Parse*);
+int sqlite3VdbeAddOp0(Vdbe*,int);
+int sqlite3VdbeAddOp1(Vdbe*,int,int);
+int sqlite3VdbeAddOp2(Vdbe*,int,int,int);
+int sqlite3VdbeGoto(Vdbe*,int);
+int sqlite3VdbeLoadString(Vdbe*,int,const char*);
+void sqlite3VdbeMultiLoad(Vdbe*,int,const char*,...);
+int sqlite3VdbeAddOp3(Vdbe*,int,int,int,int);
+int sqlite3VdbeAddOp4(Vdbe*,int,int,int,int,const char *zP4,int);
+int sqlite3VdbeAddOp4Dup8(Vdbe*,int,int,int,int,const u8*,int);
+int sqlite3VdbeAddOp4Int(Vdbe*,int,int,int,int,int);
+void sqlite3VdbeEndCoroutine(Vdbe*,int);
+# 205 "src/vdbe.h"
+VdbeOp *sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp,int iLineno);
+
+  void sqlite3VdbeExplain(Parse*,u8,const char*,...);
+  void sqlite3VdbeExplainPop(Parse*);
+  int sqlite3VdbeExplainParent(Parse*);
+# 224 "src/vdbe.h"
+void sqlite3VdbeAddParseSchemaOp(Vdbe*,int,char*);
+void sqlite3VdbeChangeOpcode(Vdbe*, u32 addr, u8);
+void sqlite3VdbeChangeP1(Vdbe*, u32 addr, int P1);
+void sqlite3VdbeChangeP2(Vdbe*, u32 addr, int P2);
+void sqlite3VdbeChangeP3(Vdbe*, u32 addr, int P3);
+void sqlite3VdbeChangeP5(Vdbe*, u16 P5);
+void sqlite3VdbeJumpHere(Vdbe*, int addr);
+int sqlite3VdbeChangeToNoop(Vdbe*, int addr);
+int sqlite3VdbeDeletePriorOpcode(Vdbe*, u8 op);
+void sqlite3VdbeChangeP4(Vdbe*, int addr, const char *zP4, int N);
+void sqlite3VdbeAppendP4(Vdbe*, void *pP4, int p4type);
+void sqlite3VdbeSetP4KeyInfo(Parse*, Index*);
+void sqlite3VdbeUsesBtree(Vdbe*, int);
+VdbeOp *sqlite3VdbeGetOp(Vdbe*, int);
+int sqlite3VdbeMakeLabel(Parse*);
+void sqlite3VdbeRunOnlyOnce(Vdbe*);
+void sqlite3VdbeReusable(Vdbe*);
+void sqlite3VdbeDelete(Vdbe*);
+void sqlite3VdbeClearObject(sqlite3*,Vdbe*);
+void sqlite3VdbeMakeReady(Vdbe*,Parse*);
+int sqlite3VdbeFinalize(Vdbe*);
+void sqlite3VdbeResolveLabel(Vdbe*, int);
+int sqlite3VdbeCurrentAddr(Vdbe*);
+
+
+
+void sqlite3VdbeResetStepResult(Vdbe*);
+void sqlite3VdbeRewind(Vdbe*);
+int sqlite3VdbeReset(Vdbe*);
+void sqlite3VdbeSetNumCols(Vdbe*,int);
+int sqlite3VdbeSetColName(Vdbe*, int, int, const char *, void(*)(void*));
+void sqlite3VdbeCountChanges(Vdbe*);
+sqlite3 *sqlite3VdbeDb(Vdbe*);
+u8 sqlite3VdbePrepareFlags(Vdbe*);
+void sqlite3VdbeSetSql(Vdbe*, const char *z, int n, u8);
+
+
+
+
+void sqlite3VdbeSwap(Vdbe*,Vdbe*);
+VdbeOp *sqlite3VdbeTakeOpArray(Vdbe*, int*, int*);
+sqlite3_value *sqlite3VdbeGetBoundValue(Vdbe*, int, u8);
+void sqlite3VdbeSetVarmask(Vdbe*, int);
+
+  char *sqlite3VdbeExpandSql(Vdbe*, const char*);
+
+int sqlite3MemCompare(const Mem*, const Mem*, const CollSeq*);
+int sqlite3BlobCompare(const Mem*, const Mem*);
+
+void sqlite3VdbeRecordUnpack(KeyInfo*,int,const void*,UnpackedRecord*);
+int sqlite3VdbeRecordCompare(int,const void*,UnpackedRecord*);
+int sqlite3VdbeRecordCompareWithSkip(int, const void *, UnpackedRecord *, int);
+UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(KeyInfo*);
+
+typedef int (*RecordCompare)(int,const void*,UnpackedRecord*);
+RecordCompare sqlite3VdbeFindCompare(UnpackedRecord*);
+
+
+void sqlite3VdbeLinkSubProgram(Vdbe *, SubProgram *);
+
+
+int sqlite3NotPureFunc(sqlite3_context*);
+# 1157 "src/sqliteInt.h" 2
+# 1 "src/pager.h" 1
+# 33 "src/pager.h"
+typedef u32 Pgno;
+
+
+
+
+typedef struct Pager Pager;
+
+
+
+
+typedef struct PgHdr DbPage;
+# 116 "src/pager.h"
+int sqlite3PagerOpen(
+  sqlite3_vfs*,
+  Pager **ppPager,
+  const char*,
+  int,
+  int,
+  int,
+  void(*)(DbPage*)
+);
+int sqlite3PagerClose(Pager *pPager, sqlite3*);
+int sqlite3PagerReadFileheader(Pager*, int, unsigned char*);
+
+
+void sqlite3PagerSetBusyHandler(Pager*, int(*)(void *), void *);
+int sqlite3PagerSetPagesize(Pager*, u32*, int);
+
+
+
+int sqlite3PagerMaxPageCount(Pager*, int);
+void sqlite3PagerSetCachesize(Pager*, int);
+int sqlite3PagerSetSpillsize(Pager*, int);
+void sqlite3PagerSetMmapLimit(Pager *, sqlite3_int64);
+void sqlite3PagerShrink(Pager*);
+void sqlite3PagerSetFlags(Pager*,unsigned);
+int sqlite3PagerLockingMode(Pager *, int);
+int sqlite3PagerSetJournalMode(Pager *, int);
+int sqlite3PagerGetJournalMode(Pager*);
+int sqlite3PagerOkToChangeJournalMode(Pager*);
+i64 sqlite3PagerJournalSizeLimit(Pager *, i64);
+sqlite3_backup **sqlite3PagerBackupPtr(Pager*);
+int sqlite3PagerFlush(Pager*);
+
+
+int sqlite3PagerGet(Pager *pPager, Pgno pgno, DbPage **ppPage, int clrFlag);
+DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno);
+void sqlite3PagerRef(DbPage*);
+void sqlite3PagerUnref(DbPage*);
+void sqlite3PagerUnrefNotNull(DbPage*);
+void sqlite3PagerUnrefPageOne(DbPage*);
+
+
+int sqlite3PagerWrite(DbPage*);
+void sqlite3PagerDontWrite(DbPage*);
+int sqlite3PagerMovepage(Pager*,DbPage*,Pgno,int);
+int sqlite3PagerPageRefcount(DbPage*);
+void *sqlite3PagerGetData(DbPage *);
+void *sqlite3PagerGetExtra(DbPage *);
+
+
+void sqlite3PagerPagecount(Pager*, int*);
+int sqlite3PagerBegin(Pager*, int exFlag, int);
+int sqlite3PagerCommitPhaseOne(Pager*,const char *zMaster, int);
+int sqlite3PagerExclusiveLock(Pager*);
+int sqlite3PagerSync(Pager *pPager, const char *zMaster);
+int sqlite3PagerCommitPhaseTwo(Pager*);
+int sqlite3PagerRollback(Pager*);
+int sqlite3PagerOpenSavepoint(Pager *pPager, int n);
+int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint);
+int sqlite3PagerSharedLock(Pager *pPager);
+
+
+  int sqlite3PagerCheckpoint(Pager *pPager, sqlite3*, int, int*, int*);
+  int sqlite3PagerWalSupported(Pager *pPager);
+  int sqlite3PagerWalCallback(Pager *pPager);
+  int sqlite3PagerOpenWal(Pager *pPager, int *pisOpen);
+  int sqlite3PagerCloseWal(Pager *pPager, sqlite3*);
+# 200 "src/pager.h"
+u8 sqlite3PagerIsreadonly(Pager*);
+u32 sqlite3PagerDataVersion(Pager*);
+
+
+
+int sqlite3PagerMemUsed(Pager*);
+const char *sqlite3PagerFilename(Pager*, int);
+sqlite3_vfs *sqlite3PagerVfs(Pager*);
+sqlite3_file *sqlite3PagerFile(Pager*);
+sqlite3_file *sqlite3PagerJrnlFile(Pager*);
+const char *sqlite3PagerJournalname(Pager*);
+void *sqlite3PagerTempSpace(Pager*);
+int sqlite3PagerIsMemdb(Pager*);
+void sqlite3PagerCacheStat(Pager *, int, int, int *);
+void sqlite3PagerClearCache(Pager*);
+int sqlite3SectorSize(sqlite3_file *);
+
+
+
+
+
+
+
+void sqlite3PagerTruncateImage(Pager*,Pgno);
+
+void sqlite3PagerRekey(DbPage*, Pgno, u16);
+# 1158 "src/sqliteInt.h" 2
+# 1 "src/pcache.h" 1
+# 18 "src/pcache.h"
+typedef struct PgHdr PgHdr;
+typedef struct PCache PCache;
+
+
+
+
+
+struct PgHdr {
+  sqlite3_pcache_page *pPage;
+  void *pData;
+  void *pExtra;
+  PCache *pCache;
+  PgHdr *pDirty;
+  Pager *pPager;
+  Pgno pgno;
+
+
+
+  u16 flags;
+
+
+
+
+
+
+  i16 nRef;
+  PgHdr *pDirtyNext;
+  PgHdr *pDirtyPrev;
+
+
+};
+# 62 "src/pcache.h"
+int sqlite3PcacheInitialize(void);
+void sqlite3PcacheShutdown(void);
+
+
+
+
+void sqlite3PCacheBufferSetup(void *, int sz, int n);
+
+
+
+
+
+int sqlite3PcacheOpen(
+  int szPage,
+  int szExtra,
+  int bPurgeable,
+  int (*xStress)(void*, PgHdr*),
+  void *pStress,
+  PCache *pToInit
+);
+
+
+int sqlite3PcacheSetPageSize(PCache *, int);
+
+
+
+
+int sqlite3PcacheSize(void);
+
+
+
+
+sqlite3_pcache_page *sqlite3PcacheFetch(PCache*, Pgno, int createFlag);
+int sqlite3PcacheFetchStress(PCache*, Pgno, sqlite3_pcache_page**);
+PgHdr *sqlite3PcacheFetchFinish(PCache*, Pgno, sqlite3_pcache_page *pPage);
+void sqlite3PcacheRelease(PgHdr*);
+
+void sqlite3PcacheDrop(PgHdr*);
+void sqlite3PcacheMakeDirty(PgHdr*);
+void sqlite3PcacheMakeClean(PgHdr*);
+void sqlite3PcacheCleanAll(PCache*);
+void sqlite3PcacheClearWritable(PCache*);
+
+
+void sqlite3PcacheMove(PgHdr*, Pgno);
+
+
+void sqlite3PcacheTruncate(PCache*, Pgno x);
+
+
+PgHdr *sqlite3PcacheDirtyList(PCache*);
+
+
+void sqlite3PcacheClose(PCache*);
+
+
+void sqlite3PcacheClearSyncFlags(PCache *);
+
+
+void sqlite3PcacheClear(PCache*);
+
+
+int sqlite3PcacheRefCount(PCache*);
+
+
+void sqlite3PcacheRef(PgHdr*);
+
+int sqlite3PcachePageRefcount(PgHdr*);
+
+
+int sqlite3PcachePagecount(PCache*);
+# 153 "src/pcache.h"
+void sqlite3PcacheSetCachesize(PCache *, int);
+# 163 "src/pcache.h"
+int sqlite3PcacheSetSpillsize(PCache *, int);
+
+
+void sqlite3PcacheShrink(PCache*);
+# 177 "src/pcache.h"
+void sqlite3PCacheSetDefault(void);
+
+
+int sqlite3HeaderSizePcache(void);
+int sqlite3HeaderSizePcache1(void);
+
+
+int sqlite3PCachePercentDirty(PCache*);
+# 1159 "src/sqliteInt.h" 2
+# 1 "src/os.h" 1
+# 27 "src/os.h"
+# 1 "src/os_setup.h" 1
+# 28 "src/os.h" 2
+# 158 "src/os.h"
+int sqlite3OsInit(void);
+
+
+
+
+void sqlite3OsClose(sqlite3_file*);
+int sqlite3OsRead(sqlite3_file*, void*, int amt, i64 offset);
+int sqlite3OsWrite(sqlite3_file*, const void*, int amt, i64 offset);
+int sqlite3OsTruncate(sqlite3_file*, i64 size);
+int sqlite3OsSync(sqlite3_file*, int);
+int sqlite3OsFileSize(sqlite3_file*, i64 *pSize);
+int sqlite3OsLock(sqlite3_file*, int);
+int sqlite3OsUnlock(sqlite3_file*, int);
+int sqlite3OsCheckReservedLock(sqlite3_file *id, int *pResOut);
+int sqlite3OsFileControl(sqlite3_file*,int,void*);
+void sqlite3OsFileControlHint(sqlite3_file*,int,void*);
+
+int sqlite3OsSectorSize(sqlite3_file *id);
+int sqlite3OsDeviceCharacteristics(sqlite3_file *id);
+
+int sqlite3OsShmMap(sqlite3_file *,int,int,int,void volatile **);
+int sqlite3OsShmLock(sqlite3_file *id, int, int, int);
+void sqlite3OsShmBarrier(sqlite3_file *id);
+int sqlite3OsShmUnmap(sqlite3_file *id, int);
+
+int sqlite3OsFetch(sqlite3_file *id, i64, int, void **);
+int sqlite3OsUnfetch(sqlite3_file *, i64, void *);
+
+
+
+
+
+int sqlite3OsOpen(sqlite3_vfs *, const char *, sqlite3_file*, int, int *);
+int sqlite3OsDelete(sqlite3_vfs *, const char *, int);
+int sqlite3OsAccess(sqlite3_vfs *, const char *, int, int *pResOut);
+int sqlite3OsFullPathname(sqlite3_vfs *, const char *, int, char *);
+
+void *sqlite3OsDlOpen(sqlite3_vfs *, const char *);
+void sqlite3OsDlError(sqlite3_vfs *, int, char *);
+void (*sqlite3OsDlSym(sqlite3_vfs *, void *, const char *))(void);
+void sqlite3OsDlClose(sqlite3_vfs *, void *);
+
+int sqlite3OsRandomness(sqlite3_vfs *, int, char *);
+int sqlite3OsSleep(sqlite3_vfs *, int);
+int sqlite3OsGetLastError(sqlite3_vfs*);
+int sqlite3OsCurrentTimeInt64(sqlite3_vfs *, sqlite3_int64*);
+
+
+
+
+
+int sqlite3OsOpenMalloc(sqlite3_vfs *, const char *, sqlite3_file **, int,int*);
+void sqlite3OsCloseFree(sqlite3_file *);
+# 1160 "src/sqliteInt.h" 2
+# 1 "src/mutex.h" 1
+# 1161 "src/sqliteInt.h" 2
+# 1200 "src/sqliteInt.h"
+struct Db {
+  char *zDbSName;
+  Btree *pBt;
+  u8 safety_level;
+  u8 bSyncSet;
+  Schema *pSchema;
+};
+# 1225 "src/sqliteInt.h"
+struct Schema {
+  int schema_cookie;
+  int iGeneration;
+  Hash tblHash;
+  Hash idxHash;
+  Hash trigHash;
+  Hash fkeyHash;
+  Table *pSeqTab;
+  u8 file_format;
+  u8 enc;
+  u16 schemaFlags;
+  int cache_size;
+};
+# 1289 "src/sqliteInt.h"
+struct Lookaside {
+  u32 bDisable;
+  u16 sz;
+  u8 bMalloced;
+  u32 nSlot;
+  u32 anStat[3];
+  LookasideSlot *pInit;
+  LookasideSlot *pFree;
+  void *pStart;
+  void *pEnd;
+};
+struct LookasideSlot {
+  LookasideSlot *pNext;
+};
+# 1313 "src/sqliteInt.h"
+struct FuncDefHash {
+  FuncDef *a[23];
+};
+# 1352 "src/sqliteInt.h"
+  typedef int (*sqlite3_xauth)(void*,int,const char*,const char*,const char*,
+                               const char*);
+# 1372 "src/sqliteInt.h"
+struct sqlite3 {
+  sqlite3_vfs *pVfs;
+  struct Vdbe *pVdbe;
+  CollSeq *pDfltColl;
+  sqlite3_mutex *mutex;
+  Db *aDb;
+  int nDb;
+  u32 mDbFlags;
+  u64 flags;
+  i64 lastRowid;
+  i64 szMmap;
+  u32 nSchemaLock;
+  unsigned int openFlags;
+  int errCode;
+  int errMask;
+  int iSysErrno;
+  u16 dbOptFlags;
+  u8 enc;
+  u8 autoCommit;
+  u8 temp_store;
+  u8 mallocFailed;
+  u8 bBenignMalloc;
+  u8 dfltLockMode;
+  signed char nextAutovac;
+  u8 suppressErr;
+  u8 vtabOnConflict;
+  u8 isTransactionSavepoint;
+  u8 mTrace;
+  u8 noSharedCache;
+  u8 nSqlExec;
+  int nextPagesize;
+  u32 magic;
+  int nChange;
+  int nTotalChange;
+  int aLimit[(11 +1)];
+  int nMaxSorterMmap;
+  struct sqlite3InitInfo {
+    int newTnum;
+    u8 iDb;
+    u8 busy;
+    unsigned orphanTrigger : 1;
+    unsigned imposterTable : 1;
+    unsigned reopenMemdb : 1;
+  } init;
+  int nVdbeActive;
+  int nVdbeRead;
+  int nVdbeWrite;
+  int nVdbeExec;
+  int nVDestroy;
+  int nExtension;
+  void **aExtension;
+  int (*xTrace)(u32,void*,void*,void*);
+  void *pTraceArg;
+
+  void (*xProfile)(void*,const char*,u64);
+  void *pProfileArg;
+
+  void *pCommitArg;
+  int (*xCommitCallback)(void*);
+  void *pRollbackArg;
+  void (*xRollbackCallback)(void*);
+  void *pUpdateArg;
+  void (*xUpdateCallback)(void*,int, const char*,const char*,sqlite_int64);
+  Parse *pParse;
+# 1444 "src/sqliteInt.h"
+  int (*xWalCallback)(void *, sqlite3 *, const char *, int);
+  void *pWalArg;
+
+  void(*xCollNeeded)(void*,sqlite3*,int eTextRep,const char*);
+  void(*xCollNeeded16)(void*,sqlite3*,int eTextRep,const void*);
+  void *pCollNeededArg;
+  sqlite3_value *pErr;
+  union {
+    volatile int isInterrupted;
+    double notUsed1;
+  } u1;
+  Lookaside lookaside;
+
+  sqlite3_xauth xAuth;
+  void *pAuthArg;
+
+
+  int (*xProgress)(void *);
+  void *pProgressArg;
+  unsigned nProgressOps;
+
+
+  int nVTrans;
+  Hash aModule;
+  VtabCtx *pVtabCtx;
+  VTable **aVTrans;
+  VTable *pDisconnect;
+
+  Hash aFunc;
+  Hash aCollSeq;
+  BusyHandler busyHandler;
+  Db aDbStatic[2];
+  Savepoint *pSavepoint;
+  int busyTimeout;
+  int nSavepoint;
+  int nStatement;
+  i64 nDeferredCons;
+  i64 nDeferredImmCons;
+  int *pnBytesFreed;
+# 1503 "src/sqliteInt.h"
+};
+# 1632 "src/sqliteInt.h"
+struct FuncDef {
+  i8 nArg;
+  u32 funcFlags;
+  void *pUserData;
+  FuncDef *pNext;
+  void (*xSFunc)(sqlite3_context*,int,sqlite3_value**);
+  void (*xFinalize)(sqlite3_context*);
+  void (*xValue)(sqlite3_context*);
+  void (*xInverse)(sqlite3_context*,int,sqlite3_value**);
+  const char *zName;
+  union {
+    FuncDef *pHash;
+    FuncDestructor *pDestructor;
+  } u;
+};
+# 1662 "src/sqliteInt.h"
+struct FuncDestructor {
+  int nRef;
+  void (*xDestroy)(void *);
+  void *pUserData;
+};
+# 1788 "src/sqliteInt.h"
+struct Savepoint {
+  char *zName;
+  i64 nDeferredCons;
+  i64 nDeferredImmCons;
+  Savepoint *pNext;
+};
+# 1809 "src/sqliteInt.h"
+struct Module {
+  const sqlite3_module *pModule;
+  const char *zName;
+  void *pAux;
+  void (*xDestroy)(void *);
+  Table *pEpoTab;
+};
+
+
+
+
+
+struct Column {
+  char *zName;
+  Expr *pDflt;
+  char *zColl;
+  u8 notNull;
+  char affinity;
+  u8 szEst;
+  u8 colFlags;
+};
+# 1848 "src/sqliteInt.h"
+struct CollSeq {
+  char *zName;
+  u8 enc;
+  void *pUser;
+  int (*xCmp)(void*,int, const void*, int, const void*);
+  void (*xDel)(void*);
+};
+# 1948 "src/sqliteInt.h"
+struct VTable {
+  sqlite3 *db;
+  Module *pMod;
+  sqlite3_vtab *pVtab;
+  int nRef;
+  u8 bConstraint;
+  int iSavepoint;
+  VTable *pNext;
+};
+
+
+
+
+
+struct Table {
+  char *zName;
+  Column *aCol;
+  Index *pIndex;
+  Select *pSelect;
+  FKey *pFKey;
+  char *zColAff;
+  ExprList *pCheck;
+
+  int tnum;
+  u32 nTabRef;
+  u32 tabFlags;
+  i16 iPKey;
+  i16 nCol;
+  LogEst nRowLogEst;
+  LogEst szTabRow;
+
+
+
+  u8 keyConf;
+
+  int addColOffset;
+
+
+  int nModuleArg;
+  char **azModuleArg;
+  VTable *pVTable;
+
+  Trigger *pTrigger;
+  Schema *pSchema;
+  Table *pNextZombie;
+};
+# 2078 "src/sqliteInt.h"
+struct FKey {
+  Table *pFrom;
+  FKey *pNextFrom;
+  char *zTo;
+  FKey *pNextTo;
+  FKey *pPrevTo;
+  int nCol;
+
+  u8 isDeferred;
+  u8 aAction[2];
+  Trigger *apTrigger[2];
+  struct sColMap {
+    int iFrom;
+    char *zCol;
+  } aCol[1];
+};
+# 2143 "src/sqliteInt.h"
+struct KeyInfo {
+  u32 nRef;
+  u8 enc;
+  u16 nKeyField;
+  u16 nAllField;
+  sqlite3 *db;
+  u8 *aSortOrder;
+  CollSeq *aColl[1];
+};
+# 2188 "src/sqliteInt.h"
+struct UnpackedRecord {
+  KeyInfo *pKeyInfo;
+  Mem *aMem;
+  u16 nField;
+  i8 default_rc;
+  u8 errCode;
+  i8 r1;
+  i8 r2;
+  u8 eqSeen;
+};
+# 2234 "src/sqliteInt.h"
+struct Index {
+  char *zName;
+  i16 *aiColumn;
+  LogEst *aiRowLogEst;
+  Table *pTable;
+  char *zColAff;
+  Index *pNext;
+  Schema *pSchema;
+  u8 *aSortOrder;
+  const char **azColl;
+  Expr *pPartIdxWhere;
+  ExprList *aColExpr;
+  int tnum;
+  LogEst szIdxRow;
+  u16 nKeyCol;
+  u16 nColumn;
+  u8 onError;
+  unsigned idxType:2;
+  unsigned bUnordered:1;
+  unsigned uniqNotNull:1;
+  unsigned isResized:1;
+  unsigned isCovering:1;
+  unsigned noSkipScan:1;
+  unsigned hasStat1:1;
+  unsigned bNoQuery:1;
+  unsigned bAscKeyBug:1;
+# 2268 "src/sqliteInt.h"
+  Bitmask colNotIdxed;
+};
+# 2296 "src/sqliteInt.h"
+struct IndexSample {
+  void *p;
+  int n;
+  tRowcnt *anEq;
+  tRowcnt *anLt;
+  tRowcnt *anDLt;
+};
+# 2320 "src/sqliteInt.h"
+struct Token {
+  const char *z;
+  unsigned int n;
+};
+# 2338 "src/sqliteInt.h"
+struct AggInfo {
+  u8 directMode;
+
+  u8 useSortingIdx;
+
+  int sortingIdx;
+  int sortingIdxPTab;
+  int nSortingColumn;
+  int mnReg, mxReg;
+  ExprList *pGroupBy;
+  struct AggInfo_col {
+    Table *pTab;
+    int iTable;
+    int iColumn;
+    int iSorterColumn;
+    int iMem;
+    Expr *pExpr;
+  } *aCol;
+  int nColumn;
+  int nAccumulator;
+
+
+  struct AggInfo_func {
+    Expr *pExpr;
+    FuncDef *pFunc;
+    int iMem;
+    int iDistinct;
+  } *aFunc;
+  int nFunc;
+};
+# 2380 "src/sqliteInt.h"
+typedef i16 ynVar;
+# 2448 "src/sqliteInt.h"
+struct Expr {
+  u8 op;
+  char affinity;
+  u32 flags;
+  union {
+    char *zToken;
+    int iValue;
+  } u;
+
+
+
+
+
+
+  Expr *pLeft;
+  Expr *pRight;
+  union {
+    ExprList *pList;
+    Select *pSelect;
+  } x;
+
+
+
+
+
+
+
+  int nHeight;
+
+  int iTable;
+
+
+
+
+  ynVar iColumn;
+
+
+  i16 iAgg;
+  i16 iRightJoinTable;
+  u8 op2;
+
+
+  AggInfo *pAggInfo;
+  union {
+    Table *pTab;
+
+    Window *pWin;
+    struct {
+      int iAddr;
+      int regReturn;
+    } sub;
+  } y;
+};
+# 2598 "src/sqliteInt.h"
+struct ExprList {
+  int nExpr;
+  struct ExprList_item {
+    Expr *pExpr;
+    char *zName;
+    char *zSpan;
+    u8 sortOrder;
+    unsigned done :1;
+    unsigned bSpanIsTab :1;
+    unsigned reusable :1;
+    unsigned bSorterRef :1;
+    union {
+      struct {
+        u16 iOrderByCol;
+        u16 iAlias;
+      } x;
+      int iConstExprReg;
+    } u;
+  } a[1];
+};
+# 2634 "src/sqliteInt.h"
+struct IdList {
+  struct IdList_item {
+    char *zName;
+    int idx;
+  } *a;
+  int nId;
+};
+# 2661 "src/sqliteInt.h"
+struct SrcList {
+  int nSrc;
+  u32 nAlloc;
+  struct SrcList_item {
+    Schema *pSchema;
+    char *zDatabase;
+    char *zName;
+    char *zAlias;
+    Table *pTab;
+    Select *pSelect;
+    int addrFillSub;
+    int regReturn;
+    int regResult;
+    struct {
+      u8 jointype;
+      unsigned notIndexed :1;
+      unsigned isIndexedBy :1;
+      unsigned isTabFunc :1;
+      unsigned isCorrelated :1;
+      unsigned viaCoroutine :1;
+      unsigned isRecursive :1;
+    } fg;
+    int iCursor;
+    Expr *pOn;
+    IdList *pUsing;
+    Bitmask colUsed;
+    union {
+      char *zIndexedBy;
+      ExprList *pFuncArg;
+    } u1;
+    Index *pIBIndex;
+  } a[1];
+};
+# 2761 "src/sqliteInt.h"
+struct NameContext {
+  Parse *pParse;
+  SrcList *pSrcList;
+  union {
+    ExprList *pEList;
+    AggInfo *pAggInfo;
+    Upsert *pUpsert;
+  } uNC;
+  NameContext *pNext;
+  int nRef;
+  int nErr;
+  int ncFlags;
+  Select *pWinSelect;
+};
+# 2815 "src/sqliteInt.h"
+struct Upsert {
+  ExprList *pUpsertTarget;
+  Expr *pUpsertTargetWhere;
+  ExprList *pUpsertSet;
+  Expr *pUpsertWhere;
+
+
+
+
+  Index *pUpsertIdx;
+  SrcList *pUpsertSrc;
+  int regData;
+  int iDataCur;
+  int iIdxCur;
+};
+# 2848 "src/sqliteInt.h"
+struct Select {
+  ExprList *pEList;
+  u8 op;
+  LogEst nSelectRow;
+  u32 selFlags;
+  int iLimit, iOffset;
+  u32 selId;
+  int addrOpenEphm[2];
+  SrcList *pSrc;
+  Expr *pWhere;
+  ExprList *pGroupBy;
+  Expr *pHaving;
+  ExprList *pOrderBy;
+  Select *pPrior;
+  Select *pNext;
+  Expr *pLimit;
+  With *pWith;
+
+  Window *pWin;
+  Window *pWinDefn;
+
+};
+# 2987 "src/sqliteInt.h"
+struct SelectDest {
+  u8 eDest;
+  int iSDParm;
+  int iSdst;
+  int nSdst;
+  char *zAffSdst;
+  ExprList *pOrderBy;
+};
+# 3005 "src/sqliteInt.h"
+struct AutoincInfo {
+  AutoincInfo *pNext;
+  Table *pTab;
+  int iDb;
+  int regCtr;
+};
+# 3030 "src/sqliteInt.h"
+struct TriggerPrg {
+  Trigger *pTrigger;
+  TriggerPrg *pNext;
+  SubProgram *pProgram;
+  int orconf;
+  u32 aColmask[2];
+};
+# 3049 "src/sqliteInt.h"
+  typedef unsigned int yDbMask;
+# 3073 "src/sqliteInt.h"
+struct Parse {
+  sqlite3 *db;
+  char *zErrMsg;
+  Vdbe *pVdbe;
+  int rc;
+  u8 colNamesSet;
+  u8 checkSchema;
+  u8 nested;
+  u8 nTempReg;
+  u8 isMultiWrite;
+  u8 mayAbort;
+  u8 hasCompound;
+  u8 okConstFactor;
+  u8 disableLookaside;
+  u8 disableVtab;
+  int nRangeReg;
+  int iRangeReg;
+  int nErr;
+  int nTab;
+  int nMem;
+  int szOpAlloc;
+  int iSelfTab;
+
+  int nLabel;
+  int nLabelAlloc;
+  int *aLabel;
+  ExprList *pConstExpr;
+  Token constraintName;
+  yDbMask writeMask;
+  yDbMask cookieMask;
+  int regRowid;
+  int regRoot;
+  int nMaxArg;
+  int nSelect;
+
+  int nTableLock;
+  TableLock *aTableLock;
+
+  AutoincInfo *pAinc;
+  Parse *pToplevel;
+  Table *pTriggerTab;
+  Parse *pParentParse;
+  int addrCrTab;
+  u32 nQueryLoop;
+  u32 oldmask;
+  u32 newmask;
+  u8 eTriggerOp;
+  u8 eOrconf;
+  u8 disableTriggers;
+# 3130 "src/sqliteInt.h"
+  int aTempReg[8];
+  Token sNameToken;
+# 3140 "src/sqliteInt.h"
+  Token sLastToken;
+  ynVar nVar;
+  u8 iPkSortOrder;
+  u8 explain;
+
+  u8 eParseMode;
+
+
+  int nVtabLock;
+
+  int nHeight;
+
+  int addrExplain;
+
+  VList *pVList;
+  Vdbe *pReprepare;
+  const char *zTail;
+  Table *pNewTable;
+  Index *pNewIndex;
+
+
+  Trigger *pNewTrigger;
+  const char *zAuthContext;
+
+  Token sArg;
+  Table **apVtabLock;
+
+  Table *pZombieTab;
+  TriggerPrg *pTriggerPrg;
+  With *pWith;
+  With *pWithToFree;
+
+  RenameToken *pRename;
+
+};
+# 3214 "src/sqliteInt.h"
+struct AuthContext {
+  const char *zAuthContext;
+  Parse *pParse;
+};
+# 3266 "src/sqliteInt.h"
+struct Trigger {
+  char *zName;
+  char *table;
+  u8 op;
+  u8 tr_tm;
+  Expr *pWhen;
+  IdList *pColumns;
+
+  Schema *pSchema;
+  Schema *pTabSchema;
+  TriggerStep *step_list;
+  Trigger *pNext;
+};
+# 3328 "src/sqliteInt.h"
+struct TriggerStep {
+  u8 op;
+  u8 orconf;
+  Trigger *pTrig;
+  Select *pSelect;
+  char *zTarget;
+  Expr *pWhere;
+  ExprList *pExprList;
+  IdList *pIdList;
+  Upsert *pUpsert;
+  char *zSpan;
+  TriggerStep *pNext;
+  TriggerStep *pLast;
+};
+
+
+
+
+
+
+typedef struct DbFixer DbFixer;
+struct DbFixer {
+  Parse *pParse;
+  Schema *pSchema;
+  int bVarOnly;
+  const char *zDb;
+  const char *zType;
+  const Token *pName;
+};
+
+
+
+
+
+struct sqlite3_str {
+  sqlite3 *db;
+  char *zText;
+  u32 nAlloc;
+  u32 mxAlloc;
+  u32 nChar;
+  u8 accError;
+  u8 printfFlags;
+};
+# 3382 "src/sqliteInt.h"
+typedef struct {
+  sqlite3 *db;
+  char **pzErrMsg;
+  int iDb;
+  int rc;
+  u32 mInitFlags;
+  u32 nInitRow;
+} InitData;
+# 3401 "src/sqliteInt.h"
+struct Sqlite3Config {
+  int bMemstat;
+  int bCoreMutex;
+  int bFullMutex;
+  int bOpenUri;
+  int bUseCis;
+  int bSmallMalloc;
+  int mxStrlen;
+  int neverCorrupt;
+  int szLookaside;
+  int nLookaside;
+  int nStmtSpill;
+  sqlite3_mem_methods m;
+  sqlite3_mutex_methods mutex;
+  sqlite3_pcache_methods2 pcache2;
+  void *pHeap;
+  int nHeap;
+  int mnReq, mxReq;
+  sqlite3_int64 szMmap;
+  sqlite3_int64 mxMmap;
+  void *pPage;
+  int szPage;
+  int nPage;
+  int mxParserStack;
+  int sharedCacheEnabled;
+  u32 szPma;
+
+
+  int isInit;
+  int inProgress;
+  int isMutexInit;
+  int isMallocInit;
+  int isPCacheInit;
+  int nRefInitMutex;
+  sqlite3_mutex *pInitMutex;
+  void (*xLog)(void*,int,const char*);
+  void *pLogArg;
+# 3453 "src/sqliteInt.h"
+  int (*xTestCallback)(int);
+
+  int bLocaltimeFault;
+  int bInternalFunctions;
+  int iOnceResetThreshold;
+  u32 szSorterRef;
+};
+# 3482 "src/sqliteInt.h"
+struct Walker {
+  Parse *pParse;
+  int (*xExprCallback)(Walker*, Expr*);
+  int (*xSelectCallback)(Walker*,Select*);
+  void (*xSelectCallback2)(Walker*,Select*);
+  int walkerDepth;
+  u8 eCode;
+  union {
+    NameContext *pNC;
+    int n;
+    int iCur;
+    SrcList *pSrcList;
+    struct SrcCount *pSrcCount;
+    struct CCurHint *pCCurHint;
+    int *aiCol;
+    struct IdxCover *pIdxCover;
+    struct IdxExprTrans *pIdxTrans;
+    ExprList *pGroupBy;
+    Select *pSelect;
+    struct WindowRewrite *pRewrite;
+    struct WhereConst *pConst;
+    struct RenameCtx *pRename;
+  } u;
+};
+
+
+int sqlite3WalkExpr(Walker*, Expr*);
+int sqlite3WalkExprList(Walker*, ExprList*);
+int sqlite3WalkSelect(Walker*, Select*);
+int sqlite3WalkSelectExpr(Walker*, Select*);
+int sqlite3WalkSelectFrom(Walker*, Select*);
+int sqlite3ExprWalkNoop(Walker*, Expr*);
+int sqlite3SelectWalkNoop(Walker*, Select*);
+int sqlite3SelectWalkFail(Walker*, Select*);
+# 3532 "src/sqliteInt.h"
+struct With {
+  int nCte;
+  With *pOuter;
+  struct Cte {
+    char *zName;
+    ExprList *pCols;
+    Select *pSelect;
+    const char *zCteErr;
+  } a[1];
+};
+# 3572 "src/sqliteInt.h"
+struct Window {
+  char *zName;
+  char *zBase;
+  ExprList *pPartition;
+  ExprList *pOrderBy;
+  u8 eFrmType;
+  u8 eStart;
+  u8 eEnd;
+  u8 bImplicitFrame;
+  u8 eExclude;
+  Expr *pStart;
+  Expr *pEnd;
+  Window *pNextWin;
+  Expr *pFilter;
+  FuncDef *pFunc;
+  int iEphCsr;
+  int regAccum;
+  int regResult;
+  int csrApp;
+  int regApp;
+  int regPart;
+  Expr *pOwner;
+  int nBufferCol;
+  int iArgCol;
+  int regOne;
+  int regStartRowid;
+  int regEndRowid;
+};
+
+
+void sqlite3WindowDelete(sqlite3*, Window*);
+void sqlite3WindowListDelete(sqlite3 *db, Window *p);
+Window *sqlite3WindowAlloc(Parse*, int, int, Expr*, int , Expr*, u8);
+void sqlite3WindowAttach(Parse*, Expr*, Window*);
+int sqlite3WindowCompare(Parse*, Window*, Window*);
+void sqlite3WindowCodeInit(Parse*, Window*);
+void sqlite3WindowCodeStep(Parse*, Select*, WhereInfo*, int, int);
+int sqlite3WindowRewrite(Parse*, Select*);
+int sqlite3ExpandSubquery(Parse*, struct SrcList_item*);
+void sqlite3WindowUpdate(Parse*, Window*, Window*, FuncDef*);
+Window *sqlite3WindowDup(sqlite3 *db, Expr *pOwner, Window *p);
+Window *sqlite3WindowListDup(sqlite3 *db, Window *p);
+void sqlite3WindowFunctions(void);
+void sqlite3WindowChain(Parse*, Window*, Window*);
+Window *sqlite3WindowAssemble(Parse*, Window*, ExprList*, ExprList*, Token*);
+# 3640 "src/sqliteInt.h"
+int sqlite3ReportError(int iErr, int lineno, const char *zType);
+int sqlite3CorruptError(int);
+int sqlite3MisuseError(int);
+int sqlite3CantopenError(int);
+# 3710 "src/sqliteInt.h"
+int sqlite3IsIdChar(u8);
+
+
+
+
+int sqlite3StrICmp(const char*,const char*);
+int sqlite3Strlen30(const char*);
+
+char *sqlite3ColumnType(Column*,char*);
+
+
+int sqlite3MallocInit(void);
+void sqlite3MallocEnd(void);
+void *sqlite3Malloc(u64);
+void *sqlite3MallocZero(u64);
+void *sqlite3DbMallocZero(sqlite3*, u64);
+void *sqlite3DbMallocRaw(sqlite3*, u64);
+void *sqlite3DbMallocRawNN(sqlite3*, u64);
+char *sqlite3DbStrDup(sqlite3*,const char*);
+char *sqlite3DbStrNDup(sqlite3*,const char*, u64);
+char *sqlite3DbSpanDup(sqlite3*,const char*,const char*);
+void *sqlite3Realloc(void*, u64);
+void *sqlite3DbReallocOrFree(sqlite3 *, void *, u64);
+void *sqlite3DbRealloc(sqlite3 *, void *, u64);
+void sqlite3DbFree(sqlite3*, void*);
+void sqlite3DbFreeNN(sqlite3*, void*);
+int sqlite3MallocSize(void*);
+int sqlite3DbMallocSize(sqlite3*, void*);
+void *sqlite3PageMalloc(int);
+void sqlite3PageFree(void*);
+void sqlite3MemSetDefault(void);
+
+void sqlite3BenignMallocHooks(void (*)(void), void (*)(void));
+
+int sqlite3HeapNearlyFull(void);
+# 3777 "src/sqliteInt.h"
+  sqlite3_mutex_methods const *sqlite3DefaultMutex(void);
+  sqlite3_mutex_methods const *sqlite3NoopMutex(void);
+  sqlite3_mutex *sqlite3MutexAlloc(int);
+  int sqlite3MutexInit(void);
+  int sqlite3MutexEnd(void);
+
+
+  void sqlite3MemoryBarrier(void);
+
+
+
+
+sqlite3_int64 sqlite3StatusValue(int);
+void sqlite3StatusUp(int, int);
+void sqlite3StatusDown(int, int);
+void sqlite3StatusHighwater(int, int);
+int sqlite3LookasideUsed(sqlite3*,int*);
+
+
+sqlite3_mutex *sqlite3Pcache1Mutex(void);
+sqlite3_mutex *sqlite3MallocMutex(void);
+# 3809 "src/sqliteInt.h"
+  int sqlite3IsNaN(double);
+# 3819 "src/sqliteInt.h"
+struct PrintfArguments {
+  int nArg;
+  int nUsed;
+  sqlite3_value **apArg;
+};
+
+char *sqlite3MPrintf(sqlite3*,const char*, ...);
+char *sqlite3VMPrintf(sqlite3*,const char*, va_list);
+# 3848 "src/sqliteInt.h"
+void sqlite3SetString(char **, sqlite3*, const char*);
+void sqlite3ErrorMsg(Parse*, const char*, ...);
+int sqlite3ErrorToParser(sqlite3*,int);
+void sqlite3Dequote(char*);
+void sqlite3DequoteExpr(Expr*);
+void sqlite3TokenInit(Token*,char*);
+int sqlite3KeywordCode(const unsigned char*, int);
+int sqlite3RunParser(Parse*, const char*, char **);
+void sqlite3FinishCoding(Parse*);
+int sqlite3GetTempReg(Parse*);
+void sqlite3ReleaseTempReg(Parse*,int);
+int sqlite3GetTempRange(Parse*,int);
+void sqlite3ReleaseTempRange(Parse*,int,int);
+void sqlite3ClearTempRegCache(Parse*);
+
+
+
+Expr *sqlite3ExprAlloc(sqlite3*,int,const Token*,int);
+Expr *sqlite3Expr(sqlite3*,int,const char*);
+void sqlite3ExprAttachSubtrees(sqlite3*,Expr*,Expr*,Expr*);
+Expr *sqlite3PExpr(Parse*, int, Expr*, Expr*);
+void sqlite3PExprAddSelect(Parse*, Expr*, Select*);
+Expr *sqlite3ExprAnd(Parse*,Expr*, Expr*);
+Expr *sqlite3ExprSimplifiedAndOr(Expr*);
+Expr *sqlite3ExprFunction(Parse*,ExprList*, Token*, int);
+void sqlite3ExprAssignVarNumber(Parse*, Expr*, u32);
+void sqlite3ExprDelete(sqlite3*, Expr*);
+void sqlite3ExprUnmapAndDelete(Parse*, Expr*);
+ExprList *sqlite3ExprListAppend(Parse*,ExprList*,Expr*);
+ExprList *sqlite3ExprListAppendVector(Parse*,ExprList*,IdList*,Expr*);
+void sqlite3ExprListSetSortOrder(ExprList*,int);
+void sqlite3ExprListSetName(Parse*,ExprList*,Token*,int);
+void sqlite3ExprListSetSpan(Parse*,ExprList*,const char*,const char*);
+void sqlite3ExprListDelete(sqlite3*, ExprList*);
+u32 sqlite3ExprListFlags(const ExprList*);
+int sqlite3IndexHasDuplicateRootPage(Index*);
+int sqlite3Init(sqlite3*, char**);
+int sqlite3InitCallback(void*, int, char**, char**);
+int sqlite3InitOne(sqlite3*, int, char**, u32);
+void sqlite3Pragma(Parse*,Token*,Token*,Token*,int);
+
+Module *sqlite3PragmaVtabRegister(sqlite3*,const char *zName);
+
+void sqlite3ResetAllSchemasOfConnection(sqlite3*);
+void sqlite3ResetOneSchema(sqlite3*,int);
+void sqlite3CollapseDatabaseArray(sqlite3*);
+void sqlite3CommitInternalChanges(sqlite3*);
+void sqlite3DeleteColumnNames(sqlite3*,Table*);
+int sqlite3ColumnsFromExprList(Parse*,ExprList*,i16*,Column**);
+void sqlite3SelectAddColumnTypeAndCollation(Parse*,Table*,Select*);
+Table *sqlite3ResultSetOfSelect(Parse*,Select*);
+void sqlite3OpenMasterTable(Parse *, int);
+Index *sqlite3PrimaryKeyIndex(Table*);
+i16 sqlite3ColumnOfIndex(Index*, i16);
+void sqlite3StartTable(Parse*,Token*,Token*,int,int,int,int);
+
+
+
+
+
+void sqlite3AddColumn(Parse*,Token*,Token*);
+void sqlite3AddNotNull(Parse*, int);
+void sqlite3AddPrimaryKey(Parse*, ExprList*, int, int, int);
+void sqlite3AddCheckConstraint(Parse*, Expr*);
+void sqlite3AddDefaultValue(Parse*,Expr*,const char*,const char*);
+void sqlite3AddCollateType(Parse*, Token*);
+void sqlite3EndTable(Parse*,Token*,Token*,u8,Select*);
+int sqlite3ParseUri(const char*,const char*,unsigned int*,
+                    sqlite3_vfs**,char**,char **);
+
+
+
+
+
+Btree *sqlite3DbNameToBtree(sqlite3*,const char*);
+
+
+
+
+  int sqlite3FaultSim(int);
+
+
+Bitvec *sqlite3BitvecCreate(u32);
+int sqlite3BitvecTest(Bitvec*, u32);
+int sqlite3BitvecTestNotNull(Bitvec*, u32);
+int sqlite3BitvecSet(Bitvec*, u32);
+void sqlite3BitvecClear(Bitvec*, u32, void*);
+void sqlite3BitvecDestroy(Bitvec*);
+u32 sqlite3BitvecSize(Bitvec*);
+
+int sqlite3BitvecBuiltinTest(int,int*);
+
+
+RowSet *sqlite3RowSetInit(sqlite3*);
+void sqlite3RowSetDelete(void*);
+void sqlite3RowSetClear(void*);
+void sqlite3RowSetInsert(RowSet*, i64);
+int sqlite3RowSetTest(RowSet*, int iBatch, i64);
+int sqlite3RowSetNext(RowSet*, i64*);
+
+void sqlite3CreateView(Parse*,Token*,Token*,Token*,ExprList*,Select*,int,int);
+
+
+  int sqlite3ViewGetColumnNames(Parse*,Table*);
+
+
+
+
+
+
+
+void sqlite3DropTable(Parse*, SrcList*, int, int);
+void sqlite3CodeDropTable(Parse*, Table*, int, int);
+void sqlite3DeleteTable(sqlite3*, Table*);
+void sqlite3FreeIndex(sqlite3*, Index*);
+
+  void sqlite3AutoincrementBegin(Parse *pParse);
+  void sqlite3AutoincrementEnd(Parse *pParse);
+
+
+
+
+void sqlite3Insert(Parse*, SrcList*, Select*, IdList*, int, Upsert*);
+void *sqlite3ArrayAllocate(sqlite3*,void*,int,int*,int*);
+IdList *sqlite3IdListAppend(Parse*, IdList*, Token*);
+int sqlite3IdListIndex(IdList*,const char*);
+SrcList *sqlite3SrcListEnlarge(Parse*, SrcList*, int, int);
+SrcList *sqlite3SrcListAppend(Parse*, SrcList*, Token*, Token*);
+SrcList *sqlite3SrcListAppendFromTerm(Parse*, SrcList*, Token*, Token*,
+                                      Token*, Select*, Expr*, IdList*);
+void sqlite3SrcListIndexedBy(Parse *, SrcList *, Token *);
+void sqlite3SrcListFuncArgs(Parse*, SrcList*, ExprList*);
+int sqlite3IndexedByLookup(Parse *, struct SrcList_item *);
+void sqlite3SrcListShiftJoinType(SrcList*);
+void sqlite3SrcListAssignCursors(Parse*, SrcList*);
+void sqlite3IdListDelete(sqlite3*, IdList*);
+void sqlite3SrcListDelete(sqlite3*, SrcList*);
+Index *sqlite3AllocateIndexObject(sqlite3*,i16,int,char**);
+void sqlite3CreateIndex(Parse*,Token*,Token*,SrcList*,ExprList*,int,Token*,
+                          Expr*, int, int, u8);
+void sqlite3DropIndex(Parse*, SrcList*, int);
+int sqlite3Select(Parse*, Select*, SelectDest*);
+Select *sqlite3SelectNew(Parse*,ExprList*,SrcList*,Expr*,ExprList*,
+                         Expr*,ExprList*,u32,Expr*);
+void sqlite3SelectDelete(sqlite3*, Select*);
+Table *sqlite3SrcListLookup(Parse*, SrcList*);
+int sqlite3IsReadOnly(Parse*, Table*, int);
+void sqlite3OpenTable(Parse*, int iCur, int iDb, Table*, int);
+
+
+
+void sqlite3DeleteFrom(Parse*, SrcList*, Expr*, ExprList*, Expr*);
+void sqlite3Update(Parse*, SrcList*, ExprList*,Expr*,int,ExprList*,Expr*,
+                   Upsert*);
+WhereInfo *sqlite3WhereBegin(Parse*,SrcList*,Expr*,ExprList*,ExprList*,u16,int);
+void sqlite3WhereEnd(WhereInfo*);
+LogEst sqlite3WhereOutputRowCount(WhereInfo*);
+int sqlite3WhereIsDistinct(WhereInfo*);
+int sqlite3WhereIsOrdered(WhereInfo*);
+int sqlite3WhereOrderByLimitOptLabel(WhereInfo*);
+int sqlite3WhereIsSorted(WhereInfo*);
+int sqlite3WhereContinueLabel(WhereInfo*);
+int sqlite3WhereBreakLabel(WhereInfo*);
+int sqlite3WhereOkOnePass(WhereInfo*, int*);
+
+
+
+void sqlite3ExprCodeLoadIndexColumn(Parse*, Index*, int, int, int);
+int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int, u8);
+void sqlite3ExprCodeGetColumnOfTable(Vdbe*, Table*, int, int, int);
+void sqlite3ExprCodeMove(Parse*, int, int, int);
+void sqlite3ExprCode(Parse*, Expr*, int);
+void sqlite3ExprCodeCopy(Parse*, Expr*, int);
+void sqlite3ExprCodeFactorable(Parse*, Expr*, int);
+int sqlite3ExprCodeAtInit(Parse*, Expr*, int);
+int sqlite3ExprCodeTemp(Parse*, Expr*, int*);
+int sqlite3ExprCodeTarget(Parse*, Expr*, int);
+void sqlite3ExprCodeAndCache(Parse*, Expr*, int);
+int sqlite3ExprCodeExprList(Parse*, ExprList*, int, int, u8);
+
+
+
+
+void sqlite3ExprIfTrue(Parse*, Expr*, int, int);
+void sqlite3ExprIfFalse(Parse*, Expr*, int, int);
+void sqlite3ExprIfFalseDup(Parse*, Expr*, int, int);
+Table *sqlite3FindTable(sqlite3*,const char*, const char*);
+
+
+Table *sqlite3LocateTable(Parse*,u32 flags,const char*, const char*);
+Table *sqlite3LocateTableItem(Parse*,u32 flags,struct SrcList_item *);
+Index *sqlite3FindIndex(sqlite3*,const char*, const char*);
+void sqlite3UnlinkAndDeleteTable(sqlite3*,int,const char*);
+void sqlite3UnlinkAndDeleteIndex(sqlite3*,int,const char*);
+void sqlite3Vacuum(Parse*,Token*,Expr*);
+int sqlite3RunVacuum(char**, sqlite3*, int, sqlite3_value*);
+char *sqlite3NameFromToken(sqlite3*, Token*);
+int sqlite3ExprCompare(Parse*,Expr*, Expr*, int);
+int sqlite3ExprCompareSkip(Expr*, Expr*, int);
+int sqlite3ExprListCompare(ExprList*, ExprList*, int);
+int sqlite3ExprImpliesExpr(Parse*,Expr*, Expr*, int);
+int sqlite3ExprImpliesNonNullRow(Expr*,int);
+void sqlite3ExprAnalyzeAggregates(NameContext*, Expr*);
+void sqlite3ExprAnalyzeAggList(NameContext*,ExprList*);
+int sqlite3ExprCoveredByIndex(Expr*, int iCur, Index *pIdx);
+int sqlite3FunctionUsesThisSrc(Expr*, SrcList*);
+Vdbe *sqlite3GetVdbe(Parse*);
+
+void sqlite3PrngSaveState(void);
+void sqlite3PrngRestoreState(void);
+
+void sqlite3RollbackAll(sqlite3*,int);
+void sqlite3CodeVerifySchema(Parse*, int);
+void sqlite3CodeVerifyNamedSchema(Parse*, const char *zDb);
+void sqlite3BeginTransaction(Parse*, int);
+void sqlite3EndTransaction(Parse*,int);
+void sqlite3Savepoint(Parse*, int, Token*);
+void sqlite3CloseSavepoints(sqlite3 *);
+void sqlite3LeaveMutexAndCloseZombie(sqlite3*);
+int sqlite3ExprIdToTrueFalse(Expr*);
+int sqlite3ExprTruthValue(const Expr*);
+int sqlite3ExprIsConstant(Expr*);
+int sqlite3ExprIsConstantNotJoin(Expr*);
+int sqlite3ExprIsConstantOrFunction(Expr*, u8);
+int sqlite3ExprIsConstantOrGroupBy(Parse*, Expr*, ExprList*);
+int sqlite3ExprIsTableConstant(Expr*,int);
+
+
+
+int sqlite3ExprIsInteger(Expr*, int*);
+int sqlite3ExprCanBeNull(const Expr*);
+int sqlite3ExprNeedsNoAffinityChange(const Expr*, char);
+int sqlite3IsRowid(const char*);
+void sqlite3GenerateRowDelete(
+    Parse*,Table*,Trigger*,int,int,int,i16,u8,u8,u8,int);
+void sqlite3GenerateRowIndexDelete(Parse*, Table*, int, int, int*, int);
+int sqlite3GenerateIndexKey(Parse*, Index*, int, int, int, int*,Index*,int);
+void sqlite3ResolvePartIdxLabel(Parse*,int);
+int sqlite3ExprReferencesUpdatedColumn(Expr*,int*,int);
+void sqlite3GenerateConstraintChecks(Parse*,Table*,int*,int,int,int,int,
+                                     u8,u8,int,int*,int*,Upsert*);
+
+
+
+
+
+void sqlite3CompleteInsertion(Parse*,Table*,int,int,int,int*,int,int,int);
+int sqlite3OpenTableAndIndices(Parse*, Table*, int, u8, int, u8*, int*, int*);
+void sqlite3BeginWriteOperation(Parse*, int, int);
+void sqlite3MultiWrite(Parse*);
+void sqlite3MayAbort(Parse*);
+void sqlite3HaltConstraint(Parse*, int, int, char*, i8, u8);
+void sqlite3UniqueConstraint(Parse*, int, Index*);
+void sqlite3RowidConstraint(Parse*, int, Table*);
+Expr *sqlite3ExprDup(sqlite3*,Expr*,int);
+ExprList *sqlite3ExprListDup(sqlite3*,ExprList*,int);
+SrcList *sqlite3SrcListDup(sqlite3*,SrcList*,int);
+IdList *sqlite3IdListDup(sqlite3*,IdList*);
+Select *sqlite3SelectDup(sqlite3*,Select*,int);
+FuncDef *sqlite3FunctionSearch(int,const char*);
+void sqlite3InsertBuiltinFuncs(FuncDef*,int);
+FuncDef *sqlite3FindFunction(sqlite3*,const char*,int,u8,u8);
+void sqlite3RegisterBuiltinFunctions(void);
+void sqlite3RegisterDateTimeFunctions(void);
+void sqlite3RegisterPerConnectionBuiltinFunctions(sqlite3*);
+int sqlite3SafetyCheckOk(sqlite3*);
+int sqlite3SafetyCheckSickOrOk(sqlite3*);
+void sqlite3ChangeCookie(Parse*, int);
+
+
+void sqlite3MaterializeView(Parse*, Table*, Expr*, ExprList*,Expr*,int);
+
+
+
+  void sqlite3BeginTrigger(Parse*, Token*,Token*,int,int,IdList*,SrcList*,
+                           Expr*,int, int);
+  void sqlite3FinishTrigger(Parse*, TriggerStep*, Token*);
+  void sqlite3DropTrigger(Parse*, SrcList*, int);
+  void sqlite3DropTriggerPtr(Parse*, Trigger*);
+  Trigger *sqlite3TriggersExist(Parse *, Table*, int, ExprList*, int *pMask);
+  Trigger *sqlite3TriggerList(Parse *, Table *);
+  void sqlite3CodeRowTrigger(Parse*, Trigger *, int, ExprList*, int, Table *,
+                            int, int, int);
+  void sqlite3CodeRowTriggerDirect(Parse *, Trigger *, Table *, int, int, int);
+  void sqliteViewTriggers(Parse*, Table*, Expr*, int, ExprList*);
+  void sqlite3DeleteTriggerStep(sqlite3*, TriggerStep*);
+  TriggerStep *sqlite3TriggerSelectStep(sqlite3*,Select*,
+                                        const char*,const char*);
+  TriggerStep *sqlite3TriggerInsertStep(Parse*,Token*, IdList*,
+                                        Select*,u8,Upsert*,
+                                        const char*,const char*);
+  TriggerStep *sqlite3TriggerUpdateStep(Parse*,Token*,ExprList*, Expr*, u8,
+                                        const char*,const char*);
+  TriggerStep *sqlite3TriggerDeleteStep(Parse*,Token*, Expr*,
+                                        const char*,const char*);
+  void sqlite3DeleteTrigger(sqlite3*, Trigger*);
+  void sqlite3UnlinkAndDeleteTrigger(sqlite3*,int,const char*);
+  u32 sqlite3TriggerColmask(Parse*,Trigger*,ExprList*,int,int,Table*,int);
+# 4161 "src/sqliteInt.h"
+int sqlite3JoinType(Parse*, Token*, Token*, Token*);
+void sqlite3CreateForeignKey(Parse*, ExprList*, Token*, ExprList*, int);
+void sqlite3DeferForeignKey(Parse*, int);
+
+  void sqlite3AuthRead(Parse*,Expr*,Schema*,SrcList*);
+  int sqlite3AuthCheck(Parse*,int, const char*, const char*, const char*);
+  void sqlite3AuthContextPush(Parse*, AuthContext*, const char*);
+  void sqlite3AuthContextPop(AuthContext*);
+  int sqlite3AuthReadCol(Parse*, const char *, const char *, int);
+
+
+
+
+
+
+void sqlite3Attach(Parse*, Expr*, Expr*, Expr*);
+void sqlite3Detach(Parse*, Expr*);
+void sqlite3FixInit(DbFixer*, Parse*, int, const char*, const Token*);
+int sqlite3FixSrcList(DbFixer*, SrcList*);
+int sqlite3FixSelect(DbFixer*, Select*);
+int sqlite3FixExpr(DbFixer*, Expr*);
+int sqlite3FixExprList(DbFixer*, ExprList*);
+int sqlite3FixTriggerStep(DbFixer*, TriggerStep*);
+int sqlite3RealSameAsInt(double,sqlite3_int64);
+int sqlite3AtoF(const char *z, double*, int, u8);
+int sqlite3GetInt32(const char *, int*);
+int sqlite3Atoi(const char*);
+
+int sqlite3Utf16ByteLen(const void *pData, int nChar);
+
+int sqlite3Utf8CharLen(const char *pData, int nByte);
+u32 sqlite3Utf8Read(const u8**);
+LogEst sqlite3LogEst(u64);
+LogEst sqlite3LogEstAdd(LogEst,LogEst);
+
+LogEst sqlite3LogEstFromDouble(double);
+
+
+
+
+
+
+VList *sqlite3VListAdd(sqlite3*,VList*,const char*,int,int);
+const char *sqlite3VListNumToName(VList*,int);
+int sqlite3VListNameToNum(VList*,const char*,int);
+
+
+
+
+
+
+int sqlite3PutVarint(unsigned char*, u64);
+u8 sqlite3GetVarint(const unsigned char *, u64 *);
+u8 sqlite3GetVarint32(const unsigned char *, u32 *);
+int sqlite3VarintLen(u64 v);
+# 4231 "src/sqliteInt.h"
+const char *sqlite3IndexAffinityStr(sqlite3*, Index*);
+void sqlite3TableAffinity(Vdbe*, Table*, int);
+char sqlite3CompareAffinity(Expr *pExpr, char aff2);
+int sqlite3IndexAffinityOk(Expr *pExpr, char idx_affinity);
+char sqlite3TableColumnAffinity(Table*,int);
+char sqlite3ExprAffinity(Expr *pExpr);
+int sqlite3Atoi64(const char*, i64*, int, u8);
+int sqlite3DecOrHexToI64(const char*, i64*);
+void sqlite3ErrorWithMsg(sqlite3*, int, const char*,...);
+void sqlite3Error(sqlite3*,int);
+void sqlite3SystemError(sqlite3*,int);
+void *sqlite3HexToBlob(sqlite3*, const char *z, int n);
+u8 sqlite3HexToInt(int h);
+int sqlite3TwoPartName(Parse *, Token *, Token *, Token **);
+# 4254 "src/sqliteInt.h"
+const char *sqlite3ErrStr(int);
+int sqlite3ReadSchema(Parse *pParse);
+CollSeq *sqlite3FindCollSeq(sqlite3*,u8 enc, const char*,int);
+int sqlite3IsBinary(const CollSeq*);
+CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char*zName);
+CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr);
+CollSeq *sqlite3ExprNNCollSeq(Parse *pParse, Expr *pExpr);
+int sqlite3ExprCollSeqMatch(Parse*,Expr*,Expr*);
+Expr *sqlite3ExprAddCollateToken(Parse *pParse, Expr*, const Token*, int);
+Expr *sqlite3ExprAddCollateString(Parse*,Expr*,const char*);
+Expr *sqlite3ExprSkipCollate(Expr*);
+int sqlite3CheckCollSeq(Parse *, CollSeq *);
+int sqlite3WritableSchema(sqlite3*);
+int sqlite3CheckObjectName(Parse *, const char *);
+void sqlite3VdbeSetChanges(sqlite3 *, int);
+int sqlite3AddInt64(i64*,i64);
+int sqlite3SubInt64(i64*,i64);
+int sqlite3MulInt64(i64*,i64);
+int sqlite3AbsInt32(int);
+
+
+
+
+
+u8 sqlite3GetBoolean(const char *z,u8);
+
+const void *sqlite3ValueText(sqlite3_value*, u8);
+int sqlite3ValueBytes(sqlite3_value*, u8);
+void sqlite3ValueSetStr(sqlite3_value*, int, const void *,u8,
+                        void(*)(void*));
+void sqlite3ValueSetNull(sqlite3_value*);
+void sqlite3ValueFree(sqlite3_value*);
+
+void sqlite3ResultIntReal(sqlite3_context*);
+
+sqlite3_value *sqlite3ValueNew(sqlite3 *);
+
+char *sqlite3Utf16to8(sqlite3 *, const void*, int, u8);
+
+int sqlite3ValueFromExpr(sqlite3 *, Expr *, u8, u8, sqlite3_value **);
+void sqlite3ValueApplyAffinity(sqlite3_value *, u8, u8);
+
+extern const unsigned char sqlite3OpcodeProperty[];
+extern const char sqlite3StrBINARY[];
+extern const unsigned char sqlite3UpperToLower[];
+extern const unsigned char sqlite3CtypeMap[];
+extern const Token sqlite3IntTokens[];
+extern struct Sqlite3Config sqlite3Config;
+extern FuncDefHash sqlite3BuiltinFunctions;
+
+extern int sqlite3PendingByte;
+
+
+
+
+
+void sqlite3RootPageMoved(sqlite3*, int, int, int);
+void sqlite3Reindex(Parse*, Token*, Token*);
+void sqlite3AlterFunctions(void);
+void sqlite3AlterRenameTable(Parse*, SrcList*, Token*);
+void sqlite3AlterRenameColumn(Parse*, SrcList*, Token*, Token*);
+int sqlite3GetToken(const unsigned char *, int *);
+void sqlite3NestedParse(Parse*, const char*, ...);
+void sqlite3ExpirePreparedStatements(sqlite3*, int);
+void sqlite3CodeRhsOfIN(Parse*, Expr*, int);
+int sqlite3CodeSubselect(Parse*, Expr*);
+void sqlite3SelectPrep(Parse*, Select*, NameContext*);
+void sqlite3SelectWrongNumTermsError(Parse *pParse, Select *p);
+int sqlite3MatchSpanName(const char*, const char*, const char*, const char*);
+int sqlite3ResolveExprNames(NameContext*, Expr*);
+int sqlite3ResolveExprListNames(NameContext*, ExprList*);
+void sqlite3ResolveSelectNames(Parse*, Select*, NameContext*);
+int sqlite3ResolveSelfReference(Parse*,Table*,int,Expr*,ExprList*);
+int sqlite3ResolveOrderGroupBy(Parse*, Select*, ExprList*, const char*);
+void sqlite3ColumnDefault(Vdbe *, Table *, int, int);
+void sqlite3AlterFinishAddColumn(Parse *, Token *);
+void sqlite3AlterBeginAddColumn(Parse *, SrcList *);
+void *sqlite3RenameTokenMap(Parse*, void*, Token*);
+void sqlite3RenameTokenRemap(Parse*, void *pTo, void *pFrom);
+void sqlite3RenameExprUnmap(Parse*, Expr*);
+void sqlite3RenameExprlistUnmap(Parse*, ExprList*);
+CollSeq *sqlite3GetCollSeq(Parse*, u8, CollSeq *, const char*);
+char sqlite3AffinityType(const char*, Column*);
+void sqlite3Analyze(Parse*, Token*, Token*);
+int sqlite3InvokeBusyHandler(BusyHandler*, sqlite3_file*);
+int sqlite3FindDb(sqlite3*, Token*);
+int sqlite3FindDbName(sqlite3 *, const char *);
+int sqlite3AnalysisLoad(sqlite3*,int iDB);
+void sqlite3DeleteIndexSamples(sqlite3*,Index*);
+void sqlite3DefaultRowEst(Index*);
+void sqlite3RegisterLikeFunctions(sqlite3*, int);
+int sqlite3IsLikeFunction(sqlite3*,Expr*,int*,char*);
+void sqlite3SchemaClear(void *);
+Schema *sqlite3SchemaGet(sqlite3 *, Btree *);
+int sqlite3SchemaToIndex(sqlite3 *db, Schema *);
+KeyInfo *sqlite3KeyInfoAlloc(sqlite3*,int,int);
+void sqlite3KeyInfoUnref(KeyInfo*);
+KeyInfo *sqlite3KeyInfoRef(KeyInfo*);
+KeyInfo *sqlite3KeyInfoOfIndex(Parse*, Index*);
+KeyInfo *sqlite3KeyInfoFromExprList(Parse*, ExprList*, int, int);
+
+
+
+
+int sqlite3CreateFunc(sqlite3 *, const char *, int, int, void *,
+  void (*)(sqlite3_context*,int,sqlite3_value **),
+  void (*)(sqlite3_context*,int,sqlite3_value **),
+  void (*)(sqlite3_context*),
+  void (*)(sqlite3_context*),
+  void (*)(sqlite3_context*,int,sqlite3_value **),
+  FuncDestructor *pDestructor
+);
+void sqlite3NoopDestructor(void*);
+void sqlite3OomFault(sqlite3*);
+void sqlite3OomClear(sqlite3*);
+int sqlite3ApiExit(sqlite3 *db, int);
+int sqlite3OpenTempDatabase(Parse *);
+
+void sqlite3StrAccumInit(StrAccum*, sqlite3*, char*, int, int);
+char *sqlite3StrAccumFinish(StrAccum*);
+void sqlite3SelectDestInit(SelectDest*,int,int);
+Expr *sqlite3CreateColumnExpr(sqlite3 *, SrcList *, int, int);
+
+void sqlite3BackupRestart(sqlite3_backup *);
+void sqlite3BackupUpdate(sqlite3_backup *, Pgno, const u8 *);
+
+
+int sqlite3ExprCheckIN(Parse*, Expr*);
+# 4400 "src/sqliteInt.h"
+  void *sqlite3ParserAlloc(void*(*)(u64), Parse*);
+  void sqlite3ParserFree(void*, void(*)(void*));
+
+void sqlite3Parser(void*, int, Token);
+int sqlite3ParserFallback(int);
+
+
+
+
+void sqlite3AutoLoadExtensions(sqlite3*);
+
+  void sqlite3CloseExtensions(sqlite3*);
+
+
+
+
+
+  void sqlite3TableLock(Parse *, int, int, u8, const char *);
+# 4438 "src/sqliteInt.h"
+   void sqlite3VtabClear(sqlite3 *db, Table*);
+   void sqlite3VtabDisconnect(sqlite3 *db, Table *p);
+   int sqlite3VtabSync(sqlite3 *db, Vdbe*);
+   int sqlite3VtabRollback(sqlite3 *db);
+   int sqlite3VtabCommit(sqlite3 *db);
+   void sqlite3VtabLock(VTable *);
+   void sqlite3VtabUnlock(VTable *);
+   void sqlite3VtabUnlockList(sqlite3*);
+   int sqlite3VtabSavepoint(sqlite3 *, int, int);
+   void sqlite3VtabImportErrmsg(Vdbe*, sqlite3_vtab*);
+   VTable *sqlite3GetVTable(sqlite3*, Table*);
+   Module *sqlite3VtabCreateModule(
+     sqlite3*,
+     const char*,
+     const sqlite3_module*,
+     void*,
+     void(*)(void*)
+   );
+
+
+int sqlite3VtabEponymousTableInit(Parse*,Module*);
+void sqlite3VtabEponymousTableClear(sqlite3*,Module*);
+void sqlite3VtabMakeWritable(Parse*,Table*);
+void sqlite3VtabBeginParse(Parse*, Token*, Token*, Token*, int);
+void sqlite3VtabFinishParse(Parse*, Token*);
+void sqlite3VtabArgInit(Parse*);
+void sqlite3VtabArgExtend(Parse*, Token*);
+int sqlite3VtabCallCreate(sqlite3*, int, const char *, char **);
+int sqlite3VtabCallConnect(Parse*, Table*);
+int sqlite3VtabCallDestroy(sqlite3*, int, const char *);
+int sqlite3VtabBegin(sqlite3 *, VTable *);
+FuncDef *sqlite3VtabOverloadFunction(sqlite3 *,FuncDef*, int nArg, Expr*);
+sqlite3_int64 sqlite3StmtCurrentTime(sqlite3_context*);
+int sqlite3VdbeParameterIndex(Vdbe*, const char*, int);
+int sqlite3TransferBindings(sqlite3_stmt *, sqlite3_stmt *);
+void sqlite3ParserReset(Parse*);
+
+
+
+int sqlite3Reprepare(Vdbe*);
+void sqlite3ExprListCheckLength(Parse*, ExprList*, const char*);
+CollSeq *sqlite3BinaryCompareCollSeq(Parse *, Expr *, Expr *);
+int sqlite3TempInMemory(const sqlite3*);
+const char *sqlite3JournalModename(int);
+
+  int sqlite3Checkpoint(sqlite3*, int, int, int*, int*);
+  int sqlite3WalDefaultHook(void*,sqlite3*,const char*,int);
+
+
+  With *sqlite3WithAdd(Parse*,With*,Token*,ExprList*,Select*);
+  void sqlite3WithDelete(sqlite3*,With*);
+  void sqlite3WithPush(Parse*, With*, u8);
+
+
+
+
+
+  Upsert *sqlite3UpsertNew(sqlite3*,ExprList*,Expr*,ExprList*,Expr*);
+  void sqlite3UpsertDelete(sqlite3*,Upsert*);
+  Upsert *sqlite3UpsertDup(sqlite3*,Upsert*);
+  int sqlite3UpsertAnalyzeTarget(Parse*,SrcList*,Upsert*);
+  void sqlite3UpsertDoUpdate(Parse*,Upsert*,Table*,Index*,int);
+# 4515 "src/sqliteInt.h"
+  void sqlite3FkCheck(Parse*, Table*, int, int, int*, int);
+  void sqlite3FkDropTable(Parse*, SrcList *, Table*);
+  void sqlite3FkActions(Parse*, Table*, ExprList*, int, int*, int);
+  int sqlite3FkRequired(Parse*, Table*, int*, int);
+  u32 sqlite3FkOldmask(Parse*, Table*);
+  FKey *sqlite3FkReferences(Table *);
+# 4530 "src/sqliteInt.h"
+  void sqlite3FkDelete(sqlite3 *, Table*);
+  int sqlite3FkLocateIndex(Parse*,Table*,FKey*,Index**,int**);
+# 4550 "src/sqliteInt.h"
+  void sqlite3BeginBenignMalloc(void);
+  void sqlite3EndBenignMalloc(void);
+# 4571 "src/sqliteInt.h"
+int sqlite3FindInIndex(Parse *, Expr *, u32, int*, int*, int*);
+
+int sqlite3JournalOpen(sqlite3_vfs *, const char *, sqlite3_file *, int, int);
+int sqlite3JournalSize(sqlite3_vfs *);
+
+
+
+
+
+int sqlite3JournalIsInMemory(sqlite3_file *p);
+void sqlite3MemJournalOpen(sqlite3_file *);
+
+void sqlite3ExprSetHeightAndFlags(Parse *pParse, Expr *p);
+
+  int sqlite3SelectExprHeight(Select *);
+  int sqlite3ExprCheckHeight(Parse*, int);
+
+
+
+
+
+u32 sqlite3Get4byte(const u8*);
+void sqlite3Put4byte(u8*, u32);
+# 4671 "src/sqliteInt.h"
+int sqlite3ThreadCreate(SQLiteThread**,void*(*)(void*),void*);
+int sqlite3ThreadJoin(SQLiteThread*, void**);
+# 4682 "src/sqliteInt.h"
+int sqlite3ExprVectorSize(Expr *pExpr);
+int sqlite3ExprIsVector(Expr *pExpr);
+Expr *sqlite3VectorFieldSubexpr(Expr*, int);
+Expr *sqlite3ExprForVectorField(Parse*,Expr*,int);
+void sqlite3VectorErrorMsg(Parse*, Expr*);
+
+
+const char **sqlite3CompileOptions(int *pnOpt);
+# 217 "src/btreeInt.h" 2
+# 232 "src/btreeInt.h"
+typedef struct MemPage MemPage;
+typedef struct BtLock BtLock;
+typedef struct CellInfo CellInfo;
+# 273 "src/btreeInt.h"
+struct MemPage {
+  u8 isInit;
+  u8 bBusy;
+  u8 intKey;
+  u8 intKeyLeaf;
+  Pgno pgno;
+
+
+  u8 leaf;
+  u8 hdrOffset;
+  u8 childPtrSize;
+  u8 max1bytePayload;
+  u8 nOverflow;
+  u16 maxLocal;
+  u16 minLocal;
+  u16 cellOffset;
+  int nFree;
+  u16 nCell;
+  u16 maskPage;
+  u16 aiOvfl[4];
+
+  u8 *apOvfl[4];
+  BtShared *pBt;
+  u8 *aData;
+  u8 *aDataEnd;
+  u8 *aCellIdx;
+  u8 *aDataOfst;
+  DbPage *pDbPage;
+  u16 (*xCellSize)(MemPage*,u8*);
+  void (*xParseCell)(MemPage*,u8*,CellInfo*);
+};
+# 312 "src/btreeInt.h"
+struct BtLock {
+  Btree *pBtree;
+  Pgno iTable;
+  u8 eLock;
+  BtLock *pNext;
+};
+# 344 "src/btreeInt.h"
+struct Btree {
+  sqlite3 *db;
+  BtShared *pBt;
+  u8 inTrans;
+  u8 sharable;
+  u8 locked;
+  u8 hasIncrblobCur;
+  int wantToLock;
+  int nBackup;
+  u32 iDataVersion;
+  Btree *pNext;
+  Btree *pPrev;
+
+  BtLock lock;
+
+};
+# 407 "src/btreeInt.h"
+struct BtShared {
+  Pager *pPager;
+  sqlite3 *db;
+  BtCursor *pCursor;
+  MemPage *pPage1;
+  u8 openFlags;
+
+  u8 autoVacuum;
+  u8 incrVacuum;
+  u8 bDoTruncate;
+
+  u8 inTransaction;
+  u8 max1bytePayload;
+
+
+
+  u16 btsFlags;
+  u16 maxLocal;
+  u16 minLocal;
+  u16 maxLeaf;
+  u16 minLeaf;
+  u32 pageSize;
+  u32 usableSize;
+  int nTransaction;
+  u32 nPage;
+  void *pSchema;
+  void (*xFreeSchema)(void*);
+  sqlite3_mutex *mutex;
+  Bitvec *pHasContent;
+
+  int nRef;
+  BtShared *pNext;
+  BtLock *pLock;
+  Btree *pWriter;
+
+  u8 *pTmpSpace;
+};
+# 463 "src/btreeInt.h"
+struct CellInfo {
+  i64 nKey;
+  u8 *pPayload;
+  u32 nPayload;
+  u16 nLocal;
+  u16 nSize;
+};
+# 508 "src/btreeInt.h"
+struct BtCursor {
+  u8 eState;
+  u8 curFlags;
+  u8 curPagerFlags;
+  u8 hints;
+  int skipNext;
+
+  Btree *pBtree;
+  Pgno *aOverflow;
+  void *pKey;
+
+
+
+
+  BtShared *pBt;
+  BtCursor *pNext;
+  CellInfo info;
+  i64 nKey;
+  Pgno pgnoRoot;
+  i8 iPage;
+  u8 curIntKey;
+  u16 ix;
+  u16 aiIdx[20 -1];
+  struct KeyInfo *pKeyInfo;
+  MemPage *pPage;
+  MemPage *apPage[20 -1];
+};
+# 675 "src/btreeInt.h"
+typedef struct IntegrityCk IntegrityCk;
+struct IntegrityCk {
+  BtShared *pBt;
+  Pager *pPager;
+  u8 *aPgRef;
+  Pgno nPage;
+  int mxErr;
+  int nErr;
+  int mallocFailed;
+  const char *zPfx;
+  int v1, v2;
+  StrAccum errMsg;
+  u32 *heap;
+};
+# 17 "src/btree.c" 2
+
+
+
+
+
+static const char zMagicHeader[] = "SQLite format 3";
+# 77 "src/btree.c"
+static BtShared * sqlite3SharedCacheList = 0;
+# 89 "src/btree.c"
+int sqlite3_enable_shared_cache(int enable){
+  sqlite3Config.sharedCacheEnabled = enable;
+  return 0;
+}
+# 275 "src/btree.c"
+static int querySharedCacheTableLock(Btree *p, Pgno iTab, u8 eLock){
+  BtShared *pBt = p->pBt;
+  BtLock *pIter;
+
+  assert( sqlite3BtreeHoldsMutex(p) );
+  assert( eLock==1 || eLock==2 );
+  assert( p->db!=0 );
+  assert( !(p->db->flags&0x00000400)||eLock==2||iTab==1 );
+
+
+
+
+
+  assert( eLock==1 || (p==pBt->pWriter && p->inTrans==2) );
+  assert( eLock==1 || pBt->inTransaction==2 );
+
+
+  if( !p->sharable ){
+    return 0;
+  }
+
+
+
+
+  if( pBt->pWriter!=p && (pBt->btsFlags & 0x0040)!=0 ){
+    ;
+    return (6 | (1<<8));
+  }
+
+  for(pIter=pBt->pLock; pIter; pIter=pIter->pNext){
+# 314 "src/btree.c"
+    assert( pIter->eLock==1 || pIter->eLock==2 );
+    assert( eLock==1 || pIter->pBtree==p || pIter->eLock==1);
+    if( pIter->pBtree!=p && pIter->iTable==iTab && pIter->eLock!=eLock ){
+      ;
+      if( eLock==2 ){
+        assert( p==pBt->pWriter );
+        pBt->btsFlags |= 0x0080;
+      }
+      return (6 | (1<<8));
+    }
+  }
+  return 0;
+}
+# 347 "src/btree.c"
+static int setSharedCacheTableLock(Btree *p, Pgno iTable, u8 eLock){
+  BtShared *pBt = p->pBt;
+  BtLock *pLock = 0;
+  BtLock *pIter;
+
+  assert( sqlite3BtreeHoldsMutex(p) );
+  assert( eLock==1 || eLock==2 );
+  assert( p->db!=0 );
+
+
+
+
+
+  assert( 0==(p->db->flags&0x00000400) || eLock==2 );
+
+
+
+  assert( p->sharable );
+  assert( 0==querySharedCacheTableLock(p, iTable, eLock) );
+
+
+  for(pIter=pBt->pLock; pIter; pIter=pIter->pNext){
+    if( pIter->iTable==iTable && pIter->pBtree==p ){
+      pLock = pIter;
+      break;
+    }
+  }
+
+
+
+
+  if( !pLock ){
+    pLock = (BtLock *)sqlite3MallocZero(sizeof(BtLock));
+    if( !pLock ){
+      return 7;
+    }
+    pLock->iTable = iTable;
+    pLock->pBtree = p;
+    pLock->pNext = pBt->pLock;
+    pBt->pLock = pLock;
+  }
+
+
+
+
+
+  assert( 2>1 );
+  if( eLock>pLock->eLock ){
+    pLock->eLock = eLock;
+  }
+
+  return 0;
+}
+# 411 "src/btree.c"
+static void clearAllSharedCacheTableLocks(Btree *p){
+  BtShared *pBt = p->pBt;
+  BtLock **ppIter = &pBt->pLock;
+
+  assert( sqlite3BtreeHoldsMutex(p) );
+  assert( p->sharable || 0==*ppIter );
+  assert( p->inTrans>0 );
+
+  while( *ppIter ){
+    BtLock *pLock = *ppIter;
+    assert( (pBt->btsFlags & 0x0040)==0 || pBt->pWriter==pLock->pBtree );
+    assert( pLock->pBtree->inTrans>=pLock->eLock );
+    if( pLock->pBtree==p ){
+      *ppIter = pLock->pNext;
+      assert( pLock->iTable!=1 || pLock==&p->lock );
+      if( pLock->iTable!=1 ){
+        sqlite3_free(pLock);
+      }
+    }else{
+      ppIter = &pLock->pNext;
+    }
+  }
+
+  assert( (pBt->btsFlags & 0x0080)==0 || pBt->pWriter );
+  if( pBt->pWriter==p ){
+    pBt->pWriter = 0;
+    pBt->btsFlags &= ~(0x0040|0x0080);
+  }else if( pBt->nTransaction==2 ){
+# 448 "src/btree.c"
+    pBt->btsFlags &= ~0x0080;
+  }
+}
+
+
+
+
+static void downgradeAllSharedCacheTableLocks(Btree *p){
+  BtShared *pBt = p->pBt;
+  if( pBt->pWriter==p ){
+    BtLock *pLock;
+    pBt->pWriter = 0;
+    pBt->btsFlags &= ~(0x0040|0x0080);
+    for(pLock=pBt->pLock; pLock; pLock=pLock->pNext){
+      assert( pLock->eLock==1 || pLock->pBtree==p );
+      pLock->eLock = 1;
+    }
+  }
+}
+
+
+
+static void releasePage(MemPage *pPage);
+static void releasePageOne(MemPage *pPage);
+static void releasePageNotNull(MemPage *pPage);
+# 508 "src/btree.c"
+static void invalidateAllOverflowCache(BtShared *pBt){
+  BtCursor *p;
+  assert( sqlite3_mutex_held(pBt->mutex) );
+  for(p=pBt->pCursor; p; p=p->pNext){
+    (p->curFlags &= ~0x04);
+  }
+}
+# 530 "src/btree.c"
+static void invalidateIncrblobCursors(
+  Btree *pBtree,
+  Pgno pgnoRoot,
+  i64 iRow,
+  int isClearTable
+){
+  BtCursor *p;
+  if( pBtree->hasIncrblobCur==0 ) return;
+  assert( sqlite3BtreeHoldsMutex(pBtree) );
+  pBtree->hasIncrblobCur = 0;
+  for(p=pBtree->pBt->pCursor; p; p=p->pNext){
+    if( (p->curFlags & 0x10)!=0 ){
+      pBtree->hasIncrblobCur = 1;
+      if( p->pgnoRoot==pgnoRoot && (isClearTable || p->info.nKey==iRow) ){
+        p->eState = 1;
+      }
+    }
+  }
+}
+# 590 "src/btree.c"
+static int btreeSetHasContent(BtShared *pBt, Pgno pgno){
+  int rc = 0;
+  if( !pBt->pHasContent ){
+    assert( pgno<=pBt->nPage );
+    pBt->pHasContent = sqlite3BitvecCreate(pBt->nPage);
+    if( !pBt->pHasContent ){
+      rc = 7;
+    }
+  }
+  if( rc==0 && pgno<=sqlite3BitvecSize(pBt->pHasContent) ){
+    rc = sqlite3BitvecSet(pBt->pHasContent, pgno);
+  }
+  return rc;
+}
+# 612 "src/btree.c"
+static int btreeGetHasContent(BtShared *pBt, Pgno pgno){
+  Bitvec *p = pBt->pHasContent;
+  return (p && (pgno>sqlite3BitvecSize(p) || sqlite3BitvecTest(p, pgno)));
+}
+
+
+
+
+
+static void btreeClearHasContent(BtShared *pBt){
+  sqlite3BitvecDestroy(pBt->pHasContent);
+  pBt->pHasContent = 0;
+}
+
+
+
+
+static void btreeReleaseAllCursorPages(BtCursor *pCur){
+  int i;
+  if( pCur->iPage>=0 ){
+    for(i=0; i<pCur->iPage; i++){
+      releasePageNotNull(pCur->apPage[i]);
+    }
+    releasePageNotNull(pCur->pPage);
+    pCur->iPage = -1;
+  }
+}
+# 653 "src/btree.c"
+static int saveCursorKey(BtCursor *pCur){
+  int rc = 0;
+  assert( 0==pCur->eState );
+  assert( 0==pCur->pKey );
+  assert( cursorHoldsMutex(pCur) );
+
+  if( pCur->curIntKey ){
+
+    pCur->nKey = sqlite3BtreeIntegerKey(pCur);
+  }else{
+
+
+
+
+
+
+    void *pKey;
+    pCur->nKey = sqlite3BtreePayloadSize(pCur);
+    pKey = sqlite3Malloc( pCur->nKey + 9 + 8 );
+    if( pKey ){
+      rc = sqlite3BtreePayload(pCur, 0, (int)pCur->nKey, pKey);
+      if( rc==0 ){
+        memset(((u8*)pKey)+pCur->nKey, 0, 9+8);
+        pCur->pKey = pKey;
+      }else{
+        sqlite3_free(pKey);
+      }
+    }else{
+      rc = 7;
+    }
+  }
+  assert( !pCur->curIntKey || !pCur->pKey );
+  return rc;
+}
+# 695 "src/btree.c"
+static int saveCursorPosition(BtCursor *pCur){
+  int rc;
+
+  assert( 0==pCur->eState || 2==pCur->eState );
+  assert( 0==pCur->pKey );
+  assert( cursorHoldsMutex(pCur) );
+
+  if( pCur->eState==2 ){
+    pCur->eState = 0;
+  }else{
+    pCur->skipNext = 0;
+  }
+
+  rc = saveCursorKey(pCur);
+  if( rc==0 ){
+    btreeReleaseAllCursorPages(pCur);
+    pCur->eState = 3;
+  }
+
+  pCur->curFlags &= ~(0x02|0x04|0x08);
+  return rc;
+}
+
+
+static int saveCursorsOnList(BtCursor*,Pgno,BtCursor*);
+# 742 "src/btree.c"
+static int saveAllCursors(BtShared *pBt, Pgno iRoot, BtCursor *pExcept){
+  BtCursor *p;
+  assert( sqlite3_mutex_held(pBt->mutex) );
+  assert( pExcept==0 || pExcept->pBt==pBt );
+  for(p=pBt->pCursor; p; p=p->pNext){
+    if( p!=pExcept && (0==iRoot || p->pgnoRoot==iRoot) ) break;
+  }
+  if( p ) return saveCursorsOnList(p, iRoot, pExcept);
+  if( pExcept ) pExcept->curFlags &= ~0x20;
+  return 0;
+}
+
+
+
+
+
+
+static int saveCursorsOnList(
+  BtCursor *p,
+  Pgno iRoot,
+  BtCursor *pExcept
+){
+  do{
+    if( p!=pExcept && (0==iRoot || p->pgnoRoot==iRoot) ){
+      if( p->eState==0 || p->eState==2 ){
+        int rc = saveCursorPosition(p);
+        if( 0!=rc ){
+          return rc;
+        }
+      }else{
+        ;
+        btreeReleaseAllCursorPages(p);
+      }
+    }
+    p = p->pNext;
+  }while( p );
+  return 0;
+}
+
+
+
+
+void sqlite3BtreeClearCursor(BtCursor *pCur){
+  assert( cursorHoldsMutex(pCur) );
+  sqlite3_free(pCur->pKey);
+  pCur->pKey = 0;
+  pCur->eState = 1;
+}
+
+
+
+
+
+
+static int btreeMoveto(
+  BtCursor *pCur,
+  const void *pKey,
+  i64 nKey,
+  int bias,
+  int *pRes
+){
+  int rc;
+  UnpackedRecord *pIdxKey;
+
+  if( pKey ){
+    KeyInfo *pKeyInfo = pCur->pKeyInfo;
+    assert( nKey==(i64)(int)nKey );
+    pIdxKey = sqlite3VdbeAllocUnpackedRecord(pKeyInfo);
+    if( pIdxKey==0 ) return 7;
+    sqlite3VdbeRecordUnpack(pKeyInfo, (int)nKey, pKey, pIdxKey);
+    if( pIdxKey->nField==0 || pIdxKey->nField>pKeyInfo->nAllField ){
+      rc = sqlite3CorruptError(813);
+      goto moveto_done;
+    }
+  }else{
+    pIdxKey = 0;
+  }
+  rc = sqlite3BtreeMovetoUnpacked(pCur, pIdxKey, nKey, bias, pRes);
+moveto_done:
+  if( pIdxKey ){
+    sqlite3DbFree(pCur->pKeyInfo->db, pIdxKey);
+  }
+  return rc;
+}
+# 834 "src/btree.c"
+static int btreeRestoreCursorPosition(BtCursor *pCur){
+  int rc;
+  int skipNext = 0;
+  assert( cursorOwnsBtShared(pCur) );
+  assert( pCur->eState>=3 );
+  if( pCur->eState==4 ){
+    return pCur->skipNext;
+  }
+  pCur->eState = 1;
+  if( sqlite3FaultSim(410) ){
+    rc = 10;
+  }else{
+    rc = btreeMoveto(pCur, pCur->pKey, pCur->nKey, 0, &skipNext);
+  }
+  if( rc==0 ){
+    sqlite3_free(pCur->pKey);
+    pCur->pKey = 0;
+    assert( pCur->eState==0 || pCur->eState==1 );
+    if( skipNext ) pCur->skipNext = skipNext;
+    if( pCur->skipNext && pCur->eState==0 ){
+      pCur->eState = 2;
+    }
+  }
+  return rc;
+}
+# 877 "src/btree.c"
+int sqlite3BtreeCursorHasMoved(BtCursor *pCur){
+  assert( ((((char*)(pCur) - (char*)0)&7)==0)
+       || pCur==sqlite3BtreeFakeValidCursor() );
+  assert( ((int)((char*)&((BtCursor*)0)->eState))==0 );
+  assert( sizeof(pCur->eState)==1 );
+  return 0 != *(u8*)pCur;
+}
+
+
+
+
+
+
+BtCursor *sqlite3BtreeFakeValidCursor(void){
+  static u8 fakeCursor = 0;
+  assert( ((int)((char*)&((BtCursor*)0)->eState))==0 );
+  return (BtCursor*)&fakeCursor;
+}
+# 909 "src/btree.c"
+int sqlite3BtreeCursorRestore(BtCursor *pCur, int *pDifferentRow){
+  int rc;
+
+  assert( pCur!=0 );
+  assert( pCur->eState!=0 );
+  rc = (pCur->eState>=3 ? btreeRestoreCursorPosition(pCur) : 0);
+  if( rc ){
+    *pDifferentRow = 1;
+    return rc;
+  }
+  if( pCur->eState!=0 ){
+    *pDifferentRow = 1;
+  }else{
+    *pDifferentRow = 0;
+  }
+  return 0;
+}
+# 941 "src/btree.c"
+void sqlite3BtreeCursorHintFlags(BtCursor *pCur, unsigned x){
+  assert( x==0x00000002 || x==0x00000001 || x==0 );
+  pCur->hints = x;
+}
+# 957 "src/btree.c"
+static Pgno ptrmapPageno(BtShared *pBt, Pgno pgno){
+  int nPagesPerMapPage;
+  Pgno iPtrMap, ret;
+  assert( sqlite3_mutex_held(pBt->mutex) );
+  if( pgno<2 ) return 0;
+  nPagesPerMapPage = (pBt->usableSize/5)+1;
+  iPtrMap = (pgno-2)/nPagesPerMapPage;
+  ret = (iPtrMap*nPagesPerMapPage) + 2;
+  if( ret==((Pgno)((sqlite3PendingByte/((pBt)->pageSize))+1)) ){
+    ret++;
+  }
+  return ret;
+}
+# 981 "src/btree.c"
+static void ptrmapPut(BtShared *pBt, Pgno key, u8 eType, Pgno parent, int *pRC){
+  DbPage *pDbPage;
+  u8 *pPtrmap;
+  Pgno iPtrmap;
+  int offset;
+  int rc;
+
+  if( *pRC ) return;
+
+  assert( sqlite3_mutex_held(pBt->mutex) );
+
+  assert( 0==(ptrmapPageno((pBt), (((Pgno)((sqlite3PendingByte/((pBt)->pageSize))+1))))==(((Pgno)((sqlite3PendingByte/((pBt)->pageSize))+1)))) );
+
+  assert( pBt->autoVacuum );
+  if( key==0 ){
+    *pRC = sqlite3CorruptError(996);
+    return;
+  }
+  iPtrmap = ptrmapPageno(pBt, key);
+  rc = sqlite3PagerGet(pBt->pPager, iPtrmap, &pDbPage, 0);
+  if( rc!=0 ){
+    *pRC = rc;
+    return;
+  }
+  if( ((char*)sqlite3PagerGetExtra(pDbPage))[0]!=0 ){
+
+
+
+    *pRC = sqlite3CorruptError(1009);
+    goto ptrmap_exit;
+  }
+  offset = (5*(key-iPtrmap-1));
+  if( offset<0 ){
+    *pRC = sqlite3CorruptError(1014);
+    goto ptrmap_exit;
+  }
+  assert( offset <= (int)pBt->usableSize-5 );
+  pPtrmap = (u8 *)sqlite3PagerGetData(pDbPage);
+
+  if( eType!=pPtrmap[offset] || sqlite3Get4byte(&pPtrmap[offset+1])!=parent ){
+    ;
+    *pRC= rc = sqlite3PagerWrite(pDbPage);
+    if( rc==0 ){
+      pPtrmap[offset] = eType;
+      sqlite3Put4byte(&pPtrmap[offset+1], parent);
+    }
+  }
+
+ptrmap_exit:
+  sqlite3PagerUnref(pDbPage);
+}
+# 1040 "src/btree.c"
+static int ptrmapGet(BtShared *pBt, Pgno key, u8 *pEType, Pgno *pPgno){
+  DbPage *pDbPage;
+  int iPtrmap;
+  u8 *pPtrmap;
+  int offset;
+  int rc;
+
+  assert( sqlite3_mutex_held(pBt->mutex) );
+
+  iPtrmap = ptrmapPageno(pBt, key);
+  rc = sqlite3PagerGet(pBt->pPager, iPtrmap, &pDbPage, 0);
+  if( rc!=0 ){
+    return rc;
+  }
+  pPtrmap = (u8 *)sqlite3PagerGetData(pDbPage);
+
+  offset = (5*(key-iPtrmap-1));
+  if( offset<0 ){
+    sqlite3PagerUnref(pDbPage);
+    return sqlite3CorruptError(1059);
+  }
+  assert( offset <= (int)pBt->usableSize-5 );
+  assert( pEType!=0 );
+  *pEType = pPtrmap[offset];
+  if( pPgno ) *pPgno = sqlite3Get4byte(&pPtrmap[offset+1]);
+
+  sqlite3PagerUnref(pDbPage);
+  if( *pEType<1 || *pEType>5 ) return sqlite3CorruptError(1067);
+  return 0;
+}
+# 1099 "src/btree.c"
+static void btreeParseCellAdjustSizeForOverflow(
+  MemPage *pPage,
+  u8 *pCell,
+  CellInfo *pInfo
+){
+# 1113 "src/btree.c"
+  int minLocal;
+  int maxLocal;
+  int surplus;
+
+  minLocal = pPage->minLocal;
+  maxLocal = pPage->maxLocal;
+  surplus = minLocal + (pInfo->nPayload - minLocal)%(pPage->pBt->usableSize-4);
+  ;
+  ;
+  if( surplus <= maxLocal ){
+    pInfo->nLocal = (u16)surplus;
+  }else{
+    pInfo->nLocal = (u16)minLocal;
+  }
+  pInfo->nSize = (u16)(&pInfo->pPayload[pInfo->nLocal] - pCell) + 4;
+}
+# 1144 "src/btree.c"
+static void btreeParseCellPtrNoPayload(
+  MemPage *pPage,
+  u8 *pCell,
+  CellInfo *pInfo
+){
+  assert( sqlite3_mutex_held(pPage->pBt->mutex) );
+  assert( pPage->leaf==0 );
+  assert( pPage->childPtrSize==4 );
+
+  (void)(pPage);
+
+  pInfo->nSize = 4 + sqlite3GetVarint(&pCell[4], (u64*)&pInfo->nKey);
+  pInfo->nPayload = 0;
+  pInfo->nLocal = 0;
+  pInfo->pPayload = 0;
+  return;
+}
+static void btreeParseCellPtr(
+  MemPage *pPage,
+  u8 *pCell,
+  CellInfo *pInfo
+){
+  u8 *pIter;
+  u32 nPayload;
+  u64 iKey;
+
+  assert( sqlite3_mutex_held(pPage->pBt->mutex) );
+  assert( pPage->leaf==0 || pPage->leaf==1 );
+  assert( pPage->intKeyLeaf );
+  assert( pPage->childPtrSize==0 );
+  pIter = pCell;
+
+
+
+
+
+
+
+  nPayload = *pIter;
+  if( nPayload>=0x80 ){
+    u8 *pEnd = &pIter[8];
+    nPayload &= 0x7f;
+    do{
+      nPayload = (nPayload<<7) | (*++pIter & 0x7f);
+    }while( (*pIter)>=0x80 && pIter<pEnd );
+  }
+  pIter++;
+
+
+
+
+
+
+
+  iKey = *pIter;
+  if( iKey>=0x80 ){
+    u8 *pEnd = &pIter[7];
+    iKey &= 0x7f;
+    while(1){
+      iKey = (iKey<<7) | (*++pIter & 0x7f);
+      if( (*pIter)<0x80 ) break;
+      if( pIter>=pEnd ){
+        iKey = (iKey<<8) | *++pIter;
+        break;
+      }
+    }
+  }
+  pIter++;
+
+  pInfo->nKey = *(i64*)&iKey;
+  pInfo->nPayload = nPayload;
+  pInfo->pPayload = pIter;
+  ;
+  ;
+  if( nPayload<=pPage->maxLocal ){
+
+
+
+    pInfo->nSize = nPayload + (u16)(pIter - pCell);
+    if( pInfo->nSize<4 ) pInfo->nSize = 4;
+    pInfo->nLocal = (u16)nPayload;
+  }else{
+    btreeParseCellAdjustSizeForOverflow(pPage, pCell, pInfo);
+  }
+}
+static void btreeParseCellPtrIndex(
+  MemPage *pPage,
+  u8 *pCell,
+  CellInfo *pInfo
+){
+  u8 *pIter;
+  u32 nPayload;
+
+  assert( sqlite3_mutex_held(pPage->pBt->mutex) );
+  assert( pPage->leaf==0 || pPage->leaf==1 );
+  assert( pPage->intKeyLeaf==0 );
+  pIter = pCell + pPage->childPtrSize;
+  nPayload = *pIter;
+  if( nPayload>=0x80 ){
+    u8 *pEnd = &pIter[8];
+    nPayload &= 0x7f;
+    do{
+      nPayload = (nPayload<<7) | (*++pIter & 0x7f);
+    }while( *(pIter)>=0x80 && pIter<pEnd );
+  }
+  pIter++;
+  pInfo->nKey = nPayload;
+  pInfo->nPayload = nPayload;
+  pInfo->pPayload = pIter;
+  ;
+  ;
+  if( nPayload<=pPage->maxLocal ){
+
+
+
+    pInfo->nSize = nPayload + (u16)(pIter - pCell);
+    if( pInfo->nSize<4 ) pInfo->nSize = 4;
+    pInfo->nLocal = (u16)nPayload;
+  }else{
+    btreeParseCellAdjustSizeForOverflow(pPage, pCell, pInfo);
+  }
+}
+static void btreeParseCell(
+  MemPage *pPage,
+  int iCell,
+  CellInfo *pInfo
+){
+  pPage->xParseCell(pPage, ((pPage)->aData + ((pPage)->maskPage & __builtin_bswap16(*(u16*)(&(pPage)->aCellIdx[2*(iCell)])))), pInfo);
+}
+# 1286 "src/btree.c"
+static u16 cellSizePtr(MemPage *pPage, u8 *pCell){
+  u8 *pIter = pCell + pPage->childPtrSize;
+  u8 *pEnd;
+  u32 nSize;
+# 1300 "src/btree.c"
+  nSize = *pIter;
+  if( nSize>=0x80 ){
+    pEnd = &pIter[8];
+    nSize &= 0x7f;
+    do{
+      nSize = (nSize<<7) | (*++pIter & 0x7f);
+    }while( *(pIter)>=0x80 && pIter<pEnd );
+  }
+  pIter++;
+  if( pPage->intKey ){
+
+
+
+    pEnd = &pIter[9];
+    while( (*pIter++)&0x80 && pIter<pEnd );
+  }
+  ;
+  ;
+  if( nSize<=pPage->maxLocal ){
+    nSize += (u32)(pIter - pCell);
+    if( nSize<4 ) nSize = 4;
+  }else{
+    int minLocal = pPage->minLocal;
+    nSize = minLocal + (nSize - minLocal) % (pPage->pBt->usableSize - 4);
+    ;
+    ;
+    if( nSize>pPage->maxLocal ){
+      nSize = minLocal;
+    }
+    nSize += 4 + (u16)(pIter - pCell);
+  }
+  assert( nSize==debuginfo.nSize || (sqlite3Config.neverCorrupt==0) );
+  return (u16)nSize;
+}
+static u16 cellSizePtrNoPayload(MemPage *pPage, u8 *pCell){
+  u8 *pIter = pCell + 4;
+  u8 *pEnd;
+# 1346 "src/btree.c"
+  (void)(pPage);
+
+
+  assert( pPage->childPtrSize==4 );
+  pEnd = pIter + 9;
+  while( (*pIter++)&0x80 && pIter<pEnd );
+  assert( debuginfo.nSize==(u16)(pIter - pCell) || (sqlite3Config.neverCorrupt==0) );
+  return (u16)(pIter - pCell);
+}
+# 1372 "src/btree.c"
+static void ptrmapPutOvflPtr(MemPage *pPage, MemPage *pSrc, u8 *pCell,int *pRC){
+  CellInfo info;
+  if( *pRC ) return;
+  assert( pCell!=0 );
+  pPage->xParseCell(pPage, pCell, &info);
+  if( info.nLocal<info.nPayload ){
+    Pgno ovfl;
+    if( (((uptr)(pSrc->aDataEnd)>=(uptr)(pCell))&&((uptr)(pSrc->aDataEnd)<(uptr)(pCell+info.nLocal))) ){
+      ;
+      *pRC = sqlite3CorruptError(1381);
+      return;
+    }
+    ovfl = sqlite3Get4byte(&pCell[info.nSize-4]);
+    ptrmapPut(pPage->pBt, ovfl, 3, pPage->pgno, pRC);
+  }
+}
+# 1403 "src/btree.c"
+static int defragmentPage(MemPage *pPage, int nMaxFrag){
+  int i;
+  int pc;
+  int hdr;
+  int size;
+  int usableSize;
+  int cellOffset;
+  int cbrk;
+  int nCell;
+  unsigned char *data;
+  unsigned char *temp;
+  unsigned char *src;
+  int iCellFirst;
+  int iCellLast;
+
+  assert( sqlite3PagerIswriteable(pPage->pDbPage) );
+  assert( pPage->pBt!=0 );
+  assert( pPage->pBt->usableSize <= 65536 );
+  assert( pPage->nOverflow==0 );
+  assert( sqlite3_mutex_held(pPage->pBt->mutex) );
+  temp = 0;
+  src = data = pPage->aData;
+  hdr = pPage->hdrOffset;
+  cellOffset = pPage->cellOffset;
+  nCell = pPage->nCell;
+  assert( nCell==((&data[hdr+3])[0]<<8 | (&data[hdr+3])[1]) || (sqlite3Config.neverCorrupt==0) );
+  iCellFirst = cellOffset + 2*nCell;
+  usableSize = pPage->pBt->usableSize;
+
+
+
+
+
+
+  if( (int)data[hdr+7]<=nMaxFrag ){
+    int iFree = ((&data[hdr+1])[0]<<8 | (&data[hdr+1])[1]);
+    if( iFree>usableSize-4 ) return sqlite3CorruptError(1439);
+    if( iFree ){
+      int iFree2 = ((&data[iFree])[0]<<8 | (&data[iFree])[1]);
+      if( iFree2>usableSize-4 ) return sqlite3CorruptError(1442);
+      if( 0==iFree2 || (data[iFree2]==0 && data[iFree2+1]==0) ){
+        u8 *pEnd = &data[cellOffset + nCell*2];
+        u8 *pAddr;
+        int sz2 = 0;
+        int sz = ((&data[iFree+2])[0]<<8 | (&data[iFree+2])[1]);
+        int top = ((&data[hdr+5])[0]<<8 | (&data[hdr+5])[1]);
+        if( top>=iFree ){
+          return sqlite3CorruptError(1450);
+        }
+        if( iFree2 ){
+          if( iFree+sz>iFree2 ) return sqlite3CorruptError(1453);
+          sz2 = ((&data[iFree2+2])[0]<<8 | (&data[iFree2+2])[1]);
+          if( iFree2+sz2 > usableSize ) return sqlite3CorruptError(1455);
+          memmove(&data[iFree+sz+sz2], &data[iFree+sz], iFree2-(iFree+sz));
+          sz += sz2;
+        }else if( iFree+sz>usableSize ){
+          return sqlite3CorruptError(1459);
+        }
+
+        cbrk = top+sz;
+        assert( cbrk+(iFree-top) <= usableSize );
+        memmove(&data[cbrk], &data[top], iFree-top);
+        for(pAddr=&data[cellOffset]; pAddr<pEnd; pAddr+=2){
+          pc = ((pAddr)[0]<<8 | (pAddr)[1]);
+          if( pc<iFree ){ ((pAddr)[0] = (u8)((pc+sz)>>8), (pAddr)[1] = (u8)(pc+sz)); }
+          else if( pc<iFree2 ){ ((pAddr)[0] = (u8)((pc+sz2)>>8), (pAddr)[1] = (u8)(pc+sz2)); }
+        }
+        goto defragment_out;
+      }
+    }
+  }
+
+  cbrk = usableSize;
+  iCellLast = usableSize - 4;
+  for(i=0; i<nCell; i++){
+    u8 *pAddr;
+    pAddr = &data[cellOffset + i*2];
+    pc = ((pAddr)[0]<<8 | (pAddr)[1]);
+    ;
+    ;
+
+
+
+    if( pc<iCellFirst || pc>iCellLast ){
+      return sqlite3CorruptError(1487);
+    }
+    assert( pc>=iCellFirst && pc<=iCellLast );
+    size = pPage->xCellSize(pPage, &src[pc]);
+    cbrk -= size;
+    if( cbrk<iCellFirst || pc+size>usableSize ){
+      return sqlite3CorruptError(1493);
+    }
+    assert( cbrk+size<=usableSize && cbrk>=iCellFirst );
+    ;
+    ;
+    ((pAddr)[0] = (u8)((cbrk)>>8), (pAddr)[1] = (u8)(cbrk));
+    if( temp==0 ){
+      int x;
+      if( cbrk==pc ) continue;
+      temp = sqlite3PagerTempSpace(pPage->pBt->pPager);
+      x = ((&data[hdr+5])[0]<<8 | (&data[hdr+5])[1]);
+      memcpy(&temp[x], &data[x], (cbrk+size) - x);
+      src = temp;
+    }
+    memcpy(&data[cbrk], &src[pc], size);
+  }
+  data[hdr+7] = 0;
+
+ defragment_out:
+  assert( pPage->nFree>=0 );
+  if( data[hdr+7]+cbrk-iCellFirst!=pPage->nFree ){
+    return sqlite3CorruptError(1514);
+  }
+  assert( cbrk>=iCellFirst );
+  ((&data[hdr+5])[0] = (u8)((cbrk)>>8), (&data[hdr+5])[1] = (u8)(cbrk));
+  data[hdr+1] = 0;
+  data[hdr+2] = 0;
+  memset(&data[iCellFirst], 0, cbrk-iCellFirst);
+  assert( sqlite3PagerIswriteable(pPage->pDbPage) );
+  return 0;
+}
+# 1539 "src/btree.c"
+static u8 *pageFindSlot(MemPage *pPg, int nByte, int *pRc){
+  const int hdr = pPg->hdrOffset;
+  u8 * const aData = pPg->aData;
+  int iAddr = hdr + 1;
+  int pc = ((&aData[iAddr])[0]<<8 | (&aData[iAddr])[1]);
+  int x;
+  int maxPC = pPg->pBt->usableSize - nByte;
+  int size;
+
+  assert( pc>0 );
+  while( pc<=maxPC ){
+
+
+
+    size = ((&aData[pc+2])[0]<<8 | (&aData[pc+2])[1]);
+    if( (x = size - nByte)>=0 ){
+      ;
+      ;
+      if( x<4 ){
+
+
+        if( aData[hdr+7]>57 ) return 0;
+
+
+
+        memcpy(&aData[iAddr], &aData[pc], 2);
+        aData[hdr+7] += (u8)x;
+      }else if( x+pc > maxPC ){
+
+        *pRc = sqlite3CorruptError(1568);
+        return 0;
+      }else{
+
+
+        ((&aData[pc+2])[0] = (u8)((x)>>8), (&aData[pc+2])[1] = (u8)(x));
+      }
+      return &aData[pc + x];
+    }
+    iAddr = pc;
+    pc = ((&aData[pc])[0]<<8 | (&aData[pc])[1]);
+    if( pc<=iAddr+size ){
+      if( pc ){
+
+        *pRc = sqlite3CorruptError(1582);
+      }
+      return 0;
+    }
+  }
+  if( pc>maxPC+nByte-4 ){
+
+    *pRc = sqlite3CorruptError(1589);
+  }
+  return 0;
+}
+# 1607 "src/btree.c"
+static int allocateSpace(MemPage *pPage, int nByte, int *pIdx){
+  const int hdr = pPage->hdrOffset;
+  u8 * const data = pPage->aData;
+  int top;
+  int rc = 0;
+  int gap;
+
+  assert( sqlite3PagerIswriteable(pPage->pDbPage) );
+  assert( pPage->pBt );
+  assert( sqlite3_mutex_held(pPage->pBt->mutex) );
+  assert( nByte>=0 );
+  assert( pPage->nFree>=nByte );
+  assert( pPage->nOverflow==0 );
+  assert( nByte < (int)(pPage->pBt->usableSize-8) );
+
+  assert( pPage->cellOffset == hdr + 12 - 4*pPage->leaf );
+  gap = pPage->cellOffset + 2*pPage->nCell;
+  assert( gap<=65536 );
+
+
+
+
+
+  top = ((&data[hdr+5])[0]<<8 | (&data[hdr+5])[1]);
+  assert( top<=(int)pPage->pBt->usableSize );
+  if( gap>top ){
+    if( top==0 && pPage->pBt->usableSize==65536 ){
+      top = 65536;
+    }else{
+      return sqlite3CorruptError(1636);
+    }
+  }
+
+
+
+
+
+  ;
+  ;
+  ;
+  if( (data[hdr+2] || data[hdr+1]) && gap+2<=top ){
+    u8 *pSpace = pageFindSlot(pPage, nByte, &rc);
+    if( pSpace ){
+      assert( pSpace>=data && (pSpace - data)<65536 );
+      *pIdx = (int)(pSpace - data);
+      return 0;
+    }else if( rc ){
+      return rc;
+    }
+  }
+
+
+
+
+  ;
+  if( gap+2+nByte>top ){
+    assert( pPage->nCell>0 || (sqlite3Config.neverCorrupt==0) );
+    assert( pPage->nFree>=0 );
+    rc = defragmentPage(pPage, ((4)<(pPage->nFree - (2+nByte))?(4):(pPage->nFree - (2+nByte))));
+    if( rc ) return rc;
+    top = (((((int)((&data[hdr+5])[0]<<8 | (&data[hdr+5])[1]))-1)&0xffff)+1);
+    assert( gap+2+nByte<=top );
+  }
+# 1678 "src/btree.c"
+  top -= nByte;
+  ((&data[hdr+5])[0] = (u8)((top)>>8), (&data[hdr+5])[1] = (u8)(top));
+  assert( top+nByte <= (int)pPage->pBt->usableSize );
+  *pIdx = top;
+  return 0;
+}
+# 1698 "src/btree.c"
+static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){
+  u16 iPtr;
+  u16 iFreeBlk;
+  u8 hdr;
+  u8 nFrag = 0;
+  u16 iOrigSize = iSize;
+  u16 x;
+  u32 iEnd = iStart + iSize;
+  unsigned char *data = pPage->aData;
+
+  assert( pPage->pBt!=0 );
+  assert( sqlite3PagerIswriteable(pPage->pDbPage) );
+  assert( (sqlite3Config.neverCorrupt==0) || iStart>=pPage->hdrOffset+6+pPage->childPtrSize );
+  assert( (sqlite3Config.neverCorrupt==0) || iEnd <= pPage->pBt->usableSize );
+  assert( sqlite3_mutex_held(pPage->pBt->mutex) );
+  assert( iSize>=4 );
+  assert( iStart<=pPage->pBt->usableSize-4 );
+
+
+
+
+  hdr = pPage->hdrOffset;
+  iPtr = hdr + 1;
+  if( data[iPtr+1]==0 && data[iPtr]==0 ){
+    iFreeBlk = 0;
+  }else{
+    while( (iFreeBlk = ((&data[iPtr])[0]<<8 | (&data[iPtr])[1]))<iStart ){
+      if( iFreeBlk<iPtr+4 ){
+        if( iFreeBlk==0 ) break;
+        return sqlite3CorruptError(1727);
+      }
+      iPtr = iFreeBlk;
+    }
+    if( iFreeBlk>pPage->pBt->usableSize-4 ){
+      return sqlite3CorruptError(1732);
+    }
+    assert( iFreeBlk>iPtr || iFreeBlk==0 );
+
+
+
+
+
+
+
+    if( iFreeBlk && iEnd+3>=iFreeBlk ){
+      nFrag = iFreeBlk - iEnd;
+      if( iEnd>iFreeBlk ) return sqlite3CorruptError(1744);
+      iEnd = iFreeBlk + ((&data[iFreeBlk+2])[0]<<8 | (&data[iFreeBlk+2])[1]);
+      if( iEnd > pPage->pBt->usableSize ){
+        return sqlite3CorruptError(1747);
+      }
+      iSize = iEnd - iStart;
+      iFreeBlk = ((&data[iFreeBlk])[0]<<8 | (&data[iFreeBlk])[1]);
+    }
+
+
+
+
+
+    if( iPtr>hdr+1 ){
+      int iPtrEnd = iPtr + ((&data[iPtr+2])[0]<<8 | (&data[iPtr+2])[1]);
+      if( iPtrEnd+3>=iStart ){
+        if( iPtrEnd>iStart ) return sqlite3CorruptError(1760);
+        nFrag += iStart - iPtrEnd;
+        iSize = iEnd - iPtr;
+        iStart = iPtr;
+      }
+    }
+    if( nFrag>data[hdr+7] ) return sqlite3CorruptError(1766);
+    data[hdr+7] -= nFrag;
+  }
+  x = ((&data[hdr+5])[0]<<8 | (&data[hdr+5])[1]);
+  if( iStart<=x ){
+
+
+
+    if( iStart<x || iPtr!=hdr+1 ) return sqlite3CorruptError(1774);
+    ((&data[hdr+1])[0] = (u8)((iFreeBlk)>>8), (&data[hdr+1])[1] = (u8)(iFreeBlk));
+    ((&data[hdr+5])[0] = (u8)((iEnd)>>8), (&data[hdr+5])[1] = (u8)(iEnd));
+  }else{
+
+    ((&data[iPtr])[0] = (u8)((iStart)>>8), (&data[iPtr])[1] = (u8)(iStart));
+  }
+  if( pPage->pBt->btsFlags & 0x000c ){
+
+
+    memset(&data[iStart], 0, iSize);
+  }
+  ((&data[iStart])[0] = (u8)((iFreeBlk)>>8), (&data[iStart])[1] = (u8)(iFreeBlk));
+  ((&data[iStart+2])[0] = (u8)((iSize)>>8), (&data[iStart+2])[1] = (u8)(iSize));
+  pPage->nFree += iOrigSize;
+  return 0;
+}
+# 1804 "src/btree.c"
+static int decodeFlags(MemPage *pPage, int flagByte){
+  BtShared *pBt;
+
+  assert( pPage->hdrOffset==(pPage->pgno==1 ? 100 : 0) );
+  assert( sqlite3_mutex_held(pPage->pBt->mutex) );
+  pPage->leaf = (u8)(flagByte>>3); assert( 0x08 == 1<<3 );
+  flagByte &= ~0x08;
+  pPage->childPtrSize = 4-4*pPage->leaf;
+  pPage->xCellSize = cellSizePtr;
+  pBt = pPage->pBt;
+  if( flagByte==(0x04 | 0x01) ){
+
+
+    assert( (0x04|0x01)==5 );
+
+
+    assert( (0x04|0x01|0x08)==13 );
+    pPage->intKey = 1;
+    if( pPage->leaf ){
+      pPage->intKeyLeaf = 1;
+      pPage->xParseCell = btreeParseCellPtr;
+    }else{
+      pPage->intKeyLeaf = 0;
+      pPage->xCellSize = cellSizePtrNoPayload;
+      pPage->xParseCell = btreeParseCellPtrNoPayload;
+    }
+    pPage->maxLocal = pBt->maxLeaf;
+    pPage->minLocal = pBt->minLeaf;
+  }else if( flagByte==0x02 ){
+
+
+    assert( (0x02)==2 );
+
+
+    assert( (0x02|0x08)==10 );
+    pPage->intKey = 0;
+    pPage->intKeyLeaf = 0;
+    pPage->xParseCell = btreeParseCellPtrIndex;
+    pPage->maxLocal = pBt->maxLocal;
+    pPage->minLocal = pBt->minLocal;
+  }else{
+
+
+    return sqlite3CorruptError(1847);
+  }
+  pPage->max1bytePayload = pBt->max1bytePayload;
+  return 0;
+}
+
+
+
+
+
+static int btreeComputeFreeSpace(MemPage *pPage){
+  int pc;
+  u8 hdr;
+  u8 *data;
+  int usableSize;
+  int nFree;
+  int top;
+  int iCellFirst;
+  int iCellLast;
+
+  assert( pPage->pBt!=0 );
+  assert( pPage->pBt->db!=0 );
+  assert( sqlite3_mutex_held(pPage->pBt->mutex) );
+  assert( pPage->pgno==sqlite3PagerPagenumber(pPage->pDbPage) );
+  assert( pPage == sqlite3PagerGetExtra(pPage->pDbPage) );
+  assert( pPage->aData == sqlite3PagerGetData(pPage->pDbPage) );
+  assert( pPage->isInit==1 );
+  assert( pPage->nFree<0 );
+
+  usableSize = pPage->pBt->usableSize;
+  hdr = pPage->hdrOffset;
+  data = pPage->aData;
+
+
+
+  top = (((((int)((&data[hdr+5])[0]<<8 | (&data[hdr+5])[1]))-1)&0xffff)+1);
+  iCellFirst = hdr + 8 + pPage->childPtrSize + 2*pPage->nCell;
+  iCellLast = usableSize - 4;
+
+
+
+
+
+  pc = ((&data[hdr+1])[0]<<8 | (&data[hdr+1])[1]);
+  nFree = data[hdr+7] + top;
+  if( pc>0 ){
+    u32 next, size;
+    if( pc<iCellFirst ){
+
+
+
+      return sqlite3CorruptError(1898);
+    }
+    while( 1 ){
+      if( pc>iCellLast ){
+
+        return sqlite3CorruptError(1903);
+      }
+      next = ((&data[pc])[0]<<8 | (&data[pc])[1]);
+      size = ((&data[pc+2])[0]<<8 | (&data[pc+2])[1]);
+      nFree = nFree + size;
+      if( next<=pc+size+3 ) break;
+      pc = next;
+    }
+    if( next>0 ){
+
+      return sqlite3CorruptError(1913);
+    }
+    if( pc+size>(unsigned int)usableSize ){
+
+      return sqlite3CorruptError(1917);
+    }
+  }
+# 1928 "src/btree.c"
+  if( nFree>usableSize || nFree<iCellFirst ){
+    return sqlite3CorruptError(1929);
+  }
+  pPage->nFree = (u16)(nFree - iCellFirst);
+  return 0;
+}
+
+
+
+
+
+static int btreeCellSizeCheck(MemPage *pPage){
+  int iCellFirst;
+  int iCellLast;
+  int i;
+  int sz;
+  int pc;
+  u8 *data;
+  int usableSize;
+  int cellOffset;
+
+  iCellFirst = pPage->cellOffset + 2*pPage->nCell;
+  usableSize = pPage->pBt->usableSize;
+  iCellLast = usableSize - 4;
+  data = pPage->aData;
+  cellOffset = pPage->cellOffset;
+  if( !pPage->leaf ) iCellLast--;
+  for(i=0; i<pPage->nCell; i++){
+    pc = __builtin_bswap16(*(u16*)(&data[cellOffset+i*2]));
+    ;
+    ;
+    if( pc<iCellFirst || pc>iCellLast ){
+      return sqlite3CorruptError(1960);
+    }
+    sz = pPage->xCellSize(pPage, &data[pc]);
+    ;
+    if( pc+sz>usableSize ){
+      return sqlite3CorruptError(1965);
+    }
+  }
+  return 0;
+}
+# 1980 "src/btree.c"
+static int btreeInitPage(MemPage *pPage){
+  u8 *data;
+  BtShared *pBt;
+
+  assert( pPage->pBt!=0 );
+  assert( pPage->pBt->db!=0 );
+  assert( sqlite3_mutex_held(pPage->pBt->mutex) );
+  assert( pPage->pgno==sqlite3PagerPagenumber(pPage->pDbPage) );
+  assert( pPage == sqlite3PagerGetExtra(pPage->pDbPage) );
+  assert( pPage->aData == sqlite3PagerGetData(pPage->pDbPage) );
+  assert( pPage->isInit==0 );
+
+  pBt = pPage->pBt;
+  data = pPage->aData + pPage->hdrOffset;
+
+
+  if( decodeFlags(pPage, data[0]) ){
+    return sqlite3CorruptError(1997);
+  }
+  assert( pBt->pageSize>=512 && pBt->pageSize<=65536 );
+  pPage->maskPage = (u16)(pBt->pageSize - 1);
+  pPage->nOverflow = 0;
+  pPage->cellOffset = pPage->hdrOffset + 8 + pPage->childPtrSize;
+  pPage->aCellIdx = data + pPage->childPtrSize + 8;
+  pPage->aDataEnd = pPage->aData + pBt->usableSize;
+  pPage->aDataOfst = pPage->aData + pPage->childPtrSize;
+
+
+  pPage->nCell = ((&data[3])[0]<<8 | (&data[3])[1]);
+  if( pPage->nCell>((pBt->pageSize-8)/6) ){
+
+    return sqlite3CorruptError(2011);
+  }
+  ;
+
+
+
+
+  assert( pPage->nCell>0
+       || (((((int)((&data[5])[0]<<8 | (&data[5])[1]))-1)&0xffff)+1)==(int)pBt->usableSize
+       || (sqlite3Config.neverCorrupt==0) );
+  pPage->nFree = -1;
+  pPage->isInit = 1;
+  if( pBt->db->flags & 0x00200000 ){
+    return btreeCellSizeCheck(pPage);
+  }
+  return 0;
+}
+
+
+
+
+
+static void zeroPage(MemPage *pPage, int flags){
+  unsigned char *data = pPage->aData;
+  BtShared *pBt = pPage->pBt;
+  u8 hdr = pPage->hdrOffset;
+  u16 first;
+
+  assert( sqlite3PagerPagenumber(pPage->pDbPage)==pPage->pgno );
+  assert( sqlite3PagerGetExtra(pPage->pDbPage) == (void*)pPage );
+  assert( sqlite3PagerGetData(pPage->pDbPage) == data );
+  assert( sqlite3PagerIswriteable(pPage->pDbPage) );
+  assert( sqlite3_mutex_held(pBt->mutex) );
+  if( pBt->btsFlags & 0x000c ){
+    memset(&data[hdr], 0, pBt->usableSize - hdr);
+  }
+  data[hdr] = (char)flags;
+  first = hdr + ((flags&0x08)==0 ? 12 : 8);
+  memset(&data[hdr+1], 0, 4);
+  data[hdr+7] = 0;
+  ((&data[hdr+5])[0] = (u8)((pBt->usableSize)>>8), (&data[hdr+5])[1] = (u8)(pBt->usableSize));
+  pPage->nFree = (u16)(pBt->usableSize - first);
+  decodeFlags(pPage, flags);
+  pPage->cellOffset = first;
+  pPage->aDataEnd = &data[pBt->usableSize];
+  pPage->aCellIdx = &data[first];
+  pPage->aDataOfst = &data[pPage->childPtrSize];
+  pPage->nOverflow = 0;
+  assert( pBt->pageSize>=512 && pBt->pageSize<=65536 );
+  pPage->maskPage = (u16)(pBt->pageSize - 1);
+  pPage->nCell = 0;
+  pPage->isInit = 1;
+}
+
+
+
+
+
+
+static MemPage *btreePageFromDbPage(DbPage *pDbPage, Pgno pgno, BtShared *pBt){
+  MemPage *pPage = (MemPage*)sqlite3PagerGetExtra(pDbPage);
+  if( pgno!=pPage->pgno ){
+    pPage->aData = sqlite3PagerGetData(pDbPage);
+    pPage->pDbPage = pDbPage;
+    pPage->pBt = pBt;
+    pPage->pgno = pgno;
+    pPage->hdrOffset = pgno==1 ? 100 : 0;
+  }
+  assert( pPage->aData==sqlite3PagerGetData(pDbPage) );
+  return pPage;
+}
+# 2094 "src/btree.c"
+static int btreeGetPage(
+  BtShared *pBt,
+  Pgno pgno,
+  MemPage **ppPage,
+  int flags
+){
+  int rc;
+  DbPage *pDbPage;
+
+  assert( flags==0 || flags==0x01 || flags==0x02 );
+  assert( sqlite3_mutex_held(pBt->mutex) );
+  rc = sqlite3PagerGet(pBt->pPager, pgno, (DbPage**)&pDbPage, flags);
+  if( rc ) return rc;
+  *ppPage = btreePageFromDbPage(pDbPage, pgno, pBt);
+  return 0;
+}
+
+
+
+
+
+
+static MemPage *btreePageLookup(BtShared *pBt, Pgno pgno){
+  DbPage *pDbPage;
+  assert( sqlite3_mutex_held(pBt->mutex) );
+  pDbPage = sqlite3PagerLookup(pBt->pPager, pgno);
+  if( pDbPage ){
+    return btreePageFromDbPage(pDbPage, pgno, pBt);
+  }
+  return 0;
+}
+
+
+
+
+
+static Pgno btreePagecount(BtShared *pBt){
+  return pBt->nPage;
+}
+u32 sqlite3BtreeLastPage(Btree *p){
+  assert( sqlite3BtreeHoldsMutex(p) );
+  assert( ((p->pBt->nPage)&0x80000000)==0 );
+  return btreePagecount(p->pBt);
+}
+# 2152 "src/btree.c"
+static int getAndInitPage(
+  BtShared *pBt,
+  Pgno pgno,
+  MemPage **ppPage,
+  BtCursor *pCur,
+  int bReadOnly
+){
+  int rc;
+  DbPage *pDbPage;
+  assert( sqlite3_mutex_held(pBt->mutex) );
+  assert( pCur==0 || ppPage==&pCur->pPage );
+  assert( pCur==0 || bReadOnly==pCur->curPagerFlags );
+  assert( pCur==0 || pCur->iPage>0 );
+
+  if( pgno>btreePagecount(pBt) ){
+    rc = sqlite3CorruptError(2167);
+    goto getAndInitPage_error1;
+  }
+  rc = sqlite3PagerGet(pBt->pPager, pgno, (DbPage**)&pDbPage, bReadOnly);
+  if( rc ){
+    goto getAndInitPage_error1;
+  }
+  *ppPage = (MemPage*)sqlite3PagerGetExtra(pDbPage);
+  if( (*ppPage)->isInit==0 ){
+    btreePageFromDbPage(pDbPage, pgno, pBt);
+    rc = btreeInitPage(*ppPage);
+    if( rc!=0 ){
+      goto getAndInitPage_error2;
+    }
+  }
+  assert( (*ppPage)->pgno==pgno );
+  assert( (*ppPage)->aData==sqlite3PagerGetData(pDbPage) );
+
+
+
+  if( pCur && ((*ppPage)->nCell<1 || (*ppPage)->intKey!=pCur->curIntKey) ){
+    rc = sqlite3CorruptError(2188);
+    goto getAndInitPage_error2;
+  }
+  return 0;
+
+getAndInitPage_error2:
+  releasePage(*ppPage);
+getAndInitPage_error1:
+  if( pCur ){
+    pCur->iPage--;
+    pCur->pPage = pCur->apPage[pCur->iPage];
+  }
+  ;
+  assert( pgno!=0 || rc==11 );
+  return rc;
+}
+
+
+
+
+
+
+
+static void releasePageNotNull(MemPage *pPage){
+  assert( pPage->aData );
+  assert( pPage->pBt );
+  assert( pPage->pDbPage!=0 );
+  assert( sqlite3PagerGetExtra(pPage->pDbPage) == (void*)pPage );
+  assert( sqlite3PagerGetData(pPage->pDbPage)==pPage->aData );
+  assert( sqlite3_mutex_held(pPage->pBt->mutex) );
+  sqlite3PagerUnrefNotNull(pPage->pDbPage);
+}
+static void releasePage(MemPage *pPage){
+  if( pPage ) releasePageNotNull(pPage);
+}
+static void releasePageOne(MemPage *pPage){
+  assert( pPage!=0 );
+  assert( pPage->aData );
+  assert( pPage->pBt );
+  assert( pPage->pDbPage!=0 );
+  assert( sqlite3PagerGetExtra(pPage->pDbPage) == (void*)pPage );
+  assert( sqlite3PagerGetData(pPage->pDbPage)==pPage->aData );
+  assert( sqlite3_mutex_held(pPage->pBt->mutex) );
+  sqlite3PagerUnrefPageOne(pPage->pDbPage);
+}
+# 2243 "src/btree.c"
+static int btreeGetUnusedPage(
+  BtShared *pBt,
+  Pgno pgno,
+  MemPage **ppPage,
+  int flags
+){
+  int rc = btreeGetPage(pBt, pgno, ppPage, flags);
+  if( rc==0 ){
+    if( sqlite3PagerPageRefcount((*ppPage)->pDbPage)>1 ){
+      releasePage(*ppPage);
+      *ppPage = 0;
+      return sqlite3CorruptError(2254);
+    }
+    (*ppPage)->isInit = 0;
+  }else{
+    *ppPage = 0;
+  }
+  return rc;
+}
+# 2272 "src/btree.c"
+static void pageReinit(DbPage *pData){
+  MemPage *pPage;
+  pPage = (MemPage *)sqlite3PagerGetExtra(pData);
+  assert( sqlite3PagerPageRefcount(pData)>0 );
+  if( pPage->isInit ){
+    assert( sqlite3_mutex_held(pPage->pBt->mutex) );
+    pPage->isInit = 0;
+    if( sqlite3PagerPageRefcount(pData)>1 ){
+
+
+
+
+
+
+      btreeInitPage(pPage);
+    }
+  }
+}
+
+
+
+
+static int btreeInvokeBusyHandler(void *pArg){
+  BtShared *pBt = (BtShared*)pArg;
+  assert( pBt->db );
+  assert( sqlite3_mutex_held(pBt->db->mutex) );
+  return sqlite3InvokeBusyHandler(&pBt->db->busyHandler,
+                                  sqlite3PagerFile(pBt->pPager));
+}
+# 2323 "src/btree.c"
+int sqlite3BtreeOpen(
+  sqlite3_vfs *pVfs,
+  const char *zFilename,
+  sqlite3 *db,
+  Btree **ppBtree,
+  int flags,
+  int vfsFlags
+){
+  BtShared *pBt = 0;
+  Btree *p;
+  sqlite3_mutex *mutexOpen = 0;
+  int rc = 0;
+  u8 nReserve;
+  unsigned char zDbHeader[100];
+
+
+  const int isTempDb = zFilename==0 || zFilename[0]==0;
+
+
+
+
+
+
+
+  const int isMemdb = (zFilename && strcmp(zFilename, ":memory:")==0)
+                       || (isTempDb && sqlite3TempInMemory(db))
+                       || (vfsFlags & 0x00000080)!=0;
+
+
+  assert( db!=0 );
+  assert( pVfs!=0 );
+  assert( sqlite3_mutex_held(db->mutex) );
+  assert( (flags&0xff)==flags );
+
+
+  assert( (flags & 8)==0 || (flags & 4)!=0 );
+
+
+  assert( (flags & 4)==0 || isTempDb );
+
+  if( isMemdb ){
+    flags |= 2;
+  }
+  if( (vfsFlags & 0x00000100)!=0 && (isMemdb || isTempDb) ){
+    vfsFlags = (vfsFlags & ~0x00000100) | 0x00000200;
+  }
+  p = sqlite3MallocZero(sizeof(Btree));
+  if( !p ){
+    return 7;
+  }
+  p->inTrans = 0;
+  p->db = db;
+
+  p->lock.pBtree = p;
+  p->lock.iTable = 1;
+
+
+
+
+
+
+
+  if( isTempDb==0 && (isMemdb==0 || (vfsFlags&0x00000040)!=0) ){
+    if( vfsFlags & 0x00020000 ){
+      int nFilename = sqlite3Strlen30(zFilename)+1;
+      int nFullPathname = pVfs->mxPathname+1;
+      char *zFullPathname = sqlite3Malloc(((nFullPathname)>(nFilename)?(nFullPathname):(nFilename)));
+      sqlite3_mutex *mutexShared;
+
+      p->sharable = 1;
+      if( !zFullPathname ){
+        sqlite3_free(p);
+        return 7;
+      }
+      if( isMemdb ){
+        memcpy(zFullPathname, zFilename, nFilename);
+      }else{
+        rc = sqlite3OsFullPathname(pVfs, zFilename,
+                                   nFullPathname, zFullPathname);
+        if( rc ){
+          sqlite3_free(zFullPathname);
+          sqlite3_free(p);
+          return rc;
+        }
+      }
+
+      mutexOpen = sqlite3MutexAlloc(4);
+      sqlite3_mutex_enter(mutexOpen);
+      mutexShared = sqlite3MutexAlloc(2);
+      sqlite3_mutex_enter(mutexShared);
+
+      for(pBt=sqlite3SharedCacheList; pBt; pBt=pBt->pNext){
+        assert( pBt->nRef>0 );
+        if( 0==strcmp(zFullPathname, sqlite3PagerFilename(pBt->pPager, 0))
+                 && sqlite3PagerVfs(pBt->pPager)==pVfs ){
+          int iDb;
+          for(iDb=db->nDb-1; iDb>=0; iDb--){
+            Btree *pExisting = db->aDb[iDb].pBt;
+            if( pExisting && pExisting->pBt==pBt ){
+              sqlite3_mutex_leave(mutexShared);
+              sqlite3_mutex_leave(mutexOpen);
+              sqlite3_free(zFullPathname);
+              sqlite3_free(p);
+              return 19;
+            }
+          }
+          p->pBt = pBt;
+          pBt->nRef++;
+          break;
+        }
+      }
+      sqlite3_mutex_leave(mutexShared);
+      sqlite3_free(zFullPathname);
+    }
+# 2447 "src/btree.c"
+  }
+
+  if( pBt==0 ){
+
+
+
+
+
+    assert( sizeof(i64)==8 );
+    assert( sizeof(u64)==8 );
+    assert( sizeof(u32)==4 );
+    assert( sizeof(u16)==2 );
+    assert( sizeof(Pgno)==4 );
+
+    pBt = sqlite3MallocZero( sizeof(*pBt) );
+    if( pBt==0 ){
+      rc = 7;
+      goto btree_open_out;
+    }
+    rc = sqlite3PagerOpen(pVfs, &pBt->pPager, zFilename,
+                          sizeof(MemPage), flags, vfsFlags, pageReinit);
+    if( rc==0 ){
+      sqlite3PagerSetMmapLimit(pBt->pPager, db->szMmap);
+      rc = sqlite3PagerReadFileheader(pBt->pPager,sizeof(zDbHeader),zDbHeader);
+    }
+    if( rc!=0 ){
+      goto btree_open_out;
+    }
+    pBt->openFlags = (u8)flags;
+    pBt->db = db;
+    sqlite3PagerSetBusyHandler(pBt->pPager, btreeInvokeBusyHandler, pBt);
+    p->pBt = pBt;
+
+    pBt->pCursor = 0;
+    pBt->pPage1 = 0;
+    if( sqlite3PagerIsreadonly(pBt->pPager) ) pBt->btsFlags |= 0x0001;
+# 2491 "src/btree.c"
+    pBt->pageSize = (zDbHeader[16]<<8) | (zDbHeader[17]<<16);
+    if( pBt->pageSize<512 || pBt->pageSize>65536
+         || ((pBt->pageSize-1)&pBt->pageSize)!=0 ){
+      pBt->pageSize = 0;
+
+
+
+
+
+
+
+      if( zFilename && !isMemdb ){
+        pBt->autoVacuum = (0 ? 1 : 0);
+        pBt->incrVacuum = (0==2 ? 1 : 0);
+      }
+
+      nReserve = 0;
+    }else{
+
+
+
+      nReserve = zDbHeader[20];
+      pBt->btsFlags |= 0x0002;
+
+      pBt->autoVacuum = (sqlite3Get4byte(&zDbHeader[36 + 4*4])?1:0);
+      pBt->incrVacuum = (sqlite3Get4byte(&zDbHeader[36 + 7*4])?1:0);
+
+    }
+    rc = sqlite3PagerSetPagesize(pBt->pPager, &pBt->pageSize, nReserve);
+    if( rc ) goto btree_open_out;
+    pBt->usableSize = pBt->pageSize - nReserve;
+    assert( (pBt->pageSize & 7)==0 );
+
+
+
+
+    pBt->nRef = 1;
+    if( p->sharable ){
+      sqlite3_mutex *mutexShared;
+      mutexShared = sqlite3MutexAlloc(2);
+      if( 1 && sqlite3Config.bCoreMutex ){
+        pBt->mutex = sqlite3MutexAlloc(0);
+        if( pBt->mutex==0 ){
+          rc = 7;
+          goto btree_open_out;
+        }
+      }
+      sqlite3_mutex_enter(mutexShared);
+      pBt->pNext = sqlite3SharedCacheList;
+      sqlite3SharedCacheList = pBt;
+      sqlite3_mutex_leave(mutexShared);
+    }
+
+  }
+
+
+
+
+
+
+  if( p->sharable ){
+    int i;
+    Btree *pSib;
+    for(i=0; i<db->nDb; i++){
+      if( (pSib = db->aDb[i].pBt)!=0 && pSib->sharable ){
+        while( pSib->pPrev ){ pSib = pSib->pPrev; }
+        if( (uptr)p->pBt<(uptr)pSib->pBt ){
+          p->pNext = pSib;
+          p->pPrev = 0;
+          pSib->pPrev = p;
+        }else{
+          while( pSib->pNext && (uptr)pSib->pNext->pBt<(uptr)p->pBt ){
+            pSib = pSib->pNext;
+          }
+          p->pNext = pSib->pNext;
+          p->pPrev = pSib;
+          if( p->pNext ){
+            p->pNext->pPrev = p;
+          }
+          pSib->pNext = p;
+        }
+        break;
+      }
+    }
+  }
+
+  *ppBtree = p;
+
+btree_open_out:
+  if( rc!=0 ){
+    if( pBt && pBt->pPager ){
+      sqlite3PagerClose(pBt->pPager, 0);
+    }
+    sqlite3_free(pBt);
+    sqlite3_free(p);
+    *ppBtree = 0;
+  }else{
+    sqlite3_file *pFile;
+
+
+
+
+
+    if( sqlite3BtreeSchema(p, 0, 0)==0 ){
+      sqlite3PagerSetCachesize(p->pBt->pPager, -2000);
+    }
+
+    pFile = sqlite3PagerFile(pBt->pPager);
+    if( pFile->pMethods ){
+      sqlite3OsFileControlHint(pFile, 30, (void*)&pBt->db);
+    }
+  }
+  if( mutexOpen ){
+    assert( sqlite3_mutex_held(mutexOpen) );
+    sqlite3_mutex_leave(mutexOpen);
+  }
+  assert( rc!=0 || sqlite3BtreeConnectionCount(*ppBtree)>0 );
+  return rc;
+}
+
+
+
+
+
+
+
+static int removeFromSharingList(BtShared *pBt){
+
+  sqlite3_mutex *pMaster;
+  BtShared *pList;
+  int removed = 0;
+
+  assert( sqlite3_mutex_notheld(pBt->mutex) );
+  pMaster = sqlite3MutexAlloc(2);
+  sqlite3_mutex_enter(pMaster);
+  pBt->nRef--;
+  if( pBt->nRef<=0 ){
+    if( sqlite3SharedCacheList==pBt ){
+      sqlite3SharedCacheList = pBt->pNext;
+    }else{
+      pList = sqlite3SharedCacheList;
+      while( (pList) && pList->pNext!=pBt ){
+        pList=pList->pNext;
+      }
+      if( (pList) ){
+        pList->pNext = pBt->pNext;
+      }
+    }
+    if( 1 ){
+      sqlite3_mutex_free(pBt->mutex);
+    }
+    removed = 1;
+  }
+  sqlite3_mutex_leave(pMaster);
+  return removed;
+
+
+
+}
+
+
+
+
+
+
+static void allocateTempSpace(BtShared *pBt){
+  if( !pBt->pTmpSpace ){
+    pBt->pTmpSpace = sqlite3PageMalloc( pBt->pageSize );
+# 2675 "src/btree.c"
+    if( pBt->pTmpSpace ){
+      memset(pBt->pTmpSpace, 0, 8);
+      pBt->pTmpSpace += 4;
+    }
+  }
+}
+
+
+
+
+static void freeTempSpace(BtShared *pBt){
+  if( pBt->pTmpSpace ){
+    pBt->pTmpSpace -= 4;
+    sqlite3PageFree(pBt->pTmpSpace);
+    pBt->pTmpSpace = 0;
+  }
+}
+
+
+
+
+int sqlite3BtreeClose(Btree *p){
+  BtShared *pBt = p->pBt;
+  BtCursor *pCur;
+
+
+  assert( sqlite3_mutex_held(p->db->mutex) );
+  sqlite3BtreeEnter(p);
+  pCur = pBt->pCursor;
+  while( pCur ){
+    BtCursor *pTmp = pCur;
+    pCur = pCur->pNext;
+    if( pTmp->pBtree==p ){
+      sqlite3BtreeCloseCursor(pTmp);
+    }
+  }
+
+
+
+
+
+  sqlite3BtreeRollback(p, 0, 0);
+  sqlite3BtreeLeave(p);
+
+
+
+
+
+  assert( p->wantToLock==0 && p->locked==0 );
+  if( !p->sharable || removeFromSharingList(pBt) ){
+
+
+
+
+
+    assert( !pBt->pCursor );
+    sqlite3PagerClose(pBt->pPager, p->db);
+    if( pBt->xFreeSchema && pBt->pSchema ){
+      pBt->xFreeSchema(pBt->pSchema);
+    }
+    sqlite3DbFree(0, pBt->pSchema);
+    freeTempSpace(pBt);
+    sqlite3_free(pBt);
+  }
+
+
+  assert( p->wantToLock==0 );
+  assert( p->locked==0 );
+  if( p->pPrev ) p->pPrev->pNext = p->pNext;
+  if( p->pNext ) p->pNext->pPrev = p->pPrev;
+
+
+  sqlite3_free(p);
+  return 0;
+}
+# 2758 "src/btree.c"
+int sqlite3BtreeSetCacheSize(Btree *p, int mxPage){
+  BtShared *pBt = p->pBt;
+  assert( sqlite3_mutex_held(p->db->mutex) );
+  sqlite3BtreeEnter(p);
+  sqlite3PagerSetCachesize(pBt->pPager, mxPage);
+  sqlite3BtreeLeave(p);
+  return 0;
+}
+# 2777 "src/btree.c"
+int sqlite3BtreeSetSpillSize(Btree *p, int mxPage){
+  BtShared *pBt = p->pBt;
+  int res;
+  assert( sqlite3_mutex_held(p->db->mutex) );
+  sqlite3BtreeEnter(p);
+  res = sqlite3PagerSetSpillsize(pBt->pPager, mxPage);
+  sqlite3BtreeLeave(p);
+  return res;
+}
+
+
+
+
+
+
+int sqlite3BtreeSetMmapLimit(Btree *p, sqlite3_int64 szMmap){
+  BtShared *pBt = p->pBt;
+  assert( sqlite3_mutex_held(p->db->mutex) );
+  sqlite3BtreeEnter(p);
+  sqlite3PagerSetMmapLimit(pBt->pPager, szMmap);
+  sqlite3BtreeLeave(p);
+  return 0;
+}
+# 2811 "src/btree.c"
+int sqlite3BtreeSetPagerFlags(
+  Btree *p,
+  unsigned pgFlags
+){
+  BtShared *pBt = p->pBt;
+  assert( sqlite3_mutex_held(p->db->mutex) );
+  sqlite3BtreeEnter(p);
+  sqlite3PagerSetFlags(pBt->pPager, pgFlags);
+  sqlite3BtreeLeave(p);
+  return 0;
+}
+# 2844 "src/btree.c"
+int sqlite3BtreeSetPageSize(Btree *p, int pageSize, int nReserve, int iFix){
+  int rc = 0;
+  BtShared *pBt = p->pBt;
+  assert( nReserve>=-1 && nReserve<=255 );
+  sqlite3BtreeEnter(p);
+
+
+
+  if( pBt->btsFlags & 0x0002 ){
+    sqlite3BtreeLeave(p);
+    return 8;
+  }
+  if( nReserve<0 ){
+    nReserve = pBt->pageSize - pBt->usableSize;
+  }
+  assert( nReserve>=0 && nReserve<=255 );
+  if( pageSize>=512 && pageSize<=65536 &&
+        ((pageSize-1)&pageSize)==0 ){
+    assert( (pageSize & 7)==0 );
+    assert( !pBt->pCursor );
+    pBt->pageSize = (u32)pageSize;
+    freeTempSpace(pBt);
+  }
+  rc = sqlite3PagerSetPagesize(pBt->pPager, &pBt->pageSize, nReserve);
+  pBt->usableSize = pBt->pageSize - (u16)nReserve;
+  if( iFix ) pBt->btsFlags |= 0x0002;
+  sqlite3BtreeLeave(p);
+  return rc;
+}
+
+
+
+
+int sqlite3BtreeGetPageSize(Btree *p){
+  return p->pBt->pageSize;
+}
+# 2892 "src/btree.c"
+int sqlite3BtreeGetReserveNoMutex(Btree *p){
+  int n;
+  assert( sqlite3_mutex_held(p->pBt->mutex) );
+  n = p->pBt->pageSize - p->pBt->usableSize;
+  return n;
+}
+# 2908 "src/btree.c"
+int sqlite3BtreeGetOptimalReserve(Btree *p){
+  int n;
+  sqlite3BtreeEnter(p);
+  n = sqlite3BtreeGetReserveNoMutex(p);
+
+
+
+  sqlite3BtreeLeave(p);
+  return n;
+}
+
+
+
+
+
+
+
+int sqlite3BtreeMaxPageCount(Btree *p, int mxPage){
+  int n;
+  sqlite3BtreeEnter(p);
+  n = sqlite3PagerMaxPageCount(p->pBt->pPager, mxPage);
+  sqlite3BtreeLeave(p);
+  return n;
+}
+# 2951 "src/btree.c"
+int sqlite3BtreeSecureDelete(Btree *p, int newFlag){
+  int b;
+  if( p==0 ) return 0;
+  sqlite3BtreeEnter(p);
+  assert( 0x0008==0x0004*2 );
+  assert( 0x000c==(0x0008|0x0004) );
+  if( newFlag>=0 ){
+    p->pBt->btsFlags &= ~0x000c;
+    p->pBt->btsFlags |= 0x0004*newFlag;
+  }
+  b = (p->pBt->btsFlags & 0x000c)/0x0004;
+  sqlite3BtreeLeave(p);
+  return b;
+}
+
+
+
+
+
+
+
+int sqlite3BtreeSetAutoVacuum(Btree *p, int autoVacuum){
+
+
+
+  BtShared *pBt = p->pBt;
+  int rc = 0;
+  u8 av = (u8)autoVacuum;
+
+  sqlite3BtreeEnter(p);
+  if( (pBt->btsFlags & 0x0002)!=0 && (av ?1:0)!=pBt->autoVacuum ){
+    rc = 8;
+  }else{
+    pBt->autoVacuum = av ?1:0;
+    pBt->incrVacuum = av==2 ?1:0;
+  }
+  sqlite3BtreeLeave(p);
+  return rc;
+
+}
+
+
+
+
+
+int sqlite3BtreeGetAutoVacuum(Btree *p){
+
+
+
+  int rc;
+  sqlite3BtreeEnter(p);
+  rc = (
+    (!p->pBt->autoVacuum)?0:
+    (!p->pBt->incrVacuum)?1:
+    2
+  );
+  sqlite3BtreeLeave(p);
+  return rc;
+
+}
+# 3040 "src/btree.c"
+static int newDatabase(BtShared*);
+# 3052 "src/btree.c"
+static int lockBtree(BtShared *pBt){
+  int rc;
+  MemPage *pPage1;
+  u32 nPage;
+  u32 nPageFile = 0;
+  u32 nPageHeader;
+
+  assert( sqlite3_mutex_held(pBt->mutex) );
+  assert( pBt->pPage1==0 );
+  rc = sqlite3PagerSharedLock(pBt->pPager);
+  if( rc!=0 ) return rc;
+  rc = btreeGetPage(pBt, 1, &pPage1, 0);
+  if( rc!=0 ) return rc;
+
+
+
+
+  nPage = nPageHeader = sqlite3Get4byte(28+(u8*)pPage1->aData);
+  sqlite3PagerPagecount(pBt->pPager, (int*)&nPageFile);
+  if( nPage==0 || memcmp(24+(u8*)pPage1->aData, 92+(u8*)pPage1->aData,4)!=0 ){
+    nPage = nPageFile;
+  }
+  if( (pBt->db->flags & 0x02000000)!=0 ){
+    nPage = 0;
+  }
+  if( nPage>0 ){
+    u32 pageSize;
+    u32 usableSize;
+    u8 *page1 = pPage1->aData;
+    rc = 26;
+
+
+
+    if( memcmp(page1, zMagicHeader, 16)!=0 ){
+      goto page1_init_failed;
+    }
+# 3097 "src/btree.c"
+    if( page1[18]>2 ){
+      pBt->btsFlags |= 0x0001;
+    }
+    if( page1[19]>2 ){
+      goto page1_init_failed;
+    }
+# 3112 "src/btree.c"
+    if( page1[19]==2 && (pBt->btsFlags & 0x0020)==0 ){
+      int isOpen = 0;
+      rc = sqlite3PagerOpenWal(pBt->pPager, &isOpen);
+      if( rc!=0 ){
+        goto page1_init_failed;
+      }else{
+        ;
+        if( isOpen==0 ){
+          releasePageOne(pPage1);
+          return 0;
+        }
+      }
+      rc = 26;
+    }else{
+      ;
+    }
+# 3136 "src/btree.c"
+    if( memcmp(&page1[21], "\100\040\040",3)!=0 ){
+      goto page1_init_failed;
+    }
+
+
+
+    pageSize = (page1[16]<<8) | (page1[17]<<16);
+
+
+    if( ((pageSize-1)&pageSize)!=0
+     || pageSize>65536
+     || pageSize<=256
+    ){
+      goto page1_init_failed;
+    }
+    pBt->btsFlags |= 0x0002;
+    assert( (pageSize & 7)==0 );
+
+
+
+
+
+
+
+    usableSize = pageSize - page1[20];
+    if( (u32)pageSize!=pBt->pageSize ){
+
+
+
+
+
+
+      releasePageOne(pPage1);
+      pBt->usableSize = usableSize;
+      pBt->pageSize = pageSize;
+      freeTempSpace(pBt);
+      rc = sqlite3PagerSetPagesize(pBt->pPager, &pBt->pageSize,
+                                   pageSize-usableSize);
+      return rc;
+    }
+    if( sqlite3WritableSchema(pBt->db)==0 && nPage>nPageFile ){
+      rc = sqlite3CorruptError(3177);
+      goto page1_init_failed;
+    }
+
+
+
+    if( usableSize<480 ){
+      goto page1_init_failed;
+    }
+    pBt->pageSize = pageSize;
+    pBt->usableSize = usableSize;
+
+    pBt->autoVacuum = (sqlite3Get4byte(&page1[36 + 4*4])?1:0);
+    pBt->incrVacuum = (sqlite3Get4byte(&page1[36 + 7*4])?1:0);
+
+  }
+# 3207 "src/btree.c"
+  pBt->maxLocal = (u16)((pBt->usableSize-12)*64/255 - 23);
+  pBt->minLocal = (u16)((pBt->usableSize-12)*32/255 - 23);
+  pBt->maxLeaf = (u16)(pBt->usableSize - 35);
+  pBt->minLeaf = (u16)((pBt->usableSize-12)*32/255 - 23);
+  if( pBt->maxLocal>127 ){
+    pBt->max1bytePayload = 127;
+  }else{
+    pBt->max1bytePayload = (u8)pBt->maxLocal;
+  }
+  assert( pBt->maxLeaf + 23 <= ((int)(pBt->pageSize-8)) );
+  pBt->pPage1 = pPage1;
+  pBt->nPage = nPage;
+  return 0;
+
+page1_init_failed:
+  releasePageOne(pPage1);
+  pBt->pPage1 = 0;
+  return rc;
+}
+# 3259 "src/btree.c"
+static void unlockBtreeIfUnused(BtShared *pBt){
+  assert( sqlite3_mutex_held(pBt->mutex) );
+  assert( countValidCursors(pBt,0)==0 || pBt->inTransaction>0 );
+  if( pBt->inTransaction==0 && pBt->pPage1!=0 ){
+    MemPage *pPage1 = pBt->pPage1;
+    assert( pPage1->aData );
+    assert( sqlite3PagerRefcount(pBt->pPager)==1 );
+    pBt->pPage1 = 0;
+    releasePageOne(pPage1);
+  }
+}
+
+
+
+
+
+
+static int newDatabase(BtShared *pBt){
+  MemPage *pP1;
+  unsigned char *data;
+  int rc;
+
+  assert( sqlite3_mutex_held(pBt->mutex) );
+  if( pBt->nPage>0 ){
+    return 0;
+  }
+  pP1 = pBt->pPage1;
+  assert( pP1!=0 );
+  data = pP1->aData;
+  rc = sqlite3PagerWrite(pP1->pDbPage);
+  if( rc ) return rc;
+  memcpy(data, zMagicHeader, sizeof(zMagicHeader));
+  assert( sizeof(zMagicHeader)==16 );
+  data[16] = (u8)((pBt->pageSize>>8)&0xff);
+  data[17] = (u8)((pBt->pageSize>>16)&0xff);
+  data[18] = 1;
+  data[19] = 1;
+  assert( pBt->usableSize<=pBt->pageSize && pBt->usableSize+255>=pBt->pageSize);
+  data[20] = (u8)(pBt->pageSize - pBt->usableSize);
+  data[21] = 64;
+  data[22] = 32;
+  data[23] = 32;
+  memset(&data[24], 0, 100-24);
+  zeroPage(pP1, 0x01|0x08|0x04 );
+  pBt->btsFlags |= 0x0002;
+
+  assert( pBt->autoVacuum==1 || pBt->autoVacuum==0 );
+  assert( pBt->incrVacuum==1 || pBt->incrVacuum==0 );
+  sqlite3Put4byte(&data[36 + 4*4], pBt->autoVacuum);
+  sqlite3Put4byte(&data[36 + 7*4], pBt->incrVacuum);
+
+  pBt->nPage = 1;
+  data[31] = 1;
+  return 0;
+}
+
+
+
+
+
+
+int sqlite3BtreeNewDb(Btree *p){
+  int rc;
+  sqlite3BtreeEnter(p);
+  p->pBt->nPage = 0;
+  rc = newDatabase(p->pBt);
+  sqlite3BtreeLeave(p);
+  return rc;
+}
+# 3364 "src/btree.c"
+int sqlite3BtreeBeginTrans(Btree *p, int wrflag, int *pSchemaVersion){
+  BtShared *pBt = p->pBt;
+  int rc = 0;
+
+  sqlite3BtreeEnter(p);
+  assert( p->pBt->inTransaction!=0 || p->pBt->nTransaction==0 ); assert( p->pBt->inTransaction>=p->inTrans );;
+
+
+
+
+
+  if( p->inTrans==2 || (p->inTrans==1 && !wrflag) ){
+    goto trans_begun;
+  }
+  assert( pBt->inTransaction==2 || (pBt->bDoTruncate)==0 );
+
+  if( (p->db->flags & 0x02000000)
+   && sqlite3PagerIsreadonly(pBt->pPager)==0
+  ){
+    pBt->btsFlags &= ~0x0001;
+  }
+
+
+  if( (pBt->btsFlags & 0x0001)!=0 && wrflag ){
+    rc = 8;
+    goto trans_begun;
+  }
+
+
+  {
+    sqlite3 *pBlock = 0;
+
+
+
+
+    if( (wrflag && pBt->inTransaction==2)
+     || (pBt->btsFlags & 0x0080)!=0
+    ){
+      pBlock = pBt->pWriter->db;
+    }else if( wrflag>1 ){
+      BtLock *pIter;
+      for(pIter=pBt->pLock; pIter; pIter=pIter->pNext){
+        if( pIter->pBtree!=p ){
+          pBlock = pIter->pBtree->db;
+          break;
+        }
+      }
+    }
+    if( pBlock ){
+      ;
+      rc = (6 | (1<<8));
+      goto trans_begun;
+    }
+  }
+
+
+
+
+
+  rc = querySharedCacheTableLock(p, 1, 1);
+  if( 0!=rc ) goto trans_begun;
+
+  pBt->btsFlags &= ~0x0010;
+  if( pBt->nPage==0 ) pBt->btsFlags |= 0x0010;
+  do {
+
+
+
+
+
+
+
+    while( pBt->pPage1==0 && 0==(rc = lockBtree(pBt)) );
+
+    if( rc==0 && wrflag ){
+      if( (pBt->btsFlags & 0x0001)!=0 ){
+        rc = 8;
+      }else{
+        rc = sqlite3PagerBegin(pBt->pPager,wrflag>1,sqlite3TempInMemory(p->db));
+        if( rc==0 ){
+          rc = newDatabase(pBt);
+        }else if( rc==(5 | (2<<8)) && pBt->inTransaction==0 ){
+
+
+
+          rc = 5;
+        }
+      }
+    }
+
+    if( rc!=0 ){
+      unlockBtreeIfUnused(pBt);
+    }
+  }while( (rc&0xFF)==5 && pBt->inTransaction==0 &&
+          btreeInvokeBusyHandler(pBt) );
+  ;
+
+  if( rc==0 ){
+    if( p->inTrans==0 ){
+      pBt->nTransaction++;
+
+      if( p->sharable ){
+        assert( p->lock.pBtree==p && p->lock.iTable==1 );
+        p->lock.eLock = 1;
+        p->lock.pNext = pBt->pLock;
+        pBt->pLock = &p->lock;
+      }
+
+    }
+    p->inTrans = (wrflag?2:1);
+    if( p->inTrans>pBt->inTransaction ){
+      pBt->inTransaction = p->inTrans;
+    }
+    if( wrflag ){
+      MemPage *pPage1 = pBt->pPage1;
+
+      assert( !pBt->pWriter );
+      pBt->pWriter = p;
+      pBt->btsFlags &= ~0x0040;
+      if( wrflag>1 ) pBt->btsFlags |= 0x0040;
+# 3492 "src/btree.c"
+      if( pBt->nPage!=sqlite3Get4byte(&pPage1->aData[28]) ){
+        rc = sqlite3PagerWrite(pPage1->pDbPage);
+        if( rc==0 ){
+          sqlite3Put4byte(&pPage1->aData[28], pBt->nPage);
+        }
+      }
+    }
+  }
+
+trans_begun:
+  if( rc==0 ){
+    if( pSchemaVersion ){
+      *pSchemaVersion = sqlite3Get4byte(&pBt->pPage1->aData[40]);
+    }
+    if( wrflag ){
+
+
+
+
+      rc = sqlite3PagerOpenSavepoint(pBt->pPager, p->db->nSavepoint);
+    }
+  }
+
+  assert( p->pBt->inTransaction!=0 || p->pBt->nTransaction==0 ); assert( p->pBt->inTransaction>=p->inTrans );;
+  sqlite3BtreeLeave(p);
+  return rc;
+}
+# 3527 "src/btree.c"
+static int setChildPtrmaps(MemPage *pPage){
+  int i;
+  int nCell;
+  int rc;
+  BtShared *pBt = pPage->pBt;
+  Pgno pgno = pPage->pgno;
+
+  assert( sqlite3_mutex_held(pPage->pBt->mutex) );
+  rc = pPage->isInit ? 0 : btreeInitPage(pPage);
+  if( rc!=0 ) return rc;
+  nCell = pPage->nCell;
+
+  for(i=0; i<nCell; i++){
+    u8 *pCell = ((pPage)->aData + ((pPage)->maskPage & __builtin_bswap16(*(u16*)(&(pPage)->aCellIdx[2*(i)]))));
+
+    ptrmapPutOvflPtr(pPage, pPage, pCell, &rc);
+
+    if( !pPage->leaf ){
+      Pgno childPgno = sqlite3Get4byte(pCell);
+      ptrmapPut(pBt, childPgno, 5, pgno, &rc);
+    }
+  }
+
+  if( !pPage->leaf ){
+    Pgno childPgno = sqlite3Get4byte(&pPage->aData[pPage->hdrOffset+8]);
+    ptrmapPut(pBt, childPgno, 5, pgno, &rc);
+  }
+
+  return rc;
+}
+# 3572 "src/btree.c"
+static int modifyPagePointer(MemPage *pPage, Pgno iFrom, Pgno iTo, u8 eType){
+  assert( sqlite3_mutex_held(pPage->pBt->mutex) );
+  assert( sqlite3PagerIswriteable(pPage->pDbPage) );
+  if( eType==4 ){
+
+    if( sqlite3Get4byte(pPage->aData)!=iFrom ){
+      return sqlite3CorruptError(3578);
+    }
+    sqlite3Put4byte(pPage->aData, iTo);
+  }else{
+    int i;
+    int nCell;
+    int rc;
+
+    rc = pPage->isInit ? 0 : btreeInitPage(pPage);
+    if( rc ) return rc;
+    nCell = pPage->nCell;
+
+    for(i=0; i<nCell; i++){
+      u8 *pCell = ((pPage)->aData + ((pPage)->maskPage & __builtin_bswap16(*(u16*)(&(pPage)->aCellIdx[2*(i)]))));
+      if( eType==3 ){
+        CellInfo info;
+        pPage->xParseCell(pPage, pCell, &info);
+        if( info.nLocal<info.nPayload ){
+          if( pCell+info.nSize > pPage->aData+pPage->pBt->usableSize ){
+            return sqlite3CorruptError(3597);
+          }
+          if( iFrom==sqlite3Get4byte(pCell+info.nSize-4) ){
+            sqlite3Put4byte(pCell+info.nSize-4, iTo);
+            break;
+          }
+        }
+      }else{
+        if( sqlite3Get4byte(pCell)==iFrom ){
+          sqlite3Put4byte(pCell, iTo);
+          break;
+        }
+      }
+    }
+
+    if( i==nCell ){
+      if( eType!=5 ||
+          sqlite3Get4byte(&pPage->aData[pPage->hdrOffset+8])!=iFrom ){
+        return sqlite3CorruptError(3615);
+      }
+      sqlite3Put4byte(&pPage->aData[pPage->hdrOffset+8], iTo);
+    }
+  }
+  return 0;
+}
+# 3633 "src/btree.c"
+static int relocatePage(
+  BtShared *pBt,
+  MemPage *pDbPage,
+  u8 eType,
+  Pgno iPtrPage,
+  Pgno iFreePage,
+  int isCommit
+){
+  MemPage *pPtrPage;
+  Pgno iDbPage = pDbPage->pgno;
+  Pager *pPager = pBt->pPager;
+  int rc;
+
+  assert( eType==4 || eType==3 ||
+      eType==5 || eType==1 );
+  assert( sqlite3_mutex_held(pBt->mutex) );
+  assert( pDbPage->pBt==pBt );
+  if( iDbPage<3 ) return sqlite3CorruptError(3650);
+
+
+ 
+                                           ;
+  rc = sqlite3PagerMovepage(pPager, pDbPage->pDbPage, iFreePage, isCommit);
+  if( rc!=0 ){
+    return rc;
+  }
+  pDbPage->pgno = iFreePage;
+# 3669 "src/btree.c"
+  if( eType==5 || eType==1 ){
+    rc = setChildPtrmaps(pDbPage);
+    if( rc!=0 ){
+      return rc;
+    }
+  }else{
+    Pgno nextOvfl = sqlite3Get4byte(pDbPage->aData);
+    if( nextOvfl!=0 ){
+      ptrmapPut(pBt, nextOvfl, 4, iFreePage, &rc);
+      if( rc!=0 ){
+        return rc;
+      }
+    }
+  }
+
+
+
+
+
+  if( eType!=1 ){
+    rc = btreeGetPage(pBt, iPtrPage, &pPtrPage, 0);
+    if( rc!=0 ){
+      return rc;
+    }
+    rc = sqlite3PagerWrite(pPtrPage->pDbPage);
+    if( rc!=0 ){
+      releasePage(pPtrPage);
+      return rc;
+    }
+    rc = modifyPagePointer(pPtrPage, iDbPage, iFreePage, eType);
+    releasePage(pPtrPage);
+    if( rc==0 ){
+      ptrmapPut(pBt, iFreePage, eType, iPtrPage, &rc);
+    }
+  }
+  return rc;
+}
+
+
+static int allocateBtreePage(BtShared *, MemPage **, Pgno *, Pgno, u8);
+# 3727 "src/btree.c"
+static int incrVacuumStep(BtShared *pBt, Pgno nFin, Pgno iLastPg, int bCommit){
+  Pgno nFreeList;
+  int rc;
+
+  assert( sqlite3_mutex_held(pBt->mutex) );
+  assert( iLastPg>nFin );
+
+  if( !(ptrmapPageno((pBt), (iLastPg))==(iLastPg)) && iLastPg!=((Pgno)((sqlite3PendingByte/((pBt)->pageSize))+1)) ){
+    u8 eType;
+    Pgno iPtrPage;
+
+    nFreeList = sqlite3Get4byte(&pBt->pPage1->aData[36]);
+    if( nFreeList==0 ){
+      return 101;
+    }
+
+    rc = ptrmapGet(pBt, iLastPg, &eType, &iPtrPage);
+    if( rc!=0 ){
+      return rc;
+    }
+    if( eType==1 ){
+      return sqlite3CorruptError(3748);
+    }
+
+    if( eType==2 ){
+      if( bCommit==0 ){
+
+
+
+
+
+        Pgno iFreePg;
+        MemPage *pFreePg;
+        rc = allocateBtreePage(pBt, &pFreePg, &iFreePg, iLastPg, 1);
+        if( rc!=0 ){
+          return rc;
+        }
+        assert( iFreePg==iLastPg );
+        releasePage(pFreePg);
+      }
+    } else {
+      Pgno iFreePg;
+      MemPage *pLastPg;
+      u8 eMode = 0;
+      Pgno iNear = 0;
+
+      rc = btreeGetPage(pBt, iLastPg, &pLastPg, 0);
+      if( rc!=0 ){
+        return rc;
+      }
+# 3785 "src/btree.c"
+      if( bCommit==0 ){
+        eMode = 2;
+        iNear = nFin;
+      }
+      do {
+        MemPage *pFreePg;
+        rc = allocateBtreePage(pBt, &pFreePg, &iFreePg, iNear, eMode);
+        if( rc!=0 ){
+          releasePage(pLastPg);
+          return rc;
+        }
+        releasePage(pFreePg);
+      }while( bCommit && iFreePg>nFin );
+      assert( iFreePg<iLastPg );
+
+      rc = relocatePage(pBt, pLastPg, eType, iPtrPage, iFreePg, bCommit);
+      releasePage(pLastPg);
+      if( rc!=0 ){
+        return rc;
+      }
+    }
+  }
+
+  if( bCommit==0 ){
+    do {
+      iLastPg--;
+    }while( iLastPg==((Pgno)((sqlite3PendingByte/((pBt)->pageSize))+1)) || (ptrmapPageno((pBt), (iLastPg))==(iLastPg)) );
+    pBt->bDoTruncate = 1;
+    pBt->nPage = iLastPg;
+  }
+  return 0;
+}
+
+
+
+
+
+
+static Pgno finalDbSize(BtShared *pBt, Pgno nOrig, Pgno nFree){
+  int nEntry;
+  Pgno nPtrmap;
+  Pgno nFin;
+
+  nEntry = pBt->usableSize/5;
+  nPtrmap = (nFree-nOrig+ptrmapPageno(pBt, nOrig)+nEntry)/nEntry;
+  nFin = nOrig - nFree - nPtrmap;
+  if( nOrig>((Pgno)((sqlite3PendingByte/((pBt)->pageSize))+1)) && nFin<((Pgno)((sqlite3PendingByte/((pBt)->pageSize))+1)) ){
+    nFin--;
+  }
+  while( (ptrmapPageno((pBt), (nFin))==(nFin)) || nFin==((Pgno)((sqlite3PendingByte/((pBt)->pageSize))+1)) ){
+    nFin--;
+  }
+
+  return nFin;
+}
+# 3849 "src/btree.c"
+int sqlite3BtreeIncrVacuum(Btree *p){
+  int rc;
+  BtShared *pBt = p->pBt;
+
+  sqlite3BtreeEnter(p);
+  assert( pBt->inTransaction==2 && p->inTrans==2 );
+  if( !pBt->autoVacuum ){
+    rc = 101;
+  }else{
+    Pgno nOrig = btreePagecount(pBt);
+    Pgno nFree = sqlite3Get4byte(&pBt->pPage1->aData[36]);
+    Pgno nFin = finalDbSize(pBt, nOrig, nFree);
+
+    if( nOrig<nFin ){
+      rc = sqlite3CorruptError(3863);
+    }else if( nFree>0 ){
+      rc = saveAllCursors(pBt, 0, 0);
+      if( rc==0 ){
+        invalidateAllOverflowCache(pBt);
+        rc = incrVacuumStep(pBt, nFin, nOrig, 0);
+      }
+      if( rc==0 ){
+        rc = sqlite3PagerWrite(pBt->pPage1->pDbPage);
+        sqlite3Put4byte(&pBt->pPage1->aData[28], pBt->nPage);
+      }
+    }else{
+      rc = 101;
+    }
+  }
+  sqlite3BtreeLeave(p);
+  return rc;
+}
+# 3891 "src/btree.c"
+static int autoVacuumCommit(BtShared *pBt){
+  int rc = 0;
+  Pager *pPager = pBt->pPager;
+ 
+
+  assert( sqlite3_mutex_held(pBt->mutex) );
+  invalidateAllOverflowCache(pBt);
+  assert(pBt->autoVacuum);
+  if( !pBt->incrVacuum ){
+    Pgno nFin;
+    Pgno nFree;
+    Pgno iFree;
+    Pgno nOrig;
+
+    nOrig = btreePagecount(pBt);
+    if( (ptrmapPageno((pBt), (nOrig))==(nOrig)) || nOrig==((Pgno)((sqlite3PendingByte/((pBt)->pageSize))+1)) ){
+
+
+
+
+      return sqlite3CorruptError(3911);
+    }
+
+    nFree = sqlite3Get4byte(&pBt->pPage1->aData[36]);
+    nFin = finalDbSize(pBt, nOrig, nFree);
+    if( nFin>nOrig ) return sqlite3CorruptError(3916);
+    if( nFin<nOrig ){
+      rc = saveAllCursors(pBt, 0, 0);
+    }
+    for(iFree=nOrig; iFree>nFin && rc==0; iFree--){
+      rc = incrVacuumStep(pBt, nFin, iFree, 1);
+    }
+    if( (rc==101 || rc==0) && nFree>0 ){
+      rc = sqlite3PagerWrite(pBt->pPage1->pDbPage);
+      sqlite3Put4byte(&pBt->pPage1->aData[32], 0);
+      sqlite3Put4byte(&pBt->pPage1->aData[36], 0);
+      sqlite3Put4byte(&pBt->pPage1->aData[28], nFin);
+      pBt->bDoTruncate = 1;
+      pBt->nPage = nFin;
+    }
+    if( rc!=0 ){
+      sqlite3PagerRollback(pPager);
+    }
+  }
+
+  assert( nRef>=sqlite3PagerRefcount(pPager) );
+  return rc;
+}
+# 3970 "src/btree.c"
+int sqlite3BtreeCommitPhaseOne(Btree *p, const char *zMaster){
+  int rc = 0;
+  if( p->inTrans==2 ){
+    BtShared *pBt = p->pBt;
+    sqlite3BtreeEnter(p);
+
+    if( pBt->autoVacuum ){
+      rc = autoVacuumCommit(pBt);
+      if( rc!=0 ){
+        sqlite3BtreeLeave(p);
+        return rc;
+      }
+    }
+    if( pBt->bDoTruncate ){
+      sqlite3PagerTruncateImage(pBt->pPager, pBt->nPage);
+    }
+
+    rc = sqlite3PagerCommitPhaseOne(pBt->pPager, zMaster, 0);
+    sqlite3BtreeLeave(p);
+  }
+  return rc;
+}
+
+
+
+
+
+static void btreeEndTransaction(Btree *p){
+  BtShared *pBt = p->pBt;
+  sqlite3 *db = p->db;
+  assert( sqlite3BtreeHoldsMutex(p) );
+
+
+  pBt->bDoTruncate = 0;
+
+  if( p->inTrans>0 && db->nVdbeRead>1 ){
+
+
+
+    downgradeAllSharedCacheTableLocks(p);
+    p->inTrans = 1;
+  }else{
+
+
+
+
+    if( p->inTrans!=0 ){
+      clearAllSharedCacheTableLocks(p);
+      pBt->nTransaction--;
+      if( 0==pBt->nTransaction ){
+        pBt->inTransaction = 0;
+      }
+    }
+
+
+
+    p->inTrans = 0;
+    unlockBtreeIfUnused(pBt);
+  }
+
+  assert( p->pBt->inTransaction!=0 || p->pBt->nTransaction==0 ); assert( p->pBt->inTransaction>=p->inTrans );;
+}
+# 4059 "src/btree.c"
+int sqlite3BtreeCommitPhaseTwo(Btree *p, int bCleanup){
+
+  if( p->inTrans==0 ) return 0;
+  sqlite3BtreeEnter(p);
+  assert( p->pBt->inTransaction!=0 || p->pBt->nTransaction==0 ); assert( p->pBt->inTransaction>=p->inTrans );;
+
+
+
+
+  if( p->inTrans==2 ){
+    int rc;
+    BtShared *pBt = p->pBt;
+    assert( pBt->inTransaction==2 );
+    assert( pBt->nTransaction>0 );
+    rc = sqlite3PagerCommitPhaseTwo(pBt->pPager);
+    if( rc!=0 && bCleanup==0 ){
+      sqlite3BtreeLeave(p);
+      return rc;
+    }
+    p->iDataVersion--;
+    pBt->inTransaction = 1;
+    btreeClearHasContent(pBt);
+  }
+
+  btreeEndTransaction(p);
+  sqlite3BtreeLeave(p);
+  return 0;
+}
+
+
+
+
+int sqlite3BtreeCommit(Btree *p){
+  int rc;
+  sqlite3BtreeEnter(p);
+  rc = sqlite3BtreeCommitPhaseOne(p, 0);
+  if( rc==0 ){
+    rc = sqlite3BtreeCommitPhaseTwo(p, 0);
+  }
+  sqlite3BtreeLeave(p);
+  return rc;
+}
+# 4128 "src/btree.c"
+int sqlite3BtreeTripAllCursors(Btree *pBtree, int errCode, int writeOnly){
+  BtCursor *p;
+  int rc = 0;
+
+  assert( (writeOnly==0 || writeOnly==1) && 0x01==1 );
+  if( pBtree ){
+    sqlite3BtreeEnter(pBtree);
+    for(p=pBtree->pBt->pCursor; p; p=p->pNext){
+      if( writeOnly && (p->curFlags & 0x01)==0 ){
+        if( p->eState==0 || p->eState==2 ){
+          rc = saveCursorPosition(p);
+          if( rc!=0 ){
+            (void)sqlite3BtreeTripAllCursors(pBtree, rc, 0);
+            break;
+          }
+        }
+      }else{
+        sqlite3BtreeClearCursor(p);
+        p->eState = 4;
+        p->skipNext = errCode;
+      }
+      btreeReleaseAllCursorPages(p);
+    }
+    sqlite3BtreeLeave(pBtree);
+  }
+  return rc;
+}
+
+
+
+
+
+static void btreeSetNPage(BtShared *pBt, MemPage *pPage1){
+  int nPage = sqlite3Get4byte(&pPage1->aData[28]);
+  ;
+  if( nPage==0 ) sqlite3PagerPagecount(pBt->pPager, &nPage);
+  ;
+  pBt->nPage = nPage;
+}
+# 4179 "src/btree.c"
+int sqlite3BtreeRollback(Btree *p, int tripCode, int writeOnly){
+  int rc;
+  BtShared *pBt = p->pBt;
+  MemPage *pPage1;
+
+  assert( writeOnly==1 || writeOnly==0 );
+  assert( tripCode==(4 | (2<<8)) || tripCode==0 );
+  sqlite3BtreeEnter(p);
+  if( tripCode==0 ){
+    rc = tripCode = saveAllCursors(pBt, 0, 0);
+    if( rc ) writeOnly = 0;
+  }else{
+    rc = 0;
+  }
+  if( tripCode ){
+    int rc2 = sqlite3BtreeTripAllCursors(p, tripCode, writeOnly);
+    assert( rc==0 || (writeOnly==0 && rc2==0) );
+    if( rc2!=0 ) rc = rc2;
+  }
+  assert( p->pBt->inTransaction!=0 || p->pBt->nTransaction==0 ); assert( p->pBt->inTransaction>=p->inTrans );;
+
+  if( p->inTrans==2 ){
+    int rc2;
+
+    assert( 2==pBt->inTransaction );
+    rc2 = sqlite3PagerRollback(pBt->pPager);
+    if( rc2!=0 ){
+      rc = rc2;
+    }
+
+
+
+
+    if( btreeGetPage(pBt, 1, &pPage1, 0)==0 ){
+      btreeSetNPage(pBt, pPage1);
+      releasePageOne(pPage1);
+    }
+    assert( countValidCursors(pBt, 1)==0 );
+    pBt->inTransaction = 1;
+    btreeClearHasContent(pBt);
+  }
+
+  btreeEndTransaction(p);
+  sqlite3BtreeLeave(p);
+  return rc;
+}
+# 4244 "src/btree.c"
+int sqlite3BtreeBeginStmt(Btree *p, int iStatement){
+  int rc;
+  BtShared *pBt = p->pBt;
+  sqlite3BtreeEnter(p);
+  assert( p->inTrans==2 );
+  assert( (pBt->btsFlags & 0x0001)==0 );
+  assert( iStatement>0 );
+  assert( iStatement>p->db->nSavepoint );
+  assert( pBt->inTransaction==2 );
+
+
+
+
+
+  rc = sqlite3PagerOpenSavepoint(pBt->pPager, iStatement);
+  sqlite3BtreeLeave(p);
+  return rc;
+}
+# 4275 "src/btree.c"
+int sqlite3BtreeSavepoint(Btree *p, int op, int iSavepoint){
+  int rc = 0;
+  if( p && p->inTrans==2 ){
+    BtShared *pBt = p->pBt;
+    assert( op==1 || op==2 );
+    assert( iSavepoint>=0 || (iSavepoint==-1 && op==2) );
+    sqlite3BtreeEnter(p);
+    if( op==2 ){
+      rc = saveAllCursors(pBt, 0, 0);
+    }
+    if( rc==0 ){
+      rc = sqlite3PagerSavepoint(pBt->pPager, op, iSavepoint);
+    }
+    if( rc==0 ){
+      if( iSavepoint<0 && (pBt->btsFlags & 0x0010)!=0 ){
+        pBt->nPage = 0;
+      }
+      rc = newDatabase(pBt);
+      btreeSetNPage(pBt, pBt->pPage1);
+
+
+
+      assert( (sqlite3Config.neverCorrupt==0) || pBt->nPage>0 );
+    }
+    sqlite3BtreeLeave(p);
+  }
+  return rc;
+}
+# 4346 "src/btree.c"
+static int btreeCursor(
+  Btree *p,
+  int iTable,
+  int wrFlag,
+  struct KeyInfo *pKeyInfo,
+  BtCursor *pCur
+){
+  BtShared *pBt = p->pBt;
+  BtCursor *pX;
+
+  assert( sqlite3BtreeHoldsMutex(p) );
+  assert( wrFlag==0
+       || wrFlag==0x00000004
+       || wrFlag==(0x00000004|0x00000008)
+  );
+
+
+
+
+
+  assert( hasSharedCacheTableLock(p, iTable, pKeyInfo!=0, (wrFlag?2:1)) );
+  assert( wrFlag==0 || !hasReadConflicts(p, iTable) );
+
+
+  assert( p->inTrans>0 );
+  assert( wrFlag==0 || p->inTrans==2 );
+  assert( pBt->pPage1 && pBt->pPage1->aData );
+  assert( wrFlag==0 || (pBt->btsFlags & 0x0001)==0 );
+
+  if( wrFlag ){
+    allocateTempSpace(pBt);
+    if( pBt->pTmpSpace==0 ) return 7;
+  }
+  if( iTable==1 && btreePagecount(pBt)==0 ){
+    assert( wrFlag==0 );
+    iTable = 0;
+  }
+
+
+
+  pCur->pgnoRoot = (Pgno)iTable;
+  pCur->iPage = -1;
+  pCur->pKeyInfo = pKeyInfo;
+  pCur->pBtree = p;
+  pCur->pBt = pBt;
+  pCur->curFlags = wrFlag ? 0x01 : 0;
+  pCur->curPagerFlags = wrFlag ? 0 : 0x02;
+
+
+  for(pX=pBt->pCursor; pX; pX=pX->pNext){
+    if( pX->pgnoRoot==(Pgno)iTable ){
+      pX->curFlags |= 0x20;
+      pCur->curFlags |= 0x20;
+    }
+  }
+  pCur->pNext = pBt->pCursor;
+  pBt->pCursor = pCur;
+  pCur->eState = 1;
+  return 0;
+}
+int sqlite3BtreeCursor(
+  Btree *p,
+  int iTable,
+  int wrFlag,
+  struct KeyInfo *pKeyInfo,
+  BtCursor *pCur
+){
+  int rc;
+  if( iTable<1 ){
+    rc = sqlite3CorruptError(4415);
+  }else{
+    sqlite3BtreeEnter(p);
+    rc = btreeCursor(p, iTable, wrFlag, pKeyInfo, pCur);
+    sqlite3BtreeLeave(p);
+  }
+  return rc;
+}
+# 4432 "src/btree.c"
+int sqlite3BtreeCursorSize(void){
+  return (((sizeof(BtCursor))+7)&~7);
+}
+# 4444 "src/btree.c"
+void sqlite3BtreeCursorZero(BtCursor *p){
+  memset(p, 0, ((int)((char*)&((BtCursor*)0)->pBt)));
+}
+
+
+
+
+
+int sqlite3BtreeCloseCursor(BtCursor *pCur){
+  Btree *pBtree = pCur->pBtree;
+  if( pBtree ){
+    BtShared *pBt = pCur->pBt;
+    sqlite3BtreeEnter(pBtree);
+    assert( pBt->pCursor!=0 );
+    if( pBt->pCursor==pCur ){
+      pBt->pCursor = pCur->pNext;
+    }else{
+      BtCursor *pPrev = pBt->pCursor;
+      do{
+        if( pPrev->pNext==pCur ){
+          pPrev->pNext = pCur->pNext;
+          break;
+        }
+        pPrev = pPrev->pNext;
+      }while( (pPrev) );
+    }
+    btreeReleaseAllCursorPages(pCur);
+    unlockBtreeIfUnused(pBt);
+    sqlite3_free(pCur->aOverflow);
+    sqlite3_free(pCur->pKey);
+    sqlite3BtreeLeave(pBtree);
+    pCur->pBtree = 0;
+  }
+  return 0;
+}
+# 4506 "src/btree.c"
+static void getCellInfo(BtCursor *pCur){
+  if( pCur->info.nSize==0 ){
+    pCur->curFlags |= 0x02;
+    btreeParseCell(pCur->pPage,pCur->ix,&pCur->info);
+  }else{
+    ;
+  }
+}
+# 4525 "src/btree.c"
+int sqlite3BtreeCursorIsValidNN(BtCursor *pCur){
+  assert( pCur!=0 );
+  return pCur->eState==0;
+}
+
+
+
+
+
+
+
+i64 sqlite3BtreeIntegerKey(BtCursor *pCur){
+  assert( cursorHoldsMutex(pCur) );
+  assert( pCur->eState==0 );
+  assert( pCur->curIntKey );
+  getCellInfo(pCur);
+  return pCur->info.nKey;
+}
+# 4567 "src/btree.c"
+u32 sqlite3BtreePayloadSize(BtCursor *pCur){
+  assert( cursorHoldsMutex(pCur) );
+  assert( pCur->eState==0 );
+  getCellInfo(pCur);
+  return pCur->info.nPayload;
+}
+# 4587 "src/btree.c"
+sqlite3_int64 sqlite3BtreeMaxRecordSize(BtCursor *pCur){
+  assert( cursorHoldsMutex(pCur) );
+  assert( pCur->eState==0 );
+  return pCur->pBt->pageSize * (sqlite3_int64)pCur->pBt->nPage;
+}
+# 4612 "src/btree.c"
+static int getOverflowPage(
+  BtShared *pBt,
+  Pgno ovfl,
+  MemPage **ppPage,
+  Pgno *pPgnoNext
+){
+  Pgno next = 0;
+  MemPage *pPage = 0;
+  int rc = 0;
+
+  assert( sqlite3_mutex_held(pBt->mutex) );
+  assert(pPgnoNext);
+# 4632 "src/btree.c"
+  if( pBt->autoVacuum ){
+    Pgno pgno;
+    Pgno iGuess = ovfl+1;
+    u8 eType;
+
+    while( (ptrmapPageno((pBt), (iGuess))==(iGuess)) || iGuess==((Pgno)((sqlite3PendingByte/((pBt)->pageSize))+1)) ){
+      iGuess++;
+    }
+
+    if( iGuess<=btreePagecount(pBt) ){
+      rc = ptrmapGet(pBt, iGuess, &eType, &pgno);
+      if( rc==0 && eType==4 && pgno==ovfl ){
+        next = iGuess;
+        rc = 101;
+      }
+    }
+  }
+
+
+  assert( next==0 || rc==101 );
+  if( rc==0 ){
+    rc = btreeGetPage(pBt, ovfl, &pPage, (ppPage==0) ? 0x02 : 0);
+    assert( rc==0 || pPage==0 );
+    if( rc==0 ){
+      next = sqlite3Get4byte(pPage->aData);
+    }
+  }
+
+  *pPgnoNext = next;
+  if( ppPage ){
+    *ppPage = pPage;
+  }else{
+    releasePage(pPage);
+  }
+  return (rc==101 ? 0 : rc);
+}
+# 4680 "src/btree.c"
+static int copyPayload(
+  void *pPayload,
+  void *pBuf,
+  int nByte,
+  int eOp,
+  DbPage *pDbPage
+){
+  if( eOp ){
+
+    int rc = sqlite3PagerWrite(pDbPage);
+    if( rc!=0 ){
+      return rc;
+    }
+    memcpy(pPayload, pBuf, nByte);
+  }else{
+
+    memcpy(pBuf, pPayload, nByte);
+  }
+  return 0;
+}
+# 4730 "src/btree.c"
+static int accessPayload(
+  BtCursor *pCur,
+  u32 offset,
+  u32 amt,
+  unsigned char *pBuf,
+  int eOp
+){
+  unsigned char *aPayload;
+  int rc = 0;
+  int iIdx = 0;
+  MemPage *pPage = pCur->pPage;
+  BtShared *pBt = pCur->pBt;
+
+
+
+
+  assert( pPage );
+  assert( eOp==0 || eOp==1 );
+  assert( pCur->eState==0 );
+  assert( pCur->ix<pPage->nCell );
+  assert( cursorHoldsMutex(pCur) );
+
+  getCellInfo(pCur);
+  aPayload = pCur->info.pPayload;
+  assert( offset+amt <= pCur->info.nPayload );
+
+  assert( aPayload > pPage->aData );
+  if( (uptr)(aPayload - pPage->aData) > (pBt->usableSize - pCur->info.nLocal) ){
+
+
+
+
+
+    return sqlite3CorruptError(4763);
+  }
+
+
+  if( offset<pCur->info.nLocal ){
+    int a = amt;
+    if( a+offset>pCur->info.nLocal ){
+      a = pCur->info.nLocal - offset;
+    }
+    rc = copyPayload(&aPayload[offset], pBuf, a, eOp, pPage->pDbPage);
+    offset = 0;
+    pBuf += a;
+    amt -= a;
+  }else{
+    offset -= pCur->info.nLocal;
+  }
+
+
+  if( rc==0 && amt>0 ){
+    const u32 ovflSize = pBt->usableSize - 4;
+    Pgno nextPage;
+
+    nextPage = sqlite3Get4byte(&aPayload[pCur->info.nLocal]);
+# 4794 "src/btree.c"
+    if( (pCur->curFlags & 0x04)==0 ){
+      int nOvfl = (pCur->info.nPayload-pCur->info.nLocal+ovflSize-1)/ovflSize;
+      if( pCur->aOverflow==0
+       || nOvfl*(int)sizeof(Pgno) > sqlite3MallocSize(pCur->aOverflow)
+      ){
+        Pgno *aNew = (Pgno*)sqlite3Realloc(
+            pCur->aOverflow, nOvfl*2*sizeof(Pgno)
+        );
+        if( aNew==0 ){
+          return 7;
+        }else{
+          pCur->aOverflow = aNew;
+        }
+      }
+      memset(pCur->aOverflow, 0, nOvfl*sizeof(Pgno));
+      pCur->curFlags |= 0x04;
+    }else{
+
+
+
+
+      if( pCur->aOverflow[offset/ovflSize] ){
+        iIdx = (offset/ovflSize);
+        nextPage = pCur->aOverflow[iIdx];
+        offset = (offset%ovflSize);
+      }
+    }
+
+    assert( rc==0 && amt>0 );
+    while( nextPage ){
+
+      assert( pCur->aOverflow[iIdx]==0
+              || pCur->aOverflow[iIdx]==nextPage
+              || (sqlite3Config.neverCorrupt==0) );
+      pCur->aOverflow[iIdx] = nextPage;
+
+      if( offset>=ovflSize ){
+
+
+
+
+
+
+        assert( pCur->curFlags & 0x04 );
+        assert( pCur->pBtree->db==pBt->db );
+        if( pCur->aOverflow[iIdx+1] ){
+          nextPage = pCur->aOverflow[iIdx+1];
+        }else{
+          rc = getOverflowPage(pBt, nextPage, 0, &nextPage);
+        }
+        offset -= ovflSize;
+      }else{
+
+
+
+        int a = amt;
+        if( a + offset > ovflSize ){
+          a = ovflSize - offset;
+        }
+# 4884 "src/btree.c"
+        {
+          DbPage *pDbPage;
+          rc = sqlite3PagerGet(pBt->pPager, nextPage, &pDbPage,
+              (eOp==0 ? 0x02 : 0)
+          );
+          if( rc==0 ){
+            aPayload = sqlite3PagerGetData(pDbPage);
+            nextPage = sqlite3Get4byte(aPayload);
+            rc = copyPayload(&aPayload[offset+4], pBuf, a, eOp, pDbPage);
+            sqlite3PagerUnref(pDbPage);
+            offset = 0;
+          }
+        }
+        amt -= a;
+        if( amt==0 ) return rc;
+        pBuf += a;
+      }
+      if( rc ) break;
+      iIdx++;
+    }
+  }
+
+  if( rc==0 && amt>0 ){
+
+    return sqlite3CorruptError(4908);
+  }
+  return rc;
+}
+# 4930 "src/btree.c"
+int sqlite3BtreePayload(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){
+  assert( cursorHoldsMutex(pCur) );
+  assert( pCur->eState==0 );
+  assert( pCur->iPage>=0 && pCur->pPage );
+  assert( pCur->ix<pCur->pPage->nCell );
+  return accessPayload(pCur, offset, amt, (unsigned char*)pBuf, 0);
+}
+
+
+
+
+
+
+
+static int accessPayloadChecked(
+  BtCursor *pCur,
+  u32 offset,
+  u32 amt,
+  void *pBuf
+){
+  int rc;
+  if ( pCur->eState==1 ){
+    return 4;
+  }
+  assert( cursorOwnsBtShared(pCur) );
+  rc = btreeRestoreCursorPosition(pCur);
+  return rc ? rc : accessPayload(pCur, offset, amt, pBuf, 0);
+}
+int sqlite3BtreePayloadChecked(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){
+  if( pCur->eState==0 ){
+    assert( cursorOwnsBtShared(pCur) );
+    return accessPayload(pCur, offset, amt, pBuf, 0);
+  }else{
+    return accessPayloadChecked(pCur, offset, amt, pBuf);
+  }
+}
+# 4987 "src/btree.c"
+static const void *fetchPayload(
+  BtCursor *pCur,
+  u32 *pAmt
+){
+  int amt;
+  assert( pCur!=0 && pCur->iPage>=0 && pCur->pPage);
+  assert( pCur->eState==0 );
+  assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
+  assert( cursorOwnsBtShared(pCur) );
+  assert( pCur->ix<pCur->pPage->nCell );
+  assert( pCur->info.nSize>0 );
+  assert( pCur->info.pPayload>pCur->pPage->aData || (sqlite3Config.neverCorrupt==0) );
+  assert( pCur->info.pPayload<pCur->pPage->aDataEnd ||(sqlite3Config.neverCorrupt==0));
+  amt = pCur->info.nLocal;
+  if( amt>(int)(pCur->pPage->aDataEnd - pCur->info.pPayload) ){
+
+
+    assert( (sqlite3Config.neverCorrupt==0) );
+    amt = ((0)>((int)(pCur->pPage->aDataEnd - pCur->info.pPayload))?(0):((int)(pCur->pPage->aDataEnd - pCur->info.pPayload)));
+  }
+  *pAmt = (u32)amt;
+  return (void*)pCur->info.pPayload;
+}
+# 5026 "src/btree.c"
+const void *sqlite3BtreePayloadFetch(BtCursor *pCur, u32 *pAmt){
+  return fetchPayload(pCur, pAmt);
+}
+# 5040 "src/btree.c"
+static int moveToChild(BtCursor *pCur, u32 newPgno){
+  BtShared *pBt = pCur->pBt;
+
+  assert( cursorOwnsBtShared(pCur) );
+  assert( pCur->eState==0 );
+  assert( pCur->iPage<20 );
+  assert( pCur->iPage>=0 );
+  if( pCur->iPage>=(20 -1) ){
+    return sqlite3CorruptError(5048);
+  }
+  pCur->info.nSize = 0;
+  pCur->curFlags &= ~(0x02|0x04);
+  pCur->aiIdx[pCur->iPage] = pCur->ix;
+  pCur->apPage[pCur->iPage] = pCur->pPage;
+  pCur->ix = 0;
+  pCur->iPage++;
+  return getAndInitPage(pBt, newPgno, &pCur->pPage, pCur, pCur->curPagerFlags);
+}
+# 5089 "src/btree.c"
+static void moveToParent(BtCursor *pCur){
+  MemPage *pLeaf;
+  assert( cursorOwnsBtShared(pCur) );
+  assert( pCur->eState==0 );
+  assert( pCur->iPage>0 );
+  assert( pCur->pPage );
+ 
+
+
+
+   ;
+  ;
+  pCur->info.nSize = 0;
+  pCur->curFlags &= ~(0x02|0x04);
+  pCur->ix = pCur->aiIdx[pCur->iPage-1];
+  pLeaf = pCur->pPage;
+  pCur->pPage = pCur->apPage[--pCur->iPage];
+  releasePageNotNull(pLeaf);
+}
+# 5130 "src/btree.c"
+static int moveToRoot(BtCursor *pCur){
+  MemPage *pRoot;
+  int rc = 0;
+
+  assert( cursorOwnsBtShared(pCur) );
+  assert( 1 < 3 );
+  assert( 0 < 3 );
+  assert( 4 > 3 );
+  assert( pCur->eState < 3 || pCur->iPage<0 );
+  assert( pCur->pgnoRoot>0 || pCur->iPage<0 );
+
+  if( pCur->iPage>=0 ){
+    if( pCur->iPage ){
+      releasePageNotNull(pCur->pPage);
+      while( --pCur->iPage ){
+        releasePageNotNull(pCur->apPage[pCur->iPage]);
+      }
+      pCur->pPage = pCur->apPage[0];
+      goto skip_init;
+    }
+  }else if( pCur->pgnoRoot==0 ){
+    pCur->eState = 1;
+    return 16;
+  }else{
+    assert( pCur->iPage==(-1) );
+    if( pCur->eState>=3 ){
+      if( pCur->eState==4 ){
+        assert( pCur->skipNext!=0 );
+        return pCur->skipNext;
+      }
+      sqlite3BtreeClearCursor(pCur);
+    }
+    rc = getAndInitPage(pCur->pBtree->pBt, pCur->pgnoRoot, &pCur->pPage,
+                        0, pCur->curPagerFlags);
+    if( rc!=0 ){
+      pCur->eState = 1;
+      return rc;
+    }
+    pCur->iPage = 0;
+    pCur->curIntKey = pCur->pPage->intKey;
+  }
+  pRoot = pCur->pPage;
+  assert( pRoot->pgno==pCur->pgnoRoot );
+# 5184 "src/btree.c"
+  assert( pRoot->intKey==1 || pRoot->intKey==0 );
+  if( pRoot->isInit==0 || (pCur->pKeyInfo==0)!=pRoot->intKey ){
+    return sqlite3CorruptError(5186);
+  }
+
+skip_init:
+  pCur->ix = 0;
+  pCur->info.nSize = 0;
+  pCur->curFlags &= ~(0x08|0x02|0x04);
+
+  pRoot = pCur->pPage;
+  if( pRoot->nCell>0 ){
+    pCur->eState = 0;
+  }else if( !pRoot->leaf ){
+    Pgno subpage;
+    if( pRoot->pgno!=1 ) return sqlite3CorruptError(5199);
+    subpage = sqlite3Get4byte(&pRoot->aData[pRoot->hdrOffset+8]);
+    pCur->eState = 0;
+    rc = moveToChild(pCur, subpage);
+  }else{
+    pCur->eState = 1;
+    rc = 16;
+  }
+  return rc;
+}
+# 5217 "src/btree.c"
+static int moveToLeftmost(BtCursor *pCur){
+  Pgno pgno;
+  int rc = 0;
+  MemPage *pPage;
+
+  assert( cursorOwnsBtShared(pCur) );
+  assert( pCur->eState==0 );
+  while( rc==0 && !(pPage = pCur->pPage)->leaf ){
+    assert( pCur->ix<pPage->nCell );
+    pgno = sqlite3Get4byte(((pPage)->aData + ((pPage)->maskPage & __builtin_bswap16(*(u16*)(&(pPage)->aCellIdx[2*(pCur->ix)])))));
+    rc = moveToChild(pCur, pgno);
+  }
+  return rc;
+}
+# 5242 "src/btree.c"
+static int moveToRightmost(BtCursor *pCur){
+  Pgno pgno;
+  int rc = 0;
+  MemPage *pPage = 0;
+
+  assert( cursorOwnsBtShared(pCur) );
+  assert( pCur->eState==0 );
+  while( !(pPage = pCur->pPage)->leaf ){
+    pgno = sqlite3Get4byte(&pPage->aData[pPage->hdrOffset+8]);
+    pCur->ix = pPage->nCell;
+    rc = moveToChild(pCur, pgno);
+    if( rc ) return rc;
+  }
+  pCur->ix = pPage->nCell-1;
+  assert( pCur->info.nSize==0 );
+  assert( (pCur->curFlags & 0x02)==0 );
+  return 0;
+}
+
+
+
+
+
+int sqlite3BtreeFirst(BtCursor *pCur, int *pRes){
+  int rc;
+
+  assert( cursorOwnsBtShared(pCur) );
+  assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
+  rc = moveToRoot(pCur);
+  if( rc==0 ){
+    assert( pCur->pPage->nCell>0 );
+    *pRes = 0;
+    rc = moveToLeftmost(pCur);
+  }else if( rc==16 ){
+    assert( pCur->pgnoRoot==0 || pCur->pPage->nCell==0 );
+    *pRes = 1;
+    rc = 0;
+  }
+  return rc;
+}
+
+
+
+
+
+int sqlite3BtreeLast(BtCursor *pCur, int *pRes){
+  int rc;
+
+  assert( cursorOwnsBtShared(pCur) );
+  assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
+
+
+  if( 0==pCur->eState && (pCur->curFlags & 0x08)!=0 ){
+# 5305 "src/btree.c"
+    *pRes = 0;
+    return 0;
+  }
+
+  rc = moveToRoot(pCur);
+  if( rc==0 ){
+    assert( pCur->eState==0 );
+    *pRes = 0;
+    rc = moveToRightmost(pCur);
+    if( rc==0 ){
+      pCur->curFlags |= 0x08;
+    }else{
+      pCur->curFlags &= ~0x08;
+    }
+  }else if( rc==16 ){
+    assert( pCur->pgnoRoot==0 || pCur->pPage->nCell==0 );
+    *pRes = 1;
+    rc = 0;
+  }
+  return rc;
+}
+# 5357 "src/btree.c"
+int sqlite3BtreeMovetoUnpacked(
+  BtCursor *pCur,
+  UnpackedRecord *pIdxKey,
+  i64 intKey,
+  int biasRight,
+  int *pRes
+){
+  int rc;
+  RecordCompare xRecordCompare;
+
+  assert( cursorOwnsBtShared(pCur) );
+  assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
+  assert( pRes );
+  assert( (pIdxKey==0)==(pCur->pKeyInfo==0) );
+  assert( pCur->eState!=0 || (pIdxKey==0)==(pCur->curIntKey!=0) );
+
+
+
+  if( pIdxKey==0
+   && pCur->eState==0 && (pCur->curFlags & 0x02)!=0
+  ){
+    if( pCur->info.nKey==intKey ){
+      *pRes = 0;
+      return 0;
+    }
+    if( pCur->info.nKey<intKey ){
+      if( (pCur->curFlags & 0x08)!=0 ){
+        *pRes = -1;
+        return 0;
+      }
+
+
+
+
+      if( pCur->info.nKey+1==intKey ){
+        *pRes = 0;
+        rc = sqlite3BtreeNext(pCur, 0);
+        if( rc==0 ){
+          getCellInfo(pCur);
+          if( pCur->info.nKey==intKey ){
+            return 0;
+          }
+        }else if( rc==101 ){
+          rc = 0;
+        }else{
+          return rc;
+        }
+      }
+    }
+  }
+
+  if( pIdxKey ){
+    xRecordCompare = sqlite3VdbeFindCompare(pIdxKey);
+    pIdxKey->errCode = 0;
+    assert( pIdxKey->default_rc==1
+         || pIdxKey->default_rc==0
+         || pIdxKey->default_rc==-1
+    );
+  }else{
+    xRecordCompare = 0;
+  }
+
+  rc = moveToRoot(pCur);
+  if( rc ){
+    if( rc==16 ){
+      assert( pCur->pgnoRoot==0 || pCur->pPage->nCell==0 );
+      *pRes = -1;
+      return 0;
+    }
+    return rc;
+  }
+  assert( pCur->pPage );
+  assert( pCur->pPage->isInit );
+  assert( pCur->eState==0 );
+  assert( pCur->pPage->nCell > 0 );
+  assert( pCur->iPage==0 || pCur->apPage[0]->intKey==pCur->curIntKey );
+  assert( pCur->curIntKey || pIdxKey );
+  for(;;){
+    int lwr, upr, idx, c;
+    Pgno chldPg;
+    MemPage *pPage = pCur->pPage;
+    u8 *pCell;
+
+
+
+
+
+
+
+    assert( pPage->nCell>0 );
+    assert( pPage->intKey==(pIdxKey==0) );
+    lwr = 0;
+    upr = pPage->nCell-1;
+    assert( biasRight==0 || biasRight==1 );
+    idx = upr>>(1-biasRight);
+    pCur->ix = (u16)idx;
+    if( xRecordCompare==0 ){
+      for(;;){
+        i64 nCellKey;
+        pCell = ((pPage)->aDataOfst + ((pPage)->maskPage & __builtin_bswap16(*(u16*)(&(pPage)->aCellIdx[2*(idx)]))));
+        if( pPage->intKeyLeaf ){
+          while( 0x80 <= *(pCell++) ){
+            if( pCell>=pPage->aDataEnd ){
+              return sqlite3CorruptError(5460);
+            }
+          }
+        }
+        sqlite3GetVarint(pCell, (u64*)&nCellKey);
+        if( nCellKey<intKey ){
+          lwr = idx+1;
+          if( lwr>upr ){ c = -1; break; }
+        }else if( nCellKey>intKey ){
+          upr = idx-1;
+          if( lwr>upr ){ c = +1; break; }
+        }else{
+          assert( nCellKey==intKey );
+          pCur->ix = (u16)idx;
+          if( !pPage->leaf ){
+            lwr = idx;
+            goto moveto_next_layer;
+          }else{
+            pCur->curFlags |= 0x02;
+            pCur->info.nKey = nCellKey;
+            pCur->info.nSize = 0;
+            *pRes = 0;
+            return 0;
+          }
+        }
+        assert( lwr+upr>=0 );
+        idx = (lwr+upr)>>1;
+      }
+    }else{
+      for(;;){
+        int nCell;
+        pCell = ((pPage)->aDataOfst + ((pPage)->maskPage & __builtin_bswap16(*(u16*)(&(pPage)->aCellIdx[2*(idx)]))));
+# 5501 "src/btree.c"
+        nCell = pCell[0];
+        if( nCell<=pPage->max1bytePayload ){
+
+
+
+          ;
+          c = xRecordCompare(nCell, (void*)&pCell[1], pIdxKey);
+        }else if( !(pCell[1] & 0x80)
+          && (nCell = ((nCell&0x7f)<<7) + pCell[1])<=pPage->maxLocal
+        ){
+
+
+          ;
+          c = xRecordCompare(nCell, (void*)&pCell[2], pIdxKey);
+        }else{
+# 5525 "src/btree.c"
+          void *pCellKey;
+          u8 * const pCellBody = pCell - pPage->childPtrSize;
+          const int nOverrun = 18;
+          pPage->xParseCell(pPage, pCellBody, &pCur->info);
+          nCell = (int)pCur->info.nKey;
+          ;
+          ;
+          ;
+          ;
+          if( nCell<2 || nCell/pCur->pBt->usableSize>pCur->pBt->nPage ){
+            rc = sqlite3CorruptError(5535);
+            goto moveto_finish;
+          }
+          pCellKey = sqlite3Malloc( nCell+nOverrun );
+          if( pCellKey==0 ){
+            rc = 7;
+            goto moveto_finish;
+          }
+          pCur->ix = (u16)idx;
+          rc = accessPayload(pCur, 0, nCell, (unsigned char*)pCellKey, 0);
+          memset(((u8*)pCellKey)+nCell,0,nOverrun);
+          pCur->curFlags &= ~0x04;
+          if( rc ){
+            sqlite3_free(pCellKey);
+            goto moveto_finish;
+          }
+          c = sqlite3VdbeRecordCompare(nCell, pCellKey, pIdxKey);
+          sqlite3_free(pCellKey);
+        }
+        assert(
+            (pIdxKey->errCode!=11 || c==0)
+         && (pIdxKey->errCode!=7 || pCur->pBtree->db->mallocFailed)
+        );
+        if( c<0 ){
+          lwr = idx+1;
+        }else if( c>0 ){
+          upr = idx-1;
+        }else{
+          assert( c==0 );
+          *pRes = 0;
+          rc = 0;
+          pCur->ix = (u16)idx;
+          if( pIdxKey->errCode ) rc = sqlite3CorruptError(5567);
+          goto moveto_finish;
+        }
+        if( lwr>upr ) break;
+        assert( lwr+upr>=0 );
+        idx = (lwr+upr)>>1;
+      }
+    }
+    assert( lwr==upr+1 || (pPage->intKey && !pPage->leaf) );
+    assert( pPage->isInit );
+    if( pPage->leaf ){
+      assert( pCur->ix<pCur->pPage->nCell );
+      pCur->ix = (u16)idx;
+      *pRes = c;
+      rc = 0;
+      goto moveto_finish;
+    }
+moveto_next_layer:
+    if( lwr>=pPage->nCell ){
+      chldPg = sqlite3Get4byte(&pPage->aData[pPage->hdrOffset+8]);
+    }else{
+      chldPg = sqlite3Get4byte(((pPage)->aData + ((pPage)->maskPage & __builtin_bswap16(*(u16*)(&(pPage)->aCellIdx[2*(lwr)])))));
+    }
+    pCur->ix = (u16)lwr;
+    rc = moveToChild(pCur, chldPg);
+    if( rc ) break;
+  }
+moveto_finish:
+  pCur->info.nSize = 0;
+  assert( (pCur->curFlags & 0x04)==0 );
+  return rc;
+}
+# 5608 "src/btree.c"
+int sqlite3BtreeEof(BtCursor *pCur){
+
+
+
+
+  return (0!=pCur->eState);
+}
+
+
+
+
+
+
+i64 sqlite3BtreeRowCountEst(BtCursor *pCur){
+  i64 n;
+  u8 i;
+
+  assert( cursorOwnsBtShared(pCur) );
+  assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
+
+
+
+
+  if( (pCur->eState!=0) ) return -1;
+  if( (pCur->pPage->leaf==0) ) return -1;
+
+  n = pCur->pPage->nCell;
+  for(i=0; i<pCur->iPage; i++){
+    n *= pCur->apPage[i]->nCell;
+  }
+  return n;
+}
+# 5661 "src/btree.c"
+static int btreeNext(BtCursor *pCur){
+  int rc;
+  int idx;
+  MemPage *pPage;
+
+  assert( cursorOwnsBtShared(pCur) );
+  if( pCur->eState!=0 ){
+    assert( (pCur->curFlags & 0x04)==0 );
+    rc = (pCur->eState>=3 ? btreeRestoreCursorPosition(pCur) : 0);
+    if( rc!=0 ){
+      return rc;
+    }
+    if( 1==pCur->eState ){
+      return 101;
+    }
+    if( pCur->eState==2 ){
+      pCur->eState = 0;
+      if( pCur->skipNext>0 ) return 0;
+    }
+  }
+
+  pPage = pCur->pPage;
+  idx = ++pCur->ix;
+  if( !pPage->isInit ){
+
+
+
+
+
+
+
+    return sqlite3CorruptError(5692);
+  }
+
+
+
+
+
+
+  ;
+
+  if( idx>=pPage->nCell ){
+    if( !pPage->leaf ){
+      rc = moveToChild(pCur, sqlite3Get4byte(&pPage->aData[pPage->hdrOffset+8]));
+      if( rc ) return rc;
+      return moveToLeftmost(pCur);
+    }
+    do{
+      if( pCur->iPage==0 ){
+        pCur->eState = 1;
+        return 101;
+      }
+      moveToParent(pCur);
+      pPage = pCur->pPage;
+    }while( pCur->ix>=pPage->nCell );
+    if( pPage->intKey ){
+      return sqlite3BtreeNext(pCur, 0);
+    }else{
+      return 0;
+    }
+  }
+  if( pPage->leaf ){
+    return 0;
+  }else{
+    return moveToLeftmost(pCur);
+  }
+}
+int sqlite3BtreeNext(BtCursor *pCur, int flags){
+  MemPage *pPage;
+  (void)(flags);
+  assert( cursorOwnsBtShared(pCur) );
+  assert( flags==0 || flags==1 );
+  pCur->info.nSize = 0;
+  pCur->curFlags &= ~(0x02|0x04);
+  if( pCur->eState!=0 ) return btreeNext(pCur);
+  pPage = pCur->pPage;
+  if( (++pCur->ix)>=pPage->nCell ){
+    pCur->ix--;
+    return btreeNext(pCur);
+  }
+  if( pPage->leaf ){
+    return 0;
+  }else{
+    return moveToLeftmost(pCur);
+  }
+}
+# 5768 "src/btree.c"
+static int btreePrevious(BtCursor *pCur){
+  int rc;
+  MemPage *pPage;
+
+  assert( cursorOwnsBtShared(pCur) );
+  assert( (pCur->curFlags & (0x08|0x04|0x02))==0 );
+  assert( pCur->info.nSize==0 );
+  if( pCur->eState!=0 ){
+    rc = (pCur->eState>=3 ? btreeRestoreCursorPosition(pCur) : 0);
+    if( rc!=0 ){
+      return rc;
+    }
+    if( 1==pCur->eState ){
+      return 101;
+    }
+    if( 2==pCur->eState ){
+      pCur->eState = 0;
+      if( pCur->skipNext<0 ) return 0;
+    }
+  }
+
+  pPage = pCur->pPage;
+  assert( pPage->isInit );
+  if( !pPage->leaf ){
+    int idx = pCur->ix;
+    rc = moveToChild(pCur, sqlite3Get4byte(((pPage)->aData + ((pPage)->maskPage & __builtin_bswap16(*(u16*)(&(pPage)->aCellIdx[2*(idx)]))))));
+    if( rc ) return rc;
+    rc = moveToRightmost(pCur);
+  }else{
+    while( pCur->ix==0 ){
+      if( pCur->iPage==0 ){
+        pCur->eState = 1;
+        return 101;
+      }
+      moveToParent(pCur);
+    }
+    assert( pCur->info.nSize==0 );
+    assert( (pCur->curFlags & (0x04))==0 );
+
+    pCur->ix--;
+    pPage = pCur->pPage;
+    if( pPage->intKey && !pPage->leaf ){
+      rc = sqlite3BtreePrevious(pCur, 0);
+    }else{
+      rc = 0;
+    }
+  }
+  return rc;
+}
+int sqlite3BtreePrevious(BtCursor *pCur, int flags){
+  assert( cursorOwnsBtShared(pCur) );
+  assert( flags==0 || flags==1 );
+  (void)(flags);
+  pCur->curFlags &= ~(0x08|0x04|0x02);
+  pCur->info.nSize = 0;
+  if( pCur->eState!=0
+   || pCur->ix==0
+   || pCur->pPage->leaf==0
+  ){
+    return btreePrevious(pCur);
+  }
+  pCur->ix--;
+  return 0;
+}
+# 5855 "src/btree.c"
+static int allocateBtreePage(
+  BtShared *pBt,
+  MemPage **ppPage,
+  Pgno *pPgno,
+  Pgno nearby,
+  u8 eMode
+){
+  MemPage *pPage1;
+  int rc;
+  u32 n;
+  u32 k;
+  MemPage *pTrunk = 0;
+  MemPage *pPrevTrunk = 0;
+  Pgno mxPage;
+
+  assert( sqlite3_mutex_held(pBt->mutex) );
+  assert( eMode==0 || (nearby>0 && (pBt->autoVacuum)) );
+  pPage1 = pBt->pPage1;
+  mxPage = btreePagecount(pBt);
+
+
+  n = sqlite3Get4byte(&pPage1->aData[36]);
+  ;
+  if( n>=mxPage ){
+    return sqlite3CorruptError(5879);
+  }
+  if( n>0 ){
+
+    Pgno iTrunk;
+    u8 searchList = 0;
+    u32 nSearch = 0;
+
+
+
+
+
+
+    if( eMode==1 ){
+      if( nearby<=mxPage ){
+        u8 eType;
+        assert( nearby>0 );
+        assert( pBt->autoVacuum );
+        rc = ptrmapGet(pBt, nearby, &eType, 0);
+        if( rc ) return rc;
+        if( eType==2 ){
+          searchList = 1;
+        }
+      }
+    }else if( eMode==2 ){
+      searchList = 1;
+    }
+
+
+
+
+
+    rc = sqlite3PagerWrite(pPage1->pDbPage);
+    if( rc ) return rc;
+    sqlite3Put4byte(&pPage1->aData[36], n-1);
+
+
+
+
+
+
+    do {
+      pPrevTrunk = pTrunk;
+      if( pPrevTrunk ){
+
+
+
+        iTrunk = sqlite3Get4byte(&pPrevTrunk->aData[0]);
+      }else{
+
+
+
+        iTrunk = sqlite3Get4byte(&pPage1->aData[32]);
+      }
+      ;
+      if( iTrunk>mxPage || nSearch++ > n ){
+        rc = sqlite3CorruptError(5935);
+      }else{
+        rc = btreeGetUnusedPage(pBt, iTrunk, &pTrunk, 0);
+      }
+      if( rc ){
+        pTrunk = 0;
+        goto end_allocate_page;
+      }
+      assert( pTrunk!=0 );
+      assert( pTrunk->aData!=0 );
+
+
+      k = sqlite3Get4byte(&pTrunk->aData[4]);
+      if( k==0 && !searchList ){
+
+
+
+        assert( pPrevTrunk==0 );
+        rc = sqlite3PagerWrite(pTrunk->pDbPage);
+        if( rc ){
+          goto end_allocate_page;
+        }
+        *pPgno = iTrunk;
+        memcpy(&pPage1->aData[32], &pTrunk->aData[0], 4);
+        *ppPage = pTrunk;
+        pTrunk = 0;
+        ;
+      }else if( k>(u32)(pBt->usableSize/4 - 2) ){
+
+        rc = sqlite3CorruptError(5964);
+        goto end_allocate_page;
+
+      }else if( searchList
+            && (nearby==iTrunk || (iTrunk<nearby && eMode==2))
+      ){
+
+
+
+        *pPgno = iTrunk;
+        *ppPage = pTrunk;
+        searchList = 0;
+        rc = sqlite3PagerWrite(pTrunk->pDbPage);
+        if( rc ){
+          goto end_allocate_page;
+        }
+        if( k==0 ){
+          if( !pPrevTrunk ){
+            memcpy(&pPage1->aData[32], &pTrunk->aData[0], 4);
+          }else{
+            rc = sqlite3PagerWrite(pPrevTrunk->pDbPage);
+            if( rc!=0 ){
+              goto end_allocate_page;
+            }
+            memcpy(&pPrevTrunk->aData[0], &pTrunk->aData[0], 4);
+          }
+        }else{
+
+
+
+
+          MemPage *pNewTrunk;
+          Pgno iNewTrunk = sqlite3Get4byte(&pTrunk->aData[8]);
+          if( iNewTrunk>mxPage ){
+            rc = sqlite3CorruptError(5998);
+            goto end_allocate_page;
+          }
+          ;
+          rc = btreeGetUnusedPage(pBt, iNewTrunk, &pNewTrunk, 0);
+          if( rc!=0 ){
+            goto end_allocate_page;
+          }
+          rc = sqlite3PagerWrite(pNewTrunk->pDbPage);
+          if( rc!=0 ){
+            releasePage(pNewTrunk);
+            goto end_allocate_page;
+          }
+          memcpy(&pNewTrunk->aData[0], &pTrunk->aData[0], 4);
+          sqlite3Put4byte(&pNewTrunk->aData[4], k-1);
+          memcpy(&pNewTrunk->aData[8], &pTrunk->aData[12], (k-1)*4);
+          releasePage(pNewTrunk);
+          if( !pPrevTrunk ){
+            assert( sqlite3PagerIswriteable(pPage1->pDbPage) );
+            sqlite3Put4byte(&pPage1->aData[32], iNewTrunk);
+          }else{
+            rc = sqlite3PagerWrite(pPrevTrunk->pDbPage);
+            if( rc ){
+              goto end_allocate_page;
+            }
+            sqlite3Put4byte(&pPrevTrunk->aData[0], iNewTrunk);
+          }
+        }
+        pTrunk = 0;
+        ;
+
+      }else if( k>0 ){
+
+        u32 closest;
+        Pgno iPage;
+        unsigned char *aData = pTrunk->aData;
+        if( nearby>0 ){
+          u32 i;
+          closest = 0;
+          if( eMode==2 ){
+            for(i=0; i<k; i++){
+              iPage = sqlite3Get4byte(&aData[8+i*4]);
+              if( iPage<=nearby ){
+                closest = i;
+                break;
+              }
+            }
+          }else{
+            int dist;
+            dist = sqlite3AbsInt32(sqlite3Get4byte(&aData[8]) - nearby);
+            for(i=1; i<k; i++){
+              int d2 = sqlite3AbsInt32(sqlite3Get4byte(&aData[8+i*4]) - nearby);
+              if( d2<dist ){
+                closest = i;
+                dist = d2;
+              }
+            }
+          }
+        }else{
+          closest = 0;
+        }
+
+        iPage = sqlite3Get4byte(&aData[8+closest*4]);
+        ;
+        if( iPage>mxPage ){
+          rc = sqlite3CorruptError(6063);
+          goto end_allocate_page;
+        }
+        ;
+        if( !searchList
+         || (iPage==nearby || (iPage<nearby && eMode==2))
+        ){
+          int noContent;
+          *pPgno = iPage;
+         
+
+                                                          ;
+          rc = sqlite3PagerWrite(pTrunk->pDbPage);
+          if( rc ) goto end_allocate_page;
+          if( closest<k-1 ){
+            memcpy(&aData[8+closest*4], &aData[4+k*4], 4);
+          }
+          sqlite3Put4byte(&aData[4], k-1);
+          noContent = !btreeGetHasContent(pBt, *pPgno)? 0x01 : 0;
+          rc = btreeGetUnusedPage(pBt, *pPgno, ppPage, noContent);
+          if( rc==0 ){
+            rc = sqlite3PagerWrite((*ppPage)->pDbPage);
+            if( rc!=0 ){
+              releasePage(*ppPage);
+              *ppPage = 0;
+            }
+          }
+          searchList = 0;
+        }
+      }
+      releasePage(pPrevTrunk);
+      pPrevTrunk = 0;
+    }while( searchList );
+  }else{
+# 6115 "src/btree.c"
+    int bNoContent = (0==(pBt->bDoTruncate))? 0x01:0;
+
+    rc = sqlite3PagerWrite(pBt->pPage1->pDbPage);
+    if( rc ) return rc;
+    pBt->nPage++;
+    if( pBt->nPage==((Pgno)((sqlite3PendingByte/((pBt)->pageSize))+1)) ) pBt->nPage++;
+
+
+    if( pBt->autoVacuum && (ptrmapPageno((pBt), (pBt->nPage))==(pBt->nPage)) ){
+
+
+
+
+      MemPage *pPg = 0;
+      ;
+      assert( pBt->nPage!=((Pgno)((sqlite3PendingByte/((pBt)->pageSize))+1)) );
+      rc = btreeGetUnusedPage(pBt, pBt->nPage, &pPg, bNoContent);
+      if( rc==0 ){
+        rc = sqlite3PagerWrite(pPg->pDbPage);
+        releasePage(pPg);
+      }
+      if( rc ) return rc;
+      pBt->nPage++;
+      if( pBt->nPage==((Pgno)((sqlite3PendingByte/((pBt)->pageSize))+1)) ){ pBt->nPage++; }
+    }
+
+    sqlite3Put4byte(28 + (u8*)pBt->pPage1->aData, pBt->nPage);
+    *pPgno = pBt->nPage;
+
+    assert( *pPgno!=((Pgno)((sqlite3PendingByte/((pBt)->pageSize))+1)) );
+    rc = btreeGetUnusedPage(pBt, *pPgno, ppPage, bNoContent);
+    if( rc ) return rc;
+    rc = sqlite3PagerWrite((*ppPage)->pDbPage);
+    if( rc!=0 ){
+      releasePage(*ppPage);
+      *ppPage = 0;
+    }
+    ;
+  }
+
+  assert( (sqlite3Config.neverCorrupt==0) || *pPgno!=((Pgno)((sqlite3PendingByte/((pBt)->pageSize))+1)) );
+
+end_allocate_page:
+  releasePage(pTrunk);
+  releasePage(pPrevTrunk);
+  assert( rc!=0 || sqlite3PagerPageRefcount((*ppPage)->pDbPage)<=1 );
+  assert( rc!=0 || (*ppPage)->isInit==0 );
+  return rc;
+}
+# 6177 "src/btree.c"
+static int freePage2(BtShared *pBt, MemPage *pMemPage, Pgno iPage){
+  MemPage *pTrunk = 0;
+  Pgno iTrunk = 0;
+  MemPage *pPage1 = pBt->pPage1;
+  MemPage *pPage;
+  int rc;
+  u32 nFree;
+
+  assert( sqlite3_mutex_held(pBt->mutex) );
+  assert( (sqlite3Config.neverCorrupt==0) || iPage>1 );
+  assert( !pMemPage || pMemPage->pgno==iPage );
+
+  if( iPage<2 || iPage>pBt->nPage ){
+    return sqlite3CorruptError(6190);
+  }
+  if( pMemPage ){
+    pPage = pMemPage;
+    sqlite3PagerRef(pPage->pDbPage);
+  }else{
+    pPage = btreePageLookup(pBt, iPage);
+  }
+
+
+  rc = sqlite3PagerWrite(pPage1->pDbPage);
+  if( rc ) goto freepage_out;
+  nFree = sqlite3Get4byte(&pPage1->aData[36]);
+  sqlite3Put4byte(&pPage1->aData[36], nFree+1);
+
+  if( pBt->btsFlags & 0x0004 ){
+
+
+
+    if( (!pPage && ((rc = btreeGetPage(pBt, iPage, &pPage, 0))!=0) )
+     || ((rc = sqlite3PagerWrite(pPage->pDbPage))!=0)
+    ){
+      goto freepage_out;
+    }
+    memset(pPage->aData, 0, pPage->pBt->pageSize);
+  }
+
+
+
+
+  if( (pBt->autoVacuum) ){
+    ptrmapPut(pBt, iPage, 2, 0, &rc);
+    if( rc ) goto freepage_out;
+  }
+# 6232 "src/btree.c"
+  if( nFree!=0 ){
+    u32 nLeaf;
+
+    iTrunk = sqlite3Get4byte(&pPage1->aData[32]);
+    rc = btreeGetPage(pBt, iTrunk, &pTrunk, 0);
+    if( rc!=0 ){
+      goto freepage_out;
+    }
+
+    nLeaf = sqlite3Get4byte(&pTrunk->aData[4]);
+    assert( pBt->usableSize>32 );
+    if( nLeaf > (u32)pBt->usableSize/4 - 2 ){
+      rc = sqlite3CorruptError(6244);
+      goto freepage_out;
+    }
+    if( nLeaf < (u32)pBt->usableSize/4 - 8 ){
+# 6267 "src/btree.c"
+      rc = sqlite3PagerWrite(pTrunk->pDbPage);
+      if( rc==0 ){
+        sqlite3Put4byte(&pTrunk->aData[4], nLeaf+1);
+        sqlite3Put4byte(&pTrunk->aData[8+nLeaf*4], iPage);
+        if( pPage && (pBt->btsFlags & 0x0004)==0 ){
+          sqlite3PagerDontWrite(pPage->pDbPage);
+        }
+        rc = btreeSetHasContent(pBt, iPage);
+      }
+      ;
+      goto freepage_out;
+    }
+  }
+
+
+
+
+
+
+
+  if( pPage==0 && 0!=(rc = btreeGetPage(pBt, iPage, &pPage, 0)) ){
+    goto freepage_out;
+  }
+  rc = sqlite3PagerWrite(pPage->pDbPage);
+  if( rc!=0 ){
+    goto freepage_out;
+  }
+  sqlite3Put4byte(pPage->aData, iTrunk);
+  sqlite3Put4byte(&pPage->aData[4], 0);
+  sqlite3Put4byte(&pPage1->aData[32], iPage);
+  ;
+
+freepage_out:
+  if( pPage ){
+    pPage->isInit = 0;
+  }
+  releasePage(pPage);
+  releasePage(pTrunk);
+  return rc;
+}
+static void freePage(MemPage *pPage, int *pRC){
+  if( (*pRC)==0 ){
+    *pRC = freePage2(pPage->pBt, pPage, pPage->pgno);
+  }
+}
+
+
+
+
+
+static int clearCell(
+  MemPage *pPage,
+  unsigned char *pCell,
+  CellInfo *pInfo
+){
+  BtShared *pBt;
+  Pgno ovflPgno;
+  int rc;
+  int nOvfl;
+  u32 ovflPageSize;
+
+  assert( sqlite3_mutex_held(pPage->pBt->mutex) );
+  pPage->xParseCell(pPage, pCell, pInfo);
+  if( pInfo->nLocal==pInfo->nPayload ){
+    return 0;
+  }
+  ;
+  ;
+  if( pCell + pInfo->nSize > pPage->aDataEnd ){
+
+    return sqlite3CorruptError(6337);
+  }
+  ovflPgno = sqlite3Get4byte(pCell + pInfo->nSize - 4);
+  pBt = pPage->pBt;
+  assert( pBt->usableSize > 4 );
+  ovflPageSize = pBt->usableSize - 4;
+  nOvfl = (pInfo->nPayload - pInfo->nLocal + ovflPageSize - 1)/ovflPageSize;
+  assert( nOvfl>0 ||
+    ((sqlite3Config.neverCorrupt==0) && (pInfo->nPayload + ovflPageSize)<ovflPageSize)
+  );
+  while( nOvfl-- ){
+    Pgno iNext = 0;
+    MemPage *pOvfl = 0;
+    if( ovflPgno<2 || ovflPgno>btreePagecount(pBt) ){
+
+
+
+      return sqlite3CorruptError(6354);
+    }
+    if( nOvfl ){
+      rc = getOverflowPage(pBt, ovflPgno, &pOvfl, &iNext);
+      if( rc ) return rc;
+    }
+
+    if( ( pOvfl || ((pOvfl = btreePageLookup(pBt, ovflPgno))!=0) )
+     && sqlite3PagerPageRefcount(pOvfl->pDbPage)!=1
+    ){
+# 6374 "src/btree.c"
+      rc = sqlite3CorruptError(6374);
+    }else{
+      rc = freePage2(pBt, pOvfl, ovflPgno);
+    }
+
+    if( pOvfl ){
+      sqlite3PagerUnref(pOvfl->pDbPage);
+    }
+    if( rc ) return rc;
+    ovflPgno = iNext;
+  }
+  return 0;
+}
+# 6400 "src/btree.c"
+static int fillInCell(
+  MemPage *pPage,
+  unsigned char *pCell,
+  const BtreePayload *pX,
+  int *pnSize
+){
+  int nPayload;
+  const u8 *pSrc;
+  int nSrc, n, rc, mn;
+  int spaceLeft;
+  MemPage *pToRelease;
+  unsigned char *pPrior;
+  unsigned char *pPayload;
+  BtShared *pBt;
+  Pgno pgnoOvfl;
+  int nHeader;
+
+  assert( sqlite3_mutex_held(pPage->pBt->mutex) );
+
+
+
+  assert( pCell<pPage->aData || pCell>=&pPage->aData[pPage->pBt->pageSize]
+            || sqlite3PagerIswriteable(pPage->pDbPage) );
+
+
+  nHeader = pPage->childPtrSize;
+  if( pPage->intKey ){
+    nPayload = pX->nData + pX->nZero;
+    pSrc = pX->pData;
+    nSrc = pX->nData;
+    assert( pPage->intKeyLeaf );
+    nHeader += (u8)(((u32)(nPayload)<(u32)0x80)?(*(&pCell[nHeader])=(unsigned char)(nPayload)),1: sqlite3PutVarint((&pCell[nHeader]),(nPayload)));
+    nHeader += sqlite3PutVarint(&pCell[nHeader], *(u64*)&pX->nKey);
+  }else{
+    assert( pX->nKey<=0x7fffffff && pX->pKey!=0 );
+    nSrc = nPayload = (int)pX->nKey;
+    pSrc = pX->pKey;
+    nHeader += (u8)(((u32)(nPayload)<(u32)0x80)?(*(&pCell[nHeader])=(unsigned char)(nPayload)),1: sqlite3PutVarint((&pCell[nHeader]),(nPayload)));
+  }
+
+
+  pPayload = &pCell[nHeader];
+  if( nPayload<=pPage->maxLocal ){
+
+
+    n = nHeader + nPayload;
+    ;
+    ;
+    if( n<4 ) n = 4;
+    *pnSize = n;
+    assert( nSrc<=nPayload );
+    ;
+    memcpy(pPayload, pSrc, nSrc);
+    memset(pPayload+nSrc, 0, nPayload-nSrc);
+    return 0;
+  }
+
+
+
+
+  mn = pPage->minLocal;
+  n = mn + (nPayload - mn) % (pPage->pBt->usableSize - 4);
+  ;
+  ;
+  if( n > pPage->maxLocal ) n = mn;
+  spaceLeft = n;
+  *pnSize = n + nHeader + 4;
+  pPrior = &pCell[nHeader+n];
+  pToRelease = 0;
+  pgnoOvfl = 0;
+  pBt = pPage->pBt;
+# 6496 "src/btree.c"
+  while( 1 ){
+    n = nPayload;
+    if( n>spaceLeft ) n = spaceLeft;
+
+
+
+    assert( pToRelease==0 || sqlite3PagerIswriteable(pToRelease->pDbPage) );
+
+
+
+    assert( pPayload<pPage->aData || pPayload>=&pPage->aData[pBt->pageSize]
+            || sqlite3PagerIswriteable(pPage->pDbPage) );
+
+    if( nSrc>=n ){
+      memcpy(pPayload, pSrc, n);
+    }else if( nSrc>0 ){
+      n = nSrc;
+      memcpy(pPayload, pSrc, n);
+    }else{
+      memset(pPayload, 0, n);
+    }
+    nPayload -= n;
+    if( nPayload<=0 ) break;
+    pPayload += n;
+    pSrc += n;
+    nSrc -= n;
+    spaceLeft -= n;
+    if( spaceLeft==0 ){
+      MemPage *pOvfl = 0;
+
+      Pgno pgnoPtrmap = pgnoOvfl;
+      if( pBt->autoVacuum ){
+        do{
+          pgnoOvfl++;
+        } while(
+          (ptrmapPageno((pBt), (pgnoOvfl))==(pgnoOvfl)) || pgnoOvfl==((Pgno)((sqlite3PendingByte/((pBt)->pageSize))+1))
+        );
+      }
+
+      rc = allocateBtreePage(pBt, &pOvfl, &pgnoOvfl, pgnoOvfl, 0);
+# 6547 "src/btree.c"
+      if( pBt->autoVacuum && rc==0 ){
+        u8 eType = (pgnoPtrmap?4:3);
+        ptrmapPut(pBt, pgnoOvfl, eType, pgnoPtrmap, &rc);
+        if( rc ){
+          releasePage(pOvfl);
+        }
+      }
+
+      if( rc ){
+        releasePage(pToRelease);
+        return rc;
+      }
+
+
+
+      assert( pToRelease==0 || sqlite3PagerIswriteable(pToRelease->pDbPage) );
+
+
+
+      assert( pPrior<pPage->aData || pPrior>=&pPage->aData[pBt->pageSize]
+            || sqlite3PagerIswriteable(pPage->pDbPage) );
+
+      sqlite3Put4byte(pPrior, pgnoOvfl);
+      releasePage(pToRelease);
+      pToRelease = pOvfl;
+      pPrior = pOvfl->aData;
+      sqlite3Put4byte(pPrior, 0);
+      pPayload = &pOvfl->aData[4];
+      spaceLeft = pBt->usableSize - 4;
+    }
+  }
+  releasePage(pToRelease);
+  return 0;
+}
+# 6590 "src/btree.c"
+static void dropCell(MemPage *pPage, int idx, int sz, int *pRC){
+  u32 pc;
+  u8 *data;
+  u8 *ptr;
+  int rc;
+  int hdr;
+
+  if( *pRC ) return;
+  assert( idx>=0 && idx<pPage->nCell );
+  assert( (sqlite3Config.neverCorrupt==0) || sz==cellSize(pPage, idx) );
+  assert( sqlite3PagerIswriteable(pPage->pDbPage) );
+  assert( sqlite3_mutex_held(pPage->pBt->mutex) );
+  assert( pPage->nFree>=0 );
+  data = pPage->aData;
+  ptr = &pPage->aCellIdx[2*idx];
+  pc = ((ptr)[0]<<8 | (ptr)[1]);
+  hdr = pPage->hdrOffset;
+  ;
+  ;
+  if( pc+sz > pPage->pBt->usableSize ){
+    *pRC = sqlite3CorruptError(6610);
+    return;
+  }
+  rc = freeSpace(pPage, pc, sz);
+  if( rc ){
+    *pRC = rc;
+    return;
+  }
+  pPage->nCell--;
+  if( pPage->nCell==0 ){
+    memset(&data[hdr+1], 0, 4);
+    data[hdr+7] = 0;
+    ((&data[hdr+5])[0] = (u8)((pPage->pBt->usableSize)>>8), (&data[hdr+5])[1] = (u8)(pPage->pBt->usableSize));
+    pPage->nFree = pPage->pBt->usableSize - pPage->hdrOffset
+                       - pPage->childPtrSize - 8;
+  }else{
+    memmove(ptr, ptr+2, 2*(pPage->nCell - idx));
+    ((&data[hdr+3])[0] = (u8)((pPage->nCell)>>8), (&data[hdr+3])[1] = (u8)(pPage->nCell));
+    pPage->nFree += 2;
+  }
+}
+# 6646 "src/btree.c"
+static void insertCell(
+  MemPage *pPage,
+  int i,
+  u8 *pCell,
+  int sz,
+  u8 *pTemp,
+  Pgno iChild,
+  int *pRC
+){
+  int idx = 0;
+  int j;
+  u8 *data;
+  u8 *pIns;
+
+  assert( *pRC==0 );
+  assert( i>=0 && i<=pPage->nCell+pPage->nOverflow );
+  assert( ((pPage->pBt->pageSize-8)/6)<=10921 );
+  assert( pPage->nCell<=((pPage->pBt->pageSize-8)/6) || (sqlite3Config.neverCorrupt==0) );
+  assert( pPage->nOverflow<=((int)(sizeof(pPage->apOvfl)/sizeof(pPage->apOvfl[0]))) );
+  assert( ((int)(sizeof(pPage->apOvfl)/sizeof(pPage->apOvfl[0])))==((int)(sizeof(pPage->aiOvfl)/sizeof(pPage->aiOvfl[0]))) );
+  assert( sqlite3_mutex_held(pPage->pBt->mutex) );
+
+
+
+
+
+  assert( sz==pPage->xCellSize(pPage, pCell) || (sz==8 && iChild>0) );
+  assert( pPage->nFree>=0 );
+  if( pPage->nOverflow || sz+2>pPage->nFree ){
+    if( pTemp ){
+      memcpy(pTemp, pCell, sz);
+      pCell = pTemp;
+    }
+    if( iChild ){
+      sqlite3Put4byte(pCell, iChild);
+    }
+    j = pPage->nOverflow++;
+
+
+
+    assert( j < ((int)(sizeof(pPage->apOvfl)/sizeof(pPage->apOvfl[0])))-1 );
+    pPage->apOvfl[j] = pCell;
+    pPage->aiOvfl[j] = (u16)i;
+
+
+
+
+
+
+    assert( j==0 || pPage->aiOvfl[j-1]<(u16)i );
+    assert( j==0 || i==pPage->aiOvfl[j-1]+1 );
+  }else{
+    int rc = sqlite3PagerWrite(pPage->pDbPage);
+    if( rc!=0 ){
+      *pRC = rc;
+      return;
+    }
+    assert( sqlite3PagerIswriteable(pPage->pDbPage) );
+    data = pPage->aData;
+    assert( &data[pPage->cellOffset]==pPage->aCellIdx );
+    rc = allocateSpace(pPage, sz, &idx);
+    if( rc ){ *pRC = rc; return; }
+
+
+    assert( idx >= 0 );
+    assert( idx >= pPage->cellOffset+2*pPage->nCell+2 || (sqlite3Config.neverCorrupt==0) );
+    assert( idx+sz <= (int)pPage->pBt->usableSize );
+    pPage->nFree -= (u16)(2 + sz);
+    if( iChild ){
+
+
+
+
+
+      memcpy(&data[idx+4], pCell+4, sz-4);
+      sqlite3Put4byte(&data[idx], iChild);
+    }else{
+      memcpy(&data[idx], pCell, sz);
+    }
+    pIns = pPage->aCellIdx + i*2;
+    memmove(pIns+2, pIns, 2*(pPage->nCell - i));
+    ((pIns)[0] = (u8)((idx)>>8), (pIns)[1] = (u8)(idx));
+    pPage->nCell++;
+
+    if( (++data[pPage->hdrOffset+4])==0 ) data[pPage->hdrOffset+3]++;
+    assert( ((&data[pPage->hdrOffset+3])[0]<<8 | (&data[pPage->hdrOffset+3])[1])==pPage->nCell || (sqlite3Config.neverCorrupt==0) );
+
+    if( pPage->pBt->autoVacuum ){
+
+
+
+      ptrmapPutOvflPtr(pPage, pPage, pCell, pRC);
+    }
+
+  }
+}
+# 6826 "src/btree.c"
+typedef struct CellArray CellArray;
+struct CellArray {
+  int nCell;
+  MemPage *pRef;
+  u8 **apCell;
+  u16 *szCell;
+  u8 *apEnd[3*2];
+  int ixNx[3*2];
+};
+
+
+
+
+
+static void populateCellCache(CellArray *p, int idx, int N){
+  assert( idx>=0 && idx+N<=p->nCell );
+  while( N>0 ){
+    assert( p->apCell[idx]!=0 );
+    if( p->szCell[idx]==0 ){
+      p->szCell[idx] = p->pRef->xCellSize(p->pRef, p->apCell[idx]);
+    }else{
+      assert( (sqlite3Config.neverCorrupt==0) ||
+              p->szCell[idx]==p->pRef->xCellSize(p->pRef, p->apCell[idx]) );
+    }
+    idx++;
+    N--;
+  }
+}
+
+
+
+
+static u16 computeCellSize(CellArray *p, int N){
+  assert( N>=0 && N<p->nCell );
+  assert( p->szCell[N]==0 );
+  p->szCell[N] = p->pRef->xCellSize(p->pRef, p->apCell[N]);
+  return p->szCell[N];
+}
+static u16 cachedCellSize(CellArray *p, int N){
+  assert( N>=0 && N<p->nCell );
+  if( p->szCell[N] ) return p->szCell[N];
+  return computeCellSize(p, N);
+}
+# 6883 "src/btree.c"
+static int rebuildPage(
+  CellArray *pCArray,
+  int iFirst,
+  int nCell,
+  MemPage *pPg
+){
+  const int hdr = pPg->hdrOffset;
+  u8 * const aData = pPg->aData;
+  const int usableSize = pPg->pBt->usableSize;
+  u8 * const pEnd = &aData[usableSize];
+  int i = iFirst;
+  u32 j;
+  int iEnd = i+nCell;
+  u8 *pCellptr = pPg->aCellIdx;
+  u8 *pTmp = sqlite3PagerTempSpace(pPg->pBt->pPager);
+  u8 *pData;
+  int k;
+  u8 *pSrcEnd;
+
+  assert( i<iEnd );
+  j = ((&aData[hdr+5])[0]<<8 | (&aData[hdr+5])[1]);
+  if( (j>(u32)usableSize) ){ j = 0; }
+  memcpy(&pTmp[j], &aData[j], usableSize - j);
+
+  for(k=0; pCArray->ixNx[k]<=i && (k<3*2); k++){}
+  pSrcEnd = pCArray->apEnd[k];
+
+  pData = pEnd;
+  while( 1 ){
+    u8 *pCell = pCArray->apCell[i];
+    u16 sz = pCArray->szCell[i];
+    assert( sz>0 );
+    if( (((uptr)(pCell)>=(uptr)(aData))&&((uptr)(pCell)<(uptr)(pEnd))) ){
+      if( ((uptr)(pCell+sz))>(uptr)pEnd ) return sqlite3CorruptError(6916);
+      pCell = &pTmp[pCell - aData];
+    }else if( (uptr)(pCell+sz)>(uptr)pSrcEnd
+           && (uptr)(pCell)<(uptr)pSrcEnd
+    ){
+      return sqlite3CorruptError(6921);
+    }
+
+    pData -= sz;
+    ((pCellptr)[0] = (u8)(((pData - aData))>>8), (pCellptr)[1] = (u8)((pData - aData)));
+    pCellptr += 2;
+    if( pData < pCellptr ) return sqlite3CorruptError(6927);
+    memcpy(pData, pCell, sz);
+    assert( sz==pPg->xCellSize(pPg, pCell) || (sqlite3Config.neverCorrupt==0) );
+    ;
+    i++;
+    if( i>=iEnd ) break;
+    if( pCArray->ixNx[k]<=i ){
+      k++;
+      pSrcEnd = pCArray->apEnd[k];
+    }
+  }
+
+
+  pPg->nCell = nCell;
+  pPg->nOverflow = 0;
+
+  ((&aData[hdr+1])[0] = (u8)((0)>>8), (&aData[hdr+1])[1] = (u8)(0));
+  ((&aData[hdr+3])[0] = (u8)((pPg->nCell)>>8), (&aData[hdr+3])[1] = (u8)(pPg->nCell));
+  ((&aData[hdr+5])[0] = (u8)((pData - aData)>>8), (&aData[hdr+5])[1] = (u8)(pData - aData));
+  aData[hdr+7] = 0x00;
+  return 0;
+}
+# 6974 "src/btree.c"
+static int pageInsertArray(
+  MemPage *pPg,
+  u8 *pBegin,
+  u8 **ppData,
+  u8 *pCellptr,
+  int iFirst,
+  int nCell,
+  CellArray *pCArray
+){
+  int i = iFirst;
+  u8 *aData = pPg->aData;
+  u8 *pData = *ppData;
+  int iEnd = iFirst + nCell;
+  int k;
+  u8 *pEnd;
+  assert( (sqlite3Config.neverCorrupt==0) || pPg->hdrOffset==0 );
+  if( iEnd<=iFirst ) return 0;
+  for(k=0; pCArray->ixNx[k]<=i && (k<3*2); k++){}
+  pEnd = pCArray->apEnd[k];
+  while( 1 ){
+    int sz, rc;
+    u8 *pSlot;
+    sz = cachedCellSize(pCArray, i);
+    if( (aData[1]==0 && aData[2]==0) || (pSlot = pageFindSlot(pPg,sz,&rc))==0 ){
+      if( (pData - pBegin)<sz ) return 1;
+      pData -= sz;
+      pSlot = pData;
+    }
+
+
+
+    assert( (pSlot+sz)<=pCArray->apCell[i]
+         || pSlot>=(pCArray->apCell[i]+sz)
+         || (sqlite3Config.neverCorrupt==0) );
+    if( (uptr)(pCArray->apCell[i]+sz)>(uptr)pEnd
+     && (uptr)(pCArray->apCell[i])<(uptr)pEnd
+    ){
+      assert( (sqlite3Config.neverCorrupt==0) );
+      (void)sqlite3CorruptError(7012);
+      return 1;
+    }
+    memmove(pSlot, pCArray->apCell[i], sz);
+    ((pCellptr)[0] = (u8)(((pSlot - aData))>>8), (pCellptr)[1] = (u8)((pSlot - aData)));
+    pCellptr += 2;
+    i++;
+    if( i>=iEnd ) break;
+    if( pCArray->ixNx[k]<=i ){
+      k++;
+      pEnd = pCArray->apEnd[k];
+    }
+  }
+  *ppData = pData;
+  return 0;
+}
+# 7038 "src/btree.c"
+static int pageFreeArray(
+  MemPage *pPg,
+  int iFirst,
+  int nCell,
+  CellArray *pCArray
+){
+  u8 * const aData = pPg->aData;
+  u8 * const pEnd = &aData[pPg->pBt->usableSize];
+  u8 * const pStart = &aData[pPg->hdrOffset + 8 + pPg->childPtrSize];
+  int nRet = 0;
+  int i;
+  int iEnd = iFirst + nCell;
+  u8 *pFree = 0;
+  int szFree = 0;
+
+  for(i=iFirst; i<iEnd; i++){
+    u8 *pCell = pCArray->apCell[i];
+    if( (((uptr)(pCell)>=(uptr)(pStart))&&((uptr)(pCell)<(uptr)(pEnd))) ){
+      int sz;
+
+
+
+      sz = pCArray->szCell[i]; assert( sz>0 );
+      if( pFree!=(pCell + sz) ){
+        if( pFree ){
+          assert( pFree>aData && (pFree - aData)<65536 );
+          freeSpace(pPg, (u16)(pFree - aData), szFree);
+        }
+        pFree = pCell;
+        szFree = sz;
+        if( pFree+sz>pEnd ) return 0;
+      }else{
+        pFree = pCell;
+        szFree += sz;
+      }
+      nRet++;
+    }
+  }
+  if( pFree ){
+    assert( pFree>aData && (pFree - aData)<65536 );
+    freeSpace(pPg, (u16)(pFree - aData), szFree);
+  }
+  return nRet;
+}
+# 7095 "src/btree.c"
+static int editPage(
+  MemPage *pPg,
+  int iOld,
+  int iNew,
+  int nNew,
+  CellArray *pCArray
+){
+  u8 * const aData = pPg->aData;
+  const int hdr = pPg->hdrOffset;
+  u8 *pBegin = &pPg->aCellIdx[nNew * 2];
+  int nCell = pPg->nCell;
+  u8 *pData;
+  u8 *pCellptr;
+  int i;
+  int iOldEnd = iOld + pPg->nCell + pPg->nOverflow;
+  int iNewEnd = iNew + nNew;
+
+
+
+
+
+
+
+  assert( nCell>=0 );
+  if( iOld<iNew ){
+    int nShift = pageFreeArray(pPg, iOld, iNew-iOld, pCArray);
+    if( nShift>nCell ) return sqlite3CorruptError(7121);
+    memmove(pPg->aCellIdx, &pPg->aCellIdx[nShift*2], nCell*2);
+    nCell -= nShift;
+  }
+  if( iNewEnd < iOldEnd ){
+    int nTail = pageFreeArray(pPg, iNewEnd, iOldEnd - iNewEnd, pCArray);
+    assert( nCell>=nTail );
+    nCell -= nTail;
+  }
+
+  pData = &aData[(((((int)((&aData[hdr+5])[0]<<8 | (&aData[hdr+5])[1]))-1)&0xffff)+1)];
+  if( pData<pBegin ) goto editpage_fail;
+
+
+  if( iNew<iOld ){
+    int nAdd = ((nNew)<(iOld-iNew)?(nNew):(iOld-iNew));
+    assert( (iOld-iNew)<nNew || nCell==0 || (sqlite3Config.neverCorrupt==0) );
+    assert( nAdd>=0 );
+    pCellptr = pPg->aCellIdx;
+    memmove(&pCellptr[nAdd*2], pCellptr, nCell*2);
+    if( pageInsertArray(
+          pPg, pBegin, &pData, pCellptr,
+          iNew, nAdd, pCArray
+    ) ) goto editpage_fail;
+    nCell += nAdd;
+  }
+
+
+  for(i=0; i<pPg->nOverflow; i++){
+    int iCell = (iOld + pPg->aiOvfl[i]) - iNew;
+    if( iCell>=0 && iCell<nNew ){
+      pCellptr = &pPg->aCellIdx[iCell * 2];
+      if( nCell>iCell ){
+        memmove(&pCellptr[2], pCellptr, (nCell - iCell) * 2);
+      }
+      nCell++;
+      if( pageInsertArray(
+            pPg, pBegin, &pData, pCellptr,
+            iCell+iNew, 1, pCArray
+      ) ) goto editpage_fail;
+    }
+  }
+
+
+  assert( nCell>=0 );
+  pCellptr = &pPg->aCellIdx[nCell*2];
+  if( pageInsertArray(
+        pPg, pBegin, &pData, pCellptr,
+        iNew+nCell, nNew-nCell, pCArray
+  ) ) goto editpage_fail;
+
+  pPg->nCell = nNew;
+  pPg->nOverflow = 0;
+
+  ((&aData[hdr+3])[0] = (u8)((pPg->nCell)>>8), (&aData[hdr+3])[1] = (u8)(pPg->nCell));
+  ((&aData[hdr+5])[0] = (u8)((pData - aData)>>8), (&aData[hdr+5])[1] = (u8)(pData - aData));
+# 7190 "src/btree.c"
+  return 0;
+ editpage_fail:
+
+  populateCellCache(pCArray, iNew, nNew);
+  return rebuildPage(pCArray, iNew, nNew, pPg);
+}
+# 7222 "src/btree.c"
+static int balance_quick(MemPage *pParent, MemPage *pPage, u8 *pSpace){
+  BtShared *const pBt = pPage->pBt;
+  MemPage *pNew;
+  int rc;
+  Pgno pgnoNew;
+
+  assert( sqlite3_mutex_held(pPage->pBt->mutex) );
+  assert( sqlite3PagerIswriteable(pParent->pDbPage) );
+  assert( pPage->nOverflow==1 );
+
+  if( pPage->nCell==0 ) return sqlite3CorruptError(7232);
+  assert( pPage->nFree>=0 );
+  assert( pParent->nFree>=0 );
+
+
+
+
+
+  rc = allocateBtreePage(pBt, &pNew, &pgnoNew, 0, 0);
+
+  if( rc==0 ){
+
+    u8 *pOut = &pSpace[4];
+    u8 *pCell = pPage->apOvfl[0];
+    u16 szCell = pPage->xCellSize(pPage, pCell);
+    u8 *pStop;
+    CellArray b;
+
+    assert( sqlite3PagerIswriteable(pNew->pDbPage) );
+    assert( (sqlite3Config.neverCorrupt==0) || pPage->aData[0]==(0x01|0x04|0x08) );
+    zeroPage(pNew, 0x01|0x04|0x08);
+    b.nCell = 1;
+    b.pRef = pPage;
+    b.apCell = &pCell;
+    b.szCell = &szCell;
+    b.apEnd[0] = pPage->aDataEnd;
+    b.ixNx[0] = 2;
+    rc = rebuildPage(&b, 0, 1, pNew);
+    if( (rc) ){
+      releasePage(pNew);
+      return rc;
+    }
+    pNew->nFree = pBt->usableSize - pNew->cellOffset - 2 - szCell;
+# 7275 "src/btree.c"
+    if( (pBt->autoVacuum) ){
+      ptrmapPut(pBt, pgnoNew, 5, pParent->pgno, &rc);
+      if( szCell>pNew->minLocal ){
+        ptrmapPutOvflPtr(pNew, pNew, pCell, &rc);
+      }
+    }
+# 7295 "src/btree.c"
+    pCell = ((pPage)->aData + ((pPage)->maskPage & __builtin_bswap16(*(u16*)(&(pPage)->aCellIdx[2*(pPage->nCell-1)]))));
+    pStop = &pCell[9];
+    while( (*(pCell++)&0x80) && pCell<pStop );
+    pStop = &pCell[9];
+    while( ((*(pOut++) = *(pCell++))&0x80) && pCell<pStop );
+
+
+    if( rc==0 ){
+      insertCell(pParent, pParent->nCell, pSpace, (int)(pOut-pSpace),
+                   0, pPage->pgno, &rc);
+    }
+
+
+    sqlite3Put4byte(&pParent->aData[pParent->hdrOffset+8], pgnoNew);
+
+
+    releasePage(pNew);
+  }
+
+  return rc;
+}
+# 7377 "src/btree.c"
+static void copyNodeContent(MemPage *pFrom, MemPage *pTo, int *pRC){
+  if( (*pRC)==0 ){
+    BtShared * const pBt = pFrom->pBt;
+    u8 * const aFrom = pFrom->aData;
+    u8 * const aTo = pTo->aData;
+    int const iFromHdr = pFrom->hdrOffset;
+    int const iToHdr = ((pTo->pgno==1) ? 100 : 0);
+    int rc;
+    int iData;
+
+
+    assert( pFrom->isInit );
+    assert( pFrom->nFree>=iToHdr );
+    assert( ((&aFrom[iFromHdr+5])[0]<<8 | (&aFrom[iFromHdr+5])[1]) <= (int)pBt->usableSize );
+
+
+    iData = ((&aFrom[iFromHdr+5])[0]<<8 | (&aFrom[iFromHdr+5])[1]);
+    memcpy(&aTo[iData], &aFrom[iData], pBt->usableSize-iData);
+    memcpy(&aTo[iToHdr], &aFrom[iFromHdr], pFrom->cellOffset + 2*pFrom->nCell);
+
+
+
+
+
+
+    pTo->isInit = 0;
+    rc = btreeInitPage(pTo);
+    if( rc==0 ) rc = btreeComputeFreeSpace(pTo);
+    if( rc!=0 ){
+      *pRC = rc;
+      return;
+    }
+
+
+
+
+    if( (pBt->autoVacuum) ){
+      *pRC = setChildPtrmaps(pTo);
+    }
+  }
+}
+# 7459 "src/btree.c"
+static int balance_nonroot(
+  MemPage *pParent,
+  int iParentIdx,
+  u8 *aOvflSpace,
+  int isRoot,
+  int bBulk
+){
+  BtShared *pBt;
+  int nMaxCells = 0;
+  int nNew = 0;
+  int nOld;
+  int i, j, k;
+  int nxDiv;
+  int rc = 0;
+  u16 leafCorrection;
+  int leafData;
+  int usableSpace;
+  int pageFlags;
+  int iSpace1 = 0;
+  int iOvflSpace = 0;
+  int szScratch;
+  MemPage *apOld[3];
+  MemPage *apNew[3 +2];
+  u8 *pRight;
+  u8 *apDiv[3 -1];
+  int cntNew[3 +2];
+  int cntOld[3 +2];
+  int szNew[3 +2];
+  u8 *aSpace1;
+  Pgno pgno;
+  u8 abDone[3 +2];
+  Pgno aPgno[3 +2];
+  Pgno aPgOrder[3 +2];
+  u16 aPgFlags[3 +2];
+  CellArray b;
+
+  memset(abDone, 0, sizeof(abDone));
+  b.nCell = 0;
+  b.apCell = 0;
+  pBt = pParent->pBt;
+  assert( sqlite3_mutex_held(pBt->mutex) );
+  assert( sqlite3PagerIswriteable(pParent->pDbPage) );
+
+
+
+
+
+
+  assert( pParent->nOverflow==0 || pParent->nOverflow==1 );
+  assert( pParent->nOverflow==0 || pParent->aiOvfl[0]==iParentIdx );
+
+  if( !aOvflSpace ){
+    return 7;
+  }
+  assert( pParent->nFree>=0 );
+# 7526 "src/btree.c"
+  i = pParent->nOverflow + pParent->nCell;
+  if( i<2 ){
+    nxDiv = 0;
+  }else{
+    assert( bBulk==0 || bBulk==1 );
+    if( iParentIdx==0 ){
+      nxDiv = 0;
+    }else if( iParentIdx==i ){
+      nxDiv = i-2+bBulk;
+    }else{
+      nxDiv = iParentIdx-1;
+    }
+    i = 2-bBulk;
+  }
+  nOld = i+1;
+  if( (i+nxDiv-pParent->nOverflow)==pParent->nCell ){
+    pRight = &pParent->aData[pParent->hdrOffset+8];
+  }else{
+    pRight = ((pParent)->aData + ((pParent)->maskPage & __builtin_bswap16(*(u16*)(&(pParent)->aCellIdx[2*(i+nxDiv-pParent->nOverflow)]))));
+  }
+  pgno = sqlite3Get4byte(pRight);
+  while( 1 ){
+    rc = getAndInitPage(pBt, pgno, &apOld[i], 0, 0);
+    if( rc ){
+      memset(apOld, 0, (i+1)*sizeof(MemPage*));
+      goto balance_cleanup;
+    }
+    if( apOld[i]->nFree<0 ){
+      rc = btreeComputeFreeSpace(apOld[i]);
+      if( rc ){
+        memset(apOld, 0, (i)*sizeof(MemPage*));
+        goto balance_cleanup;
+      }
+    }
+    if( (i--)==0 ) break;
+
+    if( pParent->nOverflow && i+nxDiv==pParent->aiOvfl[0] ){
+      apDiv[i] = pParent->apOvfl[0];
+      pgno = sqlite3Get4byte(apDiv[i]);
+      szNew[i] = pParent->xCellSize(pParent, apDiv[i]);
+      pParent->nOverflow = 0;
+    }else{
+      apDiv[i] = ((pParent)->aData + ((pParent)->maskPage & __builtin_bswap16(*(u16*)(&(pParent)->aCellIdx[2*(i+nxDiv-pParent->nOverflow)]))));
+      pgno = sqlite3Get4byte(apDiv[i]);
+      szNew[i] = pParent->xCellSize(pParent, apDiv[i]);
+# 7584 "src/btree.c"
+      if( pBt->btsFlags & 0x000c ){
+        int iOff;
+
+        iOff = ((int)(long int)(apDiv[i])) - ((int)(long int)(pParent->aData));
+        if( (iOff+szNew[i])>(int)pBt->usableSize ){
+          rc = sqlite3CorruptError(7589);
+          memset(apOld, 0, (i+1)*sizeof(MemPage*));
+          goto balance_cleanup;
+        }else{
+          memcpy(&aOvflSpace[iOff], apDiv[i], szNew[i]);
+          apDiv[i] = &aOvflSpace[apDiv[i]-pParent->aData];
+        }
+      }
+      dropCell(pParent, i+nxDiv-pParent->nOverflow, szNew[i], &rc);
+    }
+  }
+
+
+
+  nMaxCells = nOld*(((pBt->pageSize-8)/6) + ((int)(sizeof(pParent->apOvfl)/sizeof(pParent->apOvfl[0]))));
+  nMaxCells = (nMaxCells + 3)&~3;
+
+
+
+
+  szScratch =
+       nMaxCells*sizeof(u8*)
+     + nMaxCells*sizeof(u16)
+     + pBt->pageSize;
+
+  assert( szScratch<=7*(int)pBt->pageSize );
+  b.apCell = sqlite3DbMallocRaw(0,szScratch);
+  if( b.apCell==0 ){
+    rc = 7;
+    goto balance_cleanup;
+  }
+  b.szCell = (u16*)&b.apCell[nMaxCells];
+  aSpace1 = (u8*)&b.szCell[nMaxCells];
+  assert( ((((char*)(aSpace1) - (char*)0)&7)==0) );
+# 7640 "src/btree.c"
+  b.pRef = apOld[0];
+  leafCorrection = b.pRef->leaf*4;
+  leafData = b.pRef->intKeyLeaf;
+  for(i=0; i<nOld; i++){
+    MemPage *pOld = apOld[i];
+    int limit = pOld->nCell;
+    u8 *aData = pOld->aData;
+    u16 maskPage = pOld->maskPage;
+    u8 *piCell = aData + pOld->cellOffset;
+    u8 *piEnd;
+   
+
+
+
+
+    if( pOld->aData[0]!=apOld[0]->aData[0] ){
+      rc = sqlite3CorruptError(7656);
+      goto balance_cleanup;
+    }
+# 7677 "src/btree.c"
+    memset(&b.szCell[b.nCell], 0, sizeof(b.szCell[0])*(limit+pOld->nOverflow));
+    if( pOld->nOverflow>0 ){
+      if( limit<pOld->aiOvfl[0] ){
+        rc = sqlite3CorruptError(7680);
+        goto balance_cleanup;
+      }
+      limit = pOld->aiOvfl[0];
+      for(j=0; j<limit; j++){
+        b.apCell[b.nCell] = aData + (maskPage & __builtin_bswap16(*(u16*)(piCell)));
+        piCell += 2;
+        b.nCell++;
+      }
+      for(k=0; k<pOld->nOverflow; k++){
+        assert( k==0 || pOld->aiOvfl[k-1]+1==pOld->aiOvfl[k] );
+        b.apCell[b.nCell] = pOld->apOvfl[k];
+        b.nCell++;
+      }
+    }
+    piEnd = aData + pOld->cellOffset + 2*pOld->nCell;
+    while( piCell<piEnd ){
+      assert( b.nCell<nMaxCells );
+      b.apCell[b.nCell] = aData + (maskPage & __builtin_bswap16(*(u16*)(piCell)));
+      piCell += 2;
+      b.nCell++;
+    }
+    assert( (b.nCell-nCellAtStart)==(pOld->nCell+pOld->nOverflow) );
+
+    cntOld[i] = b.nCell;
+    if( i<nOld-1 && !leafData){
+      u16 sz = (u16)szNew[i];
+      u8 *pTemp;
+      assert( b.nCell<nMaxCells );
+      b.szCell[b.nCell] = sz;
+      pTemp = &aSpace1[iSpace1];
+      iSpace1 += sz;
+      assert( sz<=pBt->maxLocal+23 );
+      assert( iSpace1 <= (int)pBt->pageSize );
+      memcpy(pTemp, apDiv[i], sz);
+      b.apCell[b.nCell] = pTemp+leafCorrection;
+      assert( leafCorrection==0 || leafCorrection==4 );
+      b.szCell[b.nCell] = b.szCell[b.nCell] - leafCorrection;
+      if( !pOld->leaf ){
+        assert( leafCorrection==0 );
+        assert( pOld->hdrOffset==0 );
+
+
+        memcpy(b.apCell[b.nCell], &pOld->aData[8], 4);
+      }else{
+        assert( leafCorrection==4 );
+        while( b.szCell[b.nCell]<4 ){
+
+
+          assert( b.szCell[b.nCell]==3 || (sqlite3Config.neverCorrupt==0) );
+          assert( b.apCell[b.nCell]==&aSpace1[iSpace1-3] || (sqlite3Config.neverCorrupt==0) );
+          aSpace1[iSpace1++] = 0x00;
+          b.szCell[b.nCell]++;
+        }
+      }
+      b.nCell++;
+    }
+  }
+# 7755 "src/btree.c"
+  usableSpace = pBt->usableSize - 12 + leafCorrection;
+  for(i=k=0; i<nOld; i++, k++){
+    MemPage *p = apOld[i];
+    b.apEnd[k] = p->aDataEnd;
+    b.ixNx[k] = cntOld[i];
+    if( k && b.ixNx[k]==b.ixNx[k-1] ){
+      k--;
+    }
+    if( !leafData ){
+      k++;
+      b.apEnd[k] = pParent->aDataEnd;
+      b.ixNx[k] = cntOld[i]+1;
+    }
+    assert( p->nFree>=0 );
+    szNew[i] = usableSpace - p->nFree;
+    for(j=0; j<p->nOverflow; j++){
+      szNew[i] += 2 + p->xCellSize(p, p->apOvfl[j]);
+    }
+    cntNew[i] = cntOld[i];
+  }
+  k = nOld;
+  for(i=0; i<k; i++){
+    int sz;
+    while( szNew[i]>usableSpace ){
+      if( i+1>=k ){
+        k = i+2;
+        if( k>3 +2 ){ rc = sqlite3CorruptError(7781); goto balance_cleanup; }
+        szNew[k-1] = 0;
+        cntNew[k-1] = b.nCell;
+      }
+      sz = 2 + cachedCellSize(&b, cntNew[i]-1);
+      szNew[i] -= sz;
+      if( !leafData ){
+        if( cntNew[i]<b.nCell ){
+          sz = 2 + cachedCellSize(&b, cntNew[i]);
+        }else{
+          sz = 0;
+        }
+      }
+      szNew[i+1] += sz;
+      cntNew[i]--;
+    }
+    while( cntNew[i]<b.nCell ){
+      sz = 2 + cachedCellSize(&b, cntNew[i]);
+      if( szNew[i]+sz>usableSpace ) break;
+      szNew[i] += sz;
+      cntNew[i]++;
+      if( !leafData ){
+        if( cntNew[i]<b.nCell ){
+          sz = 2 + cachedCellSize(&b, cntNew[i]);
+        }else{
+          sz = 0;
+        }
+      }
+      szNew[i+1] -= sz;
+    }
+    if( cntNew[i]>=b.nCell ){
+      k = i+1;
+    }else if( cntNew[i] <= (i>0 ? cntNew[i-1] : 0) ){
+      rc = sqlite3CorruptError(7814);
+      goto balance_cleanup;
+    }
+  }
+# 7830 "src/btree.c"
+  for(i=k-1; i>0; i--){
+    int szRight = szNew[i];
+    int szLeft = szNew[i-1];
+    int r;
+    int d;
+
+    r = cntNew[i-1] - 1;
+    d = r + 1 - leafData;
+    (void)cachedCellSize(&b, d);
+    do{
+      assert( d<nMaxCells );
+      assert( r<nMaxCells );
+      (void)cachedCellSize(&b, r);
+      if( szRight!=0
+       && (bBulk || szRight+b.szCell[d]+2 > szLeft-(b.szCell[r]+(i==k-1?0:2)))){
+        break;
+      }
+      szRight += b.szCell[d] + 2;
+      szLeft -= b.szCell[r] + 2;
+      cntNew[i-1] = r;
+      r--;
+      d--;
+    }while( r>=0 );
+    szNew[i] = szRight;
+    szNew[i-1] = szLeft;
+    if( cntNew[i-1] <= (i>1 ? cntNew[i-2] : 0) ){
+      rc = sqlite3CorruptError(7856);
+      goto balance_cleanup;
+    }
+  }
+# 7868 "src/btree.c"
+  assert( cntNew[0]>0 || (pParent->pgno==1 && pParent->nCell==0) || (sqlite3Config.neverCorrupt==0));
+ 
+
+
+
+    ;
+
+
+
+
+  pageFlags = apOld[0]->aData[0];
+  for(i=0; i<k; i++){
+    MemPage *pNew;
+    if( i<nOld ){
+      pNew = apNew[i] = apOld[i];
+      apOld[i] = 0;
+      rc = sqlite3PagerWrite(pNew->pDbPage);
+      nNew++;
+      if( rc ) goto balance_cleanup;
+    }else{
+      assert( i>0 );
+      rc = allocateBtreePage(pBt, &pNew, &pgno, (bBulk ? 1 : pgno), 0);
+      if( rc ) goto balance_cleanup;
+      zeroPage(pNew, pageFlags);
+      apNew[i] = pNew;
+      nNew++;
+      cntOld[i] = b.nCell;
+
+
+      if( (pBt->autoVacuum) ){
+        ptrmapPut(pBt, pNew->pgno, 5, pParent->pgno, &rc);
+        if( rc!=0 ){
+          goto balance_cleanup;
+        }
+      }
+    }
+  }
+# 7918 "src/btree.c"
+  for(i=0; i<nNew; i++){
+    aPgOrder[i] = aPgno[i] = apNew[i]->pgno;
+    aPgFlags[i] = apNew[i]->pDbPage->flags;
+    for(j=0; j<i; j++){
+      if( aPgno[j]==aPgno[i] ){
+
+
+
+
+
+
+        assert( (sqlite3Config.neverCorrupt==0) );
+        rc = sqlite3CorruptError(7930);
+        goto balance_cleanup;
+      }
+    }
+  }
+  for(i=0; i<nNew; i++){
+    int iBest = 0;
+    for(j=1; j<nNew; j++){
+      if( aPgOrder[j]<aPgOrder[iBest] ) iBest = j;
+    }
+    pgno = aPgOrder[iBest];
+    aPgOrder[iBest] = 0xffffffff;
+    if( iBest!=i ){
+      if( iBest>i ){
+        sqlite3PagerRekey(apNew[iBest]->pDbPage, pBt->nPage+iBest+1, 0);
+      }
+      sqlite3PagerRekey(apNew[i]->pDbPage, pgno, aPgFlags[iBest]);
+      apNew[i]->pgno = pgno;
+    }
+  }
+
+ 
+# 7962 "src/btree.c"
+    ;
+
+  assert( sqlite3PagerIswriteable(pParent->pDbPage) );
+  sqlite3Put4byte(pRight, apNew[nNew-1]->pgno);
+
+
+
+
+  if( (pageFlags & 0x08)==0 && nOld!=nNew ){
+    MemPage *pOld = (nNew>nOld ? apNew : apOld)[nOld-1];
+    memcpy(&apNew[nNew-1]->aData[8], &pOld->aData[8], 4);
+  }
+# 7991 "src/btree.c"
+  if( (pBt->autoVacuum) ){
+    MemPage *pOld;
+    MemPage *pNew = pOld = apNew[0];
+    int cntOldNext = pNew->nCell + pNew->nOverflow;
+    int iNew = 0;
+    int iOld = 0;
+
+    for(i=0; i<b.nCell; i++){
+      u8 *pCell = b.apCell[i];
+      while( i==cntOldNext ){
+        iOld++;
+        assert( iOld<nNew || iOld<nOld );
+        assert( iOld>=0 && iOld<3 );
+        pOld = iOld<nNew ? apNew[iOld] : apOld[iOld];
+        cntOldNext += pOld->nCell + pOld->nOverflow + !leafData;
+      }
+      if( i==cntNew[iNew] ){
+        pNew = apNew[++iNew];
+        if( !leafData ) continue;
+      }
+
+
+
+
+
+
+
+      if( iOld>=nNew
+       || pNew->pgno!=aPgno[iOld]
+       || !(((uptr)(pCell)>=(uptr)(pOld->aData))&&((uptr)(pCell)<(uptr)(pOld->aDataEnd)))
+      ){
+        if( !leafCorrection ){
+          ptrmapPut(pBt, sqlite3Get4byte(pCell), 5, pNew->pgno, &rc);
+        }
+        if( cachedCellSize(&b,i)>pNew->minLocal ){
+          ptrmapPutOvflPtr(pNew, pOld, pCell, &rc);
+        }
+        if( rc ) goto balance_cleanup;
+      }
+    }
+  }
+
+
+  for(i=0; i<nNew-1; i++){
+    u8 *pCell;
+    u8 *pTemp;
+    int sz;
+    MemPage *pNew = apNew[i];
+    j = cntNew[i];
+
+    assert( j<nMaxCells );
+    assert( b.apCell[j]!=0 );
+    pCell = b.apCell[j];
+    sz = b.szCell[j] + leafCorrection;
+    pTemp = &aOvflSpace[iOvflSpace];
+    if( !pNew->leaf ){
+      memcpy(&pNew->aData[8], pCell, 4);
+    }else if( leafData ){
+
+
+
+
+
+      CellInfo info;
+      j--;
+      pNew->xParseCell(pNew, b.apCell[j], &info);
+      pCell = pTemp;
+      sz = 4 + sqlite3PutVarint(&pCell[4], info.nKey);
+      pTemp = 0;
+    }else{
+      pCell -= 4;
+# 8073 "src/btree.c"
+      if( b.szCell[j]==4 ){
+        assert(leafCorrection==4);
+        sz = pParent->xCellSize(pParent, pCell);
+      }
+    }
+    iOvflSpace += sz;
+    assert( sz<=pBt->maxLocal+23 );
+    assert( iOvflSpace <= (int)pBt->pageSize );
+    insertCell(pParent, nxDiv+i, pCell, sz, pTemp, pNew->pgno, &rc);
+    if( rc!=0 ) goto balance_cleanup;
+    assert( sqlite3PagerIswriteable(pParent->pDbPage) );
+  }
+# 8108 "src/btree.c"
+  for(i=1-nNew; i<nNew; i++){
+    int iPg = i<0 ? -i : i;
+    assert( iPg>=0 && iPg<nNew );
+    if( abDone[iPg] ) continue;
+    if( i>=0
+     || cntOld[iPg-1]>=cntNew[iPg-1]
+    ){
+      int iNew;
+      int iOld;
+      int nNewCell;
+
+
+
+      assert( iPg==0 || cntOld[iPg-1]>=cntNew[iPg-1] || abDone[iPg-1] );
+
+
+
+      assert( cntNew[iPg]>=cntOld[iPg] || abDone[iPg+1] );
+
+      if( iPg==0 ){
+        iNew = iOld = 0;
+        nNewCell = cntNew[0];
+      }else{
+        iOld = iPg<nOld ? (cntOld[iPg-1] + !leafData) : b.nCell;
+        iNew = cntNew[iPg-1] + !leafData;
+        nNewCell = cntNew[iPg] - iNew;
+      }
+
+      rc = editPage(apNew[iPg], iOld, iNew, nNewCell, &b);
+      if( rc ) goto balance_cleanup;
+      abDone[iPg]++;
+      apNew[iPg]->nFree = usableSpace-szNew[iPg];
+      assert( apNew[iPg]->nOverflow==0 );
+      assert( apNew[iPg]->nCell==nNewCell );
+    }
+  }
+
+
+  assert( memcmp(abDone, "\01\01\01\01\01", nNew)==0 );
+
+  assert( nOld>0 );
+  assert( nNew>0 );
+
+  if( isRoot && pParent->nCell==0 && pParent->hdrOffset<=apNew[0]->nFree ){
+# 8167 "src/btree.c"
+    assert( nNew==1 || (sqlite3Config.neverCorrupt==0) );
+    rc = defragmentPage(apNew[0], -1);
+    ;
+    assert( apNew[0]->nFree ==
+        ((((((int)((&apNew[0]->aData[5])[0]<<8 | (&apNew[0]->aData[5])[1]))-1)&0xffff)+1) - apNew[0]->cellOffset
+          - apNew[0]->nCell*2)
+      || rc!=0
+    );
+    copyNodeContent(apNew[0], pParent, &rc);
+    freePage(apNew[0], &rc);
+  }else if( (pBt->autoVacuum) && !leafCorrection ){
+
+
+
+    for(i=0; i<nNew; i++){
+      u32 key = sqlite3Get4byte(&apNew[i]->aData[8]);
+      ptrmapPut(pBt, key, 5, apNew[i]->pgno, &rc);
+    }
+  }
+
+  assert( pParent->isInit );
+ 
+                               ;
+
+
+
+  for(i=nNew; i<nOld; i++){
+    freePage(apOld[i], &rc);
+  }
+# 8211 "src/btree.c"
+balance_cleanup:
+  sqlite3DbFree(0,b.apCell);
+  for(i=0; i<nOld; i++){
+    releasePage(apOld[i]);
+  }
+  for(i=0; i<nNew; i++){
+    releasePage(apNew[i]);
+  }
+
+  return rc;
+}
+# 8243 "src/btree.c"
+static int balance_deeper(MemPage *pRoot, MemPage **ppChild){
+  int rc;
+  MemPage *pChild = 0;
+  Pgno pgnoChild = 0;
+  BtShared *pBt = pRoot->pBt;
+
+  assert( pRoot->nOverflow>0 );
+  assert( sqlite3_mutex_held(pBt->mutex) );
+
+
+
+
+
+  rc = sqlite3PagerWrite(pRoot->pDbPage);
+  if( rc==0 ){
+    rc = allocateBtreePage(pBt,&pChild,&pgnoChild,pRoot->pgno,0);
+    copyNodeContent(pRoot, pChild, &rc);
+    if( (pBt->autoVacuum) ){
+      ptrmapPut(pBt, pgnoChild, 5, pRoot->pgno, &rc);
+    }
+  }
+  if( rc ){
+    *ppChild = 0;
+    releasePage(pChild);
+    return rc;
+  }
+  assert( sqlite3PagerIswriteable(pChild->pDbPage) );
+  assert( sqlite3PagerIswriteable(pRoot->pDbPage) );
+  assert( pChild->nCell==pRoot->nCell || (sqlite3Config.neverCorrupt==0) );
+
+  ;
+
+
+  memcpy(pChild->aiOvfl, pRoot->aiOvfl,
+         pRoot->nOverflow*sizeof(pRoot->aiOvfl[0]));
+  memcpy(pChild->apOvfl, pRoot->apOvfl,
+         pRoot->nOverflow*sizeof(pRoot->apOvfl[0]));
+  pChild->nOverflow = pRoot->nOverflow;
+
+
+  zeroPage(pRoot, pChild->aData[0] & ~0x08);
+  sqlite3Put4byte(&pRoot->aData[pRoot->hdrOffset+8], pgnoChild);
+
+  *ppChild = pChild;
+  return 0;
+}
+# 8300 "src/btree.c"
+static int balance(BtCursor *pCur){
+  int rc = 0;
+  const int nMin = pCur->pBt->usableSize * 2 / 3;
+  u8 aBalanceQuickSpace[13];
+  u8 *pFree = 0;
+
+  ;
+  ;
+
+  do {
+    int iPage = pCur->iPage;
+    MemPage *pPage = pCur->pPage;
+
+    if( (pPage->nFree<0) && btreeComputeFreeSpace(pPage) ) break;
+    if( iPage==0 ){
+      if( pPage->nOverflow ){
+
+
+
+
+
+        assert( balance_deeper_called==0 );
+        ;
+        rc = balance_deeper(pPage, &pCur->apPage[1]);
+        if( rc==0 ){
+          pCur->iPage = 1;
+          pCur->ix = 0;
+          pCur->aiIdx[0] = 0;
+          pCur->apPage[0] = pPage;
+          pCur->pPage = pCur->apPage[1];
+          assert( pCur->pPage->nOverflow );
+        }
+      }else{
+        break;
+      }
+    }else if( pPage->nOverflow==0 && pPage->nFree<=nMin ){
+      break;
+    }else{
+      MemPage * const pParent = pCur->apPage[iPage-1];
+      int const iIdx = pCur->aiIdx[iPage-1];
+
+      rc = sqlite3PagerWrite(pParent->pDbPage);
+      if( rc==0 && pParent->nFree<0 ){
+        rc = btreeComputeFreeSpace(pParent);
+      }
+      if( rc==0 ){
+
+        if( pPage->intKeyLeaf
+         && pPage->nOverflow==1
+         && pPage->aiOvfl[0]==pPage->nCell
+         && pParent->pgno!=1
+         && pParent->nCell==iIdx
+        ){
+# 8366 "src/btree.c"
+          assert( balance_quick_called==0 );
+          ;
+          rc = balance_quick(pParent, pPage, aBalanceQuickSpace);
+        }else
+
+        {
+# 8389 "src/btree.c"
+          u8 *pSpace = sqlite3PageMalloc(pCur->pBt->pageSize);
+          rc = balance_nonroot(pParent, iIdx, pSpace, iPage==1,
+                               pCur->hints&0x00000001);
+          if( pFree ){
+
+
+
+
+            sqlite3PageFree(pFree);
+          }
+
+
+
+
+          pFree = pSpace;
+        }
+      }
+
+      pPage->nOverflow = 0;
+
+
+      releasePage(pPage);
+      pCur->iPage--;
+      assert( pCur->iPage>=0 );
+      pCur->pPage = pCur->apPage[pCur->iPage];
+    }
+  }while( rc==0 );
+
+  if( pFree ){
+    sqlite3PageFree(pFree);
+  }
+  return rc;
+}
+
+
+
+
+static int btreeOverwriteContent(
+  MemPage *pPage,
+  u8 *pDest,
+  const BtreePayload *pX,
+  int iOffset,
+  int iAmt
+){
+  int nData = pX->nData - iOffset;
+  if( nData<=0 ){
+
+    int i;
+    for(i=0; i<iAmt && pDest[i]==0; i++){}
+    if( i<iAmt ){
+      int rc = sqlite3PagerWrite(pPage->pDbPage);
+      if( rc ) return rc;
+      memset(pDest + i, 0, iAmt - i);
+    }
+  }else{
+    if( nData<iAmt ){
+
+
+      int rc = btreeOverwriteContent(pPage, pDest+nData, pX, iOffset+nData,
+                                 iAmt-nData);
+      if( rc ) return rc;
+      iAmt = nData;
+    }
+    if( memcmp(pDest, ((u8*)pX->pData) + iOffset, iAmt)!=0 ){
+      int rc = sqlite3PagerWrite(pPage->pDbPage);
+      if( rc ) return rc;
+
+
+
+
+      memmove(pDest, ((u8*)pX->pData) + iOffset, iAmt);
+    }
+  }
+  return 0;
+}
+
+
+
+
+
+static int btreeOverwriteCell(BtCursor *pCur, const BtreePayload *pX){
+  int iOffset;
+  int nTotal = pX->nData + pX->nZero;
+  int rc;
+  MemPage *pPage = pCur->pPage;
+  BtShared *pBt;
+  Pgno ovflPgno;
+  u32 ovflPageSize;
+
+  if( pCur->info.pPayload + pCur->info.nLocal > pPage->aDataEnd ){
+    return sqlite3CorruptError(8479);
+  }
+
+  rc = btreeOverwriteContent(pPage, pCur->info.pPayload, pX,
+                             0, pCur->info.nLocal);
+  if( rc ) return rc;
+  if( pCur->info.nLocal==nTotal ) return 0;
+
+
+  iOffset = pCur->info.nLocal;
+  assert( nTotal>=0 );
+  assert( iOffset>=0 );
+  ovflPgno = sqlite3Get4byte(pCur->info.pPayload + iOffset);
+  pBt = pPage->pBt;
+  ovflPageSize = pBt->usableSize - 4;
+  do{
+    rc = btreeGetPage(pBt, ovflPgno, &pPage, 0);
+    if( rc ) return rc;
+    if( sqlite3PagerPageRefcount(pPage->pDbPage)!=1 ){
+      rc = sqlite3CorruptError(8498);
+    }else{
+      if( iOffset+ovflPageSize<(u32)nTotal ){
+        ovflPgno = sqlite3Get4byte(pPage->aData);
+      }else{
+        ovflPageSize = nTotal - iOffset;
+      }
+      rc = btreeOverwriteContent(pPage, pPage->aData+4, pX,
+                                 iOffset, ovflPageSize);
+    }
+    sqlite3PagerUnref(pPage->pDbPage);
+    if( rc ) return rc;
+    iOffset += ovflPageSize;
+  }while( iOffset<nTotal );
+  return 0;
+}
+# 8546 "src/btree.c"
+int sqlite3BtreeInsert(
+  BtCursor *pCur,
+  const BtreePayload *pX,
+  int flags,
+  int seekResult
+){
+  int rc;
+  int loc = seekResult;
+  int szNew = 0;
+  int idx;
+  MemPage *pPage;
+  Btree *p = pCur->pBtree;
+  BtShared *pBt = p->pBt;
+  unsigned char *oldCell;
+  unsigned char *newCell = 0;
+
+  assert( (flags & (0x02|0x08))==flags );
+
+  if( pCur->eState==4 ){
+    assert( pCur->skipNext!=0 );
+    return pCur->skipNext;
+  }
+
+  assert( cursorOwnsBtShared(pCur) );
+  assert( (pCur->curFlags & 0x01)!=0
+              && pBt->inTransaction==2
+              && (pBt->btsFlags & 0x0001)==0 );
+  assert( hasSharedCacheTableLock(p, pCur->pgnoRoot, pCur->pKeyInfo!=0, 2) );
+
+
+
+
+
+
+  assert( (pX->pKey==0)==(pCur->pKeyInfo==0) );
+# 8593 "src/btree.c"
+  if( pCur->curFlags & 0x20 ){
+    rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur);
+    if( rc ) return rc;
+  }
+
+  if( pCur->pKeyInfo==0 ){
+    assert( pX->pKey==0 );
+
+
+    invalidateIncrblobCursors(p, pCur->pgnoRoot, pX->nKey, 0);
+# 8620 "src/btree.c"
+    if( (pCur->curFlags&0x02)!=0 && pX->nKey==pCur->info.nKey ){
+
+
+      assert( pX->nData>=0 && pX->nZero>=0 );
+      if( pCur->info.nSize!=0
+       && pCur->info.nPayload==(u32)pX->nData+pX->nZero
+      ){
+
+        return btreeOverwriteCell(pCur, pX);
+      }
+      assert( loc==0 );
+    }else if( loc==0 ){
+
+
+
+
+      rc = sqlite3BtreeMovetoUnpacked(pCur, 0, pX->nKey, flags!=0, &loc);
+      if( rc ) return rc;
+    }
+  }else{
+
+
+
+
+
+    assert( (flags & 0x02)==0 || loc==0 );
+
+
+
+
+
+
+    if( loc==0 && (flags & 0x02)==0 ){
+      if( pX->nMem ){
+        UnpackedRecord r;
+        r.pKeyInfo = pCur->pKeyInfo;
+        r.aMem = pX->aMem;
+        r.nField = pX->nMem;
+        r.default_rc = 0;
+        r.errCode = 0;
+        r.r1 = 0;
+        r.r2 = 0;
+        r.eqSeen = 0;
+        rc = sqlite3BtreeMovetoUnpacked(pCur, &r, 0, flags!=0, &loc);
+      }else{
+        rc = btreeMoveto(pCur, pX->pKey, pX->nKey, flags!=0, &loc);
+      }
+      if( rc ) return rc;
+    }
+
+
+
+
+
+    if( loc==0 ){
+      getCellInfo(pCur);
+      if( pCur->info.nKey==pX->nKey ){
+        BtreePayload x2;
+        x2.pData = pX->pKey;
+        x2.nData = pX->nKey;
+        x2.nZero = 0;
+        return btreeOverwriteCell(pCur, &x2);
+      }
+    }
+
+  }
+  assert( pCur->eState==0 || (pCur->eState==1 && loc) );
+
+  pPage = pCur->pPage;
+  assert( pPage->intKey || pX->nKey>=0 );
+  assert( pPage->leaf || !pPage->intKey );
+  if( pPage->nFree<0 ){
+    rc = btreeComputeFreeSpace(pPage);
+    if( rc ) return rc;
+  }
+
+ 
+
+                                              ;
+  assert( pPage->isInit );
+  newCell = pBt->pTmpSpace;
+  assert( newCell!=0 );
+  rc = fillInCell(pPage, newCell, pX, &szNew);
+  if( rc ) goto end_insert;
+  assert( szNew==pPage->xCellSize(pPage, newCell) );
+  assert( szNew <= ((int)(pBt->pageSize-8)) );
+  idx = pCur->ix;
+  if( loc==0 ){
+    CellInfo info;
+    assert( idx<pPage->nCell );
+    rc = sqlite3PagerWrite(pPage->pDbPage);
+    if( rc ){
+      goto end_insert;
+    }
+    oldCell = ((pPage)->aData + ((pPage)->maskPage & __builtin_bswap16(*(u16*)(&(pPage)->aCellIdx[2*(idx)]))));
+    if( !pPage->leaf ){
+      memcpy(newCell, oldCell, 4);
+    }
+    rc = clearCell(pPage, oldCell, &info);
+    if( info.nSize==szNew && info.nLocal==info.nPayload
+     && (!(pBt->autoVacuum) || szNew<pPage->minLocal)
+    ){
+# 8731 "src/btree.c"
+      assert( rc==0 );
+      if( oldCell+szNew > pPage->aDataEnd ) return sqlite3CorruptError(8732);
+      memcpy(oldCell, newCell, szNew);
+      return 0;
+    }
+    dropCell(pPage, idx, info.nSize, &rc);
+    if( rc ) goto end_insert;
+  }else if( loc<0 && pPage->nCell>0 ){
+    assert( pPage->leaf );
+    idx = ++pCur->ix;
+    pCur->curFlags &= ~0x02;
+  }else{
+    assert( pPage->leaf );
+  }
+  insertCell(pPage, idx, newCell, szNew, 0, 0, &rc);
+  assert( pPage->nOverflow==0 || rc==0 );
+  assert( rc!=0 || pPage->nCell>0 || pPage->nOverflow>0 );
+# 8769 "src/btree.c"
+  pCur->info.nSize = 0;
+  if( pPage->nOverflow ){
+    assert( rc==0 );
+    pCur->curFlags &= ~(0x02);
+    rc = balance(pCur);
+
+
+
+
+
+    pCur->pPage->nOverflow = 0;
+    pCur->eState = 1;
+    if( (flags & 0x02) && rc==0 ){
+      btreeReleaseAllCursorPages(pCur);
+      if( pCur->pKeyInfo ){
+        assert( pCur->pKey==0 );
+        pCur->pKey = sqlite3Malloc( pX->nKey );
+        if( pCur->pKey==0 ){
+          rc = 7;
+        }else{
+          memcpy(pCur->pKey, pX->pKey, pX->nKey);
+        }
+      }
+      pCur->eState = 3;
+      pCur->nKey = pX->nKey;
+    }
+  }
+  assert( pCur->iPage<0 || pCur->pPage->nOverflow==0 );
+
+end_insert:
+  return rc;
+}
+# 8819 "src/btree.c"
+int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){
+  Btree *p = pCur->pBtree;
+  BtShared *pBt = p->pBt;
+  int rc;
+  MemPage *pPage;
+  unsigned char *pCell;
+  int iCellIdx;
+  int iCellDepth;
+  CellInfo info;
+  int bSkipnext = 0;
+  u8 bPreserve = flags & 0x02;
+
+  assert( cursorOwnsBtShared(pCur) );
+  assert( pBt->inTransaction==2 );
+  assert( (pBt->btsFlags & 0x0001)==0 );
+  assert( pCur->curFlags & 0x01 );
+  assert( hasSharedCacheTableLock(p, pCur->pgnoRoot, pCur->pKeyInfo!=0, 2) );
+  assert( !hasReadConflicts(p, pCur->pgnoRoot) );
+  assert( (flags & ~(0x02 | 0x04))==0 );
+  if( pCur->eState==3 ){
+    rc = btreeRestoreCursorPosition(pCur);
+    if( rc ) return rc;
+  }
+  assert( pCur->eState==0 );
+
+  iCellDepth = pCur->iPage;
+  iCellIdx = pCur->ix;
+  pPage = pCur->pPage;
+  pCell = ((pPage)->aData + ((pPage)->maskPage & __builtin_bswap16(*(u16*)(&(pPage)->aCellIdx[2*(iCellIdx)]))));
+  if( pPage->nFree<0 && btreeComputeFreeSpace(pPage) ) return 11;
+# 8859 "src/btree.c"
+  if( bPreserve ){
+    if( !pPage->leaf
+     || (pPage->nFree+cellSizePtr(pPage,pCell)+2)>(int)(pBt->usableSize*2/3)
+     || pPage->nCell==1
+    ){
+
+
+      rc = saveCursorKey(pCur);
+      if( rc ) return rc;
+    }else{
+      bSkipnext = 1;
+    }
+  }
+# 8880 "src/btree.c"
+  if( !pPage->leaf ){
+    rc = sqlite3BtreePrevious(pCur, 0);
+    assert( rc!=101 );
+    if( rc ) return rc;
+  }
+
+
+
+  if( pCur->curFlags & 0x20 ){
+    rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur);
+    if( rc ) return rc;
+  }
+
+
+
+  if( pCur->pKeyInfo==0 ){
+    invalidateIncrblobCursors(p, pCur->pgnoRoot, pCur->info.nKey, 0);
+  }
+
+
+
+
+  rc = sqlite3PagerWrite(pPage->pDbPage);
+  if( rc ) return rc;
+  rc = clearCell(pPage, pCell, &info);
+  dropCell(pPage, iCellIdx, info.nSize, &rc);
+  if( rc ) return rc;
+
+
+
+
+
+
+  if( !pPage->leaf ){
+    MemPage *pLeaf = pCur->pPage;
+    int nCell;
+    Pgno n;
+    unsigned char *pTmp;
+
+    if( pLeaf->nFree<0 ){
+      rc = btreeComputeFreeSpace(pLeaf);
+      if( rc ) return rc;
+    }
+    if( iCellDepth<pCur->iPage-1 ){
+      n = pCur->apPage[iCellDepth+1]->pgno;
+    }else{
+      n = pCur->pPage->pgno;
+    }
+    pCell = ((pLeaf)->aData + ((pLeaf)->maskPage & __builtin_bswap16(*(u16*)(&(pLeaf)->aCellIdx[2*(pLeaf->nCell-1)]))));
+    if( pCell<&pLeaf->aData[4] ) return sqlite3CorruptError(8929);
+    nCell = pLeaf->xCellSize(pLeaf, pCell);
+    assert( ((int)(pBt->pageSize-8)) >= nCell );
+    pTmp = pBt->pTmpSpace;
+    assert( pTmp!=0 );
+    rc = sqlite3PagerWrite(pLeaf->pDbPage);
+    if( rc==0 ){
+      insertCell(pPage, iCellIdx, pCell-4, nCell+4, pTmp, n, &rc);
+    }
+    dropCell(pLeaf, pLeaf->nCell-1, nCell, &rc);
+    if( rc ) return rc;
+  }
+# 8957 "src/btree.c"
+  rc = balance(pCur);
+  if( rc==0 && pCur->iPage>iCellDepth ){
+    releasePageNotNull(pCur->pPage);
+    pCur->iPage--;
+    while( pCur->iPage>iCellDepth ){
+      releasePage(pCur->apPage[pCur->iPage--]);
+    }
+    pCur->pPage = pCur->apPage[pCur->iPage];
+    rc = balance(pCur);
+  }
+
+  if( rc==0 ){
+    if( bSkipnext ){
+      assert( bPreserve && (pCur->iPage==iCellDepth || (sqlite3Config.neverCorrupt==0)) );
+      assert( pPage==pCur->pPage || (sqlite3Config.neverCorrupt==0) );
+      assert( (pPage->nCell>0 || (sqlite3Config.neverCorrupt==0)) && iCellIdx<=pPage->nCell );
+      pCur->eState = 2;
+      if( iCellIdx>=pPage->nCell ){
+        pCur->skipNext = -1;
+        pCur->ix = pPage->nCell-1;
+      }else{
+        pCur->skipNext = 1;
+      }
+    }else{
+      rc = moveToRoot(pCur);
+      if( bPreserve ){
+        btreeReleaseAllCursorPages(pCur);
+        pCur->eState = 3;
+      }
+      if( rc==16 ) rc = 0;
+    }
+  }
+  return rc;
+}
+# 9003 "src/btree.c"
+static int btreeCreateTable(Btree *p, int *piTable, int createTabFlags){
+  BtShared *pBt = p->pBt;
+  MemPage *pRoot;
+  Pgno pgnoRoot;
+  int rc;
+  int ptfFlags;
+
+  assert( sqlite3BtreeHoldsMutex(p) );
+  assert( pBt->inTransaction==2 );
+  assert( (pBt->btsFlags & 0x0001)==0 );
+
+
+
+
+
+
+
+  if( pBt->autoVacuum ){
+    Pgno pgnoMove;
+    MemPage *pPageMove;
+
+
+
+
+
+
+    invalidateAllOverflowCache(pBt);
+
+
+
+
+
+    sqlite3BtreeGetMeta(p, 4, &pgnoRoot);
+    pgnoRoot++;
+
+
+
+
+    while( pgnoRoot==ptrmapPageno(pBt, pgnoRoot) ||
+        pgnoRoot==((Pgno)((sqlite3PendingByte/((pBt)->pageSize))+1)) ){
+      pgnoRoot++;
+    }
+    assert( pgnoRoot>=3 || (sqlite3Config.neverCorrupt==0) );
+    ;
+
+
+
+
+
+    rc = allocateBtreePage(pBt, &pPageMove, &pgnoMove, pgnoRoot, 1);
+    if( rc!=0 ){
+      return rc;
+    }
+
+    if( pgnoMove!=pgnoRoot ){
+
+
+
+
+
+
+      u8 eType = 0;
+      Pgno iPtrPage = 0;
+
+
+
+
+      rc = saveAllCursors(pBt, 0, 0);
+      releasePage(pPageMove);
+      if( rc!=0 ){
+        return rc;
+      }
+
+
+      rc = btreeGetPage(pBt, pgnoRoot, &pRoot, 0);
+      if( rc!=0 ){
+        return rc;
+      }
+      rc = ptrmapGet(pBt, pgnoRoot, &eType, &iPtrPage);
+      if( eType==1 || eType==2 ){
+        rc = sqlite3CorruptError(9083);
+      }
+      if( rc!=0 ){
+        releasePage(pRoot);
+        return rc;
+      }
+      assert( eType!=1 );
+      assert( eType!=2 );
+      rc = relocatePage(pBt, pRoot, eType, iPtrPage, pgnoMove, 0);
+      releasePage(pRoot);
+
+
+      if( rc!=0 ){
+        return rc;
+      }
+      rc = btreeGetPage(pBt, pgnoRoot, &pRoot, 0);
+      if( rc!=0 ){
+        return rc;
+      }
+      rc = sqlite3PagerWrite(pRoot->pDbPage);
+      if( rc!=0 ){
+        releasePage(pRoot);
+        return rc;
+      }
+    }else{
+      pRoot = pPageMove;
+    }
+
+
+    ptrmapPut(pBt, pgnoRoot, 1, 0, &rc);
+    if( rc ){
+      releasePage(pRoot);
+      return rc;
+    }
+
+
+
+
+
+    assert( sqlite3PagerIswriteable(pBt->pPage1->pDbPage) );
+    rc = sqlite3BtreeUpdateMeta(p, 4, pgnoRoot);
+    if( (rc) ){
+      releasePage(pRoot);
+      return rc;
+    }
+
+  }else{
+    rc = allocateBtreePage(pBt, &pRoot, &pgnoRoot, 1, 0);
+    if( rc ) return rc;
+  }
+
+  assert( sqlite3PagerIswriteable(pRoot->pDbPage) );
+  if( createTabFlags & 1 ){
+    ptfFlags = 0x01 | 0x04 | 0x08;
+  }else{
+    ptfFlags = 0x02 | 0x08;
+  }
+  zeroPage(pRoot, ptfFlags);
+  sqlite3PagerUnref(pRoot->pDbPage);
+  assert( (pBt->openFlags & 4)==0 || pgnoRoot==2 );
+  *piTable = (int)pgnoRoot;
+  return 0;
+}
+int sqlite3BtreeCreateTable(Btree *p, int *piTable, int flags){
+  int rc;
+  sqlite3BtreeEnter(p);
+  rc = btreeCreateTable(p, piTable, flags);
+  sqlite3BtreeLeave(p);
+  return rc;
+}
+
+
+
+
+
+static int clearDatabasePage(
+  BtShared *pBt,
+  Pgno pgno,
+  int freePageFlag,
+  int *pnChange
+){
+  MemPage *pPage;
+  int rc;
+  unsigned char *pCell;
+  int i;
+  int hdr;
+  CellInfo info;
+
+  assert( sqlite3_mutex_held(pBt->mutex) );
+  if( pgno>btreePagecount(pBt) ){
+    return sqlite3CorruptError(9173);
+  }
+  rc = getAndInitPage(pBt, pgno, &pPage, 0, 0);
+  if( rc ) return rc;
+  if( pPage->bBusy ){
+    rc = sqlite3CorruptError(9178);
+    goto cleardatabasepage_out;
+  }
+  pPage->bBusy = 1;
+  hdr = pPage->hdrOffset;
+  for(i=0; i<pPage->nCell; i++){
+    pCell = ((pPage)->aData + ((pPage)->maskPage & __builtin_bswap16(*(u16*)(&(pPage)->aCellIdx[2*(i)]))));
+    if( !pPage->leaf ){
+      rc = clearDatabasePage(pBt, sqlite3Get4byte(pCell), 1, pnChange);
+      if( rc ) goto cleardatabasepage_out;
+    }
+    rc = clearCell(pPage, pCell, &info);
+    if( rc ) goto cleardatabasepage_out;
+  }
+  if( !pPage->leaf ){
+    rc = clearDatabasePage(pBt, sqlite3Get4byte(&pPage->aData[hdr+8]), 1, pnChange);
+    if( rc ) goto cleardatabasepage_out;
+  }else if( pnChange ){
+    assert( pPage->intKey || (sqlite3Config.neverCorrupt==0) );
+    ;
+    *pnChange += pPage->nCell;
+  }
+  if( freePageFlag ){
+    freePage(pPage, &rc);
+  }else if( (rc = sqlite3PagerWrite(pPage->pDbPage))==0 ){
+    zeroPage(pPage, pPage->aData[hdr] | 0x08);
+  }
+
+cleardatabasepage_out:
+  pPage->bBusy = 0;
+  releasePage(pPage);
+  return rc;
+}
+# 9225 "src/btree.c"
+int sqlite3BtreeClearTable(Btree *p, int iTable, int *pnChange){
+  int rc;
+  BtShared *pBt = p->pBt;
+  sqlite3BtreeEnter(p);
+  assert( p->inTrans==2 );
+
+  rc = saveAllCursors(pBt, (Pgno)iTable, 0);
+
+  if( 0==rc ){
+
+
+
+    invalidateIncrblobCursors(p, (Pgno)iTable, 0, 1);
+    rc = clearDatabasePage(pBt, (Pgno)iTable, 0, pnChange);
+  }
+  sqlite3BtreeLeave(p);
+  return rc;
+}
+
+
+
+
+
+
+int sqlite3BtreeClearTableOfCursor(BtCursor *pCur){
+  return sqlite3BtreeClearTable(pCur->pBtree, pCur->pgnoRoot, 0);
+}
+# 9273 "src/btree.c"
+static int btreeDropTable(Btree *p, Pgno iTable, int *piMoved){
+  int rc;
+  MemPage *pPage = 0;
+  BtShared *pBt = p->pBt;
+
+  assert( sqlite3BtreeHoldsMutex(p) );
+  assert( p->inTrans==2 );
+  assert( iTable>=2 );
+  if( iTable>btreePagecount(pBt) ){
+    return sqlite3CorruptError(9282);
+  }
+
+  rc = btreeGetPage(pBt, (Pgno)iTable, &pPage, 0);
+  if( rc ) return rc;
+  rc = sqlite3BtreeClearTable(p, iTable, 0);
+  if( rc ){
+    releasePage(pPage);
+    return rc;
+  }
+
+  *piMoved = 0;
+
+
+
+
+
+  if( pBt->autoVacuum ){
+    Pgno maxRootPgno;
+    sqlite3BtreeGetMeta(p, 4, &maxRootPgno);
+
+    if( iTable==maxRootPgno ){
+
+
+
+      freePage(pPage, &rc);
+      releasePage(pPage);
+      if( rc!=0 ){
+        return rc;
+      }
+    }else{
+
+
+
+
+      MemPage *pMove;
+      releasePage(pPage);
+      rc = btreeGetPage(pBt, maxRootPgno, &pMove, 0);
+      if( rc!=0 ){
+        return rc;
+      }
+      rc = relocatePage(pBt, pMove, 1, 0, iTable, 0);
+      releasePage(pMove);
+      if( rc!=0 ){
+        return rc;
+      }
+      pMove = 0;
+      rc = btreeGetPage(pBt, maxRootPgno, &pMove, 0);
+      freePage(pMove, &rc);
+      releasePage(pMove);
+      if( rc!=0 ){
+        return rc;
+      }
+      *piMoved = maxRootPgno;
+    }
+
+
+
+
+
+
+    maxRootPgno--;
+    while( maxRootPgno==((Pgno)((sqlite3PendingByte/((pBt)->pageSize))+1))
+           || (ptrmapPageno((pBt), (maxRootPgno))==(maxRootPgno)) ){
+      maxRootPgno--;
+    }
+    assert( maxRootPgno!=((Pgno)((sqlite3PendingByte/((pBt)->pageSize))+1)) );
+
+    rc = sqlite3BtreeUpdateMeta(p, 4, maxRootPgno);
+  }else{
+    freePage(pPage, &rc);
+    releasePage(pPage);
+  }
+
+  return rc;
+}
+int sqlite3BtreeDropTable(Btree *p, int iTable, int *piMoved){
+  int rc;
+  sqlite3BtreeEnter(p);
+  rc = btreeDropTable(p, iTable, piMoved);
+  sqlite3BtreeLeave(p);
+  return rc;
+}
+# 9387 "src/btree.c"
+void sqlite3BtreeGetMeta(Btree *p, int idx, u32 *pMeta){
+  BtShared *pBt = p->pBt;
+
+  sqlite3BtreeEnter(p);
+  assert( p->inTrans>0 );
+  assert( 0==querySharedCacheTableLock(p, 1, 1) );
+  assert( pBt->pPage1 );
+  assert( idx>=0 && idx<=15 );
+
+  if( idx==15 ){
+    *pMeta = sqlite3PagerDataVersion(pBt->pPager) + p->iDataVersion;
+  }else{
+    *pMeta = sqlite3Get4byte(&pBt->pPage1->aData[36 + idx*4]);
+  }
+# 9410 "src/btree.c"
+  sqlite3BtreeLeave(p);
+}
+
+
+
+
+
+int sqlite3BtreeUpdateMeta(Btree *p, int idx, u32 iMeta){
+  BtShared *pBt = p->pBt;
+  unsigned char *pP1;
+  int rc;
+  assert( idx>=1 && idx<=15 );
+  sqlite3BtreeEnter(p);
+  assert( p->inTrans==2 );
+  assert( pBt->pPage1!=0 );
+  pP1 = pBt->pPage1->aData;
+  rc = sqlite3PagerWrite(pBt->pPage1->pDbPage);
+  if( rc==0 ){
+    sqlite3Put4byte(&pP1[36 + idx*4], iMeta);
+
+    if( idx==7 ){
+      assert( pBt->autoVacuum || iMeta==0 );
+      assert( iMeta==0 || iMeta==1 );
+      pBt->incrVacuum = (u8)iMeta;
+    }
+
+  }
+  sqlite3BtreeLeave(p);
+  return rc;
+}
+# 9450 "src/btree.c"
+int sqlite3BtreeCount(BtCursor *pCur, i64 *pnEntry){
+  i64 nEntry = 0;
+  int rc;
+
+  rc = moveToRoot(pCur);
+  if( rc==16 ){
+    *pnEntry = 0;
+    return 0;
+  }
+
+
+
+
+  while( rc==0 ){
+    int iIdx;
+    MemPage *pPage;
+
+
+
+
+
+    pPage = pCur->pPage;
+    if( pPage->leaf || !pPage->intKey ){
+      nEntry += pPage->nCell;
+    }
+# 9486 "src/btree.c"
+    if( pPage->leaf ){
+      do {
+        if( pCur->iPage==0 ){
+
+          *pnEntry = nEntry;
+          return moveToRoot(pCur);
+        }
+        moveToParent(pCur);
+      }while ( pCur->ix>=pCur->pPage->nCell );
+
+      pCur->ix++;
+      pPage = pCur->pPage;
+    }
+
+
+
+
+    iIdx = pCur->ix;
+    if( iIdx==pPage->nCell ){
+      rc = moveToChild(pCur, sqlite3Get4byte(&pPage->aData[pPage->hdrOffset+8]));
+    }else{
+      rc = moveToChild(pCur, sqlite3Get4byte(((pPage)->aData + ((pPage)->maskPage & __builtin_bswap16(*(u16*)(&(pPage)->aCellIdx[2*(iIdx)]))))));
+    }
+  }
+
+
+  return rc;
+}
+
+
+
+
+
+
+Pager *sqlite3BtreePager(Btree *p){
+  return p->pBt->pPager;
+}
+
+
+
+
+
+static void checkAppendMsg(
+  IntegrityCk *pCheck,
+  const char *zFormat,
+  ...
+){
+  va_list ap;
+  if( !pCheck->mxErr ) return;
+  pCheck->mxErr--;
+  pCheck->nErr++;
+  __builtin_va_start((ap));
+  if( pCheck->errMsg.nChar ){
+    sqlite3_str_append(&pCheck->errMsg, "\n", 1);
+  }
+  if( pCheck->zPfx ){
+    sqlite3_str_appendf(&pCheck->errMsg, pCheck->zPfx, pCheck->v1, pCheck->v2);
+  }
+  sqlite3_str_vappendf(&pCheck->errMsg, zFormat, ap);
+  ;
+  if( pCheck->errMsg.accError==7 ){
+    pCheck->mallocFailed = 1;
+  }
+}
+# 9558 "src/btree.c"
+static int getPageReferenced(IntegrityCk *pCheck, Pgno iPg){
+  assert( iPg<=pCheck->nPage && sizeof(pCheck->aPgRef[0])==1 );
+  return (pCheck->aPgRef[iPg/8] & (1 << (iPg & 0x07)));
+}
+
+
+
+
+static void setPageReferenced(IntegrityCk *pCheck, Pgno iPg){
+  assert( iPg<=pCheck->nPage && sizeof(pCheck->aPgRef[0])==1 );
+  pCheck->aPgRef[iPg/8] |= (1 << (iPg & 0x07));
+}
+# 9580 "src/btree.c"
+static int checkRef(IntegrityCk *pCheck, Pgno iPage){
+  if( iPage>pCheck->nPage || iPage==0 ){
+    checkAppendMsg(pCheck, "invalid page number %d", iPage);
+    return 1;
+  }
+  if( getPageReferenced(pCheck, iPage) ){
+    checkAppendMsg(pCheck, "2nd reference to page %d", iPage);
+    return 1;
+  }
+  setPageReferenced(pCheck, iPage);
+  return 0;
+}
+
+
+
+
+
+
+
+static void checkPtrmap(
+  IntegrityCk *pCheck,
+  Pgno iChild,
+  u8 eType,
+  Pgno iParent
+){
+  int rc;
+  u8 ePtrmapType;
+  Pgno iPtrmapParent;
+
+  rc = ptrmapGet(pCheck->pBt, iChild, &ePtrmapType, &iPtrmapParent);
+  if( rc!=0 ){
+    if( rc==7 || rc==(10 | (12<<8)) ) pCheck->mallocFailed = 1;
+    checkAppendMsg(pCheck, "Failed to read ptrmap key=%d", iChild);
+    return;
+  }
+
+  if( ePtrmapType!=eType || iPtrmapParent!=iParent ){
+    checkAppendMsg(pCheck,
+      "Bad ptr map entry key=%d expected=(%d,%d) got=(%d,%d)",
+      iChild, eType, iParent, ePtrmapType, iPtrmapParent);
+  }
+}
+
+
+
+
+
+
+static void checkList(
+  IntegrityCk *pCheck,
+  int isFreeList,
+  int iPage,
+  u32 N
+){
+  int i;
+  u32 expected = N;
+  int nErrAtStart = pCheck->nErr;
+  while( iPage!=0 && pCheck->mxErr ){
+    DbPage *pOvflPage;
+    unsigned char *pOvflData;
+    if( checkRef(pCheck, iPage) ) break;
+    N--;
+    if( sqlite3PagerGet(pCheck->pPager, (Pgno)iPage, &pOvflPage, 0) ){
+      checkAppendMsg(pCheck, "failed to get page %d", iPage);
+      break;
+    }
+    pOvflData = (unsigned char *)sqlite3PagerGetData(pOvflPage);
+    if( isFreeList ){
+      u32 n = (u32)sqlite3Get4byte(&pOvflData[4]);
+
+      if( pCheck->pBt->autoVacuum ){
+        checkPtrmap(pCheck, iPage, 2, 0);
+      }
+
+      if( n>pCheck->pBt->usableSize/4-2 ){
+        checkAppendMsg(pCheck,
+           "freelist leaf count too big on page %d", iPage);
+        N--;
+      }else{
+        for(i=0; i<(int)n; i++){
+          Pgno iFreePage = sqlite3Get4byte(&pOvflData[8+i*4]);
+
+          if( pCheck->pBt->autoVacuum ){
+            checkPtrmap(pCheck, iFreePage, 2, 0);
+          }
+
+          checkRef(pCheck, iFreePage);
+        }
+        N -= n;
+      }
+    }
+
+    else{
+
+
+
+
+      if( pCheck->pBt->autoVacuum && N>0 ){
+        i = sqlite3Get4byte(pOvflData);
+        checkPtrmap(pCheck, i, 4, iPage);
+      }
+    }
+
+    iPage = sqlite3Get4byte(pOvflData);
+    sqlite3PagerUnref(pOvflPage);
+  }
+  if( N && nErrAtStart==pCheck->nErr ){
+    checkAppendMsg(pCheck,
+      "%s is %d but should be %d",
+      isFreeList ? "size" : "overflow list length",
+      expected-N, expected);
+  }
+}
+# 9717 "src/btree.c"
+static void btreeHeapInsert(u32 *aHeap, u32 x){
+  u32 j, i = ++aHeap[0];
+  aHeap[i] = x;
+  while( (j = i/2)>0 && aHeap[j]>aHeap[i] ){
+    x = aHeap[j];
+    aHeap[j] = aHeap[i];
+    aHeap[i] = x;
+    i = j;
+  }
+}
+static int btreeHeapPull(u32 *aHeap, u32 *pOut){
+  u32 j, i, x;
+  if( (x = aHeap[0])==0 ) return 0;
+  *pOut = aHeap[1];
+  aHeap[1] = aHeap[x];
+  aHeap[x] = 0xffffffff;
+  aHeap[0]--;
+  i = 1;
+  while( (j = i*2)<=aHeap[0] ){
+    if( aHeap[j]>aHeap[j+1] ) j++;
+    if( aHeap[i]<aHeap[j] ) break;
+    x = aHeap[i];
+    aHeap[i] = aHeap[j];
+    aHeap[j] = x;
+    i = j;
+  }
+  return 1;
+}
+# 9761 "src/btree.c"
+static int checkTreePage(
+  IntegrityCk *pCheck,
+  int iPage,
+  i64 *piMinKey,
+  i64 maxKey
+){
+  MemPage *pPage = 0;
+  int i;
+  int rc;
+  int depth = -1, d2;
+  int pgno;
+  int nFrag;
+  int hdr;
+  int cellStart;
+  int nCell;
+  int doCoverageCheck = 1;
+  int keyCanBeEqual = 1;
+
+  u8 *data;
+  u8 *pCell;
+  u8 *pCellIdx;
+  BtShared *pBt;
+  u32 pc;
+  u32 usableSize;
+  u32 contentOffset;
+  u32 *heap = 0;
+  u32 x, prev = 0;
+  const char *saved_zPfx = pCheck->zPfx;
+  int saved_v1 = pCheck->v1;
+  int saved_v2 = pCheck->v2;
+  u8 savedIsInit = 0;
+
+
+
+  pBt = pCheck->pBt;
+  usableSize = pBt->usableSize;
+  if( iPage==0 ) return 0;
+  if( checkRef(pCheck, iPage) ) return 0;
+  pCheck->zPfx = "Page %d: ";
+  pCheck->v1 = iPage;
+  if( (rc = btreeGetPage(pBt, (Pgno)iPage, &pPage, 0))!=0 ){
+    checkAppendMsg(pCheck,
+       "unable to get the page. error code=%d", rc);
+    goto end_of_check;
+  }
+
+
+
+  savedIsInit = pPage->isInit;
+  pPage->isInit = 0;
+  if( (rc = btreeInitPage(pPage))!=0 ){
+    assert( rc==11 );
+    checkAppendMsg(pCheck,
+                   "btreeInitPage() returns error code %d", rc);
+    goto end_of_check;
+  }
+  if( (rc = btreeComputeFreeSpace(pPage))!=0 ){
+    assert( rc==11 );
+    checkAppendMsg(pCheck, "free space corruption", rc);
+    goto end_of_check;
+  }
+  data = pPage->aData;
+  hdr = pPage->hdrOffset;
+
+
+  pCheck->zPfx = "On tree page %d cell %d: ";
+  contentOffset = (((((int)((&data[hdr+5])[0]<<8 | (&data[hdr+5])[1]))-1)&0xffff)+1);
+  assert( contentOffset<=usableSize );
+
+
+
+  nCell = ((&data[hdr+3])[0]<<8 | (&data[hdr+3])[1]);
+  assert( pPage->nCell==nCell );
+
+
+
+  cellStart = hdr + 12 - 4*pPage->leaf;
+  assert( pPage->aCellIdx==&data[cellStart] );
+  pCellIdx = &data[cellStart + 2*(nCell-1)];
+
+  if( !pPage->leaf ){
+
+    pgno = sqlite3Get4byte(&data[hdr+8]);
+
+    if( pBt->autoVacuum ){
+      pCheck->zPfx = "On page %d at right child: ";
+      checkPtrmap(pCheck, pgno, 5, iPage);
+    }
+
+    depth = checkTreePage(pCheck, pgno, &maxKey, maxKey);
+    keyCanBeEqual = 0;
+  }else{
+
+
+    heap = pCheck->heap;
+    heap[0] = 0;
+  }
+
+
+
+  for(i=nCell-1; i>=0 && pCheck->mxErr; i--){
+    CellInfo info;
+
+
+    pCheck->v2 = i;
+    assert( pCellIdx==&data[cellStart + i*2] );
+    pc = __builtin_bswap16(*(u16*)(pCellIdx));
+    pCellIdx -= 2;
+    if( pc<contentOffset || pc>usableSize-4 ){
+      checkAppendMsg(pCheck, "Offset %d out of range %d..%d",
+                             pc, contentOffset, usableSize-4);
+      doCoverageCheck = 0;
+      continue;
+    }
+    pCell = &data[pc];
+    pPage->xParseCell(pPage, pCell, &info);
+    if( pc+info.nSize>usableSize ){
+      checkAppendMsg(pCheck, "Extends off end of page");
+      doCoverageCheck = 0;
+      continue;
+    }
+
+
+    if( pPage->intKey ){
+      if( keyCanBeEqual ? (info.nKey > maxKey) : (info.nKey >= maxKey) ){
+        checkAppendMsg(pCheck, "Rowid %lld out of order", info.nKey);
+      }
+      maxKey = info.nKey;
+      keyCanBeEqual = 0;
+    }
+
+
+    if( info.nPayload>info.nLocal ){
+      u32 nPage;
+      Pgno pgnoOvfl;
+      assert( pc + info.nSize - 4 <= usableSize );
+      nPage = (info.nPayload - info.nLocal + usableSize - 5)/(usableSize - 4);
+      pgnoOvfl = sqlite3Get4byte(&pCell[info.nSize - 4]);
+
+      if( pBt->autoVacuum ){
+        checkPtrmap(pCheck, pgnoOvfl, 3, iPage);
+      }
+
+      checkList(pCheck, 0, pgnoOvfl, nPage);
+    }
+
+    if( !pPage->leaf ){
+
+      pgno = sqlite3Get4byte(pCell);
+
+      if( pBt->autoVacuum ){
+        checkPtrmap(pCheck, pgno, 5, iPage);
+      }
+
+      d2 = checkTreePage(pCheck, pgno, &maxKey, maxKey);
+      keyCanBeEqual = 0;
+      if( d2!=depth ){
+        checkAppendMsg(pCheck, "Child page depth differs");
+        depth = d2;
+      }
+    }else{
+
+      btreeHeapInsert(heap, (pc<<16)|(pc+info.nSize-1));
+    }
+  }
+  *piMinKey = maxKey;
+
+
+
+  pCheck->zPfx = 0;
+  if( doCoverageCheck && pCheck->mxErr>0 ){
+
+
+
+    if( !pPage->leaf ){
+      heap = pCheck->heap;
+      heap[0] = 0;
+      for(i=nCell-1; i>=0; i--){
+        u32 size;
+        pc = __builtin_bswap16(*(u16*)(&data[cellStart+i*2]));
+        size = pPage->xCellSize(pPage, &data[pc]);
+        btreeHeapInsert(heap, (pc<<16)|(pc+size-1));
+      }
+    }
+
+
+
+
+
+
+    i = ((&data[hdr+1])[0]<<8 | (&data[hdr+1])[1]);
+    while( i>0 ){
+      int size, j;
+      assert( (u32)i<=usableSize-4 );
+      size = ((&data[i+2])[0]<<8 | (&data[i+2])[1]);
+      assert( (u32)(i+size)<=usableSize );
+      btreeHeapInsert(heap, (((u32)i)<<16)|(i+size-1));
+
+
+
+
+      j = ((&data[i])[0]<<8 | (&data[i])[1]);
+
+
+      assert( j==0 || j>i+size );
+      assert( (u32)j<=usableSize-4 );
+      i = j;
+    }
+# 9982 "src/btree.c"
+    nFrag = 0;
+    prev = contentOffset - 1;
+    while( btreeHeapPull(heap,&x) ){
+      if( (prev&0xffff)>=(x>>16) ){
+        checkAppendMsg(pCheck,
+          "Multiple uses for byte %u of page %d", x>>16, iPage);
+        break;
+      }else{
+        nFrag += (x>>16) - (prev&0xffff) - 1;
+        prev = x;
+      }
+    }
+    nFrag += usableSize - (prev&0xffff) - 1;
+
+
+
+
+
+    if( heap[0]==0 && nFrag!=data[hdr+7] ){
+      checkAppendMsg(pCheck,
+          "Fragmentation of %d bytes reported as %d on page %d",
+          nFrag, data[hdr+7], iPage);
+    }
+  }
+
+end_of_check:
+  if( !doCoverageCheck ) pPage->isInit = savedIsInit;
+  releasePage(pPage);
+  pCheck->zPfx = saved_zPfx;
+  pCheck->v1 = saved_v1;
+  pCheck->v2 = saved_v2;
+  return depth+1;
+}
+# 10031 "src/btree.c"
+char *sqlite3BtreeIntegrityCheck(
+  Btree *p,
+  int *aRoot,
+  int nRoot,
+  int mxErr,
+  int *pnErr
+){
+  Pgno i;
+  IntegrityCk sCheck;
+  BtShared *pBt = p->pBt;
+  u64 savedDbFlags = pBt->db->flags;
+  char zErr[100];
+  ;
+
+  sqlite3BtreeEnter(p);
+  assert( p->inTrans>0 && pBt->inTransaction>0 );
+  ;
+  assert( nRef>=0 );
+  sCheck.pBt = pBt;
+  sCheck.pPager = pBt->pPager;
+  sCheck.nPage = btreePagecount(sCheck.pBt);
+  sCheck.mxErr = mxErr;
+  sCheck.nErr = 0;
+  sCheck.mallocFailed = 0;
+  sCheck.zPfx = 0;
+  sCheck.v1 = 0;
+  sCheck.v2 = 0;
+  sCheck.aPgRef = 0;
+  sCheck.heap = 0;
+  sqlite3StrAccumInit(&sCheck.errMsg, 0, zErr, sizeof(zErr), 1000000000);
+  sCheck.errMsg.printfFlags = 0x01;
+  if( sCheck.nPage==0 ){
+    goto integrity_ck_cleanup;
+  }
+
+  sCheck.aPgRef = sqlite3MallocZero((sCheck.nPage / 8)+ 1);
+  if( !sCheck.aPgRef ){
+    sCheck.mallocFailed = 1;
+    goto integrity_ck_cleanup;
+  }
+  sCheck.heap = (u32*)sqlite3PageMalloc( pBt->pageSize );
+  if( sCheck.heap==0 ){
+    sCheck.mallocFailed = 1;
+    goto integrity_ck_cleanup;
+  }
+
+  i = ((Pgno)((sqlite3PendingByte/((pBt)->pageSize))+1));
+  if( i<=sCheck.nPage ) setPageReferenced(&sCheck, i);
+
+
+
+  sCheck.zPfx = "Main freelist: ";
+  checkList(&sCheck, 1, sqlite3Get4byte(&pBt->pPage1->aData[32]),
+            sqlite3Get4byte(&pBt->pPage1->aData[36]));
+  sCheck.zPfx = 0;
+
+
+
+
+  if( pBt->autoVacuum ){
+    int mx = 0;
+    int mxInHdr;
+    for(i=0; (int)i<nRoot; i++) if( mx<aRoot[i] ) mx = aRoot[i];
+    mxInHdr = sqlite3Get4byte(&pBt->pPage1->aData[52]);
+    if( mx!=mxInHdr ){
+      checkAppendMsg(&sCheck,
+        "max rootpage (%d) disagrees with header (%d)",
+        mx, mxInHdr
+      );
+    }
+  }else if( sqlite3Get4byte(&pBt->pPage1->aData[64])!=0 ){
+    checkAppendMsg(&sCheck,
+      "incremental_vacuum enabled with a max rootpage of zero"
+    );
+  }
+
+  ;
+  pBt->db->flags &= ~(u64)0x00200000;
+  for(i=0; (int)i<nRoot && sCheck.mxErr; i++){
+    i64 notUsed;
+    if( aRoot[i]==0 ) continue;
+
+    if( pBt->autoVacuum && aRoot[i]>1 ){
+      checkPtrmap(&sCheck, aRoot[i], 1, 0);
+    }
+
+    checkTreePage(&sCheck, aRoot[i], &notUsed, (0xffffffff|(((i64)0x7fffffff)<<32)));
+  }
+  pBt->db->flags = savedDbFlags;
+
+
+
+  for(i=1; i<=sCheck.nPage && sCheck.mxErr; i++){
+# 10132 "src/btree.c"
+    if( getPageReferenced(&sCheck, i)==0 &&
+       (ptrmapPageno(pBt, i)!=i || !pBt->autoVacuum) ){
+      checkAppendMsg(&sCheck, "Page %d is never used", i);
+    }
+    if( getPageReferenced(&sCheck, i)!=0 &&
+       (ptrmapPageno(pBt, i)==i && pBt->autoVacuum) ){
+      checkAppendMsg(&sCheck, "Pointer map page %d is referenced", i);
+    }
+
+  }
+
+
+
+integrity_ck_cleanup:
+  sqlite3PageFree(sCheck.heap);
+  sqlite3_free(sCheck.aPgRef);
+  if( sCheck.mallocFailed ){
+    sqlite3_str_reset(&sCheck.errMsg);
+    sCheck.nErr++;
+  }
+  *pnErr = sCheck.nErr;
+  if( sCheck.nErr==0 ) sqlite3_str_reset(&sCheck.errMsg);
+
+  assert( nRef==sqlite3PagerRefcount(pBt->pPager) );
+  sqlite3BtreeLeave(p);
+  return sqlite3StrAccumFinish(&sCheck.errMsg);
+}
+# 10168 "src/btree.c"
+const char *sqlite3BtreeGetFilename(Btree *p){
+  assert( p->pBt->pPager!=0 );
+  return sqlite3PagerFilename(p->pBt->pPager, 1);
+}
+# 10181 "src/btree.c"
+const char *sqlite3BtreeGetJournalname(Btree *p){
+  assert( p->pBt->pPager!=0 );
+  return sqlite3PagerJournalname(p->pBt->pPager);
+}
+
+
+
+
+int sqlite3BtreeIsInTrans(Btree *p){
+  assert( p==0 || sqlite3_mutex_held(p->db->mutex) );
+  return (p && (p->inTrans==2));
+}
+# 10203 "src/btree.c"
+int sqlite3BtreeCheckpoint(Btree *p, int eMode, int *pnLog, int *pnCkpt){
+  int rc = 0;
+  if( p ){
+    BtShared *pBt = p->pBt;
+    sqlite3BtreeEnter(p);
+    if( pBt->inTransaction!=0 ){
+      rc = 6;
+    }else{
+      rc = sqlite3PagerCheckpoint(pBt->pPager, p->db, eMode, pnLog, pnCkpt);
+    }
+    sqlite3BtreeLeave(p);
+  }
+  return rc;
+}
+
+
+
+
+
+int sqlite3BtreeIsInReadTrans(Btree *p){
+  assert( p );
+  assert( sqlite3_mutex_held(p->db->mutex) );
+  return p->inTrans!=0;
+}
+
+int sqlite3BtreeIsInBackup(Btree *p){
+  assert( p );
+  assert( sqlite3_mutex_held(p->db->mutex) );
+  return p->nBackup!=0;
+}
+# 10254 "src/btree.c"
+void *sqlite3BtreeSchema(Btree *p, int nBytes, void(*xFree)(void *)){
+  BtShared *pBt = p->pBt;
+  sqlite3BtreeEnter(p);
+  if( !pBt->pSchema && nBytes ){
+    pBt->pSchema = sqlite3DbMallocZero(0, nBytes);
+    pBt->xFreeSchema = xFree;
+  }
+  sqlite3BtreeLeave(p);
+  return pBt->pSchema;
+}
+
+
+
+
+
+
+int sqlite3BtreeSchemaLocked(Btree *p){
+  int rc;
+  assert( sqlite3_mutex_held(p->db->mutex) );
+  sqlite3BtreeEnter(p);
+  rc = querySharedCacheTableLock(p, 1, 1);
+  assert( rc==0 || rc==(6 | (1<<8)) );
+  sqlite3BtreeLeave(p);
+  return rc;
+}
+# 10287 "src/btree.c"
+int sqlite3BtreeLockTable(Btree *p, int iTab, u8 isWriteLock){
+  int rc = 0;
+  assert( p->inTrans!=0 );
+  if( p->sharable ){
+    u8 lockType = 1 + isWriteLock;
+    assert( 1 +1==2 );
+    assert( isWriteLock==0 || isWriteLock==1 );
+
+    sqlite3BtreeEnter(p);
+    rc = querySharedCacheTableLock(p, iTab, lockType);
+    if( rc==0 ){
+      rc = setSharedCacheTableLock(p, iTab, lockType);
+    }
+    sqlite3BtreeLeave(p);
+  }
+  return rc;
+}
+# 10317 "src/btree.c"
+int sqlite3BtreePutData(BtCursor *pCsr, u32 offset, u32 amt, void *z){
+  int rc;
+  assert( cursorOwnsBtShared(pCsr) );
+  assert( sqlite3_mutex_held(pCsr->pBtree->db->mutex) );
+  assert( pCsr->curFlags & 0x10 );
+
+  rc = (pCsr->eState>=3 ? btreeRestoreCursorPosition(pCsr) : 0);
+  if( rc!=0 ){
+    return rc;
+  }
+  assert( pCsr->eState!=3 );
+  if( pCsr->eState!=0 ){
+    return 4;
+  }
+# 10340 "src/btree.c"
+  saveAllCursors(pCsr->pBt, pCsr->pgnoRoot, pCsr);
+  assert( rc==0 );
+# 10350 "src/btree.c"
+  if( (pCsr->curFlags & 0x01)==0 ){
+    return 8;
+  }
+  assert( (pCsr->pBt->btsFlags & 0x0001)==0
+              && pCsr->pBt->inTransaction==2 );
+  assert( hasSharedCacheTableLock(pCsr->pBtree, pCsr->pgnoRoot, 0, 2) );
+  assert( !hasReadConflicts(pCsr->pBtree, pCsr->pgnoRoot) );
+  assert( pCsr->pPage->intKey );
+
+  return accessPayload(pCsr, offset, amt, (unsigned char *)z, 1);
+}
+
+
+
+
+void sqlite3BtreeIncrblobCursor(BtCursor *pCur){
+  pCur->curFlags |= 0x10;
+  pCur->pBtree->hasIncrblobCur = 1;
+}
+
+
+
+
+
+
+
+int sqlite3BtreeSetVersion(Btree *pBtree, int iVersion){
+  BtShared *pBt = pBtree->pBt;
+  int rc;
+
+  assert( iVersion==1 || iVersion==2 );
+
+
+
+
+  pBt->btsFlags &= ~0x0020;
+  if( iVersion==1 ) pBt->btsFlags |= 0x0020;
+
+  rc = sqlite3BtreeBeginTrans(pBtree, 0, 0);
+  if( rc==0 ){
+    u8 *aData = pBt->pPage1->aData;
+    if( aData[18]!=(u8)iVersion || aData[19]!=(u8)iVersion ){
+      rc = sqlite3BtreeBeginTrans(pBtree, 2, 0);
+      if( rc==0 ){
+        rc = sqlite3PagerWrite(pBt->pPage1->pDbPage);
+        if( rc==0 ){
+          aData[18] = (u8)iVersion;
+          aData[19] = (u8)iVersion;
+        }
+      }
+    }
+  }
+
+  pBt->btsFlags &= ~0x0020;
+  return rc;
+}
+
+
+
+
+
+int sqlite3BtreeCursorHasHint(BtCursor *pCsr, unsigned int mask){
+  return (pCsr->hints & mask)!=0;
+}
+
+
+
+
+int sqlite3BtreeIsReadonly(Btree *p){
+  return (p->pBt->btsFlags & 0x0001)!=0;
+}
+
+
+
+
+int sqlite3HeaderSizeBtree(void){ return (((sizeof(MemPage))+7)&~7); }
+
+
+
+
+
+int sqlite3BtreeSharable(Btree *p){
+  return p->sharable;
+}
+
+
+
+
+
+
+int sqlite3BtreeConnectionCount(Btree *p){
+  ;
+  return p->pBt->nRef;
+}
diff --git a/utils/benchmark/inputs/tccgen.c.ppout b/utils/benchmark/inputs/tccgen.c.ppout
new file mode 100644
index 0000000..b007f19
--- /dev/null
+++ b/utils/benchmark/inputs/tccgen.c.ppout
@@ -0,0 +1,9993 @@
+# 1 "tccgen.c"
+# 1 "<built-in>"
+# 1 "<command-line>"
+# 1 "tccgen.c"
+# 21 "tccgen.c"
+# 1 "tcc.h" 1
+# 25 "tcc.h"
+# 1 "config.h" 1
+# 26 "tcc.h" 2
+
+# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/stdlib.h" 1
+# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/_fake_defines.h" 1
+# 2 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/stdlib.h" 2
+# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/_fake_typedefs.h" 1
+
+
+
+typedef int size_t;
+typedef int __builtin_va_list;
+typedef int __gnuc_va_list;
+typedef int va_list;
+typedef int __int8_t;
+typedef int __uint8_t;
+typedef int __int16_t;
+typedef int __uint16_t;
+typedef int __int_least16_t;
+typedef int __uint_least16_t;
+typedef int __int32_t;
+typedef int __uint32_t;
+typedef int __int64_t;
+typedef int __uint64_t;
+typedef int __int_least32_t;
+typedef int __uint_least32_t;
+typedef int __s8;
+typedef int __u8;
+typedef int __s16;
+typedef int __u16;
+typedef int __s32;
+typedef int __u32;
+typedef int __s64;
+typedef int __u64;
+typedef int _LOCK_T;
+typedef int _LOCK_RECURSIVE_T;
+typedef int _off_t;
+typedef int __dev_t;
+typedef int __uid_t;
+typedef int __gid_t;
+typedef int _off64_t;
+typedef int _fpos_t;
+typedef int _ssize_t;
+typedef int wint_t;
+typedef int _mbstate_t;
+typedef int _flock_t;
+typedef int _iconv_t;
+typedef int __ULong;
+typedef int __FILE;
+typedef int ptrdiff_t;
+typedef int wchar_t;
+typedef int __off_t;
+typedef int __pid_t;
+typedef int __loff_t;
+typedef int u_char;
+typedef int u_short;
+typedef int u_int;
+typedef int u_long;
+typedef int ushort;
+typedef int uint;
+typedef int clock_t;
+typedef int time_t;
+typedef int daddr_t;
+typedef int caddr_t;
+typedef int ino_t;
+typedef int off_t;
+typedef int dev_t;
+typedef int uid_t;
+typedef int gid_t;
+typedef int pid_t;
+typedef int key_t;
+typedef int ssize_t;
+typedef int mode_t;
+typedef int nlink_t;
+typedef int fd_mask;
+typedef int _types_fd_set;
+typedef int clockid_t;
+typedef int timer_t;
+typedef int useconds_t;
+typedef int suseconds_t;
+typedef int FILE;
+typedef int fpos_t;
+typedef int cookie_read_function_t;
+typedef int cookie_write_function_t;
+typedef int cookie_seek_function_t;
+typedef int cookie_close_function_t;
+typedef int cookie_io_functions_t;
+typedef int div_t;
+typedef int ldiv_t;
+typedef int lldiv_t;
+typedef int sigset_t;
+typedef int __sigset_t;
+typedef int _sig_func_ptr;
+typedef int sig_atomic_t;
+typedef int __tzrule_type;
+typedef int __tzinfo_type;
+typedef int mbstate_t;
+typedef int sem_t;
+typedef int pthread_t;
+typedef int pthread_attr_t;
+typedef int pthread_mutex_t;
+typedef int pthread_mutexattr_t;
+typedef int pthread_cond_t;
+typedef int pthread_condattr_t;
+typedef int pthread_key_t;
+typedef int pthread_once_t;
+typedef int pthread_rwlock_t;
+typedef int pthread_rwlockattr_t;
+typedef int pthread_spinlock_t;
+typedef int pthread_barrier_t;
+typedef int pthread_barrierattr_t;
+typedef int jmp_buf;
+typedef int rlim_t;
+typedef int sa_family_t;
+typedef int sigjmp_buf;
+typedef int stack_t;
+typedef int siginfo_t;
+typedef int z_stream;
+
+
+typedef int int8_t;
+typedef int uint8_t;
+typedef int int16_t;
+typedef int uint16_t;
+typedef int int32_t;
+typedef int uint32_t;
+typedef int int64_t;
+typedef int uint64_t;
+
+
+typedef int int_least8_t;
+typedef int uint_least8_t;
+typedef int int_least16_t;
+typedef int uint_least16_t;
+typedef int int_least32_t;
+typedef int uint_least32_t;
+typedef int int_least64_t;
+typedef int uint_least64_t;
+
+
+typedef int int_fast8_t;
+typedef int uint_fast8_t;
+typedef int int_fast16_t;
+typedef int uint_fast16_t;
+typedef int int_fast32_t;
+typedef int uint_fast32_t;
+typedef int int_fast64_t;
+typedef int uint_fast64_t;
+
+
+typedef int intptr_t;
+typedef int uintptr_t;
+
+
+typedef int intmax_t;
+typedef int uintmax_t;
+
+
+typedef _Bool bool;
+
+
+typedef void* MirEGLNativeWindowType;
+typedef void* MirEGLNativeDisplayType;
+typedef struct MirConnection MirConnection;
+typedef struct MirSurface MirSurface;
+typedef struct MirSurfaceSpec MirSurfaceSpec;
+typedef struct MirScreencast MirScreencast;
+typedef struct MirPromptSession MirPromptSession;
+typedef struct MirBufferStream MirBufferStream;
+typedef struct MirPersistentId MirPersistentId;
+typedef struct MirBlob MirBlob;
+typedef struct MirDisplayConfig MirDisplayConfig;
+
+
+typedef struct xcb_connection_t xcb_connection_t;
+typedef uint32_t xcb_window_t;
+typedef uint32_t xcb_visualid_t;
+# 2 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/stdlib.h" 2
+# 28 "tcc.h" 2
+# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/stdio.h" 1
+# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/_fake_defines.h" 1
+# 2 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/stdio.h" 2
+# 29 "tcc.h" 2
+# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/stdarg.h" 1
+# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/_fake_defines.h" 1
+# 2 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/stdarg.h" 2
+# 30 "tcc.h" 2
+# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/string.h" 1
+# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/_fake_defines.h" 1
+# 2 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/string.h" 2
+# 31 "tcc.h" 2
+# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/errno.h" 1
+# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/_fake_defines.h" 1
+# 2 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/errno.h" 2
+# 32 "tcc.h" 2
+# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/math.h" 1
+# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/_fake_defines.h" 1
+# 2 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/math.h" 2
+# 33 "tcc.h" 2
+# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/fcntl.h" 1
+# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/_fake_defines.h" 1
+# 2 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/fcntl.h" 2
+# 34 "tcc.h" 2
+# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/setjmp.h" 1
+# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/_fake_defines.h" 1
+# 2 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/setjmp.h" 2
+# 35 "tcc.h" 2
+# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/time.h" 1
+# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/_fake_defines.h" 1
+# 2 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/time.h" 2
+# 36 "tcc.h" 2
+
+
+# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/unistd.h" 1
+# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/_fake_defines.h" 1
+# 2 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/unistd.h" 2
+# 39 "tcc.h" 2
+# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/sys/time.h" 1
+# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/_fake_defines.h" 1
+# 2 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/sys/time.h" 2
+# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/_fake_typedefs.h" 1
+# 2 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/sys/time.h" 2
+# 40 "tcc.h" 2
+
+# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/dlfcn.h" 1
+# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/_fake_defines.h" 1
+# 2 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/dlfcn.h" 2
+# 42 "tcc.h" 2
+
+
+extern float strtof (const char *__nptr, char **__endptr);
+extern long double strtold (const char *__nptr, char **__endptr);
+# 283 "tcc.h"
+# 1 "libtcc.h" 1
+# 12 "libtcc.h"
+struct TCCState;
+
+typedef struct TCCState TCCState;
+
+
+ TCCState *tcc_new(void);
+
+
+ void tcc_delete(TCCState *s);
+
+
+ void tcc_set_lib_path(TCCState *s, const char *path);
+
+
+ void tcc_set_error_func(TCCState *s, void *error_opaque,
+    void (*error_func)(void *opaque, const char *msg));
+
+
+ void tcc_set_options(TCCState *s, const char *str);
+
+
+
+
+
+ int tcc_add_include_path(TCCState *s, const char *pathname);
+
+
+ int tcc_add_sysinclude_path(TCCState *s, const char *pathname);
+
+
+ void tcc_define_symbol(TCCState *s, const char *sym, const char *value);
+
+
+ void tcc_undefine_symbol(TCCState *s, const char *sym);
+
+
+
+
+
+ int tcc_add_file(TCCState *s, const char *filename);
+
+
+ int tcc_compile_string(TCCState *s, const char *buf);
+
+
+
+
+
+ int tcc_set_output_type(TCCState *s, int output_type);
+
+
+
+
+
+
+
+ int tcc_add_library_path(TCCState *s, const char *pathname);
+
+
+ int tcc_add_library(TCCState *s, const char *libraryname);
+
+
+ int tcc_add_symbol(TCCState *s, const char *name, const void *val);
+
+
+
+ int tcc_output_file(TCCState *s, const char *filename);
+
+
+
+ int tcc_run(TCCState *s, int argc, char **argv);
+
+
+ int tcc_relocate(TCCState *s1, void *ptr);
+# 94 "libtcc.h"
+ void *tcc_get_symbol(TCCState *s, const char *name);
+# 284 "tcc.h" 2
+# 1 "elf.h" 1
+# 23 "elf.h"
+# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/inttypes.h" 1
+# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/_fake_defines.h" 1
+# 2 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/inttypes.h" 2
+# 24 "elf.h" 2
+# 41 "elf.h"
+typedef uint16_t Elf32_Half;
+typedef uint16_t Elf64_Half;
+
+
+typedef uint32_t Elf32_Word;
+typedef int32_t Elf32_Sword;
+typedef uint32_t Elf64_Word;
+typedef int32_t Elf64_Sword;
+
+
+typedef uint64_t Elf32_Xword;
+typedef int64_t Elf32_Sxword;
+typedef uint64_t Elf64_Xword;
+typedef int64_t Elf64_Sxword;
+
+
+typedef uint32_t Elf32_Addr;
+typedef uint64_t Elf64_Addr;
+
+
+typedef uint32_t Elf32_Off;
+typedef uint64_t Elf64_Off;
+
+
+typedef uint16_t Elf32_Section;
+typedef uint16_t Elf64_Section;
+
+
+typedef Elf32_Half Elf32_Versym;
+typedef Elf64_Half Elf64_Versym;
+
+
+
+
+
+
+typedef struct
+{
+  unsigned char e_ident[(16)];
+  Elf32_Half e_type;
+  Elf32_Half e_machine;
+  Elf32_Word e_version;
+  Elf32_Addr e_entry;
+  Elf32_Off e_phoff;
+  Elf32_Off e_shoff;
+  Elf32_Word e_flags;
+  Elf32_Half e_ehsize;
+  Elf32_Half e_phentsize;
+  Elf32_Half e_phnum;
+  Elf32_Half e_shentsize;
+  Elf32_Half e_shnum;
+  Elf32_Half e_shstrndx;
+} Elf32_Ehdr;
+
+typedef struct
+{
+  unsigned char e_ident[(16)];
+  Elf64_Half e_type;
+  Elf64_Half e_machine;
+  Elf64_Word e_version;
+  Elf64_Addr e_entry;
+  Elf64_Off e_phoff;
+  Elf64_Off e_shoff;
+  Elf64_Word e_flags;
+  Elf64_Half e_ehsize;
+  Elf64_Half e_phentsize;
+  Elf64_Half e_phnum;
+  Elf64_Half e_shentsize;
+  Elf64_Half e_shnum;
+  Elf64_Half e_shstrndx;
+} Elf64_Ehdr;
+# 282 "elf.h"
+typedef struct
+{
+  Elf32_Word sh_name;
+  Elf32_Word sh_type;
+  Elf32_Word sh_flags;
+  Elf32_Addr sh_addr;
+  Elf32_Off sh_offset;
+  Elf32_Word sh_size;
+  Elf32_Word sh_link;
+  Elf32_Word sh_info;
+  Elf32_Word sh_addralign;
+  Elf32_Word sh_entsize;
+} Elf32_Shdr;
+
+typedef struct
+{
+  Elf64_Word sh_name;
+  Elf64_Word sh_type;
+  Elf64_Xword sh_flags;
+  Elf64_Addr sh_addr;
+  Elf64_Off sh_offset;
+  Elf64_Xword sh_size;
+  Elf64_Word sh_link;
+  Elf64_Word sh_info;
+  Elf64_Xword sh_addralign;
+  Elf64_Xword sh_entsize;
+} Elf64_Shdr;
+# 392 "elf.h"
+typedef struct
+{
+  Elf32_Word st_name;
+  Elf32_Addr st_value;
+  Elf32_Word st_size;
+  unsigned char st_info;
+  unsigned char st_other;
+  Elf32_Section st_shndx;
+} Elf32_Sym;
+
+typedef struct
+{
+  Elf64_Word st_name;
+  unsigned char st_info;
+  unsigned char st_other;
+  Elf64_Section st_shndx;
+  Elf64_Addr st_value;
+  Elf64_Xword st_size;
+} Elf64_Sym;
+
+
+
+
+typedef struct
+{
+  Elf32_Half si_boundto;
+  Elf32_Half si_flags;
+} Elf32_Syminfo;
+
+typedef struct
+{
+  Elf64_Half si_boundto;
+  Elf64_Half si_flags;
+} Elf64_Syminfo;
+# 507 "elf.h"
+typedef struct
+{
+  Elf32_Addr r_offset;
+  Elf32_Word r_info;
+} Elf32_Rel;
+
+
+
+
+
+
+typedef struct
+{
+  Elf64_Addr r_offset;
+  Elf64_Xword r_info;
+} Elf64_Rel;
+
+
+
+typedef struct
+{
+  Elf32_Addr r_offset;
+  Elf32_Word r_info;
+  Elf32_Sword r_addend;
+} Elf32_Rela;
+
+typedef struct
+{
+  Elf64_Addr r_offset;
+  Elf64_Xword r_info;
+  Elf64_Sxword r_addend;
+} Elf64_Rela;
+# 552 "elf.h"
+typedef struct
+{
+  Elf32_Word p_type;
+  Elf32_Off p_offset;
+  Elf32_Addr p_vaddr;
+  Elf32_Addr p_paddr;
+  Elf32_Word p_filesz;
+  Elf32_Word p_memsz;
+  Elf32_Word p_flags;
+  Elf32_Word p_align;
+} Elf32_Phdr;
+
+typedef struct
+{
+  Elf64_Word p_type;
+  Elf64_Word p_flags;
+  Elf64_Off p_offset;
+  Elf64_Addr p_vaddr;
+  Elf64_Addr p_paddr;
+  Elf64_Xword p_filesz;
+  Elf64_Xword p_memsz;
+  Elf64_Xword p_align;
+} Elf64_Phdr;
+# 658 "elf.h"
+typedef struct
+{
+  Elf32_Sword d_tag;
+  union
+    {
+      Elf32_Word d_val;
+      Elf32_Addr d_ptr;
+    } d_un;
+} Elf32_Dyn;
+
+typedef struct
+{
+  Elf64_Sxword d_tag;
+  union
+    {
+      Elf64_Xword d_val;
+      Elf64_Addr d_ptr;
+    } d_un;
+} Elf64_Dyn;
+# 834 "elf.h"
+typedef struct
+{
+  Elf32_Half vd_version;
+  Elf32_Half vd_flags;
+  Elf32_Half vd_ndx;
+  Elf32_Half vd_cnt;
+  Elf32_Word vd_hash;
+  Elf32_Word vd_aux;
+  Elf32_Word vd_next;
+
+} Elf32_Verdef;
+
+typedef struct
+{
+  Elf64_Half vd_version;
+  Elf64_Half vd_flags;
+  Elf64_Half vd_ndx;
+  Elf64_Half vd_cnt;
+  Elf64_Word vd_hash;
+  Elf64_Word vd_aux;
+  Elf64_Word vd_next;
+
+} Elf64_Verdef;
+# 876 "elf.h"
+typedef struct
+{
+  Elf32_Word vda_name;
+  Elf32_Word vda_next;
+
+} Elf32_Verdaux;
+
+typedef struct
+{
+  Elf64_Word vda_name;
+  Elf64_Word vda_next;
+
+} Elf64_Verdaux;
+
+
+
+
+typedef struct
+{
+  Elf32_Half vn_version;
+  Elf32_Half vn_cnt;
+  Elf32_Word vn_file;
+
+  Elf32_Word vn_aux;
+  Elf32_Word vn_next;
+
+} Elf32_Verneed;
+
+typedef struct
+{
+  Elf64_Half vn_version;
+  Elf64_Half vn_cnt;
+  Elf64_Word vn_file;
+
+  Elf64_Word vn_aux;
+  Elf64_Word vn_next;
+
+} Elf64_Verneed;
+# 923 "elf.h"
+typedef struct
+{
+  Elf32_Word vna_hash;
+  Elf32_Half vna_flags;
+  Elf32_Half vna_other;
+  Elf32_Word vna_name;
+  Elf32_Word vna_next;
+
+} Elf32_Vernaux;
+
+typedef struct
+{
+  Elf64_Word vna_hash;
+  Elf64_Half vna_flags;
+  Elf64_Half vna_other;
+  Elf64_Word vna_name;
+  Elf64_Word vna_next;
+
+} Elf64_Vernaux;
+# 957 "elf.h"
+typedef struct
+{
+  uint32_t a_type;
+  union
+    {
+      uint32_t a_val;
+
+
+
+    } a_un;
+} Elf32_auxv_t;
+
+typedef struct
+{
+  uint64_t a_type;
+  union
+    {
+      uint64_t a_val;
+
+
+
+    } a_un;
+} Elf64_auxv_t;
+# 1041 "elf.h"
+typedef struct
+{
+  Elf32_Word n_namesz;
+  Elf32_Word n_descsz;
+  Elf32_Word n_type;
+} Elf32_Nhdr;
+
+typedef struct
+{
+  Elf64_Word n_namesz;
+  Elf64_Word n_descsz;
+  Elf64_Word n_type;
+} Elf64_Nhdr;
+# 1105 "elf.h"
+typedef struct
+{
+  Elf32_Xword m_value;
+  Elf32_Word m_info;
+  Elf32_Word m_poffset;
+  Elf32_Half m_repeat;
+  Elf32_Half m_stride;
+} Elf32_Move;
+
+typedef struct
+{
+  Elf64_Xword m_value;
+  Elf64_Xword m_info;
+  Elf64_Xword m_poffset;
+  Elf64_Half m_repeat;
+  Elf64_Half m_stride;
+} Elf64_Move;
+# 1489 "elf.h"
+typedef union
+{
+  struct
+    {
+      Elf32_Word gt_current_g_value;
+      Elf32_Word gt_unused;
+    } gt_header;
+  struct
+    {
+      Elf32_Word gt_g_value;
+      Elf32_Word gt_bytes;
+    } gt_entry;
+} Elf32_gptab;
+
+
+
+typedef struct
+{
+  Elf32_Word ri_gprmask;
+  Elf32_Word ri_cprmask[4];
+  Elf32_Sword ri_gp_value;
+} Elf32_RegInfo;
+
+
+
+typedef struct
+{
+  unsigned char kind;
+
+  unsigned char size;
+  Elf32_Section section;
+
+  Elf32_Word info;
+} Elf_Options;
+# 1565 "elf.h"
+typedef struct
+{
+  Elf32_Word hwp_flags1;
+  Elf32_Word hwp_flags2;
+} Elf_Options_Hw;
+# 1726 "elf.h"
+typedef struct
+{
+  Elf32_Word l_name;
+  Elf32_Word l_time_stamp;
+  Elf32_Word l_checksum;
+  Elf32_Word l_version;
+  Elf32_Word l_flags;
+} Elf32_Lib;
+
+typedef struct
+{
+  Elf64_Word l_name;
+  Elf64_Word l_time_stamp;
+  Elf64_Word l_checksum;
+  Elf64_Word l_version;
+  Elf64_Word l_flags;
+} Elf64_Lib;
+# 1757 "elf.h"
+typedef Elf32_Addr Elf32_Conflict;
+# 285 "tcc.h" 2
+# 1 "stab.h" 1
+# 9 "stab.h"
+enum __stab_debug_code
+{
+# 1 "stab.def" 1
+# 24 "stab.def"
+N_GSYM=0x20,
+
+
+
+N_FNAME=0x22,
+
+
+
+
+N_FUN=0x24,
+
+
+
+N_STSYM=0x26,
+
+
+N_LCSYM=0x28,
+
+
+
+N_MAIN=0x2a,
+
+
+
+N_PC=0x30,
+
+
+N_NSYMS=0x32,
+
+
+N_NOMAP=0x34,
+
+
+
+N_OBJ=0x38,
+
+
+
+
+N_OPT=0x3c,
+
+
+N_RSYM=0x40,
+
+
+N_M2C=0x42,
+
+
+
+N_SLINE=0x44,
+
+
+N_DSLINE=0x46,
+
+
+N_BSLINE=0x48,
+
+
+
+
+N_BROWS=0x48,
+
+
+
+
+
+N_DEFD=0x4a,
+
+
+
+
+N_EHDECL=0x50,
+
+N_MOD2=0x50,
+
+
+
+
+
+
+N_CATCH=0x54,
+
+
+N_SSYM=0x60,
+
+
+
+N_SO=0x64,
+
+
+
+N_LSYM=0x80,
+
+
+
+
+N_BINCL=0x82,
+
+
+
+N_SOL=0x84,
+
+
+
+N_PSYM=0xa0,
+
+
+
+
+
+N_EINCL=0xa2,
+
+
+N_ENTRY=0xa4,
+
+
+
+
+
+N_LBRAC=0xc0,
+
+
+
+
+
+N_EXCL=0xc2,
+
+
+N_SCOPE=0xc4,
+
+
+
+N_RBRAC=0xe0,
+
+
+N_BCOMM=0xe2,
+
+
+
+N_ECOMM=0xe4,
+
+
+
+N_ECOML=0xe8,
+
+
+
+
+N_NBTEXT=0xF0,
+N_NBDATA=0xF2,
+N_NBBSS=0xF4,
+N_NBSTS=0xF6,
+N_NBLCS=0xF8,
+
+
+
+N_LENG=0xfe,
+# 12 "stab.h" 2
+LAST_UNUSED_STAB_CODE
+};
+# 286 "tcc.h" 2
+# 320 "tcc.h"
+# 1 "x86_64-gen.c" 1
+# 57 "x86_64-gen.c"
+enum {
+    TREG_RAX = 0,
+    TREG_RCX = 1,
+    TREG_RDX = 2,
+    TREG_RSP = 4,
+    TREG_RSI = 6,
+    TREG_RDI = 7,
+
+    TREG_R8 = 8,
+    TREG_R9 = 9,
+    TREG_R10 = 10,
+    TREG_R11 = 11,
+
+    TREG_XMM0 = 16,
+    TREG_XMM1 = 17,
+    TREG_XMM2 = 18,
+    TREG_XMM3 = 19,
+    TREG_XMM4 = 20,
+    TREG_XMM5 = 21,
+    TREG_XMM6 = 22,
+    TREG_XMM7 = 23,
+
+    TREG_ST0 = 24,
+
+    TREG_MEM = 0x20
+};
+# 321 "tcc.h" 2
+# 1 "x86_64-link.c" 1
+# 322 "tcc.h" 2
+# 381 "tcc.h"
+typedef struct TokenSym {
+    struct TokenSym *hash_next;
+    struct Sym *sym_define;
+    struct Sym *sym_label;
+    struct Sym *sym_struct;
+    struct Sym *sym_identifier;
+    int tok;
+    int len;
+    char str[1];
+} TokenSym;
+
+
+
+
+typedef int nwchar_t;
+
+
+typedef struct CString {
+    int size;
+    void *data;
+    int size_allocated;
+} CString;
+
+
+typedef struct CType {
+    int t;
+    struct Sym *ref;
+} CType;
+
+
+typedef union CValue {
+    long double ld;
+    double d;
+    float f;
+    uint64_t i;
+    struct {
+        int size;
+        const void *data;
+    } str;
+    int tab[16/4];
+} CValue;
+
+
+typedef struct SValue {
+    CType type;
+    unsigned short r;
+    unsigned short r2;
+
+    CValue c;
+    struct Sym *sym;
+
+} SValue;
+
+
+struct SymAttr {
+    unsigned short
+    aligned : 5,
+    packed : 1,
+    weak : 1,
+    visibility : 2,
+    dllexport : 1,
+    dllimport : 1,
+    unused : 5;
+};
+
+
+struct FuncAttr {
+    unsigned
+    func_call : 3,
+    func_type : 2,
+    func_args : 8;
+};
+
+
+typedef struct AttributeDef {
+    struct SymAttr a;
+    struct FuncAttr f;
+    struct Section *section;
+    int alias_target;
+    int asm_label;
+    char attr_mode;
+} AttributeDef;
+
+
+typedef struct Sym {
+    int v;
+    unsigned short r;
+    struct SymAttr a;
+    union {
+        struct {
+            int c;
+            union {
+                int sym_scope;
+                int jnext;
+                struct FuncAttr f;
+                int auxtype;
+            };
+        };
+        long long enum_val;
+        int *d;
+    };
+    CType type;
+    union {
+        struct Sym *next;
+        int asm_label;
+    };
+    struct Sym *prev;
+    struct Sym *prev_tok;
+} Sym;
+
+
+typedef struct Section {
+    unsigned long data_offset;
+    unsigned char *data;
+    unsigned long data_allocated;
+    int sh_name;
+    int sh_num;
+    int sh_type;
+    int sh_flags;
+    int sh_info;
+    int sh_addralign;
+    int sh_entsize;
+    unsigned long sh_size;
+    Elf64_Addr sh_addr;
+    unsigned long sh_offset;
+    int nb_hashed_syms;
+    struct Section *link;
+    struct Section *reloc;
+    struct Section *hash;
+    struct Section *prev;
+    char name[1];
+} Section;
+
+typedef struct DLLReference {
+    int level;
+    void *handle;
+    char name[1];
+} DLLReference;
+# 554 "tcc.h"
+typedef struct BufferedFile {
+    uint8_t *buf_ptr;
+    uint8_t *buf_end;
+    int fd;
+    struct BufferedFile *prev;
+    int line_num;
+    int line_ref;
+    int ifndef_macro;
+    int ifndef_macro_saved;
+    int *ifdef_stack_ptr;
+    int include_next_index;
+    char filename[1024];
+    char *true_filename;
+    unsigned char unget[4];
+    unsigned char buffer[1];
+} BufferedFile;
+
+
+
+
+
+typedef struct TokenString {
+    int *str;
+    int len;
+    int lastlen;
+    int allocated_len;
+    int last_line_num;
+    int save_line_num;
+
+    struct TokenString *prev;
+    const int *prev_ptr;
+    char alloc;
+} TokenString;
+
+
+typedef struct InlineFunc {
+    TokenString *func_str;
+    Sym *sym;
+    char filename[1];
+} InlineFunc;
+
+
+
+typedef struct CachedInclude {
+    int ifndef_macro;
+    int once;
+    int hash_next;
+    char filename[1];
+} CachedInclude;
+
+
+
+
+typedef struct ExprValue {
+    uint64_t v;
+    Sym *sym;
+    int pcrel;
+} ExprValue;
+
+
+typedef struct ASMOperand {
+    int id;
+    char *constraint;
+    char asm_str[16];
+    SValue *vt;
+    int ref_index;
+    int input_index;
+    int priority;
+    int reg;
+    int is_llong;
+    int is_memory;
+    int is_rw;
+} ASMOperand;
+
+
+
+struct sym_attr {
+    unsigned got_offset;
+    unsigned plt_offset;
+    int plt_sym;
+    int dyn_index;
+
+
+
+};
+
+struct TCCState {
+
+    int verbose;
+    int nostdinc;
+    int nostdlib;
+    int nocommon;
+    int static_link;
+    int rdynamic;
+    int symbolic;
+    int alacarte_link;
+
+    char *tcc_lib_path;
+    char *soname;
+    char *rpath;
+    int enable_new_dtags;
+
+
+    int output_type;
+
+    int output_format;
+
+
+    int char_is_unsigned;
+    int leading_underscore;
+    int ms_extensions;
+    int dollars_in_identifiers;
+    int ms_bitfields;
+
+
+    int warn_write_strings;
+    int warn_unsupported;
+    int warn_error;
+    int warn_none;
+    int warn_implicit_function_declaration;
+    int warn_gcc_compat;
+
+
+    int do_debug;
+
+
+    int do_bounds_check;
+
+
+
+
+    int run_test;
+
+    Elf64_Addr text_addr;
+    int has_text_addr;
+
+    unsigned section_align;
+
+    char *init_symbol;
+    char *fini_symbol;
+
+
+
+
+
+    int nosse;
+
+
+
+    DLLReference **loaded_dlls;
+    int nb_loaded_dlls;
+
+
+    char **include_paths;
+    int nb_include_paths;
+
+    char **sysinclude_paths;
+    int nb_sysinclude_paths;
+
+
+    char **library_paths;
+    int nb_library_paths;
+
+
+    char **crt_paths;
+    int nb_crt_paths;
+
+
+    char **cmd_include_files;
+    int nb_cmd_include_files;
+
+
+    void *error_opaque;
+    void (*error_func)(void *opaque, const char *msg);
+    int error_set_jmp_enabled;
+    jmp_buf error_jmp_buf;
+    int nb_errors;
+
+
+    FILE *ppfp;
+    enum {
+ LINE_MACRO_OUTPUT_FORMAT_GCC,
+ LINE_MACRO_OUTPUT_FORMAT_NONE,
+ LINE_MACRO_OUTPUT_FORMAT_STD,
+    LINE_MACRO_OUTPUT_FORMAT_P10 = 11
+    } Pflag;
+    char dflag;
+
+
+    char **target_deps;
+    int nb_target_deps;
+
+
+    BufferedFile *include_stack[32];
+    BufferedFile **include_stack_ptr;
+
+    int ifdef_stack[64];
+    int *ifdef_stack_ptr;
+
+
+    int cached_includes_hash[32];
+    CachedInclude **cached_includes;
+    int nb_cached_includes;
+
+
+    int pack_stack[8];
+    int *pack_stack_ptr;
+    char **pragma_libs;
+    int nb_pragma_libs;
+
+
+
+    struct InlineFunc **inline_fns;
+    int nb_inline_fns;
+
+
+    Section **sections;
+    int nb_sections;
+
+    Section **priv_sections;
+    int nb_priv_sections;
+
+
+    Section *got;
+    Section *plt;
+
+
+    Section *dynsymtab_section;
+
+    Section *dynsym;
+
+    Section *symtab;
+
+    struct sym_attr *sym_attrs;
+    int nb_sym_attrs;
+# 805 "tcc.h"
+    const char *runtime_main;
+    void **runtime_mem;
+    int nb_runtime_mem;
+
+
+
+    struct filespec **files;
+    int nb_files;
+    int nb_libraries;
+    int filetype;
+    char *outfile;
+    int option_r;
+    int do_bench;
+    int gen_deps;
+    char *deps_outfile;
+    int option_pthread;
+    int argc;
+    char **argv;
+};
+
+struct filespec {
+    char type;
+    char alacarte;
+    char name[1];
+};
+# 1070 "tcc.h"
+enum tcc_token {
+    TOK_LAST = 256 - 1
+
+# 1 "tcctok.h" 1
+
+     ,TOK_INT
+     ,TOK_VOID
+     ,TOK_CHAR
+     ,TOK_IF
+     ,TOK_ELSE
+     ,TOK_WHILE
+     ,TOK_BREAK
+     ,TOK_RETURN
+     ,TOK_FOR
+     ,TOK_EXTERN
+     ,TOK_STATIC
+     ,TOK_UNSIGNED
+     ,TOK_GOTO
+     ,TOK_DO
+     ,TOK_CONTINUE
+     ,TOK_SWITCH
+     ,TOK_CASE
+
+     ,TOK_CONST1
+     ,TOK_CONST2
+     ,TOK_CONST3
+     ,TOK_VOLATILE1
+     ,TOK_VOLATILE2
+     ,TOK_VOLATILE3
+     ,TOK_LONG
+     ,TOK_REGISTER
+     ,TOK_SIGNED1
+     ,TOK_SIGNED2
+     ,TOK_SIGNED3
+     ,TOK_AUTO
+     ,TOK_INLINE1
+     ,TOK_INLINE2
+     ,TOK_INLINE3
+     ,TOK_RESTRICT1
+     ,TOK_RESTRICT2
+     ,TOK_RESTRICT3
+     ,TOK_EXTENSION
+
+     ,TOK_GENERIC
+
+     ,TOK_FLOAT
+     ,TOK_DOUBLE
+     ,TOK_BOOL
+     ,TOK_SHORT
+     ,TOK_STRUCT
+     ,TOK_UNION
+     ,TOK_TYPEDEF
+     ,TOK_DEFAULT
+     ,TOK_ENUM
+     ,TOK_SIZEOF
+     ,TOK_ATTRIBUTE1
+     ,TOK_ATTRIBUTE2
+     ,TOK_ALIGNOF1
+     ,TOK_ALIGNOF2
+     ,TOK_TYPEOF1
+     ,TOK_TYPEOF2
+     ,TOK_TYPEOF3
+     ,TOK_LABEL
+     ,TOK_ASM1
+     ,TOK_ASM2
+     ,TOK_ASM3
+# 71 "tcctok.h"
+     ,TOK_DEFINE
+     ,TOK_INCLUDE
+     ,TOK_INCLUDE_NEXT
+     ,TOK_IFDEF
+     ,TOK_IFNDEF
+     ,TOK_ELIF
+     ,TOK_ENDIF
+     ,TOK_DEFINED
+     ,TOK_UNDEF
+     ,TOK_ERROR
+     ,TOK_WARNING
+     ,TOK_LINE
+     ,TOK_PRAGMA
+     ,TOK___LINE__
+     ,TOK___FILE__
+     ,TOK___DATE__
+     ,TOK___TIME__
+     ,TOK___FUNCTION__
+     ,TOK___VA_ARGS__
+     ,TOK___COUNTER__
+
+
+     ,TOK___FUNC__
+
+
+     ,TOK___NAN__
+     ,TOK___SNAN__
+     ,TOK___INF__
+
+
+
+     ,TOK_SECTION1
+     ,TOK_SECTION2
+     ,TOK_ALIGNED1
+     ,TOK_ALIGNED2
+     ,TOK_PACKED1
+     ,TOK_PACKED2
+     ,TOK_WEAK1
+     ,TOK_WEAK2
+     ,TOK_ALIAS1
+     ,TOK_ALIAS2
+     ,TOK_UNUSED1
+     ,TOK_UNUSED2
+     ,TOK_CDECL1
+     ,TOK_CDECL2
+     ,TOK_CDECL3
+     ,TOK_STDCALL1
+     ,TOK_STDCALL2
+     ,TOK_STDCALL3
+     ,TOK_FASTCALL1
+     ,TOK_FASTCALL2
+     ,TOK_FASTCALL3
+     ,TOK_REGPARM1
+     ,TOK_REGPARM2
+
+     ,TOK_MODE
+     ,TOK_MODE_QI
+     ,TOK_MODE_DI
+     ,TOK_MODE_HI
+     ,TOK_MODE_SI
+     ,TOK_MODE_word
+
+     ,TOK_DLLEXPORT
+     ,TOK_DLLIMPORT
+     ,TOK_NORETURN1
+     ,TOK_NORETURN2
+     ,TOK_VISIBILITY1
+     ,TOK_VISIBILITY2
+
+     ,TOK_builtin_types_compatible_p
+     ,TOK_builtin_choose_expr
+     ,TOK_builtin_constant_p
+     ,TOK_builtin_frame_address
+     ,TOK_builtin_return_address
+     ,TOK_builtin_expect
+
+
+
+
+     ,TOK_builtin_va_arg_types
+
+
+
+
+
+
+     ,TOK_pack
+
+
+
+
+
+     ,TOK_comment
+     ,TOK_lib
+     ,TOK_push_macro
+     ,TOK_pop_macro
+     ,TOK_once
+     ,TOK_option
+
+
+
+     ,TOK_memcpy
+     ,TOK_memmove
+     ,TOK_memset
+     ,TOK___divdi3
+     ,TOK___moddi3
+     ,TOK___udivdi3
+     ,TOK___umoddi3
+     ,TOK___ashrdi3
+     ,TOK___lshrdi3
+     ,TOK___ashldi3
+     ,TOK___floatundisf
+     ,TOK___floatundidf
+
+     ,TOK___floatundixf
+     ,TOK___fixunsxfdi
+
+     ,TOK___fixunssfdi
+     ,TOK___fixunsdfdi
+# 251 "tcctok.h"
+     ,TOK_alloca
+# 285 "tcctok.h"
+     ,TOK___bound_ptr_add
+     ,TOK___bound_ptr_indir1
+     ,TOK___bound_ptr_indir2
+     ,TOK___bound_ptr_indir4
+     ,TOK___bound_ptr_indir8
+     ,TOK___bound_ptr_indir12
+     ,TOK___bound_ptr_indir16
+     ,TOK___bound_main_arg
+     ,TOK___bound_local_new
+     ,TOK___bound_local_delete
+
+
+
+
+
+
+
+     ,TOK_strlen
+     ,TOK_strcpy
+
+
+
+ ,TOK_ASMDIR_byte
+ ,TOK_ASMDIR_word
+ ,TOK_ASMDIR_align
+ ,TOK_ASMDIR_balign
+ ,TOK_ASMDIR_p2align
+ ,TOK_ASMDIR_set
+ ,TOK_ASMDIR_skip
+ ,TOK_ASMDIR_space
+ ,TOK_ASMDIR_string
+ ,TOK_ASMDIR_asciz
+ ,TOK_ASMDIR_ascii
+ ,TOK_ASMDIR_file
+ ,TOK_ASMDIR_globl
+ ,TOK_ASMDIR_global
+ ,TOK_ASMDIR_weak
+ ,TOK_ASMDIR_hidden
+ ,TOK_ASMDIR_ident
+ ,TOK_ASMDIR_size
+ ,TOK_ASMDIR_type
+ ,TOK_ASMDIR_text
+ ,TOK_ASMDIR_data
+ ,TOK_ASMDIR_bss
+ ,TOK_ASMDIR_previous
+ ,TOK_ASMDIR_pushsection
+ ,TOK_ASMDIR_popsection
+ ,TOK_ASMDIR_fill
+ ,TOK_ASMDIR_rept
+ ,TOK_ASMDIR_endr
+ ,TOK_ASMDIR_org
+ ,TOK_ASMDIR_quad
+
+
+
+
+ ,TOK_ASMDIR_code64
+
+ ,TOK_ASMDIR_short
+ ,TOK_ASMDIR_long
+ ,TOK_ASMDIR_int
+ ,TOK_ASMDIR_section
+
+
+# 1 "i386-tok.h" 1
+
+
+
+
+ ,TOK_ASM_al
+ ,TOK_ASM_cl
+ ,TOK_ASM_dl
+ ,TOK_ASM_bl
+ ,TOK_ASM_ah
+ ,TOK_ASM_ch
+ ,TOK_ASM_dh
+ ,TOK_ASM_bh
+ ,TOK_ASM_ax
+ ,TOK_ASM_cx
+ ,TOK_ASM_dx
+ ,TOK_ASM_bx
+ ,TOK_ASM_sp
+ ,TOK_ASM_bp
+ ,TOK_ASM_si
+ ,TOK_ASM_di
+ ,TOK_ASM_eax
+ ,TOK_ASM_ecx
+ ,TOK_ASM_edx
+ ,TOK_ASM_ebx
+ ,TOK_ASM_esp
+ ,TOK_ASM_ebp
+ ,TOK_ASM_esi
+ ,TOK_ASM_edi
+
+ ,TOK_ASM_rax
+ ,TOK_ASM_rcx
+ ,TOK_ASM_rdx
+ ,TOK_ASM_rbx
+ ,TOK_ASM_rsp
+ ,TOK_ASM_rbp
+ ,TOK_ASM_rsi
+ ,TOK_ASM_rdi
+
+ ,TOK_ASM_mm0
+ ,TOK_ASM_mm1
+ ,TOK_ASM_mm2
+ ,TOK_ASM_mm3
+ ,TOK_ASM_mm4
+ ,TOK_ASM_mm5
+ ,TOK_ASM_mm6
+ ,TOK_ASM_mm7
+ ,TOK_ASM_xmm0
+ ,TOK_ASM_xmm1
+ ,TOK_ASM_xmm2
+ ,TOK_ASM_xmm3
+ ,TOK_ASM_xmm4
+ ,TOK_ASM_xmm5
+ ,TOK_ASM_xmm6
+ ,TOK_ASM_xmm7
+ ,TOK_ASM_cr0
+ ,TOK_ASM_cr1
+ ,TOK_ASM_cr2
+ ,TOK_ASM_cr3
+ ,TOK_ASM_cr4
+ ,TOK_ASM_cr5
+ ,TOK_ASM_cr6
+ ,TOK_ASM_cr7
+ ,TOK_ASM_tr0
+ ,TOK_ASM_tr1
+ ,TOK_ASM_tr2
+ ,TOK_ASM_tr3
+ ,TOK_ASM_tr4
+ ,TOK_ASM_tr5
+ ,TOK_ASM_tr6
+ ,TOK_ASM_tr7
+ ,TOK_ASM_db0
+ ,TOK_ASM_db1
+ ,TOK_ASM_db2
+ ,TOK_ASM_db3
+ ,TOK_ASM_db4
+ ,TOK_ASM_db5
+ ,TOK_ASM_db6
+ ,TOK_ASM_db7
+ ,TOK_ASM_dr0
+ ,TOK_ASM_dr1
+ ,TOK_ASM_dr2
+ ,TOK_ASM_dr3
+ ,TOK_ASM_dr4
+ ,TOK_ASM_dr5
+ ,TOK_ASM_dr6
+ ,TOK_ASM_dr7
+ ,TOK_ASM_es
+ ,TOK_ASM_cs
+ ,TOK_ASM_ss
+ ,TOK_ASM_ds
+ ,TOK_ASM_fs
+ ,TOK_ASM_gs
+ ,TOK_ASM_st
+ ,TOK_ASM_rip
+
+
+
+
+ ,TOK_ASM_spl
+ ,TOK_ASM_bpl
+ ,TOK_ASM_sil
+ ,TOK_ASM_dil
+
+
+ ,TOK_ASM_movb ,TOK_ASM_movw ,TOK_ASM_movl ,TOK_ASM_movq ,TOK_ASM_mov
+
+ ,TOK_ASM_addb ,TOK_ASM_addw ,TOK_ASM_addl ,TOK_ASM_addq ,TOK_ASM_add
+ ,TOK_ASM_orb ,TOK_ASM_orw ,TOK_ASM_orl ,TOK_ASM_orq ,TOK_ASM_or
+ ,TOK_ASM_adcb ,TOK_ASM_adcw ,TOK_ASM_adcl ,TOK_ASM_adcq ,TOK_ASM_adc
+ ,TOK_ASM_sbbb ,TOK_ASM_sbbw ,TOK_ASM_sbbl ,TOK_ASM_sbbq ,TOK_ASM_sbb
+ ,TOK_ASM_andb ,TOK_ASM_andw ,TOK_ASM_andl ,TOK_ASM_andq ,TOK_ASM_and
+ ,TOK_ASM_subb ,TOK_ASM_subw ,TOK_ASM_subl ,TOK_ASM_subq ,TOK_ASM_sub
+ ,TOK_ASM_xorb ,TOK_ASM_xorw ,TOK_ASM_xorl ,TOK_ASM_xorq ,TOK_ASM_xor
+ ,TOK_ASM_cmpb ,TOK_ASM_cmpw ,TOK_ASM_cmpl ,TOK_ASM_cmpq ,TOK_ASM_cmp
+
+
+ ,TOK_ASM_incb ,TOK_ASM_incw ,TOK_ASM_incl ,TOK_ASM_incq ,TOK_ASM_inc
+ ,TOK_ASM_decb ,TOK_ASM_decw ,TOK_ASM_decl ,TOK_ASM_decq ,TOK_ASM_dec
+ ,TOK_ASM_notb ,TOK_ASM_notw ,TOK_ASM_notl ,TOK_ASM_notq ,TOK_ASM_not
+ ,TOK_ASM_negb ,TOK_ASM_negw ,TOK_ASM_negl ,TOK_ASM_negq ,TOK_ASM_neg
+ ,TOK_ASM_mulb ,TOK_ASM_mulw ,TOK_ASM_mull ,TOK_ASM_mulq ,TOK_ASM_mul
+ ,TOK_ASM_imulb ,TOK_ASM_imulw ,TOK_ASM_imull ,TOK_ASM_imulq ,TOK_ASM_imul
+ ,TOK_ASM_divb ,TOK_ASM_divw ,TOK_ASM_divl ,TOK_ASM_divq ,TOK_ASM_div
+ ,TOK_ASM_idivb ,TOK_ASM_idivw ,TOK_ASM_idivl ,TOK_ASM_idivq ,TOK_ASM_idiv
+
+ ,TOK_ASM_xchgb ,TOK_ASM_xchgw ,TOK_ASM_xchgl ,TOK_ASM_xchgq ,TOK_ASM_xchg
+ ,TOK_ASM_testb ,TOK_ASM_testw ,TOK_ASM_testl ,TOK_ASM_testq ,TOK_ASM_test
+
+
+ ,TOK_ASM_rolb ,TOK_ASM_rolw ,TOK_ASM_roll ,TOK_ASM_rolq ,TOK_ASM_rol
+ ,TOK_ASM_rorb ,TOK_ASM_rorw ,TOK_ASM_rorl ,TOK_ASM_rorq ,TOK_ASM_ror
+ ,TOK_ASM_rclb ,TOK_ASM_rclw ,TOK_ASM_rcll ,TOK_ASM_rclq ,TOK_ASM_rcl
+ ,TOK_ASM_rcrb ,TOK_ASM_rcrw ,TOK_ASM_rcrl ,TOK_ASM_rcrq ,TOK_ASM_rcr
+ ,TOK_ASM_shlb ,TOK_ASM_shlw ,TOK_ASM_shll ,TOK_ASM_shlq ,TOK_ASM_shl
+ ,TOK_ASM_shrb ,TOK_ASM_shrw ,TOK_ASM_shrl ,TOK_ASM_shrq ,TOK_ASM_shr
+ ,TOK_ASM_sarb ,TOK_ASM_sarw ,TOK_ASM_sarl ,TOK_ASM_sarq ,TOK_ASM_sar
+
+ ,TOK_ASM_shldw ,TOK_ASM_shldl ,TOK_ASM_shldq ,TOK_ASM_shld
+ ,TOK_ASM_shrdw ,TOK_ASM_shrdl ,TOK_ASM_shrdq ,TOK_ASM_shrd
+
+ ,TOK_ASM_pushw
+ ,TOK_ASM_pushl
+
+ ,TOK_ASM_pushq
+
+ ,TOK_ASM_push
+
+ ,TOK_ASM_popw
+ ,TOK_ASM_popl
+
+ ,TOK_ASM_popq
+
+ ,TOK_ASM_pop
+
+ ,TOK_ASM_inb ,TOK_ASM_inw ,TOK_ASM_inl ,TOK_ASM_in
+ ,TOK_ASM_outb ,TOK_ASM_outw ,TOK_ASM_outl ,TOK_ASM_out
+
+ ,TOK_ASM_movzbw ,TOK_ASM_movzbl ,TOK_ASM_movzbq ,TOK_ASM_movzb
+ ,TOK_ASM_movzwl
+ ,TOK_ASM_movsbw
+ ,TOK_ASM_movsbl
+ ,TOK_ASM_movswl
+
+ ,TOK_ASM_movsbq
+ ,TOK_ASM_movswq
+ ,TOK_ASM_movzwq
+ ,TOK_ASM_movslq
+
+
+ ,TOK_ASM_leaw ,TOK_ASM_leal ,TOK_ASM_leaq ,TOK_ASM_lea
+
+ ,TOK_ASM_les
+ ,TOK_ASM_lds
+ ,TOK_ASM_lss
+ ,TOK_ASM_lfs
+ ,TOK_ASM_lgs
+
+ ,TOK_ASM_call
+ ,TOK_ASM_jmp
+ ,TOK_ASM_lcall
+ ,TOK_ASM_ljmp
+
+ ,TOK_ASM_jo ,TOK_ASM_jno ,TOK_ASM_jb ,TOK_ASM_jc ,TOK_ASM_jnae ,TOK_ASM_jnb ,TOK_ASM_jnc ,TOK_ASM_jae ,TOK_ASM_je ,TOK_ASM_jz ,TOK_ASM_jne ,TOK_ASM_jnz ,TOK_ASM_jbe ,TOK_ASM_jna ,TOK_ASM_jnbe ,TOK_ASM_ja ,TOK_ASM_js ,TOK_ASM_jns ,TOK_ASM_jp ,TOK_ASM_jpe ,TOK_ASM_jnp ,TOK_ASM_jpo ,TOK_ASM_jl ,TOK_ASM_jnge ,TOK_ASM_jnl ,TOK_ASM_jge ,TOK_ASM_jle ,TOK_ASM_jng ,TOK_ASM_jnle ,TOK_ASM_jg
+
+ ,TOK_ASM_seto ,TOK_ASM_setno ,TOK_ASM_setb ,TOK_ASM_setc ,TOK_ASM_setnae ,TOK_ASM_setnb ,TOK_ASM_setnc ,TOK_ASM_setae ,TOK_ASM_sete ,TOK_ASM_setz ,TOK_ASM_setne ,TOK_ASM_setnz ,TOK_ASM_setbe ,TOK_ASM_setna ,TOK_ASM_setnbe ,TOK_ASM_seta ,TOK_ASM_sets ,TOK_ASM_setns ,TOK_ASM_setp ,TOK_ASM_setpe ,TOK_ASM_setnp ,TOK_ASM_setpo ,TOK_ASM_setl ,TOK_ASM_setnge ,TOK_ASM_setnl ,TOK_ASM_setge ,TOK_ASM_setle ,TOK_ASM_setng ,TOK_ASM_setnle ,TOK_ASM_setg
+ ,TOK_ASM_setob ,TOK_ASM_setnob ,TOK_ASM_setbb ,TOK_ASM_setcb ,TOK_ASM_setnaeb ,TOK_ASM_setnbb ,TOK_ASM_setncb ,TOK_ASM_setaeb ,TOK_ASM_seteb ,TOK_ASM_setzb ,TOK_ASM_setneb ,TOK_ASM_setnzb ,TOK_ASM_setbeb ,TOK_ASM_setnab ,TOK_ASM_setnbeb ,TOK_ASM_setab ,TOK_ASM_setsb ,TOK_ASM_setnsb ,TOK_ASM_setpb ,TOK_ASM_setpeb ,TOK_ASM_setnpb ,TOK_ASM_setpob ,TOK_ASM_setlb ,TOK_ASM_setngeb ,TOK_ASM_setnlb ,TOK_ASM_setgeb ,TOK_ASM_setleb ,TOK_ASM_setngb ,TOK_ASM_setnleb ,TOK_ASM_setgb
+ ,TOK_ASM_cmovo ,TOK_ASM_cmovno ,TOK_ASM_cmovb ,TOK_ASM_cmovc ,TOK_ASM_cmovnae ,TOK_ASM_cmovnb ,TOK_ASM_cmovnc ,TOK_ASM_cmovae ,TOK_ASM_cmove ,TOK_ASM_cmovz ,TOK_ASM_cmovne ,TOK_ASM_cmovnz ,TOK_ASM_cmovbe ,TOK_ASM_cmovna ,TOK_ASM_cmovnbe ,TOK_ASM_cmova ,TOK_ASM_cmovs ,TOK_ASM_cmovns ,TOK_ASM_cmovp ,TOK_ASM_cmovpe ,TOK_ASM_cmovnp ,TOK_ASM_cmovpo ,TOK_ASM_cmovl ,TOK_ASM_cmovnge ,TOK_ASM_cmovnl ,TOK_ASM_cmovge ,TOK_ASM_cmovle ,TOK_ASM_cmovng ,TOK_ASM_cmovnle ,TOK_ASM_cmovg
+
+ ,TOK_ASM_bsfw ,TOK_ASM_bsfl ,TOK_ASM_bsfq ,TOK_ASM_bsf
+ ,TOK_ASM_bsrw ,TOK_ASM_bsrl ,TOK_ASM_bsrq ,TOK_ASM_bsr
+ ,TOK_ASM_btw ,TOK_ASM_btl ,TOK_ASM_btq ,TOK_ASM_bt
+ ,TOK_ASM_btsw ,TOK_ASM_btsl ,TOK_ASM_btsq ,TOK_ASM_bts
+ ,TOK_ASM_btrw ,TOK_ASM_btrl ,TOK_ASM_btrq ,TOK_ASM_btr
+ ,TOK_ASM_btcw ,TOK_ASM_btcl ,TOK_ASM_btcq ,TOK_ASM_btc
+
+ ,TOK_ASM_larw ,TOK_ASM_larl ,TOK_ASM_larq ,TOK_ASM_lar
+ ,TOK_ASM_lslw ,TOK_ASM_lsll ,TOK_ASM_lslq ,TOK_ASM_lsl
+
+
+ ,TOK_ASM_fadd ,TOK_ASM_faddp ,TOK_ASM_fadds ,TOK_ASM_fiaddl ,TOK_ASM_faddl ,TOK_ASM_fiadds
+ ,TOK_ASM_fmul ,TOK_ASM_fmulp ,TOK_ASM_fmuls ,TOK_ASM_fimull ,TOK_ASM_fmull ,TOK_ASM_fimuls
+
+ ,TOK_ASM_fcom
+ ,TOK_ASM_fcom_1
+ ,TOK_ASM_fcoms ,TOK_ASM_ficoml ,TOK_ASM_fcoml ,TOK_ASM_ficoms
+
+ ,TOK_ASM_fcomp ,TOK_ASM_fcompp ,TOK_ASM_fcomps ,TOK_ASM_ficompl ,TOK_ASM_fcompl ,TOK_ASM_ficomps
+ ,TOK_ASM_fsub ,TOK_ASM_fsubp ,TOK_ASM_fsubs ,TOK_ASM_fisubl ,TOK_ASM_fsubl ,TOK_ASM_fisubs
+ ,TOK_ASM_fsubr ,TOK_ASM_fsubrp ,TOK_ASM_fsubrs ,TOK_ASM_fisubrl ,TOK_ASM_fsubrl ,TOK_ASM_fisubrs
+ ,TOK_ASM_fdiv ,TOK_ASM_fdivp ,TOK_ASM_fdivs ,TOK_ASM_fidivl ,TOK_ASM_fdivl ,TOK_ASM_fidivs
+ ,TOK_ASM_fdivr ,TOK_ASM_fdivrp ,TOK_ASM_fdivrs ,TOK_ASM_fidivrl ,TOK_ASM_fdivrl ,TOK_ASM_fidivrs
+
+ ,TOK_ASM_xaddb ,TOK_ASM_xaddw ,TOK_ASM_xaddl ,TOK_ASM_xaddq ,TOK_ASM_xadd
+ ,TOK_ASM_cmpxchgb ,TOK_ASM_cmpxchgw ,TOK_ASM_cmpxchgl ,TOK_ASM_cmpxchgq ,TOK_ASM_cmpxchg
+
+
+ ,TOK_ASM_cmpsb ,TOK_ASM_cmpsw ,TOK_ASM_cmpsl ,TOK_ASM_cmpsq ,TOK_ASM_cmps
+ ,TOK_ASM_scmpb ,TOK_ASM_scmpw ,TOK_ASM_scmpl ,TOK_ASM_scmpq ,TOK_ASM_scmp
+ ,TOK_ASM_insb ,TOK_ASM_insw ,TOK_ASM_insl ,TOK_ASM_ins
+ ,TOK_ASM_outsb ,TOK_ASM_outsw ,TOK_ASM_outsl ,TOK_ASM_outs
+ ,TOK_ASM_lodsb ,TOK_ASM_lodsw ,TOK_ASM_lodsl ,TOK_ASM_lodsq ,TOK_ASM_lods
+ ,TOK_ASM_slodb ,TOK_ASM_slodw ,TOK_ASM_slodl ,TOK_ASM_slodq ,TOK_ASM_slod
+ ,TOK_ASM_movsb ,TOK_ASM_movsw ,TOK_ASM_movsl ,TOK_ASM_movsq ,TOK_ASM_movs
+ ,TOK_ASM_smovb ,TOK_ASM_smovw ,TOK_ASM_smovl ,TOK_ASM_smovq ,TOK_ASM_smov
+ ,TOK_ASM_scasb ,TOK_ASM_scasw ,TOK_ASM_scasl ,TOK_ASM_scasq ,TOK_ASM_scas
+ ,TOK_ASM_sscab ,TOK_ASM_sscaw ,TOK_ASM_sscal ,TOK_ASM_sscaq ,TOK_ASM_ssca
+ ,TOK_ASM_stosb ,TOK_ASM_stosw ,TOK_ASM_stosl ,TOK_ASM_stosq ,TOK_ASM_stos
+ ,TOK_ASM_sstob ,TOK_ASM_sstow ,TOK_ASM_sstol ,TOK_ASM_sstoq ,TOK_ASM_ssto
+# 238 "i386-tok.h"
+# 1 "x86_64-asm.h" 1
+     ,TOK_ASM_clc
+     ,TOK_ASM_cld
+     ,TOK_ASM_cli
+     ,TOK_ASM_clts
+     ,TOK_ASM_cmc
+     ,TOK_ASM_lahf
+     ,TOK_ASM_sahf
+     ,TOK_ASM_pushfq
+     ,TOK_ASM_popfq
+     ,TOK_ASM_pushf
+     ,TOK_ASM_popf
+     ,TOK_ASM_stc
+     ,TOK_ASM_std
+     ,TOK_ASM_sti
+     ,TOK_ASM_aaa
+     ,TOK_ASM_aas
+     ,TOK_ASM_daa
+     ,TOK_ASM_das
+     ,TOK_ASM_aad
+     ,TOK_ASM_aam
+     ,TOK_ASM_cbw
+     ,TOK_ASM_cwd
+     ,TOK_ASM_cwde
+     ,TOK_ASM_cdq
+     ,TOK_ASM_cbtw
+     ,TOK_ASM_cwtl
+     ,TOK_ASM_cwtd
+     ,TOK_ASM_cltd
+     ,TOK_ASM_cqto
+     ,TOK_ASM_int3
+     ,TOK_ASM_into
+     ,TOK_ASM_iret
+     ,TOK_ASM_rsm
+     ,TOK_ASM_hlt
+     ,TOK_ASM_wait
+     ,TOK_ASM_nop
+     ,TOK_ASM_pause
+     ,TOK_ASM_xlat
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+     ,TOK_ASM_lock
+     ,TOK_ASM_rep
+     ,TOK_ASM_repe
+     ,TOK_ASM_repz
+     ,TOK_ASM_repne
+     ,TOK_ASM_repnz
+
+     ,TOK_ASM_invd
+     ,TOK_ASM_wbinvd
+     ,TOK_ASM_cpuid
+     ,TOK_ASM_wrmsr
+     ,TOK_ASM_rdtsc
+     ,TOK_ASM_rdmsr
+     ,TOK_ASM_rdpmc
+
+     ,TOK_ASM_syscall
+     ,TOK_ASM_sysret
+    
+     ,TOK_ASM_ud2
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+   
+   
+
+
+
+
+   
+    ,TOK_ASM_leave
+    ,TOK_ASM_ret
+    ,TOK_ASM_retq
+
+
+    ,TOK_ASM_lret
+
+
+
+   
+   
+   
+   
+   
+   
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+     ,TOK_ASM_fucompp
+     ,TOK_ASM_ftst
+     ,TOK_ASM_fxam
+     ,TOK_ASM_fld1
+     ,TOK_ASM_fldl2t
+     ,TOK_ASM_fldl2e
+     ,TOK_ASM_fldpi
+     ,TOK_ASM_fldlg2
+     ,TOK_ASM_fldln2
+     ,TOK_ASM_fldz
+
+     ,TOK_ASM_f2xm1
+     ,TOK_ASM_fyl2x
+     ,TOK_ASM_fptan
+     ,TOK_ASM_fpatan
+     ,TOK_ASM_fxtract
+     ,TOK_ASM_fprem1
+     ,TOK_ASM_fdecstp
+     ,TOK_ASM_fincstp
+     ,TOK_ASM_fprem
+     ,TOK_ASM_fyl2xp1
+     ,TOK_ASM_fsqrt
+     ,TOK_ASM_fsincos
+     ,TOK_ASM_frndint
+     ,TOK_ASM_fscale
+     ,TOK_ASM_fsin
+     ,TOK_ASM_fcos
+     ,TOK_ASM_fchs
+     ,TOK_ASM_fabs
+     ,TOK_ASM_fninit
+     ,TOK_ASM_fnclex
+     ,TOK_ASM_fnop
+     ,TOK_ASM_fwait
+
+
+   
+   
+   
+
+   
+   
+   
+   
+   
+
+
+   
+   
+   
+   
+
+   
+   
+   
+   
+   
+
+   
+   
+   
+   
+   
+
+
+    ,TOK_ASM_fxch
+
+
+
+   
+   
+
+   
+   
+   
+   
+    ,TOK_ASM_fnstsw
+
+
+   
+
+
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+
+
+
+
+   
+   
+
+
+   
+
+   
+   
+   
+   
+   
+   
+
+   
+   
+   
+   
+   
+   
+   
+   
+
+
+   
+   
+   
+
+
+
+   
+   
+   
+
+
+
+   
+
+
+   
+
+
+   
+
+
+
+
+   
+   
+   
+   
+   
+   
+   
+   
+
+   
+   
+   
+   
+
+
+    ,TOK_ASM_emms
+   
+
+
+
+
+
+
+
+
+
+
+
+
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+
+   
+
+   
+
+   
+
+   
+
+   
+
+   
+
+   
+
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+
+
+   
+
+   
+
+   
+
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+   
+
+   
+   
+   
+   
+   
+   
+   
+   
+   
+# 239 "i386-tok.h" 2
+# 250 "i386-tok.h"
+# 1 "x86_64-asm.h" 1
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+    
+    
+    
+    
+    
+    
+
+    
+    
+    
+    
+    
+    
+    
+
+    
+    
+     ,TOK_ASM_sysretq
+    
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+    ,TOK_ASM_ljmpw
+    ,TOK_ASM_ljmpl
+
+
+
+
+    ,TOK_ASM_enter
+   
+   
+   
+
+
+   
+
+
+
+    ,TOK_ASM_loopne
+    ,TOK_ASM_loopnz
+    ,TOK_ASM_loope
+    ,TOK_ASM_loopz
+    ,TOK_ASM_loop
+    ,TOK_ASM_jecxz
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+
+
+    ,TOK_ASM_fld
+    ,TOK_ASM_fldl
+    ,TOK_ASM_flds
+
+    ,TOK_ASM_fildl
+    ,TOK_ASM_fildq
+    ,TOK_ASM_fildll
+    ,TOK_ASM_fldt
+    ,TOK_ASM_fbld
+
+
+    ,TOK_ASM_fst
+    ,TOK_ASM_fstl
+    ,TOK_ASM_fsts
+    ,TOK_ASM_fstps
+
+    ,TOK_ASM_fstpl
+    ,TOK_ASM_fist
+    ,TOK_ASM_fistp
+    ,TOK_ASM_fistl
+    ,TOK_ASM_fistpl
+
+    ,TOK_ASM_fstp
+    ,TOK_ASM_fistpq
+    ,TOK_ASM_fistpll
+    ,TOK_ASM_fstpt
+    ,TOK_ASM_fbstp
+
+
+   
+
+
+
+    ,TOK_ASM_fucom
+    ,TOK_ASM_fucomp
+
+    ,TOK_ASM_finit
+    ,TOK_ASM_fldcw
+    ,TOK_ASM_fnstcw
+    ,TOK_ASM_fstcw
+   
+
+
+    ,TOK_ASM_fstsw
+
+
+    ,TOK_ASM_fclex
+    ,TOK_ASM_fnstenv
+    ,TOK_ASM_fstenv
+    ,TOK_ASM_fldenv
+    ,TOK_ASM_fnsave
+    ,TOK_ASM_fsave
+    ,TOK_ASM_frstor
+    ,TOK_ASM_ffree
+    ,TOK_ASM_ffreep
+    ,TOK_ASM_fxsave
+    ,TOK_ASM_fxrstor
+
+
+
+
+    ,TOK_ASM_fxsaveq
+    ,TOK_ASM_fxrstorq
+
+
+    ,TOK_ASM_arpl
+
+    ,TOK_ASM_lgdt
+    ,TOK_ASM_lgdtq
+    ,TOK_ASM_lidt
+    ,TOK_ASM_lidtq
+    ,TOK_ASM_lldt
+    ,TOK_ASM_lmsw
+
+    ,TOK_ASM_ltr
+    ,TOK_ASM_sgdt
+    ,TOK_ASM_sgdtq
+    ,TOK_ASM_sidt
+    ,TOK_ASM_sidtq
+    ,TOK_ASM_sldt
+    ,TOK_ASM_smsw
+    ,TOK_ASM_str
+
+
+    ,TOK_ASM_verr
+    ,TOK_ASM_verw
+    ,TOK_ASM_swapgs
+
+
+
+    ,TOK_ASM_bswap
+    ,TOK_ASM_bswapl
+    ,TOK_ASM_bswapq
+
+
+
+    ,TOK_ASM_invlpg
+
+
+    ,TOK_ASM_cmpxchg8b
+
+
+    ,TOK_ASM_cmpxchg16b
+
+
+
+
+    ,TOK_ASM_fcmovb
+    ,TOK_ASM_fcmove
+    ,TOK_ASM_fcmovbe
+    ,TOK_ASM_fcmovu
+    ,TOK_ASM_fcmovnb
+    ,TOK_ASM_fcmovne
+    ,TOK_ASM_fcmovnbe
+    ,TOK_ASM_fcmovnu
+
+    ,TOK_ASM_fucomi
+    ,TOK_ASM_fcomi
+    ,TOK_ASM_fucomip
+    ,TOK_ASM_fcomip
+
+
+   
+    ,TOK_ASM_movd
+
+
+
+
+
+
+
+
+
+
+
+
+    ,TOK_ASM_packssdw
+    ,TOK_ASM_packsswb
+    ,TOK_ASM_packuswb
+    ,TOK_ASM_paddb
+    ,TOK_ASM_paddw
+    ,TOK_ASM_paddd
+    ,TOK_ASM_paddsb
+    ,TOK_ASM_paddsw
+    ,TOK_ASM_paddusb
+    ,TOK_ASM_paddusw
+    ,TOK_ASM_pand
+    ,TOK_ASM_pandn
+    ,TOK_ASM_pcmpeqb
+    ,TOK_ASM_pcmpeqw
+    ,TOK_ASM_pcmpeqd
+    ,TOK_ASM_pcmpgtb
+    ,TOK_ASM_pcmpgtw
+    ,TOK_ASM_pcmpgtd
+    ,TOK_ASM_pmaddwd
+    ,TOK_ASM_pmulhw
+    ,TOK_ASM_pmullw
+    ,TOK_ASM_por
+    ,TOK_ASM_psllw
+
+    ,TOK_ASM_pslld
+
+    ,TOK_ASM_psllq
+
+    ,TOK_ASM_psraw
+
+    ,TOK_ASM_psrad
+
+    ,TOK_ASM_psrlw
+
+    ,TOK_ASM_psrld
+
+    ,TOK_ASM_psrlq
+
+    ,TOK_ASM_psubb
+    ,TOK_ASM_psubw
+    ,TOK_ASM_psubd
+    ,TOK_ASM_psubsb
+    ,TOK_ASM_psubsw
+    ,TOK_ASM_psubusb
+    ,TOK_ASM_psubusw
+    ,TOK_ASM_punpckhbw
+    ,TOK_ASM_punpckhwd
+    ,TOK_ASM_punpckhdq
+    ,TOK_ASM_punpcklbw
+    ,TOK_ASM_punpcklwd
+    ,TOK_ASM_punpckldq
+    ,TOK_ASM_pxor
+
+
+    ,TOK_ASM_movups
+
+    ,TOK_ASM_movaps
+
+    ,TOK_ASM_movhps
+
+    ,TOK_ASM_addps
+    ,TOK_ASM_cvtpi2ps
+    ,TOK_ASM_cvtps2pi
+    ,TOK_ASM_cvttps2pi
+    ,TOK_ASM_divps
+    ,TOK_ASM_maxps
+    ,TOK_ASM_minps
+    ,TOK_ASM_mulps
+    ,TOK_ASM_pavgb
+    ,TOK_ASM_pavgw
+    ,TOK_ASM_pmaxsw
+    ,TOK_ASM_pmaxub
+    ,TOK_ASM_pminsw
+    ,TOK_ASM_pminub
+    ,TOK_ASM_rcpss
+    ,TOK_ASM_rsqrtps
+    ,TOK_ASM_sqrtps
+    ,TOK_ASM_subps
+
+    ,TOK_ASM_prefetchnta
+    ,TOK_ASM_prefetcht0
+    ,TOK_ASM_prefetcht1
+    ,TOK_ASM_prefetcht2
+    ,TOK_ASM_prefetchw
+    ,TOK_ASM_lfence
+    ,TOK_ASM_mfence
+    ,TOK_ASM_sfence
+    ,TOK_ASM_clflush
+# 251 "i386-tok.h" 2
+# 350 "tcctok.h" 2
+# 1074 "tcc.h" 2
+
+};
+
+
+
+
+
+
+
+static int gnu_ext;
+
+static int tcc_ext;
+
+static struct TCCState *tcc_state;
+
+
+static char *pstrcpy(char *buf, int buf_size, const char *s);
+static char *pstrcat(char *buf, int buf_size, const char *s);
+static char *pstrncpy(char *out, const char *in, size_t num);
+ char *tcc_basename(const char *name);
+ char *tcc_fileextension (const char *name);
+
+
+ void tcc_free(void *ptr);
+ void *tcc_malloc(unsigned long size);
+ void *tcc_mallocz(unsigned long size);
+ void *tcc_realloc(void *ptr, unsigned long size);
+ char *tcc_strdup(const char *str);
+# 1120 "tcc.h"
+ void tcc_memcheck(void);
+ void tcc_error_noabort(const char *fmt, ...);
+ void tcc_error(const char *fmt, ...);
+ void tcc_warning(const char *fmt, ...);
+
+
+static void dynarray_add(void *ptab, int *nb_ptr, void *data);
+static void dynarray_reset(void *pp, int *n);
+static inline void cstr_ccat(CString *cstr, int ch);
+static void cstr_cat(CString *cstr, const char *str, int len);
+static void cstr_wccat(CString *cstr, int ch);
+static void cstr_new(CString *cstr);
+static void cstr_free(CString *cstr);
+static void cstr_reset(CString *cstr);
+
+static inline void sym_free(Sym *sym);
+static Sym *sym_push2(Sym **ps, int v, int t, int c);
+static Sym *sym_find2(Sym *s, int v);
+static Sym *sym_push(int v, CType *type, int r, int c);
+static void sym_pop(Sym **ptop, Sym *b, int keep);
+static inline Sym *struct_find(int v);
+static inline Sym *sym_find(int v);
+static Sym *global_identifier_push(int v, int t, int c);
+
+static void tcc_open_bf(TCCState *s1, const char *filename, int initlen);
+static int tcc_open(TCCState *s1, const char *filename);
+static void tcc_close(void);
+
+static int tcc_add_file_internal(TCCState *s1, const char *filename, int flags);
+# 1166 "tcc.h"
+static int tcc_add_crt(TCCState *s, const char *filename);
+static int tcc_add_dll(TCCState *s, const char *filename, int flags);
+static void tcc_add_pragma_libs(TCCState *s1);
+ int tcc_add_library_err(TCCState *s, const char *f);
+ void tcc_print_stats(TCCState *s, unsigned total_time);
+ int tcc_parse_args(TCCState *s, int *argc, char ***argv, int optind);
+# 1188 "tcc.h"
+static struct BufferedFile *file;
+static int ch, tok;
+static CValue tokc;
+static const int *macro_ptr;
+static int parse_flags;
+static int tok_flags;
+static CString tokcstr;
+
+
+static int total_lines;
+static int total_bytes;
+static int tok_ident;
+static TokenSym **table_ident;
+# 1222 "tcc.h"
+static TokenSym *tok_alloc(const char *str, int len);
+static const char *get_tok_str(int v, CValue *cv);
+static void begin_macro(TokenString *str, int alloc);
+static void end_macro(void);
+static int set_idnum(int c, int val);
+static inline void tok_str_new(TokenString *s);
+static TokenString *tok_str_alloc(void);
+static void tok_str_free(TokenString *s);
+static void tok_str_free_str(int *str);
+static void tok_str_add(TokenString *s, int t);
+static void tok_str_add_tok(TokenString *s);
+static inline void define_push(int v, int macro_type, int *str, Sym *first_arg);
+static void define_undef(Sym *s);
+static inline Sym *define_find(int v);
+static void free_defines(Sym *b);
+static Sym *label_find(int v);
+static Sym *label_push(Sym **ptop, int v, int flags);
+static void label_pop(Sym **ptop, Sym *slast, int keep);
+static void parse_define(void);
+static void preprocess(int is_bof);
+static void next_nomacro(void);
+static void next(void);
+static inline void unget_tok(int last_tok);
+static void preprocess_start(TCCState *s1, int is_asm);
+static void preprocess_end(TCCState *s1);
+static void tccpp_new(TCCState *s);
+static void tccpp_delete(TCCState *s);
+static int tcc_preprocess(TCCState *s1);
+static void skip(int c);
+static void expect(const char *msg);
+
+
+static inline int is_space(int ch) {
+    return ch == ' ' || ch == '\t' || ch == '\v' || ch == '\f' || ch == '\r';
+}
+static inline int isid(int c) {
+    return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_';
+}
+static inline int isnum(int c) {
+    return c >= '0' && c <= '9';
+}
+static inline int isoct(int c) {
+    return c >= '0' && c <= '7';
+}
+static inline int toup(int c) {
+    return (c >= 'a' && c <= 'z') ? c - 'a' + 'A' : c;
+}
+
+
+
+
+static Sym *sym_free_first;
+static void **sym_pools;
+static int nb_sym_pools;
+
+static Sym *global_stack;
+static Sym *local_stack;
+static Sym *local_label_stack;
+static Sym *global_label_stack;
+static Sym *define_stack;
+static CType char_pointer_type, func_old_type, int_type, size_type;
+static SValue __vstack[1+ 256], *vtop, *pvtop;
+
+static int rsym, anon_sym, ind, loc;
+
+static int const_wanted;
+static int nocode_wanted;
+static int global_expr;
+static CType func_vt;
+static int func_var;
+static int func_vc;
+static int last_line_num, last_ind, func_ind;
+static const char *funcname;
+static int g_debug;
+
+static void tcc_debug_start(TCCState *s1);
+static void tcc_debug_end(TCCState *s1);
+static void tcc_debug_funcstart(TCCState *s1, Sym *sym);
+static void tcc_debug_funcend(TCCState *s1, int size);
+static void tcc_debug_line(TCCState *s1);
+
+static int tccgen_compile(TCCState *s1);
+static void free_inline_functions(TCCState *s);
+static void check_vstack(void);
+
+static inline int is_float(int t);
+static int ieee_finite(double d);
+static void test_lvalue(void);
+static void vpushi(int v);
+static Elf64_Sym *elfsym(Sym *);
+static void update_storage(Sym *sym);
+static Sym *external_global_sym(int v, CType *type, int r);
+static void vset(CType *type, int r, int v);
+static void vswap(void);
+static void vpush_global_sym(CType *type, int v);
+static void vrote(SValue *e, int n);
+static void vrott(int n);
+static void vrotb(int n);
+
+
+
+
+static void vpushv(SValue *v);
+static void save_reg(int r);
+static void save_reg_upstack(int r, int n);
+static int get_reg(int rc);
+static void save_regs(int n);
+static void gaddrof(void);
+static int gv(int rc);
+static void gv2(int rc1, int rc2);
+static void vpop(void);
+static void gen_op(int op);
+static int type_size(CType *type, int *a);
+static void mk_pointer(CType *type);
+static void vstore(void);
+static void inc(int post, int c);
+static void parse_mult_str (CString *astr, const char *msg);
+static void parse_asm_str(CString *astr);
+static int lvalue_type(int t);
+static void indir(void);
+static void unary(void);
+static void expr_prod(void);
+static void expr_sum(void);
+static void gexpr(void);
+static int expr_const(void);
+
+static Sym *get_sym_ref(CType *type, Section *sec, unsigned long offset, unsigned long size);
+
+
+static int classify_x86_64_va_arg(CType *ty);
+# 1362 "tcc.h"
+typedef struct {
+    unsigned int n_strx;
+    unsigned char n_type;
+    unsigned char n_other;
+    unsigned short n_desc;
+    unsigned int n_value;
+} Stab_Sym;
+
+static Section *text_section, *data_section, *bss_section;
+static Section *common_section;
+static Section *cur_text_section;
+
+static Section *last_text_section;
+
+
+
+static Section *bounds_section;
+static Section *lbounds_section;
+static void tccelf_bounds_new(TCCState *s);
+
+
+static Section *symtab_section;
+
+static Section *stab_section, *stabstr_section;
+
+static void tccelf_new(TCCState *s);
+static void tccelf_delete(TCCState *s);
+static void tccelf_stab_new(TCCState *s);
+static void tccelf_begin_file(TCCState *s1);
+static void tccelf_end_file(TCCState *s1);
+
+static Section *new_section(TCCState *s1, const char *name, int sh_type, int sh_flags);
+static void section_realloc(Section *sec, unsigned long new_size);
+static size_t section_add(Section *sec, Elf64_Addr size, int align);
+static void *section_ptr_add(Section *sec, Elf64_Addr size);
+static void section_reserve(Section *sec, unsigned long size);
+static Section *find_section(TCCState *s1, const char *name);
+static Section *new_symtab(TCCState *s1, const char *symtab_name, int sh_type, int sh_flags, const char *strtab_name, const char *hash_name, int hash_sh_flags);
+
+static void put_extern_sym2(Sym *sym, int sh_num, Elf64_Addr value, unsigned long size, int can_add_underscore);
+static void put_extern_sym(Sym *sym, Section *section, Elf64_Addr value, unsigned long size);
+
+
+
+static void greloca(Section *s, Sym *sym, unsigned long offset, int type, Elf64_Addr addend);
+
+static int put_elf_str(Section *s, const char *sym);
+static int put_elf_sym(Section *s, Elf64_Addr value, unsigned long size, int info, int other, int shndx, const char *name);
+static int set_elf_sym(Section *s, Elf64_Addr value, unsigned long size, int info, int other, int shndx, const char *name);
+static int find_elf_sym(Section *s, const char *name);
+static void put_elf_reloc(Section *symtab, Section *s, unsigned long offset, int type, int symbol);
+static void put_elf_reloca(Section *symtab, Section *s, unsigned long offset, int type, int symbol, Elf64_Addr addend);
+
+static void put_stabs(const char *str, int type, int other, int desc, unsigned long value);
+static void put_stabs_r(const char *str, int type, int other, int desc, unsigned long value, Section *sec, int sym_index);
+static void put_stabn(int type, int other, int desc, int value);
+static void put_stabd(int type, int other, int desc);
+
+static void resolve_common_syms(TCCState *s1);
+static void relocate_syms(TCCState *s1, Section *symtab, int do_resolve);
+static void relocate_section(TCCState *s1, Section *s);
+
+static int tcc_object_type(int fd, Elf64_Ehdr *h);
+static int tcc_load_object_file(TCCState *s1, int fd, unsigned long file_offset);
+static int tcc_load_archive(TCCState *s1, int fd);
+static void tcc_add_bcheck(TCCState *s1);
+static void tcc_add_runtime(TCCState *s1);
+
+static void build_got_entries(TCCState *s1);
+static struct sym_attr *get_sym_attr(TCCState *s1, int index, int alloc);
+static void squeeze_multi_relocs(Section *sec, size_t oldrelocoffset);
+
+static Elf64_Addr get_elf_sym_addr(TCCState *s, const char *name, int err);
+
+static void *tcc_get_symbol_err(TCCState *s, const char *name);
+
+
+
+static int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level);
+static int tcc_load_ldscript(TCCState *s1);
+static uint8_t *parse_comment(uint8_t *p);
+static void minp(void);
+static inline void inp(void);
+static int handle_eob(void);
+
+
+
+
+
+
+enum gotplt_entry {
+    NO_GOTPLT_ENTRY,
+    BUILD_GOT_ONLY,
+    AUTO_GOTPLT_ENTRY,
+    ALWAYS_GOTPLT_ENTRY
+};
+
+static int code_reloc (int reloc_type);
+static int gotplt_entry_type (int reloc_type);
+static unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_attr *attr);
+static void relocate_init(Section *sr);
+static void relocate(TCCState *s1, Elf64_Rela *rel, int type, unsigned char *ptr, Elf64_Addr addr, Elf64_Addr val);
+static void relocate_plt(TCCState *s1);
+
+
+
+static const int reg_classes[25];
+
+static void gsym_addr(int t, int a);
+static void gsym(int t);
+static void load(int r, SValue *sv);
+static void store(int r, SValue *v);
+static int gfunc_sret(CType *vt, int variadic, CType *ret, int *align, int *regsize);
+static void gfunc_call(int nb_args);
+static void gfunc_prolog(CType *func_type);
+static void gfunc_epilog(void);
+static int gjmp(int t);
+static void gjmp_addr(int a);
+static int gtst(int inv, int t);
+
+static void gtst_addr(int inv, int a);
+
+
+
+static void gen_opi(int op);
+static void gen_opf(int op);
+static void gen_cvt_ftoi(int t);
+static void gen_cvt_ftof(int t);
+static void ggoto(void);
+
+static void o(unsigned int c);
+
+
+static void gen_cvt_itof(int t);
+
+static void gen_vla_sp_save(int addr);
+static void gen_vla_sp_restore(int addr);
+static void gen_vla_alloc(CType *type, int align);
+
+static inline uint16_t read16le(unsigned char *p) {
+    return p[0] | (uint16_t)p[1] << 8;
+}
+static inline void write16le(unsigned char *p, uint16_t x) {
+    p[0] = x & 255; p[1] = x >> 8 & 255;
+}
+static inline uint32_t read32le(unsigned char *p) {
+  return read16le(p) | (uint32_t)read16le(p + 2) << 16;
+}
+static inline void write32le(unsigned char *p, uint32_t x) {
+    write16le(p, x); write16le(p + 2, x >> 16);
+}
+static inline void add32le(unsigned char *p, int32_t x) {
+    write32le(p, read32le(p) + x);
+}
+static inline uint64_t read64le(unsigned char *p) {
+  return read32le(p) | (uint64_t)read32le(p + 4) << 32;
+}
+static inline void write64le(unsigned char *p, uint64_t x) {
+    write32le(p, x); write32le(p + 4, x >> 32);
+}
+static inline void add64le(unsigned char *p, int64_t x) {
+    write64le(p, read64le(p) + x);
+}
+
+
+
+static void g(int c);
+static void gen_le16(int c);
+static void gen_le32(int c);
+static void gen_addr32(int r, Sym *sym, int c);
+static void gen_addrpc32(int r, Sym *sym, int c);
+
+
+
+static void gen_bounded_ptr_add(void);
+static void gen_bounded_ptr_deref(void);
+
+
+
+
+static void gen_addr64(int r, Sym *sym, int64_t c);
+static void gen_opl(int op);
+# 1580 "tcc.h"
+static void asm_instr(void);
+static void asm_global_instr(void);
+
+static int find_constraint(ASMOperand *operands, int nb_operands, const char *name, const char **pp);
+static Sym* get_asm_sym(int name, Sym *csym);
+static void asm_expr(TCCState *s1, ExprValue *pe);
+static int asm_int_expr(TCCState *s1);
+static int tcc_assemble(TCCState *s1, int do_preprocess);
+
+static void gen_expr32(ExprValue *pe);
+
+static void gen_expr64(ExprValue *pe);
+
+static void asm_opcode(TCCState *s1, int opcode);
+static int asm_parse_regvar(int t);
+static void asm_compute_constraints(ASMOperand *operands, int nb_operands, int nb_outputs, const uint8_t *clobber_regs, int *pout_reg);
+static void subst_asm_operand(CString *add_str, SValue *sv, int modifier);
+static void asm_gen_code(ASMOperand *operands, int nb_operands, int nb_outputs, int is_output, uint8_t *clobber_regs, int out_reg);
+static void asm_clobber(uint8_t *clobber_regs, const char *str);
+# 1634 "tcc.h"
+static int rt_num_callers;
+static const char **rt_bound_error_msg;
+static void *rt_prog_main;
+static void tcc_set_num_callers(int n);
+
+static void tcc_run_free(TCCState *s1);
+# 22 "tccgen.c" 2
+# 31 "tccgen.c"
+static int rsym, anon_sym, ind, loc;
+
+static Sym *sym_free_first;
+static void **sym_pools;
+static int nb_sym_pools;
+
+static Sym *global_stack;
+static Sym *local_stack;
+static Sym *define_stack;
+static Sym *global_label_stack;
+static Sym *local_label_stack;
+static int local_scope;
+static int in_sizeof;
+static int section_sym;
+
+static int vlas_in_scope;
+static int vla_sp_root_loc;
+static int vla_sp_loc;
+
+static SValue __vstack[1+256], *vtop, *pvtop;
+
+static int const_wanted;
+static int nocode_wanted;
+
+
+static int global_expr;
+static CType func_vt;
+static int func_var;
+static int func_vc;
+static int last_line_num, last_ind, func_ind;
+static const char *funcname;
+static int g_debug;
+
+static CType char_pointer_type, func_old_type, int_type, size_type, ptrdiff_type;
+
+static struct switch_t {
+    struct case_t {
+        int64_t v1, v2;
+ int sym;
+    } **p; int n;
+    int def_sym;
+} *cur_switch;
+
+
+
+static void gen_cast(CType *type);
+static void gen_cast_s(int t);
+static inline CType *pointed_type(CType *type);
+static int is_compatible_types(CType *type1, CType *type2);
+static int parse_btype(CType *type, AttributeDef *ad);
+static CType *type_decl(CType *type, AttributeDef *ad, int *v, int td);
+static void parse_expr_type(CType *type);
+static void init_putv(CType *type, Section *sec, unsigned long c);
+static void decl_initializer(CType *type, Section *sec, unsigned long c, int first, int size_only);
+static void block(int *bsym, int *csym, int is_expr);
+static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, int has_init, int v, int scope);
+static void decl(int l);
+static int decl0(int l, int is_for_loop_init, Sym *);
+static void expr_eq(void);
+static void vla_runtime_type_size(CType *type, int *a);
+static void vla_sp_restore(void);
+static void vla_sp_restore_root(void);
+static int is_compatible_unqualified_types(CType *type1, CType *type2);
+static inline int64_t expr_const64(void);
+static void vpush64(int ty, unsigned long long v);
+static void vpush(CType *type);
+static int gvtst(int inv, int t);
+static void gen_inline_functions(TCCState *s);
+static void skip_or_save_block(TokenString **str);
+static void gv_dup(void);
+
+static inline int is_float(int t)
+{
+    int bt;
+    bt = t & 0x000f;
+    return bt == 10 || bt == 9 || bt == 8 || bt == 14;
+}
+
+
+
+
+static int ieee_finite(double d)
+{
+    int p[4];
+    memcpy(p, &d, sizeof(double));
+    return ((unsigned)((p[1] | 0x800fffff) + 1)) >> 31;
+}
+
+
+
+
+
+
+
+static void test_lvalue(void)
+{
+    if (!(vtop->r & 0x0100))
+        expect("lvalue");
+}
+
+static void check_vstack(void)
+{
+    if (pvtop != vtop)
+        tcc_error("internal compiler error: vstack leak (%d)", vtop - pvtop);
+}
+# 154 "tccgen.c"
+static void tcc_debug_start(TCCState *s1)
+{
+    if (s1->do_debug) {
+        char buf[512];
+
+
+        section_sym = put_elf_sym(symtab_section, 0, 0,
+                                  ((((0)) << 4) + (((3)) & 0xf)), 0,
+                                  text_section->sh_num, 0);
+        getcwd(buf, sizeof(buf));
+
+
+
+        pstrcat(buf, sizeof(buf), "/");
+        put_stabs_r(buf, N_SO, 0, 0,
+                    text_section->data_offset, text_section, section_sym);
+        put_stabs_r(file->filename, N_SO, 0, 0,
+                    text_section->data_offset, text_section, section_sym);
+        last_ind = 0;
+        last_line_num = 0;
+    }
+
+
+
+    put_elf_sym(symtab_section, 0, 0,
+                ((((0)) << 4) + (((4)) & 0xf)), 0,
+                0xfff1, file->filename);
+}
+
+
+static void tcc_debug_end(TCCState *s1)
+{
+    if (!s1->do_debug)
+        return;
+    put_stabs_r(0, N_SO, 0, 0,
+        text_section->data_offset, text_section, section_sym);
+
+}
+
+
+static void tcc_debug_line(TCCState *s1)
+{
+    if (!s1->do_debug)
+        return;
+    if ((last_line_num != file->line_num || last_ind != ind)) {
+        put_stabn(N_SLINE, 0, file->line_num, ind - func_ind);
+        last_ind = ind;
+        last_line_num = file->line_num;
+    }
+}
+
+
+static void tcc_debug_funcstart(TCCState *s1, Sym *sym)
+{
+    char buf[512];
+
+    if (!s1->do_debug)
+        return;
+
+
+
+    snprintf(buf, sizeof(buf), "%s:%c1",
+             funcname, sym->type.t & 0x00002000 ? 'f' : 'F');
+    put_stabs_r(buf, N_FUN, 0, file->line_num, 0,
+                cur_text_section, sym->c);
+
+    put_stabn(N_SLINE, 0, file->line_num, 0);
+
+    last_ind = 0;
+    last_line_num = 0;
+}
+
+
+static void tcc_debug_funcend(TCCState *s1, int size)
+{
+    if (!s1->do_debug)
+        return;
+    put_stabn(N_FUN, 0, 0, size);
+}
+
+
+static int tccgen_compile(TCCState *s1)
+{
+    cur_text_section = 0;
+    funcname = "";
+    anon_sym = 0x10000000;
+    section_sym = 0;
+    const_wanted = 0;
+    nocode_wanted = 0x80000000;
+
+
+    int_type.t = 3;
+    char_pointer_type.t = 1;
+    mk_pointer(&char_pointer_type);
+
+
+
+
+
+
+
+    size_type.t = 0x0800 | 4 | 0x0010;
+    ptrdiff_type.t = 0x0800 | 4;
+
+    func_old_type.t = 6;
+    func_old_type.ref = sym_push(0x20000000, &int_type, 0, 0);
+    func_old_type.ref->f.func_call = 0;
+    func_old_type.ref->f.func_type = 2;
+
+    tcc_debug_start(s1);
+# 273 "tccgen.c"
+    parse_flags = 0x0001 | 0x0002 | 0x0040;
+    next();
+    decl(0x0030);
+    gen_inline_functions(s1);
+    check_vstack();
+
+    tcc_debug_end(s1);
+    return 0;
+}
+
+
+static Elf64_Sym *elfsym(Sym *s)
+{
+  if (!s || !s->c)
+    return 0;
+  return &((Elf64_Sym *)symtab_section->data)[s->c];
+}
+
+
+static void update_storage(Sym *sym)
+{
+    Elf64_Sym *esym;
+    int sym_bind, old_sym_bind;
+
+    esym = elfsym(sym);
+    if (!esym)
+        return;
+
+    if (sym->a.visibility)
+        esym->st_other = (esym->st_other & ~((-1) & 0x03))
+            | sym->a.visibility;
+
+    if (sym->type.t & 0x00002000)
+        sym_bind = 0;
+    else if (sym->a.weak)
+        sym_bind = 2;
+    else
+        sym_bind = 1;
+    old_sym_bind = (((unsigned char) (esym->st_info)) >> 4);
+    if (sym_bind != old_sym_bind) {
+        esym->st_info = ((((sym_bind)) << 4) + (((((esym->st_info) & 0xf))) & 0xf));
+    }
+# 332 "tccgen.c"
+}
+
+
+
+
+
+static void put_extern_sym2(Sym *sym, int sh_num,
+                            Elf64_Addr value, unsigned long size,
+                            int can_add_underscore)
+{
+    int sym_type, sym_bind, info, other, t;
+    Elf64_Sym *esym;
+    const char *name;
+    char buf1[256];
+
+    char buf[32];
+
+
+    if (!sym->c) {
+        name = get_tok_str(sym->v, 0);
+
+        if (tcc_state->do_bounds_check) {
+
+
+
+            switch(sym->v) {
+# 366 "tccgen.c"
+            case TOK_memcpy:
+            case TOK_memmove:
+            case TOK_memset:
+            case TOK_strlen:
+            case TOK_strcpy:
+            case TOK_alloca:
+                strcpy(buf, "__bound_");
+                strcat(buf, name);
+                name = buf;
+                break;
+            }
+        }
+
+        t = sym->type.t;
+        if ((t & 0x000f) == 6) {
+            sym_type = 2;
+        } else if ((t & 0x000f) == 0) {
+            sym_type = 0;
+        } else {
+            sym_type = 1;
+        }
+        if (t & 0x00002000)
+            sym_bind = 0;
+        else
+            sym_bind = 1;
+        other = 0;
+# 403 "tccgen.c"
+        if (tcc_state->leading_underscore && can_add_underscore) {
+            buf1[0] = '_';
+            pstrcpy(buf1 + 1, sizeof(buf1) - 1, name);
+            name = buf1;
+        }
+        if (sym->asm_label)
+            name = get_tok_str(sym->asm_label, 0);
+        info = ((((sym_bind)) << 4) + (((sym_type)) & 0xf));
+        sym->c = put_elf_sym(symtab_section, value, size, info, other, sh_num, name);
+    } else {
+        esym = elfsym(sym);
+        esym->st_value = value;
+        esym->st_size = size;
+        esym->st_shndx = sh_num;
+    }
+    update_storage(sym);
+}
+
+static void put_extern_sym(Sym *sym, Section *section,
+                           Elf64_Addr value, unsigned long size)
+{
+    int sh_num = section ? section->sh_num : 0;
+    put_extern_sym2(sym, sh_num, value, size, 1);
+}
+
+
+static void greloca(Section *s, Sym *sym, unsigned long offset, int type,
+                     Elf64_Addr addend)
+{
+    int c = 0;
+
+    if (nocode_wanted && s == cur_text_section)
+        return;
+
+    if (sym) {
+        if (0 == sym->c)
+            put_extern_sym(sym, 0, 0, 0);
+        c = sym->c;
+    }
+
+
+    put_elf_reloca(symtab_section, s, offset, type, c, addend);
+}
+# 456 "tccgen.c"
+static Sym *__sym_malloc(void)
+{
+    Sym *sym_pool, *sym, *last_sym;
+    int i;
+
+    sym_pool = tcc_malloc((8192 / sizeof(Sym)) * sizeof(Sym));
+    dynarray_add(&sym_pools, &nb_sym_pools, sym_pool);
+
+    last_sym = sym_free_first;
+    sym = sym_pool;
+    for(i = 0; i < (8192 / sizeof(Sym)); i++) {
+        sym->next = last_sym;
+        last_sym = sym;
+        sym++;
+    }
+    sym_free_first = last_sym;
+    return last_sym;
+}
+
+static inline Sym *sym_malloc(void)
+{
+    Sym *sym;
+
+    sym = sym_free_first;
+    if (!sym)
+        sym = __sym_malloc();
+    sym_free_first = sym->next;
+    return sym;
+
+
+
+
+}
+
+static inline void sym_free(Sym *sym)
+{
+
+    sym->next = sym_free_first;
+    sym_free_first = sym;
+
+
+
+}
+
+
+static Sym *sym_push2(Sym **ps, int v, int t, int c)
+{
+    Sym *s;
+
+    s = sym_malloc();
+    memset(s, 0, sizeof *s);
+    s->v = v;
+    s->type.t = t;
+    s->c = c;
+
+    s->prev = *ps;
+    *ps = s;
+    return s;
+}
+
+
+
+static Sym *sym_find2(Sym *s, int v)
+{
+    while (s) {
+        if (s->v == v)
+            return s;
+        else if (s->v == -1)
+            return 0;
+        s = s->prev;
+    }
+    return 0;
+}
+
+
+static inline Sym *struct_find(int v)
+{
+    v -= 256;
+    if ((unsigned)v >= (unsigned)(tok_ident - 256))
+        return 0;
+    return table_ident[v]->sym_struct;
+}
+
+
+static inline Sym *sym_find(int v)
+{
+    v -= 256;
+    if ((unsigned)v >= (unsigned)(tok_ident - 256))
+        return 0;
+    return table_ident[v]->sym_identifier;
+}
+
+
+static Sym *sym_push(int v, CType *type, int r, int c)
+{
+    Sym *s, **ps;
+    TokenSym *ts;
+
+    if (local_stack)
+        ps = &local_stack;
+    else
+        ps = &global_stack;
+    s = sym_push2(ps, v, type->t, c);
+    s->type.ref = type->ref;
+    s->r = r;
+
+
+    if (!(v & 0x20000000) && (v & ~0x40000000) < 0x10000000) {
+
+        ts = table_ident[(v & ~0x40000000) - 256];
+        if (v & 0x40000000)
+            ps = &ts->sym_struct;
+        else
+            ps = &ts->sym_identifier;
+        s->prev_tok = *ps;
+        *ps = s;
+        s->sym_scope = local_scope;
+        if (s->prev_tok && s->prev_tok->sym_scope == s->sym_scope)
+            tcc_error("redeclaration of '%s'",
+                get_tok_str(v & ~0x40000000, 0));
+    }
+    return s;
+}
+
+
+static Sym *global_identifier_push(int v, int t, int c)
+{
+    Sym *s, **ps;
+    s = sym_push2(&global_stack, v, t, c);
+
+    if (v < 0x10000000) {
+        ps = &table_ident[v - 256]->sym_identifier;
+
+
+        while (*ps != 0 && (*ps)->sym_scope)
+            ps = &(*ps)->prev_tok;
+        s->prev_tok = *ps;
+        *ps = s;
+    }
+    return s;
+}
+
+
+
+static void sym_pop(Sym **ptop, Sym *b, int keep)
+{
+    Sym *s, *ss, **ps;
+    TokenSym *ts;
+    int v;
+
+    s = *ptop;
+    while(s != b) {
+        ss = s->prev;
+        v = s->v;
+
+
+        if (!(v & 0x20000000) && (v & ~0x40000000) < 0x10000000) {
+            ts = table_ident[(v & ~0x40000000) - 256];
+            if (v & 0x40000000)
+                ps = &ts->sym_struct;
+            else
+                ps = &ts->sym_identifier;
+            *ps = s->prev_tok;
+        }
+ if (!keep)
+     sym_free(s);
+        s = ss;
+    }
+    if (!keep)
+ *ptop = b;
+}
+
+
+
+static void vsetc(CType *type, int r, CValue *vc)
+{
+    int v;
+
+    if (vtop >= (__vstack + 1) + (256 - 1))
+        tcc_error("memory full (vstack)");
+# 649 "tccgen.c"
+    if (vtop >= (__vstack + 1) && !nocode_wanted) {
+        v = vtop->r & 0x003f;
+        if (v == 0x0033 || (v & ~1) == 0x0034)
+            gv(0x0001);
+    }
+
+    vtop++;
+    vtop->type = *type;
+    vtop->r = r;
+    vtop->r2 = 0x0030;
+    vtop->c = *vc;
+    vtop->sym = 0;
+}
+
+static void vswap(void)
+{
+    SValue tmp;
+
+    if (vtop >= (__vstack + 1) && !nocode_wanted) {
+        int v = vtop->r & 0x003f;
+        if (v == 0x0033 || (v & ~1) == 0x0034)
+            gv(0x0001);
+    }
+    tmp = vtop[0];
+    vtop[0] = vtop[-1];
+    vtop[-1] = tmp;
+}
+
+
+static void vpop(void)
+{
+    int v;
+    v = vtop->r & 0x003f;
+
+
+    if (v == TREG_ST0) {
+        o(0xd8dd);
+    } else
+
+    if (v == 0x0034 || v == 0x0035) {
+
+        gsym(vtop->c.i);
+    }
+    vtop--;
+}
+
+
+static void vpush(CType *type)
+{
+    vset(type, 0x0030, 0);
+}
+
+
+static void vpushi(int v)
+{
+    CValue cval;
+    cval.i = v;
+    vsetc(&int_type, 0x0030, &cval);
+}
+
+
+static void vpushs(Elf64_Addr v)
+{
+  CValue cval;
+  cval.i = v;
+  vsetc(&size_type, 0x0030, &cval);
+}
+
+
+static void vpush64(int ty, unsigned long long v)
+{
+    CValue cval;
+    CType ctype;
+    ctype.t = ty;
+    ctype.ref = 0;
+    cval.i = v;
+    vsetc(&ctype, 0x0030, &cval);
+}
+
+
+static inline void vpushll(long long v)
+{
+    vpush64(4, v);
+}
+
+static void vset(CType *type, int r, int v)
+{
+    CValue cval;
+
+    cval.i = v;
+    vsetc(type, r, &cval);
+}
+
+static void vseti(int r, int v)
+{
+    CType type;
+    type.t = 3;
+    type.ref = 0;
+    vset(&type, r, v);
+}
+
+static void vpushv(SValue *v)
+{
+    if (vtop >= (__vstack + 1) + (256 - 1))
+        tcc_error("memory full (vstack)");
+    vtop++;
+    *vtop = *v;
+}
+
+static void vdup(void)
+{
+    vpushv(vtop);
+}
+
+
+
+
+static void vrotb(int n)
+{
+    int i;
+    SValue tmp;
+
+    tmp = vtop[-n + 1];
+    for(i=-n+1;i!=0;i++)
+        vtop[i] = vtop[i+1];
+    vtop[0] = tmp;
+}
+
+
+
+
+static void vrote(SValue *e, int n)
+{
+    int i;
+    SValue tmp;
+
+    tmp = *e;
+    for(i = 0;i < n - 1; i++)
+        e[-i] = e[-i - 1];
+    e[-n + 1] = tmp;
+}
+
+
+
+
+static void vrott(int n)
+{
+    vrote(vtop, n);
+}
+
+
+static inline void vpushsym(CType *type, Sym *sym)
+{
+    CValue cval;
+    cval.i = 0;
+    vsetc(type, 0x0030 | 0x0200, &cval);
+    vtop->sym = sym;
+}
+
+
+static Sym *get_sym_ref(CType *type, Section *sec, unsigned long offset, unsigned long size)
+{
+    int v;
+    Sym *sym;
+
+    v = anon_sym++;
+    sym = global_identifier_push(v, type->t | 0x00002000, 0);
+    sym->type.ref = type->ref;
+    sym->r = 0x0030 | 0x0200;
+    put_extern_sym(sym, sec, offset, size);
+    return sym;
+}
+
+
+static void vpush_ref(CType *type, Section *sec, unsigned long offset, unsigned long size)
+{
+    vpushsym(type, get_sym_ref(type, sec, offset, size));
+}
+
+
+static Sym *external_global_sym(int v, CType *type, int r)
+{
+    Sym *s;
+
+    s = sym_find(v);
+    if (!s) {
+
+        s = global_identifier_push(v, type->t | 0x00001000, 0);
+        s->type.ref = type->ref;
+        s->r = r | 0x0030 | 0x0200;
+    } else if ((((s)->type.t & (0x000f | (0 | 0x0010))) == (0 | 0x0010))) {
+        s->type.t = type->t | (s->type.t & 0x00001000);
+        s->type.ref = type->ref;
+        update_storage(s);
+    }
+    return s;
+}
+
+
+static void patch_type(Sym *sym, CType *type)
+{
+    if (!(type->t & 0x00001000)) {
+        if (!(sym->type.t & 0x00001000))
+            tcc_error("redefinition of '%s'", get_tok_str(sym->v, 0));
+        sym->type.t &= ~0x00001000;
+    }
+
+    if ((((sym)->type.t & (0x000f | (0 | 0x0010))) == (0 | 0x0010))) {
+
+        sym->type.t = type->t & (sym->type.t | ~0x00002000);
+        sym->type.ref = type->ref;
+    }
+
+    if (!is_compatible_types(&sym->type, type)) {
+        tcc_error("incompatible types for redefinition of '%s'",
+                  get_tok_str(sym->v, 0));
+
+    } else if ((sym->type.t & 0x000f) == 6) {
+        int static_proto = sym->type.t & 0x00002000;
+
+        if ((type->t & 0x00002000) && !static_proto && !(type->t & 0x00008000))
+            tcc_warning("static storage ignored for redefinition of '%s'",
+                get_tok_str(sym->v, 0));
+
+        if (0 == (type->t & 0x00001000)) {
+
+            sym->type.t = (type->t & ~0x00002000) | static_proto;
+            if (type->t & 0x00008000)
+                sym->type.t = type->t;
+            sym->type.ref = type->ref;
+        }
+
+    } else {
+        if ((sym->type.t & 0x0040) && type->ref->c >= 0) {
+
+            if (sym->type.ref->c < 0)
+                sym->type.ref->c = type->ref->c;
+            else if (sym->type.ref->c != type->ref->c)
+                tcc_error("conflicting type for '%s'", get_tok_str(sym->v, 0));
+        }
+        if ((type->t ^ sym->type.t) & 0x00002000)
+            tcc_warning("storage mismatch for redefinition of '%s'",
+                get_tok_str(sym->v, 0));
+    }
+}
+
+
+
+static void patch_storage(Sym *sym, AttributeDef *ad, CType *type)
+{
+    if (type)
+        patch_type(sym, type);
+
+
+
+
+
+
+
+    sym->a.weak |= ad->a.weak;
+    if (ad->a.visibility) {
+        int vis = sym->a.visibility;
+        int vis2 = ad->a.visibility;
+        if (vis == 0)
+            vis = vis2;
+        else if (vis2 != 0)
+            vis = (vis < vis2) ? vis : vis2;
+        sym->a.visibility = vis;
+    }
+    if (ad->a.aligned)
+        sym->a.aligned = ad->a.aligned;
+    if (ad->asm_label)
+        sym->asm_label = ad->asm_label;
+    update_storage(sym);
+}
+
+
+static Sym *external_sym(int v, CType *type, int r, AttributeDef *ad)
+{
+    Sym *s;
+    s = sym_find(v);
+    if (!s) {
+
+        s = sym_push(v, type, r | 0x0030 | 0x0200, 0);
+        s->type.t |= 0x00001000;
+        s->a = ad->a;
+        s->sym_scope = 0;
+    } else {
+        if (s->type.ref == func_old_type.ref) {
+            s->type.ref = type->ref;
+            s->r = r | 0x0030 | 0x0200;
+            s->type.t |= 0x00001000;
+        }
+        patch_storage(s, ad, type);
+    }
+    return s;
+}
+
+
+static void vpush_global_sym(CType *type, int v)
+{
+    vpushsym(type, external_global_sym(v, type, 0));
+}
+
+
+static void save_regs(int n)
+{
+    SValue *p, *p1;
+    for(p = (__vstack + 1), p1 = vtop - n; p <= p1; p++)
+        save_reg(p->r);
+}
+
+
+static void save_reg(int r)
+{
+    save_reg_upstack(r, 0);
+}
+
+
+
+static void save_reg_upstack(int r, int n)
+{
+    int l, saved, size, align;
+    SValue *p, *p1, sv;
+    CType *type;
+
+    if ((r &= 0x003f) >= 0x0030)
+        return;
+    if (nocode_wanted)
+        return;
+
+
+    saved = 0;
+    l = 0;
+    for(p = (__vstack + 1), p1 = vtop - n; p <= p1; p++) {
+        if ((p->r & 0x003f) == r ||
+            ((p->type.t & 0x000f) == 4 && (p->r2 & 0x003f) == r)) {
+
+            if (!saved) {
+
+                r = p->r & 0x003f;
+
+                type = &p->type;
+                if ((p->r & 0x0100) ||
+                    (!is_float(type->t) && (type->t & 0x000f) != 4))
+
+                    type = &char_pointer_type;
+
+
+
+                size = type_size(type, &align);
+                loc = (loc - size) & -align;
+                sv.type.t = type->t;
+                sv.r = 0x0032 | 0x0100;
+                sv.c.i = loc;
+                store(r, &sv);
+
+
+                if (r == TREG_ST0) {
+                    o(0xd8dd);
+                }
+# 1018 "tccgen.c"
+                l = loc;
+                saved = 1;
+            }
+
+            if (p->r & 0x0100) {
+
+
+
+                p->r = (p->r & ~(0x003f | 0x8000)) | 0x0031;
+            } else {
+                p->r = lvalue_type(p->type.t) | 0x0032;
+            }
+            p->r2 = 0x0030;
+            p->c.i = l;
+        }
+    }
+}
+# 1062 "tccgen.c"
+static int get_reg(int rc)
+{
+    int r;
+    SValue *p;
+
+
+    for(r=0;r<25;r++) {
+        if (reg_classes[r] & rc) {
+            if (nocode_wanted)
+                return r;
+            for(p=(__vstack + 1);p<=vtop;p++) {
+                if ((p->r & 0x003f) == r ||
+                    (p->r2 & 0x003f) == r)
+                    goto notfound;
+            }
+            return r;
+        }
+    notfound: ;
+    }
+
+
+
+
+    for(p=(__vstack + 1);p<=vtop;p++) {
+
+        r = p->r2 & 0x003f;
+        if (r < 0x0030 && (reg_classes[r] & rc))
+            goto save_found;
+        r = p->r & 0x003f;
+        if (r < 0x0030 && (reg_classes[r] & rc)) {
+        save_found:
+            save_reg(r);
+            return r;
+        }
+    }
+
+    return -1;
+}
+
+
+
+static void move_reg(int r, int s, int t)
+{
+    SValue sv;
+
+    if (r != s) {
+        save_reg(r);
+        sv.type.t = t;
+        sv.type.ref = 0;
+        sv.r = s;
+        sv.c.i = 0;
+        load(r, &sv);
+    }
+}
+
+
+static void gaddrof(void)
+{
+    vtop->r &= ~0x0100;
+
+    if ((vtop->r & 0x003f) == 0x0031)
+        vtop->r = (vtop->r & ~(0x003f | (0x1000 | 0x2000 | 0x4000))) | 0x0032 | 0x0100;
+
+
+}
+
+
+
+static void gbound(void)
+{
+    int lval_type;
+    CType type1;
+
+    vtop->r &= ~0x0800;
+
+    if (vtop->r & 0x0100) {
+
+        if (!(vtop->r & 0x8000)) {
+            lval_type = vtop->r & ((0x1000 | 0x2000 | 0x4000) | 0x0100);
+
+            type1 = vtop->type;
+            vtop->type.t = 5;
+            gaddrof();
+            vpushi(0);
+            gen_bounded_ptr_add();
+            vtop->r |= lval_type;
+            vtop->type = type1;
+        }
+
+        gen_bounded_ptr_deref();
+    }
+}
+
+
+static void incr_bf_adr(int o)
+{
+    vtop->type = char_pointer_type;
+    gaddrof();
+    vpushi(o);
+    gen_op('+');
+    vtop->type.t = (vtop->type.t & ~(0x000f|0x0020))
+        | (1|0x0010);
+    vtop->r = (vtop->r & ~(0x1000 | 0x2000 | 0x4000))
+        | (0x1000|0x4000|0x0100);
+}
+
+
+static void load_packed_bf(CType *type, int bit_pos, int bit_size)
+{
+    int n, o, bits;
+    save_reg_upstack(vtop->r, 1);
+    vpush64(type->t & 0x000f, 0);
+    bits = 0, o = bit_pos >> 3, bit_pos &= 7;
+    do {
+        vswap();
+        incr_bf_adr(o);
+        vdup();
+        n = 8 - bit_pos;
+        if (n > bit_size)
+            n = bit_size;
+        if (bit_pos)
+            vpushi(bit_pos), gen_op(0xc9), bit_pos = 0;
+        if (n < 8)
+            vpushi((1 << n) - 1), gen_op('&');
+        gen_cast(type);
+        if (bits)
+            vpushi(bits), gen_op(0x01);
+        vrotb(3);
+        gen_op('|');
+        bits += n, bit_size -= n, o = 1;
+    } while (bit_size);
+    vswap(), vpop();
+    if (!(type->t & 0x0010)) {
+        n = ((type->t & 0x000f) == 4 ? 64 : 32) - bits;
+        vpushi(n), gen_op(0x01);
+        vpushi(n), gen_op(0x02);
+    }
+}
+
+
+static void store_packed_bf(int bit_pos, int bit_size)
+{
+    int bits, n, o, m, c;
+
+    c = (vtop->r & (0x003f | 0x0100 | 0x0200)) == 0x0030;
+    vswap();
+    save_reg_upstack(vtop->r, 1);
+    bits = 0, o = bit_pos >> 3, bit_pos &= 7;
+    do {
+        incr_bf_adr(o);
+        vswap();
+        c ? vdup() : gv_dup();
+        vrott(3);
+        if (bits)
+            vpushi(bits), gen_op(0xc9);
+        if (bit_pos)
+            vpushi(bit_pos), gen_op(0x01);
+        n = 8 - bit_pos;
+        if (n > bit_size)
+            n = bit_size;
+        if (n < 8) {
+            m = ((1 << n) - 1) << bit_pos;
+            vpushi(m), gen_op('&');
+            vpushv(vtop-1);
+            vpushi(m & 0x80 ? ~m & 0x7f : ~m);
+            gen_op('&');
+            gen_op('|');
+        }
+        vdup(), vtop[-1] = vtop[-2];
+        vstore(), vpop();
+        bits += n, bit_size -= n, bit_pos = 0, o = 1;
+    } while (bit_size);
+    vpop(), vpop();
+}
+
+static int adjust_bf(SValue *sv, int bit_pos, int bit_size)
+{
+    int t;
+    if (0 == sv->type.ref)
+        return 0;
+    t = sv->type.ref->auxtype;
+    if (t != -1 && t != 7) {
+        sv->type.t = (sv->type.t & ~0x000f) | t;
+        sv->r = (sv->r & ~(0x1000 | 0x2000 | 0x4000)) | lvalue_type(sv->type.t);
+    }
+    return t;
+}
+
+
+
+
+static int gv(int rc)
+{
+    int r, bit_pos, bit_size, size, align, rc2;
+
+
+    if (vtop->type.t & 0x0080) {
+        CType type;
+
+        bit_pos = (((vtop->type.t) >> 20) & 0x3f);
+        bit_size = (((vtop->type.t) >> (20 + 6)) & 0x3f);
+
+        vtop->type.t &= ~(((1 << (6+6)) - 1) << 20 | 0x0080);
+
+        type.ref = 0;
+        type.t = vtop->type.t & 0x0010;
+        if ((vtop->type.t & 0x000f) == 11)
+            type.t |= 0x0010;
+
+        r = adjust_bf(vtop, bit_pos, bit_size);
+
+        if ((vtop->type.t & 0x000f) == 4)
+            type.t |= 4;
+        else
+            type.t |= 3;
+
+        if (r == 7) {
+            load_packed_bf(&type, bit_pos, bit_size);
+        } else {
+            int bits = (type.t & 0x000f) == 4 ? 64 : 32;
+
+            gen_cast(&type);
+
+            vpushi(bits - (bit_pos + bit_size));
+            gen_op(0x01);
+            vpushi(bits - bit_size);
+
+            gen_op(0x02);
+        }
+        r = gv(rc);
+    } else {
+        if (is_float(vtop->type.t) &&
+            (vtop->r & (0x003f | 0x0100)) == 0x0030) {
+            unsigned long offset;
+
+
+            size = type_size(&vtop->type, &align);
+            if ((nocode_wanted > 0))
+                size = 0, align = 1;
+            offset = section_add(data_section, size, align);
+            vpush_ref(&vtop->type, data_section, offset, size);
+     vswap();
+     init_putv(&vtop->type, data_section, offset);
+     vtop->r |= 0x0100;
+        }
+
+        if (vtop->r & 0x0800)
+            gbound();
+
+
+        r = vtop->r & 0x003f;
+        rc2 = (rc & 0x0002) ? 0x0002 : 0x0001;
+
+        if (rc == 0x0004)
+            rc2 = 0x0010;
+
+        else if (rc == 0x1000)
+            rc2 = 0x2000;
+
+
+
+
+
+
+        if (r >= 0x0030
+         || (vtop->r & 0x0100)
+         || !(reg_classes[r] & rc)
+
+         || ((vtop->type.t & 0x000f) == 13 && !(reg_classes[vtop->r2] & rc2))
+         || ((vtop->type.t & 0x000f) == 14 && !(reg_classes[vtop->r2] & rc2))
+
+
+
+            )
+        {
+            r = get_reg(rc);
+
+            if (((vtop->type.t & 0x000f) == 13) || ((vtop->type.t & 0x000f) == 14)) {
+                int addr_type = 4, load_size = 8, load_type = ((vtop->type.t & 0x000f) == 13) ? 4 : 9;
+
+
+
+
+
+                int r2, original_type;
+                original_type = vtop->type.t;
+# 1360 "tccgen.c"
+                if (vtop->r & 0x0100) {
+# 1369 "tccgen.c"
+                    save_reg_upstack(vtop->r, 1);
+
+
+                    vtop->type.t = load_type;
+                    load(r, vtop);
+                    vdup();
+                    vtop[-1].r = r;
+
+                    vtop->type.t = addr_type;
+                    gaddrof();
+                    vpushi(load_size);
+                    gen_op('+');
+                    vtop->r |= 0x0100;
+                    vtop->type.t = load_type;
+                } else {
+
+                    load(r, vtop);
+                    vdup();
+                    vtop[-1].r = r;
+                    vtop->r = vtop[-1].r2;
+                }
+
+
+                r2 = get_reg(rc2);
+                load(r2, vtop);
+                vpop();
+
+                vtop->r2 = r2;
+                vtop->type.t = original_type;
+            } else if ((vtop->r & 0x0100) && !is_float(vtop->type.t)) {
+                int t1, t;
+
+
+                t = vtop->type.t;
+                t1 = t;
+
+                if (vtop->r & 0x1000)
+                    t = 1;
+                else if (vtop->r & 0x2000)
+                    t = 2;
+                if (vtop->r & 0x4000)
+                    t |= 0x0010;
+                vtop->type.t = t;
+                load(r, vtop);
+
+                vtop->type.t = t1;
+            } else {
+
+                load(r, vtop);
+            }
+        }
+        vtop->r = r;
+
+
+
+
+
+    }
+    return r;
+}
+
+
+static void gv2(int rc1, int rc2)
+{
+    int v;
+
+
+
+
+    v = vtop[0].r & 0x003f;
+    if (v != 0x0033 && (v & ~1) != 0x0034 && rc1 <= rc2) {
+        vswap();
+        gv(rc1);
+        vswap();
+        gv(rc2);
+
+        if ((vtop[-1].r & 0x003f) >= 0x0030) {
+            vswap();
+            gv(rc1);
+            vswap();
+        }
+    } else {
+        gv(rc2);
+        vswap();
+        gv(rc1);
+        vswap();
+
+        if ((vtop[0].r & 0x003f) >= 0x0030) {
+            gv(rc2);
+        }
+    }
+}
+
+
+
+static int rc_fret(int t)
+{
+
+    if (t == 10) {
+        return 0x0080;
+    }
+
+    return 0x1000;
+}
+
+
+
+static int reg_fret(int t)
+{
+
+    if (t == 10) {
+        return TREG_ST0;
+    }
+
+    return TREG_XMM0;
+}
+# 1550 "tccgen.c"
+static void gv_dup(void)
+{
+    int rc, t, r, r1;
+    SValue sv;
+
+    t = vtop->type.t;
+# 1577 "tccgen.c"
+    {
+
+        rc = 0x0001;
+        sv.type.t = 3;
+        if (is_float(t)) {
+            rc = 0x0002;
+
+            if ((t & 0x000f) == 10) {
+                rc = 0x0080;
+            }
+
+            sv.type.t = t;
+        }
+        r = gv(rc);
+        r1 = get_reg(rc);
+        sv.r = r;
+        sv.c.i = 0;
+        load(r1, &sv);
+        vdup();
+
+        if (r != r1)
+            vtop->r = r1;
+    }
+}
+
+
+
+
+static int gvtst(int inv, int t)
+{
+    int v = vtop->r & 0x003f;
+    if (v != 0x0033 && v != 0x0034 && v != 0x0035) {
+        vpushi(0);
+        gen_op(0x95);
+    }
+    if ((vtop->r & (0x003f | 0x0100 | 0x0200)) == 0x0030) {
+
+        if ((vtop->c.i != 0) != inv)
+            t = gjmp(t);
+        vtop--;
+        return t;
+    }
+    return gtst(inv, t);
+}
+# 1851 "tccgen.c"
+static uint64_t gen_opic_sdiv(uint64_t a, uint64_t b)
+{
+    uint64_t x = (a >> 63 ? -a : a) / (b >> 63 ? -b : b);
+    return (a ^ b) >> 63 ? -x : x;
+}
+
+static int gen_opic_lt(uint64_t a, uint64_t b)
+{
+    return (a ^ (uint64_t)1 << 63) < (b ^ (uint64_t)1 << 63);
+}
+
+
+
+static void gen_opic(int op)
+{
+    SValue *v1 = vtop - 1;
+    SValue *v2 = vtop;
+    int t1 = v1->type.t & 0x000f;
+    int t2 = v2->type.t & 0x000f;
+    int c1 = (v1->r & (0x003f | 0x0100 | 0x0200)) == 0x0030;
+    int c2 = (v2->r & (0x003f | 0x0100 | 0x0200)) == 0x0030;
+    uint64_t l1 = c1 ? v1->c.i : 0;
+    uint64_t l2 = c2 ? v2->c.i : 0;
+    int shm = (t1 == 4) ? 63 : 31;
+
+    if (t1 != 4 && (8 != 8 || t1 != 5))
+        l1 = ((uint32_t)l1 |
+              (v1->type.t & 0x0010 ? 0 : -(l1 & 0x80000000)));
+    if (t2 != 4 && (8 != 8 || t2 != 5))
+        l2 = ((uint32_t)l2 |
+              (v2->type.t & 0x0010 ? 0 : -(l2 & 0x80000000)));
+
+    if (c1 && c2) {
+        switch(op) {
+        case '+': l1 += l2; break;
+        case '-': l1 -= l2; break;
+        case '&': l1 &= l2; break;
+        case '^': l1 ^= l2; break;
+        case '|': l1 |= l2; break;
+        case '*': l1 *= l2; break;
+
+        case 0xb2:
+        case '/':
+        case '%':
+        case 0xb0:
+        case 0xb1:
+
+            if (l2 == 0) {
+                if (const_wanted)
+                    tcc_error("division by zero in constant");
+                goto general_case;
+            }
+            switch(op) {
+            default: l1 = gen_opic_sdiv(l1, l2); break;
+            case '%': l1 = l1 - l2 * gen_opic_sdiv(l1, l2); break;
+            case 0xb0: l1 = l1 / l2; break;
+            case 0xb1: l1 = l1 % l2; break;
+            }
+            break;
+        case 0x01: l1 <<= (l2 & shm); break;
+        case 0xc9: l1 >>= (l2 & shm); break;
+        case 0x02:
+            l1 = (l1 >> 63) ? ~(~l1 >> (l2 & shm)) : l1 >> (l2 & shm);
+            break;
+
+        case 0x92: l1 = l1 < l2; break;
+        case 0x93: l1 = l1 >= l2; break;
+        case 0x94: l1 = l1 == l2; break;
+        case 0x95: l1 = l1 != l2; break;
+        case 0x96: l1 = l1 <= l2; break;
+        case 0x97: l1 = l1 > l2; break;
+        case 0x9c: l1 = gen_opic_lt(l1, l2); break;
+        case 0x9d: l1 = !gen_opic_lt(l1, l2); break;
+        case 0x9e: l1 = !gen_opic_lt(l2, l1); break;
+        case 0x9f: l1 = gen_opic_lt(l2, l1); break;
+
+        case 0xa0: l1 = l1 && l2; break;
+        case 0xa1: l1 = l1 || l2; break;
+        default:
+            goto general_case;
+        }
+ if (t1 != 4 && (8 != 8 || t1 != 5))
+     l1 = ((uint32_t)l1 |
+  (v1->type.t & 0x0010 ? 0 : -(l1 & 0x80000000)));
+        v1->c.i = l1;
+        vtop--;
+    } else {
+
+        if (c1 && (op == '+' || op == '&' || op == '^' ||
+                   op == '|' || op == '*')) {
+            vswap();
+            c2 = c1;
+            l2 = l1;
+        }
+        if (!const_wanted &&
+            c1 && ((l1 == 0 &&
+                    (op == 0x01 || op == 0xc9 || op == 0x02)) ||
+                   (l1 == -1 && op == 0x02))) {
+
+            vtop--;
+        } else if (!const_wanted &&
+                   c2 && ((l2 == 0 && (op == '&' || op == '*')) ||
+                          (op == '|' &&
+                            (l2 == -1 || (l2 == 0xFFFFFFFF && t2 != 4))) ||
+                          (l2 == 1 && (op == '%' || op == 0xb1)))) {
+
+            if (l2 == 1)
+                vtop->c.i = 0;
+            vswap();
+            vtop--;
+        } else if (c2 && (((op == '*' || op == '/' || op == 0xb0 ||
+                          op == 0xb2) &&
+                           l2 == 1) ||
+                          ((op == '+' || op == '-' || op == '|' || op == '^' ||
+                            op == 0x01 || op == 0xc9 || op == 0x02) &&
+                           l2 == 0) ||
+                          (op == '&' &&
+                            (l2 == -1 || (l2 == 0xFFFFFFFF && t2 != 4))))) {
+
+            vtop--;
+        } else if (c2 && (op == '*' || op == 0xb2 || op == 0xb0)) {
+
+            if (l2 > 0 && (l2 & (l2 - 1)) == 0) {
+                int n = -1;
+                while (l2) {
+                    l2 >>= 1;
+                    n++;
+                }
+                vtop->c.i = n;
+                if (op == '*')
+                    op = 0x01;
+                else if (op == 0xb2)
+                    op = 0x02;
+                else
+                    op = 0xc9;
+            }
+            goto general_case;
+        } else if (c2 && (op == '+' || op == '-') &&
+                   (((vtop[-1].r & (0x003f | 0x0100 | 0x0200)) == (0x0030 | 0x0200))
+                    || (vtop[-1].r & (0x003f | 0x0100)) == 0x0032)) {
+
+            if (op == '-')
+                l2 = -l2;
+     l2 += vtop[-1].c.i;
+
+
+     if ((int)l2 != l2)
+         goto general_case;
+            vtop--;
+            vtop->c.i = l2;
+        } else {
+        general_case:
+
+                if (t1 == 4 || t2 == 4 ||
+                    (8 == 8 && (t1 == 5 || t2 == 5)))
+                    gen_opl(op);
+                else
+                    gen_opi(op);
+        }
+    }
+}
+
+
+static void gen_opif(int op)
+{
+    int c1, c2;
+    SValue *v1, *v2;
+
+
+
+
+    long double f1, f2;
+
+    v1 = vtop - 1;
+    v2 = vtop;
+
+    c1 = (v1->r & (0x003f | 0x0100 | 0x0200)) == 0x0030;
+    c2 = (v2->r & (0x003f | 0x0100 | 0x0200)) == 0x0030;
+    if (c1 && c2) {
+        if (v1->type.t == 8) {
+            f1 = v1->c.f;
+            f2 = v2->c.f;
+        } else if (v1->type.t == 9) {
+            f1 = v1->c.d;
+            f2 = v2->c.d;
+        } else {
+            f1 = v1->c.ld;
+            f2 = v2->c.ld;
+        }
+
+
+
+        if (!ieee_finite(f1) || !ieee_finite(f2))
+            goto general_case;
+
+        switch(op) {
+        case '+': f1 += f2; break;
+        case '-': f1 -= f2; break;
+        case '*': f1 *= f2; break;
+        case '/':
+            if (f2 == 0.0) {
+                if (const_wanted)
+                    tcc_error("division by zero in constant");
+                goto general_case;
+            }
+            f1 /= f2;
+            break;
+
+        default:
+            goto general_case;
+        }
+
+        if (v1->type.t == 8) {
+            v1->c.f = f1;
+        } else if (v1->type.t == 9) {
+            v1->c.d = f1;
+        } else {
+            v1->c.ld = f1;
+        }
+        vtop--;
+    } else {
+    general_case:
+        gen_opf(op);
+    }
+}
+
+static int pointed_size(CType *type)
+{
+    int align;
+    return type_size(pointed_type(type), &align);
+}
+
+static void vla_runtime_pointed_size(CType *type)
+{
+    int align;
+    vla_runtime_type_size(pointed_type(type), &align);
+}
+
+static inline int is_null_pointer(SValue *p)
+{
+    if ((p->r & (0x003f | 0x0100 | 0x0200)) != 0x0030)
+        return 0;
+    return ((p->type.t & 0x000f) == 3 && (uint32_t)p->c.i == 0) ||
+        ((p->type.t & 0x000f) == 4 && p->c.i == 0) ||
+        ((p->type.t & 0x000f) == 5 &&
+         (8 == 4 ? (uint32_t)p->c.i == 0 : p->c.i == 0));
+}
+
+static inline int is_integer_btype(int bt)
+{
+    return (bt == 1 || bt == 2 ||
+            bt == 3 || bt == 4);
+}
+
+
+static void check_comparison_pointer_types(SValue *p1, SValue *p2, int op)
+{
+    CType *type1, *type2, tmp_type1, tmp_type2;
+    int bt1, bt2;
+
+
+    if (is_null_pointer(p1) || is_null_pointer(p2))
+        return;
+    type1 = &p1->type;
+    type2 = &p2->type;
+    bt1 = type1->t & 0x000f;
+    bt2 = type2->t & 0x000f;
+
+    if ((is_integer_btype(bt1) || is_integer_btype(bt2)) && op != '-') {
+        if (op != 0xa1 && op != 0xa0 )
+            tcc_warning("comparison between pointer and integer");
+        return;
+    }
+
+
+    if (bt1 == 5) {
+        type1 = pointed_type(type1);
+    } else if (bt1 != 6)
+        goto invalid_operands;
+
+    if (bt2 == 5) {
+        type2 = pointed_type(type2);
+    } else if (bt2 != 6) {
+    invalid_operands:
+        tcc_error("invalid operands to binary %s", get_tok_str(op, 0));
+    }
+    if ((type1->t & 0x000f) == 0 ||
+        (type2->t & 0x000f) == 0)
+        return;
+    tmp_type1 = *type1;
+    tmp_type2 = *type2;
+    tmp_type1.t &= ~(0x0020 | 0x0010 | 0x0100 | 0x0200);
+    tmp_type2.t &= ~(0x0020 | 0x0010 | 0x0100 | 0x0200);
+    if (!is_compatible_types(&tmp_type1, &tmp_type2)) {
+
+        if (op == '-')
+            goto invalid_operands;
+        else
+            tcc_warning("comparison of distinct pointer types lacks a cast");
+    }
+}
+
+
+static void gen_op(int op)
+{
+    int u, t1, t2, bt1, bt2, t;
+    CType type1;
+
+redo:
+    t1 = vtop[-1].type.t;
+    t2 = vtop[0].type.t;
+    bt1 = t1 & 0x000f;
+    bt2 = t2 & 0x000f;
+
+    if (bt1 == 7 || bt2 == 7) {
+        tcc_error("operation on a struct");
+    } else if (bt1 == 6 || bt2 == 6) {
+ if (bt2 == 6) {
+     mk_pointer(&vtop->type);
+     gaddrof();
+ }
+ if (bt1 == 6) {
+     vswap();
+     mk_pointer(&vtop->type);
+     gaddrof();
+     vswap();
+ }
+ goto redo;
+    } else if (bt1 == 5 || bt2 == 5) {
+
+
+        if (op >= 0x92 && op <= 0xa1) {
+            check_comparison_pointer_types(vtop - 1, vtop, op);
+
+
+            t = 4 | 0x0010;
+
+
+
+            goto std_op;
+        }
+
+        if (bt1 == 5 && bt2 == 5) {
+            if (op != '-')
+                tcc_error("cannot use pointers here");
+            check_comparison_pointer_types(vtop - 1, vtop, op);
+
+            if (vtop[-1].type.t & 0x0400) {
+                vla_runtime_pointed_size(&vtop[-1].type);
+            } else {
+                vpushi(pointed_size(&vtop[-1].type));
+            }
+            vrott(3);
+            gen_opic(op);
+            vtop->type.t = ptrdiff_type.t;
+            vswap();
+            gen_op(0xb2);
+        } else {
+
+            if (op != '-' && op != '+')
+                tcc_error("cannot use pointers here");
+
+            if (bt2 == 5) {
+                vswap();
+                t = t1, t1 = t2, t2 = t;
+            }
+
+
+
+
+
+            type1 = vtop[-1].type;
+            type1.t &= ~0x0040;
+            if (vtop[-1].type.t & 0x0400)
+                vla_runtime_pointed_size(&vtop[-1].type);
+            else {
+                u = pointed_size(&vtop[-1].type);
+                if (u < 0)
+                    tcc_error("unknown array element size");
+
+                vpushll(u);
+
+
+
+
+            }
+            gen_op('*');
+# 2267 "tccgen.c"
+            {
+                gen_opic(op);
+            }
+
+            vtop->type = type1;
+        }
+    } else if (is_float(bt1) || is_float(bt2)) {
+
+        if (bt1 == 10 || bt2 == 10) {
+            t = 10;
+        } else if (bt1 == 9 || bt2 == 9) {
+            t = 9;
+        } else {
+            t = 8;
+        }
+
+        if (op != '+' && op != '-' && op != '*' && op != '/' &&
+            (op < 0x92 || op > 0x9f))
+            tcc_error("invalid operands for binary operation");
+        goto std_op;
+    } else if (op == 0xc9 || op == 0x02 || op == 0x01) {
+        t = bt1 == 4 ? 4 : 3;
+        if ((t1 & (0x000f | 0x0010 | 0x0080)) == (t | 0x0010))
+          t |= 0x0010;
+        t |= (0x0800 & t1);
+        goto std_op;
+    } else if (bt1 == 4 || bt2 == 4) {
+
+        t = 4 | 0x0800;
+        if (bt1 == 4)
+            t &= t1;
+        if (bt2 == 4)
+            t &= t2;
+
+        if ((t1 & (0x000f | 0x0010 | 0x0080)) == (4 | 0x0010) ||
+            (t2 & (0x000f | 0x0010 | 0x0080)) == (4 | 0x0010))
+            t |= 0x0010;
+        goto std_op;
+    } else {
+
+        t = 3 | (0x0800 & (t1 | t2));
+
+        if ((t1 & (0x000f | 0x0010 | 0x0080)) == (3 | 0x0010) ||
+            (t2 & (0x000f | 0x0010 | 0x0080)) == (3 | 0x0010))
+            t |= 0x0010;
+    std_op:
+
+
+        if (t & 0x0010) {
+            if (op == 0x02)
+                op = 0xc9;
+            else if (op == '/')
+                op = 0xb0;
+            else if (op == '%')
+                op = 0xb1;
+            else if (op == 0x9c)
+                op = 0x92;
+            else if (op == 0x9f)
+                op = 0x97;
+            else if (op == 0x9e)
+                op = 0x96;
+            else if (op == 0x9d)
+                op = 0x93;
+        }
+        vswap();
+        type1.t = t;
+        type1.ref = 0;
+        gen_cast(&type1);
+        vswap();
+
+
+        if (op == 0xc9 || op == 0x02 || op == 0x01)
+            type1.t = 3;
+        gen_cast(&type1);
+        if (is_float(t))
+            gen_opif(op);
+        else
+            gen_opic(op);
+        if (op >= 0x92 && op <= 0x9f) {
+
+            vtop->type.t = 3;
+        } else {
+            vtop->type.t = t;
+        }
+    }
+
+    if (vtop->r & 0x0100)
+        gv(is_float(vtop->type.t & 0x000f) ? 0x0002 : 0x0001);
+}
+
+
+
+static void gen_cvt_itof1(int t)
+{
+
+
+
+    if ((vtop->type.t & (0x000f | 0x0010)) ==
+        (4 | 0x0010)) {
+
+        if (t == 8)
+            vpush_global_sym(&func_old_type, TOK___floatundisf);
+
+        else if (t == 10)
+            vpush_global_sym(&func_old_type, TOK___floatundixf);
+
+        else
+            vpush_global_sym(&func_old_type, TOK___floatundidf);
+        vrott(2);
+        gfunc_call(1);
+        vpushi(0);
+        vtop->r = reg_fret(t);
+    } else {
+        gen_cvt_itof(t);
+    }
+
+}
+
+
+
+static void gen_cvt_ftoi1(int t)
+{
+
+
+
+    int st;
+
+    if (t == (4 | 0x0010)) {
+
+        st = vtop->type.t & 0x000f;
+        if (st == 8)
+            vpush_global_sym(&func_old_type, TOK___fixunssfdi);
+
+        else if (st == 10)
+            vpush_global_sym(&func_old_type, TOK___fixunsxfdi);
+
+        else
+            vpush_global_sym(&func_old_type, TOK___fixunsdfdi);
+        vrott(2);
+        gfunc_call(1);
+        vpushi(0);
+        vtop->r = TREG_RAX;
+        vtop->r2 = TREG_RDX;
+    } else {
+        gen_cvt_ftoi(t);
+    }
+
+}
+
+
+static void force_charshort_cast(int t)
+{
+    int bits, dbt;
+
+
+    if ((nocode_wanted & 0xC0000000))
+ return;
+
+    dbt = t & 0x000f;
+
+    if (dbt == 1)
+        bits = 8;
+    else
+        bits = 16;
+    if (t & 0x0010) {
+        vpushi((1 << bits) - 1);
+        gen_op('&');
+    } else {
+        if ((vtop->type.t & 0x000f) == 4)
+            bits = 64 - bits;
+        else
+            bits = 32 - bits;
+        vpushi(bits);
+        gen_op(0x01);
+
+
+
+        vtop->type.t &= ~0x0010;
+        vpushi(bits);
+        gen_op(0x02);
+    }
+}
+
+
+static void gen_cast_s(int t)
+{
+    CType type;
+    type.t = t;
+    type.ref = 0;
+    gen_cast(&type);
+}
+
+static void gen_cast(CType *type)
+{
+    int sbt, dbt, sf, df, c, p;
+
+
+
+
+    if (vtop->r & 0x0400) {
+        vtop->r &= ~0x0400;
+        force_charshort_cast(vtop->type.t);
+    }
+
+
+    if (vtop->type.t & 0x0080) {
+        gv(0x0001);
+    }
+
+    dbt = type->t & (0x000f | 0x0010);
+    sbt = vtop->type.t & (0x000f | 0x0010);
+
+    if (sbt != dbt) {
+        sf = is_float(sbt);
+        df = is_float(dbt);
+        c = (vtop->r & (0x003f | 0x0100 | 0x0200)) == 0x0030;
+        p = (vtop->r & (0x003f | 0x0100 | 0x0200)) == (0x0030 | 0x0200);
+
+
+
+        if (c) {
+
+
+            if (sbt == 8)
+                vtop->c.ld = vtop->c.f;
+            else if (sbt == 9)
+                vtop->c.ld = vtop->c.d;
+
+            if (df) {
+                if ((sbt & 0x000f) == 4) {
+                    if ((sbt & 0x0010) || !(vtop->c.i >> 63))
+                        vtop->c.ld = vtop->c.i;
+                    else
+                        vtop->c.ld = -(long double)-vtop->c.i;
+                } else if(!sf) {
+                    if ((sbt & 0x0010) || !(vtop->c.i >> 31))
+                        vtop->c.ld = (uint32_t)vtop->c.i;
+                    else
+                        vtop->c.ld = -(long double)-(uint32_t)vtop->c.i;
+                }
+
+                if (dbt == 8)
+                    vtop->c.f = (float)vtop->c.ld;
+                else if (dbt == 9)
+                    vtop->c.d = (double)vtop->c.ld;
+            } else if (sf && dbt == (4|0x0010)) {
+                vtop->c.i = vtop->c.ld;
+            } else if (sf && dbt == 11) {
+                vtop->c.i = (vtop->c.ld != 0);
+            } else {
+                if(sf)
+                    vtop->c.i = vtop->c.ld;
+                else if (sbt == (4|0x0010))
+                    ;
+                else if (sbt & 0x0010)
+                    vtop->c.i = (uint32_t)vtop->c.i;
+
+                else if (sbt == 5)
+                    ;
+
+                else if (sbt != 4)
+                    vtop->c.i = ((uint32_t)vtop->c.i |
+                                  -(vtop->c.i & 0x80000000));
+
+                if (dbt == (4|0x0010))
+                    ;
+                else if (dbt == 11)
+                    vtop->c.i = (vtop->c.i != 0);
+
+                else if (dbt == 5)
+                    ;
+
+                else if (dbt != 4) {
+                    uint32_t m = ((dbt & 0x000f) == 1 ? 0xff :
+                                  (dbt & 0x000f) == 2 ? 0xffff :
+                                  0xffffffff);
+                    vtop->c.i &= m;
+                    if (!(dbt & 0x0010))
+                        vtop->c.i |= -(vtop->c.i & ((m >> 1) + 1));
+                }
+            }
+        } else if (p && dbt == 11) {
+            vtop->r = 0x0030;
+            vtop->c.i = 1;
+        } else {
+
+            if (sf && df) {
+
+                gen_cvt_ftof(dbt);
+            } else if (df) {
+
+                gen_cvt_itof1(dbt);
+            } else if (sf) {
+
+                if (dbt == 11) {
+                     vpushi(0);
+                     gen_op(0x95);
+                } else {
+
+                    if (dbt != (3 | 0x0010) &&
+                        dbt != (4 | 0x0010) &&
+                        dbt != 4)
+                        dbt = 3;
+                    gen_cvt_ftoi1(dbt);
+                    if (dbt == 3 && (type->t & (0x000f | 0x0010)) != dbt) {
+
+                        vtop->type.t = dbt;
+                        gen_cast(type);
+                    }
+                }
+# 2602 "tccgen.c"
+            } else if ((dbt & 0x000f) == 4 ||
+                       (dbt & 0x000f) == 5 ||
+                       (dbt & 0x000f) == 6) {
+                if ((sbt & 0x000f) != 4 &&
+                    (sbt & 0x000f) != 5 &&
+                    (sbt & 0x000f) != 6) {
+
+                    gv(0x0001);
+                    if (sbt != (3 | 0x0010)) {
+
+
+
+                        int r = gv(0x0001);
+
+                        o(0x6348);
+                        o(0xc0 + (((r) & 7) << 3) + ((r) & 7));
+
+
+
+                    }
+                }
+
+            } else if (dbt == 11) {
+
+                vpushi(0);
+                gen_op(0x95);
+            } else if ((dbt & 0x000f) == 1 ||
+                       (dbt & 0x000f) == 2) {
+                if (sbt == 5) {
+                    vtop->type.t = 3;
+                    tcc_warning("nonportable conversion from pointer to char/short");
+                }
+                force_charshort_cast(dbt);
+# 2647 "tccgen.c"
+            }
+        }
+    } else if ((dbt & 0x000f) == 5 && !(vtop->r & 0x0100)) {
+
+
+        vtop->r = (vtop->r & ~(0x1000 | 0x2000 | 0x4000))
+                  | (lvalue_type(type->ref->type.t) & (0x1000 | 0x2000 | 0x4000));
+    }
+    vtop->type = *type;
+}
+
+
+static int type_size(CType *type, int *a)
+{
+    Sym *s;
+    int bt;
+
+    bt = type->t & 0x000f;
+    if (bt == 7) {
+
+        s = type->ref;
+        *a = s->r;
+        return s->c;
+    } else if (bt == 5) {
+        if (type->t & 0x0040) {
+            int ts;
+
+            s = type->ref;
+            ts = type_size(&s->type, a);
+
+            if (ts < 0 && s->c < 0)
+                ts = -ts;
+
+            return ts * s->c;
+        } else {
+            *a = 8;
+            return 8;
+        }
+    } else if (((type->t & (((1 << (6+6)) - 1) << 20 | 0x0080)) == (2 << 20)) && type->ref->c == -1) {
+        return -1;
+    } else if (bt == 10) {
+        *a = 16;
+        return 16;
+    } else if (bt == 9 || bt == 4) {
+# 2704 "tccgen.c"
+        *a = 8;
+
+        return 8;
+    } else if (bt == 3 || bt == 8) {
+        *a = 4;
+        return 4;
+    } else if (bt == 2) {
+        *a = 2;
+        return 2;
+    } else if (bt == 13 || bt == 14) {
+        *a = 8;
+        return 16;
+    } else {
+
+        *a = 1;
+        return 1;
+    }
+}
+
+
+
+static void vla_runtime_type_size(CType *type, int *a)
+{
+    if (type->t & 0x0400) {
+        type_size(&type->ref->type, a);
+        vset(&int_type, 0x0032|0x0100, type->ref->c);
+    } else {
+        vpushi(type_size(type, a));
+    }
+}
+
+static void vla_sp_restore(void) {
+    if (vlas_in_scope) {
+        gen_vla_sp_restore(vla_sp_loc);
+    }
+}
+
+static void vla_sp_restore_root(void) {
+    if (vlas_in_scope) {
+        gen_vla_sp_restore(vla_sp_root_loc);
+    }
+}
+
+
+static inline CType *pointed_type(CType *type)
+{
+    return &type->ref->type;
+}
+
+
+static void mk_pointer(CType *type)
+{
+    Sym *s;
+    s = sym_push(0x20000000, type, 0, -1);
+    type->t = 5 | (type->t & (0x00001000 | 0x00002000 | 0x00004000 | 0x00008000));
+    type->ref = s;
+}
+
+
+static int is_compatible_func(CType *type1, CType *type2)
+{
+    Sym *s1, *s2;
+
+    s1 = type1->ref;
+    s2 = type2->ref;
+    if (!is_compatible_types(&s1->type, &s2->type))
+        return 0;
+
+    if (s1->f.func_call != s2->f.func_call)
+        return 0;
+
+    if (s1->f.func_type == 2 || s2->f.func_type == 2)
+        return 1;
+    if (s1->f.func_type != s2->f.func_type)
+        return 0;
+    while (s1 != 0) {
+        if (s2 == 0)
+            return 0;
+        if (!is_compatible_unqualified_types(&s1->type, &s2->type))
+            return 0;
+        s1 = s1->next;
+        s2 = s2->next;
+    }
+    if (s2)
+        return 0;
+    return 1;
+}
+
+
+
+
+
+
+static int compare_types(CType *type1, CType *type2, int unqualified)
+{
+    int bt1, t1, t2;
+
+    t1 = type1->t & (~((0x00001000 | 0x00002000 | 0x00004000 | 0x00008000)|(((1 << (6+6)) - 1) << 20 | 0x0080)));
+    t2 = type2->t & (~((0x00001000 | 0x00002000 | 0x00004000 | 0x00008000)|(((1 << (6+6)) - 1) << 20 | 0x0080)));
+    if (unqualified) {
+
+        t1 &= ~(0x0100 | 0x0200);
+        t2 &= ~(0x0100 | 0x0200);
+    }
+
+
+    if ((t1 & 0x000f) != 1) {
+        t1 &= ~0x0020;
+        t2 &= ~0x0020;
+    }
+
+    if (t1 != t2)
+        return 0;
+
+    bt1 = t1 & 0x000f;
+    if (bt1 == 5) {
+        type1 = pointed_type(type1);
+        type2 = pointed_type(type2);
+        return is_compatible_types(type1, type2);
+    } else if (bt1 == 7) {
+        return (type1->ref == type2->ref);
+    } else if (bt1 == 6) {
+        return is_compatible_func(type1, type2);
+    } else {
+        return 1;
+    }
+}
+
+
+
+
+static int is_compatible_types(CType *type1, CType *type2)
+{
+    return compare_types(type1,type2,0);
+}
+
+
+
+static int is_compatible_unqualified_types(CType *type1, CType *type2)
+{
+    return compare_types(type1,type2,1);
+}
+
+
+
+
+
+static void type_to_str(char *buf, int buf_size,
+                 CType *type, const char *varstr)
+{
+    int bt, v, t;
+    Sym *s, *sa;
+    char buf1[256];
+    const char *tstr;
+
+    t = type->t;
+    bt = t & 0x000f;
+    buf[0] = '\0';
+
+    if (t & 0x00001000)
+        pstrcat(buf, buf_size, "extern ");
+    if (t & 0x00002000)
+        pstrcat(buf, buf_size, "static ");
+    if (t & 0x00004000)
+        pstrcat(buf, buf_size, "typedef ");
+    if (t & 0x00008000)
+        pstrcat(buf, buf_size, "inline ");
+    if (t & 0x0200)
+        pstrcat(buf, buf_size, "volatile ");
+    if (t & 0x0100)
+        pstrcat(buf, buf_size, "const ");
+
+    if (((t & 0x0020) && bt == 1)
+        || ((t & 0x0010)
+            && (bt == 2 || bt == 3 || bt == 4)
+            && !((t & (((1 << (6+6)) - 1) << 20 | 0x0080)) == (2 << 20))
+            ))
+        pstrcat(buf, buf_size, (t & 0x0010) ? "unsigned " : "signed ");
+
+    buf_size -= strlen(buf);
+    buf += strlen(buf);
+
+    switch(bt) {
+    case 0:
+        tstr = "void";
+        goto add_tstr;
+    case 11:
+        tstr = "_Bool";
+        goto add_tstr;
+    case 1:
+        tstr = "char";
+        goto add_tstr;
+    case 2:
+        tstr = "short";
+        goto add_tstr;
+    case 3:
+        tstr = "int";
+        goto maybe_long;
+    case 4:
+        tstr = "long long";
+    maybe_long:
+        if (t & 0x0800)
+            tstr = "long";
+        if (!((t & (((1 << (6+6)) - 1) << 20 | 0x0080)) == (2 << 20)))
+            goto add_tstr;
+        tstr = "enum ";
+        goto tstruct;
+    case 8:
+        tstr = "float";
+        goto add_tstr;
+    case 9:
+        tstr = "double";
+        goto add_tstr;
+    case 10:
+        tstr = "long double";
+    add_tstr:
+        pstrcat(buf, buf_size, tstr);
+        break;
+    case 7:
+        tstr = "struct ";
+        if (((t & ((((1 << (6+6)) - 1) << 20 | 0x0080)|0x000f)) == (1 << 20 | 7)))
+            tstr = "union ";
+    tstruct:
+        pstrcat(buf, buf_size, tstr);
+        v = type->ref->v & ~0x40000000;
+        if (v >= 0x10000000)
+            pstrcat(buf, buf_size, "<anonymous>");
+        else
+            pstrcat(buf, buf_size, get_tok_str(v, 0));
+        break;
+    case 6:
+        s = type->ref;
+        type_to_str(buf, buf_size, &s->type, varstr);
+        pstrcat(buf, buf_size, "(");
+        sa = s->next;
+        while (sa != 0) {
+            type_to_str(buf1, sizeof(buf1), &sa->type, 0);
+            pstrcat(buf, buf_size, buf1);
+            sa = sa->next;
+            if (sa)
+                pstrcat(buf, buf_size, ", ");
+        }
+        pstrcat(buf, buf_size, ")");
+        goto no_var;
+    case 5:
+        s = type->ref;
+        if (t & 0x0040) {
+            snprintf(buf1, sizeof(buf1), "%s[%d]", varstr ? varstr : "", s->c);
+            type_to_str(buf, buf_size, &s->type, buf1);
+            goto no_var;
+        }
+        pstrcpy(buf1, sizeof(buf1), "*");
+        if (t & 0x0100)
+            pstrcat(buf1, buf_size, "const ");
+        if (t & 0x0200)
+            pstrcat(buf1, buf_size, "volatile ");
+        if (varstr)
+            pstrcat(buf1, sizeof(buf1), varstr);
+        type_to_str(buf, buf_size, &s->type, buf1);
+        goto no_var;
+    }
+    if (varstr) {
+        pstrcat(buf, buf_size, " ");
+        pstrcat(buf, buf_size, varstr);
+    }
+ no_var: ;
+}
+
+
+
+static void gen_assign_cast(CType *dt)
+{
+    CType *st, *type1, *type2;
+    char buf1[256], buf2[256];
+    int dbt, sbt;
+
+    st = &vtop->type;
+    dbt = dt->t & 0x000f;
+    sbt = st->t & 0x000f;
+    if (sbt == 0 || dbt == 0) {
+ if (sbt == 0 && dbt == 0)
+     ;
+# 2994 "tccgen.c"
+ else
+         tcc_error("cannot cast from/to void");
+    }
+    if (dt->t & 0x0100)
+        tcc_warning("assignment of read-only location");
+    switch(dbt) {
+    case 5:
+
+
+        if (is_null_pointer(vtop))
+            goto type_ok;
+
+        if (is_integer_btype(sbt)) {
+            tcc_warning("assignment makes pointer from integer without a cast");
+            goto type_ok;
+        }
+        type1 = pointed_type(dt);
+
+        if (sbt == 6) {
+            if ((type1->t & 0x000f) != 0 &&
+                !is_compatible_types(pointed_type(dt), st))
+                tcc_warning("assignment from incompatible pointer type");
+            goto type_ok;
+        }
+        if (sbt != 5)
+            goto error;
+        type2 = pointed_type(st);
+        if ((type1->t & 0x000f) == 0 ||
+            (type2->t & 0x000f) == 0) {
+
+        } else {
+
+
+            if (!is_compatible_unqualified_types(type1, type2)) {
+
+
+
+
+  if ((type1->t & (0x000f|0x0800)) != (type2->t & (0x000f|0x0800))
+                    || ((type1->t & (((1 << (6+6)) - 1) << 20 | 0x0080)) == (2 << 20)) || ((type2->t & (((1 << (6+6)) - 1) << 20 | 0x0080)) == (2 << 20))
+                    )
+      tcc_warning("assignment from incompatible pointer type");
+     }
+        }
+
+        if ((!(type1->t & 0x0100) && (type2->t & 0x0100)) ||
+            (!(type1->t & 0x0200) && (type2->t & 0x0200)))
+            tcc_warning("assignment discards qualifiers from pointer target type");
+        break;
+    case 1:
+    case 2:
+    case 3:
+    case 4:
+        if (sbt == 5 || sbt == 6) {
+            tcc_warning("assignment makes integer from pointer without a cast");
+        } else if (sbt == 7) {
+            goto case_VT_STRUCT;
+        }
+
+        break;
+    case 7:
+    case_VT_STRUCT:
+        if (!is_compatible_unqualified_types(dt, st)) {
+        error:
+            type_to_str(buf1, sizeof(buf1), st, 0);
+            type_to_str(buf2, sizeof(buf2), dt, 0);
+            tcc_error("cannot cast '%s' to '%s'", buf1, buf2);
+        }
+        break;
+    }
+ type_ok:
+    gen_cast(dt);
+}
+
+
+static void vstore(void)
+{
+    int sbt, dbt, ft, r, t, size, align, bit_size, bit_pos, rc, delayed_cast;
+
+    ft = vtop[-1].type.t;
+    sbt = vtop->type.t & 0x000f;
+    dbt = ft & 0x000f;
+    if ((((sbt == 3 || sbt == 2) && dbt == 1) ||
+         (sbt == 3 && dbt == 2))
+ && !(vtop->type.t & 0x0080)) {
+
+        delayed_cast = 0x0400;
+        vtop->type.t = ft & (~((0x00001000 | 0x00002000 | 0x00004000 | 0x00008000)|(((1 << (6+6)) - 1) << 20 | 0x0080)));
+
+        if (ft & 0x0100)
+            tcc_warning("assignment of read-only location");
+    } else {
+        delayed_cast = 0;
+        if (!(ft & 0x0080))
+            gen_assign_cast(&vtop[-1].type);
+    }
+
+    if (sbt == 7) {
+
+
+
+            size = type_size(&vtop->type, &align);
+
+
+            vswap();
+            vtop->type.t = 5;
+            gaddrof();
+# 3111 "tccgen.c"
+            vpush_global_sym(&func_old_type, TOK_memmove);
+
+            vswap();
+
+            vpushv(vtop - 2);
+            vtop->type.t = 5;
+            gaddrof();
+
+            vpushi(size);
+            gfunc_call(3);
+
+
+    } else if (ft & 0x0080) {
+
+
+
+        vdup(), vtop[-1] = vtop[-2];
+
+        bit_pos = (((ft) >> 20) & 0x3f);
+        bit_size = (((ft) >> (20 + 6)) & 0x3f);
+
+        vtop[-1].type.t = ft & ~(((1 << (6+6)) - 1) << 20 | 0x0080);
+
+        if ((ft & 0x000f) == 11) {
+            gen_cast(&vtop[-1].type);
+            vtop[-1].type.t = (vtop[-1].type.t & ~0x000f) | (1 | 0x0010);
+        }
+
+        r = adjust_bf(vtop - 1, bit_pos, bit_size);
+        if (r == 7) {
+            gen_cast_s((ft & 0x000f) == 4 ? 4 : 3);
+            store_packed_bf(bit_pos, bit_size);
+        } else {
+            unsigned long long mask = (1ULL << bit_size) - 1;
+            if ((ft & 0x000f) != 11) {
+
+                if ((vtop[-1].type.t & 0x000f) == 4)
+                    vpushll(mask);
+                else
+                    vpushi((unsigned)mask);
+                gen_op('&');
+            }
+
+            vpushi(bit_pos);
+            gen_op(0x01);
+            vswap();
+
+            vdup();
+            vrott(3);
+
+            if ((vtop->type.t & 0x000f) == 4)
+                vpushll(~(mask << bit_pos));
+            else
+                vpushi(~((unsigned)mask << bit_pos));
+            gen_op('&');
+            gen_op('|');
+
+            vstore();
+
+            vpop();
+        }
+    } else if (dbt == 0) {
+        --vtop;
+    } else {
+
+
+            if (vtop[-1].r & 0x0800) {
+                vswap();
+                gbound();
+                vswap();
+            }
+
+            rc = 0x0001;
+            if (is_float(ft)) {
+                rc = 0x0002;
+
+                if ((ft & 0x000f) == 10) {
+                    rc = 0x0080;
+                } else if ((ft & 0x000f) == 14) {
+                    rc = 0x1000;
+                }
+
+            }
+            r = gv(rc);
+
+            if ((vtop[-1].r & 0x003f) == 0x0031) {
+                SValue sv;
+                t = get_reg(0x0001);
+
+                sv.type.t = 5;
+
+
+
+                sv.r = 0x0032 | 0x0100;
+                sv.c.i = vtop[-1].c.i;
+                load(t, &sv);
+                vtop[-1].r = t | 0x0100;
+            }
+
+
+            if (((ft & 0x000f) == 13) || ((ft & 0x000f) == 14)) {
+                int addr_type = 4, load_size = 8, load_type = ((vtop->type.t & 0x000f) == 13) ? 4 : 9;
+
+
+
+
+                vtop[-1].type.t = load_type;
+                store(r, vtop - 1);
+                vswap();
+
+                vtop->type.t = addr_type;
+                gaddrof();
+                vpushi(load_size);
+                gen_op('+');
+                vtop->r |= 0x0100;
+                vswap();
+                vtop[-1].type.t = load_type;
+
+                store(vtop->r2, vtop - 1);
+            } else {
+                store(r, vtop - 1);
+            }
+
+        vswap();
+        vtop--;
+        vtop->r |= delayed_cast;
+    }
+}
+
+
+static void inc(int post, int c)
+{
+    test_lvalue();
+    vdup();
+    if (post) {
+        gv_dup();
+        vrotb(3);
+        vrotb(3);
+    }
+
+    vpushi(c - 0xa3);
+    gen_op('+');
+    vstore();
+    if (post)
+        vpop();
+}
+
+static void parse_mult_str (CString *astr, const char *msg)
+{
+
+    if (tok != 0xb9)
+        expect(msg);
+    cstr_new(astr);
+    while (tok == 0xb9) {
+
+        cstr_cat(astr, tokc.str.data, -1);
+        next();
+    }
+    cstr_ccat(astr, '\0');
+}
+
+
+
+static int exact_log2p1(int i)
+{
+  int ret;
+  if (!i)
+    return 0;
+  for (ret = 1; i >= 1 << 8; ret += 8)
+    i >>= 8;
+  if (i >= 1 << 4)
+    ret += 4, i >>= 4;
+  if (i >= 1 << 2)
+    ret += 2, i >>= 2;
+  if (i >= 1 << 1)
+    ret++;
+  return ret;
+}
+
+
+static void parse_attribute(AttributeDef *ad)
+{
+    int t, n;
+    CString astr;
+
+redo:
+    if (tok != TOK_ATTRIBUTE1 && tok != TOK_ATTRIBUTE2)
+        return;
+    next();
+    skip('(');
+    skip('(');
+    while (tok != ')') {
+        if (tok < 256)
+            expect("attribute name");
+        t = tok;
+        next();
+        switch(t) {
+        case TOK_SECTION1:
+        case TOK_SECTION2:
+            skip('(');
+     parse_mult_str(&astr, "section name");
+            ad->section = find_section(tcc_state, (char *)astr.data);
+            skip(')');
+     cstr_free(&astr);
+            break;
+        case TOK_ALIAS1:
+        case TOK_ALIAS2:
+            skip('(');
+     parse_mult_str(&astr, "alias(\"target\")");
+            ad->alias_target =
+              tok_alloc((char*)astr.data, astr.size-1)->tok;
+            skip(')');
+     cstr_free(&astr);
+            break;
+ case TOK_VISIBILITY1:
+ case TOK_VISIBILITY2:
+            skip('(');
+     parse_mult_str(&astr,
+      "visibility(\"default|hidden|internal|protected\")");
+     if (!strcmp (astr.data, "default"))
+         ad->a.visibility = 0;
+     else if (!strcmp (astr.data, "hidden"))
+         ad->a.visibility = 2;
+     else if (!strcmp (astr.data, "internal"))
+         ad->a.visibility = 1;
+     else if (!strcmp (astr.data, "protected"))
+         ad->a.visibility = 3;
+     else
+                expect("visibility(\"default|hidden|internal|protected\")");
+            skip(')');
+     cstr_free(&astr);
+            break;
+        case TOK_ALIGNED1:
+        case TOK_ALIGNED2:
+            if (tok == '(') {
+                next();
+                n = expr_const();
+                if (n <= 0 || (n & (n - 1)) != 0)
+                    tcc_error("alignment must be a positive power of two");
+                skip(')');
+            } else {
+                n = 16;
+            }
+            ad->a.aligned = exact_log2p1(n);
+     if (n != 1 << (ad->a.aligned - 1))
+       tcc_error("alignment of %d is larger than implemented", n);
+            break;
+        case TOK_PACKED1:
+        case TOK_PACKED2:
+            ad->a.packed = 1;
+            break;
+        case TOK_WEAK1:
+        case TOK_WEAK2:
+            ad->a.weak = 1;
+            break;
+        case TOK_UNUSED1:
+        case TOK_UNUSED2:
+
+
+            break;
+        case TOK_NORETURN1:
+        case TOK_NORETURN2:
+
+
+            break;
+        case TOK_CDECL1:
+        case TOK_CDECL2:
+        case TOK_CDECL3:
+            ad->f.func_call = 0;
+            break;
+        case TOK_STDCALL1:
+        case TOK_STDCALL2:
+        case TOK_STDCALL3:
+            ad->f.func_call = 1;
+            break;
+# 3405 "tccgen.c"
+        case TOK_MODE:
+            skip('(');
+            switch(tok) {
+                case TOK_MODE_DI:
+                    ad->attr_mode = 4 + 1;
+                    break;
+                case TOK_MODE_QI:
+                    ad->attr_mode = 1 + 1;
+                    break;
+                case TOK_MODE_HI:
+                    ad->attr_mode = 2 + 1;
+                    break;
+                case TOK_MODE_SI:
+                case TOK_MODE_word:
+                    ad->attr_mode = 3 + 1;
+                    break;
+                default:
+                    tcc_warning("__mode__(%s) not supported\n", get_tok_str(tok, 0));
+                    break;
+            }
+            next();
+            skip(')');
+            break;
+        case TOK_DLLEXPORT:
+            ad->a.dllexport = 1;
+            break;
+        case TOK_DLLIMPORT:
+            ad->a.dllimport = 1;
+            break;
+        default:
+            if (tcc_state->warn_unsupported)
+                tcc_warning("'%s' attribute ignored", get_tok_str(t, 0));
+
+            if (tok == '(') {
+                int parenthesis = 0;
+                do {
+                    if (tok == '(')
+                        parenthesis++;
+                    else if (tok == ')')
+                        parenthesis--;
+                    next();
+                } while (parenthesis && tok != -1);
+            }
+            break;
+        }
+        if (tok != ',')
+            break;
+        next();
+    }
+    skip(')');
+    skip(')');
+    goto redo;
+}
+
+static Sym * find_field (CType *type, int v)
+{
+    Sym *s = type->ref;
+    v |= 0x20000000;
+    while ((s = s->next) != 0) {
+ if ((s->v & 0x20000000) &&
+     (s->type.t & 0x000f) == 7 &&
+     (s->v & ~0x20000000) >= 0x10000000) {
+     Sym *ret = find_field (&s->type, v);
+     if (ret)
+         return ret;
+ }
+ if (s->v == v)
+   break;
+    }
+    return s;
+}
+
+static void struct_add_offset (Sym *s, int offset)
+{
+    while ((s = s->next) != 0) {
+ if ((s->v & 0x20000000) &&
+     (s->type.t & 0x000f) == 7 &&
+     (s->v & ~0x20000000) >= 0x10000000) {
+     struct_add_offset(s->type.ref, offset);
+ } else
+   s->c += offset;
+    }
+}
+
+static void struct_layout(CType *type, AttributeDef *ad)
+{
+    int size, align, maxalign, offset, c, bit_pos, bit_size;
+    int packed, a, bt, prevbt, prev_bit_size;
+    int pcc = !tcc_state->ms_bitfields;
+    int pragma_pack = *tcc_state->pack_stack_ptr;
+    Sym *f;
+
+    maxalign = 1;
+    offset = 0;
+    c = 0;
+    bit_pos = 0;
+    prevbt = 7;
+    prev_bit_size = 0;
+
+
+
+    for (f = type->ref->next; f; f = f->next) {
+        if (f->type.t & 0x0080)
+            bit_size = (((f->type.t) >> (20 + 6)) & 0x3f);
+        else
+            bit_size = -1;
+        size = type_size(&f->type, &align);
+        a = f->a.aligned ? 1 << (f->a.aligned - 1) : 0;
+        packed = 0;
+
+        if (pcc && bit_size == 0) {
+
+
+        } else {
+
+            if (pcc && (f->a.packed || ad->a.packed))
+                align = packed = 1;
+
+
+            if (pragma_pack) {
+                packed = 1;
+                if (pragma_pack < align)
+                    align = pragma_pack;
+
+                if (pcc && pragma_pack < a)
+                    a = 0;
+            }
+        }
+
+        if (a)
+            align = a;
+
+        if (type->ref->type.t == (1 << 20 | 7)) {
+     if (pcc && bit_size >= 0)
+         size = (bit_size + 7) >> 3;
+     offset = 0;
+     if (size > c)
+         c = size;
+
+ } else if (bit_size < 0) {
+            if (pcc)
+                c += (bit_pos + 7) >> 3;
+     c = (c + align - 1) & -align;
+     offset = c;
+     if (size > 0)
+         c += size;
+     bit_pos = 0;
+     prevbt = 7;
+     prev_bit_size = 0;
+
+ } else {
+
+
+            if (pcc) {
+
+
+
+
+
+
+                if (bit_size == 0) {
+            new_field:
+      c = (c + ((bit_pos + 7) >> 3) + align - 1) & -align;
+      bit_pos = 0;
+                } else if (f->a.aligned) {
+                    goto new_field;
+                } else if (!packed) {
+                    int a8 = align * 8;
+             int ofs = ((c * 8 + bit_pos) % a8 + bit_size + a8 - 1) / a8;
+                    if (ofs > size / align)
+                        goto new_field;
+                }
+
+
+                if (size == 8 && bit_size <= 32)
+                    f->type.t = (f->type.t & ~0x000f) | 3, size = 4;
+
+                while (bit_pos >= align * 8)
+                    c += align, bit_pos -= align * 8;
+                offset = c;
+
+
+
+
+  if (f->v & 0x10000000
+
+                    )
+      align = 1;
+
+     } else {
+  bt = f->type.t & 0x000f;
+  if ((bit_pos + bit_size > size * 8)
+                    || (bit_size > 0) == (bt != prevbt)
+                    ) {
+      c = (c + align - 1) & -align;
+      offset = c;
+      bit_pos = 0;
+
+
+
+
+      if (bit_size || prev_bit_size)
+          c += size;
+  }
+
+
+
+
+  if (bit_size == 0 && prevbt != bt)
+      align = 1;
+  prevbt = bt;
+                prev_bit_size = bit_size;
+     }
+
+     f->type.t = (f->type.t & ~(0x3f << 20))
+          | (bit_pos << 20);
+     bit_pos += bit_size;
+ }
+ if (align > maxalign)
+     maxalign = align;
+# 3638 "tccgen.c"
+ if (f->v & 0x10000000 && (f->type.t & 0x000f) == 7) {
+     Sym *ass;
+
+
+
+
+
+
+
+     int v2 = f->type.ref->v;
+     if (!(v2 & 0x20000000) &&
+  (v2 & ~0x40000000) < 0x10000000) {
+  Sym **pps;
+
+
+
+
+
+  ass = f->type.ref;
+  f->type.ref = sym_push(anon_sym++ | 0x20000000,
+           &f->type.ref->type, 0,
+           f->type.ref->c);
+  pps = &f->type.ref->next;
+  while ((ass = ass->next) != 0) {
+      *pps = sym_push(ass->v, &ass->type, 0, ass->c);
+      pps = &((*pps)->next);
+  }
+  *pps = 0;
+     }
+     struct_add_offset(f->type.ref, offset);
+     f->c = 0;
+ } else {
+     f->c = offset;
+ }
+
+ f->r = 0;
+    }
+
+    if (pcc)
+        c += (bit_pos + 7) >> 3;
+
+
+    a = bt = ad->a.aligned ? 1 << (ad->a.aligned - 1) : 1;
+    if (a < maxalign)
+        a = maxalign;
+    type->ref->r = a;
+    if (pragma_pack && pragma_pack < maxalign && 0 == pcc) {
+
+
+        a = pragma_pack;
+        if (a < bt)
+            a = bt;
+    }
+    c = (c + a - 1) & -a;
+    type->ref->c = c;
+
+
+
+
+
+
+    for (f = type->ref->next; f; f = f->next) {
+        int s, px, cx, c0;
+        CType t;
+
+        if (0 == (f->type.t & 0x0080))
+            continue;
+        f->type.ref = f;
+        f->auxtype = -1;
+        bit_size = (((f->type.t) >> (20 + 6)) & 0x3f);
+        if (bit_size == 0)
+            continue;
+        bit_pos = (((f->type.t) >> 20) & 0x3f);
+        size = type_size(&f->type, &align);
+        if (bit_pos + bit_size <= size * 8 && f->c + size <= c)
+            continue;
+
+
+        c0 = -1, s = align = 1;
+        for (;;) {
+            px = f->c * 8 + bit_pos;
+            cx = (px >> 3) & -align;
+            px = px - (cx << 3);
+            if (c0 == cx)
+                break;
+            s = (px + bit_size + 7) >> 3;
+            if (s > 4) {
+                t.t = 4;
+            } else if (s > 2) {
+                t.t = 3;
+            } else if (s > 1) {
+                t.t = 2;
+            } else {
+                t.t = 1;
+            }
+            s = type_size(&t, &align);
+            c0 = cx;
+        }
+
+        if (px + bit_size <= s * 8 && cx + s <= c) {
+
+            f->c = cx;
+            bit_pos = px;
+     f->type.t = (f->type.t & ~(0x3f << 20))
+          | (bit_pos << 20);
+            if (s != size)
+                f->auxtype = t.t;
+
+
+
+
+
+
+        } else {
+
+            f->auxtype = 7;
+
+
+
+
+        }
+    }
+}
+
+
+static void struct_decl(CType *type, int u)
+{
+    int v, c, size, align, flexible;
+    int bit_size, bsize, bt;
+    Sym *s, *ss, **ps;
+    AttributeDef ad, ad1;
+    CType type1, btype;
+
+    memset(&ad, 0, sizeof ad);
+    next();
+    parse_attribute(&ad);
+    if (tok != '{') {
+        v = tok;
+        next();
+
+        if (v < 256)
+            expect("struct/union/enum name");
+        s = struct_find(v);
+        if (s && (s->sym_scope == local_scope || tok != '{')) {
+            if (u == s->type.t)
+                goto do_decl;
+            if (u == (2 << 20) && ((s->type.t & (((1 << (6+6)) - 1) << 20 | 0x0080)) == (2 << 20)))
+                goto do_decl;
+            tcc_error("redefinition of '%s'", get_tok_str(v, 0));
+        }
+    } else {
+        v = anon_sym++;
+    }
+
+    type1.t = u == (2 << 20) ? u | 3 | 0x0010 : u;
+    type1.ref = 0;
+
+    s = sym_push(v | 0x40000000, &type1, 0, -1);
+    s->r = 0;
+do_decl:
+    type->t = s->type.t;
+    type->ref = s;
+
+    if (tok == '{') {
+        next();
+        if (s->c != -1)
+            tcc_error("struct/union/enum already defined");
+
+
+        ps = &s->next;
+        if (u == (2 << 20)) {
+            long long ll = 0, pl = 0, nl = 0;
+     CType t;
+            t.ref = s;
+
+            t.t = 3|0x00002000|(3 << 20);
+            for(;;) {
+                v = tok;
+                if (v < TOK_DEFINE)
+                    expect("identifier");
+                ss = sym_find(v);
+                if (ss && !local_stack)
+                    tcc_error("redefinition of enumerator '%s'",
+                              get_tok_str(v, 0));
+                next();
+                if (tok == '=') {
+                    next();
+      ll = expr_const64();
+                }
+                ss = sym_push(v, &t, 0x0030, 0);
+                ss->enum_val = ll;
+                *ps = ss, ps = &ss->next;
+                if (ll < nl)
+                    nl = ll;
+                if (ll > pl)
+                    pl = ll;
+                if (tok != ',')
+                    break;
+                next();
+                ll++;
+
+                if (tok == '}')
+                    break;
+            }
+            skip('}');
+
+            t.t = 3;
+            if (nl >= 0) {
+                if (pl != (unsigned)pl)
+                    t.t = (8==8 ? 4|0x0800 : 4);
+                t.t |= 0x0010;
+            } else if (pl != (int)pl || nl != (int)nl)
+                t.t = (8==8 ? 4|0x0800 : 4);
+            s->type.t = type->t = t.t | (2 << 20);
+            s->c = 0;
+
+            for (ss = s->next; ss; ss = ss->next) {
+                ll = ss->enum_val;
+                if (ll == (int)ll)
+                    continue;
+                if (t.t & 0x0010) {
+                    ss->type.t |= 0x0010;
+                    if (ll == (unsigned)ll)
+                        continue;
+                }
+                ss->type.t = (ss->type.t & ~0x000f)
+                    | (8==8 ? 4|0x0800 : 4);
+            }
+        } else {
+            c = 0;
+            flexible = 0;
+            while (tok != '}') {
+                if (!parse_btype(&btype, &ad1)) {
+      skip(';');
+      continue;
+  }
+                while (1) {
+      if (flexible)
+          tcc_error("flexible array member '%s' not at the end of struct",
+                              get_tok_str(v, 0));
+                    bit_size = -1;
+                    v = 0;
+                    type1 = btype;
+                    if (tok != ':') {
+   if (tok != ';')
+                            type_decl(&type1, &ad1, &v, 2);
+                        if (v == 0) {
+                         if ((type1.t & 0x000f) != 7)
+                         expect("identifier");
+                         else {
+    int v = btype.ref->v;
+    if (!(v & 0x20000000) && (v & ~0x40000000) < 0x10000000) {
+        if (tcc_state->ms_extensions == 0)
+                          expect("identifier");
+    }
+                         }
+                        }
+                        if (type_size(&type1, &align) < 0) {
+       if ((u == 7) && (type1.t & 0x0040) && c)
+           flexible = 1;
+       else
+           tcc_error("field '%s' has incomplete type",
+                                      get_tok_str(v, 0));
+                        }
+                        if ((type1.t & 0x000f) == 6 ||
+                            (type1.t & (0x00001000 | 0x00002000 | 0x00004000 | 0x00008000)))
+                            tcc_error("invalid type for '%s'",
+                                  get_tok_str(v, 0));
+                    }
+                    if (tok == ':') {
+                        next();
+                        bit_size = expr_const();
+
+                        if (bit_size < 0)
+                            tcc_error("negative width in bit-field '%s'",
+                                  get_tok_str(v, 0));
+                        if (v && bit_size == 0)
+                            tcc_error("zero width for bit-field '%s'",
+                                  get_tok_str(v, 0));
+   parse_attribute(&ad1);
+                    }
+                    size = type_size(&type1, &align);
+                    if (bit_size >= 0) {
+                        bt = type1.t & 0x000f;
+                        if (bt != 3 &&
+                            bt != 1 &&
+                            bt != 2 &&
+                            bt != 11 &&
+                            bt != 4)
+                            tcc_error("bitfields must have scalar type");
+                        bsize = size * 8;
+                        if (bit_size > bsize) {
+                            tcc_error("width of '%s' exceeds its type",
+                                  get_tok_str(v, 0));
+                        } else if (bit_size == bsize
+                                    && !ad.a.packed && !ad1.a.packed) {
+
+                            ;
+                        } else if (bit_size == 64) {
+                            tcc_error("field width 64 not implemented");
+                        } else {
+                            type1.t = (type1.t & ~(((1 << (6+6)) - 1) << 20 | 0x0080))
+                                | 0x0080
+                                | (bit_size << (20 + 6));
+                        }
+                    }
+                    if (v != 0 || (type1.t & 0x000f) == 7) {
+
+
+   c = 1;
+                    }
+
+
+                    if (v == 0 &&
+   ((type1.t & 0x000f) == 7 ||
+    bit_size >= 0)) {
+          v = anon_sym++;
+      }
+                    if (v) {
+                        ss = sym_push(v | 0x20000000, &type1, 0, 0);
+                        ss->a = ad1.a;
+                        *ps = ss;
+                        ps = &ss->next;
+                    }
+                    if (tok == ';' || tok == (-1))
+                        break;
+                    skip(',');
+                }
+                skip(';');
+            }
+            skip('}');
+     parse_attribute(&ad);
+     struct_layout(type, &ad);
+        }
+    }
+}
+
+static void sym_to_attr(AttributeDef *ad, Sym *s)
+{
+    if (s->a.aligned && 0 == ad->a.aligned)
+        ad->a.aligned = s->a.aligned;
+    if (s->f.func_call && 0 == ad->f.func_call)
+        ad->f.func_call = s->f.func_call;
+    if (s->f.func_type && 0 == ad->f.func_type)
+        ad->f.func_type = s->f.func_type;
+    if (s->a.packed)
+        ad->a.packed = 1;
+}
+
+
+
+static void parse_btype_qualify(CType *type, int qualifiers)
+{
+    while (type->t & 0x0040) {
+        type->ref = sym_push(0x20000000, &type->ref->type, 0, type->ref->c);
+        type = &type->ref->type;
+    }
+    type->t |= qualifiers;
+}
+
+
+
+
+static int parse_btype(CType *type, AttributeDef *ad)
+{
+    int t, u, bt, st, type_found, typespec_found, g;
+    Sym *s;
+    CType type1;
+
+    memset(ad, 0, sizeof(AttributeDef));
+    type_found = 0;
+    typespec_found = 0;
+    t = 3;
+    bt = st = -1;
+    type->ref = 0;
+
+    while(1) {
+        switch(tok) {
+        case TOK_EXTENSION:
+
+            next();
+            continue;
+
+
+        case TOK_CHAR:
+            u = 1;
+        basic_type:
+            next();
+        basic_type1:
+            if (u == 2 || u == 0x0800) {
+                if (st != -1 || (bt != -1 && bt != 3))
+                    tmbt: tcc_error("too many basic types");
+                st = u;
+            } else {
+                if (bt != -1 || (st != -1 && u != 3))
+                    goto tmbt;
+                bt = u;
+            }
+            if (u != 3)
+                t = (t & ~(0x000f|0x0800)) | u;
+            typespec_found = 1;
+            break;
+        case TOK_VOID:
+            u = 0;
+            goto basic_type;
+        case TOK_SHORT:
+            u = 2;
+            goto basic_type;
+        case TOK_INT:
+            u = 3;
+            goto basic_type;
+        case TOK_LONG:
+            if ((t & 0x000f) == 9) {
+                t = (t & ~(0x000f|0x0800)) | 10;
+            } else if ((t & (0x000f|0x0800)) == 0x0800) {
+                t = (t & ~(0x000f|0x0800)) | 4;
+            } else {
+                u = 0x0800;
+                goto basic_type;
+            }
+            next();
+            break;
+
+
+
+
+
+
+
+        case TOK_BOOL:
+            u = 11;
+            goto basic_type;
+        case TOK_FLOAT:
+            u = 8;
+            goto basic_type;
+        case TOK_DOUBLE:
+            if ((t & (0x000f|0x0800)) == 0x0800) {
+                t = (t & ~(0x000f|0x0800)) | 10;
+            } else {
+                u = 9;
+                goto basic_type;
+            }
+            next();
+            break;
+        case TOK_ENUM:
+            struct_decl(&type1, (2 << 20));
+        basic_type2:
+            u = type1.t;
+            type->ref = type1.ref;
+            goto basic_type1;
+        case TOK_STRUCT:
+            struct_decl(&type1, 7);
+            goto basic_type2;
+        case TOK_UNION:
+            struct_decl(&type1, (1 << 20 | 7));
+            goto basic_type2;
+
+
+        case TOK_CONST1:
+        case TOK_CONST2:
+        case TOK_CONST3:
+            type->t = t;
+            parse_btype_qualify(type, 0x0100);
+            t = type->t;
+            next();
+            break;
+        case TOK_VOLATILE1:
+        case TOK_VOLATILE2:
+        case TOK_VOLATILE3:
+            type->t = t;
+            parse_btype_qualify(type, 0x0200);
+            t = type->t;
+            next();
+            break;
+        case TOK_SIGNED1:
+        case TOK_SIGNED2:
+        case TOK_SIGNED3:
+            if ((t & (0x0020|0x0010)) == (0x0020|0x0010))
+                tcc_error("signed and unsigned modifier");
+            t |= 0x0020;
+            next();
+            typespec_found = 1;
+            break;
+        case TOK_REGISTER:
+        case TOK_AUTO:
+        case TOK_RESTRICT1:
+        case TOK_RESTRICT2:
+        case TOK_RESTRICT3:
+            next();
+            break;
+        case TOK_UNSIGNED:
+            if ((t & (0x0020|0x0010)) == 0x0020)
+                tcc_error("signed and unsigned modifier");
+            t |= 0x0020 | 0x0010;
+            next();
+            typespec_found = 1;
+            break;
+
+
+        case TOK_EXTERN:
+            g = 0x00001000;
+            goto storage;
+        case TOK_STATIC:
+            g = 0x00002000;
+            goto storage;
+        case TOK_TYPEDEF:
+            g = 0x00004000;
+            goto storage;
+       storage:
+            if (t & (0x00001000|0x00002000|0x00004000) & ~g)
+                tcc_error("multiple storage classes");
+            t |= g;
+            next();
+            break;
+        case TOK_INLINE1:
+        case TOK_INLINE2:
+        case TOK_INLINE3:
+            t |= 0x00008000;
+            next();
+            break;
+
+
+        case TOK_ATTRIBUTE1:
+        case TOK_ATTRIBUTE2:
+            parse_attribute(ad);
+            if (ad->attr_mode) {
+                u = ad->attr_mode -1;
+                t = (t & ~(0x000f|0x0800)) | u;
+            }
+            break;
+
+        case TOK_TYPEOF1:
+        case TOK_TYPEOF2:
+        case TOK_TYPEOF3:
+            next();
+            parse_expr_type(&type1);
+
+            type1.t &= ~((0x00001000 | 0x00002000 | 0x00004000 | 0x00008000)&~0x00004000);
+     if (type1.ref)
+                sym_to_attr(ad, type1.ref);
+            goto basic_type2;
+        default:
+            if (typespec_found)
+                goto the_end;
+            s = sym_find(tok);
+            if (!s || !(s->type.t & 0x00004000))
+                goto the_end;
+            t &= ~(0x000f|0x0800);
+            u = t & ~(0x0100 | 0x0200), t ^= u;
+            type->t = (s->type.t & ~0x00004000) | u;
+            type->ref = s->type.ref;
+            if (t)
+                parse_btype_qualify(type, t);
+            t = type->t;
+
+            sym_to_attr(ad, s);
+            next();
+            typespec_found = 1;
+            st = bt = -2;
+            break;
+        }
+        type_found = 1;
+    }
+the_end:
+    if (tcc_state->char_is_unsigned) {
+        if ((t & (0x0020|0x000f)) == 1)
+            t |= 0x0010;
+    }
+
+    bt = t & (0x000f|0x0800);
+    if (bt == 0x0800)
+        t |= 8 == 8 ? 4 : 3;
+
+
+
+
+    type->t = t;
+    return type_found;
+}
+
+
+
+static inline void convert_parameter_type(CType *pt)
+{
+
+
+    pt->t &= ~(0x0100 | 0x0200);
+
+    pt->t &= ~0x0040;
+    if ((pt->t & 0x000f) == 6) {
+        mk_pointer(pt);
+    }
+}
+
+static void parse_asm_str(CString *astr)
+{
+    skip('(');
+    parse_mult_str(astr, "string constant");
+}
+
+
+static int asm_label_instr(void)
+{
+    int v;
+    CString astr;
+
+    next();
+    parse_asm_str(&astr);
+    skip(')');
+
+
+
+    v = tok_alloc(astr.data, astr.size - 1)->tok;
+    cstr_free(&astr);
+    return v;
+}
+
+static int post_type(CType *type, AttributeDef *ad, int storage, int td)
+{
+    int n, l, t1, arg_size, align;
+    Sym **plast, *s, *first;
+    AttributeDef ad1;
+    CType pt;
+
+    if (tok == '(') {
+
+        next();
+ if (td && !(td & 1))
+   return 0;
+ if (tok == ')')
+   l = 0;
+ else if (parse_btype(&pt, &ad1))
+   l = 1;
+ else if (td)
+   return 0;
+ else
+   l = 2;
+        first = 0;
+        plast = &first;
+        arg_size = 0;
+        if (l) {
+            for(;;) {
+
+                if (l != 2) {
+                    if ((pt.t & 0x000f) == 0 && tok == ')')
+                        break;
+                    type_decl(&pt, &ad1, &n, 2 | 1);
+                    if ((pt.t & 0x000f) == 0)
+                        tcc_error("parameter declared as void");
+                    arg_size += (type_size(&pt, &align) + 8 - 1) / 8;
+                } else {
+                    n = tok;
+                    if (n < TOK_DEFINE)
+                        expect("identifier");
+                    pt.t = 0;
+                    next();
+                }
+                convert_parameter_type(&pt);
+                s = sym_push(n | 0x20000000, &pt, 0, 0);
+                *plast = s;
+                plast = &s->next;
+                if (tok == ')')
+                    break;
+                skip(',');
+                if (l == 1 && tok == 0xc8) {
+                    l = 3;
+                    next();
+                    break;
+                }
+  if (l == 1 && !parse_btype(&pt, &ad1))
+      tcc_error("invalid type");
+            }
+        } else
+
+            l = 2;
+        skip(')');
+
+
+        type->t &= ~0x0100;
+
+
+
+        if (tok == '[') {
+            next();
+            skip(']');
+            mk_pointer(type);
+        }
+
+        ad->f.func_args = arg_size;
+        ad->f.func_type = l;
+        s = sym_push(0x20000000, type, 0, 0);
+        s->a = ad->a;
+        s->f = ad->f;
+        s->next = first;
+        type->t = 6;
+        type->ref = s;
+    } else if (tok == '[') {
+ int saved_nocode_wanted = nocode_wanted;
+
+        next();
+        if (tok == TOK_RESTRICT1)
+            next();
+        n = -1;
+        t1 = 0;
+        if (tok != ']') {
+            if (!local_stack || (storage & 0x00002000))
+                vpushi(expr_const());
+            else {
+
+
+
+
+  nocode_wanted = 0;
+  gexpr();
+     }
+            if ((vtop->r & (0x003f | 0x0100 | 0x0200)) == 0x0030) {
+                n = vtop->c.i;
+                if (n < 0)
+                    tcc_error("invalid array size");
+            } else {
+                if (!is_integer_btype(vtop->type.t & 0x000f))
+                    tcc_error("size of variable length array should be an integer");
+                t1 = 0x0400;
+            }
+        }
+        skip(']');
+
+        post_type(type, ad, storage, 0);
+        if (type->t == 6)
+            tcc_error("declaration of an array of functions");
+        t1 |= type->t & 0x0400;
+
+        if (t1 & 0x0400) {
+            loc -= type_size(&int_type, &align);
+            loc &= -align;
+            n = loc;
+
+            vla_runtime_type_size(type, &align);
+            gen_op('*');
+            vset(&int_type, 0x0032|0x0100, n);
+            vswap();
+            vstore();
+        }
+        if (n != -1)
+            vpop();
+ nocode_wanted = saved_nocode_wanted;
+
+
+
+        s = sym_push(0x20000000, type, 0, n);
+        type->t = (t1 ? 0x0400 : 0x0040) | 5;
+        type->ref = s;
+    }
+    return 1;
+}
+# 4401 "tccgen.c"
+static CType *type_decl(CType *type, AttributeDef *ad, int *v, int td)
+{
+    CType *post, *ret;
+    int qualifiers, storage;
+
+
+    storage = type->t & (0x00001000 | 0x00002000 | 0x00004000 | 0x00008000);
+    type->t &= ~(0x00001000 | 0x00002000 | 0x00004000 | 0x00008000);
+    post = ret = type;
+
+    while (tok == '*') {
+        qualifiers = 0;
+    redo:
+        next();
+        switch(tok) {
+        case TOK_CONST1:
+        case TOK_CONST2:
+        case TOK_CONST3:
+            qualifiers |= 0x0100;
+            goto redo;
+        case TOK_VOLATILE1:
+        case TOK_VOLATILE2:
+        case TOK_VOLATILE3:
+            qualifiers |= 0x0200;
+            goto redo;
+        case TOK_RESTRICT1:
+        case TOK_RESTRICT2:
+        case TOK_RESTRICT3:
+            goto redo;
+
+ case TOK_ATTRIBUTE1:
+ case TOK_ATTRIBUTE2:
+     parse_attribute(ad);
+     break;
+        }
+        mk_pointer(type);
+        type->t |= qualifiers;
+ if (ret == type)
+
+     ret = pointed_type(type);
+    }
+
+    if (tok == '(') {
+
+
+ if (!post_type(type, ad, 0, td)) {
+
+
+
+
+     parse_attribute(ad);
+     post = type_decl(type, ad, v, td);
+     skip(')');
+ }
+    } else if (tok >= 256 && (td & 2)) {
+
+ *v = tok;
+ next();
+    } else {
+ if (!(td & 1))
+   expect("identifier");
+ *v = 0;
+    }
+    post_type(post, ad, storage, 0);
+    parse_attribute(ad);
+    type->t |= storage;
+    return ret;
+}
+
+
+static int lvalue_type(int t)
+{
+    int bt, r;
+    r = 0x0100;
+    bt = t & 0x000f;
+    if (bt == 1 || bt == 11)
+        r |= 0x1000;
+    else if (bt == 2)
+        r |= 0x2000;
+    else
+        return r;
+    if (t & 0x0010)
+        r |= 0x4000;
+    return r;
+}
+
+
+static void indir(void)
+{
+    if ((vtop->type.t & 0x000f) != 5) {
+        if ((vtop->type.t & 0x000f) == 6)
+            return;
+        expect("pointer");
+    }
+    if (vtop->r & 0x0100)
+        gv(0x0001);
+    vtop->type = *pointed_type(&vtop->type);
+
+    if (!(vtop->type.t & 0x0040) && !(vtop->type.t & 0x0400)
+        && (vtop->type.t & 0x000f) != 6) {
+        vtop->r |= lvalue_type(vtop->type.t);
+
+
+        if (tcc_state->do_bounds_check)
+            vtop->r |= 0x0800;
+
+    }
+}
+
+
+static void gfunc_param_typed(Sym *func, Sym *arg)
+{
+    int func_type;
+    CType type;
+
+    func_type = func->f.func_type;
+    if (func_type == 2 ||
+        (func_type == 3 && arg == 0)) {
+
+        if ((vtop->type.t & 0x000f) == 8) {
+            gen_cast_s(9);
+        } else if (vtop->type.t & 0x0080) {
+            type.t = vtop->type.t & (0x000f | 0x0010);
+     type.ref = vtop->type.ref;
+            gen_cast(&type);
+        }
+    } else if (arg == 0) {
+        tcc_error("too many arguments to function");
+    } else {
+        type = arg->type;
+        type.t &= ~0x0100;
+        gen_assign_cast(&type);
+    }
+}
+
+
+static void expr_type(CType *type, void (*expr_fn)(void))
+{
+    nocode_wanted++;
+    expr_fn();
+    *type = vtop->type;
+    vpop();
+    nocode_wanted--;
+}
+
+
+
+static void parse_expr_type(CType *type)
+{
+    int n;
+    AttributeDef ad;
+
+    skip('(');
+    if (parse_btype(type, &ad)) {
+        type_decl(type, &ad, &n, 1);
+    } else {
+        expr_type(type, gexpr);
+    }
+    skip(')');
+}
+
+static void parse_type(CType *type)
+{
+    AttributeDef ad;
+    int n;
+
+    if (!parse_btype(type, &ad)) {
+        expect("type");
+    }
+    type_decl(type, &ad, &n, 1);
+}
+
+static void parse_builtin_params(int nc, const char *args)
+{
+    char c, sep = '(';
+    CType t;
+    if (nc)
+        nocode_wanted++;
+    next();
+    while ((c = *args++)) {
+ skip(sep);
+ sep = ',';
+ switch (c) {
+     case 'e': expr_eq(); continue;
+     case 't': parse_type(&t); vpush(&t); continue;
+     default: tcc_error("internal error"); break;
+ }
+    }
+    skip(')');
+    if (nc)
+        nocode_wanted--;
+}
+
+static void unary(void)
+{
+    int n, t, align, size, r, sizeof_caller;
+    CType type;
+    Sym *s;
+    AttributeDef ad;
+
+    sizeof_caller = in_sizeof;
+    in_sizeof = 0;
+    type.ref = 0;
+
+
+ tok_next:
+    switch(tok) {
+    case TOK_EXTENSION:
+        next();
+        goto tok_next;
+    case 0xb4:
+
+
+
+
+    case 0xb5:
+    case 0xb3:
+ t = 3;
+ push_tokc:
+ type.t = t;
+ vsetc(&type, 0x0030, &tokc);
+        next();
+        break;
+    case 0xb6:
+        t = 3 | 0x0010;
+        goto push_tokc;
+    case 0xb7:
+        t = 4;
+ goto push_tokc;
+    case 0xb8:
+        t = 4 | 0x0010;
+ goto push_tokc;
+    case 0xbb:
+        t = 8;
+ goto push_tokc;
+    case 0xbc:
+        t = 9;
+ goto push_tokc;
+    case 0xbd:
+        t = 10;
+ goto push_tokc;
+    case 0xce:
+        t = (8 == 8 ? 4 : 3) | 0x0800;
+ goto push_tokc;
+    case 0xcf:
+        t = (8 == 8 ? 4 : 3) | 0x0800 | 0x0010;
+ goto push_tokc;
+    case TOK___FUNCTION__:
+        if (!gnu_ext)
+            goto tok_identifier;
+
+    case TOK___FUNC__:
+        {
+            void *ptr;
+            int len;
+
+            len = strlen(funcname) + 1;
+
+            type.t = 1;
+            mk_pointer(&type);
+            type.t |= 0x0040;
+            type.ref->c = len;
+            vpush_ref(&type, data_section, data_section->data_offset, len);
+            if (!(nocode_wanted > 0)) {
+                ptr = section_ptr_add(data_section, len);
+                memcpy(ptr, funcname, len);
+            }
+            next();
+        }
+        break;
+    case 0xba:
+
+
+
+        t = 3;
+
+        goto str_init;
+    case 0xb9:
+
+        t = 1;
+        if (tcc_state->char_is_unsigned)
+            t = 1 | 0x0010;
+    str_init:
+        if (tcc_state->warn_write_strings)
+            t |= 0x0100;
+        type.t = t;
+        mk_pointer(&type);
+        type.t |= 0x0040;
+        memset(&ad, 0, sizeof(AttributeDef));
+        decl_initializer_alloc(&type, &ad, 0x0030, 2, 0, 0);
+        break;
+    case '(':
+        next();
+
+        if (parse_btype(&type, &ad)) {
+            type_decl(&type, &ad, &n, 1);
+            skip(')');
+
+            if (tok == '{') {
+
+                if (global_expr)
+                    r = 0x0030;
+                else
+                    r = 0x0032;
+
+                if (!(type.t & 0x0040))
+                    r |= lvalue_type(type.t);
+                memset(&ad, 0, sizeof(AttributeDef));
+                decl_initializer_alloc(&type, &ad, r, 1, 0, 0);
+            } else {
+                if (sizeof_caller) {
+                    vpush(&type);
+                    return;
+                }
+                unary();
+                gen_cast(&type);
+            }
+        } else if (tok == '{') {
+     int saved_nocode_wanted = nocode_wanted;
+            if (const_wanted)
+                tcc_error("expected constant");
+
+            save_regs(0);
+
+
+
+
+
+            block(0, 0, 1);
+     nocode_wanted = saved_nocode_wanted;
+            skip(')');
+        } else {
+            gexpr();
+            skip(')');
+        }
+        break;
+    case '*':
+        next();
+        unary();
+        indir();
+        break;
+    case '&':
+        next();
+        unary();
+
+
+
+
+
+        if ((vtop->type.t & 0x000f) != 6 &&
+            !(vtop->type.t & 0x0040))
+            test_lvalue();
+        mk_pointer(&vtop->type);
+        gaddrof();
+        break;
+    case '!':
+        next();
+        unary();
+        if ((vtop->r & (0x003f | 0x0100 | 0x0200)) == 0x0030) {
+            gen_cast_s(11);
+            vtop->c.i = !vtop->c.i;
+        } else if ((vtop->r & 0x003f) == 0x0033)
+            vtop->c.i ^= 1;
+        else {
+            save_regs(1);
+            vseti(0x0034, gvtst(1, 0));
+        }
+        break;
+    case '~':
+        next();
+        unary();
+        vpushi(-1);
+        gen_op('^');
+        break;
+    case '+':
+        next();
+        unary();
+        if ((vtop->type.t & 0x000f) == 5)
+            tcc_error("pointer not accepted for unary plus");
+
+
+
+ if (!is_float(vtop->type.t)) {
+     vpushi(0);
+     gen_op('+');
+ }
+        break;
+    case TOK_SIZEOF:
+    case TOK_ALIGNOF1:
+    case TOK_ALIGNOF2:
+        t = tok;
+        next();
+        in_sizeof++;
+        expr_type(&type, unary);
+        s = vtop[1].sym;
+        size = type_size(&type, &align);
+        if (s && s->a.aligned)
+            align = 1 << (s->a.aligned - 1);
+        if (t == TOK_SIZEOF) {
+            if (!(type.t & 0x0400)) {
+                if (size < 0)
+                    tcc_error("sizeof applied to an incomplete type");
+                vpushs(size);
+            } else {
+                vla_runtime_type_size(&type, &align);
+            }
+        } else {
+            vpushs(align);
+        }
+        vtop->type.t |= 0x0010;
+        break;
+
+    case TOK_builtin_expect:
+
+ parse_builtin_params(0, "ee");
+ vpop();
+        break;
+    case TOK_builtin_types_compatible_p:
+ parse_builtin_params(0, "tt");
+ vtop[-1].type.t &= ~(0x0100 | 0x0200);
+ vtop[0].type.t &= ~(0x0100 | 0x0200);
+ n = is_compatible_types(&vtop[-1].type, &vtop[0].type);
+ vtop -= 2;
+ vpushi(n);
+        break;
+    case TOK_builtin_choose_expr:
+ {
+     int64_t c;
+     next();
+     skip('(');
+     c = expr_const64();
+     skip(',');
+     if (!c) {
+  nocode_wanted++;
+     }
+     expr_eq();
+     if (!c) {
+  vpop();
+  nocode_wanted--;
+     }
+     skip(',');
+     if (c) {
+  nocode_wanted++;
+     }
+     expr_eq();
+     if (c) {
+  vpop();
+  nocode_wanted--;
+     }
+     skip(')');
+ }
+        break;
+    case TOK_builtin_constant_p:
+ parse_builtin_params(1, "e");
+ n = (vtop->r & (0x003f | 0x0100 | 0x0200)) == 0x0030;
+ vtop--;
+ vpushi(n);
+        break;
+    case TOK_builtin_frame_address:
+    case TOK_builtin_return_address:
+        {
+            int tok1 = tok;
+            int level;
+            next();
+            skip('(');
+            if (tok != 0xb5) {
+                tcc_error("%s only takes positive integers",
+                          tok1 == TOK_builtin_return_address ?
+                          "__builtin_return_address" :
+                          "__builtin_frame_address");
+            }
+            level = (uint32_t)tokc.i;
+            next();
+            skip(')');
+            type.t = 0;
+            mk_pointer(&type);
+            vset(&type, 0x0032, 0);
+            while (level--) {
+                mk_pointer(&vtop->type);
+                indir();
+            }
+            if (tok1 == TOK_builtin_return_address) {
+
+                vpushi(8);
+                gen_op('+');
+                mk_pointer(&vtop->type);
+                indir();
+            }
+        }
+        break;
+# 4906 "tccgen.c"
+    case TOK_builtin_va_arg_types:
+ parse_builtin_params(0, "t");
+ vpushi(classify_x86_64_va_arg(&vtop->type));
+ vswap();
+ vpop();
+        break;
+# 4942 "tccgen.c"
+    case 0xa4:
+    case 0xa2:
+        t = tok;
+        next();
+        unary();
+        inc(0, t);
+        break;
+    case '-':
+        next();
+        unary();
+        t = vtop->type.t & 0x000f;
+ if (is_float(t)) {
+
+
+     vpush(&vtop->type);
+     if (t == 8)
+         vtop->c.f = -1.0 * 0.0;
+     else if (t == 9)
+         vtop->c.d = -1.0 * 0.0;
+     else
+         vtop->c.ld = -1.0 * 0.0;
+ } else
+     vpushi(0);
+ vswap();
+ gen_op('-');
+        break;
+    case 0xa0:
+        if (!gnu_ext)
+            goto tok_identifier;
+        next();
+
+        if (tok < TOK_DEFINE)
+            expect("label identifier");
+        s = label_find(tok);
+        if (!s) {
+            s = label_push(&global_label_stack, tok, 1);
+        } else {
+            if (s->r == 2)
+                s->r = 1;
+        }
+        if (!s->type.t) {
+            s->type.t = 0;
+            mk_pointer(&s->type);
+            s->type.t |= 0x00002000;
+        }
+        vpushsym(&s->type, s);
+        next();
+        break;
+
+    case TOK_GENERIC:
+    {
+ CType controlling_type;
+ int has_default = 0;
+ int has_match = 0;
+ int learn = 0;
+ TokenString *str = 0;
+
+ next();
+ skip('(');
+ expr_type(&controlling_type, expr_eq);
+ controlling_type.t &= ~(0x0100 | 0x0200 | 0x0040);
+ for (;;) {
+     learn = 0;
+     skip(',');
+     if (tok == TOK_DEFAULT) {
+  if (has_default)
+      tcc_error("too many 'default'");
+  has_default = 1;
+  if (!has_match)
+      learn = 1;
+  next();
+     } else {
+         AttributeDef ad_tmp;
+  int itmp;
+         CType cur_type;
+  parse_btype(&cur_type, &ad_tmp);
+  type_decl(&cur_type, &ad_tmp, &itmp, 1);
+  if (compare_types(&controlling_type, &cur_type, 0)) {
+      if (has_match) {
+        tcc_error("type match twice");
+      }
+      has_match = 1;
+      learn = 1;
+  }
+     }
+     skip(':');
+     if (learn) {
+  if (str)
+      tok_str_free(str);
+  skip_or_save_block(&str);
+     } else {
+  skip_or_save_block(0);
+     }
+     if (tok == ')')
+  break;
+ }
+ if (!str) {
+     char buf[60];
+     type_to_str(buf, sizeof buf, &controlling_type, 0);
+     tcc_error("type '%s' does not match any association", buf);
+ }
+ begin_macro(str, 1);
+ next();
+ expr_eq();
+ if (tok != (-1))
+     expect(",");
+ end_macro();
+        next();
+ break;
+    }
+
+    case TOK___NAN__:
+        vpush64(9, 0x7ff8000000000000ULL);
+        next();
+        break;
+    case TOK___SNAN__:
+        vpush64(9, 0x7ff0000000000001ULL);
+        next();
+        break;
+    case TOK___INF__:
+        vpush64(9, 0x7ff0000000000000ULL);
+        next();
+        break;
+
+    default:
+    tok_identifier:
+        t = tok;
+        next();
+        if (t < TOK_DEFINE)
+            expect("identifier");
+        s = sym_find(t);
+        if (!s || (((s)->type.t & (0x000f | (0 | 0x0010))) == (0 | 0x0010))) {
+            const char *name = get_tok_str(t, 0);
+            if (tok != '(')
+                tcc_error("'%s' undeclared", name);
+
+
+            if (tcc_state->warn_implicit_function_declaration
+
+
+
+
+
+            )
+                tcc_warning("implicit declaration of function '%s'", name);
+            s = external_global_sym(t, &func_old_type, 0);
+        }
+
+        r = s->r;
+
+
+        if ((r & 0x003f) < 0x0030)
+            r = (r & ~0x003f) | 0x0032;
+
+        vset(&s->type, r, s->c);
+
+
+
+ vtop->sym = s;
+
+        if (r & 0x0200) {
+            vtop->c.i = 0;
+        } else if (r == 0x0030 && ((s->type.t & (((1 << (6+6)) - 1) << 20 | 0x0080)) == (3 << 20))) {
+            vtop->c.i = s->enum_val;
+        }
+        break;
+    }
+
+
+    while (1) {
+        if (tok == 0xa4 || tok == 0xa2) {
+            inc(1, tok);
+            next();
+        } else if (tok == '.' || tok == 0xc7 || tok == 0xbc) {
+            int qualifiers;
+
+            if (tok == 0xc7)
+                indir();
+            qualifiers = vtop->type.t & (0x0100 | 0x0200);
+            test_lvalue();
+            gaddrof();
+
+            if ((vtop->type.t & 0x000f) != 7)
+                expect("struct or union");
+            if (tok == 0xbc)
+                expect("field name");
+            next();
+            if (tok == 0xb5 || tok == 0xb6)
+                expect("field name");
+     s = find_field(&vtop->type, tok);
+            if (!s)
+                tcc_error("field not found: %s", get_tok_str(tok & ~0x20000000, &tokc));
+
+            vtop->type = char_pointer_type;
+            vpushi(s->c);
+            gen_op('+');
+
+            vtop->type = s->type;
+            vtop->type.t |= qualifiers;
+
+            if (!(vtop->type.t & 0x0040)) {
+                vtop->r |= lvalue_type(vtop->type.t);
+
+
+                if (tcc_state->do_bounds_check && (vtop->r & 0x003f) != 0x0032)
+                    vtop->r |= 0x0800;
+
+            }
+            next();
+        } else if (tok == '[') {
+            next();
+            gexpr();
+            gen_op('+');
+            indir();
+            skip(']');
+        } else if (tok == '(') {
+            SValue ret;
+            Sym *sa;
+            int nb_args, ret_nregs, ret_align, regsize, variadic;
+
+
+            if ((vtop->type.t & 0x000f) != 6) {
+
+                if ((vtop->type.t & (0x000f | 0x0040)) == 5) {
+                    vtop->type = *pointed_type(&vtop->type);
+                    if ((vtop->type.t & 0x000f) != 6)
+                        goto error_func;
+                } else {
+                error_func:
+                    expect("function pointer");
+                }
+            } else {
+                vtop->r &= ~0x0100;
+            }
+
+            s = vtop->type.ref;
+            next();
+            sa = s->next;
+            nb_args = regsize = 0;
+            ret.r2 = 0x0030;
+
+            if ((s->type.t & 0x000f) == 7) {
+                variadic = (s->f.func_type == 3);
+                ret_nregs = gfunc_sret(&s->type, variadic, &ret.type,
+                                       &ret_align, &regsize);
+                if (!ret_nregs) {
+
+                    size = type_size(&s->type, &align);
+# 5199 "tccgen.c"
+                    loc = (loc - size) & -align;
+                    ret.type = s->type;
+                    ret.r = 0x0032 | 0x0100;
+
+
+                    vseti(0x0032, loc);
+                    ret.c = vtop->c;
+                    nb_args++;
+                }
+            } else {
+                ret_nregs = 1;
+                ret.type = s->type;
+            }
+
+            if (ret_nregs) {
+
+                if (is_float(ret.type.t)) {
+                    ret.r = reg_fret(ret.type.t);
+
+                    if ((ret.type.t & 0x000f) == 14)
+                      ret.r2 = TREG_XMM1;
+
+                } else {
+
+
+                    if ((ret.type.t & 0x000f) == 13)
+
+
+
+                        ret.r2 = TREG_RDX;
+
+                    ret.r = TREG_RAX;
+                }
+                ret.c.i = 0;
+            }
+            if (tok != ')') {
+                for(;;) {
+                    expr_eq();
+                    gfunc_param_typed(s, sa);
+                    nb_args++;
+                    if (sa)
+                        sa = sa->next;
+                    if (tok == ')')
+                        break;
+                    skip(',');
+                }
+            }
+            if (sa)
+                tcc_error("too few arguments to function");
+            skip(')');
+            gfunc_call(nb_args);
+
+
+            for (r = ret.r + ret_nregs + !ret_nregs; r-- > ret.r;) {
+                vsetc(&ret.type, r, &ret.c);
+                vtop->r2 = ret.r2;
+            }
+
+
+            if (((s->type.t & 0x000f) == 7) && ret_nregs) {
+                int addr, offset;
+
+                size = type_size(&s->type, &align);
+
+
+  if (regsize > align)
+    align = regsize;
+                loc = (loc - size) & -align;
+                addr = loc;
+                offset = 0;
+                for (;;) {
+                    vset(&ret.type, 0x0032 | 0x0100, addr + offset);
+                    vswap();
+                    vstore();
+                    vtop--;
+                    if (--ret_nregs == 0)
+                        break;
+                    offset += regsize;
+                }
+                vset(&s->type, 0x0032 | 0x0100, addr);
+            }
+        } else {
+            break;
+        }
+    }
+}
+
+static void expr_prod(void)
+{
+    int t;
+
+    unary();
+    while (tok == '*' || tok == '/' || tok == '%') {
+        t = tok;
+        next();
+        unary();
+        gen_op(t);
+    }
+}
+
+static void expr_sum(void)
+{
+    int t;
+
+    expr_prod();
+    while (tok == '+' || tok == '-') {
+        t = tok;
+        next();
+        expr_prod();
+        gen_op(t);
+    }
+}
+
+static void expr_shift(void)
+{
+    int t;
+
+    expr_sum();
+    while (tok == 0x01 || tok == 0x02) {
+        t = tok;
+        next();
+        expr_sum();
+        gen_op(t);
+    }
+}
+
+static void expr_cmp(void)
+{
+    int t;
+
+    expr_shift();
+    while ((tok >= 0x96 && tok <= 0x9f) ||
+           tok == 0x92 || tok == 0x93) {
+        t = tok;
+        next();
+        expr_shift();
+        gen_op(t);
+    }
+}
+
+static void expr_cmpeq(void)
+{
+    int t;
+
+    expr_cmp();
+    while (tok == 0x94 || tok == 0x95) {
+        t = tok;
+        next();
+        expr_cmp();
+        gen_op(t);
+    }
+}
+
+static void expr_and(void)
+{
+    expr_cmpeq();
+    while (tok == '&') {
+        next();
+        expr_cmpeq();
+        gen_op('&');
+    }
+}
+
+static void expr_xor(void)
+{
+    expr_and();
+    while (tok == '^') {
+        next();
+        expr_and();
+        gen_op('^');
+    }
+}
+
+static void expr_or(void)
+{
+    expr_xor();
+    while (tok == '|') {
+        next();
+        expr_xor();
+        gen_op('|');
+    }
+}
+
+static void expr_land(void)
+{
+    expr_or();
+    if (tok == 0xa0) {
+ int t = 0;
+ for(;;) {
+     if ((vtop->r & (0x003f | 0x0100 | 0x0200)) == 0x0030) {
+                gen_cast_s(11);
+  if (vtop->c.i) {
+      vpop();
+  } else {
+      nocode_wanted++;
+      while (tok == 0xa0) {
+   next();
+   expr_or();
+   vpop();
+      }
+      nocode_wanted--;
+      if (t)
+        gsym(t);
+      gen_cast_s(3);
+      break;
+  }
+     } else {
+  if (!t)
+    save_regs(1);
+  t = gvtst(1, t);
+     }
+     if (tok != 0xa0) {
+  if (t)
+    vseti(0x0035, t);
+  else
+    vpushi(1);
+  break;
+     }
+     next();
+     expr_or();
+ }
+    }
+}
+
+static void expr_lor(void)
+{
+    expr_land();
+    if (tok == 0xa1) {
+ int t = 0;
+ for(;;) {
+     if ((vtop->r & (0x003f | 0x0100 | 0x0200)) == 0x0030) {
+                gen_cast_s(11);
+  if (!vtop->c.i) {
+      vpop();
+  } else {
+      nocode_wanted++;
+      while (tok == 0xa1) {
+   next();
+   expr_land();
+   vpop();
+      }
+      nocode_wanted--;
+      if (t)
+        gsym(t);
+      gen_cast_s(3);
+      break;
+  }
+     } else {
+  if (!t)
+    save_regs(1);
+  t = gvtst(0, t);
+     }
+     if (tok != 0xa1) {
+  if (t)
+    vseti(0x0034, t);
+  else
+    vpushi(0);
+  break;
+     }
+     next();
+     expr_land();
+ }
+    }
+}
+
+
+
+
+static int condition_3way(void)
+{
+    int c = -1;
+    if ((vtop->r & (0x003f | 0x0100)) == 0x0030 &&
+ (!(vtop->r & 0x0200) || !vtop->sym->a.weak)) {
+ vdup();
+        gen_cast_s(11);
+ c = vtop->c.i;
+ vpop();
+    }
+    return c;
+}
+
+static void expr_cond(void)
+{
+    int tt, u, r1, r2, rc, t1, t2, bt1, bt2, islv, c, g;
+    SValue sv;
+    CType type, type1, type2;
+
+    expr_lor();
+    if (tok == '?') {
+        next();
+ c = condition_3way();
+        g = (tok == ':' && gnu_ext);
+        if (c < 0) {
+
+
+            if (is_float(vtop->type.t)) {
+                rc = 0x0002;
+
+                if ((vtop->type.t & 0x000f) == 10) {
+                    rc = 0x0080;
+                }
+
+            } else
+                rc = 0x0001;
+            gv(rc);
+            save_regs(1);
+            if (g)
+                gv_dup();
+            tt = gvtst(1, 0);
+
+        } else {
+            if (!g)
+                vpop();
+            tt = 0;
+        }
+
+        if (1) {
+            if (c == 0)
+                nocode_wanted++;
+            if (!g)
+                gexpr();
+
+            type1 = vtop->type;
+            sv = *vtop;
+            vtop--;
+            skip(':');
+
+            u = 0;
+            if (c < 0)
+                u = gjmp(0);
+            gsym(tt);
+
+            if (c == 0)
+                nocode_wanted--;
+            if (c == 1)
+                nocode_wanted++;
+            expr_cond();
+            if (c == 1)
+                nocode_wanted--;
+
+            type2 = vtop->type;
+            t1 = type1.t;
+            bt1 = t1 & 0x000f;
+            t2 = type2.t;
+            bt2 = t2 & 0x000f;
+            type.ref = 0;
+
+
+            if (is_float(bt1) || is_float(bt2)) {
+                if (bt1 == 10 || bt2 == 10) {
+                    type.t = 10;
+
+                } else if (bt1 == 9 || bt2 == 9) {
+                    type.t = 9;
+                } else {
+                    type.t = 8;
+                }
+            } else if (bt1 == 4 || bt2 == 4) {
+
+                type.t = 4 | 0x0800;
+                if (bt1 == 4)
+                    type.t &= t1;
+                if (bt2 == 4)
+                    type.t &= t2;
+
+                if ((t1 & (0x000f | 0x0010 | 0x0080)) == (4 | 0x0010) ||
+                    (t2 & (0x000f | 0x0010 | 0x0080)) == (4 | 0x0010))
+                    type.t |= 0x0010;
+            } else if (bt1 == 5 || bt2 == 5) {
+
+
+  if (is_null_pointer (vtop))
+    type = type1;
+  else if (is_null_pointer (&sv))
+    type = type2;
+
+
+  else
+    type = type1;
+            } else if (bt1 == 6 || bt2 == 6) {
+
+                type = bt1 == 6 ? type1 : type2;
+            } else if (bt1 == 7 || bt2 == 7) {
+
+                type = bt1 == 7 ? type1 : type2;
+            } else if (bt1 == 0 || bt2 == 0) {
+
+                type.t = 0;
+            } else {
+
+                type.t = 3 | (0x0800 & (t1 | t2));
+
+                if ((t1 & (0x000f | 0x0010 | 0x0080)) == (3 | 0x0010) ||
+                    (t2 & (0x000f | 0x0010 | 0x0080)) == (3 | 0x0010))
+                    type.t |= 0x0010;
+            }
+
+
+            islv = (vtop->r & 0x0100) && (sv.r & 0x0100) && 7 == (type.t & 0x000f);
+            islv &= c < 0;
+
+
+            if (c != 1) {
+                gen_cast(&type);
+                if (islv) {
+                    mk_pointer(&vtop->type);
+                    gaddrof();
+                } else if (7 == (vtop->type.t & 0x000f))
+                    gaddrof();
+            }
+
+            rc = 0x0001;
+            if (is_float(type.t)) {
+                rc = 0x0002;
+
+                if ((type.t & 0x000f) == 10) {
+                    rc = 0x0080;
+                }
+
+            } else if ((type.t & 0x000f) == 4) {
+
+
+                rc = 0x0004;
+            }
+
+            tt = r2 = 0;
+            if (c < 0) {
+                r2 = gv(rc);
+                tt = gjmp(0);
+            }
+            gsym(u);
+
+
+
+            if (c != 0) {
+                *vtop = sv;
+                gen_cast(&type);
+                if (islv) {
+                    mk_pointer(&vtop->type);
+                    gaddrof();
+                } else if (7 == (vtop->type.t & 0x000f))
+                    gaddrof();
+            }
+
+            if (c < 0) {
+                r1 = gv(rc);
+                move_reg(r2, r1, type.t);
+                vtop->r = r2;
+                gsym(tt);
+                if (islv)
+                    indir();
+            }
+        }
+    }
+}
+
+static void expr_eq(void)
+{
+    int t;
+
+    expr_cond();
+    if (tok == '=' ||
+        (tok >= 0xa5 && tok <= 0xaf) ||
+        tok == 0xde || tok == 0xfc ||
+        tok == 0x81 || tok == 0x82) {
+        test_lvalue();
+        t = tok;
+        next();
+        if (t == '=') {
+            expr_eq();
+        } else {
+            vdup();
+            expr_eq();
+            gen_op(t & 0x7f);
+        }
+        vstore();
+    }
+}
+
+static void gexpr(void)
+{
+    while (1) {
+        expr_eq();
+        if (tok != ',')
+            break;
+        vpop();
+        next();
+    }
+}
+
+
+static void expr_const1(void)
+{
+    const_wanted++;
+    nocode_wanted++;
+    expr_cond();
+    nocode_wanted--;
+    const_wanted--;
+}
+
+
+static inline int64_t expr_const64(void)
+{
+    int64_t c;
+    expr_const1();
+    if ((vtop->r & (0x003f | 0x0100 | 0x0200)) != 0x0030)
+        expect("constant expression");
+    c = vtop->c.i;
+    vpop();
+    return c;
+}
+
+
+
+static int expr_const(void)
+{
+    int c;
+    int64_t wc = expr_const64();
+    c = wc;
+    if (c != wc && (unsigned)c != wc)
+        tcc_error("constant exceeds 32 bit");
+    return c;
+}
+
+
+
+static int is_label(void)
+{
+    int last_tok;
+
+
+    if (tok < TOK_DEFINE)
+        return 0;
+
+    last_tok = tok;
+    next();
+    if (tok == ':') {
+        return last_tok;
+    } else {
+        unget_tok(last_tok);
+        return 0;
+    }
+}
+
+
+static void gfunc_return(CType *func_type)
+{
+    if ((func_type->t & 0x000f) == 7) {
+        CType type, ret_type;
+        int ret_align, ret_nregs, regsize;
+        ret_nregs = gfunc_sret(func_type, func_var, &ret_type,
+                               &ret_align, &regsize);
+        if (0 == ret_nregs) {
+
+
+            type = *func_type;
+            mk_pointer(&type);
+            vset(&type, 0x0032 | 0x0100, func_vc);
+            indir();
+            vswap();
+
+            vstore();
+        } else {
+
+            int r, size, addr, align;
+            size = type_size(func_type,&align);
+            if ((vtop->r != (0x0032 | 0x0100) ||
+                 (vtop->c.i & (ret_align-1)))
+                && (align & (ret_align-1))) {
+                loc = (loc - size) & -ret_align;
+                addr = loc;
+                type = *func_type;
+                vset(&type, 0x0032 | 0x0100, addr);
+                vswap();
+                vstore();
+                vpop();
+                vset(&ret_type, 0x0032 | 0x0100, addr);
+            }
+            vtop->type = ret_type;
+            if (is_float(ret_type.t))
+                r = rc_fret(ret_type.t);
+            else
+                r = 0x0004;
+
+            if (ret_nregs == 1)
+                gv(r);
+            else {
+                for (;;) {
+                    vdup();
+                    gv(r);
+                    vpop();
+                    if (--ret_nregs == 0)
+                      break;
+
+
+
+                    r <<= 1;
+                    vtop->c.i += regsize;
+                }
+            }
+        }
+    } else if (is_float(func_type->t)) {
+        gv(rc_fret(func_type->t));
+    } else {
+        gv(0x0004);
+    }
+    vtop--;
+}
+
+
+static int case_cmp(const void *pa, const void *pb)
+{
+    int64_t a = (*(struct case_t**) pa)->v1;
+    int64_t b = (*(struct case_t**) pb)->v1;
+    return a < b ? -1 : a > b;
+}
+
+static void gcase(struct case_t **base, int len, int *bsym)
+{
+    struct case_t *p;
+    int e;
+    int ll = (vtop->type.t & 0x000f) == 4;
+    gv(0x0001);
+    while (len > 4) {
+
+        p = base[len/2];
+        vdup();
+ if (ll)
+     vpushll(p->v2);
+ else
+     vpushi(p->v2);
+        gen_op(0x9e);
+        e = gtst(1, 0);
+        vdup();
+ if (ll)
+     vpushll(p->v1);
+ else
+     vpushi(p->v1);
+        gen_op(0x9d);
+        gtst_addr(0, p->sym);
+
+        gcase(base, len/2, bsym);
+        if (cur_switch->def_sym)
+            gjmp_addr(cur_switch->def_sym);
+        else
+            *bsym = gjmp(*bsym);
+
+        gsym(e);
+        e = len/2 + 1;
+        base += e; len -= e;
+    }
+
+    while (len--) {
+        p = *base++;
+        vdup();
+ if (ll)
+     vpushll(p->v2);
+ else
+     vpushi(p->v2);
+        if (p->v1 == p->v2) {
+            gen_op(0x94);
+            gtst_addr(0, p->sym);
+        } else {
+            gen_op(0x9e);
+            e = gtst(1, 0);
+            vdup();
+     if (ll)
+         vpushll(p->v1);
+     else
+         vpushi(p->v1);
+            gen_op(0x9d);
+            gtst_addr(0, p->sym);
+            gsym(e);
+        }
+    }
+}
+
+static void block(int *bsym, int *csym, int is_expr)
+{
+    int a, b, c, d, cond;
+    Sym *s;
+
+
+    if (tcc_state->do_debug)
+        tcc_debug_line(tcc_state);
+
+    if (is_expr) {
+
+        vpushi(0);
+        vtop->type.t = 0;
+    }
+
+    if (tok == TOK_IF) {
+
+ int saved_nocode_wanted = nocode_wanted;
+        next();
+        skip('(');
+        gexpr();
+        skip(')');
+ cond = condition_3way();
+        if (cond == 1)
+            a = 0, vpop();
+        else
+            a = gvtst(1, 0);
+        if (cond == 0)
+     nocode_wanted |= 0x20000000;
+        block(bsym, csym, 0);
+ if (cond != 1)
+     nocode_wanted = saved_nocode_wanted;
+        c = tok;
+        if (c == TOK_ELSE) {
+            next();
+            d = gjmp(0);
+            gsym(a);
+     if (cond == 1)
+         nocode_wanted |= 0x20000000;
+            block(bsym, csym, 0);
+            gsym(d);
+     if (cond != 0)
+  nocode_wanted = saved_nocode_wanted;
+        } else
+            gsym(a);
+    } else if (tok == TOK_WHILE) {
+ int saved_nocode_wanted;
+ nocode_wanted &= ~0x20000000;
+        next();
+        d = ind;
+        vla_sp_restore();
+        skip('(');
+        gexpr();
+        skip(')');
+        a = gvtst(1, 0);
+        b = 0;
+        ++local_scope;
+ saved_nocode_wanted = nocode_wanted;
+        block(&a, &b, 0);
+ nocode_wanted = saved_nocode_wanted;
+        --local_scope;
+        gjmp_addr(d);
+        gsym(a);
+        gsym_addr(b, d);
+    } else if (tok == '{') {
+        Sym *llabel;
+        int block_vla_sp_loc = vla_sp_loc, saved_vlas_in_scope = vlas_in_scope;
+
+        next();
+
+        s = local_stack;
+        llabel = local_label_stack;
+        ++local_scope;
+
+
+        if (tok == TOK_LABEL) {
+            next();
+            for(;;) {
+                if (tok < TOK_DEFINE)
+                    expect("label identifier");
+                label_push(&local_label_stack, tok, 2);
+                next();
+                if (tok == ',') {
+                    next();
+                } else {
+                    skip(';');
+                    break;
+                }
+            }
+        }
+        while (tok != '}') {
+     if ((a = is_label()))
+  unget_tok(a);
+     else
+         decl(0x0032);
+            if (tok != '}') {
+                if (is_expr)
+                    vpop();
+                block(bsym, csym, is_expr);
+            }
+        }
+
+        label_pop(&local_label_stack, llabel, is_expr);
+
+        --local_scope;
+
+
+
+
+
+
+
+ sym_pop(&local_stack, s, is_expr);
+
+
+        if (vlas_in_scope > saved_vlas_in_scope) {
+            vla_sp_loc = saved_vlas_in_scope ? block_vla_sp_loc : vla_sp_root_loc;
+            vla_sp_restore();
+        }
+        vlas_in_scope = saved_vlas_in_scope;
+
+        next();
+    } else if (tok == TOK_RETURN) {
+        next();
+        if (tok != ';') {
+            gexpr();
+            gen_assign_cast(&func_vt);
+            if ((func_vt.t & 0x000f) == 0)
+                vtop--;
+            else
+                gfunc_return(&func_vt);
+        }
+        skip(';');
+
+        if (tok != '}' || local_scope != 1)
+            rsym = gjmp(rsym);
+ nocode_wanted |= 0x20000000;
+    } else if (tok == TOK_BREAK) {
+
+        if (!bsym)
+            tcc_error("cannot break");
+        *bsym = gjmp(*bsym);
+        next();
+        skip(';');
+ nocode_wanted |= 0x20000000;
+    } else if (tok == TOK_CONTINUE) {
+
+        if (!csym)
+            tcc_error("cannot continue");
+        vla_sp_restore_root();
+        *csym = gjmp(*csym);
+        next();
+        skip(';');
+    } else if (tok == TOK_FOR) {
+        int e;
+ int saved_nocode_wanted;
+ nocode_wanted &= ~0x20000000;
+        next();
+        skip('(');
+        s = local_stack;
+        ++local_scope;
+        if (tok != ';') {
+
+            if (!decl0(0x0032, 1, 0)) {
+
+                gexpr();
+                vpop();
+            }
+        }
+        skip(';');
+        d = ind;
+        c = ind;
+        vla_sp_restore();
+        a = 0;
+        b = 0;
+        if (tok != ';') {
+            gexpr();
+            a = gvtst(1, 0);
+        }
+        skip(';');
+        if (tok != ')') {
+            e = gjmp(0);
+            c = ind;
+            vla_sp_restore();
+            gexpr();
+            vpop();
+            gjmp_addr(d);
+            gsym(e);
+        }
+        skip(')');
+ saved_nocode_wanted = nocode_wanted;
+        block(&a, &b, 0);
+ nocode_wanted = saved_nocode_wanted;
+        gjmp_addr(c);
+        gsym(a);
+        gsym_addr(b, c);
+        --local_scope;
+        sym_pop(&local_stack, s, 0);
+
+    } else
+    if (tok == TOK_DO) {
+ int saved_nocode_wanted;
+ nocode_wanted &= ~0x20000000;
+        next();
+        a = 0;
+        b = 0;
+        d = ind;
+        vla_sp_restore();
+ saved_nocode_wanted = nocode_wanted;
+        block(&a, &b, 0);
+        skip(TOK_WHILE);
+        skip('(');
+        gsym(b);
+ gexpr();
+ c = gvtst(0, 0);
+ gsym_addr(c, d);
+ nocode_wanted = saved_nocode_wanted;
+        skip(')');
+        gsym(a);
+        skip(';');
+    } else
+    if (tok == TOK_SWITCH) {
+        struct switch_t *saved, sw;
+ int saved_nocode_wanted = nocode_wanted;
+ SValue switchval;
+        next();
+        skip('(');
+        gexpr();
+        skip(')');
+ switchval = *vtop--;
+        a = 0;
+        b = gjmp(0);
+        sw.p = 0; sw.n = 0; sw.def_sym = 0;
+        saved = cur_switch;
+        cur_switch = &sw;
+        block(&a, csym, 0);
+ nocode_wanted = saved_nocode_wanted;
+        a = gjmp(a);
+
+        gsym(b);
+        qsort(sw.p, sw.n, sizeof(void*), case_cmp);
+        for (b = 1; b < sw.n; b++)
+            if (sw.p[b - 1]->v2 >= sw.p[b]->v1)
+                tcc_error("duplicate case value");
+
+
+        if ((switchval.type.t & 0x000f) == 4)
+            switchval.type.t &= ~0x0010;
+        vpushv(&switchval);
+        gcase(sw.p, sw.n, &a);
+        vpop();
+        if (sw.def_sym)
+          gjmp_addr(sw.def_sym);
+        dynarray_reset(&sw.p, &sw.n);
+        cur_switch = saved;
+
+        gsym(a);
+    } else
+    if (tok == TOK_CASE) {
+        struct case_t *cr = tcc_malloc(sizeof(struct case_t));
+        if (!cur_switch)
+            expect("switch");
+ nocode_wanted &= ~0x20000000;
+        next();
+        cr->v1 = cr->v2 = expr_const64();
+        if (gnu_ext && tok == 0xc8) {
+            next();
+            cr->v2 = expr_const64();
+            if (cr->v2 < cr->v1)
+                tcc_warning("empty case range");
+        }
+        cr->sym = ind;
+        dynarray_add(&cur_switch->p, &cur_switch->n, cr);
+        skip(':');
+        is_expr = 0;
+        goto block_after_label;
+    } else
+    if (tok == TOK_DEFAULT) {
+        next();
+        skip(':');
+        if (!cur_switch)
+            expect("switch");
+        if (cur_switch->def_sym)
+            tcc_error("too many 'default'");
+        cur_switch->def_sym = ind;
+        is_expr = 0;
+        goto block_after_label;
+    } else
+    if (tok == TOK_GOTO) {
+        next();
+        if (tok == '*' && gnu_ext) {
+
+            next();
+            gexpr();
+            if ((vtop->type.t & 0x000f) != 5)
+                expect("pointer");
+            ggoto();
+        } else if (tok >= TOK_DEFINE) {
+            s = label_find(tok);
+
+            if (!s) {
+                s = label_push(&global_label_stack, tok, 1);
+            } else {
+                if (s->r == 2)
+                    s->r = 1;
+            }
+            vla_sp_restore_root();
+     if (s->r & 1)
+                s->jnext = gjmp(s->jnext);
+            else
+                gjmp_addr(s->jnext);
+            next();
+        } else {
+            expect("label identifier");
+        }
+        skip(';');
+    } else if (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3) {
+        asm_instr();
+    } else {
+        b = is_label();
+        if (b) {
+
+     next();
+            s = label_find(b);
+            if (s) {
+                if (s->r == 0)
+                    tcc_error("duplicate label '%s'", get_tok_str(s->v, 0));
+                gsym(s->jnext);
+                s->r = 0;
+            } else {
+                s = label_push(&global_label_stack, b, 0);
+            }
+            s->jnext = ind;
+            vla_sp_restore();
+
+        block_after_label:
+     nocode_wanted &= ~0x20000000;
+            if (tok == '}') {
+                tcc_warning("deprecated use of label at end of compound statement");
+            } else {
+                if (is_expr)
+                    vpop();
+                block(bsym, csym, is_expr);
+            }
+        } else {
+
+            if (tok != ';') {
+                if (is_expr) {
+                    vpop();
+                    gexpr();
+                } else {
+                    gexpr();
+                    vpop();
+                }
+            }
+            skip(';');
+        }
+    }
+}
+
+
+
+
+
+
+static void skip_or_save_block(TokenString **str)
+{
+    int braces = tok == '{';
+    int level = 0;
+    if (str)
+      *str = tok_str_alloc();
+
+    while ((level > 0 || (tok != '}' && tok != ',' && tok != ';' && tok != ')'))) {
+ int t;
+ if (tok == (-1)) {
+      if (str || level > 0)
+        tcc_error("unexpected end of file");
+      else
+        break;
+ }
+ if (str)
+   tok_str_add_tok(*str);
+ t = tok;
+ next();
+ if (t == '{' || t == '(') {
+     level++;
+ } else if (t == '}' || t == ')') {
+     level--;
+     if (level == 0 && braces && t == '}')
+       break;
+ }
+    }
+    if (str) {
+ tok_str_add(*str, -1);
+ tok_str_add(*str, 0);
+    }
+}
+
+
+
+
+static void parse_init_elem(int expr_type)
+{
+    int saved_global_expr;
+    switch(expr_type) {
+    case 1:
+
+        saved_global_expr = global_expr;
+        global_expr = 1;
+        expr_const1();
+        global_expr = saved_global_expr;
+
+
+        if (((vtop->r & (0x003f | 0x0100)) != 0x0030
+      && ((vtop->r & (0x0200|0x0100)) != (0x0200|0x0100)
+   || vtop->sym->v < 0x10000000))
+
+
+
+            )
+            tcc_error("initializer element is not constant");
+        break;
+    case 2:
+        expr_eq();
+        break;
+    }
+}
+
+
+static void init_putz(Section *sec, unsigned long c, int size)
+{
+    if (sec) {
+
+    } else {
+        vpush_global_sym(&func_old_type, TOK_memset);
+        vseti(0x0032, c);
+
+
+
+
+        vpushi(0);
+        vpushs(size);
+
+        gfunc_call(3);
+    }
+}
+
+
+
+
+
+
+
+static int decl_designator(CType *type, Section *sec, unsigned long c,
+                           Sym **cur_field, int size_only, int al)
+{
+    Sym *s, *f;
+    int index, index_last, align, l, nb_elems, elem_size;
+    unsigned long corig = c;
+
+    elem_size = 0;
+    nb_elems = 1;
+    if (gnu_ext && (l = is_label()) != 0)
+        goto struct_field;
+
+    while (nb_elems == 1 && (tok == '[' || tok == '.')) {
+        if (tok == '[') {
+            if (!(type->t & 0x0040))
+                expect("array type");
+            next();
+            index = index_last = expr_const();
+            if (tok == 0xc8 && gnu_ext) {
+                next();
+                index_last = expr_const();
+            }
+            skip(']');
+            s = type->ref;
+     if (index < 0 || (s->c >= 0 && index_last >= s->c) ||
+  index_last < index)
+         tcc_error("invalid index");
+            if (cur_field)
+  (*cur_field)->c = index_last;
+            type = pointed_type(type);
+            elem_size = type_size(type, &align);
+            c += index * elem_size;
+            nb_elems = index_last - index + 1;
+        } else {
+            next();
+            l = tok;
+        struct_field:
+            next();
+            if ((type->t & 0x000f) != 7)
+                expect("struct/union type");
+     f = find_field(type, l);
+            if (!f)
+                expect("field");
+            if (cur_field)
+                *cur_field = f;
+     type = &f->type;
+            c += f->c;
+        }
+        cur_field = 0;
+    }
+    if (!cur_field) {
+        if (tok == '=') {
+            next();
+        } else if (!gnu_ext) {
+     expect("=");
+        }
+    } else {
+        if (type->t & 0x0040) {
+     index = (*cur_field)->c;
+     if (type->ref->c >= 0 && index >= type->ref->c)
+         tcc_error("index too large");
+            type = pointed_type(type);
+            c += index * type_size(type, &align);
+        } else {
+            f = *cur_field;
+     while (f && (f->v & 0x10000000) && (f->type.t & 0x0080))
+         *cur_field = f = f->next;
+            if (!f)
+                tcc_error("too many field init");
+     type = &f->type;
+            c += f->c;
+        }
+    }
+
+
+    if (!size_only && c - corig > al)
+ init_putz(sec, corig + al, c - corig - al);
+    decl_initializer(type, sec, c, 0, size_only);
+
+
+    if (!size_only && nb_elems > 1) {
+        unsigned long c_end;
+        uint8_t *src, *dst;
+        int i;
+
+        if (!sec) {
+     vset(type, 0x0032|0x0100, c);
+     for (i = 1; i < nb_elems; i++) {
+  vset(type, 0x0032|0x0100, c + elem_size * i);
+  vswap();
+  vstore();
+     }
+     vpop();
+        } else if (!(nocode_wanted > 0)) {
+     c_end = c + nb_elems * elem_size;
+     if (c_end > sec->data_allocated)
+         section_realloc(sec, c_end);
+     src = sec->data + c;
+     dst = src;
+     for(i = 1; i < nb_elems; i++) {
+  dst += elem_size;
+  memcpy(dst, src, elem_size);
+     }
+ }
+    }
+    c += nb_elems * type_size(type, &align);
+    if (c - corig > al)
+      al = c - corig;
+    return al;
+}
+
+
+static void init_putv(CType *type, Section *sec, unsigned long c)
+{
+    int bt;
+    void *ptr;
+    CType dtype;
+
+    dtype = *type;
+    dtype.t &= ~0x0100;
+
+    if (sec) {
+ int size, align;
+
+
+        gen_assign_cast(&dtype);
+        bt = type->t & 0x000f;
+
+        if ((vtop->r & 0x0200)
+            && bt != 5
+            && bt != 6
+            && (bt != (8 == 8 ? 4 : 3)
+                || (type->t & 0x0080))
+            && !((vtop->r & 0x0030) && vtop->sym->v >= 0x10000000)
+            )
+            tcc_error("initializer element is not computable at load time");
+
+        if ((nocode_wanted > 0)) {
+            vtop--;
+            return;
+        }
+
+ size = type_size(type, &align);
+ section_reserve(sec, c + size);
+        ptr = sec->data + c;
+
+
+ if ((vtop->r & (0x0200|0x0030)) == (0x0200|0x0030) &&
+     vtop->sym->v >= 0x10000000 &&
+# 6488 "tccgen.c"
+     (vtop->type.t & 0x000f) != 5) {
+
+     Section *ssec;
+     Elf64_Sym *esym;
+     Elf64_Rela *rel;
+     esym = elfsym(vtop->sym);
+     ssec = tcc_state->sections[esym->st_shndx];
+     memmove (ptr, ssec->data + esym->st_value, size);
+     if (ssec->reloc) {
+
+
+
+
+  int num_relocs = ssec->reloc->data_offset / sizeof(*rel);
+  rel = (Elf64_Rela*)(ssec->reloc->data + ssec->reloc->data_offset);
+  while (num_relocs--) {
+      rel--;
+      if (rel->r_offset >= esym->st_value + size)
+        continue;
+      if (rel->r_offset < esym->st_value)
+        break;
+
+
+
+
+
+
+      put_elf_reloca(symtab_section, sec,
+       c + rel->r_offset - esym->st_value,
+       ((rel->r_info) & 0xffffffff),
+       ((rel->r_info) >> 32),
+
+       rel->r_addend
+
+
+
+      );
+  }
+     }
+ } else {
+            if (type->t & 0x0080) {
+                int bit_pos, bit_size, bits, n;
+                unsigned char *p, v, m;
+                bit_pos = (((vtop->type.t) >> 20) & 0x3f);
+                bit_size = (((vtop->type.t) >> (20 + 6)) & 0x3f);
+                p = (unsigned char*)ptr + (bit_pos >> 3);
+                bit_pos &= 7, bits = 0;
+                while (bit_size) {
+                    n = 8 - bit_pos;
+                    if (n > bit_size)
+                        n = bit_size;
+                    v = vtop->c.i >> bits << bit_pos;
+                    m = ((1 << n) - 1) << bit_pos;
+                    *p = (*p & ~m) | (v & m);
+                    bits += n, bit_size -= n, bit_pos = 0, ++p;
+                }
+            } else
+            switch(bt) {
+
+
+
+     case 11:
+  vtop->c.i = vtop->c.i != 0;
+     case 1:
+  *(char *)ptr |= vtop->c.i;
+  break;
+     case 2:
+  *(short *)ptr |= vtop->c.i;
+  break;
+     case 8:
+  *(float*)ptr = vtop->c.f;
+  break;
+     case 9:
+  *(double *)ptr = vtop->c.d;
+  break;
+     case 10:
+
+                if (sizeof (long double) >= 10)
+                    memcpy(ptr, &vtop->c.ld, 10);
+
+
+
+
+                else if (vtop->c.ld == 0.0)
+                    ;
+                else
+
+                if (sizeof(long double) == 16)
+      *(long double*)ptr = vtop->c.ld;
+                else if (sizeof(double) == 16)
+      *(double *)ptr = (double)vtop->c.ld;
+                else
+                    tcc_error("can't cross compile long double constants");
+  break;
+
+
+
+
+
+     case 4:
+
+     case 5:
+  {
+      Elf64_Addr val = vtop->c.i;
+
+      if (vtop->r & 0x0200)
+        greloca(sec, vtop->sym, c, 1, val);
+      else
+        *(Elf64_Addr *)ptr |= val;
+
+
+
+
+
+      break;
+  }
+     default:
+  {
+      int val = vtop->c.i;
+
+      if (vtop->r & 0x0200)
+        greloca(sec, vtop->sym, c, 1, val);
+      else
+        *(int *)ptr |= val;
+
+
+
+
+
+      break;
+  }
+     }
+ }
+        vtop--;
+    } else {
+        vset(&dtype, 0x0032|0x0100, c);
+        vswap();
+        vstore();
+        vpop();
+    }
+}
+
+
+
+
+
+
+static void decl_initializer(CType *type, Section *sec, unsigned long c,
+                             int first, int size_only)
+{
+    int len, n, no_oblock, nb, i;
+    int size1, align1;
+    int have_elem;
+    Sym *s, *f;
+    Sym indexsym;
+    CType *t1;
+
+
+
+    have_elem = tok == '}' || tok == ',';
+    if (!have_elem && tok != '{' &&
+
+
+
+ tok != 0xba && tok != 0xb9 &&
+ !size_only) {
+ parse_init_elem(!sec ? 2 : 1);
+ have_elem = 1;
+    }
+
+    if (have_elem &&
+ !(type->t & 0x0040) &&
+
+
+
+ is_compatible_unqualified_types(type, &vtop->type)) {
+        init_putv(type, sec, c);
+    } else if (type->t & 0x0040) {
+        s = type->ref;
+        n = s->c;
+        t1 = pointed_type(type);
+        size1 = type_size(t1, &align1);
+
+        no_oblock = 1;
+        if ((first && tok != 0xba && tok != 0xb9) ||
+            tok == '{') {
+            if (tok != '{')
+                tcc_error("character array initializer must be a literal,"
+                    " optionally enclosed in braces");
+            skip('{');
+            no_oblock = 0;
+        }
+
+
+
+        if ((tok == 0xba &&
+
+
+
+             (t1->t & 0x000f) == 3
+
+            ) || (tok == 0xb9 && (t1->t & 0x000f) == 1)) {
+     len = 0;
+            while (tok == 0xb9 || tok == 0xba) {
+                int cstr_len, ch;
+
+
+                if (tok == 0xb9)
+                    cstr_len = tokc.str.size;
+                else
+                    cstr_len = tokc.str.size / sizeof(nwchar_t);
+                cstr_len--;
+                nb = cstr_len;
+                if (n >= 0 && nb > (n - len))
+                    nb = n - len;
+                if (!size_only) {
+                    if (cstr_len > nb)
+                        tcc_warning("initializer-string for array is too long");
+
+
+
+                    if (sec && tok == 0xb9 && size1 == 1) {
+                        if (!(nocode_wanted > 0))
+                            memcpy(sec->data + c + len, tokc.str.data, nb);
+                    } else {
+                        for(i=0;i<nb;i++) {
+                            if (tok == 0xb9)
+                                ch = ((unsigned char *)tokc.str.data)[i];
+                            else
+                                ch = ((nwchar_t *)tokc.str.data)[i];
+       vpushi(ch);
+                            init_putv(t1, sec, c + (len + i) * size1);
+                        }
+                    }
+                }
+                len += nb;
+                next();
+            }
+
+
+            if (n < 0 || len < n) {
+                if (!size_only) {
+      vpushi(0);
+                    init_putv(t1, sec, c + (len * size1));
+                }
+                len++;
+            }
+     len *= size1;
+        } else {
+     indexsym.c = 0;
+     f = &indexsym;
+
+          do_init_list:
+     len = 0;
+     while (tok != '}' || have_elem) {
+  len = decl_designator(type, sec, c, &f, size_only, len);
+  have_elem = 0;
+  if (type->t & 0x0040) {
+      ++indexsym.c;
+
+
+
+      if (no_oblock && len >= n*size1)
+          break;
+  } else {
+      if (s->type.t == (1 << 20 | 7))
+          f = 0;
+      else
+          f = f->next;
+      if (no_oblock && f == 0)
+          break;
+  }
+
+  if (tok == '}')
+      break;
+  skip(',');
+     }
+        }
+
+ if (!size_only && len < n*size1)
+     init_putz(sec, c + len, n*size1 - len);
+        if (!no_oblock)
+            skip('}');
+
+        if (n < 0)
+            s->c = size1 == 1 ? len : ((len + size1 - 1)/size1);
+    } else if ((type->t & 0x000f) == 7) {
+ size1 = 1;
+        no_oblock = 1;
+        if (first || tok == '{') {
+            skip('{');
+            no_oblock = 0;
+        }
+        s = type->ref;
+        f = s->next;
+        n = s->c;
+ goto do_init_list;
+    } else if (tok == '{') {
+        next();
+        decl_initializer(type, sec, c, first, size_only);
+        skip('}');
+    } else if (size_only) {
+
+
+
+
+
+
+
+        skip_or_save_block(0);
+    } else {
+ if (!have_elem) {
+
+
+
+     if (tok != 0xb9 && tok != 0xba)
+       expect("string constant");
+     parse_init_elem(!sec ? 2 : 1);
+ }
+        init_putv(type, sec, c);
+    }
+}
+# 6818 "tccgen.c"
+static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
+                                   int has_init, int v, int scope)
+{
+    int size, align, addr;
+    TokenString *init_str = 0;
+
+    Section *sec;
+    Sym *flexible_array;
+    Sym *sym = 0;
+    int saved_nocode_wanted = nocode_wanted;
+
+    int bcheck = tcc_state->do_bounds_check && !(nocode_wanted > 0);
+
+
+    if (type->t & 0x00002000)
+        nocode_wanted |= (nocode_wanted > 0) ? 0x40000000 : 0x80000000;
+
+    flexible_array = 0;
+    if ((type->t & 0x000f) == 7) {
+        Sym *field = type->ref->next;
+        if (field) {
+            while (field->next)
+                field = field->next;
+            if (field->type.t & 0x0040 && field->type.ref->c < 0)
+                flexible_array = field;
+        }
+    }
+
+    size = type_size(type, &align);
+
+
+
+
+
+
+    if (size < 0 || (flexible_array && has_init)) {
+        if (!has_init)
+            tcc_error("unknown type size");
+
+        if (has_init == 2) {
+     init_str = tok_str_alloc();
+
+            while (tok == 0xb9 || tok == 0xba) {
+                tok_str_add_tok(init_str);
+                next();
+            }
+     tok_str_add(init_str, -1);
+     tok_str_add(init_str, 0);
+        } else {
+     skip_or_save_block(&init_str);
+        }
+        unget_tok(0);
+
+
+        begin_macro(init_str, 1);
+        next();
+        decl_initializer(type, 0, 0, 1, 1);
+
+        macro_ptr = init_str->str;
+        next();
+
+
+        size = type_size(type, &align);
+        if (size < 0)
+            tcc_error("unknown type size");
+    }
+
+
+    if (flexible_array &&
+ flexible_array->type.ref->c > 0)
+        size += flexible_array->type.ref->c
+         * pointed_size(&flexible_array->type);
+
+    if (ad->a.aligned) {
+ int speca = 1 << (ad->a.aligned - 1);
+        if (speca > align)
+            align = speca;
+    } else if (ad->a.packed) {
+        align = 1;
+    }
+
+    if ((nocode_wanted > 0))
+        size = 0, align = 1;
+
+    if ((r & 0x003f) == 0x0032) {
+        sec = 0;
+
+        if (bcheck && (type->t & 0x0040)) {
+            loc--;
+        }
+
+        loc = (loc - size) & -align;
+        addr = loc;
+
+
+
+
+        if (bcheck && (type->t & 0x0040)) {
+            Elf64_Addr *bounds_ptr;
+
+            loc--;
+
+            bounds_ptr = section_ptr_add(lbounds_section, 2 * sizeof(Elf64_Addr));
+            bounds_ptr[0] = addr;
+            bounds_ptr[1] = size;
+        }
+
+        if (v) {
+
+
+     if (ad->asm_label) {
+  int reg = asm_parse_regvar(ad->asm_label);
+  if (reg >= 0)
+      r = (r & ~0x003f) | reg;
+     }
+
+            sym = sym_push(v, type, r, addr);
+            sym->a = ad->a;
+        } else {
+
+            vset(type, r, addr);
+        }
+    } else {
+        if (v && scope == 0x0030) {
+
+            sym = sym_find(v);
+            if (sym) {
+                patch_storage(sym, ad, type);
+
+                if (!has_init && sym->c && elfsym(sym)->st_shndx != 0)
+                    goto no_alloc;
+            }
+        }
+
+
+        sec = ad->section;
+        if (!sec) {
+            if (has_init)
+                sec = data_section;
+            else if (tcc_state->nocommon)
+                sec = bss_section;
+        }
+
+        if (sec) {
+     addr = section_add(sec, size, align);
+
+
+            if (bcheck)
+                section_add(sec, 1, 1);
+
+        } else {
+            addr = align;
+     sec = common_section;
+        }
+
+        if (v) {
+            if (!sym) {
+                sym = sym_push(v, type, r | 0x0200, 0);
+                patch_storage(sym, ad, 0);
+            }
+
+
+            sym->sym_scope = 0;
+
+     put_extern_sym(sym, sec, addr, size);
+        } else {
+
+            sym = get_sym_ref(type, sec, addr, size);
+     vpushsym(type, sym);
+     vtop->r |= r;
+        }
+
+
+
+
+        if (bcheck) {
+            Elf64_Addr *bounds_ptr;
+
+            greloca(bounds_section, sym, bounds_section->data_offset, 1, 0);
+
+            bounds_ptr = section_ptr_add(bounds_section, 2 * sizeof(Elf64_Addr));
+            bounds_ptr[0] = 0;
+            bounds_ptr[1] = size;
+        }
+
+    }
+
+    if (type->t & 0x0400) {
+        int a;
+
+        if ((nocode_wanted > 0))
+            goto no_alloc;
+
+
+        if (vlas_in_scope == 0) {
+            if (vla_sp_root_loc == -1)
+                vla_sp_root_loc = (loc -= 8);
+            gen_vla_sp_save(vla_sp_root_loc);
+        }
+
+        vla_runtime_type_size(type, &a);
+        gen_vla_alloc(type, a);
+
+
+
+
+
+        gen_vla_sp_save(addr);
+        vla_sp_loc = addr;
+        vlas_in_scope++;
+
+    } else if (has_init) {
+ size_t oldreloc_offset = 0;
+ if (sec && sec->reloc)
+   oldreloc_offset = sec->reloc->data_offset;
+        decl_initializer(type, sec, addr, 1, 0);
+ if (sec && sec->reloc)
+   squeeze_multi_relocs(sec, oldreloc_offset);
+
+
+        if (flexible_array)
+            flexible_array->type.ref->c = -1;
+    }
+
+ no_alloc:
+
+    if (init_str) {
+        end_macro();
+        next();
+    }
+
+    nocode_wanted = saved_nocode_wanted;
+}
+
+
+
+static void gen_function(Sym *sym)
+{
+    nocode_wanted = 0;
+    ind = cur_text_section->data_offset;
+
+    put_extern_sym(sym, cur_text_section, ind, 0);
+    funcname = get_tok_str(sym->v, 0);
+    func_ind = ind;
+
+    vla_sp_loc = -1;
+    vla_sp_root_loc = -1;
+
+    tcc_debug_funcstart(tcc_state, sym);
+
+    sym_push2(&local_stack, 0x20000000, 0, 0);
+    local_scope = 1;
+    gfunc_prolog(&sym->type);
+    local_scope = 0;
+    rsym = 0;
+    block(0, 0, 0);
+    nocode_wanted = 0;
+    gsym(rsym);
+    gfunc_epilog();
+    cur_text_section->data_offset = ind;
+    label_pop(&global_label_stack, 0, 0);
+
+    local_scope = 0;
+    sym_pop(&local_stack, 0, 0);
+
+
+    elfsym(sym)->st_size = ind - func_ind;
+    tcc_debug_funcend(tcc_state, ind - func_ind);
+
+    cur_text_section = 0;
+    funcname = "";
+    func_vt.t = 0;
+    func_var = 0;
+    ind = 0;
+    nocode_wanted = 0x80000000;
+    check_vstack();
+}
+
+static void gen_inline_functions(TCCState *s)
+{
+    Sym *sym;
+    int inline_generated, i, ln;
+    struct InlineFunc *fn;
+
+    ln = file->line_num;
+
+    do {
+        inline_generated = 0;
+        for (i = 0; i < s->nb_inline_fns; ++i) {
+            fn = s->inline_fns[i];
+            sym = fn->sym;
+            if (sym && sym->c) {
+
+
+                fn->sym = 0;
+                if (file)
+                    pstrcpy(file->filename, sizeof file->filename, fn->filename);
+                sym->type.t &= ~0x00008000;
+
+                begin_macro(fn->func_str, 1);
+                next();
+                cur_text_section = text_section;
+                gen_function(sym);
+                end_macro();
+
+                inline_generated = 1;
+            }
+        }
+    } while (inline_generated);
+    file->line_num = ln;
+}
+
+static void free_inline_functions(TCCState *s)
+{
+    int i;
+
+    for (i = 0; i < s->nb_inline_fns; ++i) {
+        struct InlineFunc *fn = s->inline_fns[i];
+        if (fn->sym)
+            tok_str_free(fn->func_str);
+    }
+    dynarray_reset(&s->inline_fns, &s->nb_inline_fns);
+}
+
+
+
+static int decl0(int l, int is_for_loop_init, Sym *func_sym)
+{
+    int v, has_init, r;
+    CType type, btype;
+    Sym *sym;
+    AttributeDef ad;
+
+    while (1) {
+        if (!parse_btype(&btype, &ad)) {
+            if (is_for_loop_init)
+                return 0;
+
+            if (tok == ';' && l != 0x0033) {
+                next();
+                continue;
+            }
+            if (l != 0x0030)
+                break;
+            if (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3) {
+
+                asm_global_instr();
+                continue;
+            }
+            if (tok >= TOK_DEFINE) {
+
+
+                btype.t = 3;
+            } else {
+                if (tok != (-1))
+                    expect("declaration");
+                break;
+            }
+        }
+        if (tok == ';') {
+     if ((btype.t & 0x000f) == 7) {
+  int v = btype.ref->v;
+  if (!(v & 0x20000000) && (v & ~0x40000000) >= 0x10000000)
+             tcc_warning("unnamed struct/union that defines no instances");
+                next();
+                continue;
+     }
+            if (((btype.t & (((1 << (6+6)) - 1) << 20 | 0x0080)) == (2 << 20))) {
+                next();
+                continue;
+            }
+        }
+        while (1) {
+            type = btype;
+
+
+
+
+
+     if ((type.t & 0x0040) && type.ref->c < 0) {
+  type.ref = sym_push(0x20000000, &type.ref->type, 0, type.ref->c);
+     }
+            type_decl(&type, &ad, &v, 2);
+
+
+
+
+
+
+
+            if ((type.t & 0x000f) == 6) {
+                if ((type.t & 0x00002000) && (l == 0x0032)) {
+                    tcc_error("function without file scope cannot be static");
+                }
+
+
+                sym = type.ref;
+                if (sym->f.func_type == 2 && l == 0x0030)
+                    decl0(0x0033, 0, sym);
+            }
+
+            if (gnu_ext && (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3)) {
+                ad.asm_label = asm_label_instr();
+
+                parse_attribute(&ad);
+                if (tok == '{')
+                    expect(";");
+            }
+# 7239 "tccgen.c"
+            if (tok == '{') {
+                if (l != 0x0030)
+                    tcc_error("cannot use local functions");
+                if ((type.t & 0x000f) != 6)
+                    expect("function definition");
+
+
+
+                sym = type.ref;
+                while ((sym = sym->next) != 0) {
+                    if (!(sym->v & ~0x20000000))
+                        expect("identifier");
+      if (sym->type.t == 0)
+          sym->type = int_type;
+  }
+
+
+                if ((type.t & (0x00001000 | 0x00008000)) == (0x00001000 | 0x00008000))
+                    type.t = (type.t & ~0x00001000) | 0x00002000;
+
+
+                sym = external_global_sym(v, &type, 0);
+                type.t &= ~0x00001000;
+                patch_storage(sym, &ad, &type);
+
+
+
+
+                if ((type.t & (0x00008000 | 0x00002000)) ==
+                    (0x00008000 | 0x00002000)) {
+                    struct InlineFunc *fn;
+                    const char *filename;
+
+                    filename = file ? file->filename : "";
+                    fn = tcc_malloc(sizeof *fn + strlen(filename));
+                    strcpy(fn->filename, filename);
+                    fn->sym = sym;
+      skip_or_save_block(&fn->func_str);
+                    dynarray_add(&tcc_state->inline_fns,
+     &tcc_state->nb_inline_fns, fn);
+                } else {
+
+                    cur_text_section = ad.section;
+                    if (!cur_text_section)
+                        cur_text_section = text_section;
+                    gen_function(sym);
+                }
+                break;
+            } else {
+  if (l == 0x0033) {
+
+      for (sym = func_sym->next; sym; sym = sym->next)
+   if ((sym->v & ~0x20000000) == v)
+       goto found;
+      tcc_error("declaration for parameter '%s' but no such parameter",
+         get_tok_str(v, 0));
+found:
+      if (type.t & (0x00001000 | 0x00002000 | 0x00004000 | 0x00008000))
+          tcc_error("storage class specified for '%s'",
+      get_tok_str(v, 0));
+      if (sym->type.t != 0)
+          tcc_error("redefinition of parameter '%s'",
+      get_tok_str(v, 0));
+      convert_parameter_type(&type);
+      sym->type = type;
+  } else if (type.t & 0x00004000) {
+
+
+                    sym = sym_find(v);
+                    if (sym && sym->sym_scope == local_scope) {
+                        if (!is_compatible_types(&sym->type, &type)
+                            || !(sym->type.t & 0x00004000))
+                            tcc_error("incompatible redefinition of '%s'",
+                                get_tok_str(v, 0));
+                        sym->type = type;
+                    } else {
+                        sym = sym_push(v, &type, 0, 0);
+                    }
+                    sym->a = ad.a;
+                    sym->f = ad.f;
+                } else {
+                    r = 0;
+                    if ((type.t & 0x000f) == 6) {
+
+
+                        type.ref->f = ad.f;
+                    } else if (!(type.t & 0x0040)) {
+
+                        r |= lvalue_type(type.t);
+                    }
+                    has_init = (tok == '=');
+                    if (has_init && (type.t & 0x0400))
+                        tcc_error("variable length array cannot be initialized");
+                    if (((type.t & 0x00001000) && (!has_init || l != 0x0030)) ||
+   ((type.t & 0x000f) == 6) ||
+                        ((type.t & 0x0040) && (type.t & 0x00002000) &&
+                         !has_init && l == 0x0030 && type.ref->c < 0)) {
+
+
+
+
+                        type.t |= 0x00001000;
+                        sym = external_sym(v, &type, r, &ad);
+                        if (ad.alias_target) {
+                            Elf64_Sym *esym;
+                            Sym *alias_target;
+                            alias_target = sym_find(ad.alias_target);
+                            esym = elfsym(alias_target);
+                            if (!esym)
+                                tcc_error("unsupported forward __alias__ attribute");
+
+
+                            sym->sym_scope = 0;
+                            put_extern_sym2(sym, esym->st_shndx, esym->st_value, esym->st_size, 0);
+                        }
+                    } else {
+                        if (type.t & 0x00002000)
+                            r |= 0x0030;
+                        else
+                            r |= l;
+                        if (has_init)
+                            next();
+                        else if (l == 0x0030)
+
+                            type.t |= 0x00001000;
+                        decl_initializer_alloc(&type, &ad, r, has_init, v, l);
+                    }
+                }
+                if (tok != ',') {
+                    if (is_for_loop_init)
+                        return 1;
+                    skip(';');
+                    break;
+                }
+                next();
+            }
+            ad.a.aligned = 0;
+        }
+    }
+    return 0;
+}
+
+static void decl(int l)
+{
+    decl0(l, 0, 0);
+}
diff --git a/utils/fake_libc_include/_fake_defines.h b/utils/fake_libc_include/_fake_defines.h
index 35bd4ad..a00a63b 100644
--- a/utils/fake_libc_include/_fake_defines.h
+++ b/utils/fake_libc_include/_fake_defines.h
@@ -199,3 +199,23 @@
 #define va_end(_list)
 
 #endif
+
+/* Vectors */
+#define __m128    int
+#define __m128_u  int
+#define __m128d   int
+#define __m128d_u int
+#define __m128i   int
+#define __m128i_u int
+#define __m256    int
+#define __m256_u  int
+#define __m256d   int
+#define __m256d_u int
+#define __m256i   int
+#define __m256i_u int
+#define __m512    int
+#define __m512_u  int
+#define __m512d   int
+#define __m512d_u int
+#define __m512i   int
+#define __m512i_u int
diff --git a/utils/fake_libc_include/emmintrin.h b/utils/fake_libc_include/emmintrin.h
new file mode 100644
index 0000000..f952c1d
--- /dev/null
+++ b/utils/fake_libc_include/emmintrin.h
@@ -0,0 +1,2 @@
+#include "_fake_defines.h"
+#include "_fake_typedefs.h"
diff --git a/utils/fake_libc_include/immintrin.h b/utils/fake_libc_include/immintrin.h
new file mode 100644
index 0000000..f952c1d
--- /dev/null
+++ b/utils/fake_libc_include/immintrin.h
@@ -0,0 +1,2 @@
+#include "_fake_defines.h"
+#include "_fake_typedefs.h"
diff --git a/utils/fake_libc_include/smmintrin.h b/utils/fake_libc_include/smmintrin.h
new file mode 100644
index 0000000..f952c1d
--- /dev/null
+++ b/utils/fake_libc_include/smmintrin.h
@@ -0,0 +1,2 @@
+#include "_fake_defines.h"
+#include "_fake_typedefs.h"