diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2022-04-08 16:01:42 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2022-04-08 16:01:42 +0000 |
commit | 955f16fd48378faf5b0a83a1a9425af295bd5d99 (patch) | |
tree | e4cb3cbe173c7f08912980b116fb5b3d6f6357b8 | |
parent | 70e161b3a3287672b5b3ab7262af54e6afa1a07c (diff) | |
parent | 24385e7bc2d202bae209c86bcc9ade41b09078ba (diff) | |
download | pycparser-955f16fd48378faf5b0a83a1a9425af295bd5d99.tar.gz |
Snap for 8426163 from 24385e7bc2d202bae209c86bcc9ade41b09078ba to mainline-tzdata2-releaseandroid-mainline-12.0.0_r112aml_tz2_305400500aml_tz2_305400300aml_tz2_305400100aml_tz2_304500300aml_tz2_303900110aml_tz2_303900102aml_tz2_303800002aml_tz2_303800001aml_tz2_303200001android12-mainline-tzdata2-releaseaml_tz2_305400100
Change-Id: I38c34307e93885d46067960f5977292ae82aefb0
34 files changed, 93 insertions, 26530 deletions
diff --git a/.gitattributes b/.gitattributes deleted file mode 100644 index 91c326c..0000000 --- a/.gitattributes +++ /dev/null @@ -1,2 +0,0 @@ -*.ppout linguist-vendored=true - @@ -14,4 +14,4 @@ parser.out .tox utils/z.c *.egg-info -*.swp + diff --git a/.travis.yml b/.travis.yml index d71276e..25c9df6 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 @@ -1,8 +0,0 @@ -" 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/Android.bp b/Android.bp deleted file mode 100644 index 064c1a3..0000000 --- a/Android.bp +++ /dev/null @@ -1,31 +0,0 @@ -// -// Copyright (C) 2021 The Android Open Source Project -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package { - default_applicable_licenses: ["external_python_pycparser_license"], -} - -// Added automatically by a large-scale-change -// See: http://go/android-license-faq -license { - name: "external_python_pycparser_license", - visibility: [":__subpackages__"], - license_kinds: [ - "SPDX-license-identifier-BSD", - ], - license_text: [ - "LICENSE", - ], -} @@ -1,26 +1,9 @@ -+ 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) @@ -166,11 +149,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 @@ -178,34 +161,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) @@ -235,7 +218,7 @@ + Version 1.06 (2010.04.10) - * Bug fixes: + * Bug fixes: + coord not propagated to FuncCall nodes + lexing of the ^= token (XOREQUALS) @@ -263,7 +246,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) @@ -9,11 +9,11 @@ third_party { type: GIT value: "https://github.com/eliben/pycparser" } - version: "release_v2.20" + version: "release_v2.19" license_type: NOTICE last_upgrade_date { - year: 2020 - month: 3 - day: 4 + year: 2019 + month: 5 + day: 2 } } @@ -0,0 +1 @@ +LICENSE
\ No newline at end of file @@ -1,15 +1,9 @@ =============== -pycparser v2.20 +pycparser v2.19 =============== +: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 @@ -167,9 +161,6 @@ See `this blog post <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 ----------- @@ -249,3 +240,18 @@ updating this list because Github does a much better job at tracking 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/TEST_MAPPING b/TEST_MAPPING new file mode 100644 index 0000000..61a80b2 --- /dev/null +++ b/TEST_MAPPING @@ -0,0 +1,8 @@ +{ + "presubmit" : [ + { + "name" : "acloud_test", + "host" : true + } + ] +} @@ -19,7 +19,7 @@ Now create a new virtualenv and in it install the tarball with `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 -m twine upload dist/*` to push to PyPI +After this it's OK to rerun `python3.6 setup.py sdist upload` 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 900df8f..05c1c7e 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -2,9 +2,9 @@ environment: 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 63f5e2d..2cff874 100644 --- a/examples/dump_ast.py +++ b/examples/dump_ast.py @@ -19,9 +19,7 @@ from pycparser import c_parser, c_ast, parse_file 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(showcoord=args.coord) + ast.show() diff --git a/examples/func_calls.py b/examples/func_calls.py index 97a7271..ec31fe5 100644 --- a/examples/func_calls.py +++ b/examples/func_calls.py @@ -17,7 +17,9 @@ sys.path.extend(['.', '..']) 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 @@ -25,9 +27,6 @@ class FuncCallVisitor(c_ast.NodeVisitor): 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/Android.bp b/pycparser/Android.bp index cbab45f..4fee1fb 100644 --- a/pycparser/Android.bp +++ b/pycparser/Android.bp @@ -11,15 +11,6 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. -package { - // See: http://go/android-license-faq - // A large-scale-change added 'default_applicable_licenses' to import - // all of the 'license_kinds' from "external_python_pycparser_license" - // to get the below license kinds: - // SPDX-license-identifier-BSD - default_applicable_licenses: ["external_python_pycparser_license"], -} - python_library { name: "py-pycparser", host_supported: true, diff --git a/pycparser/__init__.py b/pycparser/__init__.py index 6e86e9f..b67389f 100644 --- a/pycparser/__init__.py +++ b/pycparser/__init__.py @@ -8,7 +8,7 @@ # License: BSD #----------------------------------------------------------------- __all__ = ['c_lexer', 'c_parser', 'c_ast'] -__version__ = '2.20' +__version__ = '2.19' import io from subprocess import check_output diff --git a/pycparser/_build_tables.py b/pycparser/_build_tables.py index 958381a..94a3891 100644 --- a/pycparser/_build_tables.py +++ b/pycparser/_build_tables.py @@ -10,17 +10,13 @@ # 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 0aeb88f..ba50966 100644 --- a/pycparser/ast_transforms.py +++ b/pycparser/ast_transforms.py @@ -74,8 +74,7 @@ def fix_switch_cases(switch_node): # 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 `switch(cond) {}`, block_items would have been None) - for child in (switch_node.stmt.block_items or []): + for child in switch_node.stmt.block_items: 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 973d24a..f789742 100644 --- a/pycparser/c_generator.py +++ b/pycparser/c_generator.py @@ -119,7 +119,7 @@ class CGenerator(object): return s def visit_Cast(self, n): - s = '(' + self._generate_type(n.to_type, emit_declname=False) + ')' + s = '(' + self._generate_type(n.to_type) + ')' return s + ' ' + self._parenthesize_unless_simple(n.expr) def visit_ExprList(self, n): @@ -291,15 +291,6 @@ class CGenerator(object): 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'. @@ -368,7 +359,7 @@ class CGenerator(object): s += self._generate_type(n.type) return s - def _generate_type(self, n, modifiers=[], emit_declname = True): + def _generate_type(self, n, modifiers=[]): """ 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 @@ -382,29 +373,23 @@ class CGenerator(object): if n.quals: s += ' '.join(n.quals) + ' ' s += self.visit(n.type) - nstr = n.declname if n.declname and emit_declname else '' + nstr = n.declname if n.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 += '[' - if modifier.dim_quals: - nstr += ' '.join(modifier.dim_quals) + ' ' - nstr += self.visit(modifier.dim) + ']' + if (i != 0 and isinstance(modifiers[i - 1], c_ast.PtrDecl)): + nstr = '(' + nstr + ')' + 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 if nstr else '') + nstr = '* %s %s' % (' '.join(modifier.quals), nstr) else: nstr = '*' + nstr if nstr: s += ' ' + nstr @@ -412,12 +397,11 @@ class CGenerator(object): elif typ == c_ast.Decl: return self._generate_decl(n.type) elif typ == c_ast.Typename: - return self._generate_type(n.type, emit_declname = emit_declname) + return self._generate_type(n.type) 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], - emit_declname = emit_declname) + return self._generate_type(n.type, modifiers + [n]) else: return self.visit(n) diff --git a/pycparser/c_lexer.py b/pycparser/c_lexer.py index 045d24e..de8445e 100644 --- a/pycparser/c_lexer.py +++ b/pycparser/c_lexer.py @@ -19,7 +19,7 @@ class CLexer(object): tokens. The public attribute filename can be set to an initial - filename, but the lexer will update it upon #line + filaneme, but the lexer will update it upon #line directives. """ def __init__(self, error_func, on_lbrace_func, on_rbrace_func, @@ -130,7 +130,7 @@ class CLexer(object): 'TYPEID', # constants - 'INT_CONST_DEC', 'INT_CONST_OCT', 'INT_CONST_HEX', 'INT_CONST_BIN', 'INT_CONST_CHAR', + 'INT_CONST_DEC', 'INT_CONST_OCT', 'INT_CONST_HEX', 'INT_CONST_BIN', 'FLOAT_CONST', 'HEX_FLOAT_CONST', 'CHAR_CONST', 'WCHAR_CONST', @@ -205,49 +205,23 @@ class CLexer(object): # parse all correct code, even if it means to sometimes parse incorrect # code. # - # 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])""" + 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])""" 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_start_in_string+')' + string_char = r"""([^"\\\n]|"""+escape_sequence+')' 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]+)""" @@ -469,10 +443,6 @@ class CLexer(object): # 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 744ede8..0e6e755 100644 --- a/pycparser/c_parser.py +++ b/pycparser/c_parser.py @@ -529,7 +529,8 @@ class CParser(PLYParser): def p_translation_unit_2(self, p): """ translation_unit : translation_unit external_declaration """ - p[1].extend(p[2]) + if p[2] is not None: + p[1].extend(p[2]) p[0] = p[1] # Declarations always come as lists (because they can be @@ -556,7 +557,7 @@ class CParser(PLYParser): def p_external_declaration_4(self, p): """ external_declaration : SEMI """ - p[0] = [] + p[0] = None def p_pp_directive(self, p): """ pp_directive : PPHASH @@ -1410,13 +1411,12 @@ class CParser(PLYParser): p[0] = self._type_modify_decl(decl=p[1], modifier=arr) def p_direct_abstract_declarator_3(self, p): - """ direct_abstract_declarator : LBRACKET type_qualifier_list_opt assignment_expression_opt RBRACKET + """ direct_abstract_declarator : LBRACKET 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[3] if len(p) > 4 else p[2], - dim_quals=quals, + dim=p[2], + dim_quals=[], coord=self._token_coord(p, 1)) def p_direct_abstract_declarator_4(self, p): @@ -1740,7 +1740,8 @@ class CParser(PLYParser): if len(p) == 2: p[0] = p[1] elif len(p) == 4: - p[0] = c_ast.StructRef(p[1], p[2], p[3], p[1].coord) + field = c_ast.ID(p[3], self._token_coord(p, 3)) + p[0] = c_ast.StructRef(p[1], p[2], field, p[1].coord) elif len(p) == 5: p[0] = c_ast.ArrayRef(p[1], p[3], p[1].coord) else: @@ -1765,23 +1766,9 @@ class CParser(PLYParser): | 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( - prefix + 'int', p[1], self._token_coord(p, 1)) + 'int', p[1], self._token_coord(p, 1)) def p_constant_2(self, p): """ constant : FLOAT_CONST @@ -43,7 +43,7 @@ setup( C compilers or analysis tools. """, license='BSD', - version='2.20', + version='2.19', 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 dd19a11..3727f91 100644 --- a/tests/test_c_generator.py +++ b/tests/test_c_generator.py @@ -1,12 +1,11 @@ -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, parse_file +from pycparser import c_parser, c_generator, c_ast _c_parser = c_parser.CParser( lex_optimize=False, @@ -333,62 +332,6 @@ class TestCtoC(unittest.TestCase): 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 d63d6fd..11c7b26 100644 --- a/tests/test_c_lexer.py +++ b/tests/test_c_lexer.py @@ -77,10 +77,6 @@ class TestCLexerNoErrors(unittest.TestCase): 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']) @@ -120,7 +116,6 @@ class TestCLexerNoErrors(unittest.TestCase): 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']) @@ -154,24 +149,6 @@ class TestCLexerNoErrors(unittest.TestCase): 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( @@ -451,24 +428,14 @@ class TestCLexerErrors(unittest.TestCase): def test_char_constants(self): self.assertLexerError("'", ERR_UNMATCHED_QUOTE) self.assertLexerError("'b\n", ERR_UNMATCHED_QUOTE) - 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("'jx'", ERR_INVALID_CCONST) self.assertLexerError(r"'\*'", ERR_INVALID_CCONST) def test_string_literals(self): - self.assertLexerError(r'"jx\`"', ERR_STRING_ESCAPE) + self.assertLexerError(r'"jx\9"', 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 b6ecdd5..a48f1c6 100755 --- a/tests/test_c_parser.py +++ b/tests/test_c_parser.py @@ -136,15 +136,6 @@ class TestCParser_fundamentals(TestCParser_base): ['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 @@ -422,7 +413,6 @@ class TestCParser_fundamentals(TestCParser_base): ['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', @@ -453,30 +443,6 @@ class TestCParser_fundamentals(TestCParser_base): ['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] @@ -529,18 +495,6 @@ class TestCParser_fundamentals(TestCParser_base): ['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); @@ -558,20 +512,8 @@ class TestCParser_fundamentals(TestCParser_base): 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 = """ @@ -886,19 +828,6 @@ class TestCParser_fundamentals(TestCParser_base): ['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 @@ -1311,22 +1240,6 @@ class TestCParser_fundamentals(TestCParser_base): 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), @@ -1494,10 +1407,6 @@ class TestCParser_fundamentals(TestCParser_base): void main() { #pragma foo for(;;) {} - #pragma baz - { - int i = 0; - } #pragma } struct s { @@ -1514,16 +1423,12 @@ class TestCParser_fundamentals(TestCParser_base): 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, 'baz') + self.assertEqual(s1_ast.ext[1].body.block_items[2].string, '') 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, 13) + self.assertEqual(s1_ast.ext[2].type.type.decls[0].coord.line, 9) def test_pragmacomp_or_statement(self): s1 = r''' @@ -1570,10 +1475,8 @@ class TestCParser_fundamentals(TestCParser_base): 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): @@ -1816,7 +1719,6 @@ class TestCParser_whole_code(TestCParser_base): 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') @@ -1844,7 +1746,6 @@ class TestCParser_whole_code(TestCParser_base): 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') @@ -1856,18 +1757,6 @@ class TestCParser_whole_code(TestCParser_base): 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 deleted file mode 100644 index 652b274..0000000 --- a/utils/benchmark/README.rst +++ /dev/null @@ -1,22 +0,0 @@ -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 deleted file mode 100644 index 003acda..0000000 --- a/utils/benchmark/benchmark-parse.py +++ /dev/null @@ -1,58 +0,0 @@ -#----------------------------------------------------------------- -# 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 deleted file mode 100644 index b1fa222..0000000 --- a/utils/benchmark/inputs/redis.c.ppout +++ /dev/null @@ -1,4621 +0,0 @@ -# 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 deleted file mode 100644 index e73a0fa..0000000 --- a/utils/benchmark/inputs/sqlite-btree.c.ppout +++ /dev/null @@ -1,11397 +0,0 @@ -# 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], ¬Used, (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 deleted file mode 100644 index b007f19..0000000 --- a/utils/benchmark/inputs/tccgen.c.ppout +++ /dev/null @@ -1,9993 +0,0 @@ -# 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, ®size); - 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, ®size); - 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 a00a63b..35bd4ad 100644 --- a/utils/fake_libc_include/_fake_defines.h +++ b/utils/fake_libc_include/_fake_defines.h @@ -199,23 +199,3 @@ #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 deleted file mode 100644 index f952c1d..0000000 --- a/utils/fake_libc_include/emmintrin.h +++ /dev/null @@ -1,2 +0,0 @@ -#include "_fake_defines.h" -#include "_fake_typedefs.h" diff --git a/utils/fake_libc_include/immintrin.h b/utils/fake_libc_include/immintrin.h deleted file mode 100644 index f952c1d..0000000 --- a/utils/fake_libc_include/immintrin.h +++ /dev/null @@ -1,2 +0,0 @@ -#include "_fake_defines.h" -#include "_fake_typedefs.h" diff --git a/utils/fake_libc_include/smmintrin.h b/utils/fake_libc_include/smmintrin.h deleted file mode 100644 index f952c1d..0000000 --- a/utils/fake_libc_include/smmintrin.h +++ /dev/null @@ -1,2 +0,0 @@ -#include "_fake_defines.h" -#include "_fake_typedefs.h" |